def visit_Name(self, name): # Display the repr of the name if it's a local variable or # _should_repr_global_name() thinks it's acceptable. locs = ast_Call(self.builtin("locals"), [], []) inlocs = ast.Compare(ast.Str(name.id), [ast.In()], [locs]) dorepr = self.helper("should_repr_global_name", name) test = ast.BoolOp(ast.Or(), [inlocs, dorepr]) expr = ast.IfExp(test, self.display(name), ast.Str(name.id)) return name, self.explanation_param(expr)
def visit_IfExpr(self, node: IfExpr, *args, **kwargs) -> C.IfExp: test = self.visit(node.test, *args, **kwargs) body = self.visit(node.body, *args, **kwargs) orelse = self.visit(node.orelse, *args, **kwargs) return C.IfExp( test=test, body=body, orelse=orelse, )
def visit_if(self, if_block: Expr): cond_body, cond_defs = self.visit(if_block.cond) true_body, true_defs = self.visit(if_block.true_branch) false_body, false_defs = self.visit(if_block.false_branch) # need to get the value out of a NDArray to check the condition # equvialent to: val.asnumpy() cond_check = ast.Call(ast.Attribute(cond_body, 'asnumpy', Load()), [], []) ret = ast.IfExp(cond_check, true_body, false_body) return (ret, cond_defs + true_defs + false_defs)
def visit_Call(self, node): self.generic_visit(node) if isinstance(node.func, ast.Name) and node.func.id == "implies": if len(node.args) != 2: raise SyntaxError("implies() must have exactly two arguments") condition, implication = node.args pos = {"lineno": node.lineno, "col_offset": node.col_offset} return ast.IfExp(condition, implication, ast.Constant(True, **pos), **pos) return node
def visit_Compare(self, compare_node): if len(compare_node.comparators) > 1: return format_string = self.formatstring_for_comparison(compare_node) if format_string is None: return statements = [] format_params = [] new_comparators = [] for i, comparator in enumerate([compare_node.left] + compare_node.comparators): name = '@contexts_assertion_var' + str(i) statements.append(self.assign(name, comparator)) new_comparators.append(self.load(name)) format_params.append(self.repr(self.load(name))) name = '@contexts_formatparam' if isinstance(compare_node.ops[0], ast.Lt): ternary_expression = ast.IfExp( ast.Compare(new_comparators[0], [ast.Gt()], [new_comparators[1]]), ast.Str('it to be greater'), ast.Str('them to be equal') ) elif isinstance(compare_node.ops[0], ast.Gt): ternary_expression = ast.IfExp( ast.Compare(new_comparators[0], [ast.Lt()], [new_comparators[1]]), ast.Str('it to be less'), ast.Str('them to be equal') ) if isinstance(compare_node.ops[0], (ast.Lt, ast.Gt)): statements.append(self.assign(name, ternary_expression)) format_params.append(self.load(name)) compare_node.left, *compare_node.comparators = new_comparators msg = self.format(format_string, format_params) statements.append(ast.Assert(compare_node, msg)) return statements
def visit_UnaryOp(self, node): if isinstance(node.op, ast.Not): return ast.copy_location(ast.IfExp( test=self.visit(node.operand), body=ast.Constant(value=False), orelse=ast.Constant(value=True), ), node) else: func = ast.Attribute(value=self.visit(node.operand), attr=unary_op_map[type(node.op)], ctx=ast.Load()) call = ast.Call(func=func, args=[], keywords=[]) return ast.copy_location(call, node)
def _mux_name(name, t_name, f_name): return ast.Assign( targets=[ ast.Name( id=self._make_name(name), ctx=ast.Store(), ), ], value=ast.IfExp( test=test, body=_build_name(t_name), orelse=_build_name(f_name), ), )
def visit_Attribute(self, node): name = node.value attr = node.attr ctx = node.ctx if isinstance(ctx, ast.Load): node = ast.IfExp( ast.Call(ast.Name("hasattr", ast.Load()), [name, ast.Str("__findattr__")], []), ast.Call(ast.Attribute(name, "__findattr__", ast.Load()), [ast.Str(attr)], []), orelse=ast.Attribute(name, attr, ctx), ) return node
def toPython(self): args = [c.toPython() if c is not None else None for c in self.children] if self.value == "where": return ast.IfExp(*args) elif self.value == "real": return ast.Attribute(args[0], 'real', ast.Load()) elif self.value == "imag": return ast.Attribute(args[0], 'imag', ast.Load()) elif self.value == 'copy': assert len(args) == 1 # implement copy as a no-op return args[0] elif self.value == 'ones_like': return ast.Num(1) else: return ast.Call(ast.Name(self.value, ast.Load()), args, [], None, None)
def expression(expr): if expr['type'] == "Identifier": n = ast.Name(lineno=1, col_offset=0) n.id = str(expr['name']) n.ctx = ast.Load() c = ast.Call(lineno=1, col_offset=0) c.func = n c.args = [] c.keywords = [] c.starargs = None c.kwargs = None return c if expr['type'] == "VariableExpression": n = ast.Name(lineno=1, col_offset=0) n.id = str(expr['id']['name']) n.ctx = ast.Load() return n if expr['type'] == "String": s = ast.Str(lineno=1, col_offset=0) s.s = expr['content'] return s if expr['type'] == "Number": n = ast.Num(lineno=1, col_offset=0) n.n = expr['value'] return n if expr['type'] == "ConditionalExpression": i = ast.IfExp(lineno=1, col_offset=0) i.test = expression(expr['test']) i.body = expression(expr['consequent']) i.orelse = expression(expr['alternate']) return i if expr['type'] == "BinaryExpression": # L20n binary expr transpile into Python's BinOp or Compare if expr['operator']['token'] in ('==', ): c = ast.Compare(lineno=1, col_offset=0) c.left = expression(expr['left']) c.ops = [ast.Eq()] c.comparators = [expression(expr['right'])] return c if expr['operator']['token'] in ('+', ): b = ast.BinOp(lineno=1, col_offset=0) b.left = expression(expr['left']) b.op = ast.Add() b.right = expression(expr['right']) return b
def _fold_conditions( condition_seq: tp.Sequence[tp.Tuple[tp.List[ast.expr], ast.expr]]) -> ast.expr: ''' "Fold" ifExpr over a Sequence of conditons and exprs ''' assert condition_seq conditions, expr = condition_seq[0] if not conditions or len(condition_seq) == 1: return expr else: conditional = ast.IfExp( test=ast.BoolOp( op=ast.And(), values=conditions, ), body=expr, orelse=_fold_conditions(condition_seq[1:]), ) return conditional
def visit_IfExp(self, node): if isinstance(node.test, (ast.Name, ast.Attribute)): return self.generic_visit(node) else: temp_var_id = f'__if_exp_{self._temporary_variable_index}' self._temporary_variable_index += 1 assignment_of_test = ast.Assign( targets=[ast.Name(id=temp_var_id, ctx=ast.Store())], value=self.visit(node.test), ) ast.copy_location(assignment_of_test, node) self.assignments.append(assignment_of_test) transformed_if_exp = ast.IfExp( test=ast.Name(id=temp_var_id, ctx=ast.Load()), body=self.visit(node.body), orelse=self.visit(node.orelse), ) ast.copy_location(transformed_if_exp, node) return transformed_if_exp
def visit_Assign(self, node: ast.Assign): if not isinstance(node.value, ast.Call): return self.generic_visit(node) if len(node.targets) != 1: return self.generic_visit(node) target = node.targets[0] if isinstance(target, ast.Subscript): target = target.value if not isinstance(target, ast.Name): return self.generic_visit(node) tname: str = target.id callnode: ast.Call = node.value fname = astunparse.unparse(callnode.func)[:-1] if fname not in ('min', 'max'): return self.generic_visit(node) if len(callnode.args) != 2: raise NotImplementedError('Arguments to min/max (%d) != 2' % len(callnode.args)) result = [] names = [] for i, arg in enumerate(callnode.args): newname = '__dace_%s%d_%s' % (fname, i, tname) names.append(newname) result.append(ast.Assign(targets=[ast.Name(id=newname)], value=arg)) result.append( ast.Assign( targets=node.targets, value=ast.IfExp( test=ast.Compare(left=ast.Name(id=names[0]), ops=[ast.Lt()], comparators=[ast.Name(id=names[1])]), body=ast.Name(id=names[0]) if fname == 'min' else ast.Name( id=names[1]), orelse=ast.Name(id=names[1]) if fname == 'min' else ast.Name(id=names[0])))) self.count += 1 return result
def branch_dist_boolop(op, values, args): if len(values) == 1: return branch_dist(values[0], args) else: return ast.Call(func=ast.Lambda( args=ast.arguments( args=[ast.arg(arg=args.lambda_arg, annotation=None)], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=ast.IfExp(test=ast.Compare( left=ast.Name(id=args.lambda_arg), ops=[ast.Gt() if isinstance(op, ast.And) else ast.LtE()], comparators=[ast.Num(n=0)]), body=ast.Name(id=args.lambda_arg), orelse=branch_dist_boolop(op, values[1:], args))), args=[branch_dist(values[0], args)], keywords=[])
def visit_If(self, node: ast.If): if len(node.body) == 1 and len(node.orelse) == 1: if not isinstance(node.body[0], ast.Assign): return self.generic_visit(node) if not isinstance(node.orelse[0], ast.Assign): return self.generic_visit(node) if_assign: ast.Assign = node.body[0] else_assign: ast.Assign = node.orelse[0] if len(if_assign.targets) != 1 or len(else_assign.targets) != 1: return self.generic_visit(node) # Replace the condition with a predicated ternary expression if astunparse.unparse(if_assign.targets[0]) == astunparse.unparse( else_assign.targets[0]): new_node = ast.Assign(targets=if_assign.targets, value=ast.IfExp( test=node.test, body=if_assign.value, orelse=else_assign.value)) return ast.copy_location(new_node, node) return self.generic_visit(node)
def parse_lookup(ast_state, l): assert isinstance(l, dict) assert set(l.keys()) >= set(('key', 'op', 'table')) key = ast_value(ast_state, l['key']) # only support >=, <= for now assert l['op'] in ['>=', '<='] op = ast.GtE() if l['op'] == '>=' else ast.LtE() default = ast_value(ast_state, l.get('default')) table = l['table'] assert isinstance(table, list) expr = default for entry in reversed(table): assert isinstance(entry, list) assert len(entry) == 2 output, cond = entry test = ast.Compare(key, [op], [ast_value(ast_state, cond)]) expr = ast.IfExp(test, ast_value(ast_state, output), expr) return expr
def _compile_rule(rule_translation, rest): test, binding_translations, ctx_update, branch_translation = \ rule_translation if len(binding_translations) == 0: body = branch_translation else: body_lambda = astx.make_Lambda( (ctx_update[id][0] for id in binding_translations.iterkeys()), branch_translation) body = astx.make_simple_Call( body_lambda, binding_translations.values()) if len(rest) == 0: orelse = astx.expr_Raise_Exception_string("Match failure.") else: orelse = fn._compile_rule(rest[0], rest[1:]) return ast.IfExp( test=test, body=body, orelse=orelse)
def translate(node, st=None, strings=None, funcName=False): if isinstance(node, oast.Add): left = translate(node.left, st, strings, funcName) right = translate(node.right, st, strings, funcName) return ast.Add(left, right) elif isinstance(node, oast.And): left = translate(node.nodes[0], st, strings, funcName) right = translate(node.nodes[1], st, strings, funcName) return ast.And(left, right) elif isinstance(node, oast.Assign): # Translate the right hand side first so it can use the older version # of the left hand side. exp = translate(node.expr, st, strings, funcName) var = node.nodes.pop() if isinstance(var, oast.AssAttr): string = strings.setdefault(var.attrname, ast.String(var.attrname)) var = translate(var.expr, st, strings, funcName) return ast.SetAttr(var, string, exp) else: var = translate(var, st, strings, funcName) return ast.Assign(var, exp) elif isinstance(node, oast.AssName): return st.getSymbol(node.name, True) elif isinstance(node, oast.CallFunc): name = translate(node.node, st, strings, True) args = [translate(a, st, strings) for a in node.args] return ast.FunctionCall(name, *args) elif isinstance(node, oast.Class): bases = [translate(base, st, strings, funcName) for base in node.bases] body = translate(node.code, st, strings, funcName) body = ast.BasicBlock(body) sym = st.getSymbol(node.name, True) name = st.getName(node.name, True) # This is here temporarily. It will be moved to the typify pass # later. sym['type'] = 'class' klass = ast.Class(name, bases, body) return ast.Assign(sym, klass) elif isinstance(node, oast.Compare): left = translate(node.expr, st, strings, funcName) op, right = node.ops[0] right = translate(right, st, strings, funcName) if op == '==': return ast.Eq(left, right) elif op == '!=': return ast.Ne(left, right) elif op == 'is': return ast.Is(left, right) elif isinstance(node, oast.Const): return ast.Integer(node.value) elif isinstance(node, oast.Dict): pairs = {} for pair in node.items: key, value = pair key = translate(key, st, strings, funcName) value = translate(value, st, strings, funcName) pairs[key] = value return ast.Dictionary(pairs) elif isinstance(node, oast.Discard): return translate(node.expr, st, strings, funcName) elif isinstance(node, oast.Div): left = translate(node.left, st, strings, funcName) right = translate(node.right, st, strings, funcName) return ast.Div(left, right) elif isinstance(node, oast.Function): sym = st.getSymbol(node.name, True) name = st.getName(node.name, True) sym['type'] = 'function' newST = SymbolTable(st) argSymbols = [ newST.getSymbol(argName, True) for argName in node.argnames ] body = translate(node.code, newST, strings, funcName) body = ast.BasicBlock(body) fun = ast.Function(name, argSymbols, body, newST) fun['simplified'] = False st.update(newST) return ast.Assign(sym, fun) elif isinstance(node, oast.Getattr): exp = translate(node.expr, st, strings, funcName) name = strings.setdefault(node.attrname, ast.String(node.attrname)) return ast.GetAttr(exp, name) elif isinstance(node, oast.If): tests = node.tests cond, then = tests.pop(0) # Translate the conditional expression. cond = translate(cond, st, strings) # Snapshot the SymbolTable st.snapshot() # Translate the 'then' clause. then = translate(then, st, strings, funcName) then = ast.BasicBlock(then) # Roll-back the SymbolTable for the 'else' clause. st.rollback() # Translate the 'else' clause. if len(tests) > 0: els = [translate(oast.If(tests, node.else_), st, funcName)] else: els = translate(node.else_, st, strings, funcName) els = ast.BasicBlock(els) return ast.If(cond, then, els, st) elif isinstance(node, oast.IfExp): cond = translate(node.test, st, strings, funcName) then = translate(node.then, st, strings, funcName) els = translate(node.else_, st, strings, funcName) return ast.IfExp(cond, then, els) elif isinstance(node, oast.Lambda): name = st.getName('lambda', True) newST = SymbolTable(st) argSymbols = map(lambda name: newST.getSymbol(name, True), node.argnames) code = ast.Return(translate(node.code, newST, strings, funcName)) block = ast.BasicBlock([code]) fun = ast.Function(name, argSymbols, block, newST) fun['simplified'] = False st.update(newST) return fun elif isinstance(node, oast.List): elements = [] for n in node.nodes: elements.append(translate(n, st, strings, funcName)) return ast.List(elements) elif isinstance(node, oast.Module): # Create a new SymbolTable for this module. st = SymbolTable() strings = {} children = translate(node.node, st, strings, funcName) block = ast.BasicBlock(children) fun = ast.Function(st.getBIF('main'), [], block, st) # Mark the main function as migrated so that it doesn't get moved # later. fun['simplified'] = True return ast.Module([fun], strings) elif isinstance(node, oast.Mul): left = translate(node.left, st, strings, funcName) right = translate(node.right, st, strings, funcName) return ast.Mul(left, right) elif isinstance(node, oast.Name): ret = 'input_int' if node.name == 'input' else node.name if ret == 'input_int': ret = st.getBIF(ret) else: if ret == 'True': ret = ast.Tru() elif ret == 'False': ret = ast.Fals() else: ret = st.getSymbol(ret) return ret elif isinstance(node, oast.Not): operand = translate(node.expr, st, strings, funcName) return ast.Not(operand) elif isinstance(node, oast.Or): left = translate(node.nodes[0], st, strings, funcName) right = translate(node.nodes[1], st, strings, funcName) return ast.Or(left, right) elif isinstance(node, oast.Printnl): children = [ translate(e, st, strings, funcName) for e in node.getChildNodes() ] children = util.flatten(children) return ast.FunctionCall(st.getBIF('print_any'), *children) elif isinstance(node, oast.Return): return ast.Return(translate(node.value, st, strings, funcName)) elif isinstance(node, oast.Stmt): stmts = [ translate(s, st, strings, funcName) for s in node.getChildNodes() ] return util.flatten(stmts) elif isinstance(node, oast.Sub): left = translate(node.left, st, strings, funcName) right = translate(node.right, st, strings, funcName) return ast.Sub(left, right) elif isinstance(node, oast.Subscript): sym = translate(node.expr, st, strings, funcName) sub = translate(node.subs[0], st, strings, funcName) return ast.Subscript(sym, sub) elif isinstance(node, oast.While): cond = translate(node.test, st, strings, funcName) body = translate(node.body, st, strings, funcName) body = ast.BasicBlock(body) return ast.While(cond, body, st) elif isinstance(node, oast.UnarySub): operand = translate(node.expr, st, strings, funcName) return ast.Negate(operand) else: raise Exception("Unsupported AST node encountered: {}".format( node.__class__.__name__))
def as_ast(dct): """See https://docs.python.org/2/library/ast.html""" if dct['ast_type'] == "Module": return ast.Module(dct["body"]) elif dct['ast_type'] == "Interactive": return ast.Interactive(dct["body"]) elif dct['ast_type'] == "Expression": return ast.Expression(dct["body"]) elif dct['ast_type'] == "Suite": return ast.Suite(dct["body"]) elif dct['ast_type'] == "FunctionDef": return ast.FunctionDef(dct["name"], dct["args"], dct["body"], dct["decorator_list"]) elif dct['ast_type'] == "ClassDef": return ast.ClassDef(dct["name"], dct["bases"], dct["body"], dct["decorator_list"]) elif dct['ast_type'] == "Return": return ast.Return(dct["value"]) elif dct['ast_type'] == "Delete": return ast.Delete(dct["targets"]) elif dct['ast_type'] == "Assign": return ast.Assign(dct["targets"], dct["value"]) elif dct['ast_type'] == "AugAssign": return ast.AugAssign(dct["target"], dct["op"], dct["value"]) elif dct['ast_type'] == "Print": return ast.Print(dct["dest"], dct["values"], dct["nl"]) elif dct['ast_type'] == "For": return ast.For(dct["target"], dct["iter"], dct["body"], dct["orelse"]) elif dct['ast_type'] == "While": return ast.While(dct["test"], dct["body"], dct["orelse"]) elif dct['ast_type'] == "If": return ast.If(dct["test"], dct["body"], dct["orelse"]) elif dct['ast_type'] == "With": return ast.With(dct["context_expr"], dct["optional_vars"], dct["body"]) elif dct['ast_type'] == "Raise": return ast.Raise(dct["type"], dct["inst"], dct["tback"]) elif dct['ast_type'] == "TryExcept": return ast.TryExcept(dct["body"], dct["handlers"], dct["orelse"]) elif dct['ast_type'] == "TryFinally": return ast.TryFinally(dct["body"], dct["finalbody"]) elif dct['ast_type'] == "Assert": return ast.Assert(dct["test"], dct["msg"]) elif dct['ast_type'] == "Import": return ast.Import(dct["names"]) elif dct['ast_type'] == "ImportFrom": return ast.ImportFrom(dct["module"], dct["names"], dct["level"]) elif dct['ast_type'] == "Exec": return ast.Exec(dct["body"], dct["globals"], dct["locals"]) elif dct['ast_type'] == "Global": return ast.Global(dct["names"]) elif dct['ast_type'] == "Expr": return ast.Expr(dct["value"]) elif dct['ast_type'] == "Pass": return ast.Pass() elif dct['ast_type'] == "Break": return ast.Break() elif dct['ast_type'] == "Continue": return ast.Continue() elif dct['ast_type'] == "BoolOp": return ast.BoolOp(dct["op"], dct["values"]) elif dct['ast_type'] == "BinOp": return ast.BinOp(dct["left"], dct["op"], dct["right"]) elif dct['ast_type'] == "UnaryOp": return ast.UnaryOp(dct["op"], dct["operand"]) elif dct['ast_type'] == "Lambda": return ast.Lambda(dct["args"], dct["body"]) elif dct['ast_type'] == "IfExp": return ast.IfExp(dct["test"], dct["body"], dct["orelse"]) elif dct['ast_type'] == "Dict": return ast.Dict(dct["keys"], dct["values"]) elif dct['ast_type'] == "Set": return ast.Set(dct["elts"]) elif dct['ast_type'] == "ListComp": return ast.ListComp(dct["elt"], dct["generators"]) elif dct['ast_type'] == "SetComp": return ast.SetComp(dct["elt"], dct["generators"]) elif dct['ast_type'] == "DictComp": return ast.DictComp(dct["key"], dct["value"], dct["generators"]) elif dct['ast_type'] == "GeneratorExp": return ast.GeneratorExp(dct["elt"], dct["generators"]) elif dct['ast_type'] == "Yield": return ast.Yield(dct["value"]) elif dct['ast_type'] == "Compare": return ast.Compare(dct["left"], dct["ops"], dct["comparators"]) elif dct['ast_type'] == "Call": return ast.Call(dct["func"], dct["args"], dct["keywords"], dct["starargs"], dct["kwargs"]) elif dct['ast_type'] == "Repr": return ast.Repr(dct["value"]) elif dct['ast_type'] == "Num": return ast.Num(dct["n"]) elif dct['ast_type'] == "Str": # Converting to ASCII return ast.Str(dct["s"].encode('ascii', 'ignore')) elif dct['ast_type'] == "Attribute": return ast.Attribute(dct["value"], dct["attr"], dct["ctx"]) elif dct['ast_type'] == "Subscript": return ast.Subscript(dct["value"], dct["slice"], dct["ctx"]) elif dct['ast_type'] == "Name": return ast.Name(dct["id"], dct["ctx"]) elif dct['ast_type'] == "List": return ast.List(dct["elts"], dct["ctx"]) elif dct['ast_type'] == "Tuple": return ast.Tuple(dct["elts"], dct["ctx"]) elif dct['ast_type'] == "Load": return ast.Load() elif dct['ast_type'] == "Store": return ast.Store() elif dct['ast_type'] == "Del": return ast.Del() elif dct['ast_type'] == "AugLoad": return ast.AugLoad() elif dct['ast_type'] == "AugStore": return ast.AugStore() elif dct['ast_type'] == "Param": return ast.Param() elif dct['ast_type'] == "Ellipsis": return ast.Ellipsis() elif dct['ast_type'] == "Slice": return ast.Slice(dct["lower"], dct["upper"], dct["step"]) elif dct['ast_type'] == "ExtSlice": return ast.ExtSlice(dct["dims"]) elif dct['ast_type'] == "Index": return ast.Index(dct["value"]) elif dct['ast_type'] == "And": return ast.And() elif dct['ast_type'] == "Or": return ast.Or() elif dct['ast_type'] == "Add": return ast.Add() elif dct['ast_type'] == "Sub": return ast.Sub() elif dct['ast_type'] == "Mult": return ast.Mult() elif dct['ast_type'] == "Div": return ast.Div() elif dct['ast_type'] == "Mod": return ast.Mod() elif dct['ast_type'] == "Pow": return ast.Pow() elif dct['ast_type'] == "LShift": return ast.LShift() elif dct['ast_type'] == "RShift": return ast.RShift() elif dct['ast_type'] == "BitOr": return ast.BitOr() elif dct['ast_type'] == "BitXor": return ast.BitXor() elif dct['ast_type'] == "BitAnd": return ast.BitAnd() elif dct['ast_type'] == "FloorDiv": return ast.FloorDiv() elif dct['ast_type'] == "Invert": return ast.Invert() elif dct['ast_type'] == "Not": return ast.Not() elif dct['ast_type'] == "UAdd": return ast.UAdd() elif dct['ast_type'] == "USub": return ast.USub() elif dct['ast_type'] == "Eq": return ast.Eq() elif dct['ast_type'] == "NotEq": return ast.NotEq() elif dct['ast_type'] == "Lt": return ast.Lt() elif dct['ast_type'] == "LtE": return ast.LtE() elif dct['ast_type'] == "Gt": return ast.Gt() elif dct['ast_type'] == "GtE": return ast.GtE() elif dct['ast_type'] == "Is": return ast.Is() elif dct['ast_type'] == "IsNot": return ast.IsNot() elif dct['ast_type'] == "In": return ast.In() elif dct['ast_type'] == "NotIn": return ast.NotIn() elif dct['ast_type'] == "comprehension": return ast.comprehension(dct["target"], dct["iter"], dct["ifs"]) elif dct['ast_type'] == "ExceptHandler": return ast.ExceptHandler(dct["type"], dct["name"], dct["body"]) elif dct['ast_type'] == "arguments": return ast.arguments(dct["args"], dct["vararg"], dct["kwarg"], dct["defaults"]) elif dct['ast_type'] == "keyword": return ast.keyword(dct["arg"], dct["value"]) elif dct['ast_type'] == "alias": return ast.alias(dct["name"], dct["asname"]) else: return dct
def test_ifexp(self): py_ast = ast.IfExp(ast.Num(1), ast.Num(2), ast.Num(3)) c_ast = TernaryOp(Constant(1), Constant(2), Constant(3)) self._check(py_ast, c_ast)
def branch_dist_comp(test, args): if isinstance(test.ops[0], ast.Eq): op_type = 0 br_dist = ast.Call(func=ast.Name(id='abs'), args=[ ast.BinOp(left=test.left, op=ast.Sub(), right=test.comparators[0]) ], keywords=[], starags=None, kwargs=None) elif isinstance(test.ops[0], ast.NotEq): op_type = 1 br_dist = ast.UnaryOp(op=ast.USub(), operand=ast.Call( func=ast.Name(id='abs'), args=[ ast.BinOp(left=test.left, op=ast.Sub(), right=test.comparators[0]) ], keywords=[], starags=None, kwargs=None)) elif isinstance(test.ops[0], ast.Lt): op_type = 1 br_dist = ast.BinOp(left=test.left, op=ast.Sub(), right=test.comparators[0]) elif isinstance(test.ops[0], ast.LtE): op_type = 0 br_dist = ast.BinOp(left=test.left, op=ast.Sub(), right=test.comparators[0]) elif isinstance(test.ops[0], ast.Gt): op_type = 1 br_dist = ast.BinOp(left=test.comparators[0], op=ast.Sub(), right=test.left) elif isinstance(test.ops[0], ast.GtE): op_type = 0 br_dist = ast.BinOp(left=test.comparators[0], op=ast.Sub(), right=test.left) return ast.Call(func=ast.Lambda( args=ast.arguments( args=[ast.arg(arg=args.lambda_arg, annotation=None)], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=ast.IfExp(test=ast.Compare( left=ast.Name(id=args.lambda_arg), ops=[ast.LtE() if op_type == 0 else ast.Lt()], comparators=[ast.Num(n=0)]), body=ast.Name(id=args.lambda_arg), orelse=ast.BinOp(left=ast.Name(id=args.lambda_arg), op=ast.Add(), right=ast.Num(args.k)))), args=[br_dist], keywords=[])
def toPython(self): # Invert | Not | UAdd | USub unaryops = { 'invert': ast.Not, # 'invert': ast.Invert, # use bitwise op, not logical op 'neg': ast.USub } # And | Or boolops = {'and': ast.And, 'or': ast.Or} # Eq | NotEq | Lt | LtE | Gt | GtE # Is | IsNot | In | NotIn cmpops = { 'gt': ast.Gt, 'ge': ast.GtE, 'eq': ast.Eq, 'ne': ast.NotEq # lt and le are handled by their reverse operation } binops = { 'add': ast.Add, 'sub': ast.Sub, 'mul': ast.Mult, 'div': ast.Div, 'mod': ast.Mod, 'pow': ast.Pow, # translate to bit ops not "logical" ops # 'and': ast.BitAnd, # 'or': ast.BitOr } op = self.value ch = self.children args = [c.toPython() for c in ch] if op in unaryops: arg = args[0] # force conversion to int to workaround numba #238 # it fixes age * ~gender but breaks count(~gender) :( # if op == 'invert': # arg = ast.BinOp(arg, ast.Add(), ast.Num(0)) return ast.UnaryOp(unaryops[op](), arg) elif op in boolops: return ast.BoolOp(boolops[op](), args) elif op in cmpops: # Transform "var != var" to "not (var == var)". This is a # workaround for numba issue #247 "(a != a) is False for nan" # This is a weak workaround because it will only work for simple # variable, while it should work for all expressions that return # nans on both sides. if (ch[0].astType == 'variable' and ch[1].astType == 'variable' and ch[0].value == ch[1].value and op == 'ne'): comparison = ast.Compare(args[0], [cmpops['eq']()], [args[1]]) return ast.UnaryOp(ast.Not(), comparison) else: return ast.Compare(args[0], [cmpops[op]()], [args[1]]) elif op == 'ones_like': return ast.Num(1) elif op == 'real': return ast.Attribute(args[0], 'real', ast.Load()) elif op == 'imag': return ast.Attribute(args[0], 'imag', ast.Load()) else: binop = ast.BinOp(args[0], binops[op](), args[1]) # shield against integer division by 0 if (op == 'div' and ch[1].astKind in ('int', 'long') and ch[1].astType != 'constant'): return ast.IfExp(args[1], binop, ast.Num(0)) return binop
def from_phpast(node): if node is None: return py.Pass(**pos(node)) if isinstance(node, str): return py.Str(node, **pos(node)) if isinstance(node, (int, float)): return py.Num(node, **pos(node)) if isinstance(node, php.Array): if node.nodes: if node.nodes[0].key is not None: keys = [] values = [] for elem in node.nodes: keys.append(from_phpast(elem.key)) values.append(from_phpast(elem.value)) return py.Dict(keys, values, **pos(node)) else: return py.List([from_phpast(x.value) for x in node.nodes], py.Load(**pos(node)), **pos(node)) else: return py.List([], py.Load(**pos(node)), **pos(node)) if isinstance(node, php.InlineHTML): args = [py.Str(node.data, **pos(node))] return py.Call( py.Name('inline_html', py.Load(**pos(node)), **pos(node)), args, [], None, None, **pos(node)) if isinstance(node, php.Echo): return py.Call(py.Name('echo', py.Load(**pos(node)), **pos(node)), list(map(from_phpast, node.nodes)), [], None, None, **pos(node)) if isinstance(node, php.Print): return py.Print(None, [from_phpast(node.node)], True, **pos(node)) if isinstance(node, php.Exit): args = [] if node.expr is not None: args.append(from_phpast(node.expr)) return py.Raise( py.Call(py.Name('Exit', py.Load(**pos(node)), **pos(node)), args, [], None, None, **pos(node)), None, None, **pos(node)) if isinstance(node, php.Return): if node.node is None: return py.Return(None, **pos(node)) else: return py.Return(from_phpast(node.node), **pos(node)) if isinstance(node, php.Break): assert node.node is None, 'level on break not supported' return py.Break(**pos(node)) if isinstance(node, php.Continue): assert node.node is None, 'level on continue not supported' return py.Continue(**pos(node)) if isinstance(node, php.Silence): return from_phpast(node.expr) if isinstance(node, php.Block): return from_phpast(php.If(1, node, [], None, lineno=node.lineno)) if isinstance(node, php.Unset): return py.Delete(list(map(from_phpast, node.nodes)), **pos(node)) if isinstance(node, php.IsSet) and len(node.nodes) == 1: if isinstance(node.nodes[0], php.ArrayOffset): return py.Compare(from_phpast(node.nodes[0].expr), [py.In(**pos(node))], [from_phpast(node.nodes[0].node)], **pos(node)) if isinstance(node.nodes[0], php.ObjectProperty): return py.Call( py.Name('hasattr', py.Load(**pos(node)), **pos(node)), [ from_phpast(node.nodes[0].node), from_phpast(node.nodes[0].name) ], [], None, None, **pos(node)) if isinstance(node.nodes[0], php.Variable): return py.Compare(py.Str( node.nodes[0].name[1:], **pos(node)), [py.In(**pos(node))], [ py.Call(py.Name('vars', py.Load(**pos(node)), **pos(node)), [], [], None, None, **pos(node)) ], **pos(node)) return py.Compare(from_phpast(node.nodes[0]), [py.IsNot(**pos(node))], [py.Name('None', py.Load(**pos(node)), **pos(node))], **pos(node)) if isinstance(node, php.Empty): return from_phpast( php.UnaryOp('!', php.BinaryOp('&&', php.IsSet([node.expr], lineno=node.lineno), node.expr, lineno=node.lineno), lineno=node.lineno)) if isinstance(node, php.Assignment): if (isinstance(node.node, php.ArrayOffset) and node.node.expr is None): return py.Call( py.Attribute(from_phpast(node.node.node), 'append', py.Load(**pos(node)), **pos(node)), [from_phpast(node.expr)], [], None, None, **pos(node)) if (isinstance(node.node, php.ObjectProperty) and isinstance(node.node.name, php.BinaryOp)): return to_stmt( py.Call(py.Name('setattr', py.Load(**pos(node)), **pos(node)), [ from_phpast(node.node.node), from_phpast(node.node.name), from_phpast(node.expr) ], [], None, None, **pos(node))) return py.Assign([store(from_phpast(node.node))], from_phpast(node.expr), **pos(node)) if isinstance(node, php.ListAssignment): return py.Assign([ py.Tuple(list(map(store, list(map(from_phpast, node.nodes)))), py.Store(**pos(node)), **pos(node)) ], from_phpast(node.expr), **pos(node)) if isinstance(node, php.AssignOp): return from_phpast( php.Assignment(node.left, php.BinaryOp(node.op[:-1], node.left, node.right, lineno=node.lineno), False, lineno=node.lineno)) if isinstance(node, (php.PreIncDecOp, php.PostIncDecOp)): return from_phpast( php.Assignment(node.expr, php.BinaryOp(node.op[0], node.expr, 1, lineno=node.lineno), False, lineno=node.lineno)) if isinstance(node, php.ArrayOffset): return py.Subscript(from_phpast(node.node), py.Index(from_phpast(node.expr), **pos(node)), py.Load(**pos(node)), **pos(node)) if isinstance(node, php.ObjectProperty): if isinstance(node.name, (php.Variable, php.BinaryOp)): return py.Call( py.Name('getattr', py.Load(**pos(node)), **pos(node)), [from_phpast(node.node), from_phpast(node.name)], [], None, None, **pos(node)) return py.Attribute(from_phpast(node.node), node.name, py.Load(**pos(node)), **pos(node)) if isinstance(node, php.Constant): name = node.name if name.lower() == 'true': name = 'True' if name.lower() == 'false': name = 'False' if name.lower() == 'null': name = 'None' return py.Name(name, py.Load(**pos(node)), **pos(node)) if isinstance(node, php.Variable): name = node.name[1:] if name == 'this': name = 'self' return py.Name(name, py.Load(**pos(node)), **pos(node)) if isinstance(node, php.Global): return py.Global([var.name[1:] for var in node.nodes], **pos(node)) if isinstance(node, php.Include): once = py.Name('True' if node.once else 'False', py.Load(**pos(node)), **pos(node)) return py.Call(py.Name('include', py.Load(**pos(node)), **pos(node)), [from_phpast(node.expr), once], [], None, None, **pos(node)) if isinstance(node, php.Require): once = py.Name('True' if node.once else 'False', py.Load(**pos(node)), **pos(node)) return py.Call(py.Name('require', py.Load(**pos(node)), **pos(node)), [from_phpast(node.expr), once], [], None, None, **pos(node)) if isinstance(node, php.UnaryOp): op = unary_ops.get(node.op) assert op is not None, "unknown unary operator: '%s'" % node.op op = op(**pos(node)) return py.UnaryOp(op, from_phpast(node.expr), **pos(node)) if isinstance(node, php.BinaryOp): if node.op == '.': pattern, pieces = build_format(node.left, node.right) if pieces: return py.BinOp( py.Str(pattern, **pos(node)), py.Mod(**pos(node)), py.Tuple(list(map(from_phpast, pieces)), py.Load(**pos(node)), **pos(node)), **pos(node)) else: return py.Str(pattern % (), **pos(node)) if node.op in bool_ops: op = bool_ops[node.op](**pos(node)) return py.BoolOp(op, [from_phpast(node.left), from_phpast(node.right)], **pos(node)) if node.op in cmp_ops: op = cmp_ops[node.op](**pos(node)) return py.Compare(from_phpast(node.left), [op], [from_phpast(node.right)], **pos(node)) op = binary_ops.get(node.op) if node.op == 'instanceof': return py.Call( func=py.Name(id='isinstance', ctx=py.Load(**pos(node))), args=[from_phpast(node.left), from_phpast(node.right)], keywords=[], starargs=None, kwargs=None) assert op is not None, "unknown binary operator: '%s'" % node.op op = op(**pos(node)) return py.BinOp(from_phpast(node.left), op, from_phpast(node.right), **pos(node)) if isinstance(node, php.TernaryOp): return py.IfExp(from_phpast(node.expr), from_phpast(node.iftrue), from_phpast(node.iffalse), **pos(node)) if isinstance(node, php.Cast): return py.Call( py.Name(casts.get(node.type, node.type), py.Load(**pos(node)), **pos(node)), [from_phpast(node.expr)], [], None, None, **pos(node)) if isinstance(node, php.If): orelse = [] if node.else_: for else_ in map(from_phpast, deblock(node.else_.node)): orelse.append(to_stmt(else_)) for elseif in reversed(node.elseifs): orelse = [ py.If( from_phpast(elseif.expr), list( map(to_stmt, list(map(from_phpast, deblock(elseif.node))))), orelse, **pos(node)) ] return py.If( from_phpast(node.expr), list(map(to_stmt, list(map(from_phpast, deblock(node.node))))), orelse, **pos(node)) if isinstance(node, php.For): assert node.test is None or len(node.test) == 1, \ 'only a single test is supported in for-loops' return from_phpast( php.Block((node.start or []) + [ php.While(node.test[0] if node.test else 1, php.Block(deblock(node.node) + (node.count or []), lineno=node.lineno), lineno=node.lineno) ], lineno=node.lineno)) if isinstance(node, php.Foreach): if node.keyvar is None: target = py.Name(node.valvar.name[1:], py.Store(**pos(node)), **pos(node)) else: target = py.Tuple([ py.Name(node.keyvar.name[1:], py.Store(**pos(node))), py.Name(node.valvar.name[1:], py.Store(**pos(node))) ], py.Store(**pos(node)), **pos(node)) return py.For( target, from_phpast(node.expr), list(map(to_stmt, list(map(from_phpast, deblock(node.node))))), [], **pos(node)) if isinstance(node, php.While): return py.While( from_phpast(node.expr), list(map(to_stmt, list(map(from_phpast, deblock(node.node))))), [], **pos(node)) if isinstance(node, php.DoWhile): condition = php.If(php.UnaryOp('!', node.expr, lineno=node.lineno), php.Break(None, lineno=node.lineno), [], None, lineno=node.lineno) return from_phpast( php.While(1, php.Block(deblock(node.node) + [condition], lineno=node.lineno), lineno=node.lineno)) if isinstance(node, php.Try): return py.TryExcept( list(map(to_stmt, list(map(from_phpast, node.nodes)))), [ py.ExceptHandler( py.Name(catch.class_, py.Load(**pos(node)), **pos(node)), store(from_phpast(catch.var)), list(map(to_stmt, list(map(from_phpast, catch.nodes)))), **pos(node)) for catch in node.catches ], [], **pos(node)) if isinstance(node, php.Throw): return py.Raise(from_phpast(node.node), None, None, **pos(node)) if isinstance(node, php.Function): args = [] defaults = [] for param in node.params: args.append( py.Name(param.name[1:], py.Param(**pos(node)), **pos(node))) if param.default is not None: defaults.append(from_phpast(param.default)) body = list(map(to_stmt, list(map(from_phpast, node.nodes)))) if not body: body = [py.Pass(**pos(node))] return py.FunctionDef(node.name, py.arguments(args, None, None, defaults), body, [], **pos(node)) if isinstance(node, php.Method): args = [] defaults = [] decorator_list = [] if 'static' in node.modifiers: decorator_list.append( py.Name('classmethod', py.Load(**pos(node)), **pos(node))) args.append(py.Name('cls', py.Param(**pos(node)), **pos(node))) else: args.append(py.Name('self', py.Param(**pos(node)), **pos(node))) for param in node.params: args.append( py.Name(param.name[1:], py.Param(**pos(node)), **pos(node))) if param.default is not None: defaults.append(from_phpast(param.default)) body = list(map(to_stmt, list(map(from_phpast, node.nodes)))) if not body: body = [py.Pass(**pos(node))] return py.FunctionDef(node.name, py.arguments(args, None, None, defaults), body, decorator_list, **pos(node)) if isinstance(node, php.Class): name = node.name bases = [] extends = node.extends or 'object' bases.append(py.Name(extends, py.Load(**pos(node)), **pos(node))) body = list(map(to_stmt, list(map(from_phpast, node.nodes)))) for stmt in body: if (isinstance(stmt, py.FunctionDef) and stmt.name in (name, '__construct')): stmt.name = '__init__' if not body: body = [py.Pass(**pos(node))] return py.ClassDef(name, bases, body, [], **pos(node)) if isinstance(node, (php.ClassConstants, php.ClassVariables)): assert len(node.nodes) == 1, \ 'only one class-level assignment supported per line' if isinstance(node.nodes[0], php.ClassConstant): name = php.Constant(node.nodes[0].name, lineno=node.lineno) else: name = php.Variable(node.nodes[0].name, lineno=node.lineno) initial = node.nodes[0].initial if initial is None: initial = php.Constant('None', lineno=node.lineno) return py.Assign([store(from_phpast(name))], from_phpast(initial), **pos(node)) if isinstance(node, (php.FunctionCall, php.New)): if isinstance(node.name, str): name = py.Name(node.name, py.Load(**pos(node)), **pos(node)) else: name = py.Subscript( py.Call(py.Name('vars', py.Load(**pos(node)), **pos(node)), [], [], None, None, **pos(node)), py.Index(from_phpast(node.name), **pos(node)), py.Load(**pos(node)), **pos(node)) args, kwargs = build_args(node.params) return py.Call(name, args, kwargs, None, None, **pos(node)) if isinstance(node, php.MethodCall): args, kwargs = build_args(node.params) return py.Call( py.Attribute(from_phpast(node.node), node.name, py.Load(**pos(node)), **pos(node)), args, kwargs, None, None, **pos(node)) if isinstance(node, php.StaticMethodCall): class_ = node.class_ if class_ == 'self': class_ = 'cls' args, kwargs = build_args(node.params) return py.Call( py.Attribute(py.Name(class_, py.Load(**pos(node)), **pos(node)), node.name, py.Load(**pos(node)), **pos(node)), args, kwargs, None, None, **pos(node)) if isinstance(node, php.StaticProperty): class_ = node.node name = node.name if isinstance(name, php.Variable): name = name.name[1:] return py.Attribute(py.Name(class_, py.Load(**pos(node)), **pos(node)), name, py.Load(**pos(node)), **pos(node)) return py.Call(py.Name('XXX', py.Load(**pos(node)), **pos(node)), [py.Str(str(node), **pos(node))], [], None, None, **pos(node))
def test_IfExp(self): if_expr = ast.IfExp(ast.Num(1), ast.Num(2), ast.Num(3)) self.verify(if_expr, '2 if 1 else 3')
def test_ifexp(self): l = ast.Name("x", ast.Load()) s = ast.Name("y", ast.Store()) for args in (s, l, l), (l, s, l), (l, l, s): self.expr(ast.IfExp(*args), "must have Load context")
def make_if_expression(): """IfExp(expr test, expr body, expr orelse)""" return ast.IfExp(test=make_expression(), body=make_expression(), orelse=make_expression())
def make_test(test, body, orelse): return ast.IfExp(test, body, orelse)
def If(test, body, orelse): return ast.IfExp(test, body, orelse)
def astAndTypeForCStatement(funcEnv, stmnt): assert isinstance(stmnt, CStatement) if stmnt._leftexpr is None: # prefixed only rightAstNode, rightType = astAndTypeForStatement( funcEnv, stmnt._rightexpr) if stmnt._op.content == "++": return getAstNode_prefixInc(rightAstNode, rightType), rightType elif stmnt._op.content == "--": return getAstNode_prefixDec(rightAstNode, rightType), rightType elif stmnt._op.content == "*": while isinstance(rightType, CTypedefType): rightType = funcEnv.globalScope.stateStruct.typedefs[ rightType.name] if isinstance(rightType, CPointerType): return getAstNodeAttrib(rightAstNode, "contents"), rightType.pointerOf elif isinstance(rightType, CFuncPointerDecl): return rightAstNode, rightType # we cannot really dereference a funcptr with ctypes ... else: assert False, str(stmnt) + " has bad type " + str(rightType) elif stmnt._op.content == "&": return makeAstNodeCall(getAstNodeAttrib("ctypes", "pointer"), rightAstNode), CPointerType(rightType) elif stmnt._op.content in OpUnary: a = ast.UnaryOp() a.op = OpUnary[stmnt._op.content]() if isPointerType(rightType): assert stmnt._op.content == "!", "the only supported unary op for ptr types is '!'" a.operand = makeAstNodeCall( ast.Name(id="bool", ctx=ast.Load()), rightAstNode) rightType = ctypes.c_int else: a.operand = getAstNode_valueFromObj( funcEnv.globalScope.stateStruct, rightAstNode, rightType) return getAstNode_newTypeInstance(funcEnv.interpreter, rightType, a), rightType else: assert False, "unary prefix op " + str(stmnt._op) + " is unknown" if stmnt._op is None: return astAndTypeForStatement(funcEnv, stmnt._leftexpr) if stmnt._rightexpr is None: leftAstNode, leftType = astAndTypeForStatement(funcEnv, stmnt._leftexpr) if stmnt._op.content == "++": return getAstNode_postfixInc(leftAstNode, leftType), leftType elif stmnt._op.content == "--": return getAstNode_postfixDec(leftAstNode, leftType), leftType else: assert False, "unary postfix op " + str(stmnt._op) + " is unknown" leftAstNode, leftType = astAndTypeForStatement(funcEnv, stmnt._leftexpr) rightAstNode, rightType = astAndTypeForStatement(funcEnv, stmnt._rightexpr) if stmnt._op.content == "=": return getAstNode_assign(funcEnv.globalScope.stateStruct, leftAstNode, leftType, rightAstNode, rightType), leftType elif stmnt._op.content in OpAugAssign: return getAstNode_augAssign(funcEnv.globalScope.stateStruct, leftAstNode, leftType, stmnt._op.content, rightAstNode, rightType), leftType elif stmnt._op.content in OpBinBool: a = ast.BoolOp() a.op = OpBinBool[stmnt._op.content]() a.values = [ getAstNode_valueFromObj(funcEnv.globalScope.stateStruct, leftAstNode, leftType), getAstNode_valueFromObj(funcEnv.globalScope.stateStruct, rightAstNode, rightType) ] return getAstNode_newTypeInstance(funcEnv.interpreter, ctypes.c_int, a), ctypes.c_int elif stmnt._op.content in OpBinCmp: a = ast.Compare() a.ops = [OpBinCmp[stmnt._op.content]()] a.left = getAstNode_valueFromObj(funcEnv.globalScope.stateStruct, leftAstNode, leftType) a.comparators = [ getAstNode_valueFromObj(funcEnv.globalScope.stateStruct, rightAstNode, rightType) ] return getAstNode_newTypeInstance(funcEnv.interpreter, ctypes.c_int, a), ctypes.c_int elif stmnt._op.content == "?:": middleAstNode, middleType = astAndTypeForStatement( funcEnv, stmnt._middleexpr) a = ast.IfExp() a.test = getAstNode_valueFromObj(funcEnv.globalScope.stateStruct, leftAstNode, leftType) a.body = middleAstNode a.orelse = rightAstNode # TODO: we take the type from middleType right now. not really correct... # So, cast the orelse part. a.orelse = getAstNode_newTypeInstance(funcEnv.interpreter, middleType, a.orelse, rightType) return a, middleType elif isPointerType(leftType): return getAstNode_ptrBinOpExpr(funcEnv.globalScope.stateStruct, leftAstNode, leftType, stmnt._op.content, rightAstNode, rightType), leftType elif stmnt._op.content in OpBin: a = ast.BinOp() a.op = OpBin[stmnt._op.content]() a.left = getAstNode_valueFromObj(funcEnv.globalScope.stateStruct, leftAstNode, leftType) a.right = getAstNode_valueFromObj(funcEnv.globalScope.stateStruct, rightAstNode, rightType) return getAstNode_newTypeInstance( funcEnv.interpreter, leftType, a), leftType # TODO: not really correct. e.g. int + float -> float else: assert False, "binary op " + str(stmnt._op) + " is unknown"
def IfThenElse(self, node): return ast.IfExp(test=self(node.test), body=self(node.iftrue), orelse=self(node.iffalse), **_linearg)