def visit_Call(self, node): if node.keywords: raise Exception('keyword arguments are not supported') if node.kwargs is not None: raise Exception('kwargs is not supported') if isinstance(node.func, _ast.Name): func = getattr(self, 'func_%s' % node.func.id, None) if func is not None: # noinspection PyCallingNonCallable return func(*node.args) if not node.starargs: self.visit(node.func) self.group(node.args, infix=', ') else: # Rewrite the call without starargs using apply. if isinstance(node.func, _ast.Attribute): this = node.func.value else: this = ast_load('this') if not node.args: args = node.starargs else: args = ast_call( ast.Attribute(ast.List(node.args, ast.Load()), 'concat', ast.Load()), node.starargs) self.visit( ast_call( ast.Attribute(node.func, 'apply', ast.Load()), this, args, ))
def _new_constant(node, value): if isinstance(value, ast.AST): # convenient shortcut: return the AST object unchanged return value # FIXME: test the config directly here? if value is None: new_node = ast.Constant(value=None) elif isinstance(value, (bool, int, float, complex, str, bytes)): new_node = ast.Constant(value=value) elif isinstance(value, (tuple, frozenset)): if not _is_constant(value): raise TypeError("container items are not constant: %r" % (value, )) new_node = ast.Constant(value=value) elif isinstance(value, list): elts = [_new_constant(node, elt) for elt in value] new_node = ast.List(elts=elts, ctx=ast.Load()) elif isinstance(value, dict): keys = [] values = [] for key, value in value.items(): keys.append(_new_constant(node, key)) values.append(_new_constant(node, value)) new_node = ast.Dict(keys=keys, values=values, ctx=ast.Load()) elif isinstance(value, set): elts = [_new_constant(node, elt) for elt in value] new_node = ast.Set(elts=elts, ctx=ast.Load()) else: raise TypeError("unknown type: %s" % type(value).__name__) copy_lineno(node, new_node) return new_node
def translate(self): """Compile the function call.""" varnames = set() if six.PY2: ident = self.ident.encode('utf-8') else: ident = self.ident funcnames = set([ident]) arg_exprs = [] for arg in self.args: subexprs, subvars, subfuncs = arg.translate() varnames.update(subvars) funcnames.update(subfuncs) # Create a subexpression that joins the result components of # the arguments. arg_exprs.append( ex_call( ast.Attribute(ex_literal(u''), 'join', ast.Load()), [ ex_call('map', [ ex_rvalue(six.text_type.__name__), ast.List(subexprs, ast.Load()), ]) ], )) subexpr_call = ex_call(FUNCTION_PREFIX + ident, arg_exprs) return [subexpr_call], varnames, funcnames
def visit_BoolOp(self, boolop): res_var = self.variable() expl_list = self.assign(ast.List([], ast.Load())) app = ast.Attribute(expl_list, "append", ast.Load()) is_or = int(isinstance(boolop.op, ast.Or)) body = save = self.statements fail_save = self.on_failure levels = len(boolop.values) - 1 self.push_format_context() # Process each operand, short-circuting if needed. for i, v in enumerate(boolop.values): if i: fail_inner = [] # cond is set in a prior loop iteration below self.on_failure.append(ast.If(cond, fail_inner, [])) # noqa self.on_failure = fail_inner self.push_format_context() res, expl = self.visit(v) body.append(ast.Assign([ast.Name(res_var, ast.Store())], res)) expl_format = self.pop_format_context(ast.Str(expl)) call = ast_Call(app, [expl_format], []) self.on_failure.append(ast.Expr(call)) if i < levels: cond = res if is_or: cond = ast.UnaryOp(ast.Not(), cond) inner = [] self.statements.append(ast.If(cond, inner, [])) self.statements = body = inner self.statements = save self.on_failure = fail_save expl_template = self.helper("format_boolop", expl_list, ast.Num(is_or)) expl = self.pop_format_context(expl_template) return ast.Name(res_var, ast.Load()), self.explanation_param(expl)
def translate(self): """Compile the template to a Python function.""" expressions, varnames, funcnames = self.expr.translate() argnames = [] for varname in varnames: argnames.append(VARIABLE_PREFIX + varname) for funcname in funcnames: argnames.append(FUNCTION_PREFIX + funcname) func = compile_func( argnames, [ast.Return(ast.List(expressions, ast.Load()))], ) def wrapper_func(values={}, functions={}): args = {} for varname in varnames: args[VARIABLE_PREFIX + varname] = values[varname] for funcname in funcnames: args[FUNCTION_PREFIX + funcname] = functions[funcname] parts = func(**args) return u''.join(parts) return wrapper_func
def ast_repr(x): """Similar to repr(), but returns an AST instead of a String, which when evaluated will return the given value.""" if type(x) in (int, float): return ast.Num(n=x) elif type(x) in (str, unicode): return ast.Str(s=x) elif type(x) is list: return ast.List(elts=map(ast_repr, x)) elif type(x) is dict: return ast.Dict(keys=map(ast_repr, x.keys()), values=map(ast_repr, x.values())) elif type(x) is set: return ast.Set(elts=map(ast_repr, x)) elif type(x) is Literal: return x.body elif type(x) is Captured: return ast.Call(ast.Name(id="Captured"), [x.val, ast_repr(x.name)], [], None, None) elif x is None: return ast.Name(id="None") elif x is True: return ast.Name(id="True") elif x is False: return ast.Name(id="False") elif isinstance(x, ast.AST): fields = [ast.keyword(a, ast_repr(b)) for a, b in ast.iter_fields(x)] return ast.Call(ast.Name(id=x.__class__.__name__), [], fields, None, None) raise Exception("Don't know how to ast_repr this: ", x)
def translate(self): """Compile the function call.""" varnames = set() funcnames = set([self.ident.encode('utf8')]) arg_exprs = [] for arg in self.args: subexprs, subvars, subfuncs = arg.translate() varnames.update(subvars) funcnames.update(subfuncs) # Create a subexpression that joins the result components of # the arguments. arg_exprs.append( ex_call( ast.Attribute(ex_literal(u''), b'join', ast.Load()), [ ex_call(b'map', [ ex_rvalue(b'unicode'), ast.List(subexprs, ast.Load()), ]) ], )) subexpr_call = ex_call(FUNCTION_PREFIX + self.ident.encode('utf8'), arg_exprs) return [subexpr_call], varnames, funcnames
def _generate_python_library_ast_node( self, name: Optional[str] = None, globs_path: str = "**/*.py", include_extra_dependencies: bool = True, ) -> ast.Expr: """Generate an AST node for a python_library Pants target Args: name: Name of the library target. If not provided, no name will be set. globs_path: File globs to include in the target. Defaults to everything. include_extra_dependencies: Flag for whether the extra dependencies specified in the config file should be included. This should usually be True except when generating a test library target. Returns: AST expression node """ keywords = [ self._get_dependencies_keyword( include_extra_dependencies=include_extra_dependencies ), ast.keyword(arg="sources", value=ast.List(elts=[ast.Str(globs_path)])), self._tags_keyword, ] if name is not None: keywords.insert(0, ast.keyword(arg="name", value=ast.Str(name))) node = ast.Expr( value=ast.Call( func=ast.Name(id="python_library"), args=[], keywords=keywords ) ) return node
def visit_Assert(self, node): is_str_mod = False if node.msg is not None: if isinstance(node.msg, ast.Constant): msg = node.msg.value elif isinstance(node.msg, ast.Str): msg = node.msg.s elif self._is_string_mod_args(node.msg): # Delay the handling until we call generic_visit() on |node|. is_str_mod = True else: raise ValueError( f"assert info must be constant, not {ast.dump(node.msg)}") else: import astor msg = astor.to_source(node.test) self.generic_visit(node) extra_args = ast.List(elts=[], ctx=ast.Load()) if is_str_mod: msg, extra_args = self._handle_string_mod_args(node.msg) new_node = self.parse_stmt('ti.ti_assert(0, 0, [])') new_node.value.args[0] = node.test new_node.value.args[1] = self.parse_expr("'{}'".format(msg.strip())) new_node.value.args[2] = extra_args new_node = ast.copy_location(new_node, node) return new_node
def get_module_nodes(self): modules = list( set(self._field_nodes.keys()) | set(self._type_nodes.keys())) result = {} for module in modules: self.add_import_statement(module, "commercetools", "types") self.add_import_statement(module, "marshmallow") type_nodes = reorder_class_definitions(self._type_nodes[module]) global_nodes = [ ast.Assign( targets=[ast.Name(id="__all__")], value=ast.List(elts=[ ast.Str(s=node.name) for node in sorted(type_nodes, key=operator.attrgetter("name")) ]), ) ] all_nodes = (self._import_nodes[module] + global_nodes + self._field_nodes[module] + type_nodes) value = ast.Module(body=all_nodes) result[module] = value result["__init__"] = self.generate_init_module(result.keys()) return result
def obj_to_ast(obj): if isinstance(obj, tuple): return ast.Tuple(elts=tuple(map(obj_to_ast, obj))) elif isinstance(obj, dict): k, v = unzip([(obj_to_ast(k), obj_to_ast(v)) for k, v in obj.items()]) return ast.Dict(k, v) elif isinstance(obj, list): return ast.List(list(map(obj_to_ast, obj))) elif isinstance(obj, type): return ast.Name(id=obj.__name__) elif isinstance(obj, int): return ast.Num(obj) elif isinstance(obj, str): return ast.Str(obj) elif obj is None: return ast.NameConstant(None) elif isinstance(obj, (typing._GenericAlias, typing._SpecialForm)): # TODO: types # issue was in pandas, where importing pandas._typing.Axis would # resolve module to typing, attempt to do "from typing import Axis" return ast.NameConstant(None) elif isinstance(obj, float) and math.isinf(obj): return parse_expr('float("inf")') elif isinstance(obj, bytes): return ast.Bytes(s=obj) else: raise ObjConversionException(f"No converter for {obj}")
def convert_tree_to_ssa(tree: ast.AST, defn_env: dict, phi_name: str = "phi"): # tree = MoveReturn().visit(tree) # tree.body.append( # ast.Return(ast.Name("__magma_ssa_return_value", ast.Load()))) ssa_visitor = SSAVisitor(phi_name) tree = ssa_visitor.visit(tree) return_transformer = TransformReturn() tree = return_transformer.visit(tree) num_return_values = len(ssa_visitor.return_values) for i in reversed(range(num_return_values)): conds = ssa_visitor.return_values[i] name = f"__magma_ssa_return_value_{i}" if i == num_return_values - 1 or not conds: if isinstance(tree.returns, ast.Tuple): tree.body.append(ast.Assign( [ast.Tuple([ast.Name(f"O{i}", ast.Store()) for i in range(len(tree.returns.elts))], ast.Store())], ast.Name(name, ast.Load()) )) else: tree.body.append(ast.Assign([ast.Name("O", ast.Load)], ast.Name(name, ast.Load()))) else: cond = conds[-1] for c in conds[:-1]: c = ast.BinOp(cond, ast.And(), c) if isinstance(tree.returns, ast.Tuple): for i in range(len(tree.returns.elts)): tree.body.append(ast.Assign( [ast.Name(f"O{i}", ast.Store())], ast.Call(ast.Name(phi_name, ast.Load()), [ ast.List([ ast.Name(f"O{i}", ast.Load()), ast.Subscript(ast.Name(name, ast.Load()), ast.Index(ast.Num(i)), ast.Load()) ], ast.Load()), cond], [])) ) else: tree.body.append(ast.Assign( [ast.Name("O", ast.Store())], ast.Call(ast.Name(phi_name, ast.Load()), [ ast.List([ast.Name("O", ast.Load()), ast.Name(name, ast.Load())], ast.Load()), cond], [])) ) return tree, ssa_visitor.args
def __init__(self, initial_values, variable_names, states, derivatives, system_tag=""): """ initial_values - initial values of global variables array. Array should be ordered in such way that all the derivatives are located in the tail. variable_names - dictionary states - states derivatives - derivatives """ self.body_init_set_var = [ast.Assign(targets=[GLOBAL_ARRAY], value=ast.Call(func=ast.Name(id='np.array', ctx=ast.Load()), args=[ast.List( elts=[ast.Constant(value=v) for v in initial_values], ctx=ast.Load())], keywords=[] ), lineno=0)] self.kernel_function = [] self.variable_names = variable_names self.states = states self.derivatives = derivatives self.functions = [] self.defined_functions = [] self.body = [] self.kernel_filename = LISTING_FILEPATH + system_tag + LISTINGFILENAME self.read_args_section = [ast.Expr(value=ast.Call(func=ast.Name(id='np.put'), args=[GLOBAL_ARRAY, ast.List( elts=[ast.Constant(value=v) for v in [self.variable_names[x] for x in self.states]], ctx=ast.Load()), ast.Name(id='states', ctx=ast.Store()) ], keywords=[]))] self.return_section = [ast.Return( value=ast.Call(func=ast.Name(id='np.take'), args=[GLOBAL_ARRAY, ast.List( elts=[ast.Constant(value=v) for v in [self.variable_names[x] for x in self.derivatives]], ctx=ast.Load()) ], keywords=[]))]
def parse(self, func): """Function decorator, returning a correct method from a pseudo-Python one""" # Get the function AST parsed = ast.parse(inspect.getsource(func)) fc_ast = parsed.body[0] argument_names = [name.id for name in fc_ast.args.args] # Init local cache self._local_ctx = {} # Translate (blocks[0][0] is the current instr) blocks, body = self._parse_body(fc_ast.body, argument_names) # Build the new function fc_ast.args.args[0:0] = [ast.Name(id='ir', ctx=ast.Param()), ast.Name(id='instr', ctx=ast.Param())] cur_instr = blocks[0][0] if len(blocks[-1][0]) == 0: ## Last block can be empty blocks.pop() other_blocks = blocks[1:] body.append(ast.Return(value=ast.Tuple(elts=[ast.List(elts=cur_instr, ctx=ast.Load()), ast.List(elts=other_blocks, ctx=ast.Load())], ctx=ast.Load()))) ret = ast.Module([ast.FunctionDef(name=fc_ast.name, args=fc_ast.args, body=body, decorator_list=[])]) # To display the generated function, use codegen.to_source # codegen: https://github.com/andreif/codegen # Compile according to the context fixed = ast.fix_missing_locations(ret) codeobj = compile(fixed, '<string>', 'exec') ctx = self._ctx.copy() eval(codeobj, ctx) # Get the function back self._functions[fc_ast.name] = ctx[fc_ast.name] return ctx[fc_ast.name]
def to_ast(self): return ast.Call(func=ast.Name(id='NamedParameters', ctx=ast.Load()), args=[ast.List(elts=[ast.Tuple(elts=[ast.Str(s=name), ty.to_ast()], ctx=ast.Load())\ for name, ty in self.parameters], ctx=ast.Load())], keywords=[], starargs=None, kwargs=None)
def visit_DictComp(self, node): # this is a quickfix to match visit_AnyComp signature # potential source of improvement there! node.elt = ast.List( [ast.Tuple([node.key, node.value], ast.Load())], ast.Load() ) return self.visit_AnyComp(node, "dict", "__dispatch__", "update")
def test_simple_enumerated_list(self): inputData = "[1, 2, 3]" expected = ast.Expr( ast.List( [ast.Num(1), ast.Num(2), ast.Num(3)], None)) result = transpile(inputData) self.assertTrue(compare_ast(result, expected))
def MakeVector(self, mv): result = ast.parse('__np__.array()', mode='eval').body result.args = [ ast.List(elts=[self(el) for el in mv.elems], ctx=ast.Load(), **_linearg) ] return result
def _convert_value(self, value): if isinstance(value, bool): return ast.Str(str(value) if value else '') elif isinstance(value, list): return ast.List(elts=list(map(self._convert_value, value)), ctx=ast.Load()) else: return ast.Str(str(value))
def to_ast(self, lineno: int, col_offset: int) -> ast.expr: return ast.List(elts=[ ast.Str(s=k, lineno=lineno, col_offset=col_offset) for k in self.members ], lineno=lineno, col_offset=col_offset, ctx=ast.Load())
def mathTransform(self, attribute, args): # operations from the math python module or builtin operations that exist in JavaScript Math: if attribute in self.directMathOperations: func = ast.Attribute(value=ast.Name(id='Math', ctx=ast.Load()), attr=attribute, ctx=ast.Load()) return ast.Call(func=func, args=args, keywords=[]) # substitutable operations, e.g. a = sum(b,c) => a = [b,c].reduce( function(x,y) { return x+y: }) elif attribute in self.subtitutableOperations: # a = sum(b,c) => a = [b,c].reduce( function(x,y) { return x+y: }) if attribute == 'sum': func = ast.Attribute(value=ast.List(elts=args, ctx=ast.Load()), attr='reduce', ctx=ast.Load()) args = [ ast.Call( func=ast.Name(id='JS', ctx=ast.Load()), args=[ast.Str(s=' function(x,y) { return x+y; }')], keywords=[]) ] return ast.Call(func=func, args=args, keywords=[]) # randint(a,b) => Math.floor(Math.random() * (b - a + 1)) + a elif attribute == 'randint': left = ast.Call( func=ast.Attribute(value=ast.Name(id='Math', ctx=ast.Load()), attr='floor', ctx=ast.Load()), args=[ ast.BinOp(left=ast.Call(func=ast.Attribute( value=ast.Name(id='Math', ctx=ast.Load()), attr='random', ctx=ast.Load()), args=[], keywords=[]), op=ast.Mult(), right=ast.BinOp(left=ast.BinOp( left=args[1], op=ast.Sub(), right=args[0]), op=ast.Add(), right=ast.Num(n=1))) ], keywords=[]) right = args[0] return ast.BinOp(left=left, op=ast.Add(), right=right) else: return None
def build_Compare(ctx, node): operands = build_exprs(ctx, [node.left] + list(node.comparators)) operators = [] for i in range(len(node.ops)): if isinstance(node.ops[i], ast.Lt): op_str = 'Lt' elif isinstance(node.ops[i], ast.LtE): op_str = 'LtE' elif isinstance(node.ops[i], ast.Gt): op_str = 'Gt' elif isinstance(node.ops[i], ast.GtE): op_str = 'GtE' elif isinstance(node.ops[i], ast.Eq): op_str = 'Eq' elif isinstance(node.ops[i], ast.NotEq): op_str = 'NotEq' elif isinstance(node.ops[i], ast.In): raise TaichiSyntaxError( '"in" is not supported in Taichi kernels.') elif isinstance(node.ops[i], ast.NotIn): raise TaichiSyntaxError( '"not in" is not supported in Taichi kernels.') elif isinstance(node.ops[i], ast.Is): raise TaichiSyntaxError( '"is" is not supported in Taichi kernels.') elif isinstance(node.ops[i], ast.IsNot): raise TaichiSyntaxError( '"is not" is not supported in Taichi kernels.') else: raise Exception(f'Unknown operator {node.ops[i]}') operators += [ ast.copy_location(ast.Str(s=op_str, kind=None), node) ] call = ast.Call( func=parse_expr('ti.chain_compare'), args=[ ast.copy_location(ast.List(elts=operands, ctx=ast.Load()), node), ast.copy_location(ast.List(elts=operators, ctx=ast.Load()), node) ], keywords=[]) call = ast.copy_location(call, node) return call
def parameterListBuilder(self, parameter_list): ast_list = [] for parameter in parameter_list: if parameter: ast_list.append(ast.Num(n=parameter)) else: ast_list.append(ast.NameConstant(value=None)) return ast.List(elts=ast_list)
def p_expr_hexstr(self, p): '''expr : HEXSTR''' s = p[1].replace('\'', '') try: _ = int(s, 16) except ValueError: raise Exception('Invalid hex literal.') byte_arr = [s[i:i + 2] for i in range(0, len(s), 2)] p[0] = ast.List(elts=byte_arr, ctx=ast.Store())
def composite(self, children): fields = [] for child in children: if isinstance(child, lark.Token): if child.type == 'NODE_TYPE': node_type = child.value else: pass elif isinstance(child, ast.AST): fields.append(child) else: pass if node_type == 'list': return ast.List(elts=fields, ctx=ast.Load()) elif node_type == 'attr': if len(fields) != 2: raise SyntaxError('Attribute node must have two fields; found ' + len(fields)) if not isinstance(fields[1], ast.Str): raise SyntaxError('Attribute name must be a string; found ' + type(fields[1])) return ast.Attribute(value=fields[0], attr=fields[1].s, ctx=ast.Load()) elif node_type == 'call': if len(fields) < 1: raise SyntaxError('Call node must have at least one field; found ' + len(fields)) return ast.Call(func=fields[0], args=fields[1:], keywords=[]) elif node_type == 'lambda': if len(fields) != 2: raise SyntaxError('Lambda node must have two fields; found ' + len(fields)) if not isinstance(fields[0], ast.List): raise SyntaxError('Lambda arguments must be in a list; found ' + type(fields[0])) for arg in fields[0].elts: if not isinstance(arg, ast.Name): raise SyntaxError('Lambda arguments must variable names; found ' + type(arg)) return ast.Lambda(args=ast.arguments(args=[ast.arg(arg=name.id, annotation=None) for name in fields[0].elts], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=fields[1]) elif node_type == 'Select': if len(fields) != 2: raise SyntaxError('Select node must have two fields; found ' + len(fields)) if not isinstance(fields[1], ast.Lambda): raise SyntaxError('Select selector must be a lambda; found ' + type(fields[1])) if len(fields[1].args.args) != 1: raise SyntaxError('Select selector must have exactly one argument; found ' + len(fields[1].args.args)) return linq_util.Select(source=fields[0], selector=fields[1]) else: raise SyntaxError('Unknown composite node type: ' + node_type)
def test_withIterNodes(self): nodes = ast.If( ast.Call(ast.Name('toto', ast.Load()), [ast.List([], ast.Load())], [], None, None), [ ast.Print( None, ast.Call(ast.Name('toto', ast.Load()), [ast.List([], ast.Load())], [], None, None), False), ], [], ) waitedRes = 'If Call Name Load List Load Print Call Name Load List Load'.split( ' ') iterRes = [n.__class__.__name__ for n in iter_nodes(nodes)] self.assertEquals(waitedRes, iterRes)
def test_capture_nested(self): ast_node = ast.List(elts=[ ast.Constant(value=1), ast.Constant(value=2), ast.Constant(value=3) ]) pattern_node = ast.List(elts=[ ast.Constant(value=anm.Capture("first")), ast.Constant(value=anm.Capture("second")), ast.Constant(value=anm.Capture("third")), ]) captures = {} matches = anm.match(ast_node, pattern_node, captures) assert matches assert captures["first"] == 1 assert captures["second"] == 2 assert captures["third"] == 3 pass
def eval_expro(expr, env, value, depth=0, maxdepth=3): # logger.debug("Evaluating expr {} to {} with env {}".format(expr, value, env)) uuid = str(uuid4())[:4] if isinstance(expr, ast.AST): logger.info("Found AST for expr -> {}".format( ast_dump_if_possible(expr))) if isinstance(value, ast.AST): logger.info("Found AST for value -> {}".format( ast_dump_if_possible(value))) if depth >= maxdepth: return fail # fmt: off return conde( (eq(expr, ast.Name(id=var('name_' + uuid), ctx=ast.Load())), lookupo(var('name_' + uuid), env, value)), # (lany( # typeo(value, int), # typeo(value, str), # ), # eq(expr, ast.Constant(value=value)),), (eq(expr, ast.Str(s=var('str_e_' + uuid))), typeo( value, str), eq(var('str_e_' + uuid), value)), (eq(expr, ast.Num(n=value)), membero(value, [_ for _ in range(5)])), (eq( expr, ast.BinOp(left=var('e1_' + uuid), op=var('op_e_' + uuid), right=var('e2_' + uuid))), typeo(var('v1_' + uuid), int), typeo(var('v2_' + uuid), int), eval_expro(var('e1_' + uuid), env, var('v1_' + uuid), depth + 1, maxdepth), eval_expro(var('e2_' + uuid), env, var('v2_' + uuid), depth + 1, maxdepth), eval_opo(var('op_e_' + uuid), var('op_v_' + uuid), var('v1_' + uuid), var('v2_' + uuid), value), binopo(var('v1_' + uuid), var('v2_' + uuid), value, op=var('op_v_' + uuid))), # Lists (eq(expr, ast.List(elts=var("list_elements_" + uuid), ctx=ast.Load())), eval_expr_listo(var("list_elements_" + uuid), env, value, depth, maxdepth)), # Functions (eq(expr, ast.Lambda(body=var('body_' + uuid), args=[])), typeo(value, FunctionType), eval_expro(var('body_' + uuid), env, var('body_v_' + uuid), depth + 1, maxdepth), eq(lambda: var('body_v_' + uuid), value)), (eq(expr, ast.Call(func=var('func_' + uuid), args=[], keywords=[])), typeo(var('func_v_' + uuid), FunctionType), eval_expro(var('func_' + uuid), env, var('func_v_' + uuid), depth + 1, maxdepth), applyo(var('func_v_' + uuid), [], value)), )
def compile_terminal(sexp: List, closure: Dict) -> ast.AST: """ Compiles primitive type variable (language built-in) to AST node. `closure` contains name bindings for target function. Variables of non-primitive (built-in) types (without corresponding AST node) are given a unique random name, converted to ast.Name and stored in closure for the target function. """ if type(sexp) is bool: return ast.NameConstant(value=sexp), closure elif type(sexp) in (int, float, complex): return ast.Num(n=sexp), closure elif type(sexp) is str: return ast.Str(s=sexp), closure elif type(sexp) is bytes: return ast.Bytes(s=sexp), closure elif type(sexp) is list: elts = [] for e in sexp: e, closure = compile_terminal(e, closure) elts.append(e) return ast.List(elts=elts, ctx=ast.Load()), closure elif type(sexp) is tuple: elts = [] for e in sexp: e, closure = compile_terminal(e, closure) elts.append(e) return ast.Tuple(elts=elts, ctx=ast.Load()), closure elif type(sexp) is dict: keys, values = [], [] for k, v in sexp.items(): k, closure = compile_terminal(k, closure) v, closure = compile_terminal(v, closure) keys.append(k) values.append(v) return ast.Dict(keys=keys, values=values), closure elif type(sexp) is set: elts = [] for e in sexp: e, closure = compile_terminal(e, closure) elts.append(e) return ast.Set(elts=elts), closure else: # Generate random name and store variable in closure. name = '_%s' % uuid.uuid4().hex closure[name] = sexp return ast.Name(id=name, ctx=ast.Load()), closure
def visit_IfExp(self, node): if not hasattr(node, "orelse"): raise NotImplementedError("If without else") node.body = self.visit(node.body) node.orelse = self.visit(node.orelse) return ast.Call( ast.Name("phi", ast.Load()), [ast.List([node.orelse, node.body], ast.Load()), node.test], [])