Skip to content

Commit

Permalink
Merge pull request #58 from jank-lang/transient
Browse files Browse the repository at this point in the history
Add initial transient support
  • Loading branch information
jeaye committed Mar 31, 2024
2 parents 0ad48ae + 48f38c2 commit e15ee12
Show file tree
Hide file tree
Showing 27 changed files with 932 additions and 17 deletions.
3 changes: 3 additions & 0 deletions CMakeLists.txt
Expand Up @@ -171,7 +171,10 @@ add_library(
src/cpp/jank/runtime/obj/persistent_vector_sequence.cpp
src/cpp/jank/runtime/obj/persistent_array_map.cpp
src/cpp/jank/runtime/obj/persistent_hash_map.cpp
src/cpp/jank/runtime/obj/transient_hash_map.cpp
src/cpp/jank/runtime/obj/transient_vector.cpp
src/cpp/jank/runtime/obj/persistent_set.cpp
src/cpp/jank/runtime/obj/transient_set.cpp
src/cpp/jank/runtime/obj/persistent_string.cpp
src/cpp/jank/runtime/obj/cons.cpp
src/cpp/jank/runtime/obj/range.cpp
Expand Down
3 changes: 3 additions & 0 deletions include/cpp/jank/prelude.hpp
Expand Up @@ -28,3 +28,6 @@
#include <jank/runtime/seq.hpp>
#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>
11 changes: 11 additions & 0 deletions include/cpp/jank/runtime/behavior/associatively_writable.hpp
Expand Up @@ -10,4 +10,15 @@ namespace jank::runtime::behavior
t->assoc(object_ptr{}, object_ptr{})
} -> std::convertible_to<object_ptr>;
};

template <typename T>
concept associatively_writable_in_place = requires(T * const t) {
{
t->assoc_in_place(object_ptr{}, object_ptr{})
} -> std::convertible_to<object_ptr>;

{
t->dissoc_in_place(object_ptr{})
} -> std::convertible_to<object_ptr>;
};
}
7 changes: 7 additions & 0 deletions include/cpp/jank/runtime/behavior/consable.hpp
Expand Up @@ -11,4 +11,11 @@ namespace jank::runtime::behavior
t->cons(object_ptr{})
}; // -> consable
};

template <typename T>
concept consable_in_place = requires(T * const t) {
{
t->cons_in_place(object_ptr{})
}; // -> consable_in_place
};
}
18 changes: 18 additions & 0 deletions include/cpp/jank/runtime/behavior/transientable.hpp
@@ -0,0 +1,18 @@
#pragma once

namespace jank::runtime::behavior
{
template <typename T>
concept persistentable = requires(T * const t) {
{
t->to_persistent()
} -> std::convertible_to<object_ptr>;
};

template <typename T>
concept transientable = requires(T * const t) {
{
t->to_transient()
} -> std::convertible_to<object_ptr>;
};
}
18 changes: 18 additions & 0 deletions include/cpp/jank/runtime/erasure.hpp
Expand Up @@ -16,6 +16,9 @@
#include <jank/runtime/obj/persistent_array_map_sequence.hpp>
#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/transient_set.hpp>
#include <jank/runtime/obj/iterator.hpp>
#include <jank/runtime/obj/range.hpp>
#include <jank/runtime/obj/jit_function.hpp>
Expand Down Expand Up @@ -173,11 +176,26 @@ namespace jank::runtime
std::forward<Args>(args)...);
}
break;
case object_type::transient_hash_map:
{
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)...);
}
break;
case object_type::transient_set:
{
return fn(expect_object<obj::transient_set>(erased), std::forward<Args>(args)...);
}
break;
case object_type::cons:
{
return fn(expect_object<obj::cons>(erased), std::forward<Args>(args)...);
Expand Down
Expand Up @@ -40,6 +40,7 @@ namespace jank::runtime::obj::detail
return false;
}

/* TODO: Is this enough? Value comparison may be needed. */
return to_hash() == hash::visit(p);
}

Expand Down
2 changes: 1 addition & 1 deletion include/cpp/jank/runtime/obj/native_function_wrapper.hpp
Expand Up @@ -69,7 +69,7 @@ namespace jank::runtime

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

