def _attr_lookup(self, attr, value): if "__" not in attr: return Compare( left=Attribute(value=Name(id="self", **self.file), attr=attr, **self.file), ops=[Eq()], comparators=[self.build_expression(value)], **self.file, ) attr, lookup = attr.split("__", 1) if lookup == "isnull": return Compare( left=Attribute(value=Name(id="self", **self.file), attr=attr, **self.file), ops=[Is() if value else IsNot()], comparators=[ Constant(value=None, **self.file) # Name(id="None", **self.file) ], **self.file, ) if lookup == "exact": return self._attr_lookup(attr, value) raise ValueError("Unhandled attr lookup")
def compBreaker(self, node): assert isinstance(node, Compare) if len(node.comparators) == 1: return node else: comp1 = Compare(node.left, node.ops[0:1], node.comparators[0:1]) comp2 = Compare(node.comparators[0], node.ops[1:], node.comparators[1:]) newNode = BoolOp(And(), [comp1, self.compBreaker(comp2)]) return newNode
def _if_gt(value): if value >= 0: comparators = [Constant(value=value, kind=None)] else: comparators = [ UnaryOp( op=USub(), operand=Constant(value=abs(value), kind=None), ), ] return [ If( test=Compare( left=Call( func=Name(id='int', ctx=Load()), args=[Name(id='value', ctx=Load())], keywords=[], ), ops=[Gt()], comparators=comparators, ), body=[ Return(value=Constant(value=False, kind=None), ), ], orelse=[], ) ]
def _generate_assignment((arg_name, arg_resource_handle)): # type: (Tuple[basestring, int]) -> If """ We have a function that looks like: def do_something(param, model_=INJECTED): <...> We insert into its beginning a statement like ___INJECT_CONTEXT_INTERNAL_RESOURCES = ___INJECT_CONTEXT_INTERNAL.resources if model_ is INJECTED: model_ = ___INJECT_CONTEXT_INTERNAL_RESOURCES[3] if model is ___INJECT_CONTEXT_INTERNAL: # means that no resource is available ___INJECT_CONTEXT_INTERNAL_RESOURCES.flag_missing('model_') Code outside of this function sets a global variable _INJECTED__model to point at the right thing. """ target_attribute = Subscript( value=Name(id=INTERNAL_RESOURCES_NAME, ctx=Load()), slice=Index(value=Num(n=arg_resource_handle)), ctx=Load()) consequence = [ Assign(targets=[Name(id=arg_name, ctx=Store())], value=target_attribute), If(test=Compare( left=Name(id=arg_name, ctx=Load()), ops=[Is()], comparators=[Name(id=INTERNAL_CONTEXT_NAME, ctx=Load())]), body=[ Expr(value=Call(func=Attribute(value=Name( id=INTERNAL_CONTEXT_NAME, ctx=Load()), attr='flag_missing', ctx=Load()), keywords=[], starargs=None, kwargs=None, args=[Str(s=arg_name)])) ], orelse=[]) ] # type: List[Union[Assign, If] return If(test=Compare( left=Name(id=arg_name, ctx=Load()), ops=[Is()], comparators=[default_nodes_mapping[arg_name]]), body=consequence, orelse=[])
def visit_Compare(self, compare: ast.Compare) -> Optional[IType]: """ Verifies if the types of the operands are valid to the compare operations If the operations are valid, changes de Python operator by the Boa operator in the syntax tree :param compare: the python ast compare operation node :return: the type of the result of the operation if the operation is valid. Otherwise, returns None :rtype: IType or None """ if len(compare.comparators) != len(compare.ops): self._log_error( CompilerError.IncorrectNumberOfOperands( compare.lineno, compare.col_offset, len(compare.ops), len(compare.comparators) + 1 # num comparators + compare.left ) ) line = compare.lineno col = compare.col_offset try: return_type = None l_operand = self.visit_value(compare.left) for index, op in enumerate(compare.ops): operator: Operator = self.get_operator(op) r_operand = self.visit_value(compare.comparators[index]) if not isinstance(operator, Operator): # the operator is invalid or it was not implemented yet self._log_error( CompilerError.UnresolvedReference(line, col, type(op).__name__) ) operation: IOperation = self.get_bin_op(operator, r_operand, l_operand) if operation is None: self._log_error( CompilerError.NotSupportedOperation(line, col, operator) ) elif not operation.is_supported: # TODO: is, is not and eq were not implemented yet self._log_error( CompilerError.NotSupportedOperation(line, col, operator) ) else: compare.ops[index] = operation return_type = operation.result line = compare.comparators[index].lineno col = compare.comparators[index].col_offset l_operand = r_operand return return_type except CompilerError.MismatchedTypes as raised_error: raised_error.line = line raised_error.col = col # raises the exception with the line/col info self._log_error(raised_error)
def emit(self): assign = IfExp(test=Compare( left=Str(s=self.name), ops=[In()], comparators=[Call(func=Name(id="dir", ctx=Load()))]), body=Name(id=self.name, ctx=Load()), orelse=Call(func=Name(id='Void', ctx=Load()))) return Log.log(self.name, assign)
def visit_Compare(self, node): self.generic_visit(node) unitcalc = UnitCalculator(self.localDict) leftUD = unitcalc.getUnitAndDim(node.left) listUD = [unitcalc.getUnitAndDim(comp) for comp in node.comparators] nonNoneDims = [ud[1] for ud in listUD + [leftUD] if ud[1] is not None] for dims in nonNoneDims: checkDimensions(nonNoneDims[0], dims) factorlist = [ud[0] / leftUD[0] for ud in listUD] newComplist = [withFactor(*t) \ for t in zip(factorlist, node.comparators)] compOp = Compare(node.left, node.ops, newComplist) compOpTrans = self.compBreaker(compOp) return compOpTrans
def comparison(self, c): x: Union[Tree, Name] y: Union[Tree, Name] check: Token x, check, y = c func = { '==': Eq, '!=': NotEq, '<': Lt, '<=': LtE, '>': Gt, '>=': GtE, }.get(check.value, None) if isinstance(x, list): x = x[0] if isinstance(x, Tree): if x.data == 'var': x = x.children[0] if isinstance(y, list): temp = [] for i in y: if isinstance(i, Tree): if i.data == 'var': i = i.children[0] if isinstance(i, Name): i = self.LoadName(i.id) temp.append(i) y = temp if isinstance(y, Tree): if y.data == 'var': y = y.children[0] if isinstance(x, Name): x = self.LoadName(x.id) if isinstance(y, Name): y = self.LoadName(y.id) if func is not None: return Compare(left=x, ops=[func()], comparators=y) else: raise TypeError(f'Unrecognised comparison operator: {check.value}')
def setter_body(item): """Construct the body of the setter function. """ new_value = Name(id="new", ctx=ast.Load()) inst_var = Attribute(value=Name(id="self", ctx=ast.Load()), attr=f"_{item.var}", ctx=ast.Store()) comp_node = Compare( left=Num(n=item.lower), ops=[ast.Lt(), ast.Lt()], comparators=[new_value, Num(n=item.upper)], ) assign_stmt = ast.Assign(targets=[inst_var], value=new_value) except_msg = f"value outside of range {item.lower} < {item.var} < {item.upper}" exc = ast.Call( func=Name(id="ValueError", ctx=ast.Load()), args=[ast.Str(s=except_msg)], keywords=[], ) else_body = ast.Raise(exc=exc, cause=None) if_node = ast.If(test=comp_node, body=[assign_stmt], orelse=[else_body]) return if_node
def _if_length(self, minimum, maximum): return [ If( test=Compare( left=Constant(value=int(minimum), kind=None), ops=[ Gt(), Gt(), ], comparators=[ Call( func=Name(id='len', ctx=Load()), args=[Name(id='value', ctx=Load())], keywords=[], ), Constant(value=int(maximum), kind=None), ], ), body=[ Return(value=Constant(value=False, kind=None), ), ], orelse=[], ), ]
def handle_f(self, f): # Do we need to use .attname here? # What about transforms/lookups? f.contains_aggregate = False if "__" in f.name: # We need to chain a bunch of attr lookups, returning None # if any of them give us a None, we should be returning a None. # # . while x is not None and parts: # . x = getattr(x, parts.pop(0), None) # return x return [ Assign(targets=[Name(id="source", **self.file_store)], value=Name(id="self", **self.file), **self.file), Assign( targets=[Name(id="parts", **self.file_store)], value=Call( func=Attribute(value=Constant(value=f.name, **self.file), attr="split", **self.file), args=[Constant(value="__", **self.file)], keywords=[], kwonlyargs=[], **self.file, ), **self.file, ), While( test=BoolOp( op=And(), values=[ Compare( left=Name(id="source", **self.file), ops=[IsNot()], comparators=[ Constant(value=None, **self.file) ], **self.file, ), Name(id="parts", **self.file), ], **self.file, ), body=[ Assign( targets=[Name(id="source", **self.file_store)], value=Call( func=Name(id="getattr", **self.file), args=[ Name(id="source", **self.file), Call( func=Attribute(value=Name(id="parts", **self.file), attr="pop", **self.file), args=[Constant(value=0, **self.file)], keywords=[], kwonlyargs=[], **self.file, ), Constant(value=None, **self.file), ], keywords=[], kwonlyargs=[], **self.file, ), **self.file, ), ], orelse=[], **self.file, ), Return(value=Name(id="source", **self.file), **self.file), ] return Attribute(value=Name(id="self", **self.file), attr=f.name, **self.file)
def comparison(ra, ctx, op): return Compare( left=convert(ra[0], ctx), ops=[op], comparators=[convert(ra[1], ctx)], )
def empty_script_tree(project_id: str, add_main_loop: bool = True) -> Module: """Creates barebones of the script (empty 'main' function). Returns ------- """ main_body: List[stmt] = [ Assign( targets=[Name(id="aps", ctx=Store())], value=Call(func=Name(id="ActionPoints", ctx=Load()), args=[Name(id="res", ctx=Load())], keywords=[]), type_comment=None, ) ] if add_main_loop: main_body.append( While(test=NameConstant(value=True, kind=None), body=[Pass()], orelse=[])) else: """put there "pass" in order to make code valid even if there is no other statement (e.g. no object from resources)""" main_body.append(Pass()) # TODO helper function for try ... except tree = Module( body=[ FunctionDef( name="main", args=arguments( args=[ arg(arg="res", annotation=Name(id=RES_CLS, ctx=Load()), type_comment=None) ], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[], ), body=main_body, decorator_list=[], returns=NameConstant(value=None, kind=None), type_comment=None, ), If( test=Compare(left=Name(id="__name__", ctx=Load()), ops=[Eq()], comparators=[Str(s="__main__", kind="")]), body=[ Try( body=[ With( items=[ withitem( context_expr=Call( func=Name(id=RES_CLS, ctx=Load()), args=[Str(s=project_id, kind="")], keywords=[], ), optional_vars=Name(id="res", ctx=Store()), ) ], body=[ Expr(value=Call( func=Name(id="main", ctx=Load()), args=[Name(id="res", ctx=Load())], keywords=[], )) ], type_comment=None, ) ], handlers=[ ExceptHandler( type=Name(id=Exception.__name__, ctx=Load()), name="e", body=[ Expr(value=Call( func=Name(id=arcor2.exceptions.runtime. print_exception.__name__, ctx=Load()), args=[Name(id="e", ctx=Load())], keywords=[], )) ], ) ], orelse=[], finalbody=[], ) ], orelse=[], ), ], type_ignores=[], ) add_import(tree, arcor2.exceptions.runtime.__name__, arcor2.exceptions.runtime.print_exception.__name__) add_import(tree, RES_MODULE, RES_CLS, try_to_import=False) add_import(tree, "action_points", "ActionPoints", try_to_import=False) return tree
def _(ra: ras.Join, ctx: Context): # Function body_ast = ast.parse(inspect.getsource(MERGE_EQUI_JOIN_FUNC)) # Loop body merge_func_ast = body_ast.body[0] merge_func_ast.name = unique_name('merge') # Create row comparison func_name = unique_name('cmp') func_args = [ ast.arg(arg='left', annotation=None), ast.arg(arg='right', annotation=None), ] # val = ast.BinOp( # left=convert(ra.operands[0].operands[1], ctx, var_name='left'), # op=ast.Sub(), # right=convert(ra.operands[1].operands[1], ctx, var_name='right'), # ) # func_return = ast.Return(value=val) left = convert(ra.operands[0].operands[1], ctx, var_name='left') right = convert(ra.operands[1].operands[1], ctx, var_name='right') if_statement = ast.If( test=Compare(left=left, ops=[ ast.Lt(), ], comparators=[ right, ]), body=[ ast.Return(value=ast.UnaryOp(op=ast.USub(), operand=ast.Num(n=1))), ], orelse=[ ast.If(test=Compare(left=left, ops=[ ast.Gt(), ], comparators=[ right, ]), body=[ ast.Return(value=ast.Num(n=1)), ], orelse=[ ast.Return(value=ast.Num(n=0)), ]), ]) func_cmp = FunctionDef(name=func_name, args=ast.arguments(args=func_args, vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[if_statement], decorator_list=[], returns=None) merge_func_ast.body.insert(0, func_cmp) # Inject functions body_ast = ast_transformer.FindAndReplaceNames({ '__cmp_func__': func_cmp, }).visit(body_ast) ast.fix_missing_locations(body_ast) logger.debug(astor.to_source(body_ast)) return body_ast
def _add_logic(container: Container, current_action: Action, super_container: Optional[Container] = None) -> None: # more paths could lead to the same action, so it might be already added # ...this is easier than searching the tree if current_action.id in added_actions: logger.debug( f"Action {current_action.name} already added, skipping.") return inputs, outputs = project.action_io(current_action.id) logger.debug( f"Adding action {current_action.name}, with {len(inputs)} input(s) and {len(outputs)} output(s)." ) act = current_action.parse_type() ac_obj = scene.object(act.obj_id).name args: List[AST] = [] # TODO make sure that the order of parameters is correct / re-order for param in current_action.parameters: if param.type == ActionParameter.TypeEnum.LINK: parsed_link = param.parse_link() parent_action = project.action(parsed_link.action_id) # TODO add support for tuples assert len(parent_action.flow(FlowTypes.DEFAULT).outputs ) == 1, "Only one result is supported atm." assert parsed_link.output_index == 0 res_name = parent_action.flow(FlowTypes.DEFAULT).outputs[0] # make sure that the result already exists if parent_action.id not in added_actions: raise SourceException( f"Action {current_action.name} attempts to use result {res_name} " f"of subsequent action {parent_action.name}.") args.append(Name(id=res_name, ctx=Load())) elif param.type == ActionParameter.TypeEnum.PROJECT_PARAMETER: args.append( Name(id=project.parameter(param.str_from_value()).name, ctx=Load())) else: plugin = plugin_from_type_name(param.type) args.append( plugin.parameter_ast(type_defs, scene, project, current_action.id, param.name)) list_of_imp_tup = plugin.need_to_be_imported( type_defs, scene, project, current_action.id, param.name) if list_of_imp_tup: # TODO what if there are two same names? for imp_tup in list_of_imp_tup: add_import(tree, imp_tup.module_name, imp_tup.class_name, try_to_import=False) add_method_call( container.body, ac_obj, act.action_type, args, [keyword(arg="an", value=Str(s=current_action.name, kind=""))], current_action.flow(FlowTypes.DEFAULT).outputs, ) added_actions.add(current_action.id) if not outputs: raise SourceException( f"Action {current_action.name} has no outputs.") elif len(outputs) == 1: output = outputs[0] if output.end == output.END: # TODO this is just temporary (while there is while loop), should be rather Return() container.body.append(Continue()) return seq_act = project.action(output.end) seq_act_inputs, _ = project.action_io(seq_act.id) if len(seq_act_inputs ) > 1: # the action belongs to a different block if seq_act.id in added_actions: return logger.debug( f"Action {seq_act.name} going to be added to super_container." ) # test if this is the correct super_container -> count distance (number of blocks) to the START blocks_to_start: Dict[str, int] = {} for inp in seq_act_inputs: parsed_start = inp.parse_start() pact = project.action(parsed_start.start_action_id) blocks_to_start[pact.id] = _blocks_to_start(pact) winner = min(blocks_to_start, key=blocks_to_start.get ) # type: ignore # TODO what is wrong with it? # TODO if blocks_to_start is cached somewhere, the second part of the condition is useless # it might happen that there are two different ways with the same distance if winner == current_action.id or all( value == list(blocks_to_start.values())[0] for value in blocks_to_start.values()): assert super_container is not None _add_logic(super_container, seq_act) return logger.debug(f"Sequential action: {seq_act.name}") _add_logic(container, seq_act, super_container) else: root_if: Optional[If] = None # action has more outputs - each output should have condition for idx, output in enumerate(outputs): if not output.condition: raise SourceException("Missing condition.") # TODO use parameter plugin (action metadata will be needed - to get the return types) # TODO support for other countable types # ...this will only work for booleans from arcor2 import json condition_value = json.loads(output.condition.value) comp = NameConstant(value=condition_value, kind=None) what = output.condition.parse_what() output_name = project.action(what.action_id).flow( what.flow_name).outputs[what.output_index] cond = If( test=Compare(left=Name(id=output_name, ctx=Load()), ops=[Eq()], comparators=[comp]), body=[], orelse=[], ) if idx == 0: root_if = cond container.body.append(root_if) logger.debug(f"Adding branch for: {condition_value}") else: assert isinstance(root_if, If) root_if.orelse.append(cond) if output.end == output.END: cond.body.append( Continue()) # TODO should be rather return continue _add_logic(cond, project.action(output.end), container)
""" if __name__ == "__main__": mod = Module(body=[ FunctionDef(name='F_6', args=arguments(args=[ arg(arg='x', annotation=Name(id='int', ctx=Load())), arg(arg='y', annotation=None) ], vararg=arg(arg='args', annotation=List(elts=[ Name(id='str', ctx=Load()) ], ctx=Load())), kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[]), body=[ Return(value=Compare(left=Name(id='x', ctx=Load()), ops=[Eq()], comparators=[Num(n=6)])) ], decorator_list=[], returns=Name(id='bool', ctx=Load())) ]) expr_ast = parse(expr) print(expr_ast) print(f"{dump(expr_ast)}\n") print(unparse(mod))
def boolexpr(self, tree): from ast import Compare return Compare(tree[0], [tree[1]], comparators=[tree[2]])