[pypy-svn] r23730 - in pypy/branch/condexpr: . pypy/interpreter/astcompiler pypy/interpreter/pyparser pypy/interpreter/pyparser/data pypy/interpreter/pyparser/test pypy/interpreter/stablecompiler pypy/interpreter/test pypy/module/__builtin__ pypy/module/__builtin__/test pypy/tool pypy/translator

blais at codespeak.net blais at codespeak.net
Tue Feb 28 02:21:54 CET 2006


Author: blais
Date: Tue Feb 28 02:21:52 2006
New Revision: 23730

Added:
   pypy/branch/condexpr/
      - copied from r23700, pypy/dist/
   pypy/branch/condexpr/pypy/interpreter/pyparser/data/Grammar2.5a
   pypy/branch/condexpr/pypy/interpreter/pyparser/data/README
   pypy/branch/condexpr/pypy/module/__builtin__/__init__.py
      - copied unchanged from r23703, pypy/dist/pypy/module/__builtin__/__init__.py
   pypy/branch/condexpr/pypy/module/__builtin__/app_functional.py
      - copied unchanged from r23703, pypy/dist/pypy/module/__builtin__/app_functional.py
   pypy/branch/condexpr/pypy/module/__builtin__/test/test_functional.py
      - copied unchanged from r23703, pypy/dist/pypy/module/__builtin__/test/test_functional.py
   pypy/branch/condexpr/pypy/translator/interactive.py
      - copied unchanged from r23703, pypy/dist/pypy/translator/interactive.py
Removed:
   pypy/branch/condexpr/pypy/interpreter/astcompiler/transformer.py
Modified:
   pypy/branch/condexpr/pypy/interpreter/astcompiler/ast.py
   pypy/branch/condexpr/pypy/interpreter/astcompiler/ast.txt
   pypy/branch/condexpr/pypy/interpreter/pyparser/astbuilder.py
   pypy/branch/condexpr/pypy/interpreter/pyparser/ebnfparse.py
   pypy/branch/condexpr/pypy/interpreter/pyparser/pysymbol.py
   pypy/branch/condexpr/pypy/interpreter/pyparser/pythonparse.py
   pypy/branch/condexpr/pypy/interpreter/pyparser/symbol.py
   pypy/branch/condexpr/pypy/interpreter/pyparser/test/test_astbuilder.py
   pypy/branch/condexpr/pypy/interpreter/stablecompiler/transformer.py
   pypy/branch/condexpr/pypy/interpreter/test/test_syntax.py
   pypy/branch/condexpr/pypy/tool/option.py
Log:
Branch for adding conditional expressions to PyPy.
This involves changing the grammar so there are lots
of changes involved.


Modified: pypy/branch/condexpr/pypy/interpreter/astcompiler/ast.py
==============================================================================
--- pypy/dist/pypy/interpreter/astcompiler/ast.py	(original)
+++ pypy/branch/condexpr/pypy/interpreter/astcompiler/ast.py	Tue Feb 28 02:21:52 2006
@@ -1232,6 +1232,63 @@
                     ops=GetSetProperty(Compare.fget_ops, Compare.fset_ops ),
                     )
 
+class CondExpr(Node):
+    def __init__(self, expr, left, right, lineno=-1):
+        Node.__init__(self, lineno)
+        self.expr = expr
+        self.left = left
+        self.right = right
+
+    def getChildren(self):
+        "NOT_RPYTHON"
+        return self.expr, self.left, self.right
+
+    def getChildNodes(self):
+        return [self.expr, self.left, self.right]
+
+    def __repr__(self):
+        return "CondExpr(%s, %s, %s)" % (self.expr.__repr__(), self.left.__repr__(), self.right.__repr__())
+
+    def accept(self, visitor):
+        return visitor.visitCondExpr(self)
+
+    def fget_expr( space, self):
+        return space.wrap(self.expr)
+    def fset_expr( space, self, w_arg):
+        self.expr = space.interp_w(Node, w_arg, can_be_None=False)
+    def fget_left( space, self):
+        return space.wrap(self.left)
+    def fset_left( space, self, w_arg):
+        self.left = space.interp_w(Node, w_arg, can_be_None=False)
+    def fget_right( space, self):
+        return space.wrap(self.right)
+    def fset_right( space, self, w_arg):
+        self.right = space.interp_w(Node, w_arg, can_be_None=False)
+
+def descr_CondExpr_new(space, w_subtype, w_expr, w_left, w_right, lineno=-1):
+    self = space.allocate_instance(CondExpr, w_subtype)
+    expr = space.interp_w(Node, w_expr, can_be_None=False)
+    self.expr = expr
+    left = space.interp_w(Node, w_left, can_be_None=False)
+    self.left = left
+    right = space.interp_w(Node, w_right, can_be_None=False)
+    self.right = right
+    self.lineno = lineno
+    return space.wrap(self)
+
+def descr_CondExpr_accept( space, w_self, w_visitor):
+    w_callable = space.getattr(w_visitor, space.wrap('visitCondExpr'))
+    args = Arguments(space, [ w_self ])
+    return space.call_args(w_callable, args)
+
+CondExpr.typedef = TypeDef('CondExpr', Node.typedef, 
+                     __new__ = interp2app(descr_CondExpr_new, unwrap_spec=[ObjSpace, W_Root, W_Root, W_Root, W_Root, int]),
+                     accept=interp2app(descr_CondExpr_accept, unwrap_spec=[ObjSpace, W_Root, W_Root] ),
+                    expr=GetSetProperty(CondExpr.fget_expr, CondExpr.fset_expr ),
+                    left=GetSetProperty(CondExpr.fget_left, CondExpr.fset_left ),
+                    right=GetSetProperty(CondExpr.fget_right, CondExpr.fset_right ),
+                    )
+
 class Const(Node):
     def __init__(self, value, lineno=-1):
         Node.__init__(self, lineno)
