model: `new` factories have a return type.
[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 semantize::typing
19 intrude import semantize::literal
20 intrude import semantize::parser
21 intrude import semantize::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, empty, loop of statements
57 fun make_loop: ALoopExpr
58 do
59 return new ALoopExpr.make
60 end
61
62 # Make a new variable read
63 fun make_var_read(variable: Variable, mtype: MType): AVarExpr
64 do
65 return new AVarExpr.make(variable, mtype)
66 end
67
68 # Make a new variable assignment
69 fun make_var_assign(variable: Variable, value: AExpr): AVarAssignExpr
70 do
71 return new AVarAssignExpr.make(variable, value)
72 end
73
74 # Make a new attribute read
75 fun make_attr_read(recv: AExpr, attribute: MAttribute): AAttrExpr
76 do
77 var mtype = attribute.intro.static_mtype.resolve_for(recv.mtype.as(not null), anchor, mmodule, true)
78 return new AAttrExpr.make(recv, attribute, mtype)
79 end
80
81 # Make a new attribute assignment
82 fun make_attr_assign(recv: AExpr, attribute: MAttribute, value: AExpr): AAttrAssignExpr
83 do
84 return new AAttrAssignExpr.make(recv, attribute, value)
85 end
86
87 # Make a new escapable block
88 fun make_do: ADoExpr
89 do
90 return new ADoExpr.make
91 end
92
93 # Make a new break for a given escapemark
94 fun make_break(escapemark: EscapeMark): ABreakExpr
95 do
96 return new ABreakExpr.make(escapemark)
97 end
98
99 # Make a new condinionnal
100 # `mtype` is the return type of the whole if, in case of a ternary operator.
101 fun make_if(condition: AExpr, mtype: nullable MType): AIfExpr
102 do
103 return new AIfExpr.make(condition, mtype)
104 end
105 end
106
107 redef class AExpr
108 # Return a new variable read that contains the value of the expression
109 # This method take care efficiently of creating and initalising an anonymous local variable
110 #
111 # Note: since this method do side-effects (AST replacement), there could be unexpected effects when used as
112 # argument of other methods related to AST transformations.
113 fun make_var_read: AVarExpr
114 do
115 var variable = self.variable_cache
116 if variable == null then
117 assert parent != null
118 var place = detach_with_placeholder
119 variable = new Variable("")
120 variable.declared_type = self.mtype
121 var nvar = new AVarAssignExpr.make(variable, self)
122 place.replace_with(nvar)
123 self.variable_cache = variable
124 end
125 return new AVarExpr.make(variable, variable.declared_type.as(not null))
126 end
127
128 private var variable_cache: nullable Variable
129
130 # The `detach` method completely remove the node in the parent.
131 # Owever, sometime, it is useful to keep the emplacement of the removed child.
132 #
133 # The standard usecase is the insertion of a node beetwen a parent `p` and a child `p.c`.
134 # To create the new node `n`, we need to attach the child to it.
135 # But, to put `n` where `c` was in `p`, the place has to be remembered.
136 #
137 # var p: AExpr
138 # var c = p.c
139 # var h = c.detach_with_placeholder
140 # var n = astbuilder.make_XXX(c)
141 # h.replace_with(n)
142 fun detach_with_placeholder: AExpr
143 do
144 var h = new APlaceholderExpr.make
145 self.replace_with(h)
146 return h
147 end
148
149
150 # Add `expr` at the end of the block
151 #
152 # REQUIRE: self isa ABlockExpr
153 #
154 # Note: this method, aimed to `ABlockExpr` is promoted to `AExpr` because of the limitations of the hierarchies generated by sablecc3
155 fun add(expr: AExpr)
156 do
157 print "add not implemented in {inspect}"
158 abort
159 end
160 end
161
162 # A placeholder for a `AExpr` node
163 # Instances are transiantly used to mark some specific emplacments in the AST
164 # during complex transformations.
165 #
166 # Their must not appear in a valid AST
167 #
168 # @see AExpr::detach_with_placeholder
169 class APlaceholderExpr
170 super AExpr
171 private init make
172 do
173 end
174 end
175
176 redef class ABlockExpr
177 private init make
178 do
179 self.is_typed = true
180 end
181
182 redef fun add(expr: AExpr)
183 do
184 n_expr.add expr
185 end
186 end
187
188 redef class ALoopExpr
189 private init make
190 do
191 _n_kwloop = new TKwloop
192 self.is_typed = true
193 n_block = new ABlockExpr
194 n_block.is_typed = true
195 end
196
197 redef fun add(expr: AExpr)
198 do
199 n_block.add expr
200 end
201 end
202
203 redef class ADoExpr
204 private init make
205 do
206 _n_kwdo = new TKwdo
207 self.is_typed = true
208 n_block = new ABlockExpr
209 n_block.is_typed = true
210 end
211
212 # Make a new break expression of the given do
213 fun make_break: ABreakExpr
214 do
215 var escapemark = self.break_mark
216 if escapemark == null then
217 escapemark = new EscapeMark(null)
218 self.break_mark = escapemark
219 end
220 return new ABreakExpr.make(escapemark)
221 end
222
223 redef fun add(expr: AExpr)
224 do
225 n_block.add expr
226 end
227 end
228
229 redef class ABreakExpr
230 private init make(escapemark: EscapeMark)
231 do
232 _n_kwbreak = new TKwbreak
233 self.escapemark = escapemark
234 escapemark.escapes.add self
235 self.is_typed = true
236 end
237 end
238
239 redef class AIfExpr
240 private init make(condition: AExpr, mtype: nullable MType)
241 do
242 _n_kwif = new TKwif
243 _n_expr = condition
244 _n_expr.parent = self
245 _n_then = new ABlockExpr.make
246 _n_else = new ABlockExpr.make
247 self.mtype = mtype
248 self.is_typed = true
249 end
250 end
251
252 redef class AType
253 private init make
254 do
255 _n_id = new TClassid
256 end
257 end
258
259 redef class ADecIntExpr
260 private init make(value: Int, t: MType)
261 do
262 self.value = value
263 self._n_number = new TNumber # dummy
264 self.mtype = t
265 end
266 end
267
268 redef class ANewExpr
269 private init make(callsite: CallSite, args: nullable Array[AExpr])
270 do
271 _n_kwnew = new TKwnew
272 _n_type = new AType.make
273 _n_args = new AListExprs
274 if args != null then
275 n_args.n_exprs.add_all(args)
276 end
277 self.callsite = callsite
278 if callsite.mproperty.is_new then
279 self.mtype = callsite.msignature.return_mtype
280 else
281 self.mtype = callsite.recv
282 end
283 self.is_typed = true
284 end
285 end
286
287 redef class ACallExpr
288 private init make(recv: AExpr, callsite: CallSite, args: nullable Array[AExpr])
289 do
290 self._n_expr = recv
291 _n_args = new AListExprs
292 _n_id = new TId
293 if args != null then
294 self.n_args.n_exprs.add_all(args)
295 end
296 self.callsite = callsite
297 self.mtype = callsite.msignature.return_mtype
298 self.is_typed = true
299 end
300 end
301
302 redef class AAttrExpr
303 private init make(recv: AExpr, attribute: MAttribute, t: MType)
304 do
305 _n_expr = recv
306 recv.parent = self
307 _n_id = new TAttrid
308 mproperty = attribute
309 mtype = t
310 end
311 end
312
313 redef class AAttrAssignExpr
314 private init make(recv: AExpr, attribute: MAttribute, value: AExpr)
315 do
316 _n_expr = recv
317 recv.parent = self
318 _n_id = new TAttrid
319 _n_value = value
320 value.parent = self
321 _n_assign = new TAssign
322 mproperty = attribute
323 mtype = value.mtype
324 end
325 end
326
327 redef class AVarExpr
328 private init make(v: Variable, mtype: MType)
329 do
330 _n_id = new TId
331 variable = v
332 self.mtype = mtype
333 end
334 end
335
336 redef class AVarAssignExpr
337 private init make(v: Variable, value: AExpr)
338 do
339 _n_id = new TId
340 _n_value = value
341 value.parent = self
342 _n_assign = new TAssign
343 variable = v
344 mtype = value.mtype
345 end
346 end
347