diff options
author | Aryadev Chavali <aryadev@aryadevchavali.com> | 2025-05-14 21:12:58 +0100 |
---|---|---|
committer | Aryadev Chavali <aryadev@aryadevchavali.com> | 2025-05-15 22:25:45 +0100 |
commit | 12de1e8db90bccd5a0eefd21075f07c7b7e3dfaa (patch) | |
tree | 0434141f2bfd24207a2864f613a1c2e3ee7181fc | |
parent | ba5c0a4579ece5d53c009a14d00e683e70b982f4 (diff) | |
download | oats-12de1e8db90bccd5a0eefd21075f07c7b7e3dfaa.tar.gz oats-12de1e8db90bccd5a0eefd21075f07c7b7e3dfaa.tar.bz2 oats-12de1e8db90bccd5a0eefd21075f07c7b7e3dfaa.zip |
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
-rw-r--r-- | Makefile | 19 | ||||
-rw-r--r-- | lib/arena.c (renamed from memory.c) | 74 | ||||
-rw-r--r-- | lib/arena.h (renamed from memory.h) | 23 | ||||
-rw-r--r-- | lib/sv.c (renamed from sv.c) | 2 | ||||
-rw-r--r-- | lib/sv.h (renamed from sv.h) | 2 | ||||
-rw-r--r-- | lib/vec.c (renamed from vec.c) | 2 | ||||
-rw-r--r-- | lib/vec.h (renamed from vec.h) | 2 | ||||
-rw-r--r-- | lisp/context.c | 92 | ||||
-rw-r--r-- | lisp/context.h | 38 | ||||
-rw-r--r-- | lisp/eval.c (renamed from eval.c) | 2 | ||||
-rw-r--r-- | lisp/eval.h (renamed from eval.h) | 2 | ||||
-rw-r--r-- | lisp/lisp.c (renamed from lisp.c) | 24 | ||||
-rw-r--r-- | lisp/lisp.h (renamed from lisp.h) | 10 | ||||
-rw-r--r-- | lisp/reader.c (renamed from reader.c) | 35 | ||||
-rw-r--r-- | lisp/reader.h (renamed from reader.h) | 6 | ||||
-rw-r--r-- | lisp/tag.c (renamed from tag.c) | 2 | ||||
-rw-r--r-- | lisp/tag.h (renamed from tag.h) | 24 | ||||
-rw-r--r-- | main.c | 24 |
18 files changed, 236 insertions, 147 deletions
@@ -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: @@ -13,7 +13,7 @@ * Description: Implementations for memory models. */ -#include "./memory.h" +#include <lib/arena.h> #include <malloc.h> #include <stdarg.h> @@ -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("<Context>: %luB/%luB main memory used\n", mem_used, mem_cap); - info("<Context>: %luB/%luB read space used\n", read_used, read_cap); - info("<Context>: %luB/%luB scratch space used\n", scr_used, scr_cap); -#endif -} @@ -10,13 +10,13 @@ * this program. If not, please go to <https://www.gnu.org/licenses/>. * 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 <base.h> #include <stdio.h> #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 @@ -13,7 +13,7 @@ * Description: String View implementation */ -#include "./sv.h" +#include <lib/sv.h> #include <stdarg.h> #include <stdio.h> @@ -16,7 +16,7 @@ #ifndef SV_H #define SV_H -#include "./memory.h" +#include <lib/arena.h> typedef struct SV { @@ -13,7 +13,7 @@ * Description: Vector implementation */ -#include "./vec.h" +#include <lib/vec.h> #include <malloc.h> #include <string.h> @@ -16,7 +16,7 @@ #ifndef VEC_H #define VEC_H -#include "./memory.h" +#include <lib/arena.h> 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 <https://www.gnu.org/licenses/>. + + * Created: 2025-05-12 + * Description: + */ + +#include <lisp/context.h> + +#include <string.h> + +// 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("<Context>: %luB/%luB main memory used\n", mem_used, mem_cap); + info("<Context>: %luB/%luB read space used\n", read_used, read_cap); + info("<Context>: %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 <https://www.gnu.org/licenses/>. + + * Created: 2025-05-12 + * Description: + */ + +#ifndef CONTEXT_H +#define CONTEXT_H + +#include <lib/arena.h> + +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 @@ -13,7 +13,7 @@ * Description: Evaluator implementation */ -#include "./eval.h" +#include <lisp/eval.h> err_t eval(context_t *ctx, lisp_t *obj, lisp_t **ret) { @@ -16,7 +16,7 @@ #ifndef EVAL_H #define EVAL_H -#include "./lisp.h" +#include <lisp/lisp.h> typedef enum { @@ -13,8 +13,8 @@ * Description: */ -#include "./lisp.h" -#include "./sv.h" +#include <lib/sv.h> +#include <lisp/lisp.h> #include <stdio.h> #include <string.h> @@ -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)) @@ -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 <lib/sv.h> +#include <lib/vec.h> +#include <lisp/context.h> +#include <lisp/tag.h> 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); @@ -13,7 +13,7 @@ * Description: Implementation of parser */ -#include "./reader.h" +#include <lisp/reader.h> #include <ctype.h> #include <string.h> @@ -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; } @@ -16,9 +16,9 @@ #ifndef READER_H #define READER_H -#include "./lisp.h" -#include "./memory.h" -#include "./vec.h" +#include <lib/vec.h> +#include <lisp/context.h> +#include <lisp/lisp.h> #define INPUT_CHUNK_SIZE 512 static const char SYM_CHARS[] = @@ -13,8 +13,8 @@ * Description: */ +#include <lisp/tag.h> #include <string.h> -#include <tag.h> lisp_t *tag_int(i64 i) { @@ -16,7 +16,7 @@ #ifndef TAG_H #define TAG_H -#include "./base.h" +#include <base.h> #include <stdbool.h> #include <stdlib.h> @@ -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, }; @@ -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 <lib/sv.h> +#include <lib/vec.h> +#include <lisp/lisp.h> +#include <lisp/reader.h> #include <assert.h> #include <ctype.h> @@ -27,6 +25,15 @@ #include <stdio.h> #include <string.h> +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) |