summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLLLL Colonq <llll@colonq>2026-06-30 14:30:19 -0400
committerLLLL Colonq <llll@colonq>2026-06-30 14:30:19 -0400
commit1c028e3a2250a56eface56ebbb1835d77e4e2579 (patch)
tree98ea5da9d75e87f44bb3eb2e153810a6a820f9b6 /src
parent1d4447bcd888dd0bd20cf4b6dd7f9192145debf0 (diff)
Big refactorHEADmaster
Diffstat (limited to 'src')
-rw-r--r--src/lexer.c2
-rw-r--r--src/library.c796
-rw-r--r--src/main.c1
-rw-r--r--src/native.c95
-rw-r--r--src/parser.c53
-rw-r--r--src/runtime.c1217
-rw-r--r--src/runtime/dump.c100
-rw-r--r--src/runtime/eval.c107
-rw-r--r--src/runtime/gc.c100
-rw-r--r--src/runtime/macroexpand.c111
-rw-r--r--src/runtime/symtab.c118
-rw-r--r--src/runtime/value.c76
-rw-r--r--src/runtime/value/array.c57
-rw-r--r--src/runtime/value/bytes.c47
-rw-r--r--src/runtime/value/cell.c47
-rw-r--r--src/runtime/value/cons.c110
-rw-r--r--src/runtime/value/func.c177
-rw-r--r--src/runtime/value/nativedata.c36
-rw-r--r--src/runtime/value/small.c96
19 files changed, 1676 insertions, 1670 deletions
diff --git a/src/lexer.c b/src/lexer.c
index 77d928e..def4084 100644
--- a/src/lexer.c
+++ b/src/lexer.c
@@ -24,7 +24,7 @@ static bool is_more_input(pit_lexer *st) {
}
static int is_symchar(int c) {
- return c != '(' && c != ')' && c != '.' && c != '\'' && c != '"'
+ return c != '(' && c != ')' && c != '[' && c != ']' && c != '.' && c != '\'' && c != '"'
&& pit_libc_ctype_isprint(c)
&& !pit_libc_ctype_isspace(c);
}
diff --git a/src/library.c b/src/library.c
index 1038004..b6b8b42 100644
--- a/src/library.c
+++ b/src/library.c
@@ -6,17 +6,17 @@
static pit_value impl_sf_quote(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- pit_runtime_eval_program_push_literal(rt, rt->program, pit_car(rt, args));
+ pit_runtime_eval_program_push_literal(rt, rt->program, pit_value_cons_car(rt, args));
return PIT_NIL;
}
static pit_value impl_sf_if(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- pit_value c = pit_car(rt, args);
+ pit_value c = pit_value_cons_car(rt, args);
if (pit_eval(rt, c) != PIT_NIL) {
- if (pit_vec_push(pit_value)(rt->expr_stack, pit_car(rt, pit_cdr(rt, args))) < 0)
+ if (pit_vec_push(pit_value)(rt->expr_stack, pit_value_cons_car(rt, pit_value_cons_cdr(rt, args))) < 0)
pit_error(rt, "in special form \"if\": evaluation stack overflow");
} else {
- if (pit_vec_push(pit_value)(rt->expr_stack, pit_car(rt, pit_cdr(rt, pit_cdr(rt, args)))) < 0)
+ if (pit_vec_push(pit_value)(rt->expr_stack, pit_value_cons_car(rt, pit_value_cons_cdr(rt, pit_value_cons_cdr(rt, args)))) < 0)
pit_error(rt, "in special form \"if\": evaluation stack overflow");
}
return PIT_NIL;
@@ -24,14 +24,14 @@ static pit_value impl_sf_if(pit_runtime *rt, pit_value args, void *data) {
static pit_value impl_sf_cond(pit_runtime *rt, pit_value args, void *data) {
(void) data;
while (args != PIT_NIL) {
- pit_value clause = pit_car(rt, args);
- pit_value cond = pit_car(rt, clause);
+ pit_value clause = pit_value_cons_car(rt, args);
+ pit_value cond = pit_value_cons_car(rt, clause);
if (pit_eval(rt, cond) != PIT_NIL) {
- if (pit_vec_push(pit_value)(rt->expr_stack, pit_cons(rt, pit_intern_cstr(rt, "progn"), pit_cdr(rt, clause))) < 0)
+ if (pit_vec_push(pit_value)(rt->expr_stack, pit_value_cons(rt, pit_symtab_intern_cstr(rt, "progn"), pit_value_cons_cdr(rt, clause))) < 0)
pit_error(rt, "in special form \"cond\": evaluation stack overflow");
return PIT_NIL;
}
- args = pit_cdr(rt, args);
+ args = pit_value_cons_cdr(rt, args);
}
if (pit_vec_push(pit_value)(rt->expr_stack, PIT_NIL) < 0)
pit_error(rt, "in special form \"cond\": evaluation stack overflow");
@@ -42,8 +42,8 @@ static pit_value impl_sf_progn(pit_runtime *rt, pit_value args, void *data) {
pit_value bodyforms = args;
pit_value final = PIT_NIL;
while (bodyforms != PIT_NIL) {
- final = pit_eval(rt, pit_car(rt, bodyforms));
- bodyforms = pit_cdr(rt, bodyforms);
+ final = pit_eval(rt, pit_value_cons_car(rt, bodyforms));
+ bodyforms = pit_value_cons_cdr(rt, bodyforms);
}
pit_runtime_eval_program_push_literal(rt, rt->program, final);
return PIT_NIL;
@@ -53,38 +53,38 @@ static pit_value impl_sf_or(pit_runtime *rt, pit_value args, void *data) {
pit_value bodyforms = args;
pit_value final = PIT_NIL;
while (bodyforms != PIT_NIL) {
- final = pit_eval(rt, pit_car(rt, bodyforms));
+ final = pit_eval(rt, pit_value_cons_car(rt, bodyforms));
if (final != PIT_NIL) break;
- bodyforms = pit_cdr(rt, bodyforms);
+ bodyforms = pit_value_cons_cdr(rt, bodyforms);
}
pit_runtime_eval_program_push_literal(rt, rt->program, final);
return PIT_NIL;
}
static pit_value impl_sf_lambda(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- pit_value as = pit_car(rt, args);
- pit_value body = pit_cdr(rt, args);
- pit_runtime_eval_program_push_literal(rt, rt->program, pit_lambda(rt, as, body));
+ pit_value as = pit_value_cons_car(rt, args);
+ pit_value body = pit_value_cons_cdr(rt, args);
+ pit_runtime_eval_program_push_literal(rt, rt->program, pit_value_func_lambda(rt, as, body));
return PIT_NIL;
}
static pit_value impl_m_defun(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- pit_value nm = pit_car(rt, args);
- pit_value as = pit_car(rt, pit_cdr(rt, args));
- pit_value body = pit_cdr(rt, pit_cdr(rt, args));
- return pit_list(rt, 3,
- pit_intern_cstr(rt, "fset!"),
- pit_list(rt, 2, pit_intern_cstr(rt, "quote"), nm),
- pit_cons(rt, pit_intern_cstr(rt, "lambda"), pit_cons(rt, as, body))
+ pit_value nm = pit_value_cons_car(rt, args);
+ pit_value as = pit_value_cons_car(rt, pit_value_cons_cdr(rt, args));
+ pit_value body = pit_value_cons_cdr(rt, pit_value_cons_cdr(rt, args));
+ return pit_value_list(rt, 3,
+ pit_symtab_intern_cstr(rt, "fset!"),
+ pit_value_list(rt, 2, pit_symtab_intern_cstr(rt, "quote"), nm),
+ pit_value_cons(rt, pit_symtab_intern_cstr(rt, "lambda"), pit_value_cons(rt, as, body))
);
}
static pit_value impl_m_defmacro(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- pit_value nm = pit_car(rt, args);
- return pit_list(rt, 3,
- pit_intern_cstr(rt, "progn"),
- pit_cons(rt, pit_intern_cstr(rt, "defun!"), args),
- pit_list(rt, 2, pit_intern_cstr(rt, "set-symbol-macro!"), nm)
+ pit_value nm = pit_value_cons_car(rt, args);
+ return pit_value_list(rt, 3,
+ pit_symtab_intern_cstr(rt, "progn"),
+ pit_value_cons(rt, pit_symtab_intern_cstr(rt, "defun!"), args),
+ pit_value_list(rt, 2, pit_symtab_intern_cstr(rt, "set-symbol-macro!"), nm)
);
}
static pit_value impl_m_defstruct(pit_runtime *rt, pit_value args, void *data) {
@@ -95,76 +95,76 @@ static pit_value impl_m_defstruct(pit_runtime *rt, pit_value args, void *data) {
char nm_str[128];
char field_str[128];
char buf[512];
- pit_value nm = pit_car(rt, args);
- pit_value fields = pit_cdr(rt, args);
+ pit_value nm = pit_value_cons_car(rt, args);
+ pit_value fields = pit_value_cons_cdr(rt, args);
i64 field_idx = 0;
- i64 nm_len = pit_as_bytes(rt, pit_symbol_name(rt, nm), (u8 *) nm_str, sizeof(nm_str) - 1);
+ i64 nm_len = pit_value_bytes_copy(rt, pit_symtab_symbol_name(rt, nm), (u8 *) nm_str, sizeof(nm_str) - 1);
if (nm_len < 0) return PIT_NIL;
nm_str[nm_len] = 0;
/* constructor */
pit_libc_string_snprintf(buf, sizeof(buf), ":%s", nm_str);
- aargs = pit_cons(rt, pit_intern_cstr(rt, buf), pit_cons(rt, pit_intern_cstr(rt, "array"), PIT_NIL));
- fields = pit_cdr(rt, args);
+ aargs = pit_value_cons(rt, pit_symtab_intern_cstr(rt, buf), pit_value_cons(rt, pit_symtab_intern_cstr(rt, "array"), PIT_NIL));
+ fields = pit_value_cons_cdr(rt, args);
while (fields != PIT_NIL) {
- i64 field_len = pit_as_bytes(rt,
- pit_symbol_name(rt, pit_car(rt, fields)),
+ i64 field_len = pit_value_bytes_copy(rt,
+ pit_symtab_symbol_name(rt, pit_value_cons_car(rt, fields)),
(u8 *) field_str, sizeof(field_str) - 1
);
if (field_len < 0) return PIT_NIL;
field_str[field_len] = 0;
pit_libc_string_snprintf(buf, sizeof(buf), ":%s", field_str);
- aargs = pit_cons(rt,
- pit_list(rt, 3, pit_intern_cstr(rt, "plist/get"), pit_intern_cstr(rt, buf), pit_intern_cstr(rt, "kwargs")),
+ aargs = pit_value_cons(rt,
+ pit_value_list(rt, 3, pit_symtab_intern_cstr(rt, "plist/get"), pit_symtab_intern_cstr(rt, buf), pit_symtab_intern_cstr(rt, "kwargs")),
aargs
);
- fields = pit_cdr(rt, fields);
+ fields = pit_value_cons_cdr(rt, fields);
}
pit_libc_string_snprintf(buf, sizeof(buf), "%s/new", nm_str);
- df = pit_list(rt, 4,
- pit_intern_cstr(rt, "defun!"),
- pit_intern_cstr(rt, buf),
- pit_list(rt, 2, pit_intern_cstr(rt, "&"), pit_intern_cstr(rt, "kwargs")),
- pit_reverse(rt, aargs)
+ df = pit_value_list(rt, 4,
+ pit_symtab_intern_cstr(rt, "defun!"),
+ pit_symtab_intern_cstr(rt, buf),
+ pit_value_list(rt, 2, pit_symtab_intern_cstr(rt, "&"), pit_symtab_intern_cstr(rt, "kwargs")),
+ pit_value_list_reverse(rt, aargs)
);
- ret = pit_cons(rt, df, ret);
+ ret = pit_value_cons(rt, df, ret);
/* getters and setters */
- fields = pit_cdr(rt, args);
+ fields = pit_value_cons_cdr(rt, args);
field_idx = 0;
while (fields != PIT_NIL) {
- i64 field_len = pit_as_bytes(rt,
- pit_symbol_name(rt, pit_car(rt, fields)),
+ i64 field_len = pit_value_bytes_copy(rt,
+ pit_symtab_symbol_name(rt, pit_value_cons_car(rt, fields)),
(u8 *) field_str, sizeof(field_str) - 1
);
if (field_len < 0) return PIT_NIL;
field_str[field_len] = 0;
/* getter */
pit_libc_string_snprintf(buf, sizeof(buf), "%s/get-%s", nm_str, field_str);
- df = pit_list(rt, 4,
- pit_intern_cstr(rt, "defun!"),
- pit_intern_cstr(rt, buf),
- pit_list(rt, 1, pit_intern_cstr(rt, "v")),
- pit_list(rt, 3,
- pit_intern_cstr(rt, "array/get"),
- pit_integer_new(rt, field_idx + 1),
- pit_intern_cstr(rt, "v")
+ df = pit_value_list(rt, 4,
+ pit_symtab_intern_cstr(rt, "defun!"),
+ pit_symtab_intern_cstr(rt, buf),
+ pit_value_list(rt, 1, pit_symtab_intern_cstr(rt, "v")),
+ pit_value_list(rt, 3,
+ pit_symtab_intern_cstr(rt, "array/get"),
+ pit_value_integer_new(rt, field_idx + 1),
+ pit_symtab_intern_cstr(rt, "v")
)
);
- ret = pit_cons(rt, df, ret);
+ ret = pit_value_cons(rt, df, ret);
/* setter */
pit_libc_string_snprintf(buf, sizeof(buf), "%s/set-%s!", nm_str, field_str);
- df = pit_list(rt, 4,
- pit_intern_cstr(rt, "defun!"),
- pit_intern_cstr(rt, buf),
- pit_list(rt, 2, pit_intern_cstr(rt, "v"), pit_intern_cstr(rt, "x")),
- pit_list(rt, 4,
- pit_intern_cstr(rt, "array/set!"),
- pit_integer_new(rt, field_idx + 1),
- pit_intern_cstr(rt, "x"),
- pit_intern_cstr(rt, "v")
+ df = pit_value_list(rt, 4,
+ pit_symtab_intern_cstr(rt, "defun!"),
+ pit_symtab_intern_cstr(rt, buf),
+ pit_value_list(rt, 2, pit_symtab_intern_cstr(rt, "v"), pit_symtab_intern_cstr(rt, "x")),
+ pit_value_list(rt, 4,
+ pit_symtab_intern_cstr(rt, "array/set!"),
+ pit_value_integer_new(rt, field_idx + 1),
+ pit_symtab_intern_cstr(rt, "x"),
+ pit_symtab_intern_cstr(rt, "v")
)
);
- ret = pit_cons(rt, df, ret);
- fields = pit_cdr(rt, fields);
+ ret = pit_value_cons(rt, df, ret);
+ fields = pit_value_cons_cdr(rt, fields);
field_idx += 1;
}
// (defstruct foo x y z)
@@ -172,48 +172,48 @@ static pit_value impl_m_defstruct(pit_runtime *rt, pit_value args, void *data) {
// (defun foo/get-x (f) ...)
// (defun foo/set-x! (f v) ...)
// pit_trace(rt, ret);
- return pit_cons(rt, pit_intern_cstr(rt, "progn"), ret);
+ return pit_value_cons(rt, pit_symtab_intern_cstr(rt, "progn"), ret);
}
static pit_value impl_m_let(pit_runtime *rt, pit_value args, void *data) {
(void) data;
pit_value lparams = PIT_NIL;
pit_value largs = PIT_NIL;
- pit_value binds = pit_car(rt, args);
- pit_value bodyforms = pit_cdr(rt, args);
+ pit_value binds = pit_value_cons_car(rt, args);
+ pit_value bodyforms = pit_value_cons_cdr(rt, args);
pit_value lambda, application;
while (binds != PIT_NIL) {
- pit_value bind = pit_car(rt, binds);
- pit_value sym = pit_car(rt, bind);
- pit_value expr = pit_car(rt, pit_cdr(rt, bind));
- lparams = pit_cons(rt, sym, lparams);
- largs = pit_cons(rt, expr, largs);
- binds = pit_cdr(rt, binds);
- }
- lambda = pit_cons(rt, pit_intern_cstr(rt, "lambda"), pit_cons(rt, lparams, bodyforms));
- application = pit_cons(rt, lambda, largs);
+ pit_value bind = pit_value_cons_car(rt, binds);
+ pit_value sym = pit_value_cons_car(rt, bind);
+ pit_value expr = pit_value_cons_car(rt, pit_value_cons_cdr(rt, bind));
+ lparams = pit_value_cons(rt, sym, lparams);
+ largs = pit_value_cons(rt, expr, largs);
+ binds = pit_value_cons_cdr(rt, binds);
+ }
+ lambda = pit_value_cons(rt, pit_symtab_intern_cstr(rt, "lambda"), pit_value_cons(rt, lparams, bodyforms));
+ application = pit_value_cons(rt, lambda, largs);
return application;
}
static pit_value impl_m_and(pit_runtime *rt, pit_value args, void *data) {
(void) data;
pit_value ret = PIT_NIL;
- args = pit_reverse(rt, args);
+ args = pit_value_list_reverse(rt, args);
if (args != PIT_NIL) {
- ret = pit_car(rt, args);
- args = pit_cdr(rt, args);
+ ret = pit_value_cons_car(rt, args);
+ args = pit_value_cons_cdr(rt, args);
}
while (args != PIT_NIL) {
- ret = pit_list(rt, 3, pit_intern_cstr(rt, "if"), pit_car(rt, args), ret, PIT_NIL);
- args = pit_cdr(rt, args);
+ ret = pit_value_list(rt, 3, pit_symtab_intern_cstr(rt, "if"), pit_value_cons_car(rt, args), ret, PIT_NIL);
+ args = pit_value_cons_cdr(rt, args);
}
return ret;
}
static pit_value impl_m_setq(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- pit_value sym = pit_car(rt, args);
- pit_value v = pit_car(rt, pit_cdr(rt, args));
- return pit_list(rt, 3,
- pit_intern_cstr(rt, "set!"),
- pit_list(rt, 2, pit_intern_cstr(rt, "quote"), sym),
+ pit_value sym = pit_value_cons_car(rt, args);
+ pit_value v = pit_value_cons_car(rt, pit_value_cons_cdr(rt, args));
+ return pit_value_list(rt, 3,
+ pit_symtab_intern_cstr(rt, "set!"),
+ pit_value_list(rt, 2, pit_symtab_intern_cstr(rt, "quote"), sym),
v
);
}
@@ -222,139 +222,139 @@ static pit_value impl_m_setq(pit_runtime *rt, pit_value args, void *data) {
// (cond ((eq x 'y) 'foo) ((eq x 'z) 'bar))
static pit_value impl_m_case(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- pit_value x = pit_car(rt, args);
- pit_value cases = pit_cdr(rt, args);
+ pit_value x = pit_value_cons_car(rt, args);
+ pit_value cases = pit_value_cons_cdr(rt, args);
pit_value clauses = PIT_NIL;
- pit_value xvar = pit_intern_cstr(rt, "(internal case)");
+ pit_value xvar = pit_symtab_intern_cstr(rt, "(internal case)");
while (cases != PIT_NIL) {
- pit_value c = pit_car(rt, cases);
- clauses = pit_cons(rt,
- pit_list(rt, 2,
- pit_list(rt, 3, pit_intern_cstr(rt, "equal?"),
+ pit_value c = pit_value_cons_car(rt, cases);
+ clauses = pit_value_cons(rt,
+ pit_value_list(rt, 2,
+ pit_value_list(rt, 3, pit_symtab_intern_cstr(rt, "equal?"),
xvar,
- pit_list(rt, 2, pit_intern_cstr(rt, "quote"), pit_car(rt, c))
+ pit_value_list(rt, 2, pit_symtab_intern_cstr(rt, "quote"), pit_value_cons_car(rt, c))
),
- pit_car(rt, pit_cdr(rt, c))
+ pit_value_cons_car(rt, pit_value_cons_cdr(rt, c))
),
clauses
);
- cases = pit_cdr(rt, cases);
+ cases = pit_value_cons_cdr(rt, cases);
}
- return pit_list(rt, 3,
- pit_intern_cstr(rt, "let"),
- pit_list(rt, 1, pit_list(rt, 2, xvar, x)),
- pit_cons(rt, pit_intern_cstr(rt, "cond"), pit_reverse(rt, clauses))
+ return pit_value_list(rt, 3,
+ pit_symtab_intern_cstr(rt, "let"),
+ pit_value_list(rt, 1, pit_value_list(rt, 2, xvar, x)),
+ pit_value_cons(rt, pit_symtab_intern_cstr(rt, "cond"), pit_value_list_reverse(rt, clauses))
);
}
static pit_value impl_set(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- pit_value sym = pit_car(rt, args);
- pit_value v = pit_car(rt, pit_cdr(rt, args));
- pit_set(rt, sym, v);
+ pit_value sym = pit_value_cons_car(rt, args);
+ pit_value v = pit_value_cons_car(rt, pit_value_cons_cdr(rt, args));
+ pit_symtab_set(rt, sym, v);
return v;
}
static pit_value impl_fset(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- pit_value sym = pit_car(rt, args);
- pit_value v = pit_car(rt, pit_cdr(rt, args));
- pit_fset(rt, sym, v);
+ pit_value sym = pit_value_cons_car(rt, args);
+ pit_value v = pit_value_cons_car(rt, pit_value_cons_cdr(rt, args));
+ pit_symtab_fset(rt, sym, v);
return v;
}
-static pit_value impl_symbol_is_macro(pit_runtime *rt, pit_value args, void *data) {
+static pit_value impl_symbol_mark_macro(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- pit_value sym = pit_car(rt, args);
- pit_symbol_is_macro(rt, sym);
+ pit_value sym = pit_value_cons_car(rt, args);
+ pit_symtab_symbol_mark_macro(rt, sym);
return PIT_NIL;
}
static pit_value impl_funcall(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- pit_value f = pit_car(rt, args);
- return pit_apply(rt, f, pit_cdr(rt, args));
+ pit_value f = pit_value_cons_car(rt, args);
+ return pit_value_apply(rt, f, pit_value_cons_cdr(rt, args));
}
static pit_value impl_apply(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- pit_value f = pit_car(rt, args);
- pit_value xs = pit_car(rt, pit_cdr(rt, args));
- return pit_apply(rt, f, xs);
+ pit_value f = pit_value_cons_car(rt, args);
+ pit_value xs = pit_value_cons_car(rt, pit_value_cons_cdr(rt, args));
+ return pit_value_apply(rt, f, xs);
}
static pit_value impl_error(pit_runtime *rt, pit_value args, void *data) {
(void) data;
rt->error = PIT_T;
- rt->error = pit_car(rt, args);
+ rt->error = pit_value_cons_car(rt, args);
rt->error_line = rt->source_line;
rt->error_column = rt->source_column;
return PIT_NIL;
}
static pit_value impl_eval(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- return pit_eval(rt, pit_car(rt, args));
+ return pit_eval(rt, pit_value_cons_car(rt, args));
}
static pit_value impl_eq_p(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- pit_value x = pit_car(rt, args);
- pit_value y = pit_car(rt, pit_cdr(rt, args));
- return pit_bool_new(rt, pit_eq(x, y));
+ pit_value x = pit_value_cons_car(rt, args);
+ pit_value y = pit_value_cons_car(rt, pit_value_cons_cdr(rt, args));
+ return pit_value_bool_new(rt, pit_value_eq(x, y));
}
static pit_value impl_equal_p(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- pit_value x = pit_car(rt, args);
- pit_value y = pit_car(rt, pit_cdr(rt, args));
- return pit_bool_new(rt, pit_equal(rt, x, y));
+ pit_value x = pit_value_cons_car(rt, args);
+ pit_value y = pit_value_cons_car(rt, pit_value_cons_cdr(rt, args));
+ return pit_value_bool_new(rt, pit_value_equal(rt, x, y));
}
static pit_value impl_integer_p(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- return pit_bool_new(rt, pit_is_integer(rt, pit_car(rt, args)));
+ return pit_value_bool_new(rt, pit_value_is_integer(rt, pit_value_cons_car(rt, args)));
}
static pit_value impl_double_p(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- return pit_bool_new(rt, pit_is_double(rt, pit_car(rt, args)));
+ return pit_value_bool_new(rt, pit_value_is_double(rt, pit_value_cons_car(rt, args)));
}
static pit_value impl_symbol_p(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- return pit_bool_new(rt, pit_is_symbol(rt, pit_car(rt, args)));
+ return pit_value_bool_new(rt, pit_value_is_symbol(rt, pit_value_cons_car(rt, args)));
}
static pit_value impl_cons_p(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- return pit_bool_new(rt, pit_is_cons(rt, pit_car(rt, args)));
+ return pit_value_bool_new(rt, pit_value_is_cons(rt, pit_value_cons_car(rt, args)));
}
static pit_value impl_array_p(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- return pit_bool_new(rt, pit_is_array(rt, pit_car(rt, args)));
+ return pit_value_bool_new(rt, pit_value_is_array(rt, pit_value_cons_car(rt, args)));
}
static pit_value impl_bytes_p(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- return pit_bool_new(rt, pit_is_bytes(rt, pit_car(rt, args)));
+ return pit_value_bool_new(rt, pit_value_is_bytes(rt, pit_value_cons_car(rt, args)));
}
static pit_value impl_function_p(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- pit_value a = pit_car(rt, args);
- bool b = (pit_is_symbol(rt, a) && pit_fget(rt, a) != PIT_NIL)
- || pit_is_func(rt, a)
- || pit_is_nativefunc(rt, a);
- return pit_bool_new(rt, b);
+ pit_value a = pit_value_cons_car(rt, args);
+ bool b = (pit_value_is_symbol(rt, a) && pit_symtab_fget(rt, a) != PIT_NIL)
+ || pit_value_is_func(rt, a)
+ || pit_value_is_nativefunc(rt, a);
+ return pit_value_bool_new(rt, b);
}
static pit_value impl_cons(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- return pit_cons(rt, pit_car(rt, args), pit_car(rt, pit_cdr(rt, args)));
+ return pit_value_cons(rt, pit_value_cons_car(rt, args), pit_value_cons_car(rt, pit_value_cons_cdr(rt, args)));
}
static pit_value impl_car(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- return pit_car(rt, pit_car(rt, args));
+ return pit_value_cons_car(rt, pit_value_cons_car(rt, args));
}
static pit_value impl_cdr(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- return pit_cdr(rt, pit_car(rt, args));
+ return pit_value_cons_cdr(rt, pit_value_cons_car(rt, args));
}
static pit_value impl_setcar(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- pit_value v = pit_car(rt, pit_cdr(rt, args));
- pit_setcar(rt, pit_car(rt, args), v);
+ pit_value v = pit_value_cons_car(rt, pit_value_cons_cdr(rt, args));
+ pit_value_cons_setcar(rt, pit_value_cons_car(rt, args), v);
return v;
}
static pit_value impl_setcdr(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- pit_value v = pit_car(rt, pit_cdr(rt, args));
- pit_setcdr(rt, pit_car(rt, args), v);
+ pit_value v = pit_value_cons_car(rt, pit_value_cons_cdr(rt, args));
+ pit_value_cons_setcdr(rt, pit_value_cons_car(rt, args), v);
return v;
}
static pit_value impl_list(pit_runtime *rt, pit_value args, void *data) {
@@ -364,195 +364,195 @@ static pit_value impl_list(pit_runtime *rt, pit_value args, void *data) {
}
static pit_value impl_list_nth(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- i64 n = pit_as_integer(rt, pit_car(rt, args));
- pit_value xs = pit_car(rt, pit_cdr(rt, args));
+ i64 n = pit_value_as_integer(rt, pit_value_cons_car(rt, args));
+ pit_value xs = pit_value_cons_car(rt, pit_value_cons_cdr(rt, args));
while (xs != PIT_NIL && n-- > 0) {
- xs = pit_cdr(rt, xs);
+ xs = pit_value_cons_cdr(rt, xs);
}
- return pit_car(rt, xs);
+ return pit_value_cons_car(rt, xs);
}
static pit_value impl_list_iota(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- i64 n = pit_as_integer(rt, pit_car(rt, args));
+ i64 n = pit_value_as_integer(rt, pit_value_cons_car(rt, args));
pit_value ret = PIT_NIL;
while (n > 0) {
- ret = pit_cons(rt, pit_integer_new(rt, --n), ret);
+ ret = pit_value_cons(rt, pit_value_integer_new(rt, --n), ret);
}
return ret;
}
static pit_value impl_list_len(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- pit_value arr = pit_car(rt, args);
- return pit_integer_new(rt, pit_list_len(rt, arr));
+ pit_value arr = pit_value_cons_car(rt, args);
+ return pit_value_integer_new(rt, pit_value_list_len(rt, arr));
}
static pit_value impl_list_reverse(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- return pit_reverse(rt, pit_car(rt, args));
+ return pit_value_list_reverse(rt, pit_value_cons_car(rt, args));
}
static pit_value impl_list_uniq(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- pit_value xs = pit_car(rt, args);
+ pit_value xs = pit_value_cons_car(rt, args);
pit_value ret = PIT_NIL;
while (xs != PIT_NIL) {
- pit_value x = pit_car(rt, xs);
- if (pit_contains_equal(rt, x, ret) == PIT_NIL) {
- ret = pit_cons(rt, x, ret);
+ pit_value x = pit_value_cons_car(rt, xs);
+ if (pit_value_list_contains_equal(rt, x, ret) == PIT_NIL) {
+ ret = pit_value_cons(rt, x, ret);
}
- xs = pit_cdr(rt, xs);
+ xs = pit_value_cons_cdr(rt, xs);
}
- return pit_reverse(rt, ret);
+ return pit_value_list_reverse(rt, ret);
}
static pit_value impl_list_append(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- args = pit_reverse(rt, args);
- pit_value ret = pit_car(rt, args);
- pit_value ls = pit_cdr(rt, args);
+ args = pit_value_list_reverse(rt, args);
+ pit_value ret = pit_value_cons_car(rt, args);
+ pit_value ls = pit_value_cons_cdr(rt, args);
while (ls != PIT_NIL) {
- pit_value xs = pit_reverse(rt, pit_car(rt, ls));
+ pit_value xs = pit_value_list_reverse(rt, pit_value_cons_car(rt, ls));
while (xs != PIT_NIL) {
- ret = pit_cons(rt, pit_car(rt, xs), ret);
- xs = pit_cdr(rt, xs);
+ ret = pit_value_cons(rt, pit_value_cons_car(rt, xs), ret);
+ xs = pit_value_cons_cdr(rt, xs);
}
- ls = pit_cdr(rt, ls);
+ ls = pit_value_cons_cdr(rt, ls);
}
return ret;
}
static pit_value impl_list_concat(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- return impl_list_append(rt, pit_car(rt, args), NULL);
+ return impl_list_append(rt, pit_value_cons_car(rt, args), NULL);
}
static pit_value impl_list_take(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- i64 num = pit_as_integer(rt, pit_car(rt, args));
- pit_value arr = pit_car(rt, pit_cdr(rt, args));
+ i64 num = pit_value_as_integer(rt, pit_value_cons_car(rt, args));
+ pit_value arr = pit_value_cons_car(rt, pit_value_cons_cdr(rt, args));
pit_value ret = PIT_NIL;
while (num > 0 && arr != PIT_NIL) {
- ret = pit_cons(rt, pit_car(rt, arr), ret);
- arr = pit_cdr(rt, arr);
+ ret = pit_value_cons(rt, pit_value_cons_car(rt, arr), ret);
+ arr = pit_value_cons_cdr(rt, arr);
num -= 1;
}
- return pit_reverse(rt, ret);
+ return pit_value_list_reverse(rt, ret);
}
static pit_value impl_list_drop(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- i64 num = pit_as_integer(rt, pit_car(rt, args));
- pit_value arr = pit_car(rt, pit_cdr(rt, args));
+ i64 num = pit_value_as_integer(rt, pit_value_cons_car(rt, args));
+ pit_value arr = pit_value_cons_car(rt, pit_value_cons_cdr(rt, args));
while (num > 0 && arr != PIT_NIL) {
- arr = pit_cdr(rt, arr);
+ arr = pit_value_cons_cdr(rt, arr);
num -= 1;
}
return arr;
}
static pit_value impl_list_map(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- pit_value func = pit_car(rt, args);
- pit_value xs = pit_car(rt, pit_cdr(rt, args));
+ pit_value func = pit_value_cons_car(rt, args);
+ pit_value xs = pit_value_cons_car(rt, pit_value_cons_cdr(rt, args));
pit_value ret = PIT_NIL;
while (xs != PIT_NIL) {
- pit_value y = pit_apply(rt, func, pit_cons(rt, pit_car(rt, xs), PIT_NIL));
- ret = pit_cons(rt, y, ret);
- xs = pit_cdr(rt, xs);
+ pit_value y = pit_value_apply(rt, func, pit_value_cons(rt, pit_value_cons_car(rt, xs), PIT_NIL));
+ ret = pit_value_cons(rt, y, ret);
+ xs = pit_value_cons_cdr(rt, xs);
}
- return pit_reverse(rt, ret);
+ return pit_value_list_reverse(rt, ret);
}
static pit_value impl_list_foldl(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- pit_value func = pit_car(rt, args);
- pit_value acc = pit_car(rt, pit_cdr(rt, args));
- pit_value xs = pit_car(rt, pit_cdr(rt, pit_cdr(rt, args)));
+ pit_value func = pit_value_cons_car(rt, args);
+ pit_value acc = pit_value_cons_car(rt, pit_value_cons_cdr(rt, args));
+ pit_value xs = pit_value_cons_car(rt, pit_value_cons_cdr(rt, pit_value_cons_cdr(rt, args)));
while (xs != PIT_NIL) {
- acc = pit_apply(rt, func, pit_list(rt, 2, pit_car(rt, xs), acc));
- xs = pit_cdr(rt, xs);
+ acc = pit_value_apply(rt, func, pit_value_list(rt, 2, pit_value_cons_car(rt, xs), acc));
+ xs = pit_value_cons_cdr(rt, xs);
}
return acc;
}
static pit_value impl_list_filter(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- pit_value func = pit_car(rt, args);
- pit_value xs = pit_car(rt, pit_cdr(rt, args));
+ pit_value func = pit_value_cons_car(rt, args);
+ pit_value xs = pit_value_cons_car(rt, pit_value_cons_cdr(rt, args));
pit_value ret = PIT_NIL;
while (xs != PIT_NIL) {
- pit_value x = pit_car(rt, xs);
- pit_value y = pit_apply(rt, func, pit_cons(rt, x, PIT_NIL));
+ pit_value x = pit_value_cons_car(rt, xs);
+ pit_value y = pit_value_apply(rt, func, pit_value_cons(rt, x, PIT_NIL));
if (y != PIT_NIL) {
- ret = pit_cons(rt, x, ret);
+ ret = pit_value_cons(rt, x, ret);
}
- xs = pit_cdr(rt, xs);
+ xs = pit_value_cons_cdr(rt, xs);
}
- return pit_reverse(rt, ret);
+ return pit_value_list_reverse(rt, ret);
}
static pit_value impl_list_find(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- pit_value func = pit_car(rt, args);
- pit_value xs = pit_car(rt, pit_cdr(rt, args));
+ pit_value func = pit_value_cons_car(rt, args);
+ pit_value xs = pit_value_cons_car(rt, pit_value_cons_cdr(rt, args));
while (xs != PIT_NIL) {
- pit_value x = pit_car(rt, xs);
- pit_value y = pit_apply(rt, func, pit_cons(rt, x, PIT_NIL));
+ pit_value x = pit_value_cons_car(rt, xs);
+ pit_value y = pit_value_apply(rt, func, pit_value_cons(rt, x, PIT_NIL));
if (y != PIT_NIL) {
return x;
}
- xs = pit_cdr(rt, xs);
+ xs = pit_value_cons_cdr(rt, xs);
}
return PIT_NIL;
}
static pit_value impl_list_contains_p(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- pit_value needle = pit_car(rt, args);
- pit_value haystack = pit_car(rt, pit_cdr(rt, args));
+ pit_value needle = pit_value_cons_car(rt, args);
+ pit_value haystack = pit_value_cons_car(rt, pit_value_cons_cdr(rt, args));
while (haystack != PIT_NIL) {
- if (pit_equal(rt, needle, pit_car(rt, haystack))) return PIT_T;
- haystack = pit_cdr(rt, haystack);
+ if (pit_value_equal(rt, needle, pit_value_cons_car(rt, haystack))) return PIT_T;
+ haystack = pit_value_cons_cdr(rt, haystack);
}
return PIT_NIL;
}
static pit_value impl_list_all_p(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- pit_value f = pit_car(rt, args);
- pit_value xs = pit_car(rt, pit_cdr(rt, args));
+ pit_value f = pit_value_cons_car(rt, args);
+ pit_value xs = pit_value_cons_car(rt, pit_value_cons_cdr(rt, args));
while (xs != PIT_NIL) {
- pit_value x = pit_car(rt, xs);
- if (pit_apply(rt, f, pit_cons(rt, x, PIT_NIL)) == PIT_NIL) {
+ pit_value x = pit_value_cons_car(rt, xs);
+ if (pit_value_apply(rt, f, pit_value_cons(rt, x, PIT_NIL)) == PIT_NIL) {
return PIT_NIL;
}
- xs = pit_cdr(rt, xs);
+ xs = pit_value_cons_cdr(rt, xs);
}
return PIT_T;
}
static pit_value impl_list_zip_with(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- pit_value f = pit_car(rt, args);
- pit_value xs = pit_car(rt, pit_cdr(rt, args));
- pit_value ys = pit_car(rt, pit_cdr(rt, pit_cdr(rt, args)));
+ pit_value f = pit_value_cons_car(rt, args);
+ pit_value xs = pit_value_cons_car(rt, pit_value_cons_cdr(rt, args));
+ pit_value ys = pit_value_cons_car(rt, pit_value_cons_cdr(rt, pit_value_cons_cdr(rt, args)));
pit_value ret = PIT_NIL;
while (xs != PIT_NIL && ys != PIT_NIL) {
- pit_value z = pit_apply(rt, f, pit_list(rt, 2, pit_car(rt, xs), pit_car(rt, ys)));
- ret = pit_cons(rt, z, ret);
- xs = pit_cdr(rt, xs); ys = pit_cdr(rt, ys);
+ pit_value z = pit_value_apply(rt, f, pit_value_list(rt, 2, pit_value_cons_car(rt, xs), pit_value_cons_car(rt, ys)));
+ ret = pit_value_cons(rt, z, ret);
+ xs = pit_value_cons_cdr(rt, xs); ys = pit_value_cons_cdr(rt, ys);
}
- return pit_reverse(rt, ret);
+ return pit_value_list_reverse(rt, ret);
}
static pit_value impl_bytes_len(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- pit_value v = pit_car(rt, args);
+ pit_value v = pit_value_cons_car(rt, args);
if (pit_value_sort(v) != PIT_VALUE_SORT_REF) {
pit_error(rt, "value is not a ref");
return PIT_NIL;
}
- pit_value_heavy *h = pit_deref(rt, pit_as_ref(rt, v));
+ pit_value_heavy *h = pit_value_ref_deref(rt, pit_value_as_ref(rt, v));
if (!h) { pit_error(rt, "bad ref"); return PIT_NIL; }
if (h->hsort != PIT_VALUE_HEAVY_SORT_BYTES) { pit_error(rt, "ref is not bytes"); return PIT_NIL; }
- return pit_integer_new(rt, h->in.bytes.len);
+ return pit_value_integer_new(rt, h->in.bytes.len);
}
static pit_value impl_bytes_range(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- i64 start = pit_as_integer(rt, pit_car(rt, args));
- i64 end = pit_as_integer(rt, pit_car(rt, pit_cdr(rt, args)));
- pit_value v = pit_car(rt, pit_cdr(rt, pit_cdr(rt, args)));
+ i64 start = pit_value_as_integer(rt, pit_value_cons_car(rt, args));
+ i64 end = pit_value_as_integer(rt, pit_value_cons_car(rt, pit_value_cons_cdr(rt, args)));
+ pit_value v = pit_value_cons_car(rt, pit_value_cons_cdr(rt, pit_value_cons_cdr(rt, args)));
if (pit_value_sort(v) != PIT_VALUE_SORT_REF) {
pit_error(rt, "value is not a ref");
return PIT_NIL;
}
- pit_value_heavy *h = pit_deref(rt, pit_as_ref(rt, v));
+ pit_value_heavy *h = pit_value_ref_deref(rt, pit_value_as_ref(rt, v));
if (!h) { pit_error(rt, "bad ref"); return PIT_NIL; }
if (h->hsort != PIT_VALUE_HEAVY_SORT_BYTES) { pit_error(rt, "ref is not bytes"); return PIT_NIL; }
if (start < 0 || start >= h->in.bytes.len) {
@@ -563,43 +563,41 @@ static pit_value impl_bytes_range(pit_runtime *rt, pit_value args, void *data) {
pit_error(rt, "bytes range end index out of bounds: %d", end);
return PIT_NIL;
}
- return pit_bytes_new(rt, h->in.bytes.data + start, end - start);
+ return pit_value_bytes_new(rt, h->in.bytes.data + start, end - start);
}
static pit_value impl_array(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- i64 scratch_reset = rt->scratch->next;
- i64 len = 0;
+ i64 len = pit_value_list_len(rt, args);
+ pit_value ret = pit_value_array_new(rt, len);
+ i64 idx = 0;
while (args != PIT_NIL) {
- pit_value *cell = pit_arena_alloc_array(rt->scratch, sizeof(pit_value));
- *cell = pit_car(rt, args);
- len += 1;
- args = pit_cdr(rt, args);
+ pit_value_array_set(rt, ret, idx++, pit_value_cons_car(rt, args));
+ args = pit_value_cons_cdr(rt, args);
}
- rt->scratch->next = scratch_reset;
- return pit_array_from_buf(rt, pit_arena_get(rt->scratch, (i32) scratch_reset), len);
+ return ret;
}
static pit_value impl_array_to_list(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- pit_value arr = pit_car(rt, args);
- i64 ilen = pit_array_len(rt, arr);
+ pit_value arr = pit_value_cons_car(rt, args);
+ i64 ilen = pit_value_array_len(rt, arr);
pit_value ret = PIT_NIL;
i64 i = 0;
for (; i < ilen; ++i) {
- ret = pit_cons(rt, pit_array_get(rt, arr, i), ret);
+ ret = pit_value_cons(rt, pit_value_array_get(rt, arr, i), ret);
}
- return pit_reverse(rt, ret);
+ return pit_value_list_reverse(rt, ret);
}
static pit_value impl_array_from_list(pit_runtime *rt, pit_value args, void *data) {
(void) data;
i64 i = 0;
- pit_value xs = pit_car(rt, args);
- i64 ilen = pit_list_len(rt, xs);
- pit_value ret = pit_array_new(rt, ilen);
- pit_value_heavy *h = pit_deref(rt, pit_as_ref(rt, ret));
+ pit_value xs = pit_value_cons_car(rt, args);
+ i64 ilen = pit_value_list_len(rt, xs);
+ pit_value ret = pit_value_array_new(rt, ilen);
+ pit_value_heavy *h = pit_value_ref_deref(rt, pit_value_as_ref(rt, ret));
if (!h) { pit_error(rt, "failed to deref heavy value for array"); return PIT_NIL; }
while (xs != PIT_NIL) {
- h->in.array.data[i] = pit_car(rt, xs);
- xs = pit_cdr(rt, xs);
+ h->in.array.data[i] = pit_value_cons_car(rt, xs);
+ xs = pit_value_cons_cdr(rt, xs);
i += 1;
}
return ret;
@@ -607,11 +605,11 @@ static pit_value impl_array_from_list(pit_runtime *rt, pit_value args, void *dat
static pit_value impl_array_repeat(pit_runtime *rt, pit_value args, void *data) {
(void) data;
i64 i = 0;
- pit_value v = pit_car(rt, args);
- pit_value len = pit_car(rt, pit_cdr(rt, args));
- i64 ilen = pit_as_integer(rt, len);
- pit_value ret = pit_array_new(rt, ilen);
- pit_value_heavy *h = pit_deref(rt, pit_as_ref(rt, ret));
+ pit_value v = pit_value_cons_car(rt, args);
+ pit_value len = pit_value_cons_car(rt, pit_value_cons_cdr(rt, args));
+ i64 ilen = pit_value_as_integer(rt, len);
+ pit_value ret = pit_value_array_new(rt, ilen);
+ pit_value_heavy *h = pit_value_ref_deref(rt, pit_value_as_ref(rt, ret));
if (!h) { pit_error(rt, "failed to deref heavy value for array"); return PIT_NIL; }
for (; i < ilen; ++i) {
h->in.array.data[i] = v;
@@ -620,98 +618,98 @@ static pit_value impl_array_repeat(pit_runtime *rt, pit_value args, void *data)
}
static pit_value impl_array_len(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- pit_value arr = pit_car(rt, args);
- return pit_integer_new(rt, pit_array_len(rt, arr));
+ pit_value arr = pit_value_cons_car(rt, args);
+ return pit_value_integer_new(rt, pit_value_array_len(rt, arr));
}
static pit_value impl_array_get(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- pit_value idx = pit_car(rt, args);
- pit_value arr = pit_car(rt, pit_cdr(rt, args));
- return pit_array_get(rt, arr, pit_as_integer(rt, idx));
+ pit_value idx = pit_value_cons_car(rt, args);
+ pit_value arr = pit_value_cons_car(rt, pit_value_cons_cdr(rt, args));
+ return pit_value_array_get(rt, arr, pit_value_as_integer(rt, idx));
}
static pit_value impl_array_set(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- pit_value idx = pit_car(rt, args);
- pit_value v = pit_car(rt, pit_cdr(rt, args));
- pit_value arr = pit_car(rt, pit_cdr(rt, pit_cdr(rt, args)));
- return pit_array_set(rt, arr, pit_as_integer(rt, idx), v);
+ pit_value idx = pit_value_cons_car(rt, args);
+ pit_value v = pit_value_cons_car(rt, pit_value_cons_cdr(rt, args));
+ pit_value arr = pit_value_cons_car(rt, pit_value_cons_cdr(rt, pit_value_cons_cdr(rt, args)));
+ return pit_value_array_set(rt, arr, pit_value_as_integer(rt, idx), v);
}
static pit_value impl_array_map(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- pit_value func = pit_car(rt, args);
- pit_value arr = pit_car(rt, pit_cdr(rt, args));
- i64 len = pit_array_len(rt, arr);
- pit_value ret = pit_array_new(rt, len);
+ pit_value func = pit_value_cons_car(rt, args);
+ pit_value arr = pit_value_cons_car(rt, pit_value_cons_cdr(rt, args));
+ i64 len = pit_value_array_len(rt, arr);
+ pit_value ret = pit_value_array_new(rt, len);
i64 i = 0;
for (i = 0; i < len; ++i) {
- pit_value y = pit_apply(rt, func, pit_cons(rt, pit_array_get(rt, arr, i), PIT_NIL));
- pit_array_set(rt, ret, i, y);
+ pit_value y = pit_value_apply(rt, func, pit_value_cons(rt, pit_value_array_get(rt, arr, i), PIT_NIL));
+ pit_value_array_set(rt, ret, i, y);
}
return ret;
}
static pit_value impl_array_map_mut(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- pit_value func = pit_car(rt, args);
- pit_value arr = pit_car(rt, pit_cdr(rt, args));
- i64 len = pit_array_len(rt, arr);
+ pit_value func = pit_value_cons_car(rt, args);
+ pit_value arr = pit_value_cons_car(rt, pit_value_cons_cdr(rt, args));
+ i64 len = pit_value_array_len(rt, arr);
i64 i = 0;
for (i = 0; i < len; ++i) {
- pit_value y = pit_apply(rt, func, pit_cons(rt, pit_array_get(rt, arr, i), PIT_NIL));
- pit_array_set(rt, arr, i, y);
+ pit_value y = pit_value_apply(rt, func, pit_value_cons(rt, pit_value_array_get(rt, arr, i), PIT_NIL));
+ pit_value_array_set(rt, arr, i, y);
}
return arr;
}
static pit_value impl_abs(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- i64 x = pit_as_integer(rt, pit_car(rt, args));
- if (x < 0) return pit_integer_new(rt, -x);
- return pit_integer_new(rt, x);
+ i64 x = pit_value_as_integer(rt, pit_value_cons_car(rt, args));
+ if (x < 0) return pit_value_integer_new(rt, -x);
+ return pit_value_integer_new(rt, x);
}
static pit_value impl_add(pit_runtime *rt, pit_value args, void *data) {
(void) data;
i64 total = 0;
while (args != PIT_NIL) {
- total += pit_as_integer(rt, pit_car(rt, args));
- args = pit_cdr(rt, args);
+ total += pit_value_as_integer(rt, pit_value_cons_car(rt, args));
+ args = pit_value_cons_cdr(rt, args);
}
- return pit_integer_new(rt, total);
+ return pit_value_integer_new(rt, total);
}
static pit_value impl_sub(pit_runtime *rt, pit_value args, void *data) {
(void) data;
i64 total = 0;
while (args != PIT_NIL) {
- total -= pit_as_integer(rt, pit_car(rt, args));
- args = pit_cdr(rt, args);
+ total -= pit_value_as_integer(rt, pit_value_cons_car(rt, args));
+ args = pit_value_cons_cdr(rt, args);
}
- return pit_integer_new(rt, total);
+ return pit_value_integer_new(rt, total);
}
static pit_value impl_mul(pit_runtime *rt, pit_value args, void *data) {
(void) data;
i64 total = 1;
while (args != PIT_NIL) {
- total *= pit_as_integer(rt, pit_car(rt, args));
- args = pit_cdr(rt, args);
+ total *= pit_value_as_integer(rt, pit_value_cons_car(rt, args));
+ args = pit_value_cons_cdr(rt, args);
}
- return pit_integer_new(rt, total);
+ return pit_value_integer_new(rt, total);
}
static pit_value impl_div(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- i64 total = pit_as_integer(rt, pit_car(rt, args));
- args = pit_cdr(rt, args);
+ i64 total = pit_value_as_integer(rt, pit_value_cons_car(rt, args));
+ args = pit_value_cons_cdr(rt, args);
while (args != PIT_NIL) {
- i64 denom = pit_as_integer(rt, pit_car(rt, args));
+ i64 denom = pit_value_as_integer(rt, pit_value_cons_car(rt, args));
if (denom == 0) {
pit_error(rt, "divide by zero");
return PIT_NIL;
}
total /= denom;
- args = pit_cdr(rt, args);
+ args = pit_value_cons_cdr(rt, args);
}
- return pit_integer_new(rt, total);
+ return pit_value_integer_new(rt, total);
}
static pit_value impl_not(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- if (pit_car(rt, args) == PIT_NIL) {
+ if (pit_value_cons_car(rt, args) == PIT_NIL) {
return PIT_T;
} else {
return PIT_NIL;
@@ -719,194 +717,194 @@ static pit_value impl_not(pit_runtime *rt, pit_value args, void *data) {
}
static pit_value impl_lt(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- i64 x = pit_as_integer(rt, pit_car(rt, args));
- i64 y = pit_as_integer(rt, pit_car(rt, pit_cdr(rt, args)));
- return pit_bool_new(rt, x < y);
+ i64 x = pit_value_as_integer(rt, pit_value_cons_car(rt, args));
+ i64 y = pit_value_as_integer(rt, pit_value_cons_car(rt, pit_value_cons_cdr(rt, args)));
+ return pit_value_bool_new(rt, x < y);
}
static pit_value impl_gt(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- i64 x = pit_as_integer(rt, pit_car(rt, args));
- i64 y = pit_as_integer(rt, pit_car(rt, pit_cdr(rt, args)));
- return pit_bool_new(rt, x > y);
+ i64 x = pit_value_as_integer(rt, pit_value_cons_car(rt, args));
+ i64 y = pit_value_as_integer(rt, pit_value_cons_car(rt, pit_value_cons_cdr(rt, args)));
+ return pit_value_bool_new(rt, x > y);
}
static pit_value impl_le(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- i64 x = pit_as_integer(rt, pit_car(rt, args));
- i64 y = pit_as_integer(rt, pit_car(rt, pit_cdr(rt, args)));
- return pit_bool_new(rt, x <= y);
+ i64 x = pit_value_as_integer(rt, pit_value_cons_car(rt, args));
+ i64 y = pit_value_as_integer(rt, pit_value_cons_car(rt, pit_value_cons_cdr(rt, args)));
+ return pit_value_bool_new(rt, x <= y);
}
static pit_value impl_ge(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- i64 x = pit_as_integer(rt, pit_car(rt, args));
- i64 y = pit_as_integer(rt, pit_car(rt, pit_cdr(rt, args)));
- return pit_bool_new(rt, x >= y);
+ i64 x = pit_value_as_integer(rt, pit_value_cons_car(rt, args));
+ i64 y = pit_value_as_integer(rt, pit_value_cons_car(rt, pit_value_cons_cdr(rt, args)));
+ return pit_value_bool_new(rt, x >= y);
}
static pit_value impl_bitwise_and(pit_runtime *rt, pit_value args, void *data) {
(void) data;
i64 total = -1;
while (args != PIT_NIL) {
- total &= pit_as_integer(rt, pit_car(rt, args));
- args = pit_cdr(rt, args);
+ total &= pit_value_as_integer(rt, pit_value_cons_car(rt, args));
+ args = pit_value_cons_cdr(rt, args);
}
- return pit_integer_new(rt, total);
+ return pit_value_integer_new(rt, total);
}
static pit_value impl_bitwise_or(pit_runtime *rt, pit_value args, void *data) {
(void) data;
i64 total = 0;
while (args != PIT_NIL) {
- total |= pit_as_integer(rt, pit_car(rt, args));
- args = pit_cdr(rt, args);
+ total |= pit_value_as_integer(rt, pit_value_cons_car(rt, args));
+ args = pit_value_cons_cdr(rt, args);
}
- return pit_integer_new(rt, total);
+ return pit_value_integer_new(rt, total);
}
static pit_value impl_bitwise_xor(pit_runtime *rt, pit_value args, void *data) {
(void) data;
i64 total = 0;
while (args != PIT_NIL) {
- total ^= pit_as_integer(rt, pit_car(rt, args));
- args = pit_cdr(rt, args);
+ total ^= pit_value_as_integer(rt, pit_value_cons_car(rt, args));
+ args = pit_value_cons_cdr(rt, args);
}
- return pit_integer_new(rt, total);
+ return pit_value_integer_new(rt, total);
}
static pit_value impl_bitwise_not(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- i64 x = pit_as_integer(rt, pit_car(rt, args));
- return pit_integer_new(rt, ~x);
+ i64 x = pit_value_as_integer(rt, pit_value_cons_car(rt, args));
+ return pit_value_integer_new(rt, ~x);
}
static pit_value impl_bitwise_lshift(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- i64 val = pit_as_integer(rt, pit_car(rt, args));
- i64 shift = pit_as_integer(rt, pit_car(rt, pit_cdr(rt, args)));
- return pit_integer_new(rt, val << shift);
+ i64 val = pit_value_as_integer(rt, pit_value_cons_car(rt, args));
+ i64 shift = pit_value_as_integer(rt, pit_value_cons_car(rt, pit_value_cons_cdr(rt, args)));
+ return pit_value_integer_new(rt, val << shift);
}
static pit_value impl_bitwise_rshift(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- i64 val = pit_as_integer(rt, pit_car(rt, args));
- i64 shift = pit_as_integer(rt, pit_car(rt, pit_cdr(rt, args)));
+ i64 val = pit_value_as_integer(rt, pit_value_cons_car(rt, args));
+ i64 shift = pit_value_as_integer(rt, pit_value_cons_car(rt, pit_value_cons_cdr(rt, args)));
if (shift >= 64) val = 0;
else val >>= shift;
- return pit_integer_new(rt, val);
+ return pit_value_integer_new(rt, val);
}
void pit_install_library_essential(pit_runtime *rt) {
/* special forms */
- pit_sfset(rt, pit_intern_cstr(rt, "quote"), pit_nativefunc_new(rt, impl_sf_quote));
- pit_sfset(rt, pit_intern_cstr(rt, "if"), pit_nativefunc_new(rt, impl_sf_if));
- pit_sfset(rt, pit_intern_cstr(rt, "cond"), pit_nativefunc_new(rt, impl_sf_cond));
- pit_sfset(rt, pit_intern_cstr(rt, "progn"), pit_nativefunc_new(rt, impl_sf_progn));
- pit_sfset(rt, pit_intern_cstr(rt, "or"), pit_nativefunc_new(rt, impl_sf_or));
- pit_sfset(rt, pit_intern_cstr(rt, "lambda"), pit_nativefunc_new(rt, impl_sf_lambda));
+ pit_symtab_sfset(rt, pit_symtab_intern_cstr(rt, "quote"), pit_value_nativefunc_new(rt, impl_sf_quote));
+ pit_symtab_sfset(rt, pit_symtab_intern_cstr(rt, "if"), pit_value_nativefunc_new(rt, impl_sf_if));
+ pit_symtab_sfset(rt, pit_symtab_intern_cstr(rt, "cond"), pit_value_nativefunc_new(rt, impl_sf_cond));
+ pit_symtab_sfset(rt, pit_symtab_intern_cstr(rt, "progn"), pit_value_nativefunc_new(rt, impl_sf_progn));
+ pit_symtab_sfset(rt, pit_symtab_intern_cstr(rt, "or"), pit_value_nativefunc_new(rt, impl_sf_or));
+ pit_symtab_sfset(rt, pit_symtab_intern_cstr(rt, "lambda"), pit_value_nativefunc_new(rt, impl_sf_lambda));
/* macros */
- pit_mset(rt, pit_intern_cstr(rt, "defun!"), pit_nativefunc_new(rt, impl_m_defun));
- pit_mset(rt, pit_intern_cstr(rt, "defmacro!"), pit_nativefunc_new(rt, impl_m_defmacro));
- pit_mset(rt, pit_intern_cstr(rt, "defstruct!"), pit_nativefunc_new(rt, impl_m_defstruct));
- pit_mset(rt, pit_intern_cstr(rt, "let"), pit_nativefunc_new(rt, impl_m_let));
- pit_mset(rt, pit_intern_cstr(rt, "and"), pit_nativefunc_new(rt, impl_m_and));
- pit_mset(rt, pit_intern_cstr(rt, "setq!"), pit_nativefunc_new(rt, impl_m_setq));
- pit_mset(rt, pit_intern_cstr(rt, "case"), pit_nativefunc_new(rt, impl_m_case));
+ pit_symtab_mset(rt, pit_symtab_intern_cstr(rt, "defun!"), pit_value_nativefunc_new(rt, impl_m_defun));
+ pit_symtab_mset(rt, pit_symtab_intern_cstr(rt, "defmacro!"), pit_value_nativefunc_new(rt, impl_m_defmacro));
+ pit_symtab_mset(rt, pit_symtab_intern_cstr(rt, "defstruct!"), pit_value_nativefunc_new(rt, impl_m_defstruct));
+ pit_symtab_mset(rt, pit_symtab_intern_cstr(rt, "let"), pit_value_nativefunc_new(rt, impl_m_let));
+ pit_symtab_mset(rt, pit_symtab_intern_cstr(rt, "and"), pit_value_nativefunc_new(rt, impl_m_and));
+ pit_symtab_mset(rt, pit_symtab_intern_cstr(rt, "setq!"), pit_value_nativefunc_new(rt, impl_m_setq));
+ pit_symtab_mset(rt, pit_symtab_intern_cstr(rt, "case"), pit_value_nativefunc_new(rt, impl_m_case));
/* error */
- pit_fset(rt, pit_intern_cstr(rt, "error!"), pit_nativefunc_new(rt, impl_error));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "error!"), pit_value_nativefunc_new(rt, impl_error));
/* eval */
- pit_fset(rt, pit_intern_cstr(rt, "eval!"), pit_nativefunc_new(rt, impl_eval));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "eval!"), pit_value_nativefunc_new(rt, impl_eval));
/* predicates */
- pit_fset(rt, pit_intern_cstr(rt, "eq?"), pit_nativefunc_new(rt, impl_eq_p));
- pit_fset(rt, pit_intern_cstr(rt, "equal?"), pit_nativefunc_new(rt, impl_equal_p));
- pit_fset(rt, pit_intern_cstr(rt, "integer?"), pit_nativefunc_new(rt, impl_integer_p));
- pit_fset(rt, pit_intern_cstr(rt, "double?"), pit_nativefunc_new(rt, impl_double_p));
- pit_fset(rt, pit_intern_cstr(rt, "symbol?"), pit_nativefunc_new(rt, impl_symbol_p));
- pit_fset(rt, pit_intern_cstr(rt, "cons?"), pit_nativefunc_new(rt, impl_cons_p));
- pit_fset(rt, pit_intern_cstr(rt, "array?"), pit_nativefunc_new(rt, impl_array_p));
- pit_fset(rt, pit_intern_cstr(rt, "bytes?"), pit_nativefunc_new(rt, impl_bytes_p));
- pit_fset(rt, pit_intern_cstr(rt, "function?"), pit_nativefunc_new(rt, impl_function_p));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "eq?"), pit_value_nativefunc_new(rt, impl_eq_p));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "equal?"), pit_value_nativefunc_new(rt, impl_equal_p));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "integer?"), pit_value_nativefunc_new(rt, impl_integer_p));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "double?"), pit_value_nativefunc_new(rt, impl_double_p));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "symbol?"), pit_value_nativefunc_new(rt, impl_symbol_p));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "cons?"), pit_value_nativefunc_new(rt, impl_cons_p));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "array?"), pit_value_nativefunc_new(rt, impl_array_p));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "bytes?"), pit_value_nativefunc_new(rt, impl_bytes_p));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "function?"), pit_value_nativefunc_new(rt, impl_function_p));
/* symbols */
- pit_fset(rt, pit_intern_cstr(rt, "set!"), pit_nativefunc_new(rt, impl_set));
- pit_fset(rt, pit_intern_cstr(rt, "fset!"), pit_nativefunc_new(rt, impl_fset));
- pit_fset(rt, pit_intern_cstr(rt, "symbol-is-macro!"), pit_nativefunc_new(rt, impl_symbol_is_macro));
- pit_fset(rt, pit_intern_cstr(rt, "funcall"), pit_nativefunc_new(rt, impl_funcall));
- pit_fset(rt, pit_intern_cstr(rt, "apply"), pit_nativefunc_new(rt, impl_apply));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "set!"), pit_value_nativefunc_new(rt, impl_set));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "fset!"), pit_value_nativefunc_new(rt, impl_fset));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "symbol-is-macro!"), pit_value_nativefunc_new(rt, impl_symbol_mark_macro));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "funcall"), pit_value_nativefunc_new(rt, impl_funcall));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "apply"), pit_value_nativefunc_new(rt, impl_apply));
/* cons cells */
- pit_fset(rt, pit_intern_cstr(rt, "cons"), pit_nativefunc_new(rt, impl_cons));
- pit_fset(rt, pit_intern_cstr(rt, "car"), pit_nativefunc_new(rt, impl_car));
- pit_fset(rt, pit_intern_cstr(rt, "cdr"), pit_nativefunc_new(rt, impl_cdr));
- pit_fset(rt, pit_intern_cstr(rt, "setcar!"), pit_nativefunc_new(rt, impl_setcar));
- pit_fset(rt, pit_intern_cstr(rt, "setcdr!"), pit_nativefunc_new(rt, impl_setcdr));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "cons"), pit_value_nativefunc_new(rt, impl_cons));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "car"), pit_value_nativefunc_new(rt, impl_car));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "cdr"), pit_value_nativefunc_new(rt, impl_cdr));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "setcar!"), pit_value_nativefunc_new(rt, impl_setcar));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "setcdr!"), pit_value_nativefunc_new(rt, impl_setcdr));
/* cons lists*/
- pit_fset(rt, pit_intern_cstr(rt, "list"), pit_nativefunc_new(rt, impl_list));
- pit_fset(rt, pit_intern_cstr(rt, "list/nth"), pit_nativefunc_new(rt, impl_list_nth));
- pit_fset(rt, pit_intern_cstr(rt, "list/iota"), pit_nativefunc_new(rt, impl_list_iota));
- pit_fset(rt, pit_intern_cstr(rt, "list/len"), pit_nativefunc_new(rt, impl_list_len));
- pit_fset(rt, pit_intern_cstr(rt, "list/reverse"), pit_nativefunc_new(rt, impl_list_reverse));
- pit_fset(rt, pit_intern_cstr(rt, "list/uniq"), pit_nativefunc_new(rt, impl_list_uniq));
- pit_fset(rt, pit_intern_cstr(rt, "list/append"), pit_nativefunc_new(rt, impl_list_append));
- pit_fset(rt, pit_intern_cstr(rt, "list/concat"), pit_nativefunc_new(rt, impl_list_concat));
- pit_fset(rt, pit_intern_cstr(rt, "list/take"), pit_nativefunc_new(rt, impl_list_take));
- pit_fset(rt, pit_intern_cstr(rt, "list/drop"), pit_nativefunc_new(rt, impl_list_drop));
- pit_fset(rt, pit_intern_cstr(rt, "list/map"), pit_nativefunc_new(rt, impl_list_map));
- pit_fset(rt, pit_intern_cstr(rt, "list/foldl"), pit_nativefunc_new(rt, impl_list_foldl));
- pit_fset(rt, pit_intern_cstr(rt, "list/filter"), pit_nativefunc_new(rt, impl_list_filter));
- pit_fset(rt, pit_intern_cstr(rt, "list/find"), pit_nativefunc_new(rt, impl_list_find));
- pit_fset(rt, pit_intern_cstr(rt, "list/contains?"), pit_nativefunc_new(rt, impl_list_contains_p));
- pit_fset(rt, pit_intern_cstr(rt, "list/all?"), pit_nativefunc_new(rt, impl_list_all_p));
- pit_fset(rt, pit_intern_cstr(rt, "list/zip-with"), pit_nativefunc_new(rt, impl_list_zip_with));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "list"), pit_value_nativefunc_new(rt, impl_list));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "list/nth"), pit_value_nativefunc_new(rt, impl_list_nth));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "list/iota"), pit_value_nativefunc_new(rt, impl_list_iota));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "list/len"), pit_value_nativefunc_new(rt, impl_list_len));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "list/reverse"), pit_value_nativefunc_new(rt, impl_list_reverse));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "list/uniq"), pit_value_nativefunc_new(rt, impl_list_uniq));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "list/append"), pit_value_nativefunc_new(rt, impl_list_append));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "list/concat"), pit_value_nativefunc_new(rt, impl_list_concat));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "list/take"), pit_value_nativefunc_new(rt, impl_list_take));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "list/drop"), pit_value_nativefunc_new(rt, impl_list_drop));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "list/map"), pit_value_nativefunc_new(rt, impl_list_map));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "list/foldl"), pit_value_nativefunc_new(rt, impl_list_foldl));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "list/filter"), pit_value_nativefunc_new(rt, impl_list_filter));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "list/find"), pit_value_nativefunc_new(rt, impl_list_find));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "list/contains?"), pit_value_nativefunc_new(rt, impl_list_contains_p));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "list/all?"), pit_value_nativefunc_new(rt, impl_list_all_p));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "list/zip-with"), pit_value_nativefunc_new(rt, impl_list_zip_with));
/* bytestrings */
- pit_fset(rt, pit_intern_cstr(rt, "bytes/len"), pit_nativefunc_new(rt, impl_bytes_len));
- pit_fset(rt, pit_intern_cstr(rt, "bytes/range"), pit_nativefunc_new(rt, impl_bytes_range));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "bytes/len"), pit_value_nativefunc_new(rt, impl_bytes_len));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "bytes/range"), pit_value_nativefunc_new(rt, impl_bytes_range));
/* array */
- pit_fset(rt, pit_intern_cstr(rt, "array"), pit_nativefunc_new(rt, impl_array));
- pit_fset(rt, pit_intern_cstr(rt, "array/to-list"), pit_nativefunc_new(rt, impl_array_to_list));
- pit_fset(rt, pit_intern_cstr(rt, "array/from-list"), pit_nativefunc_new(rt, impl_array_from_list));
- pit_fset(rt, pit_intern_cstr(rt, "array/repeat"), pit_nativefunc_new(rt, impl_array_repeat));
- pit_fset(rt, pit_intern_cstr(rt, "array/len"), pit_nativefunc_new(rt, impl_array_len));
- pit_fset(rt, pit_intern_cstr(rt, "array/get"), pit_nativefunc_new(rt, impl_array_get));
- pit_fset(rt, pit_intern_cstr(rt, "array/set!"), pit_nativefunc_new(rt, impl_array_set));
- pit_fset(rt, pit_intern_cstr(rt, "array/map"), pit_nativefunc_new(rt, impl_array_map));
- pit_fset(rt, pit_intern_cstr(rt, "array/map!"), pit_nativefunc_new(rt, impl_array_map_mut));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "array"), pit_value_nativefunc_new(rt, impl_array));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "array/to-list"), pit_value_nativefunc_new(rt, impl_array_to_list));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "array/from-list"), pit_value_nativefunc_new(rt, impl_array_from_list));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "array/repeat"), pit_value_nativefunc_new(rt, impl_array_repeat));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "array/len"), pit_value_nativefunc_new(rt, impl_array_len));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "array/get"), pit_value_nativefunc_new(rt, impl_array_get));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "array/set!"), pit_value_nativefunc_new(rt, impl_array_set));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "array/map"), pit_value_nativefunc_new(rt, impl_array_map));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "array/map!"), pit_value_nativefunc_new(rt, impl_array_map_mut));
/* arithmetic */
- pit_fset(rt, pit_intern_cstr(rt, "abs"), pit_nativefunc_new(rt, impl_abs));
- pit_fset(rt, pit_intern_cstr(rt, "+"), pit_nativefunc_new(rt, impl_add));
- pit_fset(rt, pit_intern_cstr(rt, "-"), pit_nativefunc_new(rt, impl_sub));
- pit_fset(rt, pit_intern_cstr(rt, "*"), pit_nativefunc_new(rt, impl_mul));
- pit_fset(rt, pit_intern_cstr(rt, "/"), pit_nativefunc_new(rt, impl_div));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "abs"), pit_value_nativefunc_new(rt, impl_abs));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "+"), pit_value_nativefunc_new(rt, impl_add));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "-"), pit_value_nativefunc_new(rt, impl_sub));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "*"), pit_value_nativefunc_new(rt, impl_mul));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "/"), pit_value_nativefunc_new(rt, impl_div));
/* booleans */
- pit_fset(rt, pit_intern_cstr(rt, "not"), pit_nativefunc_new(rt, impl_not));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "not"), pit_value_nativefunc_new(rt, impl_not));
/* comparisons */
- pit_fset(rt, pit_intern_cstr(rt, "<"), pit_nativefunc_new(rt, impl_lt));
- pit_fset(rt, pit_intern_cstr(rt, ">"), pit_nativefunc_new(rt, impl_gt));
- pit_fset(rt, pit_intern_cstr(rt, "<="), pit_nativefunc_new(rt, impl_le));
- pit_fset(rt, pit_intern_cstr(rt, ">="), pit_nativefunc_new(rt, impl_ge));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "<"), pit_value_nativefunc_new(rt, impl_lt));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, ">"), pit_value_nativefunc_new(rt, impl_gt));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "<="), pit_value_nativefunc_new(rt, impl_le));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, ">="), pit_value_nativefunc_new(rt, impl_ge));
/* bitwise arithmetic */
- pit_fset(rt, pit_intern_cstr(rt, "bitwise/and"), pit_nativefunc_new(rt, impl_bitwise_and));
- pit_fset(rt, pit_intern_cstr(rt, "bitwise/or"), pit_nativefunc_new(rt, impl_bitwise_or));
- pit_fset(rt, pit_intern_cstr(rt, "bitwise/xor"), pit_nativefunc_new(rt, impl_bitwise_xor));
- pit_fset(rt, pit_intern_cstr(rt, "bitwise/not"), pit_nativefunc_new(rt, impl_bitwise_not));
- pit_fset(rt, pit_intern_cstr(rt, "bitwise/lshift"), pit_nativefunc_new(rt, impl_bitwise_lshift));
- pit_fset(rt, pit_intern_cstr(rt, "bitwise/rshift"), pit_nativefunc_new(rt, impl_bitwise_rshift));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "bitwise/and"), pit_value_nativefunc_new(rt, impl_bitwise_and));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "bitwise/or"), pit_value_nativefunc_new(rt, impl_bitwise_or));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "bitwise/xor"), pit_value_nativefunc_new(rt, impl_bitwise_xor));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "bitwise/not"), pit_value_nativefunc_new(rt, impl_bitwise_not));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "bitwise/lshift"), pit_value_nativefunc_new(rt, impl_bitwise_lshift));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "bitwise/rshift"), pit_value_nativefunc_new(rt, impl_bitwise_rshift));
}
static pit_value impl_plist_get(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- pit_value k = pit_car(rt, args);
- pit_value vs = pit_car(rt, pit_cdr(rt, args));
- return pit_plist_get(rt, k, vs);
+ pit_value k = pit_value_cons_car(rt, args);
+ pit_value vs = pit_value_cons_car(rt, pit_value_cons_cdr(rt, args));
+ return pit_value_list_plist_get(rt, k, vs);
}
void pit_install_library_plist(pit_runtime *rt) {
/* property lists / keyword arguments */
- pit_fset(rt, pit_intern_cstr(rt, "plist/get"), pit_nativefunc_new(rt, impl_plist_get));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "plist/get"), pit_value_nativefunc_new(rt, impl_plist_get));
}
static pit_value impl_alist_get(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- pit_value k = pit_car(rt, args);
- pit_value vs = pit_car(rt, pit_cdr(rt, args));
+ pit_value k = pit_value_cons_car(rt, args);
+ pit_value vs = pit_value_cons_car(rt, pit_value_cons_cdr(rt, args));
while (vs != PIT_NIL) {
- pit_value v = pit_car(rt, vs);
- if (pit_equal(rt, k, pit_car(rt, v))) {
- return pit_cdr(rt, v);
+ pit_value v = pit_value_cons_car(rt, vs);
+ if (pit_value_equal(rt, k, pit_value_cons_car(rt, v))) {
+ return pit_value_cons_cdr(rt, v);
}
- vs = pit_cdr(rt, vs);
+ vs = pit_value_cons_cdr(rt, vs);
}
return PIT_NIL;
}
void pit_install_library_alist(pit_runtime *rt) {
/* association lists */
- pit_fset(rt, pit_intern_cstr(rt, "alist/get"), pit_nativefunc_new(rt, impl_alist_get));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "alist/get"), pit_value_nativefunc_new(rt, impl_alist_get));
}
diff --git a/src/main.c b/src/main.c
index 7517763..157ad87 100644
--- a/src/main.c
+++ b/src/main.c
@@ -20,6 +20,5 @@ int main(int argc, char **argv) {
pit_repl(rt);
} else {
pit_load_file(rt, argv[1]);
- if (pit_runtime_print_error(rt)) return -1;
}
}
diff --git a/src/native.c b/src/native.c
index 7af961b..fbf8efc 100644
--- a/src/native.c
+++ b/src/native.c
@@ -24,24 +24,28 @@ i64 pit_lex_file(pit_lexer *ret, char *path) {
}
bool pit_runtime_print_error(pit_runtime *rt) {
- if (!pit_eq(rt->error, PIT_NIL)) {
+ if (!pit_value_eq(rt->error, PIT_NIL)) {
char buf[1024] = {0};
- i64 end = pit_dump(rt, buf, sizeof(buf) - 1, rt->error, false);
- buf[end] = 0;
+ for (i64 i = 0; i < rt->backtrace->next; ++i) {
+ pit_annotated_ref *a = pit_vec_get(pit_annotated_ref)(rt->backtrace, i);
+ if (a == NULL) continue;
+ fprintf(stderr, "on line %ld, column %ld\n", a->annotation.line, a->annotation.column);
+ }
+ i64 end = pit_dump(rt, buf, sizeof(buf) - 1, rt->error, false); buf[end] = 0;
fprintf(stderr, "error at line %ld, column %ld: %s\n", rt->error_line, rt->error_column, buf);
return true;
}
return false;
}
-void pit_trace_(pit_runtime *rt, char *format, pit_value v) {
+void pit_debug_trace_(pit_runtime *rt, char *format, pit_value v) {
char buf[1024] = {0};
i64 end = pit_dump(rt, buf, sizeof(buf) - 1, v, true);
buf[end] = 0;
fprintf(stderr, format, buf);
}
-pit_value pit_bytes_new_file(pit_runtime *rt, char *path) {
+pit_value pit_value_bytes_new_file(pit_runtime *rt, char *path) {
if (rt->error != PIT_NIL) return PIT_NIL;
FILE *f = fopen(path, "r");
if (f == NULL) {
@@ -59,8 +63,8 @@ pit_value pit_bytes_new_file(pit_runtime *rt, char *path) {
return PIT_NIL;
}
fclose(f);
- pit_value ret = pit_heavy_new(rt);
- pit_value_heavy *h = pit_deref(rt, pit_as_ref(rt, ret));
+ pit_value ret = pit_value_ref_heavy_new(rt);
+ pit_value_heavy *h = pit_value_ref_deref(rt, pit_value_as_ref(rt, ret));
if (!h) { pit_error(rt, "failed to create new heavy value for bytes"); return PIT_NIL; }
h->hsort = PIT_VALUE_HEAVY_SORT_BYTES;
h->in.bytes.data = dest;
@@ -69,11 +73,14 @@ pit_value pit_bytes_new_file(pit_runtime *rt, char *path) {
}
static void check_invariants(pit_runtime *rt) {
- if (rt->scratch->next != 0) {
- pit_error(rt, "leaked scratch memory! %ld", rt->scratch->next);
+ if (rt->expr_stack->next != 0) {
+ pit_error(rt, "leaked expr_stack memory! %ld", rt->expr_stack->next);
+ }
+ if (rt->result_stack->next != 0) {
+ pit_error(rt, "leaked result_stack memory! %ld", rt->result_stack->next);
}
- if (rt->scratch->next != 0) {
- pit_error(rt, "leaked scratch memory! %ld", rt->scratch->next);
+ if (rt->program->next != 0) {
+ pit_error(rt, "leaked program memory! %ld", rt->program->next);
}
}
pit_value pit_load_file(pit_runtime *rt, char *path) {
@@ -91,7 +98,7 @@ pit_value pit_load_file(pit_runtime *rt, char *path) {
check_invariants(rt); if (pit_runtime_print_error(rt)) return PIT_NIL;
ret = pit_eval(rt, p);
check_invariants(rt); if (pit_runtime_print_error(rt)) return PIT_NIL;
- pit_collect_garbage(rt);
+ pit_gc(rt);
check_invariants(rt); if (pit_runtime_print_error(rt)) return PIT_NIL;
}
check_invariants(rt); if (pit_runtime_print_error(rt)) return PIT_NIL;
@@ -144,7 +151,7 @@ void pit_repl(pit_runtime *rt) {
} else {
char dumpbuf[1024] = {0};
pit_dump(rt, dumpbuf, sizeof(dumpbuf) - 1, res, true);
- pit_collect_garbage(rt);
+ pit_gc(rt);
printf("%s\n> ", dumpbuf);
}
len = 0;
@@ -165,7 +172,7 @@ static pit_value impl_diagnostics(pit_runtime *rt, pit_value args, void *data) {
}
static pit_value impl_print(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- pit_value x = pit_car(rt, args);
+ pit_value x = pit_value_cons_car(rt, args);
char buf[1024] = {0};
pit_dump(rt, buf, sizeof(buf), x, true);
buf[1023] = 0;
@@ -174,7 +181,7 @@ static pit_value impl_print(pit_runtime *rt, pit_value args, void *data) {
}
static pit_value impl_princ(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- pit_value x = pit_car(rt, args);
+ pit_value x = pit_value_cons_car(rt, args);
char buf[1024] = {0};
pit_dump(rt, buf, sizeof(buf), x, false);
buf[1023] = 0;
@@ -183,21 +190,21 @@ static pit_value impl_princ(pit_runtime *rt, pit_value args, void *data) {
}
static pit_value impl_load(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- pit_value path = pit_car(rt, args);
+ pit_value path = pit_value_cons_car(rt, args);
char pathbuf[1024] = {0};
- i64 len = pit_as_bytes(rt, path, (u8 *) pathbuf, sizeof(pathbuf) - 1);
+ i64 len = pit_value_bytes_copy(rt, path, (u8 *) pathbuf, sizeof(pathbuf) - 1);
if (len < 0) { pit_error(rt, "path was not a string"); return PIT_NIL; }
pathbuf[len] = 0;
return pit_load_file(rt, pathbuf);
}
void pit_install_library_io(pit_runtime *rt) {
/* diagnostics */
- pit_fset(rt, pit_intern_cstr(rt, "diagnostics!"), pit_nativefunc_new(rt, impl_diagnostics));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "diagnostics!"), pit_value_nativefunc_new(rt, impl_diagnostics));
/* stream IO */
- pit_fset(rt, pit_intern_cstr(rt, "print!"), pit_nativefunc_new(rt, impl_print));
- pit_fset(rt, pit_intern_cstr(rt, "princ!"), pit_nativefunc_new(rt, impl_princ));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "print!"), pit_value_nativefunc_new(rt, impl_print));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "princ!"), pit_value_nativefunc_new(rt, impl_princ));
/* disk IO */
- pit_fset(rt, pit_intern_cstr(rt, "load!"), pit_nativefunc_new(rt, impl_load));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "load!"), pit_value_nativefunc_new(rt, impl_load));
}
struct bytestring {
@@ -212,18 +219,18 @@ static pit_value impl_bs_new(pit_runtime *rt, pit_value args, void *data) {
bs->len = 0;
bs->cap = cap;
bs->data = calloc((size_t) cap, 1);
- return pit_nativedata_new(rt, pit_intern_cstr(rt, "bs"), (void *) bs);
+ return pit_value_nativedata_new(rt, pit_symtab_intern_cstr(rt, "bs"), (void *) bs);
}
static pit_value impl_bs_delete(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- pit_value v = pit_car(rt, args);
- pit_value_heavy *h = pit_deref(rt, pit_as_ref(rt, v));
+ pit_value v = pit_value_cons_car(rt, args);
+ pit_value_heavy *h = pit_value_ref_deref(rt, pit_value_as_ref(rt, v));
if (!h) { pit_error(rt, "bad ref"); return PIT_NIL; }
if (h->hsort != PIT_VALUE_HEAVY_SORT_NATIVEDATA) {
pit_error(rt, "invalid use of value as bytestring nativedata");
return PIT_NIL;
}
- if (!pit_eq(h->in.nativedata.tag, pit_intern_cstr(rt, "bs"))) {
+ if (!pit_value_eq(h->in.nativedata.tag, pit_symtab_intern_cstr(rt, "bs"))) {
pit_error(rt, "native value is not a bytestring");
return PIT_NIL;
}
@@ -240,11 +247,11 @@ static pit_value impl_bs_delete(pit_runtime *rt, pit_value args, void *data) {
}
static pit_value impl_bs_grow(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- pit_value vsz = pit_car(rt, args);
- pit_value v = pit_car(rt, pit_cdr(rt, args));
- struct bytestring *bs = pit_nativedata_get(rt, pit_intern_cstr(rt, "bs"), v);
+ pit_value vsz = pit_value_cons_car(rt, args);
+ pit_value v = pit_value_cons_car(rt, pit_value_cons_cdr(rt, args));
+ struct bytestring *bs = pit_value_nativedata_get(rt, pit_symtab_intern_cstr(rt, "bs"), v);
if (!bs) return PIT_NIL;
- i64 sz = pit_as_integer(rt, vsz);
+ i64 sz = pit_value_as_integer(rt, vsz);
if (sz > bs->len) {
if (sz > bs->cap) {
while (bs->cap < sz) bs->cap <<= 1;
@@ -256,13 +263,13 @@ static pit_value impl_bs_grow(pit_runtime *rt, pit_value args, void *data) {
}
static pit_value impl_bs_spit(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- pit_value path = pit_car(rt, args);
+ pit_value path = pit_value_cons_car(rt, args);
char pathbuf[1024] = {0};
- i64 len = pit_as_bytes(rt, path, (u8 *) pathbuf, sizeof(pathbuf) - 1);
+ i64 len = pit_value_bytes_copy(rt, path, (u8 *) pathbuf, sizeof(pathbuf) - 1);
if (len < 0) { pit_error(rt, "path was not a string"); return PIT_NIL; }
pathbuf[len] = 0;
- pit_value v = pit_car(rt, pit_cdr(rt, args));
- struct bytestring *bs = pit_nativedata_get(rt, pit_intern_cstr(rt, "bs"), v);
+ pit_value v = pit_value_cons_car(rt, pit_value_cons_cdr(rt, args));
+ struct bytestring *bs = pit_value_nativedata_get(rt, pit_symtab_intern_cstr(rt, "bs"), v);
if (!bs) return PIT_NIL;
FILE *f = fopen(pathbuf, "w+");
if (!f) { pit_error(rt, "failed to open file: %s", pathbuf); return PIT_NIL; }
@@ -276,13 +283,13 @@ static pit_value impl_bs_spit(pit_runtime *rt, pit_value args, void *data) {
}
static pit_value impl_bs_write8(pit_runtime *rt, pit_value args, void *data) {
(void) data;
- pit_value v = pit_car(rt, args);
- pit_value vidx = pit_car(rt, pit_cdr(rt, args));
- pit_value vx = pit_car(rt, pit_cdr(rt, pit_cdr(rt, args)));
- struct bytestring *bs = pit_nativedata_get(rt, pit_intern_cstr(rt, "bs"), v);
+ pit_value v = pit_value_cons_car(rt, args);
+ pit_value vidx = pit_value_cons_car(rt, pit_value_cons_cdr(rt, args));
+ pit_value vx = pit_value_cons_car(rt, pit_value_cons_cdr(rt, pit_value_cons_cdr(rt, args)));
+ struct bytestring *bs = pit_value_nativedata_get(rt, pit_symtab_intern_cstr(rt, "bs"), v);
if (!bs) return PIT_NIL;
- i64 idx = pit_as_integer(rt, vidx);
- u8 x = (u8) pit_as_integer(rt, vx);
+ i64 idx = pit_value_as_integer(rt, vidx);
+ u8 x = (u8) pit_value_as_integer(rt, vx);
if (idx >= bs->len) {
pit_error(rt, "index %d out of bounds in bytestring (length %d)", idx, bs->len);
return PIT_NIL;
@@ -292,9 +299,9 @@ static pit_value impl_bs_write8(pit_runtime *rt, pit_value args, void *data) {
}
void pit_install_library_bytestring(pit_runtime *rt) {
/* bytestrings */
- pit_fset(rt, pit_intern_cstr(rt, "bs/new!"), pit_nativefunc_new(rt, impl_bs_new));
- pit_fset(rt, pit_intern_cstr(rt, "bs/delete!"), pit_nativefunc_new(rt, impl_bs_delete));
- pit_fset(rt, pit_intern_cstr(rt, "bs/grow!"), pit_nativefunc_new(rt, impl_bs_grow));
- pit_fset(rt, pit_intern_cstr(rt, "bs/spit!"), pit_nativefunc_new(rt, impl_bs_spit));
- pit_fset(rt, pit_intern_cstr(rt, "bs/write8!"), pit_nativefunc_new(rt, impl_bs_write8));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "bs/new!"), pit_value_nativefunc_new(rt, impl_bs_new));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "bs/delete!"), pit_value_nativefunc_new(rt, impl_bs_delete));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "bs/grow!"), pit_value_nativefunc_new(rt, impl_bs_grow));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "bs/spit!"), pit_value_nativefunc_new(rt, impl_bs_spit));
+ pit_symtab_fset(rt, pit_symtab_intern_cstr(rt, "bs/write8!"), pit_value_nativefunc_new(rt, impl_bs_write8));
}
diff --git a/src/parser.c b/src/parser.c
index 9ce0c60..0f9b167 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -4,8 +4,6 @@
#include <lcq/pit/parser.h>
#include <lcq/pit/runtime.h>
-#include <stdio.h>
-
static pit_lex_token peek(pit_parser *st) {
if (!st) return PIT_LEX_TOKEN_ERROR;
return st->next.token;
@@ -76,12 +74,6 @@ pit_value pit_parse(pit_runtime *rt, pit_parser *st, bool *eof) {
}
return PIT_NIL;
case PIT_LEX_TOKEN_LPAREN: {
- /* to construct a cons-list, we need the arguments "backwards"
- we could reverse or build up a temporary list
- (or use non-tail recursion, which is basically the temporary list on the stack)
- we choose to build a temporary list on the scratch arena
- */
- i64 scratch_reset = rt->scratch->next;
pit_value ret = PIT_NIL;
while (!match(st, PIT_LEX_TOKEN_RPAREN)) {
if (match(st, PIT_LEX_TOKEN_DOT)) {
@@ -93,49 +85,44 @@ pit_value pit_parse(pit_runtime *rt, pit_parser *st, bool *eof) {
return PIT_NIL;
}
} else {
- pit_value *cell = pit_arena_alloc_array(rt->scratch, sizeof(pit_value));
- *cell = pit_parse(rt, st, eof);
+ ret = pit_value_cons(rt, pit_parse(rt, st, eof), ret);
}
if (rt->error != PIT_NIL || (eof != NULL && *eof)) {
pit_error(rt, "unterminated list");
return PIT_NIL; /* if we hit an error, stop!*/
}
}
- for (i64 i = rt->scratch->next - (i64) sizeof(pit_value);
- i >= scratch_reset;
- i -= (i64) sizeof(pit_value)
- ) {
- pit_value *v = pit_arena_get(rt->scratch, (i32) i);
- ret = pit_cons(rt, *v, ret);
- }
- rt->scratch->next = scratch_reset;
+ ret = pit_value_list_reverse(rt, ret);
if (pit_value_sort(ret) == PIT_VALUE_SORT_REF) {
- fprintf(stderr, "adding annotation (%ld): ", pit_as_ref(rt, ret));
- pit_trace_(rt, "%s\n", ret);
- pit_expr_annotations_push(rt->annotations,
- pit_as_ref(rt, ret),
- rt->source_line, rt->source_column
- );
+ pit_annotation a = {0};
+ a.line = rt->source_line;
+ a.column = rt->source_column;
+ pit_annotation_set(rt, pit_value_as_ref(rt, ret), a);
}
return ret;
}
case PIT_LEX_TOKEN_LSQUARE: {
- i64 scratch_reset = rt->scratch->next;
+ pit_value ret = PIT_NIL;
+ pit_value xs = PIT_NIL;
i64 len = 0;
while (!match(st, PIT_LEX_TOKEN_RSQUARE)) {
- pit_value *cell = pit_arena_alloc_array(rt->scratch, sizeof(pit_value));
- *cell = pit_parse(rt, st, eof);
+ pit_value x = pit_parse(rt, st, eof);
+ xs = pit_value_cons(rt, x, xs);
len += 1;
if (rt->error != PIT_NIL || (eof != NULL && *eof)) {
pit_error(rt, "unterminated array literal");
return PIT_NIL;
}
}
- rt->scratch->next = scratch_reset;
- return pit_array_from_buf(rt, pit_arena_get(rt->scratch, (i32) scratch_reset), len);
+ ret = pit_value_array_new(rt, len);
+ while (xs != PIT_NIL) {
+ pit_value_array_set(rt, ret, --len, pit_value_cons_car(rt, xs));
+ xs = pit_value_cons_cdr(rt, xs);
+ }
+ return ret;
}
case PIT_LEX_TOKEN_QUOTE:
- return pit_list(rt, 2, pit_intern_cstr(rt, "quote"), pit_parse(rt, st, eof));
+ return pit_value_list(rt, 2, pit_symtab_intern_cstr(rt, "quote"), pit_parse(rt, st, eof));
case PIT_LEX_TOKEN_INTEGER_LITERAL: {
i64 idx = st->cur.start;
i64 base = 10;
@@ -165,7 +152,7 @@ pit_value pit_parse(pit_runtime *rt, pit_parser *st, bool *eof) {
pit_error(rt, "integer literal too large"); return PIT_NIL;
}
}
- return pit_integer_new(rt, neg ? -total : total);
+ return pit_value_integer_new(rt, neg ? -total : total);
}
case PIT_LEX_TOKEN_STRING_LITERAL: {
char buf[256] = {0};
@@ -177,12 +164,12 @@ pit_value pit_parse(pit_runtime *rt, pit_parser *st, bool *eof) {
else if (buf[i] != '"') buf[cur++] = buf[i];
else break;
}
- return pit_bytes_new(rt, (u8 *) buf, cur);
+ return pit_value_bytes_new(rt, (u8 *) buf, cur);
}
case PIT_LEX_TOKEN_SYMBOL: {
char buf[256] = {0};
get_token_string(st, buf, sizeof(buf));
- return pit_intern_cstr(rt, buf);
+ return pit_symtab_intern_cstr(rt, buf);
}
default:
pit_error(rt, "unexpected token: %s", pit_lex_token_name(t));
diff --git a/src/runtime.c b/src/runtime.c
index f961c19..a8428c7 100644
--- a/src/runtime.c
+++ b/src/runtime.c
@@ -4,8 +4,6 @@
#include <lcq/pit/runtime.h>
#include <lcq/pit/library.h>
-#include <stdio.h>
-
enum pit_value_sort pit_value_sort(pit_value v) {
/* if this isn't a NaN, or it's a quiet NaN, this is a real double */
/* if (((v >> 52) & 0b011111111111) != 0b011111111111 || ((v >> 51) & 0b1) == 1) return PIT_VALUE_SORT_DOUBLE; */
@@ -30,15 +28,12 @@ pit_runtime *pit_runtime_new(u8 *buf, i64 len) {
i64 heap_size = len / 4;
i64 annotations_size = len / 32;
i64 symtab_size = len / 16;
- i64 scratch_size = len / 32;
i64 stack_size = len / 32;
ret->heap = pit_arena_new(pit_arena_alloc_back(a, heap_size), heap_size, sizeof(pit_value_heavy));
ret->backbuffer = pit_arena_new(pit_arena_alloc_back(a, heap_size), heap_size, sizeof(pit_value_heavy));
- ret->annotations = pit_expr_annotations_new(pit_arena_alloc_back(a, annotations_size), annotations_size);
- ret->annotations_backbuffer = pit_expr_annotations_new(pit_arena_alloc_back(a, annotations_size), annotations_size);
- ret->symtab = pit_arena_new(pit_arena_alloc_back(a, symtab_size), symtab_size, sizeof(pit_symtab_entry));
- ret->symtab_len = 0;
- ret->scratch = pit_arena_new(pit_arena_alloc_back(a, scratch_size), scratch_size, sizeof(u8));
+ ret->annotations = pit_vec_new(pit_annotated_ref)(pit_arena_alloc_back(a, annotations_size), annotations_size);
+ ret->backtrace = pit_vec_new(pit_annotated_ref)(pit_arena_alloc_back(a, annotations_size), annotations_size);
+ ret->symtab = pit_vec_new(pit_symtab_entry)(pit_arena_alloc_back(a, symtab_size), symtab_size);
ret->expr_stack = pit_vec_new(pit_value)(pit_arena_alloc_back(a, stack_size), stack_size);
ret->result_stack = pit_vec_new(pit_value)(pit_arena_alloc_back(a, stack_size), stack_size);
ret->program = pit_vec_new(pit_runtime_eval_ins)(pit_arena_alloc_back(a, stack_size), stack_size);
@@ -48,10 +43,10 @@ pit_runtime *pit_runtime_new(u8 *buf, i64 len) {
ret->error = PIT_NIL;
ret->source_line = ret->source_column = -1;
ret->error_line = ret->error_column = -1;
- pit_value nil = pit_intern_cstr(ret, "nil"); /* nil must be the 0th symbol for PIT_NIL to work */
- pit_set(ret, nil, PIT_NIL);
- pit_value truth = pit_intern_cstr(ret, "t");
- pit_set(ret, truth, truth);
+ pit_value nil = pit_symtab_intern_cstr(ret, "nil"); /* nil must be the 0th symbol for PIT_NIL to work */
+ pit_symtab_set(ret, nil, PIT_NIL);
+ pit_value truth = pit_symtab_intern_cstr(ret, "t");
+ pit_symtab_set(ret, truth, truth);
pit_runtime_freeze(ret);
return ret;
}
@@ -65,106 +60,7 @@ void pit_runtime_reset(pit_runtime *rt) {
rt->symtab->next = rt->frozen_symtab;
}
-#define CHECK_BUF if (buf >= end) { return buf - start; }
-#define CHECK_BUF_LABEL(label) if (buf >= end) { goto label; }
-i64 pit_dump(pit_runtime *rt, char *buf, i64 len, pit_value v, bool readable) {
- pit_value_heavy *h = NULL;
- if (len <= 0) return 0;
- switch (pit_value_sort(v)) {
- case PIT_VALUE_SORT_DOUBLE:
- #ifndef PIT_NO_DOUBLE
- return pit_libc_string_snprintf(buf, (size_t) len, "%lf", pit_as_double(rt, v));
- #else
- return pit_string_snprintf(buf, (size_t) len, "<unsupported double>");
- #endif
- case PIT_VALUE_SORT_INTEGER:
- return pit_libc_string_snprintf(buf, (size_t) len, "%ld", pit_as_integer(rt, v));
- case PIT_VALUE_SORT_SYMBOL: {
- pit_symtab_entry *ent = pit_symtab_lookup(rt, v);
- if (ent
- && pit_value_sort(ent->name) == PIT_VALUE_SORT_REF
- && (h = pit_deref(rt, pit_as_ref(rt, ent->name)))
- ) {
- i64 i = 0;
- for (; i < h->in.bytes.len && i < len - 1; ++i) {
- buf[i] = (char) h->in.bytes.data[i];
- }
- return i;
- } else {
- return pit_libc_string_snprintf(buf, (size_t) len, "<broken symbol %ld>", pit_as_symbol(rt, v));
- }
- }
- case PIT_VALUE_SORT_REF: {
- pit_ref r = pit_as_ref(rt, v);
- char *end = buf + len;
- char *start = buf;
- h = pit_deref(rt, r);
- if (!h) pit_libc_string_snprintf(buf, (size_t) len, "<ref %ld>", r);
- else {
- switch (h->hsort) {
- case PIT_VALUE_HEAVY_SORT_CELL: {
- CHECK_BUF; *(buf++) = '{';
- CHECK_BUF; buf += pit_dump(rt, buf, end - buf, pit_car(rt, h->in.cell), readable);
- CHECK_BUF; *(buf++) = '}';
- return buf - start;
- }
- case PIT_VALUE_HEAVY_SORT_CONS: {
- pit_value cur = v;
- CHECK_BUF_LABEL(list_end);
- do {
- if (pit_is_cons(rt, cur)) {
- CHECK_BUF_LABEL(list_end); *(buf++) = ' ';
- CHECK_BUF_LABEL(list_end); buf += pit_dump(rt, buf, end - buf, pit_car(rt, cur), readable);
- } else {
- CHECK_BUF_LABEL(list_end); buf += pit_libc_string_snprintf(buf, (size_t) (end - buf), " . ");
- CHECK_BUF_LABEL(list_end); buf += pit_dump(rt, buf, end - buf, cur, readable);
- }
- } while (!pit_eq((cur = pit_cdr(rt, cur)), PIT_NIL));
- CHECK_BUF_LABEL(list_end); *(buf++) = ')';
- list_end:
- *start = '(';
- return buf - start;
- }
- case PIT_VALUE_HEAVY_SORT_ARRAY: {
- i64 i = 0;
- CHECK_BUF_LABEL(array_end);
- if (h->in.array.len == 0) {
- CHECK_BUF_LABEL(array_end); *(buf++) = '[';
- } else for (; i < h->in.array.len; ++i) {
- CHECK_BUF_LABEL(array_end); *(buf++) = ' ';
- CHECK_BUF_LABEL(array_end); buf += pit_dump(rt, buf, end - buf, h->in.array.data[i], readable);
- }
- CHECK_BUF_LABEL(array_end); *(buf++) = ']';
- array_end:
- *start = '[';
- return buf - start;
- }
- case PIT_VALUE_HEAVY_SORT_BYTES: {
- i64 i = 0;
- if (readable) { CHECK_BUF; buf[i++] = '"'; }
- i64 maxlen = len - i;
- for (i64 j = 0; i < maxlen && j < h->in.bytes.len;) {
- if (buf[i - 1] != '\\' && (h->in.bytes.data[j] == '\\' || h->in.bytes.data[j] == '"')) {
- CHECK_BUF; buf[i++] = '\\';
- }
- else {
- CHECK_BUF; buf[i++] = (char) h->in.bytes.data[j++];
- }
- }
- if (readable && i < len - 1) buf[i++] = '"';
- return i;
- }
- default:
- return pit_libc_string_snprintf(buf, (size_t) len, "<ref %ld>", r);
- }
- }
- break;
- }
- }
- return 0;
-}
-
-pit_value pit_get_error(pit_runtime *rt) {
+pit_value pit_error_get(pit_runtime *rt) {
pit_value ret = rt->error;
rt->error = PIT_NIL;
return ret;
@@ -178,753 +74,29 @@ void pit_error(pit_runtime *rt, char *format, ...) {
pit_libc_string_snprintf(buf, sizeof(buf), format, vargs);
va_end(vargs);
rt->error = PIT_T; /* we set the error now to prevent infinite recursion */
- rt->error = pit_bytes_new_cstr(rt, buf); /* in case this errs also */
+ rt->error = pit_value_bytes_new_cstr(rt, buf); /* in case this errs also */
if (rt->error == PIT_NIL) rt->error = PIT_T;
rt->error_line = rt->source_line;
rt->error_column = rt->source_column;
}
}
-pit_value pit_value_new(pit_runtime *rt, enum pit_value_sort s, u64 data) {
- if (s == PIT_VALUE_SORT_DOUBLE) {
- /* if (((data >> 52) & 0b011111111111) == 0b011111111111 && ((data >> 51) & 0b1) == 0) { */
- if (((data >> 52) & 0x7ff) == 0x7ff && ((data >> 51) & 1) == 0) {
- pit_error(rt, "attempted to create a signalling NaN double");
- return PIT_NIL;
- }
- return data;
- }
- return
- /* 0b1111111111110000000000000000000000000000000000000000000000000000 */
- 0xfff0000000000000
- /* | (((u64) (s & 0b11)) << 49) */
- | (((u64) (s & 3)) << 49)
- /* | (data & 0b1111111111111111111111111111111111111111111111111); */
- | (data & 0x1ffffffffffff);
-}
-
-#ifndef PIT_NO_DOUBLE
-double pit_as_double(pit_runtime *rt, pit_value v) {
- if (pit_value_sort(v) != PIT_VALUE_SORT_DOUBLE) {
- pit_error(rt, "invalid use of value as double");
- return 0.0;
- }
- union { double dval; u64 ival; } x;
- x.ival = v;
- return x.dval;
-}
-pit_value pit_double_new(pit_runtime *rt, double d) {
- union { double dval; u64 ival; } x;
- x.dval = d;
- return pit_value_new(rt, PIT_VALUE_SORT_DOUBLE, x.ival);
-}
-#endif
-
-i64 pit_as_integer(pit_runtime *rt, pit_value v) {
- if (pit_value_sort(v) != PIT_VALUE_SORT_INTEGER) {
- pit_error(rt, "invalid use of value as integer");
- return -1;
- }
- u64 lo = pit_value_data(v);
- return ((i64) (lo << 15)) >> 15; /* sign-extend low 49 bits */
-
-}
-pit_value pit_integer_new(pit_runtime *rt, i64 i) {
- return pit_value_new(rt, PIT_VALUE_SORT_INTEGER, 0x1ffffffffffff & (u64) i);
-}
-pit_value pit_bool_new(pit_runtime *rt, bool i) {
- (void) rt;
- return i ? PIT_T : PIT_NIL;
-}
-
-pit_symbol pit_as_symbol(pit_runtime *rt, pit_value v) {
- if (pit_value_sort(v) != PIT_VALUE_SORT_SYMBOL) {
- pit_error(rt, "invalid use of value as symbol");
- return -1;
- }
- return (pit_symbol) (pit_value_data(v) & 0xffffffff);
-}
-pit_value pit_symbol_new(pit_runtime *rt, pit_symbol s) {
- return pit_value_new(rt, PIT_VALUE_SORT_SYMBOL, (u64) s);
-}
-
-pit_ref pit_as_ref(pit_runtime *rt, pit_value v) {
- if (pit_value_sort(v) != PIT_VALUE_SORT_REF) {
- pit_error(rt, "invalid use of value as ref");
- return -1;
- }
- return (pit_ref) (pit_value_data(v) & 0xffffffff);
-}
-pit_value pit_ref_new(pit_runtime *rt, pit_ref r) {
- return pit_value_new(rt, PIT_VALUE_SORT_REF, (u64) r);
-}
-
-pit_value pit_heavy_new(pit_runtime *rt) {
- pit_arena_index idx = pit_arena_alloc_index(rt->heap);
- if (idx < 0) {
- pit_error(rt, "failed to allocate space for heavy value");
- return PIT_NIL;
- }
- return pit_ref_new(rt, idx);
-}
-
-pit_value_heavy *pit_deref(pit_runtime *rt, pit_ref p) {
- return pit_arena_get(rt->heap, p);
-}
-
-bool pit_is_integer(pit_runtime *rt, pit_value a) {
- (void) rt;
- return pit_value_sort(a) == PIT_VALUE_SORT_INTEGER;
-}
-bool pit_is_double(pit_runtime *rt, pit_value a) {
- (void) rt;
- return pit_value_sort(a) == PIT_VALUE_SORT_DOUBLE;
-}
-bool pit_is_symbol(pit_runtime *rt, pit_value a) {
- (void) rt;
- return pit_value_sort(a) == PIT_VALUE_SORT_SYMBOL;
-}
-bool pit_is_value_heavy_sort(pit_runtime *rt, pit_value a, enum pit_value_heavy_sort e) {
- switch (pit_value_sort(a)) {
- case PIT_VALUE_SORT_REF: {
- pit_value_heavy *ha = pit_deref(rt, pit_as_ref(rt, a));
- if (!ha) { pit_error(rt, "bad ref"); return false; }
- return ha->hsort == e;
- }
- default:
- break;
- }
- return false;
-}
-bool pit_is_cell(pit_runtime *rt, pit_value a) {
- return pit_is_value_heavy_sort(rt, a, PIT_VALUE_HEAVY_SORT_CELL);
-}
-bool pit_is_cons(pit_runtime *rt, pit_value a) {
- return pit_is_value_heavy_sort(rt, a, PIT_VALUE_HEAVY_SORT_CONS);
-}
-bool pit_is_array(pit_runtime *rt, pit_value a) {
- return pit_is_value_heavy_sort(rt, a, PIT_VALUE_HEAVY_SORT_ARRAY);
-}
-bool pit_is_bytes(pit_runtime *rt, pit_value a) {
- return pit_is_value_heavy_sort(rt, a, PIT_VALUE_HEAVY_SORT_BYTES);
-}
-bool pit_is_func(pit_runtime *rt, pit_value a) {
- return pit_is_value_heavy_sort(rt, a, PIT_VALUE_HEAVY_SORT_FUNC);
-}
-bool pit_is_nativefunc(pit_runtime *rt, pit_value a) {
- return pit_is_value_heavy_sort(rt, a, PIT_VALUE_HEAVY_SORT_NATIVEFUNC);
-}
-bool pit_is_nativedata(pit_runtime *rt, pit_value a) {
- return pit_is_value_heavy_sort(rt, a, PIT_VALUE_HEAVY_SORT_NATIVEDATA);
-}
-bool pit_is_forwarding_pointer(pit_runtime *rt, pit_value a) {
- return pit_is_value_heavy_sort(rt, a, PIT_VALUE_HEAVY_SORT_FORWARDING_POINTER);
-}
-bool pit_eq(pit_value a, pit_value b) {
- return a == b;
-}
-bool pit_equal(pit_runtime *rt, pit_value a, pit_value b) {
- if (pit_value_sort(a) != pit_value_sort(b)) return false;
- switch (pit_value_sort(a)) {
- case PIT_VALUE_SORT_DOUBLE:
- case PIT_VALUE_SORT_INTEGER:
- case PIT_VALUE_SORT_SYMBOL:
- return pit_value_data(a) == pit_value_data(b);
- case PIT_VALUE_SORT_REF: {
- pit_value_heavy *ha = pit_deref(rt, pit_as_ref(rt, a));
- if (!ha) { pit_error(rt, "bad ref"); return false; }
- pit_value_heavy *hb = pit_deref(rt, pit_as_ref(rt, b));
- if (!hb) { pit_error(rt, "bad ref"); return false; }
- if (ha->hsort != hb->hsort) return false;
- switch (ha->hsort) {
- case PIT_VALUE_HEAVY_SORT_CELL:
- return pit_equal(rt, ha->in.cell, hb->in.cell);
- case PIT_VALUE_HEAVY_SORT_CONS:
- return pit_equal(rt, ha->in.cons.car, hb->in.cons.car)
- && pit_equal(rt, ha->in.cons.cdr, hb->in.cons.cdr);
- case PIT_VALUE_HEAVY_SORT_ARRAY: {
- if (ha->in.array.len != hb->in.array.len) return false;
- for (i64 i = 0; i < ha->in.array.len; ++i) {
- if (!pit_equal(rt, ha->in.array.data[i], hb->in.array.data[i])) return false;
- }
- return true;
- }
- case PIT_VALUE_HEAVY_SORT_BYTES: {
- if (ha->in.bytes.len != hb->in.bytes.len) return false;
- for (i64 i = 0; i < ha->in.bytes.len; ++i) {
- if (ha->in.bytes.data[i] != hb->in.bytes.data[i]) return false;
- }
- return true;
- }
- case PIT_VALUE_HEAVY_SORT_FUNC:
- return
- pit_equal(rt, ha->in.func.env, hb->in.func.env)
- && pit_equal(rt, ha->in.func.args, hb->in.func.args)
- && pit_equal(rt, ha->in.func.body, hb->in.func.body);
- case PIT_VALUE_HEAVY_SORT_NATIVEFUNC:
- return ha->in.nativefunc.f == hb->in.nativefunc.f
- && ha->in.nativefunc.data == hb->in.nativefunc.data;
- case PIT_VALUE_HEAVY_SORT_NATIVEDATA:
- return
- pit_eq(ha->in.nativedata.tag, hb->in.nativedata.tag)
- && ha->in.nativedata.data == hb->in.nativedata.data;
- case PIT_VALUE_HEAVY_SORT_FORWARDING_POINTER:
- return ha->in.forwarding_pointer == hb->in.forwarding_pointer;
- }
- }
- }
- return false;
-}
-pit_value pit_bytes_new(pit_runtime *rt, u8 *buf, i64 len) {
- u8 *dest = pit_arena_alloc_back(rt->heap, len);
- if (!dest) { pit_error(rt, "failed to allocate bytes"); return PIT_NIL; }
- pit_libc_string_memcpy(dest, buf, (size_t) len);
- pit_value ret = pit_heavy_new(rt);
- pit_value_heavy *h = pit_deref(rt, pit_as_ref(rt, ret));
- if (!h) { pit_error(rt, "failed to create new heavy value for bytes"); return PIT_NIL; }
- h->hsort = PIT_VALUE_HEAVY_SORT_BYTES;
- h->in.bytes.data = dest;
- h->in.bytes.len = len;
- return ret;
-}
-pit_value pit_bytes_new_cstr(pit_runtime *rt, char *s) {
- return pit_bytes_new(rt, (u8 *) s, (i64) pit_libc_string_strlen(s));
-}
-/* return true if v is a reference to bytes that are the same as those in buf */
-bool pit_bytes_match(pit_runtime *rt, pit_value v, u8 *buf, i64 len) {
- if (pit_value_sort(v) != PIT_VALUE_SORT_REF) return false;
- pit_value_heavy *h = pit_deref(rt, pit_as_ref(rt, v));
- if (!h) { pit_error(rt, "bad ref"); return false; }
- if (h->hsort != PIT_VALUE_HEAVY_SORT_BYTES) return false;
- if (h->in.bytes.len != len) return false;
- for (i64 i = 0; i < len; ++i)
- if (h->in.bytes.data[i] != buf[i]) {
- return false;
- }
- return true;
-}
-i64 pit_as_bytes(pit_runtime *rt, pit_value v, u8 *buf, i64 maxlen) {
- if (pit_value_sort(v) != PIT_VALUE_SORT_REF) { pit_error(rt, "not a ref"); return -1; }
- pit_value_heavy *h = pit_deref(rt, pit_as_ref(rt, v));
- if (!h) { pit_error(rt, "bad ref"); return -1; }
- if (h->hsort != PIT_VALUE_HEAVY_SORT_BYTES) {
- pit_error(rt, "invalid use of value as bytes");
- return -1;
- }
- i64 len = maxlen < h->in.bytes.len ? maxlen : h->in.bytes.len;
- for (i64 i = 0; i < len; ++i) {
- buf[i] = h->in.bytes.data[i];
- }
- return len;
-}
-
-pit_value pit_intern(pit_runtime *rt, u8 *nm, i64 len) {
- if (rt->error != PIT_NIL) return PIT_NIL;
- for (i64 sidx = 0; sidx < rt->symtab_len; ++sidx) {
- pit_symtab_entry *sent = pit_arena_get(rt->symtab, sidx);
- if (!sent) { pit_error(rt, "corrupted symbol table"); return PIT_NIL; }
- if (pit_bytes_match(rt, sent->name, nm, len)) return pit_symbol_new(rt, sidx);
- }
- pit_arena_index idx = pit_arena_alloc_index(rt->symtab);
- pit_symtab_entry *ent = pit_arena_get(rt->symtab, idx);
- if (!ent) { pit_error(rt, "failed to allocate symtab entry"); return PIT_NIL; }
- ent->name = pit_bytes_new(rt, nm, len);
- ent->value = PIT_NIL;
- ent->function = PIT_NIL;
- ent->is_macro = false;
- ent->is_special_form = false;
- ent->is_keyword = len >= 1 && nm[0] == ':';
- rt->symtab_len += 1;
- return pit_symbol_new(rt, idx);
-}
-pit_value pit_intern_cstr(pit_runtime *rt, char *nm) {
- return pit_intern(rt, (u8 *) nm, (i64) pit_libc_string_strlen(nm));
-}
-pit_value pit_symbol_name(pit_runtime *rt, pit_value sym) {
- pit_symtab_entry *ent = pit_symtab_lookup(rt, sym);
- if (!ent) { pit_error(rt, "bad symbol"); return PIT_NIL; }
- return ent->name;
-}
-bool pit_symbol_name_match(pit_runtime *rt, pit_value sym, u8 *buf, i64 len) {
- pit_symtab_entry *ent = pit_symtab_lookup(rt, sym);
- if (!ent) { pit_error(rt, "bad symbol"); return PIT_NIL; }
- return pit_bytes_match(rt, ent->name, buf, len);
-}
-bool pit_symbol_name_match_cstr(pit_runtime *rt, pit_value sym, char *s) {
- return pit_symbol_name_match(rt, sym, (u8 *) s, (i64) pit_libc_string_strlen(s));
-}
-pit_symtab_entry *pit_symtab_lookup(pit_runtime *rt, pit_value sym) {
- pit_symbol s = pit_as_symbol(rt, sym);
- return pit_arena_get(rt->symtab, s);
-}
-pit_value pit_get_value_cell(pit_runtime *rt, pit_value sym) {
- pit_symtab_entry *ent = pit_symtab_lookup(rt, sym);
- if (!ent) { pit_error(rt, "bad symbol"); return PIT_NIL; }
- return ent->value;
-}
-pit_value pit_get_function_cell(pit_runtime *rt, pit_value sym) {
- pit_symtab_entry *ent = pit_symtab_lookup(rt, sym);
- if (!ent) { pit_error(rt, "bad symbol"); return PIT_NIL; }
- return ent->function;
-}
-pit_value pit_get(pit_runtime *rt, pit_value sym) {
- return pit_cell_get(rt, pit_get_value_cell(rt, sym), sym);
-}
-void pit_set(pit_runtime *rt, pit_value sym, pit_value v) {
- pit_symbol idx = pit_as_symbol(rt, sym);
- if (idx < rt->frozen_symtab) { pit_error(rt, "attempted to modify frozen symbol"); return; }
- pit_symtab_entry *ent = pit_symtab_lookup(rt, sym);
- if (!ent) { pit_error(rt, "bad symbol"); return; }
- if (pit_value_sort(ent->value) != PIT_VALUE_SORT_REF) {
- ent->value = pit_cell_new(rt, PIT_NIL);
- }
- pit_cell_set(rt, ent->value, v, sym);
-}
-pit_value pit_fget(pit_runtime *rt, pit_value sym) {
- return pit_cell_get(rt, pit_get_function_cell(rt, sym), sym);
-}
-void pit_fset(pit_runtime *rt, pit_value sym, pit_value v) {
- pit_symbol idx = pit_as_symbol(rt, sym);
- if (idx < rt->frozen_symtab) { pit_error(rt, "attempted to modify frozen symbol"); return; }
- pit_symtab_entry *ent = pit_symtab_lookup(rt, sym);
- if (!ent) { pit_error(rt, "bad symbol"); return; }
- if (pit_value_sort(ent->function) != PIT_VALUE_SORT_REF) {
- ent->function = pit_cell_new(rt, PIT_NIL);
- }
- pit_cell_set(rt, ent->function, v, sym);
-}
-bool pit_is_symbol_macro(pit_runtime *rt, pit_value sym) {
- pit_symtab_entry *ent = pit_symtab_lookup(rt, sym);
- if (!ent) { pit_error(rt, "bad symbol"); return false; }
- return ent->is_macro;
-}
-void pit_symbol_is_macro(pit_runtime *rt, pit_value sym) {
- pit_symtab_entry *ent = pit_symtab_lookup(rt, sym);
- if (!ent) { pit_error(rt, "bad symbol"); return; }
- ent->is_macro = true;
-}
-void pit_mset(pit_runtime *rt, pit_value sym, pit_value v) {
- pit_fset(rt, sym, v);
- pit_symbol_is_macro(rt, sym);
-}
-bool pit_is_symbol_special_form(pit_runtime *rt, pit_value sym) {
- pit_symtab_entry *ent = pit_symtab_lookup(rt, sym);
- if (!ent) { pit_error(rt, "bad symbol"); return false; }
- return ent->is_special_form;
-}
-void pit_symbol_is_special_form(pit_runtime *rt, pit_value sym) {
- pit_symtab_entry *ent = pit_symtab_lookup(rt, sym);
- if (!ent) { pit_error(rt, "bad symbol"); return; }
- ent->is_special_form = true;
-}
-void pit_sfset(pit_runtime *rt, pit_value sym, pit_value v) {
- pit_fset(rt, sym, v);
- pit_symbol_is_special_form(rt, sym);
-}
-void pit_bind(pit_runtime *rt, pit_value sym, pit_value cell) {
- /* although we cannot set frozen symbols, we can still bind them temporarily - no need to check */
- pit_symtab_entry *ent = pit_symtab_lookup(rt, sym);
- if (!ent) { pit_error(rt, "bad symbol"); return; }
- if (pit_vec_push(pit_value)(rt->saved_bindings, ent->value) < 0) pit_error(rt, "binding stack overflow");
- ent->value = cell;
-}
-pit_value pit_unbind(pit_runtime *rt, pit_value sym) {
- pit_symtab_entry *ent = pit_symtab_lookup(rt, sym);
- if (!ent) { pit_error(rt, "bad symbol"); return PIT_NIL; }
- pit_value old = ent->value;
- if (pit_vec_pop(pit_value)(rt->saved_bindings, &ent->value) < 0) pit_error(rt, "binding stack underflow");
- return old;
-}
-
-pit_value pit_cell_new(pit_runtime *rt, pit_value v) {
- pit_value ret = pit_heavy_new(rt);
- pit_value_heavy *h = pit_deref(rt, pit_as_ref(rt, ret));
- if (!h) { pit_error(rt, "failed to create new heavy value for cell"); return PIT_NIL; }
- h->hsort = PIT_VALUE_HEAVY_SORT_CELL;
- h->in.cell = v;
- return ret;
-}
-pit_value pit_cell_get(pit_runtime *rt, pit_value cell, pit_value sym) {
- if (pit_value_sort(cell) != PIT_VALUE_SORT_REF) {
- char buf[256];
- i64 end = pit_dump(rt, buf, sizeof(buf) - 1, sym, false);
- buf[end] = 0;
- pit_error(rt, "attempted to get unbound variable/function: %s", buf);
- return PIT_NIL;
- }
- pit_value_heavy *h = pit_deref(rt, pit_as_ref(rt, cell));
- if (!h) { pit_error(rt, "bad ref"); return PIT_NIL; }
- if (h->hsort != PIT_VALUE_HEAVY_SORT_CELL) {
- pit_error(rt, "cell value ref does not point to cell");
- return PIT_NIL;
- }
- return h->in.cell;
-}
-void pit_cell_set(pit_runtime *rt, pit_value cell, pit_value v, pit_value sym) {
- if (pit_value_sort(cell) != PIT_VALUE_SORT_REF) {
- char buf[256];
- i64 end = pit_dump(rt, buf, sizeof(buf) - 1, sym, false);
- buf[end] = 0;
- pit_error(rt, "attempted to set unbound variable/function: %s", buf);
- return;
- }
- pit_ref idx = pit_as_ref(rt, cell);
- if (idx < rt->frozen_values) { pit_error(rt, "attempt to modify frozen cell"); return; }
- pit_value_heavy *h = pit_deref(rt, idx);
- if (!h) { pit_error(rt, "bad ref"); return; }
- if (h->hsort != PIT_VALUE_HEAVY_SORT_CELL) {
- pit_error(rt, "cell value ref does not point to cell");
- return;
- }
- h->in.cell = v;
-}
-
-pit_value pit_array_new(pit_runtime *rt, i64 len) {
- if (len < 0) { pit_error(rt, "failed to create array of negative size"); return PIT_NIL; }
- i64 byte_len = 0; pit_mul(&byte_len, sizeof(pit_value), len);
- pit_value *dest = pit_arena_alloc_array(rt->heap, byte_len);
- if (!dest) { pit_error(rt, "failed to allocate array"); return PIT_NIL; }
- for (i64 i = 0; i < len; ++i) dest[i] = PIT_NIL;
- pit_value ret = pit_heavy_new(rt);
- pit_value_heavy *h = pit_deref(rt, pit_as_ref(rt, ret));
- if (!h) { pit_error(rt, "failed to create new heavy value for array"); return PIT_NIL; }
- h->hsort = PIT_VALUE_HEAVY_SORT_ARRAY;
- h->in.array.data = dest;
- h->in.array.len = len;
- return ret;
-}
-pit_value pit_array_from_buf(pit_runtime *rt, pit_value *xs, i64 len) {
- pit_value ret = pit_array_new(rt, len);
- pit_value_heavy *h = pit_deref(rt, pit_as_ref(rt, ret));
- if (!h) { pit_error(rt, "failed to deref heavy value for array"); return PIT_NIL; }
- pit_libc_string_memcpy((u8 *) h->in.array.data, (u8 *) xs, (size_t) len * (size_t) sizeof(pit_value));
- return ret;
-}
-i64 pit_array_len(pit_runtime *rt, pit_value arr) {
- if (pit_value_sort(arr) != PIT_VALUE_SORT_REF) { pit_error(rt, "not a ref"); return -1; }
- pit_value_heavy *h = pit_deref(rt, pit_as_ref(rt, arr));
- if (!h) { pit_error(rt, "bad ref"); return -1; }
- if (h->hsort != PIT_VALUE_HEAVY_SORT_ARRAY) { pit_error(rt, "not an array"); return -1; }
- return h->in.array.len;
-}
-pit_value pit_array_get(pit_runtime *rt, pit_value arr, i64 idx) {
- if (pit_value_sort(arr) != PIT_VALUE_SORT_REF) { pit_error(rt, "not a ref"); return PIT_NIL; }
- pit_value_heavy *h = pit_deref(rt, pit_as_ref(rt, arr));
- if (!h) { pit_error(rt, "bad ref"); return PIT_NIL; }
- if (h->hsort != PIT_VALUE_HEAVY_SORT_ARRAY) { pit_error(rt, "not an array"); return PIT_NIL; }
- if (idx < 0 || idx >= h->in.array.len) {
- pit_error(rt, "array index out of bounds: %d", idx);
- return PIT_NIL;
- }
- return h->in.array.data[idx];
-}
-pit_value pit_array_set(pit_runtime *rt, pit_value arr, i64 idx, pit_value v) {
- if (pit_value_sort(arr) != PIT_VALUE_SORT_REF) { pit_error(rt, "not a ref"); return PIT_NIL; }
- pit_value_heavy *h = pit_deref(rt, pit_as_ref(rt, arr));
- if (!h) { pit_error(rt, "bad ref"); return PIT_NIL; }
- if (h->hsort != PIT_VALUE_HEAVY_SORT_ARRAY) { pit_error(rt, "not an array"); return PIT_NIL; }
- if (idx < 0 || idx >= h->in.array.len) {
- pit_error(rt, "array index out of bounds: %d", idx);
- return PIT_NIL;
- }
- h->in.array.data[idx] = v;
- return v;
-}
-
-pit_value pit_cons(pit_runtime *rt, pit_value car, pit_value cdr) {
- pit_value ret = pit_heavy_new(rt);
- pit_value_heavy *h = pit_deref(rt, pit_as_ref(rt, ret));
- if (!h) { pit_error(rt, "failed to create new heavy value for cons"); return PIT_NIL; }
- h->hsort = PIT_VALUE_HEAVY_SORT_CONS;
- h->in.cons.car = car;
- h->in.cons.cdr = cdr;
- return ret;
-}
-pit_value pit_list(pit_runtime *rt, i64 num, ...) {
- pit_value temp[64] = {0};
- pit_value ret = PIT_NIL;
- if (num > 64) { pit_error(rt, "failed to create list of size %d\n", num); return PIT_NIL; }
- va_list elems;
- va_start(elems, num);
- for (i64 i = 0; i < num; ++i) {
- temp[i] = va_arg(elems, pit_value);
- }
- va_end(elems);
- for (i64 i = 0; i < num; ++i) {
- ret = pit_cons(rt, temp[num - i - 1], ret);
- }
- return ret;
-}
-i64 pit_list_len(pit_runtime *rt, pit_value xs) {
- i64 ret = 0;
- while (xs != PIT_NIL) {
- ret += 1;
- xs = pit_cdr(rt, xs);
- }
- return ret;
-}
-pit_value pit_car(pit_runtime *rt, pit_value v) {
- if (pit_value_sort(v) != PIT_VALUE_SORT_REF) return PIT_NIL;
- pit_value_heavy *h = pit_deref(rt, pit_as_ref(rt, v));
- if (!h) { pit_error(rt, "bad ref"); return PIT_NIL; }
- if (h->hsort != PIT_VALUE_HEAVY_SORT_CONS) return PIT_NIL;
- return h->in.cons.car;
-}
-pit_value pit_cdr(pit_runtime *rt, pit_value v) {
- if (pit_value_sort(v) != PIT_VALUE_SORT_REF) return PIT_NIL;
- pit_value_heavy *h = pit_deref(rt, pit_as_ref(rt, v));
- if (!h) { pit_error(rt, "bad ref"); return PIT_NIL; }
- if (h->hsort != PIT_VALUE_HEAVY_SORT_CONS) return PIT_NIL;
- return h->in.cons.cdr;
-}
-void pit_setcar(pit_runtime *rt, pit_value v, pit_value x) {
- if (pit_value_sort(v) != PIT_VALUE_SORT_REF) { pit_error(rt, "not a ref"); return; }
- pit_ref idx = pit_as_ref(rt, v);
- if (idx < rt->frozen_values) { pit_error(rt, "attempted to modify frozen cons"); return; }
- pit_value_heavy *h = pit_deref(rt, idx);
- if (!h) { pit_error(rt, "bad ref"); return; }
- if (h->hsort != PIT_VALUE_HEAVY_SORT_CONS) { pit_error(rt, "not a cons"); return; }
- h->in.cons.car = x;
-}
-void pit_setcdr(pit_runtime *rt, pit_value v, pit_value x) {
- if (pit_value_sort(v) != PIT_VALUE_SORT_REF) { pit_error(rt, "not a ref"); return; }
- pit_ref idx = pit_as_ref(rt, v);
- if (idx < rt->frozen_values) { pit_error(rt, "attempted to modify frozen cons"); return; }
- pit_value_heavy *h = pit_deref(rt, idx);
- if (!h) { pit_error(rt, "bad ref"); return; }
- if (h->hsort != PIT_VALUE_HEAVY_SORT_CONS) { pit_error(rt, "not a cons"); return; }
- h->in.cons.cdr = x;
-}
-pit_value pit_append(pit_runtime *rt, pit_value xs, pit_value ys) {
- pit_value ret = ys;
- xs = pit_reverse(rt, xs);
- while (xs != PIT_NIL) {
- ret = pit_cons(rt, pit_car(rt, xs), ret);
- xs = pit_cdr(rt, xs);
- }
- return ret;
+void pit_annotation_set(struct pit_runtime *rt, pit_ref ref, pit_annotation annotation) {
+ pit_annotated_ref a;
+ a.ref = ref;
+ a.annotation = annotation;
+ if (pit_vec_push(pit_annotated_ref)(rt->annotations, a) < 0)
+ pit_error(rt, "annotation overflow");
}
-pit_value pit_reverse(pit_runtime *rt, pit_value xs) {
- pit_value ret = PIT_NIL;
- while (xs != PIT_NIL) {
- ret = pit_cons(rt, pit_car(rt, xs), ret);
- xs = pit_cdr(rt, xs);
- }
- return ret;
-}
-pit_value pit_contains_eq(pit_runtime *rt, pit_value needle, pit_value haystack) {
- while (haystack != PIT_NIL) {
- if (pit_eq(needle, pit_car(rt, haystack))) return PIT_T;
- haystack = pit_cdr(rt, haystack);
- }
- return PIT_NIL;
-}
-pit_value pit_contains_equal(pit_runtime *rt, pit_value needle, pit_value haystack) {
- while (haystack != PIT_NIL) {
- if (pit_equal(rt, needle, pit_car(rt, haystack))) return PIT_T;
- haystack = pit_cdr(rt, haystack);
- }
- return PIT_NIL;
-}
-pit_value pit_plist_get(pit_runtime *rt, pit_value k, pit_value vs) {
- while (vs != PIT_NIL) {
- if (pit_eq(k, pit_car(rt, vs))) {
- return pit_car(rt, pit_cdr(rt, vs));
- }
- vs = pit_cdr(rt, vs);
- }
- return PIT_NIL;
-}
-
-pit_value pit_free_vars(pit_runtime *rt, pit_value initial_bound, pit_value body) {
- i64 expr_stack_reset = rt->expr_stack->next;
- pit_value ret = PIT_NIL;
- if (pit_vec_push(pit_value)(rt->expr_stack, pit_cons(rt, initial_bound, body)) < 0)
- pit_error(rt, "free variable search stack overflow");
- while (rt->expr_stack->next > expr_stack_reset) {
- pit_value boundscur, bound, cur;
- if (pit_vec_pop(pit_value)(rt->expr_stack, &boundscur) < 0)
- pit_error(rt, "free variable search stack underflow");
- bound = pit_car(rt, boundscur);
- cur = pit_cdr(rt, boundscur);
- if (pit_is_cons(rt, cur)) {
- pit_value fsym = pit_car(rt, cur);
- bool is_symbol = pit_is_symbol(rt, fsym);
- pit_value fargs = pit_cdr(rt, cur);
- if (is_symbol && pit_symbol_name_match_cstr(rt, fsym, "lambda")) {
- pit_value new_bound = pit_append(rt, pit_car(rt, fargs), bound);
- fargs = pit_cdr(rt, fargs);
- while (fargs != PIT_NIL) {
- if (pit_vec_push(pit_value)(rt->expr_stack, pit_cons(rt, new_bound, pit_car(rt, fargs))) < 0)
- pit_error(rt, "free variable search stack overflow");
- fargs = pit_cdr(rt, fargs);
- }
- } else if (is_symbol && pit_symbol_name_match_cstr(rt, fsym, "quote")) {
- /* don't look inside quote!
- if we add other special forms, make sure to consider them here if necessary! */
- } else {
- while (fargs != PIT_NIL) {
- if (pit_vec_push(pit_value)(rt->expr_stack, pit_cons(rt, bound, pit_car(rt, fargs))) < 0)
- pit_error(rt, "free variable search stack overflow");
- fargs = pit_cdr(rt, fargs);
- }
- if (!is_symbol) {
- if (pit_vec_push(pit_value)(rt->expr_stack, pit_cons(rt, bound, fsym)) < 0)
- pit_error(rt, "free variable search stack overflow");
- }
- }
- } else if (pit_is_symbol(rt, cur)) {
- if (pit_contains_eq(rt, cur, bound) == PIT_NIL) {
- ret = pit_cons(rt, cur, ret);
- }
- }
- }
- rt->expr_stack->next = expr_stack_reset;
- return ret;
-}
-pit_value pit_lambda(pit_runtime *rt, pit_value args, pit_value body) {
- pit_value ret = pit_heavy_new(rt);
- pit_value_heavy *h = pit_deref(rt, pit_as_ref(rt, ret));
- if (!h) { pit_error(rt, "failed to create new heavy value for lambda"); return PIT_NIL; }
- pit_value expanded = pit_expand_macros(rt, pit_cons(rt, pit_intern_cstr(rt, "progn"), body));
- pit_value freevars = pit_free_vars(rt, args, expanded);
- pit_value env = PIT_NIL;
- while (freevars != PIT_NIL) {
- pit_value sym = pit_car(rt, freevars);
- pit_value cell = pit_get_value_cell(rt, sym);
- env = pit_cons(rt, pit_cons(rt, sym, cell), env);
- freevars = pit_cdr(rt, freevars);
- }
- h->hsort = PIT_VALUE_HEAVY_SORT_FUNC;
- pit_value arg_cells = PIT_NIL;
- pit_value arg_rest_nm = PIT_NIL;
- pit_value separator = pit_intern_cstr(rt, "&");
- while (args != PIT_NIL) {
- pit_value nm = pit_car(rt, args);
- if (pit_eq(nm, separator)) {
- pit_value next_nm = pit_car(rt, pit_cdr(rt, args));
- if (next_nm == PIT_NIL) { pit_error(rt, "invalid & in lambda list"); return PIT_NIL; }
- arg_rest_nm = next_nm;
- arg_cells = pit_cons(rt, next_nm, arg_cells);
- break;
- } else {
- arg_cells = pit_cons(rt, nm, arg_cells);
- args = pit_cdr(rt, args);
- }
- }
- arg_cells = pit_reverse(rt, arg_cells);
- h->in.func.args = arg_cells;
- h->in.func.arg_rest_nm = arg_rest_nm;
- h->in.func.env = env;
- h->in.func.body = expanded;
- return ret;
-}
-pit_value pit_nativefunc_new_with_data(pit_runtime *rt, pit_nativefunc f, void *data) {
- pit_value ret = pit_heavy_new(rt);
- pit_value_heavy *h = pit_deref(rt, pit_as_ref(rt, ret));
- if (!h) { pit_error(rt, "failed to create new heavy value for nativefunc"); return PIT_NIL; }
- h->hsort = PIT_VALUE_HEAVY_SORT_NATIVEFUNC;
- h->in.nativefunc.f = f;
- h->in.nativefunc.data = data;
- return ret;
-}
-pit_value pit_nativefunc_new(pit_runtime *rt, pit_nativefunc f) {
- return pit_nativefunc_new_with_data(rt, f, NULL);
-}
-pit_value pit_apply(pit_runtime *rt, pit_value f, pit_value args) {
- char buf[256] = {0};
- if (pit_is_symbol(rt, f)) {
- f = pit_fget(rt, f);
- }
- /* if f is not a symbol, assume it is a func or nativefunc
- most commonly, this happens when you funcall a variable
- with a function in the value cell, e.g. passing a lambda to a function */
- switch (pit_value_sort(f)) {
- case PIT_VALUE_SORT_REF: {
- pit_value_heavy *h = pit_deref(rt, pit_as_ref(rt, f));
- if (!h) { pit_error(rt, "bad ref"); return PIT_NIL; }
- if (h->hsort == PIT_VALUE_HEAVY_SORT_FUNC) {
- /* calling a Lisp function is simple! */
- pit_value bound = PIT_NIL;
- pit_value env = h->in.func.env;
- while (env != PIT_NIL) { /* first, bind all entries in the closure */
- pit_value b = pit_car(rt, env);
- pit_value nm = pit_car(rt, b);
- pit_bind(rt, nm, pit_cdr(rt, b));
- bound = pit_cons(rt, nm, bound);
- env = pit_cdr(rt, env);
- }
- pit_value anames = h->in.func.args;
- while (anames != PIT_NIL) { /* bind all argument names to their values */
- pit_value nm = pit_car(rt, anames);
- pit_value cell = pit_cell_new(rt, PIT_NIL);
- if (h->in.func.arg_rest_nm != PIT_NIL && pit_eq(nm, h->in.func.arg_rest_nm)) {
- pit_cell_set(rt, cell, args, nm);
- pit_bind(rt, nm, cell);
- break;
- } else {
- pit_cell_set(rt, cell, pit_car(rt, args), nm);
- pit_bind(rt, nm, cell);
- }
- bound = pit_cons(rt, nm, bound);
- args = pit_cdr(rt, args);
- anames = pit_cdr(rt, anames);
- }
- pit_value ret = pit_eval(rt, h->in.func.body); /* evaluate the body */
- while (bound != PIT_NIL) { /* unbind everything we bound earlier, in reverse */
- pit_unbind(rt, pit_car(rt, bound));
- bound = pit_cdr(rt, bound);
- }
- return ret;
- } else if (h->hsort == PIT_VALUE_HEAVY_SORT_NATIVEFUNC) {
- /* calling native functions is even simpler */
- return h->in.nativefunc.f(rt, args, h->in.nativefunc.data);
- } else {
- i64 end = pit_dump(rt, buf, sizeof(buf) - 1, f, true);
- buf[end] = 0;
- pit_error(rt, "attempted to apply non-function ref: %s", buf);
- return PIT_NIL;
+pit_annotated_ref *pit_annotation_get(struct pit_runtime *rt, pit_ref ref) {
+ for (i64 i = 0; i < rt->annotations->next; ++i) {
+ pit_annotated_ref *a = pit_vec_get(pit_annotated_ref)(rt->annotations, i);
+ if (a == NULL) pit_error(rt, "failed to get annotation");
+ else if (a->ref == ref) {
+ return a;
}
}
- default: {
- i64 end = pit_dump(rt, buf, sizeof(buf) - 1, f, true);
- buf[end] = 0;
- pit_error(rt, "attempted to apply non-function value: %s", buf);
- return PIT_NIL;
- }
- }
-}
-
-pit_value pit_nativedata_new(pit_runtime *rt, pit_value tag, void *d) {
- pit_value ret = pit_heavy_new(rt);
- pit_value_heavy *h = pit_deref(rt, pit_as_ref(rt, ret));
- if (!h) { pit_error(rt, "failed to create new heavy value for nativedata"); return PIT_NIL; }
- h->hsort = PIT_VALUE_HEAVY_SORT_NATIVEDATA;
- h->in.nativedata.tag = tag;
- h->in.nativedata.data = d;
- return ret;
-}
-void *pit_nativedata_get(pit_runtime *rt, pit_value tag, pit_value v) {
- pit_value_heavy *h = NULL;
- if (pit_value_sort(v) != PIT_VALUE_SORT_REF) {
- pit_error(rt, "value was not a reference");
- return NULL;
- }
- h = pit_deref(rt, pit_as_ref(rt, v));
- if (!h) { pit_error(rt, "bad ref"); return NULL; }
- if (h->hsort != PIT_VALUE_HEAVY_SORT_NATIVEDATA) {
- pit_error(rt, "invalid use of value as nativedata");
- return NULL;
- }
- if (!pit_eq(h->in.nativedata.tag, tag)) {
- pit_error(rt, "native value does not match tag");
- return NULL;
- }
- if (!h->in.nativedata.data) {
- pit_error(rt, "nativedata was already freed");
- return NULL;
- }
- return h->in.nativedata.data;
+ return NULL;
}
void pit_runtime_eval_program_push_literal(pit_runtime *rt, pit_vec(pit_runtime_eval_ins) *s, pit_value x) {
@@ -934,350 +106,11 @@ void pit_runtime_eval_program_push_literal(pit_runtime *rt, pit_vec(pit_runtime_
if (pit_vec_push(pit_runtime_eval_ins)(s, ent) < 0)
pit_error(rt, "evaluation program overflow");
}
-void pit_runtime_eval_program_push_apply(pit_runtime *rt, pit_vec(pit_runtime_eval_ins) *s, i64 arity) {
+void pit_runtime_eval_program_push_apply(pit_runtime *rt, pit_vec(pit_runtime_eval_ins) *s, i64 arity, pit_annotated_ref *annotation) {
pit_runtime_eval_ins ent;
ent.sort = PIT_RUNTIME_EVAL_INS_APPLY;
- ent.in.apply = arity;
+ ent.in.apply.arity = arity;
+ ent.in.apply.annotation = annotation;
if (pit_vec_push(pit_runtime_eval_ins)(s, ent) < 0)
pit_error(rt, "evaluation program overflow");
}
-
-pit_expr_annotations *pit_expr_annotations_new(u8 *buf, i64 buf_len) {
- uintptr_t base = (uintptr_t) buf;
- uintptr_t aligned = pit_align_up(base, sizeof(void *));
- pit_expr_annotations *ret = (pit_expr_annotations *) aligned;
- uintptr_t data = aligned + sizeof(pit_arena);
- i64 offset = (i64) data - (i64) base;
- i64 remaining = (i64) (buf_len - offset);
- i64 cap = remaining / (i64) sizeof(pit_expr_annotation);
- ret->next = 0;
- ret->capacity = cap;
- return ret;
-}
-void pit_expr_annotations_push(pit_expr_annotations *s, pit_ref ref, i64 line, i64 column) {
- pit_expr_annotation *ent = &s->data[s->next++];
- ent->ref = ref;
- ent->line = line;
- ent->column = column;
-}
-
-pit_expr_annotation *pit_expr_annotations_lookup(pit_expr_annotations *s, pit_ref ref) {
- for (i64 i = 0; i < s->next; ++i) {
- if (s->data[i].ref == ref) return &s->data[i];
- }
- return NULL;
-}
-
-pit_value pit_expand_macros(pit_runtime *rt, pit_value top) {
- i64 expr_stack_reset = rt->expr_stack->next;
- i64 result_stack_reset = rt->result_stack->next;
- i64 program_reset = rt->program->next;
- if (pit_vec_push(pit_value)(rt->expr_stack, top) < 0)
- pit_error(rt, "macro expansion stack overflow");
- while (rt->expr_stack->next > expr_stack_reset) {
- pit_value cur;
- if (rt->error != PIT_NIL) goto end;
- if (pit_vec_pop(pit_value)(rt->expr_stack, &cur) < 0)
- pit_error(rt, "macro expansion stack underflow");
- if (pit_is_cons(rt, cur)) {
- pit_value fsym = pit_car(rt, cur);
- bool is_symbol = pit_is_symbol(rt, fsym);
- if (is_symbol && pit_is_symbol_macro(rt, fsym)) {
- pit_value f = pit_fget(rt, fsym);
- pit_value args = pit_cdr(rt, cur);
- pit_value res = pit_apply(rt, f, args);
- if (pit_vec_push(pit_value)(rt->expr_stack, res) < 0)
- pit_error(rt, "macro expansion stack overflow");
- } else if (is_symbol && pit_symbol_name_match_cstr(rt, fsym, "defer")) {
- pit_value args = pit_cdr(rt, cur);
- pit_runtime_eval_program_push_literal(rt, rt->program, pit_car(rt, args));
- } else if (is_symbol && pit_symbol_name_match_cstr(rt, fsym, "quote")) {
- pit_runtime_eval_program_push_literal(rt, rt->program, cur);
- } else if (is_symbol && pit_symbol_name_match_cstr(rt, fsym, "lambda")) {
- pit_value args = pit_cdr(rt, cur);
- pit_value bindings = pit_car(rt, args);
- pit_value body = pit_cdr(rt, args);
- i64 argcount = 0;
- if (pit_vec_push(pit_value)(rt->expr_stack, pit_list(rt, 2, pit_intern_cstr(rt, "defer"), bindings)) < 0)
- pit_error(rt, "macro expansion stack overflow");
- while (body != PIT_NIL) {
- pit_value a = pit_car(rt, body);
- if (pit_vec_push(pit_value)(rt->expr_stack, a) < 0)
- pit_error(rt, "macro expansion stack overflow");
- body = pit_cdr(rt, body);
- argcount += 1;
- }
- pit_runtime_eval_program_push_apply(rt, rt->program, argcount + 1);
- pit_runtime_eval_program_push_literal(rt, rt->program, fsym);
- } else {
- pit_value args = pit_cdr(rt, cur);
- i64 argcount = 0;
- while (args != PIT_NIL) {
- pit_value a = pit_car(rt, args);
- if (pit_vec_push(pit_value)(rt->expr_stack, a) < 0)
- pit_error(rt, "macro expansion stack overflow");
- args = pit_cdr(rt, args);
- argcount += 1;
- }
- if (!is_symbol) {
- if (pit_vec_push(pit_value)(rt->expr_stack, fsym) < 0)
- pit_error(rt, "macro expansion stack overflow");
- }
- pit_runtime_eval_program_push_apply(rt, rt->program, argcount);
- if (is_symbol) {
- pit_runtime_eval_program_push_literal(rt, rt->program, fsym);
- }
- }
- } else {
- pit_runtime_eval_program_push_literal(rt, rt->program, cur);
- }
- }
- for (i64 idx = rt->program->next - 1; idx >= program_reset; --idx) {
- pit_runtime_eval_ins *ent = pit_vec_get(pit_runtime_eval_ins)(rt->program, idx);
- if (ent == NULL) pit_error(rt, "macro expansion program invalid");
- if (rt->error != PIT_NIL) goto end;
- switch (ent->sort) {
- case PIT_RUNTIME_EVAL_INS_LITERAL:
- if (pit_vec_push(pit_value)(rt->result_stack, ent->in.literal) < 0)
- pit_error(rt, "macro expansion stack overflow");
- break;
- case PIT_RUNTIME_EVAL_INS_APPLY: {
- pit_value f = PIT_NIL;
- pit_value args = PIT_NIL;
- if (pit_vec_pop(pit_value)(rt->result_stack, &f) < 0)
- pit_error(rt, "macro expansion stack underflow");
- for (i64 i = 0; i < ent->in.apply; ++i) {
- pit_value a;
- if (pit_vec_pop(pit_value)(rt->result_stack, &a) < 0)
- pit_error(rt, "macro expansion stack underflow");
- args = pit_cons(rt, a, args);
- }
- if (pit_vec_push(pit_value)(rt->result_stack, pit_cons(rt, f, args)) < 0)
- pit_error(rt, "macro expansion stack overflow");
- break;
- }
- default:
- pit_error(rt, "unknown program entry");
- goto end;
- }
- }
-end: {
- pit_value ret = PIT_NIL;
- if (pit_vec_pop(pit_value)(rt->result_stack, &ret) < 0)
- pit_error(rt, "macro expansion stack underflow");
- rt->expr_stack->next = expr_stack_reset;
- rt->result_stack->next = result_stack_reset;
- rt->program->next = program_reset;
- return ret;
- }
-}
-
-pit_value pit_eval(pit_runtime *rt, pit_value top) {
- i64 expr_stack_reset = rt->expr_stack->next;
- i64 result_stack_reset = rt->result_stack->next;
- i64 program_reset = rt->program->next;
- if (pit_vec_push(pit_value)(rt->expr_stack, top) < 0)
- pit_error(rt, "evaluation stack overflow");
- /* first, convert the expression tree into "polish notation" in program */
- while (rt->expr_stack->next > expr_stack_reset) {
- pit_value cur = PIT_NIL;
- if (rt->error != PIT_NIL) goto end;
- if (pit_vec_pop(pit_value)(rt->expr_stack, &cur) < 0)
- pit_error(rt, "evaluation stack underflow");
- if (pit_is_cons(rt, cur)) { /* compound expressions: function/macro application special forms */
- pit_value fsym = pit_car(rt, cur);
- bool is_symbol = pit_is_symbol(rt, fsym);
- pit_expr_annotation *ann = pit_expr_annotations_lookup(rt->annotations, pit_as_ref(rt, cur));
- fprintf(stderr, "looking up annotation (%ld): ", pit_as_ref(rt, cur));
- pit_trace_(rt, "%s\n", cur);
- if (ann) {
- fprintf(stderr, "%ld:%ld\n", ann->line, ann->column);
- rt->source_line = ann->line;
- rt->source_column = ann->column;
- } else {
- fprintf(stderr, "failed to find ann\n");
- }
- if (is_symbol && pit_is_symbol_special_form(rt, fsym)) { /* special forms */
- pit_value f = pit_fget(rt, fsym);
- pit_value args = pit_cdr(rt, cur);
- /* special forms are nativefuncs that directly manipulate the stacks
- basically macros, but we don't need to evaluate the return value */
- pit_apply(rt, f, args);
- } else if (is_symbol && pit_is_symbol_macro(rt, fsym)) { /* macros */
- pit_value f = pit_fget(rt, fsym);
- pit_value args = pit_cdr(rt, cur);
- pit_value res = pit_apply(rt, f, args);
- if (pit_vec_push(pit_value)(rt->expr_stack, res) < 0)
- pit_error(rt, "evaluation stack overflow");
- } else { /* normal functions */
- pit_value args = pit_cdr(rt, cur);
- i64 argcount = 0;
- while (args != PIT_NIL) {
- if (pit_vec_push(pit_value)(rt->expr_stack, pit_car(rt, args)) < 0)
- pit_error(rt, "evaluation stack overflow");
- args = pit_cdr(rt, args);
- argcount += 1;
- }
- if (!is_symbol) {
- if (pit_vec_push(pit_value)(rt->expr_stack, fsym) < 0)
- pit_error(rt, "evaluation stack overflow");
- }
- pit_runtime_eval_program_push_apply(rt, rt->program, argcount);
- if (is_symbol) {
- pit_value f = pit_fget(rt, fsym);
- pit_runtime_eval_program_push_literal(rt, rt->program, f);
- }
- }
- } else if (pit_is_symbol(rt, cur)) { /* unquoted symbols: variable lookup */
- pit_symtab_entry *ent = pit_symtab_lookup(rt, cur);
- if (ent->is_keyword) {
- pit_runtime_eval_program_push_literal(rt, rt->program, cur);
- } else {
- pit_runtime_eval_program_push_literal(rt, rt->program, pit_get(rt, cur));
- }
- } else { /* other expressions evaluate to themselves! */
- pit_runtime_eval_program_push_literal(rt, rt->program, cur);
- }
- }
- /* then, execute the polish notation program from right to left
- this has the nice consequence of putting the arguments in the right order */
- for (i64 idx = rt->program->next - 1; idx >= program_reset; --idx) {
- pit_runtime_eval_ins *ent = pit_vec_get(pit_runtime_eval_ins)(rt->program, idx);
- if (ent == NULL) pit_error(rt, "evaluation program invalid");
- if (rt->error != PIT_NIL) goto end;
- switch (ent->sort) {
- case PIT_RUNTIME_EVAL_INS_LITERAL:
- if (pit_vec_push(pit_value)(rt->result_stack, ent->in.literal) < 0)
- pit_error(rt, "evaluation result stack overflow");
- break;
- case PIT_RUNTIME_EVAL_INS_APPLY: {
- pit_value f = PIT_NIL;
- pit_value args = PIT_NIL;
- if (pit_vec_pop(pit_value)(rt->result_stack, &f) < 0)
- pit_error(rt, "evaluation result stack underflow");
- for (i64 i = 0; i < ent->in.apply; ++i) {
- pit_value a = PIT_NIL;
- if (pit_vec_pop(pit_value)(rt->result_stack, &a) < 0)
- pit_error(rt, "evaluation result stack underflow");
- args = pit_cons(rt, a, args);
- }
- if (pit_vec_push(pit_value)(rt->result_stack, pit_apply(rt, f, args)) < 0)
- pit_error(rt, "evaluation result stack underflow");
- break;
- }
- default:
- pit_error(rt, "unknown program entry");
- goto end;
- }
- }
-end: {
- pit_value ret = PIT_NIL;
- if (pit_vec_pop(pit_value)(rt->result_stack, &ret) < 0)
- pit_error(rt, "evaluation result stack underflow");
- rt->expr_stack->next = expr_stack_reset;
- rt->result_stack->next = result_stack_reset;
- rt->program->next = program_reset;
- return ret;
- }
-}
-
-static i64 gc_copy(pit_arena *tospace, pit_value_heavy *h) {
- if (h->hsort == PIT_VALUE_HEAVY_SORT_FORWARDING_POINTER) {
- return h->in.forwarding_pointer;
- } else {
- i64 ret = tospace->next;
- pit_value_heavy *g = pit_arena_alloc(tospace);
- *g = *h;
- h->hsort = PIT_VALUE_HEAVY_SORT_FORWARDING_POINTER;
- h->in.forwarding_pointer = ret;
- return ret;
- }
-}
-static pit_value gc_copy_value(pit_runtime *rt, pit_arena *tospace, pit_value v) {
- if (pit_value_sort(v) == PIT_VALUE_SORT_REF) {
- pit_value_heavy *h = pit_deref(rt, pit_as_ref(rt, v));
- i64 new = gc_copy(tospace, h);
- return pit_ref_new(rt, new);
- } else {
- return v;
- }
-}
-void pit_collect_garbage(pit_runtime *rt) {
- return; // TODO
- rt->frozen_values = 0;
- rt->frozen_symtab = 0;
- pit_arena *fromspace = rt->heap;
- pit_arena *tospace = rt->backbuffer;
- pit_arena_reset(tospace);
- /* populate tospace with immediately reachable values */
- for (i64 i = 0; i < rt->symtab_len; ++i) {
- pit_symtab_entry *ent = pit_arena_get(rt->symtab, i);
- ent->name = gc_copy_value(rt, tospace, ent->name);
- ent->value = gc_copy_value(rt, tospace, ent->value);
- ent->function = gc_copy_value(rt, tospace, ent->function);
- }
- for (i64 i = 0; i < rt->saved_bindings->next; ++i) {
- pit_value *v = pit_vec_get(pit_value)(rt->saved_bindings, i);
- if (v != NULL) *v = gc_copy_value(rt, tospace, *v); /* TODO handle failure here */
- }
- for (i64 scan = 0; scan < tospace->next; ++scan) {
- pit_value_heavy *h = pit_arena_get(tospace, scan);
- switch (h->hsort) {
- case PIT_VALUE_HEAVY_SORT_CELL:
- h->in.cell = gc_copy_value(rt, tospace, h->in.cell);
- break;
- case PIT_VALUE_HEAVY_SORT_CONS:
- h->in.cons.car = gc_copy_value(rt, tospace, h->in.cons.car);
- h->in.cons.cdr = gc_copy_value(rt, tospace, h->in.cons.cdr);
- break;
- case PIT_VALUE_HEAVY_SORT_ARRAY: {
- i64 byte_len = 0; pit_mul(&byte_len, sizeof(pit_value), h->in.array.len);
- pit_value *data = pit_arena_alloc_back(tospace, byte_len);
- for (i64 i = 0; i < h->in.array.len; ++i) {
- data[i] = gc_copy_value(rt, tospace, h->in.array.data[i]);
- }
- h->in.array.data = data;
- break;
- }
- case PIT_VALUE_HEAVY_SORT_BYTES: {
- u8 *data = pit_arena_alloc_back(tospace, h->in.bytes.len);
- for (i64 i = 0; i < h->in.bytes.len; ++i) {
- data[i] = h->in.bytes.data[i];
- }
- h->in.bytes.data = data;
- break;
- }
- case PIT_VALUE_HEAVY_SORT_FUNC:
- h->in.func.env = gc_copy_value(rt, tospace, h->in.func.env);
- h->in.func.args = gc_copy_value(rt, tospace, h->in.func.args);
- h->in.func.arg_rest_nm = gc_copy_value(rt, tospace, h->in.func.arg_rest_nm);
- h->in.func.body = gc_copy_value(rt, tospace, h->in.func.body);
- break;
- case PIT_VALUE_HEAVY_SORT_NATIVEFUNC: break;
- case PIT_VALUE_HEAVY_SORT_NATIVEDATA:
- h->in.nativedata.tag = gc_copy_value(rt, tospace, h->in.nativedata.tag);
- break;
- case PIT_VALUE_HEAVY_SORT_FORWARDING_POINTER:
- pit_error(rt, "garbage collection broken! encountered forwarding pointer in to-space");
- break;
- }
- }
- rt->heap = tospace;
- rt->backbuffer = fromspace;
-}
-
-int pit_runtime_test(u8 *out, i64 out_len, u8 *buf, i64 len) {
- pit_runtime *rt = pit_runtime_new(buf, len);
- pit_install_library_essential(rt);
- pit_install_library_plist(rt);
- pit_install_library_alist(rt);
- pit_lexer lex;
- pit_parser parse;
- pit_lex_cstr(&lex, "(cons (list 1 2 3) (cons '(a b c) 21))");
- pit_parser_from_lexer(&parse, &lex);
- bool eof = false;
- pit_value p = pit_parse(rt, &parse, &eof);
- pit_value res = pit_eval(rt, p);
- pit_dump(rt, (char *) out, out_len, res, false);
- return 0;
-}
diff --git a/src/runtime/dump.c b/src/runtime/dump.c
new file mode 100644
index 0000000..3d5ec9c
--- /dev/null
+++ b/src/runtime/dump.c
@@ -0,0 +1,100 @@
+#include <lcq/pit/runtime/dump.h>
+
+#define CHECK_BUF if (buf >= end) { return buf - start; }
+#define CHECK_BUF_LABEL(label) if (buf >= end) { goto label; }
+i64 pit_dump(pit_runtime *rt, char *buf, i64 len, pit_value v, bool readable) {
+ pit_value_heavy *h = NULL;
+ if (len <= 0) return 0;
+ switch (pit_value_sort(v)) {
+ case PIT_VALUE_SORT_DOUBLE:
+ #ifndef PIT_NO_DOUBLE
+ return pit_libc_string_snprintf(buf, (size_t) len, "%lf", pit_value_as_double(rt, v));
+ #else
+ return pit_string_snprintf(buf, (size_t) len, "<unsupported double>");
+ #endif
+ case PIT_VALUE_SORT_INTEGER:
+ return pit_libc_string_snprintf(buf, (size_t) len, "%ld", pit_value_as_integer(rt, v));
+ case PIT_VALUE_SORT_SYMBOL: {
+ pit_symtab_entry *ent = pit_symtab_lookup(rt, v);
+ if (ent
+ && pit_value_sort(ent->name) == PIT_VALUE_SORT_REF
+ && (h = pit_value_ref_deref(rt, pit_value_as_ref(rt, ent->name)))
+ ) {
+ i64 i = 0;
+ for (; i < h->in.bytes.len && i < len - 1; ++i) {
+ buf[i] = (char) h->in.bytes.data[i];
+ }
+ return i;
+ } else {
+ return pit_libc_string_snprintf(buf, (size_t) len, "<broken symbol %ld>", pit_value_as_symbol(rt, v));
+ }
+ }
+ case PIT_VALUE_SORT_REF: {
+ pit_ref r = pit_value_as_ref(rt, v);
+ char *end = buf + len;
+ char *start = buf;
+ h = pit_value_ref_deref(rt, r);
+ if (!h) pit_libc_string_snprintf(buf, (size_t) len, "<ref %ld>", r);
+ else {
+ switch (h->hsort) {
+ case PIT_VALUE_HEAVY_SORT_CELL: {
+ CHECK_BUF; *(buf++) = '{';
+ CHECK_BUF; buf += pit_dump(rt, buf, end - buf, pit_value_cons_car(rt, h->in.cell), readable);
+ CHECK_BUF; *(buf++) = '}';
+ return buf - start;
+ }
+ case PIT_VALUE_HEAVY_SORT_CONS: {
+ pit_value cur = v;
+ CHECK_BUF_LABEL(list_end);
+ do {
+ if (pit_value_is_cons(rt, cur)) {
+ CHECK_BUF_LABEL(list_end); *(buf++) = ' ';
+ CHECK_BUF_LABEL(list_end); buf += pit_dump(rt, buf, end - buf, pit_value_cons_car(rt, cur), readable);
+ } else {
+ CHECK_BUF_LABEL(list_end); buf += pit_libc_string_snprintf(buf, (size_t) (end - buf), " . ");
+ CHECK_BUF_LABEL(list_end); buf += pit_dump(rt, buf, end - buf, cur, readable);
+ }
+ } while (!pit_value_eq((cur = pit_value_cons_cdr(rt, cur)), PIT_NIL));
+ CHECK_BUF_LABEL(list_end); *(buf++) = ')';
+ list_end:
+ *start = '(';
+ return buf - start;
+ }
+ case PIT_VALUE_HEAVY_SORT_ARRAY: {
+ i64 i = 0;
+ CHECK_BUF_LABEL(array_end);
+ if (h->in.array.len == 0) {
+ CHECK_BUF_LABEL(array_end); *(buf++) = '[';
+ } else for (; i < h->in.array.len; ++i) {
+ CHECK_BUF_LABEL(array_end); *(buf++) = ' ';
+ CHECK_BUF_LABEL(array_end); buf += pit_dump(rt, buf, end - buf, h->in.array.data[i], readable);
+ }
+ CHECK_BUF_LABEL(array_end); *(buf++) = ']';
+ array_end:
+ *start = '[';
+ return buf - start;
+ }
+ case PIT_VALUE_HEAVY_SORT_BYTES: {
+ i64 i = 0;
+ if (readable) { CHECK_BUF; buf[i++] = '"'; }
+ i64 maxlen = len - i;
+ for (i64 j = 0; i < maxlen && j < h->in.bytes.len;) {
+ if (buf[i - 1] != '\\' && (h->in.bytes.data[j] == '\\' || h->in.bytes.data[j] == '"')) {
+ CHECK_BUF; buf[i++] = '\\';
+ }
+ else {
+ CHECK_BUF; buf[i++] = (char) h->in.bytes.data[j++];
+ }
+ }
+ if (readable && i < len - 1) buf[i++] = '"';
+ return i;
+ }
+ default:
+ return pit_libc_string_snprintf(buf, (size_t) len, "<ref %ld>", r);
+ }
+ }
+ break;
+ }
+ }
+ return 0;
+}
diff --git a/src/runtime/eval.c b/src/runtime/eval.c
new file mode 100644
index 0000000..f5eba97
--- /dev/null
+++ b/src/runtime/eval.c
@@ -0,0 +1,107 @@
+#include <lcq/pit/runtime/eval.h>
+
+pit_value pit_eval(pit_runtime *rt, pit_value top) {
+ i64 expr_stack_reset = rt->expr_stack->next;
+ i64 result_stack_reset = rt->result_stack->next;
+ i64 program_reset = rt->program->next;
+ // pit_vec_reset(pit_annotated_ref)(rt->backtrace);
+ if (pit_vec_push(pit_value)(rt->expr_stack, top) < 0)
+ pit_error(rt, "evaluation stack overflow");
+ /* first, convert the expression tree into "polish notation" in program */
+ while (rt->expr_stack->next > expr_stack_reset) {
+ pit_value cur = PIT_NIL;
+ if (rt->error != PIT_NIL) goto end;
+ if (pit_vec_pop(pit_value)(rt->expr_stack, &cur) < 0)
+ pit_error(rt, "evaluation stack underflow");
+ if (pit_value_is_cons(rt, cur)) { /* compound expressions: function/macro application special forms */
+ pit_value fsym = pit_value_cons_car(rt, cur);
+ bool is_symbol = pit_value_is_symbol(rt, fsym);
+ pit_annotated_ref *ann = pit_annotation_get(rt, pit_value_as_ref(rt, cur));
+ if (is_symbol && pit_symtab_is_symbol_special_form(rt, fsym)) { /* special forms */
+ pit_value f = pit_symtab_fget(rt, fsym);
+ pit_value args = pit_value_cons_cdr(rt, cur);
+ /* special forms are nativefuncs that directly manipulate the stacks
+ basically macros, but we don't need to evaluate the return value */
+ pit_value_apply(rt, f, args);
+ } else if (is_symbol && pit_symtab_is_symbol_macro(rt, fsym)) { /* macros */
+ pit_value f = pit_symtab_fget(rt, fsym);
+ pit_value args = pit_value_cons_cdr(rt, cur);
+ pit_value res = pit_value_apply(rt, f, args);
+ if (pit_vec_push(pit_value)(rt->expr_stack, res) < 0)
+ pit_error(rt, "evaluation stack overflow");
+ } else { /* normal functions */
+ pit_value args = pit_value_cons_cdr(rt, cur);
+ i64 argcount = 0;
+ while (args != PIT_NIL) {
+ if (pit_vec_push(pit_value)(rt->expr_stack, pit_value_cons_car(rt, args)) < 0)
+ pit_error(rt, "evaluation stack overflow");
+ args = pit_value_cons_cdr(rt, args);
+ argcount += 1;
+ }
+ if (!is_symbol) {
+ if (pit_vec_push(pit_value)(rt->expr_stack, fsym) < 0)
+ pit_error(rt, "evaluation stack overflow");
+ }
+ pit_runtime_eval_program_push_apply(rt, rt->program, argcount, ann);
+ if (is_symbol) {
+ pit_value f = pit_symtab_fget(rt, fsym);
+ pit_runtime_eval_program_push_literal(rt, rt->program, f);
+ }
+ }
+ } else if (pit_value_is_symbol(rt, cur)) { /* unquoted symbols: variable lookup */
+ pit_symtab_entry *ent = pit_symtab_lookup(rt, cur);
+ if (ent->is_keyword) {
+ pit_runtime_eval_program_push_literal(rt, rt->program, cur);
+ } else {
+ pit_runtime_eval_program_push_literal(rt, rt->program, pit_symtab_get(rt, cur));
+ }
+ } else { /* other expressions evaluate to themselves! */
+ pit_runtime_eval_program_push_literal(rt, rt->program, cur);
+ }
+ }
+ /* then, execute the polish notation program from right to left
+ this has the nice consequence of putting the arguments in the right order */
+ for (i64 idx = rt->program->next - 1; idx >= program_reset; --idx) {
+ pit_runtime_eval_ins *ent = pit_vec_get(pit_runtime_eval_ins)(rt->program, idx);
+ if (ent == NULL) pit_error(rt, "evaluation program invalid");
+ if (rt->error != PIT_NIL) goto end;
+ switch (ent->sort) {
+ case PIT_RUNTIME_EVAL_INS_LITERAL:
+ if (pit_vec_push(pit_value)(rt->result_stack, ent->in.literal) < 0)
+ pit_error(rt, "evaluation result stack overflow");
+ break;
+ case PIT_RUNTIME_EVAL_INS_APPLY: {
+ pit_value f = PIT_NIL;
+ pit_value args = PIT_NIL;
+ if (pit_vec_pop(pit_value)(rt->result_stack, &f) < 0)
+ pit_error(rt, "evaluation result stack underflow");
+ for (i64 i = 0; i < ent->in.apply.arity; ++i) {
+ pit_value a = PIT_NIL;
+ if (pit_vec_pop(pit_value)(rt->result_stack, &a) < 0)
+ pit_error(rt, "evaluation result stack underflow");
+ args = pit_value_cons(rt, a, args);
+ }
+ if (ent->in.apply.annotation != NULL) {
+ rt->source_line = ent->in.apply.annotation->annotation.line;
+ rt->source_column = ent->in.apply.annotation->annotation.column;
+ pit_vec_push(pit_annotated_ref)(rt->backtrace, *ent->in.apply.annotation);
+ }
+ if (pit_vec_push(pit_value)(rt->result_stack, pit_value_apply(rt, f, args)) < 0)
+ pit_error(rt, "evaluation result stack underflow");
+ break;
+ }
+ default:
+ pit_error(rt, "unknown program entry");
+ goto end;
+ }
+ }
+end: {
+ pit_value ret = PIT_NIL;
+ if (pit_vec_pop(pit_value)(rt->result_stack, &ret) < 0)
+ pit_error(rt, "evaluation result stack underflow");
+ rt->expr_stack->next = expr_stack_reset;
+ rt->result_stack->next = result_stack_reset;
+ rt->program->next = program_reset;
+ return ret;
+ }
+}
diff --git a/src/runtime/gc.c b/src/runtime/gc.c
new file mode 100644
index 0000000..fcb5f89
--- /dev/null
+++ b/src/runtime/gc.c
@@ -0,0 +1,100 @@
+#include <lcq/pit/runtime/gc.h>
+
+static i64 gc_copy(pit_runtime *rt, pit_value_heavy *h) {
+ if (h->hsort == PIT_VALUE_HEAVY_SORT_FORWARDING_POINTER) {
+ return h->in.forwarding_pointer;
+ } else {
+ i64 ret = rt->backbuffer->next;
+ pit_value_heavy *g = pit_arena_alloc(rt->backbuffer);
+ *g = *h;
+ h->hsort = PIT_VALUE_HEAVY_SORT_FORWARDING_POINTER;
+ h->in.forwarding_pointer = ret;
+ return ret;
+ }
+}
+static pit_value gc_copy_value(pit_runtime *rt, pit_value v) {
+ if (pit_value_sort(v) == PIT_VALUE_SORT_REF) {
+ pit_ref r = pit_value_as_ref(rt, v);
+ pit_value_heavy *h = pit_value_ref_deref(rt, r);
+ i64 new = gc_copy(rt, h);
+ pit_annotated_ref *ann = pit_annotation_get(rt, r);
+ if (ann != NULL) {
+ pit_annotated_ref newann = *ann;
+ newann.ref = new;
+ if (pit_vec_push(pit_annotated_ref)(rt->backtrace, newann) < 0)
+ pit_error(rt, "annotation overflow");
+ }
+ return pit_value_ref_new(rt, new);
+ } else {
+ return v;
+ }
+}
+void pit_gc(pit_runtime *rt) {
+ rt->frozen_values = 0;
+ rt->frozen_symtab = 0;
+ pit_arena *fromspace = rt->heap;
+ pit_arena *tospace = rt->backbuffer;
+ pit_vec(pit_annotated_ref) *fromspace_ann = rt->annotations;
+ pit_vec(pit_annotated_ref) *tospace_ann = rt->backtrace;
+ pit_arena_reset(tospace);
+ pit_vec_reset(pit_annotated_ref)(tospace_ann);
+ /* populate tospace with immediately reachable values */
+ for (i64 i = 0; i < rt->symtab->next; ++i) {
+ pit_symtab_entry *ent = pit_vec_get(pit_symtab_entry)(rt->symtab, i);
+ if (ent == NULL) continue; /* TODO warn on failure here? */
+ ent->name = gc_copy_value(rt, ent->name);
+ ent->value = gc_copy_value(rt, ent->value);
+ ent->function = gc_copy_value(rt, ent->function);
+ }
+ for (i64 i = 0; i < rt->saved_bindings->next; ++i) {
+ pit_value *v = pit_vec_get(pit_value)(rt->saved_bindings, i);
+ if (v != NULL) *v = gc_copy_value(rt, *v); /* TODO warn on failure here? */
+ }
+ for (i64 scan = 0; scan < tospace->next; ++scan) {
+ pit_value_heavy *h = pit_arena_get(tospace, scan);
+ switch (h->hsort) {
+ case PIT_VALUE_HEAVY_SORT_CELL:
+ h->in.cell = gc_copy_value(rt, h->in.cell);
+ break;
+ case PIT_VALUE_HEAVY_SORT_CONS:
+ h->in.cons.car = gc_copy_value(rt, h->in.cons.car);
+ h->in.cons.cdr = gc_copy_value(rt, h->in.cons.cdr);
+ break;
+ case PIT_VALUE_HEAVY_SORT_ARRAY: {
+ i64 byte_len = 0; pit_mul(&byte_len, sizeof(pit_value), h->in.array.len);
+ pit_value *data = pit_arena_alloc_back(tospace, byte_len);
+ for (i64 i = 0; i < h->in.array.len; ++i) {
+ data[i] = gc_copy_value(rt, h->in.array.data[i]);
+ }
+ h->in.array.data = data;
+ break;
+ }
+ case PIT_VALUE_HEAVY_SORT_BYTES: {
+ u8 *data = pit_arena_alloc_back(tospace, h->in.bytes.len);
+ for (i64 i = 0; i < h->in.bytes.len; ++i) {
+ data[i] = h->in.bytes.data[i];
+ }
+ h->in.bytes.data = data;
+ break;
+ }
+ case PIT_VALUE_HEAVY_SORT_FUNC:
+ h->in.func.env = gc_copy_value(rt, h->in.func.env);
+ h->in.func.args = gc_copy_value(rt, h->in.func.args);
+ h->in.func.arg_rest_nm = gc_copy_value(rt, h->in.func.arg_rest_nm);
+ h->in.func.body = gc_copy_value(rt, h->in.func.body);
+ break;
+ case PIT_VALUE_HEAVY_SORT_NATIVEFUNC: break;
+ case PIT_VALUE_HEAVY_SORT_NATIVEDATA:
+ h->in.nativedata.tag = gc_copy_value(rt, h->in.nativedata.tag);
+ break;
+ case PIT_VALUE_HEAVY_SORT_FORWARDING_POINTER:
+ pit_error(rt, "garbage collection broken! encountered forwarding pointer in to-space");
+ break;
+ }
+ }
+ rt->heap = tospace;
+ rt->backbuffer = fromspace;
+ rt->annotations = tospace_ann;
+ rt->backtrace = fromspace_ann;
+ pit_vec_reset(pit_annotated_ref)(rt->backtrace);
+}
diff --git a/src/runtime/macroexpand.c b/src/runtime/macroexpand.c
new file mode 100644
index 0000000..13a4fdd
--- /dev/null
+++ b/src/runtime/macroexpand.c
@@ -0,0 +1,111 @@
+#include <lcq/pit/runtime/macroexpand.h>
+
+pit_value pit_macroexpand(pit_runtime *rt, pit_value top) {
+ i64 expr_stack_reset = rt->expr_stack->next;
+ i64 result_stack_reset = rt->result_stack->next;
+ i64 program_reset = rt->program->next;
+ if (pit_vec_push(pit_value)(rt->expr_stack, top) < 0)
+ pit_error(rt, "macro expansion stack overflow");
+ while (rt->expr_stack->next > expr_stack_reset) {
+ pit_value cur;
+ if (rt->error != PIT_NIL) goto end;
+ if (pit_vec_pop(pit_value)(rt->expr_stack, &cur) < 0)
+ pit_error(rt, "macro expansion stack underflow");
+ if (pit_value_is_cons(rt, cur)) {
+ pit_value fsym = pit_value_cons_car(rt, cur);
+ bool is_symbol = pit_value_is_symbol(rt, fsym);
+ pit_annotated_ref *ann = pit_annotation_get(rt, pit_value_as_ref(rt, cur));
+ if (is_symbol && pit_symtab_is_symbol_macro(rt, fsym)) {
+ pit_value f = pit_symtab_fget(rt, fsym);
+ pit_value args = pit_value_cons_cdr(rt, cur);
+ pit_value res = pit_value_apply(rt, f, args);
+ if (pit_vec_push(pit_value)(rt->expr_stack, res) < 0)
+ pit_error(rt, "macro expansion stack overflow");
+ } else if (is_symbol && pit_symtab_symbol_name_match_cstr(rt, fsym, "defer")) {
+ pit_value args = pit_value_cons_cdr(rt, cur);
+ pit_runtime_eval_program_push_literal(rt, rt->program, pit_value_cons_car(rt, args));
+ } else if (is_symbol && pit_symtab_symbol_name_match_cstr(rt, fsym, "quote")) {
+ pit_runtime_eval_program_push_literal(rt, rt->program, cur);
+ } else if (is_symbol && pit_symtab_symbol_name_match_cstr(rt, fsym, "lambda")) {
+ pit_value args = pit_value_cons_cdr(rt, cur);
+ pit_value bindings = pit_value_cons_car(rt, args);
+ pit_value body = pit_value_cons_cdr(rt, args);
+ i64 argcount = 0;
+ if (pit_vec_push(pit_value)(rt->expr_stack, pit_value_list(rt, 2, pit_symtab_intern_cstr(rt, "defer"), bindings)) < 0)
+ pit_error(rt, "macro expansion stack overflow");
+ while (body != PIT_NIL) {
+ pit_value a = pit_value_cons_car(rt, body);
+ if (pit_vec_push(pit_value)(rt->expr_stack, a) < 0)
+ pit_error(rt, "macro expansion stack overflow");
+ body = pit_value_cons_cdr(rt, body);
+ argcount += 1;
+ }
+ pit_runtime_eval_program_push_apply(rt, rt->program, argcount + 1, ann);
+ pit_runtime_eval_program_push_literal(rt, rt->program, fsym);
+ } else {
+ pit_value args = pit_value_cons_cdr(rt, cur);
+ i64 argcount = 0;
+ while (args != PIT_NIL) {
+ pit_value a = pit_value_cons_car(rt, args);
+ if (pit_vec_push(pit_value)(rt->expr_stack, a) < 0)
+ pit_error(rt, "macro expansion stack overflow");
+ args = pit_value_cons_cdr(rt, args);
+ argcount += 1;
+ }
+ if (!is_symbol) {
+ if (pit_vec_push(pit_value)(rt->expr_stack, fsym) < 0)
+ pit_error(rt, "macro expansion stack overflow");
+ }
+ pit_runtime_eval_program_push_apply(rt, rt->program, argcount, ann);
+ if (is_symbol) {
+ pit_runtime_eval_program_push_literal(rt, rt->program, fsym);
+ }
+ }
+ } else {
+ pit_runtime_eval_program_push_literal(rt, rt->program, cur);
+ }
+ }
+ for (i64 idx = rt->program->next - 1; idx >= program_reset; --idx) {
+ pit_runtime_eval_ins *ent = pit_vec_get(pit_runtime_eval_ins)(rt->program, idx);
+ if (ent == NULL) pit_error(rt, "macro expansion program invalid");
+ if (rt->error != PIT_NIL) goto end;
+ switch (ent->sort) {
+ case PIT_RUNTIME_EVAL_INS_LITERAL:
+ if (pit_vec_push(pit_value)(rt->result_stack, ent->in.literal) < 0)
+ pit_error(rt, "macro expansion stack overflow");
+ break;
+ case PIT_RUNTIME_EVAL_INS_APPLY: {
+ pit_value f = PIT_NIL;
+ pit_value args = PIT_NIL;
+ pit_value app = PIT_NIL;
+ if (pit_vec_pop(pit_value)(rt->result_stack, &f) < 0)
+ pit_error(rt, "macro expansion stack underflow");
+ for (i64 i = 0; i < ent->in.apply.arity; ++i) {
+ pit_value a;
+ if (pit_vec_pop(pit_value)(rt->result_stack, &a) < 0)
+ pit_error(rt, "macro expansion stack underflow");
+ args = pit_value_cons(rt, a, args);
+ }
+ app = pit_value_cons(rt, f, args);
+ if (ent->in.apply.annotation != NULL) {
+ pit_annotation_set(rt, pit_value_as_ref(rt, app), ent->in.apply.annotation->annotation);
+ }
+ if (pit_vec_push(pit_value)(rt->result_stack, app) < 0)
+ pit_error(rt, "macro expansion stack overflow");
+ break;
+ }
+ default:
+ pit_error(rt, "unknown program entry");
+ goto end;
+ }
+ }
+end: {
+ pit_value ret = PIT_NIL;
+ if (pit_vec_pop(pit_value)(rt->result_stack, &ret) < 0)
+ pit_error(rt, "macro expansion stack underflow");
+ rt->expr_stack->next = expr_stack_reset;
+ rt->result_stack->next = result_stack_reset;
+ rt->program->next = program_reset;
+ return ret;
+ }
+}
diff --git a/src/runtime/symtab.c b/src/runtime/symtab.c
new file mode 100644
index 0000000..d2bc51e
--- /dev/null
+++ b/src/runtime/symtab.c
@@ -0,0 +1,118 @@
+#include <lcq/pit/runtime/symtab.h>
+
+pit_symtab_entry *pit_symtab_lookup(pit_runtime *rt, pit_value sym) {
+ pit_symbol s = pit_value_as_symbol(rt, sym);
+ return pit_vec_get(pit_symtab_entry)(rt->symtab, s);
+}
+pit_value pit_symtab_intern(pit_runtime *rt, u8 *nm, i64 len) {
+ if (rt->error != PIT_NIL) return PIT_NIL;
+ for (i64 sidx = 0; sidx < rt->symtab->next; ++sidx) {
+ pit_symtab_entry *sent = pit_vec_get(pit_symtab_entry)(rt->symtab, sidx);
+ if (sent == NULL) { pit_error(rt, "corrupted symbol table"); return PIT_NIL; }
+ if (pit_value_bytes_match(rt, sent->name, nm, len)) return pit_value_symbol_new(rt, sidx);
+ }
+ pit_symtab_entry ent;
+ ent.name = pit_value_bytes_new(rt, nm, len);
+ ent.value = PIT_NIL;
+ ent.function = PIT_NIL;
+ ent.is_macro = false;
+ ent.is_special_form = false;
+ ent.is_keyword = len >= 1 && nm[0] == ':';
+ i64 idx = pit_vec_push(pit_symtab_entry)(rt->symtab, ent);
+ if (idx < 0) { pit_error(rt, "failed to allocate symtab entry"); return PIT_NIL; }
+ return pit_value_symbol_new(rt, idx);
+}
+pit_value pit_symtab_intern_cstr(pit_runtime *rt, char *nm) {
+ return pit_symtab_intern(rt, (u8 *) nm, (i64) pit_libc_string_strlen(nm));
+}
+pit_value pit_symtab_symbol_name(pit_runtime *rt, pit_value sym) {
+ pit_symtab_entry *ent = pit_symtab_lookup(rt, sym);
+ if (!ent) { pit_error(rt, "bad symbol"); return PIT_NIL; }
+ return ent->name;
+}
+bool pit_symtab_symbol_name_match(pit_runtime *rt, pit_value sym, u8 *buf, i64 len) {
+ pit_symtab_entry *ent = pit_symtab_lookup(rt, sym);
+ if (!ent) { pit_error(rt, "bad symbol"); return PIT_NIL; }
+ return pit_value_bytes_match(rt, ent->name, buf, len);
+}
+bool pit_symtab_symbol_name_match_cstr(pit_runtime *rt, pit_value sym, char *s) {
+ return pit_symtab_symbol_name_match(rt, sym, (u8 *) s, (i64) pit_libc_string_strlen(s));
+}
+pit_value pit_symtab_get_value_cell(pit_runtime *rt, pit_value sym) {
+ pit_symtab_entry *ent = pit_symtab_lookup(rt, sym);
+ if (!ent) { pit_error(rt, "bad symbol"); return PIT_NIL; }
+ return ent->value;
+}
+pit_value pit_symtab_get_function_cell(pit_runtime *rt, pit_value sym) {
+ pit_symtab_entry *ent = pit_symtab_lookup(rt, sym);
+ if (!ent) { pit_error(rt, "bad symbol"); return PIT_NIL; }
+ return ent->function;
+}
+pit_value pit_symtab_get(pit_runtime *rt, pit_value sym) {
+ return pit_value_cell_get(rt, pit_symtab_get_value_cell(rt, sym), sym);
+}
+void pit_symtab_set(pit_runtime *rt, pit_value sym, pit_value v) {
+ pit_symbol idx = pit_value_as_symbol(rt, sym);
+ if (idx < rt->frozen_symtab) { pit_error(rt, "attempted to modify frozen symbol"); return; }
+ pit_symtab_entry *ent = pit_symtab_lookup(rt, sym);
+ if (!ent) { pit_error(rt, "bad symbol"); return; }
+ if (pit_value_sort(ent->value) != PIT_VALUE_SORT_REF) {
+ ent->value = pit_value_cell_new(rt, PIT_NIL);
+ }
+ pit_value_cell_set(rt, ent->value, v, sym);
+}
+pit_value pit_symtab_fget(pit_runtime *rt, pit_value sym) {
+ return pit_value_cell_get(rt, pit_symtab_get_function_cell(rt, sym), sym);
+}
+void pit_symtab_fset(pit_runtime *rt, pit_value sym, pit_value v) {
+ pit_symbol idx = pit_value_as_symbol(rt, sym);
+ if (idx < rt->frozen_symtab) { pit_error(rt, "attempted to modify frozen symbol"); return; }
+ pit_symtab_entry *ent = pit_symtab_lookup(rt, sym);
+ if (!ent) { pit_error(rt, "bad symbol"); return; }
+ if (pit_value_sort(ent->function) != PIT_VALUE_SORT_REF) {
+ ent->function = pit_value_cell_new(rt, PIT_NIL);
+ }
+ pit_value_cell_set(rt, ent->function, v, sym);
+}
+bool pit_symtab_is_symbol_macro(pit_runtime *rt, pit_value sym) {
+ pit_symtab_entry *ent = pit_symtab_lookup(rt, sym);
+ if (!ent) { pit_error(rt, "bad symbol"); return false; }
+ return ent->is_macro;
+}
+void pit_symtab_symbol_mark_macro(pit_runtime *rt, pit_value sym) {
+ pit_symtab_entry *ent = pit_symtab_lookup(rt, sym);
+ if (!ent) { pit_error(rt, "bad symbol"); return; }
+ ent->is_macro = true;
+}
+void pit_symtab_mset(pit_runtime *rt, pit_value sym, pit_value v) {
+ pit_symtab_fset(rt, sym, v);
+ pit_symtab_symbol_mark_macro(rt, sym);
+}
+bool pit_symtab_is_symbol_special_form(pit_runtime *rt, pit_value sym) {
+ pit_symtab_entry *ent = pit_symtab_lookup(rt, sym);
+ if (!ent) { pit_error(rt, "bad symbol"); return false; }
+ return ent->is_special_form;
+}
+void pit_symtab_symbol_mark_special_form(pit_runtime *rt, pit_value sym) {
+ pit_symtab_entry *ent = pit_symtab_lookup(rt, sym);
+ if (!ent) { pit_error(rt, "bad symbol"); return; }
+ ent->is_special_form = true;
+}
+void pit_symtab_sfset(pit_runtime *rt, pit_value sym, pit_value v) {
+ pit_symtab_fset(rt, sym, v);
+ pit_symtab_symbol_mark_special_form(rt, sym);
+}
+void pit_symtab_bind(pit_runtime *rt, pit_value sym, pit_value cell) {
+ /* although we cannot set frozen symbols, we can still bind them temporarily - no need to check */
+ pit_symtab_entry *ent = pit_symtab_lookup(rt, sym);
+ if (!ent) { pit_error(rt, "bad symbol"); return; }
+ if (pit_vec_push(pit_value)(rt->saved_bindings, ent->value) < 0) pit_error(rt, "binding stack overflow");
+ ent->value = cell;
+}
+pit_value pit_symtab_unbind(pit_runtime *rt, pit_value sym) {
+ pit_symtab_entry *ent = pit_symtab_lookup(rt, sym);
+ if (!ent) { pit_error(rt, "bad symbol"); return PIT_NIL; }
+ pit_value old = ent->value;
+ if (pit_vec_pop(pit_value)(rt->saved_bindings, &ent->value) < 0) pit_error(rt, "binding stack underflow");
+ return old;
+}
diff --git a/src/runtime/value.c b/src/runtime/value.c
new file mode 100644
index 0000000..1e9d543
--- /dev/null
+++ b/src/runtime/value.c
@@ -0,0 +1,76 @@
+#include <lcq/pit/runtime/value.h>
+
+pit_value pit_value_new(pit_runtime *rt, enum pit_value_sort s, u64 data) {
+ if (s == PIT_VALUE_SORT_DOUBLE) {
+ /* if (((data >> 52) & 0b011111111111) == 0b011111111111 && ((data >> 51) & 0b1) == 0) { */
+ if (((data >> 52) & 0x7ff) == 0x7ff && ((data >> 51) & 1) == 0) {
+ pit_error(rt, "attempted to create a signalling NaN double");
+ return PIT_NIL;
+ }
+ return data;
+ }
+ return
+ /* 0b1111111111110000000000000000000000000000000000000000000000000000 */
+ 0xfff0000000000000
+ /* | (((u64) (s & 0b11)) << 49) */
+ | (((u64) (s & 3)) << 49)
+ /* | (data & 0b1111111111111111111111111111111111111111111111111); */
+ | (data & 0x1ffffffffffff);
+}
+
+bool pit_value_eq(pit_value a, pit_value b) {
+ return a == b;
+}
+
+bool pit_value_equal(pit_runtime *rt, pit_value a, pit_value b) {
+ if (pit_value_sort(a) != pit_value_sort(b)) return false;
+ switch (pit_value_sort(a)) {
+ case PIT_VALUE_SORT_DOUBLE:
+ case PIT_VALUE_SORT_INTEGER:
+ case PIT_VALUE_SORT_SYMBOL:
+ return pit_value_data(a) == pit_value_data(b);
+ case PIT_VALUE_SORT_REF: {
+ pit_value_heavy *ha = pit_value_ref_deref(rt, pit_value_as_ref(rt, a));
+ if (!ha) { pit_error(rt, "bad ref"); return false; }
+ pit_value_heavy *hb = pit_value_ref_deref(rt, pit_value_as_ref(rt, b));
+ if (!hb) { pit_error(rt, "bad ref"); return false; }
+ if (ha->hsort != hb->hsort) return false;
+ switch (ha->hsort) {
+ case PIT_VALUE_HEAVY_SORT_CELL:
+ return pit_value_equal(rt, ha->in.cell, hb->in.cell);
+ case PIT_VALUE_HEAVY_SORT_CONS:
+ return pit_value_equal(rt, ha->in.cons.car, hb->in.cons.car)
+ && pit_value_equal(rt, ha->in.cons.cdr, hb->in.cons.cdr);
+ case PIT_VALUE_HEAVY_SORT_ARRAY: {
+ if (ha->in.array.len != hb->in.array.len) return false;
+ for (i64 i = 0; i < ha->in.array.len; ++i) {
+ if (!pit_value_equal(rt, ha->in.array.data[i], hb->in.array.data[i])) return false;
+ }
+ return true;
+ }
+ case PIT_VALUE_HEAVY_SORT_BYTES: {
+ if (ha->in.bytes.len != hb->in.bytes.len) return false;
+ for (i64 i = 0; i < ha->in.bytes.len; ++i) {
+ if (ha->in.bytes.data[i] != hb->in.bytes.data[i]) return false;
+ }
+ return true;
+ }
+ case PIT_VALUE_HEAVY_SORT_FUNC:
+ return
+ pit_value_equal(rt, ha->in.func.env, hb->in.func.env)
+ && pit_value_equal(rt, ha->in.func.args, hb->in.func.args)
+ && pit_value_equal(rt, ha->in.func.body, hb->in.func.body);
+ case PIT_VALUE_HEAVY_SORT_NATIVEFUNC:
+ return ha->in.nativefunc.f == hb->in.nativefunc.f
+ && ha->in.nativefunc.data == hb->in.nativefunc.data;
+ case PIT_VALUE_HEAVY_SORT_NATIVEDATA:
+ return
+ pit_value_eq(ha->in.nativedata.tag, hb->in.nativedata.tag)
+ && ha->in.nativedata.data == hb->in.nativedata.data;
+ case PIT_VALUE_HEAVY_SORT_FORWARDING_POINTER:
+ return ha->in.forwarding_pointer == hb->in.forwarding_pointer;
+ }
+ }
+ }
+ return false;
+}
diff --git a/src/runtime/value/array.c b/src/runtime/value/array.c
new file mode 100644
index 0000000..1af84fd
--- /dev/null
+++ b/src/runtime/value/array.c
@@ -0,0 +1,57 @@
+#include <lcq/pit/runtime/value/array.h>
+
+bool pit_value_is_array(pit_runtime *rt, pit_value a) {
+ return pit_value_is_ref_heavy_sort(rt, a, PIT_VALUE_HEAVY_SORT_ARRAY);
+}
+
+pit_value pit_value_array_new(pit_runtime *rt, i64 len) {
+ if (len < 0) { pit_error(rt, "failed to create array of negative size"); return PIT_NIL; }
+ i64 byte_len = 0; pit_mul(&byte_len, sizeof(pit_value), len);
+ pit_value *dest = pit_arena_alloc_array(rt->heap, byte_len);
+ if (!dest) { pit_error(rt, "failed to allocate array"); return PIT_NIL; }
+ for (i64 i = 0; i < len; ++i) dest[i] = PIT_NIL;
+ pit_value ret = pit_value_ref_heavy_new(rt);
+ pit_value_heavy *h = pit_value_ref_deref(rt, pit_value_as_ref(rt, ret));
+ if (!h) { pit_error(rt, "failed to create new heavy value for array"); return PIT_NIL; }
+ h->hsort = PIT_VALUE_HEAVY_SORT_ARRAY;
+ h->in.array.data = dest;
+ h->in.array.len = len;
+ return ret;
+}
+pit_value pit_value_array_from_buf(pit_runtime *rt, pit_value *xs, i64 len) {
+ pit_value ret = pit_value_array_new(rt, len);
+ pit_value_heavy *h = pit_value_ref_deref(rt, pit_value_as_ref(rt, ret));
+ if (!h) { pit_error(rt, "failed to deref heavy value for array"); return PIT_NIL; }
+ pit_libc_string_memcpy((u8 *) h->in.array.data, (u8 *) xs, (size_t) len * (size_t) sizeof(pit_value));
+ return ret;
+}
+i64 pit_value_array_len(pit_runtime *rt, pit_value arr) {
+ if (pit_value_sort(arr) != PIT_VALUE_SORT_REF) { pit_error(rt, "not a ref"); return -1; }
+ pit_value_heavy *h = pit_value_ref_deref(rt, pit_value_as_ref(rt, arr));
+ if (!h) { pit_error(rt, "bad ref"); return -1; }
+ if (h->hsort != PIT_VALUE_HEAVY_SORT_ARRAY) { pit_error(rt, "not an array"); return -1; }
+ return h->in.array.len;
+}
+pit_value pit_value_array_get(pit_runtime *rt, pit_value arr, i64 idx) {
+ if (pit_value_sort(arr) != PIT_VALUE_SORT_REF) { pit_error(rt, "not a ref"); return PIT_NIL; }
+ pit_value_heavy *h = pit_value_ref_deref(rt, pit_value_as_ref(rt, arr));
+ if (!h) { pit_error(rt, "bad ref"); return PIT_NIL; }
+ if (h->hsort != PIT_VALUE_HEAVY_SORT_ARRAY) { pit_error(rt, "not an array"); return PIT_NIL; }
+ if (idx < 0 || idx >= h->in.array.len) {
+ pit_error(rt, "array index out of bounds: %d", idx);
+ return PIT_NIL;
+ }
+ return h->in.array.data[idx];
+}
+pit_value pit_value_array_set(pit_runtime *rt, pit_value arr, i64 idx, pit_value v) {
+ if (pit_value_sort(arr) != PIT_VALUE_SORT_REF) { pit_error(rt, "not a ref"); return PIT_NIL; }
+ pit_value_heavy *h = pit_value_ref_deref(rt, pit_value_as_ref(rt, arr));
+ if (!h) { pit_error(rt, "bad ref"); return PIT_NIL; }
+ if (h->hsort != PIT_VALUE_HEAVY_SORT_ARRAY) { pit_error(rt, "not an array"); return PIT_NIL; }
+ if (idx < 0 || idx >= h->in.array.len) {
+ pit_error(rt, "array index out of bounds: %d", idx);
+ return PIT_NIL;
+ }
+ h->in.array.data[idx] = v;
+ return v;
+}
diff --git a/src/runtime/value/bytes.c b/src/runtime/value/bytes.c
new file mode 100644
index 0000000..6a6edb6
--- /dev/null
+++ b/src/runtime/value/bytes.c
@@ -0,0 +1,47 @@
+#include <lcq/pit/runtime/value/bytes.h>
+
+bool pit_value_is_bytes(pit_runtime *rt, pit_value a) {
+ return pit_value_is_ref_heavy_sort(rt, a, PIT_VALUE_HEAVY_SORT_BYTES);
+}
+pit_value pit_value_bytes_new(pit_runtime *rt, u8 *buf, i64 len) {
+ u8 *dest = pit_arena_alloc_back(rt->heap, len);
+ if (!dest) { pit_error(rt, "failed to allocate bytes"); return PIT_NIL; }
+ pit_libc_string_memcpy(dest, buf, (size_t) len);
+ pit_value ret = pit_value_ref_heavy_new(rt);
+ pit_value_heavy *h = pit_value_ref_deref(rt, pit_value_as_ref(rt, ret));
+ if (!h) { pit_error(rt, "failed to create new heavy value for bytes"); return PIT_NIL; }
+ h->hsort = PIT_VALUE_HEAVY_SORT_BYTES;
+ h->in.bytes.data = dest;
+ h->in.bytes.len = len;
+ return ret;
+}
+pit_value pit_value_bytes_new_cstr(pit_runtime *rt, char *s) {
+ return pit_value_bytes_new(rt, (u8 *) s, (i64) pit_libc_string_strlen(s));
+}
+/* return true if v is a reference to bytes that are the same as those in buf */
+bool pit_value_bytes_match(pit_runtime *rt, pit_value v, u8 *buf, i64 len) {
+ if (pit_value_sort(v) != PIT_VALUE_SORT_REF) return false;
+ pit_value_heavy *h = pit_value_ref_deref(rt, pit_value_as_ref(rt, v));
+ if (!h) { pit_error(rt, "bad ref"); return false; }
+ if (h->hsort != PIT_VALUE_HEAVY_SORT_BYTES) return false;
+ if (h->in.bytes.len != len) return false;
+ for (i64 i = 0; i < len; ++i)
+ if (h->in.bytes.data[i] != buf[i]) {
+ return false;
+ }
+ return true;
+}
+i64 pit_value_bytes_copy(pit_runtime *rt, pit_value v, u8 *buf, i64 maxlen) {
+ if (pit_value_sort(v) != PIT_VALUE_SORT_REF) { pit_error(rt, "not a ref"); return -1; }
+ pit_value_heavy *h = pit_value_ref_deref(rt, pit_value_as_ref(rt, v));
+ if (!h) { pit_error(rt, "bad ref"); return -1; }
+ if (h->hsort != PIT_VALUE_HEAVY_SORT_BYTES) {
+ pit_error(rt, "invalid use of value as bytes");
+ return -1;
+ }
+ i64 len = maxlen < h->in.bytes.len ? maxlen : h->in.bytes.len;
+ for (i64 i = 0; i < len; ++i) {
+ buf[i] = h->in.bytes.data[i];
+ }
+ return len;
+}
diff --git a/src/runtime/value/cell.c b/src/runtime/value/cell.c
new file mode 100644
index 0000000..34b9226
--- /dev/null
+++ b/src/runtime/value/cell.c
@@ -0,0 +1,47 @@
+#include <lcq/pit/runtime/value/cell.h>
+
+bool pit_value_is_cell(pit_runtime *rt, pit_value a) {
+ return pit_value_is_ref_heavy_sort(rt, a, PIT_VALUE_HEAVY_SORT_CELL);
+}
+pit_value pit_value_cell_new(pit_runtime *rt, pit_value v) {
+ pit_value ret = pit_value_ref_heavy_new(rt);
+ pit_value_heavy *h = pit_value_ref_deref(rt, pit_value_as_ref(rt, ret));
+ if (!h) { pit_error(rt, "failed to create new heavy value for cell"); return PIT_NIL; }
+ h->hsort = PIT_VALUE_HEAVY_SORT_CELL;
+ h->in.cell = v;
+ return ret;
+}
+pit_value pit_value_cell_get(pit_runtime *rt, pit_value cell, pit_value sym) {
+ if (pit_value_sort(cell) != PIT_VALUE_SORT_REF) {
+ char buf[256];
+ i64 end = pit_dump(rt, buf, sizeof(buf) - 1, sym, false);
+ buf[end] = 0;
+ pit_error(rt, "attempted to get unbound variable/function: %s", buf);
+ return PIT_NIL;
+ }
+ pit_value_heavy *h = pit_value_ref_deref(rt, pit_value_as_ref(rt, cell));
+ if (!h) { pit_error(rt, "bad ref"); return PIT_NIL; }
+ if (h->hsort != PIT_VALUE_HEAVY_SORT_CELL) {
+ pit_error(rt, "cell value ref does not point to cell");
+ return PIT_NIL;
+ }
+ return h->in.cell;
+}
+void pit_value_cell_set(pit_runtime *rt, pit_value cell, pit_value v, pit_value sym) {
+ if (pit_value_sort(cell) != PIT_VALUE_SORT_REF) {
+ char buf[256];
+ i64 end = pit_dump(rt, buf, sizeof(buf) - 1, sym, false);
+ buf[end] = 0;
+ pit_error(rt, "attempted to set unbound variable/function: %s", buf);
+ return;
+ }
+ pit_ref idx = pit_value_as_ref(rt, cell);
+ if (idx < rt->frozen_values) { pit_error(rt, "attempt to modify frozen cell"); return; }
+ pit_value_heavy *h = pit_value_ref_deref(rt, idx);
+ if (!h) { pit_error(rt, "bad ref"); return; }
+ if (h->hsort != PIT_VALUE_HEAVY_SORT_CELL) {
+ pit_error(rt, "cell value ref does not point to cell");
+ return;
+ }
+ h->in.cell = v;
+}
diff --git a/src/runtime/value/cons.c b/src/runtime/value/cons.c
new file mode 100644
index 0000000..0f35631
--- /dev/null
+++ b/src/runtime/value/cons.c
@@ -0,0 +1,110 @@
+#include <lcq/pit/runtime/value/cons.h>
+
+bool pit_value_is_cons(pit_runtime *rt, pit_value a) {
+ return pit_value_is_ref_heavy_sort(rt, a, PIT_VALUE_HEAVY_SORT_CONS);
+}
+pit_value pit_value_cons(pit_runtime *rt, pit_value car, pit_value cdr) {
+ pit_value ret = pit_value_ref_heavy_new(rt);
+ pit_value_heavy *h = pit_value_ref_deref(rt, pit_value_as_ref(rt, ret));
+ if (!h) { pit_error(rt, "failed to create new heavy value for cons"); return PIT_NIL; }
+ h->hsort = PIT_VALUE_HEAVY_SORT_CONS;
+ h->in.cons.car = car;
+ h->in.cons.cdr = cdr;
+ return ret;
+}
+pit_value pit_value_cons_car(pit_runtime *rt, pit_value v) {
+ if (pit_value_sort(v) != PIT_VALUE_SORT_REF) return PIT_NIL;
+ pit_value_heavy *h = pit_value_ref_deref(rt, pit_value_as_ref(rt, v));
+ if (!h) { pit_error(rt, "bad ref"); return PIT_NIL; }
+ if (h->hsort != PIT_VALUE_HEAVY_SORT_CONS) return PIT_NIL;
+ return h->in.cons.car;
+}
+pit_value pit_value_cons_cdr(pit_runtime *rt, pit_value v) {
+ if (pit_value_sort(v) != PIT_VALUE_SORT_REF) return PIT_NIL;
+ pit_value_heavy *h = pit_value_ref_deref(rt, pit_value_as_ref(rt, v));
+ if (!h) { pit_error(rt, "bad ref"); return PIT_NIL; }
+ if (h->hsort != PIT_VALUE_HEAVY_SORT_CONS) return PIT_NIL;
+ return h->in.cons.cdr;
+}
+void pit_value_cons_setcar(pit_runtime *rt, pit_value v, pit_value x) {
+ if (pit_value_sort(v) != PIT_VALUE_SORT_REF) { pit_error(rt, "not a ref"); return; }
+ pit_ref idx = pit_value_as_ref(rt, v);
+ if (idx < rt->frozen_values) { pit_error(rt, "attempted to modify frozen cons"); return; }
+ pit_value_heavy *h = pit_value_ref_deref(rt, idx);
+ if (!h) { pit_error(rt, "bad ref"); return; }
+ if (h->hsort != PIT_VALUE_HEAVY_SORT_CONS) { pit_error(rt, "not a cons"); return; }
+ h->in.cons.car = x;
+}
+void pit_value_cons_setcdr(pit_runtime *rt, pit_value v, pit_value x) {
+ if (pit_value_sort(v) != PIT_VALUE_SORT_REF) { pit_error(rt, "not a ref"); return; }
+ pit_ref idx = pit_value_as_ref(rt, v);
+ if (idx < rt->frozen_values) { pit_error(rt, "attempted to modify frozen cons"); return; }
+ pit_value_heavy *h = pit_value_ref_deref(rt, idx);
+ if (!h) { pit_error(rt, "bad ref"); return; }
+ if (h->hsort != PIT_VALUE_HEAVY_SORT_CONS) { pit_error(rt, "not a cons"); return; }
+ h->in.cons.cdr = x;
+}
+
+pit_value pit_value_list(pit_runtime *rt, i64 num, ...) {
+ pit_value temp[64] = {0};
+ pit_value ret = PIT_NIL;
+ if (num > 64) { pit_error(rt, "failed to create list of size %d\n", num); return PIT_NIL; }
+ va_list elems;
+ va_start(elems, num);
+ for (i64 i = 0; i < num; ++i) {
+ temp[i] = va_arg(elems, pit_value);
+ }
+ va_end(elems);
+ for (i64 i = 0; i < num; ++i) {
+ ret = pit_value_cons(rt, temp[num - i - 1], ret);
+ }
+ return ret;
+}
+i64 pit_value_list_len(pit_runtime *rt, pit_value xs) {
+ i64 ret = 0;
+ while (xs != PIT_NIL) {
+ ret += 1;
+ xs = pit_value_cons_cdr(rt, xs);
+ }
+ return ret;
+}
+pit_value pit_value_list_append(pit_runtime *rt, pit_value xs, pit_value ys) {
+ pit_value ret = ys;
+ xs = pit_value_list_reverse(rt, xs);
+ while (xs != PIT_NIL) {
+ ret = pit_value_cons(rt, pit_value_cons_car(rt, xs), ret);
+ xs = pit_value_cons_cdr(rt, xs);
+ }
+ return ret;
+}
+pit_value pit_value_list_reverse(pit_runtime *rt, pit_value xs) {
+ pit_value ret = PIT_NIL;
+ while (xs != PIT_NIL) {
+ ret = pit_value_cons(rt, pit_value_cons_car(rt, xs), ret);
+ xs = pit_value_cons_cdr(rt, xs);
+ }
+ return ret;
+}
+pit_value pit_value_list_contains_eq(pit_runtime *rt, pit_value needle, pit_value haystack) {
+ while (haystack != PIT_NIL) {
+ if (pit_value_eq(needle, pit_value_cons_car(rt, haystack))) return PIT_T;
+ haystack = pit_value_cons_cdr(rt, haystack);
+ }
+ return PIT_NIL;
+}
+pit_value pit_value_list_contains_equal(pit_runtime *rt, pit_value needle, pit_value haystack) {
+ while (haystack != PIT_NIL) {
+ if (pit_value_equal(rt, needle, pit_value_cons_car(rt, haystack))) return PIT_T;
+ haystack = pit_value_cons_cdr(rt, haystack);
+ }
+ return PIT_NIL;
+}
+pit_value pit_value_list_plist_get(pit_runtime *rt, pit_value k, pit_value vs) {
+ while (vs != PIT_NIL) {
+ if (pit_value_eq(k, pit_value_cons_car(rt, vs))) {
+ return pit_value_cons_car(rt, pit_value_cons_cdr(rt, vs));
+ }
+ vs = pit_value_cons_cdr(rt, vs);
+ }
+ return PIT_NIL;
+}
diff --git a/src/runtime/value/func.c b/src/runtime/value/func.c
new file mode 100644
index 0000000..af039eb
--- /dev/null
+++ b/src/runtime/value/func.c
@@ -0,0 +1,177 @@
+#include <lcq/pit/runtime/value/func.h>
+
+static pit_value free_vars(pit_runtime *rt, pit_value initial_bound, pit_value body) {
+ i64 expr_stack_reset = rt->expr_stack->next;
+ pit_value ret = PIT_NIL;
+ if (pit_vec_push(pit_value)(rt->expr_stack, pit_value_cons(rt, initial_bound, body)) < 0) {
+ pit_error(rt, "free variable search stack overflow");
+ return PIT_NIL;
+ }
+ while (rt->expr_stack->next > expr_stack_reset) {
+ pit_value boundscur, bound, cur;
+ if (pit_vec_pop(pit_value)(rt->expr_stack, &boundscur) < 0) {
+ pit_error(rt, "free variable search stack underflow");
+ return PIT_NIL;
+ }
+ bound = pit_value_cons_car(rt, boundscur);
+ cur = pit_value_cons_cdr(rt, boundscur);
+ if (pit_value_is_cons(rt, cur)) {
+ pit_value fsym = pit_value_cons_car(rt, cur);
+ bool is_symbol = pit_value_is_symbol(rt, fsym);
+ pit_value fargs = pit_value_cons_cdr(rt, cur);
+ if (is_symbol && pit_symtab_symbol_name_match_cstr(rt, fsym, "lambda")) {
+ pit_value new_bound = pit_value_list_append(rt, pit_value_cons_car(rt, fargs), bound);
+ fargs = pit_value_cons_cdr(rt, fargs);
+ while (fargs != PIT_NIL) {
+ if (pit_vec_push(pit_value)(rt->expr_stack, pit_value_cons(rt, new_bound, pit_value_cons_car(rt, fargs))) < 0) {
+ pit_error(rt, "free variable search stack overflow");
+ return PIT_NIL;
+ }
+ fargs = pit_value_cons_cdr(rt, fargs);
+ }
+ } else if (is_symbol && pit_symtab_symbol_name_match_cstr(rt, fsym, "quote")) {
+ /* don't look inside quote!
+ if we add other special forms, make sure to consider them here if necessary! */
+ } else {
+ while (fargs != PIT_NIL) {
+ if (pit_vec_push(pit_value)(rt->expr_stack, pit_value_cons(rt, bound, pit_value_cons_car(rt, fargs))) < 0) {
+ pit_error(rt, "free variable search stack overflow");
+ return PIT_NIL;
+ }
+ fargs = pit_value_cons_cdr(rt, fargs);
+ }
+ if (!is_symbol) {
+ if (pit_vec_push(pit_value)(rt->expr_stack, pit_value_cons(rt, bound, fsym)) < 0) {
+ pit_error(rt, "free variable search stack overflow");
+ return PIT_NIL;
+ }
+ }
+ }
+ } else if (pit_value_is_symbol(rt, cur)) {
+ if (pit_value_list_contains_eq(rt, cur, bound) == PIT_NIL) {
+ ret = pit_value_cons(rt, cur, ret);
+ }
+ }
+ }
+ rt->expr_stack->next = expr_stack_reset;
+ return ret;
+}
+
+bool pit_value_is_func(pit_runtime *rt, pit_value a) {
+ return pit_value_is_ref_heavy_sort(rt, a, PIT_VALUE_HEAVY_SORT_FUNC);
+}
+bool pit_value_is_nativefunc(pit_runtime *rt, pit_value a) {
+ return pit_value_is_ref_heavy_sort(rt, a, PIT_VALUE_HEAVY_SORT_NATIVEFUNC);
+}
+pit_value pit_value_func_lambda(pit_runtime *rt, pit_value args, pit_value body) {
+ pit_value ret = pit_value_ref_heavy_new(rt);
+ pit_value_heavy *h = pit_value_ref_deref(rt, pit_value_as_ref(rt, ret));
+ if (!h) { pit_error(rt, "failed to create new heavy value for lambda"); return PIT_NIL; }
+ pit_value expanded = pit_macroexpand(rt, pit_value_cons(rt, pit_symtab_intern_cstr(rt, "progn"), body));
+ pit_value freevars = free_vars(rt, args, expanded);
+ pit_value env = PIT_NIL;
+ while (freevars != PIT_NIL) {
+ pit_value sym = pit_value_cons_car(rt, freevars);
+ pit_value cell = pit_symtab_get_value_cell(rt, sym);
+ env = pit_value_cons(rt, pit_value_cons(rt, sym, cell), env);
+ freevars = pit_value_cons_cdr(rt, freevars);
+ }
+ h->hsort = PIT_VALUE_HEAVY_SORT_FUNC;
+ pit_value arg_cells = PIT_NIL;
+ pit_value arg_rest_nm = PIT_NIL;
+ pit_value separator = pit_symtab_intern_cstr(rt, "&");
+ while (args != PIT_NIL) {
+ pit_value nm = pit_value_cons_car(rt, args);
+ if (pit_value_eq(nm, separator)) {
+ pit_value next_nm = pit_value_cons_car(rt, pit_value_cons_cdr(rt, args));
+ if (next_nm == PIT_NIL) { pit_error(rt, "invalid & in lambda list"); return PIT_NIL; }
+ arg_rest_nm = next_nm;
+ arg_cells = pit_value_cons(rt, next_nm, arg_cells);
+ break;
+ } else {
+ arg_cells = pit_value_cons(rt, nm, arg_cells);
+ args = pit_value_cons_cdr(rt, args);
+ }
+ }
+ arg_cells = pit_value_list_reverse(rt, arg_cells);
+ h->in.func.args = arg_cells;
+ h->in.func.arg_rest_nm = arg_rest_nm;
+ h->in.func.env = env;
+ h->in.func.body = expanded;
+ return ret;
+}
+pit_value pit_value_nativefunc_new_with_data(pit_runtime *rt, pit_nativefunc f, void *data) {
+ pit_value ret = pit_value_ref_heavy_new(rt);
+ pit_value_heavy *h = pit_value_ref_deref(rt, pit_value_as_ref(rt, ret));
+ if (!h) { pit_error(rt, "failed to create new heavy value for nativefunc"); return PIT_NIL; }
+ h->hsort = PIT_VALUE_HEAVY_SORT_NATIVEFUNC;
+ h->in.nativefunc.f = f;
+ h->in.nativefunc.data = data;
+ return ret;
+}
+pit_value pit_value_nativefunc_new(pit_runtime *rt, pit_nativefunc f) {
+ return pit_value_nativefunc_new_with_data(rt, f, NULL);
+}
+pit_value pit_value_apply(pit_runtime *rt, pit_value f, pit_value args) {
+ char buf[256] = {0};
+ if (pit_value_is_symbol(rt, f)) {
+ f = pit_symtab_fget(rt, f);
+ }
+ /* if f is not a symbol, assume it is a func or nativefunc
+ most commonly, this happens when you funcall a variable
+ with a function in the value cell, e.g. passing a lambda to a function */
+ switch (pit_value_sort(f)) {
+ case PIT_VALUE_SORT_REF: {
+ pit_value_heavy *h = pit_value_ref_deref(rt, pit_value_as_ref(rt, f));
+ if (!h) { pit_error(rt, "bad ref"); return PIT_NIL; }
+ if (h->hsort == PIT_VALUE_HEAVY_SORT_FUNC) {
+ /* calling a Lisp function is simple! */
+ pit_value bound = PIT_NIL;
+ pit_value env = h->in.func.env;
+ while (env != PIT_NIL) { /* first, bind all entries in the closure */
+ pit_value b = pit_value_cons_car(rt, env);
+ pit_value nm = pit_value_cons_car(rt, b);
+ pit_symtab_bind(rt, nm, pit_value_cons_cdr(rt, b));
+ bound = pit_value_cons(rt, nm, bound);
+ env = pit_value_cons_cdr(rt, env);
+ }
+ pit_value anames = h->in.func.args;
+ while (anames != PIT_NIL) { /* bind all argument names to their values */
+ pit_value nm = pit_value_cons_car(rt, anames);
+ pit_value cell = pit_value_cell_new(rt, PIT_NIL);
+ if (h->in.func.arg_rest_nm != PIT_NIL && pit_value_eq(nm, h->in.func.arg_rest_nm)) {
+ pit_value_cell_set(rt, cell, args, nm);
+ pit_symtab_bind(rt, nm, cell);
+ break;
+ } else {
+ pit_value_cell_set(rt, cell, pit_value_cons_car(rt, args), nm);
+ pit_symtab_bind(rt, nm, cell);
+ }
+ bound = pit_value_cons(rt, nm, bound);
+ args = pit_value_cons_cdr(rt, args);
+ anames = pit_value_cons_cdr(rt, anames);
+ }
+ pit_value ret = pit_eval(rt, h->in.func.body); /* evaluate the body */
+ while (bound != PIT_NIL) { /* unbind everything we bound earlier, in reverse */
+ pit_symtab_unbind(rt, pit_value_cons_car(rt, bound));
+ bound = pit_value_cons_cdr(rt, bound);
+ }
+ return ret;
+ } else if (h->hsort == PIT_VALUE_HEAVY_SORT_NATIVEFUNC) {
+ /* calling native functions is even simpler */
+ return h->in.nativefunc.f(rt, args, h->in.nativefunc.data);
+ } else {
+ i64 end = pit_dump(rt, buf, sizeof(buf) - 1, f, true);
+ buf[end] = 0;
+ pit_error(rt, "attempted to apply non-function ref: %s", buf);
+ return PIT_NIL;
+ }
+ }
+ default: {
+ i64 end = pit_dump(rt, buf, sizeof(buf) - 1, f, true);
+ buf[end] = 0;
+ pit_error(rt, "attempted to apply non-function value: %s", buf);
+ return PIT_NIL;
+ }
+ }
+}
diff --git a/src/runtime/value/nativedata.c b/src/runtime/value/nativedata.c
new file mode 100644
index 0000000..5c6fe2b
--- /dev/null
+++ b/src/runtime/value/nativedata.c
@@ -0,0 +1,36 @@
+#include <lcq/pit/runtime/value/nativedata.h>
+
+bool pit_value_is_nativedata(pit_runtime *rt, pit_value a) {
+ return pit_value_is_ref_heavy_sort(rt, a, PIT_VALUE_HEAVY_SORT_NATIVEDATA);
+}
+pit_value pit_value_nativedata_new(pit_runtime *rt, pit_value tag, void *d) {
+ pit_value ret = pit_value_ref_heavy_new(rt);
+ pit_value_heavy *h = pit_value_ref_deref(rt, pit_value_as_ref(rt, ret));
+ if (!h) { pit_error(rt, "failed to create new heavy value for nativedata"); return PIT_NIL; }
+ h->hsort = PIT_VALUE_HEAVY_SORT_NATIVEDATA;
+ h->in.nativedata.tag = tag;
+ h->in.nativedata.data = d;
+ return ret;
+}
+void *pit_value_nativedata_get(pit_runtime *rt, pit_value tag, pit_value v) {
+ pit_value_heavy *h = NULL;
+ if (pit_value_sort(v) != PIT_VALUE_SORT_REF) {
+ pit_error(rt, "value was not a reference");
+ return NULL;
+ }
+ h = pit_value_ref_deref(rt, pit_value_as_ref(rt, v));
+ if (!h) { pit_error(rt, "bad ref"); return NULL; }
+ if (h->hsort != PIT_VALUE_HEAVY_SORT_NATIVEDATA) {
+ pit_error(rt, "invalid use of value as nativedata");
+ return NULL;
+ }
+ if (!pit_value_eq(h->in.nativedata.tag, tag)) {
+ pit_error(rt, "native value does not match tag");
+ return NULL;
+ }
+ if (!h->in.nativedata.data) {
+ pit_error(rt, "nativedata was already freed");
+ return NULL;
+ }
+ return h->in.nativedata.data;
+}
diff --git a/src/runtime/value/small.c b/src/runtime/value/small.c
new file mode 100644
index 0000000..f07e405
--- /dev/null
+++ b/src/runtime/value/small.c
@@ -0,0 +1,96 @@
+#include <lcq/pit/runtime/value/small.h>
+
+#ifndef PIT_NO_DOUBLE
+double pit_value_as_double(pit_runtime *rt, pit_value v) {
+ if (pit_value_sort(v) != PIT_VALUE_SORT_DOUBLE) {
+ pit_error(rt, "invalid use of value as double");
+ return 0.0;
+ }
+ union { double dval; u64 ival; } x;
+ x.ival = v;
+ return x.dval;
+}
+bool pit_value_is_double(pit_runtime *rt, pit_value a) {
+ (void) rt;
+ return pit_value_sort(a) == PIT_VALUE_SORT_DOUBLE;
+}
+pit_value pit_value_double_new(pit_runtime *rt, double d) {
+ union { double dval; u64 ival; } x;
+ x.dval = d;
+ return pit_value_new(rt, PIT_VALUE_SORT_DOUBLE, x.ival);
+}
+#endif
+
+i64 pit_value_as_integer(pit_runtime *rt, pit_value v) {
+ if (pit_value_sort(v) != PIT_VALUE_SORT_INTEGER) {
+ pit_error(rt, "invalid use of value as integer");
+ return -1;
+ }
+ u64 lo = pit_value_data(v);
+ return ((i64) (lo << 15)) >> 15; /* sign-extend low 49 bits */
+
+}
+bool pit_value_is_integer(pit_runtime *rt, pit_value a) {
+ (void) rt;
+ return pit_value_sort(a) == PIT_VALUE_SORT_INTEGER;
+}
+pit_value pit_value_integer_new(pit_runtime *rt, i64 i) {
+ return pit_value_new(rt, PIT_VALUE_SORT_INTEGER, 0x1ffffffffffff & (u64) i);
+}
+pit_value pit_value_bool_new(pit_runtime *rt, bool i) {
+ (void) rt;
+ return i ? PIT_T : PIT_NIL;
+}
+
+pit_symbol pit_value_as_symbol(pit_runtime *rt, pit_value v) {
+ if (pit_value_sort(v) != PIT_VALUE_SORT_SYMBOL) {
+ pit_error(rt, "invalid use of value as symbol");
+ return -1;
+ }
+ return (pit_symbol) (pit_value_data(v) & 0xffffffff);
+}
+bool pit_value_is_symbol(pit_runtime *rt, pit_value a) {
+ (void) rt;
+ return pit_value_sort(a) == PIT_VALUE_SORT_SYMBOL;
+}
+pit_value pit_value_symbol_new(pit_runtime *rt, pit_symbol s) {
+ return pit_value_new(rt, PIT_VALUE_SORT_SYMBOL, (u64) s);
+}
+
+pit_ref pit_value_as_ref(pit_runtime *rt, pit_value v) {
+ if (pit_value_sort(v) != PIT_VALUE_SORT_REF) {
+ pit_error(rt, "invalid use of value as ref");
+ return -1;
+ }
+ return (pit_ref) (pit_value_data(v) & 0xffffffff);
+}
+bool pit_value_is_ref(pit_runtime *rt, pit_value a) {
+ (void) rt;
+ return pit_value_sort(a) == PIT_VALUE_SORT_REF;
+}
+pit_value pit_value_ref_new(pit_runtime *rt, pit_ref r) {
+ return pit_value_new(rt, PIT_VALUE_SORT_REF, (u64) r);
+}
+pit_value pit_value_ref_heavy_new(pit_runtime *rt) {
+ pit_arena_index idx = pit_arena_alloc_index(rt->heap);
+ if (idx < 0) {
+ pit_error(rt, "failed to allocate space for heavy value");
+ return PIT_NIL;
+ }
+ return pit_value_ref_new(rt, idx);
+}
+pit_value_heavy *pit_value_ref_deref(pit_runtime *rt, pit_ref p) {
+ return pit_arena_get(rt->heap, p);
+}
+bool pit_value_is_ref_heavy_sort(pit_runtime *rt, pit_value a, enum pit_value_heavy_sort e) {
+ switch (pit_value_sort(a)) {
+ case PIT_VALUE_SORT_REF: {
+ pit_value_heavy *ha = pit_value_ref_deref(rt, pit_value_as_ref(rt, a));
+ if (!ha) { pit_error(rt, "bad ref"); return false; }
+ return ha->hsort == e;
+ }
+ default:
+ break;
+ }
+ return false;
+}