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 abc import ABC, abstractmethod
from dataclasses import dataclass from dataclasses import dataclass
from typing import Dict, List, Optional, Tuple, Union from typing import Dict, List, Optional, Tuple
### Types ### ### Types ###
@ -15,13 +15,6 @@ class TupleTypeExpr(TypeExpression):
def represent(self) -> str: def represent(self) -> str:
assert False, ("Unimplemented") assert False, ("Unimplemented")
@dataclass
class UnionTypeExpr(TypeExpression):
types: List[TypeExpression]
def represent(self) -> str:
assert False, ("Unimplemented")
@dataclass @dataclass
class ListTypeExpr(TypeExpression): class ListTypeExpr(TypeExpression):
type: TypeExpression type: TypeExpression

View File

@ -1,5 +1,5 @@
from dataclasses import dataclass 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_ast import *
from ppp_lexer import Lexer 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_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 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 @dataclass
class Declared: class Declared:
@ -31,7 +31,7 @@ class Constant:
def from_obj(obj: Object) -> 'Declared': def from_obj(obj: Object) -> 'Declared':
return Declared(obj.get_type(), obj) return Declared(obj.get_type(), obj)
VariableState = Union[Declared, Undeclared, Constant] VariableState = Declared | Undeclared | Constant
Module = Dict[str, VariableState] 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)) return ListType(calculate_type_expression(type_, program, must_resolve))
case TupleTypeExpr(types_): case TupleTypeExpr(types_):
return TupleType([calculate_type_expression(type, program, must_resolve) for type in 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_): 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)) 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_): case TypeSpecification(type_, types_):
@ -413,7 +411,7 @@ class BreakResult:
class NothingResult: class NothingResult:
pass pass
StatementsResult = Union[ReturnResult, ContinueResult, BreakResult, NothingResult] StatementsResult = ReturnResult | ContinueResult | BreakResult | NothingResult
def interpret_statements(statements: List_[Statement], program: ProgramState) -> StatementsResult: def interpret_statements(statements: List_[Statement], program: ProgramState) -> StatementsResult:
for statement in statements: for statement in statements:

View File

@ -2,7 +2,7 @@
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from dataclasses import dataclass 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_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 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.Open)):
if lexer.take_token(SymbolToken(Symbol.Close)): return TupleTypeExpr([]) if lexer.take_token(SymbolToken(Symbol.Close)): return TupleTypeExpr([])
def parse_union(lexer: Lexer) -> TypeExpression: types: List[TypeExpression] = [parse_type(lexer)]
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)]
while lexer.take_token(SymbolToken(Symbol.Comma)): while lexer.take_token(SymbolToken(Symbol.Comma)):
types.append(parse_union(lexer)) types.append(parse_type(lexer))
lexer.assert_token(SymbolToken(Symbol.Close)) lexer.assert_token(SymbolToken(Symbol.Close))
if len(types) == 1 and isinstance(types[0], UnionTypeExpr): base_type = TupleTypeExpr(types)
base_type = types[0]
else:
base_type = TupleTypeExpr(types)
elif lexer.take_token(SymbolToken(Symbol.OpenSquare)): elif lexer.take_token(SymbolToken(Symbol.OpenSquare)):
type = parse_type(lexer) type = parse_type(lexer)
lexer.assert_token(SymbolToken(Symbol.CloseSquare)) 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_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, 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: 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_) case _: assert False, ("Unimplemented", list_)
assert False 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: def str_to_int_impl(str_: Object) -> Object:
assert isinstance(str_, Str) assert isinstance(str_, Str)
@ -99,7 +100,7 @@ variables: Dict[str, Object] = {
'void': VoidTypeObj, 'void': VoidTypeObj,
'debug_print': DebugPrint, 'debug_print': DebugPrint,
'read': Read, 'read': Read,
'len': Len, # 'len': Len,
'str_to_int': StrToInt, 'str_to_int': StrToInt,
'none': NoneObj, 'none': NoneObj,
'range': Range, 'range': Range,

View File

@ -1,7 +1,5 @@
from dataclasses import dataclass from dataclasses import dataclass
from enum import Enum from enum import Enum
from typing import List, Literal, Tuple, Union
class Keyword(Enum): class Keyword(Enum):
Enum = 'enum' Enum = 'enum'
@ -88,14 +86,7 @@ class SymbolToken:
@dataclass @dataclass
class EofToken: pass class EofToken: pass
TokenContents = Union[ TokenContents = KeywordToken | IdentifierToken | NumberToken | StringToken | SymbolToken | EofToken
KeywordToken,
IdentifierToken,
NumberToken,
StringToken,
SymbolToken,
EofToken
]
@dataclass @dataclass
class Token: class Token:

View File

@ -1,7 +1,7 @@
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from dataclasses import dataclass from dataclasses import dataclass
from typing import Dict, List, Tuple, Union from typing import Dict, List, Tuple
import sys import sys
sys.setrecursionlimit(1000) sys.setrecursionlimit(1000)
@ -40,10 +40,6 @@ class Type(ABC):
case VariableType(self_name), VariableType(other_name): case VariableType(self_name), VariableType(other_name):
return self_name == other_name return self_name == other_name
case _, VariableType(""): return True 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 BoolType(), BoolType(): return True
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
@ -164,21 +160,6 @@ class FunctionType(Type):
is_new_return_type, new_return_type = self.return_type.new_fill(types, stack+[id(self)]) 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)) 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): class ObjectType(Primitive):
def represent(self) -> str: return 'object' def represent(self) -> str: return 'object'
Object = ObjectType() Object = ObjectType()