implement bytecode interpreter and compiler
This commit is contained in:
parent
d23a9a4827
commit
c63c1eaf6e
19 changed files with 1055 additions and 547 deletions
|
|
@ -14,6 +14,7 @@ typedef intptr_t I;
|
|||
typedef uintptr_t U;
|
||||
typedef char C;
|
||||
typedef uint8_t U8;
|
||||
typedef uint16_t U16;
|
||||
typedef uint32_t U32;
|
||||
typedef int32_t I32;
|
||||
typedef size_t Z;
|
||||
|
|
@ -26,7 +27,7 @@ typedef U O;
|
|||
#define NUM(x) (((O)((I)(x) << 1)) | (O)1)
|
||||
#define ORD(x) ((I)(x) >> 1)
|
||||
|
||||
// Pair
|
||||
// Cons pair
|
||||
typedef struct Pa {
|
||||
O head, tail;
|
||||
} Pa;
|
||||
|
|
@ -48,11 +49,21 @@ typedef struct Cl {
|
|||
O args, body, env;
|
||||
} Cl;
|
||||
|
||||
// Bytecode
|
||||
typedef struct Bc {
|
||||
Z len;
|
||||
U8 *data;
|
||||
Z constant_count;
|
||||
O *constants;
|
||||
} Bc;
|
||||
|
||||
// Primitive
|
||||
typedef struct In In;
|
||||
typedef struct Pr {
|
||||
const char *name;
|
||||
O (*fn)(In *, O, O);
|
||||
O (*fn)(In *, O *, int, O); // fn(interp, args_array, argc, env)
|
||||
int min_args; // Minimum number of arguments (-1 for no check)
|
||||
int max_args; // Maximum number of arguments (-1 for variadic)
|
||||
} Pr;
|
||||
|
||||
// Symbol table
|
||||
|
|
@ -62,7 +73,7 @@ typedef struct St {
|
|||
Sy **data;
|
||||
} St;
|
||||
|
||||
#define HEAP_BYTES (1024 * 1024)
|
||||
#define HEAP_BYTES (4 * 1024 * 1024)
|
||||
#define TYPE_MASK 7
|
||||
|
||||
enum {
|
||||
|
|
@ -81,6 +92,7 @@ enum {
|
|||
TYPE_STR,
|
||||
TYPE_CLOS,
|
||||
TYPE_MAC,
|
||||
TYPE_CODE,
|
||||
TYPE_FWD,
|
||||
TYPE__MAX,
|
||||
};
|
||||
|
|
@ -125,6 +137,14 @@ typedef struct Er {
|
|||
} stack;
|
||||
} Er;
|
||||
|
||||
// Call frame
|
||||
typedef struct Fr {
|
||||
U8 *ip;
|
||||
O env;
|
||||
} Fr;
|
||||
|
||||
#define VM_STACK_SIZE 4096
|
||||
|
||||
// Interpreter context
|
||||
typedef struct In {
|
||||
Gc gc;
|
||||
|
|
@ -132,8 +152,64 @@ typedef struct In {
|
|||
O env;
|
||||
Er err;
|
||||
O t; // the T symbol
|
||||
O stack[VM_STACK_SIZE];
|
||||
O *sp;
|
||||
} In;
|
||||
|
||||
// Opcodes
|
||||
enum {
|
||||
OP_HALT,
|
||||
OP_CONST,
|
||||
OP_GET,
|
||||
OP_SET,
|
||||
OP_JUMP,
|
||||
OP_JUMP_IF_NIL,
|
||||
OP_CALL,
|
||||
OP_RET,
|
||||
OP_POP,
|
||||
OP_CLOS,
|
||||
OP_TAIL_CALL,
|
||||
OP_BIND,
|
||||
OP_BIND_REST,
|
||||
OP_PEEK,
|
||||
OP_GET_LOCAL, // Get local variable from stack frame
|
||||
OP_SET_LOCAL, // Set local variable in stack frame
|
||||
OP_RESERVE, // Reserve space for local variables
|
||||
};
|
||||
|
||||
// Local variable info
|
||||
typedef struct Lv {
|
||||
O name; // Symbol name
|
||||
U16 index; // Stack slot index
|
||||
int captured; // Is this variable captured by a closure?
|
||||
} Lv;
|
||||
|
||||
// Compiler context
|
||||
typedef struct Cm {
|
||||
In *in;
|
||||
U8 *code;
|
||||
Z count;
|
||||
Z capacity;
|
||||
struct {
|
||||
O *data;
|
||||
Z count;
|
||||
Z capacity;
|
||||
} constants;
|
||||
struct {
|
||||
O quote;
|
||||
O iff;
|
||||
O fn;
|
||||
O progn;
|
||||
O def;
|
||||
} specials;
|
||||
struct {
|
||||
Lv *data;
|
||||
Z count;
|
||||
Z capacity;
|
||||
} locals;
|
||||
int use_stack_locals; // Use stack-based locals instead of env
|
||||
} Cm;
|
||||
|
||||
enum {
|
||||
TOK_EOF = 0,
|
||||
TOK_COMMENT = ';',
|
||||
|
|
@ -180,8 +256,6 @@ V gc_finalize(Gc *gc);
|
|||
|
||||
void error_init(Er *err);
|
||||
void error_throw(In *in, const char *fmt, ...);
|
||||
void error_push_frame(In *in, const char *frame);
|
||||
void error_pop_frame(In *in);
|
||||
void error_print(In *in);
|
||||
|
||||
// Initialize an interpreter context.
|
||||
|
|
@ -189,12 +263,6 @@ V interp_init(In *in);
|
|||
// Finalize an interpreter context.
|
||||
V interp_finalize(In *in);
|
||||
|
||||
// Evaluate a list of values.
|
||||
O interp_eval_list(In *in, O list, O env);
|
||||
|
||||
// Evaluate an expression.
|
||||
O interp_eval(In *in, O obj, O env);
|
||||
|
||||
// Intern a string
|
||||
Sy *intern(St *tab, const char *str, Z len);
|
||||
|
||||
|
|
@ -209,10 +277,15 @@ V print(O obj);
|
|||
V println(O obj);
|
||||
|
||||
O symbol_make(In *in, const char *str);
|
||||
O prim_make(In *in, const char *name, O (*fn)(In *, O, O));
|
||||
O prim_make(In *in, const char *name, O (*fn)(In *, O *, int, O), int min_args, int max_args);
|
||||
|
||||
O list_assoc(In *in, O key, O alist);
|
||||
O list_reverse(In *in, O list);
|
||||
O list_next(In *in, O *list);
|
||||
|
||||
V compile(Cm *co, O expr, I toplevel);
|
||||
V disassemble(Cm *co);
|
||||
O vm_run(Cm *c);
|
||||
|
||||
int nexttoken(Lx *lex);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue