astbuilder: `make_new` and `make_call` require a CallSite
[nit.git] / src / astbuilder.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 # Instantiation and transformation of semantic nodes in the AST of expressions and statements
16 module astbuilder
17
18 intrude import typing
19 intrude import literal
20 intrude import parser
21 intrude import scope
22
23 # General factory to build semantic nodes in the AST of expressions
24 class ASTBuilder
25 # The module used as reference for the building
26 # It is used to gather types and other stufs
27 var mmodule: MModule
28
29 # The anchor used for some mechanism relying on types
30 var anchor: nullable MClassType
31
32 # Make a new Int literal
33 fun make_int(value: Int): AIntExpr
34 do
35 return new ADecIntExpr.make(value, mmodule.get_primitive_class("Int").mclass_type)
36 end
37
38 # Make a new instatiation
39 fun make_new(callsite: CallSite, args: nullable Array[AExpr]): ANewExpr
40 do
41 return new ANewExpr.make(callsite, args)
42 end
43
44 # Make a new message send
45 fun make_call(recv: AExpr, callsite: CallSite, args: nullable Array[AExpr]): ACallExpr
46 do
47 return new ACallExpr.make(recv, callsite, args)
48 end
49
50 # Make a new, empty, sequence of statements
51 fun make_block: ABlockExpr
52 do
53 return new ABlockExpr.make
54 end
55
56 # Make a new variable read
57 fun make_var_read(variable: Variable, mtype: MType): AVarExpr
58 do
59 return new AVarExpr.make(variable, mtype)
60 end
61
62 # Make a new variable assignment
63 fun make_var_assign(variable: Variable, value: AExpr): AVarAssignExpr
64 do
65 return new AVarAssignExpr.make(variable, value)
66 end
67
68 # Make a new attribute read
69 fun make_attr_read(recv: AExpr, attribute: MAttribute): AAttrExpr
70 do
71 var mtype = attribute.intro.static_mtype.resolve_for(recv.mtype.as(not null), anchor, mmodule, true)
72 return new AAttrExpr.make(recv, attribute, mtype)
73 end
74
75 # Make a new attribute assignment
76 fun make_attr_assign(recv: AExpr, attribute: MAttribute, value: AExpr): AAttrAssignExpr
77 do
78 return new AAttrAssignExpr.make(recv, attribute, value)
79 end
80
81 # Make a new escapable block
82 fun make_do: ADoExpr
83 do
84 return new ADoExpr.make
85 end
86
87 # Make a new condinionnal
88 # `mtype` is the return type of the whole if, in case of a ternary operator.
89 fun make_if(condition: AExpr, mtype: nullable MType): AIfExpr
90 do
91 return new AIfExpr.make(condition, mtype)
92 end
93 end
94
95 redef class AExpr
96 # Return a new variable read that contains the value of the expression
97 # This method take care efficiently of creating and initalising an anonymous local variable
98 #
99 # Note: since this method do side-effects (AST replacement), there could be unexpected effects when used as
100 # argument of other methods related to AST transformations.
101 fun make_var_read: AVarExpr
102 do
103 var variable = self.variable_cache
104 if variable == null then
105 assert parent != null
106 var place = detach_with_placeholder
107 variable = new Variable("")
108 variable.declared_type = self.mtype
109 var nvar = new AVarAssignExpr.make(variable, self)
110 place.replace_with(nvar)
111 self.variable_cache = variable
112 end
113 return new AVarExpr.make(variable, variable.declared_type.as(not null))
114 end
115
116 private var variable_cache: nullable Variable
117
118 # The `detach` method completely remove the node in the parent.
119 # Owever, sometime, it is useful to keep the emplacement of the removed child.
120 #
121 # The standard usecase is the insertion of a node beetwen a parent `p` and a child `p.c`.
122 # To create the new node `n`, we need to attach the child to it.
123 # But, to put `n` where `c` was in `p`, the place has to be remembered.
124 #
125 # var p: AExpr
126 # var c = p.c
127 # var h = c.detach_with_placeholder
128 # var n = astbuilder.make_XXX(c)
129 # h.replace_with(n)
130 fun detach_with_placeholder: AExpr
131 do
132 var h = new APlaceholderExpr.make
133 self.replace_with(h)
134 return h
135 end
136
137
138 # Add `expr` at the end of the block
139 #
140 # REQUIRE: self isa ABlockExpr
141 #
142 # Note: this method, aimed to `ABlockExpr` is promoted to `AExpr` because of the limitations of the hierarchies generated by sablecc3
143 fun add(expr: AExpr)
144 do
145 abort
146 end
147 end
148
149 # A placeholder for a `AExpr` node
150 # Instances are transiantly used to mark some specific emplacments in the AST
151 # during complex transformations.
152 #
153 # Their must not appear in a valid AST
154 #
155 # @see AExpr::detach_with_placeholder
156 class APlaceholderExpr
157 super AExpr
158 private init make
159 do
160 end
161 end
162
163 redef class ABlockExpr
164 private init make
165 do
166 self.is_typed = true
167 end
168
169 redef fun add(expr: AExpr)
170 do
171 n_expr.add expr
172 end
173 end
174
175 redef class ADoExpr
176 private init make
177 do
178 _n_kwdo = new TKwdo
179 escapemark = new EscapeMark(null, false)
180 end
181
182 # Make a new break expression of the given do
183 fun make_break: ABreakExpr
184 do
185 var escapemark = self.escapemark
186 if escapemark == null then
187 escapemark = new EscapeMark(null, false)
188 self.escapemark = escapemark
189 end
190 return new ABreakExpr.make(escapemark)
191 end
192 end
193
194 redef class ABreakExpr
195 private init make(escapemark: EscapeMark)
196 do
197 self.escapemark = escapemark
198 end
199 end
200
201 redef class AIfExpr
202 private init make(condition: AExpr, mtype: nullable MType)
203 do
204 _n_kwif = new TKwif
205 _n_expr = condition
206 _n_expr.parent = self
207 _n_then = new ABlockExpr.make
208 _n_else = new ABlockExpr.make
209 self.mtype = mtype
210 self.is_typed = true
211 end
212 end
213
214 redef class AType
215 private init make
216 do
217 _n_id = new TClassid
218 end
219 end
220
221 redef class ADecIntExpr
222 private init make(value: Int, t: MType)
223 do
224 self.value = value
225 self._n_number = new TNumber # dummy
226 self.mtype = t
227 end
228 end
229
230 redef class ANewExpr
231 private init make(callsite: CallSite, args: nullable Array[AExpr])
232 do
233 _n_kwnew = new TKwnew
234 _n_type = new AType.make
235 _n_args = new AListExprs
236 if args != null then
237 n_args.n_exprs.add_all(args)
238 end
239 self.callsite = callsite
240 self.mtype = callsite.recv
241 self.is_typed = true
242 end
243 end
244
245 redef class ACallExpr
246 private init make(recv: AExpr, callsite: CallSite, args: nullable Array[AExpr])
247 do
248 self._n_expr = recv
249 _n_args = new AListExprs
250 _n_id = new TId
251 if args != null then
252 self.n_args.n_exprs.add_all(args)
253 end
254 var mtype = recv.mtype.as(not null)
255 self.callsite = callsite
256 self.mtype = callsite.msignature.return_mtype
257 self.is_typed = true
258 end
259 end
260
261 redef class AAttrExpr
262 private init make(recv: AExpr, attribute: MAttribute, t: MType)
263 do
264 _n_expr = recv
265 recv.parent = self
266 _n_id = new TAttrid
267 mproperty = attribute
268 mtype = t
269 end
270 end
271
272 redef class AAttrAssignExpr
273 private init make(recv: AExpr, attribute: MAttribute, value: AExpr)
274 do
275 _n_expr = recv
276 recv.parent = self
277 _n_id = new TAttrid
278 _n_value = value
279 value.parent = self
280 _n_assign = new TAssign
281 mproperty = attribute
282 mtype = value.mtype
283 end
284 end
285
286 redef class AVarExpr
287 private init make(v: Variable, mtype: MType)
288 do
289 _n_id = new TId
290 variable = v
291 self.mtype = mtype
292 end
293 end
294
295 redef class AVarAssignExpr
296 private init make(v: Variable, value: AExpr)
297 do
298 _n_id = new TId
299 _n_value = value
300 value.parent = self
301 _n_assign = new TAssign
302 variable = v
303 mtype = value.mtype
304 end
305 end
306