Remove bytecomp stuff (for now)
This commit is contained in:
2
Makefile
2
Makefile
@ -19,7 +19,7 @@ CFLAGS=$(DEBUG_CFLAGS) $(LLVM_SAN_FLAGS) -std=c11 -Wall -Wpedantic $\
|
|||||||
LD=gcc
|
LD=gcc
|
||||||
LDFLAGS=$(LLVM_SAN_FLAGS)
|
LDFLAGS=$(LLVM_SAN_FLAGS)
|
||||||
|
|
||||||
SRCS:=$(wildcard src/*.c) $(wildcard src/byterun/*.c)
|
SRCS:=$(wildcard src/*.c)
|
||||||
OBJS:=$(SRCS:src/%.c=bin/%.o)
|
OBJS:=$(SRCS:src/%.c=bin/%.o)
|
||||||
DEPS:=$(SRCS:src/%.c=bin/deps/%.d)
|
DEPS:=$(SRCS:src/%.c=bin/deps/%.d)
|
||||||
|
|
||||||
|
|||||||
@ -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
|
|
||||||
@ -1,210 +0,0 @@
|
|||||||
#include "assemble.h"
|
|
||||||
|
|
||||||
#include "base.h"
|
|
||||||
#include "memory.h"
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <strings.h>
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
@ -1,32 +0,0 @@
|
|||||||
#ifndef INCLUDED_ASSEMBLE_H
|
|
||||||
#define INCLUDED_ASSEMBLE_H
|
|
||||||
|
|
||||||
#include "byterun.h"
|
|
||||||
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
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
|
|
||||||
@ -1 +0,0 @@
|
|||||||
#include "byterun.h"
|
|
||||||
@ -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
|
|
||||||
@ -1,4 +1,3 @@
|
|||||||
#include "byterun/assemble.h"
|
|
||||||
#include "lisp.h"
|
#include "lisp.h"
|
||||||
#include "read.h"
|
#include "read.h"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user