rev 567 - in trunk: . pr/test src

SVN User <[email protected]> Thu, 03 Jun 2004 17:31:06 -0400
Newsgroups gmane.comp.lang.prothon.cvs
Message-ID <[email protected]>
Author: mark
Date: 2004-06-03 17:30:56 -0400 (Thu, 03 Jun 2004)
New Revision: 567

Modified:
   trunk/STATUS.txt
   trunk/pr/test/test.pr
   trunk/src/bytecodes.h
   trunk/src/console.c
   trunk/src/init.pth
   trunk/src/interp.c
   trunk/src/interp.h
   trunk/src/object.c
   trunk/src/parser_routines.c
   trunk/src/prothon.y
   trunk/src/sys.c
Log:
fixed stack problem with exceptions

Modified: trunk/STATUS.txt
===================================================================
--- trunk/STATUS.txt	2004-06-03 08:51:39 UTC (rev 566)
+++ trunk/STATUS.txt	2004-06-03 21:30:56 UTC (rev 567)
@@ -5,6 +5,8 @@
 --- GNU message catalog _"abc" strings
 --- change all strings to resource file
 
+--- replace <NULL>, <objptr:1>, and <objptr:2> with noDefault_, argList_, and kwDict_ 
+
 --- add resolution order combining prototypes and scope chains
 
 --- Add properties methods: get_,  set_, delete_
@@ -36,6 +38,8 @@
 --- add support for APR_BINARY in File.c ('b' flag)
 --- support any object that supports file methods in stdxxx (duck std)
 
+--- name_ and file_ (always absolute paths)
+
 --- nesting  /* .. */ comments 
 
 --- help() in interactive console()

Modified: trunk/pr/test/test.pr
===================================================================
--- trunk/pr/test/test.pr	2004-06-03 08:51:39 UTC (rev 566)
+++ trunk/pr/test/test.pr	2004-06-03 21:30:56 UTC (rev 567)
@@ -1,14 +1,726 @@
 #!/usr/bin/env prothon
 
-#  imp.pr
+"""String format parser"""
 
-Sys.path.append!('../../pr/test')
-Sys.path.append!('../pr/test')
-print Sys.path
+import Re as _re
+/*
+import gettext as _gettext
+import os.path as _path
+try:
+    _MyDir, MyName = _path.split(__file__)
+except:
+    _MyDir = '.'
+_LocalsDir = _path.join(_MyDir, 'locals')
+_TextDomain = 'formatparser'
+_gettext.bindtextdomain(_TextDomain, _LocalsDir)
+_gettext.textdomain(_TextDomain)
+_ = _gettext.gettext
+*/
 
-import imp2
+# Exception types.
+object FPParseError(ParseError):
+    pass
 
-print imp2.attrs_
+object FPIndexError(IndexError):
+    pass
 
-imp2.func(99)
+object FPTypeError(TypeError):
+    pass
 
