From 12de1e8db90bccd5a0eefd21075f07c7b7e3dfaa Mon Sep 17 00:00:00 2001 From: Aryadev Chavali Date: Wed, 14 May 2025 21:12:58 +0100 Subject: [PATCH] Refactor for cleanliness Move files into separate folders for ease of reading, include source directory so we can use angle bracket includes, adjust build system to make directories for objects --- Makefile | 19 +++++--- memory.c => lib/arena.c | 74 +------------------------------ memory.h => lib/arena.h | 23 ++-------- sv.c => lib/sv.c | 2 +- sv.h => lib/sv.h | 2 +- vec.c => lib/vec.c | 2 +- vec.h => lib/vec.h | 2 +- lisp/context.c | 92 +++++++++++++++++++++++++++++++++++++++ lisp/context.h | 38 ++++++++++++++++ eval.c => lisp/eval.c | 2 +- eval.h => lisp/eval.h | 2 +- lisp.c => lisp/lisp.c | 24 +++++++++- lisp.h => lisp/lisp.h | 10 ++--- reader.c => lisp/reader.c | 35 +++++++++------ reader.h => lisp/reader.h | 6 +-- tag.c => lisp/tag.c | 2 +- tag.h => lisp/tag.h | 24 +++++----- main.c | 24 +++++++--- 18 files changed, 236 insertions(+), 147 deletions(-) rename memory.c => lib/arena.c (72%) rename memory.h => lib/arena.h (71%) rename sv.c => lib/sv.c (99%) rename sv.h => lib/sv.h (98%) rename vec.c => lib/vec.c (98%) rename vec.h => lib/vec.h (97%) create mode 100644 lisp/context.c create mode 100644 lisp/context.h rename eval.c => lisp/eval.c (96%) rename eval.h => lisp/eval.h (96%) rename lisp.c => lisp/lisp.c (94%) rename lisp.h => lisp/lisp.h (92%) rename reader.c => lisp/reader.c (94%) rename reader.h => lisp/reader.h (96%) rename tag.c => lisp/tag.c (98%) rename tag.h => lisp/tag.h (82%) diff --git a/Makefile b/Makefile index c6d5504..7aee92a 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,7 @@ CC=gcc OUT=oats.out -LIBS=-I. +INCLUDES=-I. +LIBS= ARGS= RELEASE=0 @@ -16,7 +17,7 @@ CFLAGS=$(GFLAGS) $(DFLAGS) endif DIST=build -SRC:=tag.c memory.c vec.c sv.c lisp.c reader.c eval.c main.c +SRC:=lib/arena.c lib/vec.c lib/sv.c lisp/tag.c lisp/context.c lisp/lisp.c lisp/reader.c lisp/eval.c main.c OBJ:=$(SRC:%.c=$(DIST)/%.o) DEPDIR=$(DIST)/dependencies DEPS:=$(SRC:%.c=$(DEPDIR)/%.d) @@ -25,10 +26,10 @@ DEPS:=$(SRC:%.c=$(DEPDIR)/%.d) all: $(DIST)/$(OUT) $(DIST)/%.o: %.c | $(DIST) $(DEPDIR) - $(CC) $(CFLAGS) $(DEPFLAGS) $(DEPDIR)/$*.d -c $< -o $@ $(LIBS) + $(CC) $(INCLUDES) $(CFLAGS) $(DEPFLAGS) $(DEPDIR)/$*.d -c $< -o $@ $(LIBS) $(DIST)/$(OUT): $(OBJ) | $(DIST) - $(CC) $(CFLAGS) $^ -o $@ $(LIBS) + $(CC) $(INCLUDES) $(CFLAGS) $^ -o $@ $(LIBS) .PHONY: run run: $(DIST)/$(OUT) @@ -38,11 +39,19 @@ run: $(DIST)/$(OUT) clean: rm -rfv $(DIST)/* -$(DIST): +$(DIST): | $(DIST)/lib $(DIST)/lisp mkdir -p $(DIST) +$(DIST)/lib: + mkdir -p $(DIST)/lib + +$(DIST)/lisp: + mkdir -p $(DIST)/lisp + $(DEPDIR): mkdir -p $(DEPDIR) + mkdir -p $(DEPDIR)/lib + mkdir -p $(DEPDIR)/lisp .PHONY: watch: diff --git a/memory.c b/lib/arena.c similarity index 72% rename from memory.c rename to lib/arena.c index 0d9fe13..aa2d775 100644 --- a/memory.c +++ b/lib/arena.c @@ -13,7 +13,7 @@ * Description: Implementations for memory models. */ -#include "./memory.h" +#include #include #include @@ -201,75 +201,3 @@ void arena_cleanup(arena_t *arena) memset(arena, 0, sizeof(*arena)); } - -// Allocates against stable memory i.e. we can have pointers of this lying -// around without any fear of them being thrown away. -void *context_alloc(context_t *context, u64 size) -{ - return arena_alloc(&context->memory, size); -} - -// Allocate against a "scratch space", separate from main memory, for internal -// use. -void *context_salloc(context_t *context, u64 size) -{ - return arena_alloc(&context->scratch, size); -} - -void context_reset_read(context_t *context) -{ - arena_reset(&context->read); -} - -void context_reset_scratch(context_t *context) -{ - arena_reset(&context->scratch); -} - -void context_reset(context_t *context) -{ - arena_reset(&context->memory); - arena_reset(&context->read); - arena_reset(&context->scratch); -} - -void context_cleanup(context_t *context) -{ - if (!context) - return; - arena_cleanup(&context->memory); - arena_cleanup(&context->read); - arena_cleanup(&context->scratch); - memset(context, 0, sizeof(*context)); -} - -void context_report(context_t *context) -{ -#if DEBUG - // Figure this out at runtime - u64 mem_used = 0, mem_cap = 0; - for (page_t *page = context->memory.start; page; page = page->next) - { - mem_used += page->size; - mem_cap += page->capacity; - } - - u64 read_used = 0, read_cap = 0; - for (page_t *page = context->read.start; page; page = page->next) - { - read_used += page->size; - read_cap += page->capacity; - } - - u64 scr_used = 0, scr_cap = 0; - for (page_t *page = context->scratch.start; page; page = page->next) - { - scr_used += page->size; - scr_cap += page->capacity; - } - - info(": %luB/%luB main memory used\n", mem_used, mem_cap); - info(": %luB/%luB read space used\n", read_used, read_cap); - info(": %luB/%luB scratch space used\n", scr_used, scr_cap); -#endif -} diff --git a/memory.h b/lib/arena.h similarity index 71% rename from memory.h rename to lib/arena.h index bbd4d45..3b0724f 100644 --- a/memory.h +++ b/lib/arena.h @@ -10,13 +10,13 @@ * this program. If not, please go to . * Created: 2025-04-05 - * Description: Memory management structures + * Description: Arena */ -#ifndef MEMORY_H -#define MEMORY_H +#ifndef ARENA_H +#define ARENA_H -#include "./base.h" +#include #include #define PAGE_DEFAULT_SIZE 1024 @@ -48,19 +48,4 @@ void arena_attach(arena_t *arena, page_t *page); void arena_reset(arena_t *arena); void arena_cleanup(arena_t *arena); -typedef struct Context -{ - arena_t memory, read, scratch; -} context_t; - -void *context_alloc(context_t *context, u64 size); -void *context_salloc(context_t *context, u64 size); -page_t *context_get_read_page(context_t *ctx); -void context_reset_read(context_t *context); -void context_reset_scratch(context_t *context); - -void context_reset(context_t *context); -void context_cleanup(context_t *context); -void context_report(context_t *context); - #endif diff --git a/sv.c b/lib/sv.c similarity index 99% rename from sv.c rename to lib/sv.c index 50492fe..b2425b8 100644 --- a/sv.c +++ b/lib/sv.c @@ -13,7 +13,7 @@ * Description: String View implementation */ -#include "./sv.h" +#include #include #include diff --git a/sv.h b/lib/sv.h similarity index 98% rename from sv.h rename to lib/sv.h index 0fce33d..3293b1c 100644 --- a/sv.h +++ b/lib/sv.h @@ -16,7 +16,7 @@ #ifndef SV_H #define SV_H -#include "./memory.h" +#include typedef struct SV { diff --git a/vec.c b/lib/vec.c similarity index 98% rename from vec.c rename to lib/vec.c index bf1b5c6..551f679 100644 --- a/vec.c +++ b/lib/vec.c @@ -13,7 +13,7 @@ * Description: Vector implementation */ -#include "./vec.h" +#include #include #include diff --git a/vec.h b/lib/vec.h similarity index 97% rename from vec.h rename to lib/vec.h index 9f35e20..20a3523 100644 --- a/vec.h +++ b/lib/vec.h @@ -16,7 +16,7 @@ #ifndef VEC_H #define VEC_H -#include "./memory.h" +#include typedef struct { diff --git a/lisp/context.c b/lisp/context.c new file mode 100644 index 0000000..3b94e54 --- /dev/null +++ b/lisp/context.c @@ -0,0 +1,92 @@ +/* Copyright (C) 2025 Aryadev Chavali + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + Public License Version 2 + * for details. + + * You may distribute and modify this code under the terms of the + * GNU General Public License Version 2, which you should have received a copy + of along with this + * program. If not, please go to . + + * Created: 2025-05-12 + * Description: + */ + +#include + +#include + +// Allocates against stable memory i.e. we can have pointers of this lying +// around without any fear of them being thrown away. +void *context_alloc(context_t *context, u64 size) +{ + return arena_alloc(&context->memory, size); +} + +// Allocate against a "scratch space", separate from main memory, for internal +// use. +void *context_salloc(context_t *context, u64 size) +{ + return arena_alloc(&context->scratch, size); +} + +void context_reset_read(context_t *context) +{ + arena_reset(&context->read); +} + +void context_reset_scratch(context_t *context) +{ + arena_reset(&context->scratch); +} + +void context_reset(context_t *context) +{ + arena_reset(&context->memory); + arena_reset(&context->read); + arena_reset(&context->scratch); +} + +void context_cleanup(context_t *context) +{ + if (!context) + return; + arena_cleanup(&context->memory); + arena_cleanup(&context->read); + arena_cleanup(&context->scratch); + memset(context, 0, sizeof(*context)); +} + +void context_report(context_t *context) +{ +#if DEBUG + // Figure this out at runtime + u64 mem_used = 0, mem_cap = 0; + for (page_t *page = context->memory.start; page; page = page->next) + { + mem_used += page->size; + mem_cap += page->capacity; + } + + u64 read_used = 0, read_cap = 0; + for (page_t *page = context->read.start; page; page = page->next) + { + read_used += page->size; + read_cap += page->capacity; + } + + u64 scr_used = 0, scr_cap = 0; + for (page_t *page = context->scratch.start; page; page = page->next) + { + scr_used += page->size; + scr_cap += page->capacity; + } + + info(": %luB/%luB main memory used\n", mem_used, mem_cap); + info(": %luB/%luB read space used\n", read_used, read_cap); + info(": %luB/%luB scratch space used\n", scr_used, scr_cap); +#endif +} diff --git a/lisp/context.h b/lisp/context.h new file mode 100644 index 0000000..2923ad9 --- /dev/null +++ b/lisp/context.h @@ -0,0 +1,38 @@ +/* Copyright (C) 2025 Aryadev Chavali + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + Public License Version 2 + * for details. + + * You may distribute and modify this code under the terms of the + * GNU General Public License Version 2, which you should have received a copy + of along with this + * program. If not, please go to . + + * Created: 2025-05-12 + * Description: + */ + +#ifndef CONTEXT_H +#define CONTEXT_H + +#include + +typedef struct Context +{ + arena_t memory, read, scratch; +} context_t; + +void *context_alloc(context_t *context, u64 size); +void *context_salloc(context_t *context, u64 size); +page_t *context_get_read_page(context_t *ctx); +void context_reset_read(context_t *context); +void context_reset_scratch(context_t *context); + +void context_reset(context_t *context); +void context_cleanup(context_t *context); +void context_report(context_t *context); + +#endif diff --git a/eval.c b/lisp/eval.c similarity index 96% rename from eval.c rename to lisp/eval.c index 3fc49ee..3cd05ca 100644 --- a/eval.c +++ b/lisp/eval.c @@ -13,7 +13,7 @@ * Description: Evaluator implementation */ -#include "./eval.h" +#include err_t eval(context_t *ctx, lisp_t *obj, lisp_t **ret) { diff --git a/eval.h b/lisp/eval.h similarity index 96% rename from eval.h rename to lisp/eval.h index 11e2aa2..bc7fb60 100644 --- a/eval.h +++ b/lisp/eval.h @@ -16,7 +16,7 @@ #ifndef EVAL_H #define EVAL_H -#include "./lisp.h" +#include typedef enum { diff --git a/lisp.c b/lisp/lisp.c similarity index 94% rename from lisp.c rename to lisp/lisp.c index 5ee7a19..24a4788 100644 --- a/lisp.c +++ b/lisp/lisp.c @@ -13,8 +13,8 @@ * Description: */ -#include "./lisp.h" -#include "./sv.h" +#include +#include #include #include @@ -130,6 +130,13 @@ bool as_bool(lisp_t *obj) return (bool)UNTAG(obj, BOOL); } +f64 as_float(lisp_t *obj) +{ + assert(IS_TAG(obj, FLOAT)); + f64 *f = (f64 *)UNTAG(obj, FLOAT); + return f ? *f : 0; +} + vec_t *as_vec(lisp_t *obj) { assert(IS_TAG(obj, VEC)); @@ -214,6 +221,19 @@ sv_t serialise(context_t *ctx, lisp_t *ptr) , as_bool(ptr) ? "#t" : "#f"); } + case TAG_FLOAT: + { + return sv_fmt(&ctx->scratch, +#if DEBUG > 1 + "float[" +#endif + "%lf" +#if DEBUG > 1 + "]" +#endif + , + as_float(ptr)); + } case TAG_CONS: { if (!CAR(ptr) && !CDR(ptr)) diff --git a/lisp.h b/lisp/lisp.h similarity index 92% rename from lisp.h rename to lisp/lisp.h index b714e7d..2892bdb 100644 --- a/lisp.h +++ b/lisp/lisp.h @@ -16,11 +16,10 @@ #ifndef LISP_H #define LISP_H -#include "./base.h" -#include "./memory.h" -#include "./sv.h" -#include "./tag.h" -#include "./vec.h" +#include +#include +#include +#include typedef struct Cons { @@ -33,7 +32,6 @@ typedef struct Cell u8 data[]; } cell_t; -#define NIL 0 lisp_t *make_int(i64 integer); lisp_t *make_sym(context_t *ctx, char *data, u64 size); lisp_t *make_cons(context_t *ctx, lisp_t *car, lisp_t *cdr); diff --git a/reader.c b/lisp/reader.c similarity index 94% rename from reader.c rename to lisp/reader.c index b9217d3..0c8a914 100644 --- a/reader.c +++ b/lisp/reader.c @@ -13,7 +13,7 @@ * Description: Implementation of parser */ -#include "./reader.h" +#include #include #include @@ -98,33 +98,38 @@ char input_next(input_t *input, u64 offset) void input_skip(input_t *inp) { - // n + 2 lookup - sv_t current = sv_cut(inp->str, inp->offset); - sv_t lookup = sv_chop(current, 2); - while ((!input_eof(inp) && is_space(lookup.data[0])) || - lookup.data[0] == ';' || strncmp(lookup.data, "#|", 2) == 0) + while (!input_eof(inp)) { - if (lookup.data[0] == ';') + sv_t current = sv_cut(inp->str, inp->offset); + // Skip any whitespace + inp->offset += sv_while(current, is_space); + current = sv_cut(inp->str, inp->offset); + // Is there a comment to skip? + if (current.size && current.data[0] == ';') { + // Skip till newline i64 newline = sv_find_subcstr(current, "\n", 1); if (newline < 0) inp->offset = inp->str.size; else inp->offset += newline + 1; + // Then skip any whitespace } - else if (strncmp(lookup.data, "#|", 2) == 0) + // Multiline comment to skip? + else if (current.size > 2 && strncmp(current.data, "#|", 2) == 0) { i64 offset = sv_find_subcstr(current, "|#", 2); if (offset < 0) inp->offset = inp->str.size; else inp->offset += offset + 2; + // Then skip any whitespace } - - inp->offset += sv_while(sv_cut(inp->str, inp->offset), is_space); - current = sv_cut(inp->str, inp->offset); - lookup = sv_chop(current, 2); + // Nothing to skip, stop. + else + break; } + return; } perr_t parse_int(context_t *ctx, input_t *inp, lisp_t **ret) @@ -324,11 +329,13 @@ perr_t parse_reader_macro(context_t *ctx, input_t *inp, lisp_t **ret) TODO("Not implemented reader macro for characters or weird bases"); } else if (c == '(') - { return parse_vec(ctx, inp, ret); - } else if (c == 't' || c == 'f') return parse_bool(ctx, inp, ret); + else if (c == 'e') + { + // Scientific notation for floats + } return PERR_UNEXPECTED_READER_MACRO_SYMBOL; } diff --git a/reader.h b/lisp/reader.h similarity index 96% rename from reader.h rename to lisp/reader.h index 07c3672..4bd0578 100644 --- a/reader.h +++ b/lisp/reader.h @@ -16,9 +16,9 @@ #ifndef READER_H #define READER_H -#include "./lisp.h" -#include "./memory.h" -#include "./vec.h" +#include +#include +#include #define INPUT_CHUNK_SIZE 512 static const char SYM_CHARS[] = diff --git a/tag.c b/lisp/tag.c similarity index 98% rename from tag.c rename to lisp/tag.c index 5fc03e0..26db6d5 100644 --- a/tag.c +++ b/lisp/tag.c @@ -13,8 +13,8 @@ * Description: */ +#include #include -#include lisp_t *tag_int(i64 i) { diff --git a/tag.h b/lisp/tag.h similarity index 82% rename from tag.h rename to lisp/tag.h index dab1fa0..06b7b3f 100644 --- a/tag.h +++ b/lisp/tag.h @@ -16,7 +16,7 @@ #ifndef TAG_H #define TAG_H -#include "./base.h" +#include #include #include @@ -25,18 +25,20 @@ // pointers typedef struct Obj lisp_t; +#define NIL NULL + enum Tag { - TAG_NIL = 0b00000000, // Atomic types - TAG_INT = 0b00000001, // special so we can encode 63 bit integers - TAG_SYM = 0b00000100, - TAG_SSYM = 0b00001000, - TAG_CHAR = 0b00001100, - TAG_BOOL = 0b00010000, - // TAG_FLOAT = 0b00010100, - TAG_CONS = 0b00000010, // Container types - TAG_VEC = 0b00000110, - TAG_STR = 0b00001010, + TAG_NIL = 0b00000000, // Atomic types + TAG_INT = 0b00000001, // special so we can encode 63 bit integers + TAG_SYM = 0b00000100, + TAG_SSYM = 0b00001000, + TAG_CHAR = 0b00001100, + TAG_BOOL = 0b00010000, + TAG_FLOAT = 0b00010100, + TAG_CONS = 0b00000010, // Container types + TAG_VEC = 0b00000110, + TAG_STR = 0b00001010, NUM_TAGS = 9, }; diff --git a/main.c b/main.c index ab1864d..3a1c2f2 100644 --- a/main.c +++ b/main.c @@ -13,12 +13,10 @@ * Description: Entrypoint */ -#include "./base.h" -#include "./lisp.h" -#include "./memory.h" -#include "./reader.h" -#include "./sv.h" -#include "./vec.h" +#include +#include +#include +#include #include #include @@ -27,6 +25,15 @@ #include #include +void usage(char *prog_name, FILE *fp) +{ + fprintf(fp, + "Usage: %s [FILE]\n" + "Interpret FILE as scheme in the OATS interpreter.\n" + "\t[FILE]: name of file\n", + prog_name); +} + int main(int argc, char *argv[]) { int exit = 0; @@ -36,7 +43,10 @@ int main(int argc, char *argv[]) if (argc > 1) filename = argv[1]; else - filename = "./r7rs-tests.scm"; + { + usage(argv[0], stderr); + return 1; + } FILE *fp = fopen(filename, "r"); if (!fp)