Expand Down
8 changes: 8 additions & 0 deletions include/cpp/jank/runtime/obj/persistent_hash_map.hpp
Expand Up @@ -11,6 +11,9 @@ namespace jank::runtime
{
using persistent_array_map = static_object<object_type::persistent_array_map>;
using persistent_array_map_ptr = native_box<persistent_array_map>;

using transient_hash_map = static_object<object_type::transient_hash_map>;
using transient_hash_map_ptr = native_box<transient_hash_map>;
}

template <>
Expand All @@ -19,6 +22,8 @@ namespace jank::runtime
object_type::persistent_hash_map_sequence,
runtime::detail::native_persistent_hash_map>
{
using transient_type = static_object<object_type::transient_hash_map>;

static_object() = default;
static_object(static_object &&) = default;
static_object(static_object const &) = default;
Expand Down Expand Up @@ -83,6 +88,9 @@ namespace jank::runtime
object_ptr call(object_ptr) const;
object_ptr call(object_ptr, object_ptr) const;

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

value_type data{};
};

Expand Down
9 changes: 9 additions & 0 deletions include/cpp/jank/runtime/obj/persistent_set.hpp
Expand Up @@ -5,6 +5,12 @@

namespace jank::runtime
{
namespace obj
{
using transient_set = static_object<object_type::transient_set>;
using transient_set_ptr = native_box<transient_set>;
}

template <>
struct static_object<object_type::persistent_set> : gc
{
Expand Down Expand Up @@ -62,6 +68,9 @@ namespace jank::runtime
/* behavior::callable */
object_ptr call(object_ptr) const;

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

native_bool contains(object_ptr o) const;

object base{ object_type::persistent_set };
Expand Down
2 changes: 1 addition & 1 deletion include/cpp/jank/runtime/obj/persistent_string.hpp
Expand Up @@ -8,7 +8,7 @@ namespace jank::runtime
template <>
struct static_object<object_type::persistent_string> : gc
{
static constexpr native_bool pointer_free{ true };
static constexpr native_bool pointer_free{ false };

static_object() = default;
static_object(static_object &&) = default;
Expand Down
10 changes: 10 additions & 0 deletions include/cpp/jank/runtime/obj/persistent_vector.hpp
Expand Up @@ -5,9 +5,16 @@

namespace jank::runtime
{
namespace obj
{
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 native_bool pointer_free{ false };
Expand Down Expand Up @@ -65,6 +72,9 @@ 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;
Expand Down
70 changes: 70 additions & 0 deletions include/cpp/jank/runtime/obj/transient_hash_map.hpp
@@ -0,0 +1,70 @@
#pragma once

#include <jank/runtime/object.hpp>

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

using value_type = detail::native_transient_hash_map;
using persistent_type = static_object<object_type::persistent_hash_map>;

static_object() = default;
static_object(static_object &&) = default;
static_object(static_object const &) = default;
static_object(detail::native_persistent_hash_map const &d);
static_object(detail::native_persistent_hash_map &&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::associatively_readable */
object_ptr get(object_ptr const key) const;
object_ptr get(object_ptr const key, object_ptr const fallback) const;
object_ptr get_entry(object_ptr key) const;
native_bool contains(object_ptr key) const;

/* behavior::associatively_writable_in_place */
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);

/* 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_hash_map };
value_type data;
mutable native_hash hash{};
native_bool active{ true };
};

namespace obj
{
using transient_hash_map = static_object<object_type::transient_hash_map>;
using transient_hash_map_ptr = native_box<transient_hash_map>;
}
}
66 changes: 66 additions & 0 deletions include/cpp/jank/runtime/obj/transient_set.hpp
@@ -0,0 +1,66 @@
#pragma once

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

using value_type = detail::native_transient_set;
using persistent_type = static_object<object_type::persistent_set>;

static_object() = default;
static_object(static_object &&) noexcept = default;
static_object(static_object const &) = default;
static_object(detail::native_persistent_set const &d);
static_object(detail::native_persistent_set &&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) const;
object_ptr call(object_ptr const, object_ptr const fallback) const;

/* behavior::associatively_readable */
object_ptr get(object_ptr const elem) const;
object_ptr get(object_ptr const elem, object_ptr const fallback) const;
object_ptr get_entry(object_ptr const elem) const;
native_bool contains(object_ptr const elem) const;

native_box<static_object> disjoin_in_place(object_ptr const elem);

void assert_active() const;

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

namespace obj
{
using transient_set = static_object<object_type::transient_set>;
using transient_set_ptr = native_box<transient_set>;
}
}

0 comments on commit e15ee12

Please sign in to comment.