@@ -122,13 +122,26 @@ class PythonToPythonJS(NodeVisitor, inline_function.Inliner):
122122 identifier = 0
123123 _func_typedefs = ()
124124
125+ def format_error (self , node ):
126+ lines = []
127+ if self ._line_number > 0 :
128+ lines .append ( self ._source [self ._line_number - 1 ] )
129+ lines .append ( self ._source [self ._line_number ] )
130+ if self ._line_number + 1 < len (self ._source ):
131+ lines .append ( self ._source [self ._line_number + 1 ] )
132+
133+ return 'line %s\n %s\n %s' % (self ._line_number , '\n ' .join (lines ), node )
134+
125135 def __init__ (self , source = None , module = None , module_path = None , dart = False , coffee = False , lua = False ):
126136
127137 source = typedpython .transform_source ( source )
128138
129139 super (PythonToPythonJS , self ).__init__ ()
130140 self .setup_inliner ( writer )
131141
142+ self ._line = None
143+ self ._line_number = 0
144+
132145 self ._direct_operators = set () ## optimize "+" operator
133146 self ._with_ll = False ## lowlevel
134147 self ._with_lua = lua
@@ -366,6 +379,11 @@ def visit_ImportFrom(self, node):
366379 elif node .module == 'array' and node .names [0 ].name == 'array' :
367380 self ._use_array = True ## this is just a hint that calls to array call the builtin array
368381
382+ elif node .module == 'bisect' and node .names [0 ].name == 'bisect' :
383+ ## bisect library is part of the stdlib,
384+ ## in pythonjs it is a builtin function defined in builtins.py
385+ pass
386+
369387 elif node .module in lib :
370388 imported = False
371389 for n in node .names :
@@ -1004,7 +1022,7 @@ def visit_BoolOp(self, node):
10041022
10051023 def visit_If (self , node ):
10061024 if self ._with_dart and writer .is_at_global_level ():
1007- raise SyntaxError ('if statements can not be used at module level in dart' )
1025+ raise SyntaxError ( self . format_error ( 'if statements can not be used at module level in dart' ) )
10081026 elif self ._with_lua :
10091027 writer .write ('if __test_if_true__(%s):' % self .visit (node .test ))
10101028
@@ -1050,7 +1068,7 @@ def visit_Raise(self, node):
10501068
10511069 elif isinstance (node .type , ast .Call ):
10521070 if len (node .type .args ) > 1 :
1053- raise SyntaxError ('error to raise can have at most a single argument' )
1071+ raise SyntaxError ( self . format_error ( ' raise Error(x) can only have a single argument') )
10541072 if node .type .args :
10551073 writer .write ( 'raise %s(%s)' % (self .visit (node .type .func ), self .visit (node .type .args [0 ])) )
10561074 else :
@@ -1157,9 +1175,10 @@ def visit_BinOp(self, node):
11571175 if node .right .id in self ._global_nodes :
11581176 n = self ._global_nodes [ node .right .id ].n
11591177 else :
1160- raise SyntaxError
1178+ raise SyntaxError ( self . format_error ( node ) )
11611179 else :
1162- raise SyntaxError
1180+ #raise SyntaxError( self.format_error(node) )
1181+ return '__mul_op(%s,%s)' % (left , right )
11631182
11641183 elts = [ self .visit (e ) for e in node .left .elts ]
11651184 expanded = []
@@ -1495,6 +1514,11 @@ def visit_Assign(self, node):
14951514 use_runtime_errors = use_runtime_errors and self ._with_runtime_exceptions
14961515
14971516 lineno = node .lineno
1517+ if node .lineno < len (self ._source ):
1518+ src = self ._source [ node .lineno ]
1519+ self ._line_number = node .lineno
1520+ self ._line = src
1521+
14981522
14991523 if use_runtime_errors :
15001524 writer .write ('try:' )
@@ -1515,7 +1539,7 @@ def visit_Assign(self, node):
15151539 self ._typedef_vars [ node .value .id ] = target .id
15161540 return None
15171541 else :
1518- raise SyntaxError (targets )
1542+ raise SyntaxError ( self . format_error ( targets ) )
15191543
15201544 elif self ._with_rpc_name and isinstance (target , Attribute ) and isinstance (target .value , Name ) and target .value .id == self ._with_rpc_name :
15211545 writer .write ('__rpc_set__(%s, "%s", %s)' % (self ._with_rpc , target .attr , self .visit (node .value )))
@@ -1760,10 +1784,11 @@ def visit_Str(self, node):
17601784 return '"""%s"""' % s .encode ('utf-8' )
17611785
17621786 def visit_Expr (self , node ):
1763- log ('line: %s' % node .lineno )
17641787 if node .lineno < len (self ._source ):
17651788 src = self ._source [ node .lineno ]
1766- log ( src )
1789+ ## TODO raise SyntaxErrors with the line number and line source
1790+ self ._line_number = node .lineno
1791+ self ._line = src
17671792
17681793 use_runtime_errors = not (self ._with_js or self ._with_ll or self ._with_dart or self ._with_coffee or self ._with_lua )
17691794 use_runtime_errors = use_runtime_errors and self ._with_runtime_exceptions
@@ -1831,7 +1856,7 @@ def visit_Call(self, node):
18311856 #return '%s.append( [%s], __NULL_OBJECT__)' %(node.func.value.id, self.visit(node.args[0]) )
18321857 return '%s.push( %s )' % (node .func .value .id , self .visit (node .args [0 ]) )
18331858 else :
1834- raise SyntaxError
1859+ raise SyntaxError ( self . format_error ( node ) )
18351860
18361861
18371862 elif self ._with_webworker and isinstance (node .func , ast .Attribute ) and isinstance (node .func .value , Name ) and node .func .value .id == 'self' and node .func .attr == 'terminate' :
@@ -1843,7 +1868,7 @@ def visit_Call(self, node):
18431868 elif node .func .attr == 'start_webworker' :
18441869 return '__start_new_thread( %s, %s )' % (self .visit (node .args [0 ]), self .visit (node .args [1 ]))
18451870 else :
1846- raise SyntaxError (node .func .attr )
1871+ raise SyntaxError ( self . format_error ( node .func .attr ) )
18471872
18481873 elif self ._with_webworker and name in self ._global_functions :
18491874 node .calling_from_worker = True
@@ -1866,47 +1891,47 @@ def visit_Call(self, node):
18661891 self ._with_js = False
18671892 writer .with_javascript = False
18681893 else :
1869- raise SyntaxError
1894+ raise SyntaxError ( self . format_error ( node ) )
18701895
18711896 elif kw .arg == 'dart' :
18721897 if kw .value .id == 'True' :
18731898 self ._with_dart = True
18741899 elif kw .value .id == 'False' :
18751900 self ._with_dart = False
18761901 else :
1877- raise SyntaxError
1902+ raise SyntaxError ( self . format_error ( node ) )
18781903
18791904 elif kw .arg == 'coffee' :
18801905 if kw .value .id == 'True' :
18811906 self ._with_coffee = True
18821907 elif kw .value .id == 'False' :
18831908 self ._with_coffee = False
18841909 else :
1885- raise SyntaxError
1910+ raise SyntaxError ( self . format_error ( node ) )
18861911
18871912 elif kw .arg == 'lua' :
18881913 if kw .value .id == 'True' :
18891914 self ._with_lua = True
18901915 elif kw .value .id == 'False' :
18911916 self ._with_lua = False
18921917 else :
1893- raise SyntaxError
1918+ raise SyntaxError ( self . format_error ( node ) )
18941919
18951920 elif kw .arg == 'inline_functions' :
18961921 if kw .value .id == 'True' :
18971922 self ._with_inline = True
18981923 elif kw .value .id == 'False' :
18991924 self ._with_inline = False
19001925 else :
1901- raise SyntaxError
1926+ raise SyntaxError ( self . format_error ( node ) )
19021927
19031928 elif kw .arg == 'runtime_exceptions' :
19041929 if kw .value .id == 'True' :
19051930 self ._with_runtime_exceptions = True
19061931 elif kw .value .id == 'False' :
19071932 self ._with_runtime_exceptions = False
19081933 else :
1909- raise SyntaxError
1934+ raise SyntaxError ( self . format_error ( node ) )
19101935
19111936 elif kw .arg == 'direct_operator' :
19121937 if kw .value .s .lower () == 'none' :
@@ -1915,7 +1940,7 @@ def visit_Call(self, node):
19151940 self ._direct_operators .add ( kw .value .s )
19161941
19171942 else :
1918- raise SyntaxError
1943+ raise SyntaxError ( self . format_error ( node ) )
19191944
19201945 elif self ._with_ll or name == 'inline' :
19211946 args = [self .visit (arg ) for arg in node .args ]
@@ -2352,7 +2377,7 @@ def visit_FunctionDef(self, node):
23522377 elif isinstance (decorator , Attribute ) and isinstance (decorator .value , Name ) and decorator .value .id in self ._decorator_properties :
23532378 if decorator .attr == 'setter' :
23542379 if self ._decorator_properties [ decorator .value .id ]['set' ]:
2355- raise SyntaxError ('user error - the same decorator.setter is used more than once!' )
2380+ raise SyntaxError ( self . format_error ( " decorator.setter is used more than once" ) )
23562381 n = node .name + '__setprop__'
23572382 self ._decorator_properties [ decorator .value .id ]['set' ] = n
23582383 node .name = n
@@ -2424,7 +2449,7 @@ def visit_FunctionDef(self, node):
24242449 ## dart supports optional positional params [x=1, y=2], or optional named {x:1, y:2}
24252450 ## but not both at the same time.
24262451 if node .args .kwarg :
2427- raise SyntaxError ( 'dart functions can not take variable keyword arguments (**kwargs)' )
2452+ raise SyntaxError ( self . format_error ( 'dart functions can not take variable keyword arguments (**kwargs)' ) )
24282453
24292454 for dec in with_dart_decorators : writer .write ('@%s' % dec )
24302455
@@ -2441,7 +2466,7 @@ def visit_FunctionDef(self, node):
24412466
24422467 if node .args .vararg :
24432468 if node .args .defaults :
2444- raise SyntaxError ( 'dart functions can not use variable arguments (*args) and have keyword arguments' )
2469+ raise SyntaxError ( self . format_error ( 'dart functions can not use variable arguments (*args) and have keyword arguments' ) )
24452470
24462471 args .append ('__variable_args__%s' % node .args .vararg )
24472472
0 commit comments