summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/library.c92
-rw-r--r--src/library.h8
-rw-r--r--src/main.c34
-rw-r--r--src/parser.c17
-rw-r--r--src/runtime.c165
-rw-r--r--src/runtime.h60
6 files changed, 284 insertions, 92 deletions
diff --git a/src/library.c b/src/library.c
new file mode 100644
index 0000000..64ed071
--- /dev/null
+++ b/src/library.c
@@ -0,0 +1,92 @@
+#include "runtime.h"
+
+static pit_value impl_sf_quote(pit_runtime *rt, pit_value args) {
+ pit_runtime_eval_program_push(rt, rt->program, (pit_runtime_eval_program_entry) {
+ .sort = EVAL_PROGRAM_ENTRY_LITERAL,
+ .literal = pit_car(rt, args)
+ });
+ return PIT_NIL;
+}
+
+static pit_value impl_sf_if(pit_runtime *rt, pit_value args) {
+ pit_value c = pit_car(rt, args);
+ if (pit_eval(rt, c) != PIT_NIL) {
+ pit_values_push(rt, rt->expr_stack, pit_car(rt, pit_cdr(rt, args)));
+ } else {
+ pit_values_push(rt, rt->expr_stack, pit_car(rt, pit_cdr(rt, pit_cdr(rt, args))));
+ }
+ return PIT_NIL;
+}
+
+static pit_value impl_sf_progn(pit_runtime *rt, pit_value args) {
+ 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);
+ }
+ pit_runtime_eval_program_push(rt, rt->program, (pit_runtime_eval_program_entry) {
+ .sort = EVAL_PROGRAM_ENTRY_LITERAL,
+ .bind = final,
+ });
+ return PIT_NIL;
+}
+
+static pit_value impl_sf_let(pit_runtime *rt, pit_value args) {
+ pit_value binds = pit_car(rt, args);
+ pit_value unbinds = PIT_NIL;
+ 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));
+ pit_value v = pit_eval(rt, expr);
+ pit_bind(rt, sym, v);
+ binds = pit_cdr(rt, binds);
+ unbinds = pit_cons(rt, bind, unbinds);
+ }
+ impl_sf_progn(rt, pit_cdr(rt, args));
+ while (unbinds != PIT_NIL) {
+ pit_value unbind = pit_car(rt, unbinds);
+ pit_value sym = pit_car(rt, unbind);
+ pit_unbind(rt, sym);
+ unbinds = pit_cdr(rt, unbinds);
+ }
+ return PIT_NIL;
+}
+
+static pit_value impl_set(pit_runtime *rt, pit_value args) {
+ pit_value sym = pit_car(rt, args);
+ pit_value v = pit_car(rt, pit_cdr(rt, args));
+ pit_set(rt, sym, v);
+ return v;
+}
+
+static pit_value impl_print(pit_runtime *rt, pit_value args) {
+ pit_value x = pit_car(rt, args);
+ pit_trace(rt, x);
+ return x;
+}
+
+static pit_value impl_add(pit_runtime *rt, pit_value args) {
+ 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_integer_new(rt, x + y);
+}
+
+static pit_value impl_sub(pit_runtime *rt, pit_value args) {
+ 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_integer_new(rt, x - y);
+}
+
+void pit_install_library_essential(pit_runtime *rt) {
+ 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, "progn"), pit_nativefunc_new(rt, impl_sf_progn));
+ pit_sfset(rt, pit_intern_cstr(rt, "let"), pit_nativefunc_new(rt, impl_sf_let));
+
+ pit_fset(rt, pit_intern_cstr(rt, "print"), pit_nativefunc_new(rt, impl_print));
+ pit_fset(rt, pit_intern_cstr(rt, "set"), pit_nativefunc_new(rt, impl_set));
+ 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));
+}
diff --git a/src/library.h b/src/library.h
new file mode 100644
index 0000000..a472642
--- /dev/null
+++ b/src/library.h
@@ -0,0 +1,8 @@
+#ifndef LIBRARY_H
+#define LIBRARY_H
+
+#include "runtime.h"
+
+void pit_install_library_essential(pit_runtime *rt);
+
+#endif
diff --git a/src/main.c b/src/main.c
index c6bd833..215e485 100644
--- a/src/main.c
+++ b/src/main.c
@@ -5,45 +5,11 @@
#include "parser.h"
#include "runtime.h"
-pit_value test_print(pit_runtime *rt, pit_value args) {
- pit_value x = pit_car(rt, args);
- pit_trace(rt, x);
- return x;
-}
-
-pit_value test_if(pit_runtime *rt, pit_value args) {
- pit_value cform = pit_car(rt, args);
- pit_value tform = pit_car(rt, pit_cdr(rt, args));
- pit_value eform = pit_car(rt, pit_cdr(rt, pit_cdr(rt, args)));
- pit_value c = pit_eval(rt, cform);
- if (c != PIT_NIL) {
- return pit_eval(rt, tform);
- } else {
- return pit_eval(rt, eform);
- }
-}
-
-pit_value test_add(pit_runtime *rt, pit_value args) {
- 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_integer_new(rt, x + y);
-}
-
-pit_value test_sub(pit_runtime *rt, pit_value args) {
- 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_integer_new(rt, x - y);
-}
-
int main(int argc, char **argv) {
if (argc < 2) pit_panic("usage: %s FILE", argv[0]);
pit_runtime *rt = pit_runtime_new();
pit_check_error_maybe_panic(rt);
- pit_fset(rt, pit_intern_cstr(rt, "print"), pit_nativefunc_new(rt, test_print));
- pit_fset(rt, pit_intern_cstr(rt, "+"), pit_nativefunc_new(rt, test_add));
- pit_fset(rt, pit_intern_cstr(rt, "-"), pit_nativefunc_new(rt, test_sub));
- pit_mset(rt, pit_intern_cstr(rt, "if"), pit_nativefunc_new(rt, test_if));
pit_lexer *lex = pit_lex_file(argv[1]);
diff --git a/src/parser.c b/src/parser.c
index 34472d2..cb75817 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -57,17 +57,22 @@ pit_value pit_parse(pit_runtime *rt, pit_parser *st) {
pit_error(rt, "end-of-file while parsing");
return PIT_NIL;
case PIT_LEX_TOKEN_LPAREN: {
- i64 arg = 0; i64 args_cap = 32;
- pit_value *args = calloc(args_cap, sizeof(pit_value));
+ // 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;
while (!match(st, PIT_LEX_TOKEN_RPAREN)) {
- args[arg++] = pit_parse(rt, st);
+ pit_value *cell = pit_arena_alloc_bulk(rt->scratch, sizeof(pit_value));
+ *cell = pit_parse(rt, st);
if (rt->error != PIT_NIL) return PIT_NIL; // if we hit an error, stop!
- if (arg >= args_cap) args = realloc(args, (args_cap <<= 1) * sizeof(pit_value));
}
pit_value ret = PIT_NIL;
- for (int i = 0; i < arg; ++i) {
- ret = pit_cons(rt, args[arg - i - 1], ret);
+ for (i64 i = rt->scratch->next - sizeof(pit_value); i >= scratch_reset; i -= sizeof(pit_value)) {
+ pit_value *v = pit_arena_idx(rt->scratch, i);
+ ret = pit_cons(rt, *v, ret);
}
+ rt->scratch->next = scratch_reset;
return ret;
}
case PIT_LEX_TOKEN_QUOTE:
diff --git a/src/runtime.c b/src/runtime.c
index 57e3335..cf82550 100644
--- a/src/runtime.c
+++ b/src/runtime.c
@@ -7,6 +7,7 @@
#include "utils.h"
#include "runtime.h"
+#include "library.h"
pit_arena *pit_arena_new(i64 capacity, i64 elem_size) {
pit_arena *a = malloc(sizeof(pit_arena) + capacity * elem_size);
@@ -67,8 +68,14 @@ pit_runtime *pit_runtime_new() {
ret->bytes = pit_arena_new(64 * 1024, sizeof(u8));
ret->symtab = pit_arena_new(1024, sizeof(pit_symtab_entry));
ret->symtab_len = 0;
+ ret->scratch = pit_arena_new(64 * 1024, sizeof(u8));
+ ret->expr_stack = pit_values_new(1024);
+ ret->result_stack = pit_values_new(1024);
+ ret->program = pit_runtime_eval_program_new(64 * 1024);
+ ret->saved_bindings = pit_values_new(1024);
ret->error = PIT_NIL;
- pit_intern_cstr(ret, "nil");
+ pit_intern_cstr(ret, "nil"); // nil must be the 0th symbol for PIT_NIL to work
+ pit_install_library_essential(ret);
return ret;
}
@@ -350,6 +357,7 @@ pit_value pit_intern(pit_runtime *rt, u8 *nm, i64 len) {
ent->value = PIT_NIL;
ent->function = PIT_NIL;
ent->is_macro = false;
+ ent->is_special_form = false;
rt->symtab_len += 1;
return pit_symbol_new(rt, idx);
}
@@ -362,6 +370,14 @@ pit_symtab_entry *pit_symtab_lookup(pit_runtime *rt, pit_value sym) {
pit_symbol s = pit_as_symbol(rt, sym);
return pit_arena_idx(rt->symtab, s);
}
+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, strlen(s));
+}
pit_value pit_get(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; }
@@ -396,6 +412,33 @@ 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 v) {
+ pit_symtab_entry *ent = pit_symtab_lookup(rt, sym);
+ if (!ent) { pit_error(rt, "bad symbol"); return; }
+ pit_values_push(rt, rt->saved_bindings, ent->value);
+ ent->value = v;
+}
+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;
+ ent->value = pit_values_pop(rt, rt->saved_bindings);
+ return old;
+}
pit_value pit_cons(pit_runtime *rt, pit_value car, pit_value cdr) {
pit_value ret = pit_heavy_new(rt);
@@ -408,7 +451,8 @@ pit_value pit_cons(pit_runtime *rt, pit_value car, pit_value cdr) {
}
pit_value pit_list(pit_runtime *rt, i64 num, ...) {
- pit_value *temp = calloc(num, sizeof(pit_value));
+ pit_value temp[64];
+ 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) {
@@ -462,80 +506,111 @@ pit_value pit_apply(pit_runtime *rt, pit_value f, pit_value args) {
}
}
-struct eval_stack {
- i64 top, cap;
- pit_value *data;
-};
-static struct eval_stack *eval_stack_new() {
- struct eval_stack *ret = malloc(sizeof(*ret));
+pit_values *pit_values_new(i64 capacity) {
+ i64 cap = capacity / sizeof(pit_value);
+ pit_values *ret = malloc(sizeof(*ret) + cap * sizeof(pit_value));
ret->top = 0;
- ret->cap = 32;
- ret->data = calloc(ret->cap, sizeof(pit_value));
+ ret->cap = cap;
return ret;
}
-static void eval_stack_destroy(struct eval_stack *s) {
- if (s) {
- if (s->data) free(s->data);
- free(s);
- }
-}
-static void eval_stack_push(pit_runtime *rt, struct eval_stack *s, pit_value x) {
+void pit_values_push(pit_runtime *rt, pit_values *s, pit_value x) {
(void) rt;
s->data[s->top++] = x;
- if (s->top >= s->cap) s->data = realloc(s->data, (s->cap <<= 1) * sizeof(pit_value));
+ if (s->top >= s->cap) { pit_error(rt, "evaluation stack overflow"); }
}
-static pit_value eval_stack_pop(pit_runtime *rt, struct eval_stack *s) {
+pit_value pit_values_pop(pit_runtime *rt, pit_values *s) {
if (s->top == 0) { pit_error(rt, "evaluation stack underflow"); return PIT_NIL; }
return s->data[--s->top];
}
+pit_runtime_eval_program *pit_runtime_eval_program_new(i64 capacity) {
+ i64 cap = capacity / sizeof(pit_runtime_eval_program_entry);
+ pit_runtime_eval_program *ret = malloc(sizeof(*ret) + cap * sizeof(pit_runtime_eval_program_entry));
+ ret->top = 0;
+ ret->cap = cap;
+ return ret;
+}
+void pit_runtime_eval_program_push(pit_runtime *rt, pit_runtime_eval_program *s, pit_runtime_eval_program_entry x) {
+ (void) rt;
+ s->data[s->top++] = x;
+ if (s->top >= s->cap) { pit_error(rt, "evaluation program overflow"); }
+}
+
pit_value pit_eval(pit_runtime *rt, pit_value top) {
- struct eval_stack *expr_stack = eval_stack_new();
- struct eval_stack *program = eval_stack_new();
- eval_stack_push(rt, expr_stack, top);
+ i64 expr_stack_reset = rt->expr_stack->top;
+ i64 result_stack_reset = rt->result_stack->top;
+ i64 program_reset = rt->program->top;
+ pit_values_push(rt, rt->expr_stack, top);
// first, convert the expression tree into "polish notation" in program
- while (expr_stack->top > 0) {
- pit_value cur = eval_stack_pop(rt, expr_stack);
+ while (rt->expr_stack->top > 0) {
+ pit_value cur = pit_values_pop(rt, rt->expr_stack);
if (pit_is_cons(rt, cur)) { // compound expressions: function/macro application special forms
pit_value fsym = pit_car(rt, cur);
pit_value f = pit_fget(rt, fsym);
pit_value args = pit_cdr(rt, cur);
- if (pit_is_symbol_macro(rt, fsym)) {
+ if (pit_is_symbol_special_form(rt, fsym)) { // special forms
+ // 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 (pit_is_symbol_macro(rt, fsym)) { // macros
pit_value res = pit_apply(rt, f, args);
- eval_stack_push(rt, expr_stack, res);
- } else {
+ pit_values_push(rt, rt->expr_stack, res);
+ } else { // normal functions
i64 argcount = 0;
while (args != PIT_NIL) {
- eval_stack_push(rt, expr_stack, pit_car(rt, args));
+ pit_values_push(rt, rt->expr_stack, pit_car(rt, args));
args = pit_cdr(rt, args);
argcount += 1;
}
- eval_stack_push(rt, program, pit_cons(rt, f, pit_integer_new(rt, argcount)));
+ pit_runtime_eval_program_push(rt, rt->program, (pit_runtime_eval_program_entry) {
+ .sort = EVAL_PROGRAM_ENTRY_APPLY,
+ .apply.arity = argcount,
+ .apply.func = f,
+ });
}
} else if (pit_is_symbol(rt, cur)) { // unquoted symbols: variable lookup
- eval_stack_push(rt, program, pit_get(rt, cur));
- } else { // other values: used literally
- eval_stack_push(rt, program, cur);
+ pit_runtime_eval_program_push(rt, rt->program, (pit_runtime_eval_program_entry) {
+ .sort = EVAL_PROGRAM_ENTRY_LITERAL,
+ .literal = pit_get(rt, cur),
+ });
+ } else { // other expressions evaluate to themselves!
+ pit_runtime_eval_program_push(rt, rt->program, (pit_runtime_eval_program_entry) {
+ .sort = EVAL_PROGRAM_ENTRY_LITERAL,
+ .literal = cur,
+ });
}
}
- struct eval_stack *result_stack = eval_stack_new();
// 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 = program->top - 1; idx >= 0; --idx) {
- pit_value expr = program->data[idx];
- if (pit_is_cons(rt, expr)) { // this is a function call
+ for (i64 idx = rt->program->top - 1; idx >= program_reset; --idx) {
+ pit_runtime_eval_program_entry *ent = &rt->program->data[idx];
+ switch (ent->sort) {
+ case EVAL_PROGRAM_ENTRY_LITERAL:
+ pit_values_push(rt, rt->result_stack, ent->literal);
+ break;
+ case EVAL_PROGRAM_ENTRY_APPLY:
pit_value args = PIT_NIL;
- for (i64 i = 0; i < pit_as_integer(rt, pit_cdr(rt, expr)); ++i) {
- args = pit_cons(rt, eval_stack_pop(rt, result_stack), args);
+ for (i64 i = 0; i < ent->apply.arity; ++i) {
+ args = pit_cons(rt, pit_values_pop(rt, rt->result_stack), args);
}
- eval_stack_push(rt, result_stack, pit_apply(rt, pit_car(rt, expr), args));
- } else { // this is an atom
- eval_stack_push(rt, result_stack, expr);
+ pit_values_push(rt, rt->result_stack, pit_apply(rt, ent->apply.func, args));
+ break;
+ case EVAL_PROGRAM_ENTRY_BIND:
+ pit_value v = pit_values_pop(rt, rt->result_stack);
+ pit_bind(rt, ent->bind, v);
+ break;
+ case EVAL_PROGRAM_ENTRY_UNBIND:
+ pit_unbind(rt, ent->unbind);
+ break;
+ default:
+ pit_error(rt, "unknown program entry");
+ goto end;
}
}
- pit_value ret = eval_stack_pop(rt, result_stack);
- eval_stack_destroy(expr_stack);
- eval_stack_destroy(program);
- eval_stack_destroy(result_stack);
+end:
+ pit_value ret = pit_values_pop(rt, rt->result_stack);
+ rt->expr_stack->top = expr_stack_reset;
+ rt->result_stack->top = result_stack_reset;
+ rt->program->top = program_reset;
return ret;
}
diff --git a/src/runtime.h b/src/runtime.h
index 26ac1c1..2db4ee8 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -4,13 +4,19 @@
#include "types.h"
#include "utils.h"
+struct pit_runtime;
+
+// arenas
typedef struct {
i64 elem_size, capacity, next;
u8 data[];
} pit_arena;
pit_arena *pit_arena_new(i64 capacity, i64 elem_size);
i32 pit_arena_alloc_idx(pit_arena *a);
+i32 pit_arena_alloc_bulk_idx(pit_arena *a, i64 num);
+void *pit_arena_idx(pit_arena *a, i32 idx);
void *pit_arena_alloc(pit_arena *a);
+void *pit_arena_alloc_bulk(pit_arena *a, i64 num);
// nil is always the symbol with index 0
#define PIT_NIL 0b1111111111110100000000000000000000000000000000000000000000000000
@@ -26,7 +32,14 @@ typedef u64 pit_value;
enum pit_value_sort pit_value_sort(pit_value v);
u64 pit_value_data(pit_value v);
-struct pit_runtime;
+typedef struct {
+ i64 top, cap;
+ pit_value data[];
+} pit_values;
+pit_values *pit_values_new(i64 capacity);
+void pit_values_push(struct pit_runtime *rt, pit_values *s, pit_value x);
+pit_value pit_values_pop(struct pit_runtime *rt, pit_values *s);
+
typedef pit_value (*pit_nativefunc)(struct pit_runtime *rt, pit_value args);
typedef struct { // "heavy" values, the targets of refs
enum pit_value_heavy_sort {
@@ -47,16 +60,42 @@ typedef struct {
pit_value name;
pit_value value;
pit_value function;
- bool is_macro;
+ bool is_macro, is_special_form;
} pit_symtab_entry;
+// "programs"; vectors of "instructions" for a very simple VM used by the evaluator
+typedef struct {
+ enum {
+ EVAL_PROGRAM_ENTRY_LITERAL,
+ EVAL_PROGRAM_ENTRY_APPLY,
+ EVAL_PROGRAM_ENTRY_BIND,
+ EVAL_PROGRAM_ENTRY_UNBIND,
+ } sort;
+ union {
+ pit_value literal;
+ struct { i64 arity; pit_value func; } apply;
+ pit_value bind; // symbol to bind
+ pit_value unbind; // symbol to unbind
+ };
+} pit_runtime_eval_program_entry;
+typedef struct {
+ i64 top, cap;
+ pit_runtime_eval_program_entry data[];
+} pit_runtime_eval_program;
+pit_runtime_eval_program *pit_runtime_eval_program_new(i64 capacity);
+void pit_runtime_eval_program_push(struct pit_runtime *rt, pit_runtime_eval_program *s, pit_runtime_eval_program_entry x);
+
typedef struct pit_runtime {
- pit_arena *values;
- pit_arena *bytes;
- pit_arena *symtab; i64 symtab_len;
- pit_value error;
+ pit_arena *values; // all heavy values - effectively an array of pit_value_heavy
+ pit_arena *bytes; // all bytestrings (including symbol names)
+ pit_arena *symtab; i64 symtab_len; // all symbols - effectively an array of pit_symtab_entry
+ pit_arena *scratch; // temporary arena used during parsing and evaluation
+ pit_values *saved_bindings; // stack used to save old values of bindings to be restored ("shallow binding")
+ pit_values *expr_stack; // stack of subexpressions to evaluate during evaluation
+ pit_values *result_stack; // stack of intermediate values during evaluation
+ pit_runtime_eval_program *program; // intermediate stack-based program constructed during evaluation
+ pit_value error; // error value - if this is non-nil, an error has occured! only tracks the first error
} pit_runtime;
-
pit_runtime *pit_runtime_new();
i64 pit_dump(pit_runtime *rt, char *buf, i64 len, pit_value v);
@@ -101,6 +140,8 @@ bool pit_bytes_match(pit_runtime *rt, pit_value v, u8 *buf, i64 len);
// working with the symbol table
pit_value pit_intern(pit_runtime *rt, u8 *nm, i64 len);
pit_value pit_intern_cstr(pit_runtime *rt, char *nm);
+bool pit_symbol_name_match(pit_runtime *rt, pit_value sym, u8 *buf, i64 len);
+bool pit_symbol_name_match_cstr(pit_runtime *rt, pit_value sym, char *s);
pit_symtab_entry *pit_symtab_lookup(pit_runtime *rt, pit_value sym);
pit_value pit_get(pit_runtime *rt, pit_value sym);
void pit_set(pit_runtime *rt, pit_value sym, pit_value v);
@@ -109,6 +150,11 @@ void pit_fset(pit_runtime *rt, pit_value sym, pit_value v);
bool pit_is_symbol_macro(pit_runtime *rt, pit_value sym);
void pit_symbol_is_macro(pit_runtime *rt, pit_value sym);
void pit_mset(pit_runtime *rt, pit_value sym, pit_value v);
+bool pit_is_symbol_special_form(pit_runtime *rt, pit_value sym);
+void pit_symbol_is_special_form(pit_runtime *rt, pit_value sym);
+void pit_sfset(pit_runtime *rt, pit_value sym, pit_value v);
+void pit_bind(pit_runtime *rt, pit_value sym, pit_value v);
+pit_value pit_unbind(pit_runtime *rt, pit_value sym);
// working with cons cells
pit_value pit_cons(pit_runtime *rt, pit_value car, pit_value cdr);