+object Tokenizer:
+    """Break a string into tokens"""
+
+    def makeFactory(re):
+        pat = _re.compile(re)
+        def Factory(s='', psn=0, next=''):
+            return self(pat, s, psn, next)
+        Factory.regex = re
+        return Factory{}
+
+    def init_(pat, s='', psn=0, next='', end=None):
+        self.pat = pat
+        self.s = s
+        if end is None:
+            self.end = s.len()
+        else:
+            self.end = end
+        self.psn = psn
+        self.next = next
+        self.rejected = False
+
+    def synchronize(other):
+        if not self is other:
+            self.s = other.s
+            self.psn = other.psn
+            self.end = other.end
+            self.next = other.next
+
+    def nextToken():
+        if self.rejected:
+            self.rejected = False
+        elif self.psn < self.end:
+            m = self.pat.search(self.s, self.psn)
+            if m is None:
+                self.next = ''
+                self.psn = self.end
+            else:
+                self.psn = m.end()
+                self.next = self.s[m.start():self.psn]
+
+    def reject():
+        self.rejected = True
+
+    def peekNextCh():
+        if self.psn is not None:
+            try:
+                return self.s[self.psn]
+            except IndexError:
+                self.psn = None
+        return ''
+
+    def skipCh():
+        self.psn += 1
+        
+    def isEnd():
+        return self.psn >= self.end
+
+    def clear():
+        self.next = self.s = ''
+        self.psn = self.end = 0
+
+# Regular expression stuff
+# Please udate the break table if any changes made here.
+#
+# Find specifiers within a format string.
+RegEx = r"[^%]+"
+RootTokenizer = Tokenizer.makeFactory(RegEx)
+
+# Break a specifier into tokens.
+# A tokens is one of:
+# - "'" delimited string
+# - positive integer preceded by '@'
+# - character sequence starting with '%',
+#   not containing break characters or white space,
+#   and optionally ending with '%'
+# - character sequence not containing white space
+#   or break characters
+# - break character
+# Tokens can be any break character,
+# a "'" delimited string, a positive integer
+# preceded by a "@", an name starting with,
+# and optionally ending with, a '%',
+# or any character sequence not containing
+# a break character or whitespace.
+RegEx = (r"'(''|[^'])*'|"  +
+         r"@[0-9]+|"  +
+         r"%[^-\s%(),.@:'!=><+*/]*%?|"  +
+         r"[^-\s%(),.@:'!=><+*/]+|"  +
+         r"==|!=|>=|<=|"  +
+         r"[^\s]"
+         )
+FormatTokenizer = Tokenizer.makeFactory(RegEx)
+del RegEx
+    
+# Reserved characters in a specifier.
+# These form a break table.
+# Please modify the regular expressions if any
+# changes made here.
+BreakChars = r"%(),.@:'!=><+-*/"
+
+ich = BreakChars.iter_()
+Escape = ich.next()       # Marks special names at format level
+ArgListStart = ich.next() # Encloses function arguments
+ArgListEnd = ich.next()
+ArgSep = ich.next()       # Separates function arguments
+AttribRefOp = ich.next()  # References an anttribute
+PositionOp = ich.next()   # Starts a position indentifier
+ExprLitOp = ich.next()    # Leaves an expression unevaluated
+Quote = ich.next()        # Delimits a character string
+# Arithmetic / comparison operator primitives
+NotSign = ich.next()
+EqualSign = ich.next()
+GreaterThanSign = ich.next()
+LessThanSign = ich.next()
+PlusSign = ich.next()
+MinusSign = ich.next()
+TimesSign = ich.next()
+DivideSign = ich.next()
+del ich
+
+# Arithmetic / comparison operators
+EqualOp = EqualSign + EqualSign
+NotEqualOp = NotSign + EqualSign
+GreaterThanOp = GreaterThanSign
+GreaterThanOrEqualOp = GreaterThanSign + EqualSign
+LessThanOp = LessThanSign
+LessThanOrEqualOp = LessThanSign + EqualSign
+AdditionOp = PlusSign
+SubtractionOp = MinusSign
+MultiplicationOp = TimesSign
+DivisionOp = DivideSign
+
+object Node:
+    """Abstract base type for parse tree node"""
+
+    # Abstract methods.
+    def parse(tokens):
+        """Abstract parse method"""
+        raise NameError #, \
+              #"parse required for " + String(type(self))
+
+    def eval(context=None):
+        """Abstract eval method"""
+        # Though most node subclasses implement eval, it is not required.
+        # Catch unintensional calls.
+        raise NameError #, \
+              #"eval not implemented for " + String(type(self))
+    
+object Tree(Node):
+    """Abstract base type for none-leaf nodes"""
+
+    # Default methods.
+    def init_(tokens=None, parts=None):
+        if parts is None:
+            self.parts = []
+        else:
+            self.parts = list(parts)
+        self.parse(tokens)
+
+    def str_():
+        return ''.join([String(p) for p in self.iterParts()])
+
+    def addPart(part):
+        self.parts.append(part)
+
+    def iterParts(psn=0):
+        return iter(self.parts[psn:])
+    
+    def getPart(idx):
+        return self.parts[idx]
+
+    def getParts(start):
+        return self.parts[start:]
+
+object String(Node):
+    """Wrap a string in a node-like object."""
+    def init_(s):
+        self.s = s
+
+    def eval(*args):
+        return self.s
+
+    def str_():
+        return self.s
+
+object QuotedString(String):
+    """A quoted string"""
+    def init_(tokens):
+        super.init_(tokens.next[1:-1].replace(Quote*2, Quote))
+    def str_():
+        return (Quote +
+                super.str_().replace(Quote, Quote*2) +
+                Quote)
+        
+object Keyword(String):
+    """Keyword identifier node-like object"""
+    def init_(s):
+        super.init_(s)
+
+    def eval(context):
+        try:
+            obj = context.getObject(self.s)
+        except IndexError:
+            raise FPIndexError #, \
+                  #fmt(_("Identifier %(s) not found"), s=self.s)
+        return obj
+
+    def getValue():
+        return self.s
+
+    def evalAttribute(obj, context):
+        return context.getAttribute(obj, self.s)
+
+EmptyKeywordInstance = Keyword('')
+
+object IntegerLiteral(Node):
+    """Wrap an integer in a node-like object"""
+    def init_(i):
+        self.i = i
+
+    def eval(*args):
+        return self.i
+
+    def str_():
+        return String(self.i)
+
+object ArgumentPosition(Node):
+    """Argument position node-like object"""
+    def init_(tokens):
+        self.p = int(tokens.next[1:])
+
+    def eval(context):
+        return context.getObjectIdx(self.p)
+
+    def str_():
+        return PositionOp + String(self.p)
+
+def Identifier(tokens):
+    """Return token as a node"""
+    ch = tokens.next[0]
+    if ch == PositionOp:
+        node = ArgumentPosition(tokens)
+    elif ch == Quote:
+        node = QuotedString(tokens)
+    elif ch == Escape:
+        node = Keyword(tokens.next)
+    elif ch in BreakChars:
+        node = EmptyKeywordInstance
+        tokens.reject()
+    else:
+        s = tokens.next
+        try:
+            node = IntegerLiteral(int(s))
+        except ValueError:
+            node = Keyword(s)
+    return node
+
+# Accepts node in parts. Leaves token in next if any.
+object References(Tree):
+    """Reference an identifier"""
+
+    def parse(tokens):
+        while tokens.next == AttribRefOp:
+            tokens.nextToken()
+            if tokens.isEnd():
+                raise FPParseError #, \
+                      #_("Reference missing attribute keyword.")
+            node = Identifier(tokens)
+            if not isinstance(node, Keyword):
+                raise FPParseError #, \
+                      #fmt(_("Require a keyword for attribute name: got '%(n)'"),
+                      #    n=node)
+            if node is EmptyKeywordInstance:
+                raise FPParseError #, \
+                      #_("Require an attribute name: got nothing")
+            tokens.nextToken()
+            if tokens.next == ArgListStart:
+                self.addPart(FunctionCall(tokens, [node]))
+                tokens.nextToken()
+            else:
+                self.addPart(node)
+
+    def eval(context):
+        value = self.getPart(0).eval(context)
+        for attr in self.iterParts(1):
+            value = attr.evalAttribute(value, context)
+        return value
+
+    def str_():
+        return AttribRefOp.join([String(p) for p in self.iterParts()])
+
+object ExpressionClosure:
+    def init_(expr, context):
+        self.expr = expr
+        self.context = context
+
+    def getValue():
+        return self.expr.eval(self.context)
+
+    def str_():
+        return String(self.expr)
+
+# Accepts nothing. Leaves token in next, if any.
+object ExpressionLiteral(Tree):
+    def parse(tokens):
+        tokens.nextToken()
+        if tokens.next == '':
+            raise FPParseError #, \
+                  #_("Expecting an expression after a literal op.: got nothing")
+        self.addPart(QuotedExpression(tokens))
+
+    def eval(context):
+        return ExpressionClosure(self.getPart(0), context) 
+
+    def str_():
+        return ExprLitOp + String(self.getPart(0))
+
+object Negate(Node):
+    def init_(node):
+        self._node = node
+    def eval(context):
+        return context.doMethod(self._node.eval(context), '_minus_')
+    def str_():
+        return '-' + String(self._node)
+    
+# Accepts token in tokens. Leaves token in next, if any.
+def FullIdentifier(tokens):
+    if tokens.next == SubtractionOp:
+        tokens.nextToken()
+        if tokens.next is '':
+            raise FPParseError #, \
+                  #_("Unexpected end-of-negation op.")
+        node = FullIdentifier(tokens)
+        if node is EmptyKeywordInstance:
+            raise FPParseError #, \
+                  #_("Expected identifier after negation op.")
+        node = Negate(node)
+    else:
+        node = Identifier(tokens)
+        tokens.nextToken()
+        if tokens.next == ArgListStart:
+            node = FunctionCall(tokens, [node])
+            tokens.nextToken()
+        if tokens.next == AttribRefOp:
+            node = References(tokens, [node])
+    return node
+
+object BinaryOperator(Node):
+    # To be defined by subclasses
+    Op = ''
+    Method = ''
+    def getNode():
+        raise NameError #, \
+              #("BinaryOperator attribute getNode missing for %s" %
+              # type(self))
+
+    def init_(tokens, left, getNode):
+        if left is EmptyKeywordInstance:
+            raise FPParseError #, \
+                  #fmt(_("Expecting an expression before '%(s)' op."),
+                  #    s=self.Op)
+        self._left = left
+        tokens.nextToken()
+        if tokens.next == '':
+            raise FPParseError #, \
+                  #fmt(_("Unexpected end of '%(s)' expression"),
+                  #    s=self.Op)
+        right = getNode(tokens)
+        if right is EmptyKeywordInstance:
+            raise FPParseError#, \
+                  #fmt(_("Expecting an expression after '%(s)' op."),
+                  #    s=self.Op)
+        self._right = right
+
+    def eval(context):
+        return context.doMethod(self._left.eval(context),
+                                self.Method,
+                                self._right.eval(context))
+
+    def str_():
+        return "%s %s %s" % (self._left, self.Op, self._right)
+    
+object Divide(BinaryOperator):
+    Op = DivisionOp
+    Method = '_div_'
+
+object Multiply(BinaryOperator):
+    Op = MultiplicationOp
+    Method = '_mult_'
+
+# Accepts token in tokens. Leaves token in next, if any.
+def Multiplication(tokens):
+    node = FullIdentifier(tokens)
+    cont = True
+    while cont:
+        if tokens.next == MultiplicationOp:
+            node = Multiply(tokens, node, FullIdentifier)
+        elif tokens.next == DivisionOp:
+            node = Divide(tokens, node, FullIdentifier)
+        else:
+            cont = False
+    return node
+
+object Subtract(BinaryOperator):
+    Op = SubtractionOp
+    Method = '_sub_'
+
+object Add(BinaryOperator):
+    Op = AdditionOp
+    Method = '_add_'
+
+# Accepts token in tokens. Leaves token in next, if any.
+def Addition(tokens):
+    node = Multiplication(tokens)
+    cont = True
+    while cont:
+        if tokens.next == AdditionOp:
+            node = Add(tokens, node, Multiplication)
+        elif tokens.next == SubtractionOp:
+            node = Subtract(tokens, node, Multiplication)
+        else:
+            cont = False
+    return node
+
+object IsLessThanOrEqual(BinaryOperator):
+    Op = LessThanOrEqualOp
+    Method = '_le_'
+
+object IsLessThan(BinaryOperator):
+    Op = LessThanOp
+    Method = '_lt_'
+
+object IsGreaterThanOrEqual(BinaryOperator):
+    Op = GreaterThanOrEqualOp
+    Method = '_ge_'
+
+object IsGreaterThan(BinaryOperator):
+    Op = GreaterThanOp
+    Method = '_gt_'
+
+object IsNotEqual(BinaryOperator):
+    Op = NotEqualOp
+    Method = '_ne_'
+
+# Accepts node; returns token in next.
+object IsEqual(BinaryOperator):
+    Op = EqualOp
+    Method = '_eq_'
+
+# Accepts token in tokens. Leaves token in next, if any.
+def Comparison(tokens):
+    node = Addition(tokens)
+    if tokens.next == EqualOp:
+        node = IsEqual(tokens, node, Addition)
+    elif tokens.next == NotEqualOp:
+        node = IsNotEqual(tokens, node, Addition)
+    elif tokens.next == GreaterThanOp:
+        node = IsGreaterThan(tokens, node, Addition)
+    elif tokens.next == GreaterThanOrEqualOp:
+        node = IsGreaterThanOrEqual(tokens, node, Addition)
+    elif tokens.next == LessThanOp:
+        node = IsLessThan(tokens, node, Addition)
+    elif tokens.next == LessThanOrEqualOp:
+        node = IsLessThanOrEqual(tokens, node, Addition)
+    return node
+
+# Accepts token in tokens. Leaves token in next, if any.
+def QuotedExpression(tokens):
+    """Reference an identifier"""
+    if tokens.next == ExprLitOp:
+        node = ExpressionLiteral(tokens)
+    else:
+        node = Comparison(tokens)
+    return node
+
+# Accepts node in parts; ignores token in tokens;
+# leaves ArgListEnd in tokens.
+object FunctionCall(Tree):
+    """Call a function"""
+    def parse(tokens):
+        if not isinstance(self.getPart(0), Keyword):
+            raise FPParseError #, \
+                  #fmt(_("Function call requires keyword: got %(s)"),
+                  #    s=self.getPart(0))
+        while True:
+            tokens.nextToken()
+            if tokens.next == '':
+                raise FPParseError #, _("Unexpected end of arg. list")
+            node = QuotedExpression(tokens)
+            if not tokens.next:
+                raise FPParseError #, _("Unexpected end of arg. list")
+            if tokens.next == ArgListEnd: # Loop test
+                break
+            if tokens.next == ArgSep:
+                self.addPart(node)
+            else:
+                raise FPParseError #, \
+                      #fmt(_("Unexpected character %(c) in argument list"),
+                      #    c=tokens.next[0])
+        if node is not EmptyKeywordInstance:
+            self.addPart(node)
+    
+    def eval(context):
+        return context.doFunction(self.getPart(0).getValue(),
+                                  *[arg.eval(context) for arg in self.iterParts(1)])
+
+    def evalAttribute(obj, context):
+        return context.doMethod(obj, self.getPart(0).getValue(), 
+                                *[arg.eval(context) for arg in self.iterParts(1)])
+
+    def str_():
+        if self.getPart(-1) is EmptyKeywordInstance:
+            term=ArgSep
+        else:
+            term=''
+        return ("%s(%s%s)" %
+                (String(self.getPart(0)),
+                 ArgSep.join([String(p) for p in self.iterParts(1)]),
+                 term))
+
+SpecifierTokens = FormatTokenizer()  # Share with subtree node
+
+def Specifier(tokens):
+    """Parse a single format specifier"""
+    SpecifierTokens.synchronize(tokens)
+    SpecifierTokens.nextToken()
+    node = Identifier(SpecifierTokens)
+    if SpecifierTokens.next == Escape or SpecifierTokens.next[-1] != Escape:
+        SpecifierTokens.nextToken()
+        if SpecifierTokens.next == ArgListStart:
+            node = FunctionCall(SpecifierTokens, [node])
+        else:
+            raise FPParseError #, "Format specification missing arg. list."
+    tokens.synchronize(SpecifierTokens)
+    return node
+
+gen iterFormat(s):
+    """Iterate over the specifier and non-specifier parts
+       of a format."""
+    tokens = RootTokenizer(s)
+    while not tokens.isEnd():
+        if tokens.peekNextCh() == Escape:
+            yield Specifier(tokens)
+        else:
+            tokens.nextToken()
+            yield String(tokens.next)
+
+object Context:
+    """Execution environment of a specifier"""
+    
+    def init_(next, namedobjs=None, funcs=None, idxobjs=None):
+        self._nxtgetObject = next.getObject
+        if namedobjs is None or namedobjs.len() == 0:  # None or empty map
+            self._namedobjects = None
+            self.getObject = next.getObject
+        else:
+            print "mch", namedobjs
+            self._namedobjects = Dict(namedobjs)
+        self._nxtdoFunction = next.doFunction
+        if not funcs: # None or empty map
+            self._functions = None
+            self.doFunction = next.doFunction
+        else:
+            self._functions = Dict(funcs)
+        self._nxtgetObjectIdx = next.getObjectIdx
+        if not idxobjs:
+            self._indexedobjects = None
+            self.getObjectIdx = next.getObjectIdx
+        else:
+            self._indexedobjects = Tuple(idxobjs)
+        self.getAttribute = next.getAttribute
+        self.doMethod = next.doMethod
+
+    # Default context interface methods;
+    # may be overridden by instance versions.
+    def getObject(name):
+        try:
+            obj = self._namedobjects[name]
+        except IndexError:
+            obj = self._nxtgetObject(name)
+        return obj
+
+    def getObjectIdx(idx):
+        try:
+            obj = self._indexedobjects[idx]
+        except IndexError:
+            obj = self._nxtgetObjectIdx(idx)
+        return obj
+    
+    def doFunction(name, *args):
+        try:
+            fn = self._functions[name]
+        except IndexError:
+            return self._nxtdoFunction(name, *args)
+        return fn(*args)
+
+# Foratter for internal user.
+object SimpleFormatter:
+
+    def init_(map=None):
+        self._recurselevel = 0
+        if map is None:
+            self._map = {}
+        else:
+            self._map = dict(map)
+        self._map.update!({Escape: self._doFormat,
+                           '':None,
+                           Escape*2:Escape,
+                           '%sn%s' % (Escape, Escape): '\n'})
+
+    def call_(*args, **kwds):
+        """(fmt, id1=arg1, id2=arg2, ...) ==> string."""
+        if self._recurselevel > 1:
+            # We have a problem.
+            return "fmt: %s\n" +
+                   "args: %s\n" +
+                   "kwds: %s\n" % (repr(args[0]), String(args[1:]), String(kwds))
+        try:
+            fmt = args[0]
+        except IndexError:
+            raise FMTTypeError #, \
+                  #fmt(_("Formatter() takes at least 1 argument (%(n) given)"),
+                  #    n=args.len()
+        try:
+            for idx, arg in enumerate(args[1:]):
+                kwds[idx] = arg
+        except NameError:
+            for idx in args.len()-1:
+                kwds[idx] = args[idx+1]
+#            for idx, arg in zip(range(args.len()-1), args[1:]):
+#                kwds[idx] = arg
+        # Join upgrades to unicode if one of the
+        # sequence items is unicode.
+        context = self.newContext(kwds)
+        self._recurselevel += 1
+        try:
+            return ''.join([f.eval(context) for f in iterFormat(fmt)])
+        finally:
+            self._recurselevel -= 1
+
+    # Context interface.
+    def newContext(namedobjs=None, funcs=None, idxobjs=None):
+        return Context(self, namedobjs, funcs, idxobjs)
+    
+    def getObject(obj):
+        return self._map[obj]
+
+    def getObjectIdx(idx):
+        raise IndexError #, \
+              #fmt(_("Argument index @%(i) out-of-range"), i=idx)
+
+    def getAttribute(obj, attr):
+        if attr == 'type':
+            return type(obj)
+        if attr == 'str':
+            return String(obj)
+        if attr == 'unicode':
+            return unicode(obj)
+        if attr ==  'repr':
+            return repr(obj)
+        raise NameError #, \
+              #fmt(_("Unsupported attribute %(attr)"), attr=attr)
+        return '' # Never gets here
+
+    def doFunction(name, *args):
+        return self._map[name](*args)
+
+    def doMethod(obj, attr, *args):
+        if attr == 'center':
+            if isinstance(obj, unicode):
+                return obj.center(args[0])
+            return String(obj).center(args[0])
+        raise NameError #, \
+              #fmt(_("Unsupported method %(attr)"), attr=attr)
+        return '' # Never gets here
+
+    def close():
+        pass
+    
+    # Formatting function.
+    def _doFormat(obj, width=None, precision=None):
+        s = String(obj)
+        if not precision:
+            if not width:
+                return s
+            return "%*s" % (width, s)
+        if not width:
+            return "%.*s" % (precision, s)
+        return "%*.*s" % (width, precision, s)
+
+object fmt(SimpleFormatter): pass
+fmt.init_()
+
+print "Starting test now"
+print fmt("Version 0.4.3")
+print fmt("The value of pi to %(p) decimal places is %(pi,,p) .",
+          pi=3.141592658, p=4)
\ No newline at end of file

