aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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)