Rename REAMDE to README.md
[nit.git] / src / vm / variables_numbering.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2015 Julien Pagès <julien.pages@lirmm.fr>
4 #
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
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
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.
16
17 # Handle all numbering operations related to local variables in the Nit virtual machine
18 module variables_numbering
19
20 import virtual_machine
21
22 redef class VirtualMachine
23
24 # The frames of the VirtualMachine are specialized
25 redef type FRAME: VmFrame
26
27 # Number the variables in `n`.
28 # Do nothing if `n` is null
29 fun numbering(n: nullable AExpr, position: Int): Int
30 do
31 if n == null then return position
32
33 var pos = n.numbering(self, position)
34 return pos
35 end
36
37 # Redef to add the numbering of variables and arguments
38 redef fun new_frame(node, mpropdef, args)
39 do
40 var f = new VmFrame(node, mpropdef, args)
41
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))
46
47 # Create an empty environment
48 f.variables = new Array[Instance].filled_with(initialization_value, node.environment_size)
49 end
50
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)
55
56 # Create an empty environment
57 f.variables = new Array[Instance].filled_with(initialization_value, node.environment_size)
58 end
59
60 # Putting self at the beginning of the environment
61 f.variables[0] = args[0]
62 return f
63 end
64
65 # Read a `Variable` from a frame by using its position
66 redef fun read_variable(v: Variable): Instance
67 do
68 return frame.variables[v.position]
69 end
70
71 # Assign the value of the `Variable` in an environment
72 redef fun write_variable(v: Variable, value: Instance)
73 do
74 frame.variables[v.position] = value
75 end
76 end
77
78 redef class Variable
79 # The position in the environment
80 var position: Int
81 end
82
83 # Implementation of a Frame with numbered variables
84 class VmFrame
85 super Frame
86
87 # Contains the value of Variables (which are numbered)
88 var variables: Array[Instance] = new Array[Instance]
89 end
90
91 redef class AExpr
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
99 do
100 return position
101 end
102 end
103
104 redef class APropdef
105 # Indicate if the variables numbering has been done
106 private var is_numbering: Bool = false
107
108 # The size of the environment to create to call this method
109 private var environment_size: Int = 0
110 end
111
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)
117 do
118 # The position in the environment
119 var position = 0
120
121 # The `self` variable has the first position
122 if self.selfvariable != null then
123 self.selfvariable.position = position
124 position += 1
125 end
126
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
131 position += 1
132 end
133
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)
137 end
138
139 is_numbering = true
140
141 # The size of the environment to create to execute a call to this method
142 environment_size = position
143 end
144 end
145
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)
150 do
151 # The position in the environment
152 var position = 0
153
154 # The `self` variable has the first position
155 if self.selfvariable != null then
156 self.selfvariable.position = position
157 position += 1
158 end
159
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)
163 end
164
165 is_numbering = true
166
167 # The size of the environment to create to execute a call to this method
168 environment_size = position
169 end
170 end
171
172 redef class AVardeclExpr
173 redef fun numbering(v, position)
174 do
175 # Attribute a position to this variable
176 self.variable.as(not null).position = position
177 position += 1
178
179 # Recursively continue to numbering the variables
180 position = v.numbering(self.n_expr, position)
181
182 # `position` is the next available position in the environment
183 return position
184 end
185 end
186
187 redef class ABlockExpr
188 redef fun numbering(v, position)
189 do
190 for e in self.n_expr do
191 position = v.numbering(e, position)
192 end
193 return position
194 end
195 end
196
197 redef class AIfExpr
198 redef fun numbering(v, position)
199 do
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)
203
204 if pos > pos1 then
205 return pos
206 else
207 return pos1
208 end
209 end
210 end
211
212 redef class AIfexprExpr
213 redef fun numbering(v, position)
214 do
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)
218
219 if pos > pos1 then
220 return pos
221 else
222 return pos1
223 end
224 end
225 end
226
227 redef class ADoExpr
228 redef fun numbering(v, position)
229 do
230 return v.numbering(self.n_block, position)
231 end
232 end
233
234 redef class AWhileExpr
235 redef fun numbering(v, position)
236 do
237 return v.numbering(self.n_block, position)
238 end
239 end
240
241 redef class ALoopExpr
242 redef fun numbering(v, position)
243 do
244 return v.numbering(self.n_block, position)
245 end
246 end
247
248 redef class AForExpr
249 redef fun numbering(v, position)
250 do
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
255 position += 1
256 else if self.variables.length == 2 then
257 self.variables[0].position = position
258 position += 1
259 self.variables[1].position = position
260 position += 1
261 end
262 return v.numbering(self.n_block, position)
263 end
264 end
265
266 redef class AArrayExpr
267 redef fun numbering(v, position)
268 do
269 for nexpr in self.n_exprs do
270 position = v.numbering(nexpr, position)
271 end
272 return position
273 end
274 end