Modified: trunk/src/bytecodes.h
===================================================================
--- trunk/src/bytecodes.h	2004-06-03 08:51:39 UTC (rev 566)
+++ trunk/src/bytecodes.h	2004-06-03 21:30:56 UTC (rev 567)
@@ -223,6 +223,13 @@
 
 /********/ OP_TWO_WORDS_BOUNDARY, /********/ 
 
+// CLRSP
+// clear sp
+// stack: -> <empty>
+// param: <unused>
+// |opcode|
+OP_CLRSP,
+
 // POP
 // delete top-of-stack
 // param: words to pop
@@ -243,13 +250,6 @@
 // |opcode|
 OP_DUPLICATE,
 
-// SAVE_TMP
-// save top-of-stack in temporary register
-// stack: item -> <empty>
-// param: <unused>
-// |opcode|
-OP_SAVE_TMP,
-
 // RESTORE_TMP
 // push temporary register onto stack
 // stack: <empty> -> item

Modified: trunk/src/console.c
===================================================================
--- trunk/src/console.c	2004-06-03 08:51:39 UTC (rev 566)
+++ trunk/src/console.c	2004-06-03 21:30:56 UTC (rev 567)
@@ -189,7 +189,7 @@
 	new_self = new_object(ist, NULL);
 	if (!ist->frame) {
 		new_locals  = NEW_OBJ(NULL);
-		frame = create_frame(ist, new_self, NULL, NULL, new_locals, NULL, NULL);
+		frame = create_frame(ist, new_self, NULL, NULL, new_locals, NULL, NULL, "console");
 	}
 
 	if ((home = getenv("HOME")) != NULL)

Modified: trunk/src/init.pth
===================================================================
--- trunk/src/init.pth	2004-06-03 08:51:39 UTC (rev 566)
+++ trunk/src/init.pth	2004-06-03 21:30:56 UTC (rev 567)
@@ -12,7 +12,7 @@
 c:\prothon\modules\OS\debug
 c:\prothon\modules\DBM\debug
 
-# this is executed before Main1 as module PthMod1
+# this is executed before Main as module PthMod1
 
-#import Re,File
+import File
 
Modified: trunk/src/interp.c
===================================================================
--- trunk/src/interp.c	2004-06-03 08:51:39 UTC (rev 566)
+++ trunk/src/interp.c	2004-06-03 21:30:56 UTC (rev 567)
@@ -102,7 +102,7 @@
 
 //******************************** create_frame *****************************
 frame_p create_frame( isp ist, obj_p self, obj_p syn_locals, obj_p dyn_locals, 
-							   obj_p locals, obj_p func_obj, code_p code_in ) {
+							   obj_p locals, obj_p func_obj, code_p code_in, char* name ) {
     obj_p prev_scope;
 	frame_p frame;
 	code_p code = NULL;
@@ -113,7 +113,13 @@
 	frame = pr_malloc(flen);
 	memset(frame, 0, flen);
 
-	if (func_obj) frame->func = func_obj;
+	frame->func_name		  = name;
+	if (func_obj) {
+		obj_p name_obj;
+		frame->func = func_obj;
+		if (name_obj = get_attr(ist, func_obj, SYM(NAME_)))
+			frame->func_name = as_str(ist, name_obj);
+	}
 	frame->self				  = self;
 	frame->dyn_locals		  = dyn_locals;
 	frame->locals			  = locals;
@@ -125,7 +131,8 @@
 	if (!prev_scope && syn_locals) prev_scope = syn_locals;
 	if (prev_scope)
 		set_attr(ist, frame->locals, SYM(PREVSCOPE_), prev_scope);
-
+	if (!frame->func_name)
+		flen = 1;
 	return frame;																				  
 }
 
