1.1 --- a/rsvp.py Tue Aug 14 00:35:48 2007 +0200
1.2 +++ b/rsvp.py Tue Aug 14 00:36:41 2007 +0200
1.3 @@ -10,7 +10,8 @@
1.4 * Memory
1.5 * PC (program counter) stack
1.6 * Value stack
1.7 - * Current frame pointer
1.8 + * Metadata stack (containing pointers to the value stack)
1.9 + * Current frame and arguments pointers
1.10
1.11 The memory contains constants, global variable references and program code.
1.12
1.13 @@ -37,6 +38,9 @@
1.14 class EmptyPCStack(Exception):
1.15 pass
1.16
1.17 +class EmptyMetadataStack(Exception):
1.18 + pass
1.19 +
1.20 class RSVPMachine:
1.21
1.22 "A really simple virtual processor."
1.23 @@ -53,7 +57,9 @@
1.24 self.debug = debug
1.25 self.pc_stack = []
1.26 self.value_stack = []
1.27 + self.metadata_stack = []
1.28 self.current_frame = 0
1.29 + self.argument_frame = 0
1.30
1.31 def load(self, address):
1.32
1.33 @@ -110,7 +116,22 @@
1.34 return self.pc_stack.pop()
1.35 except IndexError:
1.36 raise EmptyPCStack
1.37 -
1.38 +
1.39 + def push_metadata(self, data):
1.40 +
1.41 + "Push 'data' onto the metadata stack."
1.42 +
1.43 + self.metadata_stack.append(data)
1.44 +
1.45 + def pull_metadata(self):
1.46 +
1.47 + "Pull a value from the metadata stack and return it."
1.48 +
1.49 + try:
1.50 + return self.metadata_stack.pop()
1.51 + except IndexError:
1.52 + raise EmptyMetadataStack
1.53 +
1.54 def execute(self):
1.55
1.56 "Execute code in the memory, starting from the current PC address."
1.57 @@ -150,11 +171,16 @@
1.58
1.59 """
1.60 SCF
1.61 - Save current stack frame: record the current stack frame pointer on the
1.62 - value stack.
1.63 + Save current stack and argument frames: record the current stack and
1.64 + argument frame pointers on the value stack; then set the argument frame
1.65 + pointer to the top of the stack (similar to the next frame produced by
1.66 + NSF).
1.67 """
1.68
1.69 - self.push(self.current_frame)
1.70 + self.push_metadata(self.argument_frame)
1.71 + self.push_metadata(self.current_frame)
1.72 + top = len(self.value_stack)
1.73 + self.argument_frame = top
1.74 self.pc += 1
1.75
1.76 def NSF(self):
1.77 @@ -162,14 +188,13 @@
1.78 """
1.79 NSF #n
1.80 Next stack frame of size n: set the current stack frame pointer to the
1.81 - current top of stack value minus n+1 positions, where n positions are
1.82 - used for parameter values and 1 position is used for the previous stack
1.83 - frame pointer value.
1.84 + current top of stack value minus n positions, used for parameter values.
1.85 """
1.86
1.87 top = len(self.value_stack)
1.88 n = self.load(self.pc + 1)
1.89 - self.current_frame = top - (n+1)
1.90 + self.current_frame = top - n
1.91 + self.argument_frame = 0
1.92 self.pc += 2
1.93
1.94 def PSF(self):
1.95 @@ -185,15 +210,16 @@
1.96
1.97 result = self.pull()
1.98 top = self.current_frame
1.99 - self.current_frame = self.value_stack[top]
1.100 - self.value_stack = self.value_stack[:top]
1.101 + self.current_frame = self.pull_metadata()
1.102 + self.argument_frame = self.pull_metadata()
1.103 + self.value_stack = self.value_stack[:top] # reset stack before SCF
1.104 self.push(result)
1.105 self.pc += 1
1.106
1.107 def ESF(self):
1.108
1.109 """
1.110 - ESF #m
1.111 + ESF #n
1.112 Extend stack frame by n values: allocate n positions on the stack,
1.113 typically so that local variables can be stored.
1.114 """
1.115 @@ -348,6 +374,20 @@
1.116 else:
1.117 self.pc += 2
1.118
1.119 + def MVA(self):
1.120 +
1.121 + """
1.122 + MVA #n
1.123 + Move the value from the top of the stack to the argument in position n:
1.124 + pull a value from the stack and store it in the argument frame at the
1.125 + given position.
1.126 + """
1.127 +
1.128 + pos = self.load(self.pc + 1)
1.129 + value = self.pull()
1.130 + self.value_stack[self.argument_frame + pos] = value
1.131 + self.pc += 2
1.132 +
1.133 # Library functions.
1.134
1.135 def rsvp___printnl(self):
1.136 @@ -493,10 +533,10 @@
1.137 i_n = 51
1.138 i_1 = 52
1.139 memory = ["SCF", "SCF", "LRM", i_n, "NSF", 1, "JAS", i_fact, "NSF", 1, "JAS", "rsvp___print", "RAC"]
1.140 - memory += ["SCF", "LPF", 1, "LRM", i_1, "NSF", 2, "JAS", "int_____gt__", "JAF", i_else]
1.141 - memory += ["SCF", "LPF", 1,
1.142 + memory += ["SCF", "LPF", 0, "LRM", i_1, "NSF", 2, "JAS", "int_____gt__", "JAF", i_else]
1.143 + memory += ["SCF", "LPF", 0,
1.144 "SCF",
1.145 - "SCF", "LPF", 1, "LRM", i_1, "NSF", 2, "JAS", "int_____sub__",
1.146 + "SCF", "LPF", 0, "LRM", i_1, "NSF", 2, "JAS", "int_____sub__",
1.147 "NSF", 1, "JAS", i_fact,
1.148 "NSF", 2, "JAS", "int_____mul__",
1.149 "PSF", "RAC"]
1.150 @@ -517,17 +557,17 @@
1.151 fact_assembler = RSVPAssembler()
1.152 fact_assembler.label("$fact")
1.153 fact_assembler.add_many(
1.154 - ("SCF",), ("LPF", 1), ("LRM", "$1"), ("NSF", 2), ("JAS", "int_____gt__"), ("JAF", "$else"),
1.155 - ("SCF",), ("LPF", 1),
1.156 - ("SCF",),
1.157 - ("SCF",), ("LPF", 1), ("LRM", "$1"), ("NSF", 2), ("JAS", "int_____sub__"),
1.158 - ("NSF", 1), ("JAS", "$fact"),
1.159 - ("NSF", 2), ("JAS", "int_____mul__"),
1.160 - ("PSF",), ("RAC",)
1.161 + ("SCF",), ("LPF", 0), ("LRM", "$1"), ("NSF", 2), ("JAS", "int_____gt__"), ("JAF", "$else"), # if n > 1:
1.162 + ("SCF",), ("LPF", 0), # n
1.163 + ("SCF",),
1.164 + ("SCF",), ("LPF", 0), ("LRM", "$1"), ("NSF", 2), ("JAS", "int_____sub__"), # n - 1
1.165 + ("NSF", 1), ("JAS", "$fact"), # fact(...)
1.166 + ("NSF", 2), ("JAS", "int_____mul__"), # ... * ...
1.167 + ("PSF",), ("RAC",) # return ...
1.168 )
1.169 - fact_assembler.label("$else")
1.170 + fact_assembler.label("$else") # else:
1.171 fact_assembler.add_many(
1.172 - ("LRM", "$1"), ("PSF",), ("RAC",)
1.173 + ("LRM", "$1"), ("PSF",), ("RAC",) # return 1
1.174 )
1.175 fact_assembler.label("$n")
1.176 fact_assembler.add(n)