Remove bytecomp stuff (for now)
This commit is contained in:
@ -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 "read.h"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user