@@ -735,9 +742,13 @@
 				 frame_p *switch_frame, frame_p *free_frame, obj_p return_value ){
 	obj_p res = NULL;
 	if (fr_prev) {
+		if (ist->exception_obj) {
+			fr_sp = 0;
+			fr_push(OBJ(NONE));
+		}
 		if (fr_pc == fr_code->len && fr_sp == 0)
 			fr_push(OBJ(NONE));
-		if (fr_sp != 1){
+		if (fr_sp != 1) {
 			raise_exception(ist, OBJ(INTERNAL_EXC), "stack != 1 at return call");
 			return NULL;
 		}
@@ -814,7 +825,7 @@
 #ifdef TRACE_INTERPRETER
 	if (trace_interpreter) {
 		if (!tfout) tfout = fopen("!code_trace.txt", "w");
-		fprintf(tfout, "--- starting exec_loop at frame %8x, pc: %d\n", (intptr_t) frame, frame->pc);
+		fprintf(tfout, "--- starting exec_loop at frame %8x, pc: %d, %s\n", (intptr_t) frame, frame->pc, frame->func_name);
 		fflush(tfout);
 	}
 #endif
@@ -867,16 +878,13 @@
 		switch (op) {
 			case OP_NOP: 
 				break;
+			case OP_CLRSP:
+				fr_sp = 0;
+				break;
 			case OP_PUSH: 
 				for(i=1; i < param; i++) 
 					fr_push(fr_data(i)); 
 				break;
-			case OP_SAVE_TMP:
-				temp = fr_pop;
-				break;
-			case OP_RESTORE_TMP:
-				fr_push(temp);
-				break;
 			case OP_DUPLICATE: {
 				obj_p tmp = fr_stack[fr_sp+param];
 				fr_push(tmp);
@@ -1056,7 +1064,7 @@
 				if (op == OP_GEN) {
 					frame_p new_frame = create_frame( ist, frame->self, NULL,
 							                          frame->dyn_locals, frame->locals, 
-													  func, NULL );
+													  func, NULL, NULL );
 					new_frame->gen_marker = TRUE;
 					func->data.ptr  = NULL;
 					switch_proto(ist, func, OBJ(GEN_PROTO));
@@ -1125,8 +1133,10 @@
 			case OP_RERAISE:
 				ist->exception_obj = exc_waiting;
 				exc_waiting = 0;
-				if (exc_final_return)
+				if (exc_final_return) {
 					fr_pc = exc_final_return;
+					fr_sp = 0;
+				}
 				break;
 			case OP_EXEC: {
 				parse_state* state;
@@ -1141,7 +1151,7 @@
 				state = parse_file_or_string(ist, NULL, pr_strptr(str_obj));
 				if (!state || !(code = (state->parse_results))) break;
 				new_frame = create_frame( ist, frame->self, frame->syn_locals, frame->dyn_locals, 
-					                           frame->locals, NULL, code );
+					                           frame->locals, NULL, code, "execString" );
 				new_frame->syn_locals = frame->syn_locals;
 				new_frame->prev_frame = frame;
 				frame->next_frame     = new_frame;
@@ -1205,7 +1215,7 @@
 					}
 					IF_EXC_BREAK;
 					new_frame = create_frame( ist, self, NULL, frame->locals, 
-						                           new_locals, func_obj, NULL );
+						                           new_locals, func_obj, NULL, NULL );
 					fr_next = new_frame;
 					new_frame->prev_frame = frame;
 					load_frame_params(ist, new_locals, func_obj, param*2, fr_stack+fr_sp+2);
@@ -1286,7 +1296,7 @@
 #endif
 				fr_sp--;
 				switch_frame = create_frame( ist, frame->self, frame->locals, frame->dyn_locals, 
-					                              fr_stack[fr_sp], fr_data(1), NULL );
+					                              fr_stack[fr_sp], fr_data(1), NULL, "with" );
 				switch_frame->prev_frame = frame;
 				frame->next_frame = switch_frame;
 end_op_obj:		break;
@@ -1387,7 +1397,7 @@
 					}
 					IF_EXC_BREAK;
 					new_frame = create_frame( ist, self, NULL, frame->locals, 
-						                           new_locals, func_obj, NULL );
+						                           new_locals, func_obj, NULL, NULL );
 					fr_next = new_frame;
 					new_frame->prev_frame = frame;
 					load_frame_params(ist, new_locals, func_obj, param*2, fr_stack+fr_sp+3);
