From 94905372ba3f0da472edc012dd8d547874cdc3d6 Mon Sep 17 00:00:00 2001 From: anatoly techtonik Date: Sat, 23 Nov 2013 23:44:21 +0300 Subject: [PATCH 001/521] Fix issue #53: AttributeError: 'Slice' object has no attribute 'value' --- pythonjs/pythonjs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pythonjs/pythonjs.py b/pythonjs/pythonjs.py index a79ff0d..4eb7dfb 100755 --- a/pythonjs/pythonjs.py +++ b/pythonjs/pythonjs.py @@ -135,7 +135,7 @@ def visit_Subscript(self, node): name = self.visit(node.value) return '%s["$wrapped"]' %name else: - return '%s[%s]' % (self.visit(node.value), self.visit(node.slice.value)) + return '%s[%s]' % (self.visit(node.value), self.visit(node.slice)) def visit_arguments(self, node): out = [] From 0ef3e89b747312bfe198812f67bc2a87ac83c40d Mon Sep 17 00:00:00 2001 From: hartsantler Date: Sun, 24 Nov 2013 17:56:31 -0800 Subject: [PATCH 002/521] core optimized --- pythonjs/python_to_pythonjs.py | 380 +++++++++++++++++++++++++++++---- pythonjs/pythonjs.py | 4 +- 2 files changed, 341 insertions(+), 43 deletions(-) diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index 2f9f6b2..b82ef36 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -192,7 +192,12 @@ def __init__(self, module=None, module_path=None): self._global_typed_lists = dict() ## global name : set (if len(set)==1 then we know it is a typed list) self._global_typed_dicts = dict() self._global_typed_tuples = dict() - self._global_functions = set() + self._global_functions = dict() + self._with_inline = False + self._inline = [] + self._inline_ids = 0 + self._js_classes = dict() + self._in_js_class = False self._custom_operators = {} self._injector = [] ## advanced meta-programming hacks @@ -226,6 +231,10 @@ def setup_builtins(self): self._classes['list'] = set(['__getitem__', '__setitem__']) self._classes['tuple'] = set(['__getitem__', '__setitem__']) self._builtin_classes = set(['dict', 'list', 'tuple']) + self._builtin_functions = { + 'ord':'char.charCodeAt(0)', + 'chr':'String.fromCharCode(%s)', + } def is_known_class_name(self, name): return name in self._classes @@ -292,6 +301,7 @@ def visit_ImportFrom(self, node): for n in node.names: if n.name in MINI_STDLIB[ node.module ]: writer.write( 'JS("%s")' %MINI_STDLIB[node.module][n.name] ) + self._builtin_functions[ n.name ] = n.name + '()' elif self._check_for_module( node.module ): if node.names[0].name == '*': @@ -421,8 +431,45 @@ def visit_AugAssign(self, node): def visit_Yield(self, node): return 'yield %s' % self.visit(node.value) + def _visit_js_classdef(self, node): + name = node.name + log('JavaScript-ClassDef: %s'%name) + self._js_classes[ name ] = node + self._in_js_class = True + + methods = {} + for item in node.body: + if isinstance(item, FunctionDef): + methods[ item.name ] = item + + item.args.args = item.args.args[1:] ## remove self + finfo = inspect_function( item ) + for n in finfo['name_nodes']: + if n.id == 'self': + n.id = 'this' + + init = methods.pop('__init__') + args = [self.visit(arg) for arg in init.args.args] + + writer.write('def %s(%s):' %(name,','.join(args))) + writer.push() + for b in init.body: + line = self.visit(b) + if line: + writer.write( line ) + for method in methods.values(): + line = self.visit(method) + if line: + writer.write( line ) + + writer.pull() + self._in_js_class = False def visit_ClassDef(self, node): + if self._with_js: + self._visit_js_classdef(node) + return + name = node.name log('ClassDef: %s'%name) self._in_class = name @@ -602,10 +649,18 @@ def visit_Return(self, node): writer.write('self["__dict__"]["%s"] = %s' %(self._cached_property, self.visit(node.value)) ) writer.write('return self["__dict__"]["%s"]' %self._cached_property) else: - writer.write('return %s' % self.visit(node.value)) + if self._inline: + writer.write('__returns__%s = %s' %(self._inline[-1], self.visit(node.value)) ) + writer.write('break') + else: + writer.write('return %s' % self.visit(node.value)) else: - writer.write('return') ## empty return + if self._inline: + writer.write('break') + pass ## TODO put inline inside a while loop that iterates once? and use `break` here to exit early? + else: + writer.write('return') ## empty return def visit_BinOp(self, node): left = self.visit(node.left) @@ -766,7 +821,7 @@ def visit_Attribute(self, node): return "%s['__class__']['%s']" %(node_value, node.attr) elif node.attr in typedef.attributes: - return "%s['%s']" %(node_value, node.attr) + return "%s.%s" %(node_value, node.attr) elif '__getattr__' in typedef.methods: func = typedef.get_pythonjs_function_name( '__getattr__' ) @@ -794,7 +849,7 @@ def visit_Attribute(self, node): return '%s([%s, "%s"], JSObject())' %(func, node_value, node.attr) else: - return '__get__(%s, "%s")' % (node_value, node.attr) ## TODO - double check this + return '__get__(%s, "%s")' % (node_value, node.attr) ## TODO - this could be a builtin class like: list, dict, etc. else: return '__get__(%s, "%s")' % (node_value, node.attr) ## TODO - double check this @@ -819,6 +874,9 @@ def visit_Subscript(self, node): self.visit(node.slice), ) + elif name in self._func_typedefs and self._func_typedefs[name] == 'list': + return '%s[...][%s]'%(name, self.visit(node.slice)) + elif name in self._instances: ## support x[y] operator overloading klass = self._instances[ name ] if '__getitem__' in self._classes[ klass ]: @@ -848,11 +906,18 @@ def visit_Assign(self, node): # XXX: support only one target for subscripts target = node.targets[0] if isinstance(target, Subscript): + name = self.visit(target.value) ## target.value may have "returns_type" after being visited + if isinstance(target.slice, ast.Ellipsis): code = '%s["$wrapped"] = %s' %(self.visit(target.value), self.visit(node.value)) + elif self._with_js: code = '%s[ %s ] = %s' code = code % (self.visit(target.value), self.visit(target.slice.value), self.visit(node.value)) + + elif name in self._func_typedefs and self._func_typedefs[name] == 'list': + code = '%s[...][%s] = %s'%(name, self.visit(target.slice.value), self.visit(node.value)) + else: code = "__get__(__get__(%s, '__setitem__'), '__call__')([%s, %s], JSObject())" code = code % (self.visit(target.value), self.visit(target.slice.value), self.visit(node.value)) @@ -877,7 +942,7 @@ def visit_Assign(self, node): elif typedef and target.attr in typedef.class_attributes: writer.write( '''%s['__class__']['%s'] = %s''' %(target_value, target.attr, self.visit(node.value))) elif typedef and target.attr in typedef.attributes: - writer.write( '''%s['%s'] = %s''' %(target_value, target.attr, self.visit(node.value))) + writer.write( '%s.%s = %s' %(target_value, target.attr, self.visit(node.value))) elif typedef and typedef.parents: parent_prop = typedef.check_for_parent_with( property=target.attr ) @@ -1020,7 +1085,24 @@ def visit_Expr(self, node): writer.write(self.visit(node.value)) def visit_Call(self, node): - if self._with_js: + if isinstance(node.func, ast.Attribute) and isinstance(node.func.value, Name) and node.func.value.id == 'pythonjs' and node.func.attr == 'enable': + for kw in node.keywords: + if kw.arg == 'javascript': + if kw.value.id == 'True': + self._with_js = True + elif kw.value.id == 'False': + self._with_js = False + + elif kw.arg == 'inline': + if kw.value.id == 'True': + self._with_inline = True + elif kw.value.id == 'False': + self._with_inline = False + + else: + raise SyntaxError + + elif self._with_js: args = list( map(self.visit, node.args) ) if isinstance(node.func, Name) and node.func.id == 'new': assert len(args) == 1 @@ -1029,11 +1111,15 @@ def visit_Call(self, node): elif isinstance(node.func, Name) and node.func.id == 'JS': ## avoids nested JS assert len(args) == 1 return node.args[0].s ## string literal + + elif isinstance(node.func, Name) and node.func.id in self._js_classes: + a = ','.join(args) + return ' new %s(%s)' %( self.visit(node.func), a ) else: a = ','.join(args) - return '%s( %s )' %( self.visit(node.func), a ) + return '%s(%s)' %( self.visit(node.func), a ) - if isinstance(node.func, Name) and node.func.id in ('JS', 'toString', 'JSObject', 'JSArray', 'var', 'instanceof', 'typeof'): + elif isinstance(node.func, Name) and node.func.id in ('JS', 'toString', 'JSObject', 'JSArray', 'var', 'instanceof', 'typeof'): args = list( map(self.visit, node.args) ) ## map in py3 returns an iterator not a list if node.func.id == 'var': for k in node.keywords: @@ -1063,6 +1149,8 @@ def visit_Call(self, node): call_has_args_kwargs_only = len(node.args) and len(node.keywords) and not (node.starargs or node.kwargs) call_has_args = len(node.args) or len(node.keywords) or node.starargs or node.kwargs name = self.visit(node.func) + args = None + kwargs = None if call_has_args_only: ## lambda only supports simple args for now. args = ', '.join(map(self.visit, node.args)) @@ -1097,7 +1185,88 @@ def visit_Call(self, node): code = "JS('for (var name in %s) { %s[name] = %s[...][name]; }')" % (kwargs, kwargs_name, kwargs) writer.append(code) - if call_has_args_only: + ####################################### + + #if name in self._func_typedefs: + # if args and kwargs: + # return '%s(%s, %s)' %(args_name, kwargs_name) + # elif args: + # return '%s(%s, {})' %args_name + # elif kwargs: + # return '%s([], %s)' %kwargs_name + # else: + # return '%s()' %name + + if isinstance(node.func, ast.Attribute) and isinstance(node.func.value, Name) and node.func.value.id in self._func_typedefs: + type = self._func_typedefs[ node.func.value.id ] + if type == 'list' and node.func.attr == 'append': + return '%s[...].push(%s)' %(node.func.value.id, self.visit(node.args[0])) + else: + raise RuntimeError + + elif name in self._builtin_functions and self._builtin_functions[name]: ## inlined js + if args: + return self._builtin_functions[name] % args + else: + return self._builtin_functions[name] + + elif hasattr(node,'constant') or name in self._builtin_functions: + if args and kwargs: + return '%s([%s], {%s})' %(args, kwargs) + elif args: + return '%s([%s], __NULL_OBJECT__)' %(name,args) + elif kwargs: + return '%s([], {%s})' %(name,kwargs) + else: + return '%s()' %name + + elif name in self._global_functions: + writer.write('##inlined->%s'%name) + fnode = self._global_functions[ name ] + finfo = inspect_function( fnode ) + remap = {} + for n in finfo['name_nodes']: + if n.id not in finfo['locals']: continue + if n.id not in remap: + new_name = n.id + '_%s'%self._inline_ids + remap[ n.id ] = new_name + self._inline_ids += 1 + n.id = remap[ n.id ] + + if remap: + writer.write( "JS('var %s')" %','.join(remap.values()) ) + for n in remap: + if n in finfo['typedefs']: + self._func_typedefs[ remap[n] ] = finfo['typedefs'][n] + + for i,a in enumerate(node.args): + b = self.visit( fnode.args.args[i] ) + b = remap[ b ] + writer.write( "%s = %s" %(b, self.visit(a)) ) + + self._inline.append( name ) + + writer.write("JS('var __returns__%s = null')"%name) + writer.write('while True:') + writer.push() + for b in fnode.body: + self.visit(b) + if len( finfo['return_nodes'] ) == 0: + writer.write('break') + writer.pull() + + if self._inline.pop() != name: + raise RuntimeError + + for n in remap: + gname = remap[n] + for n in finfo['name_nodes']: + if n.id == gname: + n.id = n + + return '__returns__%s' %name + + elif call_has_args_only: if name in self._global_functions: return '%s( [%s], __NULL_OBJECT__ )' %(name,args) else: @@ -1160,9 +1329,10 @@ def visit_FunctionDef(self, node): fastdef = False javascript = False self._cached_property = None + self._func_typedefs = {} if writer.is_at_global_level(): - self._global_functions.add( node.name ) + self._global_functions[ node.name ] = node ## save ast-node for decorator in reversed(node.decorator_list): log('@decorator: %s' %decorator) @@ -1211,6 +1381,15 @@ def visit_FunctionDef(self, node): assert isinstance( decorator.args[0], Name) return_type = decorator.args[0].id + elif isinstance(decorator, Call) and decorator.func.id == 'typedef': + c = decorator + assert len(c.args) == 0 and len(c.keywords) + for kw in c.keywords: + assert isinstance( kw.value, Name) + self._instances[ kw.arg ] = kw.value.id + self._func_typedefs[ kw.arg ] = kw.value.id + log('@typedef - %s : %s'%(kw.arg, kw.value.id)) + else: decorators.append( decorator ) @@ -1232,32 +1411,6 @@ def visit_FunctionDef(self, node): ## this is kept here as an option to be sure we are compatible with the ## old-style code in runtime/pythonpythonjs.py and runtime/builtins.py if not GLOBAL_VARIABLE_SCOPE: - def retrieve_vars(body): - local_vars = set() - global_vars = set() - for n in body: - if isinstance(n, Assign) and isinstance(n.targets[0], Name): ## assignment to local - TODO support `a=b=c` - local_vars.add( n.targets[0].id ) - elif isinstance(n, Assign) and isinstance(n.targets[0], ast.Tuple): - for c in n.targets[0].elts: - local_vars.add( c.id ) - elif isinstance(n, Global): - global_vars.update( n.names ) - elif isinstance(n, With) and isinstance( n.context_expr, Name ) and n.context_expr.id == 'javascript': - for c in n.body: - if isinstance(c, Assign) and isinstance(c.targets[0], Name): ## assignment to local - local_vars.add( c.targets[0].id ) - elif hasattr(n, 'body') and not isinstance(n, FunctionDef): - # do a recursive search inside new block except function def - l, g = retrieve_vars(n.body) - local_vars.update(l) - global_vars.update(g) - if hasattr(n, 'orelse'): - l, g = retrieve_vars(n.orelse) - local_vars.update(l) - global_vars.update(g) - return local_vars, global_vars - local_vars, global_vars = retrieve_vars(node.body) if local_vars-global_vars: a = ','.join( local_vars-global_vars ) @@ -1332,7 +1485,6 @@ def retrieve_vars(body): # create a JS Object to store the value of each parameter signature = ', '.join(map(lambda x: '%s=%s' % (self.visit(x.arg), self.visit(x.value)), keywords)) writer.write('signature = JSObject(%s)' % signature) - writer.write('signature["function_name"] = "%s"' %node.name) writer.write('arguments = get_arguments(signature, args, kwargs)') # # then for each argument assign its value for arg in node.args.args: @@ -1389,6 +1541,11 @@ def retrieve_vars(body): writer.pull() writer.pull() + + if self._in_js_class: + writer.write('this.%s = %s' %(node.name, node.name)) + return + ## note, in javascript function.name is a non-standard readonly attribute, ## the compiler creates anonymous functions with name set to an empty string. writer.write('%s.NAME = "%s"' %(node.name,node.name)) @@ -1454,11 +1611,45 @@ def visit_Break(self, node): writer.write('break') def visit_For(self, node): + log('for loop:') + for n in node.body: + calls = collect_calls(n) + for c in calls: + log('--call: %s' %c) + log('------: %s' %c.func) + if self._inline and False: + if isinstance(c.func, ast.Name): ## these are constant for sure + i = self._call_ids + writer.write( '''JS('var __call__%s = __get__(%s,"__call__")')''' %(i,self.visit(c.func)) ) + c.func.id = '__call__%s'%i + c.constant = True + self._call_ids += 1 + + if self._with_js: - writer.write('for %s in %s:' %(self.visit(node.target),self.visit(node.iter))) - writer.push() - map(self.visit, node.body) - writer.pull() + if isinstance(node.iter, ast.Call) and isinstance(node.iter.func, Name) and node.iter.func.id == 'range': + iter_start = '0' + if len(node.iter.args) == 2: + iter_start = self.visit(node.iter.args[0]) + iter_end = self.visit(node.iter.args[1]) + else: + iter_end = self.visit(node.iter.args[0]) + + iter_name = node.target.id + writer.write('var(%s)' %iter_name) + writer.write('%s = %s' %(iter_name, iter_start)) + writer.write('while %s < %s:' %(iter_name, iter_end)) + writer.push() + map(self.visit, node.body) + writer.write('%s += 1' %iter_name ) + writer.pull() + + + else: + writer.write('for %s in %s:' %(self.visit(node.target),self.visit(node.iter))) + writer.push() + map(self.visit, node.body) + writer.pull() else: ## TODO else remove node.target.id from self._instances @@ -1518,7 +1709,23 @@ def visit_For(self, node): return '' + _call_ids = 0 def visit_While(self, node): + log('while loop:') + for n in node.body: + continue + calls = collect_calls(n) + for c in calls: + log('--call: %s' %c) + log('------: %s' %c.func) + if isinstance(c.func, ast.Name): ## these are constant for sure + i = self._call_ids + writer.write( '__call__%s = __get__(%s,"__call__")' %(i,self.visit(c.func)) ) + c.func.id = '__call__%s'%i + c.constant = True + self._call_ids += 1 + + writer.write('while %s:' % self.visit(node.test)) writer.push() map(self.visit, node.body) @@ -1563,6 +1770,95 @@ def visit_With(self, node): else: raise SyntaxError('improper use of "with" statement') + +class CollectCalls(NodeVisitor): + _calls_ = [] + def visit_Call(self, node): + self._calls_.append( node ) + +def collect_calls(node): + CollectCalls._calls_ = calls = [] + CollectCalls().visit( node ) + return calls + +class CollectNames(NodeVisitor): + _names_ = [] + def visit_Name(self, node): + self._names_.append( node ) + +def collect_names(node): + CollectNames._names_ = names = [] + CollectNames().visit( node ) + return names + +class CollectReturns(NodeVisitor): + _returns_ = [] + def visit_Return(self, node): + self._returns_.append( node ) + +def collect_returns(node): + CollectReturns._returns_ = returns = [] + CollectReturns().visit( node ) + return returns + +def retrieve_vars(body): + local_vars = set() + global_vars = set() + for n in body: + if isinstance(n, Assign) and isinstance(n.targets[0], Name): ## assignment to local - TODO support `a=b=c` + local_vars.add( n.targets[0].id ) + elif isinstance(n, Assign) and isinstance(n.targets[0], ast.Tuple): + for c in n.targets[0].elts: + local_vars.add( c.id ) + elif isinstance(n, Global): + global_vars.update( n.names ) + elif isinstance(n, With) and isinstance( n.context_expr, Name ) and n.context_expr.id == 'javascript': + for c in n.body: + if isinstance(c, Assign) and isinstance(c.targets[0], Name): ## assignment to local + local_vars.add( c.targets[0].id ) + elif hasattr(n, 'body') and not isinstance(n, FunctionDef): + # do a recursive search inside new block except function def + l, g = retrieve_vars(n.body) + local_vars.update(l) + global_vars.update(g) + if hasattr(n, 'orelse'): + l, g = retrieve_vars(n.orelse) + local_vars.update(l) + global_vars.update(g) + + return local_vars, global_vars + +def inspect_function( node ): + local_vars, global_vars = retrieve_vars(node.body) + local_vars = local_vars - global_vars + for arg in node.args.args: + local_vars.add( arg.id ) + names = [] + returns = [] + for n in node.body: + names.extend( collect_names(n) ) + returns.extend( collect_returns(n) ) + + typedefs = {} + for decorator in node.decorator_list: + if isinstance(decorator, Call) and decorator.func.id == 'typedef': + c = decorator + assert len(c.args) == 0 and len(c.keywords) + for kw in c.keywords: + assert isinstance( kw.value, Name) + typedefs[ kw.arg ] = kw.value.id + + info = { + 'locals':local_vars, + 'globals':global_vars, + 'name_nodes':names, + 'return_nodes':returns, + 'typedefs': typedefs + } + return info + + + def main(script): input = parse(script) PythonToPythonJS().visit(input) diff --git a/pythonjs/pythonjs.py b/pythonjs/pythonjs.py index a79ff0d..b191560 100755 --- a/pythonjs/pythonjs.py +++ b/pythonjs/pythonjs.py @@ -18,6 +18,8 @@ class JSGenerator(NodeVisitor): _indent = 0 + _global_funcions = {} + @classmethod def push(cls): cls._indent += 1 @@ -125,7 +127,7 @@ def visit_FunctionDef(self, node): if node.name == self._function_stack[0]: ## could do something special here with global function #buffer += 'pythonjs.%s = %s' %(node.name, node.name) ## this is no longer needed - pass + self._global_funcions[ node.name ] = buffer assert node.name == self._function_stack.pop() return buffer From af06170437bf62824f805fc9c9733cfe251d354f Mon Sep 17 00:00:00 2001 From: hartsantler Date: Sun, 24 Nov 2013 22:57:00 -0800 Subject: [PATCH 003/521] optimized core: fixed inlining, added tests. --- pythonjs.js | 343 +++++++++++--------------- pythonjs/python_to_pythonjs.py | 212 +++++++++------- pythonjs/pythonjs.py | 4 +- runtime/builtins.py | 6 +- tests/test_function_inline.html | 40 +++ tests/test_typedef_args.html | 28 +++ tests/test_while_fast_calls.html | 32 +++ tests/test_with_javascript_class.html | 31 +++ 8 files changed, 413 insertions(+), 283 deletions(-) create mode 100644 tests/test_function_inline.html create mode 100644 tests/test_typedef_args.html create mode 100644 tests/test_while_fast_calls.html create mode 100644 tests/test_with_javascript_class.html diff --git a/pythonjs.js b/pythonjs.js index 7d370fa..8571408 100644 --- a/pythonjs.js +++ b/pythonjs.js @@ -1,4 +1,4 @@ -// PythonScript Runtime - regenerated on: Fri Nov 22 16:33:44 2013 +// PythonScript Runtime - regenerated on: Sun Nov 24 19:32:45 2013 __NULL_OBJECT__ = Object.create(null); if ("window" in this && "document" in this) { __NODEJS__ = false; @@ -399,12 +399,12 @@ __bind_property_descriptors__ = function(o, klass) { desc = { enumerable:true }; prop = klass.__properties__[ name ]; if (prop["get"]) { - desc[ "get" ] = __generate_getter__( klass,o,name ); + desc[ "get" ] = __generate_getter__(klass,o,name); } if (prop["set"]) { - desc[ "set" ] = __generate_setter__( klass,o,name ); + desc[ "set" ] = __generate_setter__(klass,o,name); } - Object.defineProperty( o,name,desc ); + Object.defineProperty(o,name,desc); name = backup; } var iter = klass.__bases__; @@ -412,7 +412,7 @@ __bind_property_descriptors__ = function(o, klass) { if (! (iter instanceof Array) ) { iter = __object_keys__(iter) } for (var base=0; base < iter.length; base++) { var backup = base; base = iter[base]; - __bind_property_descriptors__( o,base ); + __bind_property_descriptors__(o,base); base = backup; } } @@ -422,7 +422,7 @@ __bind_property_descriptors__.args_signature = ["o","klass"]; __bind_property_descriptors__.kwargs_signature = {}; __bind_property_descriptors__.types_signature = {}; __generate_getter__ = function(klass, o, n) { - return (function () {return klass.__properties__[ n ][ "get" ]( [o],{ } )}); + return (function () {return klass.__properties__[ n ][ "get" ]([o],{ })}); } __generate_getter__.NAME = "__generate_getter__"; @@ -430,7 +430,7 @@ __generate_getter__.args_signature = ["klass","o","n"]; __generate_getter__.kwargs_signature = {}; __generate_getter__.types_signature = {}; __generate_setter__ = function(klass, o, n) { - return (function (v) {return klass.__properties__[ n ][ "set" ]( [o, v],{ } )}); + return (function (v) {return klass.__properties__[ n ][ "set" ]([o, v],{ })}); } __generate_setter__.NAME = "__generate_setter__"; @@ -453,12 +453,12 @@ create_class = function(class_name, parents, attrs, props) { if (attrs.__metaclass__) { metaclass = attrs.__metaclass__; attrs.__metaclass__=undefined; - return metaclass( [class_name, parents, attrs] ); + return metaclass([class_name, parents, attrs]); } - klass = Object.create( null ); + klass = Object.create(null); klass.__bases__=parents; klass.__name__=class_name; - klass.__unbound_methods__=Object.create( null ); + klass.__unbound_methods__=Object.create(null); klass.__all_method_names__=[]; klass.__properties__=props; klass.__attributes__=attrs; @@ -469,7 +469,7 @@ create_class = function(class_name, parents, attrs, props) { var backup = key; key = iter[key]; if (typeof(attrs[key]) == "function") { klass.__unbound_methods__[ key ] = attrs[ key ]; - klass.__all_method_names__.push( key ); + klass.__all_method_names__.push(key); } if (key == "__getattribute__") { continue; @@ -485,9 +485,9 @@ create_class = function(class_name, parents, attrs, props) { for (var name=0; name < iter.length; name++) { var backup = name; name = iter[name]; prop = klass.__properties__[ name ]; - klass.__getters__.push( name ); + klass.__getters__.push(name); if (prop["set"]) { - klass.__setters__.push( name ); + klass.__setters__.push(name); } name = backup; } @@ -496,17 +496,17 @@ create_class = function(class_name, parents, attrs, props) { if (! (iter instanceof Array) ) { iter = __object_keys__(iter) } for (var base=0; base < iter.length; base++) { var backup = base; base = iter[base]; - Array.prototype.push.apply( klass.__getters__,base.__getters__ ); - Array.prototype.push.apply( klass.__setters__,base.__setters__ ); - Array.prototype.push.apply( klass.__all_method_names__,base.__all_method_names__ ); + Array.prototype.push.apply(klass.__getters__,base.__getters__); + Array.prototype.push.apply(klass.__setters__,base.__setters__); + Array.prototype.push.apply(klass.__all_method_names__,base.__all_method_names__); base = backup; } var __call__ = function() { var has_getattr, wrapper, object, has_getattribute; "Create a PythonJS object"; - object = Object.create( null ); + object = Object.create(null); object.__class__=klass; - Object.defineProperty( object,"__dict__",{ enumerable:false,value:object,writeable:false,configurable:false } ); + Object.defineProperty(object,"__dict__",{ enumerable:false,value:object,writeable:false,configurable:false }); has_getattribute = false; has_getattr = false; var iter = klass.__all_method_names__; @@ -520,7 +520,7 @@ create_class = function(class_name, parents, attrs, props) { if (name == "__getattr__") { has_getattr = true; } else { - wrapper = __get__( object,name ); + wrapper = __get__(object,name); if (!wrapper.is_wrapper) { console.log("RUNTIME ERROR: failed to get wrapper for:", name); } @@ -529,14 +529,14 @@ create_class = function(class_name, parents, attrs, props) { name = backup; } if (has_getattr) { - __get__( object,"__getattr__" ); + __get__(object,"__getattr__"); } if (has_getattribute) { - __get__( object,"__getattribute__" ); + __get__(object,"__getattribute__"); } - __bind_property_descriptors__( object,klass ); + __bind_property_descriptors__(object,klass); if (object.__init__) { - object.__init__.apply( this,arguments ); + object.__init__.apply(this,arguments); } return object; } @@ -563,7 +563,6 @@ type = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": {"bases": undefined, "class_dict": undefined}, "args": __create_array__("ob_or_class_name", "bases", "class_dict")}; - signature["function_name"] = "type"; arguments = get_arguments(signature, args, kwargs); var ob_or_class_name = arguments['ob_or_class_name']; var bases = arguments['bases']; @@ -572,7 +571,7 @@ type = function(args, kwargs) { if (bases === undefined && class_dict === undefined) { return ob_or_class_name.__class__; } else { - return create_class( ob_or_class_name,bases,class_dict ); + return create_class(ob_or_class_name,bases,class_dict); } } @@ -590,12 +589,11 @@ hasattr = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": {"method": false}, "args": __create_array__("ob", "attr", "method")}; - signature["function_name"] = "hasattr"; arguments = get_arguments(signature, args, kwargs); var ob = arguments['ob']; var attr = arguments['attr']; var method = arguments['method']; - return Object.hasOwnProperty.call( ob,attr ); + return Object.hasOwnProperty.call(ob,attr); } hasattr.NAME = "hasattr"; @@ -612,20 +610,19 @@ getattr = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": {"property": false}, "args": __create_array__("ob", "attr", "property")}; - signature["function_name"] = "getattr"; arguments = get_arguments(signature, args, kwargs); var ob = arguments['ob']; var attr = arguments['attr']; var property = arguments['property']; if (property) { - prop = _get_upstream_property( ob.__class__,attr ); + prop = _get_upstream_property(ob.__class__,attr); if (prop && prop["get"]) { - return prop[ "get" ]( [ob],{ } ); + return prop[ "get" ]([ob],{ }); } else { console.log("ERROR: getattr property error", prop); } } else { - return __get__( ob,attr ); + return __get__(ob,attr); } } @@ -643,21 +640,20 @@ setattr = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": {"property": false}, "args": __create_array__("ob", "attr", "value", "property")}; - signature["function_name"] = "setattr"; arguments = get_arguments(signature, args, kwargs); var ob = arguments['ob']; var attr = arguments['attr']; var value = arguments['value']; var property = arguments['property']; if (property) { - prop = _get_upstream_property( ob.__class__,attr ); + prop = _get_upstream_property(ob.__class__,attr); if (prop && prop["set"]) { - prop[ "set" ]( [ob, value],{ } ); + prop[ "set" ]([ob, value],{ }); } else { console.log("ERROR: setattr property error", prop); } } else { - set_attribute( ob,attr,value ); + set_attribute(ob,attr,value); } } @@ -676,7 +672,6 @@ issubclass = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("C", "B")}; - signature["function_name"] = "issubclass"; arguments = get_arguments(signature, args, kwargs); var C = arguments['C']; var B = arguments['B']; @@ -709,7 +704,6 @@ isinstance = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("ob", "klass")}; - signature["function_name"] = "isinstance"; arguments = get_arguments(signature, args, kwargs); var ob = arguments['ob']; var klass = arguments['klass']; @@ -742,13 +736,12 @@ int = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("a")}; - signature["function_name"] = "int"; arguments = get_arguments(signature, args, kwargs); var a = arguments['a']; if (a instanceof String) { - return window.parseInt( a ); + return window.parseInt(a); } else { - return Math.round( a ); + return Math.round(a); } } @@ -766,11 +759,10 @@ float = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("a")}; - signature["function_name"] = "float"; arguments = get_arguments(signature, args, kwargs); var a = arguments['a']; if (a instanceof String) { - return window.parseFloat( a ); + return window.parseFloat(a); } else { return a; } @@ -791,7 +783,6 @@ round = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("a", "places")}; - signature["function_name"] = "round"; arguments = get_arguments(signature, args, kwargs); var a = arguments['a']; var places = arguments['places']; @@ -799,10 +790,10 @@ round = function(args, kwargs) { if (b.indexOf(".") == -1) { return a; } else { - c = b.split( "." ); + c = b.split("."); x = c[ 0 ]; - y = c[ 1 ].substring( 0,places ); - return parseFloat( x + "." + y ); + y = c[ 1 ].substring(0,places); + return parseFloat(x + "." + y); } } @@ -820,7 +811,6 @@ str = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("s")}; - signature["function_name"] = "str"; arguments = get_arguments(signature, args, kwargs); var s = arguments['s']; return "" + s; @@ -887,7 +877,7 @@ _setup_str_prototype = function(args, kwargs) { if (stop < 0) { stop = this.length + stop; } - return this.substring( start,stop ); + return this.substring(start,stop); } func.NAME = "func"; @@ -896,7 +886,7 @@ _setup_str_prototype = function(args, kwargs) { func.types_signature = {}; String.prototype.__getslice__=func; var func = function() { - return this.split( "\n" ); + return this.split("\n"); } func.NAME = "func"; @@ -905,7 +895,7 @@ _setup_str_prototype = function(args, kwargs) { func.types_signature = {}; String.prototype.splitlines=func; var func = function() { - return this.trim( ); + return this.trim(); } func.NAME = "func"; @@ -969,7 +959,7 @@ _setup_str_prototype = function(args, kwargs) { func.types_signature = {}; String.prototype.join=func; var func = function() { - return this.toUpperCase( ); + return this.toUpperCase(); } func.NAME = "func"; @@ -978,7 +968,7 @@ _setup_str_prototype = function(args, kwargs) { func.types_signature = {}; String.prototype.upper=func; var func = function() { - return this.toLowerCase( ); + return this.toLowerCase(); } func.NAME = "func"; @@ -987,7 +977,7 @@ _setup_str_prototype = function(args, kwargs) { func.types_signature = {}; String.prototype.lower=func; var func = function(a) { - return this.indexOf( a ); + return this.indexOf(a); } func.NAME = "func"; @@ -1090,7 +1080,7 @@ _setup_array_prototype = function(args, kwargs) { if (stop < 0) { stop = this.length + stop; } - return this.slice( start,stop ); + return this.slice(start,stop); } func.NAME = "func"; @@ -1098,6 +1088,15 @@ _setup_array_prototype = function(args, kwargs) { func.kwargs_signature = {}; func.types_signature = {}; Array.prototype.__getslice__=func; + var func = function(item) { + this.push(item); + } + + func.NAME = "func"; + func.args_signature = ["item"]; + func.kwargs_signature = {}; + func.types_signature = {}; + Array.prototype.append=func; } _setup_array_prototype.NAME = "_setup_array_prototype"; @@ -1116,7 +1115,6 @@ range = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("num", "stop")}; - signature["function_name"] = "range"; arguments = get_arguments(signature, args, kwargs); var num = arguments['num']; var stop = arguments['stop']; @@ -1129,7 +1127,7 @@ range = function(args, kwargs) { } arr = []; while(i < num) { - arr.push( i ); + arr.push(i); i += 1; } var __args_0, __kwargs_0; @@ -1158,7 +1156,6 @@ len = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("obj")}; - signature["function_name"] = "len"; arguments = get_arguments(signature, args, kwargs); var obj = arguments['obj']; return __get__(__get__(obj, "__len__"), "__call__")(); @@ -1178,7 +1175,6 @@ next = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("obj")}; - signature["function_name"] = "next"; arguments = get_arguments(signature, args, kwargs); var obj = arguments['obj']; return __get__(__get__(obj, "next"), "__call__")(); @@ -1198,7 +1194,6 @@ map = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("func", "objs")}; - signature["function_name"] = "map"; arguments = get_arguments(signature, args, kwargs); var func = arguments['func']; var objs = arguments['objs']; @@ -1224,7 +1219,6 @@ min = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("lst")}; - signature["function_name"] = "min"; arguments = get_arguments(signature, args, kwargs); var lst = arguments['lst']; a = undefined; @@ -1260,7 +1254,6 @@ max = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("lst")}; - signature["function_name"] = "max"; arguments = get_arguments(signature, args, kwargs); var lst = arguments['lst']; a = undefined; @@ -1295,7 +1288,6 @@ abs = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("num")}; - signature["function_name"] = "abs"; arguments = get_arguments(signature, args, kwargs); var num = arguments['num']; return Math.abs(num); @@ -1307,25 +1299,41 @@ abs.kwargs_signature = { }; abs.types_signature = { }; abs.pythonscript_function = true; ord = function(args, kwargs) { - var char = args[ 0 ]; + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + /*pass*/ + } else { + args = Array.prototype.slice.call(arguments); + kwargs = Object(); + } + var signature, arguments; + signature = {"kwargs": Object(), "args": __create_array__("char")}; + arguments = get_arguments(signature, args, kwargs); + var char = arguments['char']; return char.charCodeAt(0); } ord.NAME = "ord"; ord.args_signature = ["char"]; ord.kwargs_signature = { }; -ord.fastdef = true; ord.types_signature = { }; ord.pythonscript_function = true; chr = function(args, kwargs) { - var num = args[ 0 ]; + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + /*pass*/ + } else { + args = Array.prototype.slice.call(arguments); + kwargs = Object(); + } + var signature, arguments; + signature = {"kwargs": Object(), "args": __create_array__("num")}; + arguments = get_arguments(signature, args, kwargs); + var num = arguments['num']; return String.fromCharCode(num); } chr.NAME = "chr"; chr.args_signature = ["num"]; chr.kwargs_signature = { }; -chr.fastdef = true; chr.types_signature = { }; chr.pythonscript_function = true; var Iterator, __Iterator_attrs, __Iterator_parents; @@ -1341,15 +1349,14 @@ __Iterator___init__ = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self", "obj", "index")}; - signature["function_name"] = "__Iterator___init__"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var obj = arguments['obj']; var index = arguments['index']; - self["obj"] = obj; - self["index"] = index; - self["length"] = len([obj], __NULL_OBJECT__); - self["obj_get"] = __get__(obj, "get"); + self.obj = obj; + self.index = index; + self.length = len([obj], __NULL_OBJECT__); + self.obj_get = __get__(obj, "get"); } __Iterator___init__.NAME = "__Iterator___init__"; @@ -1368,16 +1375,15 @@ __Iterator_next = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self")}; - signature["function_name"] = "__Iterator_next"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; - index = self["index"]; - length = len([self["obj"]], __NULL_OBJECT__); + index = self.index; + length = len([self.obj], __NULL_OBJECT__); if (index == length) { throw StopIteration; } - item = __get__(__get__(self["obj"], "get"), "__call__")([self["index"]], __NULL_OBJECT__); - self["index"] = self["index"] + 1; + item = __get__(__get__(self.obj, "get"), "__call__")([self.index], __NULL_OBJECT__); + self.index = self.index + 1; return item; } @@ -1397,12 +1403,11 @@ __Iterator_next_fast = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self")}; - signature["function_name"] = "__Iterator_next_fast"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; index = self.index; self.index += 1; - return self.obj_get( [index],{ } ); + return self.obj_get([index],{ }); } __Iterator_next_fast.NAME = "__Iterator_next_fast"; @@ -1426,7 +1431,6 @@ __tuple___init__ = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": {"js_object": undefined}, "args": __create_array__("self", "js_object")}; - signature["function_name"] = "__tuple___init__"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var js_object = arguments['js_object']; @@ -1475,7 +1479,6 @@ __tuple___getitem__ = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self", "index")}; - signature["function_name"] = "__tuple___getitem__"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var index = arguments['index']; @@ -1500,7 +1503,6 @@ __tuple___iter__ = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self")}; - signature["function_name"] = "__tuple___iter__"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; return __get__(Iterator, "__call__")([self, 0], __NULL_OBJECT__); @@ -1522,7 +1524,6 @@ __tuple___len__ = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self")}; - signature["function_name"] = "__tuple___len__"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; return self["$wrapped"].length; @@ -1543,11 +1544,10 @@ __tuple_index = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self", "obj")}; - signature["function_name"] = "__tuple_index"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var obj = arguments['obj']; - return self["$wrapped"].indexOf( obj ); + return self["$wrapped"].indexOf(obj); } __tuple_index.NAME = "__tuple_index"; @@ -1566,7 +1566,6 @@ __tuple_count = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self", "obj")}; - signature["function_name"] = "__tuple_count"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var obj = arguments['obj']; @@ -1599,7 +1598,6 @@ __tuple_get = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self", "index")}; - signature["function_name"] = "__tuple_get"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var index = arguments['index']; @@ -1621,7 +1619,6 @@ __tuple___contains__ = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self", "value")}; - signature["function_name"] = "__tuple___contains__"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var value = arguments['value']; @@ -1653,7 +1650,6 @@ __list___init__ = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": {"js_object": undefined, "pointer": undefined}, "args": __create_array__("self", "js_object", "pointer")}; - signature["function_name"] = "__list___init__"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var js_object = arguments['js_object']; @@ -1738,13 +1734,12 @@ __list___getslice__ = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": {"step": undefined}, "args": __create_array__("self", "start", "stop", "step")}; - signature["function_name"] = "__list___getslice__"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var start = arguments['start']; var stop = arguments['stop']; var step = arguments['step']; - arr = self["$wrapped"].__getslice__( start,stop ); + arr = self["$wrapped"].__getslice__(start,stop); var __args_2, __kwargs_2; __args_2 = []; __kwargs_2 = {"pointer": arr}; @@ -1767,11 +1762,10 @@ __list_append = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self", "obj")}; - signature["function_name"] = "__list_append"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var obj = arguments['obj']; - self["$wrapped"].push( obj ); + self["$wrapped"].push(obj); } __list_append.NAME = "__list_append"; @@ -1789,7 +1783,6 @@ __list_extend = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self", "other")}; - signature["function_name"] = "__list_extend"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var other = arguments['other']; @@ -1818,12 +1811,11 @@ __list_insert = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self", "index", "obj")}; - signature["function_name"] = "__list_insert"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var index = arguments['index']; var obj = arguments['obj']; - self["$wrapped"].splice( index,0,obj ); + self["$wrapped"].splice(index,0,obj); } __list_insert.NAME = "__list_insert"; @@ -1842,12 +1834,11 @@ __list_remove = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self", "obj")}; - signature["function_name"] = "__list_remove"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var obj = arguments['obj']; index = __get__(__get__(self, "index"), "__call__")([obj], __NULL_OBJECT__); - self["$wrapped"].splice( index,1 ); + self["$wrapped"].splice(index,1); } __list_remove.NAME = "__list_remove"; @@ -1865,10 +1856,9 @@ __list_pop = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self")}; - signature["function_name"] = "__list_pop"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; - return self["$wrapped"].pop( ); + return self["$wrapped"].pop(); } __list_pop.NAME = "__list_pop"; @@ -1886,11 +1876,10 @@ __list_index = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self", "obj")}; - signature["function_name"] = "__list_index"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var obj = arguments['obj']; - return self["$wrapped"].indexOf( obj ); + return self["$wrapped"].indexOf(obj); } __list_index.NAME = "__list_index"; @@ -1909,7 +1898,6 @@ __list_count = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self", "obj")}; - signature["function_name"] = "__list_count"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var obj = arguments['obj']; @@ -1942,10 +1930,9 @@ __list_reverse = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self")}; - signature["function_name"] = "__list_reverse"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; - self["$wrapped"] = self["$wrapped"].reverse( ); + self["$wrapped"] = self["$wrapped"].reverse(); } __list_reverse.NAME = "__list_reverse"; @@ -1963,10 +1950,9 @@ __list_shift = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self")}; - signature["function_name"] = "__list_shift"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; - return self["$wrapped"].shift( ); + return self["$wrapped"].shift(); } __list_shift.NAME = "__list_shift"; @@ -1984,12 +1970,11 @@ __list_slice = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self", "start", "end")}; - signature["function_name"] = "__list_slice"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var start = arguments['start']; var end = arguments['end']; - return self["$wrapped"].slice( start,end ); + return self["$wrapped"].slice(start,end); } __list_slice.NAME = "__list_slice"; @@ -2007,7 +1992,6 @@ __list___iter__ = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self")}; - signature["function_name"] = "__list___iter__"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; return __get__(Iterator, "__call__")([self, 0], __NULL_OBJECT__); @@ -2029,7 +2013,6 @@ __list_get = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self", "index")}; - signature["function_name"] = "__list_get"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var index = arguments['index']; @@ -2051,7 +2034,6 @@ __list_set = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self", "index", "value")}; - signature["function_name"] = "__list_set"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var index = arguments['index']; @@ -2074,7 +2056,6 @@ __list___len__ = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self")}; - signature["function_name"] = "__list___len__"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; return self["$wrapped"].length; @@ -2095,7 +2076,6 @@ __list___contains__ = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self", "value")}; - signature["function_name"] = "__list___contains__"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var value = arguments['value']; @@ -2129,7 +2109,6 @@ __dict___init__ = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": {"js_object": undefined}, "args": __create_array__("self", "js_object")}; - signature["function_name"] = "__dict___init__"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var js_object = arguments['js_object']; @@ -2165,7 +2144,6 @@ __dict_get = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": {"_default": undefined}, "args": __create_array__("self", "key", "_default")}; - signature["function_name"] = "__dict_get"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var key = arguments['key']; @@ -2207,7 +2185,6 @@ __dict_set = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self", "key", "value")}; - signature["function_name"] = "__dict_set"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var key = arguments['key']; @@ -2252,7 +2229,6 @@ __dict___len__ = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self")}; - signature["function_name"] = "__dict___len__"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; __dict = self["$wrapped"]; @@ -2275,7 +2251,6 @@ __dict___getitem__ = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self", "key")}; - signature["function_name"] = "__dict___getitem__"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var key = arguments['key']; @@ -2309,7 +2284,6 @@ __dict___setitem__ = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self", "key", "value")}; - signature["function_name"] = "__dict___setitem__"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var key = arguments['key']; @@ -2354,10 +2328,9 @@ __dict_keys = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self")}; - signature["function_name"] = "__dict_keys"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; - arr = Object.keys( self["$wrapped"] ); + arr = Object.keys(self["$wrapped"]); var __args_3, __kwargs_3; __args_3 = []; __kwargs_3 = {"js_object": arr}; @@ -2381,7 +2354,6 @@ __dict_pop = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": {"d": undefined}, "args": __create_array__("self", "key", "d")}; - signature["function_name"] = "__dict_pop"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var key = arguments['key']; @@ -2412,7 +2384,6 @@ __dict_values = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self")}; - signature["function_name"] = "__dict_values"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; __dict = self["$wrapped"]; @@ -2442,11 +2413,10 @@ __dict___contains__ = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self", "value")}; - signature["function_name"] = "__dict___contains__"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var value = arguments['value']; - keys = Object.keys( self["$wrapped"] ); + keys = Object.keys(self["$wrapped"]); if (typeof(value) == "object") { key = "@" + value.uid; } else { @@ -2474,7 +2444,6 @@ __dict___iter__ = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self")}; - signature["function_name"] = "__dict___iter__"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; return __get__(Iterator, "__call__")([__get__(__get__(self, "keys"), "__call__")(), 0], __NULL_OBJECT__); @@ -2506,37 +2475,36 @@ __array___init__ = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": {"initializer": undefined, "little_endian": false}, "args": __create_array__("self", "typecode", "initializer", "little_endian")}; - signature["function_name"] = "__array___init__"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var typecode = arguments['typecode']; var initializer = arguments['initializer']; var little_endian = arguments['little_endian']; - self["typecode"] = typecode; - self["itemsize"] = __get__(__get__(self, "typecodes"), "__getitem__")([typecode], Object()); - self["little_endian"] = little_endian; + self.typecode = typecode; + self.itemsize = __get__(__get__(self, "typecodes"), "__getitem__")([typecode], Object()); + self.little_endian = little_endian; if (initializer) { - self["length"] = len([initializer], __NULL_OBJECT__); - self["bytes"] = self["length"] * self["itemsize"]; - if (self["typecode"] == "float8") { - self["_scale"] = max([__get__(list, "__call__")([], {"js_object": [abs([min([initializer], __NULL_OBJECT__)], __NULL_OBJECT__), max([initializer], __NULL_OBJECT__)]})], __NULL_OBJECT__); - self["_norm_get"] = self["_scale"] / 127; - self["_norm_set"] = 1.0 / self["_norm_get"]; + self.length = len([initializer], __NULL_OBJECT__); + self.bytes = self.length * self.itemsize; + if (self.typecode == "float8") { + self._scale = max([__get__(list, "__call__")([], {"js_object": [abs([min([initializer], __NULL_OBJECT__)], __NULL_OBJECT__), max([initializer], __NULL_OBJECT__)]})], __NULL_OBJECT__); + self._norm_get = self._scale / 127; + self._norm_set = 1.0 / self._norm_get; } else { - if (self["typecode"] == "float16") { - self["_scale"] = max([__get__(list, "__call__")([], {"js_object": [abs([min([initializer], __NULL_OBJECT__)], __NULL_OBJECT__), max([initializer], __NULL_OBJECT__)]})], __NULL_OBJECT__); - self["_norm_get"] = self["_scale"] / 32767; - self["_norm_set"] = 1.0 / self["_norm_get"]; + if (self.typecode == "float16") { + self._scale = max([__get__(list, "__call__")([], {"js_object": [abs([min([initializer], __NULL_OBJECT__)], __NULL_OBJECT__), max([initializer], __NULL_OBJECT__)]})], __NULL_OBJECT__); + self._norm_get = self._scale / 32767; + self._norm_set = 1.0 / self._norm_get; } } } else { - self["length"] = 0; - self["bytes"] = 0; + self.length = 0; + self.bytes = 0; } - size = self["bytes"]; + size = self.bytes; buff = new ArrayBuffer(size); - self["dataview"] = new DataView(buff); - self["buffer"] = buff; + self.dataview = new DataView(buff); + self.buffer = buff; __get__(__get__(self, "fromlist"), "__call__")([initializer], __NULL_OBJECT__); } @@ -2555,10 +2523,9 @@ __array___len__ = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self")}; - signature["function_name"] = "__array___len__"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; - return self["length"]; + return self.length; } __array___len__.NAME = "__array___len__"; @@ -2577,7 +2544,6 @@ __array___contains__ = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self", "value")}; - signature["function_name"] = "__array___contains__"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var value = arguments['value']; @@ -2605,22 +2571,21 @@ __array___getitem__ = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self", "index")}; - signature["function_name"] = "__array___getitem__"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var index = arguments['index']; - step = self["itemsize"]; + step = self.itemsize; offset = step * index; - dataview = self["dataview"]; - func_name = "get" + __get__(__get__(self, "typecode_names"), "__getitem__")([self["typecode"]], Object()); + dataview = self.dataview; + func_name = "get" + __get__(__get__(self, "typecode_names"), "__getitem__")([self.typecode], Object()); func = dataview[func_name].bind(dataview); - if (offset < self["bytes"]) { + if (offset < self.bytes) { value = func(offset); - if (self["typecode"] == "float8") { - value = value * self["_norm_get"]; + if (self.typecode == "float8") { + value = value * self._norm_get; } else { - if (self["typecode"] == "float16") { - value = value * self["_norm_get"]; + if (self.typecode == "float16") { + value = value * self._norm_get; } } return value; @@ -2645,25 +2610,24 @@ __array___setitem__ = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self", "index", "value")}; - signature["function_name"] = "__array___setitem__"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var index = arguments['index']; var value = arguments['value']; - step = self["itemsize"]; + step = self.itemsize; if (index < 0) { - index = self["length"] + index - 1; + index = self.length + index - 1; } offset = step * index; - dataview = self["dataview"]; - func_name = "set" + __get__(__get__(self, "typecode_names"), "__getitem__")([self["typecode"]], Object()); + dataview = self.dataview; + func_name = "set" + __get__(__get__(self, "typecode_names"), "__getitem__")([self.typecode], Object()); func = dataview[func_name].bind(dataview); - if (offset < self["bytes"]) { - if (self["typecode"] == "float8") { - value = value * self["_norm_set"]; + if (offset < self.bytes) { + if (self.typecode == "float8") { + value = value * self._norm_set; } else { - if (self["typecode"] == "float16") { - value = value * self["_norm_set"]; + if (self.typecode == "float16") { + value = value * self._norm_set; } } func(offset, value); @@ -2687,7 +2651,6 @@ __array___iter__ = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self")}; - signature["function_name"] = "__array___iter__"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; return __get__(Iterator, "__call__")([self, 0], __NULL_OBJECT__); @@ -2709,7 +2672,6 @@ __array_get = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self", "index")}; - signature["function_name"] = "__array_get"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var index = arguments['index']; @@ -2732,27 +2694,26 @@ __array_fromlist = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self", "lst")}; - signature["function_name"] = "__array_fromlist"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var lst = arguments['lst']; length = len([lst], __NULL_OBJECT__); - step = self["itemsize"]; - typecode = self["typecode"]; + step = self.itemsize; + typecode = self.typecode; size = length * step; - dataview = self["dataview"]; + dataview = self.dataview; func_name = "set" + __get__(__get__(self, "typecode_names"), "__getitem__")([typecode], Object()); func = dataview[func_name].bind(dataview); - if (size <= self["bytes"]) { + if (size <= self.bytes) { i = 0; offset = 0; while(i < length) { item = __get__(lst, "__getitem__")([i], Object()); if (typecode == "float8") { - item *= self["_norm_set"] + item *= self._norm_set } else { if (typecode == "float16") { - item *= self["_norm_set"] + item *= self._norm_set } } func(offset,item); @@ -2780,20 +2741,19 @@ __array_resize = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self", "length")}; - signature["function_name"] = "__array_resize"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var length = arguments['length']; - buff = self["buffer"]; + buff = self.buffer; source = new Uint8Array(buff); - new_size = length * self["itemsize"]; + new_size = length * self.itemsize; new_buff = new ArrayBuffer(new_size); target = new Uint8Array(new_buff); target.set(source); - self["length"] = length; - self["bytes"] = new_size; - self["buffer"] = new_buff; - self["dataview"] = new DataView(new_buff); + self.length = length; + self.bytes = new_size; + self.buffer = new_buff; + self.dataview = new DataView(new_buff); } __array_resize.NAME = "__array_resize"; @@ -2812,12 +2772,11 @@ __array_append = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self", "value")}; - signature["function_name"] = "__array_append"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var value = arguments['value']; - length = self["length"]; - __get__(__get__(self, "resize"), "__call__")([self["length"] + 1], __NULL_OBJECT__); + length = self.length; + __get__(__get__(self, "resize"), "__call__")([self.length + 1], __NULL_OBJECT__); __get__(__get__(self, "__setitem__"), "__call__")([length, value], Object()); } @@ -2836,7 +2795,6 @@ __array_extend = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self", "lst")}; - signature["function_name"] = "__array_extend"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var lst = arguments['lst']; @@ -2866,12 +2824,11 @@ __array_to_array = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self")}; - signature["function_name"] = "__array_to_array"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; arr = []; i = 0; - while(i < self["length"]) { + while(i < self.length) { item = __array___getitem__([self, i], Object()); arr.push( item ); i += 1 @@ -2894,7 +2851,6 @@ __array_to_list = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self")}; - signature["function_name"] = "__array_to_list"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var __args_4, __kwargs_4; @@ -2920,7 +2876,6 @@ __array_to_ascii = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("self")}; - signature["function_name"] = "__array_to_ascii"; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; string = ""; @@ -2943,7 +2898,7 @@ __array_to_ascii.types_signature = { }; __array_to_ascii.pythonscript_function = true; __array_attrs["to_ascii"] = __array_to_ascii; array = create_class("array", __array_parents, __array_attrs, __array_properties); -json = { "loads":(function (s) {return JSON.parse( s )}),"dumps":(function (o) {return JSON.stringify( o )}) }; +json = { "loads":(function (s) {return JSON.parse(s)}),"dumps":(function (o) {return JSON.stringify(o)}) }; _to_pythonjs = function(args, kwargs) { var set, keys, raw, jstype, output, append; if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { @@ -2954,7 +2909,6 @@ _to_pythonjs = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("json")}; - signature["function_name"] = "_to_pythonjs"; arguments = get_arguments(signature, args, kwargs); var json = arguments['json']; var jstype, item, output; @@ -3015,7 +2969,6 @@ json_to_pythonjs = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("json")}; - signature["function_name"] = "json_to_pythonjs"; arguments = get_arguments(signature, args, kwargs); var json = arguments['json']; return _to_pythonjs([__get__(__get__(JSON, "parse"), "__call__")([json], __NULL_OBJECT__)], __NULL_OBJECT__); @@ -3036,7 +2989,6 @@ _to_json = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("pythonjs")}; - signature["function_name"] = "_to_json"; arguments = get_arguments(signature, args, kwargs); var pythonjs = arguments['pythonjs']; if (isinstance([pythonjs, list], __NULL_OBJECT__)) { @@ -3084,7 +3036,6 @@ pythonjs_to_json = function(args, kwargs) { } var signature, arguments; signature = {"kwargs": Object(), "args": __create_array__("pythonjs")}; - signature["function_name"] = "pythonjs_to_json"; arguments = get_arguments(signature, args, kwargs); var pythonjs = arguments['pythonjs']; return __get__(__get__(JSON, "stringify"), "__call__")([_to_json([pythonjs], __NULL_OBJECT__)], __NULL_OBJECT__); diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index b82ef36..f15f9d6 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -3,7 +3,7 @@ # by Amirouche Boubekki and Brett Hartshorn - copyright 2013 # License: "New BSD" -import os, sys, pickle +import os, sys, pickle, copy from types import GeneratorType import ast @@ -79,7 +79,8 @@ def _write(self, code): if not code.startswith('print '): if not code.startswith('var('): if not code == 'pass': - code = """JS('''%s''')"""%code + if not code.startswith('JS('): + code = """JS('''%s''')"""%code s = '%s%s\n' % (indentation, code) #self.output.write(s.encode('utf-8')) self.output.write(s) @@ -199,6 +200,9 @@ def __init__(self, module=None, module_path=None): self._js_classes = dict() self._in_js_class = False + self._cache_for_body_calls = False + self._cache_while_body_calls = False + self._custom_operators = {} self._injector = [] ## advanced meta-programming hacks self._in_class = None @@ -232,8 +236,9 @@ def setup_builtins(self): self._classes['tuple'] = set(['__getitem__', '__setitem__']) self._builtin_classes = set(['dict', 'list', 'tuple']) self._builtin_functions = { - 'ord':'char.charCodeAt(0)', + 'ord':'%s.charCodeAt(0)', 'chr':'String.fromCharCode(%s)', + 'abs':'Math.abs(%s)' } def is_known_class_name(self, name): @@ -356,7 +361,7 @@ def visit_Dict(self, node): def visit_Tuple(self, node): node.returns_type = 'tuple' a = '[%s]' % ', '.join(map(self.visit, node.elts)) - return '__get__(tuple, "__call__")([], JSObject(js_object=%s))' %a + return '__get__(tuple, "__call__")([], {js_object:%s})' %a def visit_List(self, node): node.returns_type = 'list' @@ -455,14 +460,22 @@ def _visit_js_classdef(self, node): writer.push() for b in init.body: line = self.visit(b) - if line: - writer.write( line ) - for method in methods.values(): - line = self.visit(method) - if line: - writer.write( line ) + if line: writer.write( line ) + + #for mname in methods: + # method = methods[mname] + # line = self.visit(method) + # if line: writer.write( line ) + # writer.write('this.%s = %s'%(mname,mname)) writer.pull() + + for mname in methods: + method = methods[mname] + line = self.visit(method) + if line: writer.write( line ) + writer.write('%s.prototype.%s = %s'%(name,mname,mname)) + self._in_js_class = False def visit_ClassDef(self, node): @@ -1082,29 +1095,101 @@ def visit_Str(self, node): return '"""%s"""' %s def visit_Expr(self, node): - writer.write(self.visit(node.value)) + line = self.visit(node.value) + if line: + writer.write(line) + + def inline_function(self, node): + name = self.visit(node.func) + log('--------------------------starting inline: %s---------------'%name) + writer.write('################################inlined->%s'%name) + fnode = self._global_functions[ name ] + fnode = copy.deepcopy( fnode ) + log('inspecting:%s' %fnode) + finfo = inspect_function( fnode ) + remap = {} + for n in finfo['name_nodes']: + if n.id not in finfo['locals']: continue + + if isinstance(n.id, Name): + log(n.id.id) + raise RuntimeError + + if n.id not in remap: + new_name = n.id + '_%s'%self._inline_ids + remap[ n.id ] = new_name + self._inline_ids += 1 + + n.id = remap[ n.id ] + + if remap: + writer.write( "JS('var %s')" %','.join(remap.values()) ) + for n in remap: + if n in finfo['typedefs']: + self._func_typedefs[ remap[n] ] = finfo['typedefs'][n] + + for i,a in enumerate(node.args): + b = self.visit( fnode.args.args[i] ) + b = remap[ b ] + writer.write( "%s = %s" %(b, self.visit(a)) ) + + self._inline.append( name ) + + writer.write("JS('var __returns__%s = null')"%name) + writer.write('while True:') + writer.push() + for b in fnode.body: + self.visit(b) + if len( finfo['return_nodes'] ) == 0: + writer.write('break') + writer.pull() + + if self._inline.pop() != name: + raise RuntimeError + + for n in remap: + gname = remap[n] + for n in finfo['name_nodes']: + if n.id == gname: + n.id = n + log('###########inlined %s###########'%name) + return '__returns__%s' %name def visit_Call(self, node): - if isinstance(node.func, ast.Attribute) and isinstance(node.func.value, Name) and node.func.value.id == 'pythonjs' and node.func.attr == 'enable': + if isinstance(node.func, ast.Attribute) and isinstance(node.func.value, Name) and node.func.value.id == 'pythonjs' and node.func.attr == 'configure': for kw in node.keywords: if kw.arg == 'javascript': if kw.value.id == 'True': self._with_js = True + writer.with_javascript = True elif kw.value.id == 'False': self._with_js = False + writer.with_javascript = False + else: + raise SyntaxError elif kw.arg == 'inline': if kw.value.id == 'True': self._with_inline = True elif kw.value.id == 'False': self._with_inline = False + else: + raise SyntaxError else: raise SyntaxError elif self._with_js: + name = self.visit(node.func) args = list( map(self.visit, node.args) ) - if isinstance(node.func, Name) and node.func.id == 'new': + + if name in self._builtin_functions and self._builtin_functions[name]: ## inlined js + if args: + return self._builtin_functions[name] % ','.join(args) + else: + return self._builtin_functions[name] + + elif isinstance(node.func, Name) and node.func.id == 'new': assert len(args) == 1 return ' new %s' %args[0] @@ -1115,6 +1200,10 @@ def visit_Call(self, node): elif isinstance(node.func, Name) and node.func.id in self._js_classes: a = ','.join(args) return ' new %s(%s)' %( self.visit(node.func), a ) + + elif name in self._global_functions and self._with_inline: + return self.inline_function( node ) + else: a = ','.join(args) return '%s(%s)' %( self.visit(node.func), a ) @@ -1204,12 +1293,6 @@ def visit_Call(self, node): else: raise RuntimeError - elif name in self._builtin_functions and self._builtin_functions[name]: ## inlined js - if args: - return self._builtin_functions[name] % args - else: - return self._builtin_functions[name] - elif hasattr(node,'constant') or name in self._builtin_functions: if args and kwargs: return '%s([%s], {%s})' %(args, kwargs) @@ -1220,51 +1303,8 @@ def visit_Call(self, node): else: return '%s()' %name - elif name in self._global_functions: - writer.write('##inlined->%s'%name) - fnode = self._global_functions[ name ] - finfo = inspect_function( fnode ) - remap = {} - for n in finfo['name_nodes']: - if n.id not in finfo['locals']: continue - if n.id not in remap: - new_name = n.id + '_%s'%self._inline_ids - remap[ n.id ] = new_name - self._inline_ids += 1 - n.id = remap[ n.id ] - - if remap: - writer.write( "JS('var %s')" %','.join(remap.values()) ) - for n in remap: - if n in finfo['typedefs']: - self._func_typedefs[ remap[n] ] = finfo['typedefs'][n] - - for i,a in enumerate(node.args): - b = self.visit( fnode.args.args[i] ) - b = remap[ b ] - writer.write( "%s = %s" %(b, self.visit(a)) ) - - self._inline.append( name ) - - writer.write("JS('var __returns__%s = null')"%name) - writer.write('while True:') - writer.push() - for b in fnode.body: - self.visit(b) - if len( finfo['return_nodes'] ) == 0: - writer.write('break') - writer.pull() - - if self._inline.pop() != name: - raise RuntimeError - - for n in remap: - gname = remap[n] - for n in finfo['name_nodes']: - if n.id == gname: - n.id = n - - return '__returns__%s' %name + elif name in self._global_functions and self._with_inline: + return self.inline_function( node ) elif call_has_args_only: if name in self._global_functions: @@ -1284,7 +1324,7 @@ def visit_Call(self, node): return '__get__(%s, "__call__")(%s, JSObject(js_object=%s))' % (name, args_name, kwargs_name) elif name in ('list', 'tuple'): if len(node.args): - return '__get__(%s, "__call__")([], JSObject(js_object=%s))' % (name, args_name) + return '__get__(%s, "__call__")([], {js_object:%s})' % (name, args_name) else: return '__get__(%s, "__call__")([], %s)' % (name, kwargs_name) else: @@ -1543,7 +1583,6 @@ def visit_FunctionDef(self, node): writer.pull() if self._in_js_class: - writer.write('this.%s = %s' %(node.name, node.name)) return ## note, in javascript function.name is a non-standard readonly attribute, @@ -1612,12 +1651,12 @@ def visit_Break(self, node): def visit_For(self, node): log('for loop:') - for n in node.body: - calls = collect_calls(n) - for c in calls: - log('--call: %s' %c) - log('------: %s' %c.func) - if self._inline and False: + if self._cache_for_body_calls: ## TODO add option for this + for n in node.body: + calls = collect_calls(n) + for c in calls: + log('--call: %s' %c) + log('------: %s' %c.func) if isinstance(c.func, ast.Name): ## these are constant for sure i = self._call_ids writer.write( '''JS('var __call__%s = __get__(%s,"__call__")')''' %(i,self.visit(c.func)) ) @@ -1712,18 +1751,18 @@ def visit_For(self, node): _call_ids = 0 def visit_While(self, node): log('while loop:') - for n in node.body: - continue - calls = collect_calls(n) - for c in calls: - log('--call: %s' %c) - log('------: %s' %c.func) - if isinstance(c.func, ast.Name): ## these are constant for sure - i = self._call_ids - writer.write( '__call__%s = __get__(%s,"__call__")' %(i,self.visit(c.func)) ) - c.func.id = '__call__%s'%i - c.constant = True - self._call_ids += 1 + if self._cache_while_body_calls: ## TODO add option for this + for n in node.body: + calls = collect_calls(n) + for c in calls: + log('--call: %s' %c) + log('------: %s' %c.func) + if isinstance(c.func, ast.Name): ## these are constant for sure + i = self._call_ids + writer.write( '__call__%s = __get__(%s,"__call__")' %(i,self.visit(c.func)) ) + c.func.id = '__call__%s'%i + c.constant = True + self._call_ids += 1 writer.write('while %s:' % self.visit(node.test)) @@ -1757,6 +1796,11 @@ def visit_With(self, node): map(self.visit, node.body) self._with_static_type = False + elif isinstance( node.context_expr, Name ) and node.context_expr.id == 'inline': + self._with_inline = True + map(self.visit, node.body) + self._with_inline = False + elif isinstance( node.context_expr, Name ) and node.optional_vars and isinstance(node.optional_vars, Name) and node.optional_vars.id == 'jsobject': #instance_name = node.context_expr.id #for n in node.body: diff --git a/pythonjs/pythonjs.py b/pythonjs/pythonjs.py index b191560..0746d1d 100755 --- a/pythonjs/pythonjs.py +++ b/pythonjs/pythonjs.py @@ -208,7 +208,9 @@ def visit_Call(self, node): return '[]' elif name == 'JS': - return node.args[0].s.replace('\n', '\\n') + s = node.args[0].s.replace('\n', '\\n') + if s.strip().startswith('#'): s = '/*%s*/'%s + return s else: if node.args: diff --git a/runtime/builtins.py b/runtime/builtins.py index 7c2ee9c..8febdef 100644 --- a/runtime/builtins.py +++ b/runtime/builtins.py @@ -351,6 +351,10 @@ def func(start, stop, step): stop = this.length + stop return this.slice(start, stop) + @Array.prototype.append + def func(item): + this.push( item ) + _setup_array_prototype() @@ -403,11 +407,9 @@ def max( lst ): def abs( num ): return JS('Math.abs(num)') -@fastdef def ord( char ): return JS('char.charCodeAt(0)') -@fastdef def chr( num ): return JS('String.fromCharCode(num)') diff --git a/tests/test_function_inline.html b/tests/test_function_inline.html new file mode 100644 index 0000000..c5ee8af --- /dev/null +++ b/tests/test_function_inline.html @@ -0,0 +1,40 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/tests/test_typedef_args.html b/tests/test_typedef_args.html new file mode 100644 index 0000000..3f5a2d4 --- /dev/null +++ b/tests/test_typedef_args.html @@ -0,0 +1,28 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/tests/test_while_fast_calls.html b/tests/test_while_fast_calls.html new file mode 100644 index 0000000..5498dde --- /dev/null +++ b/tests/test_while_fast_calls.html @@ -0,0 +1,32 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/tests/test_with_javascript_class.html b/tests/test_with_javascript_class.html new file mode 100644 index 0000000..1fc9bd4 --- /dev/null +++ b/tests/test_with_javascript_class.html @@ -0,0 +1,31 @@ + + + + + + + + + + + \ No newline at end of file From 3f35212fb6915a84591446580a77732867eaec9f Mon Sep 17 00:00:00 2001 From: hartsantler Date: Mon, 25 Nov 2013 00:05:11 -0800 Subject: [PATCH 004/521] added @inline function decorator, and pystone ultra/fast tests. --- pythonjs/python_to_pythonjs.py | 27 +++- pythonjs/pythonjs.py | 9 +- tests/pystone_fast.html | 237 ++++++++++++++++++++++++++++++++ tests/pystone_fastdef.html | 1 + tests/pystone_ultra_fast.html | 238 +++++++++++++++++++++++++++++++++ 5 files changed, 505 insertions(+), 7 deletions(-) create mode 100644 tests/pystone_fast.html create mode 100644 tests/pystone_ultra_fast.html diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index f15f9d6..ea611fc 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -699,7 +699,10 @@ def visit_BinOp(self, node): elts = [ self.visit(e) for e in node.left.elts ] expanded = [] for i in range( node.right.n ): expanded.extend( elts ) - return '__get__(list, "__call__")( [], {pointer:[%s]} )' %','.join(expanded) + if self._with_js: + return '[%s]' %','.join(expanded) + else: + return '__get__(list, "__call__")( [], {pointer:[%s]} )' %','.join(expanded) elif isinstance(node.left, Name): typedef = self.get_typedef( node.left ) @@ -877,9 +880,10 @@ def visit_Subscript(self, node): return '%s["$wrapped"]' %name elif self._with_js: - if isinstance(node.slice, ast.Slice): - raise SyntaxError - return '%s[ %s ]' %(name, self.visit(node.slice)) + if isinstance(node.slice, ast.Slice): ## allow slice on Array + return '%s.__getslice__(%s)'%(name, self.visit(node.slice)) + else: + return '%s[ %s ]' %(name, self.visit(node.slice)) elif isinstance(node.slice, ast.Slice): return '__get__(%s, "__getslice__")([%s], JSObject())' % ( @@ -906,7 +910,10 @@ def visit_Subscript(self, node): ) def visit_Slice(self, node): - lower = upper = step = None + if self._with_js: + lower = upper = step = 'undefined' + else: + lower = upper = step = None if node.lower: lower = self.visit(node.lower) if node.upper: @@ -1368,6 +1375,7 @@ def visit_FunctionDef(self, node): return_type = None fastdef = False javascript = False + inline = False self._cached_property = None self._func_typedefs = {} @@ -1376,7 +1384,11 @@ def visit_FunctionDef(self, node): for decorator in reversed(node.decorator_list): log('@decorator: %s' %decorator) - if self._with_js: ## decorators are special in with-js mode + if isinstance(decorator, Name) and decorator.id == 'inline': + inline = True + self._with_inline = True + + elif self._with_js: ## decorators are special in with-js mode with_js_decorators.append( self.visit( decorator ) ) elif isinstance(decorator, Name) and decorator.id == 'fastdef': @@ -1582,6 +1594,9 @@ def visit_FunctionDef(self, node): writer.pull() + if inline: + self._with_inline = False + if self._in_js_class: return diff --git a/pythonjs/pythonjs.py b/pythonjs/pythonjs.py index 0746d1d..3614c21 100755 --- a/pythonjs/pythonjs.py +++ b/pythonjs/pythonjs.py @@ -208,8 +208,15 @@ def visit_Call(self, node): return '[]' elif name == 'JS': - s = node.args[0].s.replace('\n', '\\n') + s = node.args[0].s.replace('\n', '\\n').replace('\0', '\\0') if s.strip().startswith('#'): s = '/*%s*/'%s + if '"' in s or "'" in s: ## can not trust direct-replace hacks + pass + else: + if ' or ' in s: + s = s.replace(' or ', ' || ') + if ' not ' in s: + s = s.replace(' not ', ' ! ') return s else: diff --git a/tests/pystone_fast.html b/tests/pystone_fast.html new file mode 100644 index 0000000..f1f9df1 --- /dev/null +++ b/tests/pystone_fast.html @@ -0,0 +1,237 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/tests/pystone_fastdef.html b/tests/pystone_fastdef.html index c46a9c1..e6df311 100644 --- a/tests/pystone_fastdef.html +++ b/tests/pystone_fastdef.html @@ -190,6 +190,7 @@ IntParOut = IntParI2 + IntLoc return IntParOut +@typedef( Array1Par=list, Array2Par=list ) @fastdef def Proc8(Array1Par, Array2Par, IntParI1, IntParI2): global IntGlob diff --git a/tests/pystone_ultra_fast.html b/tests/pystone_ultra_fast.html new file mode 100644 index 0000000..00381ac --- /dev/null +++ b/tests/pystone_ultra_fast.html @@ -0,0 +1,238 @@ + + + + + + + + + + + \ No newline at end of file From 0bc0766e4d08a74112eba85a1f0874312812dab4 Mon Sep 17 00:00:00 2001 From: hartsantler Date: Mon, 25 Nov 2013 20:10:58 -0800 Subject: [PATCH 005/521] added Richards benchmark test, fixed if expression bug, updated README --- README.rst | 6 +- pythonjs/python_to_pythonjs.py | 35 ++- pythonjs/pythonjs.py | 4 +- tests/pystone_fastdef.html | 2 +- tests/richards.html | 433 +++++++++++++++++++++++++++++++++ tests/test_subclass_init.html | 32 +++ 6 files changed, 502 insertions(+), 10 deletions(-) create mode 100644 tests/richards.html create mode 100644 tests/test_subclass_init.html diff --git a/README.rst b/README.rst index fe68f27..3cf3240 100644 --- a/README.rst +++ b/README.rst @@ -7,7 +7,11 @@ PythonJS 0.8.6 Introduction ====== -PythonJS is a Python to Javascript translator written in Python, created by Amirouche Boubekki and Brett Hartshorn. It converts a subset of Python into a subset of Javascript. It features: list comprehensions, classes, multiple inheritance, first-class functions, operator overloading, function and class decorators, HTML DOM, and easily integrates with JavaScript and external JavaScript libraries. The generated code works in the Browser and in NodeJS. +PythonJS is a Python to Javascript translator written in Python, created by Amirouche Boubekki and Brett Hartshorn, currently maintained and developed by Brett. It features: list comprehensions, classes, multiple inheritance, operator overloading, function and class decorators, HTML DOM, and easily integrates with JavaScript and external JavaScript libraries. The generated code works in the Browser and in NodeJS. + +Speed +--------------- +PythonJS allows you to select which features you need for each section of your code, where you need performance you can disable multiple inheritance, operator overloading, and other slow operations. Features can be switched off and on for blocks of code using `pythonjs.configure()` or the special `with` statements and decorators described below. NodeJS --------------- diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index ea611fc..98a2586 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -189,6 +189,7 @@ def __init__(self, module=None, module_path=None): self._typedefs = dict() ## class name : typedef (not pickled) self._globals = dict() + self._global_nodes = dict() self._with_static_type = None self._global_typed_lists = dict() ## global name : set (if len(set)==1 then we know it is a typed list) self._global_typed_dicts = dict() @@ -428,6 +429,9 @@ def visit_AugAssign(self, node): func = typedef.operators[ op ] a = '%s( [%s, %s] )' %(func, target, self.visit(node.value)) writer.write( a ) + elif op == '//=': + a = '%s = Math.floor(%s/%s)' %(target, target, self.visit(node.value)) + writer.write(a) else: ## TODO extra checks to make sure the operator type is valid in this context a = '%s %s %s' %(target, op, self.visit(node.value)) @@ -520,9 +524,10 @@ def visit_ClassDef(self, node): writer.write('__%s_properties = JSObject()' % name) for base in node.bases: - code = '__%s_parents.push(%s)' % (name, self.visit(base)) - writer.write(code) - self._class_parents[ name ].add( self.visit(base) ) + base = self.visit(base) + if base == 'object': continue + writer.write('__%s_parents.push(%s)' % (name, base)) + self._class_parents[ name ].add( base ) for item in node.body: if isinstance(item, FunctionDef): @@ -695,15 +700,28 @@ def visit_BinOp(self, node): elif op == '%' and isinstance(node.left, ast.Str): return '__sprintf( %s, %s[...] )' %(left, right) ## assumes that right is a tuple, or list. - elif op == '*' and isinstance(node.left, ast.List) and isinstance(node.right,ast.Num): + elif op == '*' and isinstance(node.left, ast.List): + if isinstance(node.right,ast.Num): + n = node.right.n + elif isinstance(node.right, Name): + if node.right.id in self._global_nodes: + n = self._global_nodes[ node.right.id ].n + else: + raise SyntaxError + else: + raise SyntaxError + elts = [ self.visit(e) for e in node.left.elts ] expanded = [] - for i in range( node.right.n ): expanded.extend( elts ) + for i in range( n ): expanded.extend( elts ) if self._with_js: return '[%s]' %','.join(expanded) else: return '__get__(list, "__call__")( [], {pointer:[%s]} )' %','.join(expanded) + elif op == '//': + return 'Math.floor(%s/%s)' %(left, right) + elif isinstance(node.left, Name): typedef = self.get_typedef( node.left ) if typedef and op in typedef.operators: @@ -732,6 +750,8 @@ def visit_Add(self, node): def visit_Sub(self, node): return '-' + def visit_FloorDiv(self, node): + return '//' def visit_Div(self, node): return '/' def visit_Mod(self, node): @@ -1011,6 +1031,7 @@ def visit_Assign(self, node): if writer.is_at_global_level(): log('GLOBAL: %s : %s'%(target.id, node_value)) self._globals[ target.id ] = None + self._global_nodes[ target.id ] = node.value if isinstance(node.value, Call) and hasattr(node.value.func, 'id') and node.value.func.id in self._classes: self._instances[ target.id ] = node.value.func.id ## keep track of instances @@ -1681,7 +1702,7 @@ def visit_For(self, node): if self._with_js: - if isinstance(node.iter, ast.Call) and isinstance(node.iter.func, Name) and node.iter.func.id == 'range': + if isinstance(node.iter, ast.Call) and isinstance(node.iter.func, Name) and node.iter.func.id in ('range','xrange'): iter_start = '0' if len(node.iter.args) == 2: iter_start = self.visit(node.iter.args[0]) @@ -1716,7 +1737,7 @@ def visit_For(self, node): is_range = False iter_start = '0' iter_end = None - if self.FAST_FOR and isinstance(node.iter, ast.Call) and isinstance(node.iter.func, Name) and node.iter.func.id == 'range': + if self.FAST_FOR and isinstance(node.iter, ast.Call) and isinstance(node.iter.func, Name) and node.iter.func.id in ('range','xrange'): is_range = True if len(node.iter.args) == 2: iter_start = self.visit(node.iter.args[0]) diff --git a/pythonjs/pythonjs.py b/pythonjs/pythonjs.py index 3614c21..9bc5c87 100755 --- a/pythonjs/pythonjs.py +++ b/pythonjs/pythonjs.py @@ -328,7 +328,9 @@ def visit_Is(self, node): return '===' def visit_Compare(self, node): - comp = [ self.visit(node.left) ] + comp = [ '('] + comp.append( self.visit(node.left) ) + comp.append( ')' ) for i in range( len(node.ops) ): comp.append( self.visit(node.ops[i]) ) comp.append( self.visit(node.comparators[i]) ) diff --git a/tests/pystone_fastdef.html b/tests/pystone_fastdef.html index e6df311..d7bc228 100644 --- a/tests/pystone_fastdef.html +++ b/tests/pystone_fastdef.html @@ -238,7 +238,7 @@ if EnumLoc == Ident3: return TRUE return FALSE - +@inline def test(): main( LOOPS ) diff --git a/tests/richards.html b/tests/richards.html new file mode 100644 index 0000000..afef394 --- /dev/null +++ b/tests/richards.html @@ -0,0 +1,433 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/tests/test_subclass_init.html b/tests/test_subclass_init.html new file mode 100644 index 0000000..f3f787b --- /dev/null +++ b/tests/test_subclass_init.html @@ -0,0 +1,32 @@ + + + + + + + + + + + \ No newline at end of file From f3cd4d9929e3c121c65f4d57fa79c19569395c4e Mon Sep 17 00:00:00 2001 From: hartsantler Date: Mon, 25 Nov 2013 21:18:45 -0800 Subject: [PATCH 006/521] allow subclasses and multiple inheritance in `with javascript` mode. --- pythonjs/python_to_pythonjs.py | 37 ++++++++++++++------- tests/test_subclass_javascript.html | 51 +++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 11 deletions(-) create mode 100644 tests/test_subclass_javascript.html diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index 98a2586..9d0771d 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -457,20 +457,21 @@ def _visit_js_classdef(self, node): if n.id == 'self': n.id = 'this' - init = methods.pop('__init__') - args = [self.visit(arg) for arg in init.args.args] + #init = methods.pop('__init__') + init = methods.get( '__init__', None) + if init: + args = [self.visit(arg) for arg in init.args.args] + else: + args = [] writer.write('def %s(%s):' %(name,','.join(args))) writer.push() - for b in init.body: - line = self.visit(b) - if line: writer.write( line ) - - #for mname in methods: - # method = methods[mname] - # line = self.visit(method) - # if line: writer.write( line ) - # writer.write('this.%s = %s'%(mname,mname)) + if init: + for b in init.body: + line = self.visit(b) + if line: writer.write( line ) + else: + writer.write('pass') writer.pull() @@ -479,6 +480,20 @@ def _visit_js_classdef(self, node): line = self.visit(method) if line: writer.write( line ) writer.write('%s.prototype.%s = %s'%(name,mname,mname)) + f = 'function () { return %s.prototype.%s.apply(arguments[0], Array.prototype.slice.call(arguments,1)) }' %(name, mname) + writer.write('%s.%s = %s'%(name,mname,f)) + + for base in node.bases: + base = self.visit(base) + if base == 'object': continue + a = [ + 'for (var n in %s.prototype) {'%base, + ' if (!(n in %s.prototype)) {'%name, + ' %s.prototype[n] = %s.prototype[n]'%(name,base), + ' }', + '}' + ] + writer.write( ''.join(a) ) self._in_js_class = False diff --git a/tests/test_subclass_javascript.html b/tests/test_subclass_javascript.html new file mode 100644 index 0000000..db69947 --- /dev/null +++ b/tests/test_subclass_javascript.html @@ -0,0 +1,51 @@ + + + + + + + + + + + \ No newline at end of file From 875486057d06bd2e689a115fc38db6ecf245d496 Mon Sep 17 00:00:00 2001 From: hartsantler Date: Mon, 25 Nov 2013 22:17:22 -0800 Subject: [PATCH 007/521] optimized core --- README.rst | 2 +- pythonjs/python_to_pythonjs.py | 5 +- pythonjs/pythonjs.py | 2 + tests/richards_fast.html | 435 +++++++++++++++++++++++++++++++++ 4 files changed, 442 insertions(+), 2 deletions(-) create mode 100644 tests/richards_fast.html diff --git a/README.rst b/README.rst index 3cf3240..63b2c00 100644 --- a/README.rst +++ b/README.rst @@ -11,7 +11,7 @@ PythonJS is a Python to Javascript translator written in Python, created by Amir Speed --------------- -PythonJS allows you to select which features you need for each section of your code, where you need performance you can disable multiple inheritance, operator overloading, and other slow operations. Features can be switched off and on for blocks of code using `pythonjs.configure()` or the special `with` statements and decorators described below. +PythonJS allows you to select which features you need for each section of your code, where you need performance you can disable operator overloading, and other slow operations. Features can be switched off and on for blocks of code using `pythonjs.configure()` or the special `with` statements and decorators described below. When PythonJS is run in fast mode (javascript with inline functions) it beats PyPy in both the Richards and Pystone benchmarks. NodeJS --------------- diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index 9d0771d..60f58d1 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -641,7 +641,10 @@ def visit_TryExcept(self, node): map(self.visit, node.handlers) def visit_Raise(self, node): - writer.write('raise %s' % self.visit(node.type)) + if self._with_js: + writer.write('throw Error') + else: + writer.write('raise %s' % self.visit(node.type)) def visit_ExceptHandler(self, node): if node.type and node.name: diff --git a/pythonjs/pythonjs.py b/pythonjs/pythonjs.py index 40c1806..802e91d 100755 --- a/pythonjs/pythonjs.py +++ b/pythonjs/pythonjs.py @@ -217,6 +217,8 @@ def visit_Call(self, node): s = s.replace(' or ', ' || ') if ' not ' in s: s = s.replace(' not ', ' ! ') + if ' and ' in s: + s = s.replace(' and ', ' && ') return s else: diff --git a/tests/richards_fast.html b/tests/richards_fast.html new file mode 100644 index 0000000..8fc0d82 --- /dev/null +++ b/tests/richards_fast.html @@ -0,0 +1,435 @@ + + + + + + + + + + + \ No newline at end of file From 84bb4dc17c18802e74b132bb6190f227e3729ee4 Mon Sep 17 00:00:00 2001 From: hartsantler Date: Tue, 26 Nov 2013 02:12:50 -0800 Subject: [PATCH 008/521] added for loop enumerate --- pythonjs.js | 393 +++++++++++++++++++-------------- pythonjs/python_to_pythonjs.py | 134 ++++++----- pythonjs/pythonjs.py | 6 + runtime/builtins.py | 17 ++ tests/test_for_loop.html | 9 + 5 files changed, 331 insertions(+), 228 deletions(-) diff --git a/pythonjs.js b/pythonjs.js index 8571408..2acdddd 100644 --- a/pythonjs.js +++ b/pythonjs.js @@ -1,6 +1,6 @@ -// PythonScript Runtime - regenerated on: Sun Nov 24 19:32:45 2013 +// PythonScript Runtime - regenerated on: Tue Nov 26 02:12:03 2013 __NULL_OBJECT__ = Object.create(null); -if ("window" in this && "document" in this) { +if (( "window" ) in this && ( "document" ) in this) { __NODEJS__ = false; pythonjs = { }; } else { @@ -13,7 +13,7 @@ jsrange = function(num) { var i, r; i = 0; r = []; - while(i < num) { + while(( i ) < num) { r.push(i); i = i + 1; } @@ -46,7 +46,7 @@ adapt_arguments = function(handler) { __get__ = function(object, attribute) { "Retrieve an attribute, method, property, or wrapper function.\n\n method are actually functions which are converted to methods by\n prepending their arguments with the current object. Properties are\n not functions!\n\n DOM support:\n http://stackoverflow.com/questions/14202699/document-createelement-not-working\n https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof\n\n Direct JavaScript Calls:\n if an external javascript function is found, and it was not a wrapper that was generated here,\n check the function for a 'cached_wrapper' attribute, if none is found then generate a new\n wrapper, cache it on the function, and return the wrapper.\n "; - if (attribute == "__call__") { + if (( attribute ) == "__call__") { if (object.pythonscript_function || object.is_wrapper) { return object; } else { @@ -70,7 +70,7 @@ __get__ = function(object, attribute) { } var attr; attr = object[attribute]; - if (__NODEJS__ === false) { + if (( __NODEJS__ ) === false) { if (object instanceof HTMLDocument) { if (typeof(attr) === 'function') { var wrapper = function(args, kwargs) { @@ -97,7 +97,7 @@ __get__ = function(object, attribute) { } } } - if (attr !== undefined) { + if (( attr ) !== undefined) { if (typeof(attr) === 'function' && attr.pythonscript_function === undefined && attr.is_wrapper === undefined) { var wrapper = function(args, kwargs) { return attr.apply(object, args); @@ -111,15 +111,15 @@ __get__ = function(object, attribute) { } var __class__, bases; attr = object[attribute]; - if (attr != undefined) { + if (( attr ) != undefined) { return attr; } __class__ = object.__class__; if (__class__) { - if (attribute in __class__.__properties__) { + if (( attribute ) in __class__.__properties__) { return __class__.__properties__[attribute]["get"]([object], Object()); } - if (attribute in __class__.__unbound_methods__) { + if (( attribute ) in __class__.__unbound_methods__) { attr = __class__.__unbound_methods__[attribute]; if (attr.fastdef) { var method = function(args, kwargs) { @@ -135,7 +135,7 @@ __get__ = function(object, attribute) { var method = function() { var args; args = Array.prototype.slice.call(arguments); - if (args[0] instanceof Array && {}.toString.call(args[1]) === '[object Object]' && args.length == 2) { + if (args[0] instanceof Array && {}.toString.call(args[1]) === '[object Object]' && ( args.length ) == 2) { /*pass*/ } else { args = [args, Object()]; @@ -150,7 +150,7 @@ __get__ = function(object, attribute) { return method; } attr = __class__[attribute]; - if (attribute in __class__) { + if (( attribute ) in __class__) { if ({}.toString.call(attr) === '[object Function]') { if (attr.fastdef) { var method = function(args, kwargs) { @@ -166,7 +166,7 @@ __get__ = function(object, attribute) { var method = function() { var args; args = Array.prototype.slice.call(arguments); - if (args[0] instanceof Array && {}.toString.call(args[1]) === '[object Object]' && args.length == 2) { + if (args[0] instanceof Array && {}.toString.call(args[1]) === '[object Object]' && ( args.length ) == 2) { /*pass*/ } else { args = [args, Object()]; @@ -206,7 +206,7 @@ __get__ = function(object, attribute) { var method = function() { var args; args = Array.prototype.slice.call(arguments); - if (args[0] instanceof Array && {}.toString.call(args[1]) === '[object Object]' && args.length == 2) { + if (args[0] instanceof Array && {}.toString.call(args[1]) === '[object Object]' && ( args.length ) == 2) { /*pass*/ } else { args = [args, Object()]; @@ -237,7 +237,7 @@ __get__ = function(object, attribute) { } base = backup; } - if ("__getattr__" in __class__) { + if (( "__getattr__" ) in __class__) { return __class__["__getattr__"]([object, attribute], Object()); } var iter = bases; @@ -254,7 +254,7 @@ __get__ = function(object, attribute) { } } if (object instanceof Array) { - if (attribute == "__getitem__") { + if (( attribute ) == "__getitem__") { var wrapper = function(args, kwargs) { return object[args[0]]; } @@ -262,7 +262,7 @@ __get__ = function(object, attribute) { wrapper.is_wrapper = true; return wrapper; } else { - if (attribute == "__setitem__") { + if (( attribute ) == "__setitem__") { var wrapper = function(args, kwargs) { object[args[0]] = args[1]; } @@ -272,7 +272,7 @@ __get__ = function(object, attribute) { } } } else { - if (attribute == "__getitem__") { + if (( attribute ) == "__getitem__") { var wrapper = function(args, kwargs) { return object[args[0]]; } @@ -280,7 +280,7 @@ __get__ = function(object, attribute) { wrapper.is_wrapper = true; return wrapper; } else { - if (attribute == "__setitem__") { + if (( attribute ) == "__setitem__") { var wrapper = function(args, kwargs) { object[args[0]] = args[1]; } @@ -294,7 +294,7 @@ __get__ = function(object, attribute) { } _get_upstream_attribute = function(base, attr) { - if (attr in base) { + if (( attr ) in base) { return base[attr]; } var iter = base.__bases__; @@ -308,7 +308,7 @@ _get_upstream_attribute = function(base, attr) { } _get_upstream_property = function(base, attr) { - if (attr in base.__properties__) { + if (( attr ) in base.__properties__) { return base.__properties__[attr]; } var iter = base.__bases__; @@ -323,10 +323,10 @@ _get_upstream_property = function(base, attr) { __set__ = function(object, attribute, value) { "\n __setattr__ is always called when an attribute is set,\n unlike __getattr__ that only triggers when an attribute is not found,\n this asymmetry is in fact part of the Python spec.\n note there is no __setattribute__\n\n In normal Python a property setter is not called before __setattr__,\n this is bad language design because the user has been more explicit\n in having the property setter.\n\n In PythonJS, property setters are called instead of __setattr__.\n "; - if ("__class__" in object && object.__class__.__setters__.indexOf(attribute) != -1) { + if (( "__class__" ) in object && ( object.__class__.__setters__.indexOf(attribute) ) != -1) { object[attribute] = value; } else { - if ("__setattr__" in object) { + if (( "__setattr__" ) in object) { object.__setattr__(attribute, value); } else { object[attribute] = value; @@ -336,14 +336,14 @@ __set__ = function(object, attribute, value) { get_arguments = function(signature, args, kwargs) { "Based on ``signature`` and ``args``, ``kwargs`` parameters retrieve\n the actual parameters.\n\n This will set default keyword arguments and retrieve positional arguments\n in kwargs if their called as such"; - if (args === undefined) { + if (( args ) === undefined) { args = []; } - if (kwargs === undefined) { + if (( kwargs ) === undefined) { kwargs = Object(); } out = Object(); - if (args.length > signature.args.length) { + if (( args.length ) > signature.args.length) { if (signature.vararg) { /*pass*/ } else { @@ -352,15 +352,15 @@ get_arguments = function(signature, args, kwargs) { } } j = 0; - while(j < signature.args.length) { + while(( j ) < signature.args.length) { name = signature.args[j]; - if (name in kwargs) { + if (( name ) in kwargs) { out[name] = kwargs[name]; } else { - if (j < args.length) { + if (( j ) < args.length) { out[name] = args[j]; } else { - if (name in signature.kwargs) { + if (( name ) in signature.kwargs) { out[name] = signature.kwargs[name]; } } @@ -467,11 +467,11 @@ create_class = function(class_name, parents, attrs, props) { if (! (iter instanceof Array) ) { iter = __object_keys__(iter) } for (var key=0; key < iter.length; key++) { var backup = key; key = iter[key]; - if (typeof(attrs[key]) == "function") { + if (( typeof(attrs[key]) ) == "function") { klass.__unbound_methods__[ key ] = attrs[ key ]; klass.__all_method_names__.push(key); } - if (key == "__getattribute__") { + if (( key ) == "__getattribute__") { continue; } klass[ key ] = attrs[ key ]; @@ -514,10 +514,10 @@ create_class = function(class_name, parents, attrs, props) { if (! (iter instanceof Array) ) { iter = __object_keys__(iter) } for (var name=0; name < iter.length; name++) { var backup = name; name = iter[name]; - if (name == "__getattribute__") { + if (( name ) == "__getattribute__") { has_getattribute = true; } else { - if (name == "__getattr__") { + if (( name ) == "__getattr__") { has_getattr = true; } else { wrapper = __get__(object,name); @@ -555,7 +555,7 @@ create_class.args_signature = ["class_name","parents","attrs","props"]; create_class.kwargs_signature = {}; create_class.types_signature = {}; type = function(args, kwargs) { - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -568,7 +568,7 @@ type = function(args, kwargs) { var bases = arguments['bases']; var class_dict = arguments['class_dict']; "\n type(object) -> the object's type\n type(name, bases, dict) -> a new type ## broken? - TODO test\n "; - if (bases === undefined && class_dict === undefined) { + if (( bases ) === undefined && ( class_dict ) === undefined) { return ob_or_class_name.__class__; } else { return create_class(ob_or_class_name,bases,class_dict); @@ -581,7 +581,7 @@ type.kwargs_signature = { bases:undefined,class_dict:undefined }; type.types_signature = { bases:"None",class_dict:"None" }; type.pythonscript_function = true; hasattr = function(args, kwargs) { - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -602,7 +602,7 @@ hasattr.kwargs_signature = { method:false }; hasattr.types_signature = { method:"False" }; hasattr.pythonscript_function = true; getattr = function(args, kwargs) { - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -632,7 +632,7 @@ getattr.kwargs_signature = { property:false }; getattr.types_signature = { property:"False" }; getattr.pythonscript_function = true; setattr = function(args, kwargs) { - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -664,7 +664,7 @@ setattr.types_signature = { property:"False" }; setattr.pythonscript_function = true; issubclass = function(args, kwargs) { var i, bases; - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -675,12 +675,12 @@ issubclass = function(args, kwargs) { arguments = get_arguments(signature, args, kwargs); var C = arguments['C']; var B = arguments['B']; - if (C === B) { + if (( C ) === B) { return true; } bases = C.__bases__; i = 0; - while(i < __get__(bases, "length")) { + while(( i ) < __get__(bases, "length")) { if (issubclass([__get__(bases, "__getitem__")([i], Object()), B], __NULL_OBJECT__)) { return true; } @@ -696,7 +696,7 @@ issubclass.types_signature = { }; issubclass.pythonscript_function = true; isinstance = function(args, kwargs) { var ob_class; - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -707,7 +707,7 @@ isinstance = function(args, kwargs) { arguments = get_arguments(signature, args, kwargs); var ob = arguments['ob']; var klass = arguments['klass']; - if (ob === undefined || ob === null) { + if (( ob ) === undefined || ( ob ) === null) { return false; } else { if (!Object.hasOwnProperty.call(ob, "__class__")) { @@ -715,7 +715,7 @@ isinstance = function(args, kwargs) { } } ob_class = ob.__class__; - if (ob_class === undefined) { + if (( ob_class ) === undefined) { return false; } else { return issubclass([ob_class, klass], __NULL_OBJECT__); @@ -728,7 +728,7 @@ isinstance.kwargs_signature = { }; isinstance.types_signature = { }; isinstance.pythonscript_function = true; int = function(args, kwargs) { - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -751,7 +751,7 @@ int.kwargs_signature = { }; int.types_signature = { }; int.pythonscript_function = true; float = function(args, kwargs) { - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -775,7 +775,7 @@ float.types_signature = { }; float.pythonscript_function = true; round = function(args, kwargs) { var b; - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -787,7 +787,7 @@ round = function(args, kwargs) { var a = arguments['a']; var places = arguments['places']; b = "" + a; - if (b.indexOf(".") == -1) { + if (( b.indexOf(".") ) == -1) { return a; } else { c = b.split("."); @@ -803,7 +803,7 @@ round.kwargs_signature = { }; round.types_signature = { }; round.pythonscript_function = true; str = function(args, kwargs) { - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -824,7 +824,7 @@ str.pythonscript_function = true; _setup_str_prototype = function(args, kwargs) { "\n Extend JavaScript String.prototype with methods that implement the Python str API.\n The decorator @String.prototype.[name] assigns the function to the prototype,\n and ensures that the special 'this' variable will work.\n "; var func = function(a) { - if (this.indexOf(a) == -1) { + if (( this.indexOf(a) ) == -1) { return false; } else { return true; @@ -874,7 +874,7 @@ _setup_str_prototype = function(args, kwargs) { String.prototype.__len__=func; var func = function(start, stop, step) { var stop; - if (stop < 0) { + if (( stop ) < 0) { stop = this.length + stop; } return this.substring(start,stop); @@ -904,7 +904,7 @@ _setup_str_prototype = function(args, kwargs) { func.types_signature = {}; String.prototype.strip=func; var func = function(a) { - if (this.substring(0, a.length) == a) { + if (( this.substring(0, a.length) ) == a) { return true; } else { return false; @@ -917,7 +917,7 @@ _setup_str_prototype = function(args, kwargs) { func.types_signature = {}; String.prototype.startswith=func; var func = function(a) { - if (this.substring(this.length - a.length, this.length) == a) { + if (( this.substring(this.length - a.length, this.length) ) == a) { return true; } else { return false; @@ -945,7 +945,7 @@ _setup_str_prototype = function(args, kwargs) { var backup = value; value = iter[value]; out += value; i += 1; - if (i < arr.length) { + if (( i ) < arr.length) { out += this; } value = backup; @@ -993,7 +993,7 @@ _setup_str_prototype = function(args, kwargs) { if (! (iter instanceof Array) ) { iter = __object_keys__(iter) } for (var char=0; char < iter.length; char++) { var backup = char; char = iter[char]; - if (char in digits || Object.hasOwnProperty.call(digits, "__contains__") && digits["__contains__"](char)) { + if (( char ) in digits || Object.hasOwnProperty.call(digits, "__contains__") && digits["__contains__"](char)) { /*pass*/ } else { return false; @@ -1036,7 +1036,7 @@ _setup_str_prototype.pythonscript_function = true; _setup_str_prototype(); _setup_array_prototype = function(args, kwargs) { var func = function(a) { - if (this.indexOf(a) == -1) { + if (( this.indexOf(a) ) == -1) { return false; } else { return true; @@ -1077,7 +1077,7 @@ _setup_array_prototype = function(args, kwargs) { Array.prototype.__iter__=func; var func = function(start, stop, step) { var stop; - if (stop < 0) { + if (( stop ) < 0) { stop = this.length + stop; } return this.slice(start,stop); @@ -1097,6 +1097,31 @@ _setup_array_prototype = function(args, kwargs) { func.kwargs_signature = {}; func.types_signature = {}; Array.prototype.append=func; + var func = function(x, low, high) { + var high, a, low, mid; + if (( low ) === undefined) { + low = 0; + } + if (( high ) === undefined) { + high = this.length; + } + while(( low ) < high) { + a = low + high; + mid = Math.floor(a / 2); + if (( x ) < this[mid]) { + high = mid; + } else { + low = mid + 1; + } + } + return low; + } + + func.NAME = "func"; + func.args_signature = ["x","low","high"]; + func.kwargs_signature = {}; + func.types_signature = {}; + Array.prototype.bisect=func; } _setup_array_prototype.NAME = "_setup_array_prototype"; @@ -1105,9 +1130,35 @@ _setup_array_prototype.kwargs_signature = { }; _setup_array_prototype.types_signature = { }; _setup_array_prototype.pythonscript_function = true; _setup_array_prototype(); +bisect = function(args, kwargs) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { + /*pass*/ + } else { + args = Array.prototype.slice.call(arguments); + kwargs = Object(); + } + var signature, arguments; + signature = {"kwargs": {"low": undefined, "high": undefined}, "args": __create_array__("a", "x", "low", "high")}; + arguments = get_arguments(signature, args, kwargs); + var a = arguments['a']; + var x = arguments['x']; + var low = arguments['low']; + var high = arguments['high']; + if (isinstance([a, list], __NULL_OBJECT__)) { + return __get__(__get__(a["$wrapped"], "bisect"), "__call__")([x, low, high], __NULL_OBJECT__); + } else { + return __get__(__get__(a, "bisect"), "__call__")([x, low, high], __NULL_OBJECT__); + } +} + +bisect.NAME = "bisect"; +bisect.args_signature = ["a", "x", "low", "high"]; +bisect.kwargs_signature = { low:undefined,high:undefined }; +bisect.types_signature = { low:"None",high:"None" }; +bisect.pythonscript_function = true; range = function(args, kwargs) { var i, arr, num; - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -1119,14 +1170,14 @@ range = function(args, kwargs) { var num = arguments['num']; var stop = arguments['stop']; "Emulates Python's range function"; - if (stop !== undefined) { + if (( stop ) !== undefined) { i = num; num = stop; } else { i = 0; } arr = []; - while(i < num) { + while(( i ) < num) { arr.push(i); i += 1; } @@ -1148,7 +1199,7 @@ __StopIteration_parents = []; __StopIteration_properties = Object(); StopIteration = create_class("StopIteration", __StopIteration_parents, __StopIteration_attrs, __StopIteration_properties); len = function(args, kwargs) { - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -1167,7 +1218,7 @@ len.kwargs_signature = { }; len.types_signature = { }; len.pythonscript_function = true; next = function(args, kwargs) { - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -1186,7 +1237,7 @@ next.kwargs_signature = { }; next.types_signature = { }; next.pythonscript_function = true; map = function(args, kwargs) { - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -1211,7 +1262,7 @@ map.return_type = "list"; map.pythonscript_function = true; min = function(args, kwargs) { var a; - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -1226,12 +1277,12 @@ min = function(args, kwargs) { __iterator__ = __get__(__get__(lst, "__iter__"), "__call__")([], Object()); var __next__; __next__ = __get__(__iterator__, "next_fast"); - while(__iterator__.index < __iterator__.length) { + while(( __iterator__.index ) < __iterator__.length) { value = __next__(); - if (a === undefined) { + if (( a ) === undefined) { a = value; } else { - if (value < a) { + if (( value ) < a) { a = value; } } @@ -1246,7 +1297,7 @@ min.types_signature = { }; min.pythonscript_function = true; max = function(args, kwargs) { var a; - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -1261,12 +1312,12 @@ max = function(args, kwargs) { __iterator__ = __get__(__get__(lst, "__iter__"), "__call__")([], Object()); var __next__; __next__ = __get__(__iterator__, "next_fast"); - while(__iterator__.index < __iterator__.length) { + while(( __iterator__.index ) < __iterator__.length) { value = __next__(); - if (a === undefined) { + if (( a ) === undefined) { a = value; } else { - if (value > a) { + if (( value ) > a) { a = value; } } @@ -1280,7 +1331,7 @@ max.kwargs_signature = { }; max.types_signature = { }; max.pythonscript_function = true; abs = function(args, kwargs) { - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -1299,7 +1350,7 @@ abs.kwargs_signature = { }; abs.types_signature = { }; abs.pythonscript_function = true; ord = function(args, kwargs) { - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -1318,7 +1369,7 @@ ord.kwargs_signature = { }; ord.types_signature = { }; ord.pythonscript_function = true; chr = function(args, kwargs) { - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -1341,7 +1392,7 @@ __Iterator_attrs = Object(); __Iterator_parents = []; __Iterator_properties = Object(); __Iterator___init__ = function(args, kwargs) { - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -1367,7 +1418,7 @@ __Iterator___init__.pythonscript_function = true; __Iterator_attrs["__init__"] = __Iterator___init__; __Iterator_next = function(args, kwargs) { var index, length, item; - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -1379,7 +1430,7 @@ __Iterator_next = function(args, kwargs) { var self = arguments['self']; index = self.index; length = len([self.obj], __NULL_OBJECT__); - if (index == length) { + if (( index ) == length) { throw StopIteration; } item = __get__(__get__(self.obj, "get"), "__call__")([self.index], __NULL_OBJECT__); @@ -1395,7 +1446,7 @@ __Iterator_next.pythonscript_function = true; __Iterator_attrs["next"] = __Iterator_next; __Iterator_next_fast = function(args, kwargs) { var index; - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -1423,7 +1474,7 @@ __tuple_parents = []; __tuple_properties = Object(); __tuple___init__ = function(args, kwargs) { var arr; - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -1441,7 +1492,7 @@ __tuple___init__ = function(args, kwargs) { __iterator__ = __get__(__get__(js_object, "__iter__"), "__call__")([], Object()); var __next__; __next__ = __get__(__iterator__, "next_fast"); - while(__iterator__.index < __iterator__.length) { + while(( __iterator__.index ) < __iterator__.length) { item = __next__(); __get__(__get__(arr, "push"), "__call__")([item], __NULL_OBJECT__); } @@ -1452,7 +1503,7 @@ __tuple___init__ = function(args, kwargs) { __iterator__ = __get__(__get__(js_object, "__iter__"), "__call__")([], Object()); var __next__; __next__ = __get__(__iterator__, "next_fast"); - while(__iterator__.index < __iterator__.length) { + while(( __iterator__.index ) < __iterator__.length) { v = __next__(); __get__(__get__(arr, "push"), "__call__")([v], __NULL_OBJECT__); } @@ -1471,7 +1522,7 @@ __tuple___init__.pythonscript_function = true; __tuple_attrs["__init__"] = __tuple___init__; __tuple___getitem__ = function(args, kwargs) { var index; - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -1482,7 +1533,7 @@ __tuple___getitem__ = function(args, kwargs) { arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var index = arguments['index']; - if (index < 0) { + if (( index ) < 0) { index = __get__(self["$wrapped"], "length") + index; } return self["$wrapped"][ index ]; @@ -1495,7 +1546,7 @@ __tuple___getitem__.types_signature = { }; __tuple___getitem__.pythonscript_function = true; __tuple_attrs["__getitem__"] = __tuple___getitem__; __tuple___iter__ = function(args, kwargs) { - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -1516,7 +1567,7 @@ __tuple___iter__.return_type = "Iterator"; __tuple___iter__.pythonscript_function = true; __tuple_attrs["__iter__"] = __tuple___iter__; __tuple___len__ = function(args, kwargs) { - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -1536,7 +1587,7 @@ __tuple___len__.types_signature = { }; __tuple___len__.pythonscript_function = true; __tuple_attrs["__len__"] = __tuple___len__; __tuple_index = function(args, kwargs) { - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -1558,7 +1609,7 @@ __tuple_index.pythonscript_function = true; __tuple_attrs["index"] = __tuple_index; __tuple_count = function(args, kwargs) { var a; - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -1575,7 +1626,7 @@ __tuple_count = function(args, kwargs) { if (! (iter instanceof Array) ) { iter = __object_keys__(iter) } for (var item=0; item < iter.length; item++) { var backup = item; item = iter[item]; - if (item == obj) { + if (( item ) == obj) { a += 1; } item = backup; @@ -1590,7 +1641,7 @@ __tuple_count.types_signature = { }; __tuple_count.pythonscript_function = true; __tuple_attrs["count"] = __tuple_count; __tuple_get = function(args, kwargs) { - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -1611,7 +1662,7 @@ __tuple_get.types_signature = { }; __tuple_get.pythonscript_function = true; __tuple_attrs["get"] = __tuple_get; __tuple___contains__ = function(args, kwargs) { - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -1622,7 +1673,7 @@ __tuple___contains__ = function(args, kwargs) { arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var value = arguments['value']; - if (self["$wrapped"].indexOf(value) == -1) { + if (( self["$wrapped"].indexOf(value) ) == -1) { return false; } else { return true; @@ -1642,7 +1693,7 @@ __list_parents = []; __list_properties = Object(); __list___init__ = function(args, kwargs) { var arr; - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -1664,7 +1715,7 @@ __list___init__ = function(args, kwargs) { __iterator__ = __get__(__get__(js_object, "__iter__"), "__call__")([], Object()); var __next__; __next__ = __get__(__iterator__, "next_fast"); - while(__iterator__.index < __iterator__.length) { + while(( __iterator__.index ) < __iterator__.length) { item = __next__(); __get__(__get__(arr, "push"), "__call__")([item], __NULL_OBJECT__); } @@ -1675,7 +1726,7 @@ __list___init__ = function(args, kwargs) { __iterator__ = __get__(__get__(js_object, "__iter__"), "__call__")([], Object()); var __next__; __next__ = __get__(__iterator__, "next_fast"); - while(__iterator__.index < __iterator__.length) { + while(( __iterator__.index ) < __iterator__.length) { v = __next__(); __get__(__get__(arr, "push"), "__call__")([v], __NULL_OBJECT__); } @@ -1697,7 +1748,7 @@ __list___getitem__ = function(args, kwargs) { var index; var self = args[ 0 ]; var index = args[ 1 ]; - if (index < 0) { + if (( index ) < 0) { index = __get__(self["$wrapped"], "length") + index; } return self["$wrapped"][ index ]; @@ -1726,7 +1777,7 @@ __list___setitem__.pythonscript_function = true; __list_attrs["__setitem__"] = __list___setitem__; __list___getslice__ = function(args, kwargs) { var arr; - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -1754,7 +1805,7 @@ __list___getslice__.return_type = "list"; __list___getslice__.pythonscript_function = true; __list_attrs["__getslice__"] = __list___getslice__; __list_append = function(args, kwargs) { - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -1775,7 +1826,7 @@ __list_append.types_signature = { }; __list_append.pythonscript_function = true; __list_attrs["append"] = __list_append; __list_extend = function(args, kwargs) { - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -1790,7 +1841,7 @@ __list_extend = function(args, kwargs) { __iterator__ = __get__(__get__(other, "__iter__"), "__call__")([], Object()); var __next__; __next__ = __get__(__iterator__, "next_fast"); - while(__iterator__.index < __iterator__.length) { + while(( __iterator__.index ) < __iterator__.length) { obj = __next__(); __get__(__get__(self, "append"), "__call__")([obj], __NULL_OBJECT__); } @@ -1803,7 +1854,7 @@ __list_extend.types_signature = { }; __list_extend.pythonscript_function = true; __list_attrs["extend"] = __list_extend; __list_insert = function(args, kwargs) { - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -1826,7 +1877,7 @@ __list_insert.pythonscript_function = true; __list_attrs["insert"] = __list_insert; __list_remove = function(args, kwargs) { var index; - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -1848,7 +1899,7 @@ __list_remove.types_signature = { }; __list_remove.pythonscript_function = true; __list_attrs["remove"] = __list_remove; __list_pop = function(args, kwargs) { - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -1868,7 +1919,7 @@ __list_pop.types_signature = { }; __list_pop.pythonscript_function = true; __list_attrs["pop"] = __list_pop; __list_index = function(args, kwargs) { - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -1890,7 +1941,7 @@ __list_index.pythonscript_function = true; __list_attrs["index"] = __list_index; __list_count = function(args, kwargs) { var a; - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -1907,7 +1958,7 @@ __list_count = function(args, kwargs) { if (! (iter instanceof Array) ) { iter = __object_keys__(iter) } for (var item=0; item < iter.length; item++) { var backup = item; item = iter[item]; - if (item == obj) { + if (( item ) == obj) { a += 1; } item = backup; @@ -1922,7 +1973,7 @@ __list_count.types_signature = { }; __list_count.pythonscript_function = true; __list_attrs["count"] = __list_count; __list_reverse = function(args, kwargs) { - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -1942,7 +1993,7 @@ __list_reverse.types_signature = { }; __list_reverse.pythonscript_function = true; __list_attrs["reverse"] = __list_reverse; __list_shift = function(args, kwargs) { - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -1962,7 +2013,7 @@ __list_shift.types_signature = { }; __list_shift.pythonscript_function = true; __list_attrs["shift"] = __list_shift; __list_slice = function(args, kwargs) { - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -1984,7 +2035,7 @@ __list_slice.types_signature = { }; __list_slice.pythonscript_function = true; __list_attrs["slice"] = __list_slice; __list___iter__ = function(args, kwargs) { - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -2005,7 +2056,7 @@ __list___iter__.return_type = "Iterator"; __list___iter__.pythonscript_function = true; __list_attrs["__iter__"] = __list___iter__; __list_get = function(args, kwargs) { - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -2026,7 +2077,7 @@ __list_get.types_signature = { }; __list_get.pythonscript_function = true; __list_attrs["get"] = __list_get; __list_set = function(args, kwargs) { - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -2048,7 +2099,7 @@ __list_set.types_signature = { }; __list_set.pythonscript_function = true; __list_attrs["set"] = __list_set; __list___len__ = function(args, kwargs) { - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -2068,7 +2119,7 @@ __list___len__.types_signature = { }; __list___len__.pythonscript_function = true; __list_attrs["__len__"] = __list___len__; __list___contains__ = function(args, kwargs) { - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -2079,7 +2130,7 @@ __list___contains__ = function(args, kwargs) { arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var value = arguments['value']; - if (self["$wrapped"].indexOf(value) == -1) { + if (( self["$wrapped"].indexOf(value) ) == -1) { return false; } else { return true; @@ -2101,7 +2152,7 @@ __dict_UID = 0; __dict_attrs["UID"] = __dict_UID; __dict___init__ = function(args, kwargs) { var i; - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -2116,7 +2167,7 @@ __dict___init__ = function(args, kwargs) { if (js_object) { if (js_object instanceof Array) { i = 0; - while(i < __get__(js_object, "length")) { + while(( i ) < __get__(js_object, "length")) { var key = js_object[i]["key"]; var value = js_object[i]["value"]; __get__(__get__(self, "set"), "__call__")([key, value], __NULL_OBJECT__); @@ -2136,7 +2187,7 @@ __dict___init__.pythonscript_function = true; __dict_attrs["__init__"] = __dict___init__; __dict_get = function(args, kwargs) { var __dict; - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -2177,7 +2228,7 @@ __dict_get.pythonscript_function = true; __dict_attrs["get"] = __dict_get; __dict_set = function(args, kwargs) { var __dict, uid; - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -2221,7 +2272,7 @@ __dict_set.pythonscript_function = true; __dict_attrs["set"] = __dict_set; __dict___len__ = function(args, kwargs) { var __dict; - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -2243,7 +2294,7 @@ __dict___len__.pythonscript_function = true; __dict_attrs["__len__"] = __dict___len__; __dict___getitem__ = function(args, kwargs) { var __dict; - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -2276,7 +2327,7 @@ __dict___getitem__.pythonscript_function = true; __dict_attrs["__getitem__"] = __dict___getitem__; __dict___setitem__ = function(args, kwargs) { var __dict, uid; - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -2320,7 +2371,7 @@ __dict___setitem__.pythonscript_function = true; __dict_attrs["__setitem__"] = __dict___setitem__; __dict_keys = function(args, kwargs) { var arr; - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -2346,7 +2397,7 @@ __dict_keys.pythonscript_function = true; __dict_attrs["keys"] = __dict_keys; __dict_pop = function(args, kwargs) { var js_object, v; - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -2359,7 +2410,7 @@ __dict_pop = function(args, kwargs) { var key = arguments['key']; var d = arguments['d']; v = __get__(__get__(self, "get"), "__call__")([key, undefined], __NULL_OBJECT__); - if (v === undefined) { + if (( v ) === undefined) { return d; } else { js_object = self["$wrapped"]; @@ -2376,7 +2427,7 @@ __dict_pop.pythonscript_function = true; __dict_attrs["pop"] = __dict_pop; __dict_values = function(args, kwargs) { var __dict, __keys, i, out; - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -2390,7 +2441,7 @@ __dict_values = function(args, kwargs) { __keys = Object.keys(__dict); out = __get__(list, "__call__")(); i = 0; - while(i < __get__(__keys, "length")) { + while(( i ) < __get__(__keys, "length")) { __get__(__get__(out, "append"), "__call__")([__dict[ __keys[i] ]], __NULL_OBJECT__); i += 1 } @@ -2405,7 +2456,7 @@ __dict_values.pythonscript_function = true; __dict_attrs["values"] = __dict_values; __dict___contains__ = function(args, kwargs) { var keys; - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -2417,12 +2468,12 @@ __dict___contains__ = function(args, kwargs) { var self = arguments['self']; var value = arguments['value']; keys = Object.keys(self["$wrapped"]); - if (typeof(value) == "object") { + if (( typeof(value) ) == "object") { key = "@" + value.uid; } else { key = "" + value; } - if (keys.indexOf(key) == -1) { + if (( keys.indexOf(key) ) == -1) { return false; } else { return true; @@ -2436,7 +2487,7 @@ __dict___contains__.types_signature = { }; __dict___contains__.pythonscript_function = true; __dict_attrs["__contains__"] = __dict___contains__; __dict___iter__ = function(args, kwargs) { - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -2467,7 +2518,7 @@ __array_typecode_names = { "c":"Int8","b":"Int8","B":"Uint8","u":"Uint16","h":"I __array_attrs["typecode_names"] = __array_typecode_names; __array___init__ = function(args, kwargs) { var size, buff; - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -2486,12 +2537,12 @@ __array___init__ = function(args, kwargs) { if (initializer) { self.length = len([initializer], __NULL_OBJECT__); self.bytes = self.length * self.itemsize; - if (self.typecode == "float8") { + if (( self.typecode ) == "float8") { self._scale = max([__get__(list, "__call__")([], {"js_object": [abs([min([initializer], __NULL_OBJECT__)], __NULL_OBJECT__), max([initializer], __NULL_OBJECT__)]})], __NULL_OBJECT__); self._norm_get = self._scale / 127; self._norm_set = 1.0 / self._norm_get; } else { - if (self.typecode == "float16") { + if (( self.typecode ) == "float16") { self._scale = max([__get__(list, "__call__")([], {"js_object": [abs([min([initializer], __NULL_OBJECT__)], __NULL_OBJECT__), max([initializer], __NULL_OBJECT__)]})], __NULL_OBJECT__); self._norm_get = self._scale / 32767; self._norm_set = 1.0 / self._norm_get; @@ -2515,7 +2566,7 @@ __array___init__.types_signature = { initializer:"None",little_endian:"False" }; __array___init__.pythonscript_function = true; __array_attrs["__init__"] = __array___init__; __array___len__ = function(args, kwargs) { - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -2536,7 +2587,7 @@ __array___len__.pythonscript_function = true; __array_attrs["__len__"] = __array___len__; __array___contains__ = function(args, kwargs) { var arr; - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -2548,7 +2599,7 @@ __array___contains__ = function(args, kwargs) { var self = arguments['self']; var value = arguments['value']; arr = __get__(__get__(self, "to_array"), "__call__")(); - if (arr.indexOf(value) == -1) { + if (( arr.indexOf(value) ) == -1) { return false; } else { return true; @@ -2563,7 +2614,7 @@ __array___contains__.pythonscript_function = true; __array_attrs["__contains__"] = __array___contains__; __array___getitem__ = function(args, kwargs) { var func_name, dataview, value, step, func, offset; - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -2579,12 +2630,12 @@ __array___getitem__ = function(args, kwargs) { dataview = self.dataview; func_name = "get" + __get__(__get__(self, "typecode_names"), "__getitem__")([self.typecode], Object()); func = dataview[func_name].bind(dataview); - if (offset < self.bytes) { + if (( offset ) < self.bytes) { value = func(offset); - if (self.typecode == "float8") { + if (( self.typecode ) == "float8") { value = value * self._norm_get; } else { - if (self.typecode == "float16") { + if (( self.typecode ) == "float16") { value = value * self._norm_get; } } @@ -2602,7 +2653,7 @@ __array___getitem__.pythonscript_function = true; __array_attrs["__getitem__"] = __array___getitem__; __array___setitem__ = function(args, kwargs) { var index, func_name, dataview, value, step, func, offset; - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -2615,18 +2666,18 @@ __array___setitem__ = function(args, kwargs) { var index = arguments['index']; var value = arguments['value']; step = self.itemsize; - if (index < 0) { + if (( index ) < 0) { index = self.length + index - 1; } offset = step * index; dataview = self.dataview; func_name = "set" + __get__(__get__(self, "typecode_names"), "__getitem__")([self.typecode], Object()); func = dataview[func_name].bind(dataview); - if (offset < self.bytes) { - if (self.typecode == "float8") { + if (( offset ) < self.bytes) { + if (( self.typecode ) == "float8") { value = value * self._norm_set; } else { - if (self.typecode == "float16") { + if (( self.typecode ) == "float16") { value = value * self._norm_set; } } @@ -2643,7 +2694,7 @@ __array___setitem__.types_signature = { }; __array___setitem__.pythonscript_function = true; __array_attrs["__setitem__"] = __array___setitem__; __array___iter__ = function(args, kwargs) { - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -2664,7 +2715,7 @@ __array___iter__.return_type = "Iterator"; __array___iter__.pythonscript_function = true; __array_attrs["__iter__"] = __array___iter__; __array_get = function(args, kwargs) { - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -2686,7 +2737,7 @@ __array_get.pythonscript_function = true; __array_attrs["get"] = __array_get; __array_fromlist = function(args, kwargs) { var typecode, i, func_name, dataview, length, item, step, func, offset, size; - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -2704,15 +2755,15 @@ __array_fromlist = function(args, kwargs) { dataview = self.dataview; func_name = "set" + __get__(__get__(self, "typecode_names"), "__getitem__")([typecode], Object()); func = dataview[func_name].bind(dataview); - if (size <= self.bytes) { + if (( size ) <= self.bytes) { i = 0; offset = 0; - while(i < length) { + while(( i ) < length) { item = __get__(lst, "__getitem__")([i], Object()); - if (typecode == "float8") { + if (( typecode ) == "float8") { item *= self._norm_set } else { - if (typecode == "float16") { + if (( typecode ) == "float16") { item *= self._norm_set } } @@ -2733,7 +2784,7 @@ __array_fromlist.pythonscript_function = true; __array_attrs["fromlist"] = __array_fromlist; __array_resize = function(args, kwargs) { var source, new_buff, target, new_size, buff; - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -2764,7 +2815,7 @@ __array_resize.pythonscript_function = true; __array_attrs["resize"] = __array_resize; __array_append = function(args, kwargs) { var length; - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -2787,7 +2838,7 @@ __array_append.types_signature = { }; __array_append.pythonscript_function = true; __array_attrs["append"] = __array_append; __array_extend = function(args, kwargs) { - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -2802,7 +2853,7 @@ __array_extend = function(args, kwargs) { __iterator__ = __get__(__get__(lst, "__iter__"), "__call__")([], Object()); var __next__; __next__ = __get__(__iterator__, "next_fast"); - while(__iterator__.index < __iterator__.length) { + while(( __iterator__.index ) < __iterator__.length) { value = __next__(); __get__(__get__(self, "append"), "__call__")([value], __NULL_OBJECT__); } @@ -2816,7 +2867,7 @@ __array_extend.pythonscript_function = true; __array_attrs["extend"] = __array_extend; __array_to_array = function(args, kwargs) { var i, item, arr; - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -2828,7 +2879,7 @@ __array_to_array = function(args, kwargs) { var self = arguments['self']; arr = []; i = 0; - while(i < self.length) { + while(( i ) < self.length) { item = __array___getitem__([self, i], Object()); arr.push( item ); i += 1 @@ -2843,7 +2894,7 @@ __array_to_array.types_signature = { }; __array_to_array.pythonscript_function = true; __array_attrs["to_array"] = __array_to_array; __array_to_list = function(args, kwargs) { - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -2868,7 +2919,7 @@ __array_to_list.pythonscript_function = true; __array_attrs["to_list"] = __array_to_list; __array_to_ascii = function(args, kwargs) { var i, length, arr, string; - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -2882,7 +2933,7 @@ __array_to_ascii = function(args, kwargs) { arr = __get__(__get__(self, "to_array"), "__call__")(); i = 0; length = __get__(arr, "length"); - while(i < length) { + while(( i ) < length) { var num = arr[i]; var char = String.fromCharCode(num); string += char @@ -2901,7 +2952,7 @@ array = create_class("array", __array_parents, __array_attrs, __array_properties json = { "loads":(function (s) {return JSON.parse(s)}),"dumps":(function (o) {return JSON.stringify(o)}) }; _to_pythonjs = function(args, kwargs) { var set, keys, raw, jstype, output, append; - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -2913,10 +2964,10 @@ _to_pythonjs = function(args, kwargs) { var json = arguments['json']; var jstype, item, output; jstype = typeof json; - if (jstype == "number") { + if (( jstype ) == "number") { return json; } - if (jstype == "string") { + if (( jstype ) == "string") { return json; } if (Object.prototype.toString.call(json) === '[object Array]') { @@ -2931,7 +2982,7 @@ _to_pythonjs = function(args, kwargs) { __iterator__ = __get__(__get__(raw, "__iter__"), "__call__")([], Object()); var __next__; __next__ = __get__(__iterator__, "next_fast"); - while(__iterator__.index < __iterator__.length) { + while(( __iterator__.index ) < __iterator__.length) { item = __next__(); __get__(append, "__call__")([_to_pythonjs([item], __NULL_OBJECT__)], __NULL_OBJECT__); } @@ -2948,7 +2999,7 @@ _to_pythonjs = function(args, kwargs) { __iterator__ = __get__(__get__(keys, "__iter__"), "__call__")([], Object()); var __next__; __next__ = __get__(__iterator__, "next_fast"); - while(__iterator__.index < __iterator__.length) { + while(( __iterator__.index ) < __iterator__.length) { key = __next__(); __get__(set, "__call__")([key, _to_pythonjs([json[key]], __NULL_OBJECT__)], __NULL_OBJECT__); } @@ -2961,7 +3012,7 @@ _to_pythonjs.kwargs_signature = { }; _to_pythonjs.types_signature = { }; _to_pythonjs.pythonscript_function = true; json_to_pythonjs = function(args, kwargs) { - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -2981,7 +3032,7 @@ json_to_pythonjs.types_signature = { }; json_to_pythonjs.pythonscript_function = true; _to_json = function(args, kwargs) { var r, key, value; - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); @@ -2997,7 +3048,7 @@ _to_json = function(args, kwargs) { __iterator__ = __get__(__get__(pythonjs, "__iter__"), "__call__")([], Object()); var __next__; __next__ = __get__(__iterator__, "next_fast"); - while(__iterator__.index < __iterator__.length) { + while(( __iterator__.index ) < __iterator__.length) { i = __next__(); __get__(__get__(r, "push"), "__call__")([_to_json([i], __NULL_OBJECT__)], __NULL_OBJECT__); } @@ -3009,7 +3060,7 @@ _to_json = function(args, kwargs) { __iterator__ = __get__(__get__(__get__(__get__(pythonjs, "keys"), "__call__")(), "__iter__"), "__call__")([], Object()); var __next__; __next__ = __get__(__iterator__, "next_fast"); - while(__iterator__.index < __iterator__.length) { + while(( __iterator__.index ) < __iterator__.length) { key = __next__(); value = _to_json([__get__(__get__(pythonjs, "get"), "__call__")([key], __NULL_OBJECT__)], __NULL_OBJECT__); key = _to_json([key], __NULL_OBJECT__); @@ -3028,7 +3079,7 @@ _to_json.kwargs_signature = { }; _to_json.types_signature = { }; _to_json.pythonscript_function = true; pythonjs_to_json = function(args, kwargs) { - if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && arguments.length == 2) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { args = Array.prototype.slice.call(arguments); diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index 60f58d1..115ec4d 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -99,6 +99,9 @@ def getvalue(self): }, 'random': { 'random': 'var random = Math.random' + }, + 'bisect' : { + 'bisect' : '/*bisect from fake bisect module*/' ## bisect is a builtin } } @@ -170,8 +173,9 @@ class PythonToPythonJS(NodeVisitor): identifier = 0 - def __init__(self, module=None, module_path=None): + def __init__(self, source=None, module=None, module_path=None): super(PythonToPythonJS, self).__init__() + self._source = source.splitlines() self._classes = dict() ## class name : [method names] self._class_parents = dict() ## class name : parents self._instance_attributes = dict() ## class name : [attribute names] @@ -1141,6 +1145,10 @@ def visit_Str(self, node): return '"""%s"""' %s def visit_Expr(self, node): + log('line: %s' %node.lineno ) + src = self._source[ node.lineno ] + log( src ) + line = self.visit(node.value) if line: writer.write(line) @@ -1407,6 +1415,9 @@ def visit_Lambda(self, node): return 'lambda %s: %s' %(','.join(args), self.visit(node.body)) def visit_FunctionDef(self, node): + log('-----------------') + log('function: %s'%node.name) + property_decorator = None decorators = [] with_js_decorators = [] @@ -1484,7 +1495,6 @@ def visit_FunctionDef(self, node): else: decorators.append( decorator ) - log('function: %s'%node.name) if self._with_js or javascript: if node.args.vararg: raise SyntaxError( 'pure javascript functions can not take variable arguments (*args)' ) @@ -1695,8 +1705,6 @@ def visit_Continue(self, node): if self._with_js: writer.write('continue') else: - if not self.FAST_FOR: - writer.write('%s = __get__(__iterator__, "next")(JSArray(), JSObject())' % self._for_iterator_target) writer.write('continue') return '' @@ -1718,86 +1726,98 @@ def visit_For(self, node): c.constant = True self._call_ids += 1 + target = node.target + enumtar = None + if isinstance(node.iter, ast.Call) and isinstance(node.iter.func, Name) and node.iter.func.id == 'enumerate': + iter = node.iter.args[0] + if isinstance(target, ast.Tuple): + enumtar = target.elts[0] + target = target.elts[1] + else: + iter = node.iter + + if enumtar: + writer.write('var(%s)'%enumtar.id) + writer.write('%s = 0' %enumtar.id) + if self._with_js: - if isinstance(node.iter, ast.Call) and isinstance(node.iter.func, Name) and node.iter.func.id in ('range','xrange'): + if isinstance(iter, ast.Call) and isinstance(iter.func, Name) and iter.func.id in ('range','xrange'): iter_start = '0' - if len(node.iter.args) == 2: - iter_start = self.visit(node.iter.args[0]) - iter_end = self.visit(node.iter.args[1]) + if len(iter.args) == 2: + iter_start = self.visit(iter.args[0]) + iter_end = self.visit(iter.args[1]) else: - iter_end = self.visit(node.iter.args[0]) + iter_end = self.visit(iter.args[0]) - iter_name = node.target.id + iter_name = target.id writer.write('var(%s)' %iter_name) writer.write('%s = %s' %(iter_name, iter_start)) writer.write('while %s < %s:' %(iter_name, iter_end)) writer.push() map(self.visit, node.body) writer.write('%s += 1' %iter_name ) - writer.pull() + if enumtar: + writer.write('%s += 1'%enumtar.id) + + writer.pull() else: - writer.write('for %s in %s:' %(self.visit(node.target),self.visit(node.iter))) + writer.write('for %s in %s:' %(self.visit(target),self.visit(iter))) writer.push() map(self.visit, node.body) + + if enumtar: + writer.write('%s += 1'%enumtar.id) + writer.pull() else: ## TODO else remove node.target.id from self._instances - if isinstance(node.iter, Name) and node.iter.id in self._global_typed_lists: - self._instances[ node.target.id ] = list( self._global_typed_lists[ node.iter.id ] )[0] + if isinstance(iter, Name) and iter.id in self._global_typed_lists: + self._instances[ target.id ] = list( self._global_typed_lists[ iter.id ] )[0] + + writer.write('var(__iterator__, %s)' % target.id) - self._for_iterator_target = node.target.id ## this could break with nested for loops - writer.write('var(__iterator__, %s)' % node.target.id) - is_range = False iter_start = '0' iter_end = None - if self.FAST_FOR and isinstance(node.iter, ast.Call) and isinstance(node.iter.func, Name) and node.iter.func.id in ('range','xrange'): + if self.FAST_FOR and isinstance(iter, ast.Call) and isinstance(iter.func, Name) and iter.func.id in ('range','xrange'): is_range = True - if len(node.iter.args) == 2: - iter_start = self.visit(node.iter.args[0]) - iter_end = self.visit(node.iter.args[1]) + if len(iter.args) == 2: + iter_start = self.visit(iter.args[0]) + iter_end = self.visit(iter.args[1]) else: - iter_end = self.visit(node.iter.args[0]) + iter_end = self.visit(iter.args[0]) else: - writer.write('__iterator__ = __get__(__get__(%s, "__iter__"), "__call__")(JSArray(), JSObject())' % self.visit(node.iter)) - - if self.FAST_FOR: - if is_range: - iter_name = node.target.id - #range_num = self.visit( node.iter.args[0] ) - writer.write('var(%s)' %iter_name) - writer.write('%s = %s' %(iter_name, iter_start)) - writer.write('while %s < %s:' %(iter_name, iter_end)) - writer.push() - map(self.visit, node.body) - writer.write('%s += 1' %iter_name ) - writer.pull() - else: - writer.write('var(__next__)') - writer.write('__next__ = __get__(__iterator__, "next_fast")') - writer.write('while __iterator__.index < __iterator__.length:') - writer.push() - writer.write('%s = __next__()' % node.target.id) - map(self.visit, node.body) - writer.pull() + writer.write('__iterator__ = __get__(__get__(%s, "__iter__"), "__call__")(JSArray(), JSObject())' % self.visit(iter)) - else: - writer.write('try:') - writer.push() - writer.write('%s = __get__(__iterator__, "next")(JSArray(), JSObject())' % node.target.id) - writer.write('while True:') + if is_range: + iter_name = target.id + writer.write('var(%s)' %iter_name) + writer.write('%s = %s' %(iter_name, iter_start)) + writer.write('while %s < %s:' %(iter_name, iter_end)) writer.push() map(self.visit, node.body) - writer.write('%s = __get__(__iterator__, "next")(JSArray(), JSObject())' % node.target.id) - writer.pull() + writer.write('%s += 1' %iter_name ) + + if enumtar: + writer.write('%s += 1'%enumtar.id) + writer.pull() - writer.write('except StopIteration:') + else: + writer.write('var(__next__)') + writer.write('__next__ = __get__(__iterator__, "next_fast")') + writer.write('while __iterator__.index < __iterator__.length:') + writer.push() - writer.write('pass') + writer.write('%s = __next__()' % target.id) + map(self.visit, node.body) + + if enumtar: + writer.write('%s += 1'%enumtar.id) + writer.pull() return '' @@ -1957,10 +1977,10 @@ def inspect_function( node ): -def main(script): - input = parse(script) - PythonToPythonJS().visit(input) - return writer.getvalue() +#def main(script): +# input = parse(script) +# PythonToPythonJS().visit(input) +# return writer.getvalue() def command(): @@ -1986,7 +2006,7 @@ def command(): data = sys.stdin.read() - compiler = PythonToPythonJS( module=module, module_path=module_path ) + compiler = PythonToPythonJS( source=data, module=module, module_path=module_path ) data = compiler.preprocess_custom_operators( data ) compiler.visit( parse(data) ) diff --git a/pythonjs/pythonjs.py b/pythonjs/pythonjs.py index 802e91d..b5eff59 100755 --- a/pythonjs/pythonjs.py +++ b/pythonjs/pythonjs.py @@ -139,6 +139,12 @@ def visit_Subscript(self, node): else: return '%s[%s]' % (self.visit(node.value), self.visit(node.slice)) + def visit_Index(self, node): + return self.visit(node.value) + + def visit_Slice(self, node): + raise SyntaxError ## slicing not allowed here at js level + def visit_arguments(self, node): out = [] for name in [self.visit(arg) for arg in node.args]: diff --git a/runtime/builtins.py b/runtime/builtins.py index 8febdef..5366875 100644 --- a/runtime/builtins.py +++ b/runtime/builtins.py @@ -355,9 +355,26 @@ def func(start, stop, step): def func(item): this.push( item ) + @Array.prototype.bisect + def func(x, low, high): + if low is None: low = 0 + if high is None: high = this.length + while low < high: + a = low+high + mid = Math.floor(a/2) + if x < this[mid]: + high = mid + else: + low = mid + 1 + return low _setup_array_prototype() +def bisect(a, x, low=None, high=None): + if isinstance(a, list): + return a[...].bisect(x, low, high) + else: + return a.bisect(x, low, high) def range(num, stop): diff --git a/tests/test_for_loop.html b/tests/test_for_loop.html index 239083a..5911080 100644 --- a/tests/test_for_loop.html +++ b/tests/test_for_loop.html @@ -52,6 +52,15 @@ print 'breaking' break + print 'testing enumerate' + for w,b in enumerate(r): + print w, b + + print 'testing enumerate - js' + with javascript: + for w,b in enumerate(r): + print w, b + From 274db9a7fc9f9fdfa0fe5d5877769cd9ba0714d5 Mon Sep 17 00:00:00 2001 From: hartsantler Date: Tue, 26 Nov 2013 14:34:11 -0800 Subject: [PATCH 009/521] improved comprehensions, generator expressions. fixed bug reported by Techtonik. --- pythonjs.js | 39 ++++++++++----- pythonjs/python_to_pythonjs.py | 77 ++++++++++++++++++++++++------ runtime/builtins.py | 18 +++++-- tests/test_dict_advanced.html | 9 +++- tests/test_list_comprehension.html | 5 ++ 5 files changed, 117 insertions(+), 31 deletions(-) diff --git a/pythonjs.js b/pythonjs.js index 2acdddd..b8f1dde 100644 --- a/pythonjs.js +++ b/pythonjs.js @@ -1,4 +1,4 @@ -// PythonScript Runtime - regenerated on: Tue Nov 26 02:12:03 2013 +// PythonScript Runtime - regenerated on: Tue Nov 26 14:31:15 2013 __NULL_OBJECT__ = Object.create(null); if (( "window" ) in this && ( "document" ) in this) { __NODEJS__ = false; @@ -1473,7 +1473,6 @@ __tuple_attrs = Object(); __tuple_parents = []; __tuple_properties = Object(); __tuple___init__ = function(args, kwargs) { - var arr; if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { @@ -1481,12 +1480,17 @@ __tuple___init__ = function(args, kwargs) { kwargs = Object(); } var signature, arguments; - signature = {"kwargs": {"js_object": undefined}, "args": __create_array__("self", "js_object")}; + signature = {"kwargs": {"js_object": undefined, "pointer": undefined}, "args": __create_array__("self", "js_object", "pointer")}; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var js_object = arguments['js_object']; - arr = []; - self["$wrapped"] = arr; + var pointer = arguments['pointer']; + if (pointer) { + self["$wrapped"] = pointer; + } else { + arr = []; + self["$wrapped"] = arr; + } if (js_object instanceof Array) { var __iterator__, item; __iterator__ = __get__(__get__(js_object, "__iter__"), "__call__")([], Object()); @@ -1515,9 +1519,9 @@ __tuple___init__ = function(args, kwargs) { } __tuple___init__.NAME = "__tuple___init__"; -__tuple___init__.args_signature = ["self", "js_object"]; -__tuple___init__.kwargs_signature = { js_object:undefined }; -__tuple___init__.types_signature = { js_object:"None" }; +__tuple___init__.args_signature = ["self", "js_object", "pointer"]; +__tuple___init__.kwargs_signature = { js_object:undefined,pointer:undefined }; +__tuple___init__.types_signature = { js_object:"None",pointer:"None" }; __tuple___init__.pythonscript_function = true; __tuple_attrs["__init__"] = __tuple___init__; __tuple___getitem__ = function(args, kwargs) { @@ -2174,7 +2178,20 @@ __dict___init__ = function(args, kwargs) { i += 1 } } else { - self["$wrapped"] = js_object; + if (isinstance([js_object, list], __NULL_OBJECT__)) { + var iter = js_object["$wrapped"]; + + if (! (iter instanceof Array) ) { iter = __object_keys__(iter) } + for (var item=0; item < iter.length; item++) { + var backup = item; item = iter[item]; + key = item["$wrapped"][ 0 ]; + value = item["$wrapped"][ 1 ]; + self["$wrapped"][ key ] = value; + item = backup; + } + } else { + self["$wrapped"] = js_object; + } } } } @@ -2538,12 +2555,12 @@ __array___init__ = function(args, kwargs) { self.length = len([initializer], __NULL_OBJECT__); self.bytes = self.length * self.itemsize; if (( self.typecode ) == "float8") { - self._scale = max([__get__(list, "__call__")([], {"js_object": [abs([min([initializer], __NULL_OBJECT__)], __NULL_OBJECT__), max([initializer], __NULL_OBJECT__)]})], __NULL_OBJECT__); + self._scale = max([__get__(list, "__call__")([], { pointer:[abs([min([initializer], __NULL_OBJECT__)], __NULL_OBJECT__), max([initializer], __NULL_OBJECT__)] })], __NULL_OBJECT__); self._norm_get = self._scale / 127; self._norm_set = 1.0 / self._norm_get; } else { if (( self.typecode ) == "float16") { - self._scale = max([__get__(list, "__call__")([], {"js_object": [abs([min([initializer], __NULL_OBJECT__)], __NULL_OBJECT__), max([initializer], __NULL_OBJECT__)]})], __NULL_OBJECT__); + self._scale = max([__get__(list, "__call__")([], { pointer:[abs([min([initializer], __NULL_OBJECT__)], __NULL_OBJECT__), max([initializer], __NULL_OBJECT__)] })], __NULL_OBJECT__); self._norm_get = self._scale / 32767; self._norm_set = 1.0 / self._norm_get; } diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index 115ec4d..87dbc16 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -366,7 +366,7 @@ def visit_Dict(self, node): def visit_Tuple(self, node): node.returns_type = 'tuple' a = '[%s]' % ', '.join(map(self.visit, node.elts)) - return '__get__(tuple, "__call__")([], {js_object:%s})' %a + return '__get__(tuple, "__call__")([], {pointer:%s})' %a def visit_List(self, node): node.returns_type = 'list' @@ -374,7 +374,7 @@ def visit_List(self, node): if self._with_js: return a else: - return '__get__(list, "__call__")([], JSObject(js_object=%s))' %a + return '__get__(list, "__call__")([], {pointer:%s})' %a def visit_ListComp(self, node): node.returns_type = 'list' @@ -392,31 +392,78 @@ def visit_ListComp(self, node): generators = list( node.generators ) self._gen_comp( generators, node ) - return '__get__(list, "__call__")([], JSObject(js_object=__comprehension__))' + return '__get__(list, "__call__")([], {pointer:__comprehension__})' def _gen_comp(self, generators, node): gen = generators.pop() - if len(gen.ifs): raise NotImplementedError ## TODO + #if len(gen.ifs): raise NotImplementedError ## TODO id = len(generators) assert isinstance(gen.target, Name) writer.write('idx%s = 0'%id) - writer.write('iter%s = %s' %(id, self.visit(gen.iter)) ) - writer.write('get%s = __get__(iter%s, "__getitem__")'%(id,id) ) - writer.write('while idx%s < __get__(len, "__call__")([iter%s], JSObject()):' %(id,id) ) - writer.push() - writer.write('var(%s)'%gen.target.id) - writer.write('%s=get%s( [idx%s], JSObject() )' %(gen.target.id, id,id) ) + is_range = False + if isinstance(gen.iter, ast.Call) and isinstance(gen.iter.func, ast.Name) and gen.iter.func.id in ('range', 'xrange'): + is_range = True + + #writer.write('iter%s = __get__(len, "__call__")([%s], JSObject())' %(id, self.visit(gen.iter.args[0])) ) + writer.write('iter%s = %s' %(id, self.visit(gen.iter.args[0])) ) + writer.write('while idx%s < iter%s:' %(id,id) ) + writer.push() + + writer.write('var(%s)'%gen.target.id) + writer.write('%s=idx%s' %(gen.target.id, id) ) + + else: + writer.write('iter%s = %s' %(id, self.visit(gen.iter)) ) + writer.write('get%s = __get__(iter%s, "__getitem__")'%(id,id) ) + + + writer.write('while idx%s < __get__(len, "__call__")([iter%s], JSObject()):' %(id,id) ) ## TODO optimize + writer.push() + + writer.write('var(%s)'%gen.target.id) + writer.write('%s=get%s( [idx%s], JSObject() )' %(gen.target.id, id,id) ) if generators: self._gen_comp( generators, node ) else: - writer.write('__comprehension__.push( %s )' %self.visit(node.elt) ) + if len(gen.ifs): + test = [] + for compare in gen.ifs: + test.append( self.visit(compare) ) + + writer.write('if %s:' %' and '.join(test)) + + writer.push() + writer.write('__comprehension__.push( %s )' %self.visit(node.elt) ) + writer.pull() + else: + + writer.write('__comprehension__.push( %s )' %self.visit(node.elt) ) writer.write('idx%s+=1' %id ) writer.pull() + def visit_GeneratorExp(self, node): + node.returns_type = 'list' + writer.write('var(__comprehension__)') + writer.write('__comprehension__ = JSArray()') + + length = len( node.generators ) + a = ['idx%s'%i for i in range(length)] + writer.write('var( %s )' %','.join(a) ) + a = ['iter%s'%i for i in range(length)] + writer.write('var( %s )' %','.join(a) ) + a = ['get%s'%i for i in range(length)] + writer.write('var( %s )' %','.join(a) ) + + generators = list( node.generators ) + self._gen_comp( generators, node ) + + return '__get__(list, "__call__")([], {pointer:__comprehension__})' + + def visit_In(self, node): return ' in ' @@ -1977,10 +2024,10 @@ def inspect_function( node ): -#def main(script): -# input = parse(script) -# PythonToPythonJS().visit(input) -# return writer.getvalue() +def main(script): + input = parse(script) + PythonToPythonJS( source=script ).visit(input) + return writer.getvalue() def command(): diff --git a/runtime/builtins.py b/runtime/builtins.py index 5366875..1edb983 100644 --- a/runtime/builtins.py +++ b/runtime/builtins.py @@ -458,10 +458,13 @@ def next_fast(self): class tuple: - def __init__(self, js_object=None): + def __init__(self, js_object=None, pointer=None): with javascript: - arr = [] - self[...] = arr + if pointer: + self[...] = pointer + else: + arr = [] + self[...] = arr if instanceof( js_object, Array ): for item in js_object: @@ -640,7 +643,14 @@ def __init__(self, js_object=None): JS('var value = js_object[i]["value"]') self.set(key, value) i += 1 - else: + + elif isinstance(js_object, list): + with javascript: + for item in js_object[...]: + key = item[...][0] + value = item[...][1] + self[...][ key ] = value + else: ## TODO - deprecate self[...] = js_object diff --git a/tests/test_dict_advanced.html b/tests/test_dict_advanced.html index 3501ab4..d966f06 100644 --- a/tests/test_dict_advanced.html +++ b/tests/test_dict_advanced.html @@ -14,7 +14,7 @@ def test(): - global d, k1, k2 + global d, k1, k2, g k1 = Key1() k2 = Key2() @@ -42,6 +42,13 @@ print d.keys() print d.values() + a = ['h', 'e', 'l', 'l', 'o'] + + print 'testing dict init from gen' + g = dict( (a[i], i) for i in xrange(len(a)) ) + print g.keys()[...] + print g.values()[...] + diff --git a/tests/test_list_comprehension.html b/tests/test_list_comprehension.html index 1177fdf..d7f283e 100644 --- a/tests/test_list_comprehension.html +++ b/tests/test_list_comprehension.html @@ -26,6 +26,11 @@ for v in x: print chr(v) + print 'testing if' + x = [ ord(c) for c in lst if c=='l'] + for v in x: + print chr(v) + print 'test complete' From 424275819a93f80df3020087d7e8effbfc4e258e Mon Sep 17 00:00:00 2001 From: hartsantler Date: Tue, 26 Nov 2013 19:46:46 -0800 Subject: [PATCH 010/521] fixed nested list comprehensions --- pythonjs.js | 104 +++++++++++++++++++++++++++-- pythonjs/python_to_pythonjs.py | 67 ++++++++++++------- runtime/builtins.py | 33 ++++++++- tests/test_list_comprehension.html | 17 ++++- tests/test_string.html | 3 + 5 files changed, 192 insertions(+), 32 deletions(-) diff --git a/pythonjs.js b/pythonjs.js index b8f1dde..cdd9398 100644 --- a/pythonjs.js +++ b/pythonjs.js @@ -1,4 +1,4 @@ -// PythonScript Runtime - regenerated on: Tue Nov 26 14:31:15 2013 +// PythonScript Runtime - regenerated on: Tue Nov 26 17:16:46 2013 __NULL_OBJECT__ = Object.create(null); if (( "window" ) in this && ( "document" ) in this) { __NODEJS__ = false; @@ -874,10 +874,14 @@ _setup_str_prototype = function(args, kwargs) { String.prototype.__len__=func; var func = function(start, stop, step) { var stop; - if (( stop ) < 0) { - stop = this.length + stop; + if (( start ) === undefined && ( stop ) === undefined && ( step ) == -1) { + return this.split("").reverse().join(""); + } else { + if (( stop ) < 0) { + stop = this.length + stop; + } + return this.substring(start,stop); } - return this.substring(start,stop); } func.NAME = "func"; @@ -1193,6 +1197,26 @@ range.kwargs_signature = { }; range.types_signature = { }; range.return_type = "list"; range.pythonscript_function = true; +xrange = function(args, kwargs) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { + /*pass*/ + } else { + args = Array.prototype.slice.call(arguments); + kwargs = Object(); + } + var signature, arguments; + signature = {"kwargs": Object(), "args": __create_array__("num", "stop")}; + arguments = get_arguments(signature, args, kwargs); + var num = arguments['num']; + var stop = arguments['stop']; + return range([num, stop], __NULL_OBJECT__); +} + +xrange.NAME = "xrange"; +xrange.args_signature = ["num", "stop"]; +xrange.kwargs_signature = { }; +xrange.types_signature = { }; +xrange.pythonscript_function = true; var StopIteration, __StopIteration_attrs, __StopIteration_parents; __StopIteration_attrs = Object(); __StopIteration_parents = []; @@ -2525,6 +2549,76 @@ __dict___iter__.return_type = "Iterator"; __dict___iter__.pythonscript_function = true; __dict_attrs["__iter__"] = __dict___iter__; dict = create_class("dict", __dict_parents, __dict_attrs, __dict_properties); +set = function(args, kwargs) { + var h, arr; + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { + /*pass*/ + } else { + args = Array.prototype.slice.call(arguments); + kwargs = Object(); + } + var signature, arguments; + signature = {"kwargs": Object(), "args": __create_array__("a")}; + arguments = get_arguments(signature, args, kwargs); + var a = arguments['a']; + arr = []; + h = Object.create(null); + if (isinstance(a, list)) { + var iter = a["$wrapped"]; + + if (! (iter instanceof Array) ) { iter = __object_keys__(iter) } + for (var item=0; item < iter.length; item++) { + var backup = item; item = iter[item]; + if (( item ) in h || Object.hasOwnProperty.call(h, "__contains__") && h["__contains__"](item)) { + continue; + } else { + h[ item ] = true; + arr.push(item); + } + item = backup; + } + } else { + var iter = a; + + if (! (iter instanceof Array) ) { iter = __object_keys__(iter) } + for (var item=0; item < iter.length; item++) { + var backup = item; item = iter[item]; + if (( item ) in h || Object.hasOwnProperty.call(h, "__contains__") && h["__contains__"](item)) { + continue; + } else { + h[ item ] = true; + arr.push(item); + } + item = backup; + } + } + return arr; +} + +set.NAME = "set"; +set.args_signature = ["a"]; +set.kwargs_signature = { }; +set.types_signature = { }; +set.pythonscript_function = true; +frozenset = function(args, kwargs) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { + /*pass*/ + } else { + args = Array.prototype.slice.call(arguments); + kwargs = Object(); + } + var signature, arguments; + signature = {"kwargs": Object(), "args": __create_array__("a")}; + arguments = get_arguments(signature, args, kwargs); + var a = arguments['a']; + return set([a], __NULL_OBJECT__); +} + +frozenset.NAME = "frozenset"; +frozenset.args_signature = ["a"]; +frozenset.kwargs_signature = { }; +frozenset.types_signature = { }; +frozenset.pythonscript_function = true; var array, __array_attrs, __array_parents; __array_attrs = Object(); __array_parents = []; @@ -3018,7 +3112,7 @@ _to_pythonjs = function(args, kwargs) { __next__ = __get__(__iterator__, "next_fast"); while(( __iterator__.index ) < __iterator__.length) { key = __next__(); - __get__(set, "__call__")([key, _to_pythonjs([json[key]], __NULL_OBJECT__)], __NULL_OBJECT__); + set([key, _to_pythonjs([json[key]], __NULL_OBJECT__)], __NULL_OBJECT__); } return output; } diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index 87dbc16..1a92ca1 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -207,6 +207,7 @@ def __init__(self, source=None, module=None, module_path=None): self._cache_for_body_calls = False self._cache_while_body_calls = False + self._comprehensions = [] self._custom_operators = {} self._injector = [] ## advanced meta-programming hacks @@ -376,10 +377,23 @@ def visit_List(self, node): else: return '__get__(list, "__call__")([], {pointer:%s})' %a + def visit_GeneratorExp(self, node): + return self.visit_ListComp(node) + + def visit_ListComp(self, node): node.returns_type = 'list' - writer.write('var(__comprehension__)') - writer.write('__comprehension__ = JSArray()') + + if len(self._comprehensions) == 0: + comps = collect_comprehensions( node ) + for i,cnode in enumerate(comps): + cname = '__comprehension%s' % i + cnode._comp_name = cname + self._comprehensions.append( cnode ) + + cname = node._comp_name + writer.write('var(%s)'%cname) + writer.write('%s = JSArray()'%cname) length = len( node.generators ) a = ['idx%s'%i for i in range(length)] @@ -392,13 +406,14 @@ def visit_ListComp(self, node): generators = list( node.generators ) self._gen_comp( generators, node ) - return '__get__(list, "__call__")([], {pointer:__comprehension__})' + self._comprehensions.remove( node ) + return '__get__(list, "__call__")([], {pointer:%s})' %cname def _gen_comp(self, generators, node): gen = generators.pop() #if len(gen.ifs): raise NotImplementedError ## TODO - id = len(generators) + id = len(generators) + self._comprehensions.index( node ) assert isinstance(gen.target, Name) writer.write('idx%s = 0'%id) @@ -428,6 +443,7 @@ def _gen_comp(self, generators, node): if generators: self._gen_comp( generators, node ) else: + cname = node._comp_name #self._comprehensions[-1] if len(gen.ifs): test = [] for compare in gen.ifs: @@ -436,32 +452,15 @@ def _gen_comp(self, generators, node): writer.write('if %s:' %' and '.join(test)) writer.push() - writer.write('__comprehension__.push( %s )' %self.visit(node.elt) ) + writer.write('%s.push( %s )' %(cname,self.visit(node.elt)) ) writer.pull() else: - writer.write('__comprehension__.push( %s )' %self.visit(node.elt) ) + writer.write('%s.push( %s )' %(cname,self.visit(node.elt)) ) writer.write('idx%s+=1' %id ) writer.pull() - def visit_GeneratorExp(self, node): - node.returns_type = 'list' - writer.write('var(__comprehension__)') - writer.write('__comprehension__ = JSArray()') - - length = len( node.generators ) - a = ['idx%s'%i for i in range(length)] - writer.write('var( %s )' %','.join(a) ) - a = ['iter%s'%i for i in range(length)] - writer.write('var( %s )' %','.join(a) ) - a = ['get%s'%i for i in range(length)] - writer.write('var( %s )' %','.join(a) ) - - generators = list( node.generators ) - self._gen_comp( generators, node ) - - return '__get__(list, "__call__")([], {pointer:__comprehension__})' def visit_In(self, node): @@ -1966,6 +1965,28 @@ def collect_returns(node): CollectReturns().visit( node ) return returns +class CollectComprehensions(NodeVisitor): + _comps_ = [] + def visit_GeneratorExp(self,node): + self._comps_.append( node ) + self.visit( node.elt ) + for gen in node.generators: + self.visit( gen.iter ) + self.visit( gen.target ) + def visit_ListComp(self, node): + self._comps_.append( node ) + self.visit( node.elt ) + for gen in node.generators: + self.visit( gen.iter ) + self.visit( gen.target ) + +def collect_comprehensions(node): + CollectComprehensions._comps_ = comps = [] + CollectComprehensions().visit( node ) + assert comps + return comps + + def retrieve_vars(body): local_vars = set() global_vars = set() diff --git a/runtime/builtins.py b/runtime/builtins.py index 1edb983..2140da3 100644 --- a/runtime/builtins.py +++ b/runtime/builtins.py @@ -251,9 +251,12 @@ def func(): @String.prototype.__getslice__ def func(start, stop, step): - if stop < 0: - stop = this.length + stop - return this.substring(start, stop) + if start is None and stop is None and step == -1: + return this.split('').reverse().join('') + else: + if stop < 0: + stop = this.length + stop + return this.substring(start, stop) @String.prototype.splitlines def func(): @@ -391,6 +394,8 @@ def range(num, stop): i += 1 return list( pointer=arr ) +def xrange(num, stop): + return range(num, stop) class StopIteration: pass @@ -774,6 +779,28 @@ def __iter__(self): return Iterator(self.keys(), 0) +def set(a): + with javascript: + arr = [] + h = Object.create(null) + if isinstance(a, list): + for item in a[...]: + if item in h: + continue + else: + h[item] = True + arr.push( item ) + else: + for item in a: + if item in h: + continue + else: + h[item] = True + arr.push( item ) + return arr + +def frozenset(a): + return set(a) class array: diff --git a/tests/test_list_comprehension.html b/tests/test_list_comprehension.html index d7f283e..98d47f7 100644 --- a/tests/test_list_comprehension.html +++ b/tests/test_list_comprehension.html @@ -6,7 +6,7 @@ def test(): - global lst, a, b + global lst, a, b, x,y,z print 'testing list of chars...' lst = ['h', 'e', 'l', 'l', 'o'] @@ -31,6 +31,21 @@ for v in x: print chr(v) + print 'testing nested1' ## TODO fix nested comprehensions + y = [ [['hello', 'world'] for p in xrange(3)] for ci in xrange(4)] + print len(y[0]) ## this should be 3 + + + print 'testing nested2' ## TODO fix nested comprehensions + nested = [ + [1,2,3], + [4,5,6] + ] + z = [ [p*p for p in n] for n in nested] + print len(z) + print len(z[0]) + + print 'test complete' diff --git a/tests/test_string.html b/tests/test_string.html index 51417b2..e4d2ecd 100644 --- a/tests/test_string.html +++ b/tests/test_string.html @@ -69,6 +69,9 @@ for line in m.splitlines(): print line + print 'testing reverse string' + print a[::-1] + print 'tests complete' From 72623e2f229da283642be24aedc40c8fbc2e1508 Mon Sep 17 00:00:00 2001 From: hartsantler Date: Wed, 27 Nov 2013 17:22:23 -0800 Subject: [PATCH 011/521] fixed list comprehensions and set implementation --- pythonjs.js | 135 ++++++++++++++++++++++------- pythonjs/python_to_pythonjs.py | 2 +- runtime/builtins.py | 62 +++++++++---- tests/test_JSArray.html | 12 +++ tests/test_list_comprehension.html | 9 +- 5 files changed, 172 insertions(+), 48 deletions(-) diff --git a/pythonjs.js b/pythonjs.js index cdd9398..b8fe43d 100644 --- a/pythonjs.js +++ b/pythonjs.js @@ -1,4 +1,4 @@ -// PythonScript Runtime - regenerated on: Tue Nov 26 17:16:46 2013 +// PythonScript Runtime - regenerated on: Wed Nov 27 17:19:14 2013 __NULL_OBJECT__ = Object.create(null); if (( "window" ) in this && ( "document" ) in this) { __NODEJS__ = false; @@ -1101,6 +1101,17 @@ _setup_array_prototype = function(args, kwargs) { func.kwargs_signature = {}; func.types_signature = {}; Array.prototype.append=func; + var func = function(item) { + var index; + index = this.indexOf(item); + this.splice(index,1); + } + + func.NAME = "func"; + func.args_signature = ["item"]; + func.kwargs_signature = {}; + func.types_signature = {}; + Array.prototype.remove=func; var func = function(x, low, high) { var high, a, low, mid; if (( low ) === undefined) { @@ -1126,6 +1137,43 @@ _setup_array_prototype = function(args, kwargs) { func.kwargs_signature = {}; func.types_signature = {}; Array.prototype.bisect=func; + var func = function(other) { + return this.filter((function (i) {return other.indexOf(i) == -1})); + } + + func.NAME = "func"; + func.args_signature = ["other"]; + func.kwargs_signature = {}; + func.types_signature = {}; + Array.prototype.difference=func; + var func = function(other) { + return this.filter((function (i) {return other.indexOf(i) != -1})); + } + + func.NAME = "func"; + func.args_signature = ["other"]; + func.kwargs_signature = {}; + func.types_signature = {}; + Array.prototype.intersection=func; + var func = function(other) { + var iter = this; + + if (! (iter instanceof Array) ) { iter = __object_keys__(iter) } + for (var item=0; item < iter.length; item++) { + var backup = item; item = iter[item]; + if (( other.indexOf(item) ) == -1) { + return false; + } + item = backup; + } + return true; + } + + func.NAME = "func"; + func.args_signature = ["other"]; + func.kwargs_signature = {}; + func.types_signature = {}; + Array.prototype.issubset=func; } _setup_array_prototype.NAME = "_setup_array_prototype"; @@ -1614,6 +1662,25 @@ __tuple___len__.kwargs_signature = { }; __tuple___len__.types_signature = { }; __tuple___len__.pythonscript_function = true; __tuple_attrs["__len__"] = __tuple___len__; +__tuple_length__getprop__ = function(args, kwargs) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { + /*pass*/ + } else { + args = Array.prototype.slice.call(arguments); + kwargs = Object(); + } + var signature, arguments; + signature = {"kwargs": Object(), "args": __create_array__("self")}; + arguments = get_arguments(signature, args, kwargs); + var self = arguments['self']; + return self["$wrapped"].length; +} + +__tuple_length__getprop__.NAME = "__tuple_length__getprop__"; +__tuple_length__getprop__.args_signature = ["self"]; +__tuple_length__getprop__.kwargs_signature = { }; +__tuple_length__getprop__.types_signature = { }; +__tuple_length__getprop__.pythonscript_function = true; __tuple_index = function(args, kwargs) { if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ @@ -1714,6 +1781,8 @@ __tuple___contains__.kwargs_signature = { }; __tuple___contains__.types_signature = { }; __tuple___contains__.pythonscript_function = true; __tuple_attrs["__contains__"] = __tuple___contains__; +__tuple_properties["length"] = Object(); +__tuple_properties["length"]["get"] = __tuple_length__getprop__; tuple = create_class("tuple", __tuple_parents, __tuple_attrs, __tuple_properties); var list, __list_attrs, __list_parents; __list_attrs = Object(); @@ -2146,6 +2215,25 @@ __list___len__.kwargs_signature = { }; __list___len__.types_signature = { }; __list___len__.pythonscript_function = true; __list_attrs["__len__"] = __list___len__; +__list_length__getprop__ = function(args, kwargs) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { + /*pass*/ + } else { + args = Array.prototype.slice.call(arguments); + kwargs = Object(); + } + var signature, arguments; + signature = {"kwargs": Object(), "args": __create_array__("self")}; + arguments = get_arguments(signature, args, kwargs); + var self = arguments['self']; + return self["$wrapped"].length; +} + +__list_length__getprop__.NAME = "__list_length__getprop__"; +__list_length__getprop__.args_signature = ["self"]; +__list_length__getprop__.kwargs_signature = { }; +__list_length__getprop__.types_signature = { }; +__list_length__getprop__.pythonscript_function = true; __list___contains__ = function(args, kwargs) { if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ @@ -2171,6 +2259,8 @@ __list___contains__.kwargs_signature = { }; __list___contains__.types_signature = { }; __list___contains__.pythonscript_function = true; __list_attrs["__contains__"] = __list___contains__; +__list_properties["length"] = Object(); +__list_properties["length"]["get"] = __list_length__getprop__; list = create_class("list", __list_parents, __list_attrs, __list_properties); var dict, __dict_attrs, __dict_parents; __dict_attrs = Object(); @@ -2550,7 +2640,7 @@ __dict___iter__.pythonscript_function = true; __dict_attrs["__iter__"] = __dict___iter__; dict = create_class("dict", __dict_parents, __dict_attrs, __dict_properties); set = function(args, kwargs) { - var h, arr; + var s; if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { @@ -2561,38 +2651,25 @@ set = function(args, kwargs) { signature = {"kwargs": Object(), "args": __create_array__("a")}; arguments = get_arguments(signature, args, kwargs); var a = arguments['a']; - arr = []; - h = Object.create(null); + "\n Python docs say that set are unordered, yet when created from a list, \n it always moves the last item to the second element.\n "; + s = []; if (isinstance(a, list)) { - var iter = a["$wrapped"]; - - if (! (iter instanceof Array) ) { iter = __object_keys__(iter) } - for (var item=0; item < iter.length; item++) { - var backup = item; item = iter[item]; - if (( item ) in h || Object.hasOwnProperty.call(h, "__contains__") && h["__contains__"](item)) { - continue; - } else { - h[ item ] = true; - arr.push(item); - } - item = backup; - } + b = a["$wrapped"].slice(); } else { - var iter = a; + b = a.slice(); + } + b.splice(1,0,b[ b.length - 1 ]); + var iter = b; - if (! (iter instanceof Array) ) { iter = __object_keys__(iter) } - for (var item=0; item < iter.length; item++) { - var backup = item; item = iter[item]; - if (( item ) in h || Object.hasOwnProperty.call(h, "__contains__") && h["__contains__"](item)) { - continue; - } else { - h[ item ] = true; - arr.push(item); - } - item = backup; + if (! (iter instanceof Array) ) { iter = __object_keys__(iter) } + for (var item=0; item < iter.length; item++) { + var backup = item; item = iter[item]; + if (( s.indexOf(item) ) == -1) { + s.push(item); } + item = backup; } - return arr; + return s; } set.NAME = "set"; diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index 1a92ca1..352d861 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -404,6 +404,7 @@ def visit_ListComp(self, node): writer.write('var( %s )' %','.join(a) ) generators = list( node.generators ) + generators.reverse() self._gen_comp( generators, node ) self._comprehensions.remove( node ) @@ -1983,7 +1984,6 @@ def visit_ListComp(self, node): def collect_comprehensions(node): CollectComprehensions._comps_ = comps = [] CollectComprehensions().visit( node ) - assert comps return comps diff --git a/runtime/builtins.py b/runtime/builtins.py index 2140da3..1dfb6f2 100644 --- a/runtime/builtins.py +++ b/runtime/builtins.py @@ -358,6 +358,11 @@ def func(start, stop, step): def func(item): this.push( item ) + @Array.prototype.remove + def func(item): + index = this.indexOf( item ) + this.splice(index, 1) + @Array.prototype.bisect def func(x, low, high): if low is None: low = 0 @@ -371,6 +376,23 @@ def func(x, low, high): low = mid + 1 return low + ## set-like features ## + ## `-` operator + @Array.prototype.difference + def func(other): + return this.filter( lambda i: other.indexOf(i)==-1) + ## `&` operator + @Array.prototype.intersection + def func(other): + return this.filter( lambda i: other.indexOf(i)!=-1) + ## `<=` operator + @Array.prototype.issubset + def func(other): + for item in this: + if other.indexOf(item) == -1: + return False + return True + _setup_array_prototype() def bisect(a, x, low=None, high=None): @@ -499,6 +521,11 @@ def __len__(self): with javascript: return self[...].length + @property + def length(self): + with javascript: + return self[...].length + def index(self, obj): with javascript: return self[...].indexOf(obj) @@ -624,6 +651,11 @@ def __len__(self): with javascript: return self[...].length + @property + def length(self): + with javascript: + return self[...].length + def __contains__(self, value): with javascript: if self[...].indexOf(value) == -1: @@ -780,24 +812,20 @@ def __iter__(self): def set(a): + ''' + Python docs say that set are unordered, yet when created from a list, + it always moves the last item to the second element. + ''' with javascript: - arr = [] - h = Object.create(null) - if isinstance(a, list): - for item in a[...]: - if item in h: - continue - else: - h[item] = True - arr.push( item ) - else: - for item in a: - if item in h: - continue - else: - h[item] = True - arr.push( item ) - return arr + s = [] + if isinstance(a, list): b = a[...].slice() + else: b = a.slice() + b.splice(1, 0, b[b.length-1]) + for item in b: + if s.indexOf(item) == -1: + s.push( item ) + return s + def frozenset(a): return set(a) diff --git a/tests/test_JSArray.html b/tests/test_JSArray.html index c837952..ade5da1 100644 --- a/tests/test_JSArray.html +++ b/tests/test_JSArray.html @@ -36,6 +36,18 @@ print 'checking JSObject' print jsob + print 'testing difference' + with javascript: + a = [1,2,3,4] + b = [1,2, 55] + c = a.difference( b ) + print c + + print 'testing intersection' + d = a.intersection( b ) + print d + print len(d) + diff --git a/tests/test_list_comprehension.html b/tests/test_list_comprehension.html index 98d47f7..fe2435d 100644 --- a/tests/test_list_comprehension.html +++ b/tests/test_list_comprehension.html @@ -22,7 +22,7 @@ ## note: 'string'.split is javascript function, and returns an array not a list! print 'testing for char in word for word in words...' words = 'hello world foo bar'.split(' ') - x = [ ord(c) for c in word for word in words ] + x = [ ord(c) for word in words for c in word ] for v in x: print chr(v) @@ -45,6 +45,13 @@ print len(z) print len(z[0]) + print 'testing nested3' + w = 5 + h = 10 + u = [x+y for y in range(h) for x in range(w)] + print u + if u[5] != 1: + print 'ERROR - u[5] is not 1', u[5] print 'test complete' From 309283212b5bb22dfdfc916967ef2e1fd9108037 Mon Sep 17 00:00:00 2001 From: hartsantler Date: Thu, 28 Nov 2013 19:14:59 -0800 Subject: [PATCH 012/521] improved set implementation --- pythonjs.js | 79 ++++++++++++++++++++++++++++++++++++-------- pythonjs/pythonjs.py | 8 ++++- runtime/builtins.py | 70 ++++++++++++++++++++++++++++++++++----- tests/test_set.html | 26 +++++++++++++++ 4 files changed, 160 insertions(+), 23 deletions(-) create mode 100644 tests/test_set.html diff --git a/pythonjs.js b/pythonjs.js index b8fe43d..c41ec48 100644 --- a/pythonjs.js +++ b/pythonjs.js @@ -1,4 +1,4 @@ -// PythonScript Runtime - regenerated on: Wed Nov 27 17:19:14 2013 +// PythonScript Runtime - regenerated on: Thu Nov 28 19:10:55 2013 __NULL_OBJECT__ = Object.create(null); if (( "window" ) in this && ( "document" ) in this) { __NODEJS__ = false; @@ -2640,7 +2640,7 @@ __dict___iter__.pythonscript_function = true; __dict_attrs["__iter__"] = __dict___iter__; dict = create_class("dict", __dict_parents, __dict_attrs, __dict_properties); set = function(args, kwargs) { - var s; + var s, fallback, hashtable; if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { @@ -2651,23 +2651,74 @@ set = function(args, kwargs) { signature = {"kwargs": Object(), "args": __create_array__("a")}; arguments = get_arguments(signature, args, kwargs); var a = arguments['a']; - "\n Python docs say that set are unordered, yet when created from a list, \n it always moves the last item to the second element.\n "; - s = []; + "\n This returns an array that is a minimal implementation of set.\n Often sets are used simply to remove duplicate entries from a list, \n and then it get converted back to a list, it is safe to use fastset for this.\n\n The array prototype is overloaded with basic set functions:\n difference\n intersection\n issubset\n\n Note: sets in Python are not subscriptable, but can be iterated over.\n\n Python docs say that set are unordered, some programs may rely on this disorder\n for randomness, for sets of integers we emulate the unorder only uppon initalization \n of the set, by masking the value by bits-1. Python implements sets starting with an \n array of length 8, and mask of 7, if set length grows to 6 (3/4th), then it allocates \n a new array of length 32 and mask of 31. This is only emulated for arrays of \n integers up to an array length of 1536.\n\n "; if (isinstance(a, list)) { - b = a["$wrapped"].slice(); + a = a["$wrapped"]; + } + hashtable = null; + if (( a.length ) <= 1536) { + hashtable = { }; + keys = []; + if (( a.length ) < 6) { + mask = 7; + } else { + if (( a.length ) < 22) { + mask = 31; + } else { + if (( a.length ) < 86) { + mask = 127; + } else { + if (( a.length ) < 342) { + mask = 511; + } else { + mask = 2047; + } + } + } + } + } + fallback = false; + if (hashtable) { + var iter = a; + + if (! (iter instanceof Array) ) { iter = __object_keys__(iter) } + for (var b=0; b < iter.length; b++) { + var backup = b; b = iter[b]; + if (typeof(b, "number") && ( b ) === ( b | 0 )) { + key = b & mask; + hashtable[ key ] = b; + keys.push(key); + } else { + fallback = true; + break; + } + b = backup; + } } else { - b = a.slice(); + fallback = true; } - b.splice(1,0,b[ b.length - 1 ]); - var iter = b; + s = []; + if (fallback) { + var iter = a; - if (! (iter instanceof Array) ) { iter = __object_keys__(iter) } - for (var item=0; item < iter.length; item++) { - var backup = item; item = iter[item]; - if (( s.indexOf(item) ) == -1) { - s.push(item); + if (! (iter instanceof Array) ) { iter = __object_keys__(iter) } + for (var item=0; item < iter.length; item++) { + var backup = item; item = iter[item]; + if (( s.indexOf(item) ) == -1) { + s.push(item); + } + item = backup; + } + } else { + keys.sort(); + var iter = keys; + + if (! (iter instanceof Array) ) { iter = __object_keys__(iter) } + for (var key=0; key < iter.length; key++) { + var backup = key; key = iter[key]; + s.push(hashtable[ key ]); + key = backup; } - item = backup; } return s; } diff --git a/pythonjs/pythonjs.py b/pythonjs/pythonjs.py index b5eff59..7259d9f 100755 --- a/pythonjs/pythonjs.py +++ b/pythonjs/pythonjs.py @@ -341,7 +341,13 @@ def visit_Compare(self, node): comp.append( ')' ) for i in range( len(node.ops) ): comp.append( self.visit(node.ops[i]) ) - comp.append( self.visit(node.comparators[i]) ) + if isinstance(node.comparators[i], ast.BinOp): + comp.append('(') + comp.append( self.visit(node.comparators[i]) ) + comp.append(')') + else: + comp.append( self.visit(node.comparators[i]) ) + return ' '.join( comp ) def visit_Not(self, node): diff --git a/runtime/builtins.py b/runtime/builtins.py index 1dfb6f2..08765f8 100644 --- a/runtime/builtins.py +++ b/runtime/builtins.py @@ -811,19 +811,70 @@ def __iter__(self): return Iterator(self.keys(), 0) + def set(a): ''' - Python docs say that set are unordered, yet when created from a list, - it always moves the last item to the second element. + This returns an array that is a minimal implementation of set. + Often sets are used simply to remove duplicate entries from a list, + and then it get converted back to a list, it is safe to use fastset for this. + + The array prototype is overloaded with basic set functions: + difference + intersection + issubset + + Note: sets in Python are not subscriptable, but can be iterated over. + + Python docs say that set are unordered, some programs may rely on this disorder + for randomness, for sets of integers we emulate the unorder only uppon initalization + of the set, by masking the value by bits-1. Python implements sets starting with an + array of length 8, and mask of 7, if set length grows to 6 (3/4th), then it allocates + a new array of length 32 and mask of 31. This is only emulated for arrays of + integers up to an array length of 1536. + ''' with javascript: + if isinstance(a, list): a = a[...] + hashtable = null + if a.length <= 1536: + hashtable = {} + keys = [] + if a.length < 6: ## hash array length 8 + mask = 7 + elif a.length < 22: ## 32 + mask = 31 + elif a.length < 86: ## 128 + mask = 127 + elif a.length < 342: ## 512 + mask = 511 + else: ## 2048 + mask = 2047 + + fallback = False + if hashtable: + for b in a: + if typeof(b,'number') and b is (b|0): ## set if integer + key = b & mask + hashtable[ key ] = b + keys.push( key ) + else: + fallback = True + break + + else: + fallback = True + s = [] - if isinstance(a, list): b = a[...].slice() - else: b = a.slice() - b.splice(1, 0, b[b.length-1]) - for item in b: - if s.indexOf(item) == -1: - s.push( item ) + + if fallback: + for item in a: + if s.indexOf(item) == -1: + s.push( item ) + else: + keys.sort() + for key in keys: + s.push( hashtable[key] ) + return s @@ -831,6 +882,9 @@ def frozenset(a): return set(a) + + + class array: ## note that class-level dicts can only be used after the dict class has been defined above, ## however, we can still not rely on using a dict here because dict creation relies on get_attribute, diff --git a/tests/test_set.html b/tests/test_set.html new file mode 100644 index 0000000..084b199 --- /dev/null +++ b/tests/test_set.html @@ -0,0 +1,26 @@ + + + + + + + + + + + \ No newline at end of file From 0c6616a2ea7463430778e2e4f8cc8d8bbe8eec40 Mon Sep 17 00:00:00 2001 From: hartsantler Date: Fri, 29 Nov 2013 12:54:29 -0800 Subject: [PATCH 013/521] new benchmark tests --- tests/bench_float.html | 74 ++++++++++++++++ tests/bench_float_fast.html | 75 ++++++++++++++++ tests/nbody.html | 163 +++++++++++++++++++++++++++++++++++ tests/nbody_fast.html | 166 ++++++++++++++++++++++++++++++++++++ tests/nbody_ultra_fast.html | 166 ++++++++++++++++++++++++++++++++++++ tests/test_expressions.html | 23 +++++ 6 files changed, 667 insertions(+) create mode 100644 tests/bench_float.html create mode 100644 tests/bench_float_fast.html create mode 100644 tests/nbody.html create mode 100644 tests/nbody_fast.html create mode 100644 tests/nbody_ultra_fast.html create mode 100644 tests/test_expressions.html diff --git a/tests/bench_float.html b/tests/bench_float.html new file mode 100644 index 0000000..63599b7 --- /dev/null +++ b/tests/bench_float.html @@ -0,0 +1,74 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/tests/bench_float_fast.html b/tests/bench_float_fast.html new file mode 100644 index 0000000..674aa5f --- /dev/null +++ b/tests/bench_float_fast.html @@ -0,0 +1,75 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/tests/nbody.html b/tests/nbody.html new file mode 100644 index 0000000..2b2080d --- /dev/null +++ b/tests/nbody.html @@ -0,0 +1,163 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/tests/nbody_fast.html b/tests/nbody_fast.html new file mode 100644 index 0000000..a9fa66a --- /dev/null +++ b/tests/nbody_fast.html @@ -0,0 +1,166 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/tests/nbody_ultra_fast.html b/tests/nbody_ultra_fast.html new file mode 100644 index 0000000..9ba8d9f --- /dev/null +++ b/tests/nbody_ultra_fast.html @@ -0,0 +1,166 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/tests/test_expressions.html b/tests/test_expressions.html new file mode 100644 index 0000000..ce167cc --- /dev/null +++ b/tests/test_expressions.html @@ -0,0 +1,23 @@ + + + + + + + + + + + \ No newline at end of file From 1debf1f5dde0f7061498e0123fd0f09adabb779e Mon Sep 17 00:00:00 2001 From: hartsantler Date: Fri, 29 Nov 2013 12:55:55 -0800 Subject: [PATCH 014/521] updated core --- pythonjs.js | 161 +++++++++++++++++++++------------ pythonjs/python_to_pythonjs.py | 61 +++++++++++-- pythonjs/pythonjs.py | 2 +- runtime/builtins.py | 16 +++- 4 files changed, 174 insertions(+), 66 deletions(-) diff --git a/pythonjs.js b/pythonjs.js index c41ec48..46b82ba 100644 --- a/pythonjs.js +++ b/pythonjs.js @@ -1,4 +1,4 @@ -// PythonScript Runtime - regenerated on: Thu Nov 28 19:10:55 2013 +// PythonScript Runtime - regenerated on: Thu Nov 28 22:43:36 2013 __NULL_OBJECT__ = Object.create(null); if (( "window" ) in this && ( "document" ) in this) { __NODEJS__ = false; @@ -15,7 +15,7 @@ jsrange = function(num) { r = []; while(( i ) < num) { r.push(i); - i = i + 1; + i = (i + 1); } return r; } @@ -786,14 +786,14 @@ round = function(args, kwargs) { arguments = get_arguments(signature, args, kwargs); var a = arguments['a']; var places = arguments['places']; - b = "" + a; + b = ("" + a); if (( b.indexOf(".") ) == -1) { return a; } else { c = b.split("."); x = c[ 0 ]; y = c[ 1 ].substring(0,places); - return parseFloat(x + "." + y); + return parseFloat(((x + ".") + y)); } } @@ -813,7 +813,7 @@ str = function(args, kwargs) { signature = {"kwargs": Object(), "args": __create_array__("s")}; arguments = get_arguments(signature, args, kwargs); var s = arguments['s']; - return "" + s; + return ("" + s); } str.NAME = "str"; @@ -878,7 +878,7 @@ _setup_str_prototype = function(args, kwargs) { return this.split("").reverse().join(""); } else { if (( stop ) < 0) { - stop = this.length + stop; + stop = (this.length + stop); } return this.substring(start,stop); } @@ -921,7 +921,7 @@ _setup_str_prototype = function(args, kwargs) { func.types_signature = {}; String.prototype.startswith=func; var func = function(a) { - if (( this.substring(this.length - a.length, this.length) ) == a) { + if (( this.substring((this.length - a.length), this.length) ) == a) { return true; } else { return false; @@ -1082,7 +1082,7 @@ _setup_array_prototype = function(args, kwargs) { var func = function(start, stop, step) { var stop; if (( stop ) < 0) { - stop = this.length + stop; + stop = (this.length + stop); } return this.slice(start,stop); } @@ -1121,12 +1121,12 @@ _setup_array_prototype = function(args, kwargs) { high = this.length; } while(( low ) < high) { - a = low + high; - mid = Math.floor(a / 2); + a = (low + high); + mid = Math.floor((a / 2)); if (( x ) < this[mid]) { high = mid; } else { - low = mid + 1; + low = (mid + 1); } } return low; @@ -1309,6 +1309,7 @@ next.kwargs_signature = { }; next.types_signature = { }; next.pythonscript_function = true; map = function(args, kwargs) { + var arr, v; if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { @@ -1320,9 +1321,19 @@ map = function(args, kwargs) { arguments = get_arguments(signature, args, kwargs); var func = arguments['func']; var objs = arguments['objs']; + arr = []; + var __iterator__, ob; + __iterator__ = __get__(__get__(objs, "__iter__"), "__call__")([], Object()); + var __next__; + __next__ = __get__(__iterator__, "next_fast"); + while(( __iterator__.index ) < __iterator__.length) { + ob = __next__(); + v = __get__(func, "__call__")([ob], __NULL_OBJECT__); + arr.push(v); + } var __args_1, __kwargs_1; __args_1 = []; - __kwargs_1 = {"js_object": map([func, objs["$wrapped"]], __NULL_OBJECT__)}; + __kwargs_1 = {"pointer": arr}; return __get__(list, "__call__")([], __kwargs_1); } @@ -1332,6 +1343,42 @@ map.kwargs_signature = { }; map.types_signature = { }; map.return_type = "list"; map.pythonscript_function = true; +filter = function(args, kwargs) { + var arr; + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { + /*pass*/ + } else { + args = Array.prototype.slice.call(arguments); + kwargs = Object(); + } + var signature, arguments; + signature = {"kwargs": Object(), "args": __create_array__("func", "objs")}; + arguments = get_arguments(signature, args, kwargs); + var func = arguments['func']; + var objs = arguments['objs']; + arr = []; + var __iterator__, ob; + __iterator__ = __get__(__get__(objs, "__iter__"), "__call__")([], Object()); + var __next__; + __next__ = __get__(__iterator__, "next_fast"); + while(( __iterator__.index ) < __iterator__.length) { + ob = __next__(); + if (__get__(func, "__call__")([ob], __NULL_OBJECT__)) { + arr.push(ob); + } + } + var __args_2, __kwargs_2; + __args_2 = []; + __kwargs_2 = {"pointer": arr}; + return __get__(list, "__call__")([], __kwargs_2); +} + +filter.NAME = "filter"; +filter.args_signature = ["func", "objs"]; +filter.kwargs_signature = { }; +filter.types_signature = { }; +filter.return_type = "list"; +filter.pythonscript_function = true; min = function(args, kwargs) { var a; if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { @@ -1506,7 +1553,7 @@ __Iterator_next = function(args, kwargs) { throw StopIteration; } item = __get__(__get__(self.obj, "get"), "__call__")([self.index], __NULL_OBJECT__); - self.index = self.index + 1; + self.index = (self.index + 1); return item; } @@ -1610,7 +1657,7 @@ __tuple___getitem__ = function(args, kwargs) { var self = arguments['self']; var index = arguments['index']; if (( index ) < 0) { - index = __get__(self["$wrapped"], "length") + index; + index = (__get__(self["$wrapped"], "length") + index); } return self["$wrapped"][ index ]; } @@ -1846,7 +1893,7 @@ __list___getitem__ = function(args, kwargs) { var self = args[ 0 ]; var index = args[ 1 ]; if (( index ) < 0) { - index = __get__(self["$wrapped"], "length") + index; + index = (__get__(self["$wrapped"], "length") + index); } return self["$wrapped"][ index ]; } @@ -1888,10 +1935,10 @@ __list___getslice__ = function(args, kwargs) { var stop = arguments['stop']; var step = arguments['step']; arr = self["$wrapped"].__getslice__(start,stop); - var __args_2, __kwargs_2; - __args_2 = []; - __kwargs_2 = {"pointer": arr}; - return __get__(list, "__call__")([], __kwargs_2); + var __args_3, __kwargs_3; + __args_3 = []; + __kwargs_3 = {"pointer": arr}; + return __get__(list, "__call__")([], __kwargs_3); } __list___getslice__.NAME = "__list___getslice__"; @@ -2513,10 +2560,10 @@ __dict_keys = function(args, kwargs) { arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; arr = Object.keys(self["$wrapped"]); - var __args_3, __kwargs_3; - __args_3 = []; - __kwargs_3 = {"js_object": arr}; - return __get__(list, "__call__")([], __kwargs_3); + var __args_4, __kwargs_4; + __args_4 = []; + __kwargs_4 = {"js_object": arr}; + return __get__(list, "__call__")([], __kwargs_4); } __dict_keys.NAME = "__dict_keys"; @@ -2600,9 +2647,9 @@ __dict___contains__ = function(args, kwargs) { var value = arguments['value']; keys = Object.keys(self["$wrapped"]); if (( typeof(value) ) == "object") { - key = "@" + value.uid; + key = ("@" + value.uid); } else { - key = "" + value; + key = ("" + value); } if (( keys.indexOf(key) ) == -1) { return false; @@ -2684,8 +2731,8 @@ set = function(args, kwargs) { if (! (iter instanceof Array) ) { iter = __object_keys__(iter) } for (var b=0; b < iter.length; b++) { var backup = b; b = iter[b]; - if (typeof(b, "number") && ( b ) === ( b | 0 )) { - key = b & mask; + if (typeof(b, "number") && ( b ) === ( (b | 0) )) { + key = (b & mask); hashtable[ key ] = b; keys.push(key); } else { @@ -2775,16 +2822,16 @@ __array___init__ = function(args, kwargs) { self.little_endian = little_endian; if (initializer) { self.length = len([initializer], __NULL_OBJECT__); - self.bytes = self.length * self.itemsize; + self.bytes = (self.length * self.itemsize); if (( self.typecode ) == "float8") { self._scale = max([__get__(list, "__call__")([], { pointer:[abs([min([initializer], __NULL_OBJECT__)], __NULL_OBJECT__), max([initializer], __NULL_OBJECT__)] })], __NULL_OBJECT__); - self._norm_get = self._scale / 127; - self._norm_set = 1.0 / self._norm_get; + self._norm_get = (self._scale / 127); + self._norm_set = (1.0 / self._norm_get); } else { if (( self.typecode ) == "float16") { self._scale = max([__get__(list, "__call__")([], { pointer:[abs([min([initializer], __NULL_OBJECT__)], __NULL_OBJECT__), max([initializer], __NULL_OBJECT__)] })], __NULL_OBJECT__); - self._norm_get = self._scale / 32767; - self._norm_set = 1.0 / self._norm_get; + self._norm_get = (self._scale / 32767); + self._norm_set = (1.0 / self._norm_get); } } } else { @@ -2865,17 +2912,17 @@ __array___getitem__ = function(args, kwargs) { var self = arguments['self']; var index = arguments['index']; step = self.itemsize; - offset = step * index; + offset = (step * index); dataview = self.dataview; - func_name = "get" + __get__(__get__(self, "typecode_names"), "__getitem__")([self.typecode], Object()); + func_name = ("get" + __get__(__get__(self, "typecode_names"), "__getitem__")([self.typecode], Object())); func = dataview[func_name].bind(dataview); if (( offset ) < self.bytes) { value = func(offset); if (( self.typecode ) == "float8") { - value = value * self._norm_get; + value = (value * self._norm_get); } else { if (( self.typecode ) == "float16") { - value = value * self._norm_get; + value = (value * self._norm_get); } } return value; @@ -2906,18 +2953,18 @@ __array___setitem__ = function(args, kwargs) { var value = arguments['value']; step = self.itemsize; if (( index ) < 0) { - index = self.length + index - 1; + index = ((self.length + index) - 1); } - offset = step * index; + offset = (step * index); dataview = self.dataview; - func_name = "set" + __get__(__get__(self, "typecode_names"), "__getitem__")([self.typecode], Object()); + func_name = ("set" + __get__(__get__(self, "typecode_names"), "__getitem__")([self.typecode], Object())); func = dataview[func_name].bind(dataview); if (( offset ) < self.bytes) { if (( self.typecode ) == "float8") { - value = value * self._norm_set; + value = (value * self._norm_set); } else { if (( self.typecode ) == "float16") { - value = value * self._norm_set; + value = (value * self._norm_set); } } func(offset, value); @@ -2990,9 +3037,9 @@ __array_fromlist = function(args, kwargs) { length = len([lst], __NULL_OBJECT__); step = self.itemsize; typecode = self.typecode; - size = length * step; + size = (length * step); dataview = self.dataview; - func_name = "set" + __get__(__get__(self, "typecode_names"), "__getitem__")([typecode], Object()); + func_name = ("set" + __get__(__get__(self, "typecode_names"), "__getitem__")([typecode], Object())); func = dataview[func_name].bind(dataview); if (( size ) <= self.bytes) { i = 0; @@ -3036,7 +3083,7 @@ __array_resize = function(args, kwargs) { var length = arguments['length']; buff = self.buffer; source = new Uint8Array(buff); - new_size = length * self.itemsize; + new_size = (length * self.itemsize); new_buff = new ArrayBuffer(new_size); target = new Uint8Array(new_buff); target.set(source); @@ -3066,7 +3113,7 @@ __array_append = function(args, kwargs) { var self = arguments['self']; var value = arguments['value']; length = self.length; - __get__(__get__(self, "resize"), "__call__")([self.length + 1], __NULL_OBJECT__); + __get__(__get__(self, "resize"), "__call__")([(self.length + 1)], __NULL_OBJECT__); __get__(__get__(self, "__setitem__"), "__call__")([length, value], Object()); } @@ -3143,10 +3190,10 @@ __array_to_list = function(args, kwargs) { signature = {"kwargs": Object(), "args": __create_array__("self")}; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; - var __args_4, __kwargs_4; - __args_4 = []; - __kwargs_4 = {"js_object": __get__(__get__(self, "to_array"), "__call__")()}; - return __get__(list, "__call__")([], __kwargs_4); + var __args_5, __kwargs_5; + __args_5 = []; + __kwargs_5 = {"js_object": __get__(__get__(self, "to_array"), "__call__")()}; + return __get__(list, "__call__")([], __kwargs_5); } __array_to_list.NAME = "__array_to_list"; @@ -3211,10 +3258,10 @@ _to_pythonjs = function(args, kwargs) { } if (Object.prototype.toString.call(json) === '[object Array]') { output = __get__(list, "__call__")(); - var __args_5, __kwargs_5; - __args_5 = []; - __kwargs_5 = {"js_object": json}; - raw = __get__(list, "__call__")([], __kwargs_5); + var __args_6, __kwargs_6; + __args_6 = []; + __kwargs_6 = {"js_object": json}; + raw = __get__(list, "__call__")([], __kwargs_6); var append; append = __get__(output, "append"); var __iterator__, item; @@ -3230,10 +3277,10 @@ _to_pythonjs = function(args, kwargs) { output = __get__(dict, "__call__")(); var set; set = __get__(output, "set"); - var __args_6, __kwargs_6; - __args_6 = []; - __kwargs_6 = {"js_object": Object.keys(json)}; - keys = __get__(list, "__call__")([], __kwargs_6); + var __args_7, __kwargs_7; + __args_7 = []; + __kwargs_7 = {"js_object": Object.keys(json)}; + keys = __get__(list, "__call__")([], __kwargs_7); var __iterator__, key; __iterator__ = __get__(__get__(keys, "__iter__"), "__call__")([], Object()); var __next__; diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index 352d861..d172323 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -102,6 +102,11 @@ def getvalue(self): }, 'bisect' : { 'bisect' : '/*bisect from fake bisect module*/' ## bisect is a builtin + }, + 'math' : { + 'sin' : 'var sin = Math.sin', + 'cos' : 'var cos = Math.cos', + 'sqrt': 'var sqrt = Math.sqrt' } } @@ -244,7 +249,10 @@ def setup_builtins(self): self._builtin_functions = { 'ord':'%s.charCodeAt(0)', 'chr':'String.fromCharCode(%s)', - 'abs':'Math.abs(%s)' + 'abs':'Math.abs(%s)', + 'cos':'Math.cos(%s)', + 'sin':'Math.sin(%s)', + 'sqrt':'Math.sqrt(%s)' } def is_known_class_name(self, name): @@ -312,7 +320,8 @@ def visit_ImportFrom(self, node): for n in node.names: if n.name in MINI_STDLIB[ node.module ]: writer.write( 'JS("%s")' %MINI_STDLIB[node.module][n.name] ) - self._builtin_functions[ n.name ] = n.name + '()' + if n.name not in self._builtin_functions: + self._builtin_functions[ n.name ] = n.name + '()' elif self._check_for_module( node.module ): if node.names[0].name == '*': @@ -367,7 +376,10 @@ def visit_Dict(self, node): def visit_Tuple(self, node): node.returns_type = 'tuple' a = '[%s]' % ', '.join(map(self.visit, node.elts)) - return '__get__(tuple, "__call__")([], {pointer:%s})' %a + if self._with_js: + return a + else: + return '__get__(tuple, "__call__")([], {pointer:%s})' %a def visit_List(self, node): node.returns_type = 'list' @@ -483,6 +495,25 @@ def visit_AugAssign(self, node): elif op == '//=': a = '%s = Math.floor(%s/%s)' %(target, target, self.visit(node.value)) writer.write(a) + + elif self._with_js: + a = '%s %s %s' %(target, op, self.visit(node.value)) + writer.write(a) + + elif isinstance(node.target, ast.Attribute): + raise NotImplementedError + + elif isinstance(node.target, ast.Subscript): + name = self.visit(node.target.value) + slice = self.visit(node.target.slice) + #if self._with_js: + # a = '%s[ %s ] %s %s' + # writer.write(a %(name, slice, op, self.visit(node.value))) + #else: + op = self.visit(node.op) + a = '__get__(%s, "__setitem__")( [%s, __get__(%s, "__getitem__")([%s], {}) %s (%s)], {} )' + writer.write(a %(name, slice, name, slice, op, self.visit(node.value))) + else: ## TODO extra checks to make sure the operator type is valid in this context a = '%s %s %s' %(target, op, self.visit(node.value)) @@ -770,7 +801,12 @@ def visit_BinOp(self, node): return '__sprintf( %s, %s[...] )' %(left, right) ## assumes that right is a tuple, or list. elif op == '*' and isinstance(node.left, ast.List): - if isinstance(node.right,ast.Num): + if len(node.left.elts) == 1 and isinstance(node.left.elts[0], ast.Name) and node.left.elts[0].id == 'None': + if self._with_js: + return 'new Array(%s)' %self.visit(node.right) + else: + return 'JS("new Array(%s)")' %self.visit(node.right) + elif isinstance(node.right,ast.Num): n = node.right.n elif isinstance(node.right, Name): if node.right.id in self._global_nodes: @@ -791,6 +827,9 @@ def visit_BinOp(self, node): elif op == '//': return 'Math.floor(%s/%s)' %(left, right) + elif op == '**': + return 'Math.pow(%s,%s)' %(left, right) + elif isinstance(node.left, Name): typedef = self.get_typedef( node.left ) if typedef and op in typedef.operators: @@ -799,7 +838,7 @@ def visit_BinOp(self, node): return '%s( [%s, %s], JSObject() )' %(func, left, right) - return '%s %s %s' % (left, op, right) + return '(%s %s %s)' % (left, op, right) def visit_Eq(self, node): return '==' @@ -810,6 +849,9 @@ def visit_NotEq(self, node): def visit_Is(self, node): return 'is' + def visit_Pow(self, node): + return '**' + def visit_Mult(self, node): return '*' @@ -1012,8 +1054,11 @@ def visit_Slice(self, node): return "%s, %s, %s" % (lower, upper, step) def visit_Assign(self, node): - # XXX: support only one target for subscripts - target = node.targets[0] + for target in node.targets: + self._visit_assign_helper( node, target ) + node = ast.Expr( value=target ) + + def _visit_assign_helper(self, node, target): if isinstance(target, Subscript): name = self.visit(target.value) ## target.value may have "returns_type" after being visited @@ -1173,6 +1218,8 @@ def visit_Assign(self, node): i ) writer.write(code) + elif self._with_js: + writer.write("%s = %s[%s]" % (target.id, r, i)) else: writer.write("%s = __get__(__get__(%s, '__getitem__'), '__call__')([%s], __NULL_OBJECT__)" % (target.id, r, i)) diff --git a/pythonjs/pythonjs.py b/pythonjs/pythonjs.py index 7259d9f..a3389cf 100755 --- a/pythonjs/pythonjs.py +++ b/pythonjs/pythonjs.py @@ -254,7 +254,7 @@ def visit_BinOp(self, node): left = self.visit(node.left) op = self.visit(node.op) right = self.visit(node.right) - return '%s %s %s' % (left, op, right) + return '(%s %s %s)' % (left, op, right) def visit_Mult(self, node): return '*' diff --git a/runtime/builtins.py b/runtime/builtins.py index 08765f8..90256fc 100644 --- a/runtime/builtins.py +++ b/runtime/builtins.py @@ -432,7 +432,21 @@ def next(obj): def map(func, objs): - return list( js_object = map(func, objs[...]) ) + with javascript: arr = [] + for ob in objs: + v = func(ob) + with javascript: + arr.push( v ) + return list( pointer=arr ) + +def filter(func, objs): + with javascript: arr = [] + for ob in objs: + if func( ob ): + with javascript: + arr.push( ob ) + return list( pointer=arr ) + def min( lst ): a = None From 52fc39eff8f56c69109d381c32304a9923a5ca0d Mon Sep 17 00:00:00 2001 From: anatoly techtonik Date: Thu, 28 Nov 2013 13:37:37 +0300 Subject: [PATCH 015/521] README.rst: reformat for readability in text editor --- README.rst | 194 +++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 165 insertions(+), 29 deletions(-) diff --git a/README.rst b/README.rst index 63b2c00..d59e9b0 100644 --- a/README.rst +++ b/README.rst @@ -7,15 +7,33 @@ PythonJS 0.8.6 Introduction ====== -PythonJS is a Python to Javascript translator written in Python, created by Amirouche Boubekki and Brett Hartshorn, currently maintained and developed by Brett. It features: list comprehensions, classes, multiple inheritance, operator overloading, function and class decorators, HTML DOM, and easily integrates with JavaScript and external JavaScript libraries. The generated code works in the Browser and in NodeJS. +PythonJS is a Python to Javascript translator written in +Python, created by Amirouche Boubekki and Brett Hartshorn, +currently maintained and developed by Brett. It features: +list comprehensions, classes, multiple inheritance, operator +overloading, function and class decorators, HTML DOM, and +easily integrates with JavaScript and external JavaScript +libraries. The generated code works in the Browser and in +NodeJS. Speed --------------- -PythonJS allows you to select which features you need for each section of your code, where you need performance you can disable operator overloading, and other slow operations. Features can be switched off and on for blocks of code using `pythonjs.configure()` or the special `with` statements and decorators described below. When PythonJS is run in fast mode (javascript with inline functions) it beats PyPy in both the Richards and Pystone benchmarks. +PythonJS allows you to select which features you need for +each section of your code, where you need performance you +can disable operator overloading, and other slow operations. +Features can be switched off and on for blocks of code using +`pythonjs.configure()` or the special `with` statements and +decorators described below. When PythonJS is run in fast +mode (javascript with inline functions) it beats PyPy in +both the Richards and Pystone benchmarks. NodeJS --------------- -Using PythonJS you can quickly port your server side code to using NodeJS. If you are using Tornado, porting is even simpler because we have written a compatibility layer that emulates the Tornado API and hides the NodeJS internal modules. +Using PythonJS you can quickly port your server side code to +using NodeJS. If you are using Tornado, porting is even +simpler because we have written a compatibility layer that +emulates the Tornado API and hides the NodeJS internal +modules. Getting Started @@ -30,13 +48,21 @@ Translate Your Script:: cd PythonJS/pythonjs ./translator.py myscript1.py myscript2.py > ~/myapp.js -The translator.py script can take in multiple Python scripts, these are appended together, and translated into a single JavaScript. The output is printed to stdout. If no command line arguments is given, then translator.py takes input from stdin. +The translator.py script can take in multiple Python +scripts, these are appended together, and translated into a +single JavaScript. The output is printed to stdout. If no +command line arguments is given, then translator.py takes +input from stdin. Test Server ----------- -PythonJS includes two test servers that run the HTML tests in PythonJS/tests. Both of these servers are written using the Tornado API. The NodeJS version is a port of the original test server adapted to work with the Tornado compatible binding. +PythonJS includes two test servers that run the HTML tests +in PythonJS/tests. Both of these servers are written using +the Tornado API. The NodeJS version is a port of the +original test server adapted to work with the Tornado +compatible binding. NodeJS Tornado @@ -72,9 +98,16 @@ Run Python Server:: Testing ------- -After running one of the test servers above, open a web browser and go to: http://localhost:8080 +After running one of the test servers above, open a web +browser and go to: http://localhost:8080 -The test server dynamically compiles Python into JavaScript, this greatly speeds up the testing and development process. Any html file you place in the PythonJS/tests directory will become available as a new web-page. When this web-page is requested the server will parse the html and check all the -The server knows that the above script needs to be dynamically compiled to JavaScript because the script is located in the "bindings" directory and the file name ends with ".py" +The server knows that the above script needs to be +dynamically compiled to JavaScript because the script is +located in the "bindings" directory and the file name ends +with ".py" Embedded Python Scripts:: @@ -95,9 +131,19 @@ Embedded Python Scripts:: -The server knows that above is an embedded Python script because the script tag has its type attribute set to "text/python". The server will compile and replace the Python code with JavaScript, change the type attribute to be "text/javascript", and serve the page to the client. +The server knows that above is an embedded Python script +because the script tag has its type attribute set to +"text/python". The server will compile and replace the +Python code with JavaScript, change the type attribute to be +"text/javascript", and serve the page to the client. -The syntax "from three import *" tells the compiler to load static type information about the previously compiled binding "three.py" into the compilers namespace, this is required because three.py uses operator overloading to wrap the THREE.js API. PythonJS programs are explicitly and implicitly statically typed to allow for operator overloading and optimizations. +The syntax "from three import *" tells the compiler to load +static type information about the previously compiled +binding "three.py" into the compilers namespace, this is +required because three.py uses operator overloading to wrap +the THREE.js API. PythonJS programs are explicitly and +implicitly statically typed to allow for operator +overloading and optimizations. Writing PythonJS Scripts @@ -143,14 +189,22 @@ HTML DOM Example:: -PythonJS allows you to call any JavaScript function directly by wrapping it at runtime. Attributes of JavaScript objects are also returned directly, like document.body. This allows you to use the HTML DOM API just as you would in normal JavaScript. +PythonJS allows you to call any JavaScript function directly +by wrapping it at runtime. Attributes of JavaScript objects +are also returned directly, like document.body. This allows +you to use the HTML DOM API just as you would in normal +JavaScript. --------------- Inline JavaScript --------------- -There are times that JavaScript needs to be directly inlined into PythonJS code, this is done with the special 'JS([str])' function that takes a string literal as its only argument. The compiler will insert the string directly into the final output JavaScript. +There are times that JavaScript needs to be directly inlined +into PythonJS code, this is done with the special +'JS([str])' function that takes a string literal as its only +argument. The compiler will insert the string directly into +the final output JavaScript. JS Example:: @@ -161,7 +215,10 @@ JS Example:: JS("arr.push('hello world')") JS("arr.push( ob )") -In the example above we create a new JavaScript Array. Notice that the if-statement above has a condition that is inlined JavaScript. Lets take a look at two alternative ways this can be rewritten. +In the example above we create a new JavaScript Array. +Notice that the if-statement above has a condition that is +inlined JavaScript. Lets take a look at two alternative +ways this can be rewritten. 1. JSArray, JSObject, and instanceof:: @@ -171,9 +228,18 @@ In the example above we create a new JavaScript Array. Notice that the if-state arr.push('hello world') arr.push( ob ) -The special function JSArray will create a new JavaScript Array object, and JSObject creates a new JavaScript Object. The 'instanceof' function will be translated into using the 'instanceof' JavaScript operator. At the end, arr.push is called without wrapping it in JS(), this is allowed because from PythonJS, we can directly call JavaScript functions by dynamically wrapping it at runtime. +The special function JSArray will create a new JavaScript +Array object, and JSObject creates a new JavaScript Object. +The 'instanceof' function will be translated into using the +'instanceof' JavaScript operator. At the end, arr.push is +called without wrapping it in JS(), this is allowed because +from PythonJS, we can directly call JavaScript functions by +dynamically wrapping it at runtime. -This code is more clear than before, but the downside is that the calls to arr.push will be slower because it gets wrapped at runtime. To have fast and clear code we need to use the final method below, 'with javascript' +This code is more clear than before, but the downside is +that the calls to arr.push will be slower because it gets +wrapped at runtime. To have fast and clear code we need to +use the final method below, 'with javascript' 2. with javascript:: @@ -184,14 +250,24 @@ This code is more clear than before, but the downside is that the calls to arr.p arr.push('hello world') arr.push( ob ) -The "with javascript:" statement can be used to mark a block of code as being direct JavaScript. The compiler will basically wrap each line it can in JS() calls. The calls to arr.push will be fast because there is no longer any runtime wrapping. Instead of using JSArray and JSObject you just use the literal notation to create them. +The "with javascript:" statement can be used to mark a block +of code as being direct JavaScript. The compiler will +basically wrap each line it can in JS() calls. The calls to +arr.push will be fast because there is no longer any runtime +wrapping. Instead of using JSArray and JSObject you just +use the literal notation to create them. --------------- Calling PythonJS Functions from JavaScript ------------------------------ -PythonJS functions can be used as callbacks in Javascript code, there are no special calling conventions that you need to worry about. Simply define a function in PythonJS and call it from JavaScript. Note that if your PythonJS function uses keyword arguments, you can use them as a normal positional arguments. +PythonJS functions can be used as callbacks in Javascript +code, there are no special calling conventions that you need +to worry about. Simply define a function in PythonJS and +call it from JavaScript. Note that if your PythonJS +function uses keyword arguments, you can use them as a +normal positional arguments. Example:: @@ -208,7 +284,12 @@ Example:: Calling PythonJS Methods from JavaScript ------------------------------ -Calling PythonJS methods is also simple, you just need to create an instance of the class in PythonJS and then pass the method to a JavaScript function, or assign it to a new variable that the JavaScript code will use. PythonJS takes care of wrapping the method for you so that "self" is bound to the method, and is callable from JavaScript. +Calling PythonJS methods is also simple, you just need to +create an instance of the class in PythonJS and then pass +the method to a JavaScript function, or assign it to a new +variable that the JavaScript code will use. PythonJS takes +care of wrapping the method for you so that "self" is bound +to the method, and is callable from JavaScript. Example:: @@ -234,7 +315,13 @@ Example:: Passing PythonJS Instances to JavaScript ------------------------------ -If you are doing something complex like deep integration with an external JavaScript library, the above technique of passing each method callback to JavaScript might become inefficient. If you want to pass the PythonJS instance itself and have its methods callable from JavaScript, you can do this now simply by passing the instance. This only works with property getter/setters. +If you are doing something complex like deep integration +with an external JavaScript library, the above technique of +passing each method callback to JavaScript might become +inefficient. If you want to pass the PythonJS instance +itself and have its methods callable from JavaScript, you +can do this now simply by passing the instance. This only +works with property getter/setters. Example:: @@ -260,7 +347,10 @@ Example:: Define JavaScript Prototypes from PythonJS ------------------------------ -If you are going beyond simple integration with an external JavaScript library, and perhaps want to change the way it works on a deeper level, you can modify JavaScript prototypes from PythonJS using some special syntax. +If you are going beyond simple integration with an external +JavaScript library, and perhaps want to change the way it +works on a deeper level, you can modify JavaScript +prototypes from PythonJS using some special syntax. Example:: @@ -278,7 +368,11 @@ Example:: def func(a): return this.indexOf(a) -The above example shows how we modify the String type in JavaScript to act more like a Python string type. The functions must be defined inside a "with javascript:" block, and the decorator format is: `[class name].prototype.[function name]` +The above example shows how we modify the String type in +JavaScript to act more like a Python string type. The +functions must be defined inside a "with javascript:" block, +and the decorator format is: +`[class name].prototype.[function name]` --------------- @@ -286,9 +380,25 @@ The above example shows how we modify the String type in JavaScript to act more Making PythonJS Wrappers for JavaScript Libraries ------------------------------ -The above techniques provide all the tools you will need to interact with JavaScript code, and easily write wrapper code in PythonJS. The last tool you will need, is a standard way of creating JavaScript objects, storing a reference to the instance, and later passing the instance to wrapped JavaScript function. In JavaScript objects are created with the `new` keyword, in PythonJS you can use the `new()` function instead. To store an instance created by `new()`, you should assign it to `self` like this: `self[...] = new( SomeJavaScriptClass() )`. - -If you have never seen `...` syntax in Python it is the rarely used Ellipsis syntax, we have hijacked it in PythonJS as a special case to assign something to a hidden attribute. The builtin types: tuple, list, dict, etc, are wrappers that internally use JavaScript Arrays or Objects, to get to these internal objects you use the Ellipsis syntax. The following example shows how the THREE.js binding wraps the Vector3 object and combines operator overloading. +The above techniques provide all the tools you will need to +interact with JavaScript code, and easily write wrapper code +in PythonJS. The last tool you will need, is a standard way +of creating JavaScript objects, storing a reference to the +instance, and later passing the instance to wrapped +JavaScript function. In JavaScript objects are created with +the `new` keyword, in PythonJS you can use the `new()` +function instead. To store an instance created by `new()`, +you should assign it to `self` like this: +`self[...] = new( SomeJavaScriptClass() )`. + +If you have never seen `...` syntax in Python it is the +rarely used Ellipsis syntax, we have hijacked it in PythonJS +as a special case to assign something to a hidden attribute. +The builtin types: tuple, list, dict, etc, are wrappers that +internally use JavaScript Arrays or Objects, to get to these +internal objects you use the Ellipsis syntax. The following +example shows how the THREE.js binding wraps the Vector3 +object and combines operator overloading. Example:: @@ -352,7 +462,19 @@ Example:: Optimized Function Calls ------------------------------ -By default PythonJS functions have runtime call checking that ensures you have called the function with the required number of arguments, and also checks to see if you had called the function from JavaScript - and if so adapt the arguments. This adds some overhead each time the function is called, and will generally be about 15 times slower than normal Python. When performance is a concern you can decorate functions that need to be fast with @fastdef, or use the `with fastdef:` with statement. Note that functions that do not have arguments are always fast. Using fastdef will make each call to your function 100 times faster, so if you call the same function many times in a loop, it is a good idea to decorate it with @fastdef. +By default PythonJS functions have runtime call checking +that ensures you have called the function with the required +number of arguments, and also checks to see if you had +called the function from JavaScript - and if so adapt the +arguments. This adds some overhead each time the function +is called, and will generally be about 15 times slower than +normal Python. When performance is a concern you can +decorate functions that need to be fast with @fastdef, or +use the `with fastdef:` with statement. Note that functions +that do not have arguments are always fast. Using fastdef +will make each call to your function 100 times faster, so if +you call the same function many times in a loop, it is a +good idea to decorate it with @fastdef. Example:: @@ -364,14 +486,20 @@ Example:: def f2( a,b,c, x=1,y=2,z=3): return a+b+c+x+y+z -If you need to call a fastdef function from JavaScript you will need to call it with arguments packed into an array as the first argument, and keyword args packed into an Object as the second argument. +If you need to call a fastdef function from JavaScript you +will need to call it with arguments packed into an array as +the first argument, and keyword args packed into an Object +as the second argument. Example:: // javascript f2( [1,2,3], {x:100, y:200, z:300} ); -If you need fast function that is callable from javascript without packing its arguments like above, you can use the @javascript decorator, or nest the function inside a `with javascript:` statement. +If you need fast function that is callable from javascript +without packing its arguments like above, you can use the +@javascript decorator, or nest the function inside a `with +javascript:` statement. Example:: @@ -389,14 +517,22 @@ Example:: NodeJS ====== -PythonJS can also be used to write server side software using NodeJS. You can use the nodejs.py helper script to translate your python script and run it in NodeJS. This has been tested with NodeJS v0.10.22. +PythonJS can also be used to write server side software +using NodeJS. You can use the nodejs.py helper script to +translate your python script and run it in NodeJS. This has +been tested with NodeJS v0.10.22. Example:: cd PythonJS ./nodejs.py myscript.py -The directory PythonJS/nodejs/bindings contains wrappers for using NodeJS modules. Some of these wrappers emulate parts of Pythons standard library, like: os, sys, io, and subprocess. The example below imports the fake io and sys libraries, and prints the contents of a file passed as the last command line argument to nodejs.py. +The directory PythonJS/nodejs/bindings contains wrappers for +using NodeJS modules. Some of these wrappers emulate parts +of Pythons standard library, like: os, sys, io, and +subprocess. The example below imports the fake io and sys +libraries, and prints the contents of a file passed as the +last command line argument to nodejs.py. Example:: From 57a81d0c02e5727a449ef1154694bad5c2cdd97e Mon Sep 17 00:00:00 2001 From: anatoly techtonik Date: Sat, 30 Nov 2013 02:18:35 +0300 Subject: [PATCH 016/521] Fix .log file generation on Windows --- pythonjs/python_to_pythonjs.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index d172323..16b605d 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -4,6 +4,7 @@ # License: "New BSD" import os, sys, pickle, copy +from tempfile import gettempdir from types import GeneratorType import ast @@ -31,7 +32,7 @@ from cStringIO import StringIO as StringIO try: - _log_file = open('/tmp/python_to_pythonjs.log', 'wb') + _log_file = open(gettempdir() + '/python_to_pythonjs.log', 'wb') except: _log_file = None def log(txt): @@ -2100,7 +2101,7 @@ def main(script): def command(): module = None - module_path = '/tmp' + module_path = gettempdir() scripts = [] if len(sys.argv) > 1: argv = sys.argv[1:] From b2d38eef23112306ad5f697344515cbb2a1b5e38 Mon Sep 17 00:00:00 2001 From: anatoly techtonik Date: Sat, 30 Nov 2013 10:25:04 +0300 Subject: [PATCH 017/521] README.rst: explain how translating process works. Hart, please check this thoroughly - I am unsure this is right. --- README.rst | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/README.rst b/README.rst index d59e9b0..9bdea77 100644 --- a/README.rst +++ b/README.rst @@ -35,6 +35,22 @@ simpler because we have written a compatibility layer that emulates the Tornado API and hides the NodeJS internal modules. +How does it work +---------------- +Translation to JavaScript is done in two steps. + + +------------+ +-----------------+ +------------+ + ¦ .py source ¦--->¦ pythonjs subset ¦--->¦ .js source ¦ + +------------+ +-----------------+ +------------+ + +First, the script walks the AST tree of Python source and +translates it into the subset of Python called `pythonjs`. +This renames Python functions to JavaScript equivalents, +adds code to converte native JavaScript object when needed, +and annotates function definitions with to feed the logic +in the next step. Next step translates annotated code into +final JavaScript form. + Getting Started =============== From 088d6fa2bb6c53e883e6cc2181a73e6b842657b7 Mon Sep 17 00:00:00 2001 From: anatoly techtonik Date: Sat, 30 Nov 2013 11:48:41 +0300 Subject: [PATCH 018/521] python_to_pythonjs.py: writer has only one buffer --- pythonjs/python_to_pythonjs.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index d172323..7f89a97 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -50,7 +50,7 @@ class Writer(object): def __init__(self): self.level = 0 - self.buffers = list() + self.buffer = list() self.output = StringIO() self.with_javascript = False @@ -64,12 +64,12 @@ def pull(self): self.level -= 1 def append(self, code): - self.buffers.append(code) + self.buffer.append(code) def write(self, code): - for buffer in self.buffers: - self._write(buffer) - self.buffers = list() + for content in self.buffer: + self._write(content) + self.buffer = list() self._write(code) def _write(self, code): From 7ac03ccc99be0662b19e044b1d0426c5cee33242 Mon Sep 17 00:00:00 2001 From: anatoly techtonik Date: Sat, 30 Nov 2013 11:53:48 +0300 Subject: [PATCH 019/521] less confusing error message about not-implemented import --- pythonjs/python_to_pythonjs.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index 7f89a97..fbdc4de 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -313,7 +313,8 @@ def _load_module(self, name): def visit_Import(self, node): for alias in node.names: writer.write( '## import: %s :: %s' %(alias.name, alias.asname) ) - raise NotImplementedError ## TODO namespaces: import x as y + ## TODO namespaces: import x as y + raise NotImplementedError('import, line %s' % node.lineno) def visit_ImportFrom(self, node): if node.module in MINI_STDLIB: From cd22ebd247b1bbbe96240836395d52a97cd67499 Mon Sep 17 00:00:00 2001 From: hartsantler Date: Sun, 1 Dec 2013 18:59:27 -0800 Subject: [PATCH 020/521] new yield support - converts simple generator function into a class with .next method --- pythonjs/python_to_pythonjs.py | 139 ++++++++++++++++++++++++++++++--- pythonjs/pythonjs.py | 6 +- tests/test_yield.html | 26 ++++++ 3 files changed, 158 insertions(+), 13 deletions(-) create mode 100644 tests/test_yield.html diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index d172323..ad1d0da 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -213,6 +213,7 @@ def __init__(self, source=None, module=None, module_path=None): self._cache_for_body_calls = False self._cache_while_body_calls = False self._comprehensions = [] + self._generator_functions = set() self._custom_operators = {} self._injector = [] ## advanced meta-programming hacks @@ -220,6 +221,12 @@ def __init__(self, source=None, module=None, module_path=None): self._with_fastdef = False self.setup_builtins() + source = self.preprocess_custom_operators( source ) + tree = parse( source ) + self._generator_function_nodes = collect_generator_functions( tree ) + self.visit( tree ) + + def preprocess_custom_operators(self, data): ''' custom operators must be defined before they are used @@ -1192,16 +1199,16 @@ def _visit_assign_helper(self, node, target): elif type == 'dict': self._global_typed_dicts[ target.id ] = set() - writer.write('%s = %s' % (target.id, node_value)) + writer.write('%s = %s' % (self.visit(target), node_value)) else: if target.id in self._globals and self._globals[target.id] is None: self._globals[target.id] = type self._instances[ target.id ] = type log('set global type: %s'%type) - writer.write('%s = %s' % (target.id, node_value)) + writer.write('%s = %s' % (self.visit(target), node_value)) else: - writer.write('%s = %s' % (target.id, node_value)) + writer.write('%s = %s' % (self.visit(target), node_value)) else: # it's a Tuple id = self.identifier @@ -1219,9 +1226,9 @@ def _visit_assign_helper(self, node, target): ) writer.write(code) elif self._with_js: - writer.write("%s = %s[%s]" % (target.id, r, i)) + writer.write("%s = %s[%s]" % (self.visit(target), r, i)) else: - writer.write("%s = __get__(__get__(%s, '__getitem__'), '__call__')([%s], __NULL_OBJECT__)" % (target.id, r, i)) + writer.write("%s = __get__(__get__(%s, '__getitem__'), '__call__')([%s], __NULL_OBJECT__)" % (self.visit(target), r, i)) def visit_Print(self, node): writer.write('print %s' % ', '.join(map(self.visit, node.values))) @@ -1331,7 +1338,10 @@ def visit_Call(self, node): name = self.visit(node.func) args = list( map(self.visit, node.args) ) - if name in self._builtin_functions and self._builtin_functions[name]: ## inlined js + if name in self._generator_functions: + return ' new %s(%s)' %(name, ','.join(args)) + + elif name in self._builtin_functions and self._builtin_functions[name]: ## inlined js if args: return self._builtin_functions[name] % ','.join(args) else: @@ -1356,6 +1366,13 @@ def visit_Call(self, node): a = ','.join(args) return '%s(%s)' %( self.visit(node.func), a ) + elif isinstance(node.func, Name) and node.func.id in self._generator_functions: + name = self.visit(node.func) + args = list( map(self.visit, node.args) ) + if name in self._generator_functions: + return 'JS("new %s(%s)")' %(name, ','.join(args)) + + elif isinstance(node.func, Name) and node.func.id in ('JS', 'toString', 'JSObject', 'JSArray', 'var', 'instanceof', 'typeof'): args = list( map(self.visit, node.args) ) ## map in py3 returns an iterator not a list if node.func.id == 'var': @@ -1510,6 +1527,11 @@ def visit_Lambda(self, node): def visit_FunctionDef(self, node): log('-----------------') + if node in self._generator_function_nodes: + log('generator function: %s'%node.name) + GeneratorFunctionTransformer( self ).visit(node) + self._generator_functions.add( node.name ) + return log('function: %s'%node.name) property_decorator = None @@ -1983,6 +2005,69 @@ def visit_With(self, node): raise SyntaxError('improper use of "with" statement') +class GeneratorFunctionTransformer( PythonToPythonJS ): + def __init__(self, compiler): + self._with_js = True + self._builtin_functions = compiler._builtin_functions + self._js_classes = compiler._js_classes + self._global_functions = compiler._global_functions + self._with_inline = False + self._cache_for_body_calls = False + self._source = compiler._source + self._instances = dict() + + def visit_Yield(self, node): + writer.write('__yield_return__ = %s'%self.visit(node.value)) + + def visit_Name(self, node): + return 'this.%s' %node.id + + def visit_FunctionDef(self, node): + args = [a.id for a in node.args.args] + writer.write('def %s(%s):' %(node.name, ','.join(args))) + writer.push() + for arg in args: + writer.write('this.%s = %s'%(arg,arg)) + + loop_node = None + for b in node.body: + if isinstance(b, ast.For): + iter_start = '0' + iter = b.iter + if isinstance(iter, ast.Call) and isinstance(iter.func, Name) and iter.func.id in ('range','xrange'): + if len(iter.args) == 2: + iter_start = self.visit(iter.args[0]) + iter_end = self.visit(iter.args[1]) + else: + iter_end = self.visit(iter.args[0]) + else: + iter_end = self.visit(iter) + + writer.write('this.__iter_start = %s'%iter_start) + writer.write('this.__iter_index = %s'%iter_start) + writer.write('this.__iter_end = %s'%iter_end) + + loop_node = b + break + + else: + self.visit(b) + writer.pull() + + writer.write('@%s.prototype'%node.name) + writer.write('def next():') + writer.push() + writer.write('if this.__iter_index < this.__iter_end:') + writer.push() + #self.visit( loop_node ) + for b in loop_node.body: + self.visit(b) + writer.write('this.__iter_index += 1') + writer.write('return __yield_return__') + writer.pull() + writer.pull() + + class CollectCalls(NodeVisitor): _calls_ = [] def visit_Call(self, node): @@ -2033,6 +2118,41 @@ def collect_comprehensions(node): CollectComprehensions().visit( node ) return comps +class CollectGenFuncs(NodeVisitor): + _funcs = [] + _genfuncs = [] + def visit_FunctionDef(self, node): + self._funcs.append( node ) + node._yields = [] + node._loops = [] + for b in node.body: + self.visit(b) + self._funcs.pop() + + def visit_Yield(self, node): + func = self._funcs[-1] + func._yields.append( node ) + if func not in self._genfuncs: + self._genfuncs.append( func ) + + def visit_For(self, node): + if len(self._funcs): + self._funcs[-1]._loops.append( node ) + for b in node.body: + self.visit(b) + + def visit_While(self, node): + if len(self._funcs): + self._funcs[-1]._loops.append( node ) + for b in node.body: + self.visit(b) + + +def collect_generator_functions(node): + CollectGenFuncs._funcs = [] + CollectGenFuncs._genfuncs = gfuncs = [] + CollectGenFuncs().visit( node ) + return gfuncs def retrieve_vars(body): local_vars = set() @@ -2093,8 +2213,7 @@ def inspect_function( node ): def main(script): - input = parse(script) - PythonToPythonJS( source=script ).visit(input) + PythonToPythonJS( source=script ) return writer.getvalue() @@ -2122,10 +2241,6 @@ def command(): compiler = PythonToPythonJS( source=data, module=module, module_path=module_path ) - - data = compiler.preprocess_custom_operators( data ) - compiler.visit( parse(data) ) - compiler.save_module() output = writer.getvalue() print( output ) ## pipe to stdout diff --git a/pythonjs/pythonjs.py b/pythonjs/pythonjs.py index a3389cf..af073cf 100755 --- a/pythonjs/pythonjs.py +++ b/pythonjs/pythonjs.py @@ -99,7 +99,11 @@ def visit_FunctionDef(self, node): self._function_stack.append( node.name ) args = self.visit(node.args) - if len(self._function_stack) == 1: + if len(node.decorator_list): + assert len(node.decorator_list)==1 + dec = self.visit(node.decorator_list[0]) + buffer = self.indent() + '%s.%s = function(%s) {\n' % (dec,node.name, ', '.join(args)) + elif len(self._function_stack) == 1: ## this style will not make function global to the eval context in NodeJS ## #buffer = self.indent() + 'function %s(%s) {\n' % (node.name, ', '.join(args)) ## this is required for eval to be able to work in NodeJS, note there is no var keyword. diff --git a/tests/test_yield.html b/tests/test_yield.html new file mode 100644 index 0000000..69c6e66 --- /dev/null +++ b/tests/test_yield.html @@ -0,0 +1,26 @@ + + + + + + + + + + + \ No newline at end of file From 1cf20a299be1730ce9f0d01f4c1c147ee9a87e1a Mon Sep 17 00:00:00 2001 From: hartsantler Date: Sun, 1 Dec 2013 19:35:22 -0800 Subject: [PATCH 021/521] automatically call generator.next() when for-looping over a generator function. --- pythonjs/python_to_pythonjs.py | 19 ++++++++++++++++++- tests/test_yield.html | 4 ++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index ad1d0da..8ac2e44 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -1897,6 +1897,7 @@ def visit_For(self, node): writer.write('var(__iterator__, %s)' % target.id) is_range = False + is_generator = False iter_start = '0' iter_end = None if self.FAST_FOR and isinstance(iter, ast.Call) and isinstance(iter.func, Name) and iter.func.id in ('range','xrange'): @@ -1906,10 +1907,24 @@ def visit_For(self, node): iter_end = self.visit(iter.args[1]) else: iter_end = self.visit(iter.args[0]) + + elif isinstance(iter, ast.Call) and isinstance(iter.func, Name) and iter.func.id in self._generator_functions: + is_generator = True else: writer.write('__iterator__ = __get__(__get__(%s, "__iter__"), "__call__")(JSArray(), JSObject())' % self.visit(iter)) - if is_range: + if is_generator: + iter_name = self.visit(target) + writer.write('var(%s, __generator__)' %iter_name) + writer.write('__generator__ = %s' %self.visit(iter)) + writer.write('while __generator__.__done__ != 1:') + writer.push() + writer.write('%s = __generator__.next()'%iter_name) + map(self.visit, node.body) + writer.pull() + + + elif is_range: iter_name = target.id writer.write('var(%s)' %iter_name) writer.write('%s = %s' %(iter_name, iter_start)) @@ -2046,6 +2061,7 @@ def visit_FunctionDef(self, node): writer.write('this.__iter_start = %s'%iter_start) writer.write('this.__iter_index = %s'%iter_start) writer.write('this.__iter_end = %s'%iter_end) + writer.write('this.__done__ = 0') loop_node = b break @@ -2065,6 +2081,7 @@ def visit_FunctionDef(self, node): writer.write('this.__iter_index += 1') writer.write('return __yield_return__') writer.pull() + writer.write('else: this.__done__ = 1') writer.pull() diff --git a/tests/test_yield.html b/tests/test_yield.html index 69c6e66..a9cd812 100644 --- a/tests/test_yield.html +++ b/tests/test_yield.html @@ -16,6 +16,10 @@ for i in range(n): print g.next() + print 'testing for over generator' + for n in fib(20): + print n + From 5b4a658f45f66bc9ac59f31f0b77a26db8390576 Mon Sep 17 00:00:00 2001 From: hartsantler Date: Mon, 2 Dec 2013 00:13:49 -0800 Subject: [PATCH 022/521] fixed yield generator functions, added fibonacci yield benchmark. --- pythonjs/python_to_pythonjs.py | 18 ++++++++++++++++-- tests/bench_fibonacci.html | 31 +++++++++++++++++++++++++++++++ tests/server.py | 1 + 3 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 tests/bench_fibonacci.html diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index 8ac2e44..f7f9eb1 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -1529,9 +1529,12 @@ def visit_FunctionDef(self, node): log('-----------------') if node in self._generator_function_nodes: log('generator function: %s'%node.name) - GeneratorFunctionTransformer( self ).visit(node) self._generator_functions.add( node.name ) - return + if '--native-yield' in sys.argv: + raise NotImplementedError ## TODO + else: + GeneratorFunctionTransformer( self ).visit(node) + return log('function: %s'%node.name) property_decorator = None @@ -1879,6 +1882,16 @@ def visit_For(self, node): writer.pull() + elif isinstance(iter, ast.Call) and isinstance(iter.func, Name) and iter.func.id in self._generator_functions: + iter_name = self.visit(target) + writer.write('var(%s, __generator__)' %iter_name) + writer.write('__generator__ = %s' %self.visit(iter)) + writer.write('while __generator__.__done__ != 1:') + writer.push() + writer.write('%s = __generator__.next()'%iter_name) + map(self.visit, node.body) + writer.pull() + else: writer.write('for %s in %s:' %(self.visit(target),self.visit(iter))) writer.push() @@ -2079,6 +2092,7 @@ def visit_FunctionDef(self, node): for b in loop_node.body: self.visit(b) writer.write('this.__iter_index += 1') + writer.write('if this.__iter_index == this.__iter_end: this.__done__ = 1') writer.write('return __yield_return__') writer.pull() writer.write('else: this.__done__ = 1') diff --git a/tests/bench_fibonacci.html b/tests/bench_fibonacci.html new file mode 100644 index 0000000..6c9e047 --- /dev/null +++ b/tests/bench_fibonacci.html @@ -0,0 +1,31 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/tests/server.py b/tests/server.py index 7f202a6..fafddff 100755 --- a/tests/server.py +++ b/tests/server.py @@ -137,6 +137,7 @@ def convert_python_html_document( data ): if 'closure="true"' in line.lower(): use_closure = True else: use_closure = False doc.append( ' + + + + + + + + \ No newline at end of file diff --git a/tests/test_yield_multiple.html b/tests/test_yield_multiple.html new file mode 100644 index 0000000..00094da --- /dev/null +++ b/tests/test_yield_multiple.html @@ -0,0 +1,26 @@ + + + + + + + + + + + \ No newline at end of file From 9fdd18e78d7cf2bef7aa7076c71d610c43228d70 Mon Sep 17 00:00:00 2001 From: hartsantler Date: Wed, 4 Dec 2013 18:55:18 -0800 Subject: [PATCH 027/521] fixed keyword defaults in with-javascript mode and fastdef mode --- README.rst | 191 +++++++++++++++++++-------------- pythonjs/python_to_pythonjs.py | 22 ++-- 2 files changed, 125 insertions(+), 88 deletions(-) diff --git a/README.rst b/README.rst index 471d583..2267381 100644 --- a/README.rst +++ b/README.rst @@ -68,99 +68,43 @@ command line arguments is given, then translator.py takes input from stdin. -Test Server ------------ -PythonJS includes two test servers that run the HTML tests -in PythonJS/tests. Both of these servers are written using -the Tornado API. The NodeJS version is a port of the -original test server adapted to work with the Tornado -compatible binding. +Writing PythonJS Scripts +===================== -NodeJS Tornado +Function Types --------------- -Install Modules:: - - sudo npm install -g mime - sudo npm install -g ws - -Run NodeJS Server:: - - cd PythonJS - ./nodejs.py nodejs/tests/tornado-demo-server.py - - -Python Tornado ---------------- +PythonJS has three main types of functions: + __normal__ + __fastdef__ + __javascript__ -Install Tornado for Python3:: - - wget https://pypi.python.org/packages/source/t/tornado/tornado-3.1.1.tar.gz - tar xvf tornado-3.1.1.tar.gz - cd tornado-3.1.1 - python3 setup.py build - sudo python3 setup.py install - -Run Python Server:: - - cd PythonJS/tests - ./server.py - -Testing -------- - -After running one of the test servers above, open a web -browser and go to: http://localhost:8080 - -The test server dynamically compiles Python into JavaScript, -this greatly speeds up the testing and development process. -Any html file you place in the PythonJS/tests directory will -become available as a new web-page. When this web-page is -requested the server will parse the html and check all the - - +Functions decorated with @javascript, or inside a __with javascript:__ block, or following the call: __pythonjs.configure(javascript=True)__ become __javascript__ type functions, these offer the highest calling speed. They do not support *args or **kwargs. When called from external JavaScript, keyword arguments are not given by name, they become positional arguments that default to the default value if undefined. When called from within PythonJS code, they need to be called from inside a __with javascript:__ block, or following the call pythonjs.configure(javascript=True) that sets all following code to be in __javascript__ mode. -The server knows that the above script needs to be -dynamically compiled to JavaScript because the script is -located in the "bindings" directory and the file name ends -with ".py" +Example:: -Embedded Python Scripts:: + pythonjs.configure( javascript=True ) - - - + def myfunc(x,y,z, a=1,b=2,c=3): + print x,y,z,a,b,c -The server knows that above is an embedded Python script -because the script tag has its type attribute set to -"text/python". The server will compile and replace the -Python code with JavaScript, change the type attribute to be -"text/javascript", and serve the page to the client. +Example JavaScript Translation:: -The syntax "from three import *" tells the compiler to load -static type information about the previously compiled -binding "three.py" into the compilers namespace, this is -required because three.py uses operator overloading to wrap -the THREE.js API. PythonJS programs are explicitly and -implicitly statically typed to allow for operator -overloading and optimizations. + myfunc = function(x, y, z, a, b, c) { + if (a === undefined) a = 1; + if (b === undefined) b = 2; + if (c === undefined) c = 3; + console.log(x, y, z, a, b, c); + } -Writing PythonJS Scripts -===================== Generator Functions ------------------- @@ -633,6 +577,97 @@ Example:: ------------------------------ +Test Server +=========== + +PythonJS includes two test servers that run the HTML tests +in PythonJS/tests. Both of these servers are written using +the Tornado API. The NodeJS version is a port of the +original test server adapted to work with the Tornado +compatible binding. + + +NodeJS Tornado +--------------- + +Install Modules:: + + sudo npm install -g mime + sudo npm install -g ws + +Run NodeJS Server:: + + cd PythonJS + ./nodejs.py nodejs/tests/tornado-demo-server.py + + +Python Tornado +--------------- + +Install Tornado for Python3:: + + wget https://pypi.python.org/packages/source/t/tornado/tornado-3.1.1.tar.gz + tar xvf tornado-3.1.1.tar.gz + cd tornado-3.1.1 + python3 setup.py build + sudo python3 setup.py install + +Run Python Server:: + + cd PythonJS/tests + ./server.py + +Testing +------- + +After running one of the test servers above, open a web +browser and go to: http://localhost:8080 + +The test server dynamically compiles Python into JavaScript, +this greatly speeds up the testing and development process. +Any html file you place in the PythonJS/tests directory will +become available as a new web-page. When this web-page is +requested the server will parse the html and check all the + + + +The server knows that the above script needs to be +dynamically compiled to JavaScript because the script is +located in the "bindings" directory and the file name ends +with ".py" + +Embedded Python Scripts:: + + + + + +The server knows that above is an embedded Python script +because the script tag has its type attribute set to +"text/python". The server will compile and replace the +Python code with JavaScript, change the type attribute to be +"text/javascript", and serve the page to the client. + +The syntax "from three import *" tells the compiler to load +static type information about the previously compiled +binding "three.py" into the compilers namespace, this is +required because three.py uses operator overloading to wrap +the THREE.js API. PythonJS programs are explicitly and +implicitly statically typed to allow for operator +overloading and optimizations. + + .. image:: https://d2weczhvl823v0.cloudfront.net/PythonJS/pythonjs/trend.png :alt: Bitdeli badge :target: https://bitdeli.com/free diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index 85c8fe2..7627a52 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -550,7 +550,6 @@ def _visit_js_classdef(self, node): for item in node.body: if isinstance(item, FunctionDef): methods[ item.name ] = item - item.args.args = item.args.args[1:] ## remove self finfo = inspect_function( item ) for n in finfo['name_nodes']: @@ -1670,21 +1669,24 @@ def visit_FunctionDef(self, node): if self._with_js or javascript: if node.args.defaults: + offset = len(node.args.args) - len(node.args.defaults) for i, arg in enumerate(node.args.args): - dindex = i - len(node.args.defaults) + dindex = i - offset if dindex >= 0: default_value = self.visit( node.args.defaults[dindex] ) - writer.write("""JS("var %s = %s || %s ")""" % (arg.id, arg.id, default_value)) - + writer.write( '''JS("if (%s === undefined) %s = %s")'''%(arg.id, arg.id, default_value) ) elif self._with_fastdef or fastdef: + offset = len(node.args.args) - len(node.args.defaults) for i, arg in enumerate(node.args.args): - #dindex = i - len(node.args.defaults) ## TODO - fixme - #if dindex >= 0 and node.args.defaults: - # default_value = self.visit( node.args.defaults[dindex] ) - # writer.write("""JS("var %s = kwargs[ '%s' ] || %s ")""" % (arg.id, arg.id, default_value)) - #else: - writer.write("""JS("var %s = args[ %s ]")""" % (arg.id, i)) + dindex = i - offset + if dindex >= 0 and node.args.defaults: + default_value = self.visit( node.args.defaults[dindex] ) + writer.write('''JS("var %s = kwargs[ '%s' ]")''' % (arg.id, arg.id)) + writer.write( '''JS("if (%s === undefined) %s = %s")'''%(arg.id, arg.id, default_value) ) + + else: + writer.write("""JS("var %s = args[ %s ]")""" % (arg.id, i)) elif len(node.args.defaults) or len(node.args.args) or node.args.vararg or node.args.kwarg: # First check the arguments are well formed From a71692b4529d0538ba4ab74394deb243a1b6cad6 Mon Sep 17 00:00:00 2001 From: hartsantler Date: Wed, 4 Dec 2013 19:32:46 -0800 Subject: [PATCH 028/521] updated README --- README.rst | 72 ++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 65 insertions(+), 7 deletions(-) diff --git a/README.rst b/README.rst index 2267381..1ed5483 100644 --- a/README.rst +++ b/README.rst @@ -76,17 +76,14 @@ Writing PythonJS Scripts Function Types --------------- -PythonJS has three main types of functions: - __normal__ - __fastdef__ - __javascript__ +PythonJS has three main types of functions: "normal", "fastdef", and "javascript". -By default a function is __normal__ and fully emulates the Python standard, it allows for: arguments, keyword args with defaults, variable length arguments (*args) and variable length keyword args (**kwargs). Functions that are __normal__ also have special logic that allows them to be called from external JavaScript like normal JavaScript functions (keyword args become normal positional arguments when called from JavaScript). Calling __normal__ functions is slow because of this overhead, when you need faster function calls you can use __fastdef__ or __javascript__. +By default a function is "normal" and fully emulates the Python standard, it allows for: arguments, keyword args with defaults, variable length arguments (*args) and variable length keyword args (**kwargs). Functions that are "normal" also have special logic that allows them to be called from external JavaScript like normal JavaScript functions (keyword args become normal positional arguments when called from JavaScript). Calling "normal" functions is slow because of this overhead, when you need faster function calls you can use "fastdef" or "javascript". -Functions decorated with @fastdef, or inside a __with fastdef:__ block become __fastdef__ type functions. This makes calling them much faster, but they do not support variable length arguments (*args) or variable length keyword args (**kwargs). +Functions decorated with @fastdef, or inside a "with fastdef:" block become "fastdef" type functions. This makes calling them much faster, but they do not support variable length arguments (*args) or variable length keyword args (**kwargs). Another limitation is that when called from external JavaScript you must pack args into an Array as the first argument, and pack keyword arguments into an Object as the second argument. -Functions decorated with @javascript, or inside a __with javascript:__ block, or following the call: __pythonjs.configure(javascript=True)__ become __javascript__ type functions, these offer the highest calling speed. They do not support *args or **kwargs. When called from external JavaScript, keyword arguments are not given by name, they become positional arguments that default to the default value if undefined. When called from within PythonJS code, they need to be called from inside a __with javascript:__ block, or following the call pythonjs.configure(javascript=True) that sets all following code to be in __javascript__ mode. +Functions decorated with @javascript, or inside a "with javascript:" block, or following the call: "pythonjs.configure(javascript=True)" become "javascript" type functions, these offer the highest calling speed. They do not support *args or **kwargs. When called from external JavaScript, keyword arguments are not given by name, they become positional arguments that default to the default value if undefined. When called from within PythonJS code, they need to be called from inside a "with javascript:" block, or following the call pythonjs.configure(javascript=True) that sets all following code to be in "javascript" mode. Example:: @@ -104,6 +101,67 @@ Example JavaScript Translation:: console.log(x, y, z, a, b, c); } +Class Types +----------- + +PythonJS has two types of classes: "normal" and "javascript". By default classes are "normal" and support operator overloading and properties. Calling methods on a "javascript" class is much faster than method calls on a "normal" class, but follow the same rules as described above for "javascript" type functions. Both class types can be used from external JavaScript, the only difference is that instances of a "normal" class can pass their methods directly as arguments to a function that will use the method as a callback - even if that external function depends on the context of "this". Whereas instances of a "javascript" class can not directly pass their methods as arguments, because they depend on the calling context of "this" - if you are familiar with JavaScript this comes as no surprise. + +Example:: + + pythonjs.configure( javascript=True ) + class A: + def __init__(self, x,y,z): + self.x = x + self.y = y + self.z = z + + def foo(self, w): + return self.x + w + +Example JavaScript Translation:: + + A = function(x, y, z) { + A.__init__(this, x,y,z); + } + + A.prototype.__init__ = function(x, y, z) { + this.x=x; + this.y=y; + this.z=z; + } + A.__init__ = function () { return A.prototype.__init__.apply(arguments[0], Array.prototype.slice.call(arguments,1)) }; + + A.prototype.foo = function(w) { + return (this.x + w); + } + A.foo = function () { return A.prototype.foo.apply(arguments[0], Array.prototype.slice.call(arguments,1)) }; + + +Method Overrides +---------------- +In the example above, you might be wondering why in the JavaScript translation, is the class A constructor calling "A.__init__(this, x,y,z)", and why is the __init__ method assigned A.prototype and then wrapped and assigned to A.__init__. This is done so that subclasses are able to override their parent's methods, but still have a way of calling them, an example that subclasses A will make this more clear. + +Example:: + + class B( A ): + def __init__(self, w): + A.__init__(self, 10, 20, 30) + self.w = w + +Example JavaScript Translation:: + + B = function(w) { + B.__init__(this, w); + } + + B.prototype.__init__ = function(w) { + A.__init__(this,10,20,30); + this.w=w; + } + B.__init__ = function () { return B.prototype.__init__.apply(arguments[0], Array.prototype.slice.call(arguments,1)) }; + + for (var n in A.prototype) { if (!(n in B.prototype)) { B.prototype[n] = A.prototype[n] }}; + Generator Functions From 83dca365429c83474e0aaf109b68156772941972 Mon Sep 17 00:00:00 2001 From: hartsantler Date: Wed, 4 Dec 2013 20:32:40 -0800 Subject: [PATCH 029/521] hack for os.path.dirname using MINI_STDLIB --- pythonjs/python_to_pythonjs.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index 7627a52..4426d2d 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -109,6 +109,9 @@ def getvalue(self): 'sin' : 'var sin = Math.sin', 'cos' : 'var cos = Math.cos', 'sqrt': 'var sqrt = Math.sqrt' + }, + 'os.path' : { + 'dirname' : "function dirname(s) { return s.slice(0, s.lastIndexOf('/')+1)}; var os = {'path':{'dirname':dirname}}" } } From fc7db126cedf40ba0c8cc9128a2975bf02be4cd3 Mon Sep 17 00:00:00 2001 From: hartsantler Date: Wed, 4 Dec 2013 21:32:03 -0800 Subject: [PATCH 030/521] updated README --- README.rst | 8 ++++++++ pythonjs/pythonjs.py | 2 +- tests/test_with_javascript_subclass.html | 6 +++--- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/README.rst b/README.rst index 1ed5483..c75a38c 100644 --- a/README.rst +++ b/README.rst @@ -238,6 +238,14 @@ Example Output:: } +Python vs JavaScript Modes +------------------------- + +PythonJS has two primary modes you can write code in: "python" and "javascript". The default mode is "python", you can mark sections of your code to use either mode with "pythonjs.configure(javascript=True/False)" or nesting blocks inside "with python:" or "with javascript:". The "javascript" mode can be used for sections of code where performance is a major concern. When in "javascript" mode the literal "[]" syntax will return a JavaScript Array instead of a PythonJS list, and a literal "{}" returns a JavaScript Object instead of a PythonJS dict. In both modes you can directly call external JavaScript functions, its only faster in "javascript" mode because function calls are direct without any wrapping. + +If your familiar with the details of the JavaScript language you might expect JavaScript rules to apply when in "javascript" mode, however they do not, it is still Python style. For example, in true JavaScript a for-in loop over an Array yields the indices, and a for-in loop over an Object yields the values - this is the opposite of what happens in Python and PythonJS. + + Directly Calling JavaScript Functions --------------- diff --git a/pythonjs/pythonjs.py b/pythonjs/pythonjs.py index af073cf..b2357e6 100755 --- a/pythonjs/pythonjs.py +++ b/pythonjs/pythonjs.py @@ -218,7 +218,7 @@ def visit_Call(self, node): return '[]' elif name == 'JS': - s = node.args[0].s.replace('\n', '\\n').replace('\0', '\\0') + s = node.args[0].s.replace('\n', '\\n').replace('\0', '\\0') ## AttributeError: 'BinOp' object has no attribute 's' - this is caused by bad quotes if s.strip().startswith('#'): s = '/*%s*/'%s if '"' in s or "'" in s: ## can not trust direct-replace hacks pass diff --git a/tests/test_with_javascript_subclass.html b/tests/test_with_javascript_subclass.html index 4530e93..983bc61 100644 --- a/tests/test_with_javascript_subclass.html +++ b/tests/test_with_javascript_subclass.html @@ -3,7 +3,6 @@ + + + + + + + + \ No newline at end of file diff --git a/tests/server.py b/tests/server.py index fafddff..767e762 100755 --- a/tests/server.py +++ b/tests/server.py @@ -20,25 +20,21 @@ webroot = os.path.dirname(os.path.abspath(__file__)), pythonscript = os.path.abspath('../pythonjs'), bindings = os.path.abspath('../bindings'), - closure = os.path.expanduser( '~/closure-compiler/compiler.jar'), + closure = os.path.expanduser( '~/closure-compiler/compiler.jar'), ## DEPRECATED runtime = os.path.abspath('../pythonjs.js'), module_cache = '/tmp', runtime_pythonjs = os.path.abspath('../runtime/pythonpythonjs.py'), ## handwritten pythonjs runtime_builtins = os.path.abspath('../runtime/builtins.py'), + dart2js = os.path.expanduser( '~/dart/dart-sdk/bin/dart2js'), + ) -def python_to_pythonjs( src, module=None, global_variable_scope=False ): - #cmdheader = '#!%s' %PATHS['module_cache'] - #if module: - # assert '.' not in module - # cmdheader += ';' + module - #cmdheader += '\n' +def python_to_pythonjs( src, module=None ): cmd = ['python2', os.path.join( PATHS['pythonscript'], 'python_to_pythonjs.py')] - if global_variable_scope: cmd.append('--global-variable-scope') if module: cmd.append( '--module' ) cmd.append( module ) @@ -51,6 +47,24 @@ def python_to_pythonjs( src, module=None, global_variable_scope=False ): stdout, stderr = p.communicate( src.encode('utf-8') ) return stdout.decode('utf-8') +def pythonjs_to_dart(src): + p = subprocess.Popen( + ['python2', os.path.join( PATHS['pythonscript'],'pythonjs_to_dart.py')], + stdin = subprocess.PIPE, + stdout = subprocess.PIPE + ) + stdout, stderr = p.communicate( src.encode('utf-8') ) + open( '/tmp/dart2js-input.js', 'wb').write( stdout ) + + cmd = [ + PATHS['dart2js'], + '-c', ## insert runtime checks + '-o', '/tmp/dart2js-output.js', + '/tmp/dart2js-input.js' + ] + subprocess.call( cmd ) + return open('/tmp/dart2js-output.js', 'rb').read().decode('utf-8') + def pythonjs_to_javascript( src, closure_compiler=False ): p = subprocess.Popen( ['python2', os.path.join( PATHS['pythonscript'],'pythonjs.py')], @@ -74,16 +88,18 @@ def pythonjs_to_javascript( src, closure_compiler=False ): return a -def python_to_javascript( src, module=None, closure_compiler=False, debug=False, dump=False, global_variable_scope=False ): - a = python_to_pythonjs( src, module=module, global_variable_scope=global_variable_scope ) +def python_to_javascript( src, module=None, closure_compiler=False, dart=True, debug=False, dump=False ): + a = python_to_pythonjs( src, module=module ) if debug: print( a ) if dump: if isinstance(dump, str): open(dump, 'wb').write( a.encode('utf-8') ) else: open('/tmp/pythonjs.dump', 'wb').write( a.encode('utf-8') ) - - return pythonjs_to_javascript( a, closure_compiler=closure_compiler ) + if dart: + return pythonjs_to_dart( a ) + else: + return pythonjs_to_javascript( a, closure_compiler=closure_compiler ) @@ -170,7 +186,6 @@ def regenerate_runtime(): c = python_to_javascript( open(PATHS['runtime_builtins'],'rb').read().decode('utf-8'), dump='/tmp/runtime-builtins.dump.py', - global_variable_scope = False ## this should be safe ) if not c.strip(): raise RuntimeError From 5f6bf790173243359ef09d21c9bb03feafc19dcb Mon Sep 17 00:00:00 2001 From: hartsantler Date: Thu, 5 Dec 2013 19:35:06 -0800 Subject: [PATCH 033/521] refactoring core for Dart: `server.py --dart` forces dart mode, dicts in with-javascript mode have labels turned into strings, added DART to ministdlib.py --- README.rst | 92 +++++++++++++++++++++++++++++++++ pythonjs/ministdlib.py | 8 ++- pythonjs/python_to_pythonjs.py | 32 +++++++++--- pythonjs/pythonjs.py | 13 +++-- pythonjs/pythonjs_to_dart.py | 13 +++++ tests/dart_helloworld.html | 2 +- tests/server.py | 57 +++++++++----------- tests/test_with_javascript.html | 6 +-- 8 files changed, 171 insertions(+), 52 deletions(-) diff --git a/README.rst b/README.rst index 5714e87..a1ca1d4 100644 --- a/README.rst +++ b/README.rst @@ -170,7 +170,99 @@ Example JavaScript Translation:: for (var n in A.prototype) { if (!(n in B.prototype)) { B.prototype[n] = A.prototype[n] }}; +Multiple Inheritance +-------------------- +Multiple inheritance is fully supported. + +Example:: + + pythonjs.configure(javascript=True) + class Root: + def method(self): + print 'method on root' + + class A( Root ): + def __init__(self,x,y,z): + print 'A.init', x,y,z + self.x = x + self.y = y + self.z = z + + def foo(self): + print 'foo' + + + class MixIn: + def mixed(self, x): + print 'mixin:', x + + class B( A, MixIn ): + def __init__(self): + print 'B.init' + A.__init__(self, 1,2,3) + print self.x, self.y, self.z + + def bar(self): + print 'bar' + +Example JavaScript Translation:: + + Root = function() { + /*pass*/ + } + + Root.prototype.method = function() { + console.log("method on root"); + } + + Root.method = function () { return Root.prototype.method.apply(arguments[0], Array.prototype.slice.call(arguments,1)) }; + A = function(x, y, z) { + A.__init__(this, x,y,z); + } + + A.prototype.__init__ = function(x, y, z) { + console.log("A.init", x, y, z); + this.x=x; + this.y=y; + this.z=z; + } + A.__init__ = function () { return A.prototype.__init__.apply(arguments[0], Array.prototype.slice.call(arguments,1)) }; + + A.prototype.foo = function() { + console.log("foo"); + } + A.foo = function () { return A.prototype.foo.apply(arguments[0], Array.prototype.slice.call(arguments,1)) }; + for (var n in Root.prototype) { if (!(n in A.prototype)) { A.prototype[n] = Root.prototype[n] }}; + + MixIn = function() { + /*pass*/ + } + + MixIn.prototype.mixed = function(x) { + console.log("mixin:", x); + } + MixIn.mixed = function () { return MixIn.prototype.mixed.apply(arguments[0], Array.prototype.slice.call(arguments,1)) }; + + B = function() { + B.__init__(this); + } + + B.prototype.__init__ = function() { + console.log("B.init"); + A.__init__(this,1,2,3); + console.log(this.x, this.y, this.z); + } + B.__init__ = function () { return B.prototype.__init__.apply(arguments[0], Array.prototype.slice.call(arguments,1)) }; + + B.prototype.bar = function() { + console.log("bar"); + } + B.bar = function () { return B.prototype.bar.apply(arguments[0], Array.prototype.slice.call(arguments,1)) }; + + for (var n in A.prototype) { if (!(n in B.prototype)) { B.prototype[n] = A.prototype[n] }}; + + for (var n in MixIn.prototype) { if (!(n in B.prototype)) { B.prototype[n] = MixIn.prototype[n] }}; Generator Functions ------------------- diff --git a/pythonjs/ministdlib.py b/pythonjs/ministdlib.py index 6f747a9..21e7194 100644 --- a/pythonjs/ministdlib.py +++ b/pythonjs/ministdlib.py @@ -2,7 +2,13 @@ # by Brett Hartshorn - copyright 2013 # You may destribute this file using the "New BSD" or MIT license -LIB = { +DART = { + 'time': { + 'time' : 'time() { return new DateTime.now().millisecondsSinceEpoch / 1000.0; }' + } +} + +JS = { 'time': { 'time': 'function time() { return new Date().getTime() / 1000.0; }', 'clock': 'function clock() { return new Date().getTime() / 1000.0; }' diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index b0458a3..1ea5e97 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -167,8 +167,10 @@ class PythonToPythonJS(NodeVisitor): identifier = 0 - def __init__(self, source=None, module=None, module_path=None): + def __init__(self, source=None, module=None, module_path=None, dart=False): super(PythonToPythonJS, self).__init__() + + self._with_dart = dart self._source = source.splitlines() self._classes = dict() ## class name : [method names] self._class_parents = dict() ## class name : parents @@ -313,10 +315,16 @@ def visit_Import(self, node): raise NotImplementedError('import, line %s' % node.lineno) def visit_ImportFrom(self, node): - if node.module in ministdlib.LIB: + if self._with_dart: + lib = ministdlib.DART + else: + lib = ministdlib.JS + + + if node.module in lib: for n in node.names: - if n.name in ministdlib.LIB[ node.module ]: - writer.write( 'JS("%s")' %ministdlib.LIB[node.module][n.name] ) + if n.name in lib[ node.module ]: + writer.write( 'JS("%s")' %lib[node.module][n.name] ) if n.name not in self._builtin_functions: self._builtin_functions[ n.name ] = n.name + '()' @@ -360,7 +368,10 @@ def visit_Dict(self, node): k = self.visit( node.keys[ i ] ) v = self.visit( node.values[i] ) if self._with_js: - a.append( '%s:%s'%(k,v) ) + if isinstance(node.keys[i], ast.Str): + a.append( '%s:%s'%(k,v) ) + else: + a.append( '"%s":%s'%(k,v) ) else: a.append( 'JSObject(key=%s, value=%s)'%(k,v) ) if self._with_js: @@ -1802,7 +1813,7 @@ def visit_FunctionDef(self, node): types.append( '%s : "%s"' %(self.visit(key), value) ) - if False: ## not dart compatible? + if not self._with_dart: ## Dart functions can not have extra attributes? ## note, in javascript function.name is a non-standard readonly attribute, ## the compiler creates anonymous functions with name set to an empty string. writer.write('%s.NAME = "%s"' %(node.name,node.name)) @@ -2313,7 +2324,7 @@ def inspect_function( node ): def main(script): - PythonToPythonJS( source=script ) + PythonToPythonJS( source=script, dart='--dart' in sys.argv ) return writer.getvalue() @@ -2340,7 +2351,12 @@ def command(): data = sys.stdin.read() - compiler = PythonToPythonJS( source=data, module=module, module_path=module_path ) + compiler = PythonToPythonJS( + source=data, + module=module, + module_path=module_path, + dart='--dart' in sys.argv + ) compiler.save_module() output = writer.getvalue() print( output ) ## pipe to stdout diff --git a/pythonjs/pythonjs.py b/pythonjs/pythonjs.py index 8ec66c7..26d2cf1 100755 --- a/pythonjs/pythonjs.py +++ b/pythonjs/pythonjs.py @@ -408,6 +408,13 @@ def visit_Dict(self, node): return '{ %s }' %b + def _visit_for_prep_iter_helper(self, node, out): + ## support "for key in JSObject" ## + #out.append( self.indent() + 'if (! (iter instanceof Array) ) { iter = Object.keys(iter) }' ) + ## new style - Object.keys only works for normal JS-objects, not ones created with `Object.create(null)` + out.append( self.indent() + 'if (! (iter instanceof Array) ) { iter = __object_keys__(iter) }' ) + + def visit_For(self, node): ''' for loops inside a `with javascript:` block will produce this faster for loop. @@ -428,11 +435,7 @@ def visit_For(self, node): out = [] out.append( self.indent() + 'var iter = %s;\n' % iter ) - ## support "for key in JSObject" ## - #out.append( self.indent() + 'if (! (iter instanceof Array) ) { iter = Object.keys(iter) }' ) - ## new style - Object.keys only works for normal JS-objects, not ones created with `Object.create(null)` - out.append( self.indent() + 'if (! (iter instanceof Array) ) { iter = __object_keys__(iter) }' ) - + self._visit_for_prep_iter_helper(node, out) out.append( self.indent() + 'for (var %s=0; %s < iter.length; %s++) {' % (target, target, target) ) self.push() diff --git a/pythonjs/pythonjs_to_dart.py b/pythonjs/pythonjs_to_dart.py index 6de1905..d80634b 100644 --- a/pythonjs/pythonjs_to_dart.py +++ b/pythonjs/pythonjs_to_dart.py @@ -7,6 +7,19 @@ import pythonjs class DartGenerator( pythonjs.JSGenerator ): + def _visit_for_prep_iter_helper(self, node, out): + pass + + + def visit_Expr(self, node): + # XXX: this is UGLY + s = self.visit(node.value) + if not s.endswith(';'): + s += ';' + return s + + + def visit_Print(self, node): args = [self.visit(e) for e in node.values] s = 'print(%s);' % ', '.join(args) diff --git a/tests/dart_helloworld.html b/tests/dart_helloworld.html index dc30d33..46b5d77 100644 --- a/tests/dart_helloworld.html +++ b/tests/dart_helloworld.html @@ -2,7 +2,7 @@ - @@ -135,7 +124,7 @@ def convert_python_html_document( data ): ''' doc = list() script = None - use_closure = False + use_dart = DART for line in data.splitlines(): if line.strip().startswith('') #doc.append( '': if script: src = '\n'.join( script ) - js = python_to_javascript( src, closure_compiler=use_closure, debug=True ) + js = python_to_javascript( src, debug=True, dart=use_dart ) doc.append( js ) doc.append( line ) script = None @@ -176,8 +165,8 @@ def convert_python_html_document( data ): def regenerate_runtime(): - print('regenerating pythonscript runtime...') - a = '// PythonScript Runtime - regenerated on: %s' %datetime.datetime.now().ctime() + print('regenerating pythonjs runtime...') + a = '// PythonJS Runtime - regenerated on: %s' %datetime.datetime.now().ctime() b = pythonjs_to_javascript( open(PATHS['runtime_pythonjs'],'rb').read().decode('utf-8'), ) @@ -224,7 +213,7 @@ def get(self, path=None): if path.endswith('.py'): print('converting python binding to javascript', name) module = name.split('.')[0] - data = python_to_javascript( data.decode('utf-8'), closure_compiler=False, module=module ) + data = python_to_javascript( data.decode('utf-8'), module=module ) if '--dump-js' in sys.argv: f = open( os.path.join('/tmp',name+'.js'), 'wb' ) f.write(data.encode('utf-8')) @@ -254,7 +243,7 @@ def get(self, path=None): data = convert_python_html_document( data.decode('utf-8') ) self.set_header("Content-Type", "text/html; charset=utf-8") elif path.endswith('.py'): - data = python_to_javascript( data.decode('utf-8'), closure_compiler=True ) + data = python_to_javascript( data.decode('utf-8') ) self.set_header("Content-Type", "text/html; charset=utf-8") self.set_header("Content-Length", len(data)) @@ -385,7 +374,7 @@ def on_close(self): if __name__ == '__main__': assert os.path.isfile( PATHS['runtime'] ) - assert os.path.isdir( PATHS['pythonscript'] ) + assert os.path.isdir( PATHS['pythonjs'] ) assert os.path.isdir( PATHS['bindings'] ) if '--regenerate-runtime' in sys.argv: diff --git a/tests/test_with_javascript.html b/tests/test_with_javascript.html index e2ce2a2..5731f2c 100644 --- a/tests/test_with_javascript.html +++ b/tests/test_with_javascript.html @@ -7,13 +7,13 @@ a = 'hello' b = 'world' -def test(): +def main(): with javascript: arr = [] arr.push('hello') arr[1] = 'world' - ob = { x:'foo', y:'bar'} + ob = { "x":'foo', y:'bar'} print arr print ob i = 0 @@ -46,6 +46,6 @@ - + From 53f61e0e7b3d9bd1b0f87ef8e0faaa061635db48 Mon Sep 17 00:00:00 2001 From: hartsantler Date: Fri, 6 Dec 2013 02:46:03 -0800 Subject: [PATCH 034/521] refactoring core for Dart: support for simple Dart classes. --- pythonjs/python_to_pythonjs.py | 67 ++++++++++++++++++++++++--- pythonjs/pythonjs_to_dart.py | 21 +++++++++ tests/server.py | 2 + tests/test_subclass_javascript.html | 4 +- tests/test_with_javascript_class.html | 7 ++- 5 files changed, 91 insertions(+), 10 deletions(-) diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index 1ea5e97..400cd92 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -538,6 +538,50 @@ def _get_js_class_base_init(self, node ): else: return self._get_js_class_base_init( n ) ## TODO fixme + def _visit_dart_classdef(self, node): + name = node.name + log('Dart-ClassDef: %s'%name) + self._js_classes[ name ] = node + + methods = {} + props = set() + for item in node.body: + if isinstance(item, FunctionDef): + methods[ item.name ] = item + item.args.args = item.args.args[1:] ## remove self + finfo = inspect_method( item ) + props.update( finfo['properties'] ) + for n in finfo['name_nodes']: + if n.id == 'self': + n.id = 'this' + + init = methods.get( '__init__', None) + + + bases = [] + for base in node.bases: + bases.append( self.visit(base) ) + if bases: + writer.write('class %s( %s ):'%(node.name, ','.join(bases))) + + else: + writer.write('class %s:' %node.name) + + writer.push() + ## declare vars here + for attr in props: + writer.write('JS("var %s")'%attr) + ## constructor + if init: + methods.pop( '__init__' ) + init.name = node.name + self.visit(init) + ## methods + for method in methods.values(): + self.visit(method) + + writer.pull() + def _visit_js_classdef(self, node): name = node.name log('JavaScript-ClassDef: %s'%name) @@ -616,7 +660,10 @@ def _visit_js_classdef(self, node): self._in_js_class = False def visit_ClassDef(self, node): - if self._with_js: + if self._with_dart: + self._visit_dart_classdef(node) + return + elif self._with_js: self._visit_js_classdef(node) return @@ -2276,10 +2323,6 @@ def retrieve_vars(body): local_vars.add( c.id ) elif isinstance(n, Global): global_vars.update( n.names ) - elif isinstance(n, With) and isinstance( n.context_expr, Name ) and n.context_expr.id == 'javascript': - for c in n.body: - if isinstance(c, Assign) and isinstance(c.targets[0], Name): ## assignment to local - local_vars.add( c.targets[0].id ) elif hasattr(n, 'body') and not isinstance(n, FunctionDef): # do a recursive search inside new block except function def l, g = retrieve_vars(n.body) @@ -2292,6 +2335,15 @@ def retrieve_vars(body): return local_vars, global_vars +def retrieve_properties(body): + props = set() + for n in body: + if isinstance(n, ast.Assign) and isinstance(n.targets[0], ast.Attribute) and isinstance(n.targets[0].value, ast.Name) and n.targets[0].value.id == 'self': + props.add( n.targets[0].attr ) + elif hasattr(n, 'body') and not isinstance(n, FunctionDef): + props.update( retrieve_properties(n.body) ) + return props + def inspect_function( node ): local_vars, global_vars = retrieve_vars(node.body) local_vars = local_vars - global_vars @@ -2321,7 +2373,10 @@ def inspect_function( node ): } return info - +def inspect_method( node ): + info = inspect_function( node ) + info['properties'] = retrieve_properties( node.body ) + return info def main(script): PythonToPythonJS( source=script, dart='--dart' in sys.argv ) diff --git a/pythonjs/pythonjs_to_dart.py b/pythonjs/pythonjs_to_dart.py index d80634b..9550eef 100644 --- a/pythonjs/pythonjs_to_dart.py +++ b/pythonjs/pythonjs_to_dart.py @@ -7,6 +7,27 @@ import pythonjs class DartGenerator( pythonjs.JSGenerator ): + def visit_ClassDef(self, node): + out = [] + bases = [] + for base in node.bases: + bases.append( self.visit(base) ) + if bases: + out.append('class %s extends %s {'%(node.name, ','.join(bases))) + + else: + out.append('class %s {' %node.name) + self.push() + for b in node.body: + line = self.visit(b) + if line.startswith('var '): + out.append( self.indent()+line ) + else: + out.append( line ) + self.pull() + out.append('}') + return '\n'.join(out) + def _visit_for_prep_iter_helper(self, node, out): pass diff --git a/tests/server.py b/tests/server.py index 9ecc2e9..266188b 100755 --- a/tests/server.py +++ b/tests/server.py @@ -50,6 +50,8 @@ def python_to_pythonjs( src, module=None, dart=False ): return stdout.decode('utf-8') def pythonjs_to_dart(src): + if os.path.isfile('/tmp/dart2js-output.js'): + os.unlink('/tmp/dart2js-output.js') p = subprocess.Popen( ['python2', os.path.join( PATHS['pythonjs'],'pythonjs_to_dart.py')], stdin = subprocess.PIPE, diff --git a/tests/test_subclass_javascript.html b/tests/test_subclass_javascript.html index db69947..6e2de97 100644 --- a/tests/test_subclass_javascript.html +++ b/tests/test_subclass_javascript.html @@ -33,7 +33,7 @@ def bar(self): print 'bar' - def test(): + def main(): global a a = B() a.foo() @@ -46,6 +46,6 @@ - + \ No newline at end of file diff --git a/tests/test_with_javascript_class.html b/tests/test_with_javascript_class.html index 1fc9bd4..751b1cf 100644 --- a/tests/test_with_javascript_class.html +++ b/tests/test_with_javascript_class.html @@ -13,19 +13,22 @@ -def test(): +def main(): print 'testing with javascript class' with javascript: for i in range(10): a = A() print a + print a.x + print a.y + print a.z - + \ No newline at end of file From 88bff6d9e9e2bc970dad75acb293aac4f0da0e9d Mon Sep 17 00:00:00 2001 From: hartsantler Date: Fri, 6 Dec 2013 06:36:14 -0800 Subject: [PATCH 035/521] updated README --- README.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.rst b/README.rst index a1ca1d4..e9b0536 100644 --- a/README.rst +++ b/README.rst @@ -34,6 +34,10 @@ decorators described below. When PythonJS is run in fast mode (javascript with inline functions) it beats PyPy in the Richards, Pystone, and N-Body benchmarks. +.. image:: http://1.bp.blogspot.com/-Pn7jNLT-Suo/UphWdu48WiI/AAAAAAAAAis/n5HgVFJwgH8/s400/nbody.png + +N-Body benchmark, PythonJS in javascript mode with inlined functions is 10x faster than PyPy2.2 + NodeJS --------------- Using PythonJS you can quickly port your server side code to @@ -343,6 +347,10 @@ Python vs JavaScript Modes PythonJS has two primary modes you can write code in: "python" and "javascript". The default mode is "python", you can mark sections of your code to use either mode with "pythonjs.configure(javascript=True/False)" or nesting blocks inside "with python:" or "with javascript:". The "javascript" mode can be used for sections of code where performance is a major concern. When in "javascript" mode the literal "[]" syntax will return a JavaScript Array instead of a PythonJS list, and a literal "{}" returns a JavaScript Object instead of a PythonJS dict. In both modes you can directly call external JavaScript functions, its only faster in "javascript" mode because function calls are direct without any wrapping. +.. image:: http://3.bp.blogspot.com/-Bl9I6tGEEMU/UqHIEK90bsI/AAAAAAAAAjk/0zn77pKXURU/s400/pystoned-modes.png + +The Pystone benchmark is 800 times faster in "javascript" mode with inlined functions than normal "python" mode. + If your familiar with the details of the JavaScript language you might expect JavaScript rules to apply when in "javascript" mode, however they do not, it is still Python style. For example, in true JavaScript a for-in loop over an Array yields the indices, and a for-in loop over an Object yields the values - this is the opposite of what happens in Python and PythonJS. From ee7efbae709001511889668b7dda48d3a6b52596 Mon Sep 17 00:00:00 2001 From: hartsantler Date: Fri, 6 Dec 2013 09:24:06 -0800 Subject: [PATCH 036/521] refactoring core for Dart: subclasses --- pythonjs/python_to_pythonjs.py | 18 ++++--- pythonjs/pythonjs.py | 14 ++--- pythonjs/pythonjs_to_dart.py | 69 +++++++++++++++++++++--- tests/test_with_javascript_class.html | 2 + tests/test_with_javascript_subclass.html | 14 ++--- 5 files changed, 91 insertions(+), 26 deletions(-) diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index 400cd92..91ef168 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -548,15 +548,17 @@ def _visit_dart_classdef(self, node): for item in node.body: if isinstance(item, FunctionDef): methods[ item.name ] = item - item.args.args = item.args.args[1:] ## remove self finfo = inspect_method( item ) props.update( finfo['properties'] ) + + if item.name == '__init__': continue + + item.args.args = item.args.args[1:] ## remove self for n in finfo['name_nodes']: if n.id == 'self': n.id = 'this' - init = methods.get( '__init__', None) - + writer.write('@properties(%s)'%','.join(props)) bases = [] for base in node.bases: @@ -567,10 +569,12 @@ def _visit_dart_classdef(self, node): else: writer.write('class %s:' %node.name) + init = methods.get( '__init__', None) + writer.push() ## declare vars here - for attr in props: - writer.write('JS("var %s")'%attr) + #for attr in props: + # writer.write('JS("var %s")'%attr) ## constructor if init: methods.pop( '__init__' ) @@ -1720,7 +1724,7 @@ def visit_FunctionDef(self, node): dindex = i - offset if dindex >= 0: default_value = self.visit( node.args.defaults[dindex] ) - writer.write( '''JS("if (%s === undefined) %s = %s")'''%(arg.id, arg.id, default_value) ) + writer.write( '''JS("if (%s == undefined) %s = %s")'''%(arg.id, arg.id, default_value) ) elif self._with_fastdef or fastdef: offset = len(node.args.args) - len(node.args.defaults) @@ -1729,7 +1733,7 @@ def visit_FunctionDef(self, node): if dindex >= 0 and node.args.defaults: default_value = self.visit( node.args.defaults[dindex] ) writer.write('''JS("var %s = kwargs[ '%s' ]")''' % (arg.id, arg.id)) - writer.write( '''JS("if (%s === undefined) %s = %s")'''%(arg.id, arg.id, default_value) ) + writer.write( '''JS("if (%s == undefined) %s = %s")'''%(arg.id, arg.id, default_value) ) else: writer.write("""JS("var %s = args[ %s ]")""" % (arg.id, i)) diff --git a/pythonjs/pythonjs.py b/pythonjs/pythonjs.py index 26d2cf1..ecb15bc 100755 --- a/pythonjs/pythonjs.py +++ b/pythonjs/pythonjs.py @@ -181,15 +181,17 @@ def visit_keyword(self, node): return node.arg, self.visit(node.value) return self.visit(node.arg), self.visit(node.value) + def _visit_call_helper_instanceof(self, node): + args = map(self.visit, node.args) + if len(args) == 2: + return '%s instanceof %s' %tuple(args) + else: + raise SyntaxError( args ) + def visit_Call(self, node): name = self.visit(node.func) if name == 'instanceof': ## this gets used by "with javascript:" blocks to test if an instance is a JavaScript type - args = map(self.visit, node.args) - if len(args) == 2: - return '%s instanceof %s' %tuple(args) - else: - raise SyntaxError( args ) - + return self._visit_call_helper_instanceof( node ) #elif name == 'new': # args = map(self.visit, node.args) # if len(args) == 1: diff --git a/pythonjs/pythonjs_to_dart.py b/pythonjs/pythonjs_to_dart.py index 9550eef..57301dc 100644 --- a/pythonjs/pythonjs_to_dart.py +++ b/pythonjs/pythonjs_to_dart.py @@ -7,23 +7,65 @@ import pythonjs class DartGenerator( pythonjs.JSGenerator ): + _classes = dict() + _class_props = dict() def visit_ClassDef(self, node): out = [] + + props = set() + self._classes[ node.name ] = node + self._class_props[ node.name ] = props + for decor in node.decorator_list: ## class decorators + if isinstance(decor, ast.Call): + props.update( [self.visit(a) for a in decor.args] ) + + + bases = [] + base_classes = [] for base in node.bases: - bases.append( self.visit(base) ) + n = self.visit(base) + bases.append( n ) + props.update( self._class_props[n] ) + base_classes.append( self._classes[n] ) if bases: - out.append('class %s extends %s {'%(node.name, ','.join(bases))) + #out.append('class %s extends %s {'%(node.name, ','.join(bases))) + out.append('class %s implements %s {'%(node.name, ','.join(bases))) + #out.append('class %s extends Object with %s {'%(node.name, ','.join(bases))) + else: out.append('class %s {' %node.name) self.push() + + for p in props: + out.append(self.indent()+ 'var %s;'%p) + + for bnode in base_classes: + for b in bnode.body: + if isinstance(b, ast.FunctionDef): + if b.name == '__init__': continue + out.append( self.visit(b) ) + for b in node.body: - line = self.visit(b) - if line.startswith('var '): - out.append( self.indent()+line ) + + if isinstance(b, ast.FunctionDef) and b.name == node.name: + args = [self.visit(a) for a in b.args.args][1:] + args = ','.join(args) + #out.append( self.indent()+'static void __init__(this, %s) : this(%s);'%(args,args)) + b._prefix = 'static void ' + b.name = '__init__' + out.append( self.visit(b) ) + out.append( + self.indent()+'%s(%s) {%s.__init__(this,%s);}'%(node.name, args, node.name, args) + ) else: - out.append( line ) + line = self.visit(b) + if line.startswith('var '): + out.append( self.indent()+line ) + else: + out.append( line ) + self.pull() out.append('}') return '\n'.join(out) @@ -64,7 +106,10 @@ def visit_Assign(self, node): def visit_FunctionDef(self, node): args = self.visit(node.args) - buffer = self.indent() + '%s(%s) {\n' % (node.name, ', '.join(args)) + buffer = self.indent() + if hasattr(node,'_prefix'): + buffer += node._prefix + buffer += '%s(%s) {\n' % (node.name, ', '.join(args)) self.push() body = list() for child in node.body: @@ -79,6 +124,16 @@ def visit_FunctionDef(self, node): return buffer + def visit_Is(self, node): + return '==' + + def _visit_call_helper_instanceof(self, node): + args = map(self.visit, node.args) + if len(args) == 2: + return '%s is %s' %tuple(args) + else: + raise SyntaxError( args ) + def main(script): diff --git a/tests/test_with_javascript_class.html b/tests/test_with_javascript_class.html index 751b1cf..11fa641 100644 --- a/tests/test_with_javascript_class.html +++ b/tests/test_with_javascript_class.html @@ -23,6 +23,8 @@ print a.x print a.y print a.z + if instanceof(a, A): + print 'a is instanceof A' diff --git a/tests/test_with_javascript_subclass.html b/tests/test_with_javascript_subclass.html index 983bc61..e4fd2d2 100644 --- a/tests/test_with_javascript_subclass.html +++ b/tests/test_with_javascript_subclass.html @@ -4,6 +4,8 @@ - + \ No newline at end of file From 72c3022abb4b860974c42e9264397293266a1084 Mon Sep 17 00:00:00 2001 From: hartsantler Date: Fri, 6 Dec 2013 17:23:48 -0800 Subject: [PATCH 037/521] Dart backend: in order to allow for multiple inheritance and subclasses to call their parents methods this implementation is required: static class methods that implement the method body with stub methods calling them and pass "this" as the first argument. --- README.rst | 23 +++++++++ pythonjs/python_to_pythonjs.py | 3 +- pythonjs/pythonjs_to_dart.py | 66 ++++++++++++++++++------ tests/test_with_javascript_subclass.html | 5 ++ 4 files changed, 80 insertions(+), 17 deletions(-) diff --git a/README.rst b/README.rst index e9b0536..cf6000e 100644 --- a/README.rst +++ b/README.rst @@ -174,6 +174,29 @@ Example JavaScript Translation:: for (var n in A.prototype) { if (!(n in B.prototype)) { B.prototype[n] = A.prototype[n] }}; + +The above output Javascript shows how the constructor for B calls B.__init__ which then calls B.prototype.__init__. +B.prototype.__init__ calls A.__init__ passing "this" as the first argument. This emulates in JavaScript how unbound methods work in Python. When using the Dart backend, the output is different but the concept is the same - static "class methods" are created that implement the method body, the instance methods are just short stubs that call the static "class methods". + +Example Dart Translation:: + + class B implements A { + var y; + var x; + var z; + var w; + B(w) {B.__init__(this,w);} + static void __init__(self, w) { + A.__init__(self,10,20,30); + self.w=w; + } + + foo(w) { return A.__foo(this,w); } + } + +Above the method "foo" calls the static class method A.__foo. Note that the static class methods are automatically prefixed with "__". + + Multiple Inheritance -------------------- diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index 91ef168..e0f56e6 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -551,7 +551,8 @@ def _visit_dart_classdef(self, node): finfo = inspect_method( item ) props.update( finfo['properties'] ) - if item.name == '__init__': continue + #if item.name == '__init__': continue + continue item.args.args = item.args.args[1:] ## remove self for n in finfo['name_nodes']: diff --git a/pythonjs/pythonjs_to_dart.py b/pythonjs/pythonjs_to_dart.py index 57301dc..db39f63 100644 --- a/pythonjs/pythonjs_to_dart.py +++ b/pythonjs/pythonjs_to_dart.py @@ -11,8 +11,9 @@ class DartGenerator( pythonjs.JSGenerator ): _class_props = dict() def visit_ClassDef(self, node): out = [] - + extends = False ## Dart has no support for multiple inheritance! props = set() + self._classes[ node.name ] = node self._class_props[ node.name ] = props for decor in node.decorator_list: ## class decorators @@ -29,9 +30,11 @@ def visit_ClassDef(self, node): props.update( self._class_props[n] ) base_classes.append( self._classes[n] ) if bases: - #out.append('class %s extends %s {'%(node.name, ','.join(bases))) - out.append('class %s implements %s {'%(node.name, ','.join(bases))) - #out.append('class %s extends Object with %s {'%(node.name, ','.join(bases))) + if extends: + assert len(bases) == 1 + out.append('class %s extends %s {'%(node.name, ','.join(bases))) + else: + out.append('class %s implements %s {'%(node.name, ', '.join(bases))) else: @@ -41,24 +44,38 @@ def visit_ClassDef(self, node): for p in props: out.append(self.indent()+ 'var %s;'%p) - for bnode in base_classes: - for b in bnode.body: - if isinstance(b, ast.FunctionDef): - if b.name == '__init__': continue - out.append( self.visit(b) ) for b in node.body: if isinstance(b, ast.FunctionDef) and b.name == node.name: args = [self.visit(a) for a in b.args.args][1:] args = ','.join(args) - #out.append( self.indent()+'static void __init__(this, %s) : this(%s);'%(args,args)) - b._prefix = 'static void ' + b._prefix = 'static void' b.name = '__init__' out.append( self.visit(b) ) - out.append( - self.indent()+'%s(%s) {%s.__init__(this,%s);}'%(node.name, args, node.name, args) - ) + if args: + out.append( + self.indent()+'%s(%s) {%s.__init__(this,%s);}'%(node.name, args, node.name, args) + ) + else: + out.append( + self.indent()+'%s() {%s.__init__(this);}'%(node.name, node.name) + ) + + elif isinstance(b, ast.FunctionDef): + args = [self.visit(a) for a in b.args.args][1:] + args = ','.join(args) + if args: + out.append(self.indent()+ '%s(%s) { return %s.__%s(this,%s); }'%(b.name, args, node.name, b.name, args) ) + else: + out.append(self.indent()+ '%s() { return %s.__%s(this); }'%(b.name, node.name, b.name) ) + + b._prefix = 'static' + name = b.name + b.name = '__%s'%name + out.append( self.visit(b) ) + b.name = name + else: line = self.visit(b) if line.startswith('var '): @@ -66,6 +83,20 @@ def visit_ClassDef(self, node): else: out.append( line ) + if not extends and base_classes: + for bnode in base_classes: + for b in bnode.body: + if isinstance(b, ast.FunctionDef): + if b.name == '__init__': continue + #out.append( self.visit(b) ) + args = [self.visit(a) for a in b.args.args][1:] + args = ','.join(args) + if args: + out.append(self.indent()+ '%s(%s) { return %s.__%s(this,%s); }'%(b.name, args, bnode.name, b.name, args) ) + else: + out.append(self.indent()+ '%s() { return %s.__%s(this); }'%(b.name, bnode.name, b.name) ) + + self.pull() out.append('}') return '\n'.join(out) @@ -85,7 +116,10 @@ def visit_Expr(self, node): def visit_Print(self, node): args = [self.visit(e) for e in node.values] - s = 'print(%s);' % ', '.join(args) + if len(args) > 1: + s = 'print([%s]);' % ', '.join(args) + else: + s = 'print(%s);' % ', '.join(args) return s @@ -108,7 +142,7 @@ def visit_FunctionDef(self, node): args = self.visit(node.args) buffer = self.indent() if hasattr(node,'_prefix'): - buffer += node._prefix + buffer += node._prefix + ' ' buffer += '%s(%s) {\n' % (node.name, ', '.join(args)) self.push() body = list() diff --git a/tests/test_with_javascript_subclass.html b/tests/test_with_javascript_subclass.html index e4fd2d2..5b334f5 100644 --- a/tests/test_with_javascript_subclass.html +++ b/tests/test_with_javascript_subclass.html @@ -26,6 +26,11 @@ return self.x + self.y + self.z + a+b+c def main(): + print 'testing super class A' + a = A('xxx', 'yyy', 'zzz') + print a.foo('www') + + print 'testing subclass B' b = B( 'hello' ) print b.x print b.foo( 100 ) From 14d2ba8739915c5b7caf40a2e4c55b4c93732dc9 Mon Sep 17 00:00:00 2001 From: hartsantler Date: Fri, 6 Dec 2013 20:07:15 -0800 Subject: [PATCH 038/521] Dart backend: fixed multiple inheritance. --- README.rst | 117 +++++++++++---------------- pythonjs/python_to_pythonjs.py | 14 +++- pythonjs/pythonjs.py | 13 +-- pythonjs/pythonjs_to_dart.py | 38 +++++++-- tests/test_multiple_inheritance.html | 11 ++- tests/test_subclass_javascript.html | 74 ++++++++--------- 6 files changed, 140 insertions(+), 127 deletions(-) diff --git a/README.rst b/README.rst index cf6000e..ffd1d85 100644 --- a/README.rst +++ b/README.rst @@ -15,13 +15,14 @@ irc freenode:: Introduction ====== -PythonJS is a Python to Javascript translator written in +PythonJS is a Python to Javascript and Dart translator written in Python, created by Amirouche Boubekki and Brett Hartshorn, currently maintained and developed by Brett. It features: list comprehensions, classes, multiple inheritance, operator overloading, function and class decorators, generator functions, HTML DOM, and easily integrates with JavaScript and external JavaScript libraries. The generated code works in the Browser and in NodeJS. +Note: the Dart backend is still very experimental. Speed --------------- @@ -200,96 +201,63 @@ Above the method "foo" calls the static class method A.__foo. Note that the sta Multiple Inheritance -------------------- -Multiple inheritance is fully supported. +Multiple inheritance is fully supported for both JavaScript and Dart backends. When using the Dart backend it will generate stub-methods that call static class methods that are prefixed with "__". +Methods that the subclass extends can call: ParentClassName.some_method(self) and this will be translated into: ParentClassName.__some_method(this) Example:: - pythonjs.configure(javascript=True) - class Root: - def method(self): - print 'method on root' - - class A( Root ): - def __init__(self,x,y,z): - print 'A.init', x,y,z - self.x = x - self.y = y - self.z = z - + class A: def foo(self): print 'foo' - - class MixIn: - def mixed(self, x): - print 'mixin:', x - - class B( A, MixIn ): - def __init__(self): - print 'B.init' - A.__init__(self, 1,2,3) - print self.x, self.y, self.z - + class B: def bar(self): print 'bar' -Example JavaScript Translation:: - - Root = function() { - /*pass*/ - } - - Root.prototype.method = function() { - console.log("method on root"); - } - - Root.method = function () { return Root.prototype.method.apply(arguments[0], Array.prototype.slice.call(arguments,1)) }; - A = function(x, y, z) { - A.__init__(this, x,y,z); - } + class C( A, B ): + def call_foo_bar(self): + print 'call_foo_bar in subclass C' + self.foo() + self.bar() - A.prototype.__init__ = function(x, y, z) { - console.log("A.init", x, y, z); - this.x=x; - this.y=y; - this.z=z; - } - A.__init__ = function () { return A.prototype.__init__.apply(arguments[0], Array.prototype.slice.call(arguments,1)) }; + ## extend foo ## + def foo(self): + A.foo(self) + print 'foo extended' - A.prototype.foo = function() { - console.log("foo"); - } - A.foo = function () { return A.prototype.foo.apply(arguments[0], Array.prototype.slice.call(arguments,1)) }; - for (var n in Root.prototype) { if (!(n in A.prototype)) { A.prototype[n] = Root.prototype[n] }}; +Example Dart Translation:: - MixIn = function() { - /*pass*/ - } + class A { + foo() { return A.__foo(this); } + static __foo(self) { + print("foo"); + } - MixIn.prototype.mixed = function(x) { - console.log("mixin:", x); } - MixIn.mixed = function () { return MixIn.prototype.mixed.apply(arguments[0], Array.prototype.slice.call(arguments,1)) }; + class B { + bar() { return B.__bar(this); } + static __bar(self) { + print("bar"); + } - B = function() { - B.__init__(this); } + class C implements A, B { + call_foo_bar() { return C.__call_foo_bar(this); } + static __call_foo_bar(self) { + print("call_foo_bar in subclass C"); + self.foo(); + self.bar(); + } - B.prototype.__init__ = function() { - console.log("B.init"); - A.__init__(this,1,2,3); - console.log(this.x, this.y, this.z); - } - B.__init__ = function () { return B.prototype.__init__.apply(arguments[0], Array.prototype.slice.call(arguments,1)) }; + foo() { return C.__foo(this); } + static __foo(self) { + A.__foo(self); + print("foo extended"); + } - B.prototype.bar = function() { - console.log("bar"); + bar() { return B.__bar(this); } } - B.bar = function () { return B.prototype.bar.apply(arguments[0], Array.prototype.slice.call(arguments,1)) }; - for (var n in A.prototype) { if (!(n in B.prototype)) { B.prototype[n] = A.prototype[n] }}; - - for (var n in MixIn.prototype) { if (!(n in B.prototype)) { B.prototype[n] = MixIn.prototype[n] }}; Generator Functions ------------------- @@ -813,6 +781,13 @@ Run Python Server:: cd PythonJS/tests ./server.py +Run Python Server in Dart Mode:: + + ./server.py --dart + +In Dart mode any test page you visit will be translated to Dart, and then converted back to JavaScript using "dart2js". You need to download the Dart SDK and make sure "dart2js" is located in: +~/dart/dart-sdk/bin/ + Testing ------- diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index e0f56e6..097186d 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -78,7 +78,7 @@ def write(self, code): def _write(self, code): indentation = self.level * 4 * ' ' - if self.with_javascript: + if self.with_javascript and False: ## deprecated if not code.endswith(':'): ## will this rule always catch: while, and if/else blocks? if not code.startswith('print '): if not code.startswith('var('): @@ -837,7 +837,10 @@ def visit_Name(self, node): elif node.id == 'False': return 'false' elif node.id == 'None': - return 'undefined' + if self._with_dart: + return 'null' + else: + return 'undefined' return node.id @@ -1288,6 +1291,9 @@ def _visit_assign_helper(self, node, target): log('set global type: %s'%type) writer.write('%s = %s' % (self.visit(target), node_value)) + + elif self._with_dart and writer.is_at_global_level(): + writer.write('var %s = %s' % (self.visit(target), node_value)) else: writer.write('%s = %s' % (self.visit(target), node_value)) @@ -1431,7 +1437,7 @@ def visit_Call(self, node): elif isinstance(node.func, Name) and node.func.id == 'new': assert len(args) == 1 - return ' new %s' %args[0] + return 'new(%s)' %args[0] elif isinstance(node.func, Name) and node.func.id == 'JS': ## avoids nested JS assert len(args) == 1 @@ -1439,7 +1445,7 @@ def visit_Call(self, node): elif isinstance(node.func, Name) and node.func.id in self._js_classes: a = ','.join(args) - return ' new %s(%s)' %( self.visit(node.func), a ) + return 'new( %s(%s) )' %( self.visit(node.func), a ) elif name in self._global_functions and self._with_inline: return self.inline_function( node ) diff --git a/pythonjs/pythonjs.py b/pythonjs/pythonjs.py index ecb15bc..9126e8c 100755 --- a/pythonjs/pythonjs.py +++ b/pythonjs/pythonjs.py @@ -192,12 +192,13 @@ def visit_Call(self, node): name = self.visit(node.func) if name == 'instanceof': ## this gets used by "with javascript:" blocks to test if an instance is a JavaScript type return self._visit_call_helper_instanceof( node ) - #elif name == 'new': - # args = map(self.visit, node.args) - # if len(args) == 1: - # return ' new %s' %args[0] - # else: - # raise SyntaxError( args ) + + elif name == 'new': + args = map(self.visit, node.args) + if len(args) == 1: + return ' new %s' %args[0] + else: + raise SyntaxError( args ) elif name == 'JSObject': if node.keywords: diff --git a/pythonjs/pythonjs_to_dart.py b/pythonjs/pythonjs_to_dart.py index db39f63..427e5cb 100644 --- a/pythonjs/pythonjs_to_dart.py +++ b/pythonjs/pythonjs_to_dart.py @@ -6,13 +6,27 @@ import ast import pythonjs +class TransformSuperCalls( ast.NodeVisitor ): + def __init__(self, node, class_names): + self._class_names = class_names + self.visit(node) + + def visit_Call(self, node): + if isinstance(node.func, ast.Attribute) and isinstance(node.func.value, ast.Name) and node.func.value.id in self._class_names: + node.func.attr = '__' + node.func.attr + + + class DartGenerator( pythonjs.JSGenerator ): _classes = dict() _class_props = dict() def visit_ClassDef(self, node): + node._parents = set() out = [] extends = False ## Dart has no support for multiple inheritance! props = set() + bases = set() + base_classes = set() self._classes[ node.name ] = node self._class_props[ node.name ] = props @@ -20,15 +34,19 @@ def visit_ClassDef(self, node): if isinstance(decor, ast.Call): props.update( [self.visit(a) for a in decor.args] ) - - - bases = [] - base_classes = [] for base in node.bases: n = self.visit(base) - bases.append( n ) + node._parents.add( n ) + + bases.add( n ) props.update( self._class_props[n] ) - base_classes.append( self._classes[n] ) + base_classes.add( self._classes[n] ) + + for p in self._classes[ n ]._parents: + bases.add( p ) + props.update( self._class_props[p] ) + base_classes.add( self._classes[p] ) + if bases: if extends: assert len(bases) == 1 @@ -44,7 +62,7 @@ def visit_ClassDef(self, node): for p in props: out.append(self.indent()+ 'var %s;'%p) - + method_names = set() for b in node.body: if isinstance(b, ast.FunctionDef) and b.name == node.name: @@ -63,6 +81,9 @@ def visit_ClassDef(self, node): ) elif isinstance(b, ast.FunctionDef): + method_names.add( b.name ) + TransformSuperCalls( b, bases ) + args = [self.visit(a) for a in b.args.args][1:] args = ','.join(args) if args: @@ -88,7 +109,8 @@ def visit_ClassDef(self, node): for b in bnode.body: if isinstance(b, ast.FunctionDef): if b.name == '__init__': continue - #out.append( self.visit(b) ) + if b.name in method_names: continue + args = [self.visit(a) for a in b.args.args][1:] args = ','.join(args) if args: diff --git a/tests/test_multiple_inheritance.html b/tests/test_multiple_inheritance.html index 669046a..e65eff4 100644 --- a/tests/test_multiple_inheritance.html +++ b/tests/test_multiple_inheritance.html @@ -4,6 +4,8 @@ From 9fa1e1164603700102b59595e564c2da6d57e085 Mon Sep 17 00:00:00 2001 From: hartsantler Date: Sat, 7 Dec 2013 21:33:29 -0800 Subject: [PATCH 039/521] Dart backend: new list class extends Dart's ListBase. New `dart_import` function for doing Dart imports. __getitem__ and __setitem__ are translate to: operator [] and operator []=. Support for getter/setter functions. For loop now works in Dart. --- pythonjs/python_to_pythonjs.py | 67 ++++++++++++------- pythonjs/pythonjs.py | 117 +++++++++++++++++++++------------ pythonjs/pythonjs_to_dart.py | 82 ++++++++++++++++++++--- runtime/dart_builtins.py | 48 ++++++++++++++ tests/server.py | 5 ++ tests/test_for_loop.html | 5 +- 6 files changed, 248 insertions(+), 76 deletions(-) create mode 100644 runtime/dart_builtins.py diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index 097186d..bb710e1 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -171,6 +171,8 @@ def __init__(self, source=None, module=None, module_path=None, dart=False): super(PythonToPythonJS, self).__init__() self._with_dart = dart + self._with_js = False + self._source = source.splitlines() self._classes = dict() ## class name : [method names] self._class_parents = dict() ## class name : parents @@ -185,7 +187,6 @@ def __init__(self, source=None, module=None, module_path=None, dart=False): self._return_type = None self._module = module self._module_path = module_path - self._with_js = False self._typedefs = dict() ## class name : typedef (not pickled) self._globals = dict() @@ -367,14 +368,14 @@ def visit_Dict(self, node): for i in range( len(node.keys) ): k = self.visit( node.keys[ i ] ) v = self.visit( node.values[i] ) - if self._with_js: + if self._with_js or self._with_dart: if isinstance(node.keys[i], ast.Str): a.append( '%s:%s'%(k,v) ) else: a.append( '"%s":%s'%(k,v) ) else: a.append( 'JSObject(key=%s, value=%s)'%(k,v) ) - if self._with_js: + if self._with_js or self._with_dart: b = ','.join( a ) return '{ %s }' %b else: @@ -384,7 +385,7 @@ def visit_Dict(self, node): def visit_Tuple(self, node): node.returns_type = 'tuple' a = '[%s]' % ', '.join(map(self.visit, node.elts)) - if self._with_js: + if self._with_js or self._with_dart: return a else: return '__get__(tuple, "__call__")([], {pointer:%s})' %a @@ -392,7 +393,7 @@ def visit_Tuple(self, node): def visit_List(self, node): node.returns_type = 'list' a = '[%s]' % ', '.join(map(self.visit, node.elts)) - if self._with_js: + if self._with_js or self._with_dart: return a else: return '__get__(list, "__call__")([], {pointer:%s})' %a @@ -504,7 +505,7 @@ def visit_AugAssign(self, node): a = '%s = Math.floor(%s/%s)' %(target, target, self.visit(node.value)) writer.write(a) - elif self._with_js: + elif self._with_js or self._with_dart: a = '%s %s %s' %(target, op, self.visit(node.value)) writer.write(a) @@ -544,6 +545,7 @@ def _visit_dart_classdef(self, node): self._js_classes[ name ] = node methods = {} + method_list = [] ## getter/setters can have the same name props = set() for item in node.body: if isinstance(item, FunctionDef): @@ -551,6 +553,9 @@ def _visit_dart_classdef(self, node): finfo = inspect_method( item ) props.update( finfo['properties'] ) + if item.name != '__init__': + method_list.append( item ) + #if item.name == '__init__': continue continue @@ -560,6 +565,8 @@ def _visit_dart_classdef(self, node): n.id = 'this' writer.write('@properties(%s)'%','.join(props)) + for dec in node.decorator_list: + writer.write('@%s'%self.visit(dec)) bases = [] for base in node.bases: @@ -582,7 +589,7 @@ def _visit_dart_classdef(self, node): init.name = node.name self.visit(init) ## methods - for method in methods.values(): + for method in method_list: self.visit(method) writer.pull() @@ -811,7 +818,7 @@ def visit_TryExcept(self, node): map(self.visit, node.handlers) def visit_Raise(self, node): - if self._with_js: + if self._with_js or self._with_dart: writer.write('throw Error') else: writer.write('raise %s' % self.visit(node.type)) @@ -831,7 +838,7 @@ def visit_Pass(self, node): writer.write('pass') def visit_Name(self, node): - if self._with_js: + if self._with_js or self._with_dart: if node.id == 'True': return 'true' elif node.id == 'False': @@ -910,7 +917,7 @@ def visit_BinOp(self, node): elts = [ self.visit(e) for e in node.left.elts ] expanded = [] for i in range( n ): expanded.extend( elts ) - if self._with_js: + if self._with_js or self._with_dart: return '[%s]' %','.join(expanded) else: return '__get__(list, "__call__")( [], {pointer:[%s]} )' %','.join(expanded) @@ -995,7 +1002,12 @@ def visit_Compare(self, node): comp.append( ' not (') a = ( self.visit(node.comparators[i]), left ) - if self._with_js: + + if self._with_dart: + ## indexOf works with lists and strings in Dart + comp.append( '%s.indexOf(%s) != -1' %(a[0], a[1]) ) + + elif self._with_js: ## this makes "if 'x' in Array" work like Python: "if 'x' in list" - TODO fix this for js-objects ## note javascript rules are confusing: "1 in [1,2]" is true, this is because a "in test" in javascript tests for an index ## TODO double check this code @@ -1032,7 +1044,7 @@ def visit_USub(self, node): def visit_Attribute(self, node): node_value = self.visit(node.value) - if self._with_js: + if self._with_js or self._with_dart: return '%s.%s' %(node_value, node.attr) typedef = None if isinstance(node.value, Name): @@ -1099,9 +1111,10 @@ def visit_Subscript(self, node): name = self.visit(node.value) if isinstance(node.slice, ast.Ellipsis): - return '%s["$wrapped"]' %name + #return '%s["$wrapped"]' %name + return '%s[...]' %name - elif self._with_js: + elif self._with_js or self._with_dart: if isinstance(node.slice, ast.Slice): ## allow slice on Array return '%s.__getslice__(%s)'%(name, self.visit(node.slice)) else: @@ -1154,9 +1167,10 @@ def _visit_assign_helper(self, node, target): name = self.visit(target.value) ## target.value may have "returns_type" after being visited if isinstance(target.slice, ast.Ellipsis): - code = '%s["$wrapped"] = %s' %(self.visit(target.value), self.visit(node.value)) + #code = '%s["$wrapped"] = %s' %(self.visit(target.value), self.visit(node.value)) + code = '%s[...] = %s' %(self.visit(target.value), self.visit(node.value)) - elif self._with_js: + elif self._with_js or self._with_dart: code = '%s[ %s ] = %s' code = code % (self.visit(target.value), self.visit(target.slice.value), self.visit(node.value)) @@ -1179,7 +1193,7 @@ def _visit_assign_helper(self, node, target): elif hasattr(target.value, 'returns_type'): typedef = self.get_typedef( class_name=target.value.returns_type ) - if self._with_js: + if self._with_js or self._with_dart: writer.write( '%s.%s=%s' %(target_value, target.attr, self.visit(node.value)) ) elif typedef and target.attr in typedef.properties and 'set' in typedef.properties[ target.attr ]: setter = typedef.properties[ target.attr ]['set'] @@ -1312,7 +1326,7 @@ def _visit_assign_helper(self, node, target): i ) writer.write(code) - elif self._with_js: + elif self._with_js or self._with_dart: writer.write("%s = %s[%s]" % (self.visit(target), r, i)) else: writer.write("%s = __get__(__get__(%s, '__getitem__'), '__call__')([%s], __NULL_OBJECT__)" % (self.visit(target), r, i)) @@ -1322,7 +1336,7 @@ def visit_Print(self, node): def visit_Str(self, node): s = node.s.replace('\n', '\\n').replace('\0', '\\0') - if self._with_js: + if self._with_js or self._with_dart: return '"%s"' %s else: if len(s) == 0: @@ -1422,7 +1436,7 @@ def visit_Call(self, node): else: raise SyntaxError - elif self._with_js: + elif self._with_js or self._with_dart: name = self.visit(node.func) args = list( map(self.visit, node.args) ) @@ -1628,6 +1642,7 @@ def visit_FunctionDef(self, node): property_decorator = None decorators = [] with_js_decorators = [] + with_dart_decorators = [] setter = False return_type = None fastdef = False @@ -1645,6 +1660,9 @@ def visit_FunctionDef(self, node): inline = True self._with_inline = True + elif self._with_dart: + with_dart_decorators.append( self.visit(decorator) ) + elif self._with_js: ## decorators are special in with-js mode with_js_decorators.append( self.visit( decorator ) ) @@ -1702,12 +1720,15 @@ def visit_FunctionDef(self, node): else: decorators.append( decorator ) - if self._with_js or javascript: + if self._with_js or javascript or self._with_dart: if node.args.vararg: raise SyntaxError( 'pure javascript functions can not take variable arguments (*args)' ) elif node.args.kwarg: raise SyntaxError( 'pure javascript functions can not take variable keyword arguments (**kwargs)' ) + if self._with_dart: + for dec in with_dart_decorators: + writer.write('@%s'%dec) args = [ a.id for a in node.args.args ] writer.write( 'def %s( %s ):' % (node.name, ','.join(args)) ) @@ -1724,7 +1745,7 @@ def visit_FunctionDef(self, node): a = ','.join( local_vars-global_vars ) writer.write('var(%s)' %a) - if self._with_js or javascript: + if self._with_js or javascript or self._with_dart: if node.args.defaults: offset = len(node.args.args) - len(node.args.defaults) for i, arg in enumerate(node.args.args): @@ -1956,7 +1977,7 @@ def visit_For(self, node): writer.write('%s = 0' %enumtar.id) - if self._with_js: + if self._with_js or self._with_dart: if isinstance(iter, ast.Call) and isinstance(iter.func, Name) and iter.func.id in ('range','xrange'): iter_start = '0' if len(iter.args) == 2: diff --git a/pythonjs/pythonjs.py b/pythonjs/pythonjs.py index 9126e8c..d9f4d1f 100755 --- a/pythonjs/pythonjs.py +++ b/pythonjs/pythonjs.py @@ -17,29 +17,30 @@ class JSGenerator(NodeVisitor): - _indent = 0 - _global_funcions = {} - - @classmethod - def push(cls): - cls._indent += 1 - @classmethod - def pull(cls): - if cls._indent > 0: - cls._indent -= 1 - @classmethod - def indent(cls): - return ' ' * cls._indent + def __init__(self): + self._indent = 0 + self._global_funcions = {} + self._function_stack = [] + + def indent(self): return ' ' * self._indent + def push(self): self._indent += 1 + def pull(self): + if self._indent > 0: self._indent -= 1 def visit_In(self, node): return ' in ' def visit_AugAssign(self, node): - a = '%s %s= %s' %(self.visit(node.target), self.visit(node.op), self.visit(node.value)) + a = '%s %s= %s;' %(self.visit(node.target), self.visit(node.op), self.visit(node.value)) return a def visit_Module(self, node): - return '\n'.join(map(self.visit, node.body)) + lines = [] + for b in node.body: + line = self.visit(b) + if line: lines.append( line ) + else:raise b + return '\n'.join(lines) def visit_Tuple(self, node): return '[%s]' % ', '.join(map(self.visit, node.elts)) @@ -92,12 +93,20 @@ def visit_Lambda(self, node): return '(function (%s) {return %s})' %(','.join(args), self.visit(node.body)) + def visit_FunctionDef(self, node): - if not hasattr(self, '_function_stack'): ## track nested functions ## - self._function_stack = [] + self._function_stack.append( node ) + node._local_vars = set() + buffer = self._visit_function( node ) + + if node == self._function_stack[0]: ## could do something special here with global function + #buffer += 'pythonjs.%s = %s' %(node.name, node.name) ## this is no longer needed + self._global_funcions[ node.name ] = buffer - self._function_stack.append( node.name ) + self._function_stack.pop() + return buffer + def _visit_function(self, node): args = self.visit(node.args) if len(node.decorator_list): assert len(node.decorator_list)==1 @@ -113,33 +122,28 @@ def visit_FunctionDef(self, node): self.push() body = list() for child in node.body: - # simple test to drop triple quote comments - #if hasattr(child, 'value'): - # if isinstance(child.value, Str): - # continue if isinstance(child, Str): continue - if isinstance(child, GeneratorType): + if isinstance(child, GeneratorType): ## not tested for sub in child: body.append( self.indent()+self.visit(sub)) else: body.append( self.indent()+self.visit(child)) + buffer += '\n'.join(body) self.pull() buffer += '\n%s}\n' %self.indent() + return buffer - if node.name == self._function_stack[0]: ## could do something special here with global function - #buffer += 'pythonjs.%s = %s' %(node.name, node.name) ## this is no longer needed - self._global_funcions[ node.name ] = buffer + def _visit_subscript_ellipsis(self, node): + name = self.visit(node.value) + return '%s["$wrapped"]' %name - assert node.name == self._function_stack.pop() - return buffer def visit_Subscript(self, node): if isinstance(node.slice, ast.Ellipsis): - name = self.visit(node.value) - return '%s["$wrapped"]' %name + return self._visit_subscript_ellipsis( node ) else: return '%s[%s]' % (self.visit(node.value), self.visit(node.slice)) @@ -208,10 +212,26 @@ def visit_Call(self, node): return '{%s}' % out else: return 'Object()' + elif name == 'var': - args = map(self.visit, node.args) - out = ', '.join(args) - return 'var %s' % out + args = [ self.visit(a) for a in node.args ] + if self._function_stack: + fnode = self._function_stack[-1] + rem = [] + for arg in args: + if arg in fnode._local_vars: + rem.append( arg ) + else: + fnode._local_vars.add( arg ) + for arg in rem: + args.remove( arg ) + + if args: + out = ', '.join(args) + return 'var %s' % out + else: + return '' + elif name == 'JSArray': if node.args: args = map(self.visit, node.args) @@ -234,6 +254,9 @@ def visit_Call(self, node): s = s.replace(' and ', ' && ') return s + elif name == 'dart_import': + return 'import "%s";' %node.args[0].s + else: if node.args: args = [self.visit(e) for e in node.args] @@ -411,13 +434,16 @@ def visit_Dict(self, node): return '{ %s }' %b - def _visit_for_prep_iter_helper(self, node, out): + def _visit_for_prep_iter_helper(self, node, out, iter_name): ## support "for key in JSObject" ## #out.append( self.indent() + 'if (! (iter instanceof Array) ) { iter = Object.keys(iter) }' ) ## new style - Object.keys only works for normal JS-objects, not ones created with `Object.create(null)` - out.append( self.indent() + 'if (! (iter instanceof Array) ) { iter = __object_keys__(iter) }' ) + out.append( + self.indent() + 'if (! (%s instanceof Array) ) { %s = __object_keys__(%s) }' %(iter_name, iter_name, iter_name) + ) + _iter_id = 0 def visit_For(self, node): ''' for loops inside a `with javascript:` block will produce this faster for loop. @@ -432,28 +458,33 @@ def visit_For(self, node): above works because [...] returns the internal Array of mylist ''' + self._iter_id += 1 + iname = '__iter%s' %self._iter_id + index = '__idx%s' %self._iter_id + target = node.target.id iter = self.visit(node.iter) # iter is the python iterator out = [] - out.append( self.indent() + 'var iter = %s;\n' % iter ) + out.append( self.indent() + 'var %s = %s;' % (iname, iter) ) + out.append( self.indent() + 'var %s = 0;' % index ) - self._visit_for_prep_iter_helper(node, out) + self._visit_for_prep_iter_helper(node, out, iname) - out.append( self.indent() + 'for (var %s=0; %s < iter.length; %s++) {' % (target, target, target) ) + out.append( self.indent() + 'for (var %s=0; %s < %s.length; %s++) {' % (index, index, iname, index) ) self.push() body = [] # backup iterator and affect value of the next element to the target - pre = 'var backup = %s; %s = iter[%s];' % (target, target, target) - body.append( self.indent() + pre ) + #pre = 'var backup = %s; %s = iter[%s];' % (target, target, target) + body.append( self.indent() + 'var %s = %s[ %s ];' %(target, iname, index) ) for line in list(map(self.visit, node.body)): body.append( self.indent() + line ) # replace the replace target with the javascript iterator - post = '%s = backup;' % target - body.append( self.indent() + post ) + #post = '%s = backup;' % target + #body.append( self.indent() + post ) self.pull() out.extend( body ) @@ -465,7 +496,7 @@ def visit_Continue(self, node): return 'continue' def visit_Break(self, node): - return 'break' + return 'break;' def main(script): tree = ast.parse( script ) diff --git a/pythonjs/pythonjs_to_dart.py b/pythonjs/pythonjs_to_dart.py index 427e5cb..da93843 100644 --- a/pythonjs/pythonjs_to_dart.py +++ b/pythonjs/pythonjs_to_dart.py @@ -15,11 +15,30 @@ def visit_Call(self, node): if isinstance(node.func, ast.Attribute) and isinstance(node.func.value, ast.Name) and node.func.value.id in self._class_names: node.func.attr = '__' + node.func.attr +class CollectNames(ast.NodeVisitor): + def __init__(self): + self._names = [] + def visit_Name(self, node): + self._names.append( node ) + +def collect_names(node): + a = CollectNames() + a.visit( node ) + return a._names class DartGenerator( pythonjs.JSGenerator ): _classes = dict() _class_props = dict() + + def _visit_subscript_ellipsis(self, node): + name = self.visit(node.value) + return '%s.$wrapped' %name + + def visit_List(self, node): + return 'new list([%s])' % ', '.join(map(self.visit, node.elts)) + + def visit_ClassDef(self, node): node._parents = set() out = [] @@ -33,14 +52,27 @@ def visit_ClassDef(self, node): for decor in node.decorator_list: ## class decorators if isinstance(decor, ast.Call): props.update( [self.visit(a) for a in decor.args] ) + elif isinstance(decor, ast.Attribute) and isinstance(decor.value, ast.Name) and decor.value.id == 'dart': + if decor.attr == 'extends': + extends = True + props.add('$wrapped') + for name_node in collect_names( node ): + if name_node.id == 'self': + name_node.id = 'this' + else: + raise SyntaxError + for base in node.bases: n = self.visit(base) node._parents.add( n ) bases.add( n ) - props.update( self._class_props[n] ) - base_classes.add( self._classes[n] ) + if n in self._class_props: + props.update( self._class_props[n] ) + base_classes.add( self._classes[n] ) + else: ## special case - subclassing a builtin like `list` + continue for p in self._classes[ n ]._parents: bases.add( p ) @@ -65,7 +97,27 @@ def visit_ClassDef(self, node): method_names = set() for b in node.body: - if isinstance(b, ast.FunctionDef) and b.name == node.name: + if extends: + if isinstance(b, ast.FunctionDef): + b.args.args = b.args.args[1:] + if b.name == node.name: + args = [self.visit(a) for a in b.args.args] + args = ','.join(args) + out.append( + self.indent()+'%s(%s) : super() { this.__init__(%s); }'%(node.name, args, args) + ) + b.name = '__init__' + elif b.name == '__getitem__': + b.name = '' + b._prefix = 'operator []' + elif b.name == '__setitem__': + b.name = '' + b._prefix = 'void operator []=' + + line = self.visit(b) + out.append( line ) + + elif isinstance(b, ast.FunctionDef) and b.name == node.name: args = [self.visit(a) for a in b.args.args][1:] args = ','.join(args) b._prefix = 'static void' @@ -123,7 +175,7 @@ def visit_ClassDef(self, node): out.append('}') return '\n'.join(out) - def _visit_for_prep_iter_helper(self, node, out): + def _visit_for_prep_iter_helper(self, node, out, iter_name): pass @@ -159,13 +211,27 @@ def visit_Assign(self, node): code = 'var %s = %s;' % (target, value) return code - def visit_FunctionDef(self, node): + def _visit_function(self, node): + getter = False + setter = False + for decor in node.decorator_list: + if isinstance(decor, ast.Name) and decor.id == 'property': + getter = True + elif isinstance(decor, ast.Attribute) and isinstance(decor.value, ast.Name) and decor.attr == 'setter': + setter = True + else: + raise SyntaxError args = self.visit(node.args) buffer = self.indent() - if hasattr(node,'_prefix'): - buffer += node._prefix + ' ' - buffer += '%s(%s) {\n' % (node.name, ', '.join(args)) + if hasattr(node,'_prefix'): buffer += node._prefix + ' ' + + if getter: + buffer += 'get %s {\n' % node.name + elif setter: + buffer += 'set %s(%s) {\n' % (node.name, ', '.join(args)) + else: + buffer += '%s(%s) {\n' % (node.name, ', '.join(args)) self.push() body = list() for child in node.body: diff --git a/runtime/dart_builtins.py b/runtime/dart_builtins.py new file mode 100644 index 0000000..1a6d9ed --- /dev/null +++ b/runtime/dart_builtins.py @@ -0,0 +1,48 @@ +# PythonJS builtins for Dart +# by Brett Hartshorn - copyright 2013 +# License: "New BSD" + +dart_import('dart:collection') + +@dart.extends +class list( ListBase ): + ''' + a List in Dart is growable if no size is given in the constructor, + otherwise if size is given it becomes a fixed length list. + + Notes: + https://code.google.com/p/dart/issues/detail?id=11201 + http://stackoverflow.com/questions/16247045/how-do-i-extend-a-list-in-dart + ''' + def __init__(self, items): + self[...] = new( List() ) + self[...].addAll( items ) + + @property + def length(self): + return self[...].length + @length.setter + def length(self,n): + self[...].length = n + + def __getitem__(self, index): + return self[...][index] + + def __setitem__(self, index, value): + self[...][index] = value + + def append(self, item): + self[...].add( item ) + + def index(self, obj): + return self[...].indexOf(obj) + + +def range(n): + r = [] + i = 0 + while i < n: + r.add( i ) + i += 1 + return r + diff --git a/tests/server.py b/tests/server.py index 266188b..dadb25c 100755 --- a/tests/server.py +++ b/tests/server.py @@ -25,6 +25,7 @@ runtime_pythonjs = os.path.abspath('../runtime/pythonpythonjs.py'), ## handwritten pythonjs runtime_builtins = os.path.abspath('../runtime/builtins.py'), + runtime_dart = os.path.abspath('../runtime/dart_builtins.py'), dart2js = os.path.expanduser( '~/dart/dart-sdk/bin/dart2js'), @@ -37,6 +38,10 @@ def python_to_pythonjs( src, module=None, dart=False ): cmd = ['python2', os.path.join( PATHS['pythonjs'], 'python_to_pythonjs.py')] if dart: cmd.append( '--dart' ) + + header = open( PATHS['runtime_dart'], 'rb' ).read().decode('utf-8') + src = header + '\n' + src + if module: cmd.append( '--module' ) cmd.append( module ) diff --git a/tests/test_for_loop.html b/tests/test_for_loop.html index 5911080..746a41f 100644 --- a/tests/test_for_loop.html +++ b/tests/test_for_loop.html @@ -5,7 +5,8 @@ + + + + + + + + \ No newline at end of file diff --git a/tests/server.py b/tests/server.py index 71271a8..0b4d4f4 100755 --- a/tests/server.py +++ b/tests/server.py @@ -30,6 +30,8 @@ dart2js = os.path.expanduser( '~/dart/dart-sdk/bin/dart2js'), dartanalyzer = os.path.expanduser( '~/dart/dart-sdk/bin/dartanalyzer'), + closure = os.path.expanduser( '~/closure-compiler/compiler.jar'), + ) DART = '--dart' in sys.argv ## force dart mode @@ -87,6 +89,19 @@ def pythonjs_to_javascript( src ): ) stdout, stderr = p.communicate( src.encode('utf-8') ) a = stdout.decode('utf-8') + + + if False and os.path.isfile( PATHS['closure'] ): + x = '/tmp/closure-input.js'; y = '/tmp/closure-output.js'; + f = open(x, 'wb'); f.write( a.encode('utf-8') ); f.close() + subprocess.call([ + 'java', '-jar', PATHS['closure'], + #'--compilation_level', 'ADVANCED_OPTIMIZATIONS', + '--js', x, '--js_output_file', y, + '--formatting', 'PRETTY_PRINT', + ]) + f = open(y, 'rb'); a = f.read().decode('utf-8'); f.close() + return a def python_to_javascript( src, module=None, dart=False, debug=False, dump=False ): From 95ea574c1be979e202d8938d585ff8f8f936dd2c Mon Sep 17 00:00:00 2001 From: hartsantler Date: Tue, 10 Dec 2013 23:15:45 -0800 Subject: [PATCH 044/521] Dart backend: translate operator overloading including inplace assignement operators to Dart. --- pythonjs/python_to_pythonjs.py | 31 +++- pythonjs/pythonjs_to_dart.py | 43 +++++ tests/test_vector3_operator_overloading.html | 179 +++++++++++++++++++ 3 files changed, 252 insertions(+), 1 deletion(-) create mode 100644 tests/test_vector3_operator_overloading.html diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index a76f9d1..b8cb68a 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -506,7 +506,36 @@ def visit_AugAssign(self, node): a = '%s = Math.floor(%s/%s)' %(target, target, self.visit(node.value)) writer.write(a) - elif self._with_js or self._with_dart: + elif self._with_dart: + if op == '+=': + a = '%s.__iadd__(%s)' %(target, self.visit(node.value)) + elif op == '-=': + a = '%s.__isub__(%s)' %(target, self.visit(node.value)) + elif op == '*=': + a = '%s.__imul__(%s)' %(target, self.visit(node.value)) + elif op == '/=': + a = '%s.__idiv__(%s)' %(target, self.visit(node.value)) + elif op == '%=': + a = '%s.__imod__(%s)' %(target, self.visit(node.value)) + elif op == '&=': + a = '%s.__iand__(%s)' %(target, self.visit(node.value)) + elif op == '|=': + a = '%s.__ior__(%s)' %(target, self.visit(node.value)) + elif op == '^=': + a = '%s.__ixor__(%s)' %(target, self.visit(node.value)) + elif op == '<<=': + a = '%s.__ilshift__(%s)' %(target, self.visit(node.value)) + elif op == '>>=': + a = '%s.__irshift__(%s)' %(target, self.visit(node.value)) + else: + raise NotImplementedError + + b = '%s %s %s' %(target, op, self.visit(node.value)) + ## dart2js is smart enough to optimize this if/else away ## + writer.write('if instanceof(%s, Number) or instanceof(%s, String): %s' %(target,target,b) ) + writer.write('else: %s' %a) + + elif self._with_js: ## no operator overloading in with-js mode a = '%s %s %s' %(target, op, self.visit(node.value)) writer.write(a) diff --git a/pythonjs/pythonjs_to_dart.py b/pythonjs/pythonjs_to_dart.py index a4e3b23..0433a71 100644 --- a/pythonjs/pythonjs_to_dart.py +++ b/pythonjs/pythonjs_to_dart.py @@ -129,6 +129,29 @@ def visit_ClassDef(self, node): elif b.name == '__setitem__': b.name = '' b._prefix = 'void operator []=' + elif b.name == '__add__': + b.name = '' + b._prefix = 'operator +' + elif b.name == '__iadd__': + b.name = '' + b._prefix = 'void operator +=' + elif b.name == '__sub__': + b.name = '' + b._prefix = 'operator -' + elif b.name == '__mul__': + b.name = '' + b._prefix = 'operator *' + elif b.name == '__div__': + b.name = '' + b._prefix = 'operator /' + + elif b.name == '__or__': + b.name = '' + b._prefix = 'operator |' + elif b.name == '__xor__': + b.name = '' + b._prefix = 'operator ^' + line = self.visit(b) @@ -158,6 +181,24 @@ def visit_ClassDef(self, node): operator = 'operator []' elif b.name == '__setitem__': operator = 'operator []=' + elif b.name == '__add__': + operator = 'operator +' + elif b.name == '__sub__': + operator = 'operator -' + elif b.name == '__mul__': + operator = 'operator *' + elif b.name == '__div__': + operator = 'operator /' + elif b.name == '__and__': + operator = 'operator &' + elif b.name == '__or__': + operator = 'operator |' + elif b.name == '__xor__': + operator = 'operator ^' + elif b.name == '__lshift__': + operator = 'operator <<' + elif b.name == '__rshift__': + operator = 'operator >>' args = [self.visit(a) for a in b.args.args][1:] args = ','.join(args) @@ -302,6 +343,8 @@ def visit_Is(self, node): def _visit_call_helper_instanceof(self, node): args = map(self.visit, node.args) if len(args) == 2: + if args[1] == 'Number': + args[1] = 'num' return '%s is %s' %tuple(args) else: raise SyntaxError( args ) diff --git a/tests/test_vector3_operator_overloading.html b/tests/test_vector3_operator_overloading.html new file mode 100644 index 0000000..787a8f4 --- /dev/null +++ b/tests/test_vector3_operator_overloading.html @@ -0,0 +1,179 @@ + + + + + + + + + + + \ No newline at end of file From cb47c620537a8888c79b246549ebcdd347ea9bd5 Mon Sep 17 00:00:00 2001 From: hartsantler Date: Sat, 14 Dec 2013 03:52:29 -0800 Subject: [PATCH 045/521] core: can not call javascript functions using keyword arguments they are converted to a JavaScript Object, if dict or list is passed to a js function - they are auto converted to Array and Object. --- README.rst | 27 + pythonjs.js | 639 +++++++++--------- pythonjs/python_to_pythonjs.py | 10 +- runtime/pythonpythonjs.py | 34 +- .../test_calling_javascript_keyword_args.html | 30 + tests/test_dom.html | 2 +- 6 files changed, 392 insertions(+), 350 deletions(-) create mode 100644 tests/test_calling_javascript_keyword_args.html diff --git a/README.rst b/README.rst index 97e06b8..e617304 100644 --- a/README.rst +++ b/README.rst @@ -384,6 +384,33 @@ are also returned directly, like document.body. This allows you to use the HTML DOM API just as you would in normal JavaScript. +If the JavaScript function you are calling takes a JavaScript +Object as the last argument you can call the function using +keyword arguments and they will be automatically converted +to a JavaScript Object. Any dictionaries or lists you pass +to a JavaScript function will be converted to: Array or Object. + +Example:: + + + + + --------------- Inline JavaScript diff --git a/pythonjs.js b/pythonjs.js index 46b82ba..1ff99f2 100644 --- a/pythonjs.js +++ b/pythonjs.js @@ -1,4 +1,4 @@ -// PythonScript Runtime - regenerated on: Thu Nov 28 22:43:36 2013 +// PythonJS Runtime - regenerated on: Sat Dec 14 03:40:42 2013 __NULL_OBJECT__ = Object.create(null); if (( "window" ) in this && ( "document" ) in this) { __NODEJS__ = false; @@ -24,13 +24,11 @@ __create_array__ = function() { "Used to fix a bug/feature of Javascript where new Array(number)\n created a array with number of undefined elements which is not\n what we want"; var array; array = []; - var iter = jsrange(arguments.length); - - if (! (iter instanceof Array) ) { iter = __object_keys__(iter) } - for (var i=0; i < iter.length; i++) { - var backup = i; i = iter[i]; + var __iter1 = jsrange(arguments.length); + if (! (__iter1 instanceof Array) ) { __iter1 = __object_keys__(__iter1) } + for (var __idx1=0; __idx1 < __iter1.length; __idx1++) { + var i = __iter1[ __idx1 ]; array.push(arguments[i]); - i = backup; } return array; } @@ -55,6 +53,26 @@ __get__ = function(object, attribute) { } else { if ({}.toString.call(object) === '[object Function]') { var wrapper = function(args, kwargs) { + var i, arg; + i = 0; + while(( i ) < args.length) { + arg = args[i]; + if (( typeof(arg) ) == "object") { + if (arg.__class__) { + if (( arg.__class__.__name__ ) == "list" || ( arg.__class__.__name__ ) == "tuple") { + args[i] = arg["$wrapped"]; + } else { + if (( arg.__class__.__name__ ) == "dict") { + args[i] = arg["$wrapped"]; + } + } + } + } + i += 1; + } + if (( Object.keys(kwargs).length ) != 0) { + args.push(kwargs); + } return object.apply(undefined, args); } @@ -184,11 +202,10 @@ __get__ = function(object, attribute) { } } bases = __class__.__bases__; - var iter = bases; - - if (! (iter instanceof Array) ) { iter = __object_keys__(iter) } - for (var base=0; base < iter.length; base++) { - var backup = base; base = iter[base]; + var __iter2 = bases; + if (! (__iter2 instanceof Array) ) { __iter2 = __object_keys__(__iter2) } + for (var __idx2=0; __idx2 < __iter2.length; __idx2++) { + var base = __iter2[ __idx2 ]; attr = _get_upstream_attribute(base, attribute); if (attr) { if ({}.toString.call(attr) === '[object Function]') { @@ -223,34 +240,29 @@ __get__ = function(object, attribute) { return attr; } } - base = backup; } - var iter = bases; - - if (! (iter instanceof Array) ) { iter = __object_keys__(iter) } - for (var base=0; base < iter.length; base++) { - var backup = base; base = iter[base]; + var __iter3 = bases; + if (! (__iter3 instanceof Array) ) { __iter3 = __object_keys__(__iter3) } + for (var __idx3=0; __idx3 < __iter3.length; __idx3++) { + var base = __iter3[ __idx3 ]; var prop; prop = _get_upstream_property(base, attribute); if (prop) { return prop["get"]([object], Object()); } - base = backup; } if (( "__getattr__" ) in __class__) { return __class__["__getattr__"]([object, attribute], Object()); } - var iter = bases; - - if (! (iter instanceof Array) ) { iter = __object_keys__(iter) } - for (var base=0; base < iter.length; base++) { - var backup = base; base = iter[base]; + var __iter4 = bases; + if (! (__iter4 instanceof Array) ) { __iter4 = __object_keys__(__iter4) } + for (var __idx4=0; __idx4 < __iter4.length; __idx4++) { + var base = __iter4[ __idx4 ]; var f; f = _get_upstream_attribute(base, "__getattr__"); if (f) { return f([object, attribute], Object()); } - base = backup; } } if (object instanceof Array) { @@ -297,13 +309,11 @@ _get_upstream_attribute = function(base, attr) { if (( attr ) in base) { return base[attr]; } - var iter = base.__bases__; - - if (! (iter instanceof Array) ) { iter = __object_keys__(iter) } - for (var parent=0; parent < iter.length; parent++) { - var backup = parent; parent = iter[parent]; + var __iter5 = base.__bases__; + if (! (__iter5 instanceof Array) ) { __iter5 = __object_keys__(__iter5) } + for (var __idx5=0; __idx5 < __iter5.length; __idx5++) { + var parent = __iter5[ __idx5 ]; return _get_upstream_attribute(parent, attr); - parent = backup; } } @@ -311,13 +321,11 @@ _get_upstream_property = function(base, attr) { if (( attr ) in base.__properties__) { return base.__properties__[attr]; } - var iter = base.__bases__; - - if (! (iter instanceof Array) ) { iter = __object_keys__(iter) } - for (var parent=0; parent < iter.length; parent++) { - var backup = parent; parent = iter[parent]; + var __iter6 = base.__bases__; + if (! (__iter6 instanceof Array) ) { __iter6 = __object_keys__(__iter6) } + for (var __idx6=0; __idx6 < __iter6.length; __idx6++) { + var parent = __iter6[ __idx6 ]; return _get_upstream_property(parent, attr); - parent = backup; } } @@ -365,7 +373,7 @@ get_arguments = function(signature, args, kwargs) { } } } - j += 1 + j += 1; } args = args.slice(j); if (signature.vararg) { @@ -387,56 +395,52 @@ __object_keys__ = function(ob) { __object_keys__.NAME = "__object_keys__"; __object_keys__.args_signature = ["ob"]; -__object_keys__.kwargs_signature = {}; -__object_keys__.types_signature = {}; +__object_keys__.kwargs_signature = { }; +__object_keys__.types_signature = { }; __bind_property_descriptors__ = function(o, klass) { var prop, desc; - var iter = klass.__properties__; - - if (! (iter instanceof Array) ) { iter = __object_keys__(iter) } - for (var name=0; name < iter.length; name++) { - var backup = name; name = iter[name]; - desc = { enumerable:true }; - prop = klass.__properties__[ name ]; + var __iter1 = klass.__properties__; + if (! (__iter1 instanceof Array) ) { __iter1 = __object_keys__(__iter1) } + for (var __idx1=0; __idx1 < __iter1.length; __idx1++) { + var name = __iter1[ __idx1 ]; + desc = { "enumerable":true }; + prop = klass.__properties__[name]; if (prop["get"]) { - desc[ "get" ] = __generate_getter__(klass,o,name); + desc["get"] = __generate_getter__(klass, o, name); } if (prop["set"]) { - desc[ "set" ] = __generate_setter__(klass,o,name); + desc["set"] = __generate_setter__(klass, o, name); } - Object.defineProperty(o,name,desc); - name = backup; + Object.defineProperty(o, name, desc); } - var iter = klass.__bases__; - - if (! (iter instanceof Array) ) { iter = __object_keys__(iter) } - for (var base=0; base < iter.length; base++) { - var backup = base; base = iter[base]; - __bind_property_descriptors__(o,base); - base = backup; + var __iter2 = klass.__bases__; + if (! (__iter2 instanceof Array) ) { __iter2 = __object_keys__(__iter2) } + for (var __idx2=0; __idx2 < __iter2.length; __idx2++) { + var base = __iter2[ __idx2 ]; + __bind_property_descriptors__(o, base); } } __bind_property_descriptors__.NAME = "__bind_property_descriptors__"; -__bind_property_descriptors__.args_signature = ["o","klass"]; -__bind_property_descriptors__.kwargs_signature = {}; -__bind_property_descriptors__.types_signature = {}; +__bind_property_descriptors__.args_signature = ["o", "klass"]; +__bind_property_descriptors__.kwargs_signature = { }; +__bind_property_descriptors__.types_signature = { }; __generate_getter__ = function(klass, o, n) { return (function () {return klass.__properties__[ n ][ "get" ]([o],{ })}); } __generate_getter__.NAME = "__generate_getter__"; -__generate_getter__.args_signature = ["klass","o","n"]; -__generate_getter__.kwargs_signature = {}; -__generate_getter__.types_signature = {}; +__generate_getter__.args_signature = ["klass", "o", "n"]; +__generate_getter__.kwargs_signature = { }; +__generate_getter__.types_signature = { }; __generate_setter__ = function(klass, o, n) { return (function (v) {return klass.__properties__[ n ][ "set" ]([o, v],{ })}); } __generate_setter__.NAME = "__generate_setter__"; -__generate_setter__.args_signature = ["klass","o","n"]; -__generate_setter__.kwargs_signature = {}; -__generate_setter__.types_signature = {}; +__generate_setter__.args_signature = ["klass", "o", "n"]; +__generate_setter__.kwargs_signature = { }; +__generate_setter__.types_signature = { }; __sprintf = function(fmt, args) { var i; i = 0; @@ -444,116 +448,108 @@ __sprintf = function(fmt, args) { } __sprintf.NAME = "__sprintf"; -__sprintf.args_signature = ["fmt","args"]; -__sprintf.kwargs_signature = {}; -__sprintf.types_signature = {}; +__sprintf.args_signature = ["fmt", "args"]; +__sprintf.kwargs_signature = { }; +__sprintf.types_signature = { }; create_class = function(class_name, parents, attrs, props) { var metaclass, klass, prop; "Create a PythonScript class"; if (attrs.__metaclass__) { metaclass = attrs.__metaclass__; - attrs.__metaclass__=undefined; + attrs.__metaclass__ = undefined; return metaclass([class_name, parents, attrs]); } klass = Object.create(null); - klass.__bases__=parents; - klass.__name__=class_name; - klass.__unbound_methods__=Object.create(null); - klass.__all_method_names__=[]; - klass.__properties__=props; - klass.__attributes__=attrs; - var iter = attrs; - - if (! (iter instanceof Array) ) { iter = __object_keys__(iter) } - for (var key=0; key < iter.length; key++) { - var backup = key; key = iter[key]; + klass.__bases__ = parents; + klass.__name__ = class_name; + klass.__unbound_methods__ = Object.create(null); + klass.__all_method_names__ = []; + klass.__properties__ = props; + klass.__attributes__ = attrs; + var __iter3 = attrs; + if (! (__iter3 instanceof Array) ) { __iter3 = __object_keys__(__iter3) } + for (var __idx3=0; __idx3 < __iter3.length; __idx3++) { + var key = __iter3[ __idx3 ]; if (( typeof(attrs[key]) ) == "function") { - klass.__unbound_methods__[ key ] = attrs[ key ]; + klass.__unbound_methods__[key] = attrs[key]; klass.__all_method_names__.push(key); } if (( key ) == "__getattribute__") { - continue; + continue } - klass[ key ] = attrs[ key ]; - key = backup; + klass[key] = attrs[key]; } - klass.__setters__=[]; - klass.__getters__=[]; - var iter = klass.__properties__; - - if (! (iter instanceof Array) ) { iter = __object_keys__(iter) } - for (var name=0; name < iter.length; name++) { - var backup = name; name = iter[name]; - prop = klass.__properties__[ name ]; + klass.__setters__ = []; + klass.__getters__ = []; + var __iter4 = klass.__properties__; + if (! (__iter4 instanceof Array) ) { __iter4 = __object_keys__(__iter4) } + for (var __idx4=0; __idx4 < __iter4.length; __idx4++) { + var name = __iter4[ __idx4 ]; + prop = klass.__properties__[name]; klass.__getters__.push(name); if (prop["set"]) { klass.__setters__.push(name); } - name = backup; } - var iter = klass.__bases__; - - if (! (iter instanceof Array) ) { iter = __object_keys__(iter) } - for (var base=0; base < iter.length; base++) { - var backup = base; base = iter[base]; - Array.prototype.push.apply(klass.__getters__,base.__getters__); - Array.prototype.push.apply(klass.__setters__,base.__setters__); - Array.prototype.push.apply(klass.__all_method_names__,base.__all_method_names__); - base = backup; + var __iter5 = klass.__bases__; + if (! (__iter5 instanceof Array) ) { __iter5 = __object_keys__(__iter5) } + for (var __idx5=0; __idx5 < __iter5.length; __idx5++) { + var base = __iter5[ __idx5 ]; + Array.prototype.push.apply(klass.__getters__, base.__getters__); + Array.prototype.push.apply(klass.__setters__, base.__setters__); + Array.prototype.push.apply(klass.__all_method_names__, base.__all_method_names__); } var __call__ = function() { var has_getattr, wrapper, object, has_getattribute; "Create a PythonJS object"; object = Object.create(null); - object.__class__=klass; - Object.defineProperty(object,"__dict__",{ enumerable:false,value:object,writeable:false,configurable:false }); + object.__class__ = klass; + Object.defineProperty(object, "__dict__", { "enumerable":false,"value":object,"writeable":false,"configurable":false }); has_getattribute = false; has_getattr = false; - var iter = klass.__all_method_names__; - - if (! (iter instanceof Array) ) { iter = __object_keys__(iter) } - for (var name=0; name < iter.length; name++) { - var backup = name; name = iter[name]; + var __iter6 = klass.__all_method_names__; + if (! (__iter6 instanceof Array) ) { __iter6 = __object_keys__(__iter6) } + for (var __idx6=0; __idx6 < __iter6.length; __idx6++) { + var name = __iter6[ __idx6 ]; if (( name ) == "__getattribute__") { has_getattribute = true; } else { if (( name ) == "__getattr__") { has_getattr = true; } else { - wrapper = __get__(object,name); + wrapper = __get__(object, name); if (!wrapper.is_wrapper) { console.log("RUNTIME ERROR: failed to get wrapper for:", name); } } } - name = backup; } if (has_getattr) { - __get__(object,"__getattr__"); + __get__(object, "__getattr__"); } if (has_getattribute) { - __get__(object,"__getattribute__"); + __get__(object, "__getattribute__"); } - __bind_property_descriptors__(object,klass); + __bind_property_descriptors__(object, klass); if (object.__init__) { - object.__init__.apply(this,arguments); + object.__init__.apply(this, arguments); } return object; } __call__.NAME = "__call__"; __call__.args_signature = []; - __call__.kwargs_signature = {}; - __call__.types_signature = {}; - __call__.pythonscript_function=true; - klass.__call__=__call__; + __call__.kwargs_signature = { }; + __call__.types_signature = { }; + __call__.pythonscript_function = true; + klass.__call__ = __call__; return klass; } create_class.NAME = "create_class"; -create_class.args_signature = ["class_name","parents","attrs","props"]; -create_class.kwargs_signature = {}; -create_class.types_signature = {}; +create_class.args_signature = ["class_name", "parents", "attrs", "props"]; +create_class.kwargs_signature = { }; +create_class.types_signature = { }; type = function(args, kwargs) { if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ @@ -571,7 +567,7 @@ type = function(args, kwargs) { if (( bases ) === undefined && ( class_dict ) === undefined) { return ob_or_class_name.__class__; } else { - return create_class(ob_or_class_name,bases,class_dict); + return create_class(ob_or_class_name, bases, class_dict); } } @@ -593,7 +589,7 @@ hasattr = function(args, kwargs) { var ob = arguments['ob']; var attr = arguments['attr']; var method = arguments['method']; - return Object.hasOwnProperty.call(ob,attr); + return Object.hasOwnProperty.call(ob, attr); } hasattr.NAME = "hasattr"; @@ -602,6 +598,7 @@ hasattr.kwargs_signature = { method:false }; hasattr.types_signature = { method:"False" }; hasattr.pythonscript_function = true; getattr = function(args, kwargs) { + var prop; if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { @@ -615,14 +612,14 @@ getattr = function(args, kwargs) { var attr = arguments['attr']; var property = arguments['property']; if (property) { - prop = _get_upstream_property(ob.__class__,attr); + prop = _get_upstream_property(ob.__class__, attr); if (prop && prop["get"]) { - return prop[ "get" ]([ob],{ }); + return prop["get"]([ob], { }); } else { console.log("ERROR: getattr property error", prop); } } else { - return __get__(ob,attr); + return __get__(ob, attr); } } @@ -632,6 +629,7 @@ getattr.kwargs_signature = { property:false }; getattr.types_signature = { property:"False" }; getattr.pythonscript_function = true; setattr = function(args, kwargs) { + var prop; if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { @@ -646,14 +644,14 @@ setattr = function(args, kwargs) { var value = arguments['value']; var property = arguments['property']; if (property) { - prop = _get_upstream_property(ob.__class__,attr); + prop = _get_upstream_property(ob.__class__, attr); if (prop && prop["set"]) { - prop[ "set" ]([ob, value],{ }); + prop["set"]([ob, value], { }); } else { console.log("ERROR: setattr property error", prop); } } else { - set_attribute(ob,attr,value); + set_attribute(ob, attr, value); } } @@ -684,7 +682,7 @@ issubclass = function(args, kwargs) { if (issubclass([__get__(bases, "__getitem__")([i], Object()), B], __NULL_OBJECT__)) { return true; } - i += 1 + i += 1; } return false; } @@ -774,7 +772,7 @@ float.kwargs_signature = { }; float.types_signature = { }; float.pythonscript_function = true; round = function(args, kwargs) { - var b; + var y, x, c, b; if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { @@ -791,8 +789,8 @@ round = function(args, kwargs) { return a; } else { c = b.split("."); - x = c[ 0 ]; - y = c[ 1 ].substring(0,places); + x = c[0]; + y = c[1].substring(0, places); return parseFloat(((x + ".") + y)); } } @@ -833,45 +831,45 @@ _setup_str_prototype = function(args, kwargs) { func.NAME = "func"; func.args_signature = ["a"]; - func.kwargs_signature = {}; - func.types_signature = {}; - String.prototype.__contains__=func; + func.kwargs_signature = { }; + func.types_signature = { }; + String.prototype.__contains__ = func; var func = function(index) { - return this[ index ]; + return this[index]; } func.NAME = "func"; func.args_signature = ["index"]; - func.kwargs_signature = {}; - func.types_signature = {}; - String.prototype.get=func; + func.kwargs_signature = { }; + func.types_signature = { }; + String.prototype.get = func; var func = function(self) { return __get__(Iterator, "__call__")([this, 0], __NULL_OBJECT__); } func.NAME = "func"; func.args_signature = ["self"]; - func.kwargs_signature = {}; - func.types_signature = {}; - String.prototype.__iter__=func; + func.kwargs_signature = { }; + func.types_signature = { }; + String.prototype.__iter__ = func; var func = function(idx) { - return this[ idx ]; + return this[idx]; } func.NAME = "func"; func.args_signature = ["idx"]; - func.kwargs_signature = {}; - func.types_signature = {}; - String.prototype.__getitem__=func; + func.kwargs_signature = { }; + func.types_signature = { }; + String.prototype.__getitem__ = func; var func = function() { return this.length; } func.NAME = "func"; func.args_signature = []; - func.kwargs_signature = {}; - func.types_signature = {}; - String.prototype.__len__=func; + func.kwargs_signature = { }; + func.types_signature = { }; + String.prototype.__len__ = func; var func = function(start, stop, step) { var stop; if (( start ) === undefined && ( stop ) === undefined && ( step ) == -1) { @@ -880,33 +878,33 @@ _setup_str_prototype = function(args, kwargs) { if (( stop ) < 0) { stop = (this.length + stop); } - return this.substring(start,stop); + return this.substring(start, stop); } } func.NAME = "func"; - func.args_signature = ["start","stop","step"]; - func.kwargs_signature = {}; - func.types_signature = {}; - String.prototype.__getslice__=func; + func.args_signature = ["start", "stop", "step"]; + func.kwargs_signature = { }; + func.types_signature = { }; + String.prototype.__getslice__ = func; var func = function() { return this.split("\n"); } func.NAME = "func"; func.args_signature = []; - func.kwargs_signature = {}; - func.types_signature = {}; - String.prototype.splitlines=func; + func.kwargs_signature = { }; + func.types_signature = { }; + String.prototype.splitlines = func; var func = function() { return this.trim(); } func.NAME = "func"; func.args_signature = []; - func.kwargs_signature = {}; - func.types_signature = {}; - String.prototype.strip=func; + func.kwargs_signature = { }; + func.types_signature = { }; + String.prototype.strip = func; var func = function(a) { if (( this.substring(0, a.length) ) == a) { return true; @@ -917,9 +915,9 @@ _setup_str_prototype = function(args, kwargs) { func.NAME = "func"; func.args_signature = ["a"]; - func.kwargs_signature = {}; - func.types_signature = {}; - String.prototype.startswith=func; + func.kwargs_signature = { }; + func.types_signature = { }; + String.prototype.startswith = func; var func = function(a) { if (( this.substring((this.length - a.length), this.length) ) == a) { return true; @@ -930,9 +928,9 @@ _setup_str_prototype = function(args, kwargs) { func.NAME = "func"; func.args_signature = ["a"]; - func.kwargs_signature = {}; - func.types_signature = {}; - String.prototype.endswith=func; + func.kwargs_signature = { }; + func.types_signature = { }; + String.prototype.endswith = func; var func = function(a) { var i, arr, out; out = ""; @@ -942,94 +940,90 @@ _setup_str_prototype = function(args, kwargs) { arr = a["$wrapped"]; } i = 0; - var iter = arr; - - if (! (iter instanceof Array) ) { iter = __object_keys__(iter) } - for (var value=0; value < iter.length; value++) { - var backup = value; value = iter[value]; + var __iter7 = arr; + if (! (__iter7 instanceof Array) ) { __iter7 = __object_keys__(__iter7) } + for (var __idx7=0; __idx7 < __iter7.length; __idx7++) { + var value = __iter7[ __idx7 ]; out += value; i += 1; if (( i ) < arr.length) { out += this; } - value = backup; } return out; } func.NAME = "func"; func.args_signature = ["a"]; - func.kwargs_signature = {}; - func.types_signature = {}; - String.prototype.join=func; + func.kwargs_signature = { }; + func.types_signature = { }; + String.prototype.join = func; var func = function() { return this.toUpperCase(); } func.NAME = "func"; func.args_signature = []; - func.kwargs_signature = {}; - func.types_signature = {}; - String.prototype.upper=func; + func.kwargs_signature = { }; + func.types_signature = { }; + String.prototype.upper = func; var func = function() { return this.toLowerCase(); } func.NAME = "func"; func.args_signature = []; - func.kwargs_signature = {}; - func.types_signature = {}; - String.prototype.lower=func; + func.kwargs_signature = { }; + func.types_signature = { }; + String.prototype.lower = func; var func = function(a) { return this.indexOf(a); } func.NAME = "func"; func.args_signature = ["a"]; - func.kwargs_signature = {}; - func.types_signature = {}; - String.prototype.index=func; + func.kwargs_signature = { }; + func.types_signature = { }; + String.prototype.index = func; var func = function() { var digits; digits = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]; - var iter = this; - - if (! (iter instanceof Array) ) { iter = __object_keys__(iter) } - for (var char=0; char < iter.length; char++) { - var backup = char; char = iter[char]; + var __iter8 = this; + if (! (__iter8 instanceof Array) ) { __iter8 = __object_keys__(__iter8) } + for (var __idx8=0; __idx8 < __iter8.length; __idx8++) { + var char = __iter8[ __idx8 ]; if (( char ) in digits || Object.hasOwnProperty.call(digits, "__contains__") && digits["__contains__"](char)) { /*pass*/ } else { return false; } - char = backup; } return true; } func.NAME = "func"; func.args_signature = []; - func.kwargs_signature = {}; - func.types_signature = {}; - String.prototype.isdigit=func; + func.kwargs_signature = { }; + func.types_signature = { }; + String.prototype.isdigit = func; var func = function(encoding) { return this; } func.NAME = "func"; func.args_signature = ["encoding"]; - func.kwargs_signature = {}; - func.types_signature = {}; - String.prototype.decode=func; + func.kwargs_signature = { }; + func.types_signature = { }; + String.prototype.decode = func; var func = function(encoding) { return this; } func.NAME = "func"; func.args_signature = ["encoding"]; - func.kwargs_signature = {}; - func.types_signature = {}; - String.prototype.encode=func; + func.kwargs_signature = { }; + func.types_signature = { }; + String.prototype.encode = func; } _setup_str_prototype.NAME = "_setup_str_prototype"; @@ -1049,69 +1043,69 @@ _setup_array_prototype = function(args, kwargs) { func.NAME = "func"; func.args_signature = ["a"]; - func.kwargs_signature = {}; - func.types_signature = {}; - Array.prototype.__contains__=func; + func.kwargs_signature = { }; + func.types_signature = { }; + Array.prototype.__contains__ = func; var func = function() { return this.length; } func.NAME = "func"; func.args_signature = []; - func.kwargs_signature = {}; - func.types_signature = {}; - Array.prototype.__len__=func; + func.kwargs_signature = { }; + func.types_signature = { }; + Array.prototype.__len__ = func; var func = function(index) { - return this[ index ]; + return this[index]; } func.NAME = "func"; func.args_signature = ["index"]; - func.kwargs_signature = {}; - func.types_signature = {}; - Array.prototype.get=func; + func.kwargs_signature = { }; + func.types_signature = { }; + Array.prototype.get = func; var func = function(self) { return __get__(Iterator, "__call__")([this, 0], __NULL_OBJECT__); } func.NAME = "func"; func.args_signature = ["self"]; - func.kwargs_signature = {}; - func.types_signature = {}; - Array.prototype.__iter__=func; + func.kwargs_signature = { }; + func.types_signature = { }; + Array.prototype.__iter__ = func; var func = function(start, stop, step) { var stop; if (( stop ) < 0) { stop = (this.length + stop); } - return this.slice(start,stop); + return this.slice(start, stop); } func.NAME = "func"; - func.args_signature = ["start","stop","step"]; - func.kwargs_signature = {}; - func.types_signature = {}; - Array.prototype.__getslice__=func; + func.args_signature = ["start", "stop", "step"]; + func.kwargs_signature = { }; + func.types_signature = { }; + Array.prototype.__getslice__ = func; var func = function(item) { this.push(item); } func.NAME = "func"; func.args_signature = ["item"]; - func.kwargs_signature = {}; - func.types_signature = {}; - Array.prototype.append=func; + func.kwargs_signature = { }; + func.types_signature = { }; + Array.prototype.append = func; var func = function(item) { var index; index = this.indexOf(item); - this.splice(index,1); + this.splice(index, 1); } func.NAME = "func"; func.args_signature = ["item"]; - func.kwargs_signature = {}; - func.types_signature = {}; - Array.prototype.remove=func; + func.kwargs_signature = { }; + func.types_signature = { }; + Array.prototype.remove = func; var func = function(x, low, high) { var high, a, low, mid; if (( low ) === undefined) { @@ -1133,47 +1127,45 @@ _setup_array_prototype = function(args, kwargs) { } func.NAME = "func"; - func.args_signature = ["x","low","high"]; - func.kwargs_signature = {}; - func.types_signature = {}; - Array.prototype.bisect=func; + func.args_signature = ["x", "low", "high"]; + func.kwargs_signature = { }; + func.types_signature = { }; + Array.prototype.bisect = func; var func = function(other) { return this.filter((function (i) {return other.indexOf(i) == -1})); } func.NAME = "func"; func.args_signature = ["other"]; - func.kwargs_signature = {}; - func.types_signature = {}; - Array.prototype.difference=func; + func.kwargs_signature = { }; + func.types_signature = { }; + Array.prototype.difference = func; var func = function(other) { return this.filter((function (i) {return other.indexOf(i) != -1})); } func.NAME = "func"; func.args_signature = ["other"]; - func.kwargs_signature = {}; - func.types_signature = {}; - Array.prototype.intersection=func; + func.kwargs_signature = { }; + func.types_signature = { }; + Array.prototype.intersection = func; var func = function(other) { - var iter = this; - - if (! (iter instanceof Array) ) { iter = __object_keys__(iter) } - for (var item=0; item < iter.length; item++) { - var backup = item; item = iter[item]; + var __iter9 = this; + if (! (__iter9 instanceof Array) ) { __iter9 = __object_keys__(__iter9) } + for (var __idx9=0; __idx9 < __iter9.length; __idx9++) { + var item = __iter9[ __idx9 ]; if (( other.indexOf(item) ) == -1) { return false; } - item = backup; } return true; } func.NAME = "func"; func.args_signature = ["other"]; - func.kwargs_signature = {}; - func.types_signature = {}; - Array.prototype.issubset=func; + func.kwargs_signature = { }; + func.types_signature = { }; + Array.prototype.issubset = func; } _setup_array_prototype.NAME = "_setup_array_prototype"; @@ -1577,7 +1569,7 @@ __Iterator_next_fast = function(args, kwargs) { var self = arguments['self']; index = self.index; self.index += 1; - return self.obj_get([index],{ }); + return self.obj_get([index], { }); } __Iterator_next_fast.NAME = "__Iterator_next_fast"; @@ -1592,6 +1584,7 @@ __tuple_attrs = Object(); __tuple_parents = []; __tuple_properties = Object(); __tuple___init__ = function(args, kwargs) { + var arr; if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { @@ -1622,9 +1615,9 @@ __tuple___init__ = function(args, kwargs) { } else { if (js_object) { if (isinstance([js_object, array], __NULL_OBJECT__) || isinstance([js_object, tuple], __NULL_OBJECT__) || isinstance([js_object, list], __NULL_OBJECT__)) { - var __iterator__, v; + var v; __iterator__ = __get__(__get__(js_object, "__iter__"), "__call__")([], Object()); - var __next__; + ; __next__ = __get__(__iterator__, "next_fast"); while(( __iterator__.index ) < __iterator__.length) { v = __next__(); @@ -1659,7 +1652,7 @@ __tuple___getitem__ = function(args, kwargs) { if (( index ) < 0) { index = (__get__(self["$wrapped"], "length") + index); } - return self["$wrapped"][ index ]; + return self["$wrapped"][index]; } __tuple___getitem__.NAME = "__tuple___getitem__"; @@ -1763,15 +1756,13 @@ __tuple_count = function(args, kwargs) { var self = arguments['self']; var obj = arguments['obj']; a = 0; - var iter = self["$wrapped"]; - - if (! (iter instanceof Array) ) { iter = __object_keys__(iter) } - for (var item=0; item < iter.length; item++) { - var backup = item; item = iter[item]; + var __iter10 = self["$wrapped"]; + if (! (__iter10 instanceof Array) ) { __iter10 = __object_keys__(__iter10) } + for (var __idx10=0; __idx10 < __iter10.length; __idx10++) { + var item = __iter10[ __idx10 ]; if (( item ) == obj) { a += 1; } - item = backup; } return a; } @@ -1794,7 +1785,7 @@ __tuple_get = function(args, kwargs) { arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var index = arguments['index']; - return self["$wrapped"][ index ]; + return self["$wrapped"][index]; } __tuple_get.NAME = "__tuple_get"; @@ -1866,9 +1857,9 @@ __list___init__ = function(args, kwargs) { } else { if (js_object) { if (isinstance([js_object, array], __NULL_OBJECT__) || isinstance([js_object, tuple], __NULL_OBJECT__) || isinstance([js_object, list], __NULL_OBJECT__)) { - var __iterator__, v; + var v; __iterator__ = __get__(__get__(js_object, "__iter__"), "__call__")([], Object()); - var __next__; + ; __next__ = __get__(__iterator__, "next_fast"); while(( __iterator__.index ) < __iterator__.length) { v = __next__(); @@ -1895,7 +1886,7 @@ __list___getitem__ = function(args, kwargs) { if (( index ) < 0) { index = (__get__(self["$wrapped"], "length") + index); } - return self["$wrapped"][ index ]; + return self["$wrapped"][index]; } __list___getitem__.NAME = "__list___getitem__"; @@ -1909,7 +1900,7 @@ __list___setitem__ = function(args, kwargs) { var self = args[ 0 ]; var index = args[ 1 ]; var value = args[ 2 ]; - self["$wrapped"][ index ] = value; + self["$wrapped"][index] = value; } __list___setitem__.NAME = "__list___setitem__"; @@ -1934,7 +1925,7 @@ __list___getslice__ = function(args, kwargs) { var start = arguments['start']; var stop = arguments['stop']; var step = arguments['step']; - arr = self["$wrapped"].__getslice__(start,stop); + arr = self["$wrapped"].__getslice__(start, stop); var __args_3, __kwargs_3; __args_3 = []; __kwargs_3 = {"pointer": arr}; @@ -2010,7 +2001,7 @@ __list_insert = function(args, kwargs) { var self = arguments['self']; var index = arguments['index']; var obj = arguments['obj']; - self["$wrapped"].splice(index,0,obj); + self["$wrapped"].splice(index, 0, obj); } __list_insert.NAME = "__list_insert"; @@ -2033,7 +2024,7 @@ __list_remove = function(args, kwargs) { var self = arguments['self']; var obj = arguments['obj']; index = __get__(__get__(self, "index"), "__call__")([obj], __NULL_OBJECT__); - self["$wrapped"].splice(index,1); + self["$wrapped"].splice(index, 1); } __list_remove.NAME = "__list_remove"; @@ -2097,15 +2088,13 @@ __list_count = function(args, kwargs) { var self = arguments['self']; var obj = arguments['obj']; a = 0; - var iter = self["$wrapped"]; - - if (! (iter instanceof Array) ) { iter = __object_keys__(iter) } - for (var item=0; item < iter.length; item++) { - var backup = item; item = iter[item]; + var __iter11 = self["$wrapped"]; + if (! (__iter11 instanceof Array) ) { __iter11 = __object_keys__(__iter11) } + for (var __idx11=0; __idx11 < __iter11.length; __idx11++) { + var item = __iter11[ __idx11 ]; if (( item ) == obj) { a += 1; } - item = backup; } return a; } @@ -2169,7 +2158,7 @@ __list_slice = function(args, kwargs) { var self = arguments['self']; var start = arguments['start']; var end = arguments['end']; - return self["$wrapped"].slice(start,end); + return self["$wrapped"].slice(start, end); } __list_slice.NAME = "__list_slice"; @@ -2211,7 +2200,7 @@ __list_get = function(args, kwargs) { arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var index = arguments['index']; - return self["$wrapped"][ index ]; + return self["$wrapped"][index]; } __list_get.NAME = "__list_get"; @@ -2233,7 +2222,7 @@ __list_set = function(args, kwargs) { var self = arguments['self']; var index = arguments['index']; var value = arguments['value']; - self["$wrapped"][ index ] = value; + self["$wrapped"][index] = value; } __list_set.NAME = "__list_set"; @@ -2316,7 +2305,7 @@ __dict_properties = Object(); __dict_UID = 0; __dict_attrs["UID"] = __dict_UID; __dict___init__ = function(args, kwargs) { - var i; + var i, value, key; if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { @@ -2336,19 +2325,17 @@ __dict___init__ = function(args, kwargs) { var key = js_object[i]["key"]; var value = js_object[i]["value"]; __get__(__get__(self, "set"), "__call__")([key, value], __NULL_OBJECT__); - i += 1 + i += 1; } } else { if (isinstance([js_object, list], __NULL_OBJECT__)) { - var iter = js_object["$wrapped"]; - - if (! (iter instanceof Array) ) { iter = __object_keys__(iter) } - for (var item=0; item < iter.length; item++) { - var backup = item; item = iter[item]; - key = item["$wrapped"][ 0 ]; - value = item["$wrapped"][ 1 ]; - self["$wrapped"][ key ] = value; - item = backup; + var __iter12 = js_object["$wrapped"]; + if (! (__iter12 instanceof Array) ) { __iter12 = __object_keys__(__iter12) } + for (var __idx12=0; __idx12 < __iter12.length; __idx12++) { + var item = __iter12[ __idx12 ]; + key = item["$wrapped"][0]; + value = item["$wrapped"][1]; + self["$wrapped"][key] = value; } } else { self["$wrapped"] = js_object; @@ -2423,7 +2410,7 @@ __dict_set = function(args, kwargs) { if (key.uid === undefined) { uid = _PythonJS_UID; key.uid = uid; - _PythonJS_UID += 1 + _PythonJS_UID += 1; } var uid = key.uid; __dict["@"+uid] = value; @@ -2432,7 +2419,7 @@ __dict_set = function(args, kwargs) { if (key.uid === undefined) { uid = _PythonJS_UID; key.uid = uid; - _PythonJS_UID += 1 + _PythonJS_UID += 1; } var uid = key.uid; __dict["@"+uid] = value; @@ -2522,7 +2509,7 @@ __dict___setitem__ = function(args, kwargs) { if (key.uid === undefined) { uid = _PythonJS_UID; key.uid = uid; - _PythonJS_UID += 1 + _PythonJS_UID += 1; } var uid = key.uid; __dict["@"+uid] = value; @@ -2531,7 +2518,7 @@ __dict___setitem__ = function(args, kwargs) { if (key.uid === undefined) { uid = _PythonJS_UID; key.uid = uid; - _PythonJS_UID += 1 + _PythonJS_UID += 1; } var uid = key.uid; __dict["@"+uid] = value; @@ -2621,7 +2608,7 @@ __dict_values = function(args, kwargs) { i = 0; while(( i ) < __get__(__keys, "length")) { __get__(__get__(out, "append"), "__call__")([__dict[ __keys[i] ]], __NULL_OBJECT__); - i += 1 + i += 1; } return out; } @@ -2633,7 +2620,7 @@ __dict_values.types_signature = { }; __dict_values.pythonscript_function = true; __dict_attrs["values"] = __dict_values; __dict___contains__ = function(args, kwargs) { - var keys; + var keys, key; if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { @@ -2687,7 +2674,7 @@ __dict___iter__.pythonscript_function = true; __dict_attrs["__iter__"] = __dict___iter__; dict = create_class("dict", __dict_parents, __dict_attrs, __dict_properties); set = function(args, kwargs) { - var s, fallback, hashtable; + var a, keys, mask, s, hashtable, key, fallback; if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { @@ -2726,45 +2713,39 @@ set = function(args, kwargs) { } fallback = false; if (hashtable) { - var iter = a; - - if (! (iter instanceof Array) ) { iter = __object_keys__(iter) } - for (var b=0; b < iter.length; b++) { - var backup = b; b = iter[b]; + var __iter13 = a; + if (! (__iter13 instanceof Array) ) { __iter13 = __object_keys__(__iter13) } + for (var __idx13=0; __idx13 < __iter13.length; __idx13++) { + var b = __iter13[ __idx13 ]; if (typeof(b, "number") && ( b ) === ( (b | 0) )) { key = (b & mask); - hashtable[ key ] = b; + hashtable[key] = b; keys.push(key); } else { fallback = true; break; } - b = backup; } } else { fallback = true; } s = []; if (fallback) { - var iter = a; - - if (! (iter instanceof Array) ) { iter = __object_keys__(iter) } - for (var item=0; item < iter.length; item++) { - var backup = item; item = iter[item]; + var __iter14 = a; + if (! (__iter14 instanceof Array) ) { __iter14 = __object_keys__(__iter14) } + for (var __idx14=0; __idx14 < __iter14.length; __idx14++) { + var item = __iter14[ __idx14 ]; if (( s.indexOf(item) ) == -1) { s.push(item); } - item = backup; } } else { keys.sort(); - var iter = keys; - - if (! (iter instanceof Array) ) { iter = __object_keys__(iter) } - for (var key=0; key < iter.length; key++) { - var backup = key; key = iter[key]; - s.push(hashtable[ key ]); - key = backup; + var __iter15 = keys; + if (! (__iter15 instanceof Array) ) { __iter15 = __object_keys__(__iter15) } + for (var __idx15=0; __idx15 < __iter15.length; __idx15++) { + var key = __iter15[ __idx15 ]; + s.push(hashtable[key]); } } return s; @@ -3047,15 +3028,15 @@ __array_fromlist = function(args, kwargs) { while(( i ) < length) { item = __get__(lst, "__getitem__")([i], Object()); if (( typecode ) == "float8") { - item *= self._norm_set + item *= self._norm_set; } else { if (( typecode ) == "float16") { - item *= self._norm_set + item *= self._norm_set; } } func(offset,item); - offset += step - i += 1 + offset += step; + i += 1; } } else { throw TypeError; @@ -3168,7 +3149,7 @@ __array_to_array = function(args, kwargs) { while(( i ) < self.length) { item = __array___getitem__([self, i], Object()); arr.push( item ); - i += 1 + i += 1; } return arr; } @@ -3222,8 +3203,8 @@ __array_to_ascii = function(args, kwargs) { while(( i ) < length) { var num = arr[i]; var char = String.fromCharCode(num); - string += char - i += 1 + string += char; + i += 1; } return string; } @@ -3248,7 +3229,7 @@ _to_pythonjs = function(args, kwargs) { signature = {"kwargs": Object(), "args": __create_array__("json")}; arguments = get_arguments(signature, args, kwargs); var json = arguments['json']; - var jstype, item, output; + var item; jstype = typeof json; if (( jstype ) == "number") { return json; @@ -3262,9 +3243,9 @@ _to_pythonjs = function(args, kwargs) { __args_6 = []; __kwargs_6 = {"js_object": json}; raw = __get__(list, "__call__")([], __kwargs_6); - var append; + ; append = __get__(output, "append"); - var __iterator__, item; + var __iterator__; __iterator__ = __get__(__get__(raw, "__iter__"), "__call__")([], Object()); var __next__; __next__ = __get__(__iterator__, "next_fast"); @@ -3275,15 +3256,15 @@ _to_pythonjs = function(args, kwargs) { return output; } output = __get__(dict, "__call__")(); - var set; + ; set = __get__(output, "set"); var __args_7, __kwargs_7; __args_7 = []; __kwargs_7 = {"js_object": Object.keys(json)}; keys = __get__(list, "__call__")([], __kwargs_7); - var __iterator__, key; + var key; __iterator__ = __get__(__get__(keys, "__iter__"), "__call__")([], Object()); - var __next__; + ; __next__ = __get__(__iterator__, "next_fast"); while(( __iterator__.index ) < __iterator__.length) { key = __next__(); @@ -3340,17 +3321,17 @@ _to_json = function(args, kwargs) { } } else { if (isinstance([pythonjs, dict], __NULL_OBJECT__)) { - var r; + ; r = Object(); - var __iterator__, key; + ; __iterator__ = __get__(__get__(__get__(__get__(pythonjs, "keys"), "__call__")(), "__iter__"), "__call__")([], Object()); - var __next__; + ; __next__ = __get__(__iterator__, "next_fast"); while(( __iterator__.index ) < __iterator__.length) { key = __next__(); value = _to_json([__get__(__get__(pythonjs, "get"), "__call__")([key], __NULL_OBJECT__)], __NULL_OBJECT__); key = _to_json([key], __NULL_OBJECT__); - r[ key ] = value; + r[key] = value; } } else { r = pythonjs; diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index b8cb68a..6de4010 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -1509,9 +1509,9 @@ def visit_Call(self, node): assert len(args) == 1 return 'new(%s)' %args[0] - elif isinstance(node.func, Name) and node.func.id == 'JS': ## avoids nested JS - assert len(args) == 1 - return node.args[0].s ## string literal + #elif isinstance(node.func, Name) and node.func.id == 'JS': ## avoids nested JS + # assert len(args) == 1 + # return node.args[0].s ## string literal elif isinstance(node.func, Name) and node.func.id in self._js_classes: a = ','.join(args) @@ -1678,8 +1678,8 @@ def visit_Call(self, node): def visit_Lambda(self, node): args = [self.visit(a) for a in node.args.args] - if self._with_js: - return '(function (%s) {return %s})' %(','.join(args), self.visit(node.body)) + if self._with_js: ## TODO is it better to return a normal lambda + return """JS('(function (%s) {return %s})')""" %(','.join(args), self.visit(node.body)) else: return 'lambda %s: %s' %(','.join(args), self.visit(node.body)) diff --git a/runtime/pythonpythonjs.py b/runtime/pythonpythonjs.py index a45fd4e..47e18c6 100644 --- a/runtime/pythonpythonjs.py +++ b/runtime/pythonpythonjs.py @@ -67,21 +67,25 @@ def __get__(object, attribute): return object.cached_wrapper elif JS("{}.toString.call(object) === '[object Function]'"): - #if JS("object.pythonscript_function === true"): - # return object - #elif JS("object.is_wrapper !== undefined"): - # return object - #else: - # JS("var cached = object.cached_wrapper") - # if cached: - # return cached - # else: ## TODO - double check if this still happens - # def wrapper(args,kwargs): return object.apply(None, args) ## TODO, bind this? - # wrapper.is_wrapper = True - # object.cached_wrapper = wrapper - # return wrapper - - def wrapper(args,kwargs): return object.apply(None, args) ## TODO, bind this? + + def wrapper(args,kwargs): + var(i, arg) + i = 0 + while i < args.length: + arg = args[i] + #if instanceof(arg, Object): ## fails on objects created by Object.create(null) + if typeof(arg) == 'object': + if arg.__class__: + if arg.__class__.__name__ == 'list' or arg.__class__.__name__ == 'tuple': + args[i] = arg[...] + elif arg.__class__.__name__ == 'dict': + args[i] = arg[...] + i += 1 + + if Object.keys(kwargs).length != 0: + args.push( kwargs ) + return object.apply(None, args) + wrapper.is_wrapper = True object.cached_wrapper = wrapper return wrapper diff --git a/tests/test_calling_javascript_keyword_args.html b/tests/test_calling_javascript_keyword_args.html new file mode 100644 index 0000000..a366e34 --- /dev/null +++ b/tests/test_calling_javascript_keyword_args.html @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/tests/test_dom.html b/tests/test_dom.html index 3cd2c31..39a49c9 100644 --- a/tests/test_dom.html +++ b/tests/test_dom.html @@ -1,6 +1,6 @@ - + From e5a668f7b9305643a70f95aa20a6b93b51a5f807 Mon Sep 17 00:00:00 2001 From: hartsantler Date: Sun, 15 Dec 2013 19:13:52 -0800 Subject: [PATCH 046/521] refactored core: deprecated builtin list class, now lists are JavaScript Array with prototype overloaded to act like a Python list. (this makes calling external javascript much simpler) fixed `not in` expression. broke the Pixi and Blockly bindings. --- pythonjs.js | 641 +++++++++++++++++++-------------- pythonjs/python_to_pythonjs.py | 84 +++-- pythonjs/pythonjs.py | 5 +- runtime/builtins.py | 95 +++-- runtime/pythonpythonjs.py | 37 +- tests/test_if_contains.html | 2 +- tests/test_if_not_in.html | 40 +- tests/test_list.html | 19 +- 8 files changed, 549 insertions(+), 374 deletions(-) diff --git a/pythonjs.js b/pythonjs.js index 1ff99f2..5570663 100644 --- a/pythonjs.js +++ b/pythonjs.js @@ -1,4 +1,4 @@ -// PythonJS Runtime - regenerated on: Sat Dec 14 03:40:42 2013 +// PythonJS Runtime - regenerated on: Sun Dec 15 19:06:10 2013 __NULL_OBJECT__ = Object.create(null); if (( "window" ) in this && ( "document" ) in this) { __NODEJS__ = false; @@ -58,14 +58,8 @@ __get__ = function(object, attribute) { while(( i ) < args.length) { arg = args[i]; if (( typeof(arg) ) == "object") { - if (arg.__class__) { - if (( arg.__class__.__name__ ) == "list" || ( arg.__class__.__name__ ) == "tuple") { - args[i] = arg["$wrapped"]; - } else { - if (( arg.__class__.__name__ ) == "dict") { - args[i] = arg["$wrapped"]; - } - } + if (arg.jsify) { + args[i] = arg.jsify(); } } i += 1; @@ -265,41 +259,21 @@ __get__ = function(object, attribute) { } } } - if (object instanceof Array) { - if (( attribute ) == "__getitem__") { - var wrapper = function(args, kwargs) { - return object[args[0]]; - } - - wrapper.is_wrapper = true; - return wrapper; - } else { - if (( attribute ) == "__setitem__") { - var wrapper = function(args, kwargs) { - object[args[0]] = args[1]; - } - - wrapper.is_wrapper = true; - return wrapper; - } + if (( attribute ) == "__getitem__") { + var wrapper = function(args, kwargs) { + return object[args[0]]; } + + wrapper.is_wrapper = true; + return wrapper; } else { - if (( attribute ) == "__getitem__") { + if (( attribute ) == "__setitem__") { var wrapper = function(args, kwargs) { - return object[args[0]]; + object[args[0]] = args[1]; } wrapper.is_wrapper = true; return wrapper; - } else { - if (( attribute ) == "__setitem__") { - var wrapper = function(args, kwargs) { - object[args[0]] = args[1]; - } - - wrapper.is_wrapper = true; - return wrapper; - } } } return undefined; @@ -518,7 +492,7 @@ create_class = function(class_name, parents, attrs, props) { has_getattr = true; } else { wrapper = __get__(object, name); - if (!wrapper.is_wrapper) { + if (! (wrapper.is_wrapper)) { console.log("RUNTIME ERROR: failed to get wrapper for:", name); } } @@ -708,7 +682,7 @@ isinstance = function(args, kwargs) { if (( ob ) === undefined || ( ob ) === null) { return false; } else { - if (!Object.hasOwnProperty.call(ob, "__class__")) { + if (! (Object.hasOwnProperty.call(ob, "__class__"))) { return false; } } @@ -992,7 +966,7 @@ _setup_str_prototype = function(args, kwargs) { if (! (__iter8 instanceof Array) ) { __iter8 = __object_keys__(__iter8) } for (var __idx8=0; __idx8 < __iter8.length; __idx8++) { var char = __iter8[ __idx8 ]; - if (( char ) in digits || Object.hasOwnProperty.call(digits, "__contains__") && digits["__contains__"](char)) { + if (Object.hasOwnProperty.call(digits, "__contains__") && digits["__contains__"](char) || Object.hasOwnProperty.call(digits, char)) { /*pass*/ } else { return false; @@ -1064,12 +1038,38 @@ _setup_array_prototype = function(args, kwargs) { func.kwargs_signature = { }; func.types_signature = { }; Array.prototype.get = func; - var func = function(self) { + var __getitem__ = function(index) { + var index; + if (( index ) < 0) { + index = (this.length + index); + } + return this[index]; + } + + __getitem__.NAME = "__getitem__"; + __getitem__.args_signature = ["index"]; + __getitem__.kwargs_signature = { }; + __getitem__.types_signature = { }; + Array.prototype.__getitem__ = __getitem__; + var __setitem__ = function(index, value) { + var index; + if (( index ) < 0) { + index = (this.length + index); + } + this[index] = value; + } + + __setitem__.NAME = "__setitem__"; + __setitem__.args_signature = ["index", "value"]; + __setitem__.kwargs_signature = { }; + __setitem__.types_signature = { }; + Array.prototype.__setitem__ = __setitem__; + var func = function() { return __get__(Iterator, "__call__")([this, 0], __NULL_OBJECT__); } func.NAME = "func"; - func.args_signature = ["self"]; + func.args_signature = []; func.kwargs_signature = { }; func.types_signature = { }; Array.prototype.__iter__ = func; @@ -1095,6 +1095,20 @@ _setup_array_prototype = function(args, kwargs) { func.kwargs_signature = { }; func.types_signature = { }; Array.prototype.append = func; + var extend = function(self, other) { + var __iter9 = other; + if (! (__iter9 instanceof Array) ) { __iter9 = __object_keys__(__iter9) } + for (var __idx9=0; __idx9 < __iter9.length; __idx9++) { + var obj = __iter9[ __idx9 ]; + this.push(obj); + } + } + + extend.NAME = "extend"; + extend.args_signature = ["self", "other"]; + extend.kwargs_signature = { }; + extend.types_signature = { }; + Array.prototype.extend = extend; var func = function(item) { var index; index = this.indexOf(item); @@ -1106,6 +1120,58 @@ _setup_array_prototype = function(args, kwargs) { func.kwargs_signature = { }; func.types_signature = { }; Array.prototype.remove = func; + var insert = function(index, obj) { + var index; + if (( index ) < 0) { + index = (this.length + index); + } + this.splice(index, 0, obj); + } + + insert.NAME = "insert"; + insert.args_signature = ["index", "obj"]; + insert.kwargs_signature = { }; + insert.types_signature = { }; + Array.prototype.insert = insert; + var remove = function(obj) { + var index; + index = this.indexOf(obj); + this.splice(index, 1); + } + + remove.NAME = "remove"; + remove.args_signature = ["obj"]; + remove.kwargs_signature = { }; + remove.types_signature = { }; + Array.prototype.remove = remove; + var index = function(obj) { + return this.indexOf(obj); + } + + index.NAME = "index"; + index.args_signature = ["obj"]; + index.kwargs_signature = { }; + index.types_signature = { }; + Array.prototype.index = index; + var count = function(obj) { + var a; + a = 0; + var __iter10 = this; + if (! (__iter10 instanceof Array) ) { __iter10 = __object_keys__(__iter10) } + for (var __idx10=0; __idx10 < __iter10.length; __idx10++) { + var item = __iter10[ __idx10 ]; + if (( item ) === obj) { + a += 1; + } + } + return a; + } + + count.NAME = "count"; + count.args_signature = ["obj"]; + count.kwargs_signature = { }; + count.types_signature = { }; + Array.prototype.count = count; var func = function(x, low, high) { var high, a, low, mid; if (( low ) === undefined) { @@ -1150,10 +1216,10 @@ _setup_array_prototype = function(args, kwargs) { func.types_signature = { }; Array.prototype.intersection = func; var func = function(other) { - var __iter9 = this; - if (! (__iter9 instanceof Array) ) { __iter9 = __object_keys__(__iter9) } - for (var __idx9=0; __idx9 < __iter9.length; __idx9++) { - var item = __iter9[ __idx9 ]; + var __iter11 = this; + if (! (__iter11 instanceof Array) ) { __iter11 = __object_keys__(__iter11) } + for (var __idx11=0; __idx11 < __iter11.length; __idx11++) { + var item = __iter11[ __idx11 ]; if (( other.indexOf(item) ) == -1) { return false; } @@ -1225,17 +1291,13 @@ range = function(args, kwargs) { arr.push(i); i += 1; } - var __args_0, __kwargs_0; - __args_0 = []; - __kwargs_0 = {"pointer": arr}; - return __get__(list, "__call__")([], __kwargs_0); + return arr; } range.NAME = "range"; range.args_signature = ["num", "stop"]; range.kwargs_signature = { }; range.types_signature = { }; -range.return_type = "list"; range.pythonscript_function = true; xrange = function(args, kwargs) { if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { @@ -1323,17 +1385,13 @@ map = function(args, kwargs) { v = __get__(func, "__call__")([ob], __NULL_OBJECT__); arr.push(v); } - var __args_1, __kwargs_1; - __args_1 = []; - __kwargs_1 = {"pointer": arr}; - return __get__(list, "__call__")([], __kwargs_1); + return arr; } map.NAME = "map"; map.args_signature = ["func", "objs"]; map.kwargs_signature = { }; map.types_signature = { }; -map.return_type = "list"; map.pythonscript_function = true; filter = function(args, kwargs) { var arr; @@ -1359,17 +1417,13 @@ filter = function(args, kwargs) { arr.push(ob); } } - var __args_2, __kwargs_2; - __args_2 = []; - __kwargs_2 = {"pointer": arr}; - return __get__(list, "__call__")([], __kwargs_2); + return arr; } filter.NAME = "filter"; filter.args_signature = ["func", "objs"]; filter.kwargs_signature = { }; filter.types_signature = { }; -filter.return_type = "list"; filter.pythonscript_function = true; min = function(args, kwargs) { var a; @@ -1756,10 +1810,10 @@ __tuple_count = function(args, kwargs) { var self = arguments['self']; var obj = arguments['obj']; a = 0; - var __iter10 = self["$wrapped"]; - if (! (__iter10 instanceof Array) ) { __iter10 = __object_keys__(__iter10) } - for (var __idx10=0; __idx10 < __iter10.length; __idx10++) { - var item = __iter10[ __idx10 ]; + var __iter12 = self["$wrapped"]; + if (! (__iter12 instanceof Array) ) { __iter12 = __object_keys__(__iter12) } + for (var __idx12=0; __idx12 < __iter12.length; __idx12++) { + var item = __iter12[ __idx12 ]; if (( item ) == obj) { a += 1; } @@ -1822,11 +1876,44 @@ __tuple_attrs["__contains__"] = __tuple___contains__; __tuple_properties["length"] = Object(); __tuple_properties["length"]["get"] = __tuple_length__getprop__; tuple = create_class("tuple", __tuple_parents, __tuple_attrs, __tuple_properties); -var list, __list_attrs, __list_parents; -__list_attrs = Object(); -__list_parents = []; -__list_properties = Object(); -__list___init__ = function(args, kwargs) { +list = function(args, kwargs) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { + /*pass*/ + } else { + args = Array.prototype.slice.call(arguments); + kwargs = Object(); + } + var signature, arguments; + signature = {"kwargs": Object(), "args": __create_array__("a")}; + arguments = get_arguments(signature, args, kwargs); + var a = arguments['a']; + if (( Object.keys(arguments).length ) == 0) { + return []; + } else { + if (a instanceof Array) { + return a.slice(); + } else { + if (( typeof(a) ) == "string") { + return a.split(""); + } else { + console.log(a); + console.log(arguments); + throw TypeError; + } + } + } +} + +list.NAME = "list"; +list.args_signature = ["a"]; +list.kwargs_signature = { }; +list.types_signature = { }; +list.pythonscript_function = true; +var pylist, __pylist_attrs, __pylist_parents; +__pylist_attrs = Object(); +__pylist_parents = []; +__pylist_properties = Object(); +__pylist___init__ = function(args, kwargs) { var arr; if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ @@ -1873,13 +1960,13 @@ __list___init__ = function(args, kwargs) { } } -__list___init__.NAME = "__list___init__"; -__list___init__.args_signature = ["self", "js_object", "pointer"]; -__list___init__.kwargs_signature = { js_object:undefined,pointer:undefined }; -__list___init__.types_signature = { js_object:"None",pointer:"None" }; -__list___init__.pythonscript_function = true; -__list_attrs["__init__"] = __list___init__; -__list___getitem__ = function(args, kwargs) { +__pylist___init__.NAME = "__pylist___init__"; +__pylist___init__.args_signature = ["self", "js_object", "pointer"]; +__pylist___init__.kwargs_signature = { js_object:undefined,pointer:undefined }; +__pylist___init__.types_signature = { js_object:"None",pointer:"None" }; +__pylist___init__.pythonscript_function = true; +__pylist_attrs["__init__"] = __pylist___init__; +__pylist___getitem__ = function(args, kwargs) { var index; var self = args[ 0 ]; var index = args[ 1 ]; @@ -1889,28 +1976,28 @@ __list___getitem__ = function(args, kwargs) { return self["$wrapped"][index]; } -__list___getitem__.NAME = "__list___getitem__"; -__list___getitem__.args_signature = ["self", "index"]; -__list___getitem__.kwargs_signature = { }; -__list___getitem__.fastdef = true; -__list___getitem__.types_signature = { }; -__list___getitem__.pythonscript_function = true; -__list_attrs["__getitem__"] = __list___getitem__; -__list___setitem__ = function(args, kwargs) { +__pylist___getitem__.NAME = "__pylist___getitem__"; +__pylist___getitem__.args_signature = ["self", "index"]; +__pylist___getitem__.kwargs_signature = { }; +__pylist___getitem__.fastdef = true; +__pylist___getitem__.types_signature = { }; +__pylist___getitem__.pythonscript_function = true; +__pylist_attrs["__getitem__"] = __pylist___getitem__; +__pylist___setitem__ = function(args, kwargs) { var self = args[ 0 ]; var index = args[ 1 ]; var value = args[ 2 ]; self["$wrapped"][index] = value; } -__list___setitem__.NAME = "__list___setitem__"; -__list___setitem__.args_signature = ["self", "index", "value"]; -__list___setitem__.kwargs_signature = { }; -__list___setitem__.fastdef = true; -__list___setitem__.types_signature = { }; -__list___setitem__.pythonscript_function = true; -__list_attrs["__setitem__"] = __list___setitem__; -__list___getslice__ = function(args, kwargs) { +__pylist___setitem__.NAME = "__pylist___setitem__"; +__pylist___setitem__.args_signature = ["self", "index", "value"]; +__pylist___setitem__.kwargs_signature = { }; +__pylist___setitem__.fastdef = true; +__pylist___setitem__.types_signature = { }; +__pylist___setitem__.pythonscript_function = true; +__pylist_attrs["__setitem__"] = __pylist___setitem__; +__pylist___getslice__ = function(args, kwargs) { var arr; if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ @@ -1926,20 +2013,20 @@ __list___getslice__ = function(args, kwargs) { var stop = arguments['stop']; var step = arguments['step']; arr = self["$wrapped"].__getslice__(start, stop); - var __args_3, __kwargs_3; - __args_3 = []; - __kwargs_3 = {"pointer": arr}; - return __get__(list, "__call__")([], __kwargs_3); + var __args_0, __kwargs_0; + __args_0 = []; + __kwargs_0 = {"pointer": arr}; + return __get__(list, "__call__")(__args_0, __kwargs_0); } -__list___getslice__.NAME = "__list___getslice__"; -__list___getslice__.args_signature = ["self", "start", "stop", "step"]; -__list___getslice__.kwargs_signature = { step:undefined }; -__list___getslice__.types_signature = { step:"None" }; -__list___getslice__.return_type = "list"; -__list___getslice__.pythonscript_function = true; -__list_attrs["__getslice__"] = __list___getslice__; -__list_append = function(args, kwargs) { +__pylist___getslice__.NAME = "__pylist___getslice__"; +__pylist___getslice__.args_signature = ["self", "start", "stop", "step"]; +__pylist___getslice__.kwargs_signature = { step:undefined }; +__pylist___getslice__.types_signature = { step:"None" }; +__pylist___getslice__.return_type = "list"; +__pylist___getslice__.pythonscript_function = true; +__pylist_attrs["__getslice__"] = __pylist___getslice__; +__pylist_append = function(args, kwargs) { if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { @@ -1954,13 +2041,13 @@ __list_append = function(args, kwargs) { self["$wrapped"].push(obj); } -__list_append.NAME = "__list_append"; -__list_append.args_signature = ["self", "obj"]; -__list_append.kwargs_signature = { }; -__list_append.types_signature = { }; -__list_append.pythonscript_function = true; -__list_attrs["append"] = __list_append; -__list_extend = function(args, kwargs) { +__pylist_append.NAME = "__pylist_append"; +__pylist_append.args_signature = ["self", "obj"]; +__pylist_append.kwargs_signature = { }; +__pylist_append.types_signature = { }; +__pylist_append.pythonscript_function = true; +__pylist_attrs["append"] = __pylist_append; +__pylist_extend = function(args, kwargs) { if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { @@ -1982,13 +2069,13 @@ __list_extend = function(args, kwargs) { } } -__list_extend.NAME = "__list_extend"; -__list_extend.args_signature = ["self", "other"]; -__list_extend.kwargs_signature = { }; -__list_extend.types_signature = { }; -__list_extend.pythonscript_function = true; -__list_attrs["extend"] = __list_extend; -__list_insert = function(args, kwargs) { +__pylist_extend.NAME = "__pylist_extend"; +__pylist_extend.args_signature = ["self", "other"]; +__pylist_extend.kwargs_signature = { }; +__pylist_extend.types_signature = { }; +__pylist_extend.pythonscript_function = true; +__pylist_attrs["extend"] = __pylist_extend; +__pylist_insert = function(args, kwargs) { if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { @@ -2004,13 +2091,13 @@ __list_insert = function(args, kwargs) { self["$wrapped"].splice(index, 0, obj); } -__list_insert.NAME = "__list_insert"; -__list_insert.args_signature = ["self", "index", "obj"]; -__list_insert.kwargs_signature = { }; -__list_insert.types_signature = { }; -__list_insert.pythonscript_function = true; -__list_attrs["insert"] = __list_insert; -__list_remove = function(args, kwargs) { +__pylist_insert.NAME = "__pylist_insert"; +__pylist_insert.args_signature = ["self", "index", "obj"]; +__pylist_insert.kwargs_signature = { }; +__pylist_insert.types_signature = { }; +__pylist_insert.pythonscript_function = true; +__pylist_attrs["insert"] = __pylist_insert; +__pylist_remove = function(args, kwargs) { var index; if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ @@ -2027,13 +2114,13 @@ __list_remove = function(args, kwargs) { self["$wrapped"].splice(index, 1); } -__list_remove.NAME = "__list_remove"; -__list_remove.args_signature = ["self", "obj"]; -__list_remove.kwargs_signature = { }; -__list_remove.types_signature = { }; -__list_remove.pythonscript_function = true; -__list_attrs["remove"] = __list_remove; -__list_pop = function(args, kwargs) { +__pylist_remove.NAME = "__pylist_remove"; +__pylist_remove.args_signature = ["self", "obj"]; +__pylist_remove.kwargs_signature = { }; +__pylist_remove.types_signature = { }; +__pylist_remove.pythonscript_function = true; +__pylist_attrs["remove"] = __pylist_remove; +__pylist_pop = function(args, kwargs) { if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { @@ -2047,13 +2134,13 @@ __list_pop = function(args, kwargs) { return self["$wrapped"].pop(); } -__list_pop.NAME = "__list_pop"; -__list_pop.args_signature = ["self"]; -__list_pop.kwargs_signature = { }; -__list_pop.types_signature = { }; -__list_pop.pythonscript_function = true; -__list_attrs["pop"] = __list_pop; -__list_index = function(args, kwargs) { +__pylist_pop.NAME = "__pylist_pop"; +__pylist_pop.args_signature = ["self"]; +__pylist_pop.kwargs_signature = { }; +__pylist_pop.types_signature = { }; +__pylist_pop.pythonscript_function = true; +__pylist_attrs["pop"] = __pylist_pop; +__pylist_index = function(args, kwargs) { if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { @@ -2068,13 +2155,13 @@ __list_index = function(args, kwargs) { return self["$wrapped"].indexOf(obj); } -__list_index.NAME = "__list_index"; -__list_index.args_signature = ["self", "obj"]; -__list_index.kwargs_signature = { }; -__list_index.types_signature = { }; -__list_index.pythonscript_function = true; -__list_attrs["index"] = __list_index; -__list_count = function(args, kwargs) { +__pylist_index.NAME = "__pylist_index"; +__pylist_index.args_signature = ["self", "obj"]; +__pylist_index.kwargs_signature = { }; +__pylist_index.types_signature = { }; +__pylist_index.pythonscript_function = true; +__pylist_attrs["index"] = __pylist_index; +__pylist_count = function(args, kwargs) { var a; if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ @@ -2088,10 +2175,10 @@ __list_count = function(args, kwargs) { var self = arguments['self']; var obj = arguments['obj']; a = 0; - var __iter11 = self["$wrapped"]; - if (! (__iter11 instanceof Array) ) { __iter11 = __object_keys__(__iter11) } - for (var __idx11=0; __idx11 < __iter11.length; __idx11++) { - var item = __iter11[ __idx11 ]; + var __iter13 = self["$wrapped"]; + if (! (__iter13 instanceof Array) ) { __iter13 = __object_keys__(__iter13) } + for (var __idx13=0; __idx13 < __iter13.length; __idx13++) { + var item = __iter13[ __idx13 ]; if (( item ) == obj) { a += 1; } @@ -2099,13 +2186,13 @@ __list_count = function(args, kwargs) { return a; } -__list_count.NAME = "__list_count"; -__list_count.args_signature = ["self", "obj"]; -__list_count.kwargs_signature = { }; -__list_count.types_signature = { }; -__list_count.pythonscript_function = true; -__list_attrs["count"] = __list_count; -__list_reverse = function(args, kwargs) { +__pylist_count.NAME = "__pylist_count"; +__pylist_count.args_signature = ["self", "obj"]; +__pylist_count.kwargs_signature = { }; +__pylist_count.types_signature = { }; +__pylist_count.pythonscript_function = true; +__pylist_attrs["count"] = __pylist_count; +__pylist_reverse = function(args, kwargs) { if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { @@ -2119,13 +2206,13 @@ __list_reverse = function(args, kwargs) { self["$wrapped"] = self["$wrapped"].reverse(); } -__list_reverse.NAME = "__list_reverse"; -__list_reverse.args_signature = ["self"]; -__list_reverse.kwargs_signature = { }; -__list_reverse.types_signature = { }; -__list_reverse.pythonscript_function = true; -__list_attrs["reverse"] = __list_reverse; -__list_shift = function(args, kwargs) { +__pylist_reverse.NAME = "__pylist_reverse"; +__pylist_reverse.args_signature = ["self"]; +__pylist_reverse.kwargs_signature = { }; +__pylist_reverse.types_signature = { }; +__pylist_reverse.pythonscript_function = true; +__pylist_attrs["reverse"] = __pylist_reverse; +__pylist_shift = function(args, kwargs) { if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { @@ -2139,13 +2226,13 @@ __list_shift = function(args, kwargs) { return self["$wrapped"].shift(); } -__list_shift.NAME = "__list_shift"; -__list_shift.args_signature = ["self"]; -__list_shift.kwargs_signature = { }; -__list_shift.types_signature = { }; -__list_shift.pythonscript_function = true; -__list_attrs["shift"] = __list_shift; -__list_slice = function(args, kwargs) { +__pylist_shift.NAME = "__pylist_shift"; +__pylist_shift.args_signature = ["self"]; +__pylist_shift.kwargs_signature = { }; +__pylist_shift.types_signature = { }; +__pylist_shift.pythonscript_function = true; +__pylist_attrs["shift"] = __pylist_shift; +__pylist_slice = function(args, kwargs) { if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { @@ -2161,13 +2248,13 @@ __list_slice = function(args, kwargs) { return self["$wrapped"].slice(start, end); } -__list_slice.NAME = "__list_slice"; -__list_slice.args_signature = ["self", "start", "end"]; -__list_slice.kwargs_signature = { }; -__list_slice.types_signature = { }; -__list_slice.pythonscript_function = true; -__list_attrs["slice"] = __list_slice; -__list___iter__ = function(args, kwargs) { +__pylist_slice.NAME = "__pylist_slice"; +__pylist_slice.args_signature = ["self", "start", "end"]; +__pylist_slice.kwargs_signature = { }; +__pylist_slice.types_signature = { }; +__pylist_slice.pythonscript_function = true; +__pylist_attrs["slice"] = __pylist_slice; +__pylist___iter__ = function(args, kwargs) { if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { @@ -2181,14 +2268,14 @@ __list___iter__ = function(args, kwargs) { return __get__(Iterator, "__call__")([self, 0], __NULL_OBJECT__); } -__list___iter__.NAME = "__list___iter__"; -__list___iter__.args_signature = ["self"]; -__list___iter__.kwargs_signature = { }; -__list___iter__.types_signature = { }; -__list___iter__.return_type = "Iterator"; -__list___iter__.pythonscript_function = true; -__list_attrs["__iter__"] = __list___iter__; -__list_get = function(args, kwargs) { +__pylist___iter__.NAME = "__pylist___iter__"; +__pylist___iter__.args_signature = ["self"]; +__pylist___iter__.kwargs_signature = { }; +__pylist___iter__.types_signature = { }; +__pylist___iter__.return_type = "Iterator"; +__pylist___iter__.pythonscript_function = true; +__pylist_attrs["__iter__"] = __pylist___iter__; +__pylist_get = function(args, kwargs) { if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { @@ -2203,13 +2290,13 @@ __list_get = function(args, kwargs) { return self["$wrapped"][index]; } -__list_get.NAME = "__list_get"; -__list_get.args_signature = ["self", "index"]; -__list_get.kwargs_signature = { }; -__list_get.types_signature = { }; -__list_get.pythonscript_function = true; -__list_attrs["get"] = __list_get; -__list_set = function(args, kwargs) { +__pylist_get.NAME = "__pylist_get"; +__pylist_get.args_signature = ["self", "index"]; +__pylist_get.kwargs_signature = { }; +__pylist_get.types_signature = { }; +__pylist_get.pythonscript_function = true; +__pylist_attrs["get"] = __pylist_get; +__pylist_set = function(args, kwargs) { if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { @@ -2225,13 +2312,13 @@ __list_set = function(args, kwargs) { self["$wrapped"][index] = value; } -__list_set.NAME = "__list_set"; -__list_set.args_signature = ["self", "index", "value"]; -__list_set.kwargs_signature = { }; -__list_set.types_signature = { }; -__list_set.pythonscript_function = true; -__list_attrs["set"] = __list_set; -__list___len__ = function(args, kwargs) { +__pylist_set.NAME = "__pylist_set"; +__pylist_set.args_signature = ["self", "index", "value"]; +__pylist_set.kwargs_signature = { }; +__pylist_set.types_signature = { }; +__pylist_set.pythonscript_function = true; +__pylist_attrs["set"] = __pylist_set; +__pylist___len__ = function(args, kwargs) { if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { @@ -2245,13 +2332,13 @@ __list___len__ = function(args, kwargs) { return self["$wrapped"].length; } -__list___len__.NAME = "__list___len__"; -__list___len__.args_signature = ["self"]; -__list___len__.kwargs_signature = { }; -__list___len__.types_signature = { }; -__list___len__.pythonscript_function = true; -__list_attrs["__len__"] = __list___len__; -__list_length__getprop__ = function(args, kwargs) { +__pylist___len__.NAME = "__pylist___len__"; +__pylist___len__.args_signature = ["self"]; +__pylist___len__.kwargs_signature = { }; +__pylist___len__.types_signature = { }; +__pylist___len__.pythonscript_function = true; +__pylist_attrs["__len__"] = __pylist___len__; +__pylist_length__getprop__ = function(args, kwargs) { if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { @@ -2265,12 +2352,12 @@ __list_length__getprop__ = function(args, kwargs) { return self["$wrapped"].length; } -__list_length__getprop__.NAME = "__list_length__getprop__"; -__list_length__getprop__.args_signature = ["self"]; -__list_length__getprop__.kwargs_signature = { }; -__list_length__getprop__.types_signature = { }; -__list_length__getprop__.pythonscript_function = true; -__list___contains__ = function(args, kwargs) { +__pylist_length__getprop__.NAME = "__pylist_length__getprop__"; +__pylist_length__getprop__.args_signature = ["self"]; +__pylist_length__getprop__.kwargs_signature = { }; +__pylist_length__getprop__.types_signature = { }; +__pylist_length__getprop__.pythonscript_function = true; +__pylist___contains__ = function(args, kwargs) { if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { @@ -2289,19 +2376,45 @@ __list___contains__ = function(args, kwargs) { } } -__list___contains__.NAME = "__list___contains__"; -__list___contains__.args_signature = ["self", "value"]; -__list___contains__.kwargs_signature = { }; -__list___contains__.types_signature = { }; -__list___contains__.pythonscript_function = true; -__list_attrs["__contains__"] = __list___contains__; -__list_properties["length"] = Object(); -__list_properties["length"]["get"] = __list_length__getprop__; -list = create_class("list", __list_parents, __list_attrs, __list_properties); +__pylist___contains__.NAME = "__pylist___contains__"; +__pylist___contains__.args_signature = ["self", "value"]; +__pylist___contains__.kwargs_signature = { }; +__pylist___contains__.types_signature = { }; +__pylist___contains__.pythonscript_function = true; +__pylist_attrs["__contains__"] = __pylist___contains__; +__pylist_properties["length"] = Object(); +__pylist_properties["length"]["get"] = __pylist_length__getprop__; +pylist = create_class("pylist", __pylist_parents, __pylist_attrs, __pylist_properties); +var jsifyable, __jsifyable_attrs, __jsifyable_parents; +__jsifyable_attrs = Object(); +__jsifyable_parents = []; +__jsifyable_properties = Object(); +__jsifyable_jsify = function(args, kwargs) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { + /*pass*/ + } else { + args = Array.prototype.slice.call(arguments); + kwargs = Object(); + } + var signature, arguments; + signature = {"kwargs": Object(), "args": __create_array__("self")}; + arguments = get_arguments(signature, args, kwargs); + var self = arguments['self']; + return self["$wrapped"]; +} + +__jsifyable_jsify.NAME = "__jsifyable_jsify"; +__jsifyable_jsify.args_signature = ["self"]; +__jsifyable_jsify.kwargs_signature = { }; +__jsifyable_jsify.types_signature = { }; +__jsifyable_jsify.pythonscript_function = true; +__jsifyable_attrs["jsify"] = __jsifyable_jsify; +jsifyable = create_class("jsifyable", __jsifyable_parents, __jsifyable_attrs, __jsifyable_properties); var dict, __dict_attrs, __dict_parents; __dict_attrs = Object(); __dict_parents = []; __dict_properties = Object(); +__dict_parents.push(jsifyable); __dict_UID = 0; __dict_attrs["UID"] = __dict_UID; __dict___init__ = function(args, kwargs) { @@ -2329,10 +2442,10 @@ __dict___init__ = function(args, kwargs) { } } else { if (isinstance([js_object, list], __NULL_OBJECT__)) { - var __iter12 = js_object["$wrapped"]; - if (! (__iter12 instanceof Array) ) { __iter12 = __object_keys__(__iter12) } - for (var __idx12=0; __idx12 < __iter12.length; __idx12++) { - var item = __iter12[ __idx12 ]; + var __iter14 = js_object["$wrapped"]; + if (! (__iter14 instanceof Array) ) { __iter14 = __object_keys__(__iter14) } + for (var __idx14=0; __idx14 < __iter14.length; __idx14++) { + var item = __iter14[ __idx14 ]; key = item["$wrapped"][0]; value = item["$wrapped"][1]; self["$wrapped"][key] = value; @@ -2535,7 +2648,6 @@ __dict___setitem__.types_signature = { }; __dict___setitem__.pythonscript_function = true; __dict_attrs["__setitem__"] = __dict___setitem__; __dict_keys = function(args, kwargs) { - var arr; if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { @@ -2546,18 +2658,13 @@ __dict_keys = function(args, kwargs) { signature = {"kwargs": Object(), "args": __create_array__("self")}; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; - arr = Object.keys(self["$wrapped"]); - var __args_4, __kwargs_4; - __args_4 = []; - __kwargs_4 = {"js_object": arr}; - return __get__(list, "__call__")([], __kwargs_4); + return Object.keys(self["$wrapped"]); } __dict_keys.NAME = "__dict_keys"; __dict_keys.args_signature = ["self"]; __dict_keys.kwargs_signature = { }; __dict_keys.types_signature = { }; -__dict_keys.return_type = "list"; __dict_keys.pythonscript_function = true; __dict_attrs["keys"] = __dict_keys; __dict_pop = function(args, kwargs) { @@ -2591,7 +2698,7 @@ __dict_pop.types_signature = { d:"None" }; __dict_pop.pythonscript_function = true; __dict_attrs["pop"] = __dict_pop; __dict_values = function(args, kwargs) { - var __dict, __keys, i, out; + var keys, out; if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { @@ -2602,13 +2709,13 @@ __dict_values = function(args, kwargs) { signature = {"kwargs": Object(), "args": __create_array__("self")}; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; - __dict = self["$wrapped"]; - __keys = Object.keys(__dict); - out = __get__(list, "__call__")(); - i = 0; - while(( i ) < __get__(__keys, "length")) { - __get__(__get__(out, "append"), "__call__")([__dict[ __keys[i] ]], __NULL_OBJECT__); - i += 1; + keys = Object.keys(self["$wrapped"]); + out = []; + var __iter15 = keys; + if (! (__iter15 instanceof Array) ) { __iter15 = __object_keys__(__iter15) } + for (var __idx15=0; __idx15 < __iter15.length; __idx15++) { + var key = __iter15[ __idx15 ]; + out.push(self["$wrapped"][key]); } return out; } @@ -2713,10 +2820,10 @@ set = function(args, kwargs) { } fallback = false; if (hashtable) { - var __iter13 = a; - if (! (__iter13 instanceof Array) ) { __iter13 = __object_keys__(__iter13) } - for (var __idx13=0; __idx13 < __iter13.length; __idx13++) { - var b = __iter13[ __idx13 ]; + var __iter16 = a; + if (! (__iter16 instanceof Array) ) { __iter16 = __object_keys__(__iter16) } + for (var __idx16=0; __idx16 < __iter16.length; __idx16++) { + var b = __iter16[ __idx16 ]; if (typeof(b, "number") && ( b ) === ( (b | 0) )) { key = (b & mask); hashtable[key] = b; @@ -2731,20 +2838,20 @@ set = function(args, kwargs) { } s = []; if (fallback) { - var __iter14 = a; - if (! (__iter14 instanceof Array) ) { __iter14 = __object_keys__(__iter14) } - for (var __idx14=0; __idx14 < __iter14.length; __idx14++) { - var item = __iter14[ __idx14 ]; + var __iter17 = a; + if (! (__iter17 instanceof Array) ) { __iter17 = __object_keys__(__iter17) } + for (var __idx17=0; __idx17 < __iter17.length; __idx17++) { + var item = __iter17[ __idx17 ]; if (( s.indexOf(item) ) == -1) { s.push(item); } } } else { keys.sort(); - var __iter15 = keys; - if (! (__iter15 instanceof Array) ) { __iter15 = __object_keys__(__iter15) } - for (var __idx15=0; __idx15 < __iter15.length; __idx15++) { - var key = __iter15[ __idx15 ]; + var __iter18 = keys; + if (! (__iter18 instanceof Array) ) { __iter18 = __object_keys__(__iter18) } + for (var __idx18=0; __idx18 < __iter18.length; __idx18++) { + var key = __iter18[ __idx18 ]; s.push(hashtable[key]); } } @@ -2805,12 +2912,12 @@ __array___init__ = function(args, kwargs) { self.length = len([initializer], __NULL_OBJECT__); self.bytes = (self.length * self.itemsize); if (( self.typecode ) == "float8") { - self._scale = max([__get__(list, "__call__")([], { pointer:[abs([min([initializer], __NULL_OBJECT__)], __NULL_OBJECT__), max([initializer], __NULL_OBJECT__)] })], __NULL_OBJECT__); + self._scale = max([[abs([min([initializer], __NULL_OBJECT__)], __NULL_OBJECT__), max([initializer], __NULL_OBJECT__)]], __NULL_OBJECT__); self._norm_get = (self._scale / 127); self._norm_set = (1.0 / self._norm_get); } else { if (( self.typecode ) == "float16") { - self._scale = max([__get__(list, "__call__")([], { pointer:[abs([min([initializer], __NULL_OBJECT__)], __NULL_OBJECT__), max([initializer], __NULL_OBJECT__)] })], __NULL_OBJECT__); + self._scale = max([[abs([min([initializer], __NULL_OBJECT__)], __NULL_OBJECT__), max([initializer], __NULL_OBJECT__)]], __NULL_OBJECT__); self._norm_get = (self._scale / 32767); self._norm_set = (1.0 / self._norm_get); } @@ -3171,17 +3278,13 @@ __array_to_list = function(args, kwargs) { signature = {"kwargs": Object(), "args": __create_array__("self")}; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; - var __args_5, __kwargs_5; - __args_5 = []; - __kwargs_5 = {"js_object": __get__(__get__(self, "to_array"), "__call__")()}; - return __get__(list, "__call__")([], __kwargs_5); + return __get__(__get__(self, "to_array"), "__call__")(); } __array_to_list.NAME = "__array_to_list"; __array_to_list.args_signature = ["self"]; __array_to_list.kwargs_signature = { }; __array_to_list.types_signature = { }; -__array_to_list.return_type = "list"; __array_to_list.pythonscript_function = true; __array_attrs["to_list"] = __array_to_list; __array_to_ascii = function(args, kwargs) { @@ -3239,10 +3342,10 @@ _to_pythonjs = function(args, kwargs) { } if (Object.prototype.toString.call(json) === '[object Array]') { output = __get__(list, "__call__")(); - var __args_6, __kwargs_6; - __args_6 = []; - __kwargs_6 = {"js_object": json}; - raw = __get__(list, "__call__")([], __kwargs_6); + var __args_1, __kwargs_1; + __args_1 = []; + __kwargs_1 = {"js_object": json}; + raw = __get__(list, "__call__")(__args_1, __kwargs_1); ; append = __get__(output, "append"); var __iterator__; @@ -3258,10 +3361,10 @@ _to_pythonjs = function(args, kwargs) { output = __get__(dict, "__call__")(); ; set = __get__(output, "set"); - var __args_7, __kwargs_7; - __args_7 = []; - __kwargs_7 = {"js_object": Object.keys(json)}; - keys = __get__(list, "__call__")([], __kwargs_7); + var __args_2, __kwargs_2; + __args_2 = []; + __kwargs_2 = {"js_object": Object.keys(json)}; + keys = __get__(list, "__call__")(__args_2, __kwargs_2); var key; __iterator__ = __get__(__get__(keys, "__iter__"), "__call__")([], Object()); ; diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index 6de4010..49aeb13 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -243,8 +243,8 @@ def preprocess_custom_operators(self, data): def setup_builtins(self): self._classes['dict'] = set(['__getitem__', '__setitem__']) - self._classes['list'] = set(['__getitem__', '__setitem__']) - self._classes['tuple'] = set(['__getitem__', '__setitem__']) + self._classes['list'] = set() #['__getitem__', '__setitem__']) + self._classes['tuple'] = set() #['__getitem__', '__setitem__']) self._builtin_classes = set(['dict', 'list', 'tuple']) self._builtin_functions = { 'ord':'%s.charCodeAt(0)', @@ -386,18 +386,20 @@ def visit_Dict(self, node): def visit_Tuple(self, node): node.returns_type = 'tuple' a = '[%s]' % ', '.join(map(self.visit, node.elts)) - if self._with_js or self._with_dart: - return a - else: - return '__get__(tuple, "__call__")([], {pointer:%s})' %a + return a + #if self._with_js or self._with_dart: + # return a + #else: + # return '__get__(tuple, "__call__")([], {pointer:%s})' %a def visit_List(self, node): node.returns_type = 'list' a = '[%s]' % ', '.join(map(self.visit, node.elts)) - if self._with_js or self._with_dart: - return a - else: - return '__get__(list, "__call__")([], {pointer:%s})' %a + return a + #if self._with_js or self._with_dart: + # return a + #else: + # return '__get__(list, "__call__")([], {pointer:%s})' %a def visit_GeneratorExp(self, node): return self.visit_ListComp(node) @@ -430,7 +432,8 @@ def visit_ListComp(self, node): self._gen_comp( generators, node ) self._comprehensions.remove( node ) - return '__get__(list, "__call__")([], {pointer:%s})' %cname + #return '__get__(list, "__call__")([], {pointer:%s})' %cname + return cname def _gen_comp(self, generators, node): @@ -851,10 +854,10 @@ def visit_TryExcept(self, node): map(self.visit, node.handlers) def visit_Raise(self, node): - if self._with_js or self._with_dart: - writer.write('throw Error') - else: - writer.write('raise %s' % self.visit(node.type)) + #if self._with_js or self._with_dart: + # writer.write('throw Error') + #else: + writer.write('raise %s' % self.visit(node.type)) def visit_ExceptHandler(self, node): if node.type and node.name: @@ -954,10 +957,11 @@ def visit_BinOp(self, node): elts = [ self.visit(e) for e in node.left.elts ] expanded = [] for i in range( n ): expanded.extend( elts ) - if self._with_js or self._with_dart: - return '[%s]' %','.join(expanded) - else: - return '__get__(list, "__call__")( [], {pointer:[%s]} )' %','.join(expanded) + #if self._with_js or self._with_dart: + # return '[%s]' %','.join(expanded) + #else: + # return '__get__(list, "__call__")( [], {pointer:[%s]} )' %','.join(expanded) + return '[%s]' %','.join(expanded) elif op == '//': return 'Math.floor(%s/%s)' %(left, right) @@ -1048,9 +1052,11 @@ def visit_Compare(self, node): ## this makes "if 'x' in Array" work like Python: "if 'x' in list" - TODO fix this for js-objects ## note javascript rules are confusing: "1 in [1,2]" is true, this is because a "in test" in javascript tests for an index ## TODO double check this code - comp.append( '%s in %s or' %(a[1], a[0]) ) ## this is ugly, will break with Arrays - comp.append( 'Object.hasOwnProperty.call(%s, "__contains__") and' %a[0]) - comp.append( "%s['__contains__'](%s)" %a ) + #comp.append( '%s in %s or' %(a[1], a[0]) ) ## this is ugly, will break with Arrays + comp.append( '( Object.hasOwnProperty.call(%s, "__contains__") and' %a[0]) + comp.append( "%s['__contains__'](%s) )" %a ) + #comp.append( ' or (instanceof(%s,Object) and %s in %s) ') + comp.append( ' or Object.hasOwnProperty.call(%s, %s)' %(a[0],a[1])) else: comp.append( "__get__(__get__(%s, '__contains__'), '__call__')([%s], JSObject())" %a ) @@ -1164,7 +1170,8 @@ def visit_Subscript(self, node): ) elif name in self._func_typedefs and self._func_typedefs[name] == 'list': - return '%s[...][%s]'%(name, self.visit(node.slice)) + #return '%s[...][%s]'%(name, self.visit(node.slice)) + return '%s[%s]'%(name, self.visit(node.slice)) elif name in self._instances: ## support x[y] operator overloading klass = self._instances[ name ] @@ -1214,7 +1221,8 @@ def _visit_assign_helper(self, node, target): code = code % (self.visit(target.value), self.visit(target.slice.value), self.visit(node.value)) elif name in self._func_typedefs and self._func_typedefs[name] == 'list': - code = '%s[...][%s] = %s'%(name, self.visit(target.slice.value), self.visit(node.value)) + #code = '%s[...][%s] = %s'%(name, self.visit(target.slice.value), self.visit(node.value)) + code = '%s[%s] = %s'%(name, self.visit(target.slice.value), self.visit(node.value)) else: code = "__get__(__get__(%s, '__setitem__'), '__call__')([%s, %s], JSObject())" @@ -1580,13 +1588,14 @@ def visit_Call(self, node): writer.append('var(%s, %s)' % (args_name, kwargs_name)) self.identifier += 1 - if name in ('list', 'tuple'): - if args: - writer.append( '%s = %s[...]' % (args_name, args)) ## test this - else: - writer.append( '%s = []' %args_name ) - else: - writer.append('%s = JSArray(%s)' % (args_name, args)) + #if name in ('list', 'tuple'): + # if args: + # writer.append( '%s = %s[...]' % (args_name, args)) ## test this + # else: + # writer.append( '%s = []' %args_name ) + #else: + # writer.append('%s = JSArray(%s)' % (args_name, args)) + writer.append('%s = JSArray(%s)' % (args_name, args)) if node.starargs: writer.append('%s.push.apply(%s, %s[...])' % (args_name, args_name, self.visit(node.starargs))) @@ -1612,7 +1621,8 @@ def visit_Call(self, node): if isinstance(node.func, ast.Attribute) and isinstance(node.func.value, Name) and node.func.value.id in self._func_typedefs: type = self._func_typedefs[ node.func.value.id ] if type == 'list' and node.func.attr == 'append': - return '%s[...].push(%s)' %(node.func.value.id, self.visit(node.args[0])) + #return '%s[...].push(%s)' %(node.func.value.id, self.visit(node.args[0])) + return '%s.push(%s)' %(node.func.value.id, self.visit(node.args[0])) else: raise RuntimeError @@ -1645,11 +1655,11 @@ def visit_Call(self, node): elif call_has_args: if name == 'dict': return '__get__(%s, "__call__")(%s, JSObject(js_object=%s))' % (name, args_name, kwargs_name) - elif name in ('list', 'tuple'): - if len(node.args): - return '__get__(%s, "__call__")([], {js_object:%s})' % (name, args_name) - else: - return '__get__(%s, "__call__")([], %s)' % (name, kwargs_name) + #elif name in ('list', 'tuple'): + # if len(node.args): + # return '__get__(%s, "__call__")([], {js_object:%s})' % (name, args_name) + # else: + # return '__get__(%s, "__call__")([], %s)' % (name, kwargs_name) else: return '__get__(%s, "__call__")(%s, %s)' % (name, args_name, kwargs_name) diff --git a/pythonjs/pythonjs.py b/pythonjs/pythonjs.py index ce30ebe..449c9a1 100755 --- a/pythonjs/pythonjs.py +++ b/pythonjs/pythonjs.py @@ -375,8 +375,10 @@ def visit_Compare(self, node): comp = [ '('] comp.append( self.visit(node.left) ) comp.append( ')' ) + for i in range( len(node.ops) ): comp.append( self.visit(node.ops[i]) ) + if isinstance(node.comparators[i], ast.BinOp): comp.append('(') comp.append( self.visit(node.comparators[i]) ) @@ -393,7 +395,8 @@ def visit_IsNot(self, node): return '!==' def visit_UnaryOp(self, node): - return self.visit(node.op) + self.visit(node.operand) + #return self.visit(node.op) + self.visit(node.operand) + return '%s (%s)' %(self.visit(node.op),self.visit(node.operand)) def visit_USub(self, node): return '-' diff --git a/runtime/builtins.py b/runtime/builtins.py index 90256fc..924afbe 100644 --- a/runtime/builtins.py +++ b/runtime/builtins.py @@ -343,8 +343,18 @@ def func(): def func(index): return this[ index ] + @Array.prototype.__getitem__ + def __getitem__(index): + if index < 0: index = this.length + index + return this[index] + + @Array.prototype.__setitem__ + def __setitem__(index, value): + if index < 0: index = this.length + index + this[ index ] = value + @Array.prototype.__iter__ - def func(self): + def func(): with python: return Iterator(this, 0) @@ -358,11 +368,41 @@ def func(start, stop, step): def func(item): this.push( item ) + @Array.prototype.extend + def extend(self, other): + for obj in other: + this.push(obj) + @Array.prototype.remove def func(item): index = this.indexOf( item ) this.splice(index, 1) + @Array.prototype.insert + def insert(index, obj): + if index < 0: index = this.length + index + this.splice(index, 0, obj) + + @Array.prototype.remove + def remove(obj): + index = this.indexOf(obj) + this.splice(index, 1) + + @Array.prototype.index + def index(obj): + return this.indexOf(obj) + + @Array.prototype.count + def count(obj): + a = 0 + for item in this: + if item is obj: ## note that `==` will not work here, `===` is required for objects + a += 1 + return a + + + ## set-like features ## + @Array.prototype.bisect def func(x, low, high): if low is None: low = 0 @@ -376,7 +416,6 @@ def func(x, low, high): low = mid + 1 return low - ## set-like features ## ## `-` operator @Array.prototype.difference def func(other): @@ -414,7 +453,7 @@ def range(num, stop): while i < num: arr.push(i) i += 1 - return list( pointer=arr ) + return arr def xrange(num, stop): return range(num, stop) @@ -437,7 +476,7 @@ def map(func, objs): v = func(ob) with javascript: arr.push( v ) - return list( pointer=arr ) + return arr def filter(func, objs): with javascript: arr = [] @@ -445,7 +484,7 @@ def filter(func, objs): if func( ob ): with javascript: arr.push( ob ) - return list( pointer=arr ) + return arr def min( lst ): @@ -564,8 +603,20 @@ def __contains__(self, value): else: return True +def list(a): + with javascript: + if Object.keys(arguments).length == 0: #arguments.length == 0: + return [] + elif instanceof(a, Array): + return a.slice() + elif typeof(a) == 'string': + return a.split('') + else: + print a + print arguments + raise TypeError -class list: +class pylist: ## DEPRECATED def __init__(self, js_object=None, pointer=None): @@ -677,7 +728,10 @@ def __contains__(self, value): else: return True -class dict: +class jsifyable: + def jsify(self): return self[...] + +class dict( jsifyable ): # http://stackoverflow.com/questions/10892322/javascript-hashtable-use-object-key # using a function as a key is allowed, but would waste memory because it gets converted to a string # http://stackoverflow.com/questions/10858632/are-functions-valid-keys-for-javascript-object-properties @@ -704,7 +758,6 @@ def __init__(self, js_object=None): else: ## TODO - deprecate self[...] = js_object - def get(self, key, _default=None): __dict = self[...] if JS("typeof(key) === 'object'"): @@ -779,14 +832,8 @@ def __setitem__(self, key, value): JS('__dict[key] = value') def keys(self): - #__dict = self.js_object - #__keys = JS('Object.keys(__dict)') ## the problem with this is that keys are coerced into strings - #out = list( js_object=__keys ) ## some bug in the translator prevents this - #out.js_object = __keys ## this style is deprecated - #return out with javascript: - arr = Object.keys( self[...] ) - return list( js_object=arr ) + return Object.keys( self[...] ) def pop(self, key, d=None): v = self.get(key, None) @@ -799,14 +846,13 @@ def pop(self, key, d=None): def values(self): - __dict = self[...] - __keys = JS('Object.keys(__dict)') - out = list() - i = 0 - while i < __keys.length: - out.append( JS('__dict[ __keys[i] ]') ) - i += 1 - return out + with javascript: + keys = Object.keys( self[...] ) + out = [] + for key in keys: + out.push( self[...][key] ) + return out + def __contains__(self, value): with javascript: @@ -1093,7 +1139,7 @@ def to_array(self): return arr def to_list(self): - return list( js_object=self.to_array() ) + return self.to_array() def to_ascii(self): string = '' @@ -1115,6 +1161,7 @@ def to_ascii(self): 'dumps': lambda o: JSON.stringify(o) } +## TODO fix this - deprecate? def _to_pythonjs(json): var(jstype, item, output) jstype = JS('typeof json') diff --git a/runtime/pythonpythonjs.py b/runtime/pythonpythonjs.py index 47e18c6..7b4c759 100644 --- a/runtime/pythonpythonjs.py +++ b/runtime/pythonpythonjs.py @@ -75,11 +75,13 @@ def wrapper(args,kwargs): arg = args[i] #if instanceof(arg, Object): ## fails on objects created by Object.create(null) if typeof(arg) == 'object': - if arg.__class__: - if arg.__class__.__name__ == 'list' or arg.__class__.__name__ == 'tuple': - args[i] = arg[...] - elif arg.__class__.__name__ == 'dict': - args[i] = arg[...] + #if arg.__class__: + # if arg.__class__.__name__ == 'list' or arg.__class__.__name__ == 'tuple': + # args[i] = arg[...] + # elif arg.__class__.__name__ == 'dict': + # args[i] = arg[...] + if arg.jsify: + args[i] = arg.jsify() i += 1 if Object.keys(kwargs).length != 0: @@ -94,9 +96,21 @@ def wrapper(args,kwargs): if Object.hasOwnProperty.call(object, '__getattribute__'): return object.__getattribute__( attribute ) + + #if JS('object instanceof Array'): + # if attribute == '__getitem__': + # def wrapper(args,kwargs): return object.__getitem__( args[0] ) + # wrapper.is_wrapper = True + # return wrapper + # elif attribute == '__setitem__': + # def wrapper(args,kwargs): object.__setitem__( args[0], args[1] ) + # wrapper.is_wrapper = True + # return wrapper + var(attr) attr = object[attribute] ## this could be a javascript object with cached method + if __NODEJS__ is False: if JS("object instanceof HTMLDocument"): #print 'DYNAMIC wrapping HTMLDocument' @@ -254,17 +268,8 @@ def method(): return f( [object, attribute], JSObject() ) - if JS('object instanceof Array'): - if attribute == '__getitem__': - def wrapper(args,kwargs): return object[ args[0] ] - wrapper.is_wrapper = True - return wrapper - elif attribute == '__setitem__': - def wrapper(args,kwargs): object[ args[0] ] = args[1] - wrapper.is_wrapper = True - return wrapper - - elif attribute == '__getitem__': ## this should be a JSObject - or anything else - is this always safe? + ## getting/setting from a normal JavaScript Object ## + if attribute == '__getitem__': def wrapper(args,kwargs): return object[ args[0] ] wrapper.is_wrapper = True return wrapper diff --git a/tests/test_if_contains.html b/tests/test_if_contains.html index 3ca356e..7d8c042 100644 --- a/tests/test_if_contains.html +++ b/tests/test_if_contains.html @@ -11,7 +11,7 @@ def __contains__(self, name): with javascript: - if name in self: + if name in Object.keys(self): return True class B: diff --git a/tests/test_if_not_in.html b/tests/test_if_not_in.html index a3fe4f9..5a29d2a 100644 --- a/tests/test_if_not_in.html +++ b/tests/test_if_not_in.html @@ -11,7 +11,7 @@ def __contains__(self, name): with javascript: - if name in self.__dict__: + if name in Object.keys(self): return True class B: @@ -31,44 +31,44 @@ def test(): print 'testing list' - if 1 not in [1,2,3]: print 'in list fails' - else: print 'OK' + if 100 not in [1,2,3]: print 'OK' + else: print 'in list fails' print 'testing dict' - if 1 not in {1:True}: print 'in dict fails' - else: print 'OK' + if 100 not in {1:True}: print 'OK' + else: print 'in dict fails' print 'testing tuple' - if 1 not in (1,2,3): print 'in tuple fails' - else: print 'OK' + if 100 not in (1,2,3): print 'OK' + else: print 'in tuple fails' print 'testing int32 array' arr = array('int32', [1,2,3,4]) print 'testing get item from array' arr[0] print 'testing item in array' - if 1 not in arr: print 'in array failed' - else: print 'OK' + if 100 not in arr: print 'OK' + else: print 'in array failed' print 'testing overloaded custom class A' a = A() - if 'x' not in a: print 'instance of overloaded A failed' - else: print 'OK' + if 'XXX' not in a: print 'OK' + else: print 'instance of overloaded A failed' with javascript: print 'testing with javascript:' arr = [1,2,3] jsob = {1:True} - if 1 not in arr: print 'in Array failed' - else: print 'OK' - if 1 not in jsob: print 'in javascript-object failed' - else: print 'OK' - - if 1 not in [1,2]: print 'in literal Array failed' - else: print 'OK' - if 'xx' not in {xx:True}: print 'in literal jsobject failed' - else: print 'OK' + if 100 not in arr: print 'OK' + else: print 'in Array failed' + if 100 not in jsob: print 'OK' + else: print 'in javascript-object failed' + + if 100 not in [1,2]: print 'OK' + else: print 'in literal Array failed' + if 'XXX' not in {xx:True}: print 'OK' + else: print 'in literal jsobject failed' diff --git a/tests/test_list.html b/tests/test_list.html index 214887c..faf944e 100644 --- a/tests/test_list.html +++ b/tests/test_list.html @@ -18,7 +18,9 @@ def test(): global a, b print('--testing literal style--') - a = [1,2,3] ## literal style + a = [ 1,2,3 ] ## literal style + a.append( {'xxx':'mydict'} ) + print a print 'testing append' a.append( 4 ) show( a ) @@ -44,22 +46,27 @@ t = tuple( a ) print t[-1] - print 'testing count' + print 'testing count - should be 1' print a.count(4) + print 'testing count - should be 2' a.append(4) print a.count(4) + a.append( 'A' ) a.append( 'A' ) a.append( 'A' ) print 'should print 3' print a.count('A') - print 'testing slice' + print 'testing slice[:]' sliced = a[:] - print sliced[...] - + print sliced + print 'testing [0,1]*10' xxx = [0,1]*10 - print xxx[...] + print xxx + print 'testing list from string' + s = list( 'abc' ) + print s From c58b2e6a1be8e02635b6a3d299fe7cb55da836a2 Mon Sep 17 00:00:00 2001 From: hartsantler Date: Mon, 16 Dec 2013 20:16:38 -0800 Subject: [PATCH 047/521] core: made jsify recursive --- pythonjs.js | 58 ++++++++++++++++++- runtime/builtins.py | 21 ++++++- .../test_calling_javascript_keyword_args.html | 2 +- 3 files changed, 77 insertions(+), 4 deletions(-) diff --git a/pythonjs.js b/pythonjs.js index 5570663..a8eaeb7 100644 --- a/pythonjs.js +++ b/pythonjs.js @@ -1,4 +1,4 @@ -// PythonJS Runtime - regenerated on: Sun Dec 15 19:06:10 2013 +// PythonJS Runtime - regenerated on: Mon Dec 16 20:15:19 2013 __NULL_OBJECT__ = Object.create(null); if (( "window" ) in this && ( "document" ) in this) { __NODEJS__ = false; @@ -1007,6 +1007,26 @@ _setup_str_prototype.types_signature = { }; _setup_str_prototype.pythonscript_function = true; _setup_str_prototype(); _setup_array_prototype = function(args, kwargs) { + var func = function() { + var i, item; + i = 0; + while(( i ) < this.length) { + item = this[i]; + if (( typeof(item) ) == "object") { + if (item.jsify) { + this[i] = item.jsify(); + } + } + i += 1; + } + return this; + } + + func.NAME = "func"; + func.args_signature = []; + func.kwargs_signature = { }; + func.types_signature = { }; + Array.prototype.jsify = func; var func = function(a) { if (( this.indexOf(a) ) == -1) { return false; @@ -2414,7 +2434,6 @@ var dict, __dict_attrs, __dict_parents; __dict_attrs = Object(); __dict_parents = []; __dict_properties = Object(); -__dict_parents.push(jsifyable); __dict_UID = 0; __dict_attrs["UID"] = __dict_UID; __dict___init__ = function(args, kwargs) { @@ -2463,6 +2482,41 @@ __dict___init__.kwargs_signature = { js_object:undefined }; __dict___init__.types_signature = { js_object:"None" }; __dict___init__.pythonscript_function = true; __dict_attrs["__init__"] = __dict___init__; +__dict_jsify = function(args, kwargs) { + var keys, value; + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { + /*pass*/ + } else { + args = Array.prototype.slice.call(arguments); + kwargs = Object(); + } + var signature, arguments; + signature = {"kwargs": Object(), "args": __create_array__("self")}; + arguments = get_arguments(signature, args, kwargs); + var self = arguments['self']; + keys = __get__(__get__(Object, "keys"), "__call__")([self["$wrapped"]], __NULL_OBJECT__); + var __iterator__, key; + __iterator__ = __get__(__get__(keys, "__iter__"), "__call__")([], Object()); + var __next__; + __next__ = __get__(__iterator__, "next_fast"); + while(( __iterator__.index ) < __iterator__.length) { + key = __next__(); + value = __get__(self["$wrapped"], "__getitem__")([key], Object()); + if (( typeof(value) ) == "object") { + if (__get__(value, "jsify")) { + __get__(__get__(self["$wrapped"], "__setitem__"), "__call__")([key, __get__(__get__(value, "jsify"), "__call__")()], Object()); + } + } + } + return self["$wrapped"]; +} + +__dict_jsify.NAME = "__dict_jsify"; +__dict_jsify.args_signature = ["self"]; +__dict_jsify.kwargs_signature = { }; +__dict_jsify.types_signature = { }; +__dict_jsify.pythonscript_function = true; +__dict_attrs["jsify"] = __dict_jsify; __dict_get = function(args, kwargs) { var __dict; if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { diff --git a/runtime/builtins.py b/runtime/builtins.py index 924afbe..89b5577 100644 --- a/runtime/builtins.py +++ b/runtime/builtins.py @@ -329,6 +329,16 @@ def func(encoding): def _setup_array_prototype(): with javascript: + @Array.prototype.jsify + def func(): + i = 0 + while i < this.length: + item = this[ i ] + if typeof(item) == 'object': + if item.jsify: + this[ i ] = item.jsify() + i += 1 + return this @Array.prototype.__contains__ def func(a): @@ -731,7 +741,7 @@ def __contains__(self, value): class jsifyable: def jsify(self): return self[...] -class dict( jsifyable ): +class dict: # http://stackoverflow.com/questions/10892322/javascript-hashtable-use-object-key # using a function as a key is allowed, but would waste memory because it gets converted to a string # http://stackoverflow.com/questions/10858632/are-functions-valid-keys-for-javascript-object-properties @@ -758,6 +768,15 @@ def __init__(self, js_object=None): else: ## TODO - deprecate self[...] = js_object + def jsify(self): + keys = Object.keys( self[...] ) + for key in keys: + value = self[...][key] + if typeof(value) == 'object': + if value.jsify: + self[...][key] = value.jsify() + return self[...] + def get(self, key, _default=None): __dict = self[...] if JS("typeof(key) === 'object'"): diff --git a/tests/test_calling_javascript_keyword_args.html b/tests/test_calling_javascript_keyword_args.html index a366e34..1b94786 100644 --- a/tests/test_calling_javascript_keyword_args.html +++ b/tests/test_calling_javascript_keyword_args.html @@ -18,7 +18,7 @@ def test(): global c - c = ['hello', 'world'] ## automatically converted to Array when passed to js_function + c = ['hello', 'world', {'xxx':99}, {'yyy':[1.1, {'sub':'AAA'}]}] print js_function( 'A','B',c, x=1, y=2, z=3 ) From edcfbe6060e68fb291fb7c4cd47e6f5ec6b29835 Mon Sep 17 00:00:00 2001 From: hartsantler Date: Tue, 17 Dec 2013 06:32:47 -0800 Subject: [PATCH 048/521] convert keyword argument types to JavaScript types when calling external JavaScript function. --- pythonjs.js | 17 ++++++++++++++--- runtime/pythonpythonjs.py | 18 +++++++++++------- .../test_calling_javascript_keyword_args.html | 4 ++-- 3 files changed, 27 insertions(+), 12 deletions(-) diff --git a/pythonjs.js b/pythonjs.js index a8eaeb7..d35a655 100644 --- a/pythonjs.js +++ b/pythonjs.js @@ -1,4 +1,4 @@ -// PythonJS Runtime - regenerated on: Mon Dec 16 20:15:19 2013 +// PythonJS Runtime - regenerated on: Mon Dec 16 20:24:12 2013 __NULL_OBJECT__ = Object.create(null); if (( "window" ) in this && ( "document" ) in this) { __NODEJS__ = false; @@ -53,7 +53,7 @@ __get__ = function(object, attribute) { } else { if ({}.toString.call(object) === '[object Function]') { var wrapper = function(args, kwargs) { - var i, arg; + var i, arg, keys; i = 0; while(( i ) < args.length) { arg = args[i]; @@ -64,8 +64,19 @@ __get__ = function(object, attribute) { } i += 1; } - if (( Object.keys(kwargs).length ) != 0) { + keys = Object.keys(kwargs); + if (( keys.length ) != 0) { args.push(kwargs); + i = 0; + while(( i ) < keys.length) { + arg = kwargs[keys[i]]; + if (( typeof(arg) ) == "object") { + if (arg.jsify) { + kwargs[keys[i]] = arg.jsify(); + } + } + i += 1; + } } return object.apply(undefined, args); } diff --git a/runtime/pythonpythonjs.py b/runtime/pythonpythonjs.py index 7b4c759..cb1aff6 100644 --- a/runtime/pythonpythonjs.py +++ b/runtime/pythonpythonjs.py @@ -69,23 +69,27 @@ def __get__(object, attribute): elif JS("{}.toString.call(object) === '[object Function]'"): def wrapper(args,kwargs): - var(i, arg) + var(i, arg, keys) i = 0 while i < args.length: arg = args[i] #if instanceof(arg, Object): ## fails on objects created by Object.create(null) if typeof(arg) == 'object': - #if arg.__class__: - # if arg.__class__.__name__ == 'list' or arg.__class__.__name__ == 'tuple': - # args[i] = arg[...] - # elif arg.__class__.__name__ == 'dict': - # args[i] = arg[...] if arg.jsify: args[i] = arg.jsify() i += 1 - if Object.keys(kwargs).length != 0: + keys = Object.keys(kwargs) + if keys.length != 0: args.push( kwargs ) + i = 0 + while i < keys.length: + arg = kwargs[ keys[i] ] + if typeof(arg) == 'object': + if arg.jsify: + kwargs[ keys[i] ] = arg.jsify() + i += 1 + return object.apply(None, args) wrapper.is_wrapper = True diff --git a/tests/test_calling_javascript_keyword_args.html b/tests/test_calling_javascript_keyword_args.html index 1b94786..4fd48ff 100644 --- a/tests/test_calling_javascript_keyword_args.html +++ b/tests/test_calling_javascript_keyword_args.html @@ -8,7 +8,7 @@ console.log('options', options); console.log( c[0] ); console.log( c[1] ); - + console.log( 'ob', options.ob ); return options.x + options.y + options.z; } @@ -19,7 +19,7 @@ def test(): global c c = ['hello', 'world', {'xxx':99}, {'yyy':[1.1, {'sub':'AAA'}]}] - print js_function( 'A','B',c, x=1, y=2, z=3 ) + print js_function( 'A','B',c, x=1, y=2, z=3, ob={'zzz':420} ) From 8d9d77b00a0ff11c8d4749b587b4f60bc1288f30 Mon Sep 17 00:00:00 2001 From: Thierry EXCOFFIER Date: Thu, 2 Jan 2014 11:44:26 +0100 Subject: [PATCH 049/521] Fix javascript 'float' and 'int' functions float("14") < float("2") now returns 'false' float('a') int('a') raises an exception window object is no more used in order to be compatible with server side JavaScript --- pythonjs.js | 20 +++++++++++--------- runtime/builtins.py | 16 ++++++++-------- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/pythonjs.js b/pythonjs.js index d35a655..9c5d59b 100644 --- a/pythonjs.js +++ b/pythonjs.js @@ -1,4 +1,4 @@ -// PythonJS Runtime - regenerated on: Mon Dec 16 20:24:12 2013 +// PythonJS Runtime - regenerated on: Thu Jan 2 11:33:21 2014 __NULL_OBJECT__ = Object.create(null); if (( "window" ) in this && ( "document" ) in this) { __NODEJS__ = false; @@ -711,6 +711,7 @@ isinstance.kwargs_signature = { }; isinstance.types_signature = { }; isinstance.pythonscript_function = true; int = function(args, kwargs) { + var a; if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { @@ -721,11 +722,11 @@ int = function(args, kwargs) { signature = {"kwargs": Object(), "args": __create_array__("a")}; arguments = get_arguments(signature, args, kwargs); var a = arguments['a']; - if (a instanceof String) { - return window.parseInt(a); - } else { - return Math.round(a); + a = Math.round(a); + if (isNaN(a)) { + throw EvalError; } + return a; } int.NAME = "int"; @@ -734,6 +735,7 @@ int.kwargs_signature = { }; int.types_signature = { }; int.pythonscript_function = true; float = function(args, kwargs) { + var a; if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { @@ -744,11 +746,11 @@ float = function(args, kwargs) { signature = {"kwargs": Object(), "args": __create_array__("a")}; arguments = get_arguments(signature, args, kwargs); var a = arguments['a']; - if (a instanceof String) { - return window.parseFloat(a); - } else { - return a; + a = Number(a); + if (isNaN(a)) { + throw EvalError; } + return a; } float.NAME = "float"; diff --git a/runtime/builtins.py b/runtime/builtins.py index 89b5577..a64ecfc 100644 --- a/runtime/builtins.py +++ b/runtime/builtins.py @@ -192,17 +192,17 @@ def isinstance( ob, klass): def int(a): with javascript: - if instanceof(a, String): - return window.parseInt(a) - else: - return Math.round(a) + a = Math.round(a) + if isNaN(a): + raise EvalError + return a def float(a): with javascript: - if instanceof(a, String): - return window.parseFloat(a) - else: - return a + a = Number(a) + if isNaN(a): + raise EvalError + return a def round(a, places): with javascript: From fb843a6d71218a84e9fb269446a631107420a883 Mon Sep 17 00:00:00 2001 From: Thierry EXCOFFIER Date: Thu, 2 Jan 2014 19:09:00 +0100 Subject: [PATCH 050/521] Javascript String.index may throw an exception as in Python. Add String.find String.find is the same than the former String.index --- pythonjs.js | 18 ++++++++++++++++-- runtime/builtins.py | 7 +++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/pythonjs.js b/pythonjs.js index 9c5d59b..444da87 100644 --- a/pythonjs.js +++ b/pythonjs.js @@ -1,4 +1,4 @@ -// PythonJS Runtime - regenerated on: Thu Jan 2 11:33:21 2014 +// PythonJS Runtime - regenerated on: Thu Jan 2 19:08:07 2014 __NULL_OBJECT__ = Object.create(null); if (( "window" ) in this && ( "document" ) in this) { __NODEJS__ = false; @@ -964,7 +964,12 @@ _setup_str_prototype = function(args, kwargs) { func.types_signature = { }; String.prototype.lower = func; var func = function(a) { - return this.indexOf(a); + var a; + a = this.indexOf(a); + if (( a ) == -1) { + throw EvalError; + } + return a; } func.NAME = "func"; @@ -972,6 +977,15 @@ _setup_str_prototype = function(args, kwargs) { func.kwargs_signature = { }; func.types_signature = { }; String.prototype.index = func; + var func = function(a) { + return this.indexOf(a); + } + + func.NAME = "func"; + func.args_signature = ["a"]; + func.kwargs_signature = { }; + func.types_signature = { }; + String.prototype.find = func; var func = function() { var digits; digits = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]; diff --git a/runtime/builtins.py b/runtime/builtins.py index a64ecfc..766b8ac 100644 --- a/runtime/builtins.py +++ b/runtime/builtins.py @@ -304,6 +304,13 @@ def func(): return this.toLowerCase() @String.prototype.index + def func(a): + a = this.indexOf(a) + if a == -1: + raise EvalError + return a + + @String.prototype.find def func(a): return this.indexOf(a) From 7d4e5e26b49525e653f2368e0d4ed1c8c092adaf Mon Sep 17 00:00:00 2001 From: Thierry EXCOFFIER Date: Thu, 2 Jan 2014 20:09:16 +0100 Subject: [PATCH 051/521] Fix the translator in the case of Python code outside of functions The following code is now translatable: a = {'x': '5'} print a['x'] --- pythonjs/python_to_pythonjs.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index 49aeb13..c28f606 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -166,6 +166,7 @@ def check_for_parent_with(self, method=None, property=None, operator=None, class class PythonToPythonJS(NodeVisitor): identifier = 0 + _func_typedefs = () def __init__(self, source=None, module=None, module_path=None, dart=False): super(PythonToPythonJS, self).__init__() From 97da96f881a1671dca833d7e30f38755fa9c6b69 Mon Sep 17 00:00:00 2001 From: Thierry EXCOFFIER Date: Fri, 3 Jan 2014 20:20:09 +0100 Subject: [PATCH 052/521] Rewrite of the 'dict' getters and setters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With this rewrite: * The getter raise an exception if the item does not exist * '@' prefix is replaced by '' because it is less common * 'uid' attribute has been replaced by '__uid__' * '__contains__' now works with keys that are functions The code runs at the same speed. As before, 4 and '4' are the same key. --- pythonjs.js | 117 ++++++++++++-------------------------------- runtime/builtins.py | 96 ++++++++++-------------------------- 2 files changed, 56 insertions(+), 157 deletions(-) diff --git a/pythonjs.js b/pythonjs.js index 444da87..1acd72d 100644 --- a/pythonjs.js +++ b/pythonjs.js @@ -1,4 +1,4 @@ -// PythonJS Runtime - regenerated on: Thu Jan 2 19:08:07 2014 +// PythonJS Runtime - regenerated on: Sat Jan 4 10:29:13 2014 __NULL_OBJECT__ = Object.create(null); if (( "window" ) in this && ( "document" ) in this) { __NODEJS__ = false; @@ -2461,8 +2461,6 @@ var dict, __dict_attrs, __dict_parents; __dict_attrs = Object(); __dict_parents = []; __dict_properties = Object(); -__dict_UID = 0; -__dict_attrs["UID"] = __dict_UID; __dict___init__ = function(args, kwargs) { var i, value, key; if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { @@ -2545,7 +2543,6 @@ __dict_jsify.types_signature = { }; __dict_jsify.pythonscript_function = true; __dict_attrs["jsify"] = __dict_jsify; __dict_get = function(args, kwargs) { - var __dict; if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { @@ -2558,25 +2555,12 @@ __dict_get = function(args, kwargs) { var self = arguments['self']; var key = arguments['key']; var _default = arguments['_default']; - __dict = self["$wrapped"]; - if (typeof(key) === 'object') { - var uid = "@"+key.uid; - if (uid in __dict) { - return __dict[uid]; - } - } else { - if (typeof(key) === 'function') { - var uid = "@"+key.uid; - if (uid in __dict) { - return __dict[uid]; - } - } else { - if (key in __dict) { - return __dict[key]; - } - } - } - return _default; + try { +return __get__(self, "__getitem__")([key], Object()); + } catch(__exception__) { +return _default; + +} } __dict_get.NAME = "__dict_get"; @@ -2586,7 +2570,6 @@ __dict_get.types_signature = { _default:"None" }; __dict_get.pythonscript_function = true; __dict_attrs["get"] = __dict_get; __dict_set = function(args, kwargs) { - var __dict, uid; if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { @@ -2599,28 +2582,7 @@ __dict_set = function(args, kwargs) { var self = arguments['self']; var key = arguments['key']; var value = arguments['value']; - __dict = self["$wrapped"]; - if (typeof(key) === 'object') { - if (key.uid === undefined) { - uid = _PythonJS_UID; - key.uid = uid; - _PythonJS_UID += 1; - } - var uid = key.uid; - __dict["@"+uid] = value; - } else { - if (typeof(key) === 'function') { - if (key.uid === undefined) { - uid = _PythonJS_UID; - key.uid = uid; - _PythonJS_UID += 1; - } - var uid = key.uid; - __dict["@"+uid] = value; - } else { - __dict[key] = value; - } - } + __get__(__get__(self, "__setitem__"), "__call__")([key, value], __NULL_OBJECT__); } __dict_set.NAME = "__dict_set"; @@ -2665,17 +2627,16 @@ __dict___getitem__ = function(args, kwargs) { var self = arguments['self']; var key = arguments['key']; __dict = self["$wrapped"]; - if (typeof(key) === 'object') { - var uid = key.uid; - return __dict["@"+uid]; - } else { - if (typeof(key) === 'function') { - var uid = key.uid; - return __dict["@"+uid]; - } else { - return __dict[key]; + if (typeof(key) === 'object' || typeof(key) === 'function') { + if (key.__uid__ && key.__uid__ in __dict) { + return __dict[key.__uid__]; } + throw IndexError; } + if (key in __dict) { + return __dict[key]; + } + throw IndexError; } __dict___getitem__.NAME = "__dict___getitem__"; @@ -2685,7 +2646,7 @@ __dict___getitem__.types_signature = { }; __dict___getitem__.pythonscript_function = true; __dict_attrs["__getitem__"] = __dict___getitem__; __dict___setitem__ = function(args, kwargs) { - var __dict, uid; + var __dict; if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { @@ -2699,26 +2660,13 @@ __dict___setitem__ = function(args, kwargs) { var key = arguments['key']; var value = arguments['value']; __dict = self["$wrapped"]; - if (typeof(key) === 'object') { - if (key.uid === undefined) { - uid = _PythonJS_UID; - key.uid = uid; - _PythonJS_UID += 1; - } - var uid = key.uid; - __dict["@"+uid] = value; - } else { - if (typeof(key) === 'function') { - if (key.uid === undefined) { - uid = _PythonJS_UID; - key.uid = uid; - _PythonJS_UID += 1; - } - var uid = key.uid; - __dict["@"+uid] = value; - } else { - __dict[key] = value; + if (typeof(key) === 'object' || typeof(key) === 'function') { + if (key.__uid__ === undefined) { + key.__uid__ = ''+_PythonJS_UID++; } + __dict[key.__uid__] = value; + } else { + __dict[key] = value; } } @@ -2808,7 +2756,6 @@ __dict_values.types_signature = { }; __dict_values.pythonscript_function = true; __dict_attrs["values"] = __dict_values; __dict___contains__ = function(args, kwargs) { - var keys, key; if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { @@ -2820,17 +2767,13 @@ __dict___contains__ = function(args, kwargs) { arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var value = arguments['value']; - keys = Object.keys(self["$wrapped"]); - if (( typeof(value) ) == "object") { - key = ("@" + value.uid); - } else { - key = ("" + value); - } - if (( keys.indexOf(key) ) == -1) { - return false; - } else { - return true; - } + try { +__dict___getitem__([self, value], Object()); +return true; + } catch(__exception__) { +return false; + +} } __dict___contains__.NAME = "__dict___contains__"; diff --git a/runtime/builtins.py b/runtime/builtins.py index 766b8ac..3931d55 100644 --- a/runtime/builtins.py +++ b/runtime/builtins.py @@ -752,7 +752,6 @@ class dict: # http://stackoverflow.com/questions/10892322/javascript-hashtable-use-object-key # using a function as a key is allowed, but would waste memory because it gets converted to a string # http://stackoverflow.com/questions/10858632/are-functions-valid-keys-for-javascript-object-properties - UID = 0 def __init__(self, js_object=None): with javascript: self[...] = {} @@ -785,75 +784,40 @@ def jsify(self): return self[...] def get(self, key, _default=None): - __dict = self[...] - if JS("typeof(key) === 'object'"): - JS('var uid = "@"+key.uid') ## gotcha - what if "@undefined" was in __dict ? - if JS('uid in __dict'): - return JS('__dict[uid]') - elif JS("typeof(key) === 'function'"): - JS('var uid = "@"+key.uid') - if JS('uid in __dict'): - return JS('__dict[uid]') - else: - if JS('key in __dict'): - return JS('__dict[key]') - - return _default + try: + return self[key] + except: + return _default def set(self, key, value): - global _PythonJS_UID - - __dict = self[...] - if JS("typeof(key) === 'object'"): - if JS("key.uid === undefined"): - uid = _PythonJS_UID - JS("key.uid = uid") - _PythonJS_UID += 1 - JS('var uid = key.uid') - JS('__dict["@"+uid] = value') - elif JS("typeof(key) === 'function'"): - if JS("key.uid === undefined"): - uid = _PythonJS_UID - JS("key.uid = uid") - _PythonJS_UID += 1 - JS('var uid = key.uid') - JS('__dict["@"+uid] = value') - else: - JS('__dict[key] = value') + self.__setitem__(key, value) def __len__(self): __dict = self[...] return JS('Object.keys(__dict).length') def __getitem__(self, key): + # XXX: '4' and 4 are the same key __dict = self[...] - if JS("typeof(key) === 'object'"): - JS('var uid = key.uid') - return JS('__dict["@"+uid]') ## "@" is needed so that integers can also be used as keys - elif JS("typeof(key) === 'function'"): - JS('var uid = key.uid') - return JS('__dict["@"+uid]') ## "@" is needed so that integers can also be used as keys - else: + if JS("typeof(key) === 'object' || typeof(key) === 'function'"): + # Test undefined because it can be in the dict + if JS("key.__uid__ && key.__uid__ in __dict"): + return JS('__dict[key.__uid__]') + raise IndexError + # Tested after in order to not convert functions to strings. + # The slow down is negligible + if JS("key in __dict"): return JS('__dict[key]') + raise IndexError def __setitem__(self, key, value): - global _PythonJS_UID - __dict = self[...] - if JS("typeof(key) === 'object'"): - if JS("key.uid === undefined"): - uid = _PythonJS_UID - JS("key.uid = uid") - _PythonJS_UID += 1 - JS('var uid = key.uid') - JS('__dict["@"+uid] = value') - elif JS("typeof(key) === 'function'"): - if JS("key.uid === undefined"): - uid = _PythonJS_UID - JS("key.uid = uid") - _PythonJS_UID += 1 - JS('var uid = key.uid') - JS('__dict["@"+uid] = value') + if JS("typeof(key) === 'object' || typeof(key) === 'function'"): + if JS("key.__uid__ === undefined"): + # "" is needed so that integers can also be + # used as keys + JS("key.__uid__ = '' + _PythonJS_UID++") + JS('__dict[key.__uid__] = value') else: JS('__dict[key] = value') @@ -869,7 +833,6 @@ def pop(self, key, d=None): js_object = self[...] JS("delete js_object[key]") return v - def values(self): with javascript: @@ -879,19 +842,12 @@ def values(self): out.push( self[...][key] ) return out - def __contains__(self, value): - with javascript: - keys = Object.keys(self[...]) ## the problem with this is that keys are coerced into strings - if typeof(value) == 'object': - key = '@'+value.uid - else: - key = ''+value ## convert to string - - if keys.indexOf( key ) == -1: - return False - else: - return True + try: + self[value] + return True + except: + return False def __iter__(self): return Iterator(self.keys(), 0) From 8b5949c066bf9d5a77de913d5234091e0298d825 Mon Sep 17 00:00:00 2001 From: Thierry EXCOFFIER Date: Sat, 4 Jan 2014 11:04:08 +0100 Subject: [PATCH 053/521] Add missing exception values: IndexError, KeyError, ValueError Put the good exception names in the buitins. --- pythonjs.js | 17 ++++++++++------- runtime/builtins.py | 13 ++++++++----- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/pythonjs.js b/pythonjs.js index 1acd72d..4c98dee 100644 --- a/pythonjs.js +++ b/pythonjs.js @@ -1,4 +1,4 @@ -// PythonJS Runtime - regenerated on: Sat Jan 4 10:29:13 2014 +// PythonJS Runtime - regenerated on: Sat Jan 4 11:01:10 2014 __NULL_OBJECT__ = Object.create(null); if (( "window" ) in this && ( "document" ) in this) { __NODEJS__ = false; @@ -370,6 +370,9 @@ get_arguments = function(signature, args, kwargs) { return out; } _PythonJS_UID = 0; +var IndexError = new RangeError(); +var KeyError = new RangeError(); +var ValueError = new RangeError(); __object_keys__ = function(ob) { var arr; "\n notes:\n . Object.keys(ob) will not work because we create PythonJS objects using `Object.create(null)`\n . this is different from Object.keys because it traverses the prototype chain.\n "; @@ -724,7 +727,7 @@ int = function(args, kwargs) { var a = arguments['a']; a = Math.round(a); if (isNaN(a)) { - throw EvalError; + throw ValueError; } return a; } @@ -748,7 +751,7 @@ float = function(args, kwargs) { var a = arguments['a']; a = Number(a); if (isNaN(a)) { - throw EvalError; + throw ValueError; } return a; } @@ -967,7 +970,7 @@ _setup_str_prototype = function(args, kwargs) { var a; a = this.indexOf(a); if (( a ) == -1) { - throw EvalError; + throw ValueError; } return a; } @@ -2631,12 +2634,12 @@ __dict___getitem__ = function(args, kwargs) { if (key.__uid__ && key.__uid__ in __dict) { return __dict[key.__uid__]; } - throw IndexError; + throw KeyError; } if (key in __dict) { return __dict[key]; } - throw IndexError; + throw KeyError; } __dict___getitem__.NAME = "__dict___getitem__"; @@ -2662,7 +2665,7 @@ __dict___setitem__ = function(args, kwargs) { __dict = self["$wrapped"]; if (typeof(key) === 'object' || typeof(key) === 'function') { if (key.__uid__ === undefined) { - key.__uid__ = ''+_PythonJS_UID++; + key.__uid__ = '' + _PythonJS_UID++; } __dict[key.__uid__] = value; } else { diff --git a/runtime/builtins.py b/runtime/builtins.py index 3931d55..db8383c 100644 --- a/runtime/builtins.py +++ b/runtime/builtins.py @@ -5,6 +5,9 @@ _PythonJS_UID = 0 +JS("var IndexError = new RangeError()") +JS("var KeyError = new RangeError()") +JS("var ValueError = new RangeError()") with javascript: @@ -194,14 +197,14 @@ def int(a): with javascript: a = Math.round(a) if isNaN(a): - raise EvalError + raise ValueError return a def float(a): with javascript: a = Number(a) if isNaN(a): - raise EvalError + raise ValueError return a def round(a, places): @@ -307,7 +310,7 @@ def func(): def func(a): a = this.indexOf(a) if a == -1: - raise EvalError + raise ValueError return a @String.prototype.find @@ -803,12 +806,12 @@ def __getitem__(self, key): # Test undefined because it can be in the dict if JS("key.__uid__ && key.__uid__ in __dict"): return JS('__dict[key.__uid__]') - raise IndexError + raise KeyError # Tested after in order to not convert functions to strings. # The slow down is negligible if JS("key in __dict"): return JS('__dict[key]') - raise IndexError + raise KeyError def __setitem__(self, key, value): __dict = self[...] From 2f5794485e5d273cf2611e4f5eca5b94ba7abf42 Mon Sep 17 00:00:00 2001 From: Thierry EXCOFFIER Date: Sun, 5 Jan 2014 21:50:19 +0100 Subject: [PATCH 054/521] Fix backslash processing (a="\\" now works) --- pythonjs/python_to_pythonjs.py | 2 +- pythonjs/pythonjs.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index c28f606..145ba9d 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -1383,7 +1383,7 @@ def visit_Print(self, node): writer.write('print %s' % ', '.join(map(self.visit, node.values))) def visit_Str(self, node): - s = node.s.replace('\n', '\\n').replace('\0', '\\0') + s = node.s.replace('\\','\\\\').replace('\n', '\\n').replace('\0', '\\0') if self._with_js or self._with_dart: return '"%s"' %s else: diff --git a/pythonjs/pythonjs.py b/pythonjs/pythonjs.py index 449c9a1..96145da 100755 --- a/pythonjs/pythonjs.py +++ b/pythonjs/pythonjs.py @@ -281,7 +281,7 @@ def visit_While(self, node): return '\n'.join( body ) def visit_Str(self, node): - s = node.s.replace('\n', '\\n') + s = node.s.replace("\\", "\\\\").replace('\n', '\\n') if '"' in s: return "'%s'" % s return '"%s"' % s From d4f083860f565aa9c7e177c2b420fc058dc51c64 Mon Sep 17 00:00:00 2001 From: hartsantler Date: Mon, 6 Jan 2014 21:41:20 -0800 Subject: [PATCH 055/521] fixed 'o' in 'helloworld' for javascript mode. --- pythonjs/python_to_pythonjs.py | 3 +++ tests/test_if_not_in.html | 3 +++ 2 files changed, 6 insertions(+) diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index c28f606..b2b2adc 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -1058,6 +1058,9 @@ def visit_Compare(self, node): comp.append( "%s['__contains__'](%s) )" %a ) #comp.append( ' or (instanceof(%s,Object) and %s in %s) ') comp.append( ' or Object.hasOwnProperty.call(%s, %s)' %(a[0],a[1])) + ## fixes 'o' in 'helloworld' in javascript mode ## + comp.append( ' or typeof(%s)=="string" and %s.__contains__(%s)' %(a[0],a[0],a[1])) + else: comp.append( "__get__(__get__(%s, '__contains__'), '__call__')([%s], JSObject())" %a ) diff --git a/tests/test_if_not_in.html b/tests/test_if_not_in.html index 5a29d2a..85f6a0e 100644 --- a/tests/test_if_not_in.html +++ b/tests/test_if_not_in.html @@ -70,6 +70,9 @@ if 'XXX' not in {xx:True}: print 'OK' else: print 'in literal jsobject failed' + if 'o' in 'hello': print 'o in hello works OK' + else: print 'o in hello FAILED' + From 7b955fb563856f285eb8d12a0f3e6752045103f0 Mon Sep 17 00:00:00 2001 From: hartsantler Date: Tue, 7 Jan 2014 20:11:03 -0800 Subject: [PATCH 056/521] "dict" in javascript mode can now use d.get('x','mydefault') --- pythonjs.js | 22 +++++++++++++++++++--- pythonjs/python_to_pythonjs.py | 14 +++++++++++++- runtime/builtins.py | 34 +++++++++++++++++++++++++++++----- tests/test_dict_methods.html | 7 +++++++ tests/test_if_not_in.html | 3 +++ 5 files changed, 71 insertions(+), 9 deletions(-) diff --git a/pythonjs.js b/pythonjs.js index 4c98dee..20b1e63 100644 --- a/pythonjs.js +++ b/pythonjs.js @@ -1,4 +1,4 @@ -// PythonJS Runtime - regenerated on: Sat Jan 4 11:01:10 2014 +// PythonJS Runtime - regenerated on: Tue Jan 7 20:07:13 2014 __NULL_OBJECT__ = Object.create(null); if (( "window" ) in this && ( "document" ) in this) { __NODEJS__ = false; @@ -373,6 +373,22 @@ _PythonJS_UID = 0; var IndexError = new RangeError(); var KeyError = new RangeError(); var ValueError = new RangeError(); +__jsdict_get = function(ob, key, default_value) { + if (default_value == undefined) default_value = undefined; + if (ob instanceof Object) { + if (key in ob) { + return ob[key]; + } + return default_value; + } else { + return ob.get(key, default_value); + } +} + +__jsdict_get.NAME = "__jsdict_get"; +__jsdict_get.args_signature = ["ob", "key", "default_value"]; +__jsdict_get.kwargs_signature = { default_value:undefined }; +__jsdict_get.types_signature = { default_value:"None" }; __object_keys__ = function(ob) { var arr; "\n notes:\n . Object.keys(ob) will not work because we create PythonJS objects using `Object.create(null)`\n . this is different from Object.keys because it traverses the prototype chain.\n "; @@ -492,7 +508,7 @@ create_class = function(class_name, parents, attrs, props) { "Create a PythonJS object"; object = Object.create(null); object.__class__ = klass; - Object.defineProperty(object, "__dict__", { "enumerable":false,"value":object,"writeable":false,"configurable":false }); + object.__dict__ = object; has_getattribute = false; has_getattr = false; var __iter6 = klass.__all_method_names__; @@ -996,7 +1012,7 @@ _setup_str_prototype = function(args, kwargs) { if (! (__iter8 instanceof Array) ) { __iter8 = __object_keys__(__iter8) } for (var __idx8=0; __idx8 < __iter8.length; __idx8++) { var char = __iter8[ __idx8 ]; - if (Object.hasOwnProperty.call(digits, "__contains__") && digits["__contains__"](char) || Object.hasOwnProperty.call(digits, char)) { + if (Object.hasOwnProperty.call(digits, "__contains__") && digits["__contains__"](char) || Object.hasOwnProperty.call(digits, char) || ( typeof(digits) ) == "string" && digits.__contains__(char)) { /*pass*/ } else { return false; diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index b2b2adc..4865f06 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -1521,6 +1521,17 @@ def visit_Call(self, node): assert len(args) == 1 return 'new(%s)' %args[0] + elif isinstance(node.func, ast.Attribute) and not self._with_dart: ## special method calls + anode = node.func + if anode.attr == 'get': + if args: + return '__jsdict_get(%s, %s)' %(self.visit(anode.value), ','.join(args) ) + else: + return '__jsdict_get(%s)' %self.visit(anode.value) + else: + a = ','.join(args) + return '%s(%s)' %( self.visit(node.func), a ) + #elif isinstance(node.func, Name) and node.func.id == 'JS': ## avoids nested JS # assert len(args) == 1 # return node.args[0].s ## string literal @@ -1622,10 +1633,11 @@ def visit_Call(self, node): # else: # return '%s()' %name + #if isinstance(node.func, ast.Attribute) and isinstance(node.func.value, Name) and node.func.value.id == 'get': ## get method call + if isinstance(node.func, ast.Attribute) and isinstance(node.func.value, Name) and node.func.value.id in self._func_typedefs: type = self._func_typedefs[ node.func.value.id ] if type == 'list' and node.func.attr == 'append': - #return '%s[...].push(%s)' %(node.func.value.id, self.visit(node.args[0])) return '%s.push(%s)' %(node.func.value.id, self.visit(node.args[0])) else: raise RuntimeError diff --git a/runtime/builtins.py b/runtime/builtins.py index db8383c..791d70f 100644 --- a/runtime/builtins.py +++ b/runtime/builtins.py @@ -9,7 +9,30 @@ JS("var KeyError = new RangeError()") JS("var ValueError = new RangeError()") +#def _setup_object_prototype(): ## NOT USED - see below +# with javascript: +# #@Object.prototype.get +# def func(key, default_value=None): +# if JS("key in this"): return this[key] +# return default_value +# +# Object.defineProperty( +# Object, +# 'get', +# {enumerable:False, value:func, writeable:False, configurable:False} +# ) +#_setup_object_prototype() +## this is better solved by making these method names special cases in the translation phase, +## when translated methods named: "get" become __jsdict_get(ob,key,default) + with javascript: + def __jsdict_get(ob, key, default_value=None): + if instanceof(ob, Object): + if JS("key in ob"): return ob[key] + return default_value + else: ## PythonJS object instance ## + ## this works because instances from PythonJS are created using Object.create(null) ## + return JS("ob.get(key, default_value)") def __object_keys__(ob): ''' @@ -87,12 +110,13 @@ def __call__(): """Create a PythonJS object""" object = Object.create(null) object.__class__ = klass + object.__dict__ = object ## we need __dict__ so that __setattr__ can still set attributes using `old-style`: self.__dict__[n]=x - Object.defineProperty( - object, - '__dict__', - {enumerable:False, value:object, writeable:False, configurable:False} - ) + #Object.defineProperty( + # object, + # '__dict__', + # {enumerable:False, value:object, writeable:False, configurable:False} + #) has_getattribute = False diff --git a/tests/test_dict_methods.html b/tests/test_dict_methods.html index 6b159d8..00c5a21 100644 --- a/tests/test_dict_methods.html +++ b/tests/test_dict_methods.html @@ -36,6 +36,13 @@ for v in d.keys(): print 'v in keys', v + print d.get('NOTKEY', '.get my default works') + + with javascript: + j = {a:1, b:2, get:'not-a-method'} + xx = j.get('c', '.get in javascript mode works') + print xx + diff --git a/tests/test_if_not_in.html b/tests/test_if_not_in.html index 85f6a0e..318dd3f 100644 --- a/tests/test_if_not_in.html +++ b/tests/test_if_not_in.html @@ -73,6 +73,9 @@ if 'o' in 'hello': print 'o in hello works OK' else: print 'o in hello FAILED' + if 'X' not in 'hello': print 'X not in hello works OK' + else: print 'o not in hello FAILED' + From 20f3d3d8bd4459a7ea722e18385d9eba653ea6cf Mon Sep 17 00:00:00 2001 From: hartsantler Date: Thu, 9 Jan 2014 07:44:44 -0800 Subject: [PATCH 057/521] allow javascript-objects return from javascript function to act like a dict with a "get" method. --- pythonjs.js | 15 ++++++++++----- pythonjs/python_to_pythonjs.py | 13 +++++++++++-- runtime/builtins.py | 12 ++++++++++-- tests/test_dict_methods.html | 7 +++++++ 4 files changed, 38 insertions(+), 9 deletions(-) diff --git a/pythonjs.js b/pythonjs.js index 20b1e63..7acee13 100644 --- a/pythonjs.js +++ b/pythonjs.js @@ -1,4 +1,4 @@ -// PythonJS Runtime - regenerated on: Tue Jan 7 20:07:13 2014 +// PythonJS Runtime - regenerated on: Thu Jan 9 07:35:49 2014 __NULL_OBJECT__ = Object.create(null); if (( "window" ) in this && ( "document" ) in this) { __NODEJS__ = false; @@ -1664,7 +1664,7 @@ __Iterator_next = function(args, kwargs) { if (( index ) == length) { throw StopIteration; } - item = __get__(__get__(self.obj, "get"), "__call__")([self.index], __NULL_OBJECT__); + item = __jsdict_get(self.obj, self.index); self.index = (self.index + 1); return item; } @@ -2645,6 +2645,7 @@ __dict___getitem__ = function(args, kwargs) { arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var key = arguments['key']; + "\n notes:\n . '4' and 4 are the same key\n . it is possible that the translator mistakes a javascript-object for a dict and inlines this function,\n that is why below we return the key in self if __dict is undefined.\n "; __dict = self["$wrapped"]; if (typeof(key) === 'object' || typeof(key) === 'function') { if (key.__uid__ && key.__uid__ in __dict) { @@ -2652,8 +2653,12 @@ __dict___getitem__ = function(args, kwargs) { } throw KeyError; } - if (key in __dict) { + if (__dict && key in __dict) { return __dict[key]; + } else { + if (( __dict ) === undefined && key in self) { + return self[key]; + } } throw KeyError; } @@ -2729,7 +2734,7 @@ __dict_pop = function(args, kwargs) { var self = arguments['self']; var key = arguments['key']; var d = arguments['d']; - v = __get__(__get__(self, "get"), "__call__")([key, undefined], __NULL_OBJECT__); + v = __jsdict_get(self, key, undefined); if (( v ) === undefined) { return d; } else { @@ -3475,7 +3480,7 @@ _to_json = function(args, kwargs) { __next__ = __get__(__iterator__, "next_fast"); while(( __iterator__.index ) < __iterator__.length) { key = __next__(); - value = _to_json([__get__(__get__(pythonjs, "get"), "__call__")([key], __NULL_OBJECT__)], __NULL_OBJECT__); + value = _to_json([__jsdict_get(pythonjs, key)], __NULL_OBJECT__); key = _to_json([key], __NULL_OBJECT__); r[key] = value; } diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index 4865f06..8b9b3e5 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -1633,9 +1633,18 @@ def visit_Call(self, node): # else: # return '%s()' %name - #if isinstance(node.func, ast.Attribute) and isinstance(node.func.value, Name) and node.func.value.id == 'get': ## get method call + if isinstance(node.func, ast.Attribute) and node.func.attr == 'get': ## special method calls + anode = node.func + if anode.attr == 'get': + if args: + return '__jsdict_get(%s, %s)' %(self.visit(anode.value), args ) + else: + return '__jsdict_get(%s)' %self.visit(anode.value) + else: + a = ','.join(args) + return '%s(%s)' %( self.visit(node.func), a ) - if isinstance(node.func, ast.Attribute) and isinstance(node.func.value, Name) and node.func.value.id in self._func_typedefs: + elif isinstance(node.func, ast.Attribute) and isinstance(node.func.value, Name) and node.func.value.id in self._func_typedefs: type = self._func_typedefs[ node.func.value.id ] if type == 'list' and node.func.attr == 'append': return '%s.push(%s)' %(node.func.value.id, self.visit(node.args[0])) diff --git a/runtime/builtins.py b/runtime/builtins.py index 791d70f..bbe50b5 100644 --- a/runtime/builtins.py +++ b/runtime/builtins.py @@ -816,6 +816,7 @@ def get(self, key, _default=None): except: return _default + def set(self, key, value): self.__setitem__(key, value) @@ -824,7 +825,12 @@ def __len__(self): return JS('Object.keys(__dict).length') def __getitem__(self, key): - # XXX: '4' and 4 are the same key + ''' + notes: + . '4' and 4 are the same key + . it is possible that the translator mistakes a javascript-object for a dict and inlines this function, + that is why below we return the key in self if __dict is undefined. + ''' __dict = self[...] if JS("typeof(key) === 'object' || typeof(key) === 'function'"): # Test undefined because it can be in the dict @@ -833,8 +839,10 @@ def __getitem__(self, key): raise KeyError # Tested after in order to not convert functions to strings. # The slow down is negligible - if JS("key in __dict"): + if __dict and JS("key in __dict"): return JS('__dict[key]') + elif __dict is None and JS("key in self"): ## js-object + return JS("self[key]") raise KeyError def __setitem__(self, key, value): diff --git a/tests/test_dict_methods.html b/tests/test_dict_methods.html index 00c5a21..01195ff 100644 --- a/tests/test_dict_methods.html +++ b/tests/test_dict_methods.html @@ -43,6 +43,13 @@ xx = j.get('c', '.get in javascript mode works') print xx + xxx = j.get('c', '.get on jsob works from python mode') + print xxx + print j.get('get') + print j['get'] + j['get'] = 'XXX' + print j['get'] + From 74bcf088c80dc7225ee3aade2cb19dbe62cece10 Mon Sep 17 00:00:00 2001 From: hartsantler Date: Thu, 9 Jan 2014 11:08:30 -0800 Subject: [PATCH 058/521] updated so that javascript-object can have more methods like dict: get, set, keys, values. --- pythonjs.js | 193 ++++++++++++++++++++------------- pythonjs/python_to_pythonjs.py | 10 ++ runtime/builtins.py | 27 +++++ tests/test_dict_methods.html | 5 + 4 files changed, 162 insertions(+), 73 deletions(-) diff --git a/pythonjs.js b/pythonjs.js index 7acee13..ee67d80 100644 --- a/pythonjs.js +++ b/pythonjs.js @@ -1,4 +1,4 @@ -// PythonJS Runtime - regenerated on: Thu Jan 9 07:35:49 2014 +// PythonJS Runtime - regenerated on: Thu Jan 9 11:07:13 2014 __NULL_OBJECT__ = Object.create(null); if (( "window" ) in this && ( "document" ) in this) { __NODEJS__ = false; @@ -389,6 +389,53 @@ __jsdict_get.NAME = "__jsdict_get"; __jsdict_get.args_signature = ["ob", "key", "default_value"]; __jsdict_get.kwargs_signature = { default_value:undefined }; __jsdict_get.types_signature = { default_value:"None" }; +__jsdict_set = function(ob, key, value) { + if (ob instanceof Object) { + ob[key] = value; + } else { + ob.set(key,value); + } +} + +__jsdict_set.NAME = "__jsdict_set"; +__jsdict_set.args_signature = ["ob", "key", "value"]; +__jsdict_set.kwargs_signature = { }; +__jsdict_set.types_signature = { }; +__jsdict_keys = function(ob) { + if (ob instanceof Object) { + return Object.keys( ob ); + } else { + return ob.keys(); + } +} + +__jsdict_keys.NAME = "__jsdict_keys"; +__jsdict_keys.args_signature = ["ob"]; +__jsdict_keys.kwargs_signature = { }; +__jsdict_keys.types_signature = { }; +__jsdict_values = function(ob) { + var arr, value; + if (ob instanceof Object) { + arr = []; + var __iter1 = ob; + if (! (__iter1 instanceof Array) ) { __iter1 = __object_keys__(__iter1) } + for (var __idx1=0; __idx1 < __iter1.length; __idx1++) { + var key = __iter1[ __idx1 ]; + if (ob.hasOwnProperty(key)) { + value = ob[key]; + arr.push(value); + } + } + return arr; + } else { + return ob.values(); + } +} + +__jsdict_values.NAME = "__jsdict_values"; +__jsdict_values.args_signature = ["ob"]; +__jsdict_values.kwargs_signature = { }; +__jsdict_values.types_signature = { }; __object_keys__ = function(ob) { var arr; "\n notes:\n . Object.keys(ob) will not work because we create PythonJS objects using `Object.create(null)`\n . this is different from Object.keys because it traverses the prototype chain.\n "; @@ -403,10 +450,10 @@ __object_keys__.kwargs_signature = { }; __object_keys__.types_signature = { }; __bind_property_descriptors__ = function(o, klass) { var prop, desc; - var __iter1 = klass.__properties__; - if (! (__iter1 instanceof Array) ) { __iter1 = __object_keys__(__iter1) } - for (var __idx1=0; __idx1 < __iter1.length; __idx1++) { - var name = __iter1[ __idx1 ]; + var __iter2 = klass.__properties__; + if (! (__iter2 instanceof Array) ) { __iter2 = __object_keys__(__iter2) } + for (var __idx2=0; __idx2 < __iter2.length; __idx2++) { + var name = __iter2[ __idx2 ]; desc = { "enumerable":true }; prop = klass.__properties__[name]; if (prop["get"]) { @@ -417,10 +464,10 @@ __bind_property_descriptors__ = function(o, klass) { } Object.defineProperty(o, name, desc); } - var __iter2 = klass.__bases__; - if (! (__iter2 instanceof Array) ) { __iter2 = __object_keys__(__iter2) } - for (var __idx2=0; __idx2 < __iter2.length; __idx2++) { - var base = __iter2[ __idx2 ]; + var __iter3 = klass.__bases__; + if (! (__iter3 instanceof Array) ) { __iter3 = __object_keys__(__iter3) } + for (var __idx3=0; __idx3 < __iter3.length; __idx3++) { + var base = __iter3[ __idx3 ]; __bind_property_descriptors__(o, base); } } @@ -470,10 +517,10 @@ create_class = function(class_name, parents, attrs, props) { klass.__all_method_names__ = []; klass.__properties__ = props; klass.__attributes__ = attrs; - var __iter3 = attrs; - if (! (__iter3 instanceof Array) ) { __iter3 = __object_keys__(__iter3) } - for (var __idx3=0; __idx3 < __iter3.length; __idx3++) { - var key = __iter3[ __idx3 ]; + var __iter4 = attrs; + if (! (__iter4 instanceof Array) ) { __iter4 = __object_keys__(__iter4) } + for (var __idx4=0; __idx4 < __iter4.length; __idx4++) { + var key = __iter4[ __idx4 ]; if (( typeof(attrs[key]) ) == "function") { klass.__unbound_methods__[key] = attrs[key]; klass.__all_method_names__.push(key); @@ -485,20 +532,20 @@ create_class = function(class_name, parents, attrs, props) { } klass.__setters__ = []; klass.__getters__ = []; - var __iter4 = klass.__properties__; - if (! (__iter4 instanceof Array) ) { __iter4 = __object_keys__(__iter4) } - for (var __idx4=0; __idx4 < __iter4.length; __idx4++) { - var name = __iter4[ __idx4 ]; + var __iter5 = klass.__properties__; + if (! (__iter5 instanceof Array) ) { __iter5 = __object_keys__(__iter5) } + for (var __idx5=0; __idx5 < __iter5.length; __idx5++) { + var name = __iter5[ __idx5 ]; prop = klass.__properties__[name]; klass.__getters__.push(name); if (prop["set"]) { klass.__setters__.push(name); } } - var __iter5 = klass.__bases__; - if (! (__iter5 instanceof Array) ) { __iter5 = __object_keys__(__iter5) } - for (var __idx5=0; __idx5 < __iter5.length; __idx5++) { - var base = __iter5[ __idx5 ]; + var __iter6 = klass.__bases__; + if (! (__iter6 instanceof Array) ) { __iter6 = __object_keys__(__iter6) } + for (var __idx6=0; __idx6 < __iter6.length; __idx6++) { + var base = __iter6[ __idx6 ]; Array.prototype.push.apply(klass.__getters__, base.__getters__); Array.prototype.push.apply(klass.__setters__, base.__setters__); Array.prototype.push.apply(klass.__all_method_names__, base.__all_method_names__); @@ -511,10 +558,10 @@ create_class = function(class_name, parents, attrs, props) { object.__dict__ = object; has_getattribute = false; has_getattr = false; - var __iter6 = klass.__all_method_names__; - if (! (__iter6 instanceof Array) ) { __iter6 = __object_keys__(__iter6) } - for (var __idx6=0; __idx6 < __iter6.length; __idx6++) { - var name = __iter6[ __idx6 ]; + var __iter7 = klass.__all_method_names__; + if (! (__iter7 instanceof Array) ) { __iter7 = __object_keys__(__iter7) } + for (var __idx7=0; __idx7 < __iter7.length; __idx7++) { + var name = __iter7[ __idx7 ]; if (( name ) == "__getattribute__") { has_getattribute = true; } else { @@ -946,10 +993,10 @@ _setup_str_prototype = function(args, kwargs) { arr = a["$wrapped"]; } i = 0; - var __iter7 = arr; - if (! (__iter7 instanceof Array) ) { __iter7 = __object_keys__(__iter7) } - for (var __idx7=0; __idx7 < __iter7.length; __idx7++) { - var value = __iter7[ __idx7 ]; + var __iter8 = arr; + if (! (__iter8 instanceof Array) ) { __iter8 = __object_keys__(__iter8) } + for (var __idx8=0; __idx8 < __iter8.length; __idx8++) { + var value = __iter8[ __idx8 ]; out += value; i += 1; if (( i ) < arr.length) { @@ -1008,10 +1055,10 @@ _setup_str_prototype = function(args, kwargs) { var func = function() { var digits; digits = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]; - var __iter8 = this; - if (! (__iter8 instanceof Array) ) { __iter8 = __object_keys__(__iter8) } - for (var __idx8=0; __idx8 < __iter8.length; __idx8++) { - var char = __iter8[ __idx8 ]; + var __iter9 = this; + if (! (__iter9 instanceof Array) ) { __iter9 = __object_keys__(__iter9) } + for (var __idx9=0; __idx9 < __iter9.length; __idx9++) { + var char = __iter9[ __idx9 ]; if (Object.hasOwnProperty.call(digits, "__contains__") && digits["__contains__"](char) || Object.hasOwnProperty.call(digits, char) || ( typeof(digits) ) == "string" && digits.__contains__(char)) { /*pass*/ } else { @@ -1162,10 +1209,10 @@ _setup_array_prototype = function(args, kwargs) { func.types_signature = { }; Array.prototype.append = func; var extend = function(self, other) { - var __iter9 = other; - if (! (__iter9 instanceof Array) ) { __iter9 = __object_keys__(__iter9) } - for (var __idx9=0; __idx9 < __iter9.length; __idx9++) { - var obj = __iter9[ __idx9 ]; + var __iter10 = other; + if (! (__iter10 instanceof Array) ) { __iter10 = __object_keys__(__iter10) } + for (var __idx10=0; __idx10 < __iter10.length; __idx10++) { + var obj = __iter10[ __idx10 ]; this.push(obj); } } @@ -1222,10 +1269,10 @@ _setup_array_prototype = function(args, kwargs) { var count = function(obj) { var a; a = 0; - var __iter10 = this; - if (! (__iter10 instanceof Array) ) { __iter10 = __object_keys__(__iter10) } - for (var __idx10=0; __idx10 < __iter10.length; __idx10++) { - var item = __iter10[ __idx10 ]; + var __iter11 = this; + if (! (__iter11 instanceof Array) ) { __iter11 = __object_keys__(__iter11) } + for (var __idx11=0; __idx11 < __iter11.length; __idx11++) { + var item = __iter11[ __idx11 ]; if (( item ) === obj) { a += 1; } @@ -1282,10 +1329,10 @@ _setup_array_prototype = function(args, kwargs) { func.types_signature = { }; Array.prototype.intersection = func; var func = function(other) { - var __iter11 = this; - if (! (__iter11 instanceof Array) ) { __iter11 = __object_keys__(__iter11) } - for (var __idx11=0; __idx11 < __iter11.length; __idx11++) { - var item = __iter11[ __idx11 ]; + var __iter12 = this; + if (! (__iter12 instanceof Array) ) { __iter12 = __object_keys__(__iter12) } + for (var __idx12=0; __idx12 < __iter12.length; __idx12++) { + var item = __iter12[ __idx12 ]; if (( other.indexOf(item) ) == -1) { return false; } @@ -1876,10 +1923,10 @@ __tuple_count = function(args, kwargs) { var self = arguments['self']; var obj = arguments['obj']; a = 0; - var __iter12 = self["$wrapped"]; - if (! (__iter12 instanceof Array) ) { __iter12 = __object_keys__(__iter12) } - for (var __idx12=0; __idx12 < __iter12.length; __idx12++) { - var item = __iter12[ __idx12 ]; + var __iter13 = self["$wrapped"]; + if (! (__iter13 instanceof Array) ) { __iter13 = __object_keys__(__iter13) } + for (var __idx13=0; __idx13 < __iter13.length; __idx13++) { + var item = __iter13[ __idx13 ]; if (( item ) == obj) { a += 1; } @@ -2241,10 +2288,10 @@ __pylist_count = function(args, kwargs) { var self = arguments['self']; var obj = arguments['obj']; a = 0; - var __iter13 = self["$wrapped"]; - if (! (__iter13 instanceof Array) ) { __iter13 = __object_keys__(__iter13) } - for (var __idx13=0; __idx13 < __iter13.length; __idx13++) { - var item = __iter13[ __idx13 ]; + var __iter14 = self["$wrapped"]; + if (! (__iter14 instanceof Array) ) { __iter14 = __object_keys__(__iter14) } + for (var __idx14=0; __idx14 < __iter14.length; __idx14++) { + var item = __iter14[ __idx14 ]; if (( item ) == obj) { a += 1; } @@ -2505,10 +2552,10 @@ __dict___init__ = function(args, kwargs) { } } else { if (isinstance([js_object, list], __NULL_OBJECT__)) { - var __iter14 = js_object["$wrapped"]; - if (! (__iter14 instanceof Array) ) { __iter14 = __object_keys__(__iter14) } - for (var __idx14=0; __idx14 < __iter14.length; __idx14++) { - var item = __iter14[ __idx14 ]; + var __iter15 = js_object["$wrapped"]; + if (! (__iter15 instanceof Array) ) { __iter15 = __object_keys__(__iter15) } + for (var __idx15=0; __idx15 < __iter15.length; __idx15++) { + var item = __iter15[ __idx15 ]; key = item["$wrapped"][0]; value = item["$wrapped"][1]; self["$wrapped"][key] = value; @@ -2764,10 +2811,10 @@ __dict_values = function(args, kwargs) { var self = arguments['self']; keys = Object.keys(self["$wrapped"]); out = []; - var __iter15 = keys; - if (! (__iter15 instanceof Array) ) { __iter15 = __object_keys__(__iter15) } - for (var __idx15=0; __idx15 < __iter15.length; __idx15++) { - var key = __iter15[ __idx15 ]; + var __iter16 = keys; + if (! (__iter16 instanceof Array) ) { __iter16 = __object_keys__(__iter16) } + for (var __idx16=0; __idx16 < __iter16.length; __idx16++) { + var key = __iter16[ __idx16 ]; out.push(self["$wrapped"][key]); } return out; @@ -2868,10 +2915,10 @@ set = function(args, kwargs) { } fallback = false; if (hashtable) { - var __iter16 = a; - if (! (__iter16 instanceof Array) ) { __iter16 = __object_keys__(__iter16) } - for (var __idx16=0; __idx16 < __iter16.length; __idx16++) { - var b = __iter16[ __idx16 ]; + var __iter17 = a; + if (! (__iter17 instanceof Array) ) { __iter17 = __object_keys__(__iter17) } + for (var __idx17=0; __idx17 < __iter17.length; __idx17++) { + var b = __iter17[ __idx17 ]; if (typeof(b, "number") && ( b ) === ( (b | 0) )) { key = (b & mask); hashtable[key] = b; @@ -2886,20 +2933,20 @@ set = function(args, kwargs) { } s = []; if (fallback) { - var __iter17 = a; - if (! (__iter17 instanceof Array) ) { __iter17 = __object_keys__(__iter17) } - for (var __idx17=0; __idx17 < __iter17.length; __idx17++) { - var item = __iter17[ __idx17 ]; + var __iter18 = a; + if (! (__iter18 instanceof Array) ) { __iter18 = __object_keys__(__iter18) } + for (var __idx18=0; __idx18 < __iter18.length; __idx18++) { + var item = __iter18[ __idx18 ]; if (( s.indexOf(item) ) == -1) { s.push(item); } } } else { keys.sort(); - var __iter18 = keys; - if (! (__iter18 instanceof Array) ) { __iter18 = __object_keys__(__iter18) } - for (var __idx18=0; __idx18 < __iter18.length; __idx18++) { - var key = __iter18[ __idx18 ]; + var __iter19 = keys; + if (! (__iter19 instanceof Array) ) { __iter19 = __object_keys__(__iter19) } + for (var __idx19=0; __idx19 < __iter19.length; __idx19++) { + var key = __iter19[ __idx19 ]; s.push(hashtable[key]); } } diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index 8b9b3e5..4184d08 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -1528,6 +1528,16 @@ def visit_Call(self, node): return '__jsdict_get(%s, %s)' %(self.visit(anode.value), ','.join(args) ) else: return '__jsdict_get(%s)' %self.visit(anode.value) + + elif anode.attr == 'set' and len(args)==2: + return '__jsdict_set(%s, %s)' %(self.visit(anode.value), ','.join(args)) + + elif anode.attr == 'keys' and not args: + return '__jsdict_keys(%s)' %self.visit(anode.value) + + elif anode.attr == 'values' and not args: + return '__jsdict_values(%s)' %self.visit(anode.value) + else: a = ','.join(args) return '%s(%s)' %( self.visit(node.func), a ) diff --git a/runtime/builtins.py b/runtime/builtins.py index bbe50b5..e28ec98 100644 --- a/runtime/builtins.py +++ b/runtime/builtins.py @@ -34,6 +34,33 @@ def __jsdict_get(ob, key, default_value=None): ## this works because instances from PythonJS are created using Object.create(null) ## return JS("ob.get(key, default_value)") + def __jsdict_set(ob, key, value): + if instanceof(ob, Object): + ob[ key ] = value + else: ## PythonJS object instance ## + ## this works because instances from PythonJS are created using Object.create(null) ## + JS("ob.set(key,value)") + + def __jsdict_keys(ob): + if instanceof(ob, Object): + return JS("Object.keys( ob )") + else: ## PythonJS object instance ## + ## this works because instances from PythonJS are created using Object.create(null) ## + return JS("ob.keys()") + + def __jsdict_values(ob): + if instanceof(ob, Object): + arr = [] + for key in ob: + if ob.hasOwnProperty(key): + value = ob[key] + arr.push( value ) + return arr + else: ## PythonJS object instance ## + ## this works because instances from PythonJS are created using Object.create(null) ## + return JS("ob.values()") + + def __object_keys__(ob): ''' notes: diff --git a/tests/test_dict_methods.html b/tests/test_dict_methods.html index 01195ff..e803bd6 100644 --- a/tests/test_dict_methods.html +++ b/tests/test_dict_methods.html @@ -42,6 +42,10 @@ j = {a:1, b:2, get:'not-a-method'} xx = j.get('c', '.get in javascript mode works') print xx + jkeys = j.keys() + print 'keys in javascript mode', jkeys + j.set('ZZZ', 'my value') + print j.values() xxx = j.get('c', '.get on jsob works from python mode') print xxx @@ -49,6 +53,7 @@ print j['get'] j['get'] = 'XXX' print j['get'] + print j['ZZZ'] From e1acde3ddb42dece39b1472bdcd874ba8f5083c2 Mon Sep 17 00:00:00 2001 From: hartsantler Date: Fri, 10 Jan 2014 02:20:09 -0800 Subject: [PATCH 059/521] js-object/dict allow: "keys" and "values" methods to be called from python mode on a js-object. --- pythonjs/python_to_pythonjs.py | 10 +++++++++- tests/test_dict_methods.html | 2 ++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index 4184d08..d3d0f42 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -1643,13 +1643,21 @@ def visit_Call(self, node): # else: # return '%s()' %name - if isinstance(node.func, ast.Attribute) and node.func.attr == 'get': ## special method calls + ## special method calls ## + if isinstance(node.func, ast.Attribute) and node.func.attr in ('get', 'keys', 'values'): anode = node.func if anode.attr == 'get': if args: return '__jsdict_get(%s, %s)' %(self.visit(anode.value), args ) else: return '__jsdict_get(%s)' %self.visit(anode.value) + + elif anode.attr == 'keys' and not args: + return '__jsdict_keys(%s)' %self.visit(anode.value) + + elif anode.attr == 'values' and not args: + return '__jsdict_values(%s)' %self.visit(anode.value) + else: a = ','.join(args) return '%s(%s)' %( self.visit(node.func), a ) diff --git a/tests/test_dict_methods.html b/tests/test_dict_methods.html index e803bd6..410e444 100644 --- a/tests/test_dict_methods.html +++ b/tests/test_dict_methods.html @@ -54,6 +54,8 @@ j['get'] = 'XXX' print j['get'] print j['ZZZ'] + print j.values() + print j.keys() From 0a728658f71630c08e149eb2735b942e22e9b7fb Mon Sep 17 00:00:00 2001 From: hartsantler Date: Fri, 10 Jan 2014 02:50:33 -0800 Subject: [PATCH 060/521] js-object/dict: allow "pop" method on js-object, and allow "len" function to work on js-object. --- pythonjs.js | 50 ++++++++++++++++++++++++++++------ pythonjs/python_to_pythonjs.py | 17 ++++++++++-- runtime/builtins.py | 24 ++++++++++++++-- tests/test_dict_methods.html | 3 ++ 4 files changed, 80 insertions(+), 14 deletions(-) diff --git a/pythonjs.js b/pythonjs.js index ee67d80..b6a9770 100644 --- a/pythonjs.js +++ b/pythonjs.js @@ -1,4 +1,4 @@ -// PythonJS Runtime - regenerated on: Thu Jan 9 11:07:13 2014 +// PythonJS Runtime - regenerated on: Fri Jan 10 02:49:27 2014 __NULL_OBJECT__ = Object.create(null); if (( "window" ) in this && ( "document" ) in this) { __NODEJS__ = false; @@ -436,6 +436,30 @@ __jsdict_values.NAME = "__jsdict_values"; __jsdict_values.args_signature = ["ob"]; __jsdict_values.kwargs_signature = { }; __jsdict_values.types_signature = { }; +__jsdict_pop = function(ob, key, _default) { + var v; + if (_default == undefined) _default = undefined; + if (ob instanceof Object) { + if (key in ob) { + v = ob[key]; + delete ob[key]; + return v; + } else { + if (( _default ) === undefined) { + throw KeyError; + } else { + return _default; + } + } + } else { + return ob.pop(key, _default); + } +} + +__jsdict_pop.NAME = "__jsdict_pop"; +__jsdict_pop.args_signature = ["ob", "key", "_default"]; +__jsdict_pop.kwargs_signature = { _default:undefined }; +__jsdict_pop.types_signature = { _default:"None" }; __object_keys__ = function(ob) { var arr; "\n notes:\n . Object.keys(ob) will not work because we create PythonJS objects using `Object.create(null)`\n . this is different from Object.keys because it traverses the prototype chain.\n "; @@ -1445,14 +1469,22 @@ len = function(args, kwargs) { kwargs = Object(); } var signature, arguments; - signature = {"kwargs": Object(), "args": __create_array__("obj")}; + signature = {"kwargs": Object(), "args": __create_array__("ob")}; arguments = get_arguments(signature, args, kwargs); - var obj = arguments['obj']; - return __get__(__get__(obj, "__len__"), "__call__")(); + var ob = arguments['ob']; + if (ob instanceof Array) { + return ob.length; + } else { + if (ob instanceof Object) { + return Object.keys(ob).length; + } else { + return __get__(__get__(ob, "__len__"), "__call__")(); + } + } } len.NAME = "len"; -len.args_signature = ["obj"]; +len.args_signature = ["ob"]; len.kwargs_signature = { }; len.types_signature = { }; len.pythonscript_function = true; @@ -2244,7 +2276,7 @@ __pylist_pop = function(args, kwargs) { signature = {"kwargs": Object(), "args": __create_array__("self")}; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; - return self["$wrapped"].pop(); + return __jsdict_pop(self["$wrapped"]); } __pylist_pop.NAME = "__pylist_pop"; @@ -2585,7 +2617,7 @@ __dict_jsify = function(args, kwargs) { signature = {"kwargs": Object(), "args": __create_array__("self")}; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; - keys = __get__(__get__(Object, "keys"), "__call__")([self["$wrapped"]], __NULL_OBJECT__); + keys = __get__(Object, "keys")(self["$wrapped"]); var __iterator__, key; __iterator__ = __get__(__get__(keys, "__iter__"), "__call__")([], Object()); var __next__; @@ -2864,7 +2896,7 @@ __dict___iter__ = function(args, kwargs) { signature = {"kwargs": Object(), "args": __create_array__("self")}; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; - return __get__(Iterator, "__call__")([__get__(__get__(self, "keys"), "__call__")(), 0], __NULL_OBJECT__); + return __get__(Iterator, "__call__")([__jsdict_keys(self), 0], __NULL_OBJECT__); } __dict___iter__.NAME = "__dict___iter__"; @@ -3522,7 +3554,7 @@ _to_json = function(args, kwargs) { ; r = Object(); ; - __iterator__ = __get__(__get__(__get__(__get__(pythonjs, "keys"), "__call__")(), "__iter__"), "__call__")([], Object()); + __iterator__ = __get__(__get__(__jsdict_keys(pythonjs), "__iter__"), "__call__")([], Object()); ; __next__ = __get__(__iterator__, "next_fast"); while(( __iterator__.index ) < __iterator__.length) { diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index d3d0f42..d339d49 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -1538,6 +1538,12 @@ def visit_Call(self, node): elif anode.attr == 'values' and not args: return '__jsdict_values(%s)' %self.visit(anode.value) + elif anode.attr == 'pop': + if args: + return '__jsdict_pop(%s, %s)' %(self.visit(anode.value), ','.join(args) ) + else: + return '__jsdict_pop(%s)' %self.visit(anode.value) + else: a = ','.join(args) return '%s(%s)' %( self.visit(node.func), a ) @@ -1644,7 +1650,7 @@ def visit_Call(self, node): # return '%s()' %name ## special method calls ## - if isinstance(node.func, ast.Attribute) and node.func.attr in ('get', 'keys', 'values'): + if isinstance(node.func, ast.Attribute) and node.func.attr in ('get', 'keys', 'values', 'pop'): anode = node.func if anode.attr == 'get': if args: @@ -1658,9 +1664,14 @@ def visit_Call(self, node): elif anode.attr == 'values' and not args: return '__jsdict_values(%s)' %self.visit(anode.value) + elif anode.attr == 'pop': + if args: + return '__jsdict_pop(%s, %s)' %(self.visit(anode.value), args ) + else: + return '__jsdict_pop(%s)' %self.visit(anode.value) + else: - a = ','.join(args) - return '%s(%s)' %( self.visit(node.func), a ) + return '%s(%s)' %( self.visit(node.func), args ) elif isinstance(node.func, ast.Attribute) and isinstance(node.func.value, Name) and node.func.value.id in self._func_typedefs: type = self._func_typedefs[ node.func.value.id ] diff --git a/runtime/builtins.py b/runtime/builtins.py index e28ec98..b22de39 100644 --- a/runtime/builtins.py +++ b/runtime/builtins.py @@ -60,6 +60,19 @@ def __jsdict_values(ob): ## this works because instances from PythonJS are created using Object.create(null) ## return JS("ob.values()") + def __jsdict_pop(ob, key, _default=None): + if instanceof(ob, Object): + if JS("key in ob"): + v = ob[key] + JS("delete ob[key]") + return v + elif _default is None: + raise KeyError + else: + return _default + else: ## PythonJS object instance ## + ## this works because instances from PythonJS are created using Object.create(null) ## + return JS("ob.pop(key, _default)") def __object_keys__(ob): ''' @@ -533,8 +546,15 @@ class StopIteration: pass -def len(obj): - return obj.__len__() +def len(ob): + if instanceof(ob, Array): + with javascript: + return ob.length + elif instanceof(ob, Object): + with javascript: + return Object.keys(ob).length + else: + return ob.__len__() def next(obj): diff --git a/tests/test_dict_methods.html b/tests/test_dict_methods.html index 410e444..041231d 100644 --- a/tests/test_dict_methods.html +++ b/tests/test_dict_methods.html @@ -46,6 +46,8 @@ print 'keys in javascript mode', jkeys j.set('ZZZ', 'my value') print j.values() + print "1==pop('a')", j.pop( 'a' ) + print "len(j)", len(j) xxx = j.get('c', '.get on jsob works from python mode') print xxx @@ -54,6 +56,7 @@ j['get'] = 'XXX' print j['get'] print j['ZZZ'] + print '2==pop("b")', j.pop( 'b' ) print j.values() print j.keys() From 05e79bf3ab18a037368a4501c835fe3b6211caf6 Mon Sep 17 00:00:00 2001 From: hartsantler Date: Fri, 10 Jan 2014 17:54:24 -0800 Subject: [PATCH 061/521] fixed init dict from list comprehension and Array's of two item sub-arrays. --- pythonjs.js | 35 ++++++++++++---------------- runtime/builtins.py | 43 ++++++++++++++++++++++------------- tests/test_dict_advanced.html | 12 ++++++---- 3 files changed, 48 insertions(+), 42 deletions(-) diff --git a/pythonjs.js b/pythonjs.js index b6a9770..ab2a960 100644 --- a/pythonjs.js +++ b/pythonjs.js @@ -1,4 +1,4 @@ -// PythonJS Runtime - regenerated on: Fri Jan 10 02:49:27 2014 +// PythonJS Runtime - regenerated on: Fri Jan 10 17:49:00 2014 __NULL_OBJECT__ = Object.create(null); if (( "window" ) in this && ( "document" ) in this) { __NODEJS__ = false; @@ -2560,7 +2560,7 @@ __dict_attrs = Object(); __dict_parents = []; __dict_properties = Object(); __dict___init__ = function(args, kwargs) { - var i, value, key; + var ob; if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { @@ -2574,27 +2574,20 @@ __dict___init__ = function(args, kwargs) { var js_object = arguments['js_object']; self["$wrapped"] = { }; if (js_object) { - if (js_object instanceof Array) { - i = 0; - while(( i ) < __get__(js_object, "length")) { - var key = js_object[i]["key"]; - var value = js_object[i]["value"]; - __get__(__get__(self, "set"), "__call__")([key, value], __NULL_OBJECT__); - i += 1; - } - } else { - if (isinstance([js_object, list], __NULL_OBJECT__)) { - var __iter15 = js_object["$wrapped"]; - if (! (__iter15 instanceof Array) ) { __iter15 = __object_keys__(__iter15) } - for (var __idx15=0; __idx15 < __iter15.length; __idx15++) { - var item = __iter15[ __idx15 ]; - key = item["$wrapped"][0]; - value = item["$wrapped"][1]; - self["$wrapped"][key] = value; + ob = js_object; + if (ob instanceof Array) { + var __iter15 = ob; + if (! (__iter15 instanceof Array) ) { __iter15 = __object_keys__(__iter15) } + for (var __idx15=0; __idx15 < __iter15.length; __idx15++) { + var o = __iter15[ __idx15 ]; + if (o instanceof Array) { + self.__setitem__(o[0], o[1]); + } else { + self.__setitem__(o["key"], o["value"]); } - } else { - self["$wrapped"] = js_object; } + } else { + console.log(["TODO init dict from:", js_object]); } } } diff --git a/runtime/builtins.py b/runtime/builtins.py index b22de39..7260bb8 100644 --- a/runtime/builtins.py +++ b/runtime/builtins.py @@ -831,22 +831,33 @@ def __init__(self, js_object=None): self[...] = {} if js_object: - if JS("js_object instanceof Array"): - i = 0 - while i < js_object.length: - JS('var key = js_object[i]["key"]') - JS('var value = js_object[i]["value"]') - self.set(key, value) - i += 1 - - elif isinstance(js_object, list): - with javascript: - for item in js_object[...]: - key = item[...][0] - value = item[...][1] - self[...][ key ] = value - else: ## TODO - deprecate - self[...] = js_object + #if JS("js_object instanceof Array"): + # i = 0 + # while i < js_object.length: + # JS('var key = js_object[i]["key"]') + # JS('var value = js_object[i]["value"]') + # self.set(key, value) + # i += 1 + + #elif isinstance(js_object, list): + # with javascript: + # for item in js_object[...]: + # key = item[...][0] + # value = item[...][1] + # self[...][ key ] = value + #else: ## TODO - deprecate + # self[...] = js_object + ob = js_object + with javascript: + if instanceof(ob, Array): + for o in ob: + if instanceof(o, Array): + self.__setitem__( o[0], o[1] ) + else: + self.__setitem__( o['key'], o['value'] ) + + else: + print('TODO init dict from:', js_object) def jsify(self): keys = Object.keys( self[...] ) diff --git a/tests/test_dict_advanced.html b/tests/test_dict_advanced.html index d966f06..a236023 100644 --- a/tests/test_dict_advanced.html +++ b/tests/test_dict_advanced.html @@ -14,11 +14,11 @@ def test(): - global d, k1, k2, g + global a, d, k1, k2, g k1 = Key1() k2 = Key2() - + print('testing objects as dict keys') d = { k1:'k1 instance', k2:'k2 instance', @@ -26,11 +26,13 @@ Key2: 'K2 class', Key1(): 'lost instance!' } + print('dict created') print d[k1] print d[k2] print d[Key1] print d[Key2] - print d['@4'] ## this is cheating! + print d['4'] ## this is cheating! + print( 'dict with object keys OK') print d.get('get default', 'My Default') print 'this should be undefined:', d.get('get undefined') @@ -46,8 +48,8 @@ print 'testing dict init from gen' g = dict( (a[i], i) for i in xrange(len(a)) ) - print g.keys()[...] - print g.values()[...] + print g.keys() + print g.values() From fb7744a420cba6428186f21319ea05cf4adf349f Mon Sep 17 00:00:00 2001 From: hartsantler Date: Fri, 10 Jan 2014 18:31:22 -0800 Subject: [PATCH 062/521] new dict methods: copy, clear, has_key, update, and items. --- pythonjs.js | 193 +++++++++++++++++++++++++++++----- runtime/builtins.py | 67 +++++++----- tests/test_dict_advanced.html | 25 +++++ 3 files changed, 233 insertions(+), 52 deletions(-) diff --git a/pythonjs.js b/pythonjs.js index ab2a960..badfaf5 100644 --- a/pythonjs.js +++ b/pythonjs.js @@ -1,4 +1,4 @@ -// PythonJS Runtime - regenerated on: Fri Jan 10 17:49:00 2014 +// PythonJS Runtime - regenerated on: Fri Jan 10 18:27:49 2014 __NULL_OBJECT__ = Object.create(null); if (( "window" ) in this && ( "document" ) in this) { __NODEJS__ = false; @@ -2560,7 +2560,7 @@ __dict_attrs = Object(); __dict_parents = []; __dict_properties = Object(); __dict___init__ = function(args, kwargs) { - var ob; + var ob, value; if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { @@ -2576,18 +2576,32 @@ __dict___init__ = function(args, kwargs) { if (js_object) { ob = js_object; if (ob instanceof Array) { - var __iter15 = ob; - if (! (__iter15 instanceof Array) ) { __iter15 = __object_keys__(__iter15) } - for (var __idx15=0; __idx15 < __iter15.length; __idx15++) { - var o = __iter15[ __idx15 ]; + var __iterator__, o; + __iterator__ = __get__(__get__(ob, "__iter__"), "__call__")([], Object()); + var __next__; + __next__ = __get__(__iterator__, "next_fast"); + while(( __iterator__.index ) < __iterator__.length) { + o = __next__(); if (o instanceof Array) { - self.__setitem__(o[0], o[1]); + __get__(__get__(self, "__setitem__"), "__call__")([__get__(o, "__getitem__")([0], Object()), __get__(o, "__getitem__")([1], Object())], __NULL_OBJECT__); } else { - self.__setitem__(o["key"], o["value"]); + __get__(__get__(self, "__setitem__"), "__call__")([__get__(o, "__getitem__")(["key"], Object()), __get__(o, "__getitem__")(["value"], Object())], __NULL_OBJECT__); } } } else { - console.log(["TODO init dict from:", js_object]); + if (isinstance([ob, dict], __NULL_OBJECT__)) { + var key; + __iterator__ = __get__(__get__(__jsdict_keys(ob), "__iter__"), "__call__")([], Object()); + ; + __next__ = __get__(__iterator__, "next_fast"); + while(( __iterator__.index ) < __iterator__.length) { + key = __next__(); + value = __get__(ob, "__getitem__")([key], Object()); + __get__(__get__(self, "__setitem__"), "__call__")([key, value], __NULL_OBJECT__); + } + } else { + console.log(["TODO init dict from:", js_object]); + } } } } @@ -2633,6 +2647,135 @@ __dict_jsify.kwargs_signature = { }; __dict_jsify.types_signature = { }; __dict_jsify.pythonscript_function = true; __dict_attrs["jsify"] = __dict_jsify; +__dict_copy = function(args, kwargs) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { + /*pass*/ + } else { + args = Array.prototype.slice.call(arguments); + kwargs = Object(); + } + var signature, arguments; + signature = {"kwargs": Object(), "args": __create_array__("self")}; + arguments = get_arguments(signature, args, kwargs); + var self = arguments['self']; + return __get__(dict, "__call__")([self], __NULL_OBJECT__); +} + +__dict_copy.NAME = "__dict_copy"; +__dict_copy.args_signature = ["self"]; +__dict_copy.kwargs_signature = { }; +__dict_copy.types_signature = { }; +__dict_copy.return_type = "dict"; +__dict_copy.pythonscript_function = true; +__dict_attrs["copy"] = __dict_copy; +__dict_clear = function(args, kwargs) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { + /*pass*/ + } else { + args = Array.prototype.slice.call(arguments); + kwargs = Object(); + } + var signature, arguments; + signature = {"kwargs": Object(), "args": __create_array__("self")}; + arguments = get_arguments(signature, args, kwargs); + var self = arguments['self']; + self["$wrapped"] = { }; +} + +__dict_clear.NAME = "__dict_clear"; +__dict_clear.args_signature = ["self"]; +__dict_clear.kwargs_signature = { }; +__dict_clear.types_signature = { }; +__dict_clear.pythonscript_function = true; +__dict_attrs["clear"] = __dict_clear; +__dict_has_key = function(args, kwargs) { + var __dict, key; + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { + /*pass*/ + } else { + args = Array.prototype.slice.call(arguments); + kwargs = Object(); + } + var signature, arguments; + signature = {"kwargs": Object(), "args": __create_array__("self", "key")}; + arguments = get_arguments(signature, args, kwargs); + var self = arguments['self']; + var key = arguments['key']; + __dict = self["$wrapped"]; + if (typeof(key) === 'object' || typeof(key) === 'function') { + key = __get__(key, "__uid__"); + } + if (key in __dict) { + return true; + } else { + return false; + } +} + +__dict_has_key.NAME = "__dict_has_key"; +__dict_has_key.args_signature = ["self", "key"]; +__dict_has_key.kwargs_signature = { }; +__dict_has_key.types_signature = { }; +__dict_has_key.pythonscript_function = true; +__dict_attrs["has_key"] = __dict_has_key; +__dict_update = function(args, kwargs) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { + /*pass*/ + } else { + args = Array.prototype.slice.call(arguments); + kwargs = Object(); + } + var signature, arguments; + signature = {"kwargs": Object(), "args": __create_array__("self", "other")}; + arguments = get_arguments(signature, args, kwargs); + var self = arguments['self']; + var other = arguments['other']; + var __iterator__, key; + __iterator__ = __get__(__get__(other, "__iter__"), "__call__")([], Object()); + var __next__; + __next__ = __get__(__iterator__, "next_fast"); + while(( __iterator__.index ) < __iterator__.length) { + key = __next__(); + __get__(__get__(self, "__setitem__"), "__call__")([key, __get__(other, "__getitem__")([key], Object())], __NULL_OBJECT__); + } +} + +__dict_update.NAME = "__dict_update"; +__dict_update.args_signature = ["self", "other"]; +__dict_update.kwargs_signature = { }; +__dict_update.types_signature = { }; +__dict_update.pythonscript_function = true; +__dict_attrs["update"] = __dict_update; +__dict_items = function(args, kwargs) { + var arr; + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { + /*pass*/ + } else { + args = Array.prototype.slice.call(arguments); + kwargs = Object(); + } + var signature, arguments; + signature = {"kwargs": Object(), "args": __create_array__("self")}; + arguments = get_arguments(signature, args, kwargs); + var self = arguments['self']; + arr = []; + var __iterator__, key; + __iterator__ = __get__(__get__(__jsdict_keys(self), "__iter__"), "__call__")([], Object()); + var __next__; + __next__ = __get__(__iterator__, "next_fast"); + while(( __iterator__.index ) < __iterator__.length) { + key = __next__(); + __get__(__get__(arr, "append"), "__call__")([[key, __get__(self, "__getitem__")([key], Object())]], __NULL_OBJECT__); + } + return arr; +} + +__dict_items.NAME = "__dict_items"; +__dict_items.args_signature = ["self"]; +__dict_items.kwargs_signature = { }; +__dict_items.types_signature = { }; +__dict_items.pythonscript_function = true; +__dict_attrs["items"] = __dict_items; __dict_get = function(args, kwargs) { if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ @@ -2836,10 +2979,10 @@ __dict_values = function(args, kwargs) { var self = arguments['self']; keys = Object.keys(self["$wrapped"]); out = []; - var __iter16 = keys; - if (! (__iter16 instanceof Array) ) { __iter16 = __object_keys__(__iter16) } - for (var __idx16=0; __idx16 < __iter16.length; __idx16++) { - var key = __iter16[ __idx16 ]; + var __iter15 = keys; + if (! (__iter15 instanceof Array) ) { __iter15 = __object_keys__(__iter15) } + for (var __idx15=0; __idx15 < __iter15.length; __idx15++) { + var key = __iter15[ __idx15 ]; out.push(self["$wrapped"][key]); } return out; @@ -2940,10 +3083,10 @@ set = function(args, kwargs) { } fallback = false; if (hashtable) { - var __iter17 = a; - if (! (__iter17 instanceof Array) ) { __iter17 = __object_keys__(__iter17) } - for (var __idx17=0; __idx17 < __iter17.length; __idx17++) { - var b = __iter17[ __idx17 ]; + var __iter16 = a; + if (! (__iter16 instanceof Array) ) { __iter16 = __object_keys__(__iter16) } + for (var __idx16=0; __idx16 < __iter16.length; __idx16++) { + var b = __iter16[ __idx16 ]; if (typeof(b, "number") && ( b ) === ( (b | 0) )) { key = (b & mask); hashtable[key] = b; @@ -2958,20 +3101,20 @@ set = function(args, kwargs) { } s = []; if (fallback) { - var __iter18 = a; - if (! (__iter18 instanceof Array) ) { __iter18 = __object_keys__(__iter18) } - for (var __idx18=0; __idx18 < __iter18.length; __idx18++) { - var item = __iter18[ __idx18 ]; + var __iter17 = a; + if (! (__iter17 instanceof Array) ) { __iter17 = __object_keys__(__iter17) } + for (var __idx17=0; __idx17 < __iter17.length; __idx17++) { + var item = __iter17[ __idx17 ]; if (( s.indexOf(item) ) == -1) { s.push(item); } } } else { keys.sort(); - var __iter19 = keys; - if (! (__iter19 instanceof Array) ) { __iter19 = __object_keys__(__iter19) } - for (var __idx19=0; __idx19 < __iter19.length; __idx19++) { - var key = __iter19[ __idx19 ]; + var __iter18 = keys; + if (! (__iter18 instanceof Array) ) { __iter18 = __object_keys__(__iter18) } + for (var __idx18=0; __idx18 < __iter18.length; __idx18++) { + var key = __iter18[ __idx18 ]; s.push(hashtable[key]); } } diff --git a/runtime/builtins.py b/runtime/builtins.py index 7260bb8..6625716 100644 --- a/runtime/builtins.py +++ b/runtime/builtins.py @@ -831,33 +831,19 @@ def __init__(self, js_object=None): self[...] = {} if js_object: - #if JS("js_object instanceof Array"): - # i = 0 - # while i < js_object.length: - # JS('var key = js_object[i]["key"]') - # JS('var value = js_object[i]["value"]') - # self.set(key, value) - # i += 1 - - #elif isinstance(js_object, list): - # with javascript: - # for item in js_object[...]: - # key = item[...][0] - # value = item[...][1] - # self[...][ key ] = value - #else: ## TODO - deprecate - # self[...] = js_object ob = js_object - with javascript: - if instanceof(ob, Array): - for o in ob: - if instanceof(o, Array): - self.__setitem__( o[0], o[1] ) - else: - self.__setitem__( o['key'], o['value'] ) - - else: - print('TODO init dict from:', js_object) + if instanceof(ob, Array): + for o in ob: + if instanceof(o, Array): + self.__setitem__( o[0], o[1] ) + else: + self.__setitem__( o['key'], o['value'] ) + elif isinstance(ob, dict): + for key in ob.keys(): + value = ob[ key ] + self.__setitem__( key, value ) + else: + print('TODO init dict from:', js_object) def jsify(self): keys = Object.keys( self[...] ) @@ -868,13 +854,40 @@ def jsify(self): self[...][key] = value.jsify() return self[...] + def copy(self): + return dict( self ) + + def clear(self): + with javascript: + self[...] = {} + + def has_key(self, key): + __dict = self[...] + if JS("typeof(key) === 'object' || typeof(key) === 'function'"): + # Test undefined because it can be in the dict + key = key.__uid__ + + if JS("key in __dict"): + return True + else: + return False + + def update(self, other): + for key in other: + self.__setitem__( key, other[key] ) + + def items(self): + arr = [] + for key in self.keys(): + arr.append( [key, self[key]] ) + return arr + def get(self, key, _default=None): try: return self[key] except: return _default - def set(self, key, value): self.__setitem__(key, value) diff --git a/tests/test_dict_advanced.html b/tests/test_dict_advanced.html index a236023..9245366 100644 --- a/tests/test_dict_advanced.html +++ b/tests/test_dict_advanced.html @@ -51,6 +51,31 @@ print g.keys() print g.values() + print 'testing init dict from dict' + g2 = dict( g ) + print g2.keys() + print g2.values() + + print 'testing dict copy' + g3 = g2.copy() + print g3.keys() + print g3.values() + + print 'testing has_key' + print g3.has_key('h') + + print 'testing update from other dict' + g3.update( d ) + print g3.keys() + print g3.values() + + print 'testing dict items' + print g3.items() + + print g3[ Key1 ] + print g3[ Key2 ] + print g3.has_key( Key1 ) + From 39e4ed9cc79759247e6833cbe979904c6251b8e0 Mon Sep 17 00:00:00 2001 From: hartsantler Date: Sat, 11 Jan 2014 15:18:51 -0800 Subject: [PATCH 063/521] fixed translating Brython's attribute assignment "self.xxx = XXX" to normal Python AST. --- bindings/ast.py | 9 ++++++++- tests/test_AST.html | 6 +++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/bindings/ast.py b/bindings/ast.py index 494fcd8..9ddda8c 100644 --- a/bindings/ast.py +++ b/bindings/ast.py @@ -10,7 +10,14 @@ def brython_tokenize(src): class Assign: def _collect_targets(self, ctx): if ctx.type == 'expr' and ctx.name == 'id': - self.targets.append( Name(ctx.tree[0]) ) + a = ctx.tree[0] + if a.type == 'id': + self.targets.append( Name(ctx.tree[0]) ) + elif a.type == 'attribute' and a.func == 'getattr' and a.value.type == 'id': + self.targets.append( Attribute(a,None) ) + else: + raise TypeError + elif ctx.type == 'assign': self._collect_targets( ctx.tree[0] ) self._collect_targets( ctx.tree[1] ) diff --git a/tests/test_AST.html b/tests/test_AST.html index 7949646..69e59c0 100644 --- a/tests/test_AST.html +++ b/tests/test_AST.html @@ -28,10 +28,10 @@ class A(X,Y): def method1(self, x,y,z): - w = x+y#+z + w = x+y+z return w def method2(self, XXX): - #self.xxx = XXX ## TODO fixme + self.xxx = XXX ## TODO fixme a = b = c = x = y = z = 1 if 1: @@ -53,7 +53,7 @@ class DebugVisitor( NodeVisitor ): def visit_IfExp(self, node): - print 'if ', self.visit(node.test) + print 'if ', self.visit(node.test), ':' for a in node.body: self.visit(a) From b848f17db1cfb8e668733b6519f1cec677d16da5 Mon Sep 17 00:00:00 2001 From: Thierry EXCOFFIER Date: Sat, 11 Jan 2014 22:41:00 +0100 Subject: [PATCH 064/521] Add a regression test framework --- regtests/dict/init.py | 14 +++ regtests/dict/item.py | 18 +++ regtests/run.py | 242 +++++++++++++++++++++++++++++++++++++++ regtests/str/specials.py | 8 ++ 4 files changed, 282 insertions(+) create mode 100644 regtests/dict/init.py create mode 100644 regtests/dict/item.py create mode 100755 regtests/run.py create mode 100644 regtests/str/specials.py diff --git a/regtests/dict/init.py b/regtests/dict/init.py new file mode 100644 index 0000000..52d0497 --- /dev/null +++ b/regtests/dict/init.py @@ -0,0 +1,14 @@ +"""Defined with {}""" +def f(): + pass +class G(object): + def __init__(self): + """XXX: Without __init__ the translation with javascript fail""" + pass +g = G() +a = {'2': 22, 3:33, f:44, G:55, g:66} +Error(a['2'] == 22) +Error(a[3] == 33) +Warning(a[f] == 44) +Warning(a[G] == 55) +Warning(a[g] == 66) diff --git a/regtests/dict/item.py b/regtests/dict/item.py new file mode 100644 index 0000000..a5c95c1 --- /dev/null +++ b/regtests/dict/item.py @@ -0,0 +1,18 @@ +"""__getitem__""" +def f(): + pass +class G(object): + def __init__(self): + """XXX: Without __init__ the translation with javascript fail""" + pass +g = G() +a = {'2': 22, 3:33} +a[f] = 44 +a[g] = 66 +a[G] = 55 +Error(a['2'] == 22) +Error(a[3] == 33) +Error(a[f] == 44) +Error(a[G] == 55) +Error(a[g] == 66) + diff --git a/regtests/run.py b/regtests/run.py new file mode 100755 index 0000000..8fe609f --- /dev/null +++ b/regtests/run.py @@ -0,0 +1,242 @@ +#!/usr/bin/env python3 + +""" +Without argument: run all the regression tests. + +About the tests: + + * They are stored as python file in the subdirectories. + * The firstline must be an explanation about the test. + * Errors(must be True) defines an Error that must be corrected + * Warning(must be True) defines something that should be corrected + once corrected, must be redefined as an Error + +""" + +import os +import re +import sys +import tempfile + +tmpname = os.path.join(tempfile.gettempdir(), "xxx_regtest") + +print("Temporary files are stored into '%s...'" % tmpname) +print() + +show_details = len(sys.argv) > 1 + +# List of valid filenames in the parameters +argv = [os.path.abspath(name) + for name in sys.argv[1:] + if os.path.exists(name) + ] + +if show_details: + display_errors = "" +else: + display_errors = "2>/dev/null" + +def files(): + """All the filenames of the regression tests""" + for dirpath, dirnames, filenames in os.walk('.'): + if dirpath == '.': + continue + for filename in filenames: + if filename.endswith(".py"): + yield dirpath + os.path.sep + filename + +def read(filename): + """Returns the file content as a string""" + f = open(filename) + content = f.read() + f.close() + return content + +def write(filename, content): + """Write the content into the file""" + f = open(filename, "w") + f.write(content) + f.close() + +def run_command(command, returns_stdout_stderr=False): + """Returns the number of problems""" + f = os.popen(command + " 2>%s.errors" % tmpname, 'r') + stdout = f.read().strip() + f.close() + + stderr = read("%s.errors" % tmpname) + if stderr: + if show_details: + print(stderr) + if returns_stdout_stderr: + return stdout, stderr + if stdout: + if show_details: + print(stdout) + + errors = stdout + stderr + + d = {} + x = errors.count("Error fail") + if x: + d['Error'] = x + x = errors.count("Warning fail") + if x: + d['Warning'] = x + if len(d) == 0 and errors != '': + if '.py", line' in errors: + d["Syntax Error Python"] = 1 + else: + d["?"] = 1 + + return d + +def patch_assert(filename): + """Patch the regression tests to add information into asserts""" + out = [] + for i, line in enumerate(read(filename).split('\n')): + out.append(re.sub("(Error|Warning)\((.*)\)", + r'\1("%s",%d,\2,"\2")' % (filename, i), + line) + ) + return '\n'.join(out) + +def patch_python(filename): + """Rewrite the Python code""" + return ("""# -*- coding: utf-8 -*- +def Error(file, line, result, test): + if not result: + print(file + ":" + str(line) + " Error fail " + test) +def Warning(file, line, result, test): + if not result: + print(file + ":" + str(line) + " Warning fail " + test) +""" + + patch_assert(filename)) + +def run_python_test_on(filename): + """Python tests""" + write("%s.py" % tmpname, patch_python(filename)) + return run_command("python %s.py %s" % (tmpname, display_errors)) + +def run_python3_test_on(filename): + """Python3 tests""" + write("%s.py" % tmpname, patch_python(filename)) + return run_command("python3 %s.py %s" % (tmpname, display_errors)) + +def run_pythonjs_test(filename): + """run tests""" + stdout, stderr = run_command(os.path.join("..", "pythonjs", + "translator.py") + + ' ' + filename, + returns_stdout_stderr=True) + if stderr: + return {'Translation error':1} + else: + return run_js(stdout) + +def run_pythonjs_test_on(filename): + """JS PythonJS tests""" + write("%s.py" % tmpname, patch_python(filename)) + return run_pythonjs_test("%s.py" % tmpname) + +def run_pythonjsjs_test_on(filename): + """JSJS PythonJS with javascript tests""" + write("%s.py" % tmpname, + 'pythonjs.configure(javascript=True)\n' + + patch_python(filename)) + return run_pythonjs_test("%s.py" % tmpname) + +def run_js(content): + """Run Javascript using Rhino""" + builtins = read(os.path.join("..", "pythonjs.js")) + # Patch in order to run Rhino + builtins = builtins.replace('Object.create(null)', '{}', 1) + # Add the program to test + content = builtins + content + # Remove documentation strings from JavaScript (Rhino don't like) + content = re.sub('^ *".*" *$', '', content) + # Add the console for Rhino + content = ''' +console = { log: print } ; +process = { title:"", version:"" } ; +''' + content + write("%s.js" % tmpname, content) + return run_command("rhino -O -1 %s.js" % tmpname) + +table_header = "%-20.20s %-30.30s" +table_cell = '%-8.8s' + +def run_test_on(filename): + """run one test and returns the number of errors""" + if not show_details: + f = open(filename) + comment = f.readline().strip(" \n\"'") + f.close() + print(table_header % (filename[2:-3], comment), end='') + sum_errors = {} + def display(function): + if show_details: + print('-'*77,'\nRunning %s\n\n' % function.__doc__) + errors = function(filename) + if errors: + if not show_details: + #print(table_cell % function.__doc__.split(' ')[0], end='') + print(table_cell % ''.join('%s%d' % (k[0], v) + for k, v in errors.items()), + end='') + else: + if not show_details: + print(table_cell % 'OK', end='') + + for k, v in errors.items(): + sum_errors[k] = sum_errors.get(k, 0) + v + + display(run_python_test_on) + display(run_python3_test_on) + display(run_pythonjs_test_on) + display(run_pythonjsjs_test_on) + print() + return sum_errors + +def run(): + """Run all the tests or the selected ones""" + + if not show_details: + print(table_header % ("", "Regtest run on") + + ''.join(table_cell % i + for i in ("Python", "Python3", "PyJS", "PyJSJS") + ) + ) + errors = [] + total_errors = {} + for filename in files(): + if show_details: + if os.path.abspath(filename) not in argv: + continue + print('*'*77) + print(filename) + sum_errors = run_test_on(filename) + if sum_errors: + errors.append(filename) + for k, v in sum_errors.items(): + total_errors[k] = total_errors.get(k, 0) + v + + print() + if errors: + nr_errors = 0 + if not show_details: + print("To see details about errors, run the commands:") + for i in errors: + print('\t%s %s' % (sys.argv[0], i)) + print("\nSummary of errors:") + for k, v in total_errors.items(): + print('\t%d %s' % (v, k)) + if k in ('Error', 'Translation error'): + nr_errors += v + if nr_errors == 0: + print("\nRegression tests run fine but with warnings") + sys.exit(nr_errors) + else: + print("Regression tests run fine") + sys.exit(0) +run() diff --git a/regtests/str/specials.py b/regtests/str/specials.py new file mode 100644 index 0000000..72291f7 --- /dev/null +++ b/regtests/str/specials.py @@ -0,0 +1,8 @@ +"""Specials chars in strings""" +Error(len('\\') == 1) +Error('éè' == 'é' + 'è') +if len('éè') == 2: # The interpreter assumes UTF8 (all except Python2) + Error('éè'[::-1] == 'èé') +else: + # run.y fail if the right part is defined as strings, must use chr() + Error(tuple('éè'[::-1]) == (chr(168), chr(195), chr(169), chr(195))) From d326e8faf195e365fc288cd32fc5cd91be815e9c Mon Sep 17 00:00:00 2001 From: hartsantler Date: Sun, 12 Jan 2014 06:35:42 -0800 Subject: [PATCH 065/521] brython/ast: function and class decorators. --- bindings/ast.py | 19 ++++++++++++++++--- tests/test_AST.html | 9 +++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/bindings/ast.py b/bindings/ast.py index 9ddda8c..71c79bc 100644 --- a/bindings/ast.py +++ b/bindings/ast.py @@ -6,6 +6,13 @@ def brython_tokenize(src): module = 'test' return JS('$tokenize(src, module)') ## Brython tokenizer +_decorators = [] +def push_decorator(ctx): + _decorators.append( ctx ) +def pop_decorators(): + arr = list( _decorators ) + _decorators.length = 0 ## javascript style + return arr class Assign: def _collect_targets(self, ctx): @@ -88,7 +95,7 @@ def __init__(self, ctx, node): self.name = ctx.name ## raw string self.args = _arguments( ctx.tree[0] ) self.body = [] - self.decorator_list = [] + self.decorator_list = pop_decorators() self.returns = None ## python3 returns annotation print 'FunctionDef::', ctx for child in node.children: @@ -139,6 +146,7 @@ def __init__(self, ctx, node): self.name = ctx.name self.bases = [] self.body = [] + self.decorator_list = pop_decorators() if len(ctx.tree) == 1: e = ctx.tree[0] @@ -198,6 +206,9 @@ def to_ast_node( ctx, node=None ): elif ctx.type == 'condition' and ctx.token == 'if': return IfExp( ctx, node ) + elif ctx.type == 'decorator': + push_decorator( to_ast_node(ctx.tree[0]) ) + else: print '-------------------------' print node @@ -211,10 +222,12 @@ def walk_nodes( node, module ): if node.type == 'expression': if node.get_ctx(): anode = to_ast_node( node.get_ctx(), node=node ) - module.append( anode ) + if anode: ## decorators do not return + module.append( anode ) elif node.get_ctx(): anode = to_ast_node( node.get_ctx(), node=node ) - module.append( anode ) + if anode: + module.append( anode ) else: for child in node.children: walk_nodes( child, module ) diff --git a/tests/test_AST.html b/tests/test_AST.html index 69e59c0..705059f 100644 --- a/tests/test_AST.html +++ b/tests/test_AST.html @@ -20,12 +20,15 @@ from ast import * source = """ +@mydecorator1 +@mydecorator2 def func(a,b, mykey=1, *S, **K): c = a+b return c func(100, 200, 'hi', mykey=1) +@myclassdecorator class A(X,Y): def method1(self, x,y,z): w = x+y+z @@ -68,6 +71,9 @@ return self.visit( node.left ) + node.op + self.visit( node.right ) def visit_FunctionDef(self, node): + for dec in node.decorator_list: + print '@', self.visit(dec) + args = [] for a in node.args.args: args.append( self.visit(a) ) @@ -93,6 +99,9 @@ print ')' def visit_ClassDef(self, node): + for dec in node.decorator_list: + print '@', self.visit(dec) + print 'class '+node.name + ':' for n in node.body: a = self.visit(n) From 722c34ef49bd946a06d6575e7b0c9e0ab2b77f41 Mon Sep 17 00:00:00 2001 From: Thierry EXCOFFIER Date: Sun, 12 Jan 2014 19:27:16 +0100 Subject: [PATCH 066/521] The regression tests use 'node' javascript interpreter if installed If 'rhino' is runnable, it will also be tested. --- regtests/run.py | 96 +++++++++++++++++++++++++++++++++++--------- regtests/str/iter.py | 14 +++++++ 2 files changed, 91 insertions(+), 19 deletions(-) create mode 100644 regtests/str/iter.py diff --git a/regtests/run.py b/regtests/run.py index 8fe609f..3063b77 100755 --- a/regtests/run.py +++ b/regtests/run.py @@ -31,6 +31,16 @@ if os.path.exists(name) ] +def runnable(command): + """Returns True is the standard oupt of the command display something""" + f = os.popen(command, "r") + output = f.read() + f.close() + return output != '' + +rhino_runnable = runnable("rhino -help") +node_runnable = runnable("node --help") + if show_details: display_errors = "" else: @@ -123,30 +133,37 @@ def run_python3_test_on(filename): write("%s.py" % tmpname, patch_python(filename)) return run_command("python3 %s.py %s" % (tmpname, display_errors)) -def run_pythonjs_test(filename): - """run tests""" +def translate_js(filename, javascript): + output_name = "%s.py" % tmpname + write(output_name, + (javascript and 'pythonjs.configure(javascript=True)\n' or '') + + patch_python(filename)) stdout, stderr = run_command(os.path.join("..", "pythonjs", "translator.py") - + ' ' + filename, + + ' ' + output_name, returns_stdout_stderr=True) if stderr: - return {'Translation error':1} + return '' + else: + return stdout + +def run_if_no_error(function): + """Run the function if the JS code is not empty""" + global js + if js: + return function(js) else: - return run_js(stdout) + return {'Translation error':1} -def run_pythonjs_test_on(filename): +def run_pythonjs_test_on(dummy_filename): """JS PythonJS tests""" - write("%s.py" % tmpname, patch_python(filename)) - return run_pythonjs_test("%s.py" % tmpname) + return run_if_no_error(run_js_rhino) def run_pythonjsjs_test_on(filename): """JSJS PythonJS with javascript tests""" - write("%s.py" % tmpname, - 'pythonjs.configure(javascript=True)\n' - + patch_python(filename)) - return run_pythonjs_test("%s.py" % tmpname) + return run_pythonjs_test_on(filename) -def run_js(content): +def run_js_rhino(content): """Run Javascript using Rhino""" builtins = read(os.path.join("..", "pythonjs.js")) # Patch in order to run Rhino @@ -163,8 +180,25 @@ def run_js(content): write("%s.js" % tmpname, content) return run_command("rhino -O -1 %s.js" % tmpname) -table_header = "%-20.20s %-30.30s" -table_cell = '%-8.8s' +def run_pythonjs_test_on_node(dummy_filename): + """JSJS PythonJS tests on Node""" + return run_if_no_error(run_js_node) + +def run_pythonjsjs_test_on_node(filename): + """JSJS PythonJS with javascript tests on Node""" + return run_pythonjs_test_on_node(filename) + +def run_js_node(content): + """Run Javascript using Node""" + builtins = read(os.path.join("..", "pythonjs.js")) + write("%s.js" % tmpname, + builtins.replace('console.log(process.title);','') + .replace('console.log(process.version);','') + + content) + return run_command("node %s.js" % tmpname) + +table_header = "%-12.12s %-28.28s" +table_cell = '%-6.6s' def run_test_on(filename): """run one test and returns the number of errors""" @@ -187,14 +221,24 @@ def display(function): else: if not show_details: print(table_cell % 'OK', end='') + sys.stdout.flush() for k, v in errors.items(): sum_errors[k] = sum_errors.get(k, 0) + v display(run_python_test_on) display(run_python3_test_on) - display(run_pythonjs_test_on) - display(run_pythonjsjs_test_on) + global js + js = translate_js(filename, False) + if rhino_runnable: + display(run_pythonjs_test_on) + if node_runnable: + display(run_pythonjs_test_on_node) + js = translate_js(filename, True) + if rhino_runnable: + display(run_pythonjsjs_test_on) + if node_runnable: + display(run_pythonjsjs_test_on_node) print() return sum_errors @@ -202,9 +246,23 @@ def run(): """Run all the tests or the selected ones""" if not show_details: + headers = ["Py-\nthon", "Py-\nthon3"] + if rhino_runnable: + headers.append("JS\nRhino") + if node_runnable: + headers.append("JS\nNode") + if rhino_runnable: + headers.append("JSJS\nRhino") + if node_runnable: + headers.append("JSJS\nNode") + print(table_header % ("", "Regtest run on") - + ''.join(table_cell % i - for i in ("Python", "Python3", "PyJS", "PyJSJS") + + ''.join(table_cell % i.split('\n')[0] + for i in headers) + ) + print(table_header % ("", "") + + ''.join(table_cell % i.split('\n')[1] + for i in headers ) ) errors = [] diff --git a/regtests/str/iter.py b/regtests/str/iter.py new file mode 100644 index 0000000..e6b4b86 --- /dev/null +++ b/regtests/str/iter.py @@ -0,0 +1,14 @@ +"""The string iterator""" + +a = list("abc") +Error(a[0] == 'a') +Error(a[1] == 'b') +Error(a[2] == 'c') + +# Does not work with javascript +a = [] +for i in "abc": + a.append(i) +Warning(a[0] == 'a') +Warning(a[1] == 'b') +Warning(a[2] == 'c') From ed1a3bf9d78aa9c87b3fbe49574943fd02c31c5c Mon Sep 17 00:00:00 2001 From: hartsantler Date: Sun, 12 Jan 2014 15:20:42 -0800 Subject: [PATCH 067/521] fixed %s string replacement, fixed iterate over string in javascript mode. --- pythonjs/python_to_pythonjs.py | 2 +- pythonjs/pythonjs.py | 2 +- tests/test_string.html | 5 +++++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index 2ae6606..1f5fecd 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -937,7 +937,7 @@ def visit_BinOp(self, node): if self._with_js: return '__sprintf( %s, %s )' %(left, right) ## assumes that right is a tuple, or list. else: - return '__sprintf( %s, %s[...] )' %(left, right) ## assumes that right is a tuple, or list. + return '__sprintf( %s, %s )' %(left, right) ## assumes that right is a tuple, or list. elif op == '*' and isinstance(node.left, ast.List): if len(node.left.elts) == 1 and isinstance(node.left.elts[0], ast.Name) and node.left.elts[0].id == 'None': diff --git a/pythonjs/pythonjs.py b/pythonjs/pythonjs.py index 96145da..dd6dbc6 100755 --- a/pythonjs/pythonjs.py +++ b/pythonjs/pythonjs.py @@ -448,7 +448,7 @@ def _visit_for_prep_iter_helper(self, node, out, iter_name): #out.append( self.indent() + 'if (! (iter instanceof Array) ) { iter = Object.keys(iter) }' ) ## new style - Object.keys only works for normal JS-objects, not ones created with `Object.create(null)` out.append( - self.indent() + 'if (! (%s instanceof Array) ) { %s = __object_keys__(%s) }' %(iter_name, iter_name, iter_name) + self.indent() + 'if (! (%s instanceof Array || typeof %s == "string") ) { %s = __object_keys__(%s) }' %(iter_name, iter_name, iter_name, iter_name) ) diff --git a/tests/test_string.html b/tests/test_string.html index e4d2ecd..b0b8460 100644 --- a/tests/test_string.html +++ b/tests/test_string.html @@ -72,6 +72,11 @@ print 'testing reverse string' print a[::-1] + print 'testing iter over string in javascript mode' + with javascript: + for i in "abc": + print i + print 'tests complete' From 46229893165921bfb8a3dfea1a6b911797ed65f2 Mon Sep 17 00:00:00 2001 From: hartsantler Date: Sun, 12 Jan 2014 17:27:31 -0800 Subject: [PATCH 068/521] Brython AST: elif/else statements are properly inserted into .orelse of IfExp ast node. --- bindings/ast.py | 49 ++++++++++++++++++++++++++++++++++++++------- tests/test_AST.html | 34 +++++++++++++++++++++++++++++-- 2 files changed, 74 insertions(+), 9 deletions(-) diff --git a/bindings/ast.py b/bindings/ast.py index 71c79bc..3cc69d1 100644 --- a/bindings/ast.py +++ b/bindings/ast.py @@ -14,6 +14,10 @@ def pop_decorators(): _decorators.length = 0 ## javascript style return arr +class Pass: + def __init__(self, ctx, node): + pass + class Assign: def _collect_targets(self, ctx): if ctx.type == 'expr' and ctx.name == 'id': @@ -99,9 +103,9 @@ def __init__(self, ctx, node): self.returns = None ## python3 returns annotation print 'FunctionDef::', ctx for child in node.children: - anode = to_ast_node( child.get_ctx() ) - if anode is None: raise TypeError - self.body.append( anode ) + anode = to_ast_node( child.get_ctx(), node=child ) + if anode: ## ctx of type: 'single_kw' and token elif/else do not return an ast node + self.body.append( anode ) class Return: @@ -172,10 +176,18 @@ def __init__(self, ctx, node): class IfExp: + ''' + if/elif/else could be translated to javascript switch/case more easily if we track elif statements, + but the python standard simply treats elif statements as nested if statements in .orelse. + In the future we can bend this rule when PythonJS becomes fully self-hosted. + ''' + _previous = None def __init__(self, ctx, node): + if ctx.token == 'if': ## can also be "elif" and "else" + IfExp._previous = self self.test = to_ast_node( ctx.tree[0] ) self.body = [] - self.orelse = None + self.orelse = [] for child in node.children: self.body.append( to_ast_node(child.get_ctx()) ) @@ -191,6 +203,7 @@ def __init__(self, ctx, node): 'class' : ClassDef, 'op' : BinOp, 'attribute' : Attribute, + 'pass' : Pass, } def to_ast_node( ctx, node=None ): @@ -203,14 +216,29 @@ def to_ast_node( ctx, node=None ): elif ctx.type in __MAP: return __MAP[ ctx.type ]( ctx, node ) + elif ctx.type == 'decorator': + push_decorator( to_ast_node(ctx.tree[0]) ) + elif ctx.type == 'condition' and ctx.token == 'if': return IfExp( ctx, node ) + elif ctx.type == 'condition' and ctx.token == 'elif': + a = IfExp( ctx, node ) + IfExp._previous.orelse.append( a ) + IfExp._previous = a - elif ctx.type == 'decorator': - push_decorator( to_ast_node(ctx.tree[0]) ) + elif ctx.type == 'single_kw': + if ctx.token == 'else' or ctx.token == 'elif': + orelse = IfExp._previous.orelse + for child in node.children: + walk_nodes( child, orelse ) + + else: + print 'unknown token for single_kw' + print ctx + raise TypeError else: - print '-------------------------' + print '---------error----------' print node print ctx raise TypeError @@ -228,6 +256,10 @@ def walk_nodes( node, module ): anode = to_ast_node( node.get_ctx(), node=node ) if anode: module.append( anode ) + #else: + # for child in node.children: + # walk_nodes( child, module ) + else: for child in node.children: walk_nodes( child, module ) @@ -263,3 +295,6 @@ def visit_Num(self, node): def visit_Name(self, node): return node.id + + def visit_Pass(self, node): + return 'pass' \ No newline at end of file diff --git a/tests/test_AST.html b/tests/test_AST.html index 705059f..5038c39 100644 --- a/tests/test_AST.html +++ b/tests/test_AST.html @@ -37,15 +37,38 @@ self.xxx = XXX ## TODO fixme a = b = c = x = y = z = 1 - if 1: + if 1 and True or False: print('hi') print('world') + elif True: + pass + else: + pass return XXX """ +source_test_elif = """ +if False: + pass +elif True: + print( 'hi elif' ) +else: + a = 1 + 1 + print('hi else') + +if False: + a = 2+2 +elif True: + print( 'hi elif2' ) +else: + a = 3 + 3 + print('hi else3') + + +""" def test(): global module @@ -58,7 +81,14 @@ def visit_IfExp(self, node): print 'if ', self.visit(node.test), ':' for a in node.body: - self.visit(a) + r = self.visit(a) + if r: print ' ', r + + if len(node.orelse): + print 'else:' + for a in node.orelse: + r = self.visit( a ) + if r: print ' ', r def visit_Assign(self, node): a = [ self.visit( t ) for t in node.targets ] From fc04f0fc7bb2c2406bf1a5f90a5d91af9fa6e66b Mon Sep 17 00:00:00 2001 From: hartsantler Date: Sun, 12 Jan 2014 20:06:30 -0800 Subject: [PATCH 069/521] core: deprecated javascript mode "{mylabel:XXX}" - now labels must be quoted: "{'mylabel':XXX}" fixed javascript mode `dicts` to allow them to use classes and instances as keys, using a ternary_operator hack. --- pythonjs.js | 256 ++++++++++++++++++--------------- pythonjs/python_to_pythonjs.py | 53 ++++--- pythonjs/pythonjs.py | 17 ++- runtime/builtins.py | 11 +- 4 files changed, 193 insertions(+), 144 deletions(-) diff --git a/pythonjs.js b/pythonjs.js index badfaf5..c1fe423 100644 --- a/pythonjs.js +++ b/pythonjs.js @@ -1,4 +1,4 @@ -// PythonJS Runtime - regenerated on: Fri Jan 10 18:27:49 2014 +// PythonJS Runtime - regenerated on: Sun Jan 12 20:04:43 2014 __NULL_OBJECT__ = Object.create(null); if (( "window" ) in this && ( "document" ) in this) { __NODEJS__ = false; @@ -25,7 +25,7 @@ __create_array__ = function() { var array; array = []; var __iter1 = jsrange(arguments.length); - if (! (__iter1 instanceof Array) ) { __iter1 = __object_keys__(__iter1) } + if (! (__iter1 instanceof Array || typeof __iter1 == "string") ) { __iter1 = __object_keys__(__iter1) } for (var __idx1=0; __idx1 < __iter1.length; __idx1++) { var i = __iter1[ __idx1 ]; array.push(arguments[i]); @@ -208,7 +208,7 @@ __get__ = function(object, attribute) { } bases = __class__.__bases__; var __iter2 = bases; - if (! (__iter2 instanceof Array) ) { __iter2 = __object_keys__(__iter2) } + if (! (__iter2 instanceof Array || typeof __iter2 == "string") ) { __iter2 = __object_keys__(__iter2) } for (var __idx2=0; __idx2 < __iter2.length; __idx2++) { var base = __iter2[ __idx2 ]; attr = _get_upstream_attribute(base, attribute); @@ -247,7 +247,7 @@ __get__ = function(object, attribute) { } } var __iter3 = bases; - if (! (__iter3 instanceof Array) ) { __iter3 = __object_keys__(__iter3) } + if (! (__iter3 instanceof Array || typeof __iter3 == "string") ) { __iter3 = __object_keys__(__iter3) } for (var __idx3=0; __idx3 < __iter3.length; __idx3++) { var base = __iter3[ __idx3 ]; var prop; @@ -260,7 +260,7 @@ __get__ = function(object, attribute) { return __class__["__getattr__"]([object, attribute], Object()); } var __iter4 = bases; - if (! (__iter4 instanceof Array) ) { __iter4 = __object_keys__(__iter4) } + if (! (__iter4 instanceof Array || typeof __iter4 == "string") ) { __iter4 = __object_keys__(__iter4) } for (var __idx4=0; __idx4 < __iter4.length; __idx4++) { var base = __iter4[ __idx4 ]; var f; @@ -295,7 +295,7 @@ _get_upstream_attribute = function(base, attr) { return base[attr]; } var __iter5 = base.__bases__; - if (! (__iter5 instanceof Array) ) { __iter5 = __object_keys__(__iter5) } + if (! (__iter5 instanceof Array || typeof __iter5 == "string") ) { __iter5 = __object_keys__(__iter5) } for (var __idx5=0; __idx5 < __iter5.length; __idx5++) { var parent = __iter5[ __idx5 ]; return _get_upstream_attribute(parent, attr); @@ -307,7 +307,7 @@ _get_upstream_property = function(base, attr) { return base.__properties__[attr]; } var __iter6 = base.__bases__; - if (! (__iter6 instanceof Array) ) { __iter6 = __object_keys__(__iter6) } + if (! (__iter6 instanceof Array || typeof __iter6 == "string") ) { __iter6 = __object_keys__(__iter6) } for (var __idx6=0; __idx6 < __iter6.length; __idx6++) { var parent = __iter6[ __idx6 ]; return _get_upstream_property(parent, attr); @@ -373,11 +373,31 @@ _PythonJS_UID = 0; var IndexError = new RangeError(); var KeyError = new RangeError(); var ValueError = new RangeError(); +__jsdict = function(items) { + var d, key; + d = {}; + var __iter1 = items; + if (! (__iter1 instanceof Array || typeof __iter1 == "string") ) { __iter1 = __object_keys__(__iter1) } + for (var __idx1=0; __idx1 < __iter1.length; __idx1++) { + var item = __iter1[ __idx1 ]; + key = item[0]; + if (key.__uid__) { + key = key.__uid__; + } + d[key] = item[1]; + } + return d; +} + +__jsdict.NAME = "__jsdict"; +__jsdict.args_signature = ["items"]; +__jsdict.kwargs_signature = { }; +__jsdict.types_signature = { }; __jsdict_get = function(ob, key, default_value) { if (default_value == undefined) default_value = undefined; if (ob instanceof Object) { if (key in ob) { - return ob[key]; + return ob[ (key.__uid__) ? key.__uid__ : key]; } return default_value; } else { @@ -417,12 +437,12 @@ __jsdict_values = function(ob) { var arr, value; if (ob instanceof Object) { arr = []; - var __iter1 = ob; - if (! (__iter1 instanceof Array) ) { __iter1 = __object_keys__(__iter1) } - for (var __idx1=0; __idx1 < __iter1.length; __idx1++) { - var key = __iter1[ __idx1 ]; + var __iter2 = ob; + if (! (__iter2 instanceof Array || typeof __iter2 == "string") ) { __iter2 = __object_keys__(__iter2) } + for (var __idx2=0; __idx2 < __iter2.length; __idx2++) { + var key = __iter2[ __idx2 ]; if (ob.hasOwnProperty(key)) { - value = ob[key]; + value = ob[ (key.__uid__) ? key.__uid__ : key]; arr.push(value); } } @@ -441,7 +461,7 @@ __jsdict_pop = function(ob, key, _default) { if (_default == undefined) _default = undefined; if (ob instanceof Object) { if (key in ob) { - v = ob[key]; + v = ob[ (key.__uid__) ? key.__uid__ : key]; delete ob[key]; return v; } else { @@ -474,24 +494,24 @@ __object_keys__.kwargs_signature = { }; __object_keys__.types_signature = { }; __bind_property_descriptors__ = function(o, klass) { var prop, desc; - var __iter2 = klass.__properties__; - if (! (__iter2 instanceof Array) ) { __iter2 = __object_keys__(__iter2) } - for (var __idx2=0; __idx2 < __iter2.length; __idx2++) { - var name = __iter2[ __idx2 ]; - desc = { "enumerable":true }; - prop = klass.__properties__[name]; - if (prop["get"]) { + var __iter3 = klass.__properties__; + if (! (__iter3 instanceof Array || typeof __iter3 == "string") ) { __iter3 = __object_keys__(__iter3) } + for (var __idx3=0; __idx3 < __iter3.length; __idx3++) { + var name = __iter3[ __idx3 ]; + desc = __jsdict([["enumerable", true]]); + prop = klass.__properties__[ (name.__uid__) ? name.__uid__ : name]; + if (prop[ ("get".__uid__) ? "get".__uid__ : "get"]) { desc["get"] = __generate_getter__(klass, o, name); } - if (prop["set"]) { + if (prop[ ("set".__uid__) ? "set".__uid__ : "set"]) { desc["set"] = __generate_setter__(klass, o, name); } Object.defineProperty(o, name, desc); } - var __iter3 = klass.__bases__; - if (! (__iter3 instanceof Array) ) { __iter3 = __object_keys__(__iter3) } - for (var __idx3=0; __idx3 < __iter3.length; __idx3++) { - var base = __iter3[ __idx3 ]; + var __iter4 = klass.__bases__; + if (! (__iter4 instanceof Array || typeof __iter4 == "string") ) { __iter4 = __object_keys__(__iter4) } + for (var __idx4=0; __idx4 < __iter4.length; __idx4++) { + var base = __iter4[ __idx4 ]; __bind_property_descriptors__(o, base); } } @@ -501,7 +521,7 @@ __bind_property_descriptors__.args_signature = ["o", "klass"]; __bind_property_descriptors__.kwargs_signature = { }; __bind_property_descriptors__.types_signature = { }; __generate_getter__ = function(klass, o, n) { - return (function () {return klass.__properties__[ n ][ "get" ]([o],{ })}); + return (function () {return klass.__properties__[ (n.__uid__) ? n.__uid__ : n][ ("get".__uid__) ? "get".__uid__ : "get"]([o], __jsdict([]))}); } __generate_getter__.NAME = "__generate_getter__"; @@ -509,7 +529,7 @@ __generate_getter__.args_signature = ["klass", "o", "n"]; __generate_getter__.kwargs_signature = { }; __generate_getter__.types_signature = { }; __generate_setter__ = function(klass, o, n) { - return (function (v) {return klass.__properties__[ n ][ "set" ]([o, v],{ })}); + return (function (v) {return klass.__properties__[ (n.__uid__) ? n.__uid__ : n][ ("set".__uid__) ? "set".__uid__ : "set"]([o, v], __jsdict([]))}); } __generate_setter__.NAME = "__generate_setter__"; @@ -541,35 +561,35 @@ create_class = function(class_name, parents, attrs, props) { klass.__all_method_names__ = []; klass.__properties__ = props; klass.__attributes__ = attrs; - var __iter4 = attrs; - if (! (__iter4 instanceof Array) ) { __iter4 = __object_keys__(__iter4) } - for (var __idx4=0; __idx4 < __iter4.length; __idx4++) { - var key = __iter4[ __idx4 ]; - if (( typeof(attrs[key]) ) == "function") { - klass.__unbound_methods__[key] = attrs[key]; + var __iter5 = attrs; + if (! (__iter5 instanceof Array || typeof __iter5 == "string") ) { __iter5 = __object_keys__(__iter5) } + for (var __idx5=0; __idx5 < __iter5.length; __idx5++) { + var key = __iter5[ __idx5 ]; + if (( typeof(attrs[ (key.__uid__) ? key.__uid__ : key]) ) == "function") { + klass.__unbound_methods__[key] = attrs[ (key.__uid__) ? key.__uid__ : key]; klass.__all_method_names__.push(key); } if (( key ) == "__getattribute__") { continue } - klass[key] = attrs[key]; + klass[key] = attrs[ (key.__uid__) ? key.__uid__ : key]; } klass.__setters__ = []; klass.__getters__ = []; - var __iter5 = klass.__properties__; - if (! (__iter5 instanceof Array) ) { __iter5 = __object_keys__(__iter5) } - for (var __idx5=0; __idx5 < __iter5.length; __idx5++) { - var name = __iter5[ __idx5 ]; - prop = klass.__properties__[name]; + var __iter6 = klass.__properties__; + if (! (__iter6 instanceof Array || typeof __iter6 == "string") ) { __iter6 = __object_keys__(__iter6) } + for (var __idx6=0; __idx6 < __iter6.length; __idx6++) { + var name = __iter6[ __idx6 ]; + prop = klass.__properties__[ (name.__uid__) ? name.__uid__ : name]; klass.__getters__.push(name); - if (prop["set"]) { + if (prop[ ("set".__uid__) ? "set".__uid__ : "set"]) { klass.__setters__.push(name); } } - var __iter6 = klass.__bases__; - if (! (__iter6 instanceof Array) ) { __iter6 = __object_keys__(__iter6) } - for (var __idx6=0; __idx6 < __iter6.length; __idx6++) { - var base = __iter6[ __idx6 ]; + var __iter7 = klass.__bases__; + if (! (__iter7 instanceof Array || typeof __iter7 == "string") ) { __iter7 = __object_keys__(__iter7) } + for (var __idx7=0; __idx7 < __iter7.length; __idx7++) { + var base = __iter7[ __idx7 ]; Array.prototype.push.apply(klass.__getters__, base.__getters__); Array.prototype.push.apply(klass.__setters__, base.__setters__); Array.prototype.push.apply(klass.__all_method_names__, base.__all_method_names__); @@ -582,10 +602,10 @@ create_class = function(class_name, parents, attrs, props) { object.__dict__ = object; has_getattribute = false; has_getattr = false; - var __iter7 = klass.__all_method_names__; - if (! (__iter7 instanceof Array) ) { __iter7 = __object_keys__(__iter7) } - for (var __idx7=0; __idx7 < __iter7.length; __idx7++) { - var name = __iter7[ __idx7 ]; + var __iter8 = klass.__all_method_names__; + if (! (__iter8 instanceof Array || typeof __iter8 == "string") ) { __iter8 = __object_keys__(__iter8) } + for (var __idx8=0; __idx8 < __iter8.length; __idx8++) { + var name = __iter8[ __idx8 ]; if (( name ) == "__getattribute__") { has_getattribute = true; } else { @@ -688,8 +708,8 @@ getattr = function(args, kwargs) { var property = arguments['property']; if (property) { prop = _get_upstream_property(ob.__class__, attr); - if (prop && prop["get"]) { - return prop["get"]([ob], { }); + if (prop && prop[ ("get".__uid__) ? "get".__uid__ : "get"]) { + return prop[ ("get".__uid__) ? "get".__uid__ : "get"]([ob], __jsdict([])); } else { console.log("ERROR: getattr property error", prop); } @@ -720,8 +740,8 @@ setattr = function(args, kwargs) { var property = arguments['property']; if (property) { prop = _get_upstream_property(ob.__class__, attr); - if (prop && prop["set"]) { - prop["set"]([ob, value], { }); + if (prop && prop[ ("set".__uid__) ? "set".__uid__ : "set"]) { + prop[ ("set".__uid__) ? "set".__uid__ : "set"]([ob, value], __jsdict([])); } else { console.log("ERROR: setattr property error", prop); } @@ -912,7 +932,7 @@ _setup_str_prototype = function(args, kwargs) { func.types_signature = { }; String.prototype.__contains__ = func; var func = function(index) { - return this[index]; + return this[ (index.__uid__) ? index.__uid__ : index]; } func.NAME = "func"; @@ -930,7 +950,7 @@ _setup_str_prototype = function(args, kwargs) { func.types_signature = { }; String.prototype.__iter__ = func; var func = function(idx) { - return this[idx]; + return this[ (idx.__uid__) ? idx.__uid__ : idx]; } func.NAME = "func"; @@ -1017,10 +1037,10 @@ _setup_str_prototype = function(args, kwargs) { arr = a["$wrapped"]; } i = 0; - var __iter8 = arr; - if (! (__iter8 instanceof Array) ) { __iter8 = __object_keys__(__iter8) } - for (var __idx8=0; __idx8 < __iter8.length; __idx8++) { - var value = __iter8[ __idx8 ]; + var __iter9 = arr; + if (! (__iter9 instanceof Array || typeof __iter9 == "string") ) { __iter9 = __object_keys__(__iter9) } + for (var __idx9=0; __idx9 < __iter9.length; __idx9++) { + var value = __iter9[ __idx9 ]; out += value; i += 1; if (( i ) < arr.length) { @@ -1079,10 +1099,10 @@ _setup_str_prototype = function(args, kwargs) { var func = function() { var digits; digits = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]; - var __iter9 = this; - if (! (__iter9 instanceof Array) ) { __iter9 = __object_keys__(__iter9) } - for (var __idx9=0; __idx9 < __iter9.length; __idx9++) { - var char = __iter9[ __idx9 ]; + var __iter10 = this; + if (! (__iter10 instanceof Array || typeof __iter10 == "string") ) { __iter10 = __object_keys__(__iter10) } + for (var __idx10=0; __idx10 < __iter10.length; __idx10++) { + var char = __iter10[ __idx10 ]; if (Object.hasOwnProperty.call(digits, "__contains__") && digits["__contains__"](char) || Object.hasOwnProperty.call(digits, char) || ( typeof(digits) ) == "string" && digits.__contains__(char)) { /*pass*/ } else { @@ -1128,7 +1148,7 @@ _setup_array_prototype = function(args, kwargs) { var i, item; i = 0; while(( i ) < this.length) { - item = this[i]; + item = this[ (i.__uid__) ? i.__uid__ : i]; if (( typeof(item) ) == "object") { if (item.jsify) { this[i] = item.jsify(); @@ -1167,7 +1187,7 @@ _setup_array_prototype = function(args, kwargs) { func.types_signature = { }; Array.prototype.__len__ = func; var func = function(index) { - return this[index]; + return this[ (index.__uid__) ? index.__uid__ : index]; } func.NAME = "func"; @@ -1180,7 +1200,7 @@ _setup_array_prototype = function(args, kwargs) { if (( index ) < 0) { index = (this.length + index); } - return this[index]; + return this[ (index.__uid__) ? index.__uid__ : index]; } __getitem__.NAME = "__getitem__"; @@ -1233,10 +1253,10 @@ _setup_array_prototype = function(args, kwargs) { func.types_signature = { }; Array.prototype.append = func; var extend = function(self, other) { - var __iter10 = other; - if (! (__iter10 instanceof Array) ) { __iter10 = __object_keys__(__iter10) } - for (var __idx10=0; __idx10 < __iter10.length; __idx10++) { - var obj = __iter10[ __idx10 ]; + var __iter11 = other; + if (! (__iter11 instanceof Array || typeof __iter11 == "string") ) { __iter11 = __object_keys__(__iter11) } + for (var __idx11=0; __idx11 < __iter11.length; __idx11++) { + var obj = __iter11[ __idx11 ]; this.push(obj); } } @@ -1293,10 +1313,10 @@ _setup_array_prototype = function(args, kwargs) { var count = function(obj) { var a; a = 0; - var __iter11 = this; - if (! (__iter11 instanceof Array) ) { __iter11 = __object_keys__(__iter11) } - for (var __idx11=0; __idx11 < __iter11.length; __idx11++) { - var item = __iter11[ __idx11 ]; + var __iter12 = this; + if (! (__iter12 instanceof Array || typeof __iter12 == "string") ) { __iter12 = __object_keys__(__iter12) } + for (var __idx12=0; __idx12 < __iter12.length; __idx12++) { + var item = __iter12[ __idx12 ]; if (( item ) === obj) { a += 1; } @@ -1320,7 +1340,7 @@ _setup_array_prototype = function(args, kwargs) { while(( low ) < high) { a = (low + high); mid = Math.floor((a / 2)); - if (( x ) < this[mid]) { + if (( x ) < this[ (mid.__uid__) ? mid.__uid__ : mid]) { high = mid; } else { low = (mid + 1); @@ -1335,7 +1355,7 @@ _setup_array_prototype = function(args, kwargs) { func.types_signature = { }; Array.prototype.bisect = func; var func = function(other) { - return this.filter((function (i) {return other.indexOf(i) == -1})); + return this.filter((function (i) {return ( other.indexOf(i) ) == -1})); } func.NAME = "func"; @@ -1344,7 +1364,7 @@ _setup_array_prototype = function(args, kwargs) { func.types_signature = { }; Array.prototype.difference = func; var func = function(other) { - return this.filter((function (i) {return other.indexOf(i) != -1})); + return this.filter((function (i) {return ( other.indexOf(i) ) != -1})); } func.NAME = "func"; @@ -1353,10 +1373,10 @@ _setup_array_prototype = function(args, kwargs) { func.types_signature = { }; Array.prototype.intersection = func; var func = function(other) { - var __iter12 = this; - if (! (__iter12 instanceof Array) ) { __iter12 = __object_keys__(__iter12) } - for (var __idx12=0; __idx12 < __iter12.length; __idx12++) { - var item = __iter12[ __idx12 ]; + var __iter13 = this; + if (! (__iter13 instanceof Array || typeof __iter13 == "string") ) { __iter13 = __object_keys__(__iter13) } + for (var __idx13=0; __idx13 < __iter13.length; __idx13++) { + var item = __iter13[ __idx13 ]; if (( other.indexOf(item) ) == -1) { return false; } @@ -1768,7 +1788,7 @@ __Iterator_next_fast = function(args, kwargs) { var self = arguments['self']; index = self.index; self.index += 1; - return self.obj_get([index], { }); + return self.obj_get([index], __jsdict([])); } __Iterator_next_fast.NAME = "__Iterator_next_fast"; @@ -1851,7 +1871,7 @@ __tuple___getitem__ = function(args, kwargs) { if (( index ) < 0) { index = (__get__(self["$wrapped"], "length") + index); } - return self["$wrapped"][index]; + return self["$wrapped"][ (index.__uid__) ? index.__uid__ : index]; } __tuple___getitem__.NAME = "__tuple___getitem__"; @@ -1955,10 +1975,10 @@ __tuple_count = function(args, kwargs) { var self = arguments['self']; var obj = arguments['obj']; a = 0; - var __iter13 = self["$wrapped"]; - if (! (__iter13 instanceof Array) ) { __iter13 = __object_keys__(__iter13) } - for (var __idx13=0; __idx13 < __iter13.length; __idx13++) { - var item = __iter13[ __idx13 ]; + var __iter14 = self["$wrapped"]; + if (! (__iter14 instanceof Array || typeof __iter14 == "string") ) { __iter14 = __object_keys__(__iter14) } + for (var __idx14=0; __idx14 < __iter14.length; __idx14++) { + var item = __iter14[ __idx14 ]; if (( item ) == obj) { a += 1; } @@ -1984,7 +2004,7 @@ __tuple_get = function(args, kwargs) { arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var index = arguments['index']; - return self["$wrapped"][index]; + return self["$wrapped"][ (index.__uid__) ? index.__uid__ : index]; } __tuple_get.NAME = "__tuple_get"; @@ -2118,7 +2138,7 @@ __pylist___getitem__ = function(args, kwargs) { if (( index ) < 0) { index = (__get__(self["$wrapped"], "length") + index); } - return self["$wrapped"][index]; + return self["$wrapped"][ (index.__uid__) ? index.__uid__ : index]; } __pylist___getitem__.NAME = "__pylist___getitem__"; @@ -2320,10 +2340,10 @@ __pylist_count = function(args, kwargs) { var self = arguments['self']; var obj = arguments['obj']; a = 0; - var __iter14 = self["$wrapped"]; - if (! (__iter14 instanceof Array) ) { __iter14 = __object_keys__(__iter14) } - for (var __idx14=0; __idx14 < __iter14.length; __idx14++) { - var item = __iter14[ __idx14 ]; + var __iter15 = self["$wrapped"]; + if (! (__iter15 instanceof Array || typeof __iter15 == "string") ) { __iter15 = __object_keys__(__iter15) } + for (var __idx15=0; __idx15 < __iter15.length; __idx15++) { + var item = __iter15[ __idx15 ]; if (( item ) == obj) { a += 1; } @@ -2432,7 +2452,7 @@ __pylist_get = function(args, kwargs) { arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var index = arguments['index']; - return self["$wrapped"][index]; + return self["$wrapped"][ (index.__uid__) ? index.__uid__ : index]; } __pylist_get.NAME = "__pylist_get"; @@ -2572,7 +2592,7 @@ __dict___init__ = function(args, kwargs) { arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var js_object = arguments['js_object']; - self["$wrapped"] = { }; + self["$wrapped"] = __jsdict([]); if (js_object) { ob = js_object; if (ob instanceof Array) { @@ -2679,7 +2699,7 @@ __dict_clear = function(args, kwargs) { signature = {"kwargs": Object(), "args": __create_array__("self")}; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; - self["$wrapped"] = { }; + self["$wrapped"] = __jsdict([]); } __dict_clear.NAME = "__dict_clear"; @@ -2979,11 +2999,11 @@ __dict_values = function(args, kwargs) { var self = arguments['self']; keys = Object.keys(self["$wrapped"]); out = []; - var __iter15 = keys; - if (! (__iter15 instanceof Array) ) { __iter15 = __object_keys__(__iter15) } - for (var __idx15=0; __idx15 < __iter15.length; __idx15++) { - var key = __iter15[ __idx15 ]; - out.push(self["$wrapped"][key]); + var __iter16 = keys; + if (! (__iter16 instanceof Array || typeof __iter16 == "string") ) { __iter16 = __object_keys__(__iter16) } + for (var __idx16=0; __idx16 < __iter16.length; __idx16++) { + var key = __iter16[ __idx16 ]; + out.push(self["$wrapped"][ (key.__uid__) ? key.__uid__ : key]); } return out; } @@ -3061,7 +3081,7 @@ set = function(args, kwargs) { } hashtable = null; if (( a.length ) <= 1536) { - hashtable = { }; + hashtable = __jsdict([]); keys = []; if (( a.length ) < 6) { mask = 7; @@ -3083,10 +3103,10 @@ set = function(args, kwargs) { } fallback = false; if (hashtable) { - var __iter16 = a; - if (! (__iter16 instanceof Array) ) { __iter16 = __object_keys__(__iter16) } - for (var __idx16=0; __idx16 < __iter16.length; __idx16++) { - var b = __iter16[ __idx16 ]; + var __iter17 = a; + if (! (__iter17 instanceof Array || typeof __iter17 == "string") ) { __iter17 = __object_keys__(__iter17) } + for (var __idx17=0; __idx17 < __iter17.length; __idx17++) { + var b = __iter17[ __idx17 ]; if (typeof(b, "number") && ( b ) === ( (b | 0) )) { key = (b & mask); hashtable[key] = b; @@ -3101,21 +3121,21 @@ set = function(args, kwargs) { } s = []; if (fallback) { - var __iter17 = a; - if (! (__iter17 instanceof Array) ) { __iter17 = __object_keys__(__iter17) } - for (var __idx17=0; __idx17 < __iter17.length; __idx17++) { - var item = __iter17[ __idx17 ]; + var __iter18 = a; + if (! (__iter18 instanceof Array || typeof __iter18 == "string") ) { __iter18 = __object_keys__(__iter18) } + for (var __idx18=0; __idx18 < __iter18.length; __idx18++) { + var item = __iter18[ __idx18 ]; if (( s.indexOf(item) ) == -1) { s.push(item); } } } else { keys.sort(); - var __iter18 = keys; - if (! (__iter18 instanceof Array) ) { __iter18 = __object_keys__(__iter18) } - for (var __idx18=0; __idx18 < __iter18.length; __idx18++) { - var key = __iter18[ __idx18 ]; - s.push(hashtable[key]); + var __iter19 = keys; + if (! (__iter19 instanceof Array || typeof __iter19 == "string") ) { __iter19 = __object_keys__(__iter19) } + for (var __idx19=0; __idx19 < __iter19.length; __idx19++) { + var key = __iter19[ __idx19 ]; + s.push(hashtable[ (key.__uid__) ? key.__uid__ : key]); } } return s; @@ -3149,9 +3169,9 @@ var array, __array_attrs, __array_parents; __array_attrs = Object(); __array_parents = []; __array_properties = Object(); -__array_typecodes = { "c":1,"b":1,"B":1,"u":2,"h":2,"H":2,"i":4,"I":4,"l":4,"L":4,"f":4,"d":8,"float32":4,"float16":2,"float8":1,"int32":4,"uint32":4,"int16":2,"uint16":2,"int8":1,"uint8":1 }; +__array_typecodes = __jsdict([["c", 1], ["b", 1], ["B", 1], ["u", 2], ["h", 2], ["H", 2], ["i", 4], ["I", 4], ["l", 4], ["L", 4], ["f", 4], ["d", 8], ["float32", 4], ["float16", 2], ["float8", 1], ["int32", 4], ["uint32", 4], ["int16", 2], ["uint16", 2], ["int8", 1], ["uint8", 1]]); __array_attrs["typecodes"] = __array_typecodes; -__array_typecode_names = { "c":"Int8","b":"Int8","B":"Uint8","u":"Uint16","h":"Int16","H":"Uint16","i":"Int32","I":"Uint32","f":"Float32","d":"Float64","float32":"Float32","float16":"Int16","float8":"Int8","int32":"Int32","uint32":"Uint32","int16":"Int16","uint16":"Uint16","int8":"Int8","uint8":"Uint8" }; +__array_typecode_names = __jsdict([["c", "Int8"], ["b", "Int8"], ["B", "Uint8"], ["u", "Uint16"], ["h", "Int16"], ["H", "Uint16"], ["i", "Int32"], ["I", "Uint32"], ["f", "Float32"], ["d", "Float64"], ["float32", "Float32"], ["float16", "Int16"], ["float8", "Int8"], ["int32", "Int32"], ["uint32", "Uint32"], ["int16", "Int16"], ["uint16", "Uint16"], ["int8", "Int8"], ["uint8", "Uint8"]]); __array_attrs["typecode_names"] = __array_typecode_names; __array___init__ = function(args, kwargs) { var size, buff; @@ -3582,7 +3602,7 @@ __array_to_ascii.types_signature = { }; __array_to_ascii.pythonscript_function = true; __array_attrs["to_ascii"] = __array_to_ascii; array = create_class("array", __array_parents, __array_attrs, __array_properties); -json = { "loads":(function (s) {return JSON.parse(s)}),"dumps":(function (o) {return JSON.stringify(o)}) }; +json = __jsdict([["loads", (function (s) {return JSON.parse(s)})], ["dumps", (function (o) {return JSON.stringify(o)})]]); _to_pythonjs = function(args, kwargs) { var set, keys, raw, jstype, output, append; if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index 1f5fecd..7a283c8 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -1,4 +1,5 @@ #!/usr/bin/env python +# _*_ coding: utf-8 _*_ # Python to PythonJS Translator # by Amirouche Boubekki and Brett Hartshorn - copyright 2013 # License: "New BSD" @@ -361,25 +362,21 @@ def visit_Assert(self, node): def visit_Dict(self, node): node.returns_type = 'dict' - #keys = [x.s for x in node.keys] - #values = map(self.visit, node.values) - #a = [ '%s=%s'%x for x in zip(keys, values) ] - #b = 'JSObject(%s)' %', '.join(a) - #return '__get__(dict, "__call__")([], JSObject(js_object=%s))' %b a = [] for i in range( len(node.keys) ): k = self.visit( node.keys[ i ] ) v = self.visit( node.values[i] ) if self._with_js or self._with_dart: - if isinstance(node.keys[i], ast.Str): - a.append( '%s:%s'%(k,v) ) - else: - a.append( '"%s":%s'%(k,v) ) + #if isinstance(node.keys[i], ast.Str): + # a.append( '%s:%s'%(k,v) ) + #else: + # a.append( '"%s":%s'%(k,v) ) + a.append( '[%s,%s]'%(k,v) ) else: a.append( 'JSObject(key=%s, value=%s)'%(k,v) ) if self._with_js or self._with_dart: b = ','.join( a ) - return '{ %s }' %b + return '__jsdict( [%s] )' %b else: b = '[%s]' %', '.join(a) return '__get__(dict, "__call__")([], JSObject(js_object=%s))' %b @@ -570,6 +567,8 @@ def visit_Yield(self, node): def _get_js_class_base_init(self, node ): for base in node.bases: + if base.id == 'object': + continue n = self._js_classes[ base.id ] if hasattr(n, '_cached_init'): return n._cached_init @@ -681,7 +680,14 @@ def _visit_js_classdef(self, node): else: writer.write('pass') + ## instance UID ## + writer.write('this.__uid__ = "" + _PythonJS_UID') + writer.write('_PythonJS_UID += 1') + writer.pull() + ## class UID ## + writer.write('%s.__uid__ = "" + _PythonJS_UID' %name) + writer.write('_PythonJS_UID += 1') keys = methods.keys() keys.sort() @@ -704,7 +710,8 @@ def _visit_js_classdef(self, node): ' }', '}' ] - writer.write( ''.join(a) ) + a = ''.join(a) + writer.write( "JS('%s')" %a ) self._in_js_class = False @@ -941,10 +948,10 @@ def visit_BinOp(self, node): elif op == '*' and isinstance(node.left, ast.List): if len(node.left.elts) == 1 and isinstance(node.left.elts[0], ast.Name) and node.left.elts[0].id == 'None': - if self._with_js: - return 'new Array(%s)' %self.visit(node.right) - else: - return 'JS("new Array(%s)")' %self.visit(node.right) + #if self._with_js: + # return 'new Array(%s)' %self.visit(node.right) + #else: + return 'JS("new Array(%s)")' %self.visit(node.right) elif isinstance(node.right,ast.Num): n = node.right.n elif isinstance(node.right, Name): @@ -1164,8 +1171,14 @@ def visit_Subscript(self, node): elif self._with_js or self._with_dart: if isinstance(node.slice, ast.Slice): ## allow slice on Array return '%s.__getslice__(%s)'%(name, self.visit(node.slice)) - else: + elif self._with_dart: + return '%s[ %s ]' %(name, self.visit(node.slice)) + + elif isinstance(node.slice, ast.Index) and isinstance(node.slice.value, ast.Num): return '%s[ %s ]' %(name, self.visit(node.slice)) + else: + s = self.visit(node.slice) + return '%s[ __ternary_operator__(%s.__uid__, %s) ]' %(name, s, s) elif isinstance(node.slice, ast.Slice): return '__get__(%s, "__getslice__")([%s], JSObject())' % ( @@ -1742,10 +1755,10 @@ def visit_Call(self, node): def visit_Lambda(self, node): args = [self.visit(a) for a in node.args.args] - if self._with_js: ## TODO is it better to return a normal lambda - return """JS('(function (%s) {return %s})')""" %(','.join(args), self.visit(node.body)) - else: - return 'lambda %s: %s' %(','.join(args), self.visit(node.body)) + #if self._with_js: ## TODO is it better to return a normal lambda + # return """JS('(function (%s) {return %s})')""" %(','.join(args), self.visit(node.body)) + #else: + return 'lambda %s: %s' %(','.join(args), self.visit(node.body)) def visit_FunctionDef(self, node): log('-----------------') diff --git a/pythonjs/pythonjs.py b/pythonjs/pythonjs.py index dd6dbc6..56c7acc 100755 --- a/pythonjs/pythonjs.py +++ b/pythonjs/pythonjs.py @@ -198,11 +198,18 @@ def visit_Call(self, node): return self._visit_call_helper_instanceof( node ) elif name == 'new': - args = map(self.visit, node.args) - if len(args) == 1: - return ' new %s' %args[0] - else: - raise SyntaxError( args ) + args = map(self.visit, node.args) + if len(args) == 1: + return ' new %s' %args[0] + else: + raise SyntaxError( args ) + + elif name == '__ternary_operator__': + args = map(self.visit, node.args) + if len(args) == 2: + return ' (%s) ? %s : %s' %(args[0], args[0], args[1]) + else: + raise SyntaxError( args ) elif name == 'JSObject': if node.keywords: diff --git a/runtime/builtins.py b/runtime/builtins.py index 6625716..17652a6 100644 --- a/runtime/builtins.py +++ b/runtime/builtins.py @@ -26,6 +26,15 @@ ## when translated methods named: "get" become __jsdict_get(ob,key,default) with javascript: + def __jsdict( items ): + d = JS("{}") + for item in items: + key = item[0] + if key.__uid__: + key = key.__uid__ + d[ key ] = item[1] + return d + def __jsdict_get(ob, key, default_value=None): if instanceof(ob, Object): if JS("key in ob"): return ob[key] @@ -86,7 +95,7 @@ def __object_keys__(ob): def __bind_property_descriptors__(o, klass): for name in klass.__properties__: - desc = {enumerable:True} + desc = {"enumerable":True} prop = klass.__properties__[ name ] if prop['get']: desc['get'] = __generate_getter__(klass, o, name) From 45538aa5650e38ad297cd266e044c19dec44f743 Mon Sep 17 00:00:00 2001 From: hartsantler Date: Sun, 12 Jan 2014 20:30:41 -0800 Subject: [PATCH 070/521] core: fixed javascript mode "a[ Object ] = XXX" --- pythonjs.js | 26 ++++----- pythonjs/python_to_pythonjs.py | 9 ++- tests/test_dict_advanced_js.html | 98 ++++++++++++++++++++++++++++++++ 3 files changed, 119 insertions(+), 14 deletions(-) create mode 100644 tests/test_dict_advanced_js.html diff --git a/pythonjs.js b/pythonjs.js index c1fe423..73c4082 100644 --- a/pythonjs.js +++ b/pythonjs.js @@ -1,4 +1,4 @@ -// PythonJS Runtime - regenerated on: Sun Jan 12 20:04:43 2014 +// PythonJS Runtime - regenerated on: Sun Jan 12 20:28:10 2014 __NULL_OBJECT__ = Object.create(null); if (( "window" ) in this && ( "document" ) in this) { __NODEJS__ = false; @@ -384,7 +384,7 @@ __jsdict = function(items) { if (key.__uid__) { key = key.__uid__; } - d[key] = item[1]; + d[ (key.__uid__) ? key.__uid__ : key] = item[1]; } return d; } @@ -411,7 +411,7 @@ __jsdict_get.kwargs_signature = { default_value:undefined }; __jsdict_get.types_signature = { default_value:"None" }; __jsdict_set = function(ob, key, value) { if (ob instanceof Object) { - ob[key] = value; + ob[ (key.__uid__) ? key.__uid__ : key] = value; } else { ob.set(key,value); } @@ -501,10 +501,10 @@ __bind_property_descriptors__ = function(o, klass) { desc = __jsdict([["enumerable", true]]); prop = klass.__properties__[ (name.__uid__) ? name.__uid__ : name]; if (prop[ ("get".__uid__) ? "get".__uid__ : "get"]) { - desc["get"] = __generate_getter__(klass, o, name); + desc[ ("get".__uid__) ? "get".__uid__ : "get"] = __generate_getter__(klass, o, name); } if (prop[ ("set".__uid__) ? "set".__uid__ : "set"]) { - desc["set"] = __generate_setter__(klass, o, name); + desc[ ("set".__uid__) ? "set".__uid__ : "set"] = __generate_setter__(klass, o, name); } Object.defineProperty(o, name, desc); } @@ -566,13 +566,13 @@ create_class = function(class_name, parents, attrs, props) { for (var __idx5=0; __idx5 < __iter5.length; __idx5++) { var key = __iter5[ __idx5 ]; if (( typeof(attrs[ (key.__uid__) ? key.__uid__ : key]) ) == "function") { - klass.__unbound_methods__[key] = attrs[ (key.__uid__) ? key.__uid__ : key]; + klass.__unbound_methods__[ (key.__uid__) ? key.__uid__ : key] = attrs[ (key.__uid__) ? key.__uid__ : key]; klass.__all_method_names__.push(key); } if (( key ) == "__getattribute__") { continue } - klass[key] = attrs[ (key.__uid__) ? key.__uid__ : key]; + klass[ (key.__uid__) ? key.__uid__ : key] = attrs[ (key.__uid__) ? key.__uid__ : key]; } klass.__setters__ = []; klass.__getters__ = []; @@ -1151,7 +1151,7 @@ _setup_array_prototype = function(args, kwargs) { item = this[ (i.__uid__) ? i.__uid__ : i]; if (( typeof(item) ) == "object") { if (item.jsify) { - this[i] = item.jsify(); + this[ (i.__uid__) ? i.__uid__ : i] = item.jsify(); } } i += 1; @@ -1213,7 +1213,7 @@ _setup_array_prototype = function(args, kwargs) { if (( index ) < 0) { index = (this.length + index); } - this[index] = value; + this[ (index.__uid__) ? index.__uid__ : index] = value; } __setitem__.NAME = "__setitem__"; @@ -2152,7 +2152,7 @@ __pylist___setitem__ = function(args, kwargs) { var self = args[ 0 ]; var index = args[ 1 ]; var value = args[ 2 ]; - self["$wrapped"][index] = value; + self["$wrapped"][ (index.__uid__) ? index.__uid__ : index] = value; } __pylist___setitem__.NAME = "__pylist___setitem__"; @@ -2474,7 +2474,7 @@ __pylist_set = function(args, kwargs) { var self = arguments['self']; var index = arguments['index']; var value = arguments['value']; - self["$wrapped"][index] = value; + self["$wrapped"][ (index.__uid__) ? index.__uid__ : index] = value; } __pylist_set.NAME = "__pylist_set"; @@ -3109,7 +3109,7 @@ set = function(args, kwargs) { var b = __iter17[ __idx17 ]; if (typeof(b, "number") && ( b ) === ( (b | 0) )) { key = (b & mask); - hashtable[key] = b; + hashtable[ (key.__uid__) ? key.__uid__ : key] = b; keys.push(key); } else { fallback = true; @@ -3717,7 +3717,7 @@ _to_json = function(args, kwargs) { key = __next__(); value = _to_json([__jsdict_get(pythonjs, key)], __NULL_OBJECT__); key = _to_json([key], __NULL_OBJECT__); - r[key] = value; + r[ (key.__uid__) ? key.__uid__ : key] = value; } } else { r = pythonjs; diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index 7a283c8..a362c34 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -1233,10 +1233,17 @@ def _visit_assign_helper(self, node, target): #code = '%s["$wrapped"] = %s' %(self.visit(target.value), self.visit(node.value)) code = '%s[...] = %s' %(self.visit(target.value), self.visit(node.value)) - elif self._with_js or self._with_dart: + elif self._with_dart: code = '%s[ %s ] = %s' code = code % (self.visit(target.value), self.visit(target.slice.value), self.visit(node.value)) + elif self._with_js: + s = self.visit(target.slice.value) + if isinstance(target.slice.value, ast.Num): + code = '%s[ %s ] = %s' % (self.visit(target.value), s, self.visit(node.value)) + else: + code = '%s[ __ternary_operator__(%s.__uid__, %s) ] = %s' % (self.visit(target.value), s, s, self.visit(node.value)) + elif name in self._func_typedefs and self._func_typedefs[name] == 'list': #code = '%s[...][%s] = %s'%(name, self.visit(target.slice.value), self.visit(node.value)) code = '%s[%s] = %s'%(name, self.visit(target.slice.value), self.visit(node.value)) diff --git a/tests/test_dict_advanced_js.html b/tests/test_dict_advanced_js.html new file mode 100644 index 0000000..641664d --- /dev/null +++ b/tests/test_dict_advanced_js.html @@ -0,0 +1,98 @@ + + + + + + + + + + + \ No newline at end of file From 414a7090d531332a40b5b10a0c3d730c8a45739a Mon Sep 17 00:00:00 2001 From: hartsantler Date: Mon, 13 Jan 2014 01:36:58 -0800 Subject: [PATCH 071/521] Brython AST: for loop ast node --- bindings/ast.py | 19 ++++++++++++++++++- tests/test_AST.html | 13 +++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/bindings/ast.py b/bindings/ast.py index 3cc69d1..2c97a68 100644 --- a/bindings/ast.py +++ b/bindings/ast.py @@ -191,6 +191,22 @@ def __init__(self, ctx, node): for child in node.children: self.body.append( to_ast_node(child.get_ctx()) ) +class For: + def __init__(self, ctx, node): + targets = ctx.tree[0] + if targets.type != 'target_list': + raise TypeError + if len(targets.tree) == 1: + self.target = to_ast_node( targets.tree[0] ) + else: ## pack into a ast.Tuple + print('TODO pack for-loop targets into ast.Tuple') + raise TypeError + + self.iter = to_ast_node( ctx.tree[1] ) + self.body = [] + for child in node.children: + self.body.append( to_ast_node(child.get_ctx()) ) + __MAP = { 'def' : FunctionDef, 'assign' : Assign, @@ -204,6 +220,7 @@ def __init__(self, ctx, node): 'op' : BinOp, 'attribute' : Attribute, 'pass' : Pass, + 'for' : For, } def to_ast_node( ctx, node=None ): @@ -297,4 +314,4 @@ def visit_Name(self, node): return node.id def visit_Pass(self, node): - return 'pass' \ No newline at end of file + return 'pass' diff --git a/tests/test_AST.html b/tests/test_AST.html index 5038c39..d15afca 100644 --- a/tests/test_AST.html +++ b/tests/test_AST.html @@ -67,6 +67,11 @@ a = 3 + 3 print('hi else3') +""" + +source = """ +for i in range(10): + a = i * i """ @@ -78,6 +83,14 @@ class DebugVisitor( NodeVisitor ): + def visit_For(self, node): + print 'for', self.visit(node.target), 'in' + self.visit(node.iter) + print ': ## for body' + for a in node.body: + r = self.visit(a) + if r: print ' ', r + def visit_IfExp(self, node): print 'if ', self.visit(node.test), ':' for a in node.body: From fef1ec2c0146b4c6f78a5709229842317b3277c7 Mon Sep 17 00:00:00 2001 From: hartsantler Date: Wed, 15 Jan 2014 06:44:11 -0800 Subject: [PATCH 072/521] import of Brython's py2js.js --- brython/LICENCE.txt | 11 + brython/py2js.js | 4234 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 4245 insertions(+) create mode 100644 brython/LICENCE.txt create mode 100644 brython/py2js.js diff --git a/brython/LICENCE.txt b/brython/LICENCE.txt new file mode 100644 index 0000000..116ae4d --- /dev/null +++ b/brython/LICENCE.txt @@ -0,0 +1,11 @@ +Copyright (c) 2012, Pierre Quentel pierre.quentel@gmail.com +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +Neither the name of the nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/brython/py2js.js b/brython/py2js.js new file mode 100644 index 0000000..001df9b --- /dev/null +++ b/brython/py2js.js @@ -0,0 +1,4234 @@ +// Python to Javascript translation engine + +;(function(){ + +var js,$pos,res,$op + +var $operators = { + "//=":"ifloordiv",">>=":"irshift","<<=":"ilshift", + "**=":"ipow","**":"pow","//":"floordiv","<<":"lshift",">>":"rshift", + "+=":"iadd","-=":"isub","*=":"imul","/=":"itruediv", + "%=":"imod","&=":"iand","|=":"ior","^=":"ixor", + "+":"add","-":"sub","*":"mul", + "/":"truediv","%":"mod","&":"and","|":"or","~":"invert", + "^":"xor","<":"lt",">":"gt", + "<=":"le",">=":"ge","==":"eq","!=":"ne", + "or":"or","and":"and", "in":"in", //"not":"not", + "is":"is","not_in":"not_in","is_not":"is_not" // fake + } + +var $oplist = [] +for(var attr in $operators){$oplist.push(attr)} + +// operators weight for precedence +var $op_order = [['or'],['and'], + ['in','not_in'], + ['<','<=','>','>=','!=','==','is','is_not'], + ['|','^','&'], + ['+'], + ['-'], + ['/','//','%'], + ['*'], + ['**'] +] + +var $op_weight={} +var $weight=1 +for (var $i=0;$i<$op_order.length;$i++){ + for(var $j=0;$j<$op_order[$i].length;$j++){ + $op_weight[$op_order[$i][$j]]=$weight + } + $weight++ +} + +var $augmented_assigns = { + "//=":"ifloordiv",">>=":"irshift","<<=":"ilshift", + "**=":"ipow","+=":"iadd","-=":"isub","*=":"imul","/=":"itruediv", + "%=":"imod", + "&=":"iand","|=":"ior","^=":"ixor" +} + +function $_SyntaxError(context,msg,indent){ + console.log('syntax error '+msg) + var ctx_node = context + while(ctx_node.type!=='node'){ctx_node=ctx_node.parent} + var tree_node = ctx_node.node + var module = tree_node.module + var line_num = tree_node.line_num + __BRYTHON__.line_info = [line_num,module] + if(indent===undefined){ + if(msg.constructor===Array){__BRYTHON__.$SyntaxError(module,msg[0],$pos)} + if(msg==="Triple string end not found"){ + // add an extra argument : used in interactive mode to + // prompt for the rest of the triple-quoted string + __BRYTHON__.$SyntaxError(module,'invalid syntax : triple string end not found',$pos) + } + __BRYTHON__.$SyntaxError(module,'invalid syntax',$pos) + }else{throw __BRYTHON__.$IndentationError(module,msg,$pos)} +} + +var $first_op_letter = [] +for($op in $operators){ + if($first_op_letter.indexOf($op.charAt(0))==-1){ + $first_op_letter.push($op.charAt(0)) + } +} + +function $Node(type){ + this.type = type + this.children=[] + this.add = function(child){ + this.children.push(child) + child.parent = this + } + this.insert = function(pos,child){ + this.children.splice(pos,0,child) + child.parent = this + } + this.toString = function(){return ""} + this.show = function(indent){ + var res = '' + if(this.type==='module'){ + for(var i=0;i0){res += '{'} + res +='\n' + for(var i=0;i0){ + for(var i=0;i0){this.res.push('{')} + this.res.push('\n') + for(var i=0;i0){ + for(var i=0;i0){ + console.log('unbound '+this.unbound+' res length '+this.res.length) + for(var i=0;i1){ + var left_items = left.tree + }else if(left.type==='expr' && + (left.tree[0].type==='list_or_tuple'||left.tree[0].type==='target_list')){ + var left_items = left.tree[0].tree + }else if(left.type==='target_list'){ + var left_items = left.tree + }else if(left.type==='list_or_tuple'){ + var left_items = left.tree + } + var right = this.tree[1] + if(left_items===null){ + return + } + var right_items = null + if(right.type==='list'||right.type==='tuple'|| + (right.type==='expr' && right.tree.length>1)){ + var right_items = right.tree + } + if(right_items!==null){ // form x,y=a,b + if(right_items.length>left_items.length){ + throw Error('ValueError : too many values to unpack (expected '+left_items.length+')') + }else if(right_items.length=0;i--){ + node.parent.insert(rank,new_nodes[i]) + } + $loop_num++ + }else{ // form x,y=a + // evaluate right argument (it might be a function call) + var new_node = new $Node('expression') + new $NodeJSCtx(new_node,'var $right=iter('+right.to_js()+');var $counter=-1') + var new_nodes = [new_node] + + var try_node = new $Node('expression') + // we must set line_num and module to generate __BRYTHON__.line_info + try_node.line_num = node.parent.children[rank].line_num + try_node.module = node.parent.children[rank].module + new $NodeJSCtx(try_node,'try') + new_nodes.push(try_node) + + for(var i=0;i=0;i--){ + node.parent.insert(rank,new_nodes[i]) + } + $loop_num++ + } + } + this.to_js = function(){ + if(this.parent.type==='call'){ // like in foo(x=0) + return '__BRYTHON__.$Kw('+this.tree[0].to_js()+','+this.tree[1].to_js()+')' + }else{ // assignment + var left = this.tree[0] + if(left.type==='expr'){ + left=left.tree[0] + } + var right = this.tree[1] + if(left.type==='attribute'){ // assign to attribute + left.func = 'setattr' + var res = left.to_js() + left.func = 'getattr' + res = res.substr(0,res.length-1) // remove trailing ) + res += ','+right.to_js()+');None;' + return res + }else if(left.type==='sub'){ // assign to item + left.func = 'setitem' // just for to_js() + var res = left.to_js() + res = res.substr(0,res.length-1) // remove trailing ) + left.func = 'getitem' // restore default function + res += ','+right.to_js()+');None;' + return res + } + var scope = $get_scope(this) + if(scope.ntype==="module"){ + var res = 'var '+left.to_js() + //if(scope.module!=='__main__'){res = 'var '+res} + if(left.to_js().charAt(0)!='$'){ + res += '=$globals["'+left.to_js()+'"]' + } + res += '='+right.to_js()+';None;' + return res + }else if(scope.ntype==='def'||scope.ntype==="generator"){ + // assignment in a function : depends if variable is local + // or global + if(scope.globals && scope.globals.indexOf(left.value)>-1){ + return left.to_js()+'=$globals["'+left.to_js()+'"]='+right.to_js() + }else{ // local to scope : prepend 'var' + var scope_id = scope.context.tree[0].id + var locals = __BRYTHON__.scope[scope_id].locals + if(locals.indexOf(left.to_js())===-1){ + locals.push(left.to_js()) + } + var res = 'var '+left.to_js()+'=' + res += '$locals["'+left.to_js()+'"]=' + res += right.to_js()+';None;' + return res + } + }else if(scope.ntype==='class'){ + // assignment in a class : creates a class attribute + left.is_left = true // used in to_js() for ids + var attr = left.to_js() + // Store the JS code in attribute 'in_class' + // In the case of a chained assignment inside a class, eg + // class foo: + // a = b = 0 + // the assignment is split into "b = 0" then "a = b" + // In the second assignment, the JS rendering of b must be + // the same as in the first assignment, ie "$class.b" + left.in_class = '$class.'+attr + return '$class.'+attr+'='+right.to_js() + } + } + } +} + +function $AttrCtx(context){ + this.type = 'attribute' + this.value = context.tree[0] + this.parent = context + context.tree.pop() + context.tree.push(this) + this.tree = [] + this.func = 'getattr' // becomes setattr for an assignment + this.toString = function(){return '(attr) '+this.value+'.'+this.name} + this.to_js = function(){ + var name = this.name + return this.func+'('+this.value.to_js()+',"'+name+'")' + } +} + +function $BodyCtx(context){ + // inline body for def, class, if, elif, else, try... + // creates a new node, child of context node + var ctx_node = context.parent + while(ctx_node.type!=='node'){ctx_node=ctx_node.parent} + var tree_node = ctx_node.node + var body_node = new $Node('expression') + tree_node.insert(0,body_node) + return new $NodeCtx(body_node) +} + +function $BreakCtx(context){ + // used for the keyword "break" + // a flag is associated to the enclosing "for" or "while" loop + // if the loop exits with a break, this flag is set to true + // so that the "else" clause of the loop, if present, is executed + + + this.type = 'break' + this.toString = function(){return 'break '} + this.parent = context + context.tree.push(this) + + // get loop context + var ctx_node = context + while(ctx_node.type!=='node'){ctx_node=ctx_node.parent} + var tree_node = ctx_node.node + var loop_node = tree_node.parent + while(true){ + if(loop_node.type==='module'){ + // "break" is not inside a loop + $_SyntaxError(context,'break outside of a loop') + }else{ + var ctx = loop_node.context.tree[0] + if(ctx.type==='for' || (ctx.type==='condition' && ctx.token==='while')){ + this.loop_ctx = ctx + break + }else if(['def','generator','class'].indexOf(ctx.type)>-1){ + // "break" must not be inside a def or class, even if they are + // enclosed in a loop + $_SyntaxError(context,'break outside of a loop') + }else{ + loop_node=loop_node.parent + } + } + } + + this.to_js = function(){ + return 'var $no_break'+this.loop_ctx.loop_num+'=false;break' + } +} + +function $CallArgCtx(context){ + this.type = 'call_arg' + this.toString = function(){return 'call_arg '+this.tree} + this.parent = context + this.start = $pos + this.tree = [] + context.tree.push(this) + this.expect='id' + this.to_js = function(){return $to_js(this.tree)} +} + +function $CallCtx(context){ + this.type = 'call' + this.func = context.tree[0] + if(this.func!==undefined){ // undefined for lambda + this.func.parent = this + } + this.parent = context + if(context.type!='class'){ + context.tree.pop() + context.tree.push(this) + }else{ + // class parameters + context.args = this + } + this.tree = [] + this.start = $pos + + this.toString = function(){return '(call) '+this.func+'('+this.tree+')'} + + this.to_js = function(){ + if(this.tree.length>0){ + if(this.tree[this.tree.length-1].tree.length==0){ + // from "foo(x,)" + this.tree.pop() + } + } + if(this.func!==undefined && + ['eval','exec'].indexOf(this.func.value)>-1){ + // get module + var ctx_node = this + while(ctx_node.parent!==undefined){ctx_node=ctx_node.parent} + var module = ctx_node.node.module + arg = this.tree[0].to_js() + var ns = '' + var _name = module+',exec_'+Math.random().toString(36).substr(2,8) + if(this.tree.length>1){ + var arg2 = this.tree[1] + if(arg2.tree!==undefined&&arg2.tree.length>0){ + arg2 = arg2.tree[0] + } + if(arg2.tree!==undefined&&arg2.tree.length>0){ + arg2 = arg2.tree[0] + } + if(arg2.type==='call'){ + if(arg2.func.value==='globals'){ + // exec in globals + ns = 'globals' + _name = module + } + }else if(arg2.type==='id'){ + ns = arg2.value + } + } + __BRYTHON__.$py_module_path[_name] = __BRYTHON__.$py_module_path[module] + // replace by the result of an anonymous function with a try/except clause + var res = '(function(){try{' + // insert globals and locals in the function + res += '\nfor(var $attr in $globals){eval("var "+$attr+"=$globals[$attr]")};' + res += '\nfor(var $attr in $locals){eval("var "+$attr+"=$locals[$attr]")};' + // if an argument namespace is passed, insert it + if(ns!=='' && ns!=='globals'){ + res += '\nfor(var $i=0;$i<'+ns+'.$keys.length;$i++){' + res += 'eval("var "+'+ns+'.$keys[$i]+"='+ns+'.$values[$i]")};' + } + // execute the Python code and return its result + // the namespace built inside the function will be in + // __BRYTHON__.scope[_name].__dict__ + res += 'var $jscode = __BRYTHON__.py2js('+arg+',"'+_name+'").to_js();' + res += 'if(__BRYTHON__.debug>1){console.log($jscode)};' + res += 'var $res = eval($jscode);' + res += 'if($res===undefined){return None};return $res' + res += '}catch(err){throw __BRYTHON__.exception(err)}' + res += '})()' + if(ns==='globals'){ + // copy the execution namespace in module and global namespace + res += ';for(var $attr in __BRYTHON__.scope["'+_name+'"].__dict__)' + res += '{window[$attr]=$globals[$attr]=' + res += '__BRYTHON__.scope["'+_name+'"].__dict__[$attr]}' + }else if(ns !=''){ + // use specified namespace + res += ';for(var $attr in __BRYTHON__.scope["'+_name+'"].__dict__)' + res += '{__builtins__.dict.$dict.__setitem__('+ns+',$attr,__BRYTHON__.scope["'+_name+'"].__dict__[$attr])}' + }else{ + // namespace not specified copy the execution namespace in module namespace + res += ';for(var $attr in __BRYTHON__.scope["'+_name+'"].__dict__){' + // check that $attr is a valid identifier + res += '\nif($attr.search(/[\.]/)>-1){continue}\n' + res += 'eval("var "+$attr+"=' + res += '$globals[$attr]=' + res += '__BRYTHON__.scope[\\"'+_name+'\\"].__dict__[$attr]")}' + } + return res + }else if(this.func!==undefined && this.func.value === 'classmethod'){ + return 'classmethod($class,'+$to_js(this.tree)+')' + }else if(this.func!==undefined && this.func.value ==='locals'){ + var scope = $get_scope(this),mod = $get_module(this) + if(scope !== null && (scope.ntype==='def'||scope.ntype=='generator')){ + return 'locals("'+scope.context.tree[0].id+'","'+mod.module+'")' + } + }else if(this.func!==undefined && this.func.value ==='globals'){ + var ctx_node = this + while(ctx_node.parent!==undefined){ctx_node=ctx_node.parent} + var module = ctx_node.node.module + return 'globals("'+module+'")' + }else if(this.func!==undefined && this.func.value ==='dir'){ + if(this.tree.length==0){ + // dir() : pass arguments (null,module name) + var mod=$get_module(this) + return 'dir(null,"'+mod.module+'")' + } + }else if(this.func!==undefined && this.func.value=='$$super'){ + if(this.tree.length==0){ + // super() called with no argument : if inside a class, add the + // class parent as first argument + var scope = $get_scope(this) + if(scope.ntype=='def' || scope.ntype=='generator'){ + if(scope.parent && scope.parent.context.tree[0].type=='class'){ + new $IdCtx(this,scope.parent.context.tree[0].name) + } + } + } + } + else if(this.func!==undefined && this.func.type=='unary'){ + // form " -(x+2) " + var op = this.func.op + if(op=='+'){return $to_js(this.tree)} + else if(op=='-'){return 'getattr('+$to_js(this.tree)+',"__neg__")()'} + else if(op=='~'){return 'getattr('+$to_js(this.tree)+',"__invert__")()'} + } + if(this.tree.length>0){ + return 'getattr('+this.func.to_js()+',"__call__")('+$to_js(this.tree)+')' + }else{return 'getattr('+this.func.to_js()+',"__call__")()'} + } +} + +function $ClassCtx(context){ + this.type = 'class' + this.parent = context + this.tree = [] + context.tree.push(this) + this.expect = 'id' + this.toString = function(){return '(class) '+this.name+' '+this.tree+' args '+this.args} + this.transform = function(node,rank){ + + // for an unknown reason, code like + // + // for base in foo: + // class Int: + // A=9 + // + // generates the class declaration twice. To avoid this we use + // a flag this.transformed + if(this.transformed){return} + // doc string + this.doc_string = $get_docstring(node) + + // insert "$class = new Object" + var instance_decl = new $Node('expression') + new $NodeJSCtx(instance_decl,'var $class = {$def_line:__BRYTHON__.line_info}') + node.insert(0,instance_decl) + + // return $class at the end of class definition + var ret_obj = new $Node('expression') + new $NodeJSCtx(ret_obj,'return $class') + node.insert(node.children.length,ret_obj) + + // close function and run it + var run_func = new $Node('expression') + new $NodeJSCtx(run_func,')()') + node.parent.insert(rank+1,run_func) + + // add doc string + rank++ + js = '$'+this.name+'.__doc__='+(this.doc_string || 'None') + var ds_node = new $Node('expression') + new $NodeJSCtx(ds_node,js) + node.parent.insert(rank+1,ds_node) + + // add attribute __module__ + rank++ + js = '$'+this.name+'.__module__="'+$get_module(this).module+'"' + var mod_node = new $Node('expression') + new $NodeJSCtx(mod_node,js) + node.parent.insert(rank+1,mod_node) + + // class constructor + var scope = $get_scope(this) + if(scope.ntype==="module"||scope.ntype!=='class'){ + js = 'var '+this.name + }else{ + js = 'var '+this.name+' = $class.'+this.name + } + js += '=__BRYTHON__.$class_constructor("'+this.name+'",$'+this.name + if(this.args!==undefined){ // class def has arguments + var arg_tree = this.args.tree,args=[],kw=[] + + for(var i=0;i0){ + res += '{'+this.tree[1].to_js()+'}' + } + } + return res + } +} + +function $DecoratorCtx(context){ + this.type = 'decorator' + this.parent = context + context.tree.push(this) + this.tree = [] + this.toString = function(){return '(decorator) '+this.tree} + this.transform = function(node,rank){ + var func_rank=rank+1,children=node.parent.children + var decorators = [this.tree] + while(true){ + if(func_rank>=children.length){$_SyntaxError(context)} + else if(children[func_rank].context.tree[0].type==='decorator'){ + decorators.push(children[func_rank].context.tree[0].tree) + children.splice(func_rank,1) + }else{break} + } + // Associate a random variable name to each decorator + // In a code such as + // class Cl(object): + // def __init__(self): + // self._x = None + // + // @property + // def x(self): + // return self._x + // + // @x.setter + // def x(self, value): + // self._x = value + // + // we can't replace the decorated methods by something like + // + // def x(self): + // return self._x + // x = property(x) # [1] + // + // def x(self,value): # [2] + // self._x = value + // x = x.setter(x) # [3] + // + // because when we want to use x.setter in [3], x is no longer the one + // defined in [1] : it has been reset by the function declaration in [2] + // The technique used here is to replace these lines by : + // + // $vth93h6g = property # random variable name + // def x(self): + // return self._x + // x = $vth93h6g(x) + // + // $h3upb5s8 = x.setter + // def x(self, value): + // self._x = value + // x = $h3upb5s8(x) + // + this.dec_ids = [] + for(var i=0;i0){required=required.substr(0,required.length-1)} + //if(defaults.length>0){defaults=defaults.substr(0,defaults.length-1)} + + var nodes = [] + // add lines of code to node children + var js = 'var $locals = __BRYTHON__.scope["'+this.id+'"].__dict__={}' + var new_node = new $Node('expression') + new $NodeJSCtx(new_node,js) + nodes.push(new_node) + + // initialize default variables + var js = 'for(var $var in $defaults){eval("var "+$var+"=$locals[$var]=$defaults[$var]")}' + var new_node = new $Node('expression') + new $NodeJSCtx(new_node,js) + nodes.push(new_node) + + for(var i=this.enclosing.length-1;i>=0;i--){ + var js = 'var $ns=__BRYTHON__.scope["'+this.enclosing[i]+'"].__dict__' + var new_node = new $Node('expression') + new $NodeJSCtx(new_node,js) + nodes.push(new_node) + + var js = 'for(var $var in $ns){$locals[$var]=$ns[$var]}' + var new_node = new $Node('expression') + new $NodeJSCtx(new_node,js) + nodes.push(new_node) + } + + var js = 'var $ns=__BRYTHON__.$MakeArgs("'+this.name+'",arguments,['+required+'],' + js += '['+defaults.join(',')+'],'+other_args+','+other_kw+',['+after_star.join(',')+'])' + var new_node = new $Node('expression') + new $NodeJSCtx(new_node,js) + nodes.push(new_node) + + var js = 'for(var $var in $ns){eval("var "+$var+"=$ns[$var]");' + js += '$locals[$var]=$ns[$var]}' + var new_node = new $Node('expression') + new $NodeJSCtx(new_node,js) + nodes.push(new_node) + + for(var i=nodes.length-1;i>=0;i--){ + node.children.splice(0,0,nodes[i]) + } + + var def_func_node = new $Node('expression') + new $NodeJSCtx(def_func_node,'return function()') + + // wrap function body in a try/catch + var try_node = new $Node('expression') + new $NodeJSCtx(try_node,'try') + + for(var i=0;i-1){ + // global variable + js+='delete $globals["'+expr.to_js()+'"]' + }else{ // local variable + js+='delete $locals["'+expr.to_js()+'"]' + } + } + return js + }else if(expr.type==='sub'){ + expr.func = 'delitem' + js = expr.to_js() + expr.func = 'getitem' + return js + }else{ + if(expr.type==='op'){ + $_SyntaxError(this,["can't delete operator"]) + }else if(expr.type==='call'){ + $_SyntaxError(this,["can't delete function call"]) + }else if(expr.type==='attribute'){ + return 'delattr('+expr.value.to_js()+',"'+expr.name+'")' + }else{ + $_SyntaxError(this,["can't delete "+expr.type]) + } + } + } + } +} + +function $DictOrSetCtx(context){ + // the real type (dist or set) is set inside $transition + // as attribute 'real' + this.type = 'dict_or_set' + this.real = 'dict_or_set' + this.expect = 'id' + this.closed = false + this.start = $pos + this.toString = function(){ + if(this.real==='dict'){return '(dict) {'+this.items+'}'} + else if(this.real==='set'){return '(set) {'+this.tree+'}'} + else{return '(dict_or_set) {'+this.tree+'}'} + } + this.parent = context + this.tree = [] + context.tree.push(this) + this.to_js = function(){ + if(this.real==='dict'){ + var res = '__BRYTHON__.$dict([' + for(var i=0;i=0;i--){ + node.parent.insert(rank,new_nodes[i]) + } + + // add lines to get next item in iterator, or exit the loop + // if __next__ raises StopIteration + var try_node = new $Node('expression') + new $NodeJSCtx(try_node,'try') + node.insert(0,try_node) + + var iter_node = new $Node('expression') + var context = new $NodeCtx(iter_node) // create ordinary node + var target_expr = new $ExprCtx(context,'left',true) + target_expr.tree = target.tree + var assign = new $AssignCtx(target_expr) // assignment to left operand + assign.tree[1] = new $JSCode('$next'+$loop_num+'()') + try_node.add(iter_node) + + var catch_node = new $Node('expression') + var js = 'catch($err){if(__BRYTHON__.is_exc($err,[__builtins__.StopIteration])){__BRYTHON__.$pop_exc();break}' + js += 'else{throw($err)}}' + new $NodeJSCtx(catch_node,js) + node.insert(1,catch_node) + + // set new loop children + node.parent.children[rank+1].children = children + $loop_num++ + } + this.to_js = function(){ + var iterable = this.tree.pop() + return 'for '+$to_js(this.tree)+' in '+iterable.to_js() + } +} + +function $FromCtx(context){ + this.type = 'from' + this.parent = context + this.module = '' + this.names = [] + this.aliases = {} + context.tree.push(this) + this.expect = 'module' + this.toString = function(){ + var res = '(from) '+this.module+' (import) '+this.names + res += '(as)' + this.aliases + return res + } + this.to_js = function(){ + var scope = $get_scope(this) + var mod = $get_module(this).module + if(mod.substr(0,13)==='__main__,exec'){mod='__main__'} + var path = __BRYTHON__.$py_module_path[mod] + var elts = path.split('/') + elts.pop() + path =elts.join('/') + // temporarily add module path to __BRYTHON__.path + var res = '' + var indent = $get_node(this).indent + var head = '' + for(var i=0;i-1){ + res += 'var ' + } + var alias = this.aliases[this.names[i]]||this.names[i] + res += alias + if(scope.ntype == 'def'){ + res += '=$locals["'+alias+'"]' + }else if(scope.ntype=='module'){ + res += '=$globals["'+alias+'"]' + } + res += '=getattr($mod,"'+this.names[i]+'")\n' + } + }else{ + if(this.names[0]=='*'){ + res += '__BRYTHON__.$import("'+this.module+'","'+mod+'")\n' + res += head+'var $mod=__BRYTHON__.imported["'+this.module+'"]\n' + res += head+'for(var $attr in $mod){\n' + res +="if($attr.substr(0,1)!=='_')\n"+head+"{var $x = 'var '+$attr+'" + if(scope.ntype==="module"){ + res += '=__BRYTHON__.scope["'+scope.module+'"].__dict__["'+"'+$attr+'"+'"]' + } + res += '=$mod["'+"'+$attr+'"+'"]'+"'"+'\n'+head+'eval($x)}}' + }else{ + res += '__BRYTHON__.$import_from("'+this.module+'",[' + for(var i=0;i-1){ + return + } + for(var i=0;i-1){ + if(ctx.vars===undefined){ctx.vars=[value]} + else if(ctx.vars.indexOf(value)===-1){ctx.vars.push(value)} + if(this.call_arg&&ctx.type==='lambda'){ + if(ctx.locals===undefined){ctx.locals=[value]} + else{ctx.locals.push(value)} + } + } + ctx = ctx.parent + } + + var scope = $get_scope(this) + if(scope.ntype=='def' || scope.ntype=='generator'){ + // if variable is declared inside a comprehension, don't add it to function + // namespace + var _ctx=this.parent + while(_ctx){ + if(_ctx.type=='list_or_tuple' && _ctx.is_comp()){return} + _ctx = _ctx.parent + } + if(context.type=='target_list'){ + if(context.parent.type=='for'){ + // a "for" loop inside the function creates a local variable : + // check if it was not referenced before + $check_unbound(this,scope,value) + }else if(context.parent.type=='comp_for'){ + // Inside a comprehension + // The variables of the same name in the returned elements before "for" + // are not referenced in the function block + var comprehension = context.parent.parent.parent + if(comprehension.parent && comprehension.parent.type=='call_arg'){ + // for the form "func(x for x in iterable)" + comprehension = comprehension.parent + } + var remove = [] + if(scope.var2node && scope.var2node[value]){ + for(var i=0;i=0;i--){ + scope.var2node[value].splice(i,1) + } + } + }else if(context.type=='expr' && context.parent.type=='comp_if'){ + // form {x for x in foo if x>5} : don't put x in referenced names + return + }else if(context.type=='global'){ + if(scope.globals === undefined){ + scope.globals = [value] + }else if(scope.globals.indexOf(value)==-1){ + scope.globals.push(value) + } + }else if(scope.globals===undefined || scope.globals.indexOf(value)==-1){ + // variable referenced in the function + if(scope.var2node===undefined){ + scope.var2node = {} + scope.var2node[value] = [this] + }else if(scope.var2node[value]===undefined){ + scope.var2node[value] = [this] + }else{ + scope.var2node[value].push(this) + } + } + } + + this.transform = function(node,rank){ + // If the variable is used in a function, we store the current node + // context in a dictionary indexed by the variables + // If later there is a local variable assigned with the same + // name, the context will be replaced by raising the exception + // "UnboundLocalError : local variable referenced before assignment" + console.log('transform id '+value) + var scope = $get_scope(this) + if(scope.ntype==='def' || scope.ntype==='generator'){ + var flag = true + var parent=this.parent + while(parent){parent=parent.parent} + if(this.parent.type==='expr' && this.parent.parent.type=='call_arg'){ + // left part of a keyword argument + if(this.parent.parent.tree[0].type==='kwarg'){ + var flag = false + } + } + if(flag){ + console.log('add '+value+' to scope') + var ctx = this.parent + while(ctx.parent!==undefined){ctx=ctx.parent} + var ctx_node = ctx.node + if(scope.var2node===undefined){ + scope.var2node = {value:[ctx_node]} + }else if(scope.var2node[value]===undefined){ + scope.var2node[value] = [ctx_node] + }else{ + scope.var2node[value].push(ctx_node) + } + } + } + } + + this.to_js = function(arg){ + var val = this.value + if(['print','eval','open'].indexOf(this.value)>-1){val = '$'+val} + if(['locals','globals'].indexOf(this.value)>-1){ + if(this.parent.type==='call'){ + var scope = $get_scope(this) + if(scope.ntype==="module"){new $StringCtx(this.parent,'"__main__"')} + else{ + var locals = scope.context.tree[0].locals + var res = '{' + for(var i=0;i-1){ + res += 'var ' + }else if(j==0 && scope.ntype==="module" && scope.module !=="__main__"){ + res += 'var ' + } + var key = parts.slice(0,j+1).join('.') + var alias = key + if(j==parts.length-1){alias = this.tree[i].alias} + res += alias + if(scope.ntype == 'def' || scope.ntype==="generator"){ + res += '=$locals["'+alias+'"]' + }else if(scope.ntype==="module"){ + res += '=$globals["'+alias+'"]' + } + res += '=__BRYTHON__.scope["'+key+'"].__dict__;' + } + } + // add None for interactive console + res += 'None;' + return res + } +} + +function $ImportedModuleCtx(context,name){ + this.type = 'imported module' + this.toString = function(){return ' (imported module) '+this.name} + this.parent = context + this.name = name + this.alias = name + context.tree.push(this) + this.to_js = function(){ + return '"'+this.name+'"' + } +} + +function $IntCtx(context,value){ + this.type = 'int' + this.value = value + this.toString = function(){return 'int '+this.value} + this.parent = context + this.tree = [] + context.tree.push(this) + this.to_js = function(){return 'Number('+this.value+')'} +} + +function $JSCode(js){ + this.js = js + this.toString = function(){return this.js} + this.to_js = function(){return this.js} +} + +function $KwArgCtx(context){ + this.type = 'kwarg' + this.toString = function(){return 'kwarg '+this.tree[0]+'='+this.tree[1]} + this.parent = context.parent + this.tree = [context.tree[0]] + // operation replaces left operand + context.parent.tree.pop() + context.parent.tree.push(this) + + // put id in list of kwargs + // used to avoid passing the id as argument of a list comprehension + var value = this.tree[0].value + var ctx = context + while(ctx.parent!==undefined){ + if(['list_or_tuple','dict_or_set','call_arg','def','lambda'].indexOf(ctx.type)>-1){ + if(ctx.kwargs===undefined){ctx.kwargs=[value]} + else if(ctx.kwargs.indexOf(value)===-1){ctx.kwargs.push(value)} + } + ctx = ctx.parent + } + + // If the keyword argument occurs inside a function, remove the occurence + // from referenced variables in the function + var scope = $get_scope(this) + if(scope.ntype=='def' || scope.ntype=='generator'){ + var ix = null,varname=context.tree[0].value + //ui slider caused an issue in which scope.var2node[varname] is undefined + // so lets check for that. + if (scope.var2node[varname] !== undefined) { + for(var i=0;i-1 + } + this.get_src = function(){ + var ctx_node = this + while(ctx_node.parent!==undefined){ctx_node=ctx_node.parent} + var module = ctx_node.node.module + return document.$py_src[module] + } + this.to_js = function(){ + if(this.real==='list'){return 'list.__call__(['+$to_js(this.tree)+'])'} + else if(['list_comp','gen_expr','dict_or_set_comp'].indexOf(this.real)>-1){ + var src = this.get_src() + var res = '__BRYTHON__.$mkdict($globals,$locals),' + + var qesc = new RegExp('"',"g") // to escape double quotes in arguments + for(var i=1;i1){ + var new_node = new $Node('expression') + var ctx = new $NodeCtx(new_node) + ctx.tree = [this.tree[1]] + new_node.indent = node.indent+4 + this.tree.pop() + node.add(new_node) + } + return $to_js(this.tree) + } +} + +function $NodeJSCtx(node,js){ // used for raw JS code + this.node = node + node.context = this + this.type = 'node_js' + this.tree = [js] + this.toString = function(){return 'js '+js} + this.to_js = function(){return js} +} + +function $NonlocalCtx(context){ + // for the moment keep this as alias for global + this.type = 'global' + this.parent = context + this.tree = [] + context.tree.push(this) + this.expect = 'id' + this.toString = function(){return 'global '+this.tree} + this.transform = function(node,rank){ + var scope = $get_scope(this) + if(scope.globals===undefined){scope.globals=[]} + for(var i=0;i1){this.tree.pop()} + return 'throw '+$to_js(this.tree) + } + } +} + +function $RawJSCtx(context,js){ + context.tree.push(this) + this.parent = context + this.toString = function(){return '(js) '+js} + this.to_js = function(){return js} +} + +function $ReturnCtx(context){ // subscription or slicing + this.type = 'return' + this.toString = function(){return 'return '+this.tree} + this.parent = context + this.tree = [] + context.tree.push(this) + this.to_js = function(){return 'return '+$to_js(this.tree)} +} + +function $SingleKwCtx(context,token){ // used for finally,else + this.type = 'single_kw' + this.token = token + this.parent = context + this.tree = [] + context.tree.push(this) + this.toString = function(){return this.token} + this.to_js = function(){ + if(this.token==='finally'){return this.token} + // For "else" we must check if the previous block was a loop + // If so, check if the loop exited with a "break" to decide + // if the block below "else" should be run + var ctx_node = context + while(ctx_node.type!=='node'){ctx_node=ctx_node.parent} + var tree_node = ctx_node.node + var parent = tree_node.parent + for(var i=0;i0 && ctx.tree[0].alias!==null + && ctx.tree[0].alias!==undefined){ + // syntax "except ErrorName as Alias" + var new_node = new $Node('expression') + var js = 'var '+ctx.tree[0].alias+'=__BRYTHON__.exception($err'+$loop_num+')' + new $NodeJSCtx(new_node,js) + node.parent.children[pos].insert(0,new_node) + } + catch_node.insert(catch_node.children.length, + node.parent.children[pos]) + if(ctx.tree.length===0){ + if(has_default){$_SyntaxError(context,'more than one except: line')} + has_default=true + } + node.parent.children.splice(pos,1) + }else if(ctx.type==='single_kw' && ctx.token==='finally'){ + if(has_else){$_SyntaxError(context,"'finally' after 'else'")} + pos++ + }else if(ctx.type==='single_kw' && ctx.token==='else'){ + if(has_else){$_SyntaxError(context,"more than one 'else'")} + has_else = true + else_body = node.parent.children[pos] + node.parent.children.splice(pos,1) + }else{break} + } + if(!has_default){ + // if no default except: clause, add a line to throw the + // exception if it was not caught + var new_node = new $Node('expression') + new $NodeJSCtx(new_node,'else{throw $err'+$loop_num+'}') + catch_node.insert(catch_node.children.length,new_node) + } + if(has_else){ + var else_node = new $Node('expression') + new $NodeJSCtx(else_node,'if(!$failed'+$loop_num+')') + for(var i=0;i" : is this.tree[1] + var indent = $ws($get_module(this).indent) + res += '$subiter'+$loop_num+'=getattr(iter('+this.tree[1].to_js()+'),"__next__")\n' + res += indent+'while(true){\n'+indent+$ws(4) + res += 'try{$'+this.func_name+'.$iter.push(' + res += '$subiter'+$loop_num+'())}\n' + res += indent+$ws(4)+'catch($err'+$loop_num+'){\n' + res += indent+$ws(8)+'if($err'+$loop_num+'.__class__.$factory===__builtins__.StopIteration)' + res += '{__BRYTHON__.$pop_exc();break}\n' + res += indent+$ws(8)+'else{throw $err'+$loop_num+'}\n}\n}' + $loop_num++ + return res + } + } +} + + +// used in loops +var $loop_num = 0 +var $iter_num = 0 + +function $add_line_num(node,rank){ + if(node.type==='module'){ + var i=0 + while(i" + // at the end of $aumented_assign, control will be + // passed to the expression + var new_node = new $Node('expression') + var new_ctx = new $NodeCtx(new_node) + var new_expr = new $ExprCtx(new_ctx,'id',false) + var _id = new $IdCtx(new_expr,'$temp') + var assign = new $AssignCtx(context) + assign.tree[0] = _id + _id.parent = assign + + var prefix = '' + + if(['+=','-=','*=','/='].indexOf(op)>-1 && + context.type=='expr' && context.tree[0].type=='id'){ + var scope = $get_scope(context) + prefix='$locals' + if(scope.ntype=='module'){prefix='$globals'} + else if(['def','generator'].indexOf(scope.ntype)>-1){ + if(scope.globals && scope.globals.indexOf(context.tree[0].value)>-1){ + prefix = '$globals' + } + } + } + + + // insert shortcut node if op is += and both args are numbers + var offset = 1 + if(prefix){ + var new_node = new $Node('expression') + var js = 'if($temp.$fast_augm && ' + js += context.to_js()+'.$fast_augm){' + js += context.to_js()+op+'$temp' + js += ';'+prefix+'["'+context.tree[0].value+'"]='+context.to_js() + js += '}' + new $NodeJSCtx(new_node,js) + parent.insert(rank+offset,new_node) + offset++ + } + // insert node 'if(!hasattr(foo,"__iadd__")) + var new_node = new $Node('expression') + var js = '' + if(prefix){js += 'else '} + js += 'if(!hasattr('+context.to_js()+',"'+func+'"))' + new $NodeJSCtx(new_node,js) + parent.insert(rank+offset,new_node) + offset ++ + + // create node for "foo = foo + bar" + var aa1 = new $Node('expression') + var ctx1 = new $NodeCtx(aa1) + var expr1 = new $ExprCtx(ctx1,'clone',false) + expr1.tree = context.tree + for(var i=0;i=0;k--){ + scope.var2node[name].splice(remove[k],1) + } + //if(scope.var2node[name].length==0){scope.var2node[name]==undefined} + + } + } + } +} + +function $get_docstring(node){ + var doc_string='""' + if(node.children.length>0){ + var firstchild = node.children[0] + if(firstchild.context.tree && firstchild.context.tree[0].type=='expr'){ + if(firstchild.context.tree[0].tree[0].type=='str') + doc_string = firstchild.context.tree[0].tree[0].to_js() + } + } + return doc_string +} + +function $get_scope(context){ + // return the $Node indicating the scope of context + // null for the script or a def $Node + var ctx_node = context.parent + while(ctx_node.type!=='node'){ctx_node=ctx_node.parent} + var tree_node = ctx_node.node + var scope = null + while(tree_node.parent && tree_node.parent.type!=='module'){ + var ntype = tree_node.parent.context.tree[0].type + if(['def','class','generator'].indexOf(ntype)>-1){ + scope = tree_node.parent + scope.ntype = ntype + scope.elt = scope.context.tree[0] + return scope + } + tree_node = tree_node.parent + } + scope = tree_node.parent || tree_node // module + scope.ntype = "module" + scope.elt = scope.module + return scope +} + +function $get_module(context){ + var ctx_node = context.parent + while(ctx_node.type!=='node'){ctx_node=ctx_node.parent} + var tree_node = ctx_node.node + var scope = null + while(tree_node.parent.type!=='module'){ + tree_node = tree_node.parent + } + scope = tree_node.parent // module + scope.ntype = "module" + return scope +} + +function $get_node(context){ + var ctx = context + while(ctx.parent){ctx=ctx.parent} + return ctx.node +} + +function $get_ids(ctx){ + var res = [] + if(ctx.type==='expr' && + ctx.tree[0].type==='list_or_tuple' && + ctx.tree[0].real==='list_comp'){return []} + if(ctx.type==='id'){res.push(ctx.value)} + else if(ctx.type==='attribute'||ctx.type==='sub'){ + var res1 = $get_ids(ctx.value) + for(var i=0;i-1){ + context.parent.tree.pop() // remove abstract expression + var commas = context.with_commas + context = context.parent + } + if(token==='id'){return new $IdCtx(new $ExprCtx(context,'id',commas),arguments[2])} + else if(token==='str'){return new $StringCtx(new $ExprCtx(context,'str',commas),arguments[2])} + else if(token==='bytes'){ + console.log('bytes '+arguments[2]) + return new $StringCtx(new $ExprCtx(context,'bytes',commas),arguments[2]) + } + else if(token==='int'){return new $IntCtx(new $ExprCtx(context,'int',commas),arguments[2])} + else if(token==='float'){return new $FloatCtx(new $ExprCtx(context,'float',commas),arguments[2])} + else if(token==='('){return new $ListOrTupleCtx(new $ExprCtx(context,'tuple',commas),'tuple')} + else if(token==='['){return new $ListOrTupleCtx(new $ExprCtx(context,'list',commas),'list')} + else if(token==='{'){return new $DictOrSetCtx(new $ExprCtx(context,'dict_or_set',commas))} + else if(token==='not'){ + if(context.type==='op'&&context.op==='is'){ // "is not" + context.op = 'is_not' + return context + }else{ + return new $NotCtx(new $ExprCtx(context,'not',commas)) + } + }else if(token==='lambda'){return new $LambdaCtx(new $ExprCtx(context,'lambda',commas))} + else if(token==='op'){ + if('+-~'.search(arguments[2])>-1){ // unary + or -, bitwise ~ + return new $UnaryCtx(new $ExprCtx(context,'unary',false),arguments[2]) + }else{$_SyntaxError(context,'token '+token+' after '+context)} + }else if(token=='='){ + $_SyntaxError(context,token) + }else if([')',','].indexOf(token)>-1 && + ['list_or_tuple','call_arg'].indexOf(context.parent.type)==-1){ + console.log('err token '+token+' type '+context.parent.type) + $_SyntaxError(context,token) + }else{return $transition(context.parent,token,arguments[2])} + + }else if(context.type==='assert'){ + + if(token==='eol'){ + return $transition(context.parent,token) + }else{$_SyntaxError(context,token)} + + }else if(context.type==='assign'){ + + if(token==='eol'){return $transition(context.parent,'eol')} + else{$_SyntaxError(context,'token '+token+' after '+context)} + + }else if(context.type==='attribute'){ + + if(token==='id'){ + var name = arguments[2] + //if(name.substr(0,2)=='$$'){name=name.substr(2)} + context.name=name + return context.parent + }else{$_SyntaxError(context,token)} + + }else if(context.type==='break'){ + + if(token==='eol'){return $transition(context.parent,'eol')} + else{$_SyntaxError(context,token)} + + }else if(context.type==='call'){ + if(token===','){return context} + else if($expr_starters.indexOf(token)>-1){ + if(context.has_dstar){$_SyntaxError(context,token)} + var expr = new $CallArgCtx(context) + return $transition(expr,token,arguments[2]) + }else if(token===')'){context.end=$pos;return context.parent} + else if(token==='op'){ + var op=arguments[2] + if(op==='-'||op==='~'){return new $UnaryCtx(new $ExprCtx(context,'unary',false),op)} + else if(op==='+'){return context} + else if(op==='*'){context.has_star = true;return new $StarArgCtx(context)} + else if(op==='**'){context_has_dstar = true;return new $DoubleStarArgCtx(context)} + else{throw Error('SyntaxError')} + }else{return $transition(context.parent,token,arguments[2])} + + }else if(context.type==='call_arg'){ + + if($expr_starters.indexOf(token)>-1 && context.expect==='id'){ + context.expect=',' + var expr = new $AbstractExprCtx(context,false) + return $transition(expr,token,arguments[2]) + }else if(token==='=' && context.expect===','){ + return new $ExprCtx(new $KwArgCtx(context),'kw_value',false) + }else if(token==='for'){ + // comprehension + $clear_ns(context) // if inside function + var lst = new $ListOrTupleCtx(context,'gen_expr') + lst.vars = context.vars // copy variables + lst.locals = context.locals + lst.intervals = [context.start] + context.tree.pop() + lst.expression = context.tree + context.tree = [lst] + lst.tree = [] + var comp = new $ComprehensionCtx(lst) + return new $TargetListCtx(new $CompForCtx(comp)) + }else if(token==='op' && context.expect==='id'){ + var op = arguments[2] + context.expect = ',' + if(op==='+'||op==='-'){ + return $transition(new $AbstractExprCtx(context,false),token,op) + }else if(op==='*'){context.expect=',';return new $StarArgCtx(context)} + else if(op==='**'){context.expect=',';return new $DoubleStarArgCtx(context)} + else{$_SyntaxError(context,'token '+token+' after '+context)} + }else if(token===')'){ + if(context.tree.length>0){ + var son = context.tree[context.tree.length-1] + if(son.type==='list_or_tuple'&&son.real==='gen_expr'){ + son.intervals.push($pos) + } + } + return $transition(context.parent,token) + }else if(token===':' && context.expect===',' && context.parent.parent.type==='lambda'){ + return $transition(context.parent.parent,token) + }else if(token===','&& context.expect===','){ + return new $CallArgCtx(context.parent) + }else{$_SyntaxError(context,'token '+token+' after '+context)} + + }else if(context.type==='class'){ + + if(token==='id' && context.expect==='id'){ + context.name = arguments[2] + context.expect = '(:' + return context + }else if(token==='('){return new $CallCtx(context)} + else if(token===':'){return $BodyCtx(context)} + else{$_SyntaxError(context,'token '+token+' after '+context)} + + //} + //else if(token==='(' && context.expect==='(:'){ + // return $transition(new $AbstractExprCtx(context,true),'(') + //}else if(token===':' && context.expect==='(:'){return $BodyCtx(context)} + //else{$_SyntaxError(context,'token '+token+' after '+context)} + + }else if(context.type==='comp_if'){ + + return $transition(context.parent,token,arguments[2]) + + }else if(context.type==='comp_for'){ + + if(token==='in' && context.expect==='in'){ + context.expect = null + return new $AbstractExprCtx(new $CompIterableCtx(context),true) + }else if(context.expect===null){ + // ids in context.tree[0] are local to the comprehension + return $transition(context.parent,token,arguments[2]) + }else{$_SyntaxError(context,'token '+token+' after '+context)} + + }else if(context.type==='comp_iterable'){ + + return $transition(context.parent,token,arguments[2]) + + }else if(context.type==='comprehension'){ + if(token==='if'){return new $AbstractExprCtx(new $CompIfCtx(context),false)} + else if(token==='for'){return new $TargetListCtx(new $CompForCtx(context))} + else{return $transition(context.parent,token,arguments[2])} + + }else if(context.type==='condition'){ + + if(token===':'){return $BodyCtx(context)} + else{$_SyntaxError(context,'token '+token+' after '+context)} + + }else if(context.type==='decorator'){ + + if(token==='id' && context.tree.length===0){ + return $transition(new $AbstractExprCtx(context,false),token,arguments[2]) + }else if(token==='eol'){return $transition(context.parent,token)} + else{$_SyntaxError(context,'token '+token+' after '+context)} + + }else if(context.type==='def'){ + + if(token==='id'){ + if(context.name){ + $_SyntaxError(context,'token '+token+' after '+context) + }else{ + context.set_name(arguments[2]) + return context + } + }else if(token==='('){context.has_args=true;return new $FuncArgs(context)} + else if(token===':' && context.has_args){return $BodyCtx(context)} + else{$_SyntaxError(context,'token '+token+' after '+context)} + + }else if(context.type==='del'){ + + if(token==='eol'){return $transition(context.parent,token)} + else{$_SyntaxError(context,'token '+token+' after '+context)} + + }else if(context.type==='dict_or_set'){ + + if(context.closed){ + if(token==='['){return new $SubCtx(context.parent)} + else if(token==='('){return new $CallArgCtx(new $CallCtx(context))} + //else if(token==='.'){return new $AttrCtx(context)} + else if(token==='op'){ + return new $AbstractExprCtx(new $OpCtx(context,arguments[2]),false) + }else{return $transition(context.parent,token,arguments[2])} + }else{ + if(context.expect===','){ + if(token==='}'){ + if(context.real==='dict_or_set'&&context.tree.length===1){ + // set with single element + context.real = 'set' + } + if(['set','set_comp','dict_comp'].indexOf(context.real)>-1|| + (context.real==='dict'&&context.tree.length%2===0)){ + context.items = context.tree + context.tree = [] + context.closed = true + return context + }else{$_SyntaxError(context,'token '+token+' after '+context)} + }else if(token===','){ + if(context.real==='dict_or_set'){context.real='set'} + if(context.real==='dict' && context.tree.length%2){ + $_SyntaxError(context,'token '+token+' after '+context) + } + context.expect = 'id' + return context + }else if(token===':'){ + if(context.real==='dict_or_set'){context.real='dict'} + if(context.real==='dict'){ + context.expect=',' + return new $AbstractExprCtx(context,false) + }else{$_SyntaxError(context,'token '+token+' after '+context)} + }else if(token==='for'){ + // comprehension + $clear_ns(context) // if defined inside a function + if(context.real==='dict_or_set'){context.real = 'set_comp'} + else{context.real='dict_comp'} + var lst = new $ListOrTupleCtx(context,'dict_or_set_comp') + lst.intervals = [context.start+1] + lst.vars = context.vars + context.tree.pop() + lst.expression = context.tree + context.tree = [lst] + lst.tree = [] + var comp = new $ComprehensionCtx(lst) + return new $TargetListCtx(new $CompForCtx(comp)) + + }else{$_SyntaxError(context,'token '+token+' after '+context)} + }else if(context.expect==='id'){ + if(token==='}'){ + if(context.tree.length==0){ // empty dict + context.items = [] + context.real = 'dict' + }else{ // trailing comma, eg {'a':1,'b':2,} + context.items = context.tree + } + context.tree = [] + context.closed = true + return context + }else if($expr_starters.indexOf(token)>-1){ + context.expect = ',' + var expr = new $AbstractExprCtx(context,false) + return $transition(expr,token,arguments[2]) + }else{$_SyntaxError(context,'token '+token+' after '+context)} + }else{return $transition(context.parent,token,arguments[2])} + } + + }else if(context.type==='double_star_arg'){ + + if($expr_starters.indexOf(token)>-1){ + return $transition(new $AbstractExprCtx(context,false),token,arguments[2]) + }else if(token===','){return context.parent} + else if(token===')'){return $transition(context.parent,token)} + else if(token===':' && context.parent.parent.type==='lambda'){ + return $transition(context.parent.parent,token) + }else{$_SyntaxError(context,'token '+token+' after '+context)} + + }else if(context.type==='except'){ + + if($expr_starters.indexOf(token)>-1 && context.expect==='id'){ + context.expect = 'as' + return $transition(new $AbstractExprCtx(context,false),token,arguments[2]) + + //if(token==='id' && context.expect==='id'){ + // new $TargetCtx(context,arguments[2]) + // context.expect='as' + // return context + }else if(token==='as' && context.expect==='as' + && context.has_alias===undefined) { // only one alias allowed + context.expect = 'alias' + context.has_alias = true + return context + }else if(token==='id' && context.expect==='alias'){ + context.expect=':' + context.tree[0].alias = arguments[2] + return context + }else if(token===':' && ['id','as',':'].indexOf(context.expect)>-1){ + return $BodyCtx(context) + }else if(token==='(' && context.expect==='id' && context.tree.length===0){ + context.parenth = true + return context + }else if(token===')' && [',','as'].indexOf(context.expect)>-1){ + context.expect = 'as' + return context + }else if(token===',' && context.parenth!==undefined && + context.has_alias === undefined && + ['as',','].indexOf(context.expect)>-1){ + context.expect='id' + return context + }else{$_SyntaxError(context,'token '+token+' after '+context.expect)} + + }else if(context.type==='expr'){ + + if($expr_starters.indexOf(token)>-1 && context.expect==='expr'){ + context.expect = ',' + return $transition(new $AbstractExprCtx(context,false),token,arguments[2]) + }else if(token==='not'&&context.expect===','){ + return new $ExprNot(context) + }else if(token==='in'&&context.expect===','){ + return $transition(context,'op','in') + }else if(token===',' && context.expect===','){ + if(context.with_commas){ + // implicit tuple + context.parent.tree.pop() + var tuple = new $ListOrTupleCtx(context.parent,'tuple') + tuple.tree = [context] + return tuple + }else{return $transition(context.parent,token)} + }else if(token==='.'){return new $AttrCtx(context)} + else if(token==='['){return new $AbstractExprCtx(new $SubCtx(context),false)} + else if(token==='('){return new $CallCtx(context)} + else if(token==='op'){ + // handle operator precedence + var op_parent=context.parent,op=arguments[2] + var op1 = context.parent,repl=null + while(true){ + if(op1.type==='expr'){op1=op1.parent} + else if(op1.type==='op'&&$op_weight[op1.op]>=$op_weight[op]){repl=op1;op1=op1.parent} + else{break} + } + if(repl===null){ + if(['and','or'].indexOf(op)>-1){ + while(context.parent.type==='not'|| + (context.parent.type==='expr'&&context.parent.parent.type==='not')){ + // 'and' and 'or' have higher precedence than 'not' + context = context.parent + op_parent = context.parent + } + }else{ + while(true){ + if(context.parent!==op1){ + context = context.parent + op_parent = context.parent + }else{ + break + } + } + } + context.parent.tree.pop() + var expr = new $ExprCtx(op_parent,'operand',context.with_commas) + expr.expect = ',' + context.parent = expr + var new_op = new $OpCtx(context,op) + return new $AbstractExprCtx(new_op,false) + } + if(repl.type==='op' + && ['<','<=','==','!=','is','>=','>'].indexOf(repl.op)>-1 + && ['<','<=','==','!=','is','>=','>'].indexOf(op)>-1){ + // chained comparisons such as 1 <= 3 < 5 + // replace by (c1 op1 c2) and (c2 op ...) + repl.parent.tree.pop() + var and_expr = new $OpCtx(repl,'and') + var c2 = repl.tree[1] // right operand of op1 + // clone c2 + var c2_clone = new Object() + for(var attr in c2){c2_clone[attr]=c2[attr]} + c2_clone.parent = and_expr + // add fake element to and_expr : it will be removed + // when new_op is created at the next line + and_expr.tree.push('xxx') + var new_op = new $OpCtx(c2_clone,op) + return new $AbstractExprCtx(new_op,false) + } + repl.parent.tree.pop() + var expr = new $ExprCtx(repl.parent,'operand',false) + expr.tree = [op1] + repl.parent = expr + var new_op = new $OpCtx(repl,op) // replace old operation + //var res = new $AbstractExprCtx(new_op,false) + return new $AbstractExprCtx(new_op,false) + + }else if(token==='augm_assign' && context.expect===','){ + return $augmented_assign(context,arguments[2]) + }else if(token==='=' && context.expect===','){ + if(context.parent.type==="call_arg"){ + return new $AbstractExprCtx(new $KwArgCtx(context),true) + }else{ + while(context.parent!==undefined){context=context.parent} + context = context.tree[0] + return new $AbstractExprCtx(new $AssignCtx(context),true) + } + }else if(token==='if' && context.parent.type!=='comp_iterable'){ + // ternary operator : expr1 if cond else expr2 + return new $AbstractExprCtx(new $TernaryCtx(context),false) + }else{return $transition(context.parent,token)} + + }else if(context.type==='expr_not'){ + + if(token==='in'){ // expr not in : operator + context.parent.tree.pop() + return new $AbstractExprCtx(new $OpCtx(context.parent,'not_in'),false) + }else{$_SyntaxError(context,'token '+token+' after '+context)} + + }else if(context.type==='for'){ + + if(token==='in'){return new $AbstractExprCtx(context,true)} + else if(token===':'){return $BodyCtx(context)} + else{$_SyntaxError(context,'token '+token+' after '+context)} + + }else if(context.type==='from'){ + + if((token==='id'||token==='.') && context.expect==='module'){ + if(token==='id'){context.module += arguments[2]} + else{context.module += '.'} + return context + }else if(token==='import' && context.expect==='module'){ + context.expect = 'id' + return context + }else if(token==='id' && context.expect==='id'){ + context.names.push(arguments[2]) + context.expect = ',' + return context + }else if(token==='op' && arguments[2]==='*' + && context.expect==='id' + && context.names.length ===0){ + context.names.push('*') + context.expect = 'eol' + return context + }else if(token===',' && context.expect===','){ + context.expect = 'id' + return context + }else if(token==='eol' && + (context.expect ===',' || context.expect==='eol')){ + return $transition(context.parent,token) + }else if (token==='as' && + (context.expect ===',' || context.expect==='eol')){ + context.expect='alias' + return context + }else if(token==='id' && context.expect==='alias'){ + context.aliases[context.names[context.names.length-1]]= arguments[2] + context.expect=',' + return context + }else if (token==='(' && context.expect === 'id') { + context.expect='id' + return context + }else if (token===')' && context.expect === ',') { + context.expect='eol' + return context + }else{$_SyntaxError(context,'token '+token+' after '+context)} + + + }else if(context.type==='func_arg_id'){ + if(token==='=' && context.expect==='='){ + context.parent.has_default = true + return new $AbstractExprCtx(context,false) + }else if(token===',' || token===')'){ + if(context.parent.has_default && context.tree.length==0){ + $pos -= context.name.length + $_SyntaxError(context,['non-default argument follows default argument']) + }else{ + return $transition(context.parent,token) + } + }else{$_SyntaxError(context,'token '+token+' after '+context)} + + }else if(context.type==='func_args'){ + + if(token==='id' && context.expect==='id'){ + context.expect = ',' + if(context.names.indexOf(arguments[2])>-1){ + $_SyntaxError(context,['duplicate argument '+arguments[2]+' in function definition']) + } + return new $FuncArgIdCtx(context,arguments[2]) + }else if(token===','){ + if(context.has_kw_arg){$_SyntaxError(context,'duplicate kw arg')} + else if(context.expect===','){ + context.expect = 'id' + return context + }else{$_SyntaxError(context,'token '+token+' after '+context)} + }else if(token===')'){ + if(context.expect===','){return context.parent} + else if(context.tree.length==0){return context.parent} // no argument + else{$_SyntaxError(context,'token '+token+' after '+context)} + }else if(token==='op'){ + var op = arguments[2] + context.expect = ',' + if(op=='*'){ + if(context.has_star_arg){$_SyntaxError(context,'duplicate star arg')} + return new $FuncStarArgCtx(context,'*') + }else if(op=='**'){ + return new $FuncStarArgCtx(context,'**') + }else{$_SyntaxError(context,'token '+op+' after '+context)} + }else{$_SyntaxError(context,'token '+token+' after '+context)} + + }else if(context.type==='func_star_arg'){ + + if(token==='id' && context.name===undefined){ + if(context.parent.names.indexOf(arguments[2])>-1){ + $_SyntaxError(context,['duplicate argument '+arguments[2]+' in function definition']) + } + context.set_name(arguments[2]) + context.parent.names.push(arguments[2]) + return context.parent + }else if(token==',' && context.name===undefined){ + // anonymous star arg - found in configparser + context.set_name('$dummy') + context.parent.names.push('$dummy') + return $transition(context.parent,token) + }else if(token==')'){ + // anonymous star arg - found in configparser + context.set_name('$dummy') + context.parent.names.push('$dummy') + return $transition(context.parent,token) + }else{$_SyntaxError(context,'token '+token+' after '+context)} + + }else if(context.type==='global'){ + + if(token==='id' && context.expect==='id'){ + new $IdCtx(context,arguments[2]) + context.expect=',' + return context + }else if(token===',' && context.expect===','){ + context.expect='id' + return context + }else if(token==='eol' && context.expect===','){ + return $transition(context.parent,token) + }else{$_SyntaxError(context,'token '+token+' after '+context)} + + + }else if(context.type==='id'){ + + if(token==='='){ + if(context.parent.type==='expr' && + context.parent.parent !== undefined && + context.parent.parent.type ==='call_arg'){ + return new $AbstractExprCtx(new $KwArgCtx(context.parent),false) + }else{return $transition(context.parent,token,arguments[2])} + }else if(token==='op'){ + return $transition(context.parent,token,arguments[2]) + }else if(['id','str','int','float'].indexOf(token)>-1){ + $_SyntaxError(context,'token '+token+' after '+context) + }else{ + return $transition(context.parent,token,arguments[2]) + } + + }else if(context.type==='import'){ + + if(token==='id' && context.expect==='id'){ + new $ImportedModuleCtx(context,arguments[2]) + context.expect=',' + return context + }else if(token==='.' && context.expect===','){ + context.expect = 'qual' + return context + }else if(token==='id' && context.expect==='qual'){ + context.expect = ',' + context.tree[context.tree.length-1].name += '.'+arguments[2] + context.tree[context.tree.length-1].alias += '.'+arguments[2] + return context + }else if(token===',' && context.expect===','){ + context.expect = 'id' + return context + }else if(token==='as' && context.expect===','){ + context.expect = 'alias' + return context + }else if(token==='id' && context.expect==='alias'){ + context.expect = ',' + context.tree[context.tree.length-1].alias = arguments[2] + var mod_name=context.tree[context.tree.length-1].name; + __BRYTHON__.$py_module_alias[mod_name]=arguments[2] + return context + }else if(token==='eol' && context.expect===','){ + return $transition(context.parent,token) + }else{$_SyntaxError(context,'token '+token+' after '+context)} + + }else if(context.type==='int'||context.type==='float'){ + + if($expr_starters.indexOf(token)>-1){ + $_SyntaxError(context,'token '+token+' after '+context) + }else{return $transition(context.parent,token,arguments[2])} + + }else if(context.type==='kwarg'){ + + if(token===','){return new $CallArgCtx(context.parent)} + else{return $transition(context.parent,token)} + + }else if(context.type==="lambda"){ + + if(token===':' && context.args===undefined){ + context.args = context.tree + context.tree = [] + context.body_start = $pos + return new $AbstractExprCtx(context,false) + }else if(context.args!==undefined){ // returning from expression + context.body_end = $pos + return $transition(context.parent,token) + }else if(context.args===undefined){ + return $transition(new $CallCtx(context),token,arguments[2]) + }else{$_SyntaxError(context,'token '+token+' after '+context)} + + }else if(context.type==='list_or_tuple'){ + + if(context.closed){ + if(token==='['){return new $SubCtx(context.parent)} + else if(token==='('){return new $CallCtx(context)} + else if(token==='op'){ + return new $AbstractExprCtx(new $OpCtx(context,arguments[2]),false) + } + else{return $transition(context.parent,token,arguments[2])} + }else{ + if(context.expect===','){ + if((context.real==='tuple'||context.real==='gen_expr') + && token===')'){ + context.closed = true + if(context.real==='gen_expr'){context.intervals.push($pos)} + return context.parent + }else if((context.real==='list'||context.real==='list_comp') + && token===']'){ + context.closed = true + if(context.real==='list_comp'){context.intervals.push($pos)} + return context + }else if(context.real==='dict_or_set_comp' && token==='}'){ + context.intervals.push($pos) + return $transition(context.parent,token) + }else if(token===','){ + if(context.real==='tuple'){context.has_comma=true} + context.expect = 'id' + return context + }else if(token==='for'){ + // comprehension + if(context.real==='list'){context.real = 'list_comp'} + else{context.real='gen_expr'} + // remove names already referenced in list from the function + // references + $clear_ns(context) + context.intervals = [context.start+1] + context.expression = context.tree + context.tree = [] // reset tree + var comp = new $ComprehensionCtx(context) + return new $TargetListCtx(new $CompForCtx(comp)) + }else{return $transition(context.parent,token,arguments[2])} + }else if(context.expect==='id'){ + if(context.real==='tuple' && token===')'){ + context.closed = true + return context.parent + }else if(context.real==='gen_expr' && token===')'){ + context.closed = true + return $transition(context.parent,token) + }else if(context.real==='list'&& token===']'){ + context.closed = true + return context + }else if(token !==')'&&token!==']'&&token!==','){ + context.expect = ',' + var expr = new $AbstractExprCtx(context,false) + return $transition(expr,token,arguments[2]) + }else if(token==','){ + $_SyntaxError(context,'unexpected comma inside list') + } + }else{return $transition(context.parent,token,arguments[2])} + } + + }else if(context.type==='list_comp'){ + + if(token===']'){return context.parent} + else if(token==='in'){return new $ExprCtx(context,'iterable',true)} + else if(token==='if'){return new $ExprCtx(context,'condition',true)} + else{$_SyntaxError(context,'token '+token+' after '+context)} + + }else if(context.type==='node'){ + + if($expr_starters.indexOf(token)>-1){ + var expr = new $AbstractExprCtx(context,true) + return $transition(expr,token,arguments[2]) + }else if(token==="op" && '+-~'.search(arguments[2])>-1){ + var expr = new $AbstractExprCtx(context,true) + return $transition(expr,token,arguments[2]) + }else if(token==='class'){return new $ClassCtx(context)} + else if(token==='break'){return new $BreakCtx(context)} + else if(token==='def'){return new $DefCtx(context)} + else if(token==='for'){return new $TargetListCtx(new $ForExpr(context))} + else if(['if','elif','while'].indexOf(token)>-1){ + return new $AbstractExprCtx(new $ConditionCtx(context,token),false) + }else if(['else','finally'].indexOf(token)>-1){ + return new $SingleKwCtx(context,token) + }else if(token==='try'){return new $TryCtx(context)} + else if(token==='except'){return new $ExceptCtx(context)} + else if(token==='assert'){return new $AbstractExprCtx(new $AssertCtx(context),'assert',true)} + else if(token==='from'){return new $FromCtx(context)} + else if(token==='import'){return new $ImportCtx(context)} + else if(token==='global'){return new $GlobalCtx(context)} + else if(token==='nonlocal'){return new $NonlocalCtx(context)} + else if(token==='lambda'){return new $LambdaCtx(context)} + else if(token==='pass'){return new $PassCtx(context)} + else if(token==='raise'){return new $RaiseCtx(context)} + else if(token==='return'){ + var ret = new $ReturnCtx(context) + return new $AbstractExprCtx(ret,true) + }else if(token==="with"){return new $AbstractExprCtx(new $WithCtx(context),false)} + else if(token==='yield'){ + var yield = new $YieldCtx(context) + return new $AbstractExprCtx(yield,true) + }else if(token==='del'){return new $AbstractExprCtx(new $DelCtx(context),true)} + else if(token==='@'){return new $DecoratorCtx(context)} + else if(token==='eol'){ + if(context.tree.length===0){ // might be the case after a : + context.node.parent.children.pop() + return context.node.parent.context + } + return context + }else{$_SyntaxError(context,'token '+token+' after '+context)} + + }else if(context.type==='not'){ + if(token==='in'){ // operator not_in + // not is always in an expression : remove it + context.parent.parent.tree.pop() // remove 'not' + return new $ExprCtx(new $OpCtx(context.parent,'not_in'),'op',false) + }else if($expr_starters.indexOf(token)>-1){ + var expr = new $AbstractExprCtx(context,false) + return $transition(expr,token,arguments[2]) + }else{return $transition(context.parent,token)} + + }else if(context.type==='op'){ + + if($expr_starters.indexOf(token)>-1){ + return $transition(new $AbstractExprCtx(context,false),token,arguments[2]) + }else if(token==='op' && '+-~'.search(arguments[2])>-1){ + return new $UnaryCtx(context,arguments[2]) + }else{return $transition(context.parent,token)} + + }else if(context.type==='pass'){ + + if(token==='eol'){return context.parent} + else{$_SyntaxError(context,'token '+token+' after '+context)} + + }else if(context.type==='raise'){ + + if(token==='id' && context.tree.length===0){ + return new $IdCtx(new $ExprCtx(context,'exc',false),arguments[2]) + }else if(token=='from' && context.tree.length>0){ + return new $AbstractExprCtx(context,false) + }else if(token==='eol'){ + return $transition(context.parent,token) + }else{$_SyntaxError(context,'token '+token+' after '+context)} + + }else if(context.type==='return'){ + + return $transition(context.parent,token) + + }else if(context.type==='single_kw'){ + + if(token===':'){return $BodyCtx(context)} + else{$_SyntaxError(context,'token '+token+' after '+context)} + + }else if(context.type==='star_arg'){ + + if($expr_starters.indexOf(token)>-1){ + return $transition(new $AbstractExprCtx(context,false),token,arguments[2]) + }else if(token===','){return $transition(context.parent,token)} + else if(token===')'){return $transition(context.parent,token)} + else if(token===':' && context.parent.parent.type==='lambda'){ + return $transition(context.parent.parent,token) + }else{$_SyntaxError(context,'token '+token+' after '+context)} + + }else if(context.type==='str'){ + + if(token==='['){return new $AbstractExprCtx(new $SubCtx(context.parent),false)} + else if(token==='('){return new $CallCtx(context)} + else if(token=='str'){ + context.tree.push(arguments[2]) + return context + }else{return $transition(context.parent,token,arguments[2])} + + }else if(context.type==='sub'){ + + // subscription x[a] or slicing x[a:b:c] + if($expr_starters.indexOf(token)>-1){ + var expr = new $AbstractExprCtx(context,false) + return $transition(expr,token,arguments[2]) + }else if(token===']'){return context.parent} + else if(token===':'){ + return new $AbstractExprCtx(context,false) + }else{$_SyntaxError(context,'token '+token+' after '+context)} + + }else if(context.type==='target_list'){ + + if(token==='id' && context.expect==='id'){ + context.expect = ',' + new $IdCtx(context,arguments[2]) + return context + }else if((token==='('||token==='[')&&context.expect==='id'){ + context.expect = ',' + return new $TargetListCtx(context) + }else if((token===')'||token===']')&&context.expect===','){ + return context.parent + }else if(token===',' && context.expect==','){ + context.expect='id' + return context + }else if(context.expect===','){return $transition(context.parent,token,arguments[2])} + else{$_SyntaxError(context,'token '+token+' after '+context)} + + }else if(context.type==='ternary'){ + + if(token==='else'){return new $AbstractExprCtx(context,false)} + else{return $transition(context.parent,token,arguments[2])} + + }else if(context.type==='try'){ + + if(token===':'){return $BodyCtx(context)} + else{$_SyntaxError(context,'token '+token+' after '+context)} + + }else if(context.type==='unary'){ + + if(['int','float'].indexOf(token)>-1){ + // replace by real value of integer or float + // parent of context is a $ExprCtx + // grand-parent is a $AbstractExprCtx + // we remove the $ExprCtx and trigger a transition + // from the $AbstractExpCtx with an integer or float + // of the correct value + context.parent.parent.tree.pop() + var value = arguments[2] + if(context.op==='-'){value=-value} + if(context.op==='~'){value=~value} + return $transition(context.parent.parent,token,value) + }else if(token==='id'){ + // replace by x.__neg__(), x.__invert__ or x + context.parent.parent.tree.pop() + var expr = new $ExprCtx(context.parent.parent,'call',false) + var expr1 = new $ExprCtx(expr,'id',false) + new $IdCtx(expr1,arguments[2]) // create id + if(context.op !== '+'){ + var repl = new $AttrCtx(expr) + if(context.op==='-'){repl.name='__neg__'} + else{repl.name='__invert__'} + // method is called with no argument + var call = new $CallCtx(expr) + // new context is the expression above the id + return expr1 + } + return context.parent + }else if(token==="op" && '+-'.search(arguments[2])>-1){ + var op = arguments[2] + if(context.op===op){context.op='+'}else{context.op='-'} + return context + }else{return $transition(context.parent,token,arguments[2])} + + }else if(context.type==='with'){ + + if(token==='id' && context.expect==='id'){ + new $TargetCtx(context,arguments[2]) + context.expect='as' + return context + }else if(token==='as' && context.expect==='as' + && context.has_alias===undefined // only one alias allowed + && context.tree.length===1){ // if aliased, must be the only exception + context.expect = 'alias' + context.has_alias = true + return context + }else if(token==='id' && context.expect==='alias'){ + if(context.parenth!==undefined){context.expect = ','} + else{context.expect=':'} + context.tree[context.tree.length-1].alias = arguments[2] + return context + }else if(token===':' && ['id','as',':'].indexOf(context.expect)>-1){ + return $BodyCtx(context) + }else if(token==='(' && context.expect==='id' && context.tree.length===0){ + context.parenth = true + return context + }else if(token===')' && [',','as'].indexOf(context.expect)>-1){ + context.expect = ':' + return context + }else if(token===',' && context.parenth!==undefined && + context.has_alias === undefined && + ['as',','].indexOf(context.expect)>-1){ + context.expect='id' + return context + }else{$_SyntaxError(context,'token '+token+' after '+context.expect)} + + }else if(context.type==='yield'){ + + if(token=='from'){ // form "yield from " + return new $AbstractExprCtx(context,true) + } + return $transition(context.parent,token) + + } +} + +__BRYTHON__.forbidden = ['alert','case','catch','constructor','Date','delete', + 'default','document','Error','history','function','location','Math','new','Number','RegExp', + 'this','throw','var','super','window'] + +function $tokenize(src,module,parent){ + var delimiters = [["#","\n","comment"],['"""','"""',"triple_string"], + ["'","'","string"],['"','"',"string"], + ["r'","'","raw_string"],['r"','"',"raw_string"]] + var br_open = {"(":0,"[":0,"{":0} + var br_close = {")":"(","]":"[","}":"{"} + var br_stack = "" + var br_pos = new Array() + var kwdict = ["class","return","break", + "for","lambda","try","finally","raise","def","from", + "nonlocal","while","del","global","with", + "as","elif","else","if","yield","assert","import", + "except","raise","in","not","pass","with" + //"False","None","True","continue", + // "and',"or","is" + ] + var unsupported = [] + var $indented = ['class','def','for','condition','single_kw','try','except','with'] + // from https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Reserved_Words + + var punctuation = {',':0,':':0} //,';':0} + var int_pattern = new RegExp("^\\d+") + var float_pattern1 = new RegExp("^\\d+\\.\\d*([eE][+-]?\\d+)?") + var float_pattern2 = new RegExp("^\\d+([eE][+-]?\\d+)") + var hex_pattern = new RegExp("^0[xX]([0-9a-fA-F]+)") + var octal_pattern = new RegExp("^0[oO]([0-7]+)") + var binary_pattern = new RegExp("^0[bB]([01]+)") + var id_pattern = new RegExp("[\\$_a-zA-Z]\\w*") + var qesc = new RegExp('"',"g") // escape double quotes + var sqesc = new RegExp("'","g") // escape single quotes + + var context = null + var root = new $Node('module') + root.module = module + root.parent = parent + root.indent = -1 + var new_node = new $Node('expression') + var current = root + var name = "" + var _type = null + var pos = 0 + indent = null + + var lnum = 1 + while(pos0){indent++} + }else{break} + } + // ignore empty lines + if(src.charAt(pos)=='\n'){pos++;lnum++;indent=null;continue} + else if(src.charAt(pos)==='#'){ // comment + var offset = src.substr(pos).search(/\n/) + if(offset===-1){break} + pos+=offset+1;lnum++;indent=null;continue + } + new_node.indent = indent + new_node.line_num = lnum + new_node.module = module + // attach new node to node with indentation immediately smaller + if(indent>current.indent){ + // control that parent ended with ':' + if(context!==null){ + if($indented.indexOf(context.tree[0].type)==-1){ + $pos = pos + $_SyntaxError(context,'unexpected indent1',pos) + } + } + // add a child to current node + current.add(new_node) + }else if(indent<=current.indent && + $indented.indexOf(context.tree[0].type)>-1 && + context.tree.length<2){ + $pos = pos + $_SyntaxError(context,'expected an indented block',pos) + }else{ // same or lower level + while(indent!==current.indent){ + current = current.parent + if(current===undefined || indent>current.indent){ + $pos = pos + $_SyntaxError(context,'unexpected indent2',pos) + } + } + current.parent.add(new_node) + } + current = new_node + context = new $NodeCtx(new_node) + continue + } + // comment + if(car=="#"){ + var end = src.substr(pos+1).search('\n') + if(end==-1){end=src.length-1} + pos += end+1;continue + } + // string + if(car=='"' || car=="'"){ + var raw = false + var bytes = false + var end = null + if(name.length>0){ + if(name.toLowerCase()=="r"){ // raw string + raw = true;name='' + }else if(name.toLowerCase()=='u'){ + // in string literals, '\U' and '\u' escapes in raw strings + // are not treated specially. + name = '' + }else if(name.toLowerCase()=='b'){ + bytes = true;name='' + }else if(['rb','br'].indexOf(name.toLowerCase())>-1){ + bytes=true;raw=true;name='' + } + } + if(src.substr(pos,3)==car+car+car){_type="triple_string";end=pos+3} + else{_type="string";end=pos+1} + var escaped = false + var zone = car + var found = false + while(end-1){ + $pos = pos-name.length + if(unsupported.indexOf(name)>-1){ + $_SyntaxError(context,"Unsupported Python keyword '"+name+"'") + } + context = $transition(context,name) + } else if($oplist.indexOf(name)>-1) { // and, or + $pos = pos-name.length + context = $transition(context,'op',name) + } else { + if(__BRYTHON__.forbidden.indexOf(name)>-1){name='$$'+name} + $pos = pos-name.length + context = $transition(context,'id',name) + } + name="" + continue + } + } + // point, ellipsis (...) + if(car=="."){ + if(pos-1){ + // number starting with . : add a 0 before the point + src = src.substr(0,pos)+'0'+src.substr(pos) + continue + } + $pos = pos + context = $transition(context,'.') + pos++;continue + } + // octal, hexadecimal, binary + if(car==="0"){ + var res = hex_pattern.exec(src.substr(pos)) + if(res){ + context=$transition(context,'int',parseInt(res[1],16)) + pos += res[0].length + continue + } + var res = octal_pattern.exec(src.substr(pos)) + if(res){ + context=$transition(context,'int',parseInt(res[1],8)) + pos += res[0].length + continue + } + var res = binary_pattern.exec(src.substr(pos)) + if(res){ + context=$transition(context,'int',parseInt(res[1],2)) + pos += res[0].length + continue + } + } + // number + if(car.search(/\d/)>-1){ + // digit + var res = float_pattern1.exec(src.substr(pos)) + if(res){ + if(res[0].search(/[eE]/)>-1){ + $pos = pos + context = $transition(context,'float',res[0]) + }else{ + $pos = pos + context = $transition(context,'float',eval(res[0])) + } + }else{ + res = float_pattern2.exec(src.substr(pos)) + if(res){ + $pos =pos + context = $transition(context,'float',res[0]) + }else{ + res = int_pattern.exec(src.substr(pos)) + $pos = pos + context = $transition(context,'int',eval(res[0])) + } + } + pos += res[0].length + continue + } + // line end + if(car=="\n"){ + lnum++ + if(br_stack.length>0){ + // implicit line joining inside brackets + pos++;continue + } else { + if(current.context.tree.length>0){ + $pos = pos + context = $transition(context,'eol') + indent=null + new_node = new $Node() + }else{ + new_node.line_num = lnum + } + pos++;continue + } + } + if(car in br_open){ + br_stack += car + br_pos[br_stack.length-1] = [context,pos] + $pos = pos + context = $transition(context,car) + pos++;continue + } + if(car in br_close){ + if(br_stack==""){ + $_SyntaxError(context,"Unexpected closing bracket") + } else if(br_close[car]!=br_stack.charAt(br_stack.length-1)){ + $_SyntaxError(context,"Unbalanced bracket") + } else { + br_stack = br_stack.substr(0,br_stack.length-1) + $pos = pos + context = $transition(context,car) + pos++;continue + } + } + if(car=="="){ + if(src.charAt(pos+1)!="="){ + $pos = pos + context = $transition(context,'=') + pos++;continue + } else { + $pos = pos + context = $transition(context,'op','==') + pos+=2;continue + } + } + if(car in punctuation){ + $pos = pos + context = $transition(context,car) + pos++;continue + } + if(car===";"){ // next instruction + $transition(context,'eol') // close previous instruction + // create a new node, at the same level as current's parent + if(current.context.tree.length===0){ + // consecutive ; are not allowed + $pos=pos + $_SyntaxError(context,'invalid syntax') + } + // if ; ends the line, ignore it + var pos1 = pos+1 + var ends_line = false + while(pos1-1){ + // find longest match + var op_match = "" + for(op_sign in $operators){ + if(op_sign==src.substr(pos,op_sign.length) + && op_sign.length>op_match.length){ + op_match=op_sign + } + } + $pos = pos + if(op_match.length>0){ + if(op_match in $augmented_assigns){ + context = $transition(context,'augm_assign',op_match) + }else{ + context = $transition(context,'op',op_match) + } + pos += op_match.length + continue + } + } + if(car=='\\' && src.charAt(pos+1)=='\n'){ + lnum++;pos+=2;continue + } + if(car=='@'){ + $pos = pos + context = $transition(context,car) + pos++;continue + } + if(car!=' '&&car!=='\t'){$pos=pos;$_SyntaxError(context,'unknown token ['+car+']')} + pos += 1 + } + + if(br_stack.length!=0){ + var br_err = br_pos[0] + $pos = br_err[1] + $_SyntaxError(br_err[0],["Unbalanced bracket "+br_stack.charAt(br_stack.length-1)]) + } + if(context!==null && $indented.indexOf(context.tree[0].type)>-1){ + $pos = pos-1 + $_SyntaxError(context,'expected an indented block',pos) + } + + return root + +} + +__BRYTHON__.py2js = function(src,module,parent){ + // src = Python source (string) + // module = module name (string) + // parent = the name of the "calling" module, eg for a list comprehension (string) + var src = src.replace(/\r\n/gm,'\n') + while (src.length>0 && (src.charAt(0)=="\n" || src.charAt(0)=="\r")){ + src = src.substr(1) + } + if(src.charAt(src.length-1)!="\n"){src+='\n'} + if(module===undefined){module='__main__'} + // Python built-in variable __name__ + var __name__ = module + if(__BRYTHON__.scope[module]===undefined){ + __BRYTHON__.scope[module] = {} + __BRYTHON__.scope[module].__dict__ = {} + } + document.$py_src[module]=src + var root = $tokenize(src,module,parent) + root.transform() + // add variable $globals + var js = 'var $globals = __BRYTHON__.scope["'+module+'"].__dict__\nvar $locals = $globals\n' + js += 'var __builtins__ = __BRYTHON__.builtins;\n' + js += 'for(var $py_builtin in __builtins__)' + js += '{eval("var "+$py_builtin+"=__builtins__[$py_builtin]")}\n' + js += 'var JSObject = __BRYTHON__.JSObject\n' + js += 'var JSConstructor = __BRYTHON__.JSConstructor\n' + var new_node = new $Node('expression') + new $NodeJSCtx(new_node,js) + root.insert(0,new_node) + // module doc string + var ds_node = new $Node('expression') + new $NodeJSCtx(ds_node,'var __doc__=$globals["__doc__"]='+root.doc_string) + root.insert(1,ds_node) + // name + var name_node = new $Node('expression') + var lib_module = module + if(module.substr(0,9)=='__main__,'){lib_module='__main__'} + new $NodeJSCtx(name_node,'var __name__=$globals["__name__"]="'+lib_module+'"') + root.insert(2,name_node) + // file + var file_node = new $Node('expression') + new $NodeJSCtx(file_node,'var __file__=$globals["__file__"]="'+__BRYTHON__.$py_module_path[module]+'"') + root.insert(3,file_node) + + if(__BRYTHON__.debug>0){$add_line_num(root,null,module)} + __BRYTHON__.modules[module] = root + return root +} + +function brython(options){ + document.$py_src = {} + __BRYTHON__.$py_module_path = {} + __BRYTHON__.$py_module_alias = {} + __BRYTHON__.path_hooks = [] + //__BRYTHON__.$py_modules = {} + __BRYTHON__.modules = {} + __BRYTHON__.imported = {} + __BRYTHON__.$py_next_hash = -Math.pow(2,53) + + // debug level + if(options===undefined){options={'debug':0}} + if(typeof options==='number'){options={'debug':options}} + __BRYTHON__.debug = options.debug + + if (options.open !== undefined) {__BRYTHON__.builtins.$open = options.open} + __BRYTHON__.builtins.$CORS=false // Cross-origin resource sharing + if (options.CORS !== undefined) {__BRYTHON__.builtins.$CORS = options.CORS} + __BRYTHON__.$options=options + __BRYTHON__.exception_stack = [] + __BRYTHON__.call_stack = [] + __BRYTHON__.scope = {} + __BRYTHON__.events = __BRYTHON__.builtins.dict() // maps $brython_id of DOM elements to events + var $elts = document.getElementsByTagName("script") + var $href = window.location.href + var $href_elts = $href.split('/') + $href_elts.pop() + var $script_path = $href_elts.join('/') + + __BRYTHON__.path = [] + if (options.pythonpath!==undefined) { + __BRYTHON__.path = options.pythonpath + } + if (!(__BRYTHON__.path.indexOf($script_path) > -1)) { + __BRYTHON__.path.push($script_path) + } + + // get path of brython.js or py2js to determine brython_path + // it will be used for imports + + for(var $i=0;$i<$elts.length;$i++){ + var $elt = $elts[$i] + var $br_scripts = ['brython.js','py2js.js','brython_full.js'] + for(var $j=0;$j<$br_scripts.length;$j++){ + var $bs = $br_scripts[$j] + if($elt.src.substr($elt.src.length-$bs.length)==$bs){ + if($elt.src.length===$bs.length || + $elt.src.charAt($elt.src.length-$bs.length-1)=='/'){ + var $path = $elt.src.substr(0,$elt.src.length-$bs.length) + __BRYTHON__.brython_path = $path + if (!(__BRYTHON__.path.indexOf($path+'Lib')> -1)) { + __BRYTHON__.path.push($path+'Lib') + } + break + } + } + } + } + + // get all scripts with type = text/python and run them + + for(var $i=0;$i<$elts.length;$i++){ + var $elt = $elts[$i] + if($elt.type=="text/python"||$elt.type==="text/python3"){ + var $src = null + if($elt.src!==''){ + // format + + + + + + + + \ No newline at end of file From 518731840c396b83c8eaedc7f9555a809a3012bd Mon Sep 17 00:00:00 2001 From: hartsantler Date: Wed, 15 Jan 2014 08:48:16 -0800 Subject: [PATCH 075/521] new support for @staticmethod --- pythonjs.js | 4 ++-- pythonjs/python_to_pythonjs.py | 3 +++ runtime/builtins.py | 2 +- tests/test_classmethod.html | 8 ++++++++ 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/pythonjs.js b/pythonjs.js index 0c608d3..2a7ac79 100644 --- a/pythonjs.js +++ b/pythonjs.js @@ -1,4 +1,4 @@ -// PythonJS Runtime - regenerated on: Wed Jan 15 08:31:55 2014 +// PythonJS Runtime - regenerated on: Wed Jan 15 08:46:01 2014 __NULL_OBJECT__ = Object.create(null); if (( "window" ) in this && ( "document" ) in this) { __NODEJS__ = false; @@ -593,7 +593,7 @@ create_class = function(class_name, parents, attrs, props) { var key = __iter5[ __idx5 ]; if (( typeof(attrs[ (key.__uid__) ? key.__uid__ : key]) ) == "function") { klass.__all_method_names__.push(key); - if (attrs[ (key.__uid__) ? key.__uid__ : key].is_classmethod) { + if (attrs[ (key.__uid__) ? key.__uid__ : key].is_classmethod || attrs[ (key.__uid__) ? key.__uid__ : key].is_staticmethod) { /*pass*/ } else { klass.__unbound_methods__[ (key.__uid__) ? key.__uid__ : key] = attrs[ (key.__uid__) ? key.__uid__ : key]; diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index 5b0e94c..9afd8f9 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -2094,6 +2094,9 @@ def visit_FunctionDef(self, node): dec = self.visit(decorator) if dec == 'classmethod': writer.write( '%s.is_classmethod = True' %node.name) + elif dec == 'staticmethod': + writer.write( '%s.is_staticmethod = True' %node.name) + writer.write( '%s.is_wrapper = True' %node.name) else: writer.write('%s = __get__(%s,"__call__")( [%s], JSObject() )' % (node.name, dec, node.name)) diff --git a/runtime/builtins.py b/runtime/builtins.py index eaf9b6a..bd92eb1 100644 --- a/runtime/builtins.py +++ b/runtime/builtins.py @@ -136,7 +136,7 @@ def create_class(class_name, parents, attrs, props): for key in attrs: if typeof( attrs[key] ) == 'function': klass.__all_method_names__.push( key ) - if attrs[key].is_classmethod: + if attrs[key].is_classmethod or attrs[key].is_staticmethod: pass else: klass.__unbound_methods__[key] = attrs[key] diff --git a/tests/test_classmethod.html b/tests/test_classmethod.html index 7c82f25..3068e23 100644 --- a/tests/test_classmethod.html +++ b/tests/test_classmethod.html @@ -10,11 +10,19 @@ print 'class', cls print a,b,c + @staticmethod + def mystatic(x,y,z): + print 'my staticmethod' + print x,y,z + def test(): A.mymethod( 1,2,3 ) a = A() a.mymethod( 4,5,6 ) + A.mystatic( 1,2,3 ) + a.mystatic( 4,5,6 ) + From c81cdafa1456187c88d75a8a5dce46f5a6c807b1 Mon Sep 17 00:00:00 2001 From: hartsantler Date: Fri, 17 Jan 2014 04:01:19 -0800 Subject: [PATCH 076/521] brython ast: support UnaryOp --- bindings/ast.py | 28 +++++++++++++++++++++++++++- tests/test_AST.html | 11 ++++++++--- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/bindings/ast.py b/bindings/ast.py index 5fe8b73..30eaf4a 100644 --- a/bindings/ast.py +++ b/bindings/ast.py @@ -70,7 +70,13 @@ def __init__(self, ctx=None, name=None): print ctx raise TypeError - +class UnaryOp: + ''' + note: this is constructed directly from an abstract_expr + ''' + def __init__(self, op=None, operand=None): + self.op = op + self.operand = operand class BinOp: def __init__(self, ctx, node): @@ -301,6 +307,26 @@ def to_ast_node( ctx, node=None ): print '--------special node_js error-------' print(ctx) raise TypeError + + elif ctx.type == 'abstract_expr': + if len(ctx.tree)==1 and ctx.tree[0].type=='expr' and ctx.tree[0].name=='call' and len(ctx.tree[0].tree)==1: + call = ctx.tree[0].tree[0] + assert call.type=='call' + func = call.func + if func.type=='attribute' and func.func=='getattr': + if func.name=='__neg__': + return UnaryOp(op='-', operand=to_ast_node(func.value)) + else: + raise TypeError + else: + print '---------abstract_expr error----------' + print ctx + raise TypeError + else: + print '---------abstract_expr error----------' + print ctx + raise TypeError + else: print '---------error----------' print node diff --git a/tests/test_AST.html b/tests/test_AST.html index 70e8dc1..89de417 100644 --- a/tests/test_AST.html +++ b/tests/test_AST.html @@ -73,15 +73,17 @@ for i in range(10): a = i * i -""" - -source = """ i = 0 while i < 10: i += 1 """ +source = """ +if True: + b = -a +""" + def test(): global module module = parse( source ) @@ -125,6 +127,9 @@ def visit_AugAssign(self, node): return self.visit(node.target) + node.op + '=' + self.visit(node.value) + def visit_UnaryOp(self, node): + return node.op + self.visit(node.operand) + def visit_BinOp(self, node): return self.visit( node.left ) + node.op + self.visit( node.right ) From a1f1266492b549e86e0aa3dbeb1b3333a449e29b Mon Sep 17 00:00:00 2001 From: hartsantler Date: Fri, 17 Jan 2014 15:25:50 -0800 Subject: [PATCH 077/521] brython ast: support for Not, List, and Tuple ast nodes. --- bindings/ast.py | 28 ++++++++++++++++++++++++++++ tests/test_AST.html | 22 ++++++++++++++++++++-- 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/bindings/ast.py b/bindings/ast.py index 30eaf4a..26b53d2 100644 --- a/bindings/ast.py +++ b/bindings/ast.py @@ -18,6 +18,25 @@ class Pass: def __init__(self, ctx, node): pass +class Not: + def __init__(self, ctx, node): + self.value = to_ast_node(ctx.tree[0]) ## not standard python + +class List: + def __init__(self, ctx, node): + self.elts = [] + #self.ctx = 'Load' # 'Store' is (x,y,z) = w + for a in ctx.tree: + self.elts.append( to_ast_node(a) ) + +class Tuple: + def __init__(self, ctx, node): + self.elts = [] + #self.ctx = 'Load' # 'Store' is (x,y,z) = w + for a in ctx.tree: + self.elts.append( to_ast_node(a) ) + + class Assign: def _collect_targets(self, ctx): if ctx.type == 'expr' and ctx.name == 'id': @@ -249,6 +268,7 @@ def __init__(self, ctx, node): 'attribute' : Attribute, 'pass' : Pass, 'for' : For, + 'not' : Not, } def to_ast_node( ctx, node=None ): @@ -264,6 +284,14 @@ def to_ast_node( ctx, node=None ): elif ctx.type in __MAP: return __MAP[ ctx.type ]( ctx, node ) + elif ctx.type == 'list_or_tuple': + if ctx.real == 'list': + return List(ctx, node) + elif ctx.real == 'tuple': + return Tuple(ctx, node) + else: + raise TypeError + elif ctx.type == 'decorator': push_decorator( to_ast_node(ctx.tree[0]) ) diff --git a/tests/test_AST.html b/tests/test_AST.html index 89de417..6742403 100644 --- a/tests/test_AST.html +++ b/tests/test_AST.html @@ -80,8 +80,10 @@ """ source = """ -if True: - b = -a +if 1 <= 2: + b = not a + x = [1,2] + y = (3,4) """ def test(): @@ -127,6 +129,22 @@ def visit_AugAssign(self, node): return self.visit(node.target) + node.op + '=' + self.visit(node.value) + + def visit_List(self, node): + s = [] + for e in node.elts: + s.append( self.visit(e) ) + return '[' + ','.join(s) + ']' + + def visit_Tuple(self, node): + s = [] + for e in node.elts: + s.append( self.visit(e) ) + return '(' + ','.join(s) + ')' + + def visit_Not(self, node): + return ' not ' + self.visit(node.value) + def visit_UnaryOp(self, node): return node.op + self.visit(node.operand) From 5e55104cbf20d9946ce346909d5d46f2b81468c8 Mon Sep 17 00:00:00 2001 From: hartsantler Date: Fri, 17 Jan 2014 16:50:20 -0800 Subject: [PATCH 078/521] brython ast: Dict ast node, and fixed Str ast node. --- bindings/ast.py | 22 +++++++++++++++++++++- tests/test_AST.html | 9 +++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/bindings/ast.py b/bindings/ast.py index 26b53d2..a9f75ec 100644 --- a/bindings/ast.py +++ b/bindings/ast.py @@ -36,6 +36,18 @@ def __init__(self, ctx, node): for a in ctx.tree: self.elts.append( to_ast_node(a) ) +class Dict: + def __init__(self, ctx, node): + self.keys = [] + self.values = [] + #for i in range(0, len(ctx.items), 2): ## TODO fix me + i = 0 + while i < len(ctx.items): + key = ctx.items[i] + val = ctx.items[i+1] + self.keys.append( to_ast_node(key) ) + self.values.append( to_ast_node(val) ) + i += 2 class Assign: def _collect_targets(self, ctx): @@ -77,7 +89,11 @@ def __init__(self, ctx, node): class Str: def __init__(self, ctx, node): - self.s = ctx.value + #self.s = ctx.value ## old brython + if len(ctx.tree) == 1: + self.s = ctx.tree[0] + else: + raise TypeError class Name: def __init__(self, ctx=None, name=None): @@ -292,6 +308,10 @@ def to_ast_node( ctx, node=None ): else: raise TypeError + elif ctx.type == 'dict_or_set': + if ctx.real == 'dict': + return Dict(ctx, node) + elif ctx.type == 'decorator': push_decorator( to_ast_node(ctx.tree[0]) ) diff --git a/tests/test_AST.html b/tests/test_AST.html index 6742403..1507d9e 100644 --- a/tests/test_AST.html +++ b/tests/test_AST.html @@ -84,6 +84,7 @@ b = not a x = [1,2] y = (3,4) + z = {'k1':'val1', 'k2':'val2'} """ def test(): @@ -129,6 +130,14 @@ def visit_AugAssign(self, node): return self.visit(node.target) + node.op + '=' + self.visit(node.value) + def visit_Dict(self, node): + s = [] + for i in range( len(node.keys) ): + k = self.visit( node.keys[i] ) + v = self.visit( node.values[i] ) + #s.append( '%s:%s'%(k,v) ) + s.append( k+':'+v ) + return '{' + ','.join(s) + '}' def visit_List(self, node): s = [] From 52717543357aa8fdab71405a3608a9d2fbe6a78d Mon Sep 17 00:00:00 2001 From: hartsantler Date: Fri, 17 Jan 2014 17:01:58 -0800 Subject: [PATCH 079/521] brython ast: added support for Subscript ast node. --- bindings/ast.py | 11 +++++++++++ tests/test_AST.html | 9 +++++++++ 2 files changed, 20 insertions(+) diff --git a/bindings/ast.py b/bindings/ast.py index a9f75ec..bd8972d 100644 --- a/bindings/ast.py +++ b/bindings/ast.py @@ -49,6 +49,16 @@ def __init__(self, ctx, node): self.values.append( to_ast_node(val) ) i += 2 +class Subscript: + def __init__(self, ctx, node): + self.value = to_ast_node(ctx.value) + self.slice = Index(value=to_ast_node(ctx.tree[0])) + #self.ctx = 'Load', 'Store', 'Del' + +class Index: + def __init__(self, value=None): + self.value = value + class Assign: def _collect_targets(self, ctx): if ctx.type == 'expr' and ctx.name == 'id': @@ -285,6 +295,7 @@ def __init__(self, ctx, node): 'pass' : Pass, 'for' : For, 'not' : Not, + 'sub' : Subscript, } def to_ast_node( ctx, node=None ): diff --git a/tests/test_AST.html b/tests/test_AST.html index 1507d9e..316e162 100644 --- a/tests/test_AST.html +++ b/tests/test_AST.html @@ -85,6 +85,9 @@ x = [1,2] y = (3,4) z = {'k1':'val1', 'k2':'val2'} + v = z[ 'k1' ] + v = x[0] + """ def test(): @@ -130,6 +133,12 @@ def visit_AugAssign(self, node): return self.visit(node.target) + node.op + '=' + self.visit(node.value) + def visit_Subscript(self, node): + return '%s[%s]' %(self.visit(node.value), self.visit(node.slice)) + + def visit_Index(self, node): + return self.visit(node.value) + def visit_Dict(self, node): s = [] for i in range( len(node.keys) ): From 06cf6d544f534ba5f8e0b645beb1e67b2a16856a Mon Sep 17 00:00:00 2001 From: hartsantler Date: Fri, 17 Jan 2014 20:25:07 -0800 Subject: [PATCH 080/521] brython ast: support for simple slices "a[1:2]" --- bindings/ast.py | 16 +++++++++++++++- tests/test_AST.html | 12 +++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/bindings/ast.py b/bindings/ast.py index bd8972d..d2e8ccd 100644 --- a/bindings/ast.py +++ b/bindings/ast.py @@ -52,13 +52,27 @@ def __init__(self, ctx, node): class Subscript: def __init__(self, ctx, node): self.value = to_ast_node(ctx.value) - self.slice = Index(value=to_ast_node(ctx.tree[0])) + if len(ctx.tree) == 1: + self.slice = Index(value=to_ast_node(ctx.tree[0])) + elif len(ctx.tree) == 2: + self.slice = Slice( + lower=to_ast_node(ctx.tree[0]), + upper=to_ast_node(ctx.tree[1]) + ) + else: + raise TypeError #self.ctx = 'Load', 'Store', 'Del' class Index: def __init__(self, value=None): self.value = value +class Slice: + def __init__(self, lower=None, upper=None, step=None): + self.lower = lower + self.upper = upper + self.step = step + class Assign: def _collect_targets(self, ctx): if ctx.type == 'expr' and ctx.name == 'id': diff --git a/tests/test_AST.html b/tests/test_AST.html index 316e162..fac66dc 100644 --- a/tests/test_AST.html +++ b/tests/test_AST.html @@ -79,7 +79,7 @@ """ -source = """ +source_list_tuple_dict = """ if 1 <= 2: b = not a x = [1,2] @@ -90,6 +90,13 @@ """ +source = """ +if True: + a = [] + b = a[1:2] + +""" + def test(): global module module = parse( source ) @@ -139,6 +146,9 @@ def visit_Index(self, node): return self.visit(node.value) + def visit_Slice(self, node): + return self.visit(node.lower) + ':' + self.visit(node.upper) + def visit_Dict(self, node): s = [] for i in range( len(node.keys) ): From 8b911778dafc23b132c09c790c418907a15b7dc5 Mon Sep 17 00:00:00 2001 From: hartsantler Date: Sat, 18 Jan 2014 16:59:51 -0800 Subject: [PATCH 081/521] brython ast: support for slice with step "a[n:n:n]" --- bindings/ast.py | 6 ++++++ tests/test_AST.html | 6 +++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/bindings/ast.py b/bindings/ast.py index d2e8ccd..67460ca 100644 --- a/bindings/ast.py +++ b/bindings/ast.py @@ -59,6 +59,12 @@ def __init__(self, ctx, node): lower=to_ast_node(ctx.tree[0]), upper=to_ast_node(ctx.tree[1]) ) + elif len(ctx.tree) == 3: + self.slice = Slice( + lower=to_ast_node(ctx.tree[0]), + upper=to_ast_node(ctx.tree[1]), + step=to_ast_node(ctx.tree[2]) + ) else: raise TypeError #self.ctx = 'Load', 'Store', 'Del' diff --git a/tests/test_AST.html b/tests/test_AST.html index fac66dc..057fab3 100644 --- a/tests/test_AST.html +++ b/tests/test_AST.html @@ -94,6 +94,7 @@ if True: a = [] b = a[1:2] + c = a[1:2:3] """ @@ -147,7 +148,10 @@ return self.visit(node.value) def visit_Slice(self, node): - return self.visit(node.lower) + ':' + self.visit(node.upper) + if node.step: + return self.visit(node.lower) + ':' + self.visit(node.upper) + ':' + self.visit(node.step) + else: + return self.visit(node.lower) + ':' + self.visit(node.upper) def visit_Dict(self, node): s = [] From 356370d81437411a6e3b970080a811108fdc7915 Mon Sep 17 00:00:00 2001 From: hartsantler Date: Sat, 18 Jan 2014 17:56:22 -0800 Subject: [PATCH 082/521] brython ast: binary and unary operator classes --- bindings/ast.py | 138 ++++++++++++++++++++++++++++++++++++++++++-- tests/test_AST.html | 22 +++++-- 2 files changed, 150 insertions(+), 10 deletions(-) diff --git a/bindings/ast.py b/bindings/ast.py index 67460ca..09c226e 100644 --- a/bindings/ast.py +++ b/bindings/ast.py @@ -19,8 +19,11 @@ def __init__(self, ctx, node): pass class Not: - def __init__(self, ctx, node): - self.value = to_ast_node(ctx.tree[0]) ## not standard python + def __init__(self, ctx=None, node=None): + if ctx: + self.value = to_ast_node(ctx.tree[0]) ## not standard python + else: + self.value = None class List: def __init__(self, ctx, node): @@ -135,13 +138,71 @@ def __init__(self, ctx=None, name=None): print ctx raise TypeError +class Add: + pass +class Sub: + pass +class Div: + pass +class FloorDiv: + pass +class Mod: + pass +class Pow: + pass +class LShift: + pass +class RShift: + pass +class BitOr: + pass +class BitXor: + pass +class BitAnd: + pass +class Is: + pass +class IsNot: + pass + +_operators = { + '+' : Add, + '-' : Sub, + '/' : Div, + '//': FloorDiv, + '%' : Mod, + '**': Pow, + '<<': LShift, + '>>': RShift, + '|' : BitOr, + '^' : BitXor, + '&' : BitAnd, + 'is': Is, + 'is_not': IsNot, + +} + +class USub: + pass +class UAdd: + pass +class Invert: + pass + class UnaryOp: ''' note: this is constructed directly from an abstract_expr ''' def __init__(self, op=None, operand=None): - self.op = op self.operand = operand + if op == '-': + self.op = USub() + elif op == '+': + self.op = UAdd() + elif op == '~': + self.op = Invert() + elif op == 'not': + self.op = Not() class BinOp: def __init__(self, ctx, node): @@ -150,7 +211,13 @@ def __init__(self, ctx, node): raise TypeError self.left = to_ast_node( ctx.tree[0] ) self.right = to_ast_node( ctx.tree[1] ) - self.op = ctx.op ## should be: +,-,*, etc... + if ctx.op in _operators: + klass = _operators[ctx.op] + self.op = klass() + else: + print('ERROR: unknown operator type') + print(ctx) + raise TypeError @@ -469,3 +536,66 @@ def visit_Name(self, node): def visit_Pass(self, node): return 'pass' + + def visit_Not(self, node): + ## note: node.value is non-standard for the `Not` node + if node.value: + return ' not ' + self.visit(node.value) + else: + return ' not ' + + def visit_IsNot(self, node): + return ' is not ' + + def visit_Eq(self, node): + return '==' + + def visit_NotEq(self, node): + return '!=' + + def visit_Is(self, node): + return ' is ' + + def visit_Pow(self, node): + return '**' + + def visit_Mult(self, node): + return '*' + + def visit_UAdd(self, node): + return '+' + def visit_USub(self, node): + return '-' + def visit_Add(self, node): + return '+' + def visit_Sub(self, node): + return '-' + + def visit_FloorDiv(self, node): + return '//' + def visit_Div(self, node): + return '/' + def visit_Mod(self, node): + return '%' + def visit_LShift(self, node): + return '<<' + def visit_RShift(self, node): + return '>>' + def visit_BitXor(self, node): + return '^' + def visit_BitOr(self, node): + return '|' + def visit_BitAnd(self, node): + return '&' + + def visit_Lt(self, node): + return '<' + + def visit_Gt(self, node): + return '>' + + def visit_GtE(self, node): + return '>=' + + def visit_LtE(self, node): + return '<=' diff --git a/tests/test_AST.html b/tests/test_AST.html index 057fab3..945ec06 100644 --- a/tests/test_AST.html +++ b/tests/test_AST.html @@ -90,7 +90,7 @@ """ -source = """ +source_slice = """ if True: a = [] b = a[1:2] @@ -98,6 +98,19 @@ """ +source = """ +if True: + a = 1 / 2 + b = 2 // 2 + c = a is b + d = a is not b + e = a**2 + g = -e + g = not e + +""" + + def test(): global module module = parse( source ) @@ -174,14 +187,11 @@ s.append( self.visit(e) ) return '(' + ','.join(s) + ')' - def visit_Not(self, node): - return ' not ' + self.visit(node.value) - def visit_UnaryOp(self, node): - return node.op + self.visit(node.operand) + return self.visit(node.op) + self.visit(node.operand) def visit_BinOp(self, node): - return self.visit( node.left ) + node.op + self.visit( node.right ) + return self.visit( node.left ) + self.visit(node.op) + self.visit( node.right ) def visit_FunctionDef(self, node): for dec in node.decorator_list: From bfdb0b9e961e559b81864dee94058c3b6858be1d Mon Sep 17 00:00:00 2001 From: hartsantler Date: Sat, 18 Jan 2014 19:01:28 -0800 Subject: [PATCH 083/521] brython ast: support Import and ImportFrom, testing translating python_to_pythonjs.py with Brython-to-AST binding. --- bindings/ast.py | 47 +++++++++++++++++++++++++++++++++++++++++++++ tests/server.py | 3 +++ tests/test_AST.html | 13 ++++++++++++- 3 files changed, 62 insertions(+), 1 deletion(-) diff --git a/bindings/ast.py b/bindings/ast.py index 09c226e..f3e825f 100644 --- a/bindings/ast.py +++ b/bindings/ast.py @@ -160,6 +160,19 @@ class BitXor: pass class BitAnd: pass + +class Eq: + pass +class NotEq: + pass +class Lt: + pass +class LtE: + pass +class Gt: + pass +class GtE: + pass class Is: pass class IsNot: @@ -177,6 +190,12 @@ class IsNot: '|' : BitOr, '^' : BitXor, '&' : BitAnd, + '==': Eq, + '!=': NotEq, + '<' : Lt, + '<=': LtE, + '>' : Gt, + '>=': GtE, 'is': Is, 'is_not': IsNot, @@ -366,6 +385,24 @@ def __init__(self, ctx, node): if anode: self.body.append( anode ) +class alias: + def __init__(self, name=None, asname=None): + self.name = name + self.asname = asname + +class Import: + def __init__(self, ctx, node): + self.names = [] + for c in ctx.tree: + self.names.append( alias(name=c.name,asname=c.alias) ) + +class ImportFrom: + def __init__(self, ctx, node): + self.module = ctx.module + self.names = [] + self.level = 0 + for name in ctx.names: + self.names.append( alias(name=name) ) __MAP = { 'def' : FunctionDef, @@ -383,6 +420,8 @@ def __init__(self, ctx, node): 'for' : For, 'not' : Not, 'sub' : Subscript, + 'import' : Import, + 'from' : ImportFrom } def to_ast_node( ctx, node=None ): @@ -522,6 +561,14 @@ def visit(self, node): ) return f( node ) + def visit_Import(self, node): + a = [ alias.name for alias in node.names ] + print 'import', ','.join(a) + + def visit_ImportFrom(self, node): + a = [ alias.name for alias in node.names ] + print 'from', node.module, 'import', ','.join(a) + def visit_Expr(self, node): return self.visit(node.value) diff --git a/tests/server.py b/tests/server.py index ab85a73..35ba231 100755 --- a/tests/server.py +++ b/tests/server.py @@ -153,6 +153,9 @@ def convert_python_html_document( data ): script = None use_dart = DART for line in data.splitlines(): + if line == 'source = $PYTHONJS': + line = open('../pythonjs/python_to_pythonjs.py', 'rb').read().decode('utf-8') + if line.strip().startswith(' +
+source = $PYTHONJS
+
+ + + + + + + + + \ No newline at end of file From c99759ce9afbcb980cc0a9a485feeb3e38d77cf3 Mon Sep 17 00:00:00 2001 From: hartsantler Date: Thu, 23 Jan 2014 16:47:52 -0800 Subject: [PATCH 090/521] fixed loop over and unpack tuple targets: "for x,y in d.items()" --- pythonjs/python_to_pythonjs.py | 43 ++++++++++++++++++++++++++++++---- tests/test_for_loop.html | 6 +++++ 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index 1ebf784..873f9eb 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -2153,6 +2153,22 @@ def visit_For(self, node): writer.write('var(%s)'%enumtar.id) writer.write('%s = 0' %enumtar.id) + vars = [] + multi_target = [] + + if isinstance(target, ast.Tuple): + vars.append( '__mtarget__') + for elt in target.elts: + if isinstance(elt, ast.Name): + multi_target.append( elt.id ) + vars.append( elt.id ) + else: + raise NotImplementedError('unknown iterator sub-target type: %s'%target) + elif isinstance(target, ast.Name): + vars.append( target.id ) + else: + raise NotImplementedError('unknown iterator target type: %s'%target) + if self._with_js or self._with_dart: if isinstance(iter, ast.Call) and isinstance(iter.func, Name) and iter.func.id in ('range','xrange'): @@ -2187,8 +2203,18 @@ def visit_For(self, node): writer.pull() else: - writer.write('for %s in %s:' %(self.visit(target),self.visit(iter))) - writer.push() + if multi_target: + writer.write('var(%s)' % ','.join(vars)) + writer.write('for %s in %s:' %('__mtarget__',self.visit(iter))) + writer.push() + for i,elt in enumerate(multi_target): + writer.write('%s = __mtarget__[%s]' %(elt,i)) + + else: + writer.write('for %s in %s:' %(self.visit(target),self.visit(iter))) + writer.push() + + map(self.visit, node.body) if enumtar: @@ -2201,7 +2227,9 @@ def visit_For(self, node): if isinstance(iter, Name) and iter.id in self._global_typed_lists: self._instances[ target.id ] = list( self._global_typed_lists[ iter.id ] )[0] - writer.write('var(__iterator__, %s)' % target.id) + vars.append('__iterator__') ## TODO - test nested for loops - this should be __iterator__N + writer.write('var(%s)' % ','.join(vars)) + is_range = False is_generator = False @@ -2250,7 +2278,14 @@ def visit_For(self, node): writer.write('while __iterator__.index < __iterator__.length:') writer.push() - writer.write('%s = __next__()' % target.id) + + if multi_target: + writer.write('__mtarget__ = __next__()') + for i,elt in enumerate(multi_target): + writer.write('%s = __mtarget__[%s]' %(elt,i)) + else: + writer.write('%s = __next__()' % target.id) + map(self.visit, node.body) if enumtar: diff --git a/tests/test_for_loop.html b/tests/test_for_loop.html index 979b21b..a4f5f40 100644 --- a/tests/test_for_loop.html +++ b/tests/test_for_loop.html @@ -64,6 +64,12 @@ for w,b in enumerate(r): print w, b + for x,y in d.items(): + print(x,y) + + with javascript: + for x,y in d.items(): + print(x,y) From 383468b7531a1cf768f58ad4e41d67d25a7405fd Mon Sep 17 00:00:00 2001 From: hartsantler Date: Thu, 23 Jan 2014 22:35:50 -0800 Subject: [PATCH 091/521] fixed calling function with *args and **kwargs. fixed dict.items(), now works on: `self.__dict__.items()` fixed builtin setattr --- pythonjs.js | 274 ++++++++++++++++++++------------- pythonjs/python_to_pythonjs.py | 42 +++-- runtime/builtins.py | 45 +++++- tests/helloworld.html | 2 +- tests/test_dict_items.html | 28 ++++ 5 files changed, 255 insertions(+), 136 deletions(-) create mode 100644 tests/test_dict_items.html diff --git a/pythonjs.js b/pythonjs.js index 3a0688b..894748b 100644 --- a/pythonjs.js +++ b/pythonjs.js @@ -1,4 +1,4 @@ -// PythonJS Runtime - regenerated on: Mon Jan 20 20:31:45 2014 +// PythonJS Runtime - regenerated on: Thu Jan 23 22:33:59 2014 __NULL_OBJECT__ = Object.create(null); if (( "window" ) in this && ( "document" ) in this) { __WEBWORKER__ = false; @@ -489,6 +489,29 @@ __jsdict_values.NAME = "__jsdict_values"; __jsdict_values.args_signature = ["ob"]; __jsdict_values.kwargs_signature = { }; __jsdict_values.types_signature = { }; +__jsdict_items = function(ob) { + var arr, value; + if (ob instanceof Object || ( ob.items ) === undefined) { + arr = []; + var __iter3 = ob; + if (! (__iter3 instanceof Array || typeof __iter3 == "string") ) { __iter3 = __object_keys__(__iter3) } + for (var __idx3=0; __idx3 < __iter3.length; __idx3++) { + var key = __iter3[ __idx3 ]; + if (Object.hasOwnProperty.call(ob, key)) { + value = ob[ (key.__uid__) ? key.__uid__ : key]; + arr.push([key, value]); + } + } + return arr; + } else { + return ob.items(); + } +} + +__jsdict_items.NAME = "__jsdict_items"; +__jsdict_items.args_signature = ["ob"]; +__jsdict_items.kwargs_signature = { }; +__jsdict_items.types_signature = { }; __jsdict_pop = function(ob, key, _default) { var v; if (_default == undefined) _default = undefined; @@ -535,10 +558,10 @@ __object_keys__.kwargs_signature = { }; __object_keys__.types_signature = { }; __bind_property_descriptors__ = function(o, klass) { var prop, desc; - var __iter3 = klass.__properties__; - if (! (__iter3 instanceof Array || typeof __iter3 == "string") ) { __iter3 = __object_keys__(__iter3) } - for (var __idx3=0; __idx3 < __iter3.length; __idx3++) { - var name = __iter3[ __idx3 ]; + var __iter4 = klass.__properties__; + if (! (__iter4 instanceof Array || typeof __iter4 == "string") ) { __iter4 = __object_keys__(__iter4) } + for (var __idx4=0; __idx4 < __iter4.length; __idx4++) { + var name = __iter4[ __idx4 ]; desc = __jsdict([["enumerable", true]]); prop = klass.__properties__[ (name.__uid__) ? name.__uid__ : name]; if (prop[ ("get".__uid__) ? "get".__uid__ : "get"]) { @@ -549,10 +572,10 @@ __bind_property_descriptors__ = function(o, klass) { } Object.defineProperty(o, name, desc); } - var __iter4 = klass.__bases__; - if (! (__iter4 instanceof Array || typeof __iter4 == "string") ) { __iter4 = __object_keys__(__iter4) } - for (var __idx4=0; __idx4 < __iter4.length; __idx4++) { - var base = __iter4[ __idx4 ]; + var __iter5 = klass.__bases__; + if (! (__iter5 instanceof Array || typeof __iter5 == "string") ) { __iter5 = __object_keys__(__iter5) } + for (var __idx5=0; __idx5 < __iter5.length; __idx5++) { + var base = __iter5[ __idx5 ]; __bind_property_descriptors__(o, base); } } @@ -578,9 +601,32 @@ __generate_setter__.args_signature = ["klass", "o", "n"]; __generate_setter__.kwargs_signature = { }; __generate_setter__.types_signature = { }; __sprintf = function(fmt, args) { + var chunks, item, arr; + chunks = fmt.split("%s"); + arr = []; var i; i = 0; - return fmt.replace(/%((%)|s)/g, function (m) { return m[2] || args[i++] }); + var __iter6 = chunks; + if (! (__iter6 instanceof Array || typeof __iter6 == "string") ) { __iter6 = __object_keys__(__iter6) } + for (var __idx6=0; __idx6 < __iter6.length; __idx6++) { + var txt = __iter6[ __idx6 ]; + arr.append(txt); + if (( i ) >= args.length) { + break; + } + item = args[ (i.__uid__) ? i.__uid__ : i]; + if (( typeof(item) ) == "string") { + arr.append(item); + } else { + if (( typeof(item) ) == "number") { + arr.append(("" + item)); + } else { + arr.append(Object.prototype.toString.call(item)); + } + } + i += 1; + } + return "".join(arr); } __sprintf.NAME = "__sprintf"; @@ -602,10 +648,10 @@ create_class = function(class_name, parents, attrs, props) { klass.__all_method_names__ = []; klass.__properties__ = props; klass.__attributes__ = attrs; - var __iter5 = attrs; - if (! (__iter5 instanceof Array || typeof __iter5 == "string") ) { __iter5 = __object_keys__(__iter5) } - for (var __idx5=0; __idx5 < __iter5.length; __idx5++) { - var key = __iter5[ __idx5 ]; + var __iter7 = attrs; + if (! (__iter7 instanceof Array || typeof __iter7 == "string") ) { __iter7 = __object_keys__(__iter7) } + for (var __idx7=0; __idx7 < __iter7.length; __idx7++) { + var key = __iter7[ __idx7 ]; if (( typeof(attrs[ (key.__uid__) ? key.__uid__ : key]) ) == "function") { klass.__all_method_names__.push(key); if (attrs[ (key.__uid__) ? key.__uid__ : key].is_classmethod || attrs[ (key.__uid__) ? key.__uid__ : key].is_staticmethod) { @@ -621,20 +667,20 @@ create_class = function(class_name, parents, attrs, props) { } klass.__setters__ = []; klass.__getters__ = []; - var __iter6 = klass.__properties__; - if (! (__iter6 instanceof Array || typeof __iter6 == "string") ) { __iter6 = __object_keys__(__iter6) } - for (var __idx6=0; __idx6 < __iter6.length; __idx6++) { - var name = __iter6[ __idx6 ]; + var __iter8 = klass.__properties__; + if (! (__iter8 instanceof Array || typeof __iter8 == "string") ) { __iter8 = __object_keys__(__iter8) } + for (var __idx8=0; __idx8 < __iter8.length; __idx8++) { + var name = __iter8[ __idx8 ]; prop = klass.__properties__[ (name.__uid__) ? name.__uid__ : name]; klass.__getters__.push(name); if (prop[ ("set".__uid__) ? "set".__uid__ : "set"]) { klass.__setters__.push(name); } } - var __iter7 = klass.__bases__; - if (! (__iter7 instanceof Array || typeof __iter7 == "string") ) { __iter7 = __object_keys__(__iter7) } - for (var __idx7=0; __idx7 < __iter7.length; __idx7++) { - var base = __iter7[ __idx7 ]; + var __iter9 = klass.__bases__; + if (! (__iter9 instanceof Array || typeof __iter9 == "string") ) { __iter9 = __object_keys__(__iter9) } + for (var __idx9=0; __idx9 < __iter9.length; __idx9++) { + var base = __iter9[ __idx9 ]; Array.prototype.push.apply(klass.__getters__, base.__getters__); Array.prototype.push.apply(klass.__setters__, base.__setters__); Array.prototype.push.apply(klass.__all_method_names__, base.__all_method_names__); @@ -647,10 +693,10 @@ create_class = function(class_name, parents, attrs, props) { object.__dict__ = object; has_getattribute = false; has_getattr = false; - var __iter8 = klass.__all_method_names__; - if (! (__iter8 instanceof Array || typeof __iter8 == "string") ) { __iter8 = __object_keys__(__iter8) } - for (var __idx8=0; __idx8 < __iter8.length; __idx8++) { - var name = __iter8[ __idx8 ]; + var __iter10 = klass.__all_method_names__; + if (! (__iter10 instanceof Array || typeof __iter10 == "string") ) { __iter10 = __object_keys__(__iter10) } + for (var __idx10=0; __idx10 < __iter10.length; __idx10++) { + var name = __iter10[ __idx10 ]; if (( name ) == "__getattribute__") { has_getattribute = true; } else { @@ -791,7 +837,7 @@ setattr = function(args, kwargs) { console.log("ERROR: setattr property error", prop); } } else { - set_attribute(ob, attr, value); + __set__(ob, attr, value); } } @@ -1082,10 +1128,10 @@ _setup_str_prototype = function(args, kwargs) { arr = a["$wrapped"]; } i = 0; - var __iter9 = arr; - if (! (__iter9 instanceof Array || typeof __iter9 == "string") ) { __iter9 = __object_keys__(__iter9) } - for (var __idx9=0; __idx9 < __iter9.length; __idx9++) { - var value = __iter9[ __idx9 ]; + var __iter11 = arr; + if (! (__iter11 instanceof Array || typeof __iter11 == "string") ) { __iter11 = __object_keys__(__iter11) } + for (var __idx11=0; __idx11 < __iter11.length; __idx11++) { + var value = __iter11[ __idx11 ]; out += value; i += 1; if (( i ) < arr.length) { @@ -1144,10 +1190,10 @@ _setup_str_prototype = function(args, kwargs) { var func = function() { var digits; digits = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]; - var __iter10 = this; - if (! (__iter10 instanceof Array || typeof __iter10 == "string") ) { __iter10 = __object_keys__(__iter10) } - for (var __idx10=0; __idx10 < __iter10.length; __idx10++) { - var char = __iter10[ __idx10 ]; + var __iter12 = this; + if (! (__iter12 instanceof Array || typeof __iter12 == "string") ) { __iter12 = __object_keys__(__iter12) } + for (var __idx12=0; __idx12 < __iter12.length; __idx12++) { + var char = __iter12[ __idx12 ]; if (Object.hasOwnProperty.call(digits, "__contains__") && digits["__contains__"](char) || Object.hasOwnProperty.call(digits, char) || ( typeof(digits) ) == "string" && digits.__contains__(char)) { /*pass*/ } else { @@ -1298,10 +1344,10 @@ _setup_array_prototype = function(args, kwargs) { func.types_signature = { }; Array.prototype.append = func; var extend = function(self, other) { - var __iter11 = other; - if (! (__iter11 instanceof Array || typeof __iter11 == "string") ) { __iter11 = __object_keys__(__iter11) } - for (var __idx11=0; __idx11 < __iter11.length; __idx11++) { - var obj = __iter11[ __idx11 ]; + var __iter13 = other; + if (! (__iter13 instanceof Array || typeof __iter13 == "string") ) { __iter13 = __object_keys__(__iter13) } + for (var __idx13=0; __idx13 < __iter13.length; __idx13++) { + var obj = __iter13[ __idx13 ]; this.push(obj); } } @@ -1358,10 +1404,10 @@ _setup_array_prototype = function(args, kwargs) { var count = function(obj) { var a; a = 0; - var __iter12 = this; - if (! (__iter12 instanceof Array || typeof __iter12 == "string") ) { __iter12 = __object_keys__(__iter12) } - for (var __idx12=0; __idx12 < __iter12.length; __idx12++) { - var item = __iter12[ __idx12 ]; + var __iter14 = this; + if (! (__iter14 instanceof Array || typeof __iter14 == "string") ) { __iter14 = __object_keys__(__iter14) } + for (var __idx14=0; __idx14 < __iter14.length; __idx14++) { + var item = __iter14[ __idx14 ]; if (( item ) === obj) { a += 1; } @@ -1418,10 +1464,10 @@ _setup_array_prototype = function(args, kwargs) { func.types_signature = { }; Array.prototype.intersection = func; var func = function(other) { - var __iter13 = this; - if (! (__iter13 instanceof Array || typeof __iter13 == "string") ) { __iter13 = __object_keys__(__iter13) } - for (var __idx13=0; __idx13 < __iter13.length; __idx13++) { - var item = __iter13[ __idx13 ]; + var __iter15 = this; + if (! (__iter15 instanceof Array || typeof __iter15 == "string") ) { __iter15 = __object_keys__(__iter15) } + for (var __idx15=0; __idx15 < __iter15.length; __idx15++) { + var item = __iter15[ __idx15 ]; if (( other.indexOf(item) ) == -1) { return false; } @@ -1586,7 +1632,7 @@ map = function(args, kwargs) { var func = arguments['func']; var objs = arguments['objs']; arr = []; - var __iterator__, ob; + var ob, __iterator__; __iterator__ = __get__(__get__(objs, "__iter__"), "__call__")([], Object()); var __next__; __next__ = __get__(__iterator__, "next_fast"); @@ -1617,7 +1663,7 @@ filter = function(args, kwargs) { var func = arguments['func']; var objs = arguments['objs']; arr = []; - var __iterator__, ob; + var ob, __iterator__; __iterator__ = __get__(__get__(objs, "__iter__"), "__call__")([], Object()); var __next__; __next__ = __get__(__iterator__, "next_fast"); @@ -1648,7 +1694,7 @@ min = function(args, kwargs) { arguments = get_arguments(signature, args, kwargs); var lst = arguments['lst']; a = undefined; - var __iterator__, value; + var value, __iterator__; __iterator__ = __get__(__get__(lst, "__iter__"), "__call__")([], Object()); var __next__; __next__ = __get__(__iterator__, "next_fast"); @@ -1683,7 +1729,7 @@ max = function(args, kwargs) { arguments = get_arguments(signature, args, kwargs); var lst = arguments['lst']; a = undefined; - var __iterator__, value; + var value, __iterator__; __iterator__ = __get__(__get__(lst, "__iter__"), "__call__")([], Object()); var __next__; __next__ = __get__(__iterator__, "next_fast"); @@ -1868,7 +1914,7 @@ __tuple___init__ = function(args, kwargs) { self["$wrapped"] = arr; } if (js_object instanceof Array) { - var __iterator__, item; + var item, __iterator__; __iterator__ = __get__(__get__(js_object, "__iter__"), "__call__")([], Object()); var __next__; __next__ = __get__(__iterator__, "next_fast"); @@ -2020,10 +2066,10 @@ __tuple_count = function(args, kwargs) { var self = arguments['self']; var obj = arguments['obj']; a = 0; - var __iter14 = self["$wrapped"]; - if (! (__iter14 instanceof Array || typeof __iter14 == "string") ) { __iter14 = __object_keys__(__iter14) } - for (var __idx14=0; __idx14 < __iter14.length; __idx14++) { - var item = __iter14[ __idx14 ]; + var __iter16 = self["$wrapped"]; + if (! (__iter16 instanceof Array || typeof __iter16 == "string") ) { __iter16 = __object_keys__(__iter16) } + for (var __idx16=0; __idx16 < __iter16.length; __idx16++) { + var item = __iter16[ __idx16 ]; if (( item ) == obj) { a += 1; } @@ -2143,7 +2189,7 @@ __pylist___init__ = function(args, kwargs) { arr = []; self["$wrapped"] = arr; if (js_object instanceof Array) { - var __iterator__, item; + var item, __iterator__; __iterator__ = __get__(__get__(js_object, "__iter__"), "__call__")([], Object()); var __next__; __next__ = __get__(__iterator__, "next_fast"); @@ -2269,7 +2315,7 @@ __pylist_extend = function(args, kwargs) { arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var other = arguments['other']; - var __iterator__, obj; + var obj, __iterator__; __iterator__ = __get__(__get__(other, "__iter__"), "__call__")([], Object()); var __next__; __next__ = __get__(__iterator__, "next_fast"); @@ -2385,10 +2431,10 @@ __pylist_count = function(args, kwargs) { var self = arguments['self']; var obj = arguments['obj']; a = 0; - var __iter15 = self["$wrapped"]; - if (! (__iter15 instanceof Array || typeof __iter15 == "string") ) { __iter15 = __object_keys__(__iter15) } - for (var __idx15=0; __idx15 < __iter15.length; __idx15++) { - var item = __iter15[ __idx15 ]; + var __iter17 = self["$wrapped"]; + if (! (__iter17 instanceof Array || typeof __iter17 == "string") ) { __iter17 = __object_keys__(__iter17) } + for (var __idx17=0; __idx17 < __iter17.length; __idx17++) { + var item = __iter17[ __idx17 ]; if (( item ) == obj) { a += 1; } @@ -2633,48 +2679,54 @@ __dict___init__ = function(args, kwargs) { kwargs = Object(); } var signature, arguments; - signature = {"kwargs": {"js_object": undefined}, "args": __create_array__("self", "js_object")}; + signature = {"kwargs": {"js_object": undefined, "pointer": undefined}, "args": __create_array__("self", "js_object", "pointer")}; arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var js_object = arguments['js_object']; + var pointer = arguments['pointer']; self["$wrapped"] = __jsdict([]); - if (js_object) { - ob = js_object; - if (ob instanceof Array) { - var __iterator__, o; - __iterator__ = __get__(__get__(ob, "__iter__"), "__call__")([], Object()); - var __next__; - __next__ = __get__(__iterator__, "next_fast"); - while(( __iterator__.index ) < __iterator__.length) { - o = __next__(); - if (o instanceof Array) { - __get__(__get__(self, "__setitem__"), "__call__")([__get__(o, "__getitem__")([0], Object()), __get__(o, "__getitem__")([1], Object())], __NULL_OBJECT__); - } else { - __get__(__get__(self, "__setitem__"), "__call__")([__get__(o, "__getitem__")(["key"], Object()), __get__(o, "__getitem__")(["value"], Object())], __NULL_OBJECT__); - } - } - } else { - if (isinstance([ob, dict], __NULL_OBJECT__)) { - var key; - __iterator__ = __get__(__get__(__jsdict_keys(ob), "__iter__"), "__call__")([], Object()); - ; + if (( pointer ) !== undefined) { + self["$wrapped"] = pointer; + } else { + if (js_object) { + ob = js_object; + if (ob instanceof Array) { + var o, __iterator__; + __iterator__ = __get__(__get__(ob, "__iter__"), "__call__")([], Object()); + var __next__; __next__ = __get__(__iterator__, "next_fast"); while(( __iterator__.index ) < __iterator__.length) { - key = __next__(); - value = __get__(ob, "__getitem__")([key], Object()); - __get__(__get__(self, "__setitem__"), "__call__")([key, value], __NULL_OBJECT__); + o = __next__(); + if (o instanceof Array) { + __get__(__get__(self, "__setitem__"), "__call__")([__get__(o, "__getitem__")([0], Object()), __get__(o, "__getitem__")([1], Object())], __NULL_OBJECT__); + } else { + __get__(__get__(self, "__setitem__"), "__call__")([__get__(o, "__getitem__")(["key"], Object()), __get__(o, "__getitem__")(["value"], Object())], __NULL_OBJECT__); + } } } else { - console.log(["TODO init dict from:", js_object]); + if (isinstance([ob, dict], __NULL_OBJECT__)) { + var key; + __iterator__ = __get__(__get__(__jsdict_keys(ob), "__iter__"), "__call__")([], Object()); + ; + __next__ = __get__(__iterator__, "next_fast"); + while(( __iterator__.index ) < __iterator__.length) { + key = __next__(); + value = __get__(ob, "__getitem__")([key], Object()); + __get__(__get__(self, "__setitem__"), "__call__")([key, value], __NULL_OBJECT__); + } + } else { + console.log("ERROR init dict from:", js_object); + throw TypeError; + } } } } } __dict___init__.NAME = "__dict___init__"; -__dict___init__.args_signature = ["self", "js_object"]; -__dict___init__.kwargs_signature = { js_object:undefined }; -__dict___init__.types_signature = { js_object:"None" }; +__dict___init__.args_signature = ["self", "js_object", "pointer"]; +__dict___init__.kwargs_signature = { js_object:undefined,pointer:undefined }; +__dict___init__.types_signature = { js_object:"None",pointer:"None" }; __dict___init__.pythonscript_function = true; __dict_attrs["__init__"] = __dict___init__; __dict_jsify = function(args, kwargs) { @@ -2690,7 +2742,7 @@ __dict_jsify = function(args, kwargs) { arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; keys = __get__(Object, "keys")(self["$wrapped"]); - var __iterator__, key; + var key, __iterator__; __iterator__ = __get__(__get__(keys, "__iter__"), "__call__")([], Object()); var __next__; __next__ = __get__(__iterator__, "next_fast"); @@ -2795,7 +2847,7 @@ __dict_update = function(args, kwargs) { arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var other = arguments['other']; - var __iterator__, key; + var key, __iterator__; __iterator__ = __get__(__get__(other, "__iter__"), "__call__")([], Object()); var __next__; __next__ = __get__(__iterator__, "next_fast"); @@ -2824,7 +2876,7 @@ __dict_items = function(args, kwargs) { arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; arr = []; - var __iterator__, key; + var key, __iterator__; __iterator__ = __get__(__get__(__jsdict_keys(self), "__iter__"), "__call__")([], Object()); var __next__; __next__ = __get__(__iterator__, "next_fast"); @@ -3044,10 +3096,10 @@ __dict_values = function(args, kwargs) { var self = arguments['self']; keys = Object.keys(self["$wrapped"]); out = []; - var __iter16 = keys; - if (! (__iter16 instanceof Array || typeof __iter16 == "string") ) { __iter16 = __object_keys__(__iter16) } - for (var __idx16=0; __idx16 < __iter16.length; __idx16++) { - var key = __iter16[ __idx16 ]; + var __iter18 = keys; + if (! (__iter18 instanceof Array || typeof __iter18 == "string") ) { __iter18 = __object_keys__(__iter18) } + for (var __idx18=0; __idx18 < __iter18.length; __idx18++) { + var key = __iter18[ __idx18 ]; out.push(self["$wrapped"][ (key.__uid__) ? key.__uid__ : key]); } return out; @@ -3148,10 +3200,10 @@ set = function(args, kwargs) { } fallback = false; if (hashtable) { - var __iter17 = a; - if (! (__iter17 instanceof Array || typeof __iter17 == "string") ) { __iter17 = __object_keys__(__iter17) } - for (var __idx17=0; __idx17 < __iter17.length; __idx17++) { - var b = __iter17[ __idx17 ]; + var __iter19 = a; + if (! (__iter19 instanceof Array || typeof __iter19 == "string") ) { __iter19 = __object_keys__(__iter19) } + for (var __idx19=0; __idx19 < __iter19.length; __idx19++) { + var b = __iter19[ __idx19 ]; if (typeof(b, "number") && ( b ) === ( (b | 0) )) { key = (b & mask); hashtable[ (key.__uid__) ? key.__uid__ : key] = b; @@ -3166,20 +3218,20 @@ set = function(args, kwargs) { } s = []; if (fallback) { - var __iter18 = a; - if (! (__iter18 instanceof Array || typeof __iter18 == "string") ) { __iter18 = __object_keys__(__iter18) } - for (var __idx18=0; __idx18 < __iter18.length; __idx18++) { - var item = __iter18[ __idx18 ]; + var __iter20 = a; + if (! (__iter20 instanceof Array || typeof __iter20 == "string") ) { __iter20 = __object_keys__(__iter20) } + for (var __idx20=0; __idx20 < __iter20.length; __idx20++) { + var item = __iter20[ __idx20 ]; if (( s.indexOf(item) ) == -1) { s.push(item); } } } else { keys.sort(); - var __iter19 = keys; - if (! (__iter19 instanceof Array || typeof __iter19 == "string") ) { __iter19 = __object_keys__(__iter19) } - for (var __idx19=0; __idx19 < __iter19.length; __idx19++) { - var key = __iter19[ __idx19 ]; + var __iter21 = keys; + if (! (__iter21 instanceof Array || typeof __iter21 == "string") ) { __iter21 = __object_keys__(__iter21) } + for (var __idx21=0; __idx21 < __iter21.length; __idx21++) { + var key = __iter21[ __idx21 ]; s.push(hashtable[ (key.__uid__) ? key.__uid__ : key]); } } @@ -3551,7 +3603,7 @@ __array_extend = function(args, kwargs) { arguments = get_arguments(signature, args, kwargs); var self = arguments['self']; var lst = arguments['lst']; - var __iterator__, value; + var value, __iterator__; __iterator__ = __get__(__get__(lst, "__iter__"), "__call__")([], Object()); var __next__; __next__ = __get__(__iterator__, "next_fast"); @@ -3742,7 +3794,7 @@ _to_json = function(args, kwargs) { var pythonjs = arguments['pythonjs']; if (isinstance([pythonjs, list], __NULL_OBJECT__)) { r = []; - var __iterator__, i; + var i, __iterator__; __iterator__ = __get__(__get__(pythonjs, "__iter__"), "__call__")([], Object()); var __next__; __next__ = __get__(__iterator__, "next_fast"); diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index 873f9eb..4631cb0 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -379,7 +379,8 @@ def visit_Dict(self, node): return '__jsdict( [%s] )' %b else: b = '[%s]' %', '.join(a) - return '__get__(dict, "__call__")([], JSObject(js_object=%s))' %b + #return '__get__(dict, "__call__")([], JSObject(js_object=%s))' %b + return '__get__(dict, "__call__")([%s], JSObject())' %b def visit_Tuple(self, node): node.returns_type = 'tuple' @@ -1656,12 +1657,17 @@ def visit_Call(self, node): writer.append('%s = JSArray(%s)' % (args_name, args)) if node.starargs: - writer.append('%s.push.apply(%s, %s[...])' % (args_name, args_name, self.visit(node.starargs))) + writer.append('%s.push.apply(%s, %s)' % (args_name, args_name, self.visit(node.starargs))) + writer.append('%s = JSObject(%s)' % (kwargs_name, kwargs)) if node.kwargs: kwargs = self.visit(node.kwargs) - code = "JS('for (var name in %s) { %s[name] = %s[...][name]; }')" % (kwargs, kwargs_name, kwargs) + writer.write('var(__kwargs_temp)') + writer.write('__kwargs_temp = %s[...]' %kwargs) + #code = "JS('for (var name in %s) { %s[name] = %s[...][name]; }')" % (kwargs, kwargs_name, kwargs) + #code = "for __name in %s: %s[__name] = %s[__name]" % (kwargs, kwargs_name, kwargs) + code = "JS('for (var name in __kwargs_temp) { %s[name] = __kwargs_temp[name]; }')" %kwargs_name writer.append(code) ####################################### @@ -1677,7 +1683,7 @@ def visit_Call(self, node): # return '%s()' %name ## special method calls ## - if isinstance(node.func, ast.Attribute) and node.func.attr in ('get', 'keys', 'values', 'pop'): + if isinstance(node.func, ast.Attribute) and node.func.attr in ('get', 'keys', 'values', 'pop', 'items'): anode = node.func if anode.attr == 'get': if args: @@ -1691,6 +1697,9 @@ def visit_Call(self, node): elif anode.attr == 'values' and not args: return '__jsdict_values(%s)' %self.visit(anode.value) + elif anode.attr == 'items' and not args: + return '__jsdict_items(%s)' %self.visit(anode.value) + elif anode.attr == 'pop': if args: return '__jsdict_pop(%s, %s)' %(self.visit(anode.value), args ) @@ -1735,12 +1744,7 @@ def visit_Call(self, node): elif call_has_args: if name == 'dict': - return '__get__(%s, "__call__")(%s, JSObject(js_object=%s))' % (name, args_name, kwargs_name) - #elif name in ('list', 'tuple'): - # if len(node.args): - # return '__get__(%s, "__call__")([], {js_object:%s})' % (name, args_name) - # else: - # return '__get__(%s, "__call__")([], %s)' % (name, kwargs_name) + return '__get__(%s, "__call__")(%s, JSObject(pointer=%s))' % (name, args_name, kwargs_name) else: return '__get__(%s, "__call__")(%s, %s)' % (name, args_name, kwargs_name) @@ -1993,15 +1997,19 @@ def visit_FunctionDef(self, node): writer.write("""JS("var %s = arguments['%s']")""" % (arg.id, arg.id)) if node.args.vararg: writer.write("""JS("var %s = arguments['%s']")""" % (node.args.vararg, node.args.vararg)) + + ## DEPRECATED # turn it into a list - expr = '%s = __get__(list, "__call__")(__create_array__(%s), {});' - expr = expr % (node.args.vararg, node.args.vararg) - writer.write(expr) + #expr = '%s = __get__(list, "__call__")(__create_array__(%s), {});' + #expr = expr % (node.args.vararg, node.args.vararg) + #writer.write(expr) if node.args.kwarg: writer.write("""JS('var %s = arguments["%s"]')""" % (node.args.kwarg, node.args.kwarg)) - expr = '%s = __get__(dict, "__call__")(__create_array__(%s), {});' - expr = expr % (node.args.kwarg, node.args.kwarg) - writer.write(expr) + + ## DEPRECATED + #expr = '%s = __get__(dict, "__call__")(__create_array__(%s), {});' + #expr = expr % (node.args.kwarg, node.args.kwarg) + #writer.write(expr) else: log('(function has no arguments)') @@ -2209,7 +2217,7 @@ def visit_For(self, node): writer.push() for i,elt in enumerate(multi_target): writer.write('%s = __mtarget__[%s]' %(elt,i)) - + else: writer.write('for %s in %s:' %(self.visit(target),self.visit(iter))) writer.push() diff --git a/runtime/builtins.py b/runtime/builtins.py index f47756e..f6dfa8f 100644 --- a/runtime/builtins.py +++ b/runtime/builtins.py @@ -69,6 +69,19 @@ def __jsdict_values(ob): ## this works because instances from PythonJS are created using Object.create(null) ## return JS("ob.values()") + def __jsdict_items(ob): + ## `ob.items is None` is for: "self.__dict__.items()" because self.__dict__ is not actually a dict + if instanceof(ob, Object) or ob.items is None: + arr = [] + for key in ob: + #if ob.hasOwnProperty(key): + if Object.hasOwnProperty.call(ob, key): + value = ob[key] + arr.push( [key,value] ) + return arr + else: ## PythonJS object instance ## + return JS("ob.items()") + def __jsdict_pop(ob, key, _default=None): if instanceof(ob, Array): if ob.length: @@ -120,8 +133,22 @@ def __generate_setter__(klass, o, n): def __sprintf(fmt, args): - i = 0 - return JS("fmt.replace(/%((%)|s)/g, function (m) { return m[2] || args[i++] })") + ## note: '%sXXX%s'.split().length != args.length + ## because `%s` at the start or end will split to empty chunks ## + chunks = fmt.split('%s') + arr = [] + for i,txt in enumerate(chunks): + arr.append( txt ) + if i >= args.length: + break + item = args[i] + if typeof(item) == 'string': + arr.append( item ) + elif typeof(item) == 'number': + arr.append( ''+item ) + else: + arr.append( Object.prototype.toString.call(item) ) + return ''.join(arr) def create_class(class_name, parents, attrs, props): """Create a PythonScript class""" @@ -149,7 +176,7 @@ def create_class(class_name, parents, attrs, props): if key == '__getattribute__': continue klass[key] = attrs[key] - ## this is needed for fast lookup of property names in set_attribute ## + ## this is needed for fast lookup of property names in __set__ ## klass.__setters__ = [] klass.__getters__ = [] for name in klass.__properties__: @@ -247,7 +274,7 @@ def setattr(ob, attr, value, property=False): else: print "ERROR: setattr property error", prop else: - set_attribute(ob, attr, value) + __set__(ob, attr, value) def issubclass(C, B): if C is B: @@ -843,11 +870,14 @@ class dict: # http://stackoverflow.com/questions/10892322/javascript-hashtable-use-object-key # using a function as a key is allowed, but would waste memory because it gets converted to a string # http://stackoverflow.com/questions/10858632/are-functions-valid-keys-for-javascript-object-properties - def __init__(self, js_object=None): + def __init__(self, js_object=None, pointer=None): with javascript: self[...] = {} - if js_object: + if pointer is not None: + self[...] = pointer + + elif js_object: ob = js_object if instanceof(ob, Array): for o in ob: @@ -860,7 +890,8 @@ def __init__(self, js_object=None): value = ob[ key ] self.__setitem__( key, value ) else: - print('TODO init dict from:', js_object) + print 'ERROR init dict from:', js_object + raise TypeError def jsify(self): keys = Object.keys( self[...] ) diff --git a/tests/helloworld.html b/tests/helloworld.html index 933d767..4ae7424 100644 --- a/tests/helloworld.html +++ b/tests/helloworld.html @@ -1,6 +1,6 @@ - + + + + + + + + + \ No newline at end of file From 2f9f22838ddbd74dfde45b69e094a8a005b89946 Mon Sep 17 00:00:00 2001 From: hartsantler Date: Fri, 24 Jan 2014 01:03:47 -0800 Subject: [PATCH 092/521] fixed if test on empty dict now returns False --- pythonjs.js | 46 ++++++++++++++++++++++++---------- pythonjs/python_to_pythonjs.py | 10 +++++++- regtests/dict/if_empty.py | 21 ++++++++++++++++ runtime/builtins.py | 10 ++++++++ 4 files changed, 73 insertions(+), 14 deletions(-) create mode 100644 regtests/dict/if_empty.py diff --git a/pythonjs.js b/pythonjs.js index 894748b..1707c55 100644 --- a/pythonjs.js +++ b/pythonjs.js @@ -1,4 +1,4 @@ -// PythonJS Runtime - regenerated on: Thu Jan 23 22:33:59 2014 +// PythonJS Runtime - regenerated on: Fri Jan 24 00:56:54 2014 __NULL_OBJECT__ = Object.create(null); if (( "window" ) in this && ( "document" ) in this) { __WEBWORKER__ = false; @@ -406,6 +406,26 @@ _PythonJS_UID = 0; var IndexError = new RangeError(); var KeyError = new RangeError(); var ValueError = new RangeError(); +__test_if_true__ = function(ob) { + if (ob instanceof Array) { + return ( ob.length ) != 0; + } else { + if (isinstance(ob, dict)) { + return ( Object.keys(ob["$wrapped"]).length ) != 0; + } else { + if (ob instanceof Object) { + return ( Object.keys(ob).length ) != 0; + } else { + return true; + } + } + } +} + +__test_if_true__.NAME = "__test_if_true__"; +__test_if_true__.args_signature = ["ob"]; +__test_if_true__.kwargs_signature = { }; +__test_if_true__.types_signature = { }; __jsdict = function(items) { var d, key; d = {}; @@ -710,10 +730,10 @@ create_class = function(class_name, parents, attrs, props) { } } } - if (has_getattr) { + if (__test_if_true__(has_getattr)) { __get__(object, "__getattr__"); } - if (has_getattribute) { + if (__test_if_true__(has_getattribute)) { __get__(object, "__getattribute__"); } __bind_property_descriptors__(object, klass); @@ -797,7 +817,7 @@ getattr = function(args, kwargs) { var ob = arguments['ob']; var attr = arguments['attr']; var property = arguments['property']; - if (property) { + if (__test_if_true__(property)) { prop = _get_upstream_property(ob.__class__, attr); if (prop && prop[ ("get".__uid__) ? "get".__uid__ : "get"]) { return prop[ ("get".__uid__) ? "get".__uid__ : "get"]([ob], __jsdict([])); @@ -829,7 +849,7 @@ setattr = function(args, kwargs) { var attr = arguments['attr']; var value = arguments['value']; var property = arguments['property']; - if (property) { + if (__test_if_true__(property)) { prop = _get_upstream_property(ob.__class__, attr); if (prop && prop[ ("set".__uid__) ? "set".__uid__ : "set"]) { prop[ ("set".__uid__) ? "set".__uid__ : "set"]([ob, value], __jsdict([])); @@ -1907,7 +1927,7 @@ __tuple___init__ = function(args, kwargs) { var self = arguments['self']; var js_object = arguments['js_object']; var pointer = arguments['pointer']; - if (pointer) { + if (__test_if_true__(pointer)) { self["$wrapped"] = pointer; } else { arr = []; @@ -1923,7 +1943,7 @@ __tuple___init__ = function(args, kwargs) { __get__(__get__(arr, "push"), "__call__")([item], __NULL_OBJECT__); } } else { - if (js_object) { + if (__test_if_true__(js_object)) { if (isinstance([js_object, array], __NULL_OBJECT__) || isinstance([js_object, tuple], __NULL_OBJECT__) || isinstance([js_object, list], __NULL_OBJECT__)) { var v; __iterator__ = __get__(__get__(js_object, "__iter__"), "__call__")([], Object()); @@ -2183,7 +2203,7 @@ __pylist___init__ = function(args, kwargs) { var self = arguments['self']; var js_object = arguments['js_object']; var pointer = arguments['pointer']; - if (pointer) { + if (__test_if_true__(pointer)) { self["$wrapped"] = pointer; } else { arr = []; @@ -2198,7 +2218,7 @@ __pylist___init__ = function(args, kwargs) { __get__(__get__(arr, "push"), "__call__")([item], __NULL_OBJECT__); } } else { - if (js_object) { + if (__test_if_true__(js_object)) { if (isinstance([js_object, array], __NULL_OBJECT__) || isinstance([js_object, tuple], __NULL_OBJECT__) || isinstance([js_object, list], __NULL_OBJECT__)) { var v; __iterator__ = __get__(__get__(js_object, "__iter__"), "__call__")([], Object()); @@ -2688,7 +2708,7 @@ __dict___init__ = function(args, kwargs) { if (( pointer ) !== undefined) { self["$wrapped"] = pointer; } else { - if (js_object) { + if (__test_if_true__(js_object)) { ob = js_object; if (ob instanceof Array) { var o, __iterator__; @@ -3199,7 +3219,7 @@ set = function(args, kwargs) { } } fallback = false; - if (hashtable) { + if (__test_if_true__(hashtable)) { var __iter19 = a; if (! (__iter19 instanceof Array || typeof __iter19 == "string") ) { __iter19 = __object_keys__(__iter19) } for (var __idx19=0; __idx19 < __iter19.length; __idx19++) { @@ -3217,7 +3237,7 @@ set = function(args, kwargs) { fallback = true; } s = []; - if (fallback) { + if (__test_if_true__(fallback)) { var __iter20 = a; if (! (__iter20 instanceof Array || typeof __iter20 == "string") ) { __iter20 = __object_keys__(__iter20) } for (var __idx20=0; __idx20 < __iter20.length; __idx20++) { @@ -3288,7 +3308,7 @@ __array___init__ = function(args, kwargs) { self.typecode = typecode; self.itemsize = __get__(__get__(self, "typecodes"), "__getitem__")([typecode], Object()); self.little_endian = little_endian; - if (initializer) { + if (__test_if_true__(initializer)) { self.length = len([initializer], __NULL_OBJECT__); self.bytes = (self.length * self.itemsize); if (( self.typecode ) == "float8") { diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index 4631cb0..519a08b 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -845,7 +845,15 @@ def visit_BoolOp(self, node): return op.join( [self.visit(v) for v in node.values] ) def visit_If(self, node): - writer.write('if %s:' % self.visit(node.test)) + if isinstance(node.test, ast.Dict): + if self._with_js: + writer.write('if Object.keys(%s).length:' % self.visit(node.test)) + else: + writer.write('if %s.keys().length:' % self.visit(node.test)) + elif isinstance(node.test, ast.Name): + writer.write('if __test_if_true__(%s):' % self.visit(node.test)) + else: + writer.write('if %s:' % self.visit(node.test)) writer.push() map(self.visit, node.body) writer.pull() diff --git a/regtests/dict/if_empty.py b/regtests/dict/if_empty.py new file mode 100644 index 0000000..3093db6 --- /dev/null +++ b/regtests/dict/if_empty.py @@ -0,0 +1,21 @@ +"""if empty dict then false""" +d = {} +if d: + err1 = 1 +else: + err1 = 0 + +if {}: + err2 = 1 +else: + err2 = 0 + +d['x'] = 'xxx' +if d: + err3 = 0 +else: + err3 = 1 + +Error( err1 == 0 ) +Error( err2 == 0 ) +Error( err3 == 0 ) diff --git a/runtime/builtins.py b/runtime/builtins.py index f6dfa8f..d468d15 100644 --- a/runtime/builtins.py +++ b/runtime/builtins.py @@ -26,6 +26,16 @@ ## when translated methods named: "get" become __jsdict_get(ob,key,default) with javascript: + def __test_if_true__( ob ): + if instanceof(ob, Array): + return ob.length != 0 + elif isinstance(ob, dict): + return Object.keys( ob[...] ).length != 0 + elif instanceof(ob, Object): + return Object.keys(ob).length != 0 + else: + return True + def __jsdict( items ): d = JS("{}") for item in items: From 38dffa8968e3fd1a4b4bf20833942b40fbf8898e Mon Sep 17 00:00:00 2001 From: hartsantler Date: Fri, 24 Jan 2014 01:09:02 -0800 Subject: [PATCH 093/521] fixed if test on empty list now returns False. --- pythonjs/python_to_pythonjs.py | 4 ++++ regtests/list/if_empty.py | 21 +++++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 regtests/list/if_empty.py diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index 519a08b..2de2fe2 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -850,6 +850,10 @@ def visit_If(self, node): writer.write('if Object.keys(%s).length:' % self.visit(node.test)) else: writer.write('if %s.keys().length:' % self.visit(node.test)) + + elif isinstance(node.test, ast.List): + writer.write('if %s.length:' % self.visit(node.test)) + elif isinstance(node.test, ast.Name): writer.write('if __test_if_true__(%s):' % self.visit(node.test)) else: diff --git a/regtests/list/if_empty.py b/regtests/list/if_empty.py new file mode 100644 index 0000000..4c27c51 --- /dev/null +++ b/regtests/list/if_empty.py @@ -0,0 +1,21 @@ +"""if empty list then false""" +d = [] +if d: + err1 = 1 +else: + err1 = 0 + +if []: + err2 = 1 +else: + err2 = 0 + +d.append('xxx') +if d: + err3 = 0 +else: + err3 = 1 + +Error( err1 == 0 ) +Error( err2 == 0 ) +Error( err3 == 0 ) From 83e0a0d21abafb9e18894267dd6894b826a90c58 Mon Sep 17 00:00:00 2001 From: hartsantler Date: Fri, 24 Jan 2014 03:54:39 -0800 Subject: [PATCH 094/521] fixed list.extend fixed concatenate lists `[]+[]` --- pythonjs.js | 242 ++++++++++++++++++++------------- pythonjs/python_to_pythonjs.py | 3 + regtests/list/concatenate.py | 10 ++ regtests/run.py | 4 +- runtime/builtins.py | 33 ++++- tests/test_list.html | 6 + 6 files changed, 203 insertions(+), 95 deletions(-) create mode 100644 regtests/list/concatenate.py diff --git a/pythonjs.js b/pythonjs.js index 1707c55..dbbee35 100644 --- a/pythonjs.js +++ b/pythonjs.js @@ -1,4 +1,4 @@ -// PythonJS Runtime - regenerated on: Fri Jan 24 00:56:54 2014 +// PythonJS Runtime - regenerated on: Fri Jan 24 03:52:27 2014 __NULL_OBJECT__ = Object.create(null); if (( "window" ) in this && ( "document" ) in this) { __WEBWORKER__ = false; @@ -426,6 +426,31 @@ __test_if_true__.NAME = "__test_if_true__"; __test_if_true__.args_signature = ["ob"]; __test_if_true__.kwargs_signature = { }; __test_if_true__.types_signature = { }; +__add_op = function(a, b) { + var c, t; + t = typeof(a); + if (( t ) == "number" || ( t ) == "string") { + return a+b; + } else { + if (a instanceof Array) { + c = []; + c.extend(a); + c.extend(b); + return c; + } else { + if (a.__add__) { + return a.__add__(b); + } else { + throw TypeError; + } + } + } +} + +__add_op.NAME = "__add_op"; +__add_op.args_signature = ["a", "b"]; +__add_op.kwargs_signature = { }; +__add_op.types_signature = { }; __jsdict = function(items) { var d, key; d = {}; @@ -639,7 +664,7 @@ __sprintf = function(fmt, args) { arr.append(item); } else { if (( typeof(item) ) == "number") { - arr.append(("" + item)); + arr.append(__add_op("", item)); } else { arr.append(Object.prototype.toString.call(item)); } @@ -992,14 +1017,14 @@ round = function(args, kwargs) { arguments = get_arguments(signature, args, kwargs); var a = arguments['a']; var places = arguments['places']; - b = ("" + a); + b = __add_op("", a); if (( b.indexOf(".") ) == -1) { return a; } else { c = b.split("."); x = c[0]; y = c[1].substring(0, places); - return parseFloat(((x + ".") + y)); + return parseFloat(__add_op(__add_op(x, "."), y)); } } @@ -1019,7 +1044,7 @@ str = function(args, kwargs) { signature = {"kwargs": Object(), "args": __create_array__("s")}; arguments = get_arguments(signature, args, kwargs); var s = arguments['s']; - return ("" + s); + return __add_op("", s); } str.NAME = "str"; @@ -1084,7 +1109,7 @@ _setup_str_prototype = function(args, kwargs) { return this.split("").reverse().join(""); } else { if (( stop ) < 0) { - stop = (this.length + stop); + stop = __add_op(this.length, stop); } return this.substring(start, stop); } @@ -1309,7 +1334,7 @@ _setup_array_prototype = function(args, kwargs) { var __getitem__ = function(index) { var index; if (( index ) < 0) { - index = (this.length + index); + index = __add_op(this.length, index); } return this[ (index.__uid__) ? index.__uid__ : index]; } @@ -1322,7 +1347,7 @@ _setup_array_prototype = function(args, kwargs) { var __setitem__ = function(index, value) { var index; if (( index ) < 0) { - index = (this.length + index); + index = __add_op(this.length, index); } this[ (index.__uid__) ? index.__uid__ : index] = value; } @@ -1344,7 +1369,7 @@ _setup_array_prototype = function(args, kwargs) { var func = function(start, stop, step) { var stop; if (( stop ) < 0) { - stop = (this.length + stop); + stop = __add_op(this.length, stop); } return this.slice(start, stop); } @@ -1363,7 +1388,7 @@ _setup_array_prototype = function(args, kwargs) { func.kwargs_signature = { }; func.types_signature = { }; Array.prototype.append = func; - var extend = function(self, other) { + var extend = function(other) { var __iter13 = other; if (! (__iter13 instanceof Array || typeof __iter13 == "string") ) { __iter13 = __object_keys__(__iter13) } for (var __idx13=0; __idx13 < __iter13.length; __idx13++) { @@ -1373,7 +1398,7 @@ _setup_array_prototype = function(args, kwargs) { } extend.NAME = "extend"; - extend.args_signature = ["self", "other"]; + extend.args_signature = ["other"]; extend.kwargs_signature = { }; extend.types_signature = { }; Array.prototype.extend = extend; @@ -1391,7 +1416,7 @@ _setup_array_prototype = function(args, kwargs) { var insert = function(index, obj) { var index; if (( index ) < 0) { - index = (this.length + index); + index = __add_op(this.length, index); } this.splice(index, 0, obj); } @@ -1449,12 +1474,12 @@ _setup_array_prototype = function(args, kwargs) { high = this.length; } while(( low ) < high) { - a = (low + high); + a = __add_op(low, high); mid = Math.floor((a / 2)); if (( x ) < this[ (mid.__uid__) ? mid.__uid__ : mid]) { high = mid; } else { - low = (mid + 1); + low = __add_op(mid, 1); } } return low; @@ -1875,7 +1900,7 @@ __Iterator_next = function(args, kwargs) { throw StopIteration; } item = __jsdict_get(self.obj, self.index); - self.index = (self.index + 1); + self.index = __add_op(self.index, 1); return item; } @@ -1909,11 +1934,44 @@ __Iterator_next_fast.types_signature = { }; __Iterator_next_fast.pythonscript_function = true; __Iterator_attrs["next_fast"] = __Iterator_next_fast; Iterator = create_class("Iterator", __Iterator_parents, __Iterator_attrs, __Iterator_properties); -var tuple, __tuple_attrs, __tuple_parents; -__tuple_attrs = Object(); -__tuple_parents = []; -__tuple_properties = Object(); -__tuple___init__ = function(args, kwargs) { +tuple = function(args, kwargs) { + if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { + /*pass*/ + } else { + args = Array.prototype.slice.call(arguments); + kwargs = Object(); + } + var signature, arguments; + signature = {"kwargs": Object(), "args": __create_array__("a")}; + arguments = get_arguments(signature, args, kwargs); + var a = arguments['a']; + if (( Object.keys(arguments).length ) == 0) { + return []; + } else { + if (a instanceof Array) { + return a.slice(); + } else { + if (( typeof(a) ) == "string") { + return a.split(""); + } else { + console.log(a); + console.log(arguments); + throw TypeError; + } + } + } +} + +tuple.NAME = "tuple"; +tuple.args_signature = ["a"]; +tuple.kwargs_signature = { }; +tuple.types_signature = { }; +tuple.pythonscript_function = true; +var pytuple, __pytuple_attrs, __pytuple_parents; +__pytuple_attrs = Object(); +__pytuple_parents = []; +__pytuple_properties = Object(); +__pytuple___init__ = function(args, kwargs) { var arr; if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ @@ -1960,13 +2018,13 @@ __tuple___init__ = function(args, kwargs) { } } -__tuple___init__.NAME = "__tuple___init__"; -__tuple___init__.args_signature = ["self", "js_object", "pointer"]; -__tuple___init__.kwargs_signature = { js_object:undefined,pointer:undefined }; -__tuple___init__.types_signature = { js_object:"None",pointer:"None" }; -__tuple___init__.pythonscript_function = true; -__tuple_attrs["__init__"] = __tuple___init__; -__tuple___getitem__ = function(args, kwargs) { +__pytuple___init__.NAME = "__pytuple___init__"; +__pytuple___init__.args_signature = ["self", "js_object", "pointer"]; +__pytuple___init__.kwargs_signature = { js_object:undefined,pointer:undefined }; +__pytuple___init__.types_signature = { js_object:"None",pointer:"None" }; +__pytuple___init__.pythonscript_function = true; +__pytuple_attrs["__init__"] = __pytuple___init__; +__pytuple___getitem__ = function(args, kwargs) { var index; if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ @@ -1980,18 +2038,18 @@ __tuple___getitem__ = function(args, kwargs) { var self = arguments['self']; var index = arguments['index']; if (( index ) < 0) { - index = (__get__(self["$wrapped"], "length") + index); + index = __add_op(__get__(self["$wrapped"], "length"), index); } return self["$wrapped"][ (index.__uid__) ? index.__uid__ : index]; } -__tuple___getitem__.NAME = "__tuple___getitem__"; -__tuple___getitem__.args_signature = ["self", "index"]; -__tuple___getitem__.kwargs_signature = { }; -__tuple___getitem__.types_signature = { }; -__tuple___getitem__.pythonscript_function = true; -__tuple_attrs["__getitem__"] = __tuple___getitem__; -__tuple___iter__ = function(args, kwargs) { +__pytuple___getitem__.NAME = "__pytuple___getitem__"; +__pytuple___getitem__.args_signature = ["self", "index"]; +__pytuple___getitem__.kwargs_signature = { }; +__pytuple___getitem__.types_signature = { }; +__pytuple___getitem__.pythonscript_function = true; +__pytuple_attrs["__getitem__"] = __pytuple___getitem__; +__pytuple___iter__ = function(args, kwargs) { if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { @@ -2005,14 +2063,14 @@ __tuple___iter__ = function(args, kwargs) { return __get__(Iterator, "__call__")([self, 0], __NULL_OBJECT__); } -__tuple___iter__.NAME = "__tuple___iter__"; -__tuple___iter__.args_signature = ["self"]; -__tuple___iter__.kwargs_signature = { }; -__tuple___iter__.types_signature = { }; -__tuple___iter__.return_type = "Iterator"; -__tuple___iter__.pythonscript_function = true; -__tuple_attrs["__iter__"] = __tuple___iter__; -__tuple___len__ = function(args, kwargs) { +__pytuple___iter__.NAME = "__pytuple___iter__"; +__pytuple___iter__.args_signature = ["self"]; +__pytuple___iter__.kwargs_signature = { }; +__pytuple___iter__.types_signature = { }; +__pytuple___iter__.return_type = "Iterator"; +__pytuple___iter__.pythonscript_function = true; +__pytuple_attrs["__iter__"] = __pytuple___iter__; +__pytuple___len__ = function(args, kwargs) { if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { @@ -2026,13 +2084,13 @@ __tuple___len__ = function(args, kwargs) { return self["$wrapped"].length; } -__tuple___len__.NAME = "__tuple___len__"; -__tuple___len__.args_signature = ["self"]; -__tuple___len__.kwargs_signature = { }; -__tuple___len__.types_signature = { }; -__tuple___len__.pythonscript_function = true; -__tuple_attrs["__len__"] = __tuple___len__; -__tuple_length__getprop__ = function(args, kwargs) { +__pytuple___len__.NAME = "__pytuple___len__"; +__pytuple___len__.args_signature = ["self"]; +__pytuple___len__.kwargs_signature = { }; +__pytuple___len__.types_signature = { }; +__pytuple___len__.pythonscript_function = true; +__pytuple_attrs["__len__"] = __pytuple___len__; +__pytuple_length__getprop__ = function(args, kwargs) { if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { @@ -2046,12 +2104,12 @@ __tuple_length__getprop__ = function(args, kwargs) { return self["$wrapped"].length; } -__tuple_length__getprop__.NAME = "__tuple_length__getprop__"; -__tuple_length__getprop__.args_signature = ["self"]; -__tuple_length__getprop__.kwargs_signature = { }; -__tuple_length__getprop__.types_signature = { }; -__tuple_length__getprop__.pythonscript_function = true; -__tuple_index = function(args, kwargs) { +__pytuple_length__getprop__.NAME = "__pytuple_length__getprop__"; +__pytuple_length__getprop__.args_signature = ["self"]; +__pytuple_length__getprop__.kwargs_signature = { }; +__pytuple_length__getprop__.types_signature = { }; +__pytuple_length__getprop__.pythonscript_function = true; +__pytuple_index = function(args, kwargs) { if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { @@ -2066,13 +2124,13 @@ __tuple_index = function(args, kwargs) { return self["$wrapped"].indexOf(obj); } -__tuple_index.NAME = "__tuple_index"; -__tuple_index.args_signature = ["self", "obj"]; -__tuple_index.kwargs_signature = { }; -__tuple_index.types_signature = { }; -__tuple_index.pythonscript_function = true; -__tuple_attrs["index"] = __tuple_index; -__tuple_count = function(args, kwargs) { +__pytuple_index.NAME = "__pytuple_index"; +__pytuple_index.args_signature = ["self", "obj"]; +__pytuple_index.kwargs_signature = { }; +__pytuple_index.types_signature = { }; +__pytuple_index.pythonscript_function = true; +__pytuple_attrs["index"] = __pytuple_index; +__pytuple_count = function(args, kwargs) { var a; if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ @@ -2097,13 +2155,13 @@ __tuple_count = function(args, kwargs) { return a; } -__tuple_count.NAME = "__tuple_count"; -__tuple_count.args_signature = ["self", "obj"]; -__tuple_count.kwargs_signature = { }; -__tuple_count.types_signature = { }; -__tuple_count.pythonscript_function = true; -__tuple_attrs["count"] = __tuple_count; -__tuple_get = function(args, kwargs) { +__pytuple_count.NAME = "__pytuple_count"; +__pytuple_count.args_signature = ["self", "obj"]; +__pytuple_count.kwargs_signature = { }; +__pytuple_count.types_signature = { }; +__pytuple_count.pythonscript_function = true; +__pytuple_attrs["count"] = __pytuple_count; +__pytuple_get = function(args, kwargs) { if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { @@ -2118,13 +2176,13 @@ __tuple_get = function(args, kwargs) { return self["$wrapped"][ (index.__uid__) ? index.__uid__ : index]; } -__tuple_get.NAME = "__tuple_get"; -__tuple_get.args_signature = ["self", "index"]; -__tuple_get.kwargs_signature = { }; -__tuple_get.types_signature = { }; -__tuple_get.pythonscript_function = true; -__tuple_attrs["get"] = __tuple_get; -__tuple___contains__ = function(args, kwargs) { +__pytuple_get.NAME = "__pytuple_get"; +__pytuple_get.args_signature = ["self", "index"]; +__pytuple_get.kwargs_signature = { }; +__pytuple_get.types_signature = { }; +__pytuple_get.pythonscript_function = true; +__pytuple_attrs["get"] = __pytuple_get; +__pytuple___contains__ = function(args, kwargs) { if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ } else { @@ -2143,15 +2201,15 @@ __tuple___contains__ = function(args, kwargs) { } } -__tuple___contains__.NAME = "__tuple___contains__"; -__tuple___contains__.args_signature = ["self", "value"]; -__tuple___contains__.kwargs_signature = { }; -__tuple___contains__.types_signature = { }; -__tuple___contains__.pythonscript_function = true; -__tuple_attrs["__contains__"] = __tuple___contains__; -__tuple_properties["length"] = Object(); -__tuple_properties["length"]["get"] = __tuple_length__getprop__; -tuple = create_class("tuple", __tuple_parents, __tuple_attrs, __tuple_properties); +__pytuple___contains__.NAME = "__pytuple___contains__"; +__pytuple___contains__.args_signature = ["self", "value"]; +__pytuple___contains__.kwargs_signature = { }; +__pytuple___contains__.types_signature = { }; +__pytuple___contains__.pythonscript_function = true; +__pytuple_attrs["__contains__"] = __pytuple___contains__; +__pytuple_properties["length"] = Object(); +__pytuple_properties["length"]["get"] = __pytuple_length__getprop__; +pytuple = create_class("pytuple", __pytuple_parents, __pytuple_attrs, __pytuple_properties); list = function(args, kwargs) { if (args instanceof Array && {}.toString.call(kwargs) === '[object Object]' && ( arguments.length ) == 2) { /*pass*/ @@ -2247,7 +2305,7 @@ __pylist___getitem__ = function(args, kwargs) { var self = args[ 0 ]; var index = args[ 1 ]; if (( index ) < 0) { - index = (__get__(self["$wrapped"], "length") + index); + index = __add_op(__get__(self["$wrapped"], "length"), index); } return self["$wrapped"][ (index.__uid__) ? index.__uid__ : index]; } @@ -3402,7 +3460,7 @@ __array___getitem__ = function(args, kwargs) { step = self.itemsize; offset = (step * index); dataview = self.dataview; - func_name = ("get" + __get__(__get__(self, "typecode_names"), "__getitem__")([self.typecode], Object())); + func_name = __add_op("get", __get__(__get__(self, "typecode_names"), "__getitem__")([self.typecode], Object())); func = dataview[func_name].bind(dataview); if (( offset ) < self.bytes) { value = func(offset); @@ -3441,11 +3499,11 @@ __array___setitem__ = function(args, kwargs) { var value = arguments['value']; step = self.itemsize; if (( index ) < 0) { - index = ((self.length + index) - 1); + index = (__add_op(self.length, index) - 1); } offset = (step * index); dataview = self.dataview; - func_name = ("set" + __get__(__get__(self, "typecode_names"), "__getitem__")([self.typecode], Object())); + func_name = __add_op("set", __get__(__get__(self, "typecode_names"), "__getitem__")([self.typecode], Object())); func = dataview[func_name].bind(dataview); if (( offset ) < self.bytes) { if (( self.typecode ) == "float8") { @@ -3527,7 +3585,7 @@ __array_fromlist = function(args, kwargs) { typecode = self.typecode; size = (length * step); dataview = self.dataview; - func_name = ("set" + __get__(__get__(self, "typecode_names"), "__getitem__")([typecode], Object())); + func_name = __add_op("set", __get__(__get__(self, "typecode_names"), "__getitem__")([typecode], Object())); func = dataview[func_name].bind(dataview); if (( size ) <= self.bytes) { i = 0; @@ -3601,7 +3659,7 @@ __array_append = function(args, kwargs) { var self = arguments['self']; var value = arguments['value']; length = self.length; - __get__(__get__(self, "resize"), "__call__")([(self.length + 1)], __NULL_OBJECT__); + __get__(__get__(self, "resize"), "__call__")([__add_op(self.length, 1)], __NULL_OBJECT__); __get__(__get__(self, "__setitem__"), "__call__")([length, value], Object()); } diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index 2de2fe2..4aeb796 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -990,6 +990,9 @@ def visit_BinOp(self, node): elif op == '**': return 'Math.pow(%s,%s)' %(left, right) + elif op == '+' and not self._with_dart: + return '__add_op(%s, %s)'%(left, right) + elif isinstance(node.left, Name): typedef = self.get_typedef( node.left ) if typedef and op in typedef.operators: diff --git a/regtests/list/concatenate.py b/regtests/list/concatenate.py new file mode 100644 index 0000000..aecd24b --- /dev/null +++ b/regtests/list/concatenate.py @@ -0,0 +1,10 @@ +"""concatenate lists""" +a = [1,2] +b = [3,4] +c = a + b + +Error( len(c)==4 ) +Error( c[0]==1 ) +Error( c[1]==2 ) +Error( c[2]==3 ) +Error( c[3]==4 ) diff --git a/regtests/run.py b/regtests/run.py index 3063b77..a66a552 100755 --- a/regtests/run.py +++ b/regtests/run.py @@ -38,8 +38,10 @@ def runnable(command): f.close() return output != '' -rhino_runnable = runnable("rhino -help") +## rhino has problems: like maximum callstack errors simply freeze up rhino +rhino_runnable = runnable("rhino -help") and '--rhino' in sys.argv node_runnable = runnable("node --help") +assert rhino_runnable or node_runnable if show_details: display_errors = "" diff --git a/runtime/builtins.py b/runtime/builtins.py index d468d15..04e444a 100644 --- a/runtime/builtins.py +++ b/runtime/builtins.py @@ -36,6 +36,20 @@ def __test_if_true__( ob ): else: return True + def __add_op(a, b): + t = typeof(a) + if t == 'number' or t == 'string': + return JS("a+b") + elif instanceof(a, Array): + c = [] + c.extend(a) + c.extend(b) + return c + elif a.__add__: + return a.__add__(b) + else: + raise TypeError + def __jsdict( items ): d = JS("{}") for item in items: @@ -507,7 +521,7 @@ def func(item): this.push( item ) @Array.prototype.extend - def extend(self, other): + def extend(other): for obj in other: this.push(obj) @@ -682,7 +696,22 @@ def next_fast(self): return self.obj_get( [index], {} ) -class tuple: +def tuple(a): + ## TODO tuple needs a solution for dict keys + with javascript: + if Object.keys(arguments).length == 0: #arguments.length == 0: + return [] + elif instanceof(a, Array): + return a.slice() + elif typeof(a) == 'string': + return a.split('') + else: + print a + print arguments + raise TypeError + + +class pytuple: ## tuple is deprecated def __init__(self, js_object=None, pointer=None): with javascript: if pointer: diff --git a/tests/test_list.html b/tests/test_list.html index faf944e..8f505ac 100644 --- a/tests/test_list.html +++ b/tests/test_list.html @@ -68,6 +68,12 @@ s = list( 'abc' ) print s + print 'testing list concat' + a = [1,2] + b = [3,4] + c = a + b + print( c ) + From fbbd0bbe6150307191aa63d4ee65a643fb066959 Mon Sep 17 00:00:00 2001 From: hartsantler Date: Fri, 24 Jan 2014 13:51:04 -0800 Subject: [PATCH 095/521] allow negative list indices in javascript mode for literals. --- pythonjs/python_to_pythonjs.py | 5 ++++- regtests/list/neg_index.py | 5 +++++ 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 regtests/list/neg_index.py diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index 4aeb796..a0a4bbd 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -1191,7 +1191,10 @@ def visit_Subscript(self, node): return '%s[ %s ]' %(name, self.visit(node.slice)) elif isinstance(node.slice, ast.Index) and isinstance(node.slice.value, ast.Num): - return '%s[ %s ]' %(name, self.visit(node.slice)) + if node.slice.value.n < 0: + return '%s[ %s.length+%s ]' %(name, name, self.visit(node.slice)) + else: + return '%s[ %s ]' %(name, self.visit(node.slice)) else: s = self.visit(node.slice) return '%s[ __ternary_operator__(%s.__uid__, %s) ]' %(name, s, s) diff --git a/regtests/list/neg_index.py b/regtests/list/neg_index.py new file mode 100644 index 0000000..dd6e2b9 --- /dev/null +++ b/regtests/list/neg_index.py @@ -0,0 +1,5 @@ +"""negative list indices""" +a = [1,2,3,4] +idx = -2 +Error( a[-1]==4 ) ## this works in javascript mode because the translator knows index is negative +Error( a[idx]==3 ) ## this fails in javascript mode. From e98b3017f29cf77d59bd874467a620cc2762239b Mon Sep 17 00:00:00 2001 From: hartsantler Date: Fri, 24 Jan 2014 14:01:58 -0800 Subject: [PATCH 096/521] allow dart translation to be enabled with "pythonjs.configure(dart=True)" --- pythonjs/python_to_pythonjs.py | 8 ++++++++ regtests/run.py | 1 + 2 files changed, 9 insertions(+) diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index a0a4bbd..a36d3ba 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -1532,6 +1532,14 @@ def visit_Call(self, node): else: raise SyntaxError + elif kw.arg == 'dart': + if kw.value.id == 'True': + self._with_dart = True + elif kw.value.id == 'False': + self._with_dart = False + else: + raise SyntaxError + elif kw.arg == 'inline': if kw.value.id == 'True': self._with_inline = True diff --git a/regtests/run.py b/regtests/run.py index a66a552..df043fd 100755 --- a/regtests/run.py +++ b/regtests/run.py @@ -41,6 +41,7 @@ def runnable(command): ## rhino has problems: like maximum callstack errors simply freeze up rhino rhino_runnable = runnable("rhino -help") and '--rhino' in sys.argv node_runnable = runnable("node --help") +dart2js_runnable = runnable( os.path.expanduser( '~/dart/dart-sdk/bin/dart2js') ) ## TODO - dart tests assert rhino_runnable or node_runnable if show_details: From fd1f0728a89b0f55cdb6e6c57c0d94b37bdf6a60 Mon Sep 17 00:00:00 2001 From: hartsantler Date: Sat, 25 Jan 2014 18:32:14 -0800 Subject: [PATCH 097/521] regression tests now also translate to dart, then translate the output using dart2js, and then run the test in nodejs. --- pythonjs/python_to_pythonjs.py | 12 +++- pythonjs/pythonjs_to_dart.py | 5 +- pythonjs/translator.py | 6 +- regtests/dict/if_empty.py | 35 +++++----- regtests/dict/init.py | 16 +++-- regtests/dict/item.py | 21 +++--- regtests/list/concatenate.py | 18 ++--- regtests/list/if_empty.py | 35 +++++----- regtests/list/neg_index.py | 9 +-- regtests/run.py | 123 ++++++++++++++++++++++++++------- regtests/str/iter.py | 22 +++--- regtests/str/specials.py | 16 +++-- runtime/dart_builtins.py | 8 ++- tests/dart_helloworld.html | 2 + 14 files changed, 216 insertions(+), 112 deletions(-) diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index a36d3ba..4fa7ebd 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -219,7 +219,13 @@ def __init__(self, source=None, module=None, module_path=None, dart=False): source = self.preprocess_custom_operators( source ) tree = parse( source ) self._generator_function_nodes = collect_generator_functions( tree ) - self.visit( tree ) + + for node in tree.body: + ## skip module level doc strings ## + if isinstance(node, ast.Expr) and isinstance(node.value, ast.Str): + pass + else: + self.visit(node) def preprocess_custom_operators(self, data): @@ -1396,8 +1402,8 @@ def _visit_assign_helper(self, node, target): writer.write('%s = %s' % (self.visit(target), node_value)) - elif self._with_dart and writer.is_at_global_level(): - writer.write('JS("var %s = %s")' % (self.visit(target), node_value)) + #elif self._with_dart and writer.is_at_global_level(): + # writer.write('JS("var %s = %s")' % (self.visit(target), node_value)) else: writer.write('%s = %s' % (self.visit(target), node_value)) diff --git a/pythonjs/pythonjs_to_dart.py b/pythonjs/pythonjs_to_dart.py index 0433a71..a60cb10 100644 --- a/pythonjs/pythonjs_to_dart.py +++ b/pythonjs/pythonjs_to_dart.py @@ -92,7 +92,10 @@ def visit_ClassDef(self, node): assert len(bases) == 1 out.append('class %s extends %s {'%(node.name, ','.join(bases))) else: - out.append('class %s implements %s {'%(node.name, ', '.join(bases))) + if bases[0] == 'object': + out.append('class %s {' %node.name) + else: + out.append('class %s implements %s {'%(node.name, ', '.join(bases))) else: diff --git a/pythonjs/translator.py b/pythonjs/translator.py index cbf4fbd..fc4ffee 100755 --- a/pythonjs/translator.py +++ b/pythonjs/translator.py @@ -3,11 +3,15 @@ from python_to_pythonjs import main as python_to_pythonjs from pythonjs import main as pythonjs_to_javascript +from pythonjs_to_dart import main as pythonjs_to_dart def main(script): a = python_to_pythonjs(script) - return pythonjs_to_javascript( a ) + if '--dart' in sys.argv: + return pythonjs_to_dart( a ) + else: + return pythonjs_to_javascript( a ) def command(): diff --git a/regtests/dict/if_empty.py b/regtests/dict/if_empty.py index 3093db6..803f09d 100644 --- a/regtests/dict/if_empty.py +++ b/regtests/dict/if_empty.py @@ -1,21 +1,22 @@ """if empty dict then false""" -d = {} -if d: - err1 = 1 -else: - err1 = 0 +def main(): + d = {} + if d: + err1 = 1 + else: + err1 = 0 -if {}: - err2 = 1 -else: - err2 = 0 + if {}: + err2 = 1 + else: + err2 = 0 -d['x'] = 'xxx' -if d: - err3 = 0 -else: - err3 = 1 + d['x'] = 'xxx' + if d: + err3 = 0 + else: + err3 = 1 -Error( err1 == 0 ) -Error( err2 == 0 ) -Error( err3 == 0 ) + TestError( err1 == 0 ) + TestError( err2 == 0 ) + TestError( err3 == 0 ) diff --git a/regtests/dict/init.py b/regtests/dict/init.py index 52d0497..8ac1a04 100644 --- a/regtests/dict/init.py +++ b/regtests/dict/init.py @@ -5,10 +5,12 @@ class G(object): def __init__(self): """XXX: Without __init__ the translation with javascript fail""" pass -g = G() -a = {'2': 22, 3:33, f:44, G:55, g:66} -Error(a['2'] == 22) -Error(a[3] == 33) -Warning(a[f] == 44) -Warning(a[G] == 55) -Warning(a[g] == 66) + +def main(): + g = G() + a = {'2': 22, 3:33, f:44, G:55, g:66} + TestError(a['2'] == 22) + TestError(a[3] == 33) + TestError(a[f] == 44) + TestError(a[G] == 55) + TestError(a[g] == 66) diff --git a/regtests/dict/item.py b/regtests/dict/item.py index a5c95c1..6e6240a 100644 --- a/regtests/dict/item.py +++ b/regtests/dict/item.py @@ -5,14 +5,15 @@ class G(object): def __init__(self): """XXX: Without __init__ the translation with javascript fail""" pass -g = G() -a = {'2': 22, 3:33} -a[f] = 44 -a[g] = 66 -a[G] = 55 -Error(a['2'] == 22) -Error(a[3] == 33) -Error(a[f] == 44) -Error(a[G] == 55) -Error(a[g] == 66) +def main(): + g = G() + a = {'2': 22, 3:33} + a[f] = 44 + a[g] = 66 + a[G] = 55 + TestError(a['2'] == 22) + TestError(a[3] == 33) + TestError(a[f] == 44) + TestError(a[G] == 55) + TestError(a[g] == 66) diff --git a/regtests/list/concatenate.py b/regtests/list/concatenate.py index aecd24b..50e21e8 100644 --- a/regtests/list/concatenate.py +++ b/regtests/list/concatenate.py @@ -1,10 +1,12 @@ """concatenate lists""" -a = [1,2] -b = [3,4] -c = a + b -Error( len(c)==4 ) -Error( c[0]==1 ) -Error( c[1]==2 ) -Error( c[2]==3 ) -Error( c[3]==4 ) +def main(): + a = [1,2] + b = [3,4] + c = a + b + + TestError( len(c)==4 ) + TestError( c[0]==1 ) + TestError( c[1]==2 ) + TestError( c[2]==3 ) + TestError( c[3]==4 ) diff --git a/regtests/list/if_empty.py b/regtests/list/if_empty.py index 4c27c51..9e3af6a 100644 --- a/regtests/list/if_empty.py +++ b/regtests/list/if_empty.py @@ -1,21 +1,22 @@ """if empty list then false""" -d = [] -if d: - err1 = 1 -else: - err1 = 0 +def main(): + d = [] + if d: + err1 = 1 + else: + err1 = 0 -if []: - err2 = 1 -else: - err2 = 0 + if []: + err2 = 1 + else: + err2 = 0 -d.append('xxx') -if d: - err3 = 0 -else: - err3 = 1 + d.append('xxx') + if d: + err3 = 0 + else: + err3 = 1 -Error( err1 == 0 ) -Error( err2 == 0 ) -Error( err3 == 0 ) + TestError( err1 == 0 ) + TestError( err2 == 0 ) + TestError( err3 == 0 ) diff --git a/regtests/list/neg_index.py b/regtests/list/neg_index.py index dd6e2b9..7569a1f 100644 --- a/regtests/list/neg_index.py +++ b/regtests/list/neg_index.py @@ -1,5 +1,6 @@ """negative list indices""" -a = [1,2,3,4] -idx = -2 -Error( a[-1]==4 ) ## this works in javascript mode because the translator knows index is negative -Error( a[idx]==3 ) ## this fails in javascript mode. +def main(): + a = [1,2,3,4] + idx = -2 + TestError( a[-1]==4 ) ## this works in javascript mode because the translator knows index is negative + TestError( a[idx]==3 ) ## this fails in javascript mode. diff --git a/regtests/run.py b/regtests/run.py index df043fd..33d46a2 100755 --- a/regtests/run.py +++ b/regtests/run.py @@ -13,10 +13,7 @@ """ -import os -import re -import sys -import tempfile +import os, sys, re, tempfile, subprocess tmpname = os.path.join(tempfile.gettempdir(), "xxx_regtest") @@ -41,7 +38,8 @@ def runnable(command): ## rhino has problems: like maximum callstack errors simply freeze up rhino rhino_runnable = runnable("rhino -help") and '--rhino' in sys.argv node_runnable = runnable("node --help") -dart2js_runnable = runnable( os.path.expanduser( '~/dart/dart-sdk/bin/dart2js') ) ## TODO - dart tests +dart2js = os.path.expanduser( '~/dart/dart-sdk/bin/dart2js') +dart2js_runnable = runnable( dart2js ) ## TODO - dart tests assert rhino_runnable or node_runnable if show_details: @@ -108,23 +106,45 @@ def patch_assert(filename): """Patch the regression tests to add information into asserts""" out = [] for i, line in enumerate(read(filename).split('\n')): - out.append(re.sub("(Error|Warning)\((.*)\)", + out.append(re.sub("(TestError|TestWarning)\((.*)\)", r'\1("%s",%d,\2,"\2")' % (filename, i), line) ) return '\n'.join(out) -def patch_python(filename): - """Rewrite the Python code""" - return ("""# -*- coding: utf-8 -*- -def Error(file, line, result, test): - if not result: + +_patch_header = """# -*- coding: utf-8 -*- +def TestError(file, line, result, test): + if result == False: print(file + ":" + str(line) + " Error fail " + test) -def Warning(file, line, result, test): - if not result: +def TestWarning(file, line, result, test): + if result == False: print(file + ":" + str(line) + " Warning fail " + test) """ - + patch_assert(filename)) + +def patch_python(filename, dart=False): + """Rewrite the Python code""" + code = patch_assert(filename) + + ## a main function can not be simply injected like this for dart, + ## because dart has special rules about what can be created outside + ## of the main function at the module level. + #if dart: + # out = [] + # main_inserted = False + # for line in code.splitlines(): + # if line.startswith('TestError') or line.startswith('TestWarning'): + # if not main_inserted: + # out.append('def main():') + # main_inserted = True + # out.append( '\t'+line ) + # else: + # out.append( line ) + # code = '\n'.join( out ) + if dart: + return '\n'.join( [_patch_header, code] ) + else: + return '\n'.join( [_patch_header, code, 'main()'] ) def run_python_test_on(filename): """Python tests""" @@ -136,19 +156,54 @@ def run_python3_test_on(filename): write("%s.py" % tmpname, patch_python(filename)) return run_command("python3 %s.py %s" % (tmpname, display_errors)) -def translate_js(filename, javascript): +def translate_js(filename, javascript=False, dart=False): output_name = "%s.py" % tmpname - write(output_name, - (javascript and 'pythonjs.configure(javascript=True)\n' or '') - + patch_python(filename)) - stdout, stderr = run_command(os.path.join("..", "pythonjs", - "translator.py") - + ' ' + output_name, - returns_stdout_stderr=True) + if javascript: + content = 'pythonjs.configure(javascript=True)\n' + patch_python(filename) + elif dart: + source = [ + 'pythonjs.configure(dart=True)', + open('../runtime/dart_builtins.py', 'rb').read().decode('utf-8'), + patch_python(filename, dart=True) + ] + content = '\n'.join( source ) + else: + content = patch_python(filename) + + write(output_name, content) + cmd = [ + os.path.join("..", "pythonjs", "translator.py"), + output_name + ] + if dart: + cmd.append( '--dart' ) + stdout, stderr = run_command(' '.join(cmd), returns_stdout_stderr=True) if stderr: return '' else: - return stdout + if dart: + + if os.path.isfile('/tmp/dart2js-output.js'): + os.unlink('/tmp/dart2js-output.js') + + dart_input = '/tmp/dart2js-input.dart' + open( dart_input, 'wb').write( stdout.encode('utf-8') ) + + cmd = [ + dart2js, + '-o', '/tmp/dart2js-output.js', + dart_input + ] + #subprocess.call( cmd ) ## this shows dart2js errors in red ## + sout, serr = run_command(' '.join(cmd), returns_stdout_stderr=True) + + if os.path.isfile('/tmp/dart2js-output.js'): + return open('/tmp/dart2js-output.js', 'rb').read().decode('utf-8') + else: + return '' + + else: + return stdout def run_if_no_error(function): """Run the function if the JS code is not empty""" @@ -200,6 +255,16 @@ def run_js_node(content): + content) return run_command("node %s.js" % tmpname) +def run_pythonjs_dart_test_on_node(dummy_filename): + """Dart2js PythonJS tests on Node""" + return run_if_no_error(run_dart2js_node) + +def run_dart2js_node(content): + """Run Dart2js using Node""" + write("%s.js" % tmpname, content) + return run_command("node %s.js" % tmpname) + + table_header = "%-12.12s %-28.28s" table_cell = '%-6.6s' @@ -232,16 +297,22 @@ def display(function): display(run_python_test_on) display(run_python3_test_on) global js - js = translate_js(filename, False) + js = translate_js(filename, javascript=False) if rhino_runnable: display(run_pythonjs_test_on) if node_runnable: display(run_pythonjs_test_on_node) - js = translate_js(filename, True) + + js = translate_js(filename, javascript=True) if rhino_runnable: display(run_pythonjsjs_test_on) if node_runnable: display(run_pythonjsjs_test_on_node) + + if dart2js_runnable and node_runnable: + js = translate_js(filename, javascript=False, dart=True) + display(run_pythonjs_dart_test_on_node) + print() return sum_errors @@ -258,6 +329,8 @@ def run(): headers.append("JSJS\nRhino") if node_runnable: headers.append("JSJS\nNode") + if dart2js_runnable: + headers.append("Dart2js\nNode") print(table_header % ("", "Regtest run on") + ''.join(table_cell % i.split('\n')[0] diff --git a/regtests/str/iter.py b/regtests/str/iter.py index e6b4b86..5dcf95d 100644 --- a/regtests/str/iter.py +++ b/regtests/str/iter.py @@ -1,14 +1,14 @@ """The string iterator""" -a = list("abc") -Error(a[0] == 'a') -Error(a[1] == 'b') -Error(a[2] == 'c') +def main(): + a = list("abc") + TestError(a[0] == 'a') + TestError(a[1] == 'b') + TestError(a[2] == 'c') -# Does not work with javascript -a = [] -for i in "abc": - a.append(i) -Warning(a[0] == 'a') -Warning(a[1] == 'b') -Warning(a[2] == 'c') + a = [] + for i in "abc": + a.append(i) + TestError(a[0] == 'a') + TestError(a[1] == 'b') + TestError(a[2] == 'c') diff --git a/regtests/str/specials.py b/regtests/str/specials.py index 72291f7..3b9ee80 100644 --- a/regtests/str/specials.py +++ b/regtests/str/specials.py @@ -1,8 +1,10 @@ """Specials chars in strings""" -Error(len('\\') == 1) -Error('éè' == 'é' + 'è') -if len('éè') == 2: # The interpreter assumes UTF8 (all except Python2) - Error('éè'[::-1] == 'èé') -else: - # run.y fail if the right part is defined as strings, must use chr() - Error(tuple('éè'[::-1]) == (chr(168), chr(195), chr(169), chr(195))) + +def main(): + TestError(len('\\') == 1) + TestError('éè' == 'é' + 'è') + if len('éè') == 2: # The interpreter assumes UTF8 (all except Python2) + TestError('éè'[::-1] == 'èé') + else: + # run.py fails if the right part is defined as strings, must use chr() + TestError(tuple('éè'[::-1]) == (chr(168), chr(195), chr(169), chr(195))) diff --git a/runtime/dart_builtins.py b/runtime/dart_builtins.py index b1f26ea..91114c4 100644 --- a/runtime/dart_builtins.py +++ b/runtime/dart_builtins.py @@ -46,6 +46,8 @@ def index(self, obj): return self[...].indexOf(obj) +tuple = list + #@dart.extends class dict: #( HashMap ): ''' @@ -86,4 +88,8 @@ def range(n): return r def len(a): - return a.length \ No newline at end of file + return a.length + +def str(a): + ## TODO conversions to string + return a \ No newline at end of file diff --git a/tests/dart_helloworld.html b/tests/dart_helloworld.html index 46b5d77..1231af9 100644 --- a/tests/dart_helloworld.html +++ b/tests/dart_helloworld.html @@ -4,6 +4,8 @@ From 3f4b97321dca1ff15faaf09f299214c3f4d45da8 Mon Sep 17 00:00:00 2001 From: hartsantler Date: Fri, 31 Jan 2014 15:59:20 -0800 Subject: [PATCH 112/521] fixed dict.items() in javascript mode. all backends now pass for_loop regression test. --- pythonjs/python_to_pythonjs.py | 3 +++ regtests/loop/for_loop.py | 2 +- tests/test_for_loop.html | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index 8980d5a..1dd0040 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -1614,6 +1614,9 @@ def visit_Call(self, node): elif anode.attr == 'values' and not args: return '__jsdict_values(%s)' %self.visit(anode.value) + elif anode.attr == 'items' and not args: + return '__jsdict_items(%s)' %self.visit(anode.value) + elif anode.attr == 'pop': if args: return '__jsdict_pop(%s, %s)' %(self.visit(anode.value), ','.join(args) ) diff --git a/regtests/loop/for_loop.py b/regtests/loop/for_loop.py index 52ec490..ecf9573 100644 --- a/regtests/loop/for_loop.py +++ b/regtests/loop/for_loop.py @@ -39,7 +39,7 @@ def main(): k += key v += ob[key] TestError(k=='ab' or k=='ba') - TestError(v=='AB' or k=='BA') + TestError(v=='AB' or v=='BA') keys = [] values = [] diff --git a/tests/test_for_loop.html b/tests/test_for_loop.html index c77476d..55d9ad1 100644 --- a/tests/test_for_loop.html +++ b/tests/test_for_loop.html @@ -70,6 +70,7 @@ keys = [] values = [] with javascript: + d = {'a' : 'A', 'b' : 'B'} for x,y in d.items(): print(x,y) keys.append( x ) From 76d2000c54d893cf8d4d903d6b87e033afb69af9 Mon Sep 17 00:00:00 2001 From: hartsantler Date: Fri, 31 Jan 2014 16:53:09 -0800 Subject: [PATCH 113/521] fixed "yield" (generator functions) for python mode and javascript mode. TODO: support "yield" for dart and coffee. --- pythonjs/python_to_pythonjs.py | 13 +++++++++++-- regtests/loop/yield.py | 27 +++++++++++++++++++++++++++ tests/test_yield_multiple.html | 3 +++ 3 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 regtests/loop/yield.py diff --git a/pythonjs/python_to_pythonjs.py b/pythonjs/python_to_pythonjs.py index 1dd0040..e89f299 100755 --- a/pythonjs/python_to_pythonjs.py +++ b/pythonjs/python_to_pythonjs.py @@ -1579,7 +1579,7 @@ def visit_Call(self, node): args = list( map(self.visit, node.args) ) if name in self._generator_functions: - return ' new %s(%s)' %(name, ','.join(args)) + return ' new(%s(%s))' %(name, ','.join(args)) elif self._with_dart and name in self._builtin_functions_dart: if args: @@ -2472,7 +2472,16 @@ class GeneratorFunctionTransformer( PythonToPythonJS ): ''' def __init__(self, node, compiler=None): - self._with_js = True + self._with_js = False + self._with_dart = False + self._with_coffee = False + if compiler._with_dart: ## TODO + self._with_dart = True + elif compiler._with_coffee: ## TODO + self._with_coffee = True + else: + self._with_js = True + self._builtin_functions = compiler._builtin_functions self._js_classes = compiler._js_classes self._global_functions = compiler._global_functions diff --git a/regtests/loop/yield.py b/regtests/loop/yield.py new file mode 100644 index 0000000..fb4a2db --- /dev/null +++ b/regtests/loop/yield.py @@ -0,0 +1,27 @@ +''' +generator function +''' + +def fib(n): + a, b = 0, 1 + for x in range(n): + yield a + a,b = b, a+b + yield 'world' + +def main(): + arr = [] + for n in fib(20): + arr.append( n ) + + TestError( arr[0]==0 ) + TestError( arr[1]==1 ) + TestError( arr[2]==1 ) + TestError( arr[3]==2 ) + TestError( arr[4]==3 ) + TestError( arr[5]==5 ) + TestError( arr[6]==8 ) + TestError( arr[7]==13 ) + TestError( arr[8]==21 ) + TestError( arr[9]==34 ) + TestError( arr[10]==55 ) diff --git a/tests/test_yield_multiple.html b/tests/test_yield_multiple.html index 00094da..93c9d58 100644 --- a/tests/test_yield_multiple.html +++ b/tests/test_yield_multiple.html @@ -3,6 +3,9 @@ + + + +
+ + + + + \ No newline at end of file diff --git a/pypubjs/main.html b/pypubjs/main.html new file mode 100644 index 0000000..d5d69a0 --- /dev/null +++ b/pypubjs/main.html @@ -0,0 +1,252 @@ + + + + + + + + + + + + + + + +
+ + + + + \ No newline at end of file diff --git a/pythonjs-linux b/pythonjs-linux new file mode 100755 index 0000000..2a33f7d --- /dev/null +++ b/pythonjs-linux @@ -0,0 +1,2 @@ +#!/bin/bash +external/node-webkit/linux/nw . \ No newline at end of file diff --git a/pythonjs-osx b/pythonjs-osx new file mode 100755 index 0000000..377d2ba --- /dev/null +++ b/pythonjs-osx @@ -0,0 +1,2 @@ +#!/bin/bash +external/node-webkit/osx/node-webkit.app/Contents/MacOS/node-webkit . \ No newline at end of file diff --git a/pythonjs-windows.bat b/pythonjs-windows.bat new file mode 100644 index 0000000..30fa570 --- /dev/null +++ b/pythonjs-windows.bat @@ -0,0 +1 @@ +external\node-webkit\windows\nw.exe . \ No newline at end of file From 19dfe4ff64a3d71c624c293182427bc195a9127b Mon Sep 17 00:00:00 2001 From: hartsantler Date: Sun, 16 Feb 2014 18:10:29 -0800 Subject: [PATCH 149/521] pypubjs: added buttons for publish to all platforms. --- pypubjs/main.html | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/pypubjs/main.html b/pypubjs/main.html index d5d69a0..e3225c6 100644 --- a/pypubjs/main.html +++ b/pypubjs/main.html @@ -238,14 +238,40 @@
python scripts
+ + From 4e00f90abef97cf13e54047053e0ef7b9853dbd4 Mon Sep 17 00:00:00 2001 From: hartsantler Date: Wed, 19 Feb 2014 23:14:17 -0800 Subject: [PATCH 150/521] updated external: ace.js, bootstrap, and jquery --- external/ace.js/mode-css.js | 738 ++ external/ace.js/mode-html.js | 2311 +++++++ external/ace.js/worker-css.js | 8245 ++++++++++++++++++++++ external/bootstrap/bootstrap.min.js | 6 + external/css/bootstrap.css | 5792 +--------------- external/jquery/jquery-latest.js | 9789 +++++++++++++++++++++++++++ 6 files changed, 21097 insertions(+), 5784 deletions(-) create mode 100644 external/ace.js/mode-css.js create mode 100644 external/ace.js/mode-html.js create mode 100644 external/ace.js/worker-css.js create mode 100644 external/bootstrap/bootstrap.min.js create mode 100644 external/jquery/jquery-latest.js diff --git a/external/ace.js/mode-css.js b/external/ace.js/mode-css.js new file mode 100644 index 0000000..4498fec --- /dev/null +++ b/external/ace.js/mode-css.js @@ -0,0 +1,738 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2010, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + +ace.define('ace/mode/css', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/text', 'ace/tokenizer', 'ace/mode/css_highlight_rules', 'ace/mode/matching_brace_outdent', 'ace/worker/worker_client', 'ace/mode/behaviour/css', 'ace/mode/folding/cstyle'], function(require, exports, module) { + + +var oop = require("../lib/oop"); +var TextMode = require("./text").Mode; +var Tokenizer = require("../tokenizer").Tokenizer; +var CssHighlightRules = require("./css_highlight_rules").CssHighlightRules; +var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent; +var WorkerClient = require("../worker/worker_client").WorkerClient; +var CssBehaviour = require("./behaviour/css").CssBehaviour; +var CStyleFoldMode = require("./folding/cstyle").FoldMode; + +var Mode = function() { + this.HighlightRules = CssHighlightRules; + this.$outdent = new MatchingBraceOutdent(); + this.$behaviour = new CssBehaviour(); + this.foldingRules = new CStyleFoldMode(); +}; +oop.inherits(Mode, TextMode); + +(function() { + + this.foldingRules = "cStyle"; + this.blockComment = {start: "/*", end: "*/"}; + + this.getNextLineIndent = function(state, line, tab) { + var indent = this.$getIndent(line); + var tokens = this.getTokenizer().getLineTokens(line, state).tokens; + if (tokens.length && tokens[tokens.length-1].type == "comment") { + return indent; + } + + var match = line.match(/^.*\{\s*$/); + if (match) { + indent += tab; + } + + return indent; + }; + + this.checkOutdent = function(state, line, input) { + return this.$outdent.checkOutdent(line, input); + }; + + this.autoOutdent = function(state, doc, row) { + this.$outdent.autoOutdent(doc, row); + }; + + this.createWorker = function(session) { + var worker = new WorkerClient(["ace"], "ace/mode/css_worker", "Worker"); + worker.attachToDocument(session.getDocument()); + + worker.on("csslint", function(e) { + session.setAnnotations(e.data); + }); + + worker.on("terminate", function() { + session.clearAnnotations(); + }); + + return worker; + }; + +}).call(Mode.prototype); + +exports.Mode = Mode; + +}); + +ace.define('ace/mode/css_highlight_rules', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/lang', 'ace/mode/text_highlight_rules'], function(require, exports, module) { + + +var oop = require("../lib/oop"); +var lang = require("../lib/lang"); +var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; +var supportType = exports.supportType = "animation-fill-mode|alignment-adjust|alignment-baseline|animation-delay|animation-direction|animation-duration|animation-iteration-count|animation-name|animation-play-state|animation-timing-function|animation|appearance|azimuth|backface-visibility|background-attachment|background-break|background-clip|background-color|background-image|background-origin|background-position|background-repeat|background-size|background|baseline-shift|binding|bleed|bookmark-label|bookmark-level|bookmark-state|bookmark-target|border-bottom|border-bottom-color|border-bottom-left-radius|border-bottom-right-radius|border-bottom-style|border-bottom-width|border-collapse|border-color|border-image|border-image-outset|border-image-repeat|border-image-slice|border-image-source|border-image-width|border-left|border-left-color|border-left-style|border-left-width|border-radius|border-right|border-right-color|border-right-style|border-right-width|border-spacing|border-style|border-top|border-top-color|border-top-left-radius|border-top-right-radius|border-top-style|border-top-width|border-width|border|bottom|box-align|box-decoration-break|box-direction|box-flex-group|box-flex|box-lines|box-ordinal-group|box-orient|box-pack|box-shadow|box-sizing|break-after|break-before|break-inside|caption-side|clear|clip|color-profile|color|column-count|column-fill|column-gap|column-rule|column-rule-color|column-rule-style|column-rule-width|column-span|column-width|columns|content|counter-increment|counter-reset|crop|cue-after|cue-before|cue|cursor|direction|display|dominant-baseline|drop-initial-after-adjust|drop-initial-after-align|drop-initial-before-adjust|drop-initial-before-align|drop-initial-size|drop-initial-value|elevation|empty-cells|fit|fit-position|float-offset|float|font-family|font-size|font-size-adjust|font-stretch|font-style|font-variant|font-weight|font|grid-columns|grid-rows|hanging-punctuation|height|hyphenate-after|hyphenate-before|hyphenate-character|hyphenate-lines|hyphenate-resource|hyphens|icon|image-orientation|image-rendering|image-resolution|inline-box-align|left|letter-spacing|line-height|line-stacking-ruby|line-stacking-shift|line-stacking-strategy|line-stacking|list-style-image|list-style-position|list-style-type|list-style|margin-bottom|margin-left|margin-right|margin-top|margin|mark-after|mark-before|mark|marks|marquee-direction|marquee-play-count|marquee-speed|marquee-style|max-height|max-width|min-height|min-width|move-to|nav-down|nav-index|nav-left|nav-right|nav-up|opacity|orphans|outline-color|outline-offset|outline-style|outline-width|outline|overflow-style|overflow-x|overflow-y|overflow|padding-bottom|padding-left|padding-right|padding-top|padding|page-break-after|page-break-before|page-break-inside|page-policy|page|pause-after|pause-before|pause|perspective-origin|perspective|phonemes|pitch-range|pitch|play-during|position|presentation-level|punctuation-trim|quotes|rendering-intent|resize|rest-after|rest-before|rest|richness|right|rotation-point|rotation|ruby-align|ruby-overhang|ruby-position|ruby-span|size|speak-header|speak-numeral|speak-punctuation|speak|speech-rate|stress|string-set|table-layout|target-name|target-new|target-position|target|text-align-last|text-align|text-decoration|text-emphasis|text-height|text-indent|text-justify|text-outline|text-shadow|text-transform|text-wrap|top|transform-origin|transform-style|transform|transition-delay|transition-duration|transition-property|transition-timing-function|transition|unicode-bidi|vertical-align|visibility|voice-balance|voice-duration|voice-family|voice-pitch-range|voice-pitch|voice-rate|voice-stress|voice-volume|volume|white-space-collapse|white-space|widows|width|word-break|word-spacing|word-wrap|z-index"; +var supportFunction = exports.supportFunction = "rgb|rgba|url|attr|counter|counters"; +var supportConstant = exports.supportConstant = "absolute|after-edge|after|all-scroll|all|alphabetic|always|antialiased|armenian|auto|avoid-column|avoid-page|avoid|balance|baseline|before-edge|before|below|bidi-override|block-line-height|block|bold|bolder|border-box|both|bottom|box|break-all|break-word|capitalize|caps-height|caption|center|central|char|circle|cjk-ideographic|clone|close-quote|col-resize|collapse|column|consider-shifts|contain|content-box|cover|crosshair|cubic-bezier|dashed|decimal-leading-zero|decimal|default|disabled|disc|disregard-shifts|distribute-all-lines|distribute-letter|distribute-space|distribute|dotted|double|e-resize|ease-in|ease-in-out|ease-out|ease|ellipsis|end|exclude-ruby|fill|fixed|georgian|glyphs|grid-height|groove|hand|hanging|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|icon|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|ideographic|inactive|include-ruby|inherit|initial|inline-block|inline-box|inline-line-height|inline-table|inline|inset|inside|inter-ideograph|inter-word|invert|italic|justify|katakana-iroha|katakana|keep-all|last|left|lighter|line-edge|line-through|line|linear|list-item|local|loose|lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|mathematical|max-height|max-size|medium|menu|message-box|middle|move|n-resize|ne-resize|newspaper|no-change|no-close-quote|no-drop|no-open-quote|no-repeat|none|normal|not-allowed|nowrap|nw-resize|oblique|open-quote|outset|outside|overline|padding-box|page|pointer|pre-line|pre-wrap|pre|preserve-3d|progress|relative|repeat-x|repeat-y|repeat|replaced|reset-size|ridge|right|round|row-resize|rtl|s-resize|scroll|se-resize|separate|slice|small-caps|small-caption|solid|space|square|start|static|status-bar|step-end|step-start|steps|stretch|strict|sub|super|sw-resize|table-caption|table-cell|table-column-group|table-column|table-footer-group|table-header-group|table-row-group|table-row|table|tb-rl|text-after-edge|text-before-edge|text-bottom|text-size|text-top|text|thick|thin|transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|use-script|vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|z-index|zero"; +var supportConstantColor = exports.supportConstantColor = "aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow"; +var supportConstantFonts = exports.supportConstantFonts = "arial|century|comic|courier|garamond|georgia|helvetica|impact|lucida|symbol|system|tahoma|times|trebuchet|utopia|verdana|webdings|sans-serif|serif|monospace"; + +var numRe = exports.numRe = "\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))"; +var pseudoElements = exports.pseudoElements = "(\\:+)\\b(after|before|first-letter|first-line|moz-selection|selection)\\b"; +var pseudoClasses = exports.pseudoClasses = "(:)\\b(active|checked|disabled|empty|enabled|first-child|first-of-type|focus|hover|indeterminate|invalid|last-child|last-of-type|link|not|nth-child|nth-last-child|nth-last-of-type|nth-of-type|only-child|only-of-type|required|root|target|valid|visited)\\b"; + +var CssHighlightRules = function() { + + var keywordMapper = this.createKeywordMapper({ + "support.function": supportFunction, + "support.constant": supportConstant, + "support.type": supportType, + "support.constant.color": supportConstantColor, + "support.constant.fonts": supportConstantFonts + }, "text", true); + + this.$rules = { + "start" : [{ + token : "comment", // multi line comment + regex : "\\/\\*", + push : "comment" + }, { + token: "paren.lparen", + regex: "\\{", + push: "ruleset" + }, { + token: "string", + regex: "@.*?{", + push: "media" + }, { + token: "keyword", + regex: "#[a-z0-9-_]+" + }, { + token: "variable", + regex: "\\.[a-z0-9-_]+" + }, { + token: "string", + regex: ":[a-z0-9-_]+" + }, { + token: "constant", + regex: "[a-z0-9-_]+" + }, { + caseInsensitive: true + }], + + "media" : [{ + token : "comment", // multi line comment + regex : "\\/\\*", + push : "comment" + }, { + token: "paren.lparen", + regex: "\\{", + push: "ruleset" + }, { + token: "string", + regex: "\\}", + next: "pop" + }, { + token: "keyword", + regex: "#[a-z0-9-_]+" + }, { + token: "variable", + regex: "\\.[a-z0-9-_]+" + }, { + token: "string", + regex: ":[a-z0-9-_]+" + }, { + token: "constant", + regex: "[a-z0-9-_]+" + }, { + caseInsensitive: true + }], + + "comment" : [{ + token : "comment", + regex : "\\*\\/", + next : "pop" + }, { + defaultToken : "comment" + }], + + "ruleset" : [ + { + token : "paren.rparen", + regex : "\\}", + next: "pop" + }, { + token : "comment", // multi line comment + regex : "\\/\\*", + push : "comment" + }, { + token : "string", // single line + regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]' + }, { + token : "string", // single line + regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']" + }, { + token : ["constant.numeric", "keyword"], + regex : "(" + numRe + ")(ch|cm|deg|em|ex|fr|gd|grad|Hz|in|kHz|mm|ms|pc|pt|px|rad|rem|s|turn|vh|vm|vw|%)" + }, { + token : "constant.numeric", + regex : numRe + }, { + token : "constant.numeric", // hex6 color + regex : "#[a-f0-9]{6}" + }, { + token : "constant.numeric", // hex3 color + regex : "#[a-f0-9]{3}" + }, { + token : ["punctuation", "entity.other.attribute-name.pseudo-element.css"], + regex : pseudoElements + }, { + token : ["punctuation", "entity.other.attribute-name.pseudo-class.css"], + regex : pseudoClasses + }, { + token : ["support.function", "string", "support.function"], + regex : "(url\\()(.*)(\\))" + }, { + token : keywordMapper, + regex : "\\-?[a-zA-Z_][a-zA-Z0-9_\\-]*" + }, { + caseInsensitive: true + }] + }; + + this.normalizeRules(); +}; + +oop.inherits(CssHighlightRules, TextHighlightRules); + +exports.CssHighlightRules = CssHighlightRules; + +}); + +ace.define('ace/mode/matching_brace_outdent', ['require', 'exports', 'module' , 'ace/range'], function(require, exports, module) { + + +var Range = require("../range").Range; + +var MatchingBraceOutdent = function() {}; + +(function() { + + this.checkOutdent = function(line, input) { + if (! /^\s+$/.test(line)) + return false; + + return /^\s*\}/.test(input); + }; + + this.autoOutdent = function(doc, row) { + var line = doc.getLine(row); + var match = line.match(/^(\s*\})/); + + if (!match) return 0; + + var column = match[1].length; + var openBracePos = doc.findMatchingBracket({row: row, column: column}); + + if (!openBracePos || openBracePos.row == row) return 0; + + var indent = this.$getIndent(doc.getLine(openBracePos.row)); + doc.replace(new Range(row, 0, row, column-1), indent); + }; + + this.$getIndent = function(line) { + return line.match(/^\s*/)[0]; + }; + +}).call(MatchingBraceOutdent.prototype); + +exports.MatchingBraceOutdent = MatchingBraceOutdent; +}); + +ace.define('ace/mode/behaviour/css', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/behaviour', 'ace/mode/behaviour/cstyle', 'ace/token_iterator'], function(require, exports, module) { + + +var oop = require("../../lib/oop"); +var Behaviour = require("../behaviour").Behaviour; +var CstyleBehaviour = require("./cstyle").CstyleBehaviour; +var TokenIterator = require("../../token_iterator").TokenIterator; + +var CssBehaviour = function () { + + this.inherit(CstyleBehaviour); + + this.add("colon", "insertion", function (state, action, editor, session, text) { + if (text === ':') { + var cursor = editor.getCursorPosition(); + var iterator = new TokenIterator(session, cursor.row, cursor.column); + var token = iterator.getCurrentToken(); + if (token && token.value.match(/\s+/)) { + token = iterator.stepBackward(); + } + if (token && token.type === 'support.type') { + var line = session.doc.getLine(cursor.row); + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar === ':') { + return { + text: '', + selection: [1, 1] + } + } + if (!line.substring(cursor.column).match(/^\s*;/)) { + return { + text: ':;', + selection: [1, 1] + } + } + } + } + }); + + this.add("colon", "deletion", function (state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && selected === ':') { + var cursor = editor.getCursorPosition(); + var iterator = new TokenIterator(session, cursor.row, cursor.column); + var token = iterator.getCurrentToken(); + if (token && token.value.match(/\s+/)) { + token = iterator.stepBackward(); + } + if (token && token.type === 'support.type') { + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.end.column, range.end.column + 1); + if (rightChar === ';') { + range.end.column ++; + return range; + } + } + } + }); + + this.add("semicolon", "insertion", function (state, action, editor, session, text) { + if (text === ';') { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar === ';') { + return { + text: '', + selection: [1, 1] + } + } + } + }); + +} +oop.inherits(CssBehaviour, CstyleBehaviour); + +exports.CssBehaviour = CssBehaviour; +}); + +ace.define('ace/mode/behaviour/cstyle', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/behaviour', 'ace/token_iterator', 'ace/lib/lang'], function(require, exports, module) { + + +var oop = require("../../lib/oop"); +var Behaviour = require("../behaviour").Behaviour; +var TokenIterator = require("../../token_iterator").TokenIterator; +var lang = require("../../lib/lang"); + +var SAFE_INSERT_IN_TOKENS = + ["text", "paren.rparen", "punctuation.operator"]; +var SAFE_INSERT_BEFORE_TOKENS = + ["text", "paren.rparen", "punctuation.operator", "comment"]; + + +var autoInsertedBrackets = 0; +var autoInsertedRow = -1; +var autoInsertedLineEnd = ""; +var maybeInsertedBrackets = 0; +var maybeInsertedRow = -1; +var maybeInsertedLineStart = ""; +var maybeInsertedLineEnd = ""; + +var CstyleBehaviour = function () { + + CstyleBehaviour.isSaneInsertion = function(editor, session) { + var cursor = editor.getCursorPosition(); + var iterator = new TokenIterator(session, cursor.row, cursor.column); + if (!this.$matchTokenType(iterator.getCurrentToken() || "text", SAFE_INSERT_IN_TOKENS)) { + var iterator2 = new TokenIterator(session, cursor.row, cursor.column + 1); + if (!this.$matchTokenType(iterator2.getCurrentToken() || "text", SAFE_INSERT_IN_TOKENS)) + return false; + } + iterator.stepForward(); + return iterator.getCurrentTokenRow() !== cursor.row || + this.$matchTokenType(iterator.getCurrentToken() || "text", SAFE_INSERT_BEFORE_TOKENS); + }; + + CstyleBehaviour.$matchTokenType = function(token, types) { + return types.indexOf(token.type || token) > -1; + }; + + CstyleBehaviour.recordAutoInsert = function(editor, session, bracket) { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + if (!this.isAutoInsertedClosing(cursor, line, autoInsertedLineEnd[0])) + autoInsertedBrackets = 0; + autoInsertedRow = cursor.row; + autoInsertedLineEnd = bracket + line.substr(cursor.column); + autoInsertedBrackets++; + }; + + CstyleBehaviour.recordMaybeInsert = function(editor, session, bracket) { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + if (!this.isMaybeInsertedClosing(cursor, line)) + maybeInsertedBrackets = 0; + maybeInsertedRow = cursor.row; + maybeInsertedLineStart = line.substr(0, cursor.column) + bracket; + maybeInsertedLineEnd = line.substr(cursor.column); + maybeInsertedBrackets++; + }; + + CstyleBehaviour.isAutoInsertedClosing = function(cursor, line, bracket) { + return autoInsertedBrackets > 0 && + cursor.row === autoInsertedRow && + bracket === autoInsertedLineEnd[0] && + line.substr(cursor.column) === autoInsertedLineEnd; + }; + + CstyleBehaviour.isMaybeInsertedClosing = function(cursor, line) { + return maybeInsertedBrackets > 0 && + cursor.row === maybeInsertedRow && + line.substr(cursor.column) === maybeInsertedLineEnd && + line.substr(0, cursor.column) == maybeInsertedLineStart; + }; + + CstyleBehaviour.popAutoInsertedClosing = function() { + autoInsertedLineEnd = autoInsertedLineEnd.substr(1); + autoInsertedBrackets--; + }; + + CstyleBehaviour.clearMaybeInsertedClosing = function() { + maybeInsertedBrackets = 0; + maybeInsertedRow = -1; + }; + + this.add("braces", "insertion", function (state, action, editor, session, text) { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + if (text == '{') { + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "" && selected !== "{" && editor.getWrapBehavioursEnabled()) { + return { + text: '{' + selected + '}', + selection: false + }; + } else if (CstyleBehaviour.isSaneInsertion(editor, session)) { + if (/[\]\}\)]/.test(line[cursor.column])) { + CstyleBehaviour.recordAutoInsert(editor, session, "}"); + return { + text: '{}', + selection: [1, 1] + }; + } else { + CstyleBehaviour.recordMaybeInsert(editor, session, "{"); + return { + text: '{', + selection: [1, 1] + }; + } + } + } else if (text == '}') { + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar == '}') { + var matching = session.$findOpeningBracket('}', {column: cursor.column + 1, row: cursor.row}); + if (matching !== null && CstyleBehaviour.isAutoInsertedClosing(cursor, line, text)) { + CstyleBehaviour.popAutoInsertedClosing(); + return { + text: '', + selection: [1, 1] + }; + } + } + } else if (text == "\n" || text == "\r\n") { + var closing = ""; + if (CstyleBehaviour.isMaybeInsertedClosing(cursor, line)) { + closing = lang.stringRepeat("}", maybeInsertedBrackets); + CstyleBehaviour.clearMaybeInsertedClosing(); + } + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar == '}' || closing !== "") { + var openBracePos = session.findMatchingBracket({row: cursor.row, column: cursor.column}, '}'); + if (!openBracePos) + return null; + + var indent = this.getNextLineIndent(state, line.substring(0, cursor.column), session.getTabString()); + var next_indent = this.$getIndent(line); + + return { + text: '\n' + indent + '\n' + next_indent + closing, + selection: [1, indent.length, 1, indent.length] + }; + } + } + }); + + this.add("braces", "deletion", function (state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && selected == '{') { + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.end.column, range.end.column + 1); + if (rightChar == '}') { + range.end.column++; + return range; + } else { + maybeInsertedBrackets--; + } + } + }); + + this.add("parens", "insertion", function (state, action, editor, session, text) { + if (text == '(') { + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "" && editor.getWrapBehavioursEnabled()) { + return { + text: '(' + selected + ')', + selection: false + }; + } else if (CstyleBehaviour.isSaneInsertion(editor, session)) { + CstyleBehaviour.recordAutoInsert(editor, session, ")"); + return { + text: '()', + selection: [1, 1] + }; + } + } else if (text == ')') { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar == ')') { + var matching = session.$findOpeningBracket(')', {column: cursor.column + 1, row: cursor.row}); + if (matching !== null && CstyleBehaviour.isAutoInsertedClosing(cursor, line, text)) { + CstyleBehaviour.popAutoInsertedClosing(); + return { + text: '', + selection: [1, 1] + }; + } + } + } + }); + + this.add("parens", "deletion", function (state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && selected == '(') { + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.start.column + 1, range.start.column + 2); + if (rightChar == ')') { + range.end.column++; + return range; + } + } + }); + + this.add("brackets", "insertion", function (state, action, editor, session, text) { + if (text == '[') { + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "" && editor.getWrapBehavioursEnabled()) { + return { + text: '[' + selected + ']', + selection: false + }; + } else if (CstyleBehaviour.isSaneInsertion(editor, session)) { + CstyleBehaviour.recordAutoInsert(editor, session, "]"); + return { + text: '[]', + selection: [1, 1] + }; + } + } else if (text == ']') { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar == ']') { + var matching = session.$findOpeningBracket(']', {column: cursor.column + 1, row: cursor.row}); + if (matching !== null && CstyleBehaviour.isAutoInsertedClosing(cursor, line, text)) { + CstyleBehaviour.popAutoInsertedClosing(); + return { + text: '', + selection: [1, 1] + }; + } + } + } + }); + + this.add("brackets", "deletion", function (state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && selected == '[') { + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.start.column + 1, range.start.column + 2); + if (rightChar == ']') { + range.end.column++; + return range; + } + } + }); + + this.add("string_dquotes", "insertion", function (state, action, editor, session, text) { + if (text == '"' || text == "'") { + var quote = text; + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "" && selected !== "'" && selected != '"' && editor.getWrapBehavioursEnabled()) { + return { + text: quote + selected + quote, + selection: false + }; + } else { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var leftChar = line.substring(cursor.column-1, cursor.column); + if (leftChar == '\\') { + return null; + } + var tokens = session.getTokens(selection.start.row); + var col = 0, token; + var quotepos = -1; // Track whether we're inside an open quote. + + for (var x = 0; x < tokens.length; x++) { + token = tokens[x]; + if (token.type == "string") { + quotepos = -1; + } else if (quotepos < 0) { + quotepos = token.value.indexOf(quote); + } + if ((token.value.length + col) > selection.start.column) { + break; + } + col += tokens[x].value.length; + } + if (!token || (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf(quote) === token.value.length-1)))) { + if (!CstyleBehaviour.isSaneInsertion(editor, session)) + return; + return { + text: quote + quote, + selection: [1,1] + }; + } else if (token && token.type === "string") { + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar == quote) { + return { + text: '', + selection: [1, 1] + }; + } + } + } + } + }); + + this.add("string_dquotes", "deletion", function (state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && (selected == '"' || selected == "'")) { + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.start.column + 1, range.start.column + 2); + if (rightChar == selected) { + range.end.column++; + return range; + } + } + }); + +}; + +oop.inherits(CstyleBehaviour, Behaviour); + +exports.CstyleBehaviour = CstyleBehaviour; +}); + +ace.define('ace/mode/folding/cstyle', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/range', 'ace/mode/folding/fold_mode'], function(require, exports, module) { + + +var oop = require("../../lib/oop"); +var Range = require("../../range").Range; +var BaseFoldMode = require("./fold_mode").FoldMode; + +var FoldMode = exports.FoldMode = function(commentRegex) { + if (commentRegex) { + this.foldingStartMarker = new RegExp( + this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start) + ); + this.foldingStopMarker = new RegExp( + this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end) + ); + } +}; +oop.inherits(FoldMode, BaseFoldMode); + +(function() { + + this.foldingStartMarker = /(\{|\[)[^\}\]]*$|^\s*(\/\*)/; + this.foldingStopMarker = /^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/; + + this.getFoldWidgetRange = function(session, foldStyle, row) { + var line = session.getLine(row); + var match = line.match(this.foldingStartMarker); + if (match) { + var i = match.index; + + if (match[1]) + return this.openingBracketBlock(session, match[1], row, i); + + return session.getCommentFoldRange(row, i + match[0].length, 1); + } + + if (foldStyle !== "markbeginend") + return; + + var match = line.match(this.foldingStopMarker); + if (match) { + var i = match.index + match[0].length; + + if (match[1]) + return this.closingBracketBlock(session, match[1], row, i); + + return session.getCommentFoldRange(row, i, -1); + } + }; + +}).call(FoldMode.prototype); + +}); diff --git a/external/ace.js/mode-html.js b/external/ace.js/mode-html.js new file mode 100644 index 0000000..be26a7c --- /dev/null +++ b/external/ace.js/mode-html.js @@ -0,0 +1,2311 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Distributed under the BSD license: + * + * Copyright (c) 2010, Ajax.org B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Ajax.org B.V. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ***** END LICENSE BLOCK ***** */ + +ace.define('ace/mode/html', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/text', 'ace/mode/javascript', 'ace/mode/css', 'ace/tokenizer', 'ace/mode/html_highlight_rules', 'ace/mode/behaviour/html', 'ace/mode/folding/html', 'ace/mode/html_completions'], function(require, exports, module) { + + +var oop = require("../lib/oop"); +var TextMode = require("./text").Mode; +var JavaScriptMode = require("./javascript").Mode; +var CssMode = require("./css").Mode; +var Tokenizer = require("../tokenizer").Tokenizer; +var HtmlHighlightRules = require("./html_highlight_rules").HtmlHighlightRules; +var HtmlBehaviour = require("./behaviour/html").HtmlBehaviour; +var HtmlFoldMode = require("./folding/html").FoldMode; +var HtmlCompletions = require("./html_completions").HtmlCompletions; + +var Mode = function() { + this.HighlightRules = HtmlHighlightRules; + this.$behaviour = new HtmlBehaviour(); + this.$completer = new HtmlCompletions(); + + this.createModeDelegates({ + "js-": JavaScriptMode, + "css-": CssMode + }); + + this.foldingRules = new HtmlFoldMode(); +}; +oop.inherits(Mode, TextMode); + +(function() { + + this.blockComment = {start: ""}; + + this.getNextLineIndent = function(state, line, tab) { + return this.$getIndent(line); + }; + + this.checkOutdent = function(state, line, input) { + return false; + }; + + this.getCompletions = function(state, session, pos, prefix) { + return this.$completer.getCompletions(state, session, pos, prefix); + }; + +}).call(Mode.prototype); + +exports.Mode = Mode; +}); + +ace.define('ace/mode/javascript', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/text', 'ace/tokenizer', 'ace/mode/javascript_highlight_rules', 'ace/mode/matching_brace_outdent', 'ace/range', 'ace/worker/worker_client', 'ace/mode/behaviour/cstyle', 'ace/mode/folding/cstyle'], function(require, exports, module) { + + +var oop = require("../lib/oop"); +var TextMode = require("./text").Mode; +var Tokenizer = require("../tokenizer").Tokenizer; +var JavaScriptHighlightRules = require("./javascript_highlight_rules").JavaScriptHighlightRules; +var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent; +var Range = require("../range").Range; +var WorkerClient = require("../worker/worker_client").WorkerClient; +var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour; +var CStyleFoldMode = require("./folding/cstyle").FoldMode; + +var Mode = function() { + this.HighlightRules = JavaScriptHighlightRules; + + this.$outdent = new MatchingBraceOutdent(); + this.$behaviour = new CstyleBehaviour(); + this.foldingRules = new CStyleFoldMode(); +}; +oop.inherits(Mode, TextMode); + +(function() { + + this.lineCommentStart = "//"; + this.blockComment = {start: "/*", end: "*/"}; + + this.getNextLineIndent = function(state, line, tab) { + var indent = this.$getIndent(line); + + var tokenizedLine = this.getTokenizer().getLineTokens(line, state); + var tokens = tokenizedLine.tokens; + var endState = tokenizedLine.state; + + if (tokens.length && tokens[tokens.length-1].type == "comment") { + return indent; + } + + if (state == "start" || state == "no_regex") { + var match = line.match(/^.*(?:\bcase\b.*\:|[\{\(\[])\s*$/); + if (match) { + indent += tab; + } + } else if (state == "doc-start") { + if (endState == "start" || endState == "no_regex") { + return ""; + } + var match = line.match(/^\s*(\/?)\*/); + if (match) { + if (match[1]) { + indent += " "; + } + indent += "* "; + } + } + + return indent; + }; + + this.checkOutdent = function(state, line, input) { + return this.$outdent.checkOutdent(line, input); + }; + + this.autoOutdent = function(state, doc, row) { + this.$outdent.autoOutdent(doc, row); + }; + + this.createWorker = function(session) { + var worker = new WorkerClient(["ace"], "ace/mode/javascript_worker", "JavaScriptWorker"); + worker.attachToDocument(session.getDocument()); + + worker.on("jslint", function(results) { + session.setAnnotations(results.data); + }); + + worker.on("terminate", function() { + session.clearAnnotations(); + }); + + return worker; + }; + +}).call(Mode.prototype); + +exports.Mode = Mode; +}); + +ace.define('ace/mode/javascript_highlight_rules', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/doc_comment_highlight_rules', 'ace/mode/text_highlight_rules'], function(require, exports, module) { + + +var oop = require("../lib/oop"); +var DocCommentHighlightRules = require("./doc_comment_highlight_rules").DocCommentHighlightRules; +var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; + +var JavaScriptHighlightRules = function() { + var keywordMapper = this.createKeywordMapper({ + "variable.language": + "Array|Boolean|Date|Function|Iterator|Number|Object|RegExp|String|Proxy|" + // Constructors + "Namespace|QName|XML|XMLList|" + // E4X + "ArrayBuffer|Float32Array|Float64Array|Int16Array|Int32Array|Int8Array|" + + "Uint16Array|Uint32Array|Uint8Array|Uint8ClampedArray|" + + "Error|EvalError|InternalError|RangeError|ReferenceError|StopIteration|" + // Errors + "SyntaxError|TypeError|URIError|" + + "decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|" + // Non-constructor functions + "isNaN|parseFloat|parseInt|" + + "JSON|Math|" + // Other + "this|arguments|prototype|window|document" , // Pseudo + "keyword": + "const|yield|import|get|set|" + + "break|case|catch|continue|default|delete|do|else|finally|for|function|" + + "if|in|instanceof|new|return|switch|throw|try|typeof|let|var|while|with|debugger|" + + "__parent__|__count__|escape|unescape|with|__proto__|" + + "class|enum|extends|super|export|implements|private|public|interface|package|protected|static", + "storage.type": + "const|let|var|function", + "constant.language": + "null|Infinity|NaN|undefined", + "support.function": + "alert", + "constant.language.boolean": "true|false" + }, "identifier"); + var kwBeforeRe = "case|do|else|finally|in|instanceof|return|throw|try|typeof|yield|void"; + var identifierRe = "[a-zA-Z\\$_\u00a1-\uffff][a-zA-Z\\d\\$_\u00a1-\uffff]*\\b"; + + var escapedRe = "\\\\(?:x[0-9a-fA-F]{2}|" + // hex + "u[0-9a-fA-F]{4}|" + // unicode + "[0-2][0-7]{0,2}|" + // oct + "3[0-6][0-7]?|" + // oct + "37[0-7]?|" + // oct + "[4-7][0-7]?|" + //oct + ".)"; + + this.$rules = { + "no_regex" : [ + { + token : "comment", + regex : "\\/\\/", + next : "line_comment" + }, + DocCommentHighlightRules.getStartRule("doc-start"), + { + token : "comment", // multi line comment + regex : /\/\*/, + next : "comment" + }, { + token : "string", + regex : "'(?=.)", + next : "qstring" + }, { + token : "string", + regex : '"(?=.)', + next : "qqstring" + }, { + token : "constant.numeric", // hex + regex : /0[xX][0-9a-fA-F]+\b/ + }, { + token : "constant.numeric", // float + regex : /[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?\b/ + }, { + token : [ + "storage.type", "punctuation.operator", "support.function", + "punctuation.operator", "entity.name.function", "text","keyword.operator" + ], + regex : "(" + identifierRe + ")(\\.)(prototype)(\\.)(" + identifierRe +")(\\s*)(=)", + next: "function_arguments" + }, { + token : [ + "storage.type", "punctuation.operator", "entity.name.function", "text", + "keyword.operator", "text", "storage.type", "text", "paren.lparen" + ], + regex : "(" + identifierRe + ")(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()", + next: "function_arguments" + }, { + token : [ + "entity.name.function", "text", "keyword.operator", "text", "storage.type", + "text", "paren.lparen" + ], + regex : "(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s*)(\\()", + next: "function_arguments" + }, { + token : [ + "storage.type", "punctuation.operator", "entity.name.function", "text", + "keyword.operator", "text", + "storage.type", "text", "entity.name.function", "text", "paren.lparen" + ], + regex : "(" + identifierRe + ")(\\.)(" + identifierRe +")(\\s*)(=)(\\s*)(function)(\\s+)(\\w+)(\\s*)(\\()", + next: "function_arguments" + }, { + token : [ + "storage.type", "text", "entity.name.function", "text", "paren.lparen" + ], + regex : "(function)(\\s+)(" + identifierRe + ")(\\s*)(\\()", + next: "function_arguments" + }, { + token : [ + "entity.name.function", "text", "punctuation.operator", + "text", "storage.type", "text", "paren.lparen" + ], + regex : "(" + identifierRe + ")(\\s*)(:)(\\s*)(function)(\\s*)(\\()", + next: "function_arguments" + }, { + token : [ + "text", "text", "storage.type", "text", "paren.lparen" + ], + regex : "(:)(\\s*)(function)(\\s*)(\\()", + next: "function_arguments" + }, { + token : "keyword", + regex : "(?:" + kwBeforeRe + ")\\b", + next : "start" + }, { + token : ["punctuation.operator", "support.function"], + regex : /(\.)(s(?:h(?:ift|ow(?:Mod(?:elessDialog|alDialog)|Help))|croll(?:X|By(?:Pages|Lines)?|Y|To)?|t(?:op|rike)|i(?:n|zeToContent|debar|gnText)|ort|u(?:p|b(?:str(?:ing)?)?)|pli(?:ce|t)|e(?:nd|t(?:Re(?:sizable|questHeader)|M(?:i(?:nutes|lliseconds)|onth)|Seconds|Ho(?:tKeys|urs)|Year|Cursor|Time(?:out)?|Interval|ZOptions|Date|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(?:ome|andleEvent)|navigate|c(?:har(?:CodeAt|At)|o(?:s|n(?:cat|textual|firm)|mpile)|eil|lear(?:Timeout|Interval)?|a(?:ptureEvents|ll)|reate(?:StyleSheet|Popup|EventObject))|t(?:o(?:GMTString|S(?:tring|ource)|U(?:TCString|pperCase)|Lo(?:caleString|werCase))|est|a(?:n|int(?:Enabled)?))|i(?:s(?:NaN|Finite)|ndexOf|talics)|d(?:isableExternalCapture|ump|etachEvent)|u(?:n(?:shift|taint|escape|watch)|pdateCommands)|j(?:oin|avaEnabled)|p(?:o(?:p|w)|ush|lugins.refresh|a(?:ddings|rse(?:Int|Float)?)|r(?:int|ompt|eference))|e(?:scape|nableExternalCapture|val|lementFromPoint|x(?:p|ec(?:Script|Command)?))|valueOf|UTC|queryCommand(?:State|Indeterm|Enabled|Value)|f(?:i(?:nd|le(?:ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(?:nt(?:size|color)|rward)|loor|romCharCode)|watch|l(?:ink|o(?:ad|g)|astIndexOf)|a(?:sin|nchor|cos|t(?:tachEvent|ob|an(?:2)?)|pply|lert|b(?:s|ort))|r(?:ou(?:nd|teEvents)|e(?:size(?:By|To)|calc|turnValue|place|verse|l(?:oad|ease(?:Capture|Events)))|andom)|g(?:o|et(?:ResponseHeader|M(?:i(?:nutes|lliseconds)|onth)|Se(?:conds|lection)|Hours|Year|Time(?:zoneOffset)?|Da(?:y|te)|UTC(?:M(?:i(?:nutes|lliseconds)|onth)|Seconds|Hours|Da(?:y|te)|FullYear)|FullYear|A(?:ttention|llResponseHeaders)))|m(?:in|ove(?:B(?:y|elow)|To(?:Absolute)?|Above)|ergeAttributes|a(?:tch|rgins|x))|b(?:toa|ig|o(?:ld|rderWidths)|link|ack))\b(?=\()/ + }, { + token : ["punctuation.operator", "support.function.dom"], + regex : /(\.)(s(?:ub(?:stringData|mit)|plitText|e(?:t(?:NamedItem|Attribute(?:Node)?)|lect))|has(?:ChildNodes|Feature)|namedItem|c(?:l(?:ick|o(?:se|neNode))|reate(?:C(?:omment|DATASection|aption)|T(?:Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(?:ntityReference|lement)|Attribute))|tabIndex|i(?:nsert(?:Row|Before|Cell|Data)|tem)|open|delete(?:Row|C(?:ell|aption)|T(?:Head|Foot)|Data)|focus|write(?:ln)?|a(?:dd|ppend(?:Child|Data))|re(?:set|place(?:Child|Data)|move(?:NamedItem|Child|Attribute(?:Node)?)?)|get(?:NamedItem|Element(?:sBy(?:Name|TagName)|ById)|Attribute(?:Node)?)|blur)\b(?=\()/ + }, { + token : ["punctuation.operator", "support.constant"], + regex : /(\.)(s(?:ystemLanguage|cr(?:ipts|ollbars|een(?:X|Y|Top|Left))|t(?:yle(?:Sheets)?|atus(?:Text|bar)?)|ibling(?:Below|Above)|ource|uffixes|e(?:curity(?:Policy)?|l(?:ection|f)))|h(?:istory|ost(?:name)?|as(?:h|Focus))|y|X(?:MLDocument|SLDocument)|n(?:ext|ame(?:space(?:s|URI)|Prop))|M(?:IN_VALUE|AX_VALUE)|c(?:haracterSet|o(?:n(?:structor|trollers)|okieEnabled|lorDepth|mp(?:onents|lete))|urrent|puClass|l(?:i(?:p(?:boardData)?|entInformation)|osed|asses)|alle(?:e|r)|rypto)|t(?:o(?:olbar|p)|ext(?:Transform|Indent|Decoration|Align)|ags)|SQRT(?:1_2|2)|i(?:n(?:ner(?:Height|Width)|put)|ds|gnoreCase)|zIndex|o(?:scpu|n(?:readystatechange|Line)|uter(?:Height|Width)|p(?:sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(?:i(?:splay|alog(?:Height|Top|Width|Left|Arguments)|rectories)|e(?:scription|fault(?:Status|Ch(?:ecked|arset)|View)))|u(?:ser(?:Profile|Language|Agent)|n(?:iqueID|defined)|pdateInterval)|_content|p(?:ixelDepth|ort|ersonalbar|kcs11|l(?:ugins|atform)|a(?:thname|dding(?:Right|Bottom|Top|Left)|rent(?:Window|Layer)?|ge(?:X(?:Offset)?|Y(?:Offset)?))|r(?:o(?:to(?:col|type)|duct(?:Sub)?|mpter)|e(?:vious|fix)))|e(?:n(?:coding|abledPlugin)|x(?:ternal|pando)|mbeds)|v(?:isibility|endor(?:Sub)?|Linkcolor)|URLUnencoded|P(?:I|OSITIVE_INFINITY)|f(?:ilename|o(?:nt(?:Size|Family|Weight)|rmName)|rame(?:s|Element)|gColor)|E|whiteSpace|l(?:i(?:stStyleType|n(?:eHeight|kColor))|o(?:ca(?:tion(?:bar)?|lName)|wsrc)|e(?:ngth|ft(?:Context)?)|a(?:st(?:M(?:odified|atch)|Index|Paren)|yer(?:s|X)|nguage))|a(?:pp(?:MinorVersion|Name|Co(?:deName|re)|Version)|vail(?:Height|Top|Width|Left)|ll|r(?:ity|guments)|Linkcolor|bove)|r(?:ight(?:Context)?|e(?:sponse(?:XML|Text)|adyState))|global|x|m(?:imeTypes|ultiline|enubar|argin(?:Right|Bottom|Top|Left))|L(?:N(?:10|2)|OG(?:10E|2E))|b(?:o(?:ttom|rder(?:Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(?:Color|Image)))\b/ + }, { + token : ["storage.type", "punctuation.operator", "support.function.firebug"], + regex : /(console)(\.)(warn|info|log|error|time|timeEnd|assert)\b/ + }, { + token : keywordMapper, + regex : identifierRe + }, { + token : "keyword.operator", + regex : /--|\+\+|[!$%&*+\-~]|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|%=|\+=|\-=|&=|\^=/, + next : "start" + }, { + token : "punctuation.operator", + regex : /\?|\:|\,|\;|\./, + next : "start" + }, { + token : "paren.lparen", + regex : /[\[({]/, + next : "start" + }, { + token : "paren.rparen", + regex : /[\])}]/ + }, { + token : "keyword.operator", + regex : /\/=?/, + next : "start" + }, { + token: "comment", + regex: /^#!.*$/ + } + ], + "start": [ + DocCommentHighlightRules.getStartRule("doc-start"), + { + token : "comment", // multi line comment + regex : "\\/\\*", + next : "comment_regex_allowed" + }, { + token : "comment", + regex : "\\/\\/", + next : "line_comment_regex_allowed" + }, { + token: "string.regexp", + regex: "\\/", + next: "regex" + }, { + token : "text", + regex : "\\s+|^$", + next : "start" + }, { + token: "empty", + regex: "", + next: "no_regex" + } + ], + "regex": [ + { + token: "regexp.keyword.operator", + regex: "\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)" + }, { + token: "string.regexp", + regex: "/\\w*", + next: "no_regex" + }, { + token : "invalid", + regex: /\{\d+\b,?\d*\}[+*]|[+*$^?][+*]|[$^][?]|\?{3,}/ + }, { + token : "constant.language.escape", + regex: /\(\?[:=!]|\)|\{\d+\b,?\d*\}|[+*]\?|[()$^+*?]/ + }, { + token : "constant.language.delimiter", + regex: /\|/ + }, { + token: "constant.language.escape", + regex: /\[\^?/, + next: "regex_character_class" + }, { + token: "empty", + regex: "$", + next: "no_regex" + }, { + defaultToken: "string.regexp" + } + ], + "regex_character_class": [ + { + token: "regexp.keyword.operator", + regex: "\\\\(?:u[\\da-fA-F]{4}|x[\\da-fA-F]{2}|.)" + }, { + token: "constant.language.escape", + regex: "]", + next: "regex" + }, { + token: "constant.language.escape", + regex: "-" + }, { + token: "empty", + regex: "$", + next: "no_regex" + }, { + defaultToken: "string.regexp.charachterclass" + } + ], + "function_arguments": [ + { + token: "variable.parameter", + regex: identifierRe + }, { + token: "punctuation.operator", + regex: "[, ]+" + }, { + token: "punctuation.operator", + regex: "$" + }, { + token: "empty", + regex: "", + next: "no_regex" + } + ], + "comment_regex_allowed" : [ + {token : "comment", regex : "\\*\\/", next : "start"}, + {defaultToken : "comment"} + ], + "comment" : [ + {token : "comment", regex : "\\*\\/", next : "no_regex"}, + {defaultToken : "comment"} + ], + "line_comment_regex_allowed" : [ + {token : "comment", regex : "$|^", next : "start"}, + {defaultToken : "comment"} + ], + "line_comment" : [ + {token : "comment", regex : "$|^", next : "no_regex"}, + {defaultToken : "comment"} + ], + "qqstring" : [ + { + token : "constant.language.escape", + regex : escapedRe + }, { + token : "string", + regex : "\\\\$", + next : "qqstring" + }, { + token : "string", + regex : '"|$', + next : "no_regex" + }, { + defaultToken: "string" + } + ], + "qstring" : [ + { + token : "constant.language.escape", + regex : escapedRe + }, { + token : "string", + regex : "\\\\$", + next : "qstring" + }, { + token : "string", + regex : "'|$", + next : "no_regex" + }, { + defaultToken: "string" + } + ] + }; + + this.embedRules(DocCommentHighlightRules, "doc-", + [ DocCommentHighlightRules.getEndRule("no_regex") ]); +}; + +oop.inherits(JavaScriptHighlightRules, TextHighlightRules); + +exports.JavaScriptHighlightRules = JavaScriptHighlightRules; +}); + +ace.define('ace/mode/doc_comment_highlight_rules', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/text_highlight_rules'], function(require, exports, module) { + + +var oop = require("../lib/oop"); +var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; + +var DocCommentHighlightRules = function() { + + this.$rules = { + "start" : [ { + token : "comment.doc.tag", + regex : "@[\\w\\d_]+" // TODO: fix email addresses + }, { + token : "comment.doc.tag", + regex : "\\bTODO\\b" + }, { + defaultToken : "comment.doc" + }] + }; +}; + +oop.inherits(DocCommentHighlightRules, TextHighlightRules); + +DocCommentHighlightRules.getStartRule = function(start) { + return { + token : "comment.doc", // doc comment + regex : "\\/\\*(?=\\*)", + next : start + }; +}; + +DocCommentHighlightRules.getEndRule = function (start) { + return { + token : "comment.doc", // closing comment + regex : "\\*\\/", + next : start + }; +}; + + +exports.DocCommentHighlightRules = DocCommentHighlightRules; + +}); + +ace.define('ace/mode/matching_brace_outdent', ['require', 'exports', 'module' , 'ace/range'], function(require, exports, module) { + + +var Range = require("../range").Range; + +var MatchingBraceOutdent = function() {}; + +(function() { + + this.checkOutdent = function(line, input) { + if (! /^\s+$/.test(line)) + return false; + + return /^\s*\}/.test(input); + }; + + this.autoOutdent = function(doc, row) { + var line = doc.getLine(row); + var match = line.match(/^(\s*\})/); + + if (!match) return 0; + + var column = match[1].length; + var openBracePos = doc.findMatchingBracket({row: row, column: column}); + + if (!openBracePos || openBracePos.row == row) return 0; + + var indent = this.$getIndent(doc.getLine(openBracePos.row)); + doc.replace(new Range(row, 0, row, column-1), indent); + }; + + this.$getIndent = function(line) { + return line.match(/^\s*/)[0]; + }; + +}).call(MatchingBraceOutdent.prototype); + +exports.MatchingBraceOutdent = MatchingBraceOutdent; +}); + +ace.define('ace/mode/behaviour/cstyle', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/behaviour', 'ace/token_iterator', 'ace/lib/lang'], function(require, exports, module) { + + +var oop = require("../../lib/oop"); +var Behaviour = require("../behaviour").Behaviour; +var TokenIterator = require("../../token_iterator").TokenIterator; +var lang = require("../../lib/lang"); + +var SAFE_INSERT_IN_TOKENS = + ["text", "paren.rparen", "punctuation.operator"]; +var SAFE_INSERT_BEFORE_TOKENS = + ["text", "paren.rparen", "punctuation.operator", "comment"]; + + +var autoInsertedBrackets = 0; +var autoInsertedRow = -1; +var autoInsertedLineEnd = ""; +var maybeInsertedBrackets = 0; +var maybeInsertedRow = -1; +var maybeInsertedLineStart = ""; +var maybeInsertedLineEnd = ""; + +var CstyleBehaviour = function () { + + CstyleBehaviour.isSaneInsertion = function(editor, session) { + var cursor = editor.getCursorPosition(); + var iterator = new TokenIterator(session, cursor.row, cursor.column); + if (!this.$matchTokenType(iterator.getCurrentToken() || "text", SAFE_INSERT_IN_TOKENS)) { + var iterator2 = new TokenIterator(session, cursor.row, cursor.column + 1); + if (!this.$matchTokenType(iterator2.getCurrentToken() || "text", SAFE_INSERT_IN_TOKENS)) + return false; + } + iterator.stepForward(); + return iterator.getCurrentTokenRow() !== cursor.row || + this.$matchTokenType(iterator.getCurrentToken() || "text", SAFE_INSERT_BEFORE_TOKENS); + }; + + CstyleBehaviour.$matchTokenType = function(token, types) { + return types.indexOf(token.type || token) > -1; + }; + + CstyleBehaviour.recordAutoInsert = function(editor, session, bracket) { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + if (!this.isAutoInsertedClosing(cursor, line, autoInsertedLineEnd[0])) + autoInsertedBrackets = 0; + autoInsertedRow = cursor.row; + autoInsertedLineEnd = bracket + line.substr(cursor.column); + autoInsertedBrackets++; + }; + + CstyleBehaviour.recordMaybeInsert = function(editor, session, bracket) { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + if (!this.isMaybeInsertedClosing(cursor, line)) + maybeInsertedBrackets = 0; + maybeInsertedRow = cursor.row; + maybeInsertedLineStart = line.substr(0, cursor.column) + bracket; + maybeInsertedLineEnd = line.substr(cursor.column); + maybeInsertedBrackets++; + }; + + CstyleBehaviour.isAutoInsertedClosing = function(cursor, line, bracket) { + return autoInsertedBrackets > 0 && + cursor.row === autoInsertedRow && + bracket === autoInsertedLineEnd[0] && + line.substr(cursor.column) === autoInsertedLineEnd; + }; + + CstyleBehaviour.isMaybeInsertedClosing = function(cursor, line) { + return maybeInsertedBrackets > 0 && + cursor.row === maybeInsertedRow && + line.substr(cursor.column) === maybeInsertedLineEnd && + line.substr(0, cursor.column) == maybeInsertedLineStart; + }; + + CstyleBehaviour.popAutoInsertedClosing = function() { + autoInsertedLineEnd = autoInsertedLineEnd.substr(1); + autoInsertedBrackets--; + }; + + CstyleBehaviour.clearMaybeInsertedClosing = function() { + maybeInsertedBrackets = 0; + maybeInsertedRow = -1; + }; + + this.add("braces", "insertion", function (state, action, editor, session, text) { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + if (text == '{') { + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "" && selected !== "{" && editor.getWrapBehavioursEnabled()) { + return { + text: '{' + selected + '}', + selection: false + }; + } else if (CstyleBehaviour.isSaneInsertion(editor, session)) { + if (/[\]\}\)]/.test(line[cursor.column])) { + CstyleBehaviour.recordAutoInsert(editor, session, "}"); + return { + text: '{}', + selection: [1, 1] + }; + } else { + CstyleBehaviour.recordMaybeInsert(editor, session, "{"); + return { + text: '{', + selection: [1, 1] + }; + } + } + } else if (text == '}') { + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar == '}') { + var matching = session.$findOpeningBracket('}', {column: cursor.column + 1, row: cursor.row}); + if (matching !== null && CstyleBehaviour.isAutoInsertedClosing(cursor, line, text)) { + CstyleBehaviour.popAutoInsertedClosing(); + return { + text: '', + selection: [1, 1] + }; + } + } + } else if (text == "\n" || text == "\r\n") { + var closing = ""; + if (CstyleBehaviour.isMaybeInsertedClosing(cursor, line)) { + closing = lang.stringRepeat("}", maybeInsertedBrackets); + CstyleBehaviour.clearMaybeInsertedClosing(); + } + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar == '}' || closing !== "") { + var openBracePos = session.findMatchingBracket({row: cursor.row, column: cursor.column}, '}'); + if (!openBracePos) + return null; + + var indent = this.getNextLineIndent(state, line.substring(0, cursor.column), session.getTabString()); + var next_indent = this.$getIndent(line); + + return { + text: '\n' + indent + '\n' + next_indent + closing, + selection: [1, indent.length, 1, indent.length] + }; + } + } + }); + + this.add("braces", "deletion", function (state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && selected == '{') { + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.end.column, range.end.column + 1); + if (rightChar == '}') { + range.end.column++; + return range; + } else { + maybeInsertedBrackets--; + } + } + }); + + this.add("parens", "insertion", function (state, action, editor, session, text) { + if (text == '(') { + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "" && editor.getWrapBehavioursEnabled()) { + return { + text: '(' + selected + ')', + selection: false + }; + } else if (CstyleBehaviour.isSaneInsertion(editor, session)) { + CstyleBehaviour.recordAutoInsert(editor, session, ")"); + return { + text: '()', + selection: [1, 1] + }; + } + } else if (text == ')') { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar == ')') { + var matching = session.$findOpeningBracket(')', {column: cursor.column + 1, row: cursor.row}); + if (matching !== null && CstyleBehaviour.isAutoInsertedClosing(cursor, line, text)) { + CstyleBehaviour.popAutoInsertedClosing(); + return { + text: '', + selection: [1, 1] + }; + } + } + } + }); + + this.add("parens", "deletion", function (state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && selected == '(') { + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.start.column + 1, range.start.column + 2); + if (rightChar == ')') { + range.end.column++; + return range; + } + } + }); + + this.add("brackets", "insertion", function (state, action, editor, session, text) { + if (text == '[') { + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "" && editor.getWrapBehavioursEnabled()) { + return { + text: '[' + selected + ']', + selection: false + }; + } else if (CstyleBehaviour.isSaneInsertion(editor, session)) { + CstyleBehaviour.recordAutoInsert(editor, session, "]"); + return { + text: '[]', + selection: [1, 1] + }; + } + } else if (text == ']') { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar == ']') { + var matching = session.$findOpeningBracket(']', {column: cursor.column + 1, row: cursor.row}); + if (matching !== null && CstyleBehaviour.isAutoInsertedClosing(cursor, line, text)) { + CstyleBehaviour.popAutoInsertedClosing(); + return { + text: '', + selection: [1, 1] + }; + } + } + } + }); + + this.add("brackets", "deletion", function (state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && selected == '[') { + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.start.column + 1, range.start.column + 2); + if (rightChar == ']') { + range.end.column++; + return range; + } + } + }); + + this.add("string_dquotes", "insertion", function (state, action, editor, session, text) { + if (text == '"' || text == "'") { + var quote = text; + var selection = editor.getSelectionRange(); + var selected = session.doc.getTextRange(selection); + if (selected !== "" && selected !== "'" && selected != '"' && editor.getWrapBehavioursEnabled()) { + return { + text: quote + selected + quote, + selection: false + }; + } else { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var leftChar = line.substring(cursor.column-1, cursor.column); + if (leftChar == '\\') { + return null; + } + var tokens = session.getTokens(selection.start.row); + var col = 0, token; + var quotepos = -1; // Track whether we're inside an open quote. + + for (var x = 0; x < tokens.length; x++) { + token = tokens[x]; + if (token.type == "string") { + quotepos = -1; + } else if (quotepos < 0) { + quotepos = token.value.indexOf(quote); + } + if ((token.value.length + col) > selection.start.column) { + break; + } + col += tokens[x].value.length; + } + if (!token || (quotepos < 0 && token.type !== "comment" && (token.type !== "string" || ((selection.start.column !== token.value.length+col-1) && token.value.lastIndexOf(quote) === token.value.length-1)))) { + if (!CstyleBehaviour.isSaneInsertion(editor, session)) + return; + return { + text: quote + quote, + selection: [1,1] + }; + } else if (token && token.type === "string") { + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar == quote) { + return { + text: '', + selection: [1, 1] + }; + } + } + } + } + }); + + this.add("string_dquotes", "deletion", function (state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && (selected == '"' || selected == "'")) { + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.start.column + 1, range.start.column + 2); + if (rightChar == selected) { + range.end.column++; + return range; + } + } + }); + +}; + +oop.inherits(CstyleBehaviour, Behaviour); + +exports.CstyleBehaviour = CstyleBehaviour; +}); + +ace.define('ace/mode/folding/cstyle', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/range', 'ace/mode/folding/fold_mode'], function(require, exports, module) { + + +var oop = require("../../lib/oop"); +var Range = require("../../range").Range; +var BaseFoldMode = require("./fold_mode").FoldMode; + +var FoldMode = exports.FoldMode = function(commentRegex) { + if (commentRegex) { + this.foldingStartMarker = new RegExp( + this.foldingStartMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.start) + ); + this.foldingStopMarker = new RegExp( + this.foldingStopMarker.source.replace(/\|[^|]*?$/, "|" + commentRegex.end) + ); + } +}; +oop.inherits(FoldMode, BaseFoldMode); + +(function() { + + this.foldingStartMarker = /(\{|\[)[^\}\]]*$|^\s*(\/\*)/; + this.foldingStopMarker = /^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/; + + this.getFoldWidgetRange = function(session, foldStyle, row) { + var line = session.getLine(row); + var match = line.match(this.foldingStartMarker); + if (match) { + var i = match.index; + + if (match[1]) + return this.openingBracketBlock(session, match[1], row, i); + + return session.getCommentFoldRange(row, i + match[0].length, 1); + } + + if (foldStyle !== "markbeginend") + return; + + var match = line.match(this.foldingStopMarker); + if (match) { + var i = match.index + match[0].length; + + if (match[1]) + return this.closingBracketBlock(session, match[1], row, i); + + return session.getCommentFoldRange(row, i, -1); + } + }; + +}).call(FoldMode.prototype); + +}); + +ace.define('ace/mode/css', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/text', 'ace/tokenizer', 'ace/mode/css_highlight_rules', 'ace/mode/matching_brace_outdent', 'ace/worker/worker_client', 'ace/mode/behaviour/css', 'ace/mode/folding/cstyle'], function(require, exports, module) { + + +var oop = require("../lib/oop"); +var TextMode = require("./text").Mode; +var Tokenizer = require("../tokenizer").Tokenizer; +var CssHighlightRules = require("./css_highlight_rules").CssHighlightRules; +var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent; +var WorkerClient = require("../worker/worker_client").WorkerClient; +var CssBehaviour = require("./behaviour/css").CssBehaviour; +var CStyleFoldMode = require("./folding/cstyle").FoldMode; + +var Mode = function() { + this.HighlightRules = CssHighlightRules; + this.$outdent = new MatchingBraceOutdent(); + this.$behaviour = new CssBehaviour(); + this.foldingRules = new CStyleFoldMode(); +}; +oop.inherits(Mode, TextMode); + +(function() { + + this.foldingRules = "cStyle"; + this.blockComment = {start: "/*", end: "*/"}; + + this.getNextLineIndent = function(state, line, tab) { + var indent = this.$getIndent(line); + var tokens = this.getTokenizer().getLineTokens(line, state).tokens; + if (tokens.length && tokens[tokens.length-1].type == "comment") { + return indent; + } + + var match = line.match(/^.*\{\s*$/); + if (match) { + indent += tab; + } + + return indent; + }; + + this.checkOutdent = function(state, line, input) { + return this.$outdent.checkOutdent(line, input); + }; + + this.autoOutdent = function(state, doc, row) { + this.$outdent.autoOutdent(doc, row); + }; + + this.createWorker = function(session) { + var worker = new WorkerClient(["ace"], "ace/mode/css_worker", "Worker"); + worker.attachToDocument(session.getDocument()); + + worker.on("csslint", function(e) { + session.setAnnotations(e.data); + }); + + worker.on("terminate", function() { + session.clearAnnotations(); + }); + + return worker; + }; + +}).call(Mode.prototype); + +exports.Mode = Mode; + +}); + +ace.define('ace/mode/css_highlight_rules', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/lang', 'ace/mode/text_highlight_rules'], function(require, exports, module) { + + +var oop = require("../lib/oop"); +var lang = require("../lib/lang"); +var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; +var supportType = exports.supportType = "animation-fill-mode|alignment-adjust|alignment-baseline|animation-delay|animation-direction|animation-duration|animation-iteration-count|animation-name|animation-play-state|animation-timing-function|animation|appearance|azimuth|backface-visibility|background-attachment|background-break|background-clip|background-color|background-image|background-origin|background-position|background-repeat|background-size|background|baseline-shift|binding|bleed|bookmark-label|bookmark-level|bookmark-state|bookmark-target|border-bottom|border-bottom-color|border-bottom-left-radius|border-bottom-right-radius|border-bottom-style|border-bottom-width|border-collapse|border-color|border-image|border-image-outset|border-image-repeat|border-image-slice|border-image-source|border-image-width|border-left|border-left-color|border-left-style|border-left-width|border-radius|border-right|border-right-color|border-right-style|border-right-width|border-spacing|border-style|border-top|border-top-color|border-top-left-radius|border-top-right-radius|border-top-style|border-top-width|border-width|border|bottom|box-align|box-decoration-break|box-direction|box-flex-group|box-flex|box-lines|box-ordinal-group|box-orient|box-pack|box-shadow|box-sizing|break-after|break-before|break-inside|caption-side|clear|clip|color-profile|color|column-count|column-fill|column-gap|column-rule|column-rule-color|column-rule-style|column-rule-width|column-span|column-width|columns|content|counter-increment|counter-reset|crop|cue-after|cue-before|cue|cursor|direction|display|dominant-baseline|drop-initial-after-adjust|drop-initial-after-align|drop-initial-before-adjust|drop-initial-before-align|drop-initial-size|drop-initial-value|elevation|empty-cells|fit|fit-position|float-offset|float|font-family|font-size|font-size-adjust|font-stretch|font-style|font-variant|font-weight|font|grid-columns|grid-rows|hanging-punctuation|height|hyphenate-after|hyphenate-before|hyphenate-character|hyphenate-lines|hyphenate-resource|hyphens|icon|image-orientation|image-rendering|image-resolution|inline-box-align|left|letter-spacing|line-height|line-stacking-ruby|line-stacking-shift|line-stacking-strategy|line-stacking|list-style-image|list-style-position|list-style-type|list-style|margin-bottom|margin-left|margin-right|margin-top|margin|mark-after|mark-before|mark|marks|marquee-direction|marquee-play-count|marquee-speed|marquee-style|max-height|max-width|min-height|min-width|move-to|nav-down|nav-index|nav-left|nav-right|nav-up|opacity|orphans|outline-color|outline-offset|outline-style|outline-width|outline|overflow-style|overflow-x|overflow-y|overflow|padding-bottom|padding-left|padding-right|padding-top|padding|page-break-after|page-break-before|page-break-inside|page-policy|page|pause-after|pause-before|pause|perspective-origin|perspective|phonemes|pitch-range|pitch|play-during|position|presentation-level|punctuation-trim|quotes|rendering-intent|resize|rest-after|rest-before|rest|richness|right|rotation-point|rotation|ruby-align|ruby-overhang|ruby-position|ruby-span|size|speak-header|speak-numeral|speak-punctuation|speak|speech-rate|stress|string-set|table-layout|target-name|target-new|target-position|target|text-align-last|text-align|text-decoration|text-emphasis|text-height|text-indent|text-justify|text-outline|text-shadow|text-transform|text-wrap|top|transform-origin|transform-style|transform|transition-delay|transition-duration|transition-property|transition-timing-function|transition|unicode-bidi|vertical-align|visibility|voice-balance|voice-duration|voice-family|voice-pitch-range|voice-pitch|voice-rate|voice-stress|voice-volume|volume|white-space-collapse|white-space|widows|width|word-break|word-spacing|word-wrap|z-index"; +var supportFunction = exports.supportFunction = "rgb|rgba|url|attr|counter|counters"; +var supportConstant = exports.supportConstant = "absolute|after-edge|after|all-scroll|all|alphabetic|always|antialiased|armenian|auto|avoid-column|avoid-page|avoid|balance|baseline|before-edge|before|below|bidi-override|block-line-height|block|bold|bolder|border-box|both|bottom|box|break-all|break-word|capitalize|caps-height|caption|center|central|char|circle|cjk-ideographic|clone|close-quote|col-resize|collapse|column|consider-shifts|contain|content-box|cover|crosshair|cubic-bezier|dashed|decimal-leading-zero|decimal|default|disabled|disc|disregard-shifts|distribute-all-lines|distribute-letter|distribute-space|distribute|dotted|double|e-resize|ease-in|ease-in-out|ease-out|ease|ellipsis|end|exclude-ruby|fill|fixed|georgian|glyphs|grid-height|groove|hand|hanging|hebrew|help|hidden|hiragana-iroha|hiragana|horizontal|icon|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|ideographic|inactive|include-ruby|inherit|initial|inline-block|inline-box|inline-line-height|inline-table|inline|inset|inside|inter-ideograph|inter-word|invert|italic|justify|katakana-iroha|katakana|keep-all|last|left|lighter|line-edge|line-through|line|linear|list-item|local|loose|lower-alpha|lower-greek|lower-latin|lower-roman|lowercase|lr-tb|ltr|mathematical|max-height|max-size|medium|menu|message-box|middle|move|n-resize|ne-resize|newspaper|no-change|no-close-quote|no-drop|no-open-quote|no-repeat|none|normal|not-allowed|nowrap|nw-resize|oblique|open-quote|outset|outside|overline|padding-box|page|pointer|pre-line|pre-wrap|pre|preserve-3d|progress|relative|repeat-x|repeat-y|repeat|replaced|reset-size|ridge|right|round|row-resize|rtl|s-resize|scroll|se-resize|separate|slice|small-caps|small-caption|solid|space|square|start|static|status-bar|step-end|step-start|steps|stretch|strict|sub|super|sw-resize|table-caption|table-cell|table-column-group|table-column|table-footer-group|table-header-group|table-row-group|table-row|table|tb-rl|text-after-edge|text-before-edge|text-bottom|text-size|text-top|text|thick|thin|transparent|underline|upper-alpha|upper-latin|upper-roman|uppercase|use-script|vertical-ideographic|vertical-text|visible|w-resize|wait|whitespace|z-index|zero"; +var supportConstantColor = exports.supportConstantColor = "aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow"; +var supportConstantFonts = exports.supportConstantFonts = "arial|century|comic|courier|garamond|georgia|helvetica|impact|lucida|symbol|system|tahoma|times|trebuchet|utopia|verdana|webdings|sans-serif|serif|monospace"; + +var numRe = exports.numRe = "\\-?(?:(?:[0-9]+)|(?:[0-9]*\\.[0-9]+))"; +var pseudoElements = exports.pseudoElements = "(\\:+)\\b(after|before|first-letter|first-line|moz-selection|selection)\\b"; +var pseudoClasses = exports.pseudoClasses = "(:)\\b(active|checked|disabled|empty|enabled|first-child|first-of-type|focus|hover|indeterminate|invalid|last-child|last-of-type|link|not|nth-child|nth-last-child|nth-last-of-type|nth-of-type|only-child|only-of-type|required|root|target|valid|visited)\\b"; + +var CssHighlightRules = function() { + + var keywordMapper = this.createKeywordMapper({ + "support.function": supportFunction, + "support.constant": supportConstant, + "support.type": supportType, + "support.constant.color": supportConstantColor, + "support.constant.fonts": supportConstantFonts + }, "text", true); + + this.$rules = { + "start" : [{ + token : "comment", // multi line comment + regex : "\\/\\*", + push : "comment" + }, { + token: "paren.lparen", + regex: "\\{", + push: "ruleset" + }, { + token: "string", + regex: "@.*?{", + push: "media" + }, { + token: "keyword", + regex: "#[a-z0-9-_]+" + }, { + token: "variable", + regex: "\\.[a-z0-9-_]+" + }, { + token: "string", + regex: ":[a-z0-9-_]+" + }, { + token: "constant", + regex: "[a-z0-9-_]+" + }, { + caseInsensitive: true + }], + + "media" : [{ + token : "comment", // multi line comment + regex : "\\/\\*", + push : "comment" + }, { + token: "paren.lparen", + regex: "\\{", + push: "ruleset" + }, { + token: "string", + regex: "\\}", + next: "pop" + }, { + token: "keyword", + regex: "#[a-z0-9-_]+" + }, { + token: "variable", + regex: "\\.[a-z0-9-_]+" + }, { + token: "string", + regex: ":[a-z0-9-_]+" + }, { + token: "constant", + regex: "[a-z0-9-_]+" + }, { + caseInsensitive: true + }], + + "comment" : [{ + token : "comment", + regex : "\\*\\/", + next : "pop" + }, { + defaultToken : "comment" + }], + + "ruleset" : [ + { + token : "paren.rparen", + regex : "\\}", + next: "pop" + }, { + token : "comment", // multi line comment + regex : "\\/\\*", + push : "comment" + }, { + token : "string", // single line + regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]' + }, { + token : "string", // single line + regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']" + }, { + token : ["constant.numeric", "keyword"], + regex : "(" + numRe + ")(ch|cm|deg|em|ex|fr|gd|grad|Hz|in|kHz|mm|ms|pc|pt|px|rad|rem|s|turn|vh|vm|vw|%)" + }, { + token : "constant.numeric", + regex : numRe + }, { + token : "constant.numeric", // hex6 color + regex : "#[a-f0-9]{6}" + }, { + token : "constant.numeric", // hex3 color + regex : "#[a-f0-9]{3}" + }, { + token : ["punctuation", "entity.other.attribute-name.pseudo-element.css"], + regex : pseudoElements + }, { + token : ["punctuation", "entity.other.attribute-name.pseudo-class.css"], + regex : pseudoClasses + }, { + token : ["support.function", "string", "support.function"], + regex : "(url\\()(.*)(\\))" + }, { + token : keywordMapper, + regex : "\\-?[a-zA-Z_][a-zA-Z0-9_\\-]*" + }, { + caseInsensitive: true + }] + }; + + this.normalizeRules(); +}; + +oop.inherits(CssHighlightRules, TextHighlightRules); + +exports.CssHighlightRules = CssHighlightRules; + +}); + +ace.define('ace/mode/behaviour/css', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/behaviour', 'ace/mode/behaviour/cstyle', 'ace/token_iterator'], function(require, exports, module) { + + +var oop = require("../../lib/oop"); +var Behaviour = require("../behaviour").Behaviour; +var CstyleBehaviour = require("./cstyle").CstyleBehaviour; +var TokenIterator = require("../../token_iterator").TokenIterator; + +var CssBehaviour = function () { + + this.inherit(CstyleBehaviour); + + this.add("colon", "insertion", function (state, action, editor, session, text) { + if (text === ':') { + var cursor = editor.getCursorPosition(); + var iterator = new TokenIterator(session, cursor.row, cursor.column); + var token = iterator.getCurrentToken(); + if (token && token.value.match(/\s+/)) { + token = iterator.stepBackward(); + } + if (token && token.type === 'support.type') { + var line = session.doc.getLine(cursor.row); + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar === ':') { + return { + text: '', + selection: [1, 1] + } + } + if (!line.substring(cursor.column).match(/^\s*;/)) { + return { + text: ':;', + selection: [1, 1] + } + } + } + } + }); + + this.add("colon", "deletion", function (state, action, editor, session, range) { + var selected = session.doc.getTextRange(range); + if (!range.isMultiLine() && selected === ':') { + var cursor = editor.getCursorPosition(); + var iterator = new TokenIterator(session, cursor.row, cursor.column); + var token = iterator.getCurrentToken(); + if (token && token.value.match(/\s+/)) { + token = iterator.stepBackward(); + } + if (token && token.type === 'support.type') { + var line = session.doc.getLine(range.start.row); + var rightChar = line.substring(range.end.column, range.end.column + 1); + if (rightChar === ';') { + range.end.column ++; + return range; + } + } + } + }); + + this.add("semicolon", "insertion", function (state, action, editor, session, text) { + if (text === ';') { + var cursor = editor.getCursorPosition(); + var line = session.doc.getLine(cursor.row); + var rightChar = line.substring(cursor.column, cursor.column + 1); + if (rightChar === ';') { + return { + text: '', + selection: [1, 1] + } + } + } + }); + +} +oop.inherits(CssBehaviour, CstyleBehaviour); + +exports.CssBehaviour = CssBehaviour; +}); + +ace.define('ace/mode/html_highlight_rules', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/lang', 'ace/mode/css_highlight_rules', 'ace/mode/javascript_highlight_rules', 'ace/mode/xml_highlight_rules'], function(require, exports, module) { + + +var oop = require("../lib/oop"); +var lang = require("../lib/lang"); +var CssHighlightRules = require("./css_highlight_rules").CssHighlightRules; +var JavaScriptHighlightRules = require("./javascript_highlight_rules").JavaScriptHighlightRules; +var XmlHighlightRules = require("./xml_highlight_rules").XmlHighlightRules; + +var tagMap = lang.createMap({ + a : 'anchor', + button : 'form', + form : 'form', + img : 'image', + input : 'form', + label : 'form', + script : 'script', + select : 'form', + textarea : 'form', + style : 'style', + table : 'table', + tbody : 'table', + td : 'table', + tfoot : 'table', + th : 'table', + tr : 'table' +}); + +var HtmlHighlightRules = function() { + XmlHighlightRules.call(this); + + this.addRules({ + attributes: [{ + include : "space" + }, { + token : "entity.other.attribute-name", + regex : "[-_a-zA-Z0-9:]+" + }, { + token : "keyword.operator.separator", + regex : "=", + push : [{ + include: "space" + }, { + token : "string", + regex : "[^<>='\"`\\s]+", + next : "pop" + }, { + token : "empty", + regex : "", + next : "pop" + }] + }, { + include : "string" + }], + tag: [{ + token : function(start, tag) { + var group = tagMap[tag]; + return ["meta.tag.punctuation.begin", + "meta.tag.name" + (group ? "." + group : "")]; + }, + regex : "(<)([-_a-zA-Z0-9:]+)", + next: "start_tag_stuff" + }, { + token : function(start, tag) { + var group = tagMap[tag]; + return ["meta.tag.punctuation.begin", + "meta.tag.name" + (group ? "." + group : "")]; + }, + regex : "(", next : "start"} + ], + end_tag_stuff: [ + {include : "space"}, + {token : "meta.tag.punctuation.end", regex : ">", next : "start"} + ] + }); + + this.embedTagRules(CssHighlightRules, "css-", "style"); + this.embedTagRules(JavaScriptHighlightRules, "js-", "script"); + + if (this.constructor === HtmlHighlightRules) + this.normalizeRules(); +}; + +oop.inherits(HtmlHighlightRules, XmlHighlightRules); + +exports.HtmlHighlightRules = HtmlHighlightRules; +}); + +ace.define('ace/mode/xml_highlight_rules', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/xml_util', 'ace/mode/text_highlight_rules'], function(require, exports, module) { + + +var oop = require("../lib/oop"); +var xmlUtil = require("./xml_util"); +var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; + +var XmlHighlightRules = function(normalize) { + this.$rules = { + start : [ + {token : "punctuation.string.begin", regex : "<\\!\\[CDATA\\[", next : "cdata"}, + { + token : ["punctuation.instruction.begin", "keyword.instruction"], + regex : "(<\\?)(xml)(?=[\\s])", next : "xml_declaration" + }, + { + token : ["punctuation.instruction.begin", "keyword.instruction"], + regex : "(<\\?)([-_a-zA-Z0-9]+)", next : "instruction" + }, + {token : "comment", regex : "<\\!--", next : "comment"}, + { + token : ["punctuation.doctype.begin", "meta.tag.doctype"], + regex : "(<\\!)(DOCTYPE)(?=[\\s])", next : "doctype" + }, + {include : "tag"}, + {include : "reference"} + ], + + xml_declaration : [ + {include : "attributes"}, + {include : "instruction"} + ], + + instruction : [ + {token : "punctuation.instruction.end", regex : "\\?>", next : "start"} + ], + + doctype : [ + {include : "space"}, + {include : "string"}, + {token : "punctuation.doctype.end", regex : ">", next : "start"}, + {token : "xml-pe", regex : "[-_a-zA-Z0-9:]+"}, + {token : "punctuation.begin", regex : "\\[", push : "declarations"} + ], + + declarations : [{ + token : "text", + regex : "\\s+" + }, { + token: "punctuation.end", + regex: "]", + next: "pop" + }, { + token : ["punctuation.begin", "keyword"], + regex : "(<\\!)([-_a-zA-Z0-9]+)", + push : [{ + token : "text", + regex : "\\s+" + }, + { + token : "punctuation.end", + regex : ">", + next : "pop" + }, + {include : "string"}] + }], + + cdata : [ + {token : "string.end", regex : "\\]\\]>", next : "start"}, + {token : "text", regex : "\\s+"}, + {token : "text", regex : "(?:[^\\]]|\\](?!\\]>))+"} + ], + + comment : [ + {token : "comment", regex : "-->", next : "start"}, + {defaultToken : "comment"} + ], + + tag : [{ + token : ["meta.tag.punctuation.begin", "meta.tag.name"], + regex : "(<)((?:[-_a-zA-Z0-9]+:)?[-_a-zA-Z0-9]+)", + next: [ + {include : "attributes"}, + {token : "meta.tag.punctuation.end", regex : "/?>", next : "start"} + ] + }, { + token : ["meta.tag.punctuation.begin", "meta.tag.name"], + regex : "(", next : "start"} + ] + }], + + space : [ + {token : "text", regex : "\\s+"} + ], + + reference : [{ + token : "constant.language.escape", + regex : "(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)" + }, { + token : "invalid.illegal", regex : "&" + }], + + string: [{ + token : "string", + regex : "'", + push : "qstring_inner" + }, { + token : "string", + regex : '"', + push : "qqstring_inner" + }], + + qstring_inner: [ + {token : "string", regex: "'", next: "pop"}, + {include : "reference"}, + {defaultToken : "string"} + ], + + qqstring_inner: [ + {token : "string", regex: '"', next: "pop"}, + {include : "reference"}, + {defaultToken : "string"} + ], + + attributes: [{ + token : "entity.other.attribute-name", + regex : "(?:[-_a-zA-Z0-9]+:)?[-_a-zA-Z0-9]+" + }, { + token : "keyword.operator.separator", + regex : "=" + }, { + include : "space" + }, { + include : "string" + }] + }; + + if (this.constructor === XmlHighlightRules) + this.normalizeRules(); +}; + + +(function() { + + this.embedTagRules = function(HighlightRules, prefix, tag){ + this.$rules.tag.unshift({ + token : ["meta.tag.punctuation.begin", "meta.tag.name." + tag], + regex : "(<)(" + tag + ")", + next: [ + {include : "space"}, + {include : "attributes"}, + {token : "meta.tag.punctuation.end", regex : "/?>", next : prefix + "start"} + ] + }); + + this.$rules[tag + "-end"] = [ + {include : "space"}, + {token : "meta.tag.punctuation.end", regex : ">", next: "start", + onMatch : function(value, currentState, stack) { + stack.splice(0); + return this.token; + }} + ] + + this.embedRules(HighlightRules, prefix, [{ + token: ["meta.tag.punctuation.begin", "meta.tag.name." + tag], + regex : "(" + }]); + }; + +}).call(TextHighlightRules.prototype); + +oop.inherits(XmlHighlightRules, TextHighlightRules); + +exports.XmlHighlightRules = XmlHighlightRules; +}); + +ace.define('ace/mode/xml_util', ['require', 'exports', 'module' ], function(require, exports, module) { + + +function string(state) { + return [{ + token : "string", + regex : '"', + next : state + "_qqstring" + }, { + token : "string", + regex : "'", + next : state + "_qstring" + }]; +} + +function multiLineString(quote, state) { + return [ + {token : "string", regex : quote, next : state}, + { + token : "constant.language.escape", + regex : "(?:&#[0-9]+;)|(?:&#x[0-9a-fA-F]+;)|(?:&[a-zA-Z0-9_:\\.-]+;)" + }, + {defaultToken : "string"} + ]; +} + +exports.tag = function(states, name, nextState, tagMap) { + states[name] = [{ + token : "text", + regex : "\\s+" + }, { + + token : !tagMap ? "meta.tag.tag-name" : function(value) { + if (tagMap[value]) + return "meta.tag.tag-name." + tagMap[value]; + else + return "meta.tag.tag-name"; + }, + regex : "[-_a-zA-Z0-9:]+", + next : name + "_embed_attribute_list" + }, { + token: "empty", + regex: "", + next : name + "_embed_attribute_list" + }]; + + states[name + "_qstring"] = multiLineString("'", name + "_embed_attribute_list"); + states[name + "_qqstring"] = multiLineString("\"", name + "_embed_attribute_list"); + + states[name + "_embed_attribute_list"] = [{ + token : "meta.tag.r", + regex : "/?>", + next : nextState + }, { + token : "keyword.operator", + regex : "=" + }, { + token : "entity.other.attribute-name", + regex : "[-_a-zA-Z0-9:]+" + }, { + token : "constant.numeric", // float + regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b" + }, { + token : "text", + regex : "\\s+" + }].concat(string(name)); +}; + +}); + +ace.define('ace/mode/behaviour/html', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/behaviour/xml', 'ace/mode/behaviour/cstyle', 'ace/token_iterator'], function(require, exports, module) { + + +var oop = require("../../lib/oop"); +var XmlBehaviour = require("../behaviour/xml").XmlBehaviour; +var CstyleBehaviour = require("./cstyle").CstyleBehaviour; +var TokenIterator = require("../../token_iterator").TokenIterator; +var voidElements = ['area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr']; + +function hasType(token, type) { + var tokenTypes = token.type.split('.'); + return type.split('.').every(function(type){ + return (tokenTypes.indexOf(type) !== -1); + }); + return hasType; +} + +var HtmlBehaviour = function () { + + this.inherit(XmlBehaviour); // Get xml behaviour + + this.add("autoclosing", "insertion", function (state, action, editor, session, text) { + if (text == '>') { + var position = editor.getCursorPosition(); + var iterator = new TokenIterator(session, position.row, position.column); + var token = iterator.getCurrentToken(); + + if (token && hasType(token, 'string') && iterator.getCurrentTokenColumn() + token.value.length > position.column) + return; + var atCursor = false; + if (!token || !hasType(token, 'meta.tag') && !(hasType(token, 'text') && token.value.match('/'))){ + do { + token = iterator.stepBackward(); + } while (token && (hasType(token, 'string') || hasType(token, 'keyword.operator') || hasType(token, 'entity.attribute-name') || hasType(token, 'text'))); + } else { + atCursor = true; + } + if (!token || !hasType(token, 'meta.tag.name') || iterator.stepBackward().value.match('/')) { + return; + } + var element = token.value; + if (atCursor){ + var element = element.substring(0, position.column - token.start); + } + if (voidElements.indexOf(element) !== -1){ + return; + } + return { + text: '>' + '', + selection: [1, 1] + } + } + }); +} +oop.inherits(HtmlBehaviour, XmlBehaviour); + +exports.HtmlBehaviour = HtmlBehaviour; +}); + +ace.define('ace/mode/behaviour/xml', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/mode/behaviour', 'ace/mode/behaviour/cstyle', 'ace/token_iterator'], function(require, exports, module) { + + +var oop = require("../../lib/oop"); +var Behaviour = require("../behaviour").Behaviour; +var CstyleBehaviour = require("./cstyle").CstyleBehaviour; +var TokenIterator = require("../../token_iterator").TokenIterator; + +function hasType(token, type) { + var tokenTypes = token.type.split('.'); + return type.split('.').every(function(type){ + return (tokenTypes.indexOf(type) !== -1); + }); + return hasType; +} + +var XmlBehaviour = function () { + + this.inherit(CstyleBehaviour, ["string_dquotes"]); // Get string behaviour + + this.add("autoclosing", "insertion", function (state, action, editor, session, text) { + if (text == '>') { + var position = editor.getCursorPosition(); + var iterator = new TokenIterator(session, position.row, position.column); + var token = iterator.getCurrentToken(); + + if (token && hasType(token, 'string') && iterator.getCurrentTokenColumn() + token.value.length > position.column) + return; + var atCursor = false; + if (!token || !hasType(token, 'meta.tag') && !(hasType(token, 'text') && token.value.match('/'))){ + do { + token = iterator.stepBackward(); + } while (token && (hasType(token, 'string') || hasType(token, 'keyword.operator') || hasType(token, 'entity.attribute-name') || hasType(token, 'text'))); + } else { + atCursor = true; + } + if (!token || !hasType(token, 'meta.tag.name') || iterator.stepBackward().value.match('/')) { + return; + } + var tag = token.value; + if (atCursor){ + var tag = tag.substring(0, position.column - token.start); + } + + return { + text: '>' + '', + selection: [1, 1] + } + } + }); + + this.add('autoindent', 'insertion', function (state, action, editor, session, text) { + if (text == "\n") { + var cursor = editor.getCursorPosition(); + var line = session.getLine(cursor.row); + var rightChars = line.substring(cursor.column, cursor.column + 2); + if (rightChars == '?)/; + this._parseTag = function(tag) { + + var match = tag.match(this.tagRe); + var column = 0; + + return { + value: tag, + match: match ? match[2] : "", + closing: match ? !!match[3] : false, + selfClosing: match ? !!match[5] || match[2] == "/>" : false, + tagName: match ? match[4] : "", + column: match[1] ? column + match[1].length : column + }; + }; + this._readTagForward = function(iterator) { + var token = iterator.getCurrentToken(); + if (!token) + return null; + + var value = ""; + var start; + + do { + if (token.type.lastIndexOf("meta.tag", 0) === 0) { + if (!start) { + var start = { + row: iterator.getCurrentTokenRow(), + column: iterator.getCurrentTokenColumn() + }; + } + value += token.value; + if (value.indexOf(">") !== -1) { + var tag = this._parseTag(value); + tag.start = start; + tag.end = { + row: iterator.getCurrentTokenRow(), + column: iterator.getCurrentTokenColumn() + token.value.length + }; + iterator.stepForward(); + return tag; + } + } + } while(token = iterator.stepForward()); + + return null; + }; + + this._readTagBackward = function(iterator) { + var token = iterator.getCurrentToken(); + if (!token) + return null; + + var value = ""; + var end; + + do { + if (token.type.lastIndexOf("meta.tag", 0) === 0) { + if (!end) { + end = { + row: iterator.getCurrentTokenRow(), + column: iterator.getCurrentTokenColumn() + token.value.length + }; + } + value = token.value + value; + if (value.indexOf("<") !== -1) { + var tag = this._parseTag(value); + tag.end = end; + tag.start = { + row: iterator.getCurrentTokenRow(), + column: iterator.getCurrentTokenColumn() + }; + iterator.stepBackward(); + return tag; + } + } + } while(token = iterator.stepBackward()); + + return null; + }; + + this._pop = function(stack, tag) { + while (stack.length) { + + var top = stack[stack.length-1]; + if (!tag || top.tagName == tag.tagName) { + return stack.pop(); + } + else if (this.voidElements[tag.tagName]) { + return; + } + else if (this.voidElements[top.tagName]) { + stack.pop(); + continue; + } else { + return null; + } + } + }; + + this.getFoldWidgetRange = function(session, foldStyle, row) { + var firstTag = this._getFirstTagInLine(session, row); + + if (!firstTag.match) + return null; + + var isBackward = firstTag.closing || firstTag.selfClosing; + var stack = []; + var tag; + + if (!isBackward) { + var iterator = new TokenIterator(session, row, firstTag.column); + var start = { + row: row, + column: firstTag.column + firstTag.tagName.length + 2 + }; + while (tag = this._readTagForward(iterator)) { + if (tag.selfClosing) { + if (!stack.length) { + tag.start.column += tag.tagName.length + 2; + tag.end.column -= 2; + return Range.fromPoints(tag.start, tag.end); + } else + continue; + } + + if (tag.closing) { + this._pop(stack, tag); + if (stack.length == 0) + return Range.fromPoints(start, tag.start); + } + else { + stack.push(tag) + } + } + } + else { + var iterator = new TokenIterator(session, row, firstTag.column + firstTag.match.length); + var end = { + row: row, + column: firstTag.column + }; + + while (tag = this._readTagBackward(iterator)) { + if (tag.selfClosing) { + if (!stack.length) { + tag.start.column += tag.tagName.length + 2; + tag.end.column -= 2; + return Range.fromPoints(tag.start, tag.end); + } else + continue; + } + + if (!tag.closing) { + this._pop(stack, tag); + if (stack.length == 0) { + tag.start.column += tag.tagName.length + 2; + return Range.fromPoints(tag.start, end); + } + } + else { + stack.push(tag) + } + } + } + + }; + +}).call(FoldMode.prototype); + +}); + +ace.define('ace/mode/html_completions', ['require', 'exports', 'module' , 'ace/token_iterator'], function(require, exports, module) { + + +var TokenIterator = require("../token_iterator").TokenIterator; + +var commonAttributes = [ + "accesskey", + "class", + "contenteditable", + "contextmenu", + "dir", + "draggable", + "dropzone", + "hidden", + "id", + "lang", + "spellcheck", + "style", + "tabindex", + "title", + "translate" +]; + +var eventAttributes = [ + "onabort", + "onblur", + "oncancel", + "oncanplay", + "oncanplaythrough", + "onchange", + "onclick", + "onclose", + "oncontextmenu", + "oncuechange", + "ondblclick", + "ondrag", + "ondragend", + "ondragenter", + "ondragleave", + "ondragover", + "ondragstart", + "ondrop", + "ondurationchange", + "onemptied", + "onended", + "onerror", + "onfocus", + "oninput", + "oninvalid", + "onkeydown", + "onkeypress", + "onkeyup", + "onload", + "onloadeddata", + "onloadedmetadata", + "onloadstart", + "onmousedown", + "onmousemove", + "onmouseout", + "onmouseover", + "onmouseup", + "onmousewheel", + "onpause", + "onplay", + "onplaying", + "onprogress", + "onratechange", + "onreset", + "onscroll", + "onseeked", + "onseeking", + "onselect", + "onshow", + "onstalled", + "onsubmit", + "onsuspend", + "ontimeupdate", + "onvolumechange", + "onwaiting" +]; + +var globalAttributes = commonAttributes.concat(eventAttributes); + +var attributeMap = { + "html": ["manifest"], + "head": [], + "title": [], + "base": ["href", "target"], + "link": ["href", "hreflang", "rel", "media", "type", "sizes"], + "meta": ["http-equiv", "name", "content", "charset"], + "style": ["type", "media", "scoped"], + "script": ["charset", "type", "src", "defer", "async"], + "noscript": ["href"], + "body": ["onafterprint", "onbeforeprint", "onbeforeunload", "onhashchange", "onmessage", "onoffline", "onpopstate", "onredo", "onresize", "onstorage", "onundo", "onunload"], + "section": [], + "nav": [], + "article": ["pubdate"], + "aside": [], + "h1": [], + "h2": [], + "h3": [], + "h4": [], + "h5": [], + "h6": [], + "header": [], + "footer": [], + "address": [], + "main": [], + "p": [], + "hr": [], + "pre": [], + "blockquote": ["cite"], + "ol": ["start", "reversed"], + "ul": [], + "li": ["value"], + "dl": [], + "dt": [], + "dd": [], + "figure": [], + "figcaption": [], + "div": [], + "a": ["href", "target", "ping", "rel", "media", "hreflang", "type"], + "em": [], + "strong": [], + "small": [], + "s": [], + "cite": [], + "q": ["cite"], + "dfn": [], + "abbr": [], + "data": [], + "time": ["datetime"], + "code": [], + "var": [], + "samp": [], + "kbd": [], + "sub": [], + "sup": [], + "i": [], + "b": [], + "u": [], + "mark": [], + "ruby": [], + "rt": [], + "rp": [], + "bdi": [], + "bdo": [], + "span": [], + "br": [], + "wbr": [], + "ins": ["cite", "datetime"], + "del": ["cite", "datetime"], + "img": ["alt", "src", "height", "width", "usemap", "ismap"], + "iframe": ["name", "src", "height", "width", "sandbox", "seamless"], + "embed": ["src", "height", "width", "type"], + "object": ["param", "data", "type", "height" , "width", "usemap", "name", "form", "classid"], + "param": ["name", "value"], + "video": ["src", "autobuffer", "autoplay", "loop", "controls", "width", "height", "poster"], + "audio": ["src", "autobuffer", "autoplay", "loop", "controls"], + "source": ["src", "type", "media"], + "track": ["kind", "src", "srclang", "label", "default"], + "canvas": ["width", "height"], + "map": ["name"], + "area": ["shape", "coords", "href", "hreflang", "alt", "target", "media", "rel", "ping", "type"], + "svg": [], + "math": [], + "table": ["summary"], + "caption": [], + "colgroup": ["span"], + "col": ["span"], + "tbody": [], + "thead": [], + "tfoot": [], + "tr": [], + "td": ["headers", "rowspan", "colspan"], + "th": ["headers", "rowspan", "colspan", "scope"], + "form": ["accept-charset", "action", "autocomplete", "enctype", "method", "name", "novalidate", "target"], + "fieldset": ["disabled", "form", "name"], + "legend": [], + "label": ["form", "for"], + "input": ["type", "accept", "alt", "autocomplete", "checked", "disabled", "form", "formaction", "formenctype", "formmethod", "formnovalidate", "formtarget", "height", "list", "max", "maxlength", "min", "multiple", "pattern", "placeholder", "readonly", "required", "size", "src", "step", "width", "files", "value"], + "button": ["autofocus", "disabled", "form", "formaction", "formenctype", "formmethod", "formnovalidate", "formtarget", "name", "value", "type"], + "select": ["autofocus", "disabled", "form", "multiple", "name", "size"], + "datalist": [], + "optgroup": ["disabled", "label"], + "option": ["disabled", "selected", "label", "value"], + "textarea": ["autofocus", "disabled", "form", "maxlength", "name", "placeholder", "readonly", "required", "rows", "cols", "wrap"], + "keygen": ["autofocus", "challenge", "disabled", "form", "keytype", "name"], + "output": ["for", "form", "name"], + "progress": ["value", "max"], + "meter": ["value", "min", "max", "low", "high", "optimum"], + "details": ["open"], + "summary": [], + "command": ["type", "label", "icon", "disabled", "checked", "radiogroup", "command"], + "menu": ["type", "label"], + "dialog": ["open"] +}; + +var allElements = Object.keys(attributeMap); + +function hasType(token, type) { + var tokenTypes = token.type.split('.'); + return type.split('.').every(function(type){ + return (tokenTypes.indexOf(type) !== -1); + }); +} + +function findTagName(session, pos) { + var iterator = new TokenIterator(session, pos.row, pos.column); + var token = iterator.getCurrentToken(); + if (!token || !hasType(token, 'tag') && !(hasType(token, 'text') && token.value.match('/'))){ + do { + token = iterator.stepBackward(); + } while (token && (hasType(token, 'string') || hasType(token, 'operator') || hasType(token, 'attribute-name') || hasType(token, 'text'))); + } + if (token && hasType(token, 'tag-name') && !iterator.stepBackward().value.match('/')) + return token.value; +} + +var HtmlCompletions = function() { + +}; + +(function() { + + this.getCompletions = function(state, session, pos, prefix) { + var token = session.getTokenAt(pos.row, pos.column); + + if (!token) + return []; + if (hasType(token, "tag-name") || (token.value == '<' && hasType(token, "text"))) + return this.getTagCompletions(state, session, pos, prefix); + if (hasType(token, 'text') || hasType(token, 'attribute-name')) + return this.getAttributeCompetions(state, session, pos, prefix); + + return []; + }; + + this.getTagCompletions = function(state, session, pos, prefix) { + var elements = allElements; + if (prefix) { + elements = elements.filter(function(element){ + return element.indexOf(prefix) === 0; + }); + } + return elements.map(function(element){ + return { + value: element, + meta: "tag" + }; + }); + }; + + this.getAttributeCompetions = function(state, session, pos, prefix) { + var tagName = findTagName(session, pos); + if (!tagName) + return []; + var attributes = globalAttributes; + if (tagName in attributeMap) { + attributes = attributes.concat(attributeMap[tagName]); + } + if (prefix) { + attributes = attributes.filter(function(attribute){ + return attribute.indexOf(prefix) === 0; + }); + } + return attributes.map(function(attribute){ + return { + caption: attribute, + snippet: attribute + '="$0"', + meta: "attribute" + }; + }); + }; + +}).call(HtmlCompletions.prototype); + +exports.HtmlCompletions = HtmlCompletions; +}); diff --git a/external/ace.js/worker-css.js b/external/ace.js/worker-css.js new file mode 100644 index 0000000..a7a647e --- /dev/null +++ b/external/ace.js/worker-css.js @@ -0,0 +1,8245 @@ +"no use strict"; +;(function(window) { +if (typeof window.window != "undefined" && window.document) { + return; +} + +window.console = function() { + var msgs = Array.prototype.slice.call(arguments, 0); + postMessage({type: "log", data: msgs}); +}; +window.console.error = +window.console.warn = +window.console.log = +window.console.trace = window.console; + +window.window = window; +window.ace = window; + +window.normalizeModule = function(parentId, moduleName) { + if (moduleName.indexOf("!") !== -1) { + var chunks = moduleName.split("!"); + return normalizeModule(parentId, chunks[0]) + "!" + normalizeModule(parentId, chunks[1]); + } + if (moduleName.charAt(0) == ".") { + var base = parentId.split("/").slice(0, -1).join("/"); + moduleName = base + "/" + moduleName; + + while(moduleName.indexOf(".") !== -1 && previous != moduleName) { + var previous = moduleName; + moduleName = moduleName.replace(/\/\.\//, "/").replace(/[^\/]+\/\.\.\//, ""); + } + } + + return moduleName; +}; + +window.require = function(parentId, id) { + if (!id) { + id = parentId + parentId = null; + } + if (!id.charAt) + throw new Error("worker.js require() accepts only (parentId, id) as arguments"); + + id = normalizeModule(parentId, id); + + var module = require.modules[id]; + if (module) { + if (!module.initialized) { + module.initialized = true; + module.exports = module.factory().exports; + } + return module.exports; + } + + var chunks = id.split("/"); + if (!require.tlns) + return console.log("unable to load " + id); + chunks[0] = require.tlns[chunks[0]] || chunks[0]; + var path = chunks.join("/") + ".js"; + + require.id = id; + importScripts(path); + return require(parentId, id); +}; + +require.modules = {}; +require.tlns = {}; + +window.define = function(id, deps, factory) { + if (arguments.length == 2) { + factory = deps; + if (typeof id != "string") { + deps = id; + id = require.id; + } + } else if (arguments.length == 1) { + factory = id; + id = require.id; + } + + if (id.indexOf("text!") === 0) + return; + + var req = function(deps, factory) { + return require(id, deps, factory); + }; + + require.modules[id] = { + exports: {}, + factory: function() { + var module = this; + var returnExports = factory(req, module.exports, module); + if (returnExports) + module.exports = returnExports; + return module; + } + }; +}; + +window.initBaseUrls = function initBaseUrls(topLevelNamespaces) { + require.tlns = topLevelNamespaces; +} + +window.initSender = function initSender() { + + var EventEmitter = require("ace/lib/event_emitter").EventEmitter; + var oop = require("ace/lib/oop"); + + var Sender = function() {}; + + (function() { + + oop.implement(this, EventEmitter); + + this.callback = function(data, callbackId) { + postMessage({ + type: "call", + id: callbackId, + data: data + }); + }; + + this.emit = function(name, data) { + postMessage({ + type: "event", + name: name, + data: data + }); + }; + + }).call(Sender.prototype); + + return new Sender(); +} + +window.main = null; +window.sender = null; + +window.onmessage = function(e) { + var msg = e.data; + if (msg.command) { + if (main[msg.command]) + main[msg.command].apply(main, msg.args); + else + throw new Error("Unknown command:" + msg.command); + } + else if (msg.init) { + initBaseUrls(msg.tlns); + require("ace/lib/es5-shim"); + sender = initSender(); + var clazz = require(msg.module)[msg.classname]; + main = new clazz(sender); + } + else if (msg.event && sender) { + sender._emit(msg.event, msg.data); + } +}; +})(this); + +ace.define('ace/lib/event_emitter', ['require', 'exports', 'module' ], function(require, exports, module) { + + +var EventEmitter = {}; +var stopPropagation = function() { this.propagationStopped = true; }; +var preventDefault = function() { this.defaultPrevented = true; }; + +EventEmitter._emit = +EventEmitter._dispatchEvent = function(eventName, e) { + this._eventRegistry || (this._eventRegistry = {}); + this._defaultHandlers || (this._defaultHandlers = {}); + + var listeners = this._eventRegistry[eventName] || []; + var defaultHandler = this._defaultHandlers[eventName]; + if (!listeners.length && !defaultHandler) + return; + + if (typeof e != "object" || !e) + e = {}; + + if (!e.type) + e.type = eventName; + if (!e.stopPropagation) + e.stopPropagation = stopPropagation; + if (!e.preventDefault) + e.preventDefault = preventDefault; + + listeners = listeners.slice(); + for (var i=0; i 0) { + if (pos > length) + pos = length; + } else if (pos == void 0) { + pos = 0; + } else if (pos < 0) { + pos = Math.max(length + pos, 0); + } + + if (!(pos+removeCount < length)) + removeCount = length - pos; + + var removed = this.slice(pos, pos+removeCount); + var insert = slice.call(arguments, 2); + var add = insert.length; + if (pos === length) { + if (add) { + this.push.apply(this, insert); + } + } else { + var remove = Math.min(removeCount, length - pos); + var tailOldPos = pos + remove; + var tailNewPos = tailOldPos + add - remove; + var tailCount = length - tailOldPos; + var lengthAfterRemove = length - remove; + + if (tailNewPos < tailOldPos) { // case A + for (var i = 0; i < tailCount; ++i) { + this[tailNewPos+i] = this[tailOldPos+i]; + } + } else if (tailNewPos > tailOldPos) { // case B + for (i = tailCount; i--; ) { + this[tailNewPos+i] = this[tailOldPos+i]; + } + } // else, add == remove (nothing to do) + + if (add && pos === lengthAfterRemove) { + this.length = lengthAfterRemove; // truncate array + this.push.apply(this, insert); + } else { + this.length = lengthAfterRemove + add; // reserves space + for (i = 0; i < add; ++i) { + this[pos+i] = insert[i]; + } + } + } + return removed; + }; + } +} +if (!Array.isArray) { + Array.isArray = function isArray(obj) { + return _toString(obj) == "[object Array]"; + }; +} +var boxedString = Object("a"), + splitString = boxedString[0] != "a" || !(0 in boxedString); + +if (!Array.prototype.forEach) { + Array.prototype.forEach = function forEach(fun /*, thisp*/) { + var object = toObject(this), + self = splitString && _toString(this) == "[object String]" ? + this.split("") : + object, + thisp = arguments[1], + i = -1, + length = self.length >>> 0; + if (_toString(fun) != "[object Function]") { + throw new TypeError(); // TODO message + } + + while (++i < length) { + if (i in self) { + fun.call(thisp, self[i], i, object); + } + } + }; +} +if (!Array.prototype.map) { + Array.prototype.map = function map(fun /*, thisp*/) { + var object = toObject(this), + self = splitString && _toString(this) == "[object String]" ? + this.split("") : + object, + length = self.length >>> 0, + result = Array(length), + thisp = arguments[1]; + if (_toString(fun) != "[object Function]") { + throw new TypeError(fun + " is not a function"); + } + + for (var i = 0; i < length; i++) { + if (i in self) + result[i] = fun.call(thisp, self[i], i, object); + } + return result; + }; +} +if (!Array.prototype.filter) { + Array.prototype.filter = function filter(fun /*, thisp */) { + var object = toObject(this), + self = splitString && _toString(this) == "[object String]" ? + this.split("") : + object, + length = self.length >>> 0, + result = [], + value, + thisp = arguments[1]; + if (_toString(fun) != "[object Function]") { + throw new TypeError(fun + " is not a function"); + } + + for (var i = 0; i < length; i++) { + if (i in self) { + value = self[i]; + if (fun.call(thisp, value, i, object)) { + result.push(value); + } + } + } + return result; + }; +} +if (!Array.prototype.every) { + Array.prototype.every = function every(fun /*, thisp */) { + var object = toObject(this), + self = splitString && _toString(this) == "[object String]" ? + this.split("") : + object, + length = self.length >>> 0, + thisp = arguments[1]; + if (_toString(fun) != "[object Function]") { + throw new TypeError(fun + " is not a function"); + } + + for (var i = 0; i < length; i++) { + if (i in self && !fun.call(thisp, self[i], i, object)) { + return false; + } + } + return true; + }; +} +if (!Array.prototype.some) { + Array.prototype.some = function some(fun /*, thisp */) { + var object = toObject(this), + self = splitString && _toString(this) == "[object String]" ? + this.split("") : + object, + length = self.length >>> 0, + thisp = arguments[1]; + if (_toString(fun) != "[object Function]") { + throw new TypeError(fun + " is not a function"); + } + + for (var i = 0; i < length; i++) { + if (i in self && fun.call(thisp, self[i], i, object)) { + return true; + } + } + return false; + }; +} +if (!Array.prototype.reduce) { + Array.prototype.reduce = function reduce(fun /*, initial*/) { + var object = toObject(this), + self = splitString && _toString(this) == "[object String]" ? + this.split("") : + object, + length = self.length >>> 0; + if (_toString(fun) != "[object Function]") { + throw new TypeError(fun + " is not a function"); + } + if (!length && arguments.length == 1) { + throw new TypeError("reduce of empty array with no initial value"); + } + + var i = 0; + var result; + if (arguments.length >= 2) { + result = arguments[1]; + } else { + do { + if (i in self) { + result = self[i++]; + break; + } + if (++i >= length) { + throw new TypeError("reduce of empty array with no initial value"); + } + } while (true); + } + + for (; i < length; i++) { + if (i in self) { + result = fun.call(void 0, result, self[i], i, object); + } + } + + return result; + }; +} +if (!Array.prototype.reduceRight) { + Array.prototype.reduceRight = function reduceRight(fun /*, initial*/) { + var object = toObject(this), + self = splitString && _toString(this) == "[object String]" ? + this.split("") : + object, + length = self.length >>> 0; + if (_toString(fun) != "[object Function]") { + throw new TypeError(fun + " is not a function"); + } + if (!length && arguments.length == 1) { + throw new TypeError("reduceRight of empty array with no initial value"); + } + + var result, i = length - 1; + if (arguments.length >= 2) { + result = arguments[1]; + } else { + do { + if (i in self) { + result = self[i--]; + break; + } + if (--i < 0) { + throw new TypeError("reduceRight of empty array with no initial value"); + } + } while (true); + } + + do { + if (i in this) { + result = fun.call(void 0, result, self[i], i, object); + } + } while (i--); + + return result; + }; +} +if (!Array.prototype.indexOf || ([0, 1].indexOf(1, 2) != -1)) { + Array.prototype.indexOf = function indexOf(sought /*, fromIndex */ ) { + var self = splitString && _toString(this) == "[object String]" ? + this.split("") : + toObject(this), + length = self.length >>> 0; + + if (!length) { + return -1; + } + + var i = 0; + if (arguments.length > 1) { + i = toInteger(arguments[1]); + } + i = i >= 0 ? i : Math.max(0, length + i); + for (; i < length; i++) { + if (i in self && self[i] === sought) { + return i; + } + } + return -1; + }; +} +if (!Array.prototype.lastIndexOf || ([0, 1].lastIndexOf(0, -3) != -1)) { + Array.prototype.lastIndexOf = function lastIndexOf(sought /*, fromIndex */) { + var self = splitString && _toString(this) == "[object String]" ? + this.split("") : + toObject(this), + length = self.length >>> 0; + + if (!length) { + return -1; + } + var i = length - 1; + if (arguments.length > 1) { + i = Math.min(i, toInteger(arguments[1])); + } + i = i >= 0 ? i : length - Math.abs(i); + for (; i >= 0; i--) { + if (i in self && sought === self[i]) { + return i; + } + } + return -1; + }; +} +if (!Object.getPrototypeOf) { + Object.getPrototypeOf = function getPrototypeOf(object) { + return object.__proto__ || ( + object.constructor ? + object.constructor.prototype : + prototypeOfObject + ); + }; +} +if (!Object.getOwnPropertyDescriptor) { + var ERR_NON_OBJECT = "Object.getOwnPropertyDescriptor called on a " + + "non-object: "; + Object.getOwnPropertyDescriptor = function getOwnPropertyDescriptor(object, property) { + if ((typeof object != "object" && typeof object != "function") || object === null) + throw new TypeError(ERR_NON_OBJECT + object); + if (!owns(object, property)) + return; + + var descriptor, getter, setter; + descriptor = { enumerable: true, configurable: true }; + if (supportsAccessors) { + var prototype = object.__proto__; + object.__proto__ = prototypeOfObject; + + var getter = lookupGetter(object, property); + var setter = lookupSetter(object, property); + object.__proto__ = prototype; + + if (getter || setter) { + if (getter) descriptor.get = getter; + if (setter) descriptor.set = setter; + return descriptor; + } + } + descriptor.value = object[property]; + return descriptor; + }; +} +if (!Object.getOwnPropertyNames) { + Object.getOwnPropertyNames = function getOwnPropertyNames(object) { + return Object.keys(object); + }; +} +if (!Object.create) { + var createEmpty; + if (Object.prototype.__proto__ === null) { + createEmpty = function () { + return { "__proto__": null }; + }; + } else { + createEmpty = function () { + var empty = {}; + for (var i in empty) + empty[i] = null; + empty.constructor = + empty.hasOwnProperty = + empty.propertyIsEnumerable = + empty.isPrototypeOf = + empty.toLocaleString = + empty.toString = + empty.valueOf = + empty.__proto__ = null; + return empty; + } + } + + Object.create = function create(prototype, properties) { + var object; + if (prototype === null) { + object = createEmpty(); + } else { + if (typeof prototype != "object") + throw new TypeError("typeof prototype["+(typeof prototype)+"] != 'object'"); + var Type = function () {}; + Type.prototype = prototype; + object = new Type(); + object.__proto__ = prototype; + } + if (properties !== void 0) + Object.defineProperties(object, properties); + return object; + }; +} + +function doesDefinePropertyWork(object) { + try { + Object.defineProperty(object, "sentinel", {}); + return "sentinel" in object; + } catch (exception) { + } +} +if (Object.defineProperty) { + var definePropertyWorksOnObject = doesDefinePropertyWork({}); + var definePropertyWorksOnDom = typeof document == "undefined" || + doesDefinePropertyWork(document.createElement("div")); + if (!definePropertyWorksOnObject || !definePropertyWorksOnDom) { + var definePropertyFallback = Object.defineProperty; + } +} + +if (!Object.defineProperty || definePropertyFallback) { + var ERR_NON_OBJECT_DESCRIPTOR = "Property description must be an object: "; + var ERR_NON_OBJECT_TARGET = "Object.defineProperty called on non-object: " + var ERR_ACCESSORS_NOT_SUPPORTED = "getters & setters can not be defined " + + "on this javascript engine"; + + Object.defineProperty = function defineProperty(object, property, descriptor) { + if ((typeof object != "object" && typeof object != "function") || object === null) + throw new TypeError(ERR_NON_OBJECT_TARGET + object); + if ((typeof descriptor != "object" && typeof descriptor != "function") || descriptor === null) + throw new TypeError(ERR_NON_OBJECT_DESCRIPTOR + descriptor); + if (definePropertyFallback) { + try { + return definePropertyFallback.call(Object, object, property, descriptor); + } catch (exception) { + } + } + if (owns(descriptor, "value")) { + + if (supportsAccessors && (lookupGetter(object, property) || + lookupSetter(object, property))) + { + var prototype = object.__proto__; + object.__proto__ = prototypeOfObject; + delete object[property]; + object[property] = descriptor.value; + object.__proto__ = prototype; + } else { + object[property] = descriptor.value; + } + } else { + if (!supportsAccessors) + throw new TypeError(ERR_ACCESSORS_NOT_SUPPORTED); + if (owns(descriptor, "get")) + defineGetter(object, property, descriptor.get); + if (owns(descriptor, "set")) + defineSetter(object, property, descriptor.set); + } + + return object; + }; +} +if (!Object.defineProperties) { + Object.defineProperties = function defineProperties(object, properties) { + for (var property in properties) { + if (owns(properties, property)) + Object.defineProperty(object, property, properties[property]); + } + return object; + }; +} +if (!Object.seal) { + Object.seal = function seal(object) { + return object; + }; +} +if (!Object.freeze) { + Object.freeze = function freeze(object) { + return object; + }; +} +try { + Object.freeze(function () {}); +} catch (exception) { + Object.freeze = (function freeze(freezeObject) { + return function freeze(object) { + if (typeof object == "function") { + return object; + } else { + return freezeObject(object); + } + }; + })(Object.freeze); +} +if (!Object.preventExtensions) { + Object.preventExtensions = function preventExtensions(object) { + return object; + }; +} +if (!Object.isSealed) { + Object.isSealed = function isSealed(object) { + return false; + }; +} +if (!Object.isFrozen) { + Object.isFrozen = function isFrozen(object) { + return false; + }; +} +if (!Object.isExtensible) { + Object.isExtensible = function isExtensible(object) { + if (Object(object) === object) { + throw new TypeError(); // TODO message + } + var name = ''; + while (owns(object, name)) { + name += '?'; + } + object[name] = true; + var returnValue = owns(object, name); + delete object[name]; + return returnValue; + }; +} +if (!Object.keys) { + var hasDontEnumBug = true, + dontEnums = [ + "toString", + "toLocaleString", + "valueOf", + "hasOwnProperty", + "isPrototypeOf", + "propertyIsEnumerable", + "constructor" + ], + dontEnumsLength = dontEnums.length; + + for (var key in {"toString": null}) { + hasDontEnumBug = false; + } + + Object.keys = function keys(object) { + + if ( + (typeof object != "object" && typeof object != "function") || + object === null + ) { + throw new TypeError("Object.keys called on a non-object"); + } + + var keys = []; + for (var name in object) { + if (owns(object, name)) { + keys.push(name); + } + } + + if (hasDontEnumBug) { + for (var i = 0, ii = dontEnumsLength; i < ii; i++) { + var dontEnum = dontEnums[i]; + if (owns(object, dontEnum)) { + keys.push(dontEnum); + } + } + } + return keys; + }; + +} +if (!Date.now) { + Date.now = function now() { + return new Date().getTime(); + }; +} +var ws = "\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003" + + "\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028" + + "\u2029\uFEFF"; +if (!String.prototype.trim || ws.trim()) { + ws = "[" + ws + "]"; + var trimBeginRegexp = new RegExp("^" + ws + ws + "*"), + trimEndRegexp = new RegExp(ws + ws + "*$"); + String.prototype.trim = function trim() { + return String(this).replace(trimBeginRegexp, "").replace(trimEndRegexp, ""); + }; +} + +function toInteger(n) { + n = +n; + if (n !== n) { // isNaN + n = 0; + } else if (n !== 0 && n !== (1/0) && n !== -(1/0)) { + n = (n > 0 || -1) * Math.floor(Math.abs(n)); + } + return n; +} + +function isPrimitive(input) { + var type = typeof input; + return ( + input === null || + type === "undefined" || + type === "boolean" || + type === "number" || + type === "string" + ); +} + +function toPrimitive(input) { + var val, valueOf, toString; + if (isPrimitive(input)) { + return input; + } + valueOf = input.valueOf; + if (typeof valueOf === "function") { + val = valueOf.call(input); + if (isPrimitive(val)) { + return val; + } + } + toString = input.toString; + if (typeof toString === "function") { + val = toString.call(input); + if (isPrimitive(val)) { + return val; + } + } + throw new TypeError(); +} +var toObject = function (o) { + if (o == null) { // this matches both null and undefined + throw new TypeError("can't convert "+o+" to object"); + } + return Object(o); +}; + +}); + +ace.define('ace/mode/css_worker', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/lang', 'ace/worker/mirror', 'ace/mode/css/csslint'], function(require, exports, module) { + + +var oop = require("../lib/oop"); +var lang = require("../lib/lang"); +var Mirror = require("../worker/mirror").Mirror; +var CSSLint = require("./css/csslint").CSSLint; + +var Worker = exports.Worker = function(sender) { + Mirror.call(this, sender); + this.setTimeout(400); + this.ruleset = null; + this.setDisabledRules("ids"); + this.setInfoRules("adjoining-classes|qualified-headings|zero-units|gradients|import|outline-none"); +}; + +oop.inherits(Worker, Mirror); + +(function() { + this.setInfoRules = function(ruleNames) { + if (typeof ruleNames == "string") + ruleNames = ruleNames.split("|"); + this.infoRules = lang.arrayToMap(ruleNames); + this.doc.getValue() && this.deferredUpdate.schedule(100); + }; + + this.setDisabledRules = function(ruleNames) { + if (!ruleNames) { + this.ruleset = null; + } else { + if (typeof ruleNames == "string") + ruleNames = ruleNames.split("|"); + var all = {}; + + CSSLint.getRules().forEach(function(x){ + all[x.id] = true; + }); + ruleNames.forEach(function(x) { + delete all[x]; + }); + + this.ruleset = all; + } + this.doc.getValue() && this.deferredUpdate.schedule(100); + }; + + this.onUpdate = function() { + var value = this.doc.getValue(); + var infoRules = this.infoRules; + + var result = CSSLint.verify(value, this.ruleset); + this.sender.emit("csslint", result.messages.map(function(msg) { + return { + row: msg.line - 1, + column: msg.col - 1, + text: msg.message, + type: infoRules[msg.rule.id] ? "info" : msg.type, + rule: msg.rule.name + } + })); + }; + +}).call(Worker.prototype); + +}); + +ace.define('ace/lib/lang', ['require', 'exports', 'module' ], function(require, exports, module) { + + +exports.stringReverse = function(string) { + return string.split("").reverse().join(""); +}; + +exports.stringRepeat = function (string, count) { + var result = ''; + while (count > 0) { + if (count & 1) + result += string; + + if (count >>= 1) + string += string; + } + return result; +}; + +var trimBeginRegexp = /^\s\s*/; +var trimEndRegexp = /\s\s*$/; + +exports.stringTrimLeft = function (string) { + return string.replace(trimBeginRegexp, ''); +}; + +exports.stringTrimRight = function (string) { + return string.replace(trimEndRegexp, ''); +}; + +exports.copyObject = function(obj) { + var copy = {}; + for (var key in obj) { + copy[key] = obj[key]; + } + return copy; +}; + +exports.copyArray = function(array){ + var copy = []; + for (var i=0, l=array.length; i= length) { + position.row = Math.max(0, length - 1); + position.column = this.getLine(length-1).length; + } else if (position.row < 0) + position.row = 0; + return position; + }; + this.insert = function(position, text) { + if (!text || text.length === 0) + return position; + + position = this.$clipPosition(position); + if (this.getLength() <= 1) + this.$detectNewLine(text); + + var lines = this.$split(text); + var firstLine = lines.splice(0, 1)[0]; + var lastLine = lines.length == 0 ? null : lines.splice(lines.length - 1, 1)[0]; + + position = this.insertInLine(position, firstLine); + if (lastLine !== null) { + position = this.insertNewLine(position); // terminate first line + position = this._insertLines(position.row, lines); + position = this.insertInLine(position, lastLine || ""); + } + return position; + }; + this.insertLines = function(row, lines) { + if (row >= this.getLength()) + return this.insert({row: row, column: 0}, "\n" + lines.join("\n")); + return this._insertLines(Math.max(row, 0), lines); + }; + this._insertLines = function(row, lines) { + if (lines.length == 0) + return {row: row, column: 0}; + if (lines.length > 0xFFFF) { + var end = this._insertLines(row, lines.slice(0xFFFF)); + lines = lines.slice(0, 0xFFFF); + } + + var args = [row, 0]; + args.push.apply(args, lines); + this.$lines.splice.apply(this.$lines, args); + + var range = new Range(row, 0, row + lines.length, 0); + var delta = { + action: "insertLines", + range: range, + lines: lines + }; + this._emit("change", { data: delta }); + return end || range.end; + }; + this.insertNewLine = function(position) { + position = this.$clipPosition(position); + var line = this.$lines[position.row] || ""; + + this.$lines[position.row] = line.substring(0, position.column); + this.$lines.splice(position.row + 1, 0, line.substring(position.column, line.length)); + + var end = { + row : position.row + 1, + column : 0 + }; + + var delta = { + action: "insertText", + range: Range.fromPoints(position, end), + text: this.getNewLineCharacter() + }; + this._emit("change", { data: delta }); + + return end; + }; + this.insertInLine = function(position, text) { + if (text.length == 0) + return position; + + var line = this.$lines[position.row] || ""; + + this.$lines[position.row] = line.substring(0, position.column) + text + + line.substring(position.column); + + var end = { + row : position.row, + column : position.column + text.length + }; + + var delta = { + action: "insertText", + range: Range.fromPoints(position, end), + text: text + }; + this._emit("change", { data: delta }); + + return end; + }; + this.remove = function(range) { + if (!range instanceof Range) + range = Range.fromPoints(range.start, range.end); + range.start = this.$clipPosition(range.start); + range.end = this.$clipPosition(range.end); + + if (range.isEmpty()) + return range.start; + + var firstRow = range.start.row; + var lastRow = range.end.row; + + if (range.isMultiLine()) { + var firstFullRow = range.start.column == 0 ? firstRow : firstRow + 1; + var lastFullRow = lastRow - 1; + + if (range.end.column > 0) + this.removeInLine(lastRow, 0, range.end.column); + + if (lastFullRow >= firstFullRow) + this._removeLines(firstFullRow, lastFullRow); + + if (firstFullRow != firstRow) { + this.removeInLine(firstRow, range.start.column, this.getLine(firstRow).length); + this.removeNewLine(range.start.row); + } + } + else { + this.removeInLine(firstRow, range.start.column, range.end.column); + } + return range.start; + }; + this.removeInLine = function(row, startColumn, endColumn) { + if (startColumn == endColumn) + return; + + var range = new Range(row, startColumn, row, endColumn); + var line = this.getLine(row); + var removed = line.substring(startColumn, endColumn); + var newLine = line.substring(0, startColumn) + line.substring(endColumn, line.length); + this.$lines.splice(row, 1, newLine); + + var delta = { + action: "removeText", + range: range, + text: removed + }; + this._emit("change", { data: delta }); + return range.start; + }; + this.removeLines = function(firstRow, lastRow) { + if (firstRow < 0 || lastRow >= this.getLength()) + return this.remove(new Range(firstRow, 0, lastRow + 1, 0)); + return this._removeLines(firstRow, lastRow); + }; + + this._removeLines = function(firstRow, lastRow) { + var range = new Range(firstRow, 0, lastRow + 1, 0); + var removed = this.$lines.splice(firstRow, lastRow - firstRow + 1); + + var delta = { + action: "removeLines", + range: range, + nl: this.getNewLineCharacter(), + lines: removed + }; + this._emit("change", { data: delta }); + return removed; + }; + this.removeNewLine = function(row) { + var firstLine = this.getLine(row); + var secondLine = this.getLine(row+1); + + var range = new Range(row, firstLine.length, row+1, 0); + var line = firstLine + secondLine; + + this.$lines.splice(row, 2, line); + + var delta = { + action: "removeText", + range: range, + text: this.getNewLineCharacter() + }; + this._emit("change", { data: delta }); + }; + this.replace = function(range, text) { + if (!range instanceof Range) + range = Range.fromPoints(range.start, range.end); + if (text.length == 0 && range.isEmpty()) + return range.start; + if (text == this.getTextRange(range)) + return range.end; + + this.remove(range); + if (text) { + var end = this.insert(range.start, text); + } + else { + end = range.start; + } + + return end; + }; + this.applyDeltas = function(deltas) { + for (var i=0; i=0; i--) { + var delta = deltas[i]; + + var range = Range.fromPoints(delta.range.start, delta.range.end); + + if (delta.action == "insertLines") + this._removeLines(range.start.row, range.end.row - 1); + else if (delta.action == "insertText") + this.remove(range); + else if (delta.action == "removeLines") + this._insertLines(range.start.row, delta.lines); + else if (delta.action == "removeText") + this.insert(range.start, delta.text); + } + }; + this.indexToPosition = function(index, startRow) { + var lines = this.$lines || this.getAllLines(); + var newlineLength = this.getNewLineCharacter().length; + for (var i = startRow || 0, l = lines.length; i < l; i++) { + index -= lines[i].length + newlineLength; + if (index < 0) + return {row: i, column: index + lines[i].length + newlineLength}; + } + return {row: l-1, column: lines[l-1].length}; + }; + this.positionToIndex = function(pos, startRow) { + var lines = this.$lines || this.getAllLines(); + var newlineLength = this.getNewLineCharacter().length; + var index = 0; + var row = Math.min(pos.row, lines.length); + for (var i = startRow || 0; i < row; ++i) + index += lines[i].length + newlineLength; + + return index + pos.column; + }; + +}).call(Document.prototype); + +exports.Document = Document; +}); + +ace.define('ace/range', ['require', 'exports', 'module' ], function(require, exports, module) { + +var comparePoints = function(p1, p2) { + return p1.row - p2.row || p1.column - p2.column; +}; +var Range = function(startRow, startColumn, endRow, endColumn) { + this.start = { + row: startRow, + column: startColumn + }; + + this.end = { + row: endRow, + column: endColumn + }; +}; + +(function() { + this.isEqual = function(range) { + return this.start.row === range.start.row && + this.end.row === range.end.row && + this.start.column === range.start.column && + this.end.column === range.end.column; + }; + this.toString = function() { + return ("Range: [" + this.start.row + "/" + this.start.column + + "] -> [" + this.end.row + "/" + this.end.column + "]"); + }; + + this.contains = function(row, column) { + return this.compare(row, column) == 0; + }; + this.compareRange = function(range) { + var cmp, + end = range.end, + start = range.start; + + cmp = this.compare(end.row, end.column); + if (cmp == 1) { + cmp = this.compare(start.row, start.column); + if (cmp == 1) { + return 2; + } else if (cmp == 0) { + return 1; + } else { + return 0; + } + } else if (cmp == -1) { + return -2; + } else { + cmp = this.compare(start.row, start.column); + if (cmp == -1) { + return -1; + } else if (cmp == 1) { + return 42; + } else { + return 0; + } + } + }; + this.comparePoint = function(p) { + return this.compare(p.row, p.column); + }; + this.containsRange = function(range) { + return this.comparePoint(range.start) == 0 && this.comparePoint(range.end) == 0; + }; + this.intersects = function(range) { + var cmp = this.compareRange(range); + return (cmp == -1 || cmp == 0 || cmp == 1); + }; + this.isEnd = function(row, column) { + return this.end.row == row && this.end.column == column; + }; + this.isStart = function(row, column) { + return this.start.row == row && this.start.column == column; + }; + this.setStart = function(row, column) { + if (typeof row == "object") { + this.start.column = row.column; + this.start.row = row.row; + } else { + this.start.row = row; + this.start.column = column; + } + }; + this.setEnd = function(row, column) { + if (typeof row == "object") { + this.end.column = row.column; + this.end.row = row.row; + } else { + this.end.row = row; + this.end.column = column; + } + }; + this.inside = function(row, column) { + if (this.compare(row, column) == 0) { + if (this.isEnd(row, column) || this.isStart(row, column)) { + return false; + } else { + return true; + } + } + return false; + }; + this.insideStart = function(row, column) { + if (this.compare(row, column) == 0) { + if (this.isEnd(row, column)) { + return false; + } else { + return true; + } + } + return false; + }; + this.insideEnd = function(row, column) { + if (this.compare(row, column) == 0) { + if (this.isStart(row, column)) { + return false; + } else { + return true; + } + } + return false; + }; + this.compare = function(row, column) { + if (!this.isMultiLine()) { + if (row === this.start.row) { + return column < this.start.column ? -1 : (column > this.end.column ? 1 : 0); + }; + } + + if (row < this.start.row) + return -1; + + if (row > this.end.row) + return 1; + + if (this.start.row === row) + return column >= this.start.column ? 0 : -1; + + if (this.end.row === row) + return column <= this.end.column ? 0 : 1; + + return 0; + }; + this.compareStart = function(row, column) { + if (this.start.row == row && this.start.column == column) { + return -1; + } else { + return this.compare(row, column); + } + }; + this.compareEnd = function(row, column) { + if (this.end.row == row && this.end.column == column) { + return 1; + } else { + return this.compare(row, column); + } + }; + this.compareInside = function(row, column) { + if (this.end.row == row && this.end.column == column) { + return 1; + } else if (this.start.row == row && this.start.column == column) { + return -1; + } else { + return this.compare(row, column); + } + }; + this.clipRows = function(firstRow, lastRow) { + if (this.end.row > lastRow) + var end = {row: lastRow + 1, column: 0}; + else if (this.end.row < firstRow) + var end = {row: firstRow, column: 0}; + + if (this.start.row > lastRow) + var start = {row: lastRow + 1, column: 0}; + else if (this.start.row < firstRow) + var start = {row: firstRow, column: 0}; + + return Range.fromPoints(start || this.start, end || this.end); + }; + this.extend = function(row, column) { + var cmp = this.compare(row, column); + + if (cmp == 0) + return this; + else if (cmp == -1) + var start = {row: row, column: column}; + else + var end = {row: row, column: column}; + + return Range.fromPoints(start || this.start, end || this.end); + }; + + this.isEmpty = function() { + return (this.start.row === this.end.row && this.start.column === this.end.column); + }; + this.isMultiLine = function() { + return (this.start.row !== this.end.row); + }; + this.clone = function() { + return Range.fromPoints(this.start, this.end); + }; + this.collapseRows = function() { + if (this.end.column == 0) + return new Range(this.start.row, 0, Math.max(this.start.row, this.end.row-1), 0) + else + return new Range(this.start.row, 0, this.end.row, 0) + }; + this.toScreenRange = function(session) { + var screenPosStart = session.documentToScreenPosition(this.start); + var screenPosEnd = session.documentToScreenPosition(this.end); + + return new Range( + screenPosStart.row, screenPosStart.column, + screenPosEnd.row, screenPosEnd.column + ); + }; + this.moveBy = function(row, column) { + this.start.row += row; + this.start.column += column; + this.end.row += row; + this.end.column += column; + }; + +}).call(Range.prototype); +Range.fromPoints = function(start, end) { + return new Range(start.row, start.column, end.row, end.column); +}; +Range.comparePoints = comparePoints; + +Range.comparePoints = function(p1, p2) { + return p1.row - p2.row || p1.column - p2.column; +}; + + +exports.Range = Range; +}); + +ace.define('ace/anchor', ['require', 'exports', 'module' , 'ace/lib/oop', 'ace/lib/event_emitter'], function(require, exports, module) { + + +var oop = require("./lib/oop"); +var EventEmitter = require("./lib/event_emitter").EventEmitter; + +var Anchor = exports.Anchor = function(doc, row, column) { + this.$onChange = this.onChange.bind(this); + this.attach(doc); + + if (typeof column == "undefined") + this.setPosition(row.row, row.column); + else + this.setPosition(row, column); +}; + +(function() { + + oop.implement(this, EventEmitter); + this.getPosition = function() { + return this.$clipPositionToDocument(this.row, this.column); + }; + this.getDocument = function() { + return this.document; + }; + this.$insertRight = false; + this.onChange = function(e) { + var delta = e.data; + var range = delta.range; + + if (range.start.row == range.end.row && range.start.row != this.row) + return; + + if (range.start.row > this.row) + return; + + if (range.start.row == this.row && range.start.column > this.column) + return; + + var row = this.row; + var column = this.column; + var start = range.start; + var end = range.end; + + if (delta.action === "insertText") { + if (start.row === row && start.column <= column) { + if (start.column === column && this.$insertRight) { + } else if (start.row === end.row) { + column += end.column - start.column; + } else { + column -= start.column; + row += end.row - start.row; + } + } else if (start.row !== end.row && start.row < row) { + row += end.row - start.row; + } + } else if (delta.action === "insertLines") { + if (start.row <= row) { + row += end.row - start.row; + } + } else if (delta.action === "removeText") { + if (start.row === row && start.column < column) { + if (end.column >= column) + column = start.column; + else + column = Math.max(0, column - (end.column - start.column)); + + } else if (start.row !== end.row && start.row < row) { + if (end.row === row) + column = Math.max(0, column - end.column) + start.column; + row -= (end.row - start.row); + } else if (end.row === row) { + row -= end.row - start.row; + column = Math.max(0, column - end.column) + start.column; + } + } else if (delta.action == "removeLines") { + if (start.row <= row) { + if (end.row <= row) + row -= end.row - start.row; + else { + row = start.row; + column = 0; + } + } + } + + this.setPosition(row, column, true); + }; + this.setPosition = function(row, column, noClip) { + var pos; + if (noClip) { + pos = { + row: row, + column: column + }; + } else { + pos = this.$clipPositionToDocument(row, column); + } + + if (this.row == pos.row && this.column == pos.column) + return; + + var old = { + row: this.row, + column: this.column + }; + + this.row = pos.row; + this.column = pos.column; + this._emit("change", { + old: old, + value: pos + }); + }; + this.detach = function() { + this.document.removeEventListener("change", this.$onChange); + }; + this.attach = function(doc) { + this.document = doc || this.document; + this.document.on("change", this.$onChange); + }; + this.$clipPositionToDocument = function(row, column) { + var pos = {}; + + if (row >= this.document.getLength()) { + pos.row = Math.max(0, this.document.getLength() - 1); + pos.column = this.document.getLine(pos.row).length; + } + else if (row < 0) { + pos.row = 0; + pos.column = 0; + } + else { + pos.row = row; + pos.column = Math.min(this.document.getLine(pos.row).length, Math.max(0, column)); + } + + if (column < 0) + pos.column = 0; + + return pos; + }; + +}).call(Anchor.prototype); + +}); +ace.define('ace/mode/css/csslint', ['require', 'exports', 'module' ], function(require, exports, module) { +var parserlib = {}; +(function(){ +function EventTarget(){ + this._listeners = {}; +} + +EventTarget.prototype = { + constructor: EventTarget, + addListener: function(type, listener){ + if (!this._listeners[type]){ + this._listeners[type] = []; + } + + this._listeners[type].push(listener); + }, + fire: function(event){ + if (typeof event == "string"){ + event = { type: event }; + } + if (typeof event.target != "undefined"){ + event.target = this; + } + + if (typeof event.type == "undefined"){ + throw new Error("Event object missing 'type' property."); + } + + if (this._listeners[event.type]){ + var listeners = this._listeners[event.type].concat(); + for (var i=0, len=listeners.length; i < len; i++){ + listeners[i].call(this, event); + } + } + }, + removeListener: function(type, listener){ + if (this._listeners[type]){ + var listeners = this._listeners[type]; + for (var i=0, len=listeners.length; i < len; i++){ + if (listeners[i] === listener){ + listeners.splice(i, 1); + break; + } + } + + + } + } +}; +function StringReader(text){ + this._input = text.replace(/\n\r?/g, "\n"); + this._line = 1; + this._col = 1; + this._cursor = 0; +} + +StringReader.prototype = { + constructor: StringReader, + getCol: function(){ + return this._col; + }, + getLine: function(){ + return this._line ; + }, + eof: function(){ + return (this._cursor == this._input.length); + }, + peek: function(count){ + var c = null; + count = (typeof count == "undefined" ? 1 : count); + if (this._cursor < this._input.length){ + c = this._input.charAt(this._cursor + count - 1); + } + + return c; + }, + read: function(){ + var c = null; + if (this._cursor < this._input.length){ + if (this._input.charAt(this._cursor) == "\n"){ + this._line++; + this._col=1; + } else { + this._col++; + } + c = this._input.charAt(this._cursor++); + } + + return c; + }, + mark: function(){ + this._bookmark = { + cursor: this._cursor, + line: this._line, + col: this._col + }; + }, + + reset: function(){ + if (this._bookmark){ + this._cursor = this._bookmark.cursor; + this._line = this._bookmark.line; + this._col = this._bookmark.col; + delete this._bookmark; + } + }, + readTo: function(pattern){ + + var buffer = "", + c; + while (buffer.length < pattern.length || buffer.lastIndexOf(pattern) != buffer.length - pattern.length){ + c = this.read(); + if (c){ + buffer += c; + } else { + throw new Error("Expected \"" + pattern + "\" at line " + this._line + ", col " + this._col + "."); + } + } + + return buffer; + + }, + readWhile: function(filter){ + + var buffer = "", + c = this.read(); + + while(c !== null && filter(c)){ + buffer += c; + c = this.read(); + } + + return buffer; + + }, + readMatch: function(matcher){ + + var source = this._input.substring(this._cursor), + value = null; + if (typeof matcher == "string"){ + if (source.indexOf(matcher) === 0){ + value = this.readCount(matcher.length); + } + } else if (matcher instanceof RegExp){ + if (matcher.test(source)){ + value = this.readCount(RegExp.lastMatch.length); + } + } + + return value; + }, + readCount: function(count){ + var buffer = ""; + + while(count--){ + buffer += this.read(); + } + + return buffer; + } + +}; +function SyntaxError(message, line, col){ + this.col = col; + this.line = line; + this.message = message; + +} +SyntaxError.prototype = new Error(); +function SyntaxUnit(text, line, col, type){ + this.col = col; + this.line = line; + this.text = text; + this.type = type; +} +SyntaxUnit.fromToken = function(token){ + return new SyntaxUnit(token.value, token.startLine, token.startCol); +}; + +SyntaxUnit.prototype = { + constructor: SyntaxUnit, + valueOf: function(){ + return this.toString(); + }, + toString: function(){ + return this.text; + } + +}; +function TokenStreamBase(input, tokenData){ + this._reader = input ? new StringReader(input.toString()) : null; + this._token = null; + this._tokenData = tokenData; + this._lt = []; + this._ltIndex = 0; + + this._ltIndexCache = []; +} +TokenStreamBase.createTokenData = function(tokens){ + + var nameMap = [], + typeMap = {}, + tokenData = tokens.concat([]), + i = 0, + len = tokenData.length+1; + + tokenData.UNKNOWN = -1; + tokenData.unshift({name:"EOF"}); + + for (; i < len; i++){ + nameMap.push(tokenData[i].name); + tokenData[tokenData[i].name] = i; + if (tokenData[i].text){ + typeMap[tokenData[i].text] = i; + } + } + + tokenData.name = function(tt){ + return nameMap[tt]; + }; + + tokenData.type = function(c){ + return typeMap[c]; + }; + + return tokenData; +}; + +TokenStreamBase.prototype = { + constructor: TokenStreamBase, + match: function(tokenTypes, channel){ + if (!(tokenTypes instanceof Array)){ + tokenTypes = [tokenTypes]; + } + + var tt = this.get(channel), + i = 0, + len = tokenTypes.length; + + while(i < len){ + if (tt == tokenTypes[i++]){ + return true; + } + } + this.unget(); + return false; + }, + mustMatch: function(tokenTypes, channel){ + + var token; + if (!(tokenTypes instanceof Array)){ + tokenTypes = [tokenTypes]; + } + + if (!this.match.apply(this, arguments)){ + token = this.LT(1); + throw new SyntaxError("Expected " + this._tokenData[tokenTypes[0]].name + + " at line " + token.startLine + ", col " + token.startCol + ".", token.startLine, token.startCol); + } + }, + advance: function(tokenTypes, channel){ + + while(this.LA(0) !== 0 && !this.match(tokenTypes, channel)){ + this.get(); + } + + return this.LA(0); + }, + get: function(channel){ + + var tokenInfo = this._tokenData, + reader = this._reader, + value, + i =0, + len = tokenInfo.length, + found = false, + token, + info; + if (this._lt.length && this._ltIndex >= 0 && this._ltIndex < this._lt.length){ + + i++; + this._token = this._lt[this._ltIndex++]; + info = tokenInfo[this._token.type]; + while((info.channel !== undefined && channel !== info.channel) && + this._ltIndex < this._lt.length){ + this._token = this._lt[this._ltIndex++]; + info = tokenInfo[this._token.type]; + i++; + } + if ((info.channel === undefined || channel === info.channel) && + this._ltIndex <= this._lt.length){ + this._ltIndexCache.push(i); + return this._token.type; + } + } + token = this._getToken(); + if (token.type > -1 && !tokenInfo[token.type].hide){ + token.channel = tokenInfo[token.type].channel; + this._token = token; + this._lt.push(token); + this._ltIndexCache.push(this._lt.length - this._ltIndex + i); + if (this._lt.length > 5){ + this._lt.shift(); + } + if (this._ltIndexCache.length > 5){ + this._ltIndexCache.shift(); + } + this._ltIndex = this._lt.length; + } + info = tokenInfo[token.type]; + if (info && + (info.hide || + (info.channel !== undefined && channel !== info.channel))){ + return this.get(channel); + } else { + return token.type; + } + }, + LA: function(index){ + var total = index, + tt; + if (index > 0){ + if (index > 5){ + throw new Error("Too much lookahead."); + } + while(total){ + tt = this.get(); + total--; + } + while(total < index){ + this.unget(); + total++; + } + } else if (index < 0){ + + if(this._lt[this._ltIndex+index]){ + tt = this._lt[this._ltIndex+index].type; + } else { + throw new Error("Too much lookbehind."); + } + + } else { + tt = this._token.type; + } + + return tt; + + }, + LT: function(index){ + this.LA(index); + return this._lt[this._ltIndex+index-1]; + }, + peek: function(){ + return this.LA(1); + }, + token: function(){ + return this._token; + }, + tokenName: function(tokenType){ + if (tokenType < 0 || tokenType > this._tokenData.length){ + return "UNKNOWN_TOKEN"; + } else { + return this._tokenData[tokenType].name; + } + }, + tokenType: function(tokenName){ + return this._tokenData[tokenName] || -1; + }, + unget: function(){ + if (this._ltIndexCache.length){ + this._ltIndex -= this._ltIndexCache.pop();//--; + this._token = this._lt[this._ltIndex - 1]; + } else { + throw new Error("Too much lookahead."); + } + } + +}; + + + + +parserlib.util = { +StringReader: StringReader, +SyntaxError : SyntaxError, +SyntaxUnit : SyntaxUnit, +EventTarget : EventTarget, +TokenStreamBase : TokenStreamBase +}; +})(); +(function(){ +var EventTarget = parserlib.util.EventTarget, +TokenStreamBase = parserlib.util.TokenStreamBase, +StringReader = parserlib.util.StringReader, +SyntaxError = parserlib.util.SyntaxError, +SyntaxUnit = parserlib.util.SyntaxUnit; + + +var Colors = { + aliceblue :"#f0f8ff", + antiquewhite :"#faebd7", + aqua :"#00ffff", + aquamarine :"#7fffd4", + azure :"#f0ffff", + beige :"#f5f5dc", + bisque :"#ffe4c4", + black :"#000000", + blanchedalmond :"#ffebcd", + blue :"#0000ff", + blueviolet :"#8a2be2", + brown :"#a52a2a", + burlywood :"#deb887", + cadetblue :"#5f9ea0", + chartreuse :"#7fff00", + chocolate :"#d2691e", + coral :"#ff7f50", + cornflowerblue :"#6495ed", + cornsilk :"#fff8dc", + crimson :"#dc143c", + cyan :"#00ffff", + darkblue :"#00008b", + darkcyan :"#008b8b", + darkgoldenrod :"#b8860b", + darkgray :"#a9a9a9", + darkgreen :"#006400", + darkkhaki :"#bdb76b", + darkmagenta :"#8b008b", + darkolivegreen :"#556b2f", + darkorange :"#ff8c00", + darkorchid :"#9932cc", + darkred :"#8b0000", + darksalmon :"#e9967a", + darkseagreen :"#8fbc8f", + darkslateblue :"#483d8b", + darkslategray :"#2f4f4f", + darkturquoise :"#00ced1", + darkviolet :"#9400d3", + deeppink :"#ff1493", + deepskyblue :"#00bfff", + dimgray :"#696969", + dodgerblue :"#1e90ff", + firebrick :"#b22222", + floralwhite :"#fffaf0", + forestgreen :"#228b22", + fuchsia :"#ff00ff", + gainsboro :"#dcdcdc", + ghostwhite :"#f8f8ff", + gold :"#ffd700", + goldenrod :"#daa520", + gray :"#808080", + green :"#008000", + greenyellow :"#adff2f", + honeydew :"#f0fff0", + hotpink :"#ff69b4", + indianred :"#cd5c5c", + indigo :"#4b0082", + ivory :"#fffff0", + khaki :"#f0e68c", + lavender :"#e6e6fa", + lavenderblush :"#fff0f5", + lawngreen :"#7cfc00", + lemonchiffon :"#fffacd", + lightblue :"#add8e6", + lightcoral :"#f08080", + lightcyan :"#e0ffff", + lightgoldenrodyellow :"#fafad2", + lightgray :"#d3d3d3", + lightgreen :"#90ee90", + lightpink :"#ffb6c1", + lightsalmon :"#ffa07a", + lightseagreen :"#20b2aa", + lightskyblue :"#87cefa", + lightslategray :"#778899", + lightsteelblue :"#b0c4de", + lightyellow :"#ffffe0", + lime :"#00ff00", + limegreen :"#32cd32", + linen :"#faf0e6", + magenta :"#ff00ff", + maroon :"#800000", + mediumaquamarine:"#66cdaa", + mediumblue :"#0000cd", + mediumorchid :"#ba55d3", + mediumpurple :"#9370d8", + mediumseagreen :"#3cb371", + mediumslateblue :"#7b68ee", + mediumspringgreen :"#00fa9a", + mediumturquoise :"#48d1cc", + mediumvioletred :"#c71585", + midnightblue :"#191970", + mintcream :"#f5fffa", + mistyrose :"#ffe4e1", + moccasin :"#ffe4b5", + navajowhite :"#ffdead", + navy :"#000080", + oldlace :"#fdf5e6", + olive :"#808000", + olivedrab :"#6b8e23", + orange :"#ffa500", + orangered :"#ff4500", + orchid :"#da70d6", + palegoldenrod :"#eee8aa", + palegreen :"#98fb98", + paleturquoise :"#afeeee", + palevioletred :"#d87093", + papayawhip :"#ffefd5", + peachpuff :"#ffdab9", + peru :"#cd853f", + pink :"#ffc0cb", + plum :"#dda0dd", + powderblue :"#b0e0e6", + purple :"#800080", + red :"#ff0000", + rosybrown :"#bc8f8f", + royalblue :"#4169e1", + saddlebrown :"#8b4513", + salmon :"#fa8072", + sandybrown :"#f4a460", + seagreen :"#2e8b57", + seashell :"#fff5ee", + sienna :"#a0522d", + silver :"#c0c0c0", + skyblue :"#87ceeb", + slateblue :"#6a5acd", + slategray :"#708090", + snow :"#fffafa", + springgreen :"#00ff7f", + steelblue :"#4682b4", + tan :"#d2b48c", + teal :"#008080", + thistle :"#d8bfd8", + tomato :"#ff6347", + turquoise :"#40e0d0", + violet :"#ee82ee", + wheat :"#f5deb3", + white :"#ffffff", + whitesmoke :"#f5f5f5", + yellow :"#ffff00", + yellowgreen :"#9acd32", + activeBorder :"Active window border.", + activecaption :"Active window caption.", + appworkspace :"Background color of multiple document interface.", + background :"Desktop background.", + buttonface :"The face background color for 3-D elements that appear 3-D due to one layer of surrounding border.", + buttonhighlight :"The color of the border facing the light source for 3-D elements that appear 3-D due to one layer of surrounding border.", + buttonshadow :"The color of the border away from the light source for 3-D elements that appear 3-D due to one layer of surrounding border.", + buttontext :"Text on push buttons.", + captiontext :"Text in caption, size box, and scrollbar arrow box.", + graytext :"Grayed (disabled) text. This color is set to #000 if the current display driver does not support a solid gray color.", + highlight :"Item(s) selected in a control.", + highlighttext :"Text of item(s) selected in a control.", + inactiveborder :"Inactive window border.", + inactivecaption :"Inactive window caption.", + inactivecaptiontext :"Color of text in an inactive caption.", + infobackground :"Background color for tooltip controls.", + infotext :"Text color for tooltip controls.", + menu :"Menu background.", + menutext :"Text in menus.", + scrollbar :"Scroll bar gray area.", + threeddarkshadow :"The color of the darker (generally outer) of the two borders away from the light source for 3-D elements that appear 3-D due to two concentric layers of surrounding border.", + threedface :"The face background color for 3-D elements that appear 3-D due to two concentric layers of surrounding border.", + threedhighlight :"The color of the lighter (generally outer) of the two borders facing the light source for 3-D elements that appear 3-D due to two concentric layers of surrounding border.", + threedlightshadow :"The color of the darker (generally inner) of the two borders facing the light source for 3-D elements that appear 3-D due to two concentric layers of surrounding border.", + threedshadow :"The color of the lighter (generally inner) of the two borders away from the light source for 3-D elements that appear 3-D due to two concentric layers of surrounding border.", + window :"Window background.", + windowframe :"Window frame.", + windowtext :"Text in windows." +}; +function Combinator(text, line, col){ + + SyntaxUnit.call(this, text, line, col, Parser.COMBINATOR_TYPE); + this.type = "unknown"; + if (/^\s+$/.test(text)){ + this.type = "descendant"; + } else if (text == ">"){ + this.type = "child"; + } else if (text == "+"){ + this.type = "adjacent-sibling"; + } else if (text == "~"){ + this.type = "sibling"; + } + +} + +Combinator.prototype = new SyntaxUnit(); +Combinator.prototype.constructor = Combinator; +function MediaFeature(name, value){ + + SyntaxUnit.call(this, "(" + name + (value !== null ? ":" + value : "") + ")", name.startLine, name.startCol, Parser.MEDIA_FEATURE_TYPE); + this.name = name; + this.value = value; +} + +MediaFeature.prototype = new SyntaxUnit(); +MediaFeature.prototype.constructor = MediaFeature; +function MediaQuery(modifier, mediaType, features, line, col){ + + SyntaxUnit.call(this, (modifier ? modifier + " ": "") + (mediaType ? mediaType : "") + (mediaType && features.length > 0 ? " and " : "") + features.join(" and "), line, col, Parser.MEDIA_QUERY_TYPE); + this.modifier = modifier; + this.mediaType = mediaType; + this.features = features; + +} + +MediaQuery.prototype = new SyntaxUnit(); +MediaQuery.prototype.constructor = MediaQuery; +function Parser(options){ + EventTarget.call(this); + + + this.options = options || {}; + + this._tokenStream = null; +} +Parser.DEFAULT_TYPE = 0; +Parser.COMBINATOR_TYPE = 1; +Parser.MEDIA_FEATURE_TYPE = 2; +Parser.MEDIA_QUERY_TYPE = 3; +Parser.PROPERTY_NAME_TYPE = 4; +Parser.PROPERTY_VALUE_TYPE = 5; +Parser.PROPERTY_VALUE_PART_TYPE = 6; +Parser.SELECTOR_TYPE = 7; +Parser.SELECTOR_PART_TYPE = 8; +Parser.SELECTOR_SUB_PART_TYPE = 9; + +Parser.prototype = function(){ + + var proto = new EventTarget(), //new prototype + prop, + additions = { + constructor: Parser, + DEFAULT_TYPE : 0, + COMBINATOR_TYPE : 1, + MEDIA_FEATURE_TYPE : 2, + MEDIA_QUERY_TYPE : 3, + PROPERTY_NAME_TYPE : 4, + PROPERTY_VALUE_TYPE : 5, + PROPERTY_VALUE_PART_TYPE : 6, + SELECTOR_TYPE : 7, + SELECTOR_PART_TYPE : 8, + SELECTOR_SUB_PART_TYPE : 9, + + _stylesheet: function(){ + + var tokenStream = this._tokenStream, + charset = null, + count, + token, + tt; + + this.fire("startstylesheet"); + this._charset(); + + this._skipCruft(); + while (tokenStream.peek() == Tokens.IMPORT_SYM){ + this._import(); + this._skipCruft(); + } + while (tokenStream.peek() == Tokens.NAMESPACE_SYM){ + this._namespace(); + this._skipCruft(); + } + tt = tokenStream.peek(); + while(tt > Tokens.EOF){ + + try { + + switch(tt){ + case Tokens.MEDIA_SYM: + this._media(); + this._skipCruft(); + break; + case Tokens.PAGE_SYM: + this._page(); + this._skipCruft(); + break; + case Tokens.FONT_FACE_SYM: + this._font_face(); + this._skipCruft(); + break; + case Tokens.KEYFRAMES_SYM: + this._keyframes(); + this._skipCruft(); + break; + case Tokens.UNKNOWN_SYM: //unknown @ rule + tokenStream.get(); + if (!this.options.strict){ + this.fire({ + type: "error", + error: null, + message: "Unknown @ rule: " + tokenStream.LT(0).value + ".", + line: tokenStream.LT(0).startLine, + col: tokenStream.LT(0).startCol + }); + count=0; + while (tokenStream.advance([Tokens.LBRACE, Tokens.RBRACE]) == Tokens.LBRACE){ + count++; //keep track of nesting depth + } + + while(count){ + tokenStream.advance([Tokens.RBRACE]); + count--; + } + + } else { + throw new SyntaxError("Unknown @ rule.", tokenStream.LT(0).startLine, tokenStream.LT(0).startCol); + } + break; + case Tokens.S: + this._readWhitespace(); + break; + default: + if(!this._ruleset()){ + switch(tt){ + case Tokens.CHARSET_SYM: + token = tokenStream.LT(1); + this._charset(false); + throw new SyntaxError("@charset not allowed here.", token.startLine, token.startCol); + case Tokens.IMPORT_SYM: + token = tokenStream.LT(1); + this._import(false); + throw new SyntaxError("@import not allowed here.", token.startLine, token.startCol); + case Tokens.NAMESPACE_SYM: + token = tokenStream.LT(1); + this._namespace(false); + throw new SyntaxError("@namespace not allowed here.", token.startLine, token.startCol); + default: + tokenStream.get(); //get the last token + this._unexpectedToken(tokenStream.token()); + } + + } + } + } catch(ex) { + if (ex instanceof SyntaxError && !this.options.strict){ + this.fire({ + type: "error", + error: ex, + message: ex.message, + line: ex.line, + col: ex.col + }); + } else { + throw ex; + } + } + + tt = tokenStream.peek(); + } + + if (tt != Tokens.EOF){ + this._unexpectedToken(tokenStream.token()); + } + + this.fire("endstylesheet"); + }, + + _charset: function(emit){ + var tokenStream = this._tokenStream, + charset, + token, + line, + col; + + if (tokenStream.match(Tokens.CHARSET_SYM)){ + line = tokenStream.token().startLine; + col = tokenStream.token().startCol; + + this._readWhitespace(); + tokenStream.mustMatch(Tokens.STRING); + + token = tokenStream.token(); + charset = token.value; + + this._readWhitespace(); + tokenStream.mustMatch(Tokens.SEMICOLON); + + if (emit !== false){ + this.fire({ + type: "charset", + charset:charset, + line: line, + col: col + }); + } + } + }, + + _import: function(emit){ + + var tokenStream = this._tokenStream, + tt, + uri, + importToken, + mediaList = []; + tokenStream.mustMatch(Tokens.IMPORT_SYM); + importToken = tokenStream.token(); + this._readWhitespace(); + + tokenStream.mustMatch([Tokens.STRING, Tokens.URI]); + uri = tokenStream.token().value.replace(/(?:url\()?["']([^"']+)["']\)?/, "$1"); + + this._readWhitespace(); + + mediaList = this._media_query_list(); + tokenStream.mustMatch(Tokens.SEMICOLON); + this._readWhitespace(); + + if (emit !== false){ + this.fire({ + type: "import", + uri: uri, + media: mediaList, + line: importToken.startLine, + col: importToken.startCol + }); + } + + }, + + _namespace: function(emit){ + + var tokenStream = this._tokenStream, + line, + col, + prefix, + uri; + tokenStream.mustMatch(Tokens.NAMESPACE_SYM); + line = tokenStream.token().startLine; + col = tokenStream.token().startCol; + this._readWhitespace(); + if (tokenStream.match(Tokens.IDENT)){ + prefix = tokenStream.token().value; + this._readWhitespace(); + } + + tokenStream.mustMatch([Tokens.STRING, Tokens.URI]); + uri = tokenStream.token().value.replace(/(?:url\()?["']([^"']+)["']\)?/, "$1"); + + this._readWhitespace(); + tokenStream.mustMatch(Tokens.SEMICOLON); + this._readWhitespace(); + + if (emit !== false){ + this.fire({ + type: "namespace", + prefix: prefix, + uri: uri, + line: line, + col: col + }); + } + + }, + + _media: function(){ + var tokenStream = this._tokenStream, + line, + col, + mediaList;// = []; + tokenStream.mustMatch(Tokens.MEDIA_SYM); + line = tokenStream.token().startLine; + col = tokenStream.token().startCol; + + this._readWhitespace(); + + mediaList = this._media_query_list(); + + tokenStream.mustMatch(Tokens.LBRACE); + this._readWhitespace(); + + this.fire({ + type: "startmedia", + media: mediaList, + line: line, + col: col + }); + + while(true) { + if (tokenStream.peek() == Tokens.PAGE_SYM){ + this._page(); + } else if (!this._ruleset()){ + break; + } + } + + tokenStream.mustMatch(Tokens.RBRACE); + this._readWhitespace(); + + this.fire({ + type: "endmedia", + media: mediaList, + line: line, + col: col + }); + }, + _media_query_list: function(){ + var tokenStream = this._tokenStream, + mediaList = []; + + + this._readWhitespace(); + + if (tokenStream.peek() == Tokens.IDENT || tokenStream.peek() == Tokens.LPAREN){ + mediaList.push(this._media_query()); + } + + while(tokenStream.match(Tokens.COMMA)){ + this._readWhitespace(); + mediaList.push(this._media_query()); + } + + return mediaList; + }, + _media_query: function(){ + var tokenStream = this._tokenStream, + type = null, + ident = null, + token = null, + expressions = []; + + if (tokenStream.match(Tokens.IDENT)){ + ident = tokenStream.token().value.toLowerCase(); + if (ident != "only" && ident != "not"){ + tokenStream.unget(); + ident = null; + } else { + token = tokenStream.token(); + } + } + + this._readWhitespace(); + + if (tokenStream.peek() == Tokens.IDENT){ + type = this._media_type(); + if (token === null){ + token = tokenStream.token(); + } + } else if (tokenStream.peek() == Tokens.LPAREN){ + if (token === null){ + token = tokenStream.LT(1); + } + expressions.push(this._media_expression()); + } + + if (type === null && expressions.length === 0){ + return null; + } else { + this._readWhitespace(); + while (tokenStream.match(Tokens.IDENT)){ + if (tokenStream.token().value.toLowerCase() != "and"){ + this._unexpectedToken(tokenStream.token()); + } + + this._readWhitespace(); + expressions.push(this._media_expression()); + } + } + + return new MediaQuery(ident, type, expressions, token.startLine, token.startCol); + }, + _media_type: function(){ + return this._media_feature(); + }, + _media_expression: function(){ + var tokenStream = this._tokenStream, + feature = null, + token, + expression = null; + + tokenStream.mustMatch(Tokens.LPAREN); + + feature = this._media_feature(); + this._readWhitespace(); + + if (tokenStream.match(Tokens.COLON)){ + this._readWhitespace(); + token = tokenStream.LT(1); + expression = this._expression(); + } + + tokenStream.mustMatch(Tokens.RPAREN); + this._readWhitespace(); + + return new MediaFeature(feature, (expression ? new SyntaxUnit(expression, token.startLine, token.startCol) : null)); + }, + _media_feature: function(){ + var tokenStream = this._tokenStream; + + tokenStream.mustMatch(Tokens.IDENT); + + return SyntaxUnit.fromToken(tokenStream.token()); + }, + _page: function(){ + var tokenStream = this._tokenStream, + line, + col, + identifier = null, + pseudoPage = null; + tokenStream.mustMatch(Tokens.PAGE_SYM); + line = tokenStream.token().startLine; + col = tokenStream.token().startCol; + + this._readWhitespace(); + + if (tokenStream.match(Tokens.IDENT)){ + identifier = tokenStream.token().value; + if (identifier.toLowerCase() === "auto"){ + this._unexpectedToken(tokenStream.token()); + } + } + if (tokenStream.peek() == Tokens.COLON){ + pseudoPage = this._pseudo_page(); + } + + this._readWhitespace(); + + this.fire({ + type: "startpage", + id: identifier, + pseudo: pseudoPage, + line: line, + col: col + }); + + this._readDeclarations(true, true); + + this.fire({ + type: "endpage", + id: identifier, + pseudo: pseudoPage, + line: line, + col: col + }); + + }, + _margin: function(){ + var tokenStream = this._tokenStream, + line, + col, + marginSym = this._margin_sym(); + + if (marginSym){ + line = tokenStream.token().startLine; + col = tokenStream.token().startCol; + + this.fire({ + type: "startpagemargin", + margin: marginSym, + line: line, + col: col + }); + + this._readDeclarations(true); + + this.fire({ + type: "endpagemargin", + margin: marginSym, + line: line, + col: col + }); + return true; + } else { + return false; + } + }, + _margin_sym: function(){ + + var tokenStream = this._tokenStream; + + if(tokenStream.match([Tokens.TOPLEFTCORNER_SYM, Tokens.TOPLEFT_SYM, + Tokens.TOPCENTER_SYM, Tokens.TOPRIGHT_SYM, Tokens.TOPRIGHTCORNER_SYM, + Tokens.BOTTOMLEFTCORNER_SYM, Tokens.BOTTOMLEFT_SYM, + Tokens.BOTTOMCENTER_SYM, Tokens.BOTTOMRIGHT_SYM, + Tokens.BOTTOMRIGHTCORNER_SYM, Tokens.LEFTTOP_SYM, + Tokens.LEFTMIDDLE_SYM, Tokens.LEFTBOTTOM_SYM, Tokens.RIGHTTOP_SYM, + Tokens.RIGHTMIDDLE_SYM, Tokens.RIGHTBOTTOM_SYM])) + { + return SyntaxUnit.fromToken(tokenStream.token()); + } else { + return null; + } + + }, + + _pseudo_page: function(){ + + var tokenStream = this._tokenStream; + + tokenStream.mustMatch(Tokens.COLON); + tokenStream.mustMatch(Tokens.IDENT); + + return tokenStream.token().value; + }, + + _font_face: function(){ + var tokenStream = this._tokenStream, + line, + col; + tokenStream.mustMatch(Tokens.FONT_FACE_SYM); + line = tokenStream.token().startLine; + col = tokenStream.token().startCol; + + this._readWhitespace(); + + this.fire({ + type: "startfontface", + line: line, + col: col + }); + + this._readDeclarations(true); + + this.fire({ + type: "endfontface", + line: line, + col: col + }); + }, + + _operator: function(inFunction){ + + var tokenStream = this._tokenStream, + token = null; + + if (tokenStream.match([Tokens.SLASH, Tokens.COMMA]) || + (inFunction && tokenStream.match([Tokens.PLUS, Tokens.STAR, Tokens.MINUS]))){ + token = tokenStream.token(); + this._readWhitespace(); + } + return token ? PropertyValuePart.fromToken(token) : null; + + }, + + _combinator: function(){ + + var tokenStream = this._tokenStream, + value = null, + token; + + if(tokenStream.match([Tokens.PLUS, Tokens.GREATER, Tokens.TILDE])){ + token = tokenStream.token(); + value = new Combinator(token.value, token.startLine, token.startCol); + this._readWhitespace(); + } + + return value; + }, + + _unary_operator: function(){ + + var tokenStream = this._tokenStream; + + if (tokenStream.match([Tokens.MINUS, Tokens.PLUS])){ + return tokenStream.token().value; + } else { + return null; + } + }, + + _property: function(){ + + var tokenStream = this._tokenStream, + value = null, + hack = null, + tokenValue, + token, + line, + col; + if (tokenStream.peek() == Tokens.STAR && this.options.starHack){ + tokenStream.get(); + token = tokenStream.token(); + hack = token.value; + line = token.startLine; + col = token.startCol; + } + + if(tokenStream.match(Tokens.IDENT)){ + token = tokenStream.token(); + tokenValue = token.value; + if (tokenValue.charAt(0) == "_" && this.options.underscoreHack){ + hack = "_"; + tokenValue = tokenValue.substring(1); + } + + value = new PropertyName(tokenValue, hack, (line||token.startLine), (col||token.startCol)); + this._readWhitespace(); + } + + return value; + }, + _ruleset: function(){ + + var tokenStream = this._tokenStream, + tt, + selectors; + try { + selectors = this._selectors_group(); + } catch (ex){ + if (ex instanceof SyntaxError && !this.options.strict){ + this.fire({ + type: "error", + error: ex, + message: ex.message, + line: ex.line, + col: ex.col + }); + tt = tokenStream.advance([Tokens.RBRACE]); + if (tt == Tokens.RBRACE){ + } else { + throw ex; + } + + } else { + throw ex; + } + return true; + } + if (selectors){ + + this.fire({ + type: "startrule", + selectors: selectors, + line: selectors[0].line, + col: selectors[0].col + }); + + this._readDeclarations(true); + + this.fire({ + type: "endrule", + selectors: selectors, + line: selectors[0].line, + col: selectors[0].col + }); + + } + + return selectors; + + }, + _selectors_group: function(){ + var tokenStream = this._tokenStream, + selectors = [], + selector; + + selector = this._selector(); + if (selector !== null){ + + selectors.push(selector); + while(tokenStream.match(Tokens.COMMA)){ + this._readWhitespace(); + selector = this._selector(); + if (selector !== null){ + selectors.push(selector); + } else { + this._unexpectedToken(tokenStream.LT(1)); + } + } + } + + return selectors.length ? selectors : null; + }, + _selector: function(){ + + var tokenStream = this._tokenStream, + selector = [], + nextSelector = null, + combinator = null, + ws = null; + nextSelector = this._simple_selector_sequence(); + if (nextSelector === null){ + return null; + } + + selector.push(nextSelector); + + do { + combinator = this._combinator(); + + if (combinator !== null){ + selector.push(combinator); + nextSelector = this._simple_selector_sequence(); + if (nextSelector === null){ + this._unexpectedToken(tokenStream.LT(1)); + } else { + selector.push(nextSelector); + } + } else { + if (this._readWhitespace()){ + ws = new Combinator(tokenStream.token().value, tokenStream.token().startLine, tokenStream.token().startCol); + combinator = this._combinator(); + nextSelector = this._simple_selector_sequence(); + if (nextSelector === null){ + if (combinator !== null){ + this._unexpectedToken(tokenStream.LT(1)); + } + } else { + + if (combinator !== null){ + selector.push(combinator); + } else { + selector.push(ws); + } + + selector.push(nextSelector); + } + } else { + break; + } + + } + } while(true); + + return new Selector(selector, selector[0].line, selector[0].col); + }, + _simple_selector_sequence: function(){ + + var tokenStream = this._tokenStream, + elementName = null, + modifiers = [], + selectorText= "", + components = [ + function(){ + return tokenStream.match(Tokens.HASH) ? + new SelectorSubPart(tokenStream.token().value, "id", tokenStream.token().startLine, tokenStream.token().startCol) : + null; + }, + this._class, + this._attrib, + this._pseudo, + this._negation + ], + i = 0, + len = components.length, + component = null, + found = false, + line, + col; + line = tokenStream.LT(1).startLine; + col = tokenStream.LT(1).startCol; + + elementName = this._type_selector(); + if (!elementName){ + elementName = this._universal(); + } + + if (elementName !== null){ + selectorText += elementName; + } + + while(true){ + if (tokenStream.peek() === Tokens.S){ + break; + } + while(i < len && component === null){ + component = components[i++].call(this); + } + + if (component === null){ + if (selectorText === ""){ + return null; + } else { + break; + } + } else { + i = 0; + modifiers.push(component); + selectorText += component.toString(); + component = null; + } + } + + + return selectorText !== "" ? + new SelectorPart(elementName, modifiers, selectorText, line, col) : + null; + }, + _type_selector: function(){ + + var tokenStream = this._tokenStream, + ns = this._namespace_prefix(), + elementName = this._element_name(); + + if (!elementName){ + if (ns){ + tokenStream.unget(); + if (ns.length > 1){ + tokenStream.unget(); + } + } + + return null; + } else { + if (ns){ + elementName.text = ns + elementName.text; + elementName.col -= ns.length; + } + return elementName; + } + }, + _class: function(){ + + var tokenStream = this._tokenStream, + token; + + if (tokenStream.match(Tokens.DOT)){ + tokenStream.mustMatch(Tokens.IDENT); + token = tokenStream.token(); + return new SelectorSubPart("." + token.value, "class", token.startLine, token.startCol - 1); + } else { + return null; + } + + }, + _element_name: function(){ + + var tokenStream = this._tokenStream, + token; + + if (tokenStream.match(Tokens.IDENT)){ + token = tokenStream.token(); + return new SelectorSubPart(token.value, "elementName", token.startLine, token.startCol); + + } else { + return null; + } + }, + _namespace_prefix: function(){ + var tokenStream = this._tokenStream, + value = ""; + if (tokenStream.LA(1) === Tokens.PIPE || tokenStream.LA(2) === Tokens.PIPE){ + + if(tokenStream.match([Tokens.IDENT, Tokens.STAR])){ + value += tokenStream.token().value; + } + + tokenStream.mustMatch(Tokens.PIPE); + value += "|"; + + } + + return value.length ? value : null; + }, + _universal: function(){ + var tokenStream = this._tokenStream, + value = "", + ns; + + ns = this._namespace_prefix(); + if(ns){ + value += ns; + } + + if(tokenStream.match(Tokens.STAR)){ + value += "*"; + } + + return value.length ? value : null; + + }, + _attrib: function(){ + + var tokenStream = this._tokenStream, + value = null, + ns, + token; + + if (tokenStream.match(Tokens.LBRACKET)){ + token = tokenStream.token(); + value = token.value; + value += this._readWhitespace(); + + ns = this._namespace_prefix(); + + if (ns){ + value += ns; + } + + tokenStream.mustMatch(Tokens.IDENT); + value += tokenStream.token().value; + value += this._readWhitespace(); + + if(tokenStream.match([Tokens.PREFIXMATCH, Tokens.SUFFIXMATCH, Tokens.SUBSTRINGMATCH, + Tokens.EQUALS, Tokens.INCLUDES, Tokens.DASHMATCH])){ + + value += tokenStream.token().value; + value += this._readWhitespace(); + + tokenStream.mustMatch([Tokens.IDENT, Tokens.STRING]); + value += tokenStream.token().value; + value += this._readWhitespace(); + } + + tokenStream.mustMatch(Tokens.RBRACKET); + + return new SelectorSubPart(value + "]", "attribute", token.startLine, token.startCol); + } else { + return null; + } + }, + _pseudo: function(){ + + var tokenStream = this._tokenStream, + pseudo = null, + colons = ":", + line, + col; + + if (tokenStream.match(Tokens.COLON)){ + + if (tokenStream.match(Tokens.COLON)){ + colons += ":"; + } + + if (tokenStream.match(Tokens.IDENT)){ + pseudo = tokenStream.token().value; + line = tokenStream.token().startLine; + col = tokenStream.token().startCol - colons.length; + } else if (tokenStream.peek() == Tokens.FUNCTION){ + line = tokenStream.LT(1).startLine; + col = tokenStream.LT(1).startCol - colons.length; + pseudo = this._functional_pseudo(); + } + + if (pseudo){ + pseudo = new SelectorSubPart(colons + pseudo, "pseudo", line, col); + } + } + + return pseudo; + }, + _functional_pseudo: function(){ + + var tokenStream = this._tokenStream, + value = null; + + if(tokenStream.match(Tokens.FUNCTION)){ + value = tokenStream.token().value; + value += this._readWhitespace(); + value += this._expression(); + tokenStream.mustMatch(Tokens.RPAREN); + value += ")"; + } + + return value; + }, + _expression: function(){ + + var tokenStream = this._tokenStream, + value = ""; + + while(tokenStream.match([Tokens.PLUS, Tokens.MINUS, Tokens.DIMENSION, + Tokens.NUMBER, Tokens.STRING, Tokens.IDENT, Tokens.LENGTH, + Tokens.FREQ, Tokens.ANGLE, Tokens.TIME, + Tokens.RESOLUTION, Tokens.SLASH])){ + + value += tokenStream.token().value; + value += this._readWhitespace(); + } + + return value.length ? value : null; + + }, + _negation: function(){ + + var tokenStream = this._tokenStream, + line, + col, + value = "", + arg, + subpart = null; + + if (tokenStream.match(Tokens.NOT)){ + value = tokenStream.token().value; + line = tokenStream.token().startLine; + col = tokenStream.token().startCol; + value += this._readWhitespace(); + arg = this._negation_arg(); + value += arg; + value += this._readWhitespace(); + tokenStream.match(Tokens.RPAREN); + value += tokenStream.token().value; + + subpart = new SelectorSubPart(value, "not", line, col); + subpart.args.push(arg); + } + + return subpart; + }, + _negation_arg: function(){ + + var tokenStream = this._tokenStream, + args = [ + this._type_selector, + this._universal, + function(){ + return tokenStream.match(Tokens.HASH) ? + new SelectorSubPart(tokenStream.token().value, "id", tokenStream.token().startLine, tokenStream.token().startCol) : + null; + }, + this._class, + this._attrib, + this._pseudo + ], + arg = null, + i = 0, + len = args.length, + elementName, + line, + col, + part; + + line = tokenStream.LT(1).startLine; + col = tokenStream.LT(1).startCol; + + while(i < len && arg === null){ + + arg = args[i].call(this); + i++; + } + if (arg === null){ + this._unexpectedToken(tokenStream.LT(1)); + } + if (arg.type == "elementName"){ + part = new SelectorPart(arg, [], arg.toString(), line, col); + } else { + part = new SelectorPart(null, [arg], arg.toString(), line, col); + } + + return part; + }, + + _declaration: function(){ + + var tokenStream = this._tokenStream, + property = null, + expr = null, + prio = null, + error = null, + invalid = null, + propertyName= ""; + + property = this._property(); + if (property !== null){ + + tokenStream.mustMatch(Tokens.COLON); + this._readWhitespace(); + + expr = this._expr(); + if (!expr || expr.length === 0){ + this._unexpectedToken(tokenStream.LT(1)); + } + + prio = this._prio(); + propertyName = property.toString(); + if (this.options.starHack && property.hack == "*" || + this.options.underscoreHack && property.hack == "_") { + + propertyName = property.text; + } + + try { + this._validateProperty(propertyName, expr); + } catch (ex) { + invalid = ex; + } + + this.fire({ + type: "property", + property: property, + value: expr, + important: prio, + line: property.line, + col: property.col, + invalid: invalid + }); + + return true; + } else { + return false; + } + }, + + _prio: function(){ + + var tokenStream = this._tokenStream, + result = tokenStream.match(Tokens.IMPORTANT_SYM); + + this._readWhitespace(); + return result; + }, + + _expr: function(inFunction){ + + var tokenStream = this._tokenStream, + values = [], + value = null, + operator = null; + + value = this._term(); + if (value !== null){ + + values.push(value); + + do { + operator = this._operator(inFunction); + if (operator){ + values.push(operator); + } /*else { + values.push(new PropertyValue(valueParts, valueParts[0].line, valueParts[0].col)); + valueParts = []; + }*/ + + value = this._term(); + + if (value === null){ + break; + } else { + values.push(value); + } + } while(true); + } + + return values.length > 0 ? new PropertyValue(values, values[0].line, values[0].col) : null; + }, + + _term: function(){ + + var tokenStream = this._tokenStream, + unary = null, + value = null, + token, + line, + col; + unary = this._unary_operator(); + if (unary !== null){ + line = tokenStream.token().startLine; + col = tokenStream.token().startCol; + } + if (tokenStream.peek() == Tokens.IE_FUNCTION && this.options.ieFilters){ + + value = this._ie_function(); + if (unary === null){ + line = tokenStream.token().startLine; + col = tokenStream.token().startCol; + } + } else if (tokenStream.match([Tokens.NUMBER, Tokens.PERCENTAGE, Tokens.LENGTH, + Tokens.ANGLE, Tokens.TIME, + Tokens.FREQ, Tokens.STRING, Tokens.IDENT, Tokens.URI, Tokens.UNICODE_RANGE])){ + + value = tokenStream.token().value; + if (unary === null){ + line = tokenStream.token().startLine; + col = tokenStream.token().startCol; + } + this._readWhitespace(); + } else { + token = this._hexcolor(); + if (token === null){ + if (unary === null){ + line = tokenStream.LT(1).startLine; + col = tokenStream.LT(1).startCol; + } + if (value === null){ + if (tokenStream.LA(3) == Tokens.EQUALS && this.options.ieFilters){ + value = this._ie_function(); + } else { + value = this._function(); + } + } + + } else { + value = token.value; + if (unary === null){ + line = token.startLine; + col = token.startCol; + } + } + + } + + return value !== null ? + new PropertyValuePart(unary !== null ? unary + value : value, line, col) : + null; + + }, + + _function: function(){ + + var tokenStream = this._tokenStream, + functionText = null, + expr = null, + lt; + + if (tokenStream.match(Tokens.FUNCTION)){ + functionText = tokenStream.token().value; + this._readWhitespace(); + expr = this._expr(true); + functionText += expr; + if (this.options.ieFilters && tokenStream.peek() == Tokens.EQUALS){ + do { + + if (this._readWhitespace()){ + functionText += tokenStream.token().value; + } + if (tokenStream.LA(0) == Tokens.COMMA){ + functionText += tokenStream.token().value; + } + + tokenStream.match(Tokens.IDENT); + functionText += tokenStream.token().value; + + tokenStream.match(Tokens.EQUALS); + functionText += tokenStream.token().value; + lt = tokenStream.peek(); + while(lt != Tokens.COMMA && lt != Tokens.S && lt != Tokens.RPAREN){ + tokenStream.get(); + functionText += tokenStream.token().value; + lt = tokenStream.peek(); + } + } while(tokenStream.match([Tokens.COMMA, Tokens.S])); + } + + tokenStream.match(Tokens.RPAREN); + functionText += ")"; + this._readWhitespace(); + } + + return functionText; + }, + + _ie_function: function(){ + + var tokenStream = this._tokenStream, + functionText = null, + expr = null, + lt; + if (tokenStream.match([Tokens.IE_FUNCTION, Tokens.FUNCTION])){ + functionText = tokenStream.token().value; + + do { + + if (this._readWhitespace()){ + functionText += tokenStream.token().value; + } + if (tokenStream.LA(0) == Tokens.COMMA){ + functionText += tokenStream.token().value; + } + + tokenStream.match(Tokens.IDENT); + functionText += tokenStream.token().value; + + tokenStream.match(Tokens.EQUALS); + functionText += tokenStream.token().value; + lt = tokenStream.peek(); + while(lt != Tokens.COMMA && lt != Tokens.S && lt != Tokens.RPAREN){ + tokenStream.get(); + functionText += tokenStream.token().value; + lt = tokenStream.peek(); + } + } while(tokenStream.match([Tokens.COMMA, Tokens.S])); + + tokenStream.match(Tokens.RPAREN); + functionText += ")"; + this._readWhitespace(); + } + + return functionText; + }, + + _hexcolor: function(){ + + var tokenStream = this._tokenStream, + token = null, + color; + + if(tokenStream.match(Tokens.HASH)){ + + token = tokenStream.token(); + color = token.value; + if (!/#[a-f0-9]{3,6}/i.test(color)){ + throw new SyntaxError("Expected a hex color but found '" + color + "' at line " + token.startLine + ", col " + token.startCol + ".", token.startLine, token.startCol); + } + this._readWhitespace(); + } + + return token; + }, + + _keyframes: function(){ + var tokenStream = this._tokenStream, + token, + tt, + name, + prefix = ""; + + tokenStream.mustMatch(Tokens.KEYFRAMES_SYM); + token = tokenStream.token(); + if (/^@\-([^\-]+)\-/.test(token.value)) { + prefix = RegExp.$1; + } + + this._readWhitespace(); + name = this._keyframe_name(); + + this._readWhitespace(); + tokenStream.mustMatch(Tokens.LBRACE); + + this.fire({ + type: "startkeyframes", + name: name, + prefix: prefix, + line: token.startLine, + col: token.startCol + }); + + this._readWhitespace(); + tt = tokenStream.peek(); + while(tt == Tokens.IDENT || tt == Tokens.PERCENTAGE) { + this._keyframe_rule(); + this._readWhitespace(); + tt = tokenStream.peek(); + } + + this.fire({ + type: "endkeyframes", + name: name, + prefix: prefix, + line: token.startLine, + col: token.startCol + }); + + this._readWhitespace(); + tokenStream.mustMatch(Tokens.RBRACE); + + }, + + _keyframe_name: function(){ + var tokenStream = this._tokenStream, + token; + + tokenStream.mustMatch([Tokens.IDENT, Tokens.STRING]); + return SyntaxUnit.fromToken(tokenStream.token()); + }, + + _keyframe_rule: function(){ + var tokenStream = this._tokenStream, + token, + keyList = this._key_list(); + + this.fire({ + type: "startkeyframerule", + keys: keyList, + line: keyList[0].line, + col: keyList[0].col + }); + + this._readDeclarations(true); + + this.fire({ + type: "endkeyframerule", + keys: keyList, + line: keyList[0].line, + col: keyList[0].col + }); + + }, + + _key_list: function(){ + var tokenStream = this._tokenStream, + token, + key, + keyList = []; + keyList.push(this._key()); + + this._readWhitespace(); + + while(tokenStream.match(Tokens.COMMA)){ + this._readWhitespace(); + keyList.push(this._key()); + this._readWhitespace(); + } + + return keyList; + }, + + _key: function(){ + + var tokenStream = this._tokenStream, + token; + + if (tokenStream.match(Tokens.PERCENTAGE)){ + return SyntaxUnit.fromToken(tokenStream.token()); + } else if (tokenStream.match(Tokens.IDENT)){ + token = tokenStream.token(); + + if (/from|to/i.test(token.value)){ + return SyntaxUnit.fromToken(token); + } + + tokenStream.unget(); + } + this._unexpectedToken(tokenStream.LT(1)); + }, + _skipCruft: function(){ + while(this._tokenStream.match([Tokens.S, Tokens.CDO, Tokens.CDC])){ + } + }, + _readDeclarations: function(checkStart, readMargins){ + var tokenStream = this._tokenStream, + tt; + + + this._readWhitespace(); + + if (checkStart){ + tokenStream.mustMatch(Tokens.LBRACE); + } + + this._readWhitespace(); + + try { + + while(true){ + + if (tokenStream.match(Tokens.SEMICOLON) || (readMargins && this._margin())){ + } else if (this._declaration()){ + if (!tokenStream.match(Tokens.SEMICOLON)){ + break; + } + } else { + break; + } + this._readWhitespace(); + } + + tokenStream.mustMatch(Tokens.RBRACE); + this._readWhitespace(); + + } catch (ex) { + if (ex instanceof SyntaxError && !this.options.strict){ + this.fire({ + type: "error", + error: ex, + message: ex.message, + line: ex.line, + col: ex.col + }); + tt = tokenStream.advance([Tokens.SEMICOLON, Tokens.RBRACE]); + if (tt == Tokens.SEMICOLON){ + this._readDeclarations(false, readMargins); + } else if (tt != Tokens.RBRACE){ + throw ex; + } + + } else { + throw ex; + } + } + + }, + _readWhitespace: function(){ + + var tokenStream = this._tokenStream, + ws = ""; + + while(tokenStream.match(Tokens.S)){ + ws += tokenStream.token().value; + } + + return ws; + }, + _unexpectedToken: function(token){ + throw new SyntaxError("Unexpected token '" + token.value + "' at line " + token.startLine + ", col " + token.startCol + ".", token.startLine, token.startCol); + }, + _verifyEnd: function(){ + if (this._tokenStream.LA(1) != Tokens.EOF){ + this._unexpectedToken(this._tokenStream.LT(1)); + } + }, + _validateProperty: function(property, value){ + Validation.validate(property, value); + }, + + parse: function(input){ + this._tokenStream = new TokenStream(input, Tokens); + this._stylesheet(); + }, + + parseStyleSheet: function(input){ + return this.parse(input); + }, + + parseMediaQuery: function(input){ + this._tokenStream = new TokenStream(input, Tokens); + var result = this._media_query(); + this._verifyEnd(); + return result; + }, + parsePropertyValue: function(input){ + + this._tokenStream = new TokenStream(input, Tokens); + this._readWhitespace(); + + var result = this._expr(); + this._readWhitespace(); + this._verifyEnd(); + return result; + }, + parseRule: function(input){ + this._tokenStream = new TokenStream(input, Tokens); + this._readWhitespace(); + + var result = this._ruleset(); + this._readWhitespace(); + this._verifyEnd(); + return result; + }, + parseSelector: function(input){ + + this._tokenStream = new TokenStream(input, Tokens); + this._readWhitespace(); + + var result = this._selector(); + this._readWhitespace(); + this._verifyEnd(); + return result; + }, + parseStyleAttribute: function(input){ + input += "}"; // for error recovery in _readDeclarations() + this._tokenStream = new TokenStream(input, Tokens); + this._readDeclarations(); + } + }; + for (prop in additions){ + if (additions.hasOwnProperty(prop)){ + proto[prop] = additions[prop]; + } + } + + return proto; +}(); +var Properties = { + "alignment-adjust" : "auto | baseline | before-edge | text-before-edge | middle | central | after-edge | text-after-edge | ideographic | alphabetic | hanging | mathematical | | ", + "alignment-baseline" : "baseline | use-script | before-edge | text-before-edge | after-edge | text-after-edge | central | middle | ideographic | alphabetic | hanging | mathematical", + "animation" : 1, + "animation-delay" : { multi: "