[pypy-commit] lang-js default: wip... compiles with jit

stepahn noreply at buildbot.pypy.org
Fri Dec 28 11:34:53 CET 2012


Author: Stephan <stephan at stzal.com>
Branch: 
Changeset: r271:1783ca154ffd
Date: 2012-08-03 17:41 +0200
http://bitbucket.org/pypy/lang-js/changeset/1783ca154ffd/

Log:	wip... compiles with jit

diff --git a/js/builtins_global.py b/js/builtins_global.py
--- a/js/builtins_global.py
+++ b/js/builtins_global.py
@@ -88,7 +88,7 @@
            rpos -= 1
 
     assert rpos >= 0
-    result = unistr[lpos: rpos]
+    result = unistr[lpos:rpos]
     return result
 
 def _lstrip(unistr):
@@ -161,25 +161,29 @@
 
     return NAN
 
+
 # 15.1.2.3
 @w_return
 def parse_float(this, args):
-    from pypy.rlib.rsre import rsre_re as re
+    from pypy.rlib.rsre import rsre_core as re
     from runistr import encode_unicode_utf8
+    from js.constants import num_lit_rexp
 
     string = get_arg(args, 0)
     input_string = string.to_string()
     trimmed_string = _strip(input_string)
     str_trimmed_string = encode_unicode_utf8(trimmed_string)
 
-    number_string = str_trimmed_string
+    match_data = num_lit_rexp.match(str_trimmed_string)
+    if match_data is not None:
+        number_string = match_data.group()
+    else:
+        number_string = ''
 
-    #rexp = r'(?:[+-]?((?:(?:\d+)(?:\.\d*)?)|Infinity|(?:\.[0-9]+))(?:[eE][\+\-]?[0-9]*)?)'
-    #match_data = re.match(rexp, str_trimmed_string)
-    #if match_data is not None:
-        #number_string = match_data.group()
-    #else:
-        #number_string = ''
+    if number_string == 'Infinity' or number_string == '+Infinity':
+        return INFINITY
+    elif number_string == '-Infinity':
+        return -INFINITY
 
     try:
         number = float(number_string)
@@ -294,7 +298,7 @@
 @w_return
 def pypy_repr(this, args):
     o = args[0]
-    return unicode(o)
+    return str(o)
 
 @w_return
 def inspect(this, args):
diff --git a/js/constants.py b/js/constants.py
--- a/js/constants.py
+++ b/js/constants.py
@@ -1,29 +1,7 @@
-escapes = [
-    r'\n',
-    r'\r',
-    r'\f',
-    r'\v',
-    r'\ ',
-    r'\t',
-    r"\'",
-    r'\b',
-    r'\"',
-    r'\\',
-    r'\u'] #don't know what to do with these
+from pypy.rlib.rsre.rsre_re import compile
 
-codes = [
-    '\n',
-    '\r',
-    '\f',
-    '\v',
-    '\ ',
-    '\t',
-    "'",
-    "\b",
-    '"',
-    '\\',
-    '\u']
-
-escapedict = dict(zip(codes, escapes))
-unescapedict = dict(zip(escapes, codes))
-
+num_lit_exp = r'(?:[+-]?((?:(?:\d+)(?:\.\d*)?)|Infinity|(?:\.[0-9]+))(?:[eE][\+\-]?[0-9]*)?)'
+num_lit_rexp = compile(num_lit_exp)
+num_rexp = compile(r'^%s$' % num_lit_exp)
+hex_rexp = compile(r'^0[xX]([\dA-Fa-f]+)$')
+oct_rexp = compile(r'^0([0-7]+)$')
diff --git a/js/contants.py b/js/contants.py
new file mode 100644
--- /dev/null
+++ b/js/contants.py
@@ -0,0 +1,6 @@
+from js import jsobj
+
+w_Null = jsobj.W_Null()
+w_Undefined = jsobj.W_Undefined()
+w_False = jsobj.W_Boolean(False)
+w_True = jsobj.W_Boolean(True)
diff --git a/js/jscode.py b/js/jscode.py
--- a/js/jscode.py
+++ b/js/jscode.py
@@ -8,13 +8,15 @@
 
 from pypy.rlib import jit, debug
 
