[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