[pypy-commit] lang-js default: fixed ASTBuilder scoping to work with eval
stepahn
noreply at buildbot.pypy.org
Fri Dec 28 11:32:18 CET 2012
Author: Stephan <stephan at stzal.com>
Branch:
Changeset: r121:183292ceb28a
Date: 2011-09-06 19:11 +0200
http://bitbucket.org/pypy/lang-js/changeset/183292ceb28a/
Log: fixed ASTBuilder scoping to work with eval
diff --git a/js/astbuilder.py b/js/astbuilder.py
--- a/js/astbuilder.py
+++ b/js/astbuilder.py
@@ -11,7 +11,7 @@
self.declared_variables = []
def __repr__(self):
- return 'Scope ' + repr(self.local_variables)
+ return '%s: %s; %s' % (object.__repr__(self), repr(self.local_variables), repr(self.declared_variables))
def add_local(self, identifier):
if not self.is_local(identifier):
@@ -32,26 +32,46 @@
raise ValueError
return idx
+class GlobalScope(Scope):
+ def add_local(self, identifier):
+ pass
+
+ def declare_local(self, identifier):
+ if not identifier in self.declared_variables:
+ self.declared_variables.append(identifier)
+
+ def is_local(self, identifier):
+ return False
+
+ def get_local(self, identifier):
+ raise ValueError
+
+class EvalScope(GlobalScope):
+ def declare_local(self, identifier):
+ pass
+
class Scopes(object):
def __init__(self):
- self.scopes = []
+ self._scopes = []
+ self._scopes.append(GlobalScope())
def current_scope(self):
- if not self.scopes:
+ if not self._scopes:
return None
else:
- return self.scopes[-1]
+ return self._scopes[-1]
def new_scope(self):
- self.scopes.append(Scope())
+ self._scopes.append(Scope())
def end_scope(self):
- self.scopes.pop()
+ self._scopes.pop()
def declarations(self):
if self.scope_present():
return self.current_scope().declared_variables
- return []
+ else:
+ return []
def is_local(self, identifier):
return self.scope_present() == True and self.current_scope().is_local(identifier) == True
@@ -118,7 +138,6 @@
}
def __init__(self):
- self.varlists = []
self.funclists = []
self.scopes = Scopes()
self.sourcename = ""
@@ -318,18 +337,14 @@
def visit_sourceelements(self, node):
pos = self.get_pos(node)
- self.varlists.append({})
self.funclists.append({})
nodes=[]
for child in node.children:
node = self.dispatch(child)
if node is not None:
nodes.append(node)
+ # XXX is this still needed or can it be dropped?
var_decl = self.scopes.declarations()
- if not var_decl:
- var_decl = self.varlists.pop().keys()
- else:
- self.varlists.pop()
func_decl = self.funclists.pop()
return operations.SourceElements(pos, var_decl, func_decl, nodes, self.sourcename)
@@ -365,7 +380,6 @@
identifier = self.dispatch(node.children[0])
identifier_name = identifier.get_literal()
self.scopes.declare_local(identifier_name)
- self.varlists[-1][identifier_name] = None
if len(node.children) > 1:
expr = self.dispatch(node.children[1])
else:
@@ -605,3 +619,22 @@
body = self.dispatch(node.children[1])
return operations.With(pos, identifier, body)
+ASTBUILDER = ASTBuilder()
+
+# XXX this is somewhat hackish
+def new_ast_builder():
+ b = ASTBUILDER
+ b.funclists = []
+ b.scopes = Scopes()
+ b.sourcename = ""
+ return b
+
+def make_ast_builder(sourcename = ''):
+ b = new_ast_builder() #ASTBuilder()
+ b.set_sourcename(sourcename)
+ return b
+
+def make_eval_ast_builder(sourcename = ''):
+ b = make_ast_builder(sourcename)
+ b.scopes._scopes = [EvalScope()]
+ return b
diff --git a/js/interpreter.py b/js/interpreter.py
--- a/js/interpreter.py
+++ b/js/interpreter.py
@@ -3,7 +3,7 @@
from pypy.rlib import rrandom
random = rrandom.Random(int(time.time()))
from js.jsparser import parse, ParseError
-from js.astbuilder import ASTBuilder
+from js.astbuilder import make_ast_builder, make_eval_ast_builder
from js.jsobj import W_Object,\
w_Undefined, W_NewBuiltin, W_IntNumber, w_Null, create_object, W_Boolean,\
W_FloatNumber, W_String, W_Builtin, W_Array, w_Null, newbool,\
@@ -20,8 +20,6 @@
from pypy.rlib.listsort import TimSort
from pypy.rlib import jit
-ASTBUILDER = ASTBuilder()
-
def writer(x):
print x
@@ -36,8 +34,14 @@
@jit.dont_look_inside
def load_source(script_source, sourcename):
temp_tree = parse(script_source)
- ASTBUILDER.sourcename = sourcename
- return ASTBUILDER.dispatch(temp_tree)
+ builder = make_ast_builder()
+ return builder.dispatch(temp_tree)
+
+ at jit.dont_look_inside
+def eval_source(script_source, sourcename):
+ temp_tree = parse(script_source)
+ builder = make_eval_ast_builder()
+ return builder.dispatch(temp_tree)
def load_file(filename):
f = open_file_as_stream(filename)
@@ -147,7 +151,7 @@
return w_Undefined
try:
- node = load_source(src, 'evalcode')
+ node = eval_source(src, 'evalcode')
except ParseError, e:
raise ThrowException(W_String('SyntaxError: '+str(e)))
@@ -335,7 +339,8 @@
functioncode = "function () {}"
#remove program and sourcelements node
funcnode = parse(functioncode).children[0].children[0]
- ast = ASTBUILDER.dispatch(funcnode)
+ builder = make_ast_builder()
+ ast = builder.dispatch(funcnode)
bytecode = JsCode()
ast.emit(bytecode)
func = bytecode.make_js_function()
diff --git a/js/jscode.py b/js/jscode.py
--- a/js/jscode.py
+++ b/js/jscode.py
@@ -112,9 +112,7 @@
if self.has_labels:
self.remove_labels()
- #import pdb; pdb.set_trace()
return JsFunction(name, params, self)
- #return JsFunction(name, params, self.opcodes[:])
def remove_labels(self):
""" Basic optimization to remove all labels and change
More information about the pypy-commit
mailing list