# HG changeset patch # User Paul Boddie # Date 1235782173 -3600 # Node ID ae20cd4d0679a04b593dd1a0126921cd421c5144 # Parent 932777a0111f978c755e391affe9afc0fc9f0f7f Fixed namespace behaviour around assignments in order to record assigned values properly. Fixed StoreFrameIndex to use the parameter table and to accept the target as an operand (via the current value). Fixed StoreAddress to save the source value. Introduced exception raising from within some instructions. Expanded the DataObject to include function codes, employed by StoreFrameIndex. Expanded the as_raw methods to have access to the parameter table. Added default argument population in CheckFrame. Added assignments in test programs in order to inspect program effects. diff -r 932777a0111f -r ae20cd4d0679 micropython/__init__.py --- a/micropython/__init__.py Sun Feb 22 22:31:21 2009 +0100 +++ b/micropython/__init__.py Sat Feb 28 01:49:33 2009 +0100 @@ -260,26 +260,26 @@ for item in self.code: if isinstance(item, micropython.data.Attr): - self.raw_code += item.as_raw(objtable) + self.raw_code += item.as_raw(objtable, paramtable) elif isinstance(item, Block): assert item.location == len(self.raw_code) - self.raw_code += item.as_raw(objtable) + self.raw_code += item.as_raw(objtable, paramtable) # Using classcode, attrcode, codeaddr, codedetails, instance. elif isinstance(item, micropython.data.Class): assert item.instance_template_location == len(self.raw_code) - self.raw_code += item.as_raw(objtable) + self.raw_code += item.as_raw(objtable, paramtable) assert item.location == len(self.raw_code) - 1 elif isinstance(item, micropython.data.Const): assert item.location == len(self.raw_code) - self.raw_code += item.as_raw(objtable) + self.raw_code += item.as_raw(objtable, paramtable) elif isinstance(item, micropython.data.Function): assert item.location == len(self.raw_code) - self.raw_code += item.as_raw(objtable) + self.raw_code += item.as_raw(objtable, paramtable) # Check the code location only where the code has been generated. @@ -288,7 +288,7 @@ elif isinstance(item, micropython.data.Module): assert item.location == len(self.raw_code) - self.raw_code += item.as_raw(objtable) + self.raw_code += item.as_raw(objtable, paramtable) else: self.raw_code.append(item) diff -r 932777a0111f -r ae20cd4d0679 micropython/ast.py --- a/micropython/ast.py Sun Feb 22 22:31:21 2009 +0100 +++ b/micropython/ast.py Sat Feb 28 01:49:33 2009 +0100 @@ -770,14 +770,19 @@ continue # Generate code for the keyword and the positioning - # operation. + # operation. Get the value as the source of the assignment. self.dispatch(arg.expr) + self.record_value() + + # Store the source value using the callable's parameter + # table information. + + self.new_op(temp) self.new_op(StoreFrameIndex(paramindex)) - # use (callable+0)+paramindex+table - # checks embedded offset against (callable+0) - # moves the current value to frame+position + self.set_source() + self.discard_value() # Record the highest possible frame position for this argument. diff -r 932777a0111f -r ae20cd4d0679 micropython/common.py --- a/micropython/common.py Sun Feb 22 22:31:21 2009 +0100 +++ b/micropython/common.py Sat Feb 28 01:49:33 2009 +0100 @@ -3,7 +3,7 @@ """ Common classes. -Copyright (C) 2007, 2008 Paul Boddie +Copyright (C) 2007, 2008, 2009 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -84,10 +84,7 @@ def __repr__(self): return "Block(%r, location=%r)" % (id(self), self.location) - def as_raw(self, objtable): - - "Return the code for the given 'block'." - + def as_raw(self, objtable, paramtable): for i, item in enumerate(self.code): if hasattr(item, "location"): item.location = location + i @@ -99,16 +96,17 @@ "A representation of a raw program data object." - def __init__(self, classcode, attrcode, codeaddr, codedetails, instance, name): + def __init__(self, classcode, attrcode, codeaddr, codedetails, instance, name, funccode=None): self.classcode = classcode self.attrcode = attrcode self.codeaddr = codeaddr self.codedetails = codedetails self.instance = instance self.name = name + self.funccode = funccode def __repr__(self): - return "%r # %s" % ((self.classcode, self.attrcode, self.codeaddr, self.codedetails, self.instance), self.name) + return "%r # %s" % ((self.classcode, self.attrcode, self.codeaddr, self.codedetails, self.instance, self.funccode), self.name) # Inspection representations. diff -r 932777a0111f -r ae20cd4d0679 micropython/data.py --- a/micropython/data.py Sun Feb 22 22:31:21 2009 +0100 +++ b/micropython/data.py Sat Feb 28 01:49:33 2009 +0100 @@ -20,7 +20,7 @@ -------- -The central classes in this module are the following: +The central data structure classes in this module are the following: * Class * Function @@ -34,7 +34,7 @@ access names within their defined scopes. Specific methods also exist in order to distinguish between certain kinds of attributes: - * Class: (class|all_class|instance|all)_attributes + * Class: class_attributes, all_class_attributes, instance_attributes, all_attributes * Function: parameters, locals, all_locals * Module: module_attributes @@ -101,7 +101,7 @@ self.module.set(name, value, 0) else: attr = self._set(name, value) - attr.update(attr.value, single_assignment) + attr.update(value, single_assignment) def set_module(self, name, value): @@ -310,7 +310,7 @@ self.name, shortrepr(self.value), self.assignments ) - def as_raw(self, objtable): + def as_raw(self, objtable, paramtable): return [ ( self.context and self.context.location, @@ -365,7 +365,7 @@ __shortrepr__ = __repr__ - def as_raw(self, objtable): + def as_raw(self, objtable, paramtable): # NOTE: Need class details! return [ DataObject( @@ -461,7 +461,7 @@ def __shortrepr__(self): return "Class(%r, %s)" % (self.name, shortrepr(self.parent)) - def as_raw(self, objtable): + def as_raw(self, objtable, paramtable): classcode = objtable.as_list().get_code(self.full_name()) attrcode = objtable.get_index(self.full_name()) @@ -861,7 +861,7 @@ self.name, shortrepr(self.parent) ) - def as_raw(self, objtable): + def as_raw(self, objtable, paramtable): # NOTE: Need class and parameter details! Should arguably be types.FunctionType. return [ DataObject( @@ -873,7 +873,8 @@ len(self.defaults) ), 0, - "__builtins__.function" + "__builtins__.function", + paramtable.as_list().get_code(self.full_name()) ) ] @@ -1065,7 +1066,7 @@ def __shortrepr__(self): return "Module(%r)" % self.name - def as_raw(self, objtable): + def as_raw(self, objtable, paramtable): return [ DataObject( objtable.as_list().get_code(self.full_name()), diff -r 932777a0111f -r ae20cd4d0679 micropython/opt.py --- a/micropython/opt.py Sun Feb 22 22:31:21 2009 +0100 +++ b/micropython/opt.py Sat Feb 28 01:49:33 2009 +0100 @@ -172,7 +172,7 @@ """ Return whether 'instruction' can use simple input from the current - value. Such instructions would, in a low-level implementation, be able + value. Such instructions would, in a low-level implementation, be able to have the simple input registers as operands. """ @@ -180,6 +180,7 @@ StoreTemp, StoreFrame, StoreResult, StoreException, # as the value being stored LoadAddressContext, LoadAttr, LoadAttrIndex, # as the object being referenced StoreAttr, StoreAttrIndex, StoreCallable, # as the object being referenced + StoreFrameIndex, # as the object being referenced LoadCallable, TestIdentity, TestIdentityAddress, CheckSelf, # as one of the operands CheckException, CheckFrame, MakeObject, diff -r 932777a0111f -r ae20cd4d0679 micropython/rsvp.py --- a/micropython/rsvp.py Sun Feb 22 22:31:21 2009 +0100 +++ b/micropython/rsvp.py Sat Feb 28 01:49:33 2009 +0100 @@ -163,7 +163,7 @@ class LoadAttr(AR): "Load into the current value the given attribute of the object referenced by the current value." class StoreAttr(AR): "Store the source value into the given attribute of the object referenced by the current value." class LoadAttrIndex(Immediate): "Load into the current value the attribute of the current value with the given index." -class StoreAttrIndex(Immediate): "Store an object in the attribute with the given index." +class StoreAttrIndex(Immediate): "Store the source value into the attribute of the current value with the given index." # Access to object details. @@ -176,7 +176,7 @@ class DropFrame(Instruction): "Drop an invocation frame." class RecoverFrame(Instruction): "Recover the current frame as an invocation frame." class StoreFrame(Immediate): "Store the current value as an argument for the parameter with the given position." -class StoreFrameIndex(Immediate): "Store the current value as an argument for the parameter with the given index." +class StoreFrameIndex(Immediate): "Store the source value as an argument of the current value for the parameter with the given index." class LoadContext(Instruction): "Load the context of an invocation." class CheckFrame(Immediate): "Check the invocation frame and context for the target." class CheckSelf(Instruction): "Check the first argument of an invocation against the target." diff -r 932777a0111f -r ae20cd4d0679 micropython/table.py --- a/micropython/table.py Sun Feb 22 22:31:21 2009 +0100 +++ b/micropython/table.py Sat Feb 28 01:49:33 2009 +0100 @@ -193,6 +193,7 @@ "A parameter list." def entry_as_raw(self, entry): + # param_index, position = entry return entry class Table: diff -r 932777a0111f -r ae20cd4d0679 rsvp.py --- a/rsvp.py Sun Feb 22 22:31:21 2009 +0100 +++ b/rsvp.py Sat Feb 28 01:49:33 2009 +0100 @@ -273,9 +273,11 @@ instructions would otherwise have. """ + value = self.value if self.instruction.source is not None: self.perform(self.instruction.source) self.source = self.value + self.value = value if self.instruction.input is not None: self.perform(self.instruction.input) @@ -324,7 +326,7 @@ def StoreAddress(self): # Preserve context. - self.save(self.operand, self.value) + self.save(self.operand, self.source) def MakeObject(self): size = self.operand @@ -362,6 +364,7 @@ self.value = self.load(ref + offset) else: self.exception = self.attr_error + return self.RaiseException() def StoreAttrIndex(self): context, ref = self.value @@ -371,10 +374,12 @@ if attr_index == self.operand: if class_attr: self.exception = self.type_error + return self.RaiseException() else: self.save(ref + offset, self.source) else: self.exception = self.attr_error + return self.RaiseException() # NOTE: LoadAttrIndexContext is a possibility if a particular attribute can always be overridden. @@ -398,12 +403,14 @@ context, ref = self.value frame = self.invocation_sp_stack[-1] # different from the current frame after MakeFrame data = self.load(ref) - element = self.objlist[data.classcode + self.operand] - attr_index, class_attr, replace_context, offset = element - if attr_index == self.operand: - self.frame_stack[frame + offset] = self.value + element = self.paramlist[data.funccode + self.operand] + # NOTE: Need to ensure correct positioning where a context has been generated. + param_index, offset = element + if param_index == self.operand: + self.frame_stack[frame + offset + 1] = self.source # add 1 to skip the context always generated else: self.exception = self.type_error + return self.RaiseException() def LoadCallable(self): context, ref = self.value @@ -437,11 +444,24 @@ self.invocation_sp_stack[-1] += 1 operand -= 1 + # Test the frame size. + nargs, ndefaults = data.codedetails if not ((nargs - ndefaults) <= operand <= nargs): raise Exception, "CheckFrame %r (%r <= %r <= %r)" % (self.operand, nargs - ndefaults, operand, nargs) - # NOTE: Support population of defaults. + # Support population of defaults. + # This involves copying the "attributes" of a function into the frame. + + default = operand - (nargs - ndefaults) + self.frame_stack.extend([None] * (nargs - operand)) + pos = self.operand + + while operand < nargs: + self.frame_stack[frame + pos] = self.load(ref + default + 1) # skip header + default += 1 + pos += 1 + operand += 1 def CheckSelf(self): context, ref = self.value diff -r 932777a0111f -r ae20cd4d0679 tests/call_func_default.py --- a/tests/call_func_default.py Sun Feb 22 22:31:21 2009 +0100 +++ b/tests/call_func_default.py Sat Feb 28 01:49:33 2009 +0100 @@ -1,9 +1,9 @@ #!/usr/bin/env python def f(a, b, c=4): - pass + return c -f(1, 2, 3) -f(1, 2) +r1 = f(1, 2, 3) +r2 = f(1, 2) # vim: tabstop=4 expandtab shiftwidth=4 diff -r 932777a0111f -r ae20cd4d0679 tests/call_func_default_redefine.py --- a/tests/call_func_default_redefine.py Sun Feb 22 22:31:21 2009 +0100 +++ b/tests/call_func_default_redefine.py Sat Feb 28 01:49:33 2009 +0100 @@ -1,16 +1,16 @@ #!/usr/bin/env python def f(a, b, c=4): - pass + return c g = f -g(1, c=3, b=2) -g(1, 2) +r1 = g(1, c=3, b=2) +r2 = g(1, 2) def g(a, c, b=5): - pass + return b -g(1, c=3, b=2) -g(1, 3) +r3 = g(1, c=3, b=2) +r4 = g(1, 3) # vim: tabstop=4 expandtab shiftwidth=4