# HG changeset patch # User paulb@localhost.localdomain # Date 1187044601 -7200 # Node ID 7747766e42deedf3e0c4c09fe621a031f9d8636d # Parent ed73c500b8877eb15fd5f9adc6b80a1eeb2a2761 Introduced a metadata stack (for frame/argument pointers). Added some code generation support for invocations. diff -r ed73c500b887 -r 7747766e42de rsvp.py --- a/rsvp.py Tue Aug 14 00:35:48 2007 +0200 +++ b/rsvp.py Tue Aug 14 00:36:41 2007 +0200 @@ -10,7 +10,8 @@ * Memory * PC (program counter) stack * Value stack - * Current frame pointer + * Metadata stack (containing pointers to the value stack) + * Current frame and arguments pointers The memory contains constants, global variable references and program code. @@ -37,6 +38,9 @@ class EmptyPCStack(Exception): pass +class EmptyMetadataStack(Exception): + pass + class RSVPMachine: "A really simple virtual processor." @@ -53,7 +57,9 @@ self.debug = debug self.pc_stack = [] self.value_stack = [] + self.metadata_stack = [] self.current_frame = 0 + self.argument_frame = 0 def load(self, address): @@ -110,7 +116,22 @@ return self.pc_stack.pop() except IndexError: raise EmptyPCStack - + + def push_metadata(self, data): + + "Push 'data' onto the metadata stack." + + self.metadata_stack.append(data) + + def pull_metadata(self): + + "Pull a value from the metadata stack and return it." + + try: + return self.metadata_stack.pop() + except IndexError: + raise EmptyMetadataStack + def execute(self): "Execute code in the memory, starting from the current PC address." @@ -150,11 +171,16 @@ """ SCF - Save current stack frame: record the current stack frame pointer on the - value stack. + Save current stack and argument frames: record the current stack and + argument frame pointers on the value stack; then set the argument frame + pointer to the top of the stack (similar to the next frame produced by + NSF). """ - self.push(self.current_frame) + self.push_metadata(self.argument_frame) + self.push_metadata(self.current_frame) + top = len(self.value_stack) + self.argument_frame = top self.pc += 1 def NSF(self): @@ -162,14 +188,13 @@ """ NSF #n Next stack frame of size n: set the current stack frame pointer to the - current top of stack value minus n+1 positions, where n positions are - used for parameter values and 1 position is used for the previous stack - frame pointer value. + current top of stack value minus n positions, used for parameter values. """ top = len(self.value_stack) n = self.load(self.pc + 1) - self.current_frame = top - (n+1) + self.current_frame = top - n + self.argument_frame = 0 self.pc += 2 def PSF(self): @@ -185,15 +210,16 @@ result = self.pull() top = self.current_frame - self.current_frame = self.value_stack[top] - self.value_stack = self.value_stack[:top] + self.current_frame = self.pull_metadata() + self.argument_frame = self.pull_metadata() + self.value_stack = self.value_stack[:top] # reset stack before SCF self.push(result) self.pc += 1 def ESF(self): """ - ESF #m + ESF #n Extend stack frame by n values: allocate n positions on the stack, typically so that local variables can be stored. """ @@ -348,6 +374,20 @@ else: self.pc += 2 + def MVA(self): + + """ + MVA #n + Move the value from the top of the stack to the argument in position n: + pull a value from the stack and store it in the argument frame at the + given position. + """ + + pos = self.load(self.pc + 1) + value = self.pull() + self.value_stack[self.argument_frame + pos] = value + self.pc += 2 + # Library functions. def rsvp___printnl(self): @@ -493,10 +533,10 @@ i_n = 51 i_1 = 52 memory = ["SCF", "SCF", "LRM", i_n, "NSF", 1, "JAS", i_fact, "NSF", 1, "JAS", "rsvp___print", "RAC"] - memory += ["SCF", "LPF", 1, "LRM", i_1, "NSF", 2, "JAS", "int_____gt__", "JAF", i_else] - memory += ["SCF", "LPF", 1, + memory += ["SCF", "LPF", 0, "LRM", i_1, "NSF", 2, "JAS", "int_____gt__", "JAF", i_else] + memory += ["SCF", "LPF", 0, "SCF", - "SCF", "LPF", 1, "LRM", i_1, "NSF", 2, "JAS", "int_____sub__", + "SCF", "LPF", 0, "LRM", i_1, "NSF", 2, "JAS", "int_____sub__", "NSF", 1, "JAS", i_fact, "NSF", 2, "JAS", "int_____mul__", "PSF", "RAC"] @@ -517,17 +557,17 @@ fact_assembler = RSVPAssembler() fact_assembler.label("$fact") fact_assembler.add_many( - ("SCF",), ("LPF", 1), ("LRM", "$1"), ("NSF", 2), ("JAS", "int_____gt__"), ("JAF", "$else"), - ("SCF",), ("LPF", 1), - ("SCF",), - ("SCF",), ("LPF", 1), ("LRM", "$1"), ("NSF", 2), ("JAS", "int_____sub__"), - ("NSF", 1), ("JAS", "$fact"), - ("NSF", 2), ("JAS", "int_____mul__"), - ("PSF",), ("RAC",) + ("SCF",), ("LPF", 0), ("LRM", "$1"), ("NSF", 2), ("JAS", "int_____gt__"), ("JAF", "$else"), # if n > 1: + ("SCF",), ("LPF", 0), # n + ("SCF",), + ("SCF",), ("LPF", 0), ("LRM", "$1"), ("NSF", 2), ("JAS", "int_____sub__"), # n - 1 + ("NSF", 1), ("JAS", "$fact"), # fact(...) + ("NSF", 2), ("JAS", "int_____mul__"), # ... * ... + ("PSF",), ("RAC",) # return ... ) - fact_assembler.label("$else") + fact_assembler.label("$else") # else: fact_assembler.add_many( - ("LRM", "$1"), ("PSF",), ("RAC",) + ("LRM", "$1"), ("PSF",), ("RAC",) # return 1 ) fact_assembler.label("$n") fact_assembler.add(n) diff -r ed73c500b887 -r 7747766e42de simplify/generator.py --- a/simplify/generator.py Tue Aug 14 00:35:48 2007 +0200 +++ b/simplify/generator.py Tue Aug 14 00:36:41 2007 +0200 @@ -103,17 +103,39 @@ # NOTE: consumption as parameters. for subprogram in invoke.invocations: + consumed_args = invoke.consumed_args[subprogram] # NOTE: Generate switch table. - # Reserve the namespace. + # Save the current frame. + + sub.add("SCF") + + # Extend the stack for the arguments. + + nparams = len(consumed_args) + if not invoke.share_locals: + sub.add("ESF", nparams) + + # For each argument, evaluate the expression. - params = subprogram.paramtypes.keys() - nparams = len(params) - if not invoke.share_locals: + for arg in invoke.args: + if arg is None: + continue + + self.dispatch(arg) + + # Then, save the argument to the correct part of the arguments + # frame. + + pos = self.arg_position(consumed_args, arg) + sub.add("MVA", pos) + + # Reserve the namespace. + sub.add("NSF", nparams) - sub.add("JAS", subprogram.full_name()) + sub.add("JAS", "sub$%s$%s" % (subprogram.module.name, subprogram.full_name())) if not invoke.share_locals: sub.add("PSF") # previous stack frame @@ -156,6 +178,17 @@ self.current_assemblers.pop() self.assemblers.append(sub) + def arg_position(self, consumed_args, arg): + + """ + Return, for the specified 'consumed_args', the position of 'arg' in the + list, handling keyword arguments appropriately. + """ + + if isinstance(arg, Keyword): + arg = arg.expr + return consumed_args.index(arg) + # Convenience functions. def generate(module):