nitvm: The interpreter and the vm have each their own specialized frames
authorJulien Pagès <julien.projet@gmail.com>
Fri, 13 Mar 2015 15:54:18 +0000 (16:54 +0100)
committerJulien Pagès <julien.projet@gmail.com>
Sun, 15 Mar 2015 11:53:15 +0000 (12:53 +0100)
The class Frame is now abstract

Signed-off-by: Julien Pagès <julien.projet@gmail.com>

src/interpreter/debugger.nit
src/interpreter/naive_interpreter.nit
src/variables_numbering.nit

index 4400939..1765d9e 100644 (file)
@@ -225,7 +225,7 @@ class Debugger
        # Auto continues the execution until the end or until an error is encountered
        var autocontinue = false
 
-       redef type FRAME: Frame
+       redef type FRAME: InterpreterFrame
 
        #######################################################################
        ##                  Execution of statement function                  ##
@@ -1411,7 +1411,7 @@ redef class AMethPropdef
        # Not supposed to be used by anyone else than the Debugger.
        private fun rt_call(v: Debugger, mpropdef: MMethodDef, args: Array[Instance]): nullable Instance
        do
-               var f = new Frame(self, self.mpropdef.as(not null), args)
+               var f = new InterpreterFrame(self, self.mpropdef.as(not null), args)
                var curr_instances = v.frame.map
                for i in curr_instances.keys do
                        f.map[i] = curr_instances[i]
index c92ba90..311d917 100644 (file)
@@ -323,7 +323,7 @@ class NaiveInterpreter
        # *`args` Arguments of the call
        fun new_frame(node: ANode, mpropdef: MPropDef, args: Array[Instance]): FRAME
        do
-               return new Frame(node, mpropdef, args)
+               return new InterpreterFrame(node, mpropdef, args)
        end
 
        # Exit the program with a message
@@ -352,14 +352,14 @@ class NaiveInterpreter
        # Retrieve the value of the variable in the current frame
        fun read_variable(v: Variable): Instance
        do
-               var f = frames.first
+               var f = frames.first.as(InterpreterFrame)
                return f.map[v]
        end
 
        # Assign the value of the variable in the current frame
        fun write_variable(v: Variable, value: Instance)
        do
-               var f = frames.first
+               var f = frames.first.as(InterpreterFrame)
                f.map[v] = value
        end
 
@@ -679,7 +679,7 @@ class PrimitiveInstance[E]
 end
 
 # Information about local variables in a running method
-class Frame
+abstract class Frame
        # The current visited node
        # The node is stored by frame to keep a stack trace
        var current_node: ANode
@@ -688,9 +688,16 @@ class Frame
        var mpropdef: MPropDef
        # Arguments of the method (the first is the receiver)
        var arguments: Array[Instance]
+       # Indicate if the expression has an array comprehension form
+       var comprehension: nullable Array[Instance] = null
+end
+
+# Implementation of a Frame with a Hashmap to store local variables
+class InterpreterFrame
+       super Frame
+
        # Mapping between a variable and the current value
        private var map: Map[Variable, Instance] = new HashMap[Variable, Instance]
-       var comprehension: nullable Array[Instance] = null
 end
 
 redef class ANode
index 7698ad2..1190fab 100644 (file)
@@ -21,6 +21,9 @@ import vm
 
 redef class VirtualMachine
 
+       # The frames of the VirtualMachine are specialized
+       redef type FRAME: VmFrame
+
        # Number the variables in `n`.
        # Do nothing if `n` is null
        fun numbering(n: nullable AExpr, position: Int): Int
@@ -30,6 +33,46 @@ redef class VirtualMachine
                var pos = n.numbering(self, position)
                return pos
        end
+
+       # Redef to add the numbering of variables and arguments
+       redef fun new_frame(node, mpropdef, args)
+       do
+               var f = new VmFrame(node, mpropdef, args)
+
+               # If this Frame is for a method then number variables into the body of the method
+               if node isa AMethPropdef then
+                       # Number the variables
+                       if not node.is_numbering then node.numbering_variables(self, mpropdef.as(MMethodDef))
+
+                       # Create an empty environment
+                       f.variables = new Array[Instance].filled_with(initialization_value, node.environment_size)
+               end
+
+               # If this Frame is for an attribute with a block then number the block
+               if node isa AAttrPropdef then
+                       # Number the variables
+                       if not node.is_numbering then node.numbering_variables(self)
+
+                       # Create an empty environment
+                       f.variables = new Array[Instance].filled_with(initialization_value, node.environment_size)
+               end
+
+               # Putting self at the beginning of the environment
+               f.variables[0] = args[0]
+               return f
+       end
+
+       # Read a `Variable` from a frame by using its position
+       redef fun read_variable(v: Variable): Instance
+       do
+               return frame.variables[v.position]
+       end
+
+       # Assign the value of the `Variable` in an environment
+       redef fun write_variable(v: Variable, value: Instance)
+       do
+               frame.variables[v.position] = value
+       end
 end
 
 redef class Variable
@@ -37,6 +80,14 @@ redef class Variable
        var position: Int
 end
 
+# Implementation of a Frame with numbered variables
+class VmFrame
+       super Frame
+
+       # Contains the value of Variables (which are numbered)
+       var variables: Array[Instance] = new Array[Instance]
+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`