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:
germax26 2024-08-13 12:45:42 +10:00
parent dd3b933e03
commit b02ca87760
Signed by: germax26
SSH Key Fingerprint: SHA256:N3w+8798IMWBt7SYH8G1C0iJlIa2HIIcRCXwILT5FvM
7 changed files with 15 additions and 62 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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