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

Temp commit: todo

parent 0f582e92
...@@ -21,17 +21,31 @@ class list(Generic[U]): ...@@ -21,17 +21,31 @@ class list(Generic[U]):
def __mul__(self, other: int) -> Self: ... 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]): class Iterator(Generic[U]):
def __iter__(self) -> Self: ... def __iter__(self) -> Self: ...
def __next__(self) -> U: ... 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 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: ...@@ -6,7 +6,49 @@ def fibo(n: int) -> int:
a = fork(lambda: fibo(n - 1)) a = fork(lambda: fibo(n - 1))
b = fork(lambda: fibo(n - 2)) b = fork(lambda: fibo(n - 2))
sync() sync()
return a.get() + b.get() 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__": if __name__ == "__main__":
......
...@@ -10,7 +10,7 @@ from transpiler.phases.typing.scope import Scope ...@@ -10,7 +10,7 @@ from transpiler.phases.typing.scope import Scope
def transpile(source): def transpile(source):
res = ast.parse(source) res = ast.parse(source, type_comments=True)
#res = initial_pytype.run(source, res) #res = initial_pytype.run(source, res)
IfMainVisitor().visit(res) IfMainVisitor().visit(res)
ScoperBlockVisitor().visit(res) ScoperBlockVisitor().visit(res)
......
...@@ -98,18 +98,6 @@ class ScoperExprVisitor(ScoperVisitor): ...@@ -98,18 +98,6 @@ class ScoperExprVisitor(ScoperVisitor):
return actual 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]): def visit_function_call(self, ftype: BaseType, arguments: List[BaseType]):
if not isinstance(ftype, FunctionType): if not isinstance(ftype, FunctionType):
raise IncompatibleTypesError(f"Cannot call {ftype}") raise IncompatibleTypesError(f"Cannot call {ftype}")
...@@ -117,8 +105,8 @@ class ScoperExprVisitor(ScoperVisitor): ...@@ -117,8 +105,8 @@ class ScoperExprVisitor(ScoperVisitor):
equivalent = FunctionType(arguments, ftype.return_type) equivalent = FunctionType(arguments, ftype.return_type)
try: try:
ftype.unify(equivalent) ftype.unify(equivalent)
except: except IncompatibleTypesError as e:
raise IncompatibleTypesError(f"Cannot call {ftype} with {equivalent}") raise IncompatibleTypesError(f"Cannot call {ftype} with {equivalent}: {e}")
return ftype.return_type return ftype.return_type
def visit_Lambda(self, node: ast.Lambda) -> BaseType: def visit_Lambda(self, node: ast.Lambda) -> BaseType:
...@@ -141,10 +129,7 @@ class ScoperExprVisitor(ScoperVisitor): ...@@ -141,10 +129,7 @@ class ScoperExprVisitor(ScoperVisitor):
def visit_BinOp(self, node: ast.BinOp) -> BaseType: def visit_BinOp(self, node: ast.BinOp) -> BaseType:
left, right = map(self.visit, (node.left, node.right)) left, right = map(self.visit, (node.left, node.right))
try: try:
return self.visit_function_call( return self.make_dunder([left, right], DUNDER[type(node.op)])
self.visit_getattr(TypeType(left), f"__{DUNDER[type(node.op)]}__"),
[left, right]
)
except IncompatibleTypesError as e: except IncompatibleTypesError as e:
raise IncompatibleTypesError(f"{e} in `{ast.unparse(node)}`") raise IncompatibleTypesError(f"{e} in `{ast.unparse(node)}`")
...@@ -197,11 +182,12 @@ class ScoperExprVisitor(ScoperVisitor): ...@@ -197,11 +182,12 @@ 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)
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]
if isinstance(left, TypeType) and isinstance(left.type_object, abc.ABCMeta): if isinstance(left, TypeType) and isinstance(left.type_object, abc.ABCMeta):
# generic # 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 pass
raise NotImplementedError(node) return self.make_dunder([left, *args], "getitem")
def visit_UnaryOp(self, node: ast.UnaryOp) -> BaseType: def visit_UnaryOp(self, node: ast.UnaryOp) -> BaseType:
raise NotImplementedError(node) raise NotImplementedError(node)
...@@ -213,3 +199,9 @@ class ScoperExprVisitor(ScoperVisitor): ...@@ -213,3 +199,9 @@ class ScoperExprVisitor(ScoperVisitor):
if then != else_: if then != else_:
raise NotImplementedError("IfExp with different types not handled yet") raise NotImplementedError("IfExp with different types not handled yet")
return then 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): ...@@ -59,6 +59,7 @@ class StdlibVisitor(NodeVisitorSeq):
pass pass
def visit_FunctionDef(self, node: ast.FunctionDef): 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_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] arg_types = [arg_visitor.visit(arg.annotation or arg.arg) for arg in node.args.args]
ret_type = arg_visitor.visit(node.returns) ret_type = arg_visitor.visit(node.returns)
......
...@@ -2,6 +2,7 @@ import typing ...@@ -2,6 +2,7 @@ import typing
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from dataclasses import dataclass, field from dataclasses import dataclass, field
from enum import Enum from enum import Enum
from itertools import zip_longest
from typing import Dict, Optional, List, ClassVar, Callable, Any from typing import Dict, Optional, List, ClassVar, Callable, Any
...@@ -106,6 +107,7 @@ class TypeOperator(BaseType, ABC): ...@@ -106,6 +107,7 @@ class TypeOperator(BaseType, ABC):
args: List[BaseType] args: List[BaseType]
name: str = None name: str = None
variadic: bool = False variadic: bool = False
optional_at: Optional[int] = None
gen_methods: ClassVar[Dict[str, GenMethodFactory]] = {} gen_methods: ClassVar[Dict[str, GenMethodFactory]] = {}
def __init_subclass__(cls, **kwargs): def __init_subclass__(cls, **kwargs):
...@@ -137,15 +139,38 @@ class TypeOperator(BaseType, ABC): ...@@ -137,15 +139,38 @@ class TypeOperator(BaseType, ABC):
else: else:
return return
raise IncompatibleTypesError(f"Cannot unify {self} and {other} with different type and no common parents") 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): if len(self.args) != len(other.args):
raise IncompatibleTypesError(f"Cannot unify {self} and {other} with different number of arguments") a, b = self, other
for a, b in zip(self.args, other.args): 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): if isinstance(a, BaseType) and isinstance(b, BaseType):
a.unify(b) a.unify(b)
else: else:
if a != b: if a != b:
raise IncompatibleTypesError(f"Cannot unify {a} and {b}") raise IncompatibleTypesError(f"Cannot unify {a} and {b}")
def contains_internal(self, other: "BaseType") -> bool: def contains_internal(self, other: "BaseType") -> bool:
return any(arg.contains(other) for arg in self.args) 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