@@ -4232,6 +4289,8 @@
         return self.default( node )
     def visitCompare(self, node):
         return self.default( node )
+    def visitCondExpr(self, node):
+        return self.default( node )
     def visitConst(self, node):
         return self.default( node )
     def visitContinue(self, node):

Modified: pypy/branch/condexpr/pypy/interpreter/astcompiler/ast.txt
==============================================================================
--- pypy/dist/pypy/interpreter/astcompiler/ast.txt	(original)
+++ pypy/branch/condexpr/pypy/interpreter/astcompiler/ast.txt	Tue Feb 28 02:21:52 2006
@@ -78,6 +78,7 @@
 AbstractTest:
 Or(AbstractTest): nodes!
 And(AbstractTest): nodes!
+CondExpr: expr, left, right
 BitOp:
 Bitor(BitOp): nodes!
 Bitxor(BitOp): nodes!

Modified: pypy/branch/condexpr/pypy/interpreter/pyparser/astbuilder.py
==============================================================================
--- pypy/dist/pypy/interpreter/pyparser/astbuilder.py	(original)
+++ pypy/branch/condexpr/pypy/interpreter/pyparser/astbuilder.py	Tue Feb 28 02:21:52 2006
@@ -1,6 +1,6 @@
 """This module provides the astbuilder class which is to be used
 by GrammarElements to directly build the AST during parsing
-without going trhough the nested tuples step
+without going through the nested tuples step
 """
 
 from grammar import BaseGrammarBuilder, AbstractContext
@@ -257,9 +257,9 @@
             ifs = []
         else:
             assert False, 'Unexpected token: expecting for in listcomp'
-        # 
+        #
         # Original implementation:
-        # 
+        #
         # if tokens[index].get_value() == 'for':
         #     index += 1 # skip 'for'
         #     ass_node = to_lvalue(tokens[index], consts.OP_ASSIGN)
@@ -320,7 +320,7 @@
 
 def get_docstring(builder,stmt):
     """parses a Stmt node.
-    
+
     If a docstring if found, the Discard node is **removed**
     from <stmt> and the docstring is returned.
 
@@ -340,7 +340,7 @@
                 del stmt.nodes[0]
                 doc = expr.value
     return doc
-    
+
 
 def to_lvalue(ast_node, flags):
     lineno = ast_node.lineno
@@ -388,7 +388,7 @@
                                  lineno, 0, '')
         else:
             raise SyntaxError("can't assign to non-lvalue",
-                             lineno, 0, '') 
+                             lineno, 0, '')
 
 def is_augassign( ast_node ):
     if ( isinstance( ast_node, ast.Name ) or
@@ -410,7 +410,7 @@
         i -= 1
     atoms.reverse()
     return atoms
-    
+
 #def eval_string(value):
 #    """temporary implementation
 #
@@ -466,7 +466,7 @@
 
 def parse_attraccess(tokens):
     """parses token list like ['a', '.', 'b', '.', 'c', ...]
-    
+
     and returns an ast node : ast.Getattr(Getattr(Name('a'), 'b'), 'c' ...)
     """
     token = tokens[0]
@@ -579,7 +579,7 @@
         return lst[first:last]
     else:
         return []
-    
+
 
 def build_power(builder, nb):
     """power: atom trailer* ['**' factor]"""
@@ -742,7 +742,10 @@
             builder.push(TokenObject(tok.NAME, 'is not', lineno))
     else:
         assert False, "TODO" # uh ?
-        
+
+def build_or_test(builder, nb):
+    return build_binary_expr(builder, nb, ast.Or)
+
 def build_and_test(builder, nb):
     return build_binary_expr(builder, nb, ast.And)
 
