34
34
35
35
BUILTIN_FUNCTIONS = {'print' , 'input' , 'str' , 'int' , 'len' , 'any' , 'all' , 'sum' }
36
36
37
+ FORBIDDEN_TOP_LEVEL_FUNCTIONS = {'map' , 'filter' }
38
+
37
39
ITERABLE_TYPES = {'String' , 'List' , 'Dictionary' , 'Set' , 'Array' }
38
40
39
41
TESTABLE_TYPE = 'Boolean'
@@ -353,7 +355,62 @@ def _translate_call(self, func, args, keywords, starargs=None, kwargs=None, loca
353
355
args .append (arg )
354
356
355
357
356
- if isinstance (func , ast .Name ) and func .id in BUILTIN_FUNCTIONS :
358
+
359
+ if isinstance (func , ast .Name ) and func .id in FORBIDDEN_TOP_LEVEL_FUNCTIONS :
360
+ raise translation_error ('%s supported only as list(%s)' % (func .id , func .id ),
361
+ location , self .lines [location [0 ]])
362
+ elif isinstance (func , ast .Name ) and func .id == 'list' :
363
+ if len (args ) != 1 or not isinstance (args [0 ], ast .Call ) or not isinstance (args [0 ].func , ast .Name ) or args [0 ].func .id not in FORBIDDEN_TOP_LEVEL_FUNCTIONS :
364
+ raise translation_error ('list currently not supported' ,
365
+ location , self .lines [location [0 ]],
366
+ suggestions = 'list is currently only supported for list(filter)' )
367
+ if len (args [0 ].args ) != 2 :
368
+ raise type_check_error ('%s expects 2 arg, received %d args' % (args [0 ].func .id , len (args [0 ].args )),
369
+ location , self .lines [location [0 ]])
370
+ receiver_node = self ._translate_node (args [0 ].args [1 ])
371
+ if self ._general_type (receiver_node ['pseudo_type' ]) != 'List' :
372
+ raise type_check_error ('#%s currently works only' % args [0 ].func .id ,
373
+ location , self .lines [location [0 ]],
374
+ wrong_type = receiver_node ['pseudo_type' ])
375
+
376
+
377
+ if isinstance (args [0 ].args [0 ], ast .Lambda ):
378
+ if len (args [0 ].args [0 ].args .args ) != 1 :
379
+ raise translation_error ('lambda expected 1 arg, received %d' % len (args [0 ].args [0 ].args .args ),
380
+ location , self .lines [location [0 ]])
381
+
382
+ arg_nodes = [self ._translate_functional_lambda (args [0 ].args [0 ], receiver_node ['pseudo_type' ][1 ])]
383
+ else :
384
+ arg_nodes = [self ._translate_node (args [0 ].args .args [0 ], in_call = True )]
385
+
386
+ if args [0 ].func .id == 'map' :
387
+ return_type = ['List' , arg_nodes [0 ]['pseudo_type' ][- 1 ]]
388
+ else :
389
+ if arg_nodes [0 ]['pseudo_type' ][- 1 ] != 'Boolean' :
390
+ l = {'type' : 'local' , 'name' : args [0 ].args [0 ].args .args [0 ].arg , 'pseudo_type' : arg_nodes ['pseudo_type' ][- 1 ]}
391
+ arg_nodes [0 ] = {
392
+ 'type' : 'anonymous_function' ,
393
+ 'pseudo_type' : ['Function' , arg_nodes ['pseudo_type' ][- 1 ], 'Boolean' ],
394
+ 'return_type' : 'Boolean' ,
395
+ 'params' : [l ],
396
+ 'block' : [self ._testable ({
397
+ 'type' : 'call' ,
398
+ 'function' : arg_nodes [0 ],
399
+ 'args' : [l ],
400
+ 'pseudo_type' : arg_nodes [0 ]['pseudo_type' ][- 1 ]
401
+ })]
402
+ }
403
+
404
+ return_type = ['List' , 'Boolean' ]
405
+ return {
406
+ 'type' : 'standard_method_call' ,
407
+ 'receiver' : receiver_node ,
408
+ 'message' : args [0 ].func .id ,
409
+ 'args' : arg_nodes ,
410
+ 'pseudo_type' : return_type
411
+ }
412
+
413
+ elif isinstance (func , ast .Name ) and func .id in BUILTIN_FUNCTIONS :
357
414
if func .id in ['any' , 'all' , 'sum' ]:
358
415
if len (args ) != 1 :
359
416
raise translation_error ('%s expected 1 arg, not %d' % (func .id , len (args )),
@@ -527,13 +584,8 @@ def _translate_builtin_call(self, namespace, function, args, location):
527
584
'pseudo-python doesn\' t support %s %s' % (namespace , function ),
528
585
location , self .lines [location [0 ]],
529
586
suggestions = 'pseudo-python supports those %s functions\n %s' % (
530
- namespace , '\n ' .join (
531
- ' %s %s -> %s' % (
532
- name ,
533
- ' ' .join (serialize_type (arg ) for arg in t [:- 1 ]),
534
- serialize_type (t [- 1 ]))
535
- for name , t in TYPED_API ['_%s' % namespace ].items ()).strip ()))
536
-
587
+ namespace ,
588
+ prepare_table (TYPED_API [namespace ], ORIGINAL_METHODS .get (namespace )).strip ()))
537
589
538
590
539
591
if not isinstance (api , dict ):
@@ -1405,6 +1457,30 @@ def _translate_nameconstant(self, value, location):
1405
1457
elif value is None :
1406
1458
return {'type' : 'null' , 'pseudo_type' : 'Void' }
1407
1459
1460
+ def _translate_functional_lambda (self , l , arg_type ):
1461
+
1462
+ params = [{'type' : 'local' , 'name' : l .args .args [0 ].arg , 'pseudo_type' : arg_type }]
1463
+ self .type_env = self .type_env .child_env ({l .args .args [0 ].arg : arg_type })
1464
+ old_f , self .function_name = self .function_name , 'lambda'
1465
+ node = self ._translate_node (l .body )
1466
+ nodes = [{
1467
+ 'type' : 'implicit_return' ,
1468
+ 'pseudo_type' : node ['pseudo_type' ],
1469
+ 'value' : node
1470
+ }]
1471
+ self .function_name = old_f
1472
+ self .type_env = self .type_env .parent
1473
+ return {
1474
+ 'type' : 'anonymous_function' ,
1475
+ 'params' : params ,
1476
+ 'block' : nodes ,
1477
+ 'pseudo_type' : ['Function' , arg_type , node ['pseudo_type' ]],
1478
+ 'return_type' : node ['pseudo_type' ]
1479
+ }
1480
+
1481
+ def _translate_lambda (self , body , args , location ):
1482
+ raise
1483
+
1408
1484
def _translate_listcomp (self , generators , elt , location ):
1409
1485
if isinstance (generators [0 ].target , ast .Name ):
1410
1486
sketchup , env = self ._translate_iter (generators [0 ].target , generators [0 ].iter )
@@ -1427,7 +1503,7 @@ def _translate_listcomp(self, generators, elt, location):
1427
1503
'args' : [{
1428
1504
'type' : 'anonymous_function' ,
1429
1505
'params' : [sketchup ['iterators' ]['iterator' ]],
1430
- 'pseudo_type' : ['Function' , sketchup ['iterators' ]['iterator' ]['pseudo_type' ],
1506
+ 'pseudo_type' : ['Function' , sketchup ['iterators' ]['iterator' ]['pseudo_type' ],
1431
1507
elt ['pseudo_type' ]],
1432
1508
'return_type' : elt ['pseudo_type' ],
1433
1509
'block' : [{
0 commit comments