Commit 1c590c5d authored by Tom Niget's avatar Tom Niget

Temp commit: todo

parent 0f582e92
......@@ -21,17 +21,31 @@ class list(Generic[U]):
def __mul__(self, other: int) -> Self: ...
def first(self) -> U: ...
def __getitem__(self, index: int) -> U: ...
def pop(self, index: int = -1) -> U: ...
assert [1, 2, 3][1]
assert list[int].first
class Iterator(Generic[U]):
def __iter__(self) -> Self: ...
def __next__(self) -> U: ...
def next(it: Iterator[U], default: None) -> U: ...
# type: TypeVar("U")
def next(it: Iterator[U], default: None) -> U:
...
# what happens with multiple functions
def print(*args) -> None: ...
def range(*args) -> Iterator[int]: ...
\ No newline at end of file
def range(*args) -> Iterator[int]: ...
def rangeb(*args) -> Iterator[bool]: ...
assert next(range(6), None)
assert next(rangeb(6), None)
\ No newline at end of file
......@@ -6,7 +6,49 @@ def fibo(n: int) -> int:
a = fork(lambda: fibo(n - 1))
b = fork(lambda: fibo(n - 2))
sync()
return a.get() + b.get()
"""
def fibo(n: int) -> int:
if n < 2:
return n
with sync(): # {
a = fork(lambda: fibo(n - 1))
b = fork(lambda: fibo(n - 2))
# }
return a + b
"""
"""
Task<int> fibo(int n) {
if (n < 2) {
return n;
}
Forked<int> a;
Forked<int> b;
{
a = fork(fibo(n - 1));
// cvcvc
b = fork(fibo(n - 2));
co_await sync();
}
co_return a.get() + b.get();
"""
"""
Task<int> fibo(int n) {
int a, b;
co_return []() -> Join<int> {
if (n < 2) {
return n;
}
co_await fork(fibo(n - 1), a);
co_await fork(fibo(n - 2), b);
co_await Sync();
co_return a + b;
}();
}
"""
if __name__ == "__main__":
......
......@@ -10,7 +10,7 @@ from transpiler.phases.typing.scope import Scope
def transpile(source):
res = ast.parse(source)
res = ast.parse(source, type_comments=True)
#res = initial_pytype.run(source, res)
IfMainVisitor().visit(res)
ScoperBlockVisitor().visit(res)
......
......@@ -98,18 +98,6 @@ class ScoperExprVisitor(ScoperVisitor):
return actual
if isinstance(rtype, Promise):
node.is_await = True
if rtype.kind == PromiseKind.FORKED \
and isinstance(fty := self.scope.function.obj_type.return_type, Promise):
fty.kind = PromiseKind.JOIN
else:
return rtype.return_type
else:
node.is_await = False
return rtype
def visit_function_call(self, ftype: BaseType, arguments: List[BaseType]):
if not isinstance(ftype, FunctionType):
raise IncompatibleTypesError(f"Cannot call {ftype}")
......@@ -117,8 +105,8 @@ class ScoperExprVisitor(ScoperVisitor):
equivalent = FunctionType(arguments, ftype.return_type)
try:
ftype.unify(equivalent)
except:
raise IncompatibleTypesError(f"Cannot call {ftype} with {equivalent}")
except IncompatibleTypesError as e:
raise IncompatibleTypesError(f"Cannot call {ftype} with {equivalent}: {e}")
return ftype.return_type
def visit_Lambda(self, node: ast.Lambda) -> BaseType:
......@@ -141,10 +129,7 @@ class ScoperExprVisitor(ScoperVisitor):
def visit_BinOp(self, node: ast.BinOp) -> BaseType:
left, right = map(self.visit, (node.left, node.right))
try:
return self.visit_function_call(
self.visit_getattr(TypeType(left), f"__{DUNDER[type(node.op)]}__"),
[left, right]
)
return self.make_dunder([left, right], DUNDER[type(node.op)])
except IncompatibleTypesError as e:
raise IncompatibleTypesError(f"{e} in `{ast.unparse(node)}`")
......@@ -197,11 +182,12 @@ class ScoperExprVisitor(ScoperVisitor):
def visit_Subscript(self, node: ast.Subscript) -> BaseType:
left = self.visit(node.value)
args = node.slice if type(node.slice) == tuple else [node.slice]
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(*[self.visit(e).type_object for e in args]))
return TypeType(left.type_object(*[arg.type_object for arg in args]))
pass
raise NotImplementedError(node)
return self.make_dunder([left, *args], "getitem")
def visit_UnaryOp(self, node: ast.UnaryOp) -> BaseType:
raise NotImplementedError(node)
......@@ -213,3 +199,9 @@ class ScoperExprVisitor(ScoperVisitor):
if then != else_:
raise NotImplementedError("IfExp with different types not handled yet")
return then
def make_dunder(self, args: List[BaseType], name: str) -> BaseType:
return self.visit_function_call(
self.visit_getattr(TypeType(args[0]), f"__{name}__"),
args
)
\ No newline at end of file
......@@ -59,6 +59,7 @@ class StdlibVisitor(NodeVisitorSeq):
pass
def visit_FunctionDef(self, node: ast.FunctionDef):
tc = node.type_comment # todo : lire les commetnaries de type pour les fonctions génériques sinon trouver autre chose
arg_visitor = TypeAnnotationVisitor(self.scope.child(ScopeKind.FUNCTION), self.cur_class)
arg_types = [arg_visitor.visit(arg.annotation or arg.arg) for arg in node.args.args]
ret_type = arg_visitor.visit(node.returns)
......
......@@ -2,6 +2,7 @@ import typing
from abc import ABC, abstractmethod
from dataclasses import dataclass, field
from enum import Enum
from itertools import zip_longest
from typing import Dict, Optional, List, ClassVar, Callable, Any
......@@ -106,6 +107,7 @@ class TypeOperator(BaseType, ABC):
args: List[BaseType]
name: str = None
variadic: bool = False
optional_at: Optional[int] = None
gen_methods: ClassVar[Dict[str, GenMethodFactory]] = {}
def __init_subclass__(cls, **kwargs):
......@@ -137,15 +139,38 @@ class TypeOperator(BaseType, ABC):
else:
return
raise IncompatibleTypesError(f"Cannot unify {self} and {other} with different type and no common parents")
if len(self.args) != len(other.args) and not (self.variadic or other.variadic):
raise IncompatibleTypesError(f"Cannot unify {self} and {other} with different number of arguments")
for a, b in zip(self.args, other.args):
if len(self.args) != len(other.args):
a, b = self, other
a_opt = a.optional_at is not None
b_opt = b.optional_at is not None
if a_opt and b_opt:
raise IncompatibleTypesError(f"This really should never happen")
if b_opt:
a, b = b, a
if a_opt:
# a = f(A, B; C=?, D=?)
# b = g(A, B, ... ?)
# either
# |a| < |b| => b has more args => invalid
# |a| ≥ |b| => b has less args => valid, up to |b|, so normal course of events
x = True
# c'est pété => utiliser le truc de la boucle en bas
if not (self.variadic or other.variadic):
raise IncompatibleTypesError(f"Cannot unify {self} and {other} with different number of arguments")
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
if isinstance(a, BaseType) and isinstance(b, BaseType):
a.unify(b)
else:
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)
......
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