@@ -756,8 +759,18 @@
         assert False, "not_test implementation incomplete in not_test"
 
 def build_test(builder, nb):
-    return build_binary_expr(builder, nb, ast.Or)
-    
+    atoms = get_atoms(builder, nb)
+    if len(atoms) == 1:
+        builder.push(atoms[0])
+    elif len(atoms) == 5:
+        builder.push(
+            ast.CondExpr(atoms[2], atoms[0], atoms[4], atoms[1].lineno))
+    else:
+        assert False, "invalid number of atoms for rule 'test'"
+
+# Note: we do not include a build_old_test() because it does not need to do
+# anything.
+
 def build_testlist(builder, nb):
     return build_binary_expr(builder, nb, ast.Tuple)
 
@@ -837,7 +850,7 @@
             stmts.extend(node.nodes)
         elif isinstance(node, TokenObject) and node.name == tok.ENDMARKER:
             # XXX Can't we just remove the last element of the list ?
-            break    
+            break
         elif isinstance(node, TokenObject) and node.name == tok.NEWLINE:
             continue
         else:
@@ -911,7 +924,6 @@
     names, defaults, flags = parse_arglist(slicecut(atoms, 1, -2))
     builder.push(ast.Lambda(names, defaults, flags, code, lineno))
 
-
 def build_trailer(builder, nb):
     """trailer: '(' ')' | '(' arglist ')' | '[' subscriptlist ']' | '.' NAME
     """
@@ -1009,7 +1021,7 @@
         else:
             builder.push(SlicelistObject('slice', sliceinfos, lineno))
 
-        
+
 def build_listmaker(builder, nb):
     """listmaker: test ( list_for | (',' test)* [','] )"""
     atoms = get_atoms(builder, nb)
@@ -1325,7 +1337,7 @@
 def build_del_stmt(builder, nb):
     atoms = get_atoms(builder, nb)
     builder.push(to_lvalue(atoms[1], consts.OP_DELETE))
-        
+
 
 def build_assert_stmt(builder, nb):
     """assert_stmt: 'assert' test [',' test]"""
@@ -1404,7 +1416,7 @@
                ['else' ':' suite] | 'try' ':' suite 'finally' ':' suite)
     # NB compile.c makes sure that the default except clause is last
     except_clause: 'except' [test [',' test]]
-   
+
     """
     atoms = get_atoms(builder, nb)
     l = len(atoms)
@@ -1446,6 +1458,7 @@
     sym['expr'] : build_expr,
     sym['comparison'] : build_comparison,
     sym['comp_op'] : build_comp_op,
+    sym['or_test'] : build_or_test,
     sym['and_test'] : build_and_test,
     sym['not_test'] : build_not_test,
     sym['test'] : build_test,
@@ -1457,6 +1470,7 @@
     sym['file_input'] : build_file_input,
     sym['testlist_gexp'] : build_testlist_gexp,
     sym['lambdef'] : build_lambdef,
+    sym['old_lambdef'] : build_lambdef,
     sym['trailer'] : build_trailer,
     sym['arglist'] : build_arglist,
     sym['subscript'] : build_subscript,
@@ -1494,8 +1508,8 @@
         self.count = count
         self.lineno = lineno # src.getline()
         self.col = 0  # src.getcol()
-        
-    
+
+
 class RuleObject(BaseRuleObject):
     """A simple object used to wrap a rule or token"""
     def __init__(self, name, count, lineno):
@@ -1511,18 +1525,18 @@
 
 class TempRuleObject(BaseRuleObject):
     """used to keep track of how many items get_atom() should pop"""
-    
+
     def __init__(self, name, count, lineno):
         BaseRuleObject.__init__(self, count, lineno)
         self.temp_rulename = name
-        
+
     def __str__(self):
         return "<Rule: %s/%d>" % (self.temp_rulename, self.count)
 
     def __repr__(self):
         return "<Rule: %s/%d>" % (self.temp_rulename, self.count)
 
-    
+
 class TokenObject(ast.Node):
     """A simple object used to wrap a rule or token"""
     def __init__(self, name, value, lineno):
@@ -1532,7 +1546,7 @@
         # self.line = 0 # src.getline()
         self.col = 0  # src.getcol()
         self.lineno = lineno
-        
+
     def get_name(self):
         return tok.tok_rpunct.get(self.name,
                                   tok.tok_name.get(self.name, str(self.name)))
@@ -1542,10 +1556,10 @@
         if value is None:
             value = ''
         return value
-    
+
     def __str__(self):
         return "<Token: (%s,%s)>" % (self.get_name(), self.value)
-    
+
     def __repr__(self):
         return "<Token: (%r,%s)>" % (self.get_name(), self.value)
 
@@ -1568,13 +1582,13 @@
 
     def __str__(self):
         return "<ArgList: (%s, %s, %s)>" % self.value
-    
+
     def __repr__(self):
         return "<ArgList: (%s, %s, %s)>" % self.value
-    
+
 class SubscriptObject(ObjectAccessor):
     """helper class to build subscript list
