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 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
|
||||||
|
@ -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:
|
||||||
|
@ -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
|
||||||
|
@ -23,21 +23,10 @@ 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 = types[0]
|
|
||||||
else:
|
|
||||||
base_type = TupleTypeExpr(types)
|
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)
|
||||||
|
@ -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,
|
||||||
|
@ -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:
|
||||||
|
21
ppp_types.py
21
ppp_types.py
@ -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()
|
||||||
|
Loading…
Reference in New Issue
Block a user