Legibility clean-ups for Shell and Regex code.
[cslatevm.git] / src / syntax / macro.slate
blobde84938bf7bbb9cfd84c778526431da190840ea4
1 node@(nodes Node traits) expand &environment: env
2 "Alias of macroExpand"
3 [node macroExpand &environment: env].
5 node@(nodes Node traits) macroExpand &environment: _
6 "The default do-nothing action of macro expansion."
8   node
9 ].
11 ann@(nodes Annotation traits) macroExpand &environment: env
12 "Return the annotation node, but replace the expression that the node
13 annotates with its expansion."
14 [| expansion |
15   ann value == (expansion := ann value macroExpand &environment: env)
16     ifFalse: [ann value := expansion].
17   ann
20 macro@(nodes Macro traits) macroExpand &optionals: opts &environment: env
21 "Simply apply the macro-method to its arguments. The generated nodes
22 inherit the macro node's debugging information."
23 [| expansion |
24   macro selector = #macroExpand ifTrue:
25     [error: 'Cannot macroExpand `macroExpand. Use `(expr) macroExpand instead'.
26      ^ macro].
27   opts := opts
28     ifNil: [#{}]
29     ifNotNil:
30       [[| :result |
31         opts keywords with: opts arguments do:
32           [| :key :arg | result nextPutAll: {key intern. arg}]] writingAs: #{}].
33   expansion :=
34     (macro selector sendTo: macro arguments
35       &optionals: (opts ; {#&environment:. env}))
36         macroExpand &environment: env.
37   macro lineNumber ifNotNilDo:
38     [| :lineNumber |
39      expansion walk:
40        [| :child | child lineNumber `defaultsTo: lineNumber]].
41   expansion
44 message@(nodes Message traits) macroExpand &optionals: opts &environment: env
45 "Replace each argument to the message with its macro-expanded value.
46 When appropriate substitute a LoadVariable or StoreVariable for the message."
47 [| expansion |
48   "Ensure macro expansions properly refer to Variables."
49   env ifNotNil:
50     [message == (expansion := env linkVariablesIn: message)
51        ifFalse: [^ (expansion macroExpand &optionals: opts &environment: env)]].
52   message arguments
53     doWithIndex:
54       [| :argument :index |
55        argument == (expansion := argument macroExpand &environment: env)
56          ifFalse: [message arguments at: index put: expansion]].
57   opts
58     ifNil: [message]
59     ifNotNil:
60       [opts message == message
61          ifFalse: [opts message := message].
62        opts arguments
63          doWithIndex:
64            [| :argument :index |
65             argument == (expansion := argument macroExpand &environment: env)
66               ifFalse:
67                 [opts arguments at: index put: expansion]].
68        opts]
71 opts@(nodes OptionalKeywords traits) macroExpand &environment: env
72 "Replace each argument to the optional keywords with its macro-expanded value."
74   opts message macroExpand &optionals: opts &environment: env
77 rest@(nodes RestArguments traits) macroExpand &environment: env
78 "Replace each rest argument with its macro-expanded value."
80   (rest for: (rest message macroExpand &environment: env)) `>>
81     [arguments := rest arguments collect:
82        [| :arg | arg macroExpand &environment: env]. ]
85 group@(nodes CompoundStatement traits) macroExpand &environment: env
86 "Replace the group's contents with their macro-expansions. This covers:
87 Arrays, Blocks, and Parentheses."
89   group statements
90     doWithIndex:
91       [| :statement :index expansion |
92        statement == (expansion := statement macroExpand &environment: env)
93          ifFalse:
94            [group statements at: index put: expansion]].
95   group
98 block@(nodes Block traits) macroExpand &environment: env
99 "Set up the environment optional parameter to use the block as its value,
100 and resend it on to handle the main structure."
102   env ifNotNil: [env linkVariablesIn: block].
103   env := block.
104   resend
107 method@(nodes MethodDefinition traits) macroExpand &environment: env
108 "MethodDefinition nodes must handle the additional complication of roles."
110   method roles
111     doWithIndex:
112       [| :role :index |
113        role ifNotNil:
114          [| expansion |
115           role == (expansion := role macroExpand &environment: env)
116             ifFalse: [method roles at: index put: expansion]]].
117   resend
120 load@(nodes LoadVariable traits) macroExpand &environment: env
122   env
123     ifNil: [load]
124     ifNotNil: [env linkVariablesIn: load]
127 store@(nodes StoreVariable traits) macroExpand &environment: env
128 "Expand the value to be stored."
129 [| expansion |
130   env ifNotNil:
131     [store == (expansion := env linkVariablesIn: store)
132        ifFalse: [^ (expansion macroExpand &environment: env)]].
133   store value == (expansion := store value macroExpand &environment: env)
134     ifFalse: [store value := expansion].
135   store
138 ret@(nodes Return traits) macroExpand &environment: env
139 "Expand the value to be returned."
140 [| expansion |
141   ret value == (expansion := ret value macroExpand &environment: env)
142     ifFalse: [ret value := expansion].
143   ret
146 _@(nodes Block traits) linkVariablesIn: node
148   node
151 b@(nodes Block traits) linkVariablesIn: load@(nodes LoadVariable traits)
153   (b includesScope: load variable scope)
154     ifTrue:
155       [load]
156     ifFalse:
157       [(b findVariable: load variable name)
158         ifNil:
159           [nodes UnaryMessage sending: load variable name to: {nodes ImplicitArgument}]
160         ifNotNilDo:
161           [| :var |
162            load variable := var.
163            load]]
166 b@(nodes Block traits) linkVariablesIn: store@(nodes StoreVariable traits)
168   (b includesScope: store variable scope)
169     ifTrue:
170       [store]
171     ifFalse:
172       [(b findVariable: store variable name)
173         ifNil:
174           [nodes KeywordMessage
175              sending: store variable name name ; ':'
176              to: {nodes ImplicitArgument. store value}]
177         ifNotNilDo:
178           [| :var |
179            store variable := var.
180            store]]
183 b@(nodes Block traits) linkVariablesIn: msg@(nodes UnaryMessage traits)
185   (msg arguments first isSameAs: nodes ImplicitArgument)
186     ifTrue: [(b findVariable: msg selector)
187                ifNil: [msg]
188                ifNotNilDo: #load `er]
189     ifFalse: [msg]
192 b@(nodes Block traits) linkVariablesIn: msg@(nodes KeywordMessage traits)
194   (msg arguments first isSameAs: nodes ImplicitArgument)
195     /\ [msg arguments size = 2]
196     ifTrue: [(b findVariable: msg selector name allButLast intern)
197                ifNil: [msg]
198                ifNotNilDo: [| :var | var store: msg arguments second]]
199     ifFalse: [msg]
202 parent@(nodes Block traits) linkVariablesIn: child@(nodes Block traits)
204   child parentScope == parent \/ [child == parent]
205     ifFalse: [child parentScope := parent].
206   child
209 b@(nodes Block traits) linkVariables
210 "Fixes up a Block syntax tree so that all message sends within which should
211 actually be loads and stores are turned into those corresponding expression
212 types. This works by recursing down the tree with linkVariablesIn:."
214    b transformBy: [| :node | b linkVariablesIn: node]