Skip to content

Commit

Permalink
rewrite lisp sort in C++
Browse files Browse the repository at this point in the history
  • Loading branch information
evanbowman committed Dec 10, 2024
1 parent 21ff1dd commit a13acf0
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 17 deletions.
17 changes: 0 additions & 17 deletions scripts/stdlib.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -104,23 +104,6 @@
(set sym (union tmp tmp))))


(defn/c merge (l1 l2 comp)
(cond
((not l1) l2)
((not l2) l1)
((comp (car l1) (car l2))
(cons (car l1) ((this) (cdr l1) l2 comp)))
(true (cons (car l2) ((this) l1 (cdr l2) comp)))))


(defn/c sort (lat comp)
(if (not (cdr lat))
lat
(let ((len (length lat)))
(merge ((this) (slice lat 0 (/ len 2)) comp)
((this) (slice lat (/ len 2)) comp)
comp))))

;; While suboptimal, these functions have the benefit of being small.
(defn/c min (lat) (car (sort lat <)))
(defn/c max (lat) (car (sort lat >)))
Expand Down
35 changes: 35 additions & 0 deletions source/script/lisp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5174,6 +5174,41 @@ BUILTIN_TABLE(
[](int argc) {
return bound_context->callstack_->cons().cdr()->cons().car();
}}},
{"sort",
{2,
[](int argc) {
L_EXPECT_OP(0, function);
L_EXPECT_OP(1, cons);

auto comp = get_op0();
if (not is_list(get_op1())) {
return make_error("sort parameter must be list!");
}

using TempBuffer = Buffer<Value*, 509>;
auto buf = allocate_dynamic_fast<TempBuffer>("sort-buffer");

l_foreach(get_op1(), [&buf](Value* v) {
buf->push_back(v);
});

std::sort(buf->begin(), buf->end(),
[comp](Value* lhs, Value* rhs) {
push_op(lhs);
push_op(rhs);
funcall(comp, 2);
auto result = get_op0();
pop_op(); // result
return is_boolean_true(result);
});

ListBuilder result;
for (Value* v : *buf) {
result.push_back(v);
}

return result.result();
}}},
{"env",
{0,
[](int argc) {
Expand Down

0 comments on commit a13acf0

Please sign in to comment.