Skip to content

Commit

Permalink
Add native repeat object
Browse files Browse the repository at this point in the history
  • Loading branch information
jianlingzhong committed Nov 11, 2024
1 parent 3afd224 commit 31a10c5
Show file tree
Hide file tree
Showing 6 changed files with 208 additions and 6 deletions.
1 change: 1 addition & 0 deletions compiler+runtime/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ add_library(
src/cpp/jank/runtime/obj/persistent_string_sequence.cpp
src/cpp/jank/runtime/obj/cons.cpp
src/cpp/jank/runtime/obj/range.cpp
src/cpp/jank/runtime/obj/repeat.cpp
src/cpp/jank/runtime/obj/iterator.cpp
src/cpp/jank/runtime/obj/lazy_sequence.cpp
src/cpp/jank/runtime/obj/chunk_buffer.cpp
Expand Down
11 changes: 11 additions & 0 deletions compiler+runtime/include/cpp/jank/runtime/erasure.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include <jank/runtime/obj/array_chunk.hpp>
#include <jank/runtime/obj/chunked_cons.hpp>
#include <jank/runtime/obj/range.hpp>
#include <jank/runtime/obj/repeat.hpp>
#include <jank/runtime/obj/jit_function.hpp>
#include <jank/runtime/obj/multi_function.hpp>
#include <jank/runtime/obj/native_function_wrapper.hpp>
Expand Down Expand Up @@ -286,6 +287,11 @@ namespace jank::runtime
return fn(expect_object<obj::range>(erased), std::forward<Args>(args)...);
}
break;
case object_type::repeat:
{
return fn(expect_object<obj::repeat>(erased), std::forward<Args>(args)...);
}
break;
case object_type::native_array_sequence:
{
return fn(expect_object<obj::native_array_sequence>(erased), std::forward<Args>(args)...);
Expand Down Expand Up @@ -522,6 +528,11 @@ namespace jank::runtime
return fn(expect_object<obj::range>(erased), std::forward<Args>(args)...);
}
break;
case object_type::repeat:
{
return fn(expect_object<obj::repeat>(erased), std::forward<Args>(args)...);
}
break;
case object_type::native_array_sequence:
{
return fn(expect_object<obj::native_array_sequence>(erased), std::forward<Args>(args)...);
Expand Down
56 changes: 56 additions & 0 deletions compiler+runtime/include/cpp/jank/runtime/obj/repeat.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#pragma once

#include <jank/runtime/behavior/seqable.hpp>

namespace jank::runtime
{
template <>
struct static_object<object_type::repeat> : gc
{
static constexpr native_bool pointer_free{ false };
static constexpr native_integer INFINITE{ -1 };
using bounds_check_t = native_bool (*)(object_ptr);

static_object() = default;
static_object(object_ptr value);
static_object(object_ptr count, object_ptr value);

static object_ptr create(object_ptr value);
static object_ptr create(object_ptr count, object_ptr value);

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

/* behavior::seqable */
native_box<static_object> seq();
native_box<static_object> fresh_seq() const;

/* behavior::sequenceable */
object_ptr first() const;
native_box<static_object> next() const;

/* behavior::sequenceable_in_place */
native_box<static_object> next_in_place();

/* behavior::conjable */
obj::cons_ptr conj(object_ptr head) const;

/* behavior::metadatable */
native_box<static_object> with_meta(object_ptr m) const;

object base{ object_type::repeat };
object_ptr value{};
object_ptr count{};
option<object_ptr> meta{};
};

namespace obj
{
using repeat = static_object<object_type::repeat>;
using repeat_ptr = native_box<repeat>;
}
}
1 change: 1 addition & 0 deletions compiler+runtime/include/cpp/jank/runtime/object.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ namespace jank::runtime
cons,
lazy_sequence,
range,
repeat,
iterator,
native_array_sequence,
native_vector_sequence,
Expand Down
134 changes: 134 additions & 0 deletions compiler+runtime/src/cpp/jank/runtime/obj/repeat.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
#include <jank/runtime/obj/repeat.hpp>

namespace jank::runtime
{

obj::repeat::static_object(object_ptr const value)
: value{ value }
, count{ make_box(INFINITE) }
{
}

obj::repeat::static_object(object_ptr const count, object_ptr const value)
: value{ value }
, count{ count }
{
}

object_ptr obj::repeat::create(object_ptr const value)
{
return make_box<obj::repeat>(value);
}

object_ptr obj::repeat::create(object_ptr const count, object_ptr const value)
{
if(lte(count, make_box(0)))
{
return obj::persistent_list::empty();
}
return make_box<obj::repeat>(count, value);
}

obj::repeat_ptr obj::repeat::seq()
{
return this;
}

obj::repeat_ptr obj::repeat::fresh_seq() const
{
return make_box<obj::repeat>(count, value);
}

object_ptr obj::repeat::first() const
{
return value;
}

obj::repeat_ptr obj::repeat::next() const
{
if(runtime::equal(count, make_box(INFINITE)))
{
return this;
}
if(lt(count, make_box(1)))
{
return nullptr;
}
return make_box<obj::repeat>(make_box(add(count, make_box(-1))), value);
}

obj::repeat_ptr obj::repeat::next_in_place()
{
if(runtime::equal(count, make_box(INFINITE)))
{
return this;
}
if(lte(count, make_box(1)))
{
return nullptr;
}
count = add(count, make_box(-1));
return this;
}

obj::cons_ptr obj::repeat::conj(object_ptr const head) const
{
return make_box<obj::cons>(head, this);
}

native_bool obj::repeat::equal(object const &o) const
{
return visit_object(
[this](auto const typed_o) {
using T = typename decltype(typed_o)::value_type;

if constexpr(!behavior::seqable<T>)
{
return false;
}
else
{
auto seq(typed_o->fresh_seq());
/* TODO: This is common code; can it be shared? */
for(auto it(fresh_seq()); it != nullptr;
it = runtime::next_in_place(it), seq = runtime::next_in_place(seq))
{
if(seq == nullptr || !runtime::equal(it, seq->first()))
{
return false;
}
}
return true;
}
},
&o);
}

void obj::repeat::to_string(fmt::memory_buffer &buff)
{
runtime::to_string(seq(), buff);
}

native_persistent_string obj::repeat::to_string()
{
return runtime::to_string(seq());
}

native_persistent_string obj::repeat::to_code_string()
{
return runtime::to_code_string(seq());
}

native_hash obj::repeat::to_hash() const
{
return hash::ordered(&base);
}

obj::repeat_ptr obj::repeat::with_meta(object_ptr const m) const
{
auto const meta(behavior::detail::validate_meta(m));
auto ret(fresh_seq());
ret->meta = meta;
return ret;
}
}
11 changes: 5 additions & 6 deletions compiler+runtime/src/jank/clojure/core.jank
Original file line number Diff line number Diff line change
Expand Up @@ -2236,13 +2236,12 @@
; TODO: Custom cycle object
(lazy-seq (concat coll (cycle coll))))

; Returns a lazy (infinite!, or length n if supplied) sequence of xs.
; Returns a lazy (infinite!, or length n if supplied) sequence of val.
(defn repeat
; TODO: Custom repeat object
([x]
(lazy-seq (cons x (repeat x))))
([n x]
(take n (repeat x))))
([val]
(native/raw "__value = obj::repeat::create(~{ val });"))
([count val]
(native/raw "__value = obj::repeat::create(~{ count }, ~{ val });")))

; Returns a vector of [(take n coll) (drop n coll)]
(defn split-at [n coll]
Expand Down

0 comments on commit 31a10c5

Please sign in to comment.