[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