Improvements to namespaces and file inclusion
[shapes.git] / examples / features / namespaces.blank
blobcdfc977b8ae25130a704b5ead7fe842d5234ea72
1 /** This file is part of Shapes.
2  **
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
6  ** any later version.
7  **
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.
12  **
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/>.
15  **
16  ** Copyright 2013, 2014 Henrik Tidefelt
17  **/
19 /** Namespaces add restrictions to the lexical scoping.  Namespaces can never provide access to
20  ** bindings that are out of lexical scope.
21  **
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..
26  **      ..MyExtension..
27  **      ..
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.
30  **    Examples:
31  **      MyExtension..Private..
32  **      Private..
33  **        (nothing at all)
34  **      ^^..
35  **      ^^..Private..
36  **      ^^..^^..
37  **
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
41  **   ..a
42  **   MyExtension..Private..a
43  **   a
44  **   ^^..^^..a
45  **
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.
49  **
50  ** A binding can only be introduced in the current namespace.  Example:
51  **   a: 1
52  **
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.
56  **
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.
61  **
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?
66  **/
68 ##lookin ..Shapes
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. **/
80 ##pop MyExtension
82 •stdout << MyExtension..a << "{n} /** Reference to a from outside MyExtension. **/
85 /** A namespace can be opened several times. **/
86 ##push MyExtension
88 { /** The namespace doesn't change when opening a code bracket. **/
89   /** Still in MyExtension **/
90   b: 2 /** Place b in MyExtension. **/
91   •stdout << b << "{n}
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. **/
99 ##push Restricted
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}
106 ##pop Restricted
108 ##push Internal
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.
112  **/
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. **/
124 ##pop Internal
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..-. **/
131 ##pop -
133 /** Reopen the private namespace **/
134 ##push -
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). **/
139 ##pop -
141 ##pop MyExtension
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:
147  **/
149 /** TODO!
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.
154  **/
156 ##push ImportA
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.
162  **/
163 ##push MyPackage
164 foo: 1
165 ##pop MyPackage
166 ##pop ImportA
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!)
173  **/
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.
179  **/
180 x: 1 /** Here is ..x **/
181 ##push A
182 x: 2 /** Here is ..A..x **/
183 ##pop A
185   x: 3 /** Here is another ..x **/
186 ##push A
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.
191    **/
192   •stdout << `Resolving x is less obvious: ´ << x << ` (expected what?)´ << "{n}
193 ##pop A
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.
197  **/
198 |** y: 1 /** User's own variable, unaware of A1 introducing A..y below: **/
199 |** ##needs A1
200 |** {
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.)
209 |**    **/
210 |** ##needs A2
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
216 |**    ** variables.
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.
223 |**    **/
224 |** }
227 /** Question:
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
233  **
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.
236  **
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.
240  **/