aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAryadev Chavali <aryadev@aryadevchavali.com>2025-05-14 21:12:58 +0100
committerAryadev Chavali <aryadev@aryadevchavali.com>2025-05-15 22:25:45 +0100
commit12de1e8db90bccd5a0eefd21075f07c7b7e3dfaa (patch)
tree0434141f2bfd24207a2864f613a1c2e3ee7181fc
parentba5c0a4579ece5d53c009a14d00e683e70b982f4 (diff)
downloadoats-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--Makefile19
-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.c92
-rw-r--r--lisp/context.h38
-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.c24
18 files changed, 236 insertions, 147 deletions
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
index 0d9fe13..aa2d775 100644
--- a/memory.c
+++ b/lib/arena.c
@@ -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
-}
diff --git a/memory.h b/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 <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
diff --git a/sv.c b/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 <lib/sv.h>
#include <stdarg.h>
#include <stdio.h>
diff --git a/sv.h b/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 <lib/arena.h>
typedef struct SV
{
diff --git a/vec.c b/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 <lib/vec.h>
#include <malloc.h>
#include <string.h>
diff --git a/vec.h b/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 <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
diff --git a/eval.c b/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 <lisp/eval.h>
err_t eval(context_t *ctx, lisp_t *obj, lisp_t **ret)
{
diff --git a/eval.h b/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 <lisp/lisp.h>
typedef enum
{
diff --git a/lisp.c b/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 <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))
diff --git a/lisp.h b/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 <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);
diff --git a/reader.c b/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 <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;
}
diff --git a/reader.h b/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 <lib/vec.h>
+#include <lisp/context.h>
+#include <lisp/lisp.h>
#define INPUT_CHUNK_SIZE 512
static const char SYM_CHARS[] =
diff --git a/tag.c b/lisp/tag.c
index 5fc03e0..26db6d5 100644
--- a/tag.c
+++ b/lisp/tag.c
@@ -13,8 +13,8 @@
* Description:
*/
+#include <lisp/tag.h>
#include <string.h>
-#include <tag.h>
lisp_t *tag_int(i64 i)
{
diff --git a/tag.h b/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 <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,
};
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 <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)