-    
+
     self.value represents the __getitem__ argument
     """
     def __init__(self, name, value, lineno):
@@ -1584,7 +1598,7 @@
 
     def __str__(self):
         return "<SubscriptList: (%s)>" % self.value
-    
+
     def __repr__(self):
         return "<SubscriptList: (%s)>" % self.value
 
@@ -1603,10 +1617,10 @@
 
     def __str__(self):
         return "<SliceList: (%s)>" % self.value
-    
+
     def __repr__(self):
         return "<SliceList: (%s)>" % self.value
-    
+
 
 class AstBuilderContext(AbstractContext):
     """specific context management for AstBuidler"""
@@ -1622,7 +1636,7 @@
         self.rule_stack = []
         self.space = space
         self.source_encoding = None
-        
+
     def context(self):
         return AstBuilderContext(self.rule_stack)
 
@@ -1718,12 +1732,12 @@
             l = space.builtin.get('long')
             return space.call_function(l, space.wrap(value), space.wrap(base))
         if value.endswith('j') or value.endswith('J'):
-            c = space.builtin.get('complex') 
+            c = space.builtin.get('complex')
             return space.call_function(c, space.wrap(value))
         try:
             i = space.builtin.get('int')
             return space.call_function(i, space.wrap(value), space.wrap(base))
-        except: 
+        except:
             f = space.builtin.get('float')
             return space.call_function(f, space.wrap(value))
 
@@ -1760,4 +1774,4 @@
         else:
             obj2 = "-"
         print "% 3d | %30s | %30s" % (i, obj1, obj2)
-    
+

Added: pypy/branch/condexpr/pypy/interpreter/pyparser/data/Grammar2.5a
==============================================================================
--- (empty file)
+++ pypy/branch/condexpr/pypy/interpreter/pyparser/data/Grammar2.5a	Tue Feb 28 02:21:52 2006
@@ -0,0 +1,129 @@
+# Grammar for Python
+
+# Note:  Changing the grammar specified in this file will most likely
+#        require corresponding changes in the parser module
+#        (../Modules/parsermodule.c).  If you can't make the changes to
+#        that module yourself, please co-ordinate the required changes
+#        with someone who can; ask around on python-dev for help.  Fred
+#        Drake <fdrake at acm.org> will probably be listening there.
+
+# Commands for Kees Blom's railroad program
+#diagram:token NAME
+#diagram:token NUMBER
+#diagram:token STRING
+#diagram:token NEWLINE
+#diagram:token ENDMARKER
+#diagram:token INDENT
+#diagram:output\input python.bla
+#diagram:token DEDENT
+#diagram:output\textwidth 20.04cm\oddsidemargin  0.0cm\evensidemargin 0.0cm
+#diagram:rules
+
+# Start symbols for the grammar:
+#	single_input is a single interactive statement;
+#	file_input is a module or sequence of commands read from an input file;
+#	eval_input is the input for the eval() and input() functions.
+# NB: compound_stmt in single_input is followed by extra NEWLINE!
+single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE
+file_input: (NEWLINE | stmt)* ENDMARKER
+eval_input: testlist NEWLINE* ENDMARKER
+
+decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
+decorators: decorator+
+funcdef: [decorators] 'def' NAME parameters ':' suite
+parameters: '(' [varargslist] ')'
+varargslist: (fpdef ['=' test] ',')* ('*' NAME [',' '**' NAME] | '**' NAME) | fpdef ['=' test] (',' fpdef ['=' test])* [',']
+fpdef: NAME | '(' fplist ')'
+fplist: fpdef (',' fpdef)* [',']
+
+stmt: simple_stmt | compound_stmt
+simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
+small_stmt: expr_stmt | print_stmt  | del_stmt | pass_stmt | flow_stmt | import_stmt | global_stmt | exec_stmt | assert_stmt
+expr_stmt: testlist (augassign testlist | ('=' testlist)*)
+augassign: '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' | '<<=' | '>>=' | '**=' | '//='
+# For normal assignments, additional restrictions enforced by the interpreter
+print_stmt: 'print' ( '>>' test [ (',' test)+ [','] ] | [ test (',' test)* [','] ] )
+del_stmt: 'del' exprlist
+pass_stmt: 'pass'
+flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt | yield_stmt
+break_stmt: 'break'
+continue_stmt: 'continue'
+return_stmt: 'return' [testlist]
+yield_stmt: 'yield' testlist
+raise_stmt: 'raise' [test [',' test [',' test]]]
+import_stmt: import_name | import_from
+import_name: 'import' dotted_as_names
+import_from: 'from' dotted_name 'import' ('*' | '(' import_as_names [','] ')' | import_as_names)
+import_as_name: NAME [NAME NAME]
+dotted_as_name: dotted_name [NAME NAME]
+import_as_names: import_as_name (',' import_as_name)*
+dotted_as_names: dotted_as_name (',' dotted_as_name)*
+dotted_name: NAME ('.' NAME)*
+global_stmt: 'global' NAME (',' NAME)*
+exec_stmt: 'exec' expr ['in' test [',' test]]
+assert_stmt: 'assert' test [',' test]
+
+compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | funcdef | classdef
+if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
+while_stmt: 'while' test ':' suite ['else' ':' suite]
+for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite]
+try_stmt: ('try' ':' suite (except_clause ':' suite)+ #diagram:break
+           ['else' ':' suite] | 'try' ':' suite 'finally' ':' suite)
+# NB compile.c makes sure that the default except clause is last
+except_clause: 'except' [test [',' test]]
+suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT
+
+# Backward compatibility cruft to support:
+# [ x for x in lambda: True, lambda: False if x() ]
+# even while also allowing:
+# lambda x: 5 if x else 2
+# (But not a mix of the two)
+testlist_safe: old_test [(',' old_test)+ [',']]
+old_test: or_test | old_lambdef
+old_lambdef: 'lambda' [varargslist] ':' old_test
+
+test: or_test ['if' or_test 'else' test] | lambdef
+or_test: and_test ('or' and_test)*
+and_test: not_test ('and' not_test)*
+not_test: 'not' not_test | comparison
+comparison: expr (comp_op expr)*
+comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is' 'not'|'is'
+expr: xor_expr ('|' xor_expr)*
+xor_expr: and_expr ('^' and_expr)*
+and_expr: shift_expr ('&' shift_expr)*
+shift_expr: arith_expr (('<<'|'>>') arith_expr)*
+arith_expr: term (('+'|'-') term)*
+term: factor (('*'|'/'|'%'|'//') factor)*
+factor: ('+'|'-'|'~') factor | power
+power: atom trailer* ['**' factor]
+atom: '(' [testlist_gexp] ')' | '[' [listmaker] ']' | '{' [dictmaker] '}' | '`' testlist1 '`' | NAME | NUMBER | STRING+
+listmaker: test ( list_for | (',' test)* [','] )
+testlist_gexp: test ( gen_for | (',' test)* [','] )
+lambdef: 'lambda' [varargslist] ':' test
+# trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
+trailer: '(' ')' | '(' arglist ')' | '[' subscriptlist ']' | '.' NAME
+subscriptlist: subscript (',' subscript)* [',']
+subscript: '.' '.' '.' | [test] ':' [test] [sliceop] | test
+sliceop: ':' [test]
+exprlist: expr (',' expr)* [',']
+testlist: test (',' test)* [',']
+dictmaker: test ':' test (',' test ':' test)* [',']
+
+classdef: 'class' NAME ['(' testlist ')'] ':' suite
+
+# arglist: (argument ',')* (argument [',']| '*' test [',' '**' test] | '**' test)
+arglist: (argument ',')* ( '*' test [',' '**' test] | '**' test | argument | [argument ','] )
+argument: [test '='] test [gen_for] # Really [keyword '='] test
+
+list_iter: list_for | list_if
+list_for: 'for' exprlist 'in' testlist_safe [list_iter]
+list_if: 'if' test [list_iter]
+
+gen_iter: gen_for | gen_if
+gen_for: 'for' exprlist 'in' or_test [gen_iter]
+gen_if: 'if' test [gen_iter]
+
+testlist1: test (',' test)*
+
+# not used in grammar, but may appear in "node" passed from Parser to Compiler
+encoding_decl: NAME

Added: pypy/branch/condexpr/pypy/interpreter/pyparser/data/README
==============================================================================
--- (empty file)
+++ pypy/branch/condexpr/pypy/interpreter/pyparser/data/README	Tue Feb 28 02:21:52 2006
@@ -0,0 +1,5 @@
+If you modify the grammar, you need to regenerate interpreter/pyparser/symbol.py
+
+Note that you could delete the old grammars, because the stable compiler only
+supports the latest.
+

Modified: pypy/branch/condexpr/pypy/interpreter/pyparser/ebnfparse.py
==============================================================================
--- pypy/dist/pypy/interpreter/pyparser/ebnfparse.py	(original)
+++ pypy/branch/condexpr/pypy/interpreter/pyparser/ebnfparse.py	Tue Feb 28 02:21:52 2006
@@ -260,7 +260,7 @@
 
 from pprint import pprint
 if __name__ == "__main__":
-    grambuild = parse_grammar(file('data/Grammar2.3'))
+    grambuild = parse_grammar(file('data/Grammar2.5a'))
     for i,r in enumerate(grambuild.items):
         print "%  3d : %s" % (i, r)
     pprint(grambuild.terminals.keys())

Modified: pypy/branch/condexpr/pypy/interpreter/pyparser/pysymbol.py
==============================================================================
--- pypy/dist/pypy/interpreter/pyparser/pysymbol.py	(original)
+++ pypy/branch/condexpr/pypy/interpreter/pyparser/pysymbol.py	Tue Feb 28 02:21:52 2006
@@ -60,7 +60,7 @@
     globals()[_name] = _value
 
     
-
+# (This function does not seen to be called right now)
 def update_symbols( parser ):
     """Update the symbol module according to rules
     in PythonParser instance : parser"""
@@ -70,3 +70,32 @@
 # There is no symbol in this module until the grammar is loaded
 # once loaded the grammar parser will fill the mappings with the
 # grammar symbols
+
+def gen_symbol_file( grammar ):
+    """
+    Generate a compatible symbol file for symbol.py, using the grammar that has
+    been generated from the grammar in the PyPy parser.  (Note that we assume
+    that the parser generates the tokens deterministically.)
+    """
+    import os.path
+    f = open(os.path.join(os.path.dirname(__file__), 'symbol.py'), 'w')
+    print >> f, """
+#  This file is automatically generated; please don't muck it up!
+#
+#  To update the symbols in this file, call this function from python_grammar()
+#  and call PyPy.
+"""
+    for k, v in grammar.symbols.sym_name.iteritems():
+        if k >= 0:
+            print >> f, '%s = %s' % (v, k)
+
+    print >> f, """
+
+# Generate sym_name
+sym_name = {}
+for _name, _value in globals().items():
+    if type(_value) is type(0):
+        sym_name[_value] = _name
+"""
+    f.close()
+    

Modified: pypy/branch/condexpr/pypy/interpreter/pyparser/pythonparse.py
==============================================================================
--- pypy/dist/pypy/interpreter/pyparser/pythonparse.py	(original)
+++ pypy/branch/condexpr/pypy/interpreter/pyparser/pythonparse.py	Tue Feb 28 02:21:52 2006
@@ -48,7 +48,7 @@
         goalnumber = pysymbol._cpython_symbols.sym_values[goal]
         target = self.rules[goalnumber]
         src = Source(lines, flags)
-    
+
         result = target.match(src, builder)
         if not result:
             line, lineno = src.debug()
@@ -56,7 +56,7 @@
             raise SyntaxError("invalid syntax", lineno, -1, line)
             # return None
         return builder
-    
+
 _recode_to_utf8 = gateway.applevel(r'''
     def _recode_to_utf8(text, encoding):
         return unicode(text, encoding).encode("utf-8")
@@ -96,7 +96,7 @@
     if eol2 < 0:
         return _check_line_for_encoding(s[eol + 1:])
     return _check_line_for_encoding(s[eol + 1:eol2])
-    
+
 def _check_line_for_encoding(line):
     """returns the declared encoding or None"""
     i = 0
@@ -112,7 +112,7 @@
     """returns the python grammar corresponding to our CPython version"""
     if version == "native":
         _ver = PYTHON_VERSION
-    elif version in ("2.3","2.4"):
+    elif version in ("2.3","2.4","2.5a"):
         _ver = version
     return os.path.join( os.path.dirname(__file__), "data", "Grammar" + _ver ), _ver
 
@@ -126,6 +126,12 @@
     gram = ebnfparse.parse_grammar( file(fname) )
     grammar.DEBUG = level
     parser = PythonParser( gram )
+
+    # Uncomment this to generate the symbol.py for the parser using the grammar
+    # that is being generated by PyPy.  Note: we really should put this
+    # somewhere else.
+    ## pysymbol.gen_symbol_file(gram)
+
     return parser
 
 debug_print( "Loading grammar %s" % PYTHON_GRAMMAR )
@@ -141,7 +147,7 @@
 def parse_file_input(pyf, gram, builder ):
     """Parse a python file"""
     return gram.parse_source( pyf.read(), "file_input", builder )
-    
+
 def parse_single_input(textsrc, gram, builder ):
     """Parse a python single statement"""
     return gram.parse_source( textsrc, "single_input", builder )
@@ -157,4 +163,4 @@
 
 def make_rule( space, w_rule ):
     rule = space.str_w( w_rule )
-    
+

Modified: pypy/branch/condexpr/pypy/interpreter/pyparser/symbol.py
==============================================================================
--- pypy/dist/pypy/interpreter/pyparser/symbol.py	(original)
+++ pypy/branch/condexpr/pypy/interpreter/pyparser/symbol.py	Tue Feb 28 02:21:52 2006
@@ -1,15 +1,9 @@
-#! /usr/bin/env python
-
-"""Non-terminal symbols of Python grammar (from "graminit.h")."""
 
 #  This file is automatically generated; please don't muck it up!
 #
-#  To update the symbols in this file, 'cd' to the top directory of
-#  the python source tree after building the interpreter and run:
-#
-#    python Lib/symbol.py
+#  To update the symbols in this file, call this function from python_grammar()
+#  and call PyPy.
 
-#--start constants--
 single_input = 256
 file_input = 257
 eval_input = 258
@@ -88,20 +82,14 @@
 gen_if = 331
 testlist1 = 332
 encoding_decl = 333
-#--end constants--
+old_test = 334
+or_test = 335
+old_lambdef = 336
+
 
+# Generate sym_name
 sym_name = {}
 for _name, _value in globals().items():
     if type(_value) is type(0):
         sym_name[_value] = _name
 
-
-def main():
-    import sys
-    import token
-    if len(sys.argv) == 1:
-        sys.argv = sys.argv + ["Include/graminit.h", "Lib/symbol.py"]
-    token.main()
-
-if __name__ == "__main__":
-    main()

Modified: pypy/branch/condexpr/pypy/interpreter/pyparser/test/test_astbuilder.py
==============================================================================
--- pypy/dist/pypy/interpreter/pyparser/test/test_astbuilder.py	(original)
+++ pypy/branch/condexpr/pypy/interpreter/pyparser/test/test_astbuilder.py	Tue Feb 28 02:21:52 2006
@@ -206,8 +206,22 @@
     "[a, (b,c), d] = e",
     "a, (b, c), d = e",
     ]
-EXPECTED["k[v,]"] = "Module(None, Stmt([Discard(Subscript(Name('k'), 2, Tuple([Name('v')])))]))"
-EXPECTED["m[a,b]"] = "Module(None, Stmt([Discard(Subscript(Name('m'), 2, Tuple([Name('a'), Name('b')])))]))"
+
+# We do not export the following tests because we would have to implement 2.5
+# features in the stable compiler (other than just building the AST).
+expressions_inbetweenversions = expressions + [
+    "1 if True else 2",
+    "1 if False else 2",
+    ]
+
+EXPECTED["k[v,]"] = ("Module(None, Stmt([Discard(Subscript(Name('k'), 2, "
+                     "Tuple([Name('v')])))]))")
+EXPECTED["m[a,b]"] = ("Module(None, Stmt([Discard(Subscript(Name('m'), 2, "
+                      "Tuple([Name('a'), Name('b')])))]))")
+EXPECTED["1 if True else 2"] = ("Module(None, Stmt([Discard(CondExpr("
+                                "Name('True'), Const(1), Const(2)))]))")
+EXPECTED["1 if False else 2"] = ("Module(None, Stmt([Discard(CondExpr("
+                                 "Name('False'), Const(1), Const(2)))]))")
 
 funccalls = [
     "l = func()",
@@ -601,7 +615,7 @@
 
 TESTS = [
     constants,
-    expressions,
+    expressions_inbetweenversions,
     augassigns,
     comparisons,
     funccalls,

Modified: pypy/branch/condexpr/pypy/interpreter/stablecompiler/transformer.py
==============================================================================
--- pypy/dist/pypy/interpreter/stablecompiler/transformer.py	(original)
+++ pypy/branch/condexpr/pypy/interpreter/stablecompiler/transformer.py	Tue Feb 28 02:21:52 2006
@@ -308,9 +308,12 @@
 
         return Lambda(names, defaults, flags, code, lineno=nodelist[1][2])
 
+    # (This is like lambdef but it uses the old_test instead.)
+    # old_lambdef: 'lambda' [varargslist] ':' old_test
+    old_lambdef = lambdef
+
     def classdef(self, nodelist):
         # classdef: 'class' NAME ['(' testlist ')'] ':' suite
-
         name = nodelist[1][1]
         doc = self.get_docstring(nodelist[-1])
         if nodelist[2][0] == token.COLON:
@@ -579,7 +582,7 @@
 
     def testlist(self, nodelist):
         # testlist: expr (',' expr)* [',']
-        # testlist_safe: test [(',' test)+ [',']]
+        # testlist_safe: old_test [(',' old_test)+ [',']]
         # exprlist: expr (',' expr)* [',']
         return self.com_binary(Tuple, nodelist)
 
@@ -594,15 +597,33 @@
         return self.testlist(nodelist)
 
     def test(self, nodelist):
-        # and_test ('or' and_test)* | lambdef
-        if len(nodelist) == 1 and nodelist[0][0] == symbol.lambdef:
-            return self.lambdef(nodelist[0])
-        return self.com_binary(Or, nodelist)
+        # test: or_test ['if' or_test 'else' test] | lambdef
+        if len(nodelist) == 1:
+            if nodelist[0][0] == symbol.lambdef:
+                return self.lambdef(nodelist[0])
+            else:
+                # Normal or-expression
+                return self.com_node(nodelist[0])
+        else:
+            # Here we implement conditional expressions
+            return ast.CondExpr(nodelist[2], nodelist[0], nodelist[4],
+                                nodelist[1].lineno)
 
     def and_test(self, nodelist):
         # not_test ('and' not_test)*
         return self.com_binary(And, nodelist)
 
+    def old_test(self, nodelist):
+        # old_test: or_test | old_lambdef
+        if len(nodelist) == 1 and nodelist[0][0] == symbol.lambdef:
+            return self.lambdef(nodelist[0])
+        assert len(nodelist) == 1
+        return self.com_node(nodelist[0])
+
+    def or_test(self, nodelist):
+        # or_test: and_test ('or' and_test)*
+        return self.com_binary(Or, nodelist)
+
     def not_test(self, nodelist):
         # 'not' not_test | comparison
         result = self.com_node(nodelist[-1])
@@ -1396,6 +1417,8 @@
     symbol.testlist,
     symbol.testlist_safe,
     symbol.test,
+    symbol.old_test,
+    symbol.or_test,
     symbol.and_test,
     symbol.not_test,
     symbol.comparison,
@@ -1421,54 +1444,10 @@
     token.NOTEQUAL : '!=',
     }
 
-_legal_node_types = [
-    symbol.funcdef,
-    symbol.classdef,
-    symbol.stmt,
-    symbol.small_stmt,
-    symbol.flow_stmt,
-    symbol.simple_stmt,
-    symbol.compound_stmt,
-    symbol.expr_stmt,
-    symbol.print_stmt,
-    symbol.del_stmt,
-    symbol.pass_stmt,
-    symbol.break_stmt,
-    symbol.continue_stmt,
-    symbol.return_stmt,
-    symbol.raise_stmt,
-    symbol.import_stmt,
-    symbol.global_stmt,
-    symbol.exec_stmt,
-    symbol.assert_stmt,
-    symbol.if_stmt,
-    symbol.while_stmt,
-    symbol.for_stmt,
-    symbol.try_stmt,
-    symbol.suite,
-    symbol.testlist,
-    symbol.testlist_safe,
-    symbol.test,
-    symbol.and_test,
-    symbol.not_test,
-    symbol.comparison,
-    symbol.exprlist,
-    symbol.expr,
-    symbol.xor_expr,
-    symbol.and_expr,
-    symbol.shift_expr,
-    symbol.arith_expr,
-    symbol.term,
-    symbol.factor,
-    symbol.power,
-    symbol.atom,
-    ]
-
-if hasattr(symbol, 'yield_stmt'):
-    _legal_node_types.append(symbol.yield_stmt)
-
 _assign_types = [
     symbol.test,
+    symbol.old_test,
+    symbol.or_test,
     symbol.and_test,
     symbol.not_test,
     symbol.comparison,

Modified: pypy/branch/condexpr/pypy/interpreter/test/test_syntax.py
==============================================================================
--- pypy/dist/pypy/interpreter/test/test_syntax.py	(original)
+++ pypy/branch/condexpr/pypy/interpreter/test/test_syntax.py	Tue Feb 28 02:21:52 2006
@@ -248,6 +248,15 @@
         raise
 
 
+class AppTestCondExpr:
+
+    def test_condexpr(self):
+        for s, expected in [("x = 1 if True else 2", 1),
+                            ("x = 1 if False else 2", 2)]:
+            exec s
+            assert x == expected
+
+        
 if __name__ == '__main__':
     # only to check on top of CPython (you need 2.4)
     from py.test import raises

Modified: pypy/branch/condexpr/pypy/tool/option.py
==============================================================================
--- pypy/dist/pypy/tool/option.py	(original)
+++ pypy/branch/condexpr/pypy/tool/option.py	Tue Feb 28 02:21:52 2006
@@ -16,7 +16,7 @@
          # "ast" uses interpreter/pyparser & interpreter/astcompiler.py 
          # "cpython" uses cpython parser and cpython c-level compiler 
     usemodules = []                        
-    version = "2.4" # "native" / "2.3" / "2.4"
+    version = "2.5a" # "native" / "2.3" / "2.4" / "2.5a"
 
 def run_tb_server(option, opt, value, parser):
     from pypy.tool import tb_server



More information about the Pypy-commit mailing list