diff --git a/Makefile b/Makefile index e096bcb..5ee2e03 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,7 @@ CFLAGS=$(DEBUG_CFLAGS) $(LLVM_SAN_FLAGS) -std=c11 -Wall -Wpedantic $\ LD=gcc LDFLAGS=$(LLVM_SAN_FLAGS) -SRCS:=$(wildcard src/*.c) $(wildcard src/byterun/*.c) +SRCS:=$(wildcard src/*.c) OBJS:=$(SRCS:src/%.c=bin/%.o) DEPS:=$(SRCS:src/%.c=bin/deps/%.d) diff --git a/src/byterun/BYTECODE.md b/src/byterun/BYTECODE.md deleted file mode 100644 index 44c7664..0000000 --- a/src/byterun/BYTECODE.md +++ /dev/null @@ -1,59 +0,0 @@ -The bytecode interpreter runs using a stack. Most instructions operate on the -stack. Each instruction starts with a 1 byte opcode. If it has arguments, they -come next (and are detailed below). All functions push their return value onto -the stack (though some produce no return value). - -The leftmost (most significant) bit of the opcode is the "save flag" if it is -set, the instruction does not remove its arguments from the stack. - -Each block of bytecode (function, etc.) starts with some constants. They have -the following format - -WORDSIZE bytes - Number of constants -NOTE: in the below MINSIZE is the minimum number of bytes needed to reach any -object, signed. -The constants start with 1 byte for type (as in base.h). Their formats follow: -FIXNUM: WORDSIZE bytes (for the value with the tag already set). -FLOAT: WORDSIZE bytes (for the value with the tag already set). -CONS: two MINSIZE bytes fields for the car and cdr. -STRING: WORDSIZE bytes for the length, then the bytes themselves. -SYMBOL: WORDSIZE bytes for the length, then the bytes themselves. These are for -the name. The VM interns the symbol when it loads the bytecode. -VECTOR: WORDSIZE bytes for the length. Then MINSIZE bytes for each element. -HASH_TABLE: Not a valid constant -FUNCTION: TODO - Not implemented yet (this will include lambdas). -LIST (Type code is FUNCTION + 1): Ditto vector, but a list is created -instead. This is just a convenience. - -Instructions (Name - Opcode): - -NIL - 0x0: Push nil onto the stack. - -CONS - 0x1: Return a cons of the top of the stack. The top becomes the cdr and -the next element the car. - -CAR - 0x2: Return the car of the cons on top of the stack. - -CDR - 0x3: Return the cdr of the cons on top of the stack. - -NULL - 0x4: Return t if the top if the stack is nil, otherwise return nil. - -POP - 0x5: Throw away the top of the stack (produces no value). Doing this with -the save flag set is a noop. - -COPY - 0x6: Takes one argument which is a zero-indexed offset from the top of -the stack (as in 0 is the top). Pushes a copy of the element onto the top of the -stack. - -LOAD - 0x7: Load the constant numbered onto the top of the stack. This takes no -stack arguments. It takes one constant argument (which is the smallest width -necessary to load all constants). This argument is simply a number. - -EQ - 0x8: If the top two elements of the stack are the same, object, return t, -otherwise return nil. - -FUNCALL - 0x9: Call the function on top of the stack. The second argument is the -number of arguments. That many elements are then used as the arguments. The -first argument is the one directly following the count. - -PRINT - 0x7f: DEBUG ONLY - print the top of the stack diff --git a/src/byterun/assemble.c b/src/byterun/assemble.c deleted file mode 100644 index eda2882..0000000 --- a/src/byterun/assemble.c +++ /dev/null @@ -1,210 +0,0 @@ -#include "assemble.h" - -#include "base.h" -#include "memory.h" - -#include -#include -#include -#include - -BytecodeOpcode bytecode_opcode_by_name(const char *name, size_t length) { - struct Bucket { - size_t name_len; - const char *name; - BytecodeOpcode opcode; - struct Bucket *next; - }; - static struct Bucket *TABLE[26] = {NULL}; - static bool did_init = false; - if (!did_init) { -#define PUT(mname) \ - { \ - struct Bucket *n = lisp_malloc(sizeof(struct Bucket)); \ - n->name_len = sizeof(#mname) - 1; \ - n->name = #mname; \ - n->opcode = BO_##mname; \ - size_t hash = tolower(#mname[0]) - 'a'; \ - n->next = TABLE[hash]; \ - TABLE[hash] = n; \ - } - PUT(NIL); - PUT(CONS); - PUT(CAR); - PUT(CDR); - PUT(NULL); - PUT(POP); - PUT(COPY); - PUT(LOAD); - PUT(EQ); - PUT(FUNCALL); - PUT(PRINT); -#undef PUT - did_init = true; - } - if (!length) { - return BO_INVALID; - } - size_t hash = tolower(name[0]) - 'a'; - assert(0 <= hash && hash <= 25); - for (struct Bucket *cur = TABLE[hash]; cur; cur = cur->next) { - if (cur->name_len == length && strcasecmp(cur->name, name) == 0) { - return cur->opcode; - } - } - return BO_INVALID; -} - -const char *bytecode_opcode_name(BytecodeOpcode opcode, size_t *length) { -#define DEF(name) \ - case BO_##name: \ - if (length) { \ - *length = sizeof(#name) - 1; \ - } \ - return #name - switch (opcode) { - DEF(NIL); - DEF(CONS); - DEF(CAR); - DEF(CDR); - DEF(NULL); - DEF(POP); - DEF(COPY); - DEF(LOAD); - DEF(EQ); - DEF(FUNCALL); - DEF(PRINT); - case BO_INVALID: - return NULL; - default: - abort(); - } -#undef DEF -} - -BytecodeConstType bytecode_const_type_by_name(const char *name, size_t length) { -#define CHECK(type) \ - if (strcasecmp(name, #type)) { \ - return BYTECODE_CONST_##type; \ - } - CHECK(FIXNUM); - CHECK(FLOAT); - CHECK(CONS); - CHECK(STRING); - CHECK(SYMBOL); - CHECK(VECTOR); - CHECK(FUNCTION); - CHECK(LIST); - return BYTECODE_CONST_INVALID; -#undef CHECK -} - -const char *bytecode_const_name(BytecodeConstType type, size_t *length) { -#define DEF(name) \ - case BYTECODE_CONST_##name: \ - if (length) { \ - *length = sizeof(#name) - 1; \ - } \ - return #name; - switch (type) { - DEF(FIXNUM); - DEF(FLOAT); - DEF(CONS); - DEF(STRING); - DEF(SYMBOL); - DEF(VECTOR); - DEF(FUNCTION); - DEF(LIST); - case BO_INVALID: - return NULL; - default: - abort(); - } -} - -enum AssembleMode { MODE_NONE, MODE_CONSTANTS, MODE_TEXT }; - -typedef struct { - BytecodeConstType type; - union { - fixnum_t fixnum; - lisp_float_t lisp_float; - struct { - intptr_t car; - intptr_t cdr; - } cons; - struct { - size_t length; - const char *bytes; - } string; - struct { - size_t length; - const char *bytes; - } symbol; - struct { - size_t length; - intptr_t elements; - } vector; - struct { - // TODO implement - int dummy; - } function; - struct { - size_t length; - intptr_t elements; - } list; - }; -} AssembleConstant; - -struct AssembleState { - enum AssembleMode mode; - size_t line_no; - - size_t num_constants; - AssembleConstant *constants; - size_t num_instructions; -}; - -static bool is_blank_string(const char *data, size_t len) { - for (size_t i = 0; i < len; ++i) { - if (data[i] != ' ' && data[i] != '\t') { - return false; - } - } - return true; -} - -static BytecodeAssembleStatus -process_line_none_mode(struct AssembleState *restrict state, - const size_t line_len, const char line[line_len], - BytecodeAssembleError *restrict error) {} - -BytecodeAssembleStatus -bytecode_assemble(const size_t src_length, const char src[src_length], - size_t *restrict out_length, char **restrict out, - BytecodeAssembleError *restrict error) { - StringStream stream; - string_stream_init(&stream); - struct AssembleState state = { - .mode = MODE_NONE, - .line_no = 1, - .num_constants = 0, - .constants = NULL, - .num_instructions = 0, - }; - const char *line = NULL; - size_t line_len; - while (strgetline(src, src_length, &line, &line_len)) { - switch (state.mode) { - case MODE_NONE: - process_line_none_mode(&state, line_len, line, error); - break; - case MODE_CONSTANTS: - case MODE_TEXT: - break; - } - ++state.line_no; - } - string_stream_steal(&stream, out, out_length); - return BYTECODE_ASSEMBLE_OK; -} diff --git a/src/byterun/assemble.h b/src/byterun/assemble.h deleted file mode 100644 index d6d8a48..0000000 --- a/src/byterun/assemble.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef INCLUDED_ASSEMBLE_H -#define INCLUDED_ASSEMBLE_H - -#include "byterun.h" - -#include - -BytecodeOpcode bytecode_opcode_by_name(const char *name, size_t length); -const char *bytecode_opcode_name(BytecodeOpcode opcode, size_t *length); - -BytecodeConstType bytecode_const_type_by_name(const char *name, size_t length); -const char *bytecode_const_name(BytecodeConstType type, size_t *length); - -typedef enum { - BYTECODE_ASSEMBLE_OK, - BYTECODE_ASSEMBLE_SYNTAX, -} BytecodeAssembleStatus; - -typedef struct { - size_t line; - size_t col; - size_t length; - const char *detail; -} BytecodeAssembleError; - -BytecodeAssembleStatus bytecode_assemble(const size_t src_length, - const char src[src_length], - size_t *restrict out_length, - char **restrict out, - BytecodeAssembleError *restrict error); - -#endif diff --git a/src/byterun/byterun.c b/src/byterun/byterun.c deleted file mode 100644 index 267d70e..0000000 --- a/src/byterun/byterun.c +++ /dev/null @@ -1 +0,0 @@ -#include "byterun.h" diff --git a/src/byterun/byterun.h b/src/byterun/byterun.h deleted file mode 100644 index 59c70d5..0000000 --- a/src/byterun/byterun.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef INCLUDED_BYTERUN_H -#define INCLUDED_BYTERUN_H - -typedef enum { - BO_NIL = 0x00, - BO_CONS = 0x01, - BO_CAR = 0x02, - BO_CDR = 0x03, - BO_NULL = 0x04, - BO_POP = 0x05, - BO_COPY = 0x06, - BO_LOAD = 0x07, - BO_EQ = 0x08, - BO_FUNCALL = 0x09, - BO_PRINT = 0x7f, - BO_INVALID = 0xff, -} BytecodeOpcode; - -// make sure this is kept up to date with base.h -typedef enum { - BYTECODE_CONST_FIXNUM = 0, - BYTECODE_CONST_FLOAT = 1, - BYTECODE_CONST_CONS = 2, - BYTECODE_CONST_STRING = 3, - BYTECODE_CONST_SYMBOL = 4, - BYTECODE_CONST_VECTOR = 5, - // So such constant BYTECODE_CONST_HASH_TABLE = 6, - BYTECODE_CONST_FUNCTION = 7, - BYTECODE_CONST_LIST = 8, - BYTECODE_CONST_INVALID = 0xff, -} BytecodeConstType; - -#endif diff --git a/src/main.c b/src/main.c index 7565900..0ebcfdb 100644 --- a/src/main.c +++ b/src/main.c @@ -1,4 +1,3 @@ -#include "byterun/assemble.h" #include "lisp.h" #include "read.h"