nitvm: The local variables are numbered
[nit.git] / src / 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 vm
21
22 redef class VirtualMachine
23
24 # Number the variables in `n`.
25 # Do nothing if `n` is null
26 fun numbering(n: nullable AExpr, position: Int): Int
27 do
28 if n == null then return position
29
30 var pos = n.numbering(self, position)
31 return pos
32 end
33 end
34
35 redef class Variable
36 # The position in the environment
37 var position: Int
38 end
39
40 redef class AExpr
41 # Give a position to each variable declared in the node.
42 # NOTE: Do not call this method directly, but use `v.numbering`
43 # This method is here to be implemented by subclasses.
44 # *`v` The current instance of the virtual machine
45 # *`position` The first available position in the environment a variable can have
46 # Return the next available position a variable can have
47 public fun numbering(v: VirtualMachine, position: Int): Int
48 do
49 return position
50 end
51 end
52
53 redef class APropdef
54 # Indicate if the variables numbering has been done
55 private var is_numbering: Bool = false
56
57 # The size of the environment to create to call this method
58 private var environment_size: Int = 0
59 end
60
61 redef class AMethPropdef
62 # Assign a position in the environment to each local variable of `mpropdef`
63 # *`v` The current VirtualMachine
64 # *`mpropdef` The method to number
65 private fun numbering_variables(v: VirtualMachine, mpropdef: MMethodDef)
66 do
67 # The position in the environment
68 var position = 0
69
70 # The `self` variable has the first position
71 if self.selfvariable != null then
72 self.selfvariable.position = position
73 position += 1
74 end
75
76 # Number the parameters
77 for i in [0..mpropdef.msignature.arity[ do
78 var variable = self.n_signature.n_params[i].variable
79 variable.as(not null).position = position
80 position += 1
81 end
82
83 # Recursively go into the AST nodes to number all local variables
84 if n_block != null then
85 position = v.numbering(self.n_block, position)
86 end
87
88 is_numbering = true
89
90 # The size of the environment to create to execute a call to this method
91 environment_size = position
92 end
93 end
94
95 redef class AAttrPropdef
96 # Assign a position in the environment to each local variable of `mpropdef`
97 # *`v` The current VirtualMachine
98 private fun numbering_variables(v: VirtualMachine)
99 do
100 # The position in the environment
101 var position = 0
102
103 # The `self` variable has the first position
104 if self.selfvariable != null then
105 self.selfvariable.position = position
106 position += 1
107 end
108
109 # Recursively go into the AST nodes to number all local variables
110 if n_block != null then
111 position = v.numbering(self.n_block, position)
112 end
113
114 is_numbering = true
115
116 # The size of the environment to create to execute a call to this method
117 environment_size = position
118 end
119 end
120
121 redef class AVardeclExpr
122 redef fun numbering(v, position)
123 do
124 # Attribute a position to this variable
125 self.variable.as(not null).position = position
126 position += 1
127
128 # Recursively continue to numbering the variables
129 position = v.numbering(self.n_expr, position)
130
131 # `position` is the next available position in the environment
132 return position
133 end
134 end
135
136 redef class ABlockExpr
137 redef fun numbering(v, position)
138 do
139 for e in self.n_expr do
140 position = v.numbering(e, position)
141 end
142 return position
143 end
144 end
145
146 redef class AIfExpr
147 redef fun numbering(v, position)
148 do
149 # Attribute numbers separetely for the two branches
150 var pos = v.numbering(self.n_then, position)
151 var pos1 = v.numbering(self.n_else, position)
152
153 if pos > pos1 then
154 return pos
155 else
156 return pos1
157 end
158 end
159 end
160
161 redef class AIfexprExpr
162 redef fun numbering(v, position)
163 do
164 # Attribute numbers separetely for the two branches
165 var pos = v.numbering(self.n_then, position)
166 var pos1 = v.numbering(self.n_else, position)
167
168 if pos > pos1 then
169 return pos
170 else
171 return pos1
172 end
173 end
174 end
175
176 redef class ADoExpr
177 redef fun numbering(v, position)
178 do
179 return v.numbering(self.n_block, position)
180 end
181 end
182
183 redef class AWhileExpr
184 redef fun numbering(v, position)
185 do
186 return v.numbering(self.n_block, position)
187 end
188 end
189
190 redef class ALoopExpr
191 redef fun numbering(v, position)
192 do
193 return v.numbering(self.n_block, position)
194 end
195 end
196
197 redef class AForExpr
198 redef fun numbering(v, position)
199 do
200 # Give a position to each variable declared in the header of the for
201 if self.variables.length == 1 then
202 self.variables.first.position = position
203 self.variables[0].position = position
204 position += 1
205 else if self.variables.length == 2 then
206 self.variables[0].position = position
207 position += 1
208 self.variables[1].position = position
209 position += 1
210 end
211 return v.numbering(self.n_block, position)
212 end
213 end
214
215 redef class AArrayExpr
216 redef fun numbering(v, position)
217 do
218 for nexpr in self.n_exprs do
219 position = v.numbering(nexpr, position)
220 end
221 return position
222 end
223 end