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 3 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
1 change: 1 addition & 0 deletions include/cpp/jank/prelude.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@
#include <jank/runtime/behavior/numberable.hpp>
#include <jank/runtime/behavior/nameable.hpp>
#include <jank/runtime/behavior/transientable.hpp>
#include <jank/runtime/behavior/associatively_writable.hpp>
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace jank::runtime::behavior
template <typename T>
concept associatively_writable_in_place = requires(T * const t) {
{
t->assoc_in_place(object_ptr{}, object_ptr{})
t->assoc_in_place(object_ptr{}, 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 @@ -23,6 +23,8 @@ namespace jank::runtime
return ret;
}

native_box<static_object> pop_in_place();

/* behavior::objectable */
native_bool equal(object const &) const;
native_persistent_string to_string() const;
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
10 changes: 10 additions & 0 deletions src/cpp/jank/runtime/obj/transient_vector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,16 @@ namespace jank::runtime
return static_cast<native_hash>(reinterpret_cast<uintptr_t>(this));
}

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;
}

size_t obj::transient_vector::count() const
{
assert_active();
Expand Down
86 changes: 86 additions & 0 deletions src/jank/clojure/core.jank
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,92 @@
#{ o }#
);"))

(defn conj!
([]
(transient []))
([coll]
coll)
([coll x]
(native/raw "__value = visit_object
(
[=](auto const typed_t, auto const head) -> object_ptr
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like these were changed from [&] to [=], but I think they can be []. Did you hit an issue with that?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the compiler's mad at me:

➜  jank git:(transient-vector-fns) ✗ ./bin/compile
[1/1] Generating classes/core-libraries
input_line_94:18:29: error: variable 'call_574' cannot be implicitly captured in a lambda with no capture-default specified
                    { throw call_574; }
                            ^
input_line_94:9:243: note: 'call_574' declared here
        jank::profile::timer __timer{ "dissoc_BANG__558" };auto const map_575(jank::make_box<jank::runtime::obj::persistent_array_map>(jank::runtime::detail::in_place_unique{}, jank::make_array_box<object_ptr>(const_561, coll),2));auto const call_574(jank::runtime::dynamic_call(ex_info_559->deref(), const_560, map_575));object_ptr native_573{ obj::nil::nil_const() };{ object_ptr __value{ obj::nil::nil_const() };__value = visit_object
                                                                                                                                                                                                                                                  ^
input_line_94:11:19: note: lambda expression begins here
                  [](auto const typed_t, auto const key) -> object_ptr
                  ^
input_line_94:11:20: note: capture 'call_574' by value
                  [](auto const typed_t, auto const key) -> object_ptr
                   ^
                   call_574

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, that's because you're throwing coll instead of typed_coll. Since you have the fully typed version as the first param to the lambda, we can use that rather than also capturing the erased version.

{
using T = typename decltype(typed_t)::value_type;

if constexpr(behavior::persistentable<T>)
{ return typed_t->cons_in_place(head); }
else
{ throw #{ (ex-info :not-persistentable {:o coll}) }#; }
},
#{ coll }#,
#{ x }#
);
")))

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

if constexpr(behavior::associatively_writable_in_place<T>)
{ return typed_t->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_t, auto const key) -> object_ptr
{
using T = typename decltype(typed_t)::value_type;

if constexpr(behavior::associatively_writable_in_place<T>)
{ return typed_t->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 "__value = visit_object
(
[=](auto const typed_t) -> object_ptr
{
using T = typename decltype(typed_t)::value_type;

if constexpr(std::same_as<T, obj::transient_vector>)
{ return typed_t->pop_in_place(); }
else
{ throw #{ (ex-info :not-transient-vector {:o coll}) }#; }
},
#{ coll }#
);
")))

; Functions.

(defn- spread [arglist]
Expand Down
Loading