@@ -1539,7 +1549,7 @@
 #ifdef TRACE_INTERPRETER
 				if (trace_interpreter) {
 					fprintf(tfout, "--- delete top frame %8x\n", (intptr_t) tmp_frame);
-					fprintf(tfout, "--- new top frame is %8x\n", (intptr_t) frame);
+					fprintf(tfout, "--- new top frame is %8x, %s\n", (intptr_t) frame, frame->func_name);
 					fflush(tfout);
 				}
 #endif
@@ -1584,7 +1594,7 @@
 #ifdef TRACE_INTERPRETER
 			if (trace_interpreter) {
 				if (frame != DONE_FRAME_FLAG)
-					fprintf(tfout, "--- switch to frame %8x\n", (intptr_t) frame);
+					fprintf(tfout, "--- switch to frame %8x, %s\n", (intptr_t) frame, frame->func_name);
 				fflush(tfout);
 			}
 #endif
@@ -1666,7 +1676,7 @@
 		if (! (aself = get_attr(ist, func_obj, SYM(BINDOBJ_))) )
 			aself = self;   if_exc_return 0;
 		new_frame = create_frame(	ist, aself, NULL, NULL, 
-			                        new_locals, func_obj, NULL );
+			                        new_locals, func_obj, NULL, NULL );
 		new_frame->called_from_c = TRUE;
 		ist->frame->next_frame = new_frame;
 		new_frame->prev_frame = ist->frame;
@@ -1754,19 +1764,19 @@
 	if (framep && *framep) {
 		frame = *framep;
 		new_frame = create_frame( ist, frame->self, frame->syn_locals, frame->dyn_locals, 
-									   frame->locals, NULL, code );
+									   frame->locals, NULL, code, "execString" );
 		pr_free(*framep);
 		frame = NULL;
 	} else {
 		frame = ist->frame;
 		if (frame)
 			new_frame = create_frame( ist, frame->self, frame->syn_locals, frame->dyn_locals, 
-			                               frame->locals, NULL, code );
+			                               frame->locals, NULL, code, "execString" );
 		else {
 			obj_p new_globals = NEW_OBJ(NULL);
 			new_locals = NEW_OBJ(NULL);
 			new_frame = create_frame( ist, new_globals, new_locals, new_locals, 
-				                           new_locals, NULL, code );
+				                           new_locals, NULL, code, "execString" );
 		}
 	}
 	new_frame->called_from_c = TRUE;
@@ -1785,7 +1795,7 @@
 	obj_p thread;
 	frame_p frame, new_frame;
 	parse_state* state;
