transform: disable transform of ASuperstringExpr
[nit.git] / src / transform.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 # Thansformations that simplify the AST of expressions
16 # This module transform complex AST `AExpr` nodes into simplier ones
17 module transform
18
19 import astbuilder
20 import auto_super_init
21 import astvalidation
22
23 redef class ToolContext
24 var transform_phase: Phase = new TransformPhase(self, [typing_phase, auto_super_init_phase])
25 end
26
27 private class TransformPhase
28 super Phase
29
30 redef fun process_npropdef(npropdef: APropdef)
31 do
32 var val
33
34 var v = new TransformVisitor(self, npropdef)
35 v.enter_visit(npropdef)
36
37 val = new ASTValidationVisitor
38 val.enter_visit(npropdef)
39 end
40 end
41
42 private class TransformVisitor
43 super Visitor
44
45 var phase: TransformPhase
46 var mmodule: MModule
47 var mclassdef: MClassDef
48 var mpropdef: MPropDef
49 var builder: ASTBuilder
50
51 init(phase: TransformPhase, npropdef: APropdef)
52 do
53 self.phase = phase
54 self.mpropdef = npropdef.mpropdef.as(not null)
55 self.mclassdef = mpropdef.mclassdef
56 self.mmodule = mclassdef.mmodule
57 self.builder = new ASTBuilder(mmodule, mpropdef.mclassdef.bound_mtype)
58 end
59
60 redef fun visit(node)
61 do
62 if node isa AAnnotations then return
63 node.visit_all(self)
64 node.accept_transform_visitor(self)
65 end
66
67 # Get a primitive class or display a fatal error on `location`.
68 fun get_class(location: AExpr, name: String): MClass
69 do
70 return mmodule.get_primitive_class(name)
71 end
72
73 # Get a primitive method or display a fatal error on `location`.
74 fun get_method(location: AExpr, name: String, recv: MClass): MMethod
75 do
76 return phase.toolcontext.modelbuilder.force_get_primitive_method(location, name, recv, mmodule)
77 end
78 end
79
80 redef class ANode
81 private fun accept_transform_visitor(v: TransformVisitor)
82 do
83 end
84 end
85
86 redef class AVardeclExpr
87 # `var x = y` is replaced with `x = y`
88 #
89 # Declarations are only useful for scope rules
90 # Once names are associated with real objects, ther declaration become useless
91 # Therefore, if there is no initial value, then just ignore it
92 # Else, replace it with a simple assignment
93 redef fun accept_transform_visitor(v)
94 do
95 var nexpr = n_expr
96 if nexpr == null then
97 # do nothing
98 # note: not detached because the collection is currently under iteration
99 else
100 var nvar = v.builder.make_var_assign(self.variable.as(not null), nexpr)
101 replace_with(nvar)
102 end
103 end
104 end
105
106 redef class AIfexprExpr
107 # is replaced with `AIfExpr`
108 # Expression if and statement-if use two distinct classes for historical reasons
109 # However, on can replace the `AIfexprExpr` with the simpler `AIfExpr`
110 redef fun accept_transform_visitor(v)
111 do
112 var nif = v.builder.make_if(n_expr, self.mtype)
113 nif.n_then.add(n_then)
114 nif.n_else.add(n_else)
115
116 replace_with(nif)
117 end
118 end
119
120 redef class AOrExpr
121 # `x or y` is replaced with `if x then x else y`
122 redef fun accept_transform_visitor(v)
123 do
124 var nif = v.builder.make_if(n_expr, self.mtype)
125 nif.n_then.add(n_expr.make_var_read)
126 nif.n_else.add(n_expr2)
127
128 replace_with(nif)
129 end
130 end
131
132 redef class AImpliesExpr
133 redef fun accept_transform_visitor(v)
134 do
135 # TODO
136 end
137 end
138
139 redef class AAndExpr
140 # `x and y` is replaced with `if x then y else x`
141 redef fun accept_transform_visitor(v)
142 do
143 var nif = v.builder.make_if(n_expr, self.mtype)
144 nif.n_then.add(n_expr2)
145 nif.n_else.add(n_expr.make_var_read)
146
147 replace_with(nif)
148 end
149 end
150
151 redef class AWhileExpr
152 redef fun accept_transform_visitor(v)
153 do
154 # TODO
155 end
156 end
157
158 redef class AForExpr
159 redef fun accept_transform_visitor(v)
160 do
161 # TODO
162 end
163 end
164
165 redef class AArrayExpr
166 # `[x,y]` is replaced with
167 #
168 # var t = new Array[X].with_capacity(2)
169 # t.add(x)
170 # t.add(y)
171 # t
172 redef fun accept_transform_visitor(v)
173 do
174 var mtype = self.mtype.as(MClassType)
175 var nblock = v.builder.make_block
176
177 var meth = v.get_method(self, "with_capacity", mtype.mclass)
178 var nnew = v.builder.make_new(mtype, meth, [v.builder.make_int(n_exprs.n_exprs.length)])
179 nblock.add nnew
180
181 var madd = v.get_method(self, "push", mtype.mclass)
182 for nexpr in self.n_exprs.n_exprs do
183 var nadd = v.builder.make_call(nnew.make_var_read, madd, [nexpr])
184 nblock.add nadd
185 end
186 var nres = nnew.make_var_read
187 nblock.add nres
188
189 replace_with(nblock)
190 end
191 end
192
193 redef class ASuperstringExpr
194 # `"x{y}z"` is replaced with
195 #
196 # var t = new Array[Object].with_capacity(3)
197 # t.add("x")
198 # t.add(y)
199 # t.add("z")
200 # t.to_s
201 redef fun accept_transform_visitor(v)
202 do
203 if true then return # FIXME: transformation disabled for the moment
204
205 var nblock = v.builder.make_block
206
207 var arraytype = v.get_class(self, "Array").get_mtype([v.get_class(self, "Object").mclass_type])
208 var meth = v.get_method(self, "with_capacity", arraytype.mclass)
209 var nnew = v.builder.make_new(arraytype, meth, [v.builder.make_int(n_exprs.length)])
210 nblock.add nnew
211
212 var madd = v.get_method(self, "add", arraytype.mclass)
213 for nexpr in self.n_exprs do
214 var nadd = v.builder.make_call(nnew.make_var_read, madd, [nexpr])
215 nblock.add nadd
216 end
217
218 var mtos = v.get_method(self, "to_s", arraytype.mclass)
219 var ntos = v.builder.make_call(nnew.make_var_read, mtos, null)
220 nblock.add ntos
221
222 replace_with(nblock)
223 end
224 end
225
226 redef class ACrangeExpr
227 # `[x..y]` is replaced with `new Range[X](x,y)`
228 redef fun accept_transform_visitor(v)
229 do
230 var mtype = self.mtype.as(MClassType)
231 replace_with(v.builder.make_new(mtype, init_callsite.mproperty, [n_expr, n_expr2]))
232 end
233 end
234
235 redef class AOrangeExpr
236 # `[x..y[` is replaced with `new Range[X].without_last(x,y)`
237 redef fun accept_transform_visitor(v)
238 do
239 var mtype = self.mtype.as(MClassType)
240 replace_with(v.builder.make_new(mtype, init_callsite.mproperty, [n_expr, n_expr2]))
241 end
242 end
243
244 redef class AParExpr
245 # `(x)` is replaced with `x`
246 redef fun accept_transform_visitor(v)
247 do
248 replace_with(n_expr)
249 end
250 end
251
252 redef class ASendReassignFormExpr
253 # `x.foo(y)+=z` is replaced with
254 #
255 # x.foo(y) = x.foo(y) + z
256 #
257 # witch is, in reality:
258 #
259 # x."foo="(y, x.foo(y)."+"(z))
260 redef fun accept_transform_visitor(v)
261 do
262 var nblock = v.builder.make_block
263 nblock.add(n_expr)
264
265 var read_args = new Array[AExpr]
266 var write_args = new Array[AExpr]
267 for a in raw_arguments.as(not null) do
268 nblock.add(a)
269 read_args.add(a.make_var_read)
270 write_args.add(a.make_var_read)
271 end
272
273 var nread = v.builder.make_call(n_expr.make_var_read, callsite.mproperty, read_args)
274
275 var nnewvalue = v.builder.make_call(nread, reassign_callsite.mproperty, [n_value])
276
277 write_args.add(nnewvalue)
278 var nwrite = v.builder.make_call(n_expr.make_var_read, write_callsite.mproperty, write_args)
279 nblock.add(nwrite)
280
281 replace_with(nblock)
282 end
283 end
284
285 redef class AVarReassignExpr
286 # `v += z` is replaced with `v = v + z`
287 redef fun accept_transform_visitor(v)
288 do
289 var variable = self.variable.as(not null)
290
291 var nread = v.builder.make_var_read(variable, read_type.as(not null))
292
293 var nnewvalue = v.builder.make_call(nread, reassign_callsite.mproperty, [n_value])
294 var nwrite = v.builder.make_var_assign(variable, nnewvalue)
295
296 replace_with(nwrite)
297 end
298 end
299
300 redef class AAttrReassignExpr
301 # `x.a += z` is replaced with `x.a = x.a + z`
302 redef fun accept_transform_visitor(v)
303 do
304 var nblock = v.builder.make_block
305 nblock.add(n_expr)
306 var attribute = self.mproperty.as(not null)
307
308 var nread = v.builder.make_attr_read(n_expr.make_var_read, attribute)
309 var nnewvalue = v.builder.make_call(nread, reassign_callsite.mproperty, [n_value])
310 var nwrite = v.builder.make_attr_assign(n_expr.make_var_read, attribute, nnewvalue)
311 nblock.add(nwrite)
312
313 replace_with(nblock)
314 end
315 end