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

Fix instance methods and start work on actors and mutexes

parent 3060d6c4
...@@ -140,6 +140,7 @@ static constexpr auto PyNone = std::nullopt; ...@@ -140,6 +140,7 @@ static constexpr auto PyNone = std::nullopt;
#include "builtins/set.hpp" #include "builtins/set.hpp"
#include "builtins/slice.hpp" #include "builtins/slice.hpp"
#include "builtins/str.hpp" #include "builtins/str.hpp"
#include "builtins/mutex.hpp"
auto is_cpp() { return typon::TyBool(true); } auto is_cpp() { return typon::TyBool(true); }
...@@ -414,6 +415,11 @@ template <auto IDX, typename T> auto constant_get(T &&val) { ...@@ -414,6 +415,11 @@ template <auto IDX, typename T> auto constant_get(T &&val) {
return dot(std::forward<T>(val), oo__getitem__oo)(IDX); return dot(std::forward<T>(val), oo__getitem__oo)(IDX);
} }
} }
}; // namespace typon }; // namespace typon
#endif // TYPON_BUILTINS_HPP #endif // TYPON_BUILTINS_HPP
#ifndef TYPON_MUTEX_HPP
#define TYPON_MUTEX_HPP
#include <ranges>
namespace view = std::views;
#include <python/basedef.hpp>
namespace typon {
using namespace referencemodel;
template<typename _Base0 = object>
struct TyMutex__oo : classtype<_Base0, TyMutex__oo<>> {
static constexpr std::string_view name = "Mutex";
template<typename T>
struct Obj : instance<TyMutex__oo<>, Obj<T>> {
typon::Mutex mutex;
T val;
};
struct : method {
auto operator()(auto self, auto callback) -> typon::Task<TyNone> const {
auto lock = dot(self, mutex).lock();
co_await lock;
co_await callback(dot(self, val));
co_return {};
}
} static constexpr when{};
template<typename T>
auto operator()(T val) const {
auto obj = arc(Obj<T>());
dot(obj, val) = val;
return obj;
}
};
template<typename T>
using ArcMutex = Arc<TyMutex__oo<>::template Obj<T>>;
}
static constexpr typon::TyMutex__oo<> Mutex;
#endif // TYPON_MUTEX_HPP
...@@ -215,4 +215,17 @@ def future[T](f: Callable[[], T]) -> Task[Future[T]]: ...@@ -215,4 +215,17 @@ def future[T](f: Callable[[], T]) -> Task[Future[T]]:
def sync() -> None: def sync() -> None:
# stub # stub
pass pass
\ No newline at end of file
class Cell[T]:
def __init__(self, val: T) -> None: ...
class Mutex[T]:
def __init__(self, val: T) -> None: ...
def when[R](self, f: Callable[[Cell[T]], R]) -> R:
pass
assert Cell(123)
assert Cell("abc")
assert Mutex(True)
\ No newline at end of file
# class Cell[T]:
# val: T
#
# class Mutex[T]:
# cell: Cell[T]
#
# def when[R](self, f: Callable[[Cell[T]], R]) -> R:
# pass
#
# def __enter__(self) -> Cell[T]:
# # locks then returns cell
# return self.cell
#
# def __exit__(self, exc_type, exc_val, exc_tb):
# # unlocks
# pass
# @arc
class Actor[T]:
mutex: Mutex[T]
def __init__(self, val: T):
self.mutex = Mutex(val)
# def when(self, f: Callable[[T], object]):
# return future(lambda: self.mutex.when(f))
def thing(x):
print("hello", x)
if __name__ == "__main__":
act = Actor(123)
act.mutex.when(thing)
# class Actor[T]:
# def __init__(self):
# self.fifo = []
# future(lambda: self.handle())
#
# def handle(self):
# while True:
# if self.fifo:
# f = self.fifo.pop(0)
# self.mutex.when(f)
# else:
# yield
#
# mutex: Mutex[T]
#
# def when(self, f: Callable[[T], object]):
# #return future(lambda: self.mutex.when(f))
# self.fifo.append(f)
#
#
#
# class A:
# def f(self): pass
#
# a = Actor[A]()
#
# a.when(A.f)
#
# b = Actor[int]()
...@@ -6,11 +6,12 @@ class Person: ...@@ -6,11 +6,12 @@ class Person:
age: int age: int
def __init__(self, name, age): def __init__(self, name, age):
print("init")
self.name = name self.name = name
self.age = age self.age = age
def afficher(self): def afficher(self):
print(self.name, self.age) print("afficher", self.name, self.age)
# def creer(): # def creer():
# return Person("jean", 123) # return Person("jean", 123)
...@@ -19,8 +20,8 @@ if __name__ == "__main__": ...@@ -19,8 +20,8 @@ if __name__ == "__main__":
y = Person y = Person
#x = creer() #x = creer()
x = Person("jean", 123) x = Person("jean", 123)
print(x.name) print("name", x.name)
print(x.age) print("age", x.age)
x.afficher() x.afficher()
#y.afficher(x) y.afficher(x)
...@@ -8,6 +8,7 @@ from transpiler.phases.typing.types import ConcreteType, TypeVariable, RuntimeVa ...@@ -8,6 +8,7 @@ from transpiler.phases.typing.types import ConcreteType, TypeVariable, RuntimeVa
def emit_class(name: str, node: ConcreteType) -> Iterable[str]: def emit_class(name: str, node: ConcreteType) -> Iterable[str]:
__TB_NODE__ = node.block_data.node
yield f"template <typename _Base0 = referencemodel::object>" yield f"template <typename _Base0 = referencemodel::object>"
yield f"struct {name}__oo : referencemodel::classtype<_Base0, {name}__oo<>> {{" yield f"struct {name}__oo : referencemodel::classtype<_Base0, {name}__oo<>> {{"
yield f"static constexpr std::string_view name = \"{name}\";" yield f"static constexpr std::string_view name = \"{name}\";"
...@@ -16,15 +17,22 @@ def emit_class(name: str, node: ConcreteType) -> Iterable[str]: ...@@ -16,15 +17,22 @@ def emit_class(name: str, node: ConcreteType) -> Iterable[str]:
# for stmt in node.body: # for stmt in node.body:
# yield from inner.visit(stmt) # yield from inner.visit(stmt)
if node.generic_parent.parameters: def template_params():
yield "template<" if node.generic_parent.parameters:
yield from join(",", (f"typename {p.name}" for p in node.generic_parent.parameters)) yield from (p.name for p in node.generic_parent.parameters)
yield ">" else:
yield "_Void"
yield "template<"
yield from join(",", (f"typename {name}" for name in template_params()))
yield ">"
yield f"struct Obj : referencemodel::instance<{name}__oo<>, Obj" yield f"struct Obj : referencemodel::instance<{name}__oo<>, Obj"
yield "<"
if node.generic_parent.parameters: if node.generic_parent.parameters:
yield "<"
yield from join(",", (p.name for p in node.generic_parent.parameters)) yield from join(",", (p.name for p in node.generic_parent.parameters))
yield ">" else:
yield "_Void"
yield ">"
yield "> {" yield "> {"
for mname, mdef in node.fields.items(): for mname, mdef in node.fields.items():
...@@ -37,10 +45,10 @@ def emit_class(name: str, node: ConcreteType) -> Iterable[str]: ...@@ -37,10 +45,10 @@ def emit_class(name: str, node: ConcreteType) -> Iterable[str]:
# for stmt in node.body: # for stmt in node.body:
# yield from inner.visit(stmt) # yield from inner.visit(stmt)
yield "template <typename... U>" # yield "template <typename... U>"
yield "Obj(U&&... args) {" # yield "Obj(U&&... args) {"
yield "dot(this, __init__)(this, std::forward<U>(args)...);" # yield "dot(this, __init__)(this, std::forward<U>(args)...);"
yield "}" # yield "}"
yield "};" yield "};"
...@@ -50,15 +58,25 @@ def emit_class(name: str, node: ConcreteType) -> Iterable[str]: ...@@ -50,15 +58,25 @@ def emit_class(name: str, node: ConcreteType) -> Iterable[str]:
if isinstance(mdef.val, ast.FunctionDef): if isinstance(mdef.val, ast.FunctionDef):
gen_p = [TypeVariable(p.name, emit_as_is=True) for p in mdef.type.parameters] gen_p = [TypeVariable(p.name, emit_as_is=True) for p in mdef.type.parameters]
ty = mdef.type.instantiate(gen_p) ty = mdef.type.instantiate(gen_p)
ScoperExprVisitor(ty.block_data.scope).visit_function_call(ty, [TypeVariable() for _ in ty.parameters]) ScoperExprVisitor(ty.block_data.scope).visit_function_call(ty, [TypeVariable(decltype_str=f"decltype({arg.arg})") for arg in ty.block_data.node.args.args])
yield from emit_function(mname, ty, "method") yield from emit_function(mname, ty, "method")
yield "template <typename... T>" yield "template <"
yield "auto operator() (T&&... args) const {" yield from join(",", (f"typename {name}" for name in template_params()))
yield "return referencemodel::rc(Obj(std::forward<T>(args)...));" yield ", typename... $T"
yield ">"
def obj_params():
yield from join(",", template_params())
yield "auto operator() ($T&&... args) const -> typon::Task<decltype(referencemodel::rc(Obj<"
yield from obj_params()
yield ">{}))> {"
yield "auto obj = referencemodel::rc(Obj<"
yield from obj_params()
yield ">{});"
yield "co_await dot(obj, __init__)(std::forward<$T>(args)...);"
yield "co_return obj;"
yield "}" yield "}"
yield f"}};" yield f"}};"
yield f"static constexpr {name}__oo<> {name} {{}};" yield f"static constexpr {name}__oo<> {name} {{}};"
yield f"static_assert(sizeof {name} == 1);" yield f"static_assert(sizeof {name} == 1);"
\ No newline at end of file
...@@ -178,7 +178,18 @@ class ExpressionVisitor(NodeVisitor): ...@@ -178,7 +178,18 @@ class ExpressionVisitor(NodeVisitor):
else: else:
yield from self.visit(node.func) yield from self.visit(node.func)
yield ")(" yield ")"
if isinstance(node.func.type, ClassTypeType):
inner = node.func.type.inner_type
assert inner is node.type.generic_parent
yield ".template operator()"
yield "<"
yield from join(", ", (self.visit(arg) for arg in node.type.generic_args))
yield ">"
yield "("
yield from join(", ", map(self.visit, node.args)) yield from join(", ", map(self.visit, node.args))
yield ")" yield ")"
#raise NotImplementedError() #raise NotImplementedError()
......
...@@ -44,7 +44,8 @@ def emit_module(mod: ModuleType) -> Iterable[str]: ...@@ -44,7 +44,8 @@ def emit_module(mod: ModuleType) -> Iterable[str]:
match ty: match ty:
case CallableInstanceType(): case CallableInstanceType():
ty.generic_parent.instance_cache = [] ty.generic_parent.instance_cache = []
ScoperExprVisitor(ty.block_data.scope).visit_function_call(ty, [TypeVariable() for _ in ty.parameters]) ScoperExprVisitor(ty.block_data.scope).visit_function_call(
ty, [TypeVariable(decltype_str=arg.arg) for arg in ty.block_data.node.args.args])
yield from emit_function(name, ty, gen_p=gen_p) yield from emit_function(name, ty, gen_p=gen_p)
case GenericInstanceType() if isinstance(ty.generic_parent, UserGenericType): case GenericInstanceType() if isinstance(ty.generic_parent, UserGenericType):
yield from emit_class(name, ty) yield from emit_class(name, ty)
......
...@@ -71,9 +71,11 @@ class NodeVisitor(UniversalVisitor): ...@@ -71,9 +71,11 @@ class NodeVisitor(UniversalVisitor):
yield "typon::TyNone" yield "typon::TyNone"
case types.TY_STR: case types.TY_STR:
yield 'decltype(""_ps)' yield 'decltype(""_ps)'
case types.TypeVariable(name, emit_as_is=em): case types.TypeVariable(name, emit_as_is=em, decltype_str=dt):
if em: if em:
yield name yield name
elif dt:
yield dt
else: else:
raise UnresolvedTypeVariableError(node) raise UnresolvedTypeVariableError(node)
yield f"$VAR__{name}" yield f"$VAR__{name}"
...@@ -96,6 +98,8 @@ class NodeVisitor(UniversalVisitor): ...@@ -96,6 +98,8 @@ class NodeVisitor(UniversalVisitor):
yield "typon::Join" yield "typon::Join"
case types.TY_FORKED: case types.TY_FORKED:
yield "typon::Forked" yield "typon::Forked"
case types.TY_MUTEX:
yield "typon::ArcMutex"
case _: case _:
raise NotImplementedError(node) raise NotImplementedError(node)
......
...@@ -2,7 +2,7 @@ from transpiler.phases.typing.common import PRELUDE ...@@ -2,7 +2,7 @@ from transpiler.phases.typing.common import PRELUDE
from transpiler.phases.typing.scope import VarKind, VarDecl from transpiler.phases.typing.scope import VarKind, VarDecl
from transpiler.phases.typing.types import TY_TASK, TY_CALLABLE, TY_OPTIONAL, TY_CPP_TYPE, TY_BUILTIN_FEATURE, TY_TUPLE, \ from transpiler.phases.typing.types import TY_TASK, TY_CALLABLE, TY_OPTIONAL, TY_CPP_TYPE, TY_BUILTIN_FEATURE, TY_TUPLE, \
TY_DICT, TY_SET, TY_LIST, TY_COMPLEX, TY_BYTES, TY_STR, TY_FLOAT, TY_INT, TY_BOOL, TY_OBJECT, TY_JOIN, TY_FUTURE, \ TY_DICT, TY_SET, TY_LIST, TY_COMPLEX, TY_BYTES, TY_STR, TY_FLOAT, TY_INT, TY_BOOL, TY_OBJECT, TY_JOIN, TY_FUTURE, \
TY_FORKED, TY_GENERATOR TY_FORKED, TY_GENERATOR, TY_MUTEX
prelude_vars = { prelude_vars = {
"object": TY_OBJECT, "object": TY_OBJECT,
...@@ -23,6 +23,7 @@ prelude_vars = { ...@@ -23,6 +23,7 @@ prelude_vars = {
"Future": TY_FUTURE, "Future": TY_FUTURE,
"Forked": TY_FORKED, "Forked": TY_FORKED,
"Generator": TY_GENERATOR, "Generator": TY_GENERATOR,
"Mutex": TY_MUTEX
} }
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()})
......
...@@ -46,6 +46,12 @@ class TypeAnnotationVisitor(NodeVisitorSeq): ...@@ -46,6 +46,12 @@ class TypeAnnotationVisitor(NodeVisitorSeq):
assert isinstance(ty_op, GenericType) assert isinstance(ty_op, GenericType)
return ty_op.instantiate(args) return ty_op.instantiate(args)
def visit_Call(self, node: ast.Call) -> BaseType:
if orig := getattr(node, "orig_node", None):
if isinstance(orig, ast.Subscript):
return self.visit_Subscript(orig)
raise NotImplementedError()
def visit_List(self, node: ast.List) -> BaseType: def visit_List(self, node: ast.List) -> BaseType:
return TypeListType([self.visit(elt) for elt in node.elts]) return TypeListType([self.visit(elt) for elt in node.elts])
......
...@@ -9,7 +9,7 @@ from transpiler.phases.typing.exceptions import ArgumentCountMismatchError, Type ...@@ -9,7 +9,7 @@ from transpiler.phases.typing.exceptions import ArgumentCountMismatchError, Type
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, MethodType, TY_TUPLE, GenericInstanceType, PROMISES, TRANSPARENT_PROMISES, \ TypeVariable, TY_LAMBDA, TypeListType, MethodType, TY_TUPLE, GenericInstanceType, PROMISES, TRANSPARENT_PROMISES, \
TY_FORKED, TY_JOIN, TypeTupleType, TupleInstanceType TY_FORKED, TY_JOIN, TypeTupleType, TupleInstanceType, TY_TYPE
from transpiler.phases.typing.scope import ScopeKind, VarDecl, VarKind from transpiler.phases.typing.scope import ScopeKind, VarDecl, VarKind
from transpiler.utils import linenodata from transpiler.utils import linenodata
...@@ -142,9 +142,10 @@ class ScoperExprVisitor(ScoperVisitor): ...@@ -142,9 +142,10 @@ class ScoperExprVisitor(ScoperVisitor):
def visit_function_call(self, ftype: ResolvedConcreteType, arguments: List[BaseType]): def visit_function_call(self, ftype: ResolvedConcreteType, arguments: List[BaseType]):
ftype = ftype.deref() ftype = ftype.deref()
if isinstance(ftype, ClassTypeType): if isinstance(ftype, ClassTypeType):
init = self.visit_getattr(ftype, "__init__") ftype = ftype.inner_type.deref()
self.visit_function_call(init, [ftype.inner_type, *arguments]) init = self.visit_getattr(TY_TYPE.instantiate([ftype]), "__init__")
return ftype.inner_type self.visit_function_call(init, [ftype, *arguments])
return ftype
# assert isinstance(ftype, CallableInstanceType) TODO # assert isinstance(ftype, CallableInstanceType) TODO
...@@ -161,6 +162,7 @@ class ScoperExprVisitor(ScoperVisitor): ...@@ -161,6 +162,7 @@ class ScoperExprVisitor(ScoperVisitor):
break break
raise ArgumentCountMismatchError(ftype, arguments) raise ArgumentCountMismatchError(ftype, arguments)
if not a.try_assign(b): if not a.try_assign(b):
a.try_assign(b)
raise TypeMismatchError(a, b, TypeMismatchKind.DIFFERENT_TYPE) raise TypeMismatchError(a, b, TypeMismatchKind.DIFFERENT_TYPE)
if not ftype.is_native: if not ftype.is_native:
...@@ -201,7 +203,7 @@ class ScoperExprVisitor(ScoperVisitor): ...@@ -201,7 +203,7 @@ class ScoperExprVisitor(ScoperVisitor):
# return equivalent.return_type # return equivalent.return_type
def visit_Lambda(self, node: ast.Lambda) -> BaseType: def visit_Lambda(self, node: ast.Lambda) -> BaseType:
argtypes = [TypeVariable() for _ in node.args.args] argtypes = [TypeVariable(decltype_str=f"decltype({arg.arg})") for arg in node.args.args]
rtype = TypeVariable() rtype = TypeVariable()
ftype = TY_LAMBDA.instantiate([TypeListType(argtypes), rtype]) ftype = TY_LAMBDA.instantiate([TypeListType(argtypes), rtype])
scope = self.scope.child(ScopeKind.FUNCTION) scope = self.scope.child(ScopeKind.FUNCTION)
......
...@@ -119,6 +119,7 @@ class TypeVariable(ConcreteType): ...@@ -119,6 +119,7 @@ class TypeVariable(ConcreteType):
var_name: str = field(default_factory=lambda: next_var_id()) var_name: str = field(default_factory=lambda: next_var_id())
resolved: Optional[ConcreteType] = None resolved: Optional[ConcreteType] = None
emit_as_is: bool = False emit_as_is: bool = False
decltype_str: Optional[str] = None
def resolve(self) -> ConcreteType: def resolve(self) -> ConcreteType:
if self.resolved is None: if self.resolved is None:
...@@ -143,8 +144,15 @@ class TypeVariable(ConcreteType): ...@@ -143,8 +144,15 @@ class TypeVariable(ConcreteType):
if other.contains(self): if other.contains(self):
from transpiler.phases.typing.exceptions import RecursiveTypeUnificationError from transpiler.phases.typing.exceptions import RecursiveTypeUnificationError
raise RecursiveTypeUnificationError(self, other) raise RecursiveTypeUnificationError(self, other)
self.resolved = other self.resolved = other
if isinstance(other, TypeVariable) and self.decltype_str != other.decltype_str:
if (self.decltype_str and self.decltype_str.startswith("decltype")) and (other.decltype_str and other.decltype_str.startswith("decltype")):
pass
elif (self.decltype_str and self.decltype_str.startswith("decltype")):
other.decltype_str = self.decltype_str
def contains_internal(self, other: BaseType) -> bool: def contains_internal(self, other: BaseType) -> bool:
return self.resolve() is other.resolve() return self.resolve() is other.resolve()
...@@ -337,11 +345,12 @@ class GenericType(BaseType): ...@@ -337,11 +345,12 @@ class GenericType(BaseType):
return res return res
def instantiate_default(self) -> GenericInstanceType: def instantiate_default(self) -> GenericInstanceType:
return self.instantiate([TypeVariable() for _ in self.parameters]) return self.instantiate([TypeVariable(decltype_str=p.name) for p in self.parameters])
def __str__(self): def __str__(self):
try: try:
return str(self.instantiate_default()) default = self.instantiate_default()
return "<" + ", ".join(str(arg.name()) for arg in default.generic_args) + "> " + str(default)
except: except:
return super().__str__() return super().__str__()
...@@ -421,6 +430,9 @@ TY_SET = create_builtin_generic_type("set") ...@@ -421,6 +430,9 @@ 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")
TY_MUTEX = create_builtin_generic_type("Mutex")
# @dataclass(eq=False) # @dataclass(eq=False)
# class PromiseInstanceType(GenericInstanceType): # class PromiseInstanceType(GenericInstanceType):
# value: ConcreteType # value: ConcreteType
...@@ -576,6 +588,7 @@ class CallableInstanceType(GenericInstanceType, MethodType): ...@@ -576,6 +588,7 @@ class CallableInstanceType(GenericInstanceType, MethodType):
return f"({", ".join(map(str, self.parameters + (["*args"] if self.is_variadic else [])))}) -> {self.return_type}" return f"({", ".join(map(str, self.parameters + (["*args"] if self.is_variadic else [])))}) -> {self.return_type}"
def try_assign_internal(self, other: BaseType) -> bool: def try_assign_internal(self, other: BaseType) -> bool:
other = other.deref()
if not isinstance(other, CallableInstanceType): if not isinstance(other, CallableInstanceType):
return False return False
......
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