-	char full_doc[1024], *name;
+	char full_doc[1024], *name, *frame_name;
 	code_p code;
 	int i;
 
@@ -1819,7 +1829,11 @@
 	set_obj_doc(module, full_doc);
 	frame = ist->frame;
 	//new_locals = NEW_OBJ(NULL);
-	new_frame = create_frame( ist, NULL, NULL, NULL, module, NULL, code );
+	if (filename)
+		frame_name = filename;
+	else
+		frame_name = "execString";
+	new_frame = create_frame( ist, NULL, NULL, NULL, module, NULL, code, frame_name );
 	new_frame->called_from_c = TRUE;
 	if (frame) ist->frame->next_frame = new_frame;
 	new_frame->prev_frame = ist->frame;
@@ -1934,7 +1948,7 @@
 	}
 	new_locals = NEW_OBJ(NULL);
 	thread_module = NEW_OBJ(NULL);
-	new_frame = create_frame( ist, thread_module, thread_module, NULL, new_locals, func_obj, NULL );
+	new_frame = create_frame(ist, thread_module, thread_module, NULL, new_locals, func_obj, NULL , NULL);
 	new_frame->called_from_c = TRUE;
 	new_frame->prev_frame = NULL;
 	load_frame_params( ist, new_locals, func_obj, parm_cnt, lbl_val_arr);
@@ -1992,10 +2006,8 @@
 		pr_assert(param);
 		fprintf(fout,"%4d %20s(%4d) %s", pc, "OP_NOP", param, codedata(str, code, op, param, pc));
 		break;
-	case OP_SAVE_TMP: fprintf(fout,"%4d %20s(%4d) %s", pc, "OP_SAVE_TMP", param, codedata(str, code, op, param, pc));
+	case OP_CLRSP: fprintf(fout,"%4d %20s(%4d) %s", pc, "OP_CLRSP", param, codedata(str, code, op, param, pc));
 		break;
-	case OP_RESTORE_TMP: fprintf(fout,"%4d %20s(%4d) %s", pc, "OP_RESTORE_TMP", param, codedata(str, code, op, param, pc));
-		break;
 	case OP_IMPORT: fprintf(fout,"%4d %20s(%4d) %s", pc, "OP_IMPORT", param, codedata(str, code, op, param, pc));
 		break;
 	case OP_IMPORT_AS: fprintf(fout,"%4d %20s(%4d) %s", pc, "OP_IMPORT_AS", param, codedata(str, code, op, param, pc));

Modified: trunk/src/interp.h
===================================================================
--- trunk/src/interp.h	2004-06-03 08:51:39 UTC (rev 566)
+++ trunk/src/interp.h	2004-06-03 21:30:56 UTC (rev 567)
@@ -91,6 +91,7 @@
 	code_p		code;
 	clist_p		exc_stack;
 	int			stack_ptr;
+	char*		func_name;
 	obj_p		stack[];
 } frame_t;
 
@@ -113,7 +114,7 @@
 } fparam_proc_state_t;
 
 frame_p create_frame( isp ist, obj_p self, obj_p syn_locals, obj_p dyn_locals, 
-					           obj_p locals, obj_p func_obj, code_p code_in );
+					           obj_p locals, obj_p func_obj, code_p code_in, char* name );
 
 void *main_thread(apr_thread_t *handle, void *filename);
 void *user_thread(apr_thread_t *handle, void *argv); 

Modified: trunk/src/object.c
===================================================================
--- trunk/src/object.c	2004-06-03 08:51:39 UTC (rev 566)
+++ trunk/src/object.c	2004-06-03 21:30:56 UTC (rev 567)
@@ -992,6 +992,7 @@
 		if (scope == super_obj) super_obj = NULL;
 		last_scope = scope;
 		scope = get_attr(ist, scope, SYM(PREVSCOPE_));
+		pr_assert(last_scope != scope);
 	}
 	if (!res && last_scope)
 		return get_proto_attr(ist, last_scope, key, scope_pp, super_obj);

Modified: trunk/src/parser_routines.c
===================================================================
--- trunk/src/parser_routines.c	2004-06-03 08:51:39 UTC (rev 566)
+++ trunk/src/parser_routines.c	2004-06-03 21:30:56 UTC (rev 567)
@@ -1167,21 +1167,20 @@
 	int len=0, stack_depth=0, max_stack_depth = 0;
 	int k=0, end_icall_loc, end_exc_loc, end_loc;
 	calc_code(rparm, &len, &stack_depth, &max_stack_depth); 
-	len += 2;
+	len += 1;
 	calc_code(ref, &len, &stack_depth, &max_stack_depth); 
 	len += 9;
 	end_icall_loc = len;
 	len += 4;
 	calc_code(ref, &len, &stack_depth, &max_stack_depth); 
-	len += 6;
+	len += 7;
 	calc_code(ref, &len, &stack_depth, &max_stack_depth);
-	len += 3;
+	len += 2;
 	end_exc_loc = len;
 	len++;
 	end_loc = len;
 	res = new_code(param, len, stack_depth, max_stack_depth, 0);
 	add_code(rparm, res, &k);
-	res->code_data[k++].bytecode.opcode = OP_SAVE_TMP;
 	res->code_data[k  ].bytecode.opcode = OP_TRYEXCEPT;
 	res->code_data[k  ].bytecode.param  = end_icall_loc - k;
 	k++;
@@ -1192,11 +1191,12 @@
 	res->code_data[k++].data = sym_id_table[iop].id;
 	res->code_data[k++].data = NULL;
 	res->code_data[k++].data = PARAM_NORMAL;
-	res->code_data[k++].bytecode.opcode = OP_RESTORE_TMP;
+	res->code_data[k  ].bytecode.opcode = OP_DUPLICATE;
+	res->code_data[k++].bytecode.param  = -5;
 	res->code_data[k  ].bytecode.opcode = OP_CALL;
 	res->code_data[k++].bytecode.param  = 1;
 	res->code_data[k  ].bytecode.opcode = OP_POP;
-	res->code_data[k++].bytecode.param  = 1;
+	res->code_data[k++].bytecode.param  = 2;
 	res->code_data[k  ].bytecode.opcode = OP_BR;
 	res->code_data[k  ].bytecode.param  = end_loc - k;
 	k++;
@@ -1215,18 +1215,19 @@
 	res->code_data[k++].data = sym_id_table[op].id;
 	res->code_data[k++].data = NULL;
 	res->code_data[k++].data = PARAM_NORMAL;
-	res->code_data[k++].bytecode.opcode = OP_RESTORE_TMP;
+	res->code_data[k  ].bytecode.opcode = OP_DUPLICATE;
+	res->code_data[k++].bytecode.param  = -5;
 	res->code_data[k  ].bytecode.opcode = OP_CALL;
 	res->code_data[k++].bytecode.param  = 1;
 	add_code(ref, res, &k);
 	res->code_data[k  ].bytecode.opcode = OP_ASSIGN;
 	res->code_data[k++].bytecode.param  = 1;
 	res->code_data[k  ].bytecode.opcode = OP_POP;
-	res->code_data[k++].bytecode.param  = 1;
+	res->code_data[k++].bytecode.param  = 2;
 	pr_assert(end_exc_loc = k);
 	res->code_data[k++].bytecode.opcode = OP_RERAISE;
 	pr_assert(end_loc = k);
-	res->stack_depth -= 7;
+	res->stack_depth = 0;
 	return debug_retrn(__LINE__, res);
 }
 code_p while_expr_body_else(void* param, obj_p label, code_p expr, code_p body, code_p els){
@@ -1598,6 +1599,7 @@
 	calc_code(body, &len, &stack_depth, &max_stack_depth); 
 	len += 2;
 	except_loc = len;  
+	len += 1;
 	for(i=0; i < llen; i++)
 		calc_code(clist_item(except_list,i), &len, &stack_depth, &max_stack_depth);
 	len += llen + 1;
@@ -1614,6 +1616,7 @@
 	res->code_data[k  ].bytecode.param  = els_loc - k;
 	k++;
 	pr_assert(except_loc == k);
+	res->code_data[k++].bytecode.opcode = OP_CLRSP;
 	for (i = 0; i < llen; i++, k++) {
 		add_code(clist_item(except_list,i), res, &k);
 		res->code_data[k  ].bytecode.opcode = OP_BR;
@@ -1628,12 +1631,13 @@
 }
 code_p tryfinally_body(void* param, code_p body, code_p final){
 	code *res;
-	int k=0, len=2, stack_depth=0, max_stack_depth = 0;
+	int k=0, len=3, stack_depth=0, max_stack_depth = 0;
 	calc_code(body, &len, &stack_depth, &max_stack_depth);
 	calc_code(final, &len, &stack_depth, &max_stack_depth);
 	res = new_code(param, len, stack_depth, max_stack_depth, OP_TRYFINALLY);
 	res->code_data[k++].bytecode.param = body->len+1;
 	add_code(body, res, &k);
+	res->code_data[k++].bytecode.opcode = OP_CLRSP;
 	add_code(final, res, &k);
 	res->code_data[k++].bytecode.opcode = OP_RERAISE;
 	pr_assert(res->len == k);

Modified: trunk/src/prothon.y
===================================================================
--- trunk/src/prothon.y	2004-06-03 08:51:39 UTC (rev 566)
+++ trunk/src/prothon.y	2004-06-03 21:30:56 UTC (rev 567)
@@ -992,6 +992,11 @@
 		str_ptr[str_index++]=0;		
 		str_ptr = pr_realloc(str_ptr, str_index);
 		lvalp->str_type = new_string_n_obj((((parse_state*) yylex_param)->ist), str_ptr, str_index-1); 
+#ifdef TRACE_PARSER
+	if (trace_parser){
+		fprintf((((parse_state*) yylex_param)->debug_stream, "\"%s\"\n",str_ptr);
+	}
+#endif
 		return STRING;
 	}
 	goto not_quote;
@@ -1153,6 +1158,11 @@
 
 		str_ptr = pr_realloc(str_ptr, str_index);
 		lvalp->str_type = new_string_n_obj((((parse_state*) yylex_param)->ist), str_ptr, str_index-1); 
+#ifdef TRACE_PARSER
+	if (trace_parser){
+		fprintf((((parse_state*) yylex_param)->debug_stream, "\"%s\"\n",str_ptr);
+	}
+#endif
 		return LABEL;
 	}
 	/* process dot, int, or float */

Modified: trunk/src/sys.c
===================================================================
--- trunk/src/sys.c	2004-06-03 08:51:39 UTC (rev 566)
+++ trunk/src/sys.c	2004-06-03 21:30:56 UTC (rev 567)
@@ -174,7 +174,7 @@
 				path[len-1] = 0;
 			strcpy(home, path);
 			have_home = TRUE;
-			set_attr(ist, sys_module, sym(ist, "prothonhome"), NEW_STRING(home));
+			set_attr(ist, sys_module, sym(ist, "home"), NEW_STRING(home));
 		}
 	}
 	if (!have_home) {
@@ -193,7 +193,6 @@
 	list_append(ist, vers_tuple, NEW_STRING(PROTHON_VERSION_DATE));
 	vers_tuple->immutable = TRUE;
 	set_attr(ist, sys_module, sym(ist, "version"), vers_tuple);
-	set_attr(ist, sys_module, sym(ist, "maxint"),  NEW_INT(MAX_INT_VAL));
 	set_attr(ist, sys_module, sym(ist, "modules"), OBJ(MODULES));
 	set_attr( ist, sys_module, sym(ist, "exit"),
 		      new_C_func_obj(ist, sys_exit, list2(ist, sym(ist,"num"),NEW_INT(1))) );