1 /** This file is part of Shapes.
3 ** Shapes is free software: you can redistribute it and/or modify
4 ** it under the terms of the GNU General Public License as published by
5 ** the Free Software Foundation, either version 3 of the License, or
8 ** Shapes is distributed in the hope that it will be useful,
9 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
10 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 ** GNU General Public License for more details.
13 ** You should have received a copy of the GNU General Public License
14 ** along with Shapes. If not, see <http://www.gnu.org/licenses/>.
16 ** Copyright 2013, 2014 Henrik Tidefelt
19 /** Namespaces add restrictions to the lexical scoping. Namespaces can never provide access to
20 ** bindings that are out of lexical scope.
22 ** There are two kinds of namespace paths:
23 ** o Absolute namespace paths, beginning with a double dot (..), followed by any number of namespace
24 ** names separated by more double dots, and a trailing double dot. Examples:
25 ** ..MyExtension..Private..
28 ** o Relative namespace paths, which look the same as absolute namespace paths except the leading double dot,
29 ** and allowing any number of ^^.. in the beginning.
31 ** MyExtension..Private..
38 ** There are two corresponding kinds of identifiers; absolute identifiers and relative identifiers.
39 ** Each is made up by a namespace path followed by an identifier token. Examples:
40 ** ..MyExtension..Private..a
42 ** MyExtension..Private..a
46 ** Looking up the binding for an absolute identifier involves no searching, while relative identifiers
47 ** are first searched in the current namespace, and then recursively in surrounding namespaces until the
48 ** global namespace is reached.
50 ** A binding can only be introduced in the current namespace. Example:
53 ** There is one special kind of namespace identified by a dash, with each such namespace being called
54 ** a "private namespace". Since the dash cannot be part of any absolute or relative identifier, bindings
55 ** in a private namespace are not accessible from outside this namespace.
57 ** To save typing, one can define temporary aliases. Example:
58 ** ##alias A = TmpA..MyPackage
59 ** The alias is introduced as a namespace inside the current namespace, but differs from real namespaces in that it,
60 ** cannot be entered, thereby ensuring that the bindings introduced in the aliased namespace are the only ones.
62 ** A namespace can have identifiers that are aliases for other identifiers, typically in other namespaces. Example
63 ** ##alias Internal..a
64 ** ##alias bb = Internal..b (do we really need remapping of identifiers to different names?)
65 ** Do we really need identifier aliases at all? Isn't namespace aliases enough?
70 a: 0 /** Place a in global namespace **/
71 •stdout << a << "{n} /** Refer to a using relative identifier (as if there were no namespaces). **/
72 •stdout << ..a << "{n} /** The global namespace is indicated by a double dot, and this called an absolute identifier. **/
74 /** A namespace must be opened and closed within the same code bracket. **/
75 ##push MyExtension /** Any identifier may serve as namespace name **/
77 a: 1 /** Place a in MyExtension. **/
78 •stdout << a << "{n} /** Refer to a as usual when inside MyExtension. **/
82 •stdout << MyExtension..a << "{n} /** Reference to a from outside MyExtension. **/
85 /** A namespace can be opened several times. **/
88 { /** The namespace doesn't change when opening a code bracket. **/
89 /** Still in MyExtension **/
90 b: 2 /** Place b in MyExtension. **/
92 /** It would be an error to be in a different namespace than MyExtension upon leaving the code bracket. **/
95 /** b is not in lexical scope here. **/
96 |** •stdout << b << "{n}
98 /** Open a new namespace inside MyExtension. **/
101 c: 3 /** Place c in MyExtension..Restricted. **/
103 /** Since a is not found in the current namespace, it is searched recursively in the surrounding namespaces, and found in MyExtension. **/
104 •stdout << a + c << "{n}
110 /** Since Restricted..c is not found in the current namespace, it is searched recursively in the surrounding namespaces, and found in MyExtension.
111 ** That is, we find MyExtension..Restricted..c.
113 •stdout << Restricted..c << "{n}
115 a: 5 /** Place another a in MyExtension..Internal. **/
116 •stdout << a << "{n} /** Refer to MyExtension..Internal..a. **/
117 •stdout << ..MyExtension..a << "{n} /** Reference relative to global namespace (this is called using the absolute identifier). **/
119 /** Source code reflection. **/
120 •stdout << (resolved_identifier_string Restricted..c) << "{n} /** Will print ..MyExtension..Restricted..a. **/
122 f: 7 /** This binding is exposed using an alias in MyExtension. **/
126 /** Open a private namespace that cannot be searched from the outside. **/
127 ##push - /** The dash is a special syntax, different from the usual identifier. **/
129 e: 4 /** Place e in MyExtension..-. **/
133 /** Reopen the private namespace **/
136 /** There is just one private namespace inside each named namespace, so this works: **/
137 •stdout << e << "{n} /** Refer to MyExtension..-..e (also known as -..e). **/
144 /** Let..s say there are two extensions, ExtA and ExtB, that happen to
145 ** use the same namespace MyPackage, and we must avoid the risk of conflicting identifiers, then we place each
146 ** extension in a super-namespace, and then add aliases for convenience:
150 ** Only allow ##needs in the global namespace, so that the only thing that matters when doing a need is the
151 ** current namespace.
152 ** This will make the use of ##needs much more clear, and namespaces can still be used to prevent a ##needs from
153 ** unwanted cluttering of existing namespaces.
157 /** Pretend needing the package ExtA **/
158 |**##needs ExtA /** Adds bindings in ImportA..MyPackage... **/
159 /** It would be a mess if ExtA introduced bindings outside ImportA!
160 ** Perhaps the possibility to introduce bindings outside the current namespace must be restricted
161 ** to private namespaces only.
167 ##alias ExtA = ImportA..MyPackage
169 /** Remember that ##needs must remember in what namespace an extension has been read. A subsequent ##needs in a different
170 ** namespace cannot just be skipped. Getting a remapping to work would probably be difficult since we won't keep track of the
171 ** exact list of symbols introduced during each need. Hence, we probably must accept reading it all in again, just to get
172 ** things in the new namespace... (What a waste!)
175 •stdout << `foo in ExtA: ´ << ExtA..foo << `, also available as: ´ << ImportA..MyPackage..foo << "{n}
178 /** Identifiers are searched along two axes, and one has to be given priority.
180 x: 1 /** Here is ..x **/
182 x: 2 /** Here is ..A..x **/
185 x: 3 /** Here is another ..x **/
187 •stdout << `Resolving ..x is easy: ´ << ..x << ` (expexed 3)´ << "{n}
188 •stdout << `Resolving A..x is easy: ´ << A..x << ` (expexed 2)´ << "{n}
189 /** There is no ..A..x in the current bracket, so resolving x here forces us to search both
190 ** surrounding brackets and enclosing namespaces.
192 •stdout << `Resolving x is less obvious: ´ << x << ` (expected what?)´ << "{n}
195 /** To understand how to resolve the last case above, consider how the situation could arise when working
196 ** with ##needs and multiple extensions populating the same namespace.
198 |** y: 1 /** User's own variable, unaware of A1 introducing A..y below: **/
201 |** y: 3 /** User introducing y again, still unaware that there's a A..y as well. **/
202 |** /** Now, when the user temporarily needs some things from A2. Now, A2 assumes A..y to be present,
203 |** ** without requiring that it has to be the one from A1 (therefore, A2 does not ##needs A1).
204 |** ** The user only knows that A1 is one of several variants that will work as a prerequisite for A2,
205 |** ** and it would probably come as a big surprise if introducing a variable in the global namespace
206 |** ** destroyed the connection between the two packages.
207 |** ** That is, resolving variables gives priority to namespace over code bracket. (It would have been
208 |** ** easier to implement if it was the other way around.)
211 |** /** On the other hand, one could also argue that doing ##needs on dependent packages in different code
212 |** ** brackets is stupid and shouldn't be expected to work. It might even make sense to recommend that
213 |** ** one should never enter a new namespace when inside an explicit code bracket (explicit meaning one
214 |** ** opened and closed with { and }, thereby excliding the implicit code bracket that contains the entire
215 |** ** program). Such a recommendation seems rather natural, and would allow for more efficient lookup of
217 |** ** To complete the story, it would be good to come up with an example where it actually makes more sense
218 |** ** to give code bracket priority over namespace. In the example above, giving the code bracket priority
219 |** ** means that we find the x that is lexically closer (fewer characters away in the source).
220 |** ** Note that the roles of namespace and code bracket in the example cannot be switched, because a namespace
221 |** ** can be opened in more than one location, but a closed code bracket can never be opened again in a
222 |** ** different location.
228 ** Given a variable with absolute identifier ..A..B..C..x and a location in the source where
229 ** we are in namespace ..A..B, is it safe to refer to the variable using only C..X?
230 ** More generally, can the any common prefix of the variable's absolute identifier and the current
231 ** namespace always be removed without changing the reference? For example, can ..A..B..C..x be replaced
232 ** with B..C..x within the environment ..A..B..K..L
234 ** The answer is that it is not save to do so. Absolute identifiers such as ..A..B..B..C..x or
235 ** ..A..B..K..B..C..x would shadow the original variable.
237 ** Most of the time, removing the longest common prefix would probably work, but to be on the safe side
238 ** one should verify the result before accepting it. It might also be possible to remove just a part of
239 ** the common prefix.