From 31c529e83a0d90c182b89384eb8b483462c10b7b Mon Sep 17 00:00:00 2001 From: Dane Johnson Date: Thu, 28 Aug 2025 09:06:22 -0500 Subject: [PATCH] Start working on reference for runtime environment --- reference/.gitignore | 3 + reference/Makefile | 5 +- reference/common.h | 27 +++++++++ reference/gc.c | 30 +--------- reference/gc.h | 26 +++------ reference/runtime.c | 135 +++++++++++++++++++++++++++++++++++++++++++ reference/runtime.h | 17 ++++++ reference/scheme.c | 25 ++++++++ 8 files changed, 219 insertions(+), 49 deletions(-) create mode 100644 reference/.gitignore create mode 100644 reference/common.h create mode 100644 reference/runtime.c create mode 100644 reference/runtime.h create mode 100644 reference/scheme.c diff --git a/reference/.gitignore b/reference/.gitignore new file mode 100644 index 0000000..20c61e4 --- /dev/null +++ b/reference/.gitignore @@ -0,0 +1,3 @@ +*.o +scheme +scheme.exe \ No newline at end of file diff --git a/reference/Makefile b/reference/Makefile index 92b7585..58dc73f 100644 --- a/reference/Makefile +++ b/reference/Makefile @@ -1,6 +1,5 @@ CFLAGS=-g -all: gctest +all: scheme -gctest: gc.o - $(CC) $(CFLAGS) -o $@ $< +scheme: gc.o runtime.o diff --git a/reference/common.h b/reference/common.h new file mode 100644 index 0000000..a2bc006 --- /dev/null +++ b/reference/common.h @@ -0,0 +1,27 @@ +#ifndef _COMMON_H_ +#define _COMMON_H_ + +#define SIZE 1024 +#define BROKEN_HEART 1 +#define CONS 2 +#define INTEGER 3 +#define SYMBOL 4 +#define BYE 5 + +typedef struct box_t { + char type; + union { + int integer; + char* symbol; + struct cons_t* cons; + }; +} box_t; + +typedef struct cons_t { + box_t car; + box_t cdr; +} cons_t; + +extern cons_t *the_empty_list; + +#endif // _COMMON_H_ diff --git a/reference/gc.c b/reference/gc.c index 3c1ef91..b811cdc 100644 --- a/reference/gc.c +++ b/reference/gc.c @@ -1,11 +1,12 @@ // Cheney style stop and copy garbage collector #include "gc.h" +cons_t *the_empty_list = NULL; + static cons_t *old, *new, *scanptr, *freeptr, *eom, *root; -static cons_t *the_empty_list = NULL; size_t tos; -void init() { +void gc_init() { old = calloc(sizeof(cons_t), SIZE); freeptr = old; eom = old + (SIZE / 2); @@ -61,28 +62,3 @@ void relocate(cons_t* cons) { move(cons->car); move(cons->cdr); } - -int main() { - init(); - // Simulate running linear fibonnaci - root->car.type = INTEGER; - root->car.integer = 1; - root->cdr.type = CONS; - root->cdr.cons = alloc(); - root->cdr.cons->car.type = INTEGER; - root->cdr.cons->car.integer = 0; - root->cdr.cons->cdr.type = CONS; - root->cdr.cons->cdr.cons = the_empty_list; - for (size_t i = 0; i < 29; i++) { - cons_t *cons = alloc(); - cons->car.type = INTEGER; - cons->car.integer = root->car.integer + root->cdr.cons->car.integer; - - cons->cdr.type = CONS; - cons->cdr.cons = root; - root->cdr.cons = the_empty_list; - root = cons; - }; - printf("%d\n", root->car.integer); // 832040, and we've definitely run gc a few times -} - diff --git a/reference/gc.h b/reference/gc.h index 83bfc34..969f95b 100644 --- a/reference/gc.h +++ b/reference/gc.h @@ -1,28 +1,16 @@ +#ifndef _GC_H_ +#define _GC_H_ + #include #include #include #include +#include "common.h" -#define SIZE 8 -#define BROKEN_HEART 1 -#define CONS 2 -#define INTEGER 3 - -typedef struct box_t { - char type; - union { - int integer; - struct cons_t* cons; - }; -} box_t; - -typedef struct cons_t { - box_t car; - box_t cdr; -} cons_t; - -void init(); +void gc_init(); cons_t *alloc(); void gc_run(); void gc_loop(); void relocate(cons_t*); + +#endif // _GC_H_ diff --git a/reference/runtime.c b/reference/runtime.c new file mode 100644 index 0000000..e4486b4 --- /dev/null +++ b/reference/runtime.c @@ -0,0 +1,135 @@ +#include "runtime.h" + +box_t cons(box_t car, box_t cdr) { + cons_t* kons = alloc(); + kons->car = car; + kons->cdr = cdr; + box_t box; + box.type = CONS; + box.cons = kons; + return box; +} + +void chomp_ws() { + char c = getchar(); + for(;;) { + if (c == ' ' || c == '\t' || c == '\n' || c == '\r') { + c = getchar(); + } else { + ungetchar(c); + break; + } + } +} + +box_t read_integer() { + char buf[256]; + size_t i = 0; + char next = getchar(); + while(isdigit(next)) { + buf[i] = next; + next = getchar(); + i++; + } + ungetchar(next); + buf[i] = 0; + box_t res; + res.type = INTEGER; + res.integer = atoi(buf); + chomp_ws(); + return res; +} + +box_t read_symbol() { + char buf[256]; + size_t i = 0; + char next = getchar(); + while (isalpha(next)) { // Totally insufficent but we'll look into it later + buf[i] = next; + next = getchar(); + i++; + } + ungetchar(next); + buf[i] = 0; + box_t res; + char *str = strndup(buf, i); + res.type = SYMBOL; + res.symbol = str; + chomp_ws(); // Clean up whitespace afterwards + return res; +} + +box_t read_list() { + char c = getchar(); + box_t val; + if (c == ')') { + chomp_ws(); + val.type = CONS; + val.cons = the_empty_list; + return val; + } else { + ungetchar(c); + box_t car = read(); + box_t cdr = read_list(); + return cons(car, cdr); + } +} + +box_t read() { + chomp_ws(); + char next = getchar(); + if (next == '(') { + chomp_ws(); + return read_list(); + } else if (isdigit(next)) { + ungetchar(next); + return read_integer(); + } else if (isalpha(next) || ispunct(next)) { + ungetchar(next); + return read_symbol(); + } else if (next == EOF) { + box_t bye; + bye.type = BYE; + return bye; + } else { + fprintf(stderr, "Bad input"); + exit(1); + } +} + +void scm_print_cons(box_t exp) { + printf("("); + while(exp.type = CONS && exp.cons != the_empty_list) { + scm_print(exp.cons->car); + if (exp.cons->cdr.cons != the_empty_list) { + printf(" "); + } + exp = exp.cons->cdr; + } + if (exp.cons == the_empty_list) { + printf(")"); + } else { + printf(". "); + scm_print(exp); + printf(")"); + } +} + +void scm_print(box_t exp) { + switch (exp.type) { + case INTEGER: + printf("%d", exp.integer); + break; + case SYMBOL: + printf("%s", exp.symbol); + break; + case CONS: + scm_print_cons(exp); + break; + } +} + + +box_t eval(box_t exp) { + return exp; +} diff --git a/reference/runtime.h b/reference/runtime.h new file mode 100644 index 0000000..01f591f --- /dev/null +++ b/reference/runtime.h @@ -0,0 +1,17 @@ +#ifndef _RUNTIME_H_ +#define _RUNTIME_H_ + +#include +#include +#include +#include +#include "common.h" +#include "gc.h" + +#define ungetchar(X) ungetc(X, stdin) + +box_t read(); +box_t eval(box_t); +void scm_print(box_t); + +#endif // _RUNTIME_H_ diff --git a/reference/scheme.c b/reference/scheme.c new file mode 100644 index 0000000..4871643 --- /dev/null +++ b/reference/scheme.c @@ -0,0 +1,25 @@ + +#include "gc.h" +#include "runtime.h" + +void prompt() { + printf("> "); +} + +int repl() { + box_t res; + do { + prompt(); + box_t in = read(); + res = eval(in); + scm_print(res); + printf("\n"); + } while (res.type != BYE); + + return 0; +} + +int main() { + gc_init(); + return repl(); +}