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 then number variables into the body of the method
43 if node
isa AMethPropdef then
44 # Number the variables
45 if not node
.is_numbering
then node
.numbering_variables
(self, mpropdef
.as(MMethodDef))
47 # Create an empty environment
48 f
.variables
= new Array[Instance].filled_with
(initialization_value
, node
.environment_size
)
51 # If this Frame is for an attribute with a block then number the block
52 if node
isa AAttrPropdef then
53 # Number the variables
54 if not node
.is_numbering
then node
.numbering_variables
(self)
56 # Create an empty environment
57 f
.variables
= new Array[Instance].filled_with
(initialization_value
, node
.environment_size
)
60 # Putting self at the beginning of the environment
61 f
.variables
[0] = args
[0]
65 # Read a `Variable` from a frame by using its position
66 redef fun read_variable
(v
: Variable): Instance
68 return frame
.variables
[v
.position
]
71 # Assign the value of the `Variable` in an environment
72 redef fun write_variable
(v
: Variable, value
: Instance)
74 frame
.variables
[v
.position
] = value
79 # The position in the environment
83 # Implementation of a Frame with numbered variables
87 # Contains the value of Variables (which are numbered)
88 var variables
: Array[Instance] = new Array[Instance]
92 # Give a position to each variable declared in the node.
93 # NOTE: Do not call this method directly, but use `v.numbering`
94 # This method is here to be implemented by subclasses.
95 # *`v` The current instance of the virtual machine
96 # *`position` The first available position in the environment a variable can have
97 # Return the next available position a variable can have
98 public
fun numbering
(v
: VirtualMachine, position
: Int): Int
105 # Indicate if the variables numbering has been done
106 private var is_numbering
: Bool = false
108 # The size of the environment to create to call this method
109 private var environment_size
: Int = 0
112 redef class AMethPropdef
113 # Assign a position in the environment to each local variable of `mpropdef`
114 # *`v` The current VirtualMachine
115 # *`mpropdef` The method to number
116 private fun numbering_variables
(v
: VirtualMachine, mpropdef
: MMethodDef)
118 # The position in the environment
121 # The `self` variable has the first position
122 if self.selfvariable
!= null then
123 self.selfvariable
.position
= position
127 # Number the parameters
128 for i
in [0..mpropdef
.msignature
.arity
[ do
129 var variable
= self.n_signature
.n_params
[i
].variable
130 variable
.as(not null).position
= position
134 # Recursively go into the AST nodes to number all local variables
135 if n_block
!= null then
136 position
= v
.numbering
(self.n_block
, position
)
141 # The size of the environment to create to execute a call to this method
142 environment_size
= position
146 redef class AAttrPropdef
147 # Assign a position in the environment to each local variable of `mpropdef`
148 # *`v` The current VirtualMachine
149 private fun numbering_variables
(v
: VirtualMachine)
151 # The position in the environment
154 # The `self` variable has the first position
155 if self.selfvariable
!= null then
156 self.selfvariable
.position
= position
160 # Recursively go into the AST nodes to number all local variables
161 if n_block
!= null then
162 position
= v
.numbering
(self.n_block
, position
)
167 # The size of the environment to create to execute a call to this method
168 environment_size
= position
172 redef class AVardeclExpr
173 redef fun numbering
(v
, position
)
175 # Attribute a position to this variable
176 self.variable
.as(not null).position
= position
179 # Recursively continue to numbering the variables
180 position
= v
.numbering
(self.n_expr
, position
)
182 # `position` is the next available position in the environment
187 redef class ABlockExpr
188 redef fun numbering
(v
, position
)
190 for e
in self.n_expr
do
191 position
= v
.numbering
(e
, position
)
198 redef fun numbering
(v
, position
)
200 # Attribute numbers separetely for the two branches
201 var pos
= v
.numbering
(self.n_then
, position
)
202 var pos1
= v
.numbering
(self.n_else
, position
)
212 redef class AIfexprExpr
213 redef fun numbering
(v
, position
)
215 # Attribute numbers separetely for the two branches
216 var pos
= v
.numbering
(self.n_then
, position
)
217 var pos1
= v
.numbering
(self.n_else
, position
)
228 redef fun numbering
(v
, position
)
230 return v
.numbering
(self.n_block
, position
)
234 redef class AWhileExpr
235 redef fun numbering
(v
, position
)
237 return v
.numbering
(self.n_block
, position
)
241 redef class ALoopExpr
242 redef fun numbering
(v
, position
)
244 return v
.numbering
(self.n_block
, position
)
249 redef fun numbering
(v
, position
)
251 # Give a position to each variable declared in the header of the for
252 if self.variables
.length
== 1 then
253 self.variables
.first
.position
= position
254 self.variables
[0].position
= position
256 else if self.variables
.length
== 2 then
257 self.variables
[0].position
= position
259 self.variables
[1].position
= position
262 return v
.numbering
(self.n_block
, position
)
266 redef class AArrayExpr
267 redef fun numbering
(v
, position
)
269 for nexpr
in self.n_exprs
do
270 position
= v
.numbering
(nexpr
, position
)