diff --git a/CMakeLists.txt b/CMakeLists.txt index 7d2c8bfdb..f9354c3ce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -171,6 +171,7 @@ add_library( 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/persistent_string.cpp src/cpp/jank/runtime/obj/cons.cpp diff --git a/include/cpp/jank/runtime/obj/persistent_vector.hpp b/include/cpp/jank/runtime/obj/persistent_vector.hpp index 7557c0a24..d49d3126d 100644 --- a/include/cpp/jank/runtime/obj/persistent_vector.hpp +++ b/include/cpp/jank/runtime/obj/persistent_vector.hpp @@ -7,9 +7,6 @@ namespace jank::runtime { namespace obj { - using persistent_vector = static_object; - using persistent_vector_ptr = native_box; - using transient_vector = static_object; using transient_vector_ptr = native_box; } @@ -69,4 +66,10 @@ namespace jank::runtime option meta; mutable native_hash hash{}; }; + + namespace obj + { + using persistent_vector = static_object; + using persistent_vector_ptr = native_box; + } } diff --git a/include/cpp/jank/runtime/obj/transient_vector.hpp b/include/cpp/jank/runtime/obj/transient_vector.hpp index 33e318458..0b0f32d57 100644 --- a/include/cpp/jank/runtime/obj/transient_vector.hpp +++ b/include/cpp/jank/runtime/obj/transient_vector.hpp @@ -42,7 +42,12 @@ namespace jank::runtime /* behavior::callable */ object_ptr call(object_ptr) const; - object_ptr call(object_ptr, object_ptr) const; + + /* behavior::associatively_readable */ + object_ptr get(object_ptr idx) const; + object_ptr get(object_ptr idx, object_ptr fallback) const; + object_ptr get_entry(object_ptr key) const; + native_bool contains(object_ptr key) const; void assert_active() const; diff --git a/src/cpp/jank/evaluate.cpp b/src/cpp/jank/evaluate.cpp index 7548436dd..36f4a1652 100644 --- a/src/cpp/jank/evaluate.cpp +++ b/src/cpp/jank/evaluate.cpp @@ -244,7 +244,8 @@ namespace jank::evaluate } } } - else if constexpr(std::same_as) + else if constexpr(std::same_as + || std::same_as) { auto const s(expr.arg_exprs.size()); if(s != 1) diff --git a/src/cpp/jank/runtime/behavior/callable.cpp b/src/cpp/jank/runtime/behavior/callable.cpp index 168d049c0..6be50d3d2 100644 --- a/src/cpp/jank/runtime/behavior/callable.cpp +++ b/src/cpp/jank/runtime/behavior/callable.cpp @@ -1,3 +1,4 @@ +#include "jank/runtime/obj/persistent_vector.hpp" #include #include @@ -69,6 +70,7 @@ namespace jank::runtime else if constexpr(std::same_as || std::same_as || std::same_as + || std::same_as || std::same_as) { return typed_source->call(a1); diff --git a/src/cpp/jank/runtime/obj/transient_vector.cpp b/src/cpp/jank/runtime/obj/transient_vector.cpp index dd2f74817..86650703f 100644 --- a/src/cpp/jank/runtime/obj/transient_vector.cpp +++ b/src/cpp/jank/runtime/obj/transient_vector.cpp @@ -1,10 +1,10 @@ -#include "jank/runtime/detail/object_util.hpp" -#include "jank/runtime/erasure.hpp" -#include "jank/type.hpp" +#include +#include +#include #include #include #include -#include +#include namespace jank::runtime { @@ -65,46 +65,100 @@ namespace jank::runtime { assert_active(); active = false; - return make_box(std::move(data)); + return make_box(data.persistent()); } - object_ptr obj::transient_vector::call(object_ptr const o) const + object_ptr obj::transient_vector::call(object_ptr const idx) const { assert_active(); - if(o->type == object_type::integer) + if(idx->type == object_type::integer) { - auto const i(expect_object(o)->data); + auto const i(expect_object(idx)->data); + if(i < 0 || data.size() <= static_cast(i)) + { + throw std::runtime_error{ + fmt::format("Index out of bound; index = {}, count = {}", i, count()) + }; + } + + return data[i]; + } + else + { + throw std::runtime_error{ fmt::format("key must be an integer; found {}", + runtime::detail::to_string(idx)) }; + } + } + + object_ptr obj::transient_vector::get(object_ptr idx) const + { + assert_active(); + if(idx->type == object_type::integer) + { + auto const i(expect_object(idx)->data); if(i < 0 || data.size() <= static_cast(i)) { return obj::nil::nil_const(); } - return data.at(i); + return data[i]; } else { throw std::runtime_error{ fmt::format("key must be an integer; found {}", - runtime::detail::to_string(o)) }; + runtime::detail::to_string(idx)) }; } } - object_ptr obj::transient_vector::call(object_ptr const o, object_ptr const fallback) const + object_ptr obj::transient_vector::get(object_ptr idx, object_ptr fallback) const { assert_active(); - if(o->type == object_type::integer) + if(idx->type == object_type::integer) { - auto const i(expect_object(o)->data); + auto const i(expect_object(idx)->data); if(i < 0 || data.size() <= static_cast(i)) { return fallback; } - return data.at(i); + return data[i]; } else { throw std::runtime_error{ fmt::format("key must be an integer; found {}", - runtime::detail::to_string(o)) }; + runtime::detail::to_string(idx)) }; + } + } + + object_ptr obj::transient_vector::get_entry(object_ptr const key) const + { + if(key->type == object_type::integer) + { + auto const i(expect_object(key)->data); + if(i < 0 || data.size() <= static_cast(i)) + { + return obj::nil::nil_const(); + } + /* TODO: Map entry type? */ + return make_box(key, data[i]); + } + else + { + throw std::runtime_error{ fmt::format("get_entry on a vector must be an integer; found {}", + runtime::detail::to_string(key)) }; + } + } + + native_bool obj::transient_vector::contains(object_ptr const key) const + { + if(key->type == object_type::integer) + { + auto const i(expect_object(key)->data); + return i >= 0 && static_cast(i) < data.size(); + } + else + { + return false; } }