Commit ef37573d authored by Tom Niget's avatar Tom Niget

Continue work with functions and stuff

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