# This file is part of NIT ( http://www.nitlanguage.org ). # # Copyright 2015 Julien Pagès # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Handle all numbering operations related to local variables in the Nit virtual machine module variables_numbering import vm redef class VirtualMachine # Number the variables in `n`. # Do nothing if `n` is null fun numbering(n: nullable AExpr, position: Int): Int do if n == null then return position var pos = n.numbering(self, position) return pos end end redef class Variable # The position in the environment var position: Int end redef class AExpr # Give a position to each variable declared in the node. # NOTE: Do not call this method directly, but use `v.numbering` # This method is here to be implemented by subclasses. # *`v` The current instance of the virtual machine # *`position` The first available position in the environment a variable can have # Return the next available position a variable can have public fun numbering(v: VirtualMachine, position: Int): Int do return position end end redef class APropdef # Indicate if the variables numbering has been done private var is_numbering: Bool = false # The size of the environment to create to call this method private var environment_size: Int = 0 end redef class AMethPropdef # Assign a position in the environment to each local variable of `mpropdef` # *`v` The current VirtualMachine # *`mpropdef` The method to number private fun numbering_variables(v: VirtualMachine, mpropdef: MMethodDef) do # The position in the environment var position = 0 # The `self` variable has the first position if self.selfvariable != null then self.selfvariable.position = position position += 1 end # Number the parameters for i in [0..mpropdef.msignature.arity[ do var variable = self.n_signature.n_params[i].variable variable.as(not null).position = position position += 1 end # Recursively go into the AST nodes to number all local variables if n_block != null then position = v.numbering(self.n_block, position) end is_numbering = true # The size of the environment to create to execute a call to this method environment_size = position end end redef class AAttrPropdef # Assign a position in the environment to each local variable of `mpropdef` # *`v` The current VirtualMachine private fun numbering_variables(v: VirtualMachine) do # The position in the environment var position = 0 # The `self` variable has the first position if self.selfvariable != null then self.selfvariable.position = position position += 1 end # Recursively go into the AST nodes to number all local variables if n_block != null then position = v.numbering(self.n_block, position) end is_numbering = true # The size of the environment to create to execute a call to this method environment_size = position end end redef class AVardeclExpr redef fun numbering(v, position) do # Attribute a position to this variable self.variable.as(not null).position = position position += 1 # Recursively continue to numbering the variables position = v.numbering(self.n_expr, position) # `position` is the next available position in the environment return position end end redef class ABlockExpr redef fun numbering(v, position) do for e in self.n_expr do position = v.numbering(e, position) end return position end end redef class AIfExpr redef fun numbering(v, position) do # Attribute numbers separetely for the two branches var pos = v.numbering(self.n_then, position) var pos1 = v.numbering(self.n_else, position) if pos > pos1 then return pos else return pos1 end end end redef class AIfexprExpr redef fun numbering(v, position) do # Attribute numbers separetely for the two branches var pos = v.numbering(self.n_then, position) var pos1 = v.numbering(self.n_else, position) if pos > pos1 then return pos else return pos1 end end end redef class ADoExpr redef fun numbering(v, position) do return v.numbering(self.n_block, position) end end redef class AWhileExpr redef fun numbering(v, position) do return v.numbering(self.n_block, position) end end redef class ALoopExpr redef fun numbering(v, position) do return v.numbering(self.n_block, position) end end redef class AForExpr redef fun numbering(v, position) do # Give a position to each variable declared in the header of the for if self.variables.length == 1 then self.variables.first.position = position self.variables[0].position = position position += 1 else if self.variables.length == 2 then self.variables[0].position = position position += 1 self.variables[1].position = position position += 1 end return v.numbering(self.n_block, position) end end redef class AArrayExpr redef fun numbering(v, position) do for nexpr in self.n_exprs do position = v.numbering(nexpr, position) end return position end end