Commit 8cadfa12 authored by Tom Niget's avatar Tom Niget

Fix unification checks and type instantiation

parent e523e730
from typing import Self, TypeVar, Generic
from typing import Self, TypeVar, Generic, Tuple
class int:
......@@ -13,6 +13,7 @@ class int:
assert int.__add__
U = TypeVar("U")
V = TypeVar("V")
class list(Generic[U]):
......@@ -44,13 +45,29 @@ def identity(x: U) -> U:
assert identity(1)
assert identity("a")
def identity_2(x: U, y: V) -> Tuple[U, V]:
...
assert list.__add__
assert list.__add__([5], [[6][0]])
assert list[U].__add__
assert list[U].__add__([1], [2])
assert list[U].__add__
assert list[int].__add__
assert identity_2(1, "a")
assert lambda x, y: identity_2(x, y)
assert lambda x: identity_2(x, x)
def print(*args) -> None: ...
def range(*args) -> Iterator[int]: ...
def rangeb(*args) -> Iterator[bool]: ...
assert [].__add__
assert [6].__add__
assert [True].__add__
assert next(range(6), None)
assert next(rangeb(6), None)
\ No newline at end of file
assert lambda x: [x].__add__
assert next(range(6), None)
\ No newline at end of file
......@@ -4,7 +4,7 @@ from pathlib import Path
from transpiler.phases.typing.scope import VarKind, VarDecl, ScopeKind
from transpiler.phases.typing.stdlib import PRELUDE, StdlibVisitor
from transpiler.phases.typing.types import TY_TYPE, TY_INT, TY_STR, TY_BOOL, TY_COMPLEX, TY_NONE, FunctionType, \
TypeVariable, TY_MODULE, CppType, PyList, TypeType, Forked, Task, Future, PyIterator
TypeVariable, TY_MODULE, CppType, PyList, TypeType, Forked, Task, Future, PyIterator, TupleType
PRELUDE.vars.update({
# "int": VarDecl(VarKind.LOCAL, TY_TYPE, TY_INT),
......@@ -28,7 +28,8 @@ PRELUDE.vars.update({
"Forked": VarDecl(VarKind.LOCAL, TypeType(Forked)),
"Task": VarDecl(VarKind.LOCAL, TypeType(Task)),
"Future": VarDecl(VarKind.LOCAL, TypeType(Future)),
"Iterator": VarDecl(VarKind.LOCAL, TypeType(PyIterator))
"Iterator": VarDecl(VarKind.LOCAL, TypeType(PyIterator)),
"Tuple": VarDecl(VarKind.LOCAL, TypeType(TupleType)),
})
typon_std = Path(__file__).parent.parent.parent.parent / "stdlib"
......
import abc
import ast
import inspect
from typing import List
from transpiler.phases.typing import ScopeKind, VarDecl, VarKind
......@@ -108,7 +109,7 @@ class ScoperExprVisitor(ScoperVisitor):
try:
ftype.unify(equivalent)
except IncompatibleTypesError as e:
raise IncompatibleTypesError(f"Cannot call {ftype} with {equivalent}: {e}")
raise IncompatibleTypesError(f"Cannot call {ftype} with ({(', '.join(map(str, arguments)))}): {e}")
return ftype.return_type
def visit_Lambda(self, node: ast.Lambda) -> BaseType:
......@@ -147,6 +148,12 @@ class ScoperExprVisitor(ScoperVisitor):
if isinstance(ltype, TypeType):
ltype = ltype.type_object
bound = False
if isinstance(ltype, abc.ABCMeta):
ctor = ltype.__init__
args = list(inspect.signature(ctor).parameters.values())[1:]
if not all(arg.annotation == BaseType for arg in args):
raise NotImplementedError("I don't know how to handle this type")
ltype = ltype(*(TypeVariable() for _ in args))
if attr := ltype.members.get(name):
return attr
if meth := ltype.methods.get(name):
......@@ -187,7 +194,7 @@ class ScoperExprVisitor(ScoperVisitor):
args = [self.visit(e) for e in args]
if isinstance(left, TypeType) and isinstance(left.type_object, abc.ABCMeta):
# generic
return TypeType(left.type_object(*[arg.type_object for arg in args]))
return TypeType(left.type_object(*[arg.type_object if isinstance(arg, TypeType) else arg for arg in args]))
pass
return self.make_dunder([left, *args], "getitem")
......
import dataclasses
import typing
from abc import ABC, abstractmethod
from dataclasses import dataclass, field
......@@ -41,6 +42,10 @@ class BaseType(ABC):
def contains_internal(self, other: "BaseType") -> bool:
pass
# @abstractmethod
# def clone(self) -> "BaseType":
# pass
def gen_sub(self, this: "BaseType", typevars: Dict[str, "BaseType"]) -> "Self":
return self
......@@ -49,6 +54,8 @@ class BaseType(ABC):
T = typing.TypeVar("T")
class MagicType(BaseType, typing.Generic[T]):
val: T
......@@ -66,6 +73,9 @@ class MagicType(BaseType, typing.Generic[T]):
def __str__(self):
return str(self.val)
def clone(self) -> "BaseType":
return MagicType(self.val)
cur_var = 0
......@@ -161,6 +171,9 @@ class TypeOperator(BaseType, ABC):
if not (self.variadic or other.variadic):
raise IncompatibleTypesError(f"Cannot unify {self} and {other} with different number of arguments")
if len(self.args) == 0:
if self.name != other.name:
raise IncompatibleTypesError(f"Cannot unify {self} and {other}")
for i, (a, b) in enumerate(zip_longest(self.args, other.args)):
if a is None and self.variadic or b is None and other.variadic:
continue
......@@ -171,7 +184,6 @@ class TypeOperator(BaseType, ABC):
if a != b:
raise IncompatibleTypesError(f"Cannot unify {a} and {b}")
def contains_internal(self, other: "BaseType") -> bool:
return any(arg.contains(other) for arg in self.args)
......@@ -182,20 +194,23 @@ class TypeOperator(BaseType, ABC):
return hash((self.name, tuple(self.args)))
def gen_sub(self, this: BaseType, typevars) -> "Self":
if len(self.args) == 0:
return self
res = object.__new__(self.__class__) # todo: ugly... should make a clone()
if isinstance(this, TypeOperator):
vardict = dict(zip(typevars.keys(), this.args))
else:
vardict = typevars
for k in dataclasses.fields(self):
setattr(res, k.name, getattr(self, k.name))
res.args = [arg.resolve().gen_sub(this, vardict) for arg in self.args]
res.name = self.name
res.variadic = self.variadic
return res
def to_list(self) -> List["BaseType"]:
return [self, *self.args]
class FunctionType(TypeOperator):
def __init__(self, args: List[BaseType], ret: BaseType):
super().__init__([ret, *args])
......@@ -287,6 +302,7 @@ class PyDict(TypeOperator):
def value_type(self):
return self.args[1]
class PyIterator(TypeOperator):
def __init__(self, arg: BaseType):
super().__init__([arg], "iter")
......@@ -296,9 +312,8 @@ class PyIterator(TypeOperator):
return self.args[0]
class TupleType(TypeOperator):
def __init__(self, args: List[BaseType]):
def __init__(self, *args: List[BaseType]):
super().__init__(args, "tuple")
......@@ -334,17 +349,23 @@ class Promise(TypeOperator, ABC):
return [PyIterator(self.return_type), *super().get_parents()]
return super().get_parents()
class Forked(Promise):
"""Only use this for type specs"""
def __init__(self, ret: BaseType):
super().__init__(ret, PromiseKind.FORKED)
class Task(Promise):
"""Only use this for type specs"""
def __init__(self, ret: BaseType):
super().__init__(ret, PromiseKind.TASK)
class Future(Promise):
"""Only use this for type specs"""
def __init__(self, ret: BaseType):
super().__init__(ret, PromiseKind.FUTURE)
\ No newline at end of file
super().__init__(ret, PromiseKind.FUTURE)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment