[pypy-svn] r52382 - in pypy/branch/jit-refactoring/pypy/lang/js: . doc test
fijal at codespeak.net
fijal at codespeak.net
Tue Mar 11 17:57:39 CET 2008
Author: fijal
Date: Tue Mar 11 17:57:37 2008
New Revision: 52382
Added:
pypy/branch/jit-refactoring/pypy/lang/js/doc/
pypy/branch/jit-refactoring/pypy/lang/js/doc/bytecode.txt (contents, props changed)
pypy/branch/jit-refactoring/pypy/lang/js/jscode.py (contents, props changed)
Modified:
pypy/branch/jit-refactoring/pypy/lang/js/jsobj.py
pypy/branch/jit-refactoring/pypy/lang/js/operations.py
pypy/branch/jit-refactoring/pypy/lang/js/test/test_parser.py
Log:
Some general chaos. Almost nothing is working right now.
Added: pypy/branch/jit-refactoring/pypy/lang/js/doc/bytecode.txt
==============================================================================
--- (empty file)
+++ pypy/branch/jit-refactoring/pypy/lang/js/doc/bytecode.txt Tue Mar 11 17:57:37 2008
@@ -0,0 +1,44 @@
+Bytecode specification for the pypy javascript interpreter.
+
+We implement stack-based machine. We'll likely extend the bytecode for
+performance.
+
+LOAD_INTCONSTANT <constant>
+LOAD_FLOATCONSTANT <constant>
+LOAD_STRINGCONSTANT <constant>
+...
+
+LOAD_VARIABLE <identifier>
+
+simple identifier dereferencing
+
+LOAD_UNDEFINED, LOAD_NULL
+
+STORE <identifier>
+
+stores the last value on stack into identifierx
+
+Arithmetic binary operations:
+(all pops two values and pushes on stack the result)
+
+ADD, SUB, MUL, DIV, MOD
+BITXOR, BITOR, BITAND
+AND, OR, EQ, NE, IS, ISNOT, GT, GE, LT, LE,
+RSHIT, URSHIFT, LSHIFT
+
+Unary arithmetic operations:
+(pops one value and pushes result to the stack)
+
+BITNOT,
+NOT, UPLUS, UMINUS
+
+PREDECR, POSTDECR, PREINCR, POSTINCR
+decrement and increment (++, --) prefix and postfix
+
+control flow:
+
+XXX
+
+function control flow:
+
+DECLARE_FUNCTION <bytecode>
Added: pypy/branch/jit-refactoring/pypy/lang/js/jscode.py
==============================================================================
--- (empty file)
+++ pypy/branch/jit-refactoring/pypy/lang/js/jscode.py Tue Mar 11 17:57:37 2008
@@ -0,0 +1,88 @@
+
+from pypy.lang.js.jsobj import W_IntNumber
+
+class JsCode(object):
+ """ That object stands for code of a single javascript function
+ """
+ def __init__(self):
+ self.opcodes = []
+
+ def emit(self, operation, args):
+ try:
+ self.opcodes.append(OpcodeMap[operation](args))
+ except KeyError:
+ raise ValueError("Unknown opcode %s" % (operation,))
+
+ def __repr__(self):
+ return "\n".join([repr(i) for i in self.opcodes])
+
+ def __eq__(self, list_of_opcodes):
+ if len(list_of_opcodes) != len(self.opcodes):
+ return False
+ return all([i == j for i, j in zip(self.opcodes, list_of_opcodes)])
+
+class Opcode(object):
+ def __init__(self, args):
+ raise NotImplementedError("Purely abstract")
+
+ def eval(self, ctx, stack):
+ """ Execute in context ctx
+ """
+ raise NotImplementedError
+
+ def __eq__(self, other):
+ return repr(self) == other
+
+class BaseBinaryComparison(Opcode):
+ def eval(self, ctx):
+ s2 = self.left.eval(ctx).GetValue()
+ s4 = self.right.eval(ctx).GetValue()
+ return self.decision(ctx, s2, s4)
+
+ def decision(self, ctx, op1, op2):
+ raise NotImplementedError
+
+class BaseBinaryBitwiseOp(Opcode):
+ def eval(self, ctx):
+ s5 = self.left.eval(ctx).GetValue().ToInt32()
+ s6 = self.right.eval(ctx).GetValue().ToInt32()
+ return self.decision(ctx, s5, s6)
+
+ def decision(self, ctx, op1, op2):
+ raise NotImplementedError
+
+class Undefined(Opcode):
+ def eval(self, ctx):
+ return w_Undefined
+
+ def execute(self, ctx):
+ return w_Undefined
+
+class LOAD_INTCONSTANT(Opcode):
+ def __init__(self, args):
+ assert len(args) == 1
+ self.w_intvalue = W_IntNumber(int(args[0]))
+
+ def eval(self, ctx):
+ return self.w_intvalue
+
+ def __repr__(self):
+ return 'LOAD_INTCONSTANT %s' % (self.w_intvalue.intval,)
+
+class LOAD_VARIABLE(Opcode):
+ def __init__(self, args):
+ assert len(args) == 1
+ self.identifier = args[0]
+
+ def eval(self, ctx):
+ return ctx.resolve_identifier(self.identifier)
+
+ def __repr__(self):
+ return 'LOAD_VARIABLE "%s"' % (self.identifier,)
+
+OpcodeMap = {}
+
+for name, value in locals().items():
+ if name.upper() == name and issubclass(value, Opcode):
+ OpcodeMap[name] = value
+
Modified: pypy/branch/jit-refactoring/pypy/lang/js/jsobj.py
==============================================================================
--- pypy/branch/jit-refactoring/pypy/lang/js/jsobj.py (original)
+++ pypy/branch/jit-refactoring/pypy/lang/js/jsobj.py Tue Mar 11 17:57:37 2008
@@ -535,7 +535,6 @@
return W_Reference(identifier, obj)
return W_Reference(identifier)
-
def global_context(w_global):
assert isinstance(w_global, W_PrimitiveObject)
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 Tue Mar 11 17:57:37 2008
@@ -34,16 +34,9 @@
Initializes the content from the AST specific for each node type
"""
raise NotImplementedError
-
- def eval(self, ctx):
- """
- Used for expression evaluation
- """
- raise NotImplementedError
- def execute(self, ctx):
- """
- Called on statament execution
+ def emit(self, bytecode):
+ """ Emits bytecode
"""
raise NotImplementedError
@@ -72,7 +65,6 @@
class UnaryOp(Expression):
def __init__(self, pos, expr, postfix=False):
self.pos = pos
- #assert isinstance(expr, Node)
self.expr = expr
self.postfix = postfix
@@ -81,36 +73,25 @@
self.pos = pos
self.left = left
self.right = right
-
-class BinaryComparisonOp(BinaryOp):
- def eval(self, ctx):
- s2 = self.left.eval(ctx).GetValue()
- s4 = self.right.eval(ctx).GetValue()
- return self.decision(ctx, s2, s4)
-
- def decision(self, ctx, op1, op2):
- raise NotImplementedError
-class BinaryBitwiseOp(BinaryOp):
- def eval(self, ctx):
- s5 = self.left.eval(ctx).GetValue().ToInt32()
- s6 = self.right.eval(ctx).GetValue().ToInt32()
- return self.decision(ctx, s5, s6)
-
- def decision(self, ctx, op1, op2):
- raise NotImplementedError
+ def emit(self, bytecode):
+ self.left.emit(bytecode)
+ self.right.emit(bytecode)
+ bytecode.emit(self.operation_name)
class Undefined(Statement):
- def eval(self, ctx):
- return w_Undefined
-
- def execute(self, ctx):
- return w_Undefined
-
-astundef = Undefined(Position())
+ def emit(self, bytecode):
+ bytecode.emit('LOAD_UNDEFINED')
-class PropertyInit(BinaryOp):
- pass
+class PropertyInit(Expression):
+ def __init__(self, identifier, expr):
+ self.identifier = identifier
+ assert isinstance(identifier, str)
+ self.expr = expr
+
+ def emit(self, bytecode):
+ self.expr.emit(bytecode)
+ bytecode.emit('STORE', [self.identifier])
class Array(ListOp):
def eval(self, ctx):
@@ -175,7 +156,7 @@
raise e
-class BitwiseAnd(BinaryBitwiseOp):
+class BitwiseAnd(BinaryOp):
def decision(self, ctx, op1, op2):
return W_IntNumber(op1&op2)
@@ -186,13 +167,13 @@
return W_IntNumber(~op1)
-class BitwiseOr(BinaryBitwiseOp):
+class BitwiseOr(BinaryOp):
def decision(self, ctx, op1, op2):
return W_IntNumber(op1|op2)
-class BitwiseXor(BinaryBitwiseOp):
+class BitwiseXor(BinaryOp):
def decision(self, ctx, op1, op2):
return W_IntNumber(op1^op2)
@@ -277,7 +258,7 @@
self.name = name
self.body = body
self.params = params
-
+
def eval(self, ctx):
proto = ctx.get_global().Get('Function').Get('prototype')
w_func = W_Object(ctx=ctx, Prototype=proto, Class='Function', callfunc=self)
@@ -295,12 +276,12 @@
def __init__(self, pos, name):
self.pos = pos
self.name = name
-
- def eval(self, ctx):
- return ctx.resolve_identifier(self.name)
-
- def get_literal(self):
- return self.name
+
+ def emit(self, bytecode):
+ bytecode.emit('LOAD_VARIABLE', [self.name])
+
+# def get_literal(self):
+# return self.name
class This(Identifier):
@@ -308,7 +289,7 @@
class If(Statement):
- def __init__(self, pos, condition, thenpart, elsepart=astundef):
+ def __init__(self, pos, condition, thenpart, elsepart=None):
self.pos = pos
self.condition = condition
self.thenPart = thenpart
@@ -375,7 +356,7 @@
return s4
-class Ge(BinaryComparisonOp):
+class Ge(BinaryOp):
def decision(self, ctx, op1, op2):
s5 = ARC(ctx, op1, op2)
if s5 in (-1, 1):
@@ -384,7 +365,7 @@
return W_Boolean(True)
-class Gt(BinaryComparisonOp):
+class Gt(BinaryOp):
def decision(self, ctx, op1, op2):
s5 = ARC(ctx, op2, op1)
if s5 == -1:
@@ -393,7 +374,7 @@
return W_Boolean(s5)
-class Le(BinaryComparisonOp):
+class Le(BinaryOp):
def decision(self, ctx, op1, op2):
s5 = ARC(ctx, op2, op1)
if s5 in (-1, 1):
@@ -402,7 +383,7 @@
return W_Boolean(True)
-class Lt(BinaryComparisonOp):
+class Lt(BinaryOp):
def decision(self, ctx, op1, op2):
s5 = ARC(ctx, op1, op2)
if s5 == -1:
@@ -417,19 +398,19 @@
#
##############################################################################
-class Ursh(BinaryComparisonOp):
+class Ursh(BinaryOp):
def decision(self, ctx, op1, op2):
a = op1.ToUInt32()
b = op2.ToUInt32()
return W_IntNumber(a >> (b & 0x1F))
-class Rsh(BinaryComparisonOp):
+class Rsh(BinaryOp):
def decision(self, ctx, op1, op2):
a = op1.ToInt32()
b = op2.ToUInt32()
return W_IntNumber(a >> intmask(b & 0x1F))
-class Lsh(BinaryComparisonOp):
+class Lsh(BinaryOp):
def decision(self, ctx, op1, op2):
a = op1.ToInt32()
b = op2.ToUInt32()
@@ -499,11 +480,11 @@
r = x.ToNumber() == y.ToNumber()
return r
-class Eq(BinaryComparisonOp):
+class Eq(BinaryOp):
def decision(self, ctx, op1, op2):
return W_Boolean(AEC(ctx, op1, op2))
-class Ne(BinaryComparisonOp):
+class Ne(BinaryOp):
def decision(self, ctx, op1, op2):
return W_Boolean(not AEC(ctx, op1, op2))
@@ -540,16 +521,16 @@
return x.ToBoolean() == x.ToBoolean()
return x == y
-class StrictEq(BinaryComparisonOp):
+class StrictEq(BinaryOp):
def decision(self, ctx, op1, op2):
return W_Boolean(SEC(ctx, op1, op2))
-class StrictNe(BinaryComparisonOp):
+class StrictNe(BinaryOp):
def decision(self, ctx, op1, op2):
return W_Boolean(not SEC(ctx, op1, op2))
-class In(BinaryComparisonOp):
+class In(BinaryOp):
"""
The in operator, eg: "property in object"
"""
@@ -759,8 +740,8 @@
self.pos = pos
self.num = num
- def eval(self, ctx):
- return W_IntNumber(int(self.num))
+ def emit(self, bytecode):
+ bytecode.emit('LOAD_INTCONSTANT', [self.num])
class FloatNumber(BaseNumber):
def __init__(self, pos, num):
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 Tue Mar 11 17:57:37 2008
@@ -6,6 +6,7 @@
from pypy.rlib.parsing.tree import RPythonVisitor
from pypy.lang.js.jsobj import W_Object, global_context, ThrowException, empty_context
from pypy.lang.js.astbuilder import ASTBuilder
+from pypy.lang.js.jscode import JsCode
from pypy import conftest
import sys
@@ -279,17 +280,19 @@
class TestToASTExpr(BaseGrammarTest):
def setup_class(cls):
cls.parse = parse_func('expression')
- cls.ctx = empty_context()
def to_ast(self, s):
return ASTBuilder().dispatch(self.parse(s))
- def eval_expr(self, s):
+ def compile(self, s):
ast = self.to_ast(s)
- w_Global = W_Object()
- w_Object = W_Object(Prototype=W_Object())
- w_Global.Put('Object', w_Object)
- return ast.eval(global_context(w_Global))
+ bytecode = JsCode()
+ ast.emit(bytecode)
+ return bytecode
+# w_Global = W_Object()
+# w_Object = W_Object(Prototype=W_Object())
+# w_Global.Put('Object', w_Object)
+# return ast.eval(global_context(w_Global))
def test_get_pos(self):
from pypy.lang.js import operations
@@ -305,10 +308,12 @@
assert pos.start == 0
def test_primaryexpression(self):
- w_num = self.eval_expr('(6)')
- assert w_num.ToNumber() == 6
- w_num = self.eval_expr('((((6))))')
- assert w_num.ToNumber() == 6
+ bytecode = self.compile('(6)')
+ assert bytecode == ['LOAD_INTCONSTANT 6']
+ bytecode = self.compile('((((6))))')
+ assert bytecode == ['LOAD_INTCONSTANT 6']
+ bytecode = self.compile('x')
+ assert bytecode == ['LOAD_VARIABLE "x"']
# w_array = self.eval_expr('[1,2,3]')
# assert w_array.ToString(self.ctx) == '1,2,3'
w_identifier = self.eval_expr('x')
More information about the Pypy-commit
mailing list