def sequence_call(tifa, function_type, callee, args, position): # TODO: Should inherit the emptiness too return_type = sequence_type(empty=True) if args: return_type.subtype = args[0].index(LiteralNum(0)) return_type.empty = False return return_type
def action(target, type): if isinstance(target, ast.Name): self.store_variable(target.id, type) elif isinstance(target, (ast.Tuple, ast.List)): for i, elt in enumerate(target.elts): eltType = type.index(LiteralNum(i)) action(elt, eltType) elif isinstance(target, ast.Subscript): pass
def action(target, type): if isinstance(target, ast.Name): self.store_variable(target.id, type) elif isinstance(target, (ast.Tuple, ast.List)): for i, elt in enumerate(target.elts): eltType = type.index(LiteralNum(i)) action(elt, eltType) elif isinstance(target, ast.Subscript): pass elif isinstance(target, ast.Attribute): left_hand_type = self.visit(target.value) if isinstance(left_hand_type, InstanceType): left_hand_type.add_attr(target.attr, type)
def _walk_target(self, target, type): """ Recursively apply the type to the target Args: target (Ast): The current AST node to process type (Type): The type to apply to this node """ if isinstance(target, ast.Name): self.store_iter_variable(target.id, type, self.locate(target)) return target.id elif isinstance(target, (ast.Tuple, ast.List)): result = None for i, elt in enumerate(target.elts): elt_type = type.index(LiteralNum(i)) potential_name = self._walk_target(elt, elt_type) if potential_name is not None and result is None: result = potential_name return result
def get_literal(self, node): if isinstance(node, ast.Num): return LiteralNum(node.n) elif isinstance(node, ast.Str): return LiteralStr(node.s) elif isinstance(node, ast.Tuple): values = [] for elt in node.elts: subvalue = self.get_literal(elt) if subvalue is not None: values.append(subvalue) else: return None return LiteralTuple(values) elif isinstance(node, ast.Name): if node.id == "None": return LiteralNone() elif node.id == "False": return LiteralBool(False) elif node.id == "True": return LiteralBool(True) return None
def _visit_collection_loop(self, node): # Handle the iteration list iter = node.iter iter_list_name = None if isinstance(iter, ast.Name): iter_list_name = iter.id if iter_list_name == "___": self.report_issue("Unconnected blocks", {"position": self.locate(iter)}) state = self.iterate_variable(iter_list_name, self.locate(iter)) iter_type = state.type else: iter_type = self.visit(iter) if iter_type.is_empty(): self.report_issue("Iterating over empty list", { "name": iter_list_name, "position": self.locate(iter) }) if not isinstance(iter_type, INDEXABLE_TYPES): self.report_issue("Iterating over non-list", { "name": iter_list_name, "position": self.locate(iter) }) iter_subtype = iter_type.index(LiteralNum(0)) # Handle the iteration variable iter_variable_name = self._walk_target(node.target, iter_subtype) if iter_variable_name and iter_list_name: if iter_variable_name == iter_list_name: self.report_issue( "Iteration Problem", { "name": iter_variable_name, "position": self.locate(node.target) })