allocate global variable entry area by malloc and save it into pic_state

This commit is contained in:
Yuichi Nishiwaki 2013-10-18 00:15:15 +09:00
parent c92a672e01
commit e7a5784fd7
6 changed files with 61 additions and 63 deletions

View File

@ -12,6 +12,7 @@
#define PIC_HEAP_SIZE 8192 #define PIC_HEAP_SIZE 8192
#define PIC_STACK_SIZE 1024 #define PIC_STACK_SIZE 1024
#define PIC_IREP_SIZE 256 #define PIC_IREP_SIZE 256
#define PIC_GLOBALS_SIZE 1024
/* enable all debug flags */ /* enable all debug flags */
#define DEBUG 1 #define DEBUG 1

View File

@ -27,6 +27,8 @@ typedef struct {
pic_value sADD, sSUB, sMUL, sDIV; pic_value sADD, sSUB, sMUL, sDIV;
struct pic_env *global_env; struct pic_env *global_env;
pic_value *globals;
size_t glen, gcapa;
struct pic_irep **irep; struct pic_irep **irep;
size_t ilen, icapa; size_t ilen, icapa;

View File

@ -27,7 +27,6 @@ struct pic_code {
union { union {
double f; double f;
int i; int i;
struct pic_pair *gvar;
} u; } u;
}; };

View File

