Remove Dictionaries
Remove parsing and evaluating of Dictionaries
This commit is contained in:
parent
2b840ff8b9
commit
238980d602
19
ppp_ast.py
19
ppp_ast.py
@ -209,25 +209,6 @@ class LoopComprehension(Expression):
|
|||||||
|
|
||||||
def precedence(self) -> int: return 13
|
def precedence(self) -> int: return 13
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class DictionaryExpr(Expression):
|
|
||||||
dict: List[Tuple[Expression, Expression]]
|
|
||||||
|
|
||||||
def represent(self) -> str: assert False
|
|
||||||
|
|
||||||
def precedence(self) -> int: return 13
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class DictComprehension(Expression):
|
|
||||||
body: Tuple[Expression, Expression]
|
|
||||||
variable: str # TODO: Pattern matching
|
|
||||||
array: Expression
|
|
||||||
|
|
||||||
def represent(self) -> str:
|
|
||||||
assert False, ("Unimplemented")
|
|
||||||
|
|
||||||
def precedence(self) -> int: return 13
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Return(Expression):
|
class Return(Expression):
|
||||||
expression: Expression
|
expression: Expression
|
||||||
|
@ -3,11 +3,11 @@ from typing import Dict, List as List_, Optional, Tuple, Union
|
|||||||
|
|
||||||
from ppp_ast import *
|
from ppp_ast import *
|
||||||
from ppp_lexer import Lexer
|
from ppp_lexer import Lexer
|
||||||
from ppp_object import Bool, Dictionary, EnumValue, Function, Hashable, Int, Object, Str, Struct, Tuple as TupleObject, List as ListObject, Return as ReturnObject, TypeObject, Dictionary as DictionaryObject, Void
|
from ppp_object import Bool, EnumValue, Function, Hashable, Int, Object, Str, Struct, Tuple as TupleObject, List as ListObject, Return as ReturnObject, TypeObject, Void
|
||||||
from ppp_parser import is_valid_target, parse_statement
|
from ppp_parser import is_valid_target, parse_statement
|
||||||
from ppp_tokens import EofToken
|
from ppp_tokens import EofToken
|
||||||
from ppp_stdlib import variables
|
from ppp_stdlib import variables
|
||||||
from ppp_types import DictionaryType, EnumType, FunctionType, GenericType, Int as IntType, ListType, ReturnType, Str as StrType, StructType, TupleType, Type, TypeType, UnionType, VariableType, Void as VoidType
|
from ppp_types import EnumType, FunctionType, GenericType, Int as IntType, ListType, ReturnType, Str as StrType, StructType, TupleType, Type, TypeType, UnionType, VariableType, Void as VoidType
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Declared:
|
class Declared:
|
||||||
@ -279,14 +279,6 @@ def calculate_expression(expression: Expression, program: ProgramState) -> Objec
|
|||||||
element = array.list[index.num]
|
element = array.list[index.num]
|
||||||
assert element.get_type().is_subtype_of(array_type)
|
assert element.get_type().is_subtype_of(array_type)
|
||||||
return element
|
return element
|
||||||
elif isinstance(array, DictionaryObject):
|
|
||||||
index = calculate_expression(index_, program)
|
|
||||||
assert index.get_type().is_subtype_of(array.type.key_type)
|
|
||||||
index_h = index.hash()
|
|
||||||
assert index_h in array.dict, f"{index} is not in {array}! {array_}, {index_}"
|
|
||||||
value = array.dict[index_h]
|
|
||||||
assert value.get_type().is_subtype_of(array.type.value_type)
|
|
||||||
return value
|
|
||||||
else:
|
else:
|
||||||
assert False, "Unreachable"
|
assert False, "Unreachable"
|
||||||
case Bnot(expression_):
|
case Bnot(expression_):
|
||||||
@ -328,73 +320,11 @@ def calculate_expression(expression: Expression, program: ProgramState) -> Objec
|
|||||||
else:
|
else:
|
||||||
elements_type = elements[-1].get_type()
|
elements_type = elements[-1].get_type()
|
||||||
|
|
||||||
if not elements: return ListObject(ListType(VariableType("")), [])
|
|
||||||
assert elements_type
|
|
||||||
return ListObject(ListType(elements_type), elements)
|
|
||||||
elif isinstance(array, Dictionary):
|
|
||||||
elements = []
|
|
||||||
elements_type = None
|
|
||||||
for element_h in array.dict:
|
|
||||||
element = element_h.get_object()
|
|
||||||
program.push_context({variable: Declared.from_obj(element)})
|
|
||||||
elements.append(calculate_expression(body_, program))
|
|
||||||
program.pop_context()
|
|
||||||
if elements_type:
|
|
||||||
assert elements[-1].get_type().is_subtype_of(elements_type)
|
|
||||||
else:
|
|
||||||
elements_type = elements[-1].get_type()
|
|
||||||
|
|
||||||
if not elements: return ListObject(ListType(VariableType("")), [])
|
if not elements: return ListObject(ListType(VariableType("")), [])
|
||||||
assert elements_type
|
assert elements_type
|
||||||
return ListObject(ListType(elements_type), elements)
|
return ListObject(ListType(elements_type), elements)
|
||||||
else:
|
else:
|
||||||
assert False, ("Unimplemented", array)
|
assert False, ("Unimplemented", array)
|
||||||
case DictionaryExpr(dict_):
|
|
||||||
dict: Dict[Hashable, Object] = {}
|
|
||||||
if not dict_:
|
|
||||||
return Dictionary(DictionaryType(VariableType(""), VariableType("")), {})
|
|
||||||
key_type, value_type = None, None
|
|
||||||
for (key_, value_) in dict_:
|
|
||||||
key = calculate_expression(key_, program)
|
|
||||||
value = calculate_expression(value_, program)
|
|
||||||
if key_type:
|
|
||||||
assert value_type, "Unreachable"
|
|
||||||
assert key.get_type().is_subtype_of(key_type)
|
|
||||||
assert value.get_type().is_subtype_of(value_type)
|
|
||||||
else:
|
|
||||||
assert not value_type
|
|
||||||
key_type = key.get_type()
|
|
||||||
value_type = value.get_type()
|
|
||||||
dict[key.hash()] = value
|
|
||||||
assert key_type and value_type
|
|
||||||
assert not (isinstance(key_type, VariableType) and key_type.name == '')
|
|
||||||
return Dictionary(DictionaryType(key_type, value_type), dict)
|
|
||||||
case DictComprehension(body_, variable, array_):
|
|
||||||
array = calculate_expression(array_, program)
|
|
||||||
assert array.get_type().is_indexable()
|
|
||||||
if isinstance(array, ListObject):
|
|
||||||
key_, value_ = body_
|
|
||||||
dict_entries: Dict[Hashable, Object] = {}
|
|
||||||
key_type = None
|
|
||||||
value_type = None
|
|
||||||
for element in array.list:
|
|
||||||
program.push_context({variable: Declared.from_obj(element)})
|
|
||||||
key = calculate_expression(key_, program)
|
|
||||||
key_h = key.hash()
|
|
||||||
dict_entries[key_h] = calculate_expression(value_, program)
|
|
||||||
program.pop_context()
|
|
||||||
if key_type:
|
|
||||||
assert value_type
|
|
||||||
assert key.get_type().is_subtype_of(key_type)
|
|
||||||
assert dict_entries[key_h].get_type().is_subtype_of(value_type)
|
|
||||||
else:
|
|
||||||
assert not value_type
|
|
||||||
key_type = key.get_type()
|
|
||||||
value_type = dict_entries[key_h].get_type()
|
|
||||||
if not dict_entries: return Dictionary(DictionaryType(VariableType(""), VariableType("")), {})
|
|
||||||
assert key_type and value_type
|
|
||||||
assert not (isinstance(key_type, VariableType) and key_type.name == '')
|
|
||||||
return Dictionary(DictionaryType(key_type, value_type), dict_entries)
|
|
||||||
case _:
|
case _:
|
||||||
assert False, ("Unimplemented", expression)
|
assert False, ("Unimplemented", expression)
|
||||||
assert False
|
assert False
|
||||||
@ -515,17 +445,6 @@ def interpret_statements(statements: List_[Statement], program: ProgramState) ->
|
|||||||
value = calculate_expression(rhs, program)
|
value = calculate_expression(rhs, program)
|
||||||
assert array.get_type().is_indexable(), array
|
assert array.get_type().is_indexable(), array
|
||||||
match array:
|
match array:
|
||||||
case Dictionary(dict_type, dict_):
|
|
||||||
try:
|
|
||||||
index_h = index.hash()
|
|
||||||
except AssertionError:
|
|
||||||
assert False, (array_, index_, index, dict_)
|
|
||||||
if isinstance(dict_type.key_type, VariableType) and dict_type.key_type.name == "":
|
|
||||||
dict_type.key_type, dict_type.value_type = index.get_type(), value.get_type()
|
|
||||||
assert index.get_type().is_subtype_of(dict_type.key_type), (index, dict_type.key_type)
|
|
||||||
assert value.get_type().is_subtype_of(dict_type.value_type), (value, dict_type.value_type)
|
|
||||||
|
|
||||||
dict_[index_h] = value
|
|
||||||
case _: assert False, ("Unimplemented", array)
|
case _: assert False, ("Unimplemented", array)
|
||||||
case _:
|
case _:
|
||||||
assert False, ("Unimplemented", lhs)
|
assert False, ("Unimplemented", lhs)
|
||||||
@ -633,17 +552,6 @@ def interpret_statements(statements: List_[Statement], program: ProgramState) ->
|
|||||||
case NothingResult(): pass
|
case NothingResult(): pass
|
||||||
case ReturnResult(_): return return_value
|
case ReturnResult(_): return return_value
|
||||||
case _: assert False, ("Unimplemented", return_value)
|
case _: assert False, ("Unimplemented", return_value)
|
||||||
elif isinstance(array, Dictionary):
|
|
||||||
for value_h in array.dict:
|
|
||||||
value = value_h.get_object()
|
|
||||||
assert value.get_type().is_subtype_of(array.type.key_type)
|
|
||||||
program.push_context({variable: Declared.from_obj(value)})
|
|
||||||
return_value = interpret_statements([body], program)
|
|
||||||
program.pop_context()
|
|
||||||
match return_value:
|
|
||||||
case NothingResult(): pass
|
|
||||||
case ReturnResult(_): return return_value
|
|
||||||
case _: assert False, ("Unimplemented", return_value)
|
|
||||||
case ContinueStatement(): return ContinueResult()
|
case ContinueStatement(): return ContinueResult()
|
||||||
case BreakStatement(): return BreakResult()
|
case BreakStatement(): return BreakResult()
|
||||||
case Import(file_):
|
case Import(file_):
|
||||||
|
@ -5,7 +5,7 @@ from dataclasses import dataclass
|
|||||||
from typing import Callable, Dict, List as List_, Tuple as Tuple_, Union as Union_
|
from typing import Callable, Dict, List as List_, Tuple as Tuple_, Union as Union_
|
||||||
|
|
||||||
from ppp_ast import Statement
|
from ppp_ast import Statement
|
||||||
from ppp_types import ArrayType, DictionaryType, EnumType, FunctionType, ListType, ReturnType, StructType, TupleType, Type, Int as IntType, Str as StrType, Bool as BoolType, Void as VoidType, TypeType
|
from ppp_types import ArrayType, EnumType, FunctionType, ListType, ReturnType, StructType, TupleType, Type, Int as IntType, Str as StrType, Bool as BoolType, Void as VoidType, TypeType
|
||||||
|
|
||||||
class Object(ABC):
|
class Object(ABC):
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
@ -99,14 +99,6 @@ class Struct(Object):
|
|||||||
|
|
||||||
def get_type(self) -> Type: return self.type
|
def get_type(self) -> Type: return self.type
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Dictionary(Object):
|
|
||||||
type: DictionaryType
|
|
||||||
dict: 'Dict[Hashable, Object]'
|
|
||||||
|
|
||||||
def get_type(self) -> Type: return self.type
|
|
||||||
|
|
||||||
|
|
||||||
class Hashable(ABC):
|
class Hashable(ABC):
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def __hash__(self) -> int: ...
|
def __hash__(self) -> int: ...
|
||||||
@ -136,6 +128,6 @@ class HEnumValue(Hashable):
|
|||||||
|
|
||||||
def __hash__(self) -> int:
|
def __hash__(self) -> int:
|
||||||
return hash(('object', 'enum', self.type, self.name, tuple(self.values)))
|
return hash(('object', 'enum', self.type, self.name, tuple(self.values)))
|
||||||
|
|
||||||
def get_object(self) -> Object:
|
def get_object(self) -> Object:
|
||||||
return EnumValue(self.type, self.name, [value.get_object() for value in self.values])
|
return EnumValue(self.type, self.name, [value.get_object() for value in self.values])
|
||||||
|
@ -134,26 +134,6 @@ def parse_primary(lexer: Lexer) -> Expression:
|
|||||||
expressions.append(parse_expression(lexer))
|
expressions.append(parse_expression(lexer))
|
||||||
lexer.assert_token(SymbolToken(Symbol.CloseSquare))
|
lexer.assert_token(SymbolToken(Symbol.CloseSquare))
|
||||||
base_expression = Array(expressions)
|
base_expression = Array(expressions)
|
||||||
elif lexer.take_token(SymbolToken(Symbol.OpenCurly)):
|
|
||||||
if lexer.take_token(SymbolToken(Symbol.CloseCurly)):
|
|
||||||
base_expression = DictionaryExpr([])
|
|
||||||
else:
|
|
||||||
def parse_dict_entry() -> Tuple[Expression, Expression]:
|
|
||||||
key = parse_expression(lexer)
|
|
||||||
lexer.assert_token(SymbolToken(Symbol.Colon))
|
|
||||||
return (key, parse_expression(lexer))
|
|
||||||
dict_entries: List[Tuple[Expression, Expression]] = [parse_dict_entry()]
|
|
||||||
if lexer.take_token(KeywordToken(Keyword.For)):
|
|
||||||
variable = parse_identifier(lexer) # TODO: Pattern matching
|
|
||||||
lexer.assert_token(KeywordToken(Keyword.In))
|
|
||||||
expression = parse_expression(lexer)
|
|
||||||
lexer.assert_token(SymbolToken(Symbol.CloseCurly))
|
|
||||||
base_expression = DictComprehension(dict_entries[0], variable, expression)
|
|
||||||
else:
|
|
||||||
while lexer.take_token(SymbolToken(Symbol.Comma)):
|
|
||||||
dict_entries.append(parse_dict_entry())
|
|
||||||
lexer.assert_token(SymbolToken(Symbol.CloseCurly))
|
|
||||||
base_expression = DictionaryExpr(dict_entries)
|
|
||||||
elif lexer.check_tokenkind(StringToken):
|
elif lexer.check_tokenkind(StringToken):
|
||||||
base_expression = String(parse_string(lexer))
|
base_expression = String(parse_string(lexer))
|
||||||
elif lexer.check_tokenkind(NumberToken):
|
elif lexer.check_tokenkind(NumberToken):
|
||||||
|
@ -2,7 +2,7 @@ from typing import Callable, Dict, List, Tuple
|
|||||||
|
|
||||||
from ppp_ast import Statements
|
from ppp_ast import Statements
|
||||||
from ppp_object import Bool, EnumValue, Int, Object, Function, Str, TypeObject, Void, List as ListObject
|
from ppp_object import Bool, EnumValue, Int, Object, Function, Str, TypeObject, Void, List as ListObject
|
||||||
from ppp_types import Bool as BoolType, DictionaryType, FunctionType, GenericType, Int as IntType, Str as StrType, Type, TypeType, VariableType, Void as VoidType, Object as ObjectType, UnionType, ListType
|
from ppp_types import Bool as BoolType, FunctionType, GenericType, Int as IntType, Str as StrType, Type, TypeType, VariableType, Void as VoidType, Object as ObjectType, UnionType, ListType
|
||||||
|
|
||||||
|
|
||||||
def PythonFunction(name: str, parameters: List[Tuple[str, Type]], return_type: Type, func: Callable[..., Object]) -> Object:
|
def PythonFunction(name: str, parameters: List[Tuple[str, Type]], return_type: Type, func: Callable[..., Object]) -> Object:
|
||||||
@ -30,7 +30,7 @@ DebugPrint = PythonFunction("debug_print", [('object', ObjectType)], VoidType, d
|
|||||||
def read_impl(str_: Object) -> Object:
|
def read_impl(str_: Object) -> Object:
|
||||||
assert isinstance(str_, Str)
|
assert isinstance(str_, Str)
|
||||||
with open(str_.str) as f: return Str(f.read())
|
with open(str_.str) as f: return Str(f.read())
|
||||||
|
|
||||||
Read = PythonFunction("read", [('file_path', StrType)], StrType, read_impl)
|
Read = PythonFunction("read", [('file_path', StrType)], StrType, read_impl)
|
||||||
|
|
||||||
def len_impl(list_: Object) -> Object:
|
def len_impl(list_: Object) -> Object:
|
||||||
@ -74,7 +74,7 @@ def id_impl(obj: Object) -> Object:
|
|||||||
match obj:
|
match obj:
|
||||||
case EnumValue(_, _, _): return Int(id(obj))
|
case EnumValue(_, _, _): return Int(id(obj))
|
||||||
case _: assert False, ("Unimplemented", obj)
|
case _: assert False, ("Unimplemented", obj)
|
||||||
|
|
||||||
|
|
||||||
Id = PythonFunction("id", [('object', ObjectType)], IntType, id_impl)
|
Id = PythonFunction("id", [('object', ObjectType)], IntType, id_impl)
|
||||||
|
|
||||||
@ -82,7 +82,6 @@ StrTypeObj = TypeObject(StrType)
|
|||||||
IntTypeObj = TypeObject(IntType)
|
IntTypeObj = TypeObject(IntType)
|
||||||
VoidTypeObj = TypeObject(VoidType)
|
VoidTypeObj = TypeObject(VoidType)
|
||||||
BoolTypeObj = TypeObject(BoolType)
|
BoolTypeObj = TypeObject(BoolType)
|
||||||
DictTypeObj = TypeObject(GenericType([VariableType("K"), VariableType("V")], DictionaryType(VariableType("K"), VariableType("V"))))
|
|
||||||
|
|
||||||
True_ = Bool(True)
|
True_ = Bool(True)
|
||||||
False_ = Bool(False)
|
False_ = Bool(False)
|
||||||
@ -98,7 +97,6 @@ variables: Dict[str, Object] = {
|
|||||||
'int': IntTypeObj,
|
'int': IntTypeObj,
|
||||||
'bool': BoolTypeObj,
|
'bool': BoolTypeObj,
|
||||||
'void': VoidTypeObj,
|
'void': VoidTypeObj,
|
||||||
'dict': DictTypeObj,
|
|
||||||
'debug_print': DebugPrint,
|
'debug_print': DebugPrint,
|
||||||
'read': Read,
|
'read': Read,
|
||||||
'len': Len,
|
'len': Len,
|
||||||
@ -107,4 +105,4 @@ variables: Dict[str, Object] = {
|
|||||||
'range': Range,
|
'range': Range,
|
||||||
'join_by': JoinBy,
|
'join_by': JoinBy,
|
||||||
'id': Id
|
'id': Id
|
||||||
}
|
}
|
||||||
|
61
ppp_types.py
61
ppp_types.py
@ -18,7 +18,7 @@ class Type(ABC):
|
|||||||
for (self_argument, other_argument) in zip(self_arguments, other_arguments):
|
for (self_argument, other_argument) in zip(self_arguments, other_arguments):
|
||||||
if not other_argument.is_subtype_of(self_argument): return False
|
if not other_argument.is_subtype_of(self_argument): return False
|
||||||
return self_return_type.is_subtype_of(other_return_type)
|
return self_return_type.is_subtype_of(other_return_type)
|
||||||
case EnumType(self_name, self_members), EnumType(other_name, other_members):
|
case EnumType(self_name, self_members), EnumType(other_name, other_members):
|
||||||
# if self_name == other_name: assert self is other, (num_expressions, self, other, self_name, other_name, self_members, other_members)
|
# if self_name == other_name: assert self is other, (num_expressions, self, other, self_name, other_name, self_members, other_members)
|
||||||
return self is other
|
return self is other
|
||||||
return self_name == other_name
|
return self_name == other_name
|
||||||
@ -45,9 +45,6 @@ class Type(ABC):
|
|||||||
if type.is_subtype_of(union_type): return True
|
if type.is_subtype_of(union_type): return True
|
||||||
return False
|
return False
|
||||||
case BoolType(), BoolType(): return True
|
case BoolType(), BoolType(): return True
|
||||||
case DictionaryType(self_key_type, self_value_type), DictionaryType(other_key_type, other_value_type):
|
|
||||||
if isinstance(self_key_type, VariableType) and self_key_type.name == "" and isinstance(self_value_type, VariableType) and self_value_type.name == "": return True
|
|
||||||
return other_key_type.is_subtype_of(self_key_type) and self_value_type.is_subtype_of(other_value_type)
|
|
||||||
case type, ObjectType(): return True
|
case type, ObjectType(): return True
|
||||||
case type_a, type_b if type_a.__class__ != type_b.__class__: return False
|
case type_a, type_b if type_a.__class__ != type_b.__class__: return False
|
||||||
case _, _: assert False, ("Unimplemented", self, other)
|
case _, _: assert False, ("Unimplemented", self, other)
|
||||||
@ -69,7 +66,7 @@ class Type(ABC):
|
|||||||
new_types = [type.new_fill(types, stack+[id(self)]) for type in type_list]
|
new_types = [type.new_fill(types, stack+[id(self)]) for type in type_list]
|
||||||
is_new = any([new_type[0] for new_type in new_types])
|
is_new = any([new_type[0] for new_type in new_types])
|
||||||
return (is_new, [new_type[1] for new_type in new_types])
|
return (is_new, [new_type[1] for new_type in new_types])
|
||||||
|
|
||||||
def new_fill_dict(self, type_dict: 'Dict[str, Type]', types: 'Dict[str, Type]', stack: List[int]) -> 'Tuple[bool, Dict[str, Type]]':
|
def new_fill_dict(self, type_dict: 'Dict[str, Type]', types: 'Dict[str, Type]', stack: List[int]) -> 'Tuple[bool, Dict[str, Type]]':
|
||||||
new_types = {field: type_dict[field].new_fill(types, stack+[id(self)]) for field in type_dict}
|
new_types = {field: type_dict[field].new_fill(types, stack+[id(self)]) for field in type_dict}
|
||||||
is_new = any([new_types[field][0] for field in new_types])
|
is_new = any([new_types[field][0] for field in new_types])
|
||||||
@ -77,7 +74,7 @@ class Type(ABC):
|
|||||||
|
|
||||||
class Primitive(Type):
|
class Primitive(Type):
|
||||||
def fill(self, types: Dict[str, Type], stack: List[int]) -> Type: return self
|
def fill(self, types: Dict[str, Type], stack: List[int]) -> Type: return self
|
||||||
|
|
||||||
def new_fill(self, types: Dict[str, Type], stack: List[int]) -> Tuple[bool, Type]: return (False, self)
|
def new_fill(self, types: Dict[str, Type], stack: List[int]) -> Tuple[bool, Type]: return (False, self)
|
||||||
|
|
||||||
class IntType(Primitive):
|
class IntType(Primitive):
|
||||||
@ -118,7 +115,7 @@ class TupleType(Type):
|
|||||||
if id(self) in stack: return self
|
if id(self) in stack: return self
|
||||||
self.types = [type.fill(types, stack+[id(self)]) for type in self.types]
|
self.types = [type.fill(types, stack+[id(self)]) for type in self.types]
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def new_fill(self, types: Dict[str, Type], stack: List[int]) -> Tuple[bool, Type]:
|
def new_fill(self, types: Dict[str, Type], stack: List[int]) -> Tuple[bool, Type]:
|
||||||
is_new, new_types = self.new_fill_list(self.types, types, stack)
|
is_new, new_types = self.new_fill_list(self.types, types, stack)
|
||||||
return (is_new, TupleType(new_types))
|
return (is_new, TupleType(new_types))
|
||||||
@ -135,7 +132,7 @@ class ListType(Type):
|
|||||||
if id(self) in stack: return self
|
if id(self) in stack: return self
|
||||||
self.type = self.type.fill(types, stack+[id(self)])
|
self.type = self.type.fill(types, stack+[id(self)])
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def new_fill(self, types: Dict[str, Type], stack: List[int]) -> Tuple[bool, Type]:
|
def new_fill(self, types: Dict[str, Type], stack: List[int]) -> Tuple[bool, Type]:
|
||||||
assert id(self) not in stack
|
assert id(self) not in stack
|
||||||
is_new, new_type = self.type.new_fill(types, stack+[id(self)])
|
is_new, new_type = self.type.new_fill(types, stack+[id(self)])
|
||||||
@ -160,7 +157,7 @@ class FunctionType(Type):
|
|||||||
self.arguments = [argument.fill(types, stack+[id(self)]) for argument in self.arguments]
|
self.arguments = [argument.fill(types, stack+[id(self)]) for argument in self.arguments]
|
||||||
self.return_type = self.return_type.fill(types, stack+[id(self)])
|
self.return_type = self.return_type.fill(types, stack+[id(self)])
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def new_fill(self, types: Dict[str, Type], stack: List[int]) -> Tuple[bool, Type]:
|
def new_fill(self, types: Dict[str, Type], stack: List[int]) -> Tuple[bool, Type]:
|
||||||
assert id(self) not in stack # TODO: Wtf?
|
assert id(self) not in stack # TODO: Wtf?
|
||||||
is_new_arguments, new_arguments = self.new_fill_list(self.arguments, types, stack)
|
is_new_arguments, new_arguments = self.new_fill_list(self.arguments, types, stack)
|
||||||
@ -175,11 +172,11 @@ class UnionType(Type):
|
|||||||
if id(self) in stack: return self
|
if id(self) in stack: return self
|
||||||
self.types = [type.fill(types, stack+[id(self)]) for type in self.types]
|
self.types = [type.fill(types, stack+[id(self)]) for type in self.types]
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def new_fill(self, types: Dict[str, Type], stack: List[int]) -> Tuple[bool, Type]:
|
def new_fill(self, types: Dict[str, Type], stack: List[int]) -> Tuple[bool, Type]:
|
||||||
is_new, new_types = self.new_fill_list(self.types, types, stack)
|
is_new, new_types = self.new_fill_list(self.types, types, stack)
|
||||||
return (is_new, UnionType(new_types))
|
return (is_new, UnionType(new_types))
|
||||||
|
|
||||||
def represent(self) -> str: return '('+'|'.join([type.represent() for type in self.types])+')'
|
def represent(self) -> str: return '('+'|'.join([type.represent() for type in self.types])+')'
|
||||||
|
|
||||||
class ObjectType(Primitive):
|
class ObjectType(Primitive):
|
||||||
@ -196,12 +193,12 @@ class ReturnType(Type):
|
|||||||
if id(self) in stack: return self
|
if id(self) in stack: return self
|
||||||
self.type = self.type.fill(types, stack+[id(self)])
|
self.type = self.type.fill(types, stack+[id(self)])
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def new_fill(self, types: Dict[str, Type], stack: List[int]) -> Tuple[bool, Type]:
|
def new_fill(self, types: Dict[str, Type], stack: List[int]) -> Tuple[bool, Type]:
|
||||||
assert id(self) not in stack
|
assert id(self) not in stack
|
||||||
is_new, new_type = self.type.new_fill(types, stack+[id(self)])
|
is_new, new_type = self.type.new_fill(types, stack+[id(self)])
|
||||||
return (is_new, ReturnType(new_type))
|
return (is_new, ReturnType(new_type))
|
||||||
|
|
||||||
|
|
||||||
num_expressions: int = 0
|
num_expressions: int = 0
|
||||||
@dataclass
|
@dataclass
|
||||||
@ -219,7 +216,7 @@ class EnumType(Type):
|
|||||||
self.members = {member_name: [element.fill(types, stack+[id(self)]) for element in self.members[member_name]] for member_name in self.members}
|
self.members = {member_name: [element.fill(types, stack+[id(self)]) for element in self.members[member_name]] for member_name in self.members}
|
||||||
self.generics = [type.fill(types, stack+[id(self)]) for type in self.generics]
|
self.generics = [type.fill(types, stack+[id(self)]) for type in self.generics]
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def new_fill(self, types: Dict[str, Type], stack: List[int]) -> Tuple[bool, Type]:
|
def new_fill(self, types: Dict[str, Type], stack: List[int]) -> Tuple[bool, Type]:
|
||||||
assert id(self) not in stack
|
assert id(self) not in stack
|
||||||
is_new = False
|
is_new = False
|
||||||
@ -229,7 +226,7 @@ class EnumType(Type):
|
|||||||
is_new_member, new_members[member_name] = self.new_fill_list(member, types, stack)
|
is_new_member, new_members[member_name] = self.new_fill_list(member, types, stack)
|
||||||
is_new = is_new or is_new_member
|
is_new = is_new or is_new_member
|
||||||
return (is_new, EnumType(self.name, new_members, self.generics) if is_new else self)
|
return (is_new, EnumType(self.name, new_members, self.generics) if is_new else self)
|
||||||
|
|
||||||
def __hash__(self) -> int:
|
def __hash__(self) -> int:
|
||||||
return hash(('type', 'enum', self.name, tuple([(member, tuple(self.members[member])) for member in self.members]), tuple(self.generics)))
|
return hash(('type', 'enum', self.name, tuple([(member, tuple(self.members[member])) for member in self.members]), tuple(self.generics)))
|
||||||
|
|
||||||
@ -239,7 +236,7 @@ class StructType(Type):
|
|||||||
members: Dict[str, Type]
|
members: Dict[str, Type]
|
||||||
generics: List[Type]
|
generics: List[Type]
|
||||||
|
|
||||||
def represent(self) -> str:
|
def represent(self) -> str:
|
||||||
assert not self.generics
|
assert not self.generics
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
@ -253,39 +250,19 @@ class StructType(Type):
|
|||||||
assert id(self) not in stack
|
assert id(self) not in stack
|
||||||
is_new, new_members = self.new_fill_dict(self.members, types, stack)
|
is_new, new_members = self.new_fill_dict(self.members, types, stack)
|
||||||
return (is_new, StructType(self.name, new_members, self.generics) if is_new else self)
|
return (is_new, StructType(self.name, new_members, self.generics) if is_new else self)
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class VariableType(Type):
|
class VariableType(Type):
|
||||||
name: str
|
name: str
|
||||||
|
|
||||||
def represent(self) -> str: return self.name + '?'
|
def represent(self) -> str: return self.name + '?'
|
||||||
|
|
||||||
def fill(self, types: Dict[str, Type], stack: List[int]) -> Type:
|
def fill(self, types: Dict[str, Type], stack: List[int]) -> Type:
|
||||||
return types.get(self.name, self)
|
return types.get(self.name, self)
|
||||||
|
|
||||||
def new_fill(self, types: Dict[str, Type], stack: List[int]) -> Tuple[bool, Type]:
|
def new_fill(self, types: Dict[str, Type], stack: List[int]) -> Tuple[bool, Type]:
|
||||||
return (self.name in types, types.get(self.name, self))
|
return (self.name in types, types.get(self.name, self))
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class DictionaryType(Type):
|
|
||||||
key_type: Type
|
|
||||||
value_type: Type
|
|
||||||
|
|
||||||
def represent(self) -> str: return f"dict[{self.key_type.represent()}, {self.value_type.represent()}]"
|
|
||||||
|
|
||||||
def fill(self, types: Dict[str, Type], stack: List[int]) -> Type:
|
|
||||||
if id(self) in stack: return self
|
|
||||||
self.key_type = self.key_type.fill(types, stack+[id(self)])
|
|
||||||
self.value_type = self.value_type.fill(types, stack+[id(self)])
|
|
||||||
return self
|
|
||||||
|
|
||||||
def new_fill(self, types: Dict[str, Type], stack: List[int]) -> Tuple[bool, Type]:
|
|
||||||
is_new_key, new_key_type = self.key_type.new_fill(types, stack+[id(self)])
|
|
||||||
is_new_value, new_value_type = self.value_type.new_fill(types, stack+[id(self)])
|
|
||||||
return (is_new_key or is_new_value, DictionaryType(new_key_type, new_value_type))
|
|
||||||
|
|
||||||
def is_indexable(self) -> bool: return True
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class GenericType(Type):
|
class GenericType(Type):
|
||||||
variables: List[VariableType]
|
variables: List[VariableType]
|
||||||
@ -297,10 +274,10 @@ class GenericType(Type):
|
|||||||
if id(self) in stack: return self
|
if id(self) in stack: return self
|
||||||
self.type = self.type.fill(types, stack+[id(self)])
|
self.type = self.type.fill(types, stack+[id(self)])
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def new_fill(self, types: Dict[str, Type], stack: List[int]) -> Tuple[bool, Type]:
|
def new_fill(self, types: Dict[str, Type], stack: List[int]) -> Tuple[bool, Type]:
|
||||||
assert False
|
assert False
|
||||||
|
|
||||||
def substitute(self, types: List[Type]) -> Type:
|
def substitute(self, types: List[Type]) -> Type:
|
||||||
assert len(types) == len(self.variables), f"{self.type.represent()} expected {len(self.variables)} type parameters, but got {len(types)}!"
|
assert len(types) == len(self.variables), f"{self.type.represent()} expected {len(self.variables)} type parameters, but got {len(types)}!"
|
||||||
return self.type.new_fill({variable.name: type for (variable, type) in zip(self.variables, types)}, [])[1]
|
return self.type.new_fill({variable.name: type for (variable, type) in zip(self.variables, types)}, [])[1]
|
||||||
|
Loading…
Reference in New Issue
Block a user