Skip to content

Commit

Permalink
Add list* and all apply arities
Browse files Browse the repository at this point in the history
This also fixes an off-by-one in sequence length counting.
  • Loading branch information
jeaye committed Dec 10, 2023
1 parent 2604960 commit 5c7f752
Show file tree
Hide file tree
Showing 10 changed files with 108 additions and 52 deletions.
2 changes: 1 addition & 1 deletion include/cpp/jank/runtime/behavior/seqable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace jank::runtime::behavior
{ t->seq() } -> std::convertible_to<object_ptr>;
/* Returns a unique seq which can be updated in place. This is an optimization which allows
* one allocation for a fresh seq which can then be mutated any number of times to traverse
* the data. */
* the data. Also must return nullptr when the sequence is empty. */
{ t->fresh_seq() } -> std::convertible_to<object_ptr>;
};

Expand Down
4 changes: 2 additions & 2 deletions include/cpp/jank/runtime/obj/detail/iterator_sequence.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ namespace jank::runtime::obj::detail
native_box<Derived> seq()
{ return static_cast<Derived*>(this); }
native_box<Derived> fresh_seq() const
{ return jank::make_box<Derived>(coll, begin, end, size); }
{ return make_box<Derived>(coll, begin, end, size); }

/* behavior::countable */
size_t count() const
Expand All @@ -75,7 +75,7 @@ namespace jank::runtime::obj::detail
if(n == end)
{ return nullptr; }

return jank::make_box<Derived>(coll, n, end, size);
return make_box<Derived>(coll, n, end, size);
}
native_box<Derived> next_in_place()
{
Expand Down
2 changes: 1 addition & 1 deletion include/cpp/jank/runtime/obj/native_array_sequence.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace jank::runtime
{
static constexpr bool pointer_free{ false };

static_object() = default;
static_object() = delete;
static_object(static_object &&) = default;
static_object(static_object const &) = default;
static_object(object_ptr * const arr, size_t const size);
Expand Down
2 changes: 1 addition & 1 deletion src/cpp/jank/runtime/behavior/callable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -548,7 +548,7 @@ namespace jank::runtime

if constexpr(seqable<T>)
{
auto const s(typed_args->seq());
auto const s(typed_args->fresh_seq());
auto const length(runtime::detail::sequence_length(s, max_params + 1));
switch(length)
{
Expand Down
2 changes: 1 addition & 1 deletion src/cpp/jank/runtime/obj/cons.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace jank::runtime
{
obj::cons::static_object(object_ptr const head, object_ptr const tail)
: head{ head }, tail{ tail }
{ }
{ assert(head); }

obj::cons_ptr obj::cons::seq()
{ return this; }
Expand Down
16 changes: 11 additions & 5 deletions src/cpp/jank/runtime/obj/native_array_sequence.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,16 @@ namespace jank::runtime
{
obj::native_array_sequence::static_object(object_ptr * const arr, size_t const size)
: arr{ arr }, size{ size }
{ }
{
assert(arr);
assert(size > 0);
}
obj::native_array_sequence::static_object(object_ptr * const arr, size_t const index, size_t const size)
: arr{ arr }, index{ index }, size{ size }
{ }
{
assert(arr);
assert(size > 0);
}

/* behavior::objectable */
native_bool obj::native_array_sequence::equal(object const &o) const
Expand All @@ -27,9 +33,9 @@ namespace jank::runtime

/* behavior::seqable */
obj::native_array_sequence_ptr obj::native_array_sequence::seq()
{ return size == 0 ? nullptr : this; }
{ return this; }
obj::native_array_sequence_ptr obj::native_array_sequence::fresh_seq()
{ return size == 0 ? nullptr : make_box<obj::native_array_sequence>(arr, index, size); }
{ return make_box<obj::native_array_sequence>(arr, index, size); }

/* behavior::countable */
size_t obj::native_array_sequence::count() const
Expand Down Expand Up @@ -71,5 +77,5 @@ namespace jank::runtime
}

obj::cons_ptr obj::native_array_sequence::cons(object_ptr const head)
{ return make_box<obj::cons>(head, size == 0 ? nullptr : this); }
{ return make_box<obj::cons>(head, this); }
}
6 changes: 3 additions & 3 deletions src/cpp/jank/runtime/obj/native_vector_sequence.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ namespace jank::runtime
{
obj::native_vector_sequence::static_object(native_vector<object_ptr> const &data, size_t index)
: data{ data }, index{ index }
{ }
{ assert(!data.empty()); }
obj::native_vector_sequence::static_object(native_vector<object_ptr> &&data)
: data{ std::move(data) }
{ }
{ assert(!data.empty()); }
obj::native_vector_sequence::static_object(native_vector<object_ptr> &&data, size_t index)
: data{ std::move(data) }, index{ index }
{ }
{ assert(!data.empty()); }

/* behavior::objectable */
native_bool obj::native_vector_sequence::equal(object const &o) const
Expand Down
10 changes: 5 additions & 5 deletions src/cpp/jank/runtime/obj/vector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ namespace jank::runtime
obj::vector_ptr obj::vector::create(object_ptr const s)
{
if(s == nullptr)
{ return jank::make_box<obj::vector>(); }
{ return make_box<obj::vector>(); }

return visit_object
(
Expand All @@ -32,7 +32,7 @@ namespace jank::runtime
runtime::detail::native_transient_vector v;
for(auto i(typed_s->fresh_seq()); i != nullptr; i = i->next_in_place())
{ v.push_back(i->first()); }
return jank::make_box<obj::vector>(v.persistent());
return make_box<obj::vector>(v.persistent());
}
else
{ throw std::runtime_error{ fmt::format("invalid sequence: {}", typed_s->to_string()) }; }
Expand Down Expand Up @@ -67,14 +67,14 @@ namespace jank::runtime
{
if(data.empty())
{ return nullptr; }
return jank::make_box<obj::persistent_vector_sequence>(const_cast<obj::vector*>(this));
return make_box<obj::persistent_vector_sequence>(const_cast<obj::vector*>(this));
}

obj::persistent_vector_sequence_ptr obj::vector::fresh_seq() const
{
if(data.empty())
{ return nullptr; }
return jank::make_box<obj::persistent_vector_sequence>(const_cast<obj::vector*>(this));
return make_box<obj::persistent_vector_sequence>(const_cast<obj::vector*>(this));
}

size_t obj::vector::count() const
Expand All @@ -90,7 +90,7 @@ namespace jank::runtime
object_ptr obj::vector::with_meta(object_ptr const m) const
{
auto const meta(behavior::detail::validate_meta(m));
auto ret(jank::make_box<obj::vector>(data));
auto ret(make_box<obj::vector>(data));
ret->meta = meta;
return ret;
}
Expand Down
2 changes: 1 addition & 1 deletion src/cpp/jank/runtime/seq.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ namespace jank::runtime
{ return typed_s->count(); }
else if constexpr(behavior::seqable<T>)
{
size_t length{ 1 };
size_t length{ 0 };
for(auto i(typed_s->fresh_seq()); i != nullptr && length < max; i = i->next_in_place())
{ ++length; }
return length;
Expand Down
114 changes: 82 additions & 32 deletions src/jank/clojure/core.jank
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@
(cons 'let* (cons args body)))

; TODO: Higher arities. Needs clojure.core/spread, which needs clojure.core/cons.
(defn apply [f args]
(defn apply* [f args]
(native/raw "__value = runtime::apply_to(#{ f }#, #{ args }#);"))

(defn or*
Expand All @@ -314,7 +314,7 @@

(defmacro or
[& args]
(apply or* args))
(apply* or* args))

(defn and*
([]
Expand All @@ -330,7 +330,7 @@

(defmacro and
[& args]
(apply and* args))
(apply* and* args))

; Takes a set of test/expr pairs. It evaluates each test one at a
; time. If a test returns logical true, cond evaluates and returns
Expand All @@ -350,6 +350,64 @@
(defn macroexpand [form]
(native/raw "__value = __rt_ctx.macroexpand(#{ form }#);"))

; Relations.
;; Miscellaneous.
(defn true? [o]
(native/raw "__value = runtime::detail::equal(#{ o }#, #{ true }#) ? #{ true }# : #{ false }#"))
(defn false? [o]
(native/raw "__value = runtime::detail::equal(#{ o }#, #{ false }#) ? #{ true }# : #{ false }#"))
(defn not [o]
(native/raw "__value = runtime::detail::equal(#{ o }#, #{ false }#) ? #{ true }# : #{ false }#"))
(defn some? [o]
(native/raw "__value = (o == obj::nil::nil_const()) ? #{ false }# : #{ true }#"))

; Functions.

; Takes a fn f and returns a fn that takes the same arguments as f,
; has the same effects, if any, and returns the opposite truth value.
(defn complement [f]
; TODO: borked?
f
;(fn
; ([] (not (f)))
; ([x] (not (f x)))
; ([x y] (not (f x y)))
; ([x y & zs] (not (apply f x y zs))))
)

(defn- spread [arglist]
(cond
(nil? arglist) nil
(nil? (next arglist)) (seq (first arglist))
:else (cons (first arglist) (spread (next arglist)))))

; Creates a new seq containing the items prepended to the rest, the
; last of which will be treated as a sequence.
(defn list*
([args]
(seq args))
([a args]
(cons a args))
([a b args]
(cons a (cons b args)))
([a b c args]
(cons a (cons b (cons c args))))
([a b c d & more]
(cons a (cons b (cons c (cons d (spread more)))))))

; Applies fn f to the argument list formed by prepending intervening arguments to args.
(defn apply
([f args]
(native/raw "__value = runtime::apply_to(#{ f }#, #{ args }#);"))
([f x args]
(native/raw "__value = runtime::apply_to(#{ f }#, #{ (list* x args) }#);"))
([f x y args]
(native/raw "__value = runtime::apply_to(#{ f }#, #{ (list* x y args) }#);"))
([f x y z args]
(native/raw "__value = runtime::apply_to(#{ f }#, #{ (list* x y z args) }#);"))
([f a b c d & args]
(native/raw "__value = runtime::apply_to(#{ f }#, #{ (cons a (cons b (cons c (cons d (spread args))))) }#);")))

; Utils.
(defn reduce*
([f coll]
Expand Down Expand Up @@ -377,18 +435,6 @@
#{ coll }#
);")))


; Relations.
;; Miscellaneous.
(defn true? [o]
(native/raw "__value = runtime::detail::equal(#{ o }#, #{ true }#) ? #{ true }# : #{ false }#"))
(defn false? [o]
(native/raw "__value = runtime::detail::equal(#{ o }#, #{ false }#) ? #{ true }# : #{ false }#"))
(defn not [o]
(native/raw "__value = runtime::detail::equal(#{ o }#, #{ false }#) ? #{ true }# : #{ false }#"))
(defn some? [o]
(native/raw "__value = (o == obj::nil::nil_const()) ? #{ false }# : #{ true }#"))

; Strings.
(defn string? [o]
(native/raw "__value = make_box(#{ o }#->type == object_type::string);"))
Expand All @@ -400,25 +446,29 @@
([o & args]
(native/raw "__value = visit_object
(
[=](auto const typed_args) -> object_ptr
{
using T = typename decltype(typed_args)::value_type;

if constexpr(behavior::sequenceable<T>)
[=](auto const typed_args) -> object_ptr
{
fmt::memory_buffer buff;
buff.reserve(16);
runtime::detail::to_string(#{ o }#, buff);
runtime::detail::to_string(typed_args->first(), buff);
for(auto it(typed_args->next_in_place()); it != nullptr; it = it->next_in_place())
{ runtime::detail::to_string(typed_args->first(), buff); }
return make_box<obj::string>(native_string{ buff.data(), buff.size() });
}
else
{ throw #{ (ex-info :invalid-seq {:args args}) }#; }
using T = typename decltype(typed_args)::value_type;

if constexpr(behavior::sequenceable<T>)
{
fmt::memory_buffer buff;
buff.reserve(16);
runtime::detail::to_string(#{ o }#, buff);
if(0 < runtime::detail::sequence_length(typed_args))
{
auto const fresh(typed_args->fresh_seq());
runtime::detail::to_string(fresh->first(), buff);
for(auto it(fresh->next_in_place()); it != nullptr; it = it->next_in_place())
{ runtime::detail::to_string(it->first(), buff); }
}
return make_box<obj::string>(native_string{ buff.data(), buff.size() });
}
else
{ throw #{ (ex-info :invalid-seq {:args args}) }#; }
},
#{ args }#
);")))
#{ args }#
);")))

(defn subs
([s start]
Expand Down

0 comments on commit 5c7f752

Please sign in to comment.