# HG changeset patch # User Paul Boddie # Date 1207443223 -7200 # Node ID 8b8bb2f70246cdd4682aa674b8651477941c5d08 # Parent eb3c1ed9dbee841eea24d62f7889f5848be002fa Added missing built-in definitions. Added a fake sys module. Improved exception handling around missing table entries and missing built-in objects. Added __class__ attributes to class namespaces. Fixed is_relocated and added is_method to test the suitability of functions for "self" optimisations. Added -omax for all supported optimisations. diff -r eb3c1ed9dbee -r 8b8bb2f70246 lib/builtins.py --- a/lib/builtins.py Mon Mar 31 00:54:03 2008 +0200 +++ b/lib/builtins.py Sun Apr 06 02:53:43 2008 +0200 @@ -24,24 +24,48 @@ def __bool__(self): pass def __iadd__(self, other): pass -class bool: +class basestring(object): + def __init__(self, x=None): pass + def __getitem__(self, index): pass + def __getslice__(self, start, end=None): pass + def __iadd__(self, other): pass + def __add__(self, other): pass + def __radd__(self, other): pass + def __mul__(self, other): pass + def __radd__(self, other): pass + def __mod__(self, other): pass + def __lt__(self, other): pass + def __gt__(self, other): pass + def __le__(self, other): pass + def __ge__(self, other): pass + def __eq__(self, other): pass + def __ne__(self, other): pass + def __len__(self): pass + def __str__(self): pass + def __bool__(self): pass + def join(self, l): pass + +class bool(object): def __bool__(self): pass def __str__(self): pass -class buffer: +class buffer(object): def __init__(self, size): pass def append(self, s): pass def __str__(self): pass -class dict: +class complex(object): + def __init__(self, real, imag=None): pass + +class dict(object): def __init__(self, *args): pass def __setitem__(self, key, value): pass def __getitem__(self, key): pass -class file: +class file(object): def write(self, s): pass -class float: +class float(object): def __init__(self, number_or_string=None): pass def __iadd__(self, other): pass def __isub__(self, other): pass @@ -69,7 +93,10 @@ def __str__(self): pass def __bool__(self): pass -class int: +class frozenset(object): + def __init__(self, iterable): pass + +class int(object): def __init__(self, number_or_string=None): pass def __iadd__(self, other): pass def __isub__(self, other): pass @@ -102,7 +129,7 @@ def __str__(self): pass def __bool__(self): pass -class list: +class list(object): def __init__(self, args=()): pass def __getitem__(self, index): pass def __setitem__(self, index, value): pass @@ -116,7 +143,7 @@ def __iter__(self): pass def __bool__(self): pass -class long: +class long(object): def __init__(self, number_or_string=None): pass def __iadd__(self, other): pass def __isub__(self, other): pass @@ -147,37 +174,19 @@ def __str__(self): pass def __bool__(self): pass -class none: - def __bool__(self): pass - def __str__(self): pass +class set(object): + def __init__(self, iterable): pass -NoneType = none - -class slice: +class slice(object): def __init__(self, start_or_end, end=None, step=None): pass -class str: - def __init__(self, x=None): pass - def __getitem__(self, index): pass - def __getslice__(self, start, end=None): pass - def __iadd__(self, other): pass - def __add__(self, other): pass - def __radd__(self, other): pass - def __mul__(self, other): pass - def __radd__(self, other): pass - def __mod__(self, other): pass - def __lt__(self, other): pass - def __gt__(self, other): pass - def __le__(self, other): pass - def __ge__(self, other): pass - def __eq__(self, other): pass - def __ne__(self, other): pass - def __len__(self): pass - def __str__(self): pass - def __bool__(self): pass - def join(self, l): pass +class str(basestring): + pass -class tuple: +class type(object): + pass + +class tuple(object): def __init__(self, args): pass def __getitem__(self, index): pass def __getslice__(self, start, end=None): pass @@ -187,48 +196,141 @@ def __iter__(self): pass def __bool__(self): pass -class xrange: +class unicode(basestring): + pass + +class xrange(object): def __init__(self, start_or_end, end=None, step=1): pass def __iter__(self): pass def next(self): pass -class Exception: +# Exceptions and warnings. + +class BaseException(object): def __init__(self, *args): pass -class AssertionError(Exception): - pass - -class AttributeError(Exception): - pass - -class IndexError(Exception): - pass - -class StopIteration(Exception): - pass +class Exception(BaseException): pass +class Warning(object): pass -class TypeError(Exception): - pass - -class NotImplementedType: - pass +class ArithmeticError(Exception): pass +class AssertionError(Exception): pass +class AttributeError(Exception): pass +class DeprecationWarning(Exception): pass +class EOFError(Exception): pass +class EnvironmentError(Exception): pass +class FloatingPointError(Exception): pass +class FutureWarning(Warning): pass +class GeneratorExit(Exception): pass +class IndexError(Exception): pass +class IOError(Exception): pass +class ImportError(Exception): pass +class ImportWarning(Warning): pass +class IndentationError(Exception): pass +class IndexError(Exception): pass +class KeyError(Exception): pass +class KeyboardInterrupt(Exception): pass +class LookupError(Exception): pass +class MemoryError(Exception): pass +class NameError(Exception): pass +class NotImplementedError(Exception): pass +class OSError(Exception): pass +class OverflowError(Exception): pass +class PendingDeprecationWarning(Warning): pass +class ReferenceError(Exception): pass +class RuntimeError(Exception): pass +class RuntimeWarning(Warning): pass +class StandardError(Exception): pass +class StopIteration(Exception): pass +class SyntaxError(Exception): pass +class SyntaxWarning(Warning): pass +class SystemError(Exception): pass +class SystemExit(Exception): pass +class TabError(Exception): pass +class TypeError(Exception): pass +class UnboundLocalError(Exception): pass +class UnicodeDecodeError(Exception): pass +class UnicodeEncodeError(Exception): pass +class UnicodeError(Exception): pass +class UnicodeTranslateError(Exception): pass +class UnicodeWarning(Warning): pass +class UserWarning(Warning): pass +class ValueError(Exception): pass +class ZeroDivisionError(Exception): pass -# General functions. +# Various types. + +class EllipsisType(object): pass -def isinstance(obj, cls): pass -def issubclass(cls1, cls2): pass -def len(x): pass -def max(*l): pass -def range(start_or_end, end=None, step=None): pass +class NoneType(object): + def __bool__(self): pass + def __str__(self): pass + +class NotImplementedType: pass # Special values. True = bool() False = bool() None = none() -stdin = file() -stdout = file() -stderr = file() +Ellipsis = ellipsis() NotImplemented = NotImplementedType() +# General functions. +# NOTE: Some of these are actually provided by classes in CPython. +# NOTE: We may refuse to support some of these in practice, such as... +# NOTE: super, reload. + +def __import__(name, globals=None, locals=None, fromlist=None, level=-1): pass +def abs(number): pass +def all(iterable): pass +def any(iterable): pass +def callable(obj): pass +def chr(i): pass +def classmethod(function): pass +def cmp(x, y): pass +def compile(source, filename, mode, flags=None, dont_inherit=None): pass +def delattr(obj, name): pass +def dir(obj=None): pass +def divmod(x, y): pass +def enumerate(iterable): pass +def eval(source, globals=None, locals=None): pass +def execfile(filename, globals=None, locals=None): pass +def filter(function, sequence): pass +def getattr(obj, name, default=None): pass +def globals(): pass +def hasattr(obj, name): pass +def hash(obj): pass +def help(*args, **kw): pass +def hex(number): pass +def id(obj): pass +def input(prompt=None): pass +def isinstance(obj, cls_or_tuple): pass +def issubclass(obj, cls_or_tuple): pass +def iter(collection_or_callable, sentinel=None): pass +def len(obj): pass +def locals(): pass +def map(function, *args): pass +def max(*args, **kw): pass +def min(*args, **kw): pass +def oct(number): pass +def open(name, mode=None, buffering=None): pass +def ord(c): pass +def pow(x, y, z=None): pass +def property(fget=None, fset=None, fdel=None, doc=None): pass +def range(start_or_end, end=None, step=None): pass +def raw_input(prompt=None): pass +def reduce(function, sequence, initial=None): pass +def reload(module): pass +def repr(obj): pass +def reversed(sequence): pass +def round(number, ndigits=None): pass +def setattr(obj, name, value): pass +def sorted(iterable, cmp=None, key=None, reverse=False): pass +def staticmethod(function): pass +def sum(sequence, start=0): pass +def super(*args): pass +def unichr(i): pass +def vars(obj=None): pass +def zip(*args): pass + # vim: tabstop=4 expandtab shiftwidth=4 diff -r eb3c1ed9dbee -r 8b8bb2f70246 lib/sys.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/sys.py Sun Apr 06 02:53:43 2008 +0200 @@ -0,0 +1,26 @@ +#!/usr/bin/env python + +""" +System functions and objects. + +Copyright (C) 2008 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 +Foundation; either version 3 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see . +""" + +stdin = file() +stdout = file() +stderr = file() + +# vim: tabstop=4 expandtab shiftwidth=4 diff -r eb3c1ed9dbee -r 8b8bb2f70246 micropython/__init__.py --- a/micropython/__init__.py Mon Mar 31 00:54:03 2008 +0200 +++ b/micropython/__init__.py Sun Apr 06 02:53:43 2008 +0200 @@ -50,6 +50,8 @@ class supports the generation of a program image. """ + supported_optimisations = micropython.ast.Translation.supported_optimisations + def __init__(self, path=None, verbose=0): """ diff -r eb3c1ed9dbee -r 8b8bb2f70246 micropython/ast.py --- a/micropython/ast.py Mon Mar 31 00:54:03 2008 +0200 +++ b/micropython/ast.py Sun Apr 06 02:53:43 2008 +0200 @@ -29,7 +29,7 @@ except NameError: from sets import Set as set -class TranslateError(ProcessingError): pass +class TranslateError(NodeProcessingError): pass class Label: @@ -195,9 +195,9 @@ """ self.dispatch(node.expr) - self._generateAttr(node.attrname, classes) + self._generateAttr(node, node.attrname, classes) - def _generateAttr(self, attrname, classes): + def _generateAttr(self, node, attrname, classes): """ Generate code for the access to 'attrname' using the given 'classes'. @@ -222,21 +222,39 @@ target = last.attr.value target_name = target.full_name() - table_entry = self.objtable.table[target_name] - pos = table_entry[attrname] + + try: + table_entry = self.objtable.table[target_name] + except KeyError: + raise TranslateError(self.module.full_name(), node, + "No object entry exists for target %r." % target_name) + + try: + pos = table_entry[attrname] + except KeyError: + raise TranslateError(self.module.full_name(), node, + "No attribute entry exists for name %r in target %r." % (attrname, target_name)) + self.replace_op(AttrInstruction(pos)) # Where the last operation involves the special 'self' name, check to # see if the attribute is acceptably positioned. - elif isinstance(last, LoadName) and last.attr.name == "self" and not self.unit.is_relocated(attrname): + elif self.unit.is_method() and isinstance(last, LoadName) and \ + last.attr.name == "self" and not self.unit.is_relocated(attrname): + attr = self.unit.parent.all_attributes()[attrname] self.new_op(AttrInstruction(attr)) # Otherwise, perform a normal operation. else: - index = self.objtable.get_index(attrname) + try: + index = self.objtable.get_index(attrname) + except self.objtable.TableError: + raise TranslateError(self.module.full_name(), node, + "No attribute entry exists for name %r." % attrname) + self.new_op(AttrIndexInstruction(index)) def _startCallFunc(self): @@ -437,7 +455,10 @@ def _get_builtin(self, name, node): if self.builtins is not None: - return self.builtins[name] + try: + return self.builtins[name] + except KeyError: + raise TranslateError(self.module.full_name(), node, "No __builtins__ definition is available for name %r." % name) else: raise TranslateError(self.module.full_name(), node, "No __builtins__ module is available for name %r." % name) @@ -534,7 +555,7 @@ self._startCallFunc() self.new_op(LoadTemp(1)) - self._generateAttr(left_method, (LoadAttr, LoadAttrIndex)) + self._generateAttr(node, left_method, (LoadAttr, LoadAttrIndex)) self.new_op(LoadTemp(1)) # Explicit context as first argument. self.new_op(LoadTemp(2)) self._endCallFunc() @@ -548,7 +569,7 @@ self.set_label(right_label) self._startCallFunc() self.new_op(LoadTemp(2)) - self._generateAttr(right_method, (LoadAttr, LoadAttrIndex)) + self._generateAttr(node, right_method, (LoadAttr, LoadAttrIndex)) self.new_op(LoadTemp(2)) # Explicit context as first argument. self.new_op(LoadTemp(1)) self._endCallFunc() @@ -661,7 +682,7 @@ self._startCallFunc() self.dispatch(node.list) - self._generateAttr("__iter__", (LoadAttr, LoadAttrIndex)) + self._generateAttr(node, "__iter__", (LoadAttr, LoadAttrIndex)) self._generateCallFunc([], node) self._endCallFunc() @@ -675,7 +696,7 @@ self._startCallFunc() self.new_op(Duplicate()) - self._generateAttr("next", (LoadAttr, LoadAttrIndex)) + self._generateAttr(node, "next", (LoadAttr, LoadAttrIndex)) self._generateCallFunc([], node) self._endCallFunc() diff -r eb3c1ed9dbee -r 8b8bb2f70246 micropython/common.py --- a/micropython/common.py Mon Mar 31 00:54:03 2008 +0200 +++ b/micropython/common.py Sun Apr 06 02:53:43 2008 +0200 @@ -23,6 +23,12 @@ "A processing error." + pass + +class NodeProcessingError(ProcessingError): + + "A processing error associated with a particular program node." + def __init__(self, unit_name, node, message): self.unit_name = unit_name self.node = node diff -r eb3c1ed9dbee -r 8b8bb2f70246 micropython/inspect.py --- a/micropython/inspect.py Mon Mar 31 00:54:03 2008 +0200 +++ b/micropython/inspect.py Sun Apr 06 02:53:43 2008 +0200 @@ -312,6 +312,10 @@ self.allattr = None # cache for all_attributes self.allattr_names = None # from allattr + # Add this class to its attributes. + + self.set("__class__", self) + # Image generation details. self.location = None @@ -653,6 +657,12 @@ del self.localnames[name] return self.localnames + def is_method(self): + + "Return whether this function is a method." + + return isinstance(self.parent, Class) + def is_relocated(self, name): """ @@ -669,12 +679,14 @@ "Make sure all attributes are fully defined." + i = None for i, name in enumerate(self.argnames): self[name].position = i - j = i - for i, attr in enumerate(self.locals().values()): - attr.position = i + j + if i is not None: + j = i + for i, attr in enumerate(self.locals().values()): + attr.position = i + j def function_from_method(self): diff -r eb3c1ed9dbee -r 8b8bb2f70246 micropython/table.py --- a/micropython/table.py Mon Mar 31 00:54:03 2008 +0200 +++ b/micropython/table.py Sun Apr 06 02:53:43 2008 +0200 @@ -3,7 +3,7 @@ """ Preparation of run-time attribute lookup tables. -Copyright (C) 2007 Paul Boddie +Copyright (C) 2007, 2008 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 @@ -19,16 +19,20 @@ this program. If not, see . """ +from micropython.common import * try: set except NameError: from sets import Set as set +class TableError(ProcessingError): pass + class List: """ A displaced list containing attribute details and an index mapping names to - offsets in the list. + offsets in the list. This is the optimised form of the table initially + constructed to record object attributes. """ def __init__(self, names): @@ -135,6 +139,8 @@ "A lookup table." + TableError = TableError + def __init__(self): self.attributes = set() self.table = {} @@ -171,13 +177,19 @@ "Return the code of the given 'name'." - return self.object_names().index(name) + try: + return self.object_names().index(name) + except ValueError: + raise TableError, "Name %r is not registered as an object in the table." % name def get_index(self, name): "Return the index of the given 'name'." - return self.attribute_names().index(name) + try: + return self.attribute_names().index(name) + except ValueError: + raise TableError, "Name %r is not registered as an attribute in the table." % name def as_matrix(self): diff -r eb3c1ed9dbee -r 8b8bb2f70246 test.py --- a/test.py Mon Mar 31 00:54:03 2008 +0200 +++ b/test.py Sun Apr 06 02:53:43 2008 +0200 @@ -13,12 +13,17 @@ print name, attr if __name__ == "__main__": - requested_optimisations = [] - for arg in sys.argv[2:]: - if arg.startswith("-o"): - requested_optimisations.append(arg[2:]) + args = sys.argv[2:] + i = micropython.Importer(sys.path, "-v" in args) - i = micropython.Importer(sys.path, "-v" in sys.argv) + if "-omax" in args: + requested_optimisations = i.supported_optimisations + else: + requested_optimisations = [] + for arg in args: + if arg.startswith("-o"): + requested_optimisations.append(arg[2:]) + try: builtins = i.load_from_file("lib/builtins.py", "__builtins__") if len(sys.argv) < 2: