1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2015 Julien Pagès <julien.pages@lirmm.fr>
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
17 # Handle all numbering operations related to local variables in the Nit virtual machine
18 module variables_numbering
20 import virtual_machine
22 redef class VirtualMachine
24 # The frames of the VirtualMachine are specialized
25 redef type FRAME: VmFrame
27 # Number the variables in `n`.
28 # Do nothing if `n` is null
29 fun numbering
(n
: nullable AExpr, position
: Int): Int
31 if n
== null then return position
33 var pos
= n
.numbering
(self, position
)
37 # Redef to add the numbering of variables and arguments
38 redef fun new_frame
(node
, mpropdef
, args
)
40 var f
= new VmFrame(node
, mpropdef
, args
)
42 # If this Frame is for a method or an attribute block then number variables into the body of the method
43 if node
isa APropdef then
44 # Compile the code (number its local variables)
45 if not node
.is_compiled
then node
.compile
(self)
47 # Create an empty environment
48 f
.variables
= new Array[Instance].filled_with
(initialization_value
, node
.environment_size
)
51 # Putting self at the beginning of the environment
52 f
.variables
[0] = args
[0]
56 # Read a `Variable` from a frame by using its position
57 redef fun read_variable
(v
: Variable): Instance
59 return frame
.variables
[v
.position
]
62 # Assign the value of the `Variable` in an environment
63 redef fun write_variable
(v
: Variable, value
: Instance)
65 frame
.variables
[v
.position
] = value
70 # The position in the environment
71 var position
: Int is writable
74 # Implementation of a Frame with numbered variables
78 # Contains the value of Variables (which are numbered)
79 var variables
: Array[Instance] = new Array[Instance]
83 # Give a position to each variable declared in the node.
84 # NOTE: Do not call this method directly, but use `v.numbering`
85 # This method is here to be implemented by subclasses.
86 # *`v` The current instance of the virtual machine
87 # *`position` The first available position in the environment a variable can have
88 # Return the next available position a variable can have
89 public
fun numbering
(v
: VirtualMachine, position
: Int): Int
96 # Indicite if this propdef was compile
97 var is_compiled
: Bool = false
99 # Indicate if the variables numbering has been done
100 private var is_numbering
: Bool = false
102 # The size of the environment to create to call this method
103 private var environment_size
: Int = 0
105 # Compile this propdef
106 # *`vm` The running instance of `VirtualMachine`
107 fun compile
(vm
: VirtualMachine)
109 # Number the variables
110 if not is_numbering
then numbering_variables
(vm
)
115 # Numbering the variable inside the propdef
116 fun numbering_variables
(vm
: VirtualMachine) is abstract
119 redef class AMethPropdef
120 # Assign a position in the environment to each local variable
121 # *`vm` The current VirtualMachine
122 redef fun numbering_variables
(vm
: VirtualMachine)
124 # The position in the environment
127 # The `self` variable has the first position
128 if self.selfvariable
!= null then
129 self.selfvariable
.position
= position
133 # Number the parameters
134 for i
in [0..mpropdef
.msignature
.arity
[ do
135 var variable
= self.n_signature
.n_params
[i
].variable
136 variable
.as(not null).position
= position
140 # Recursively go into the AST nodes to number all local variables
141 if n_block
!= null then
142 position
= vm
.numbering
(self.n_block
, position
)
147 # The size of the environment to create to execute a call to this method
148 environment_size
= position
152 redef class AAttrPropdef
153 # Assign a position in the environment to each local variable
154 # *`vm` The current VirtualMachine
155 redef fun numbering_variables
(vm
: VirtualMachine)
157 # The position in the environment
160 # The `self` variable has the first position
161 if self.selfvariable
!= null then
162 self.selfvariable
.position
= position
166 # Recursively go into the AST nodes to number all local variables
167 if n_block
!= null then
168 position
= vm
.numbering
(self.n_block
, position
)
173 # The size of the environment to create to execute a call to this method
174 environment_size
= position
178 redef class AVardeclExpr
179 redef fun numbering
(v
, position
)
181 # Attribute a position to this variable
182 self.variable
.as(not null).position
= position
185 # Recursively continue to numbering the variables
186 position
= v
.numbering
(self.n_expr
, position
)
188 # `position` is the next available position in the environment
193 redef class ABlockExpr
194 redef fun numbering
(v
, position
)
196 for e
in self.n_expr
do
197 position
= v
.numbering
(e
, position
)
204 redef fun numbering
(v
, position
)
206 # Attribute numbers separetely for the two branches
207 var pos
= v
.numbering
(self.n_then
, position
)
208 var pos1
= v
.numbering
(self.n_else
, position
)
218 redef class AIfexprExpr
219 redef fun numbering
(v
, position
)
221 # Attribute numbers separetely for the two branches
222 var pos
= v
.numbering
(self.n_then
, position
)
223 var pos1
= v
.numbering
(self.n_else
, position
)
234 redef fun numbering
(v
, position
)
236 return v
.numbering
(self.n_block
, position
)
240 redef class AWhileExpr
241 redef fun numbering
(v
, position
)
243 return v
.numbering
(self.n_block
, position
)
247 redef class ALoopExpr
248 redef fun numbering
(v
, position
)
250 return v
.numbering
(self.n_block
, position
)
255 redef fun numbering
(v
, position
)
257 # Give a position to each variable declared in the header of the for
258 if self.variables
.length
== 1 then
259 self.variables
.first
.position
= position
260 self.variables
[0].position
= position
262 else if self.variables
.length
== 2 then
263 self.variables
[0].position
= position
265 self.variables
[1].position
= position
268 return v
.numbering
(self.n_block
, position
)
272 redef class AArrayExpr
273 redef fun numbering
(v
, position
)
275 for nexpr
in self.n_exprs
do
276 position
= v
.numbering
(nexpr
, position
)