@ -169,7 +169,6 @@ static void
gc_mark_phase(pic_state *pic) gc_mark_phase(pic_state *pic)
{ {
pic_value *stack; pic_value *stack;
pic_callinfo *ci;
struct pic_env *env; struct pic_env *env;
int i; int i;

View File

@ -42,6 +42,11 @@ pic_open()
pic->ilen = 0; pic->ilen = 0;
pic->icapa = PIC_IREP_SIZE; pic->icapa = PIC_IREP_SIZE;
/* globals */
pic->globals = (struct pic_value *)malloc(sizeof(pic_value) * PIC_GLOBALS_SIZE);
pic->glen = 0;
pic->gcapa = PIC_GLOBALS_SIZE;
/* GC arena */ /* GC arena */
pic->arena_idx = 0; pic->arena_idx = 0;

114
src/vm.c
View File

@ -24,65 +24,55 @@ pic_assq(pic_state *pic, pic_value key, pic_value assoc)
goto enter; goto enter;
} }
enum scope_type { static bool
SCOPE_GLOBAL, env_lookup(pic_state *pic, pic_value sym, struct pic_env *env, int *depth, int *idx)
SCOPE_NONLOCAL,
SCOPE_LOCAL,
};
static enum scope_type
env_lookup(pic_state *pic, pic_value sym, struct pic_env *env, struct pic_pair **p)
{ {
pic_value v; pic_value v;
bool f = true; int d = 0;
enter: enter:
v = pic_assq(pic, sym, env->assoc); v = pic_assq(pic, sym, env->assoc);
if (! pic_nil_p(v)) { if (! pic_nil_p(v)) {
*p = pic_pair_ptr(v); if (env->parent == NULL) { /* global */
goto leave; *depth = -1;
}
else { /* non-global */
*depth = d;
}
*idx = (int)pic_float(pic_pair_ptr(v)->cdr);
return true;
} }
f = false;
if (env->parent) { if (env->parent) {
env = env->parent; env = env->parent;
++d;
goto enter; goto enter;
} }
return false;
*p = NULL;
leave:
if (env->parent) {
if (f) {
return SCOPE_LOCAL;
}
else {
return SCOPE_NONLOCAL;
}
}
else {
return SCOPE_GLOBAL;
}
} }
static struct pic_pair * static int
env_define(pic_state *pic, pic_value sym, struct pic_env *env) env_global_define(pic_state *pic, pic_value sym)
{ {
pic_value cell; pic_value cell;
int d, idx;
cell = pic_cons(pic, sym, pic_undef_value()); if (env_lookup(pic, sym, pic->global_env, &d, &idx)) {
env->assoc = pic_cons(pic, cell, env->assoc); return idx;
}
return pic_pair_ptr(cell); idx = pic->glen++;
cell = pic_cons(pic, sym, pic_float_value(idx));
pic->global_env->assoc = pic_cons(pic, cell, pic->global_env->assoc);
return idx;
} }
static struct pic_env * static struct pic_env *
env_new(pic_state *pic, pic_value args, struct pic_env *env) env_new(pic_state *pic, pic_value args, struct pic_env *env)
{ {
struct pic_env *inner_env; struct pic_env *inner_env;
pic_value v; pic_value v, cell;
struct pic_pair *cell;
int i; int i;
inner_env = (struct pic_env *)pic_alloc(pic, sizeof(struct pic_env)); inner_env = (struct pic_env *)pic_alloc(pic, sizeof(struct pic_env));
@ -91,8 +81,10 @@ env_new(pic_state *pic, pic_value args, struct pic_env *env)
i = -1; i = -1;
for (v = args; ! pic_nil_p(v); v = pic_cdr(pic, v)) { for (v = args; ! pic_nil_p(v); v = pic_cdr(pic, v)) {
cell = env_define(pic, pic_car(pic, v), inner_env); pic_value sym = pic_car(pic, v);
cell->cdr = pic_float_value(i--);
cell = pic_cons(pic, sym, pic_float_value(i--));
inner_env->assoc = pic_cons(pic, cell, inner_env->assoc);
} }
return inner_env; return inner_env;
@ -102,13 +94,13 @@ void
pic_defun(pic_state *pic, const char *name, pic_func_t cfunc) pic_defun(pic_state *pic, const char *name, pic_func_t cfunc)
{ {
struct pic_proc *proc; struct pic_proc *proc;
struct pic_pair *cell; int idx;
proc = (struct pic_proc *)pic_obj_alloc(pic, sizeof(struct pic_proc), PIC_TT_PROC); proc = (struct pic_proc *)pic_obj_alloc(pic, sizeof(struct pic_proc), PIC_TT_PROC);
proc->cfunc_p = true; proc->cfunc_p = true;
proc->u.cfunc = cfunc; proc->u.cfunc = cfunc;
cell = env_define(pic, pic_intern_cstr(pic, name), pic->global_env); idx = env_global_define(pic, pic_intern_cstr(pic, name));
cell->cdr = pic_obj_value(proc); pic->globals[idx] = pic_obj_value(proc);
} }
void void
@ -164,10 +156,10 @@ print_irep(pic_state *pic, struct pic_irep *irep)
printf("OP_PUSHNUM\t%g\n", irep->code[i].u.f); printf("OP_PUSHNUM\t%g\n", irep->code[i].u.f);
break; break;
case OP_GREF: case OP_GREF:
printf("OP_GREF\t%p\n", irep->code[i].u.gvar); printf("OP_GREF\t%i\n", irep->code[i].u.i);
break; break;
case OP_GSET: case OP_GSET:
printf("OP_GSET\t%p\n", irep->code[i].u.gvar); printf("OP_GSET\t%i\n", irep->code[i].u.i);
break; break;
case OP_LREF: case OP_LREF:
printf("OP_LREF\t%d\n", irep->code[i].u.i); printf("OP_LREF\t%d\n", irep->code[i].u.i);
@ -241,25 +233,25 @@ pic_gen(pic_state *pic, struct pic_irep *irep, pic_value obj, struct pic_env *en
switch (pic_type(obj)) { switch (pic_type(obj)) {
case PIC_TT_SYMBOL: { case PIC_TT_SYMBOL: {
enum scope_type s; bool b;
struct pic_pair *gvar; int depth, idx;
s = env_lookup(pic, obj, env, &gvar); b = env_lookup(pic, obj, env, &depth, &idx);
if (! gvar) { if (! b) {
pic_raise(pic, "unbound variable"); pic_raise(pic, "unbound variable");
} }
switch (s) {
case SCOPE_LOCAL: if (depth == -1) { /* global */
irep->code[irep->clen].insn = OP_LREF;
irep->code[irep->clen].u.i = (int)pic_float(gvar->cdr);
irep->clen++;
break;
case SCOPE_GLOBAL:
irep->code[irep->clen].insn = OP_GREF; irep->code[irep->clen].insn = OP_GREF;
irep->code[irep->clen].u.gvar = gvar; irep->code[irep->clen].u.i = idx;
irep->clen++; irep->clen++;
break; }
case SCOPE_NONLOCAL: else if (depth == 0) { /* local */
irep->code[irep->clen].insn = OP_LREF;
irep->code[irep->clen].u.i = idx;
irep->clen++;
}
else { /* nonlocal */
pic_raise(pic, "reference to closed variable not supported"); pic_raise(pic, "reference to closed variable not supported");
} }
break; break;
@ -269,14 +261,14 @@ pic_gen(pic_state *pic, struct pic_irep *irep, pic_value obj, struct pic_env *en
proc = pic_car(pic, obj); proc = pic_car(pic, obj);
if (pic_eq_p(pic, proc, sDEFINE)) { if (pic_eq_p(pic, proc, sDEFINE)) {
struct pic_pair *gvar; int idx;
gvar = env_define(pic, pic_car(pic, pic_cdr(pic, obj)), env); idx = env_global_define(pic, pic_car(pic, pic_cdr(pic, obj)));
pic_gen(pic, irep, pic_car(pic, pic_cdr(pic, pic_cdr(pic, obj))), env); pic_gen(pic, irep, pic_car(pic, pic_cdr(pic, pic_cdr(pic, obj))), env);
irep->code[irep->clen].insn = OP_GSET; irep->code[irep->clen].insn = OP_GSET;
irep->code[irep->clen].u.gvar = gvar; irep->code[irep->clen].u.i = idx;
irep->clen++; irep->clen++;
irep->code[irep->clen].insn = OP_PUSHFALSE; irep->code[irep->clen].insn = OP_PUSHFALSE;
irep->clen++; irep->clen++;
@ -524,11 +516,11 @@ pic_run(pic_state *pic, struct pic_proc *proc, pic_value args)
NEXT; NEXT;
} }
CASE(OP_GREF) { CASE(OP_GREF) {
PUSH(pc->u.gvar->cdr); PUSH(pic->globals[pc->u.i]);
NEXT; NEXT;
} }
CASE(OP_GSET) { CASE(OP_GSET) {
pc->u.gvar->cdr = POP(); pic->globals[pc->u.i] = POP();
NEXT; NEXT;
} }
CASE(OP_LREF) { CASE(OP_LREF) {