Remove union types
I will need to implement polymorphism later to allow for functions like `len` to work. Len currently relies on saying that its argument is either a list or a string, as strings are not a subtype of lists.
This commit is contained in:
		
							parent
							
								
									dd3b933e03
								
							
						
					
					
						commit
						b02ca87760
					
				@ -1,6 +1,6 @@
 | 
			
		||||
from abc import ABC, abstractmethod
 | 
			
		||||
from dataclasses import dataclass
 | 
			
		||||
from typing import Dict, List, Optional, Tuple, Union
 | 
			
		||||
from typing import Dict, List, Optional, Tuple
 | 
			
		||||
 | 
			
		||||
### Types ###
 | 
			
		||||
 | 
			
		||||
@ -15,13 +15,6 @@ class TupleTypeExpr(TypeExpression):
 | 
			
		||||
	def represent(self) -> str:
 | 
			
		||||
		assert False, ("Unimplemented")
 | 
			
		||||
 | 
			
		||||
@dataclass
 | 
			
		||||
class UnionTypeExpr(TypeExpression):
 | 
			
		||||
	types: List[TypeExpression]
 | 
			
		||||
 | 
			
		||||
	def represent(self) -> str:
 | 
			
		||||
		assert False, ("Unimplemented")
 | 
			
		||||
 | 
			
		||||
@dataclass
 | 
			
		||||
class ListTypeExpr(TypeExpression):
 | 
			
		||||
	type: TypeExpression
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,5 @@
 | 
			
		||||
from dataclasses import dataclass
 | 
			
		||||
from typing import Dict, List as List_, Optional, Tuple, Union
 | 
			
		||||
from typing import Dict, List as List_, Optional, Tuple
 | 
			
		||||
 | 
			
		||||
from ppp_ast import *
 | 
			
		||||
from ppp_lexer import Lexer
 | 
			
		||||
@ -7,7 +7,7 @@ from ppp_object import Bool, EnumValue, Function, Int, Object, Str, Struct, Tupl
 | 
			
		||||
from ppp_parser import is_valid_target, parse_statement
 | 
			
		||||
from ppp_tokens import EofToken
 | 
			
		||||
from ppp_stdlib import variables
 | 
			
		||||
from ppp_types import 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, VariableType, Void as VoidType
 | 
			
		||||
 | 
			
		||||
@dataclass
 | 
			
		||||
class Declared:
 | 
			
		||||
@ -31,7 +31,7 @@ class Constant:
 | 
			
		||||
	def from_obj(obj: Object) -> 'Declared':
 | 
			
		||||
		return Declared(obj.get_type(), obj)
 | 
			
		||||
 | 
			
		||||
VariableState = Union[Declared, Undeclared, Constant]
 | 
			
		||||
VariableState = Declared | Undeclared | Constant
 | 
			
		||||
 | 
			
		||||
Module = Dict[str, VariableState]
 | 
			
		||||
 | 
			
		||||
