[pypy-svn] r52538 - in pypy/branch/jit-refactoring/pypy/lang/js: . doc test

fijal at codespeak.net fijal at codespeak.net
Fri Mar 14 23:29:13 CET 2008


Author: fijal
Date: Fri Mar 14 23:29:12 2008
New Revision: 52538

Modified:
   pypy/branch/jit-refactoring/pypy/lang/js/astbuilder.py
   pypy/branch/jit-refactoring/pypy/lang/js/doc/bytecode.txt
   pypy/branch/jit-refactoring/pypy/lang/js/jscode.py
   pypy/branch/jit-refactoring/pypy/lang/js/operations.py
   pypy/branch/jit-refactoring/pypy/lang/js/test/test_parser.py
Log:
Function declaraction and function expression.


Modified: pypy/branch/jit-refactoring/pypy/lang/js/astbuilder.py
==============================================================================
--- pypy/branch/jit-refactoring/pypy/lang/js/astbuilder.py	(original)
+++ pypy/branch/jit-refactoring/pypy/lang/js/astbuilder.py	Fri Mar 14 23:29:12 2008
@@ -47,6 +47,8 @@
     }
     
     def __init__(self):
+        self.varlists = []
+        self.funclists = []
         self.sourcename = ""
         RPythonVisitor.__init__(self)
     
@@ -200,8 +202,6 @@
         return operations.Identifier(pos, name)
     
     def visit_program(self, node):
-        self.varlists = []
-        self.funclists = []
         pos = self.get_pos(node)
         body = self.dispatch(node.children[0])
         return operations.Program(pos, body)
@@ -235,7 +235,7 @@
         identifier, i = self.get_next_expr(node, i)
         parameters, i = self.get_next_expr(node, i)
         functionbody, i = self.get_next_expr(node, i)
-        if parameters == operations.astundef:
+        if parameters is None:
             p = []
         else:
             p = [pident.get_literal() for pident in parameters.nodes]
@@ -359,7 +359,7 @@
     def get_next_expr(self, node, i):
         if isinstance(node.children[i], Symbol) and \
            node.children[i].additional_info in [';', ')', '(', '}']:
-            return operations.astundef, i+1
+            return None, i+1
         else:
             return self.dispatch(node.children[i]), i+2
     
@@ -368,7 +368,7 @@
         if len(node.children) > 0:
             target = self.dispatch(node.children[0])
         else:
-            target = operations.astundef
+            target = None
         return operations.Break(pos, target)
     
     def visit_returnstatement(self, node):

Modified: pypy/branch/jit-refactoring/pypy/lang/js/doc/bytecode.txt
==============================================================================
--- pypy/branch/jit-refactoring/pypy/lang/js/doc/bytecode.txt	(original)
+++ pypy/branch/jit-refactoring/pypy/lang/js/doc/bytecode.txt	Fri Mar 14 23:29:12 2008
@@ -28,6 +28,22 @@
 
 create array out of num elements on the stack
 
+object creation:
+
+LOAD_OBJECT <list of parameters>
+
+Takes one element per one parameter from the stack and initializes
+object this way.
+
+POP
+
+pops one element from the stack.
+
+LOAD_FUNCTION <code object>
+
+loads function object (declared earlier) to a stack. used for
+function expressions.
+
 Arithmetic binary operations:
 (all pops two values and pushes on stack the result)
 
@@ -45,17 +61,14 @@
 PREDECR, POSTDECR, PREINCR, POSTINCR
 decrement and increment (++, --) prefix and postfix
 
-object creation:
-
-LOAD_OBJECT <list of parameters>
-
-Takes one element per one parameter from the stack and initializes
-object this way.
-
 control flow:
 
-XXX
+JUMP, LABEL, JUMP_IF_TRUE, JUMP_IF_FALSE
 
 function control flow:
 
-DECLARE_FUNCTION <bytecode>
+DECLARE_FUNCTION <code object>
+
+scope control opcodes:
+
+DECLARE_VAR <name>

Modified: pypy/branch/jit-refactoring/pypy/lang/js/jscode.py
==============================================================================
--- pypy/branch/jit-refactoring/pypy/lang/js/jscode.py	(original)
+++ pypy/branch/jit-refactoring/pypy/lang/js/jscode.py	Fri Mar 14 23:29:12 2008
@@ -58,6 +58,12 @@
             return False
         return all([i == j for i, j in zip(self.opcodes, list_of_opcodes)])
 
