Skip to content

Commit

Permalink
Merge pull request #62 from Samy-33/transient-vector-fns
Browse files Browse the repository at this point in the history
feat(transient): adds conj!, assoc!, dissoc! and pop! for transients
  • Loading branch information
jeaye authored Mar 22, 2024
2 parents d51223d + b25c901 commit 250a33e
Show file tree
Hide file tree
Showing 7 changed files with 113 additions and 5 deletions.
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-consable-in-place {:o coll}) }; }
},
~{ 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

0 comments on commit 250a33e

Please sign in to comment.