1 # This file is part of NIT ( http://www.nitlanguage.org ).
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
7 # http://www.apache.org/licenses/LICENSE-2.0
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.
15 # Instantiation and transformation of semantic nodes in the AST of expressions and statements
19 intrude import literal
23 # General factory to build semantic nodes in the AST of expressions
25 # The module used as reference for the building
26 # It is used to gather types and other stufs
29 # The anchor used for some mechanism relying on types
30 var anchor
: nullable MClassType
32 # Make a new Int literal
33 fun make_int
(value
: Int): AIntExpr
35 return new AIntExpr.make
(value
, mmodule
.get_primitive_class
("Int").mclass_type
)
38 # Make a new instatiation
39 fun make_new
(mtype
: MClassType, constructor
: MMethod, args
: nullable Array[AExpr]): ANewExpr
41 return new ANewExpr.make
(mtype
, constructor
, args
)
44 # Make a new message send
45 fun make_call
(recv
: AExpr, mmethod
: MMethod, args
: nullable Array[AExpr]): ACallExpr
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
)
52 # Make a new, empty, sequence of statements
53 fun make_block
: ABlockExpr
55 return new ABlockExpr.make
58 # Make a new variable read
59 fun make_var_read
(variable
: Variable, mtype
: MType): AVarExpr
61 return new AVarExpr.make
(variable
, mtype
)
64 # Make a new variable assignment
65 fun make_var_assign
(variable
: Variable, value
: AExpr): AVarAssignExpr
67 return new AVarAssignExpr.make
(variable
, value
)
70 # Make a new attribute read
71 fun make_attr_read
(recv
: AExpr, attribute
: MAttribute): AAttrExpr
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
)
77 # Make a new attribute assignment
78 fun make_attr_assign
(recv
: AExpr, attribute
: MAttribute, value
: AExpr): AAttrAssignExpr
80 return new AAttrAssignExpr.make
(recv
, attribute
, value
)
83 # Make a new escapable block
86 return new ADoExpr.make
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
93 return new AIfExpr.make
(condition
, mtype
)
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
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
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
115 return new AVarExpr.make
(variable
, variable
.declared_type
.as(not null))
118 private var variable_cache
: nullable Variable
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.
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.
129 # var h = c.detach_with_placeholder
130 # var n = astbuilder.make_XXX(c)
132 fun detach_with_placeholder
: AExpr
134 var h
= new APlaceholderExpr.make
140 # Add `expr` at the end of the block
142 # REQUIRE: self isa ABlockExpr
144 # Note: this method, aimed to `ABlockExpr` is promoted to `AExpr` because of the limitations of the hierarchies generated by sablecc3
151 # A placeholder for a `AExpr` node
152 # Instances are transiantly used to mark some specific emplacments in the AST
153 # during complex transformations.
155 # Their must not appear in a valid AST
157 # @see AExpr::detach_with_placeholder
158 class APlaceholderExpr
165 redef class ABlockExpr
171 redef fun add
(expr
: AExpr)
181 escapemark
= new EscapeMark(null, false)
184 # Make a new break expression of the given do
185 fun make_break
: ABreakExpr
187 var escapemark
= self.escapemark
188 if escapemark
== null then
189 escapemark
= new EscapeMark(null, false)
190 self.escapemark
= escapemark
192 return new ABreakExpr.make
(escapemark
)
196 redef class ABreakExpr
197 private init make
(escapemark
: EscapeMark)
199 self.escapemark
= escapemark
204 private init make
(condition
: AExpr, mtype
: nullable MType)
208 _n_expr
.parent
= self
209 _n_then
= new ABlockExpr.make
210 _n_else
= new ABlockExpr.make
224 private init make
(value
: Int, t
: MType)
227 self._n_number
= new TNumber # dummy
233 private init make
(mtype
: MClassType, mmethod
: MMethod, args
: nullable Array[AExpr])
235 _n_kwnew
= new TKwnew
236 _n_type
= new AType.make
237 _n_args
= new AListExprs
239 n_args
.n_exprs
.add_all
(args
)
241 callsite
= new CallSite(self, mtype
, true, mmethod
, mmethod
.intro
, mmethod
.intro
.msignature
.as(not null), false)
246 redef class ACallExpr
247 private init make
(recv
: AExpr, mmethod
: MMethod, args
: nullable Array[AExpr], t
: nullable MType)
251 self.raw_arguments
= args
or else new Array[AExpr]
252 _n_args
= new AListExprs
255 self.n_args
.n_exprs
.add_all
(args
)
257 var mtype
= recv
.mtype
.as(not null)
258 callsite
= new CallSite(self, mtype
, true, mmethod
, mmethod
.intro
, mmethod
.intro
.msignature
.as(not null), false)
264 redef class AAttrExpr
265 private init make
(recv
: AExpr, attribute
: MAttribute, t
: MType)
270 mproperty
= attribute
275 redef class AAttrAssignExpr
276 private init make
(recv
: AExpr, attribute
: MAttribute, value
: AExpr)
283 _n_assign
= new TAssign
284 mproperty
= attribute
290 private init make
(v
: Variable, mtype
: MType)
298 redef class AVarAssignExpr
299 private init make
(v
: Variable, value
: AExpr)
304 _n_assign
= new TAssign