Skip to content

Commit

Permalink
feat(transient-vector): adds initial support for transient vector
Browse files Browse the repository at this point in the history
  • Loading branch information
Samy-33 committed Mar 8, 2024
1 parent e7bcbf3 commit a5e5254
Show file tree
Hide file tree
Showing 6 changed files with 202 additions and 6 deletions.
6 changes: 6 additions & 0 deletions include/cpp/jank/runtime/erasure.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <jank/runtime/obj/persistent_hash_map.hpp>
#include <jank/runtime/obj/persistent_hash_map_sequence.hpp>
#include <jank/runtime/obj/transient_hash_map.hpp>
#include <jank/runtime/obj/transient_vector.hpp>
#include <jank/runtime/obj/iterator.hpp>
#include <jank/runtime/obj/range.hpp>
#include <jank/runtime/obj/jit_function.hpp>
Expand Down Expand Up @@ -179,6 +180,11 @@ namespace jank::runtime
return fn(expect_object<obj::transient_hash_map>(erased), std::forward<Args>(args)...);
}
break;
case object_type::transient_vector:
{
return fn(expect_object<obj::transient_vector>(erased), std::forward<Args>(args)...);
}
break;
case object_type::persistent_set:
{
return fn(expect_object<obj::persistent_set>(erased), std::forward<Args>(args)...);
Expand Down
19 changes: 13 additions & 6 deletions include/cpp/jank/runtime/obj/persistent_vector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,19 @@

namespace jank::runtime
{
namespace obj
{
using persistent_vector = static_object<object_type::persistent_vector>;
using persistent_vector_ptr = native_box<persistent_vector>;

using transient_vector = static_object<object_type::transient_vector>;
using transient_vector_ptr = native_box<transient_vector>;
}

template <>
struct static_object<object_type::persistent_vector> : gc
{
using transient_type = static_object<object_type::transient_vector>;
using value_type = runtime::detail::native_persistent_vector;

static constexpr bool pointer_free{ false };
Expand Down Expand Up @@ -51,15 +61,12 @@ namespace jank::runtime
/* behavior::consable */
native_box<static_object> cons(object_ptr head) const;

/* behavior::transientable */
obj::transient_vector_ptr to_transient() const;

object base{ object_type::persistent_vector };
value_type data;
option<object_ptr> meta;
mutable native_hash hash{};
};

namespace obj
{
using persistent_vector = static_object<object_type::persistent_vector>;
using persistent_vector_ptr = native_box<persistent_vector>;
}
}
60 changes: 60 additions & 0 deletions include/cpp/jank/runtime/obj/transient_vector.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#pragma once

#include <jank/runtime/object.hpp>

namespace jank::runtime
{
template <>
struct static_object<object_type::transient_vector> : gc
{
static constexpr bool pointer_free{ false };

using value_type = detail::native_transient_vector;
using persistent_type = static_object<object_type::persistent_vector>;

static_object() = default;
static_object(static_object &&) = default;
static_object(static_object const &) = default;
static_object(detail::native_persistent_vector const &d);
static_object(detail::native_persistent_vector &&d);
static_object(value_type &&d);

static native_box<static_object> empty()
{
static auto const ret(make_box<static_object>());
return ret;
}

/* behavior::objectable */
native_bool equal(object const &) const;
native_persistent_string to_string() const;
void to_string(fmt::memory_buffer &buff) const;
native_hash to_hash() const;

/* behavior::countable */
size_t count() const;

/* behavior::consable_in_place */
native_box<static_object> cons_in_place(object_ptr head);

/* behavior::persistentable */
native_box<persistent_type> to_persistent();

/* behavior::callable */
object_ptr call(object_ptr) const;
object_ptr call(object_ptr, object_ptr) const;

void assert_active() const;

object base{ object_type::transient_vector };
value_type data;
mutable native_hash hash{};
native_bool active{ true };
};

namespace obj
{
using transient_vector = static_object<object_type::transient_vector>;
using transient_vector_ptr = native_box<transient_vector>;
}
}
1 change: 1 addition & 0 deletions include/cpp/jank/runtime/object.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ namespace jank::runtime
persistent_hash_map,
persistent_hash_map_sequence,
transient_hash_map,
transient_vector,
persistent_set,
cons,
range,
Expand Down
6 changes: 6 additions & 0 deletions src/cpp/jank/runtime/obj/persistent_vector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <jank/runtime/util.hpp>
#include <jank/runtime/obj/native_function_wrapper.hpp>
#include <jank/runtime/obj/persistent_vector.hpp>
#include <jank/runtime/obj/transient_vector.hpp>

namespace jank::runtime
{
Expand Down Expand Up @@ -102,6 +103,11 @@ namespace jank::runtime
return ret;
}

obj::transient_vector_ptr obj::persistent_vector::to_transient() const
{
return make_box<obj::transient_vector>(data);
}

object_ptr obj::persistent_vector::with_meta(object_ptr const m) const
{
auto const meta(behavior::detail::validate_meta(m));
Expand Down
116 changes: 116 additions & 0 deletions src/cpp/jank/runtime/obj/transient_vector.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
#include "jank/runtime/detail/object_util.hpp"
#include "jank/runtime/erasure.hpp"
#include "jank/type.hpp"
#include <jank/runtime/util.hpp>
#include <jank/runtime/obj/native_function_wrapper.hpp>
#include <jank/runtime/obj/transient_vector.hpp>
#include <stdexcept>

namespace jank::runtime
{
obj::transient_vector::static_object(runtime::detail::native_persistent_vector &&d)
: data{ d.transient() }
{
}

obj::transient_vector::static_object(runtime::detail::native_persistent_vector const &d)
: data{ d.transient() }
{
}

obj::transient_vector::static_object(runtime::detail::native_transient_vector &&d)
: data{ d }
{
}

native_bool obj::transient_vector::equal(object const &o) const
{
/* Transient equality, in Clojure, is based solely on identity. */
return &base == &o;
}

native_persistent_string obj::transient_vector::to_string() const
{
fmt::memory_buffer buff;
to_string(buff);
return native_persistent_string{ buff.data(), buff.size() };
}

void obj::transient_vector::to_string(fmt::memory_buffer &buff) const
{
auto inserter(std::back_inserter(buff));
fmt::format_to(inserter, "{}@{}", magic_enum::enum_name(base.type), fmt::ptr(&base));
}

native_hash obj::transient_vector::to_hash() const
{
/* Hash is also based only on identity. Clojure uses default hashCode, which does the same. */
return static_cast<native_hash>(reinterpret_cast<uintptr_t>(this));
}

size_t obj::transient_vector::count() const
{
assert_active();
return data.size();
}

obj::transient_vector_ptr obj::transient_vector::cons_in_place(object_ptr const head)
{
assert_active();
data.push_back(head);
return this;
}

native_box<obj::transient_vector::persistent_type> obj::transient_vector::to_persistent()
{
assert_active();
active = false;
return make_box<obj::persistent_vector>(std::move(data));
}

object_ptr obj::transient_vector::call(object_ptr const o) const
{
assert_active();
if(o->type == object_type::integer)
{
auto const i(expect_object<obj::integer>(o)->data);
if(i < 0 || data.size() <= static_cast<size_t>(i))
{
return obj::nil::nil_const();
}

return data.at(i);
}
else
{
throw std::runtime_error{ fmt::format("key must be an integer; found {}", runtime::detail::to_string(o))};
}
}

object_ptr obj::transient_vector::call(object_ptr const o, object_ptr const fallback) const
{
assert_active();
if(o->type == object_type::integer)
{
auto const i(expect_object<obj::integer>(o)->data);
if(i < 0 || data.size() <= static_cast<size_t>(i))
{
return fallback;
}

return data.at(i);
}
else
{
throw std::runtime_error{ fmt::format("key must be an integer; found {}", runtime::detail::to_string(o))};
}
}

void obj::transient_vector::assert_active() const
{
if(!active)
{
throw std::runtime_error{ "transient used after it's been made persistent" };
}
}
}

0 comments on commit a5e5254

Please sign in to comment.