# 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 ##
# 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]
# *`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
# 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
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
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
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
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
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`