+class JsFunction(object):
+    def __init__(self, name, params, code):
+        self.name = name
+        self.params = params
+        self.code = code
+
 class Opcode(object):
     def eval(self, ctx, stack):
         """ Execute in context ctx
@@ -158,6 +164,13 @@
     def __repr__(self):
         return 'LOAD_ARRAY %d' % (self.counter,)
 
+class LOAD_FUNCTION(Opcode):
+    def __init__(self, funcobj):
+        self.funcobj = funcobj
+
+    def __repr__(self):
+        return 'LOAD_FUNCTION' # XXX
+
 class STORE_MEMBER(Opcode):
     def eval(self, ctx):
         XXX
@@ -247,6 +260,29 @@
 class JUMP_IF_TRUE(BaseJump):
     pass
 
+class DECLARE_FUNCTION(Opcode):
+    def __init__(self, funcobj):
+        self.funcobj = funcobj
+
+    def __repr__(self):
+        funcobj = self.funcobj
+        if funcobj.name is None:
+            name = ""
+        else:
+            name = funcobj.name + " "
+        codestr = '\n'.join(['  %r' % (op,) for op in funcobj.code.opcodes])
+        return 'DECLARE_FUNCTION %s%r [\n%s\n]' % (name, funcobj.params, codestr)
+
+class DECLARE_VAR(Opcode):
+    def __init__(self, name):
+        self.name = name
+
+    def __repr__(self):
+        return 'DECLARE_VAR "%s"' % (self.name,)
+
+class RETURN(Opcode):
+    pass
+
 OpcodeMap = {}
 
 for name, value in locals().items():

Modified: pypy/branch/jit-refactoring/pypy/lang/js/operations.py
==============================================================================
--- pypy/branch/jit-refactoring/pypy/lang/js/operations.py	(original)
+++ pypy/branch/jit-refactoring/pypy/lang/js/operations.py	Fri Mar 14 23:29:12 2008
@@ -13,6 +13,7 @@
      isnan, isinf
 from pypy.lang.js.execution import ExecutionReturned, JsTypeError,\
      ThrowException
+from pypy.lang.js.jscode import JsCode, JsFunction
 from constants import unescapedict, SLASH
 
 import sys
@@ -321,10 +322,23 @@
 class FunctionStatement(Statement):
     def __init__(self, pos, name, params, body):
         self.pos = pos
-        self.name = name
+        if name is None:
+            self.name = None
+        else:
+            assert isinstance(name, Identifier)
+            self.name = name.name
         self.body = body
         self.params = params
 
+    def emit(self, bytecode):
+        code = JsCode()
+        self.body.emit(code)
+        funcobj = JsFunction(self.name, self.params, code)
+        bytecode.emit('DECLARE_FUNCTION', funcobj)
+        if self.name is None:
+            # XXX looks awful
+            bytecode.emit('LOAD_FUNCTION', funcobj)
+
     def eval(self, ctx):
         proto = ctx.get_global().Get('Function').Get('prototype')
         w_func = W_Object(ctx=ctx, Prototype=proto, Class='Function', callfunc=self)
@@ -346,8 +360,8 @@
     def emit(self, bytecode):
         bytecode.emit('LOAD_VARIABLE', self.name)
         
-#    def get_literal(self):
-#        return self.name
+    def get_literal(self):
+        return self.name
     
 
 class This(Identifier):
@@ -912,6 +926,15 @@
         self.nodes = nodes
         self.sourcename = sourcename
 
+    def emit(self, bytecode):
+        for varname in self.var_decl:
+            bytecode.emit('DECLARE_VAR', varname)
+        for funcname, funccode in self.func_decl.items():
+            funccode.emit(bytecode)
+
+        for node in self.nodes:
+            node.emit(bytecode)
+
     def execute(self, ctx):
         for varname in self.var_decl:
             ctx.variable.Put(varname, w_Undefined, dd=True)
@@ -946,6 +969,10 @@
     def __init__(self, pos, expr):
         self.pos = pos
         self.expr = expr
+
+    def emit(self, bytecode):
+        self.expr.emit(bytecode)
+        bytecode.emit('RETURN')
     
     def execute(self, ctx):
         if isinstance(self.expr, Undefined):
@@ -1004,8 +1031,13 @@
 class VariableDeclaration(Expression):
     def __init__(self, pos, identifier, expr=None):
         self.pos = pos
-        self.identifier = identifier
+        assert isinstance(identifier, Identifier)
+        self.identifier = identifier.name
         self.expr = expr
+
+    def emit(self, bytecode):
+        self.expr.emit(bytecode)
+        bytecode.emit('STORE', self.identifier)
     
     def eval(self, ctx):
         name = self.identifier.get_literal()
@@ -1020,6 +1052,10 @@
     def __init__(self, pos, nodes):
         self.pos = pos
         self.nodes = nodes
+
+    def emit(self, bytecode):
+        for node in self.nodes:
+            node.emit(bytecode)
     
     def eval(self, ctx):
         for var in self.nodes:
@@ -1030,6 +1066,9 @@
     def __init__(self, pos, body):
         self.pos = pos
         self.body = body
+
+    def emit(self, bytecode):
+        self.body.emit(bytecode)
     
     def execute(self, ctx):
         return self.body.eval(ctx)

Modified: pypy/branch/jit-refactoring/pypy/lang/js/test/test_parser.py
==============================================================================
--- pypy/branch/jit-refactoring/pypy/lang/js/test/test_parser.py	(original)
+++ pypy/branch/jit-refactoring/pypy/lang/js/test/test_parser.py	Fri Mar 14 23:29:12 2008
@@ -426,8 +426,20 @@
                                 'LOAD_VARIABLE "x"',
                                 'JUMP_IF_TRUE 0'])
 
+class TestToAstFunction(BaseTestToAST):
+    def setup_class(cls):
+        cls.parse = parse_func('sourceelements')
+
     def test_function_decl(self):
-        pass
+        self.check('function f(x, y, z) {x;}',
+                   ['DECLARE_FUNCTION f [\'x\', \'y\', \'z\'] [\n  LOAD_VARIABLE "x"\n]'])
+
+    def test_function_expression(self):
+        self.check('var x = function() {return x}',[
+            'DECLARE_VAR "x"',
+            'DECLARE_FUNCTION [] [\n  LOAD_VARIABLE "x"\n  RETURN\n]',
+            'LOAD_FUNCTION',
+            'STORE "x"'])
 
 from pypy.lang.js.jsparser import parse
     



More information about the Pypy-commit mailing list