Commit c307f373 authored by Tom Niget's avatar Tom Niget

Work on mutexes (wip)

parent e2d96f04
...@@ -12,8 +12,10 @@ ...@@ -12,8 +12,10 @@
#include <string> #include <string>
#include <python/basedef.hpp> #include <python/basedef.hpp>
#include <typon/typon.hpp> #include <typon/typon.hpp>
#ifdef __cpp_lib_unreachable #ifdef __cpp_lib_unreachable
#include <utility> #include <utility>
[[noreturn]] inline void TYPON_UNREACHABLE() { std::unreachable(); } [[noreturn]] inline void TYPON_UNREACHABLE() { std::unreachable(); }
...@@ -62,14 +64,13 @@ template <PySmartPtr T> struct RealType<T> { ...@@ -62,14 +64,13 @@ template <PySmartPtr T> struct RealType<T> {
namespace typon { namespace typon {
//class TyNone {}; // class TyNone {};
using TyNone = std::nullopt_t; using TyNone = std::nullopt_t;
auto None = std::nullopt; auto None = std::nullopt;
} // namespace typon } // namespace typon
static constexpr auto None = typon::None; static constexpr auto None = typon::None;
// typon_len // typon_len
...@@ -127,7 +128,6 @@ std::ostream &operator<<(std::ostream &os, std::optional<T> const &opt) { ...@@ -127,7 +128,6 @@ std::ostream &operator<<(std::ostream &os, std::optional<T> const &opt) {
return opt ? os << opt.value() : os << "None"; return opt ? os << opt.value() : os << "None";
} }
#define system_error(err, message) \ #define system_error(err, message) \
do { \ do { \
puts(message); \ puts(message); \
...@@ -140,12 +140,12 @@ std::ostream &operator<<(std::ostream &os, std::optional<T> const &opt) { ...@@ -140,12 +140,12 @@ std::ostream &operator<<(std::ostream &os, std::optional<T> const &opt) {
#include "builtins/dict.hpp" #include "builtins/dict.hpp"
#include "builtins/int.hpp" #include "builtins/int.hpp"
#include "builtins/list.hpp" #include "builtins/list.hpp"
#include "builtins/mutex.hpp"
#include "builtins/print.hpp" #include "builtins/print.hpp"
#include "builtins/range.hpp" #include "builtins/range.hpp"
#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); }
...@@ -421,8 +421,22 @@ template <auto IDX, typename T> auto constant_get(T &&val) { ...@@ -421,8 +421,22 @@ template <auto IDX, typename T> auto constant_get(T &&val) {
} }
} }
struct {
using has_sync = std::true_type;
template <typename T>
auto typon$$sync(T value) const -> decltype(referencemodel::Rc(future(std::declval<Task<T>>())))
{
//return referencemodel::Rc(future(task));
throw;
}
template <typename Task>
auto operator()(Task task) const -> typon::Task<decltype(referencemodel::Rc(future(std::move(task))))>
{
co_return referencemodel::Rc(co_await future(std::move(task)));
}
} static constexpr future_stdlib{};
}; // namespace typon }; // namespace typon
......
...@@ -7,59 +7,62 @@ ...@@ -7,59 +7,62 @@
namespace view = std::views; namespace view = std::views;
#include <python/basedef.hpp> #include <python/basedef.hpp>
#include "print.hpp"
namespace typon { namespace typon {
using namespace referencemodel; using namespace referencemodel;
template<typename _Base0 = object> template <typename _Base0 = object>
struct TyCell__oo : classtype<_Base0, TyCell__oo<>> { struct TyCell__oo : classtype<_Base0, TyCell__oo<>> {
static constexpr std::string_view name = "Cell"; static constexpr std::string_view name = "Cell";
template<typename T> template <typename T> struct Obj : instance<TyCell__oo<>, Obj<T>> {
struct Obj : instance<TyCell__oo<>, Obj<T>> {
T val; T val;
Obj() = default; Obj() = default;
Obj(Obj const&) = delete; Obj(Obj const &) = delete;
}; };
template<typename T> template <typename T> auto operator()(T val) const { return Obj<T>{val}; }
auto operator()(T val) const {
return Obj<T>{val};
}
}; };
template<typename _Base0 = object> template <typename _Base0 = object>
struct TyMutex__oo : classtype<_Base0, TyMutex__oo<>> { struct TyMutex__oo : classtype<_Base0, TyMutex__oo<>> {
static constexpr std::string_view name = "Mutex"; static constexpr std::string_view name = "Mutex";
template<typename T> template <typename T> struct Obj : instance<TyMutex__oo<>, Obj<T>> {
struct Obj : instance<TyMutex__oo<>, Obj<T>> {
typon::Mutex mutex; typon::Mutex mutex;
TyCell__oo<>::Obj<T> cell; TyCell__oo<>::Obj<T> cell;
}; };
struct : method { struct : method {
auto operator()(auto self, auto callback) -> typon::Task<TyNone> const { using has_sync = std::true_type;
auto typon$$sync(auto, auto) -> TyNone const { return None; }
auto operator()(auto _self, auto callback) -> typon::Task<TyNone> const {
print("1"_ps);
auto self = arc(_self);
print("2"_ps);
auto lock = dot(self, mutex).lock(); auto lock = dot(self, mutex).lock();
print("3"_ps);
co_await lock; co_await lock;
print("4"_ps);
co_await callback(ref(dot(self, cell))); co_await callback(ref(dot(self, cell)));
print("5"_ps);
co_return None; co_return None;
} }
} static constexpr when{}; } static constexpr when{};
template<typename T> template <typename T> auto operator()(T val) const {
auto operator()(T val) const {
auto obj = referencemodel::meta::arc<Obj<T>>(std::in_place); auto obj = referencemodel::meta::arc<Obj<T>>(std::in_place);
dot(obj, cell).val = val; dot(obj, cell).val = val;
return obj; return obj;
} }
}; };
template<typename T> template <typename T> using ArcMutex = Arc<TyMutex__oo<>::template Obj<T>>;
using ArcMutex = Arc<TyMutex__oo<>::template Obj<T>>;
} } // namespace typon
static constexpr typon::TyMutex__oo<> Mutex; static constexpr typon::TyMutex__oo<> Mutex;
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
namespace view = std::views; namespace view = std::views;
#include <python/basedef.hpp> #include <python/basedef.hpp>
#include "int.hpp"
auto stride = [](int n) { auto stride = [](int n) {
return [s = -1, n](auto const &) mutable { return [s = -1, n](auto const &) mutable {
...@@ -30,7 +31,7 @@ struct range_s : TyBuiltin<range_s> { ...@@ -30,7 +31,7 @@ struct range_s : TyBuiltin<range_s> {
auto End = Step < 0 ? Begin : std::max(start, stop); auto End = Step < 0 ? Begin : std::max(start, stop);
return view::iota(Begin, End) | view::filter(stride(std::abs(Step))) | return view::iota(Begin, End) | view::filter(stride(std::abs(Step))) |
view::transform([start, stop](std::size_t i) { view::transform([start, stop](std::size_t i) {
return start < stop ? i : stop - (i - start); return typon::TyInt(start < stop ? i : stop - (i - start));
}); });
} }
......
...@@ -23,12 +23,11 @@ struct TySlice__oo : classtype<_Base0, TySlice__oo<>> { ...@@ -23,12 +23,11 @@ struct TySlice__oo : classtype<_Base0, TySlice__oo<>> {
Stop stop; Stop stop;
Step step; Step step;
Obj(Start start, Stop stop, Step step) : start(start), stop(stop), step(step) {} Obj(Start start, Stop stop, Step step)
: start(start), stop(stop), step(step) {}
}; };
template <typename Stop> template <typename Stop> auto operator()(Stop stop) const {
auto operator()(Stop stop) const {
return Obj<TyNone, Stop, TyNone>{None, stop, None}; return Obj<TyNone, Stop, TyNone>{None, stop, None};
} }
...@@ -40,13 +39,12 @@ struct TySlice__oo : classtype<_Base0, TySlice__oo<>> { ...@@ -40,13 +39,12 @@ struct TySlice__oo : classtype<_Base0, TySlice__oo<>> {
template <typename Start, typename Stop, typename Step> template <typename Start, typename Stop, typename Step>
auto operator()(Start start, Stop stop, Step step) const { auto operator()(Start start, Stop stop, Step step) const {
return Obj<Start, Stop, Step>{start, stop, step}; return Obj<Start, Stop, Step>{start, stop, step};
} }
}; };
static constexpr TySlice__oo<> TySlice{}; static constexpr TySlice__oo<> TySlice{};
} } // namespace typon
/*struct TySlice { /*struct TySlice {
TySlice() = default; TySlice() = default;
TySlice(const TySlice &) = default; TySlice(const TySlice &) = default;
......
...@@ -185,15 +185,14 @@ struct socket__oo : referencemodel::moduletype<socket__oo<>> { ...@@ -185,15 +185,14 @@ struct socket__oo : referencemodel::moduletype<socket__oo<>> {
err != 0) { err != 0) {
system_error(err, "getaddrinfo()"); system_error(err, "getaddrinfo()");
} }
auto rlist = typon::TyList({ auto rlist = typon::TyList(
// make tuple (family, type, proto, canonname, sockaddr) {// make tuple (family, type, proto, canonname, sockaddr)
// (int, int, int, str, str) // (int, int, int, str, str)
std::make_tuple( std::make_tuple(
typon::TyInt(res->ai_family), typon::TyInt(res->ai_socktype), typon::TyInt(res->ai_family), typon::TyInt(res->ai_socktype),
typon::TyInt(res->ai_protocol), typon::TyInt(res->ai_protocol),
typon::TyStr(res->ai_canonname ? res->ai_canonname : ""), typon::TyStr(res->ai_canonname ? res->ai_canonname : ""),
typon::TyStr(res->ai_addr ? res->ai_addr->sa_data : "")) typon::TyStr(res->ai_addr ? res->ai_addr->sa_data : ""))});
});
::freeaddrinfo(res); ::freeaddrinfo(res);
return rlist; return rlist;
} }
......
from time import sleep
class Actor[T]:
mutex: Mutex[T]
def __init__(self, val: T):
self.mutex = Mutex(val)
def when[U](self, f: Callable[[Cell[T]], U]):
return future(lambda: self.mutex.when(f))
def inc(cell):
print("inc")
x = cell.val
sleep(1)
cell.val = x + 1
print("current:", cell.val)
def truc():
print("a")
a = Actor(0)
print("b")
for i in range(10):
print("spawn", i)
a.when(inc)
print("spawned", i)
future = a.when(lambda cell: print("final:", cell.val))
# future.get()
print("done")
if __name__ == "__main__":
print("Actor:")
truc()
\ No newline at end of file
...@@ -20,9 +20,7 @@ class Actor[T]: ...@@ -20,9 +20,7 @@ class Actor[T]:
mutex: Mutex[T] mutex: Mutex[T]
def __init__(self, val: T): def __init__(self, val: T):
print("l")
self.mutex = Mutex(val) self.mutex = Mutex(val)
print("m")
# def when(self, f: Callable[[T], object]): # def when(self, f: Callable[[T], object]):
# return future(lambda: self.mutex.when(f)) # return future(lambda: self.mutex.when(f))
...@@ -31,9 +29,7 @@ def thing(x): ...@@ -31,9 +29,7 @@ def thing(x):
print("hello", x) print("hello", x)
if __name__ == "__main__": if __name__ == "__main__":
print("j")
act = Actor(123) act = Actor(123)
print("k")
act.mutex.when(thing) act.mutex.when(thing)
# class Actor[T]: # class Actor[T]:
......
...@@ -22,13 +22,13 @@ def truc(): ...@@ -22,13 +22,13 @@ def truc():
m = Mutex(0) m = Mutex(0)
for _ in range(10): for _ in range(10):
fork(lambda: m.when(inc)) fork(lambda: m.when(inc))
sync() #sync()
def nomutex(): def nomutex():
t = Thing(0) t = Thing(0)
for _ in range(10): for _ in range(10):
fork(lambda: t.inc()) fork(lambda: t.inc())
sync() #sync()
if __name__ == "__main__": if __name__ == "__main__":
......
...@@ -64,7 +64,7 @@ def emit_class(name: str, node: ConcreteType) -> Iterable[str]: ...@@ -64,7 +64,7 @@ def emit_class(name: str, node: ConcreteType) -> Iterable[str]:
yield "template <" yield "template <"
if node.generic_parent.parameters: if node.generic_parent.parameters:
yield from join(",", (f"typename {name}" for name in node.generic_parent.parameters)) yield from join(",", (f"typename {p.name}" for p in node.generic_parent.parameters))
yield ", typename... $T" yield ", typename... $T"
else: else:
yield "typename... $T, typename _Void = void" yield "typename... $T, typename _Void = void"
......
...@@ -127,8 +127,11 @@ class ExpressionVisitor(NodeVisitor): ...@@ -127,8 +127,11 @@ class ExpressionVisitor(NodeVisitor):
assert len(node.args) == 1 assert len(node.args) == 1
arg = node.args[0] arg = node.args[0]
assert isinstance(arg, ast.Lambda) assert isinstance(arg, ast.Lambda)
fixed = node.func.id
if fixed == "future": # Temporary until we separate the namespaces
fixed = "future_stdlib"
if self.generator != CoroutineMode.SYNC: if self.generator != CoroutineMode.SYNC:
yield f"co_await typon::{node.func.id}(" yield f"co_await typon::{fixed}("
assert isinstance(arg.body, ast.Call) assert isinstance(arg.body, ast.Call)
yield from self.visit(arg.body.func) yield from self.visit(arg.body.func)
yield "(" yield "("
...@@ -136,7 +139,14 @@ class ExpressionVisitor(NodeVisitor): ...@@ -136,7 +139,14 @@ class ExpressionVisitor(NodeVisitor):
yield ")" yield ")"
yield ")" yield ")"
else: else:
match node.func.id:
case "fork":
yield from self.visit(arg.body) # fork is transparent
case "future":
yield "typon::future_stdlib.typon$$sync("
yield from self.visit(arg.body) yield from self.visit(arg.body)
yield ")"
return return
if isinstance(node.func, ast.Name) and node.func.id == "sync": if isinstance(node.func, ast.Name) and node.func.id == "sync":
...@@ -154,7 +164,8 @@ class ExpressionVisitor(NodeVisitor): ...@@ -154,7 +164,8 @@ class ExpressionVisitor(NodeVisitor):
if self.generator != CoroutineMode.SYNC: if self.generator != CoroutineMode.SYNC:
nty = node.type.resolve() nty = node.type.resolve()
if isinstance(nty, ResolvedConcreteType) and ( if isinstance(nty, ResolvedConcreteType) and (
nty.inherits(TY_FUTURE) or ( #nty.inherits(TY_FUTURE) or
(
is_get and nty.inherits(TY_FORKED) is_get and nty.inherits(TY_FORKED)
) )
): ):
...@@ -175,7 +186,7 @@ class ExpressionVisitor(NodeVisitor): ...@@ -175,7 +186,7 @@ class ExpressionVisitor(NodeVisitor):
if is_get and node.func.value.type.inherits(TY_FUTURE, TY_FORKED): if is_get and node.func.value.type.inherits(TY_FUTURE, TY_FORKED):
yield "(" yield "("
yield from self.visit(node.func.value) yield from self.visit(node.func.value)
yield ").get" yield ")->get"
else: else:
yield from self.visit(node.func) yield from self.visit(node.func)
...@@ -252,10 +263,10 @@ class ExpressionVisitor(NodeVisitor): ...@@ -252,10 +263,10 @@ class ExpressionVisitor(NodeVisitor):
templ, args, _ = self.process_args(node.args) templ, args, _ = self.process_args(node.args)
yield templ yield templ
yield args yield args
yield "->" yield "-> typon::Task<"
yield from self.visit(node.type.deref().return_type) yield from self.visit(node.type.deref().return_type)
yield "{" yield "> {"
yield "return" yield "co_return"
yield from self.visit(node.body) yield from self.visit(node.body)
yield ";" yield ";"
yield "}" yield "}"
......
...@@ -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_TYPE, TY_SLICE TY_FORKED, TY_JOIN, TypeTupleType, TupleInstanceType, TY_TYPE, TY_SLICE, BoundFuncTypeBase
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
...@@ -166,6 +166,8 @@ class ScoperExprVisitor(ScoperVisitor): ...@@ -166,6 +166,8 @@ class ScoperExprVisitor(ScoperVisitor):
raise TypeMismatchError(a, b, TypeMismatchKind.DIFFERENT_TYPE) raise TypeMismatchError(a, b, TypeMismatchKind.DIFFERENT_TYPE)
if not ftype.is_native: if not ftype.is_native:
if isinstance(ftype.generic_parent, BoundFuncTypeBase):
i += 1
pname = ftype.block_data.node.args.args[i].arg pname = ftype.block_data.node.args.args[i].arg
ftype.block_data.scope.declare_local(pname, b) ftype.block_data.scope.declare_local(pname, b)
......
...@@ -16,7 +16,7 @@ from transpiler.phases.typing.scope import Scope, VarDecl, VarKind, ScopeKind ...@@ -16,7 +16,7 @@ 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, BlockData, TY_TASK, UserGenericType, UserType MethodType, UniqueTypeMixin, GenericType, BlockData, TY_TASK, UserGenericType, UserType, BoundFuncTypeBase
from transpiler.phases.utils import NodeVisitorSeq from transpiler.phases.utils import NodeVisitorSeq
def visit_generic_item( def visit_generic_item(
...@@ -254,7 +254,7 @@ class StdlibVisitor(NodeVisitorSeq): ...@@ -254,7 +254,7 @@ class StdlibVisitor(NodeVisitorSeq):
if cur_class_ref is not None: if cur_class_ref is not None:
def remove_self(self, self_type): def remove_self(self, self_type):
class BoundFuncType(UniqueTypeMixin, GenericType): class BoundFuncType(BoundFuncTypeBase, GenericType):
def name(self) -> str: def name(self) -> str:
return f"BoundFuncType${node.name}" return f"BoundFuncType${node.name}"
......
...@@ -238,6 +238,9 @@ class UniqueTypeMixin: ...@@ -238,6 +238,9 @@ class UniqueTypeMixin:
def contains_internal(self, other: "BaseType") -> bool: def contains_internal(self, other: "BaseType") -> bool:
return self == other return self == other
class BoundFuncTypeBase(UniqueTypeMixin):
pass
@dataclass(eq=False) @dataclass(eq=False)
class BuiltinType(UniqueTypeMixin, ResolvedConcreteType): class BuiltinType(UniqueTypeMixin, ResolvedConcreteType):
pass pass
......
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