Remove Dictionaries

Remove parsing and evaluating of Dictionaries
This commit is contained in:
germax26 2024-08-12 00:00:03 +10:00
parent 2b840ff8b9
commit 238980d602
Signed by: germax26
SSH Key Fingerprint: SHA256:N3w+8798IMWBt7SYH8G1C0iJlIa2HIIcRCXwILT5FvM
6 changed files with 28 additions and 192 deletions

View File

@ -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

View File

@ -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_):

View 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: ...

View File

@ -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):

View File

@ -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:
@ -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,

View File

@ -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)
@ -266,26 +263,6 @@ class VariableType(Type):
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]