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
This commit is contained in:
19
Makefile
19
Makefile
@@ -1,6 +1,7 @@
|
|||||||
CC=gcc
|
CC=gcc
|
||||||
OUT=oats.out
|
OUT=oats.out
|
||||||
LIBS=-I.
|
INCLUDES=-I.
|
||||||
|
LIBS=
|
||||||
ARGS=
|
ARGS=
|
||||||
|
|
||||||
RELEASE=0
|
RELEASE=0
|
||||||
@@ -16,7 +17,7 @@ CFLAGS=$(GFLAGS) $(DFLAGS)
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
DIST=build
|
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)
|
OBJ:=$(SRC:%.c=$(DIST)/%.o)
|
||||||
DEPDIR=$(DIST)/dependencies
|
DEPDIR=$(DIST)/dependencies
|
||||||
DEPS:=$(SRC:%.c=$(DEPDIR)/%.d)
|
DEPS:=$(SRC:%.c=$(DEPDIR)/%.d)
|
||||||
@@ -25,10 +26,10 @@ DEPS:=$(SRC:%.c=$(DEPDIR)/%.d)
|
|||||||
all: $(DIST)/$(OUT)
|
all: $(DIST)/$(OUT)
|
||||||
|
|
||||||
$(DIST)/%.o: %.c | $(DIST) $(DEPDIR)
|
$(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)
|
$(DIST)/$(OUT): $(OBJ) | $(DIST)
|
||||||
$(CC) $(CFLAGS) $^ -o $@ $(LIBS)
|
$(CC) $(INCLUDES) $(CFLAGS) $^ -o $@ $(LIBS)
|
||||||
|
|
||||||
.PHONY: run
|
.PHONY: run
|
||||||
run: $(DIST)/$(OUT)
|
run: $(DIST)/$(OUT)
|
||||||
@@ -38,11 +39,19 @@ run: $(DIST)/$(OUT)
|
|||||||
clean:
|
clean:
|
||||||
rm -rfv $(DIST)/*
|
rm -rfv $(DIST)/*
|
||||||
|
|
||||||
$(DIST):
|
$(DIST): | $(DIST)/lib $(DIST)/lisp
|
||||||
mkdir -p $(DIST)
|
mkdir -p $(DIST)
|
||||||
|
|
||||||
|
$(DIST)/lib:
|
||||||
|
mkdir -p $(DIST)/lib
|
||||||
|
|
||||||
|
$(DIST)/lisp:
|
||||||
|
mkdir -p $(DIST)/lisp
|
||||||
|
|
||||||
$(DEPDIR):
|
$(DEPDIR):
|
||||||
mkdir -p $(DEPDIR)
|
mkdir -p $(DEPDIR)
|
||||||
|
mkdir -p $(DEPDIR)/lib
|
||||||
|
mkdir -p $(DEPDIR)/lisp
|
||||||
|
|
||||||
.PHONY:
|
.PHONY:
|
||||||
watch:
|
watch:
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
* Description: Implementations for memory models.
|
* Description: Implementations for memory models.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "./memory.h"
|
#include <lib/arena.h>
|
||||||
|
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
@@ -201,75 +201,3 @@ void arena_cleanup(arena_t *arena)
|
|||||||
|
|
||||||
memset(arena, 0, sizeof(*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/>.
|
* this program. If not, please go to <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
* Created: 2025-04-05
|
* Created: 2025-04-05
|
||||||
* Description: Memory management structures
|
* Description: Arena
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef MEMORY_H
|
#ifndef ARENA_H
|
||||||
#define MEMORY_H
|
#define ARENA_H
|
||||||
|
|
||||||
#include "./base.h"
|
#include <base.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#define PAGE_DEFAULT_SIZE 1024
|
#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_reset(arena_t *arena);
|
||||||
void arena_cleanup(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
|
#endif
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
* Description: String View implementation
|
* Description: String View implementation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "./sv.h"
|
#include <lib/sv.h>
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
#ifndef SV_H
|
#ifndef SV_H
|
||||||
#define SV_H
|
#define SV_H
|
||||||
|
|
||||||
#include "./memory.h"
|
#include <lib/arena.h>
|
||||||
|
|
||||||
typedef struct SV
|
typedef struct SV
|
||||||
{
|
{
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
* Description: Vector implementation
|
* Description: Vector implementation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "./vec.h"
|
#include <lib/vec.h>
|
||||||
|
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
#ifndef VEC_H
|
#ifndef VEC_H
|
||||||
#define VEC_H
|
#define VEC_H
|
||||||
|
|
||||||
#include "./memory.h"
|
#include <lib/arena.h>
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
92
lisp/context.c
Normal file
92
lisp/context.c
Normal file
@@ -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
|
||||||
|
}
|
||||||
38
lisp/context.h
Normal file
38
lisp/context.h
Normal file
@@ -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
|
* Description: Evaluator implementation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "./eval.h"
|
#include <lisp/eval.h>
|
||||||
|
|
||||||
err_t eval(context_t *ctx, lisp_t *obj, lisp_t **ret)
|
err_t eval(context_t *ctx, lisp_t *obj, lisp_t **ret)
|
||||||
{
|
{
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
#ifndef EVAL_H
|
#ifndef EVAL_H
|
||||||
#define EVAL_H
|
#define EVAL_H
|
||||||
|
|
||||||
#include "./lisp.h"
|
#include <lisp/lisp.h>
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
@@ -13,8 +13,8 @@
|
|||||||
* Description:
|
* Description:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "./lisp.h"
|
#include <lib/sv.h>
|
||||||
#include "./sv.h"
|
#include <lisp/lisp.h>
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -130,6 +130,13 @@ bool as_bool(lisp_t *obj)
|
|||||||
return (bool)UNTAG(obj, BOOL);
|
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)
|
vec_t *as_vec(lisp_t *obj)
|
||||||
{
|
{
|
||||||
assert(IS_TAG(obj, VEC));
|
assert(IS_TAG(obj, VEC));
|
||||||
@@ -214,6 +221,19 @@ sv_t serialise(context_t *ctx, lisp_t *ptr)
|
|||||||
,
|
,
|
||||||
as_bool(ptr) ? "#t" : "#f");
|
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:
|
case TAG_CONS:
|
||||||
{
|
{
|
||||||
if (!CAR(ptr) && !CDR(ptr))
|
if (!CAR(ptr) && !CDR(ptr))
|
||||||
@@ -16,11 +16,10 @@
|
|||||||
#ifndef LISP_H
|
#ifndef LISP_H
|
||||||
#define LISP_H
|
#define LISP_H
|
||||||
|
|
||||||
#include "./base.h"
|
#include <lib/sv.h>
|
||||||
#include "./memory.h"
|
#include <lib/vec.h>
|
||||||
#include "./sv.h"
|
#include <lisp/context.h>
|
||||||
#include "./tag.h"
|
#include <lisp/tag.h>
|
||||||
#include "./vec.h"
|
|
||||||
|
|
||||||
typedef struct Cons
|
typedef struct Cons
|
||||||
{
|
{
|
||||||
@@ -33,7 +32,6 @@ typedef struct Cell
|
|||||||
u8 data[];
|
u8 data[];
|
||||||
} cell_t;
|
} cell_t;
|
||||||
|
|
||||||
#define NIL 0
|
|
||||||
lisp_t *make_int(i64 integer);
|
lisp_t *make_int(i64 integer);
|
||||||
lisp_t *make_sym(context_t *ctx, char *data, u64 size);
|
lisp_t *make_sym(context_t *ctx, char *data, u64 size);
|
||||||
lisp_t *make_cons(context_t *ctx, lisp_t *car, lisp_t *cdr);
|
lisp_t *make_cons(context_t *ctx, lisp_t *car, lisp_t *cdr);
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
* Description: Implementation of parser
|
* Description: Implementation of parser
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "./reader.h"
|
#include <lisp/reader.h>
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -98,33 +98,38 @@ char input_next(input_t *input, u64 offset)
|
|||||||
|
|
||||||
void input_skip(input_t *inp)
|
void input_skip(input_t *inp)
|
||||||
{
|
{
|
||||||
// n + 2 lookup
|
while (!input_eof(inp))
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
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);
|
i64 newline = sv_find_subcstr(current, "\n", 1);
|
||||||
if (newline < 0)
|
if (newline < 0)
|
||||||
inp->offset = inp->str.size;
|
inp->offset = inp->str.size;
|
||||||
else
|
else
|
||||||
inp->offset += newline + 1;
|
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);
|
i64 offset = sv_find_subcstr(current, "|#", 2);
|
||||||
if (offset < 0)
|
if (offset < 0)
|
||||||
inp->offset = inp->str.size;
|
inp->offset = inp->str.size;
|
||||||
else
|
else
|
||||||
inp->offset += offset + 2;
|
inp->offset += offset + 2;
|
||||||
|
// Then skip any whitespace
|
||||||
}
|
}
|
||||||
|
// Nothing to skip, stop.
|
||||||
inp->offset += sv_while(sv_cut(inp->str, inp->offset), is_space);
|
else
|
||||||
current = sv_cut(inp->str, inp->offset);
|
break;
|
||||||
lookup = sv_chop(current, 2);
|
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
perr_t parse_int(context_t *ctx, input_t *inp, lisp_t **ret)
|
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");
|
TODO("Not implemented reader macro for characters or weird bases");
|
||||||
}
|
}
|
||||||
else if (c == '(')
|
else if (c == '(')
|
||||||
{
|
|
||||||
return parse_vec(ctx, inp, ret);
|
return parse_vec(ctx, inp, ret);
|
||||||
}
|
|
||||||
else if (c == 't' || c == 'f')
|
else if (c == 't' || c == 'f')
|
||||||
return parse_bool(ctx, inp, ret);
|
return parse_bool(ctx, inp, ret);
|
||||||
|
else if (c == 'e')
|
||||||
|
{
|
||||||
|
// Scientific notation for floats
|
||||||
|
}
|
||||||
return PERR_UNEXPECTED_READER_MACRO_SYMBOL;
|
return PERR_UNEXPECTED_READER_MACRO_SYMBOL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -16,9 +16,9 @@
|
|||||||
#ifndef READER_H
|
#ifndef READER_H
|
||||||
#define READER_H
|
#define READER_H
|
||||||
|
|
||||||
#include "./lisp.h"
|
#include <lib/vec.h>
|
||||||
#include "./memory.h"
|
#include <lisp/context.h>
|
||||||
#include "./vec.h"
|
#include <lisp/lisp.h>
|
||||||
|
|
||||||
#define INPUT_CHUNK_SIZE 512
|
#define INPUT_CHUNK_SIZE 512
|
||||||
static const char SYM_CHARS[] =
|
static const char SYM_CHARS[] =
|
||||||
@@ -13,8 +13,8 @@
|
|||||||
* Description:
|
* Description:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <lisp/tag.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <tag.h>
|
|
||||||
|
|
||||||
lisp_t *tag_int(i64 i)
|
lisp_t *tag_int(i64 i)
|
||||||
{
|
{
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
#ifndef TAG_H
|
#ifndef TAG_H
|
||||||
#define TAG_H
|
#define TAG_H
|
||||||
|
|
||||||
#include "./base.h"
|
#include <base.h>
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -25,18 +25,20 @@
|
|||||||
// pointers
|
// pointers
|
||||||
typedef struct Obj lisp_t;
|
typedef struct Obj lisp_t;
|
||||||
|
|
||||||
|
#define NIL NULL
|
||||||
|
|
||||||
enum Tag
|
enum Tag
|
||||||
{
|
{
|
||||||
TAG_NIL = 0b00000000, // Atomic types
|
TAG_NIL = 0b00000000, // Atomic types
|
||||||
TAG_INT = 0b00000001, // special so we can encode 63 bit integers
|
TAG_INT = 0b00000001, // special so we can encode 63 bit integers
|
||||||
TAG_SYM = 0b00000100,
|
TAG_SYM = 0b00000100,
|
||||||
TAG_SSYM = 0b00001000,
|
TAG_SSYM = 0b00001000,
|
||||||
TAG_CHAR = 0b00001100,
|
TAG_CHAR = 0b00001100,
|
||||||
TAG_BOOL = 0b00010000,
|
TAG_BOOL = 0b00010000,
|
||||||
// TAG_FLOAT = 0b00010100,
|
TAG_FLOAT = 0b00010100,
|
||||||
TAG_CONS = 0b00000010, // Container types
|
TAG_CONS = 0b00000010, // Container types
|
||||||
TAG_VEC = 0b00000110,
|
TAG_VEC = 0b00000110,
|
||||||
TAG_STR = 0b00001010,
|
TAG_STR = 0b00001010,
|
||||||
|
|
||||||
NUM_TAGS = 9,
|
NUM_TAGS = 9,
|
||||||
};
|
};
|
||||||
24
main.c
24
main.c
@@ -13,12 +13,10 @@
|
|||||||
* Description: Entrypoint
|
* Description: Entrypoint
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "./base.h"
|
#include <lib/sv.h>
|
||||||
#include "./lisp.h"
|
#include <lib/vec.h>
|
||||||
#include "./memory.h"
|
#include <lisp/lisp.h>
|
||||||
#include "./reader.h"
|
#include <lisp/reader.h>
|
||||||
#include "./sv.h"
|
|
||||||
#include "./vec.h"
|
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@@ -27,6 +25,15 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.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 main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int exit = 0;
|
int exit = 0;
|
||||||
@@ -36,7 +43,10 @@ int main(int argc, char *argv[])
|
|||||||
if (argc > 1)
|
if (argc > 1)
|
||||||
filename = argv[1];
|
filename = argv[1];
|
||||||
else
|
else
|
||||||
filename = "./r7rs-tests.scm";
|
{
|
||||||
|
usage(argv[0], stderr);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
FILE *fp = fopen(filename, "r");
|
FILE *fp = fopen(filename, "r");
|
||||||
if (!fp)
|
if (!fp)
|
||||||
|
|||||||
Reference in New Issue
Block a user