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
 | 
			
		||||
 | 
			
		||||
@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
 | 
			
		||||
class Return(Expression):
 | 
			
		||||
	expression: Expression
 | 
			
		||||
 | 
			
		||||
@ -3,11 +3,11 @@ from typing import Dict, List as List_, Optional, Tuple, Union
 | 
			
		||||
 | 
			
		||||
from ppp_ast import *
 | 
			
		||||
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_tokens import EofToken
 | 
			
		||||
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
 | 
			
		||||
class Declared:
 | 
			
		||||
@ -279,14 +279,6 @@ def calculate_expression(expression: Expression, program: ProgramState) -> Objec
 | 
			
		||||
				element = array.list[index.num]
 | 
			
		||||
				assert element.get_type().is_subtype_of(array_type)
 | 
			
		||||
				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:
 | 
			
		||||
				assert False, "Unreachable"
 | 
			
		||||
		case Bnot(expression_):
 | 
			
		||||
@ -328,73 +320,11 @@ def calculate_expression(expression: Expression, program: ProgramState) -> Objec
 | 
			
		||||
					else:
 | 
			
		||||
						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("")), [])
 | 
			
		||||
				assert elements_type
 | 
			
		||||
				return ListObject(ListType(elements_type), elements)
 | 
			
		||||
			else:
 | 
			
		||||
				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 _:
 | 
			
		||||
			assert False, ("Unimplemented", expression)
 | 
			
		||||
	assert False
 | 
			
		||||
@ -515,17 +445,6 @@ def interpret_statements(statements: List_[Statement], program: ProgramState) ->
 | 
			
		||||
						value = calculate_expression(rhs, program)
 | 
			
		||||
						assert array.get_type().is_indexable(), 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", lhs)
 | 
			
		||||
@ -633,17 +552,6 @@ def interpret_statements(statements: List_[Statement], program: ProgramState) ->
 | 
			
		||||
							case NothingResult(): pass
 | 
			
		||||
							case ReturnResult(_): return 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 BreakStatement(): return BreakResult()
 | 
			
		||||
			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 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):
 | 
			
		||||
	@abstractmethod
 | 
			
		||||
@ -99,14 +99,6 @@ class Struct(Object):
 | 
			
		||||
 | 
			
		||||
	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):
 | 
			
		||||
	@abstractmethod
 | 
			
		||||
	def __hash__(self) -> int: ...
 | 
			
		||||
 | 
			
		||||
@ -134,26 +134,6 @@ def parse_primary(lexer: Lexer) -> Expression:
 | 
			
		||||
					expressions.append(parse_expression(lexer))
 | 
			
		||||
				lexer.assert_token(SymbolToken(Symbol.CloseSquare))
 | 
			
		||||
				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):
 | 
			
		||||
		base_expression = String(parse_string(lexer))
 | 
			
		||||
	elif lexer.check_tokenkind(NumberToken):
 | 
			
		||||
 | 
			
		||||
@ -2,7 +2,7 @@ from typing import Callable, Dict, List, Tuple
 | 
			
		||||
 | 
			
		||||
from ppp_ast import Statements
 | 
			
		||||
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:
 | 
			
		||||
@ -82,7 +82,6 @@ StrTypeObj = TypeObject(StrType)
 | 
			
		||||
IntTypeObj = TypeObject(IntType)
 | 
			
		||||
VoidTypeObj = TypeObject(VoidType)
 | 
			
		||||
BoolTypeObj = TypeObject(BoolType)
 | 
			
		||||
DictTypeObj = TypeObject(GenericType([VariableType("K"), VariableType("V")], DictionaryType(VariableType("K"), VariableType("V"))))
 | 
			
		||||
 | 
			
		||||
True_ = Bool(True)
 | 
			
		||||
False_ = Bool(False)
 | 
			
		||||
@ -98,7 +97,6 @@ variables: Dict[str, Object] = {
 | 
			
		||||
	'int': IntTypeObj,
 | 
			
		||||
	'bool': BoolTypeObj,
 | 
			
		||||
	'void': VoidTypeObj,
 | 
			
		||||
	'dict': DictTypeObj,
 | 
			
		||||
	'debug_print': DebugPrint,
 | 
			
		||||
	'read': Read,
 | 
			
		||||
	'len': Len,
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										23
									
								
								ppp_types.py
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								ppp_types.py
									
									
									
									
									
								
							@ -45,9 +45,6 @@ class Type(ABC):
 | 
			
		||||
					if type.is_subtype_of(union_type): return True
 | 
			
		||||
				return False
 | 
			
		||||
			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_a, type_b if type_a.__class__ != type_b.__class__: return False
 | 
			
		||||
			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]:
 | 
			
		||||
		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
 | 
			
		||||
class GenericType(Type):
 | 
			
		||||
	variables: List[VariableType]
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user