@ -340,8 +340,6 @@ def calculate_type_expression(expression: TypeExpression, program: ProgramState,
 | 
			
		||||
			return ListType(calculate_type_expression(type_, program, must_resolve))
 | 
			
		||||
		case TupleTypeExpr(types_):
 | 
			
		||||
			return TupleType([calculate_type_expression(type, program, must_resolve) for type in types_])
 | 
			
		||||
		case UnionTypeExpr(types_):
 | 
			
		||||
			return UnionType([calculate_type_expression(type, program, must_resolve) for type in types_])
 | 
			
		||||
		case FunctionTypeExpr(arguments_, return_type_):
 | 
			
		||||
			return FunctionType([calculate_type_expression(argument, program, must_resolve) for argument in arguments_], calculate_type_expression(return_type_, program, must_resolve))
 | 
			
		||||
		case TypeSpecification(type_, types_):
 | 
			
		||||
@ -413,7 +411,7 @@ class BreakResult:
 | 
			
		||||
class NothingResult:
 | 
			
		||||
	pass
 | 
			
		||||
 | 
			
		||||
StatementsResult = Union[ReturnResult, ContinueResult, BreakResult, NothingResult]
 | 
			
		||||
StatementsResult = ReturnResult | ContinueResult | BreakResult | NothingResult
 | 
			
		||||
 | 
			
		||||
def interpret_statements(statements: List_[Statement], program: ProgramState) -> StatementsResult:
 | 
			
		||||
	for statement in statements:
 | 
			
		||||
 | 
			
		||||
@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
from abc import ABC, abstractmethod
 | 
			
		||||
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_
 | 
			
		||||
 | 
			
		||||
from ppp_ast import Statement
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
@ -23,22 +23,11 @@ def parse_type_primary(lexer: Lexer) -> TypeExpression:
 | 
			
		||||
	if lexer.take_token(SymbolToken(Symbol.Open)):
 | 
			
		||||
		if lexer.take_token(SymbolToken(Symbol.Close)): return TupleTypeExpr([])
 | 
			
		||||
 | 
			
		||||
		def parse_union(lexer: Lexer) -> TypeExpression:
 | 
			
		||||
			union_types: List[TypeExpression] = [parse_type(lexer)]
 | 
			
		||||
			while lexer.take_token(SymbolToken(Symbol.Pipe)):
 | 
			
		||||
				union_types.append(parse_type(lexer))
 | 
			
		||||
			if len(union_types) == 1:
 | 
			
		||||
				return union_types[0]
 | 
			
		||||
			return UnionTypeExpr(union_types)
 | 
			
		||||
 | 
			
		||||
		types: List[TypeExpression] = [parse_union(lexer)]
 | 
			
		||||
		types: List[TypeExpression] = [parse_type(lexer)]
 | 
			
		||||
		while lexer.take_token(SymbolToken(Symbol.Comma)):
 | 
			
		||||
			types.append(parse_union(lexer))
 | 
			
		||||
			types.append(parse_type(lexer))
 | 
			
		||||
		lexer.assert_token(SymbolToken(Symbol.Close))
 | 
			
		||||
		if len(types) == 1 and isinstance(types[0], UnionTypeExpr):
 | 
			
		||||
			base_type = types[0]
 | 
			
		||||
		else:
 | 
			
		||||
			base_type = TupleTypeExpr(types)
 | 
			
		||||
		base_type = TupleTypeExpr(types)
 | 
			
		||||
	elif lexer.take_token(SymbolToken(Symbol.OpenSquare)):
 | 
			
		||||
		type = parse_type(lexer)
 | 
			
		||||
		lexer.assert_token(SymbolToken(Symbol.CloseSquare))
 | 
			
		||||
 | 
			
		||||
@ -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, 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, ListType
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def PythonFunction(name: str, parameters: List[Tuple[str, Type]], return_type: Type, func: Callable[..., Object]) -> Object:
 | 
			
		||||
@ -41,7 +41,8 @@ def len_impl(list_: Object) -> Object:
 | 
			
		||||
		case _: assert False, ("Unimplemented", list_)
 | 
			
		||||
	assert False
 | 
			
		||||
 | 
			
		||||
Len = PythonFunction("len", [('list', UnionType([ListType(VariableType("")), StrType]))], IntType, len_impl)
 | 
			
		||||
# TODO: Use polymorphism to make this work for both list<T> and str
 | 
			
		||||
# Len = PythonFunction("len", [('list', UnionType([ListType(VariableType("")), StrType]))], IntType, len_impl)
 | 
			
		||||
 | 
			
		||||
def str_to_int_impl(str_: Object) -> Object:
 | 
			
		||||
	assert isinstance(str_, Str)
 | 
			
		||||
@ -99,7 +100,7 @@ variables: Dict[str, Object] = {
 | 
			
		||||
	'void': VoidTypeObj,
 | 
			
		||||
	'debug_print': DebugPrint,
 | 
			
		||||
	'read': Read,
 | 
			
		||||
	'len': Len,
 | 
			
		||||
	# 'len': Len,
 | 
			
		||||
	'str_to_int': StrToInt,
 | 
			
		||||
	'none': NoneObj,
 | 
			
		||||
	'range': Range,
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,5 @@
 | 
			
		||||
from dataclasses import dataclass
 | 
			
		||||
from enum import Enum
 | 
			
		||||
from typing import List, Literal, Tuple, Union
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Keyword(Enum):
 | 
			
		||||
	Enum = 'enum'
 | 
			
		||||
@ -88,14 +86,7 @@ class SymbolToken:
 | 
			
		||||
@dataclass
 | 
			
		||||
class EofToken: pass
 | 
			
		||||
 | 
			
		||||
TokenContents = Union[
 | 
			
		||||
	KeywordToken,
 | 
			
		||||
	IdentifierToken,
 | 
			
		||||
	NumberToken,
 | 
			
		||||
	StringToken,
 | 
			
		||||
	SymbolToken,
 | 
			
		||||
	EofToken
 | 
			
		||||
]
 | 
			
		||||
TokenContents = KeywordToken | IdentifierToken | NumberToken | StringToken | SymbolToken | EofToken
 | 
			
		||||
 | 
			
		||||
@dataclass
 | 
			
		||||
class Token:
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										21
									
								
								ppp_types.py
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								ppp_types.py
									
									
									
									
									
								
							@ -1,7 +1,7 @@
 | 
			
		||||
 | 
			
		||||
from abc import ABC, abstractmethod
 | 
			
		||||
from dataclasses import dataclass
 | 
			
		||||
from typing import Dict, List, Tuple, Union
 | 
			
		||||
from typing import Dict, List, Tuple
 | 
			
		||||
 | 
			
		||||
import sys
 | 
			
		||||
sys.setrecursionlimit(1000)
 | 
			
		||||
@ -40,10 +40,6 @@ class Type(ABC):
 | 
			
		||||
			case VariableType(self_name), VariableType(other_name):
 | 
			
		||||
				return self_name == other_name
 | 
			
		||||
			case _, VariableType(""): return True
 | 
			
		||||
			case type, UnionType(types):
 | 
			
		||||
				for union_type in types:
 | 
			
		||||
					if type.is_subtype_of(union_type): return True
 | 
			
		||||
				return False
 | 
			
		||||
			case BoolType(), BoolType(): return True
 | 
			
		||||
			case type, ObjectType(): return True
 | 
			
		||||
			case type_a, type_b if type_a.__class__ != type_b.__class__: return False
 | 
			
		||||
@ -164,21 +160,6 @@ class FunctionType(Type):
 | 
			
		||||
		is_new_return_type, new_return_type = self.return_type.new_fill(types, stack+[id(self)])
 | 
			
		||||
		return (is_new_arguments or is_new_return_type, FunctionType(new_arguments, new_return_type))
 | 
			
		||||
 | 
			
		||||
@dataclass
 | 
			
		||||
class UnionType(Type):
 | 
			
		||||
	types: List[Type]
 | 
			
		||||
 | 
			
		||||
	def fill(self, types: Dict[str, Type], stack: List[int]) -> Type:
 | 
			
		||||
		if id(self) in stack: return self
 | 
			
		||||
		self.types = [type.fill(types, stack+[id(self)]) for type in self.types]
 | 
			
		||||
		return self
 | 
			
		||||
 | 
			
		||||
	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)
 | 
			
		||||
		return (is_new, UnionType(new_types))
 | 
			
		||||
 | 
			
		||||
	def represent(self) -> str: return '('+'|'.join([type.represent() for type in self.types])+')'
 | 
			
		||||
 | 
			
		||||
class ObjectType(Primitive):
 | 
			
		||||
	def represent(self) -> str: return 'object'
 | 
			
		||||
Object = ObjectType()
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user