def visit_Compare(self, node): """ Args: node: Returns: """ # Handle left and right left = self.visit(node.left) comparators = [self.visit(compare) for compare in node.comparators] # Handle ops for op, right in zip(node.ops, comparators): if isinstance(op, (ast.Eq, ast.NotEq, ast.Is, ast.IsNot)): continue elif isinstance(op, (ast.Lt, ast.LtE, ast.GtE, ast.Gt)): if are_types_equal(left, right): if isinstance(left, ORDERABLE_TYPES): continue elif isinstance(op, (ast.In, ast.NotIn)): if isinstance(right, INDEXABLE_TYPES): continue self._issue( incompatible_types(self.locate(), op, left, right, report=self.report)) return BoolType()
def visit_Name(self, node): """ Args: node: Returns: """ name = node.id if name == "___": self._issue(unconnected_blocks(self.locate())) if isinstance(node.ctx, ast.Load): if name == "True" or name == "False": return BoolType() elif name == "None": return NoneType() else: variable = self.find_variable_scope(name) builtin = get_builtin_function(name) if not variable.exists and builtin: return builtin else: state = self.load_variable(name) return state.type else: variable = self.find_variable_scope(name) if variable.exists: return variable.state.type else: return UnknownType()
def visit_Bool(self, node): """ Visit a constant boolean value. Args: node (ast.AST): The boolean value Node. Returns: Type: A Bool type. """ return BoolType()
def visit_NameConstant(self, node): """ Args: node: Returns: """ value = node.value if isinstance(value, bool): return BoolType() else: return NoneType()
def get_pedal_type_from_json(val): """ Args: val: Returns: """ if val['type'] == 'DictType': values = [get_pedal_type_from_json(v) for v in val['values']] empty = val.get('empty', None) if 'literals' in val: literals = [ get_pedal_literal_from_json(l) for l in val['literals'] ] return DictType(empty, literals=literals, values=values) else: keys = [get_pedal_type_from_json(k) for k in val['keys']] return DictType(empty, keys=keys, values=values) elif val['type'] == 'ListType': return ListType(get_pedal_type_from_json(val.get('subtype', None)), val.get('empty', None)) elif val['type'] == 'StrType': return StrType(val.get('empty', None)) elif val['type'] == 'BoolType': return BoolType() elif val['type'] == 'NoneType': return NoneType() elif val['type'] == 'NumType': return NumType() elif val['type'] == 'ModuleType': submodules = { name: get_pedal_type_from_json(m) for name, m in val.get('submodules', {}).items() } fields = { name: get_pedal_type_from_json(m) for name, m in val.get('fields', {}).items() } return ModuleType(name=val.get('name'), submodules=submodules, fields=fields) elif val['type'] == 'FunctionType': returns = get_pedal_type_from_json( val.get('returns', {'type': 'NoneType'})) return FunctionType(name=val.get('name'), returns=returns)
def visit_BoolOp(self, node): """ Args: node: Returns: """ # Handle left and right values = [] for value in node.values: values.append(self.visit(value)) # TODO: Truthiness is not supported! Probably need a Union type # TODO: Literals used as truthy value # Handle operation return BoolType()
def get_pedal_type_from_value(value, type_space=None) -> Type: """ Converts the Python value to a Pedal Type """ if isinstance(value, bool): return BoolType() if isinstance(value, (int, float, complex)): return NumType() if isinstance(value, str): return StrType() if isinstance(value, type(None)): return NoneType() if isinstance(value, tuple): return TupleType( (get_pedal_type_from_value(t, type_space) for t in value)) if isinstance(value, set): return SetType( (get_pedal_type_from_value(t, type_space) for t in value)) if isinstance(value, frozenset): return FrozenSetType( (get_pedal_type_from_value(t, type_space) for t in value)) if isinstance(value, list): if value: return ListType(empty=False, subtype=get_pedal_type_from_value(value[0])) else: return ListType(empty=True) if isinstance(value, dict): if not value: return DictType(empty=True) if all(isinstance(value, str) for k in value.keys()): return DictType(literals=[LiteralStr(s) for s in value.keys()], values=[ get_pedal_type_from_value(vv, type_space) for vv in value.values() ]) return DictType(keys=[ get_pedal_type_from_ast(k, type_space) for k in value.keys() ], values=[ get_pedal_type_from_ast(vv, type_space) for vv in value.values() ]) return UnknownType()
def visit_UnaryOp(self, node): """ Args: node: Returns: """ # Handle operand operand = self.visit(node.operand) if isinstance(node.op, ast.Not): return BoolType() elif isinstance(operand, UnknownType): return UnknownType() elif type(node.op) in VALID_UNARYOP_TYPES: op_lookup = VALID_UNARYOP_TYPES[type(node.op)] if type(operand) in op_lookup: return op_lookup[type(operand)]() return UnknownType()
def BoolType_any(*x): """ Ignores all parameters to return a BoolType """ return BoolType()
def get_builtin_function(name): """ Args: name: Returns: """ # Void Functions if name == "print": return FunctionType(name="print", returns=NoneType()) # Math Functions elif name in ("int", "abs", "float", "len", "ord", "pow", "round", "sum"): return FunctionType(name=name, returns=NumType()) # Boolean Functions elif name in ("bool", "all", "any", "isinstance"): return FunctionType(name=name, returns=BoolType()) # String Functions elif name in ("str", 'chr', 'bin', 'repr', 'input'): return FunctionType(name=name, returns=StrType()) # File Functions elif name == "open": return FunctionType(name="open", returns=FileType()) # List Functions elif name == "map": return FunctionType(name="map", returns=ListType(empty=False)) elif name == "list": return FunctionType(name="list", definition=_builtin_sequence_constructor(ListType)) # Set Functions elif name == "set": return FunctionType(name="set", definition=_builtin_sequence_constructor(SetType)) # Dict Functions elif name == "dict": return FunctionType(name="dict", returns=DictType()) # Pass through elif name == "sorted": return FunctionType(name="sorted", returns='identity') elif name == "reversed": return FunctionType(name="reversed", returns='identity') elif name == "filter": return FunctionType(name="filter", returns='identity') # Special Functions elif name == "type": return FunctionType(name="type", returns=UnknownType()) elif name == "range": return FunctionType(name="range", returns=ListType(NumType(), empty=False)) elif name == "dir": return FunctionType(name="dir", returns=ListType(StrType(), empty=False)) elif name == "max": return FunctionType(name="max", returns='element') elif name == "min": return FunctionType(name="min", returns='element') elif name == "zip": return FunctionType(name="zip", returns=_builtin_zip) elif name == "__import__": return FunctionType(name="__import__", returns=ModuleType()) elif name == "globals": return FunctionType(name="globals", returns=DictType(keys=StrType(), values=UnknownType(), empty=False)) elif name in ("classmethod", "staticmethod"): return FunctionType(name=name, returns='identity') elif name in ("__name__", ): return StrType()
}), 'math': ModuleType('math', fields={ 'ceil': FunctionType(name='ceil', returns=NumType()), 'copysign': FunctionType(name='copysign', returns=NumType()), 'fabs': FunctionType(name='fabs', returns=NumType()), 'factorial': FunctionType(name='factorial', returns=NumType()), 'floor': FunctionType(name='floor', returns=NumType()), 'fmod': FunctionType(name='fmod', returns=NumType()), 'frexp': FunctionType(name='frexp', returns=NumType()), 'fsum': FunctionType(name='fsum', returns=NumType()), 'gcd': FunctionType(name='gcd', returns=NumType()), 'isclose': FunctionType(name='isclose', returns=BoolType()), 'isfinite': FunctionType(name='isfinite', returns=BoolType()), 'isinf': FunctionType(name='isinf', returns=BoolType()), 'isnan': FunctionType(name='isnan', returns=BoolType()), 'ldexp': FunctionType(name='ldexp', returns=NumType()), 'modf': FunctionType(name='modf', returns=NumType()), 'trunc': FunctionType(name='trunc', returns=NumType()), 'log': FunctionType(name='log', returns=NumType()), 'log1p': FunctionType(name='log1p', returns=NumType()), 'log2': FunctionType(name='log2', returns=NumType()), 'log10': FunctionType(name='log10', returns=NumType()), 'pow': FunctionType(name='pow', returns=NumType()), 'sqrt': FunctionType(name='sqrt', returns=NumType()), 'sin': FunctionType(name='sin', returns=NumType()), 'cos': FunctionType(name='cos', returns=NumType()),