Skip to content

Commit aa3b04a

Browse files
author
hartsantler
committed
SyntaxErrors in 1st phase of translation will now show the line number and source code that caused the error.
fixed bisect builtin.
1 parent 46845a0 commit aa3b04a

3 files changed

Lines changed: 48 additions & 23 deletions

File tree

pythonjs/python_to_pythonjs.py

Lines changed: 44 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -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

pythonjs/pythonjs.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2038,7 +2038,7 @@ bisect = function(args, kwargs) {
20382038
var x = __args__['x'];
20392039
var low = __args__['low'];
20402040
var high = __args__['high'];
2041-
return __get__(__get__(a, "bisect", "missing attribute `bisect` - line 760: return a.bisect(x, low, high)"), "__call__")([x, low, high], __NULL_OBJECT__);
2041+
return a.bisect(x, low, high);
20422042
}
20432043

20442044
bisect.NAME = "bisect";

pythonjs/runtime/builtins.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -755,9 +755,9 @@ def index(obj):
755755

756756

757757
def bisect(a, x, low=None, high=None):
758-
#if isinstance(a, list):
759-
# return a[...].bisect(x, low, high)
760-
return a.bisect(x, low, high)
758+
## bisect function from bisect module of the stdlib
759+
with javascript:
760+
return a.bisect(x, low, high)
761761

762762

763763
def range(num, stop, step):

0 commit comments

Comments
 (0)