-def get_printable_location(pc, jsfunction):
-    try:
-        return str(jsfunction.opcodes[pc])
-    except IndexError:
-        return "???"
+def get_printable_location(pc, debug, jscode):
+    if pc < jscode._opcode_count():
+        opcode = jscode._get_opcode(pc)
+        return '%d: %s' % (pc, str(opcode))
+    else:
+        return '%d: %s' % (pc, 'end of opcodes')
 
 #jitdriver = JitDriver(greens=['pc', 'self'], reds=['ctx'], get_printable_location = get_printable_location, virtualizables=['ctx'])
+jitdriver = JitDriver(greens=['pc', 'debug', 'self'], reds=['result', 'ctx'], get_printable_location = get_printable_location)
 
 def ast_to_bytecode(ast, symbol_map):
     bytecode = JsCode(symbol_map)
@@ -58,7 +60,6 @@
     def params(self):
         return self._symbols.parameters
 
-    @jit.elidable
     def estimated_stack_size(self):
         # TODO: compute only once
         if self._estimated_stack_size == -1:
@@ -214,7 +215,7 @@
 
         self.unlabel()
 
-        if len(self.opcodes) == 0:
+        if self._opcode_count() == 0:
             return NormalCompletion()
 
         if debug:
@@ -223,7 +224,8 @@
         pc = 0
         result = None
         while True:
-            if pc >= len(self.opcodes):
+            jitdriver.jit_merge_point(pc = pc, debug = debug, self = self, ctx = ctx, result = result)
+            if pc >= self._opcode_count():
                 break
             opcode = self._get_opcode(pc)
             result = opcode.eval(ctx)
@@ -241,6 +243,8 @@
 
             if isinstance(opcode, BaseJump):
                 new_pc = opcode.do_jump(ctx, pc)
+                if new_pc < pc:
+                    jitdriver.can_enter_jit(pc = pc, debug = debug, self = self, ctx = ctx, result = result)
                 pc = new_pc
                 continue
             else:
diff --git a/js/jsobj.py b/js/jsobj.py
--- a/js/jsobj.py
+++ b/js/jsobj.py
@@ -1069,6 +1069,7 @@
             return False
     return True
 
+
 class W_String(W_Primitive):
     _type_ = 'string'
 
@@ -1097,36 +1098,46 @@
             return True
 
     def ToNumber(self):
+        from js.builtins_global import _strip
+        from runistr import encode_unicode_utf8
+        from js.constants import hex_rexp, oct_rexp, num_rexp
+
         u_strval = self._strval_
 
-        if u_strval == u'':
+        u_strval = _strip(u_strval)
+        s = encode_unicode_utf8(u_strval)
+
+        if s == '':
             return 0.0
 
-        if _isspace(u_strval):
-            return 0.0
+        match_data = num_rexp.match(s)
+        if match_data is not None:
+            num_lit = match_data.group()
+            assert num_lit is not None
+            assert isinstance(num_lit, str)
 
-        strval = str(u_strval)
-        print(strval)
+            if num_lit == 'Infinity' or num_lit == '+Infinity':
+                return INFINITY
+            elif num_lit == '-Infinity':
+                return -INFINITY
 
-        try:
-            return float(strval)
-        except ValueError:
-            try:
-                s = strval
-                if len(s) > 2 and (s.startswith('0x') or s.startswith('0X')):
-                  s = s[2:]
-                return float(int(s, 16))
-            except ValueError:
-                try:
-                    return float(int(strval, 8))
-                except ValueError:
-                    return NAN
-                except OverflowError:
-                    return INFINITY
-            except OverflowError:
-                return INFINITY
-        except OverflowError:
-            return INFINITY
+            return float(num_lit)
+
+        match_data = hex_rexp.match(s)
+        if match_data is not None:
+            hex_lit = match_data.group(1)
+            assert hex_lit is not None
+            assert hex_lit.startswith('0x') is False
+            assert hex_lit.startswith('0X') is False
+            return int(hex_lit, 16)
+
+        match_data = oct_rexp.match(s)
+        if match_data is not None:
+            oct_lit = match_data.group(1)
+            assert oct_lit is not None
+            return int(oct_lit, 8)
+
+        return NAN
 
 class W_Number(W_Primitive):
     """ Base class for numbers, both known to be floats
diff --git a/js/jsparser.py b/js/jsparser.py
--- a/js/jsparser.py
+++ b/js/jsparser.py
@@ -13,7 +13,20 @@
     print e.nice_error_message(filename=str(GFILE),source=t)
     raise
 
+NFILE = py.path.local(__file__).dirpath().join('jsgrammar_numeric.txt')
+try:
+    n = NFILE.read(mode='U')
+    n_regexs, n_rules, n_ToAST = parse_ebnf(n)
+except ParseError,e:
+    print e.nice_error_message(filename=str(GFILE),source=t)
+    raise
+
 parsef = make_parse_function(regexs, rules, eof=True)
 def parse(code):
     t = parsef(code)
     return ToAST().transform(t)
+
+parsen = make_parse_function(n_regexs, n_rules, eof=True)
+def parse_numbe(code):
+    t = parsen(code)
+    return n_ToAST().transform(t)
diff --git a/js/py-js.py b/js/py-js.py
new file mode 100755
--- /dev/null
+++ b/js/py-js.py
@@ -0,0 +1,127 @@
+#!/usr/bin/env python
+
+import os, sys
+from js.execution import JsException
+from pypy.rlib.objectmodel import enforceargs
+from pypy.rlib.parsing.parsing import ParseError
+
+def main(argv):
+    opts, files = parse_args(argv)
+
+    debug = opts.get('debug', False)
+    inspect = opts.get('inspect', False)
+
+    try:
+        run(files, debug, inspect)
+    except SystemExit:
+        printmessage(u"\n")
+
+    return 0
+
+def run(files, debug, inspect):
+    from js.object_space import object_space
+    from js.interpreter import Interpreter
+
+    interactive = len(files) == 0
+
+    object_space.DEBUG = debug
+    interp = Interpreter()
+
+    for f in files:
+        try:
+            interp.run_file(f)
+        except JsException as e:
+            printerrormessage(unicode(f), e._msg())
+            raise SystemExit
+
+    if inspect or interactive:
+        repl(interp)
+
+ at enforceargs(unicode, unicode)
+def printerrormessage(filename, message):
+    printmessage(u"ERROR in %s: %s\n" % (filename, message))
+
+
+def repl(interpreter):
+    filename = u'<stdin>'
+    while True:
+        printmessage(u'js> ')
+        line = readline()
+
+        try:
+            result = interpreter.run_src(line)
+            result_string = result.to_string()
+            printmessage(u"%s\n"% (result_string))
+        except ParseError as exc:
+            printsyntaxerror(filename, exc, line)
+            continue
+        except JsException as e:
+            printerrormessage(filename, e._msg())
+            continue
+
+# https://bitbucket.org/cfbolz/pyrolog/src/f18f2ccc23a4/prolog/interpreter/translatedmain.py
+ at enforceargs(unicode)
+def printmessage(msg):
+    from js.runistr import encode_unicode_utf8
+    os.write(1, encode_unicode_utf8(msg))
+
+def printsyntaxerror(filename, exc, source):
+    # XXX format syntax errors nicier
+    marker_indent = u' ' * exc.source_pos.columnno
+    error = exc.errorinformation.failure_reasons
+    error_lineno = exc.source_pos.lineno
+    error_line = (source.splitlines())[error_lineno]
+    printmessage(u'Syntax Error in: %s:%d\n' % (unicode(filename), error_lineno))
+    printmessage(u'%s\n' % (unicode(error_line)))
+    printmessage(u'%s^\n' %(marker_indent))
+    printmessage(u'Error: %s\n' %(unicode(str(error))))
+
+# https://bitbucket.org/cfbolz/pyrolog/src/f18f2ccc23a4/prolog/interpreter/translatedmain.py
+def readline():
+    result = []
+    while True:
+        s = os.read(0, 1)
+        result.append(s)
+        if s == "\n":
+            break
+        if s == '':
+            if len(result) > 1:
+                break
+            raise SystemExit
+    return "".join(result)
+
+def parse_args(argv):
+    opts = {'inspect': False, 'debug': False}
+
+    for i in xrange(len(argv)):
+        if argv[i] == '-d':
+            opts['debug'] = True
+            del(argv[i])
+            break
+
+    for i in xrange(len(argv)):
+        if argv[i] == '-i':
+            opts['inspect'] = True
+            del(argv[i])
+            break
+
+    del(argv[0])
+
+    return opts, argv
+
+if __name__ == '__main__':
+    import sys
+    main(sys.argv)
+
+# _____ Define and setup target ___
+
+def target(driver, args):
+    driver.exe_name = 'py-js'
+    return entry_point, None
+
+def jitpolicy(driver):
+    from pypy.jit.codewriter.policy import JitPolicy
+    return JitPolicy()
+
+def entry_point(argv):
+    return main(argv)


More information about the pypy-commit mailing list