Skip to content

Commit

Permalink
Hook output
Browse files Browse the repository at this point in the history
  • Loading branch information
CaptainZippy committed Oct 5, 2024
1 parent c92a69d commit 080a131
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 24 deletions.
72 changes: 52 additions & 20 deletions src/littlelambda.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <inttypes.h>
#include <charconv>
#include <cstring>
#include <format>
#include <optional>
#include <span>
#include <string>
Expand Down Expand Up @@ -515,55 +516,86 @@ static bool truthy(lam_value v) {
return false;
}

void lam_print(lam_value val, const char* end) {
void lam_print(lam_vm* vm, lam_value val, const char* end) {
/*struct Adaptor {
using difference_type = std::ptrdiff_t;
char buf[64];
int count{0};
lam_hooks* h;
Adaptor(lam_hooks* hooks) : h(hooks) {}
~Adaptor() { _flush(); }
void _flush() {
if (count) {
h->output(buf, count);
count = 0;
}
}
inline Adaptor& operator++() {
++count;
if (count >= sizeof(buf)) {
_flush();
}
return *this;
}
Adaptor& operator++(int) {
auto copy = *this;
++*this;
return copy;
}
inline char& operator*() { return buf[count]; }
};
static_assert(std::output_iterator<Adaptor, char>);
Adaptor out{vm->hooks}; */
char out[256];
std::format_to_n_result<char*> next{};

switch (val.type()) {
case lam_type::Double:
printf("%lf", val.as_double());
next = std::format_to_n(out, sizeof(out), "{}", val.as_double());
break;
case lam_type::Int:
printf("%i", val.as_int());
next = std::format_to_n(out, sizeof(out), "{}", val.as_int());
break;
case lam_type::Null:
printf("null");
next = std::format_to_n(out, sizeof(out), "{}","null");
break;
case lam_type::Opaque:
printf("Opaque{%" PRIu64 "}", val.as_opaque());
next = std::format_to_n(out, sizeof(out), "Opaque<{}>", val.as_opaque());
break;
case lam_type::Symbol:
printf(":%s", val.as_symbol()->val());
next = std::format_to_n(out, sizeof(out), ":{}", val.as_symbol()->val());
break;
case lam_type::String:
printf("%s", val.as_string()->val());
next = std::format_to_n(out, sizeof(out), "{}", val.as_string()->val());
break;
case lam_type::List: {
printf("(");
vm->hooks->output("(", 1);
auto lst = val.as_list();
const char* sep = "";
for (auto i = 0; i < lst->len; ++i) {
printf("%s", sep);
sep = " ";
lam_print(lst->at(i));
lam_print(vm, lst->at(i), (i+1==lst->len) ? ")" : " ");
}
printf(")");
break;
}
case lam_type::Applicative:
printf("Ap{%s}", val.as_callable()->name);
next = std::format_to_n(out, sizeof(out), "Ap<{}>", val.as_callable()->name);
break;
case lam_type::Operative:
printf("Op{%s}", val.as_callable()->name);
next = std::format_to_n(out, sizeof(out), "Op<{}>", val.as_callable()->name);
break;
case lam_type::Environment:
printf("Env{%p}", val.as_env());
next = std::format_to_n(out, sizeof(out), "Env<{}>", (void*)val.as_env());
break;
case lam_type::Error:
printf("Err{%x,%s}", val.as_error()->code, val.as_error()->msg);
next = std::format_to_n(out, sizeof(out), "Err<{:x},{}>", val.as_error()->code, val.as_error()->msg);
break;
default:
assert(false);
}
vm->hooks->output(out, next.out - out);
if (end) {
printf("%s", end);
vm->hooks->output(end, strlen(end));
}
}

Expand Down Expand Up @@ -832,7 +864,7 @@ static lam_env* lam_make_env_builtin(lam_vm* vm) {
// (print expr...) Print the given expressions
"print", [](lam_callable* call, lam_env* env, auto a, auto n) -> lam_value_or_tail_call {
for (auto i = 0; i < n; ++i) {
lam_print(a[i]);
lam_print(env->vm, a[i]);
}
return lam_value{};
});
Expand Down Expand Up @@ -1242,7 +1274,7 @@ lam_vm* lam_vm_new(lam_hooks* hooks) {
return vm;
}

template<typename T>
template <typename T>
static inline void swap_reset_container(T& t) {
T e;
t.swap(e);
Expand Down
3 changes: 2 additions & 1 deletion src/littlelambda.h
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ lam_value lam_eval(lam_vm* vm, lam_value val);
lam_result lam_parse(lam_vm* vm, const char* input, const char* end, const char** restart);

/// Print the given value.
void lam_print(lam_value val, const char* end = nullptr);
void lam_print(lam_vm* vm, lam_value val, const char* end = nullptr);

/// Functionality provided by external systems.
struct lam_hooks {
Expand All @@ -324,6 +324,7 @@ struct lam_hooks {
virtual void mem_free(void* addr) = 0;
virtual void init() = 0;
virtual void quit() = 0;
virtual void output(const char* s, size_t n) = 0;
virtual lam_result import(lam_vm* vm, const char* modname) = 0;
};

Expand Down
8 changes: 5 additions & 3 deletions src/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ struct DebugHooks : lam_hooks {
}
_allocs.clear();
}
void output(const char* s, size_t n) { fwrite(s, 1, n, stdout); }
lam_result import(lam_vm* vm, const char* modname) override { return import_impl(vm, modname); }

std::unordered_map<void*, std::stacktrace> _allocs;
Expand All @@ -123,6 +124,7 @@ struct SimpleHooks : lam_hooks {
void init() { _nalloc = 0; }
void quit() { assert(_nalloc == 0); }
lam_result import(lam_vm* vm, const char* modname) override { return import_impl(vm, modname); }
void output(const char* s, size_t n) { fwrite(s, 1, n, stdout); }
};

void test_all(lam_hooks& hooks) {
Expand Down Expand Up @@ -176,22 +178,22 @@ void test_all(lam_hooks& hooks) {
" (if (= x 0) 0 .)\n"
" (* x y))\n"
" ($define (perim x y) (* 2 (+ x y))))");
lam_print(expr1a, "\n");
lam_print(vm, expr1a, "\n");
lam_value expr1b = lam_parse_or_die(vm,
"($module foo .)\n"
"($define (area x y)\n"
" (if (= x 0) 0 .)\n"
" (* x y))\n"
"($define (perim x y) (* 2 (+ x y)))");
lam_print(expr1b, "\n");
lam_print(vm, expr1b, "\n");
lam_vm_delete(vm);
}

if (1) {
lam_vm* vm = lam_vm_new(&hooks);
lam_value op = lam_make_opaque(22);
// TODO env->bind("val", op);
lam_print(op, "\n");
lam_print(vm, op, "\n");
lam_value expr = lam_parse_or_die(vm, "(print val \"\\n\")");
lam_eval(vm, expr);
lam_vm_delete(vm);
Expand Down

0 comments on commit 080a131

Please sign in to comment.