Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(transient): adds conj!, assoc!, dissoc! and pop! for transients #62

Merged
merged 7 commits into from
Mar 22, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions include/cpp/jank/prelude.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,5 @@
#include <jank/runtime/behavior/numberable.hpp>
#include <jank/runtime/behavior/nameable.hpp>
#include <jank/runtime/behavior/transientable.hpp>
#include <jank/runtime/behavior/consable.hpp>
#include <jank/runtime/behavior/associatively_writable.hpp>
4 changes: 4 additions & 0 deletions include/cpp/jank/runtime/behavior/associatively_writable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,9 @@ namespace jank::runtime::behavior
{
t->assoc_in_place(object_ptr{}, object_ptr{})
} -> std::convertible_to<object_ptr>;

{
t->dissoc_in_place(object_ptr{})
} -> std::convertible_to<object_ptr>;
};
}
3 changes: 2 additions & 1 deletion include/cpp/jank/runtime/obj/transient_hash_map.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ namespace jank::runtime
native_bool contains(object_ptr key) const;

/* behavior::associatively_writable_in_place */
native_box<static_object> assoc_in_place(object_ptr key, object_ptr val);
native_box<static_object> assoc_in_place(object_ptr const key, object_ptr const val);
native_box<static_object> dissoc_in_place(object_ptr const key);

/* behavior::consable_in_place */
native_box<static_object> cons_in_place(object_ptr head);
Expand Down
2 changes: 2 additions & 0 deletions include/cpp/jank/runtime/obj/transient_vector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ namespace jank::runtime
object_ptr get_entry(object_ptr const idx) const;
native_bool contains(object_ptr const elem) const;

native_box<static_object> pop_in_place();

void assert_active() const;

object base{ object_type::transient_vector };
Expand Down
7 changes: 7 additions & 0 deletions src/cpp/jank/runtime/obj/transient_hash_map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,13 @@ namespace jank::runtime
return this;
}

obj::transient_hash_map_ptr obj::transient_hash_map::dissoc_in_place(object_ptr const key)
{
assert_active();
data.erase(key);
return this;
}

obj::transient_hash_map_ptr obj::transient_hash_map::cons_in_place(object_ptr const head)
{
assert_active();
Expand Down
12 changes: 12 additions & 0 deletions src/cpp/jank/runtime/obj/transient_vector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,18 @@ namespace jank::runtime
}
}

obj::transient_vector_ptr obj::transient_vector::pop_in_place()
{
assert_active();
if(data.empty())
{
throw std::runtime_error{ "Can't pop empty vector" };
}

data.take(data.size() - 1);
return this;
}

void obj::transient_vector::assert_active() const
{
if(!active)
Expand Down
88 changes: 84 additions & 4 deletions src/jank/clojure/core.jank
Original file line number Diff line number Diff line change
Expand Up @@ -400,9 +400,9 @@
if constexpr(behavior::transientable<T>)
{ return typed_o->to_transient(); }
else
{ throw #{ (ex-info :not-transientable {:o o}) }#; }
{ throw ~{ (ex-info :not-transientable {:o o}) }; }
},
#{ o }#
~{ o }
);"))

; Returns a new, persistent version of the transient collection, in
Expand All @@ -418,11 +418,91 @@
if constexpr(behavior::persistentable<T>)
{ return typed_o->to_persistent(); }
else
{ throw #{ (ex-info :not-persistentable {:o o}) }#; }
{ throw ~{ (ex-info :not-persistentable {:o o}) }; }
},
#{ o }#
~{ o }
);"))

(defn conj!
([]
(transient []))
([coll]
coll)
([coll x]
(native/raw "__value = visit_object
(
[=](auto const typed_coll, auto const head) -> object_ptr
{
using T = typename decltype(typed_coll)::value_type;

if constexpr(behavior::consable_in_place<T>)
{ return typed_coll->cons_in_place(head); }
else
{ throw ~{ (ex-info :not-persistentable {:o coll}) }; }
Samy-33 marked this conversation as resolved.
Show resolved Hide resolved
},
~{ coll },
~{ x }
);
")))

(defn assoc!
([coll k v]
(native/raw "__value = visit_object
(
[=](auto const typed_coll, auto const key, auto const val) -> object_ptr
{
using T = typename decltype(typed_coll)::value_type;

if constexpr(behavior::associatively_writable_in_place<T>)
{ return typed_coll->assoc_in_place(key, val); }
else
{ throw ~{ (ex-info :not-associatively_writable_in_place {:o coll}) }; }
},
~{ coll },
~{ k },
~{ v }
);
"))
([coll k v & kvs]
(let [ret (assoc! coll k v)]
(if kvs
(recur ret (first kvs) (second kvs) (nnext kvs))
ret))))

(defn dissoc!
([coll k]
(native/raw "__value = visit_object
(
[=](auto const typed_coll, auto const key) -> object_ptr
{
using T = typename decltype(typed_coll)::value_type;

if constexpr(behavior::associatively_writable_in_place<T>)
{ return typed_coll->dissoc_in_place(key); }
else
{ throw ~{ (ex-info :not-associatively_writable_in_place {:o coll}) }; }
},
~{ coll },
~{ k }
);
"))
([coll k & ks]
(let [ret (dissoc! coll k)]
(if ks
(recur ret (first ks) (next ks))
ret))))

(defn pop!
([coll]
(native/raw "if( ~{ coll }->type == object_type::transient_vector )
{
auto transient_coll = expect_object<obj::transient_vector>(~{ coll });
__value = transient_coll->pop_in_place();
}
else
{ throw ~{ (ex-info :not-transient-vector {:o coll}) }; }
")))

; Functions.

(defn- spread [arglist]
Expand Down
Loading