Commit ef37573d authored by Tom Niget's avatar Tom Niget

Continue work with functions and stuff

parent 6454a3ad
......@@ -26,6 +26,7 @@ class float:
def __init__(self, x: object) -> None: ...
assert int.__add__
assert (5).__add__
class slice:
pass
......@@ -89,7 +90,9 @@ class dict[U, V]:
assert(len(["a"]))
#assert list.__getitem__
assert [].__getitem__
assert [4].__getitem__
assert [1, 2, 3][1]
......@@ -115,7 +118,6 @@ def identity_2[U, V](x: U, y: V) -> tuple[U, V]:
assert list.__add__
assert list.__add__([5], [[6][0]])
#assert list[U].__add__
assert list[int].__add__
assert identity_2(1, "a")
assert lambda x, y: identity_2(x, y)
......
......@@ -3,9 +3,6 @@ from typing import Callable
class Forked[T]:
def get(self) -> T: ...
class Task[T]:
pass
class Future[T]:
def get(self) -> Task[T]: ...
......
......@@ -4,7 +4,8 @@ from logging import debug
from transpiler.phases.typing.scope import VarKind, VarDecl, ScopeKind, Scope
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, ResolvedConcreteType, \
MemberDef, TY_FLOAT, TY_BUILTIN_FEATURE, TY_TUPLE, TY_DICT, TY_SET, TY_LIST, TY_BYTES, TY_OBJECT, TY_CPP_TYPE
MemberDef, TY_FLOAT, TY_BUILTIN_FEATURE, TY_TUPLE, TY_DICT, TY_SET, TY_LIST, TY_BYTES, TY_OBJECT, TY_CPP_TYPE, \
TY_OPTIONAL, UniqueTypeMixin, TY_CALLABLE, TY_TASK
# PRELUDE.vars.update({
# "int": VarDecl(VarKind.LOCAL, TypeType(TY_INT)),
......@@ -44,16 +45,21 @@ prelude_vars = {
"dict": TY_DICT,
"tuple": TY_TUPLE,
"BuiltinFeature": TY_BUILTIN_FEATURE,
"CppType": TY_CPP_TYPE
"CppType": TY_CPP_TYPE,
"Optional": TY_OPTIONAL,
"Callable": TY_CALLABLE,
"Task": TY_TASK
}
PRELUDE.vars.update({name: VarDecl(VarKind.LOCAL, ty.type_type()) for name, ty in prelude_vars.items()})
typon_std = Path(__file__).parent.parent.parent.parent / "stdlib"
def make_module(name: str, scope: Scope) -> ResolvedConcreteType:
class CreatedType(ResolvedConcreteType):
def __str__(self):
class CreatedType(UniqueTypeMixin, ResolvedConcreteType):
def name(self):
return name
ty = CreatedType()
for n, v in scope.vars.items():
......
......@@ -85,15 +85,15 @@ class TypeMismatchError(CompileError):
@dataclass
class ArgumentCountMismatchError(CompileError):
func: "TypeOperator"
arguments: "TypeOperator"
func: "CallableInstanceType"
arguments: "list"
def __str__(self) -> str:
fcount = str(len(self.func.args))
if self.func.variadic:
fcount = str(len(self.func.parameters))
if self.func.is_variadic:
fcount = f"at least {fcount}"
return f"Argument count mismatch: expected {fcount}, got {len(self.arguments.args)}"
return f"Argument count mismatch: expected {fcount}, got {len(self.arguments)}"
def detail(self, last_node: ast.AST = None) -> str:
return f"""
......
import abc
import ast
import inspect
from itertools import zip_longest
from typing import List
from transpiler.phases.typing import ScopeKind, VarDecl, VarKind
from transpiler.phases.typing.common import ScoperVisitor, get_iter, get_next, is_builtin
from transpiler.phases.typing.exceptions import ArgumentCountMismatchError
from transpiler.phases.typing.types import BaseType, TY_STR, TY_BOOL, TY_INT, TY_COMPLEX, TY_FLOAT, TY_NONE, \
ClassTypeType, ResolvedConcreteType, GenericType, CallableInstanceType, TY_LIST, TY_SET, TY_DICT, RuntimeValue, \
TypeVariable, TY_LAMBDA, TypeListType
TypeVariable, TY_LAMBDA, TypeListType, MethodType
from transpiler.utils import linenodata
DUNDER = {
......@@ -121,11 +123,23 @@ class ScoperExprVisitor(ScoperVisitor):
return actual
def visit_function_call(self, ftype: ResolvedConcreteType, arguments: List[BaseType]):
if isinstance(ftype, GenericType):
ftype = ftype.instantiate_default()
ftype = ftype.deref()
if isinstance(ftype, ClassTypeType):
init = self.visit_getattr(ftype, "__init__")
self.visit_function_call(init, [ftype.inner_type, *arguments])
return ftype.inner_type
assert isinstance(ftype, CallableInstanceType)
for a, b in zip(ftype.parameters, arguments):
a.try_assign(b)
for i, (a, b) in enumerate(zip_longest(ftype.parameters, arguments)):
if b is None:
if i >= ftype.optional_at:
continue
raise ArgumentCountMismatchError(ftype, arguments)
if a is None and ftype.is_variadic:
break
assert a.try_assign(b)
return ftype.return_type
# if isinstance(ftype, TypeType):# and isinstance(ftype.type_object, UserType):
# init: FunctionType = self.visit_getattr(ftype, "__init__").remove_self()
......@@ -188,16 +202,9 @@ class ScoperExprVisitor(ScoperVisitor):
ltype = ltype.inner_type
bound = False
if isinstance(ltype, GenericType):
ltype = ltype.instantiate_default()
ltype = ltype.deref()
assert isinstance(ltype, ResolvedConcreteType)
# 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 mdecl := ltype.members.get(name):
# attr = mdecl.type
# if getattr(attr, "is_python_func", False):
......@@ -213,7 +220,7 @@ class ScoperExprVisitor(ScoperVisitor):
ty = field.type.resolve()
if getattr(ty, "is_python_func", False):
ty.python_func_used = True
if isinstance(ty, CallableInstanceType):
if isinstance(ty, MethodType):
if bound and field.in_class_def and type(field.val) != RuntimeValue:
return ty.remove_self()
return ty
......@@ -263,7 +270,7 @@ class ScoperExprVisitor(ScoperVisitor):
def visit_Subscript(self, node: ast.Subscript) -> BaseType:
left = self.visit(node.value)
if isinstance(left, ClassTypeType):
return self.anno().visit(node)
return self.anno().visit(node).type_type()
args = node.slice if type(node.slice) == tuple else [node.slice]
args = [self.visit(e) for e in args]
return self.make_dunder([left, *args], "getitem")
......@@ -285,7 +292,7 @@ class ScoperExprVisitor(ScoperVisitor):
def make_dunder(self, args: List[BaseType], name: str) -> BaseType:
return self.visit_function_call(
self.visit_getattr(args[0], f"__{name}__"),
args
args[1:]
)
def visit_ListComp(self, node: ast.ListComp) -> BaseType:
......
......@@ -12,7 +12,8 @@ from transpiler.phases.typing.expr import ScoperExprVisitor
from transpiler.phases.typing.scope import Scope, VarDecl, VarKind, ScopeKind
from transpiler.phases.typing.types import BaseType, BuiltinGenericType, BuiltinType, create_builtin_generic_type, \
create_builtin_type, ConcreteType, GenericInstanceType, TypeListType, TypeTupleType, GenericParameter, \
GenericParameterKind, TypeVariable, ResolvedConcreteType, MemberDef, ClassTypeType, CallableInstanceType
GenericParameterKind, TypeVariable, ResolvedConcreteType, MemberDef, ClassTypeType, CallableInstanceType, \
MethodType, UniqueTypeMixin, GenericType
from transpiler.phases.utils import NodeVisitorSeq
def visit_generic_item(
......@@ -126,14 +127,16 @@ class StdlibVisitor(NodeVisitorSeq):
arg_visitor = TypeAnnotationVisitor(scope)
output.parameters = [arg_visitor.visit(arg.annotation) for arg in node.args.args]
output.return_type = arg_visitor.visit(node.returns)
output.optional_at = len(node.args.args) - len(node.args.defaults)
output.is_variadic = args.vararg is not None
@dataclass(eq=False, init=False)
class InstanceType(CallableInstanceType):
def __init__(self):
super().__init__([], None)
super().__init__([], None, 0)
def __str__(self):
return f"{node.name}({", ".join(map(str, self.parameters))}) -> {self.return_type}"
return f"{node.name}{super().__str__()}"
'''
......@@ -174,9 +177,29 @@ class StdlibVisitor(NodeVisitorSeq):
# node.type_params.append(ast.TypeVar("Self", None))
if True or node.type_params:
class FuncType(BuiltinGenericType):
bases = [BuiltinGenericType]
cur_class_ref = self.cur_class
if cur_class_ref is not None:
bases.append(MethodType)
class FuncType(*bases):
def name(self):
return f"FuncTypeGen${node.name}"
if cur_class_ref is not None:
def remove_self(self, new_return_type = None):
class BoundFuncType(UniqueTypeMixin, GenericType):
def name(self) -> str:
return f"BoundFuncType${node.name}"
def _instantiate(self, args: list[ConcreteType]) -> GenericInstanceType:
return NewType.instantiate(args).remove_self()
def __str__(self):
return str(self.instantiate_default())
res = BoundFuncType()
res.parameters = NewType.parameters
return res
else:
class FuncType(InstanceType):
pass
......
......@@ -75,6 +75,9 @@ class BaseType(ABC):
except:
return False
def deref(self):
return self
cur_var = 0
......@@ -283,6 +286,9 @@ class GenericType(BaseType):
except:
return super().__str__()
def deref(self):
return self.instantiate_default().deref()
@dataclass(eq=False, init=False)
class BuiltinGenericType(UniqueTypeMixin, GenericType):
......@@ -341,6 +347,25 @@ TY_SET = create_builtin_generic_type("set")
TY_DICT = create_builtin_generic_type("dict")
TY_TUPLE = create_builtin_generic_type("tuple")
@dataclass(eq=False)
class TaskInstanceType(GenericInstanceType):
value: ConcreteType
def deref(self):
return self.value.deref()
class TaskType(UniqueTypeMixin, GenericType):
def name(self):
return "Task"
def _instantiate(self, args: list[ConcreteType]) -> GenericInstanceType:
assert len(args) == 1
return TaskInstanceType(args[0])
TY_TASK = TaskType()
TY_TUPLE.instantiate_ = lambda args: TupleInstanceType(args)
@dataclass(unsafe_hash=False)
......@@ -403,15 +428,41 @@ class UnionType(UniqueTypeMixin, GenericType):
TY_UNION = UnionType()
class OptionalType(UniqueTypeMixin, GenericType):
def name(self) -> str:
return "Optional"
def _instantiate(self, args: list[ConcreteType]) -> GenericInstanceType:
assert len(args) == 1
return UnionInstanceType([args[0], TY_NONE])
TY_OPTIONAL = OptionalType()
@typing.runtime_checkable
class MethodType(typing.Protocol):
def remove_self(self, new_return_type = None) -> ...:
raise NotImplementedError()
@dataclass(eq=False)
class CallableInstanceType(GenericInstanceType):
class CallableInstanceType(GenericInstanceType, MethodType):
parameters: list[ConcreteType]
return_type: ConcreteType
optional_at: int = None
is_variadic: bool = False
def remove_self(self):
return self.generic_parent.instantiate([TypeListType(self.parameters[1:]), self.return_type])
def __post_init__(self):
if self.optional_at is None:
self.optional_at = len(self.parameters)
def remove_self(self, new_return_type = None):
res = CallableInstanceType(self.parameters[1:], new_return_type or self.return_type, self.optional_at - 1, self.is_variadic)
res.generic_parent = self.generic_parent
res.generic_args = self.generic_args
return res
#return self.generic_parent.instantiate([TypeListType(self.parameters[1:]), new_return_type or self.return_type])
def __str__(self):
return f"({", ".join(map(str, self.parameters))}{", *args" if self.is_variadic else ""}) -> {self.return_type}"
class CallableType(UniqueTypeMixin, GenericType):
......@@ -481,3 +532,4 @@ class ClassType(UniqueTypeMixin, GenericType):
return ClassTypeType(*args)
TY_TYPE = ClassType()
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