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