Merge branch 'improve-hygiene'

This commit is contained in:
Yuichi Nishiwaki 2014-02-12 11:36:35 +09:00
commit 5f2424b69e
11 changed files with 264 additions and 293 deletions

View File

@ -23,7 +23,6 @@
#define PIC_STACK_SIZE 1024 #define PIC_STACK_SIZE 1024
#define PIC_RESCUE_SIZE 30 #define PIC_RESCUE_SIZE 30
#define PIC_GLOBALS_SIZE 1024 #define PIC_GLOBALS_SIZE 1024
#define PIC_MACROS_SIZE 1024
#define PIC_SYM_POOL_SIZE 128 #define PIC_SYM_POOL_SIZE 128
#define PIC_IREP_SIZE 8 #define PIC_IREP_SIZE 8
#define PIC_POOL_SIZE 8 #define PIC_POOL_SIZE 8

View File

@ -107,6 +107,8 @@ typedef struct {
pic_value *globals; pic_value *globals;
size_t glen, gcapa; size_t glen, gcapa;
xhash *macros;
pic_value lib_tbl; pic_value lib_tbl;
struct pic_lib *lib; struct pic_lib *lib;

View File

@ -11,31 +11,13 @@ extern "C" {
struct pic_senv { struct pic_senv {
PIC_OBJECT_HEADER PIC_OBJECT_HEADER
xhash *name;
struct pic_senv *up; struct pic_senv *up;
/* positive for variables, negative for macros (bitwise-not) */
xhash *tbl;
struct pic_syntax **stx;
size_t xlen, xcapa;
}; };
struct pic_syntax { struct pic_macro {
PIC_OBJECT_HEADER PIC_OBJECT_HEADER
enum { struct pic_proc *proc;
PIC_STX_DEFINE,
PIC_STX_SET,
PIC_STX_QUOTE,
PIC_STX_LAMBDA,
PIC_STX_IF,
PIC_STX_BEGIN,
PIC_STX_MACRO,
PIC_STX_DEFMACRO,
PIC_STX_DEFSYNTAX,
PIC_STX_DEFLIBRARY,
PIC_STX_IMPORT,
PIC_STX_EXPORT
} kind;
pic_sym sym;
struct pic_proc *macro;
struct pic_senv *senv; struct pic_senv *senv;
}; };
@ -48,19 +30,16 @@ struct pic_sc {
#define pic_sc(v) ((struct pic_sc *)pic_ptr(v)) #define pic_sc(v) ((struct pic_sc *)pic_ptr(v))
#define pic_sc_p(v) (pic_type(v) == PIC_TT_SC) #define pic_sc_p(v) (pic_type(v) == PIC_TT_SC)
#define pic_syntax(v) ((struct pic_syntax *)pic_ptr(v)) #define pic_macro(v) ((struct pic_macro *)pic_ptr(v))
#define pic_syntax_p(v) (pic_type(v) == PIC_TT_SYNTAX) #define pic_macro_p(v) (pic_type(v) == PIC_TT_MACRO)
#define pic_senv(v) ((struct pic_senv *)pic_ptr(v)) #define pic_senv(v) ((struct pic_senv *)pic_ptr(v))
#define pic_senv_p(v) (pic_type(v) == PIC_TT_SENV) #define pic_senv_p(v) (pic_type(v) == PIC_TT_SENV)
#define pic_senv_ptr(v) ((struct pic_senv *)pic_ptr(v)) #define pic_senv_ptr(v) ((struct pic_senv *)pic_ptr(v))
struct pic_senv *pic_null_syntactic_env(pic_state *pic); struct pic_senv *pic_null_syntactic_env(pic_state *);
struct pic_senv *pic_minimal_syntactic_env(pic_state *pic); struct pic_senv *pic_minimal_syntactic_env(pic_state *);
struct pic_senv *pic_core_syntactic_env(pic_state *pic); struct pic_senv *pic_core_syntactic_env(pic_state *);
struct pic_syntax *pic_syntax_new(pic_state *, int kind, pic_sym sym);
struct pic_syntax *pic_syntax_new_macro(pic_state *, pic_sym, struct pic_proc *, struct pic_senv *senv);
#if defined(__cplusplus) #if defined(__cplusplus)
} }

View File

@ -43,6 +43,8 @@ int pic_proc_cv_size(pic_state *, struct pic_proc *);
pic_value pic_proc_cv_ref(pic_state *, struct pic_proc *, size_t); pic_value pic_proc_cv_ref(pic_state *, struct pic_proc *, size_t);
void pic_proc_cv_set(pic_state *, struct pic_proc *, size_t, pic_value); void pic_proc_cv_set(pic_state *, struct pic_proc *, size_t, pic_value);
struct pic_proc *pic_papply(pic_state *, struct pic_proc *, pic_value);
#if defined(__cplusplus) #if defined(__cplusplus)
} }
#endif #endif

View File

@ -99,7 +99,7 @@ enum pic_tt {
PIC_TT_ENV, PIC_TT_ENV,
PIC_TT_CONT, PIC_TT_CONT,
PIC_TT_SENV, PIC_TT_SENV,
PIC_TT_SYNTAX, PIC_TT_MACRO,
PIC_TT_SC, PIC_TT_SC,
PIC_TT_LIB, PIC_TT_LIB,
PIC_TT_VAR, PIC_TT_VAR,
@ -248,8 +248,8 @@ pic_type_repr(enum pic_tt tt)
return "sc"; return "sc";
case PIC_TT_SENV: case PIC_TT_SENV:
return "senv"; return "senv";
case PIC_TT_SYNTAX: case PIC_TT_MACRO:
return "syntax"; return "macro";
case PIC_TT_LIB: case PIC_TT_LIB:
return "lib"; return "lib";
case PIC_TT_VAR: case PIC_TT_VAR:

View File

@ -98,9 +98,9 @@ static void pop_scope(analyze_state *);
state->slot = pic_intern_cstr(pic, name); \ state->slot = pic_intern_cstr(pic, name); \
} while (0) } while (0)
#define register_renamed_symbol(pic, state, slot, lib, name) do { \ #define register_renamed_symbol(pic, state, slot, lib, id) do { \
xh_entry *e; \ xh_entry *e; \
if (! (e = xh_get_int(lib->senv->tbl, pic_intern_cstr(pic, name)))) \ if (! (e = xh_get_int(lib->senv->name, pic_intern_cstr(pic, id)))) \
pic_error(pic, "internal error! native VM procedure not found"); \ pic_error(pic, "internal error! native VM procedure not found"); \
state->slot = e->val; \ state->slot = e->val; \
} while (0) } while (0)
@ -561,7 +561,7 @@ analyze_node(analyze_state *state, pic_value obj, bool tailpos)
case PIC_TT_PORT: case PIC_TT_PORT:
case PIC_TT_ERROR: case PIC_TT_ERROR:
case PIC_TT_SENV: case PIC_TT_SENV:
case PIC_TT_SYNTAX: case PIC_TT_MACRO:
case PIC_TT_SC: case PIC_TT_SC:
case PIC_TT_LIB: case PIC_TT_LIB:
case PIC_TT_VAR: case PIC_TT_VAR:
@ -1445,7 +1445,7 @@ global_ref(pic_state *pic, const char *name)
pic_sym sym; pic_sym sym;
sym = pic_intern_cstr(pic, name); sym = pic_intern_cstr(pic, name);
if (! (e = xh_get_int(pic->lib->senv->tbl, sym))) { if (! (e = xh_get_int(pic->lib->senv->name, sym))) {
return -1; return -1;
} }
assert(e->val >= 0); assert(e->val >= 0);
@ -1470,7 +1470,7 @@ global_def(pic_state *pic, const char *name)
gsym = pic_gensym(pic, sym); gsym = pic_gensym(pic, sym);
/* register to the senv */ /* register to the senv */
xh_put_int(pic->lib->senv->tbl, sym, gsym); xh_put_int(pic->lib->senv->name, sym, gsym);
/* register to the global table */ /* register to the global table */
gidx = pic->glen++; gidx = pic->glen++;

View File

@ -387,14 +387,14 @@ gc_mark_object(pic_state *pic, struct pic_object *obj)
gc_mark(pic, cont->results); gc_mark(pic, cont->results);
break; break;
} }
case PIC_TT_SYNTAX: { case PIC_TT_MACRO: {
struct pic_syntax *stx = (struct pic_syntax *)obj; struct pic_macro *mac = (struct pic_macro *)obj;
if (stx->macro) { if (mac->proc) {
gc_mark_object(pic, (struct pic_object *)stx->macro); gc_mark_object(pic, (struct pic_object *)mac->proc);
} }
if (stx->senv) { if (mac->senv) {
gc_mark_object(pic, (struct pic_object *)stx->senv); gc_mark_object(pic, (struct pic_object *)mac->senv);
} }
break; break;
} }
@ -404,13 +404,6 @@ gc_mark_object(pic_state *pic, struct pic_object *obj)
if (senv->up) { if (senv->up) {
gc_mark_object(pic, (struct pic_object *)senv->up); gc_mark_object(pic, (struct pic_object *)senv->up);
} }
if (senv->stx) {
size_t i;
for (i = 0; i < senv->xlen; ++i) {
gc_mark_object(pic, (struct pic_object *)senv->stx[i]);
}
}
break; break;
} }
case PIC_TT_SC: { case PIC_TT_SC: {
@ -476,6 +469,7 @@ gc_mark_phase(pic_state *pic)
pic_callinfo *ci; pic_callinfo *ci;
size_t i; size_t i;
int j; int j;
xh_iter it;
/* block */ /* block */
gc_mark_block(pic, pic->blk); gc_mark_block(pic, pic->blk);
@ -512,6 +506,11 @@ gc_mark_phase(pic_state *pic)
gc_mark(pic, pic->globals[i]); gc_mark(pic, pic->globals[i]);
} }
/* macro objects */
for (xh_begin(pic->macros, &it); ! xh_isend(&it); xh_next(&it)) {
gc_mark_object(pic, (struct pic_object *)it.e->val);
}
/* library table */ /* library table */
gc_mark(pic, pic->lib_tbl); gc_mark(pic, pic->lib_tbl);
} }
@ -565,12 +564,10 @@ gc_finalize_object(pic_state *pic, struct pic_object *obj)
} }
case PIC_TT_SENV: { case PIC_TT_SENV: {
struct pic_senv *senv = (struct pic_senv *)obj; struct pic_senv *senv = (struct pic_senv *)obj;
xh_destroy(senv->tbl); xh_destroy(senv->name);
if (senv->stx)
pic_free(pic, senv->stx);
break; break;
} }
case PIC_TT_SYNTAX: { case PIC_TT_MACRO: {
break; break;
} }
case PIC_TT_SC: { case PIC_TT_SC: {

View File

@ -13,65 +13,18 @@
static pic_value macroexpand(pic_state *, pic_value, struct pic_senv *); static pic_value macroexpand(pic_state *, pic_value, struct pic_senv *);
static pic_value macroexpand_list(pic_state *, pic_value, struct pic_senv *); static pic_value macroexpand_list(pic_state *, pic_value, struct pic_senv *);
struct pic_senv * static struct pic_senv *
pic_null_syntactic_env(pic_state *pic) new_senv(pic_state *pic, struct pic_senv *up)
{ {
struct pic_senv *senv; struct pic_senv *senv;
senv = (struct pic_senv *)pic_obj_alloc(pic, sizeof(struct pic_senv), PIC_TT_SENV); senv = (struct pic_senv *)pic_obj_alloc(pic, sizeof(struct pic_senv), PIC_TT_SENV);
senv->up = NULL; senv->up = up;
senv->tbl = xh_new_int(); senv->name = xh_new_int();
senv->stx = (struct pic_syntax **)pic_calloc(pic, PIC_MACROS_SIZE, sizeof(struct pic_syntax *));
senv->xlen = 0;
senv->xcapa = PIC_MACROS_SIZE;
return senv; return senv;
} }
#define register_core_syntax(pic,senv,kind,name) do { \
pic_sym sym = pic_intern_cstr(pic, name); \
senv->stx[senv->xlen] = pic_syntax_new(pic, kind, sym); \
xh_put_int(senv->tbl, sym, ~senv->xlen); \
senv->xlen++; \
} while (0)
struct pic_senv *
pic_minimal_syntactic_env(pic_state *pic)
{
struct pic_senv *senv = pic_null_syntactic_env(pic);
register_core_syntax(pic, senv, PIC_STX_DEFLIBRARY, "define-library");
register_core_syntax(pic, senv, PIC_STX_IMPORT, "import");
register_core_syntax(pic, senv, PIC_STX_EXPORT, "export");
return senv;
}
struct pic_senv *
pic_core_syntactic_env(pic_state *pic)
{
struct pic_senv *senv = pic_minimal_syntactic_env(pic);
register_core_syntax(pic, senv, PIC_STX_DEFINE, "define");
register_core_syntax(pic, senv, PIC_STX_SET, "set!");
register_core_syntax(pic, senv, PIC_STX_QUOTE, "quote");
register_core_syntax(pic, senv, PIC_STX_LAMBDA, "lambda");
register_core_syntax(pic, senv, PIC_STX_IF, "if");
register_core_syntax(pic, senv, PIC_STX_BEGIN, "begin");
register_core_syntax(pic, senv, PIC_STX_DEFMACRO, "define-macro");
register_core_syntax(pic, senv, PIC_STX_DEFSYNTAX, "define-syntax");
return senv;
}
#undef register_core_syntax
static struct pic_senv *
new_global_senv(pic_state *pic)
{
return pic->lib->senv;
}
static struct pic_senv * static struct pic_senv *
new_local_senv(pic_state *pic, pic_value formals, struct pic_senv *up) new_local_senv(pic_state *pic, pic_value formals, struct pic_senv *up)
{ {
@ -79,12 +32,7 @@ new_local_senv(pic_state *pic, pic_value formals, struct pic_senv *up)
pic_value a; pic_value a;
pic_sym sym; pic_sym sym;
senv = (struct pic_senv *)pic_obj_alloc(pic, sizeof(struct pic_senv), PIC_TT_SENV); senv = new_senv(pic, up);
senv->up = up;
senv->tbl = xh_new_int();
senv->stx = NULL;
senv->xlen = 0;
senv->xcapa = 0;
for (a = formals; pic_pair_p(a); a = pic_cdr(pic, a)) { for (a = formals; pic_pair_p(a); a = pic_cdr(pic, a)) {
pic_value v = pic_car(pic, a); pic_value v = pic_car(pic, a);
@ -96,14 +44,14 @@ new_local_senv(pic_state *pic, pic_value formals, struct pic_senv *up)
pic_error(pic, "syntax error"); pic_error(pic, "syntax error");
} }
sym = pic_sym(v); sym = pic_sym(v);
xh_put_int(senv->tbl, sym, pic_gensym(pic, sym)); xh_put_int(senv->name, sym, pic_gensym(pic, sym));
} }
if (! pic_sym_p(a)) { if (! pic_sym_p(a)) {
a = macroexpand(pic, a, up); a = macroexpand(pic, a, up);
} }
if (pic_sym_p(a)) { if (pic_sym_p(a)) {
sym = pic_sym(a); sym = pic_sym(a);
xh_put_int(senv->tbl, sym, pic_gensym(pic, sym)); xh_put_int(senv->name, sym, pic_gensym(pic, sym));
} }
else if (! pic_nil_p(a)) { else if (! pic_nil_p(a)) {
pic_error(pic, "syntax error"); pic_error(pic, "syntax error");
@ -111,30 +59,15 @@ new_local_senv(pic_state *pic, pic_value formals, struct pic_senv *up)
return senv; return senv;
} }
struct pic_syntax * struct pic_macro *
pic_syntax_new(pic_state *pic, int kind, pic_sym sym) macro_new(pic_state *pic, struct pic_proc *proc, struct pic_senv *mac_env)
{ {
struct pic_syntax *stx; struct pic_macro *mac;
stx = (struct pic_syntax *)pic_obj_alloc(pic, sizeof(struct pic_syntax), PIC_TT_SYNTAX); mac = (struct pic_macro *)pic_obj_alloc(pic, sizeof(struct pic_macro), PIC_TT_MACRO);
stx->kind = kind; mac->senv = mac_env;
stx->sym = sym; mac->proc = proc;
stx->macro = NULL; return mac;
stx->senv = NULL;
return stx;
}
struct pic_syntax *
pic_syntax_new_macro(pic_state *pic, pic_sym sym, struct pic_proc *macro, struct pic_senv *mac_env)
{
struct pic_syntax *stx;
stx = (struct pic_syntax *)pic_obj_alloc(pic, sizeof(struct pic_syntax), PIC_TT_SYNTAX);
stx->kind = PIC_STX_MACRO;
stx->sym = sym;
stx->macro = macro;
stx->senv = mac_env;
return stx;
} }
static struct pic_sc * static struct pic_sc *
@ -149,29 +82,28 @@ sc_new(pic_state *pic, pic_value expr, struct pic_senv *senv)
} }
static bool static bool
pic_identifier_p(pic_value obj) identifier_p(pic_value obj)
{ {
if (pic_sym_p(obj)) { if (pic_sym_p(obj)) {
return true; return true;
} }
if (pic_sc_p(obj)) { if (pic_sc_p(obj)) {
return pic_identifier_p(pic_sc(obj)->expr); return identifier_p(pic_sc(obj)->expr);
} }
return false; return false;
} }
static pic_value static bool
strip(pic_state *pic, pic_value expr) identifier_eq_p(pic_state *pic, struct pic_senv *e1, pic_value x, struct pic_senv *e2, pic_value y)
{ {
if (pic_sc_p(expr)) { if (! (identifier_p(x) && identifier_p(y))) {
return strip(pic, pic_sc(expr)->expr); return false;
} }
else if (pic_pair_p(expr)) {
return pic_cons(pic, x = macroexpand(pic, x, e1);
strip(pic, pic_car(pic, expr)), y = macroexpand(pic, y, e2);
strip(pic, pic_cdr(pic, expr)));
} return pic_eq_p(x, y);
return expr;
} }
void void
@ -185,30 +117,19 @@ pic_import(pic_state *pic, pic_value spec)
pic_error(pic, "library not found"); pic_error(pic, "library not found");
} }
for (xh_begin(lib->exports, &it); ! xh_isend(&it); xh_next(&it)) { for (xh_begin(lib->exports, &it); ! xh_isend(&it); xh_next(&it)) {
#if DEBUG #if DEBUG
if (it.e->val >= 0) { if (it.e->val >= 0) {
printf("* importing %s as %s\n", pic_symbol_name(pic, (long)it.e->key), pic_symbol_name(pic, it.e->val)); printf("* importing %s as %s\n",
pic_symbol_name(pic, (long)it.e->key),
pic_symbol_name(pic, it.e->val));
} }
else { else {
printf("* importing %s\n", pic_symbol_name(pic, (long)it.e->key)); printf("* importing %s\n", pic_symbol_name(pic, (long)it.e->key));
} }
#endif #endif
if (it.e->val >= 0) {
xh_put_int(pic->lib->senv->tbl, (long)it.e->key, it.e->val);
}
else { /* syntax object */
size_t idx;
struct pic_senv *senv = pic->lib->senv;
idx = senv->xlen; xh_put_int(pic->lib->senv->name, (long)it.e->key, it.e->val);
if (idx >= senv->xcapa) {
pic_abort(pic, "macro table overflow");
}
/* bring macro object from imported lib */
senv->stx[idx] = lib->senv->stx[~it.e->val];
xh_put_int(senv->tbl, (long)it.e->key, ~idx);
senv->xlen++;
}
} }
} }
@ -217,7 +138,7 @@ pic_export(pic_state *pic, pic_sym sym)
{ {
xh_entry *e; xh_entry *e;
e = xh_get_int(pic->lib->senv->tbl, sym); e = xh_get_int(pic->lib->senv->name, sym);
if (! e) { if (! e) {
pic_error(pic, "symbol not defined"); pic_error(pic, "symbol not defined");
} }
@ -225,40 +146,55 @@ pic_export(pic_state *pic, pic_sym sym)
} }
static void static void
defsyntax(pic_state *pic, const char *name, struct pic_proc *macro, struct pic_senv *mac_env) defsyntax(pic_state *pic, pic_sym sym, struct pic_proc *macro, struct pic_senv *mac_env)
{ {
pic_sym sym; struct pic_macro *mac;
struct pic_syntax *stx; pic_sym uniq;
struct pic_senv *global_senv = pic->lib->senv;
size_t idx;
sym = pic_intern_cstr(pic, name); mac = macro_new(pic, macro, mac_env);
stx = pic_syntax_new_macro(pic, sym, macro, mac_env);
idx = global_senv->xlen; uniq = pic_gensym(pic, sym);
if (idx >= global_senv->xcapa) { xh_put_int(pic->lib->senv->name, sym, uniq);
pic_abort(pic, "macro table overflow"); xh_put_int(pic->macros, uniq, (long)mac);
}
global_senv->stx[idx] = stx;
xh_put_int(global_senv->tbl, sym, ~idx);
global_senv->xlen++;
} }
static void static void
defmacro(pic_state *pic, const char *name, struct pic_proc *macro) defmacro(pic_state *pic, pic_sym sym, struct pic_proc *macro)
{ {
defsyntax(pic, name, macro, NULL); defsyntax(pic, sym, macro, NULL);
} }
void void
pic_defmacro(pic_state *pic, const char *name, struct pic_proc *macro) pic_defmacro(pic_state *pic, const char *name, struct pic_proc *macro)
{ {
defmacro(pic, name, macro); defmacro(pic, pic_intern_cstr(pic, name), macro);
/* auto export! */ /* auto export! */
pic_export(pic, pic_intern_cstr(pic, name)); pic_export(pic, pic_intern_cstr(pic, name));
} }
static pic_sym
symbol_rename(pic_state *pic, pic_sym sym, struct pic_senv *senv)
{
xh_entry *e;
pic_sym uniq;
if (! pic_interned_p(pic, sym)) {
return sym;
}
while (true) {
if ((e = xh_get_int(senv->name, sym)) != NULL) {
return (pic_sym)e->val;
}
if (! senv->up)
break;
senv = senv->up;
}
uniq = pic_gensym(pic, sym);
xh_put_int(senv->name, sym, uniq);
return uniq;
}
static pic_value static pic_value
macroexpand(pic_state *pic, pic_value expr, struct pic_senv *senv) macroexpand(pic_state *pic, pic_value expr, struct pic_senv *senv)
{ {
@ -278,34 +214,17 @@ macroexpand(pic_state *pic, pic_value expr, struct pic_senv *senv)
return macroexpand(pic, sc->expr, sc->senv); return macroexpand(pic, sc->expr, sc->senv);
} }
case PIC_TT_SYMBOL: { case PIC_TT_SYMBOL: {
xh_entry *e; return pic_symbol_value(symbol_rename(pic, pic_sym(expr), senv));
pic_sym uniq;
if (! pic_interned_p(pic, pic_sym(expr))) {
return expr;
}
while (true) {
if ((e = xh_get_int(senv->tbl, pic_sym(expr))) != NULL) {
if (e->val >= 0)
return pic_symbol_value(e->val);
else
return pic_obj_value(senv->stx[~e->val]);
}
if (! senv->up)
break;
senv = senv->up;
}
uniq = pic_gensym(pic, pic_sym(expr));
xh_put_int(senv->tbl, pic_sym(expr), uniq);
return pic_symbol_value(uniq);
} }
case PIC_TT_PAIR: { case PIC_TT_PAIR: {
pic_value car, v; pic_value car, v;
xh_entry *e;
car = macroexpand(pic, pic_car(pic, expr), senv); car = macroexpand(pic, pic_car(pic, expr), senv);
if (pic_syntax_p(car)) { if (pic_sym_p(car)) {
switch (pic_syntax(car)->kind) { pic_sym tag = pic_sym(car);
case PIC_STX_DEFLIBRARY: {
if (tag == pic->sDEFINE_LIBRARY) {
struct pic_lib *prev = pic->lib; struct pic_lib *prev = pic->lib;
if (pic_length(pic, expr) < 2) { if (pic_length(pic, expr) < 2) {
@ -335,14 +254,16 @@ macroexpand(pic_state *pic, pic_value expr, struct pic_senv *senv)
return pic_none_value(); return pic_none_value();
} }
case PIC_STX_IMPORT: {
else if (tag == pic->sIMPORT) {
pic_value spec; pic_value spec;
pic_for_each (spec, pic_cdr(pic, expr)) { pic_for_each (spec, pic_cdr(pic, expr)) {
pic_import(pic, spec); pic_import(pic, spec);
} }
return pic_none_value(); return pic_none_value();
} }
case PIC_STX_EXPORT: {
else if (tag == pic->sEXPORT) {
pic_value spec; pic_value spec;
pic_for_each (spec, pic_cdr(pic, expr)) { pic_for_each (spec, pic_cdr(pic, expr)) {
if (! pic_sym_p(spec)) { if (! pic_sym_p(spec)) {
@ -353,7 +274,8 @@ macroexpand(pic_state *pic, pic_value expr, struct pic_senv *senv)
} }
return pic_none_value(); return pic_none_value();
} }
case PIC_STX_DEFSYNTAX: {
else if (tag == pic->sDEFINE_SYNTAX) {
pic_value var, val; pic_value var, val;
struct pic_proc *proc; struct pic_proc *proc;
@ -361,7 +283,7 @@ macroexpand(pic_state *pic, pic_value expr, struct pic_senv *senv)
pic_error(pic, "syntax error"); pic_error(pic, "syntax error");
} }
var = strip(pic, pic_cadr(pic, expr)); var = pic_cadr(pic, expr);
if (! pic_sym_p(var)) { if (! pic_sym_p(var)) {
pic_error(pic, "syntax error"); pic_error(pic, "syntax error");
} }
@ -378,12 +300,13 @@ macroexpand(pic_state *pic, pic_value expr, struct pic_senv *senv)
abort(); abort();
} }
assert(pic_proc_p(v)); assert(pic_proc_p(v));
defsyntax(pic, pic_symbol_name(pic, pic_sym(var)), pic_proc_ptr(v), senv); defsyntax(pic, pic_sym(var), pic_proc_ptr(v), senv);
pic_gc_arena_restore(pic, ai); pic_gc_arena_restore(pic, ai);
return pic_none_value(); return pic_none_value();
} }
case PIC_STX_DEFMACRO: {
else if (tag == pic->sDEFINE_MACRO) {
pic_value var, val; pic_value var, val;
struct pic_proc *proc; struct pic_proc *proc;
@ -420,41 +343,16 @@ macroexpand(pic_state *pic, pic_value expr, struct pic_senv *senv)
abort(); abort();
} }
assert(pic_proc_p(v)); assert(pic_proc_p(v));
defmacro(pic, pic_symbol_name(pic, pic_sym(var)), pic_proc_ptr(v)); defmacro(pic, pic_sym(var), pic_proc_ptr(v));
pic_gc_arena_restore(pic, ai); pic_gc_arena_restore(pic, ai);
return pic_none_value(); return pic_none_value();
} }
case PIC_STX_MACRO: {
if (pic_syntax(car)->senv == NULL) { /* legacy macro */
v = pic_apply(pic, pic_syntax(car)->macro, pic_cdr(pic, expr));
if (pic->err) {
printf("macroexpand error: %s\n", pic_errmsg(pic));
abort();
}
}
else {
v = pic_apply_argv(pic, pic_syntax(car)->macro, 3, expr, pic_obj_value(senv), pic_obj_value(pic_syntax(car)->senv));
if (pic->err) {
printf("macroexpand error: %s\n", pic_errmsg(pic));
abort();
}
}
pic_gc_arena_restore(pic, ai);
pic_gc_protect(pic, v);
#if DEBUG else if (tag == pic->sLAMBDA) {
puts("after expand-1:");
pic_debug(pic, v);
puts("");
#endif
return macroexpand(pic, v, senv);
}
case PIC_STX_LAMBDA: {
struct pic_senv *in = new_local_senv(pic, pic_cadr(pic, expr), senv); struct pic_senv *in = new_local_senv(pic, pic_cadr(pic, expr), senv);
v = pic_cons(pic, pic_symbol_value(pic_syntax(car)->sym), v = pic_cons(pic, car,
pic_cons(pic, pic_cons(pic,
macroexpand_list(pic, pic_cadr(pic, expr), in), macroexpand_list(pic, pic_cadr(pic, expr), in),
macroexpand_list(pic, pic_cddr(pic, expr), in))); macroexpand_list(pic, pic_cddr(pic, expr), in)));
@ -463,7 +361,8 @@ macroexpand(pic_state *pic, pic_value expr, struct pic_senv *senv)
pic_gc_protect(pic, v); pic_gc_protect(pic, v);
return v; return v;
} }
case PIC_STX_DEFINE: {
else if (tag == pic->sDEFINE) {
pic_sym var; pic_sym var;
pic_value formals; pic_value formals;
@ -485,11 +384,11 @@ macroexpand(pic_state *pic, pic_value expr, struct pic_senv *senv)
pic_error(pic, "binding to non-symbol object"); pic_error(pic, "binding to non-symbol object");
} }
var = pic_sym(a); var = pic_sym(a);
xh_put_int(senv->tbl, var, pic_gensym(pic, var)); xh_put_int(senv->name, var, pic_gensym(pic, var));
/* binding value */ /* binding value */
v = pic_cons(pic, pic_symbol_value(pic_syntax(car)->sym), v = pic_cons(pic, car,
pic_cons(pic, pic_cons(pic,
macroexpand_list(pic, pic_cadr(pic, expr), in), macroexpand_list(pic, pic_cadr(pic, expr), in),
macroexpand_list(pic, pic_cddr(pic, expr), in))); macroexpand_list(pic, pic_cddr(pic, expr), in)));
@ -506,24 +405,62 @@ macroexpand(pic_state *pic, pic_value expr, struct pic_senv *senv)
} }
var = pic_sym(formals); var = pic_sym(formals);
/* do not make duplicate variable slot */ /* do not make duplicate variable slot */
if (xh_get_int(senv->tbl, var) == NULL) { if (xh_get_int(senv->name, var) == NULL) {
xh_put_int(senv->tbl, var, pic_gensym(pic, var)); xh_put_int(senv->name, var, pic_gensym(pic, var));
} }
v = pic_cons(pic, pic_symbol_value(tag),
macroexpand_list(pic, pic_cdr(pic, expr), senv));
pic_gc_arena_restore(pic, ai);
pic_gc_protect(pic, v);
return v;
} }
FALLTHROUGH;
case PIC_STX_SET: else if (tag == pic->sSETBANG || tag == pic->sIF || tag == pic->sBEGIN) {
case PIC_STX_IF: v = pic_cons(pic, car, macroexpand_list(pic, pic_cdr(pic, expr), senv));
case PIC_STX_BEGIN:
v = pic_cons(pic, pic_symbol_value(pic_syntax(car)->sym), macroexpand_list(pic, pic_cdr(pic, expr), senv));
pic_gc_arena_restore(pic, ai); pic_gc_arena_restore(pic, ai);
pic_gc_protect(pic, v); pic_gc_protect(pic, v);
return v; return v;
case PIC_STX_QUOTE: }
v = pic_cons(pic, pic_symbol_value(pic_syntax(car)->sym), pic_cdr(pic, expr));
else if (tag == pic->sQUOTE) {
v = pic_cons(pic, car, pic_cdr(pic, expr));
pic_gc_arena_restore(pic, ai); pic_gc_arena_restore(pic, ai);
pic_gc_protect(pic, v); pic_gc_protect(pic, v);
return v; return v;
} }
/* macro */
if ((e = xh_get_int(pic->macros, tag)) != NULL) {
pic_value v;
struct pic_macro *mac;
mac = (struct pic_macro *)e->val;
if (mac->senv == NULL) { /* legacy macro */
v = pic_apply(pic, mac->proc, pic_cdr(pic, expr));
if (pic->err) {
printf("macroexpand error: %s\n", pic_errmsg(pic));
abort();
}
}
else {
v = pic_apply_argv(pic, mac->proc, 3, expr, pic_obj_value(senv), pic_obj_value(mac->senv));
if (pic->err) {
printf("macroexpand error: %s\n", pic_errmsg(pic));
abort();
}
}
pic_gc_arena_restore(pic, ai);
pic_gc_protect(pic, v);
#if DEBUG
puts("after expand-1:");
pic_debug(pic, v);
puts("");
#endif
return macroexpand(pic, v, senv);
}
} }
v = pic_cons(pic, car, macroexpand_list(pic, pic_cdr(pic, expr), senv)); v = pic_cons(pic, car, macroexpand_list(pic, pic_cdr(pic, expr), senv));
@ -549,7 +486,7 @@ macroexpand(pic_state *pic, pic_value expr, struct pic_senv *senv)
case PIC_TT_CONT: case PIC_TT_CONT:
case PIC_TT_UNDEF: case PIC_TT_UNDEF:
case PIC_TT_SENV: case PIC_TT_SENV:
case PIC_TT_SYNTAX: case PIC_TT_MACRO:
case PIC_TT_LIB: case PIC_TT_LIB:
case PIC_TT_VAR: case PIC_TT_VAR:
case PIC_TT_IREP: case PIC_TT_IREP:
@ -575,18 +512,15 @@ macroexpand_list(pic_state *pic, pic_value list, struct pic_senv *senv)
pic_value pic_value
pic_macroexpand(pic_state *pic, pic_value expr) pic_macroexpand(pic_state *pic, pic_value expr)
{ {
struct pic_senv *senv;
pic_value v; pic_value v;
senv = new_global_senv(pic);
#if DEBUG #if DEBUG
puts("before expand:"); puts("before expand:");
pic_debug(pic, expr); pic_debug(pic, expr);
puts(""); puts("");
#endif #endif
v = macroexpand(pic, expr, senv); v = macroexpand(pic, expr, pic->lib->senv);
#if DEBUG #if DEBUG
puts("after expand:"); puts("after expand:");
@ -597,6 +531,46 @@ pic_macroexpand(pic_state *pic, pic_value expr)
return v; return v;
} }
struct pic_senv *
pic_null_syntactic_env(pic_state *pic)
{
return new_senv(pic, NULL);
}
#define register_core_syntax(pic,senv,id) do { \
pic_sym sym = pic_intern_cstr(pic, id); \
xh_put_int(senv->name, sym, sym); \
} while (0)
struct pic_senv *
pic_minimal_syntactic_env(pic_state *pic)
{
struct pic_senv *senv = pic_null_syntactic_env(pic);
register_core_syntax(pic, senv, "define-library");
register_core_syntax(pic, senv, "import");
register_core_syntax(pic, senv, "export");
return senv;
}
struct pic_senv *
pic_core_syntactic_env(pic_state *pic)
{
struct pic_senv *senv = pic_minimal_syntactic_env(pic);
register_core_syntax(pic, senv, "define");
register_core_syntax(pic, senv, "set!");
register_core_syntax(pic, senv, "quote");
register_core_syntax(pic, senv, "lambda");
register_core_syntax(pic, senv, "if");
register_core_syntax(pic, senv, "begin");
register_core_syntax(pic, senv, "define-macro");
register_core_syntax(pic, senv, "define-syntax");
return senv;
}
/* once read.c is implemented move there */ /* once read.c is implemented move there */
static pic_value static pic_value
pic_macro_include(pic_state *pic) pic_macro_include(pic_state *pic)
@ -655,7 +629,7 @@ pic_macro_identifier_p(pic_state *pic)
pic_get_args(pic, "o", &obj); pic_get_args(pic, "o", &obj);
return pic_bool_value(pic_identifier_p(obj)); return pic_bool_value(identifier_p(obj));
} }
static pic_value static pic_value
@ -675,14 +649,7 @@ pic_macro_identifier_eq_p(pic_state *pic)
} }
e2 = pic_senv(f); e2 = pic_senv(f);
if (! (pic_identifier_p(x) && pic_identifier_p(y))) { return pic_bool_value(identifier_eq_p(pic, e1, x, e2, y));
return pic_false_value();
}
x = macroexpand(pic, x, e1);
y = macroexpand(pic, y, e2);
return pic_bool_value(pic_eq_p(x, y));
} }
static pic_value static pic_value
@ -690,19 +657,12 @@ er_macro_rename(pic_state *pic)
{ {
pic_sym sym; pic_sym sym;
struct pic_senv *mac_env; struct pic_senv *mac_env;
pic_value v;
pic_get_args(pic, "m", &sym); pic_get_args(pic, "m", &sym);
mac_env = pic_senv_ptr(pic_proc_cv_ref(pic, pic_get_proc(pic), 1)); mac_env = pic_senv_ptr(pic_proc_cv_ref(pic, pic_get_proc(pic), 1));
v = macroexpand(pic, pic_symbol_value(sym), mac_env); return pic_symbol_value(symbol_rename(pic, sym, mac_env));
if (pic_syntax_p(v)) {
return pic_symbol_value(sym);
}
else {
return v;
}
} }
static pic_value static pic_value
@ -710,6 +670,7 @@ er_macro_compare(pic_state *pic)
{ {
pic_value a, b; pic_value a, b;
struct pic_senv *use_env; struct pic_senv *use_env;
pic_sym m, n;
pic_get_args(pic, "oo", &a, &b); pic_get_args(pic, "oo", &a, &b);
@ -718,10 +679,10 @@ er_macro_compare(pic_state *pic)
use_env = pic_senv_ptr(pic_proc_cv_ref(pic, pic_get_proc(pic), 0)); use_env = pic_senv_ptr(pic_proc_cv_ref(pic, pic_get_proc(pic), 0));
a = macroexpand(pic, a, use_env); m = symbol_rename(pic, pic_sym(a), use_env);
b = macroexpand(pic, b, use_env); n = symbol_rename(pic, pic_sym(b), use_env);
return pic_bool_value(pic_eq_p(a, b)); return pic_bool_value(m == n);
} }
static pic_value static pic_value
@ -773,19 +734,12 @@ ir_macro_inject(pic_state *pic)
{ {
pic_sym sym; pic_sym sym;
struct pic_senv *use_env; struct pic_senv *use_env;
pic_value v;
pic_get_args(pic, "m", &sym); pic_get_args(pic, "m", &sym);
use_env = pic_senv_ptr(pic_proc_cv_ref(pic, pic_get_proc(pic), 0)); use_env = pic_senv_ptr(pic_proc_cv_ref(pic, pic_get_proc(pic), 0));
v = macroexpand(pic, pic_symbol_value(sym), use_env); return pic_symbol_value(symbol_rename(pic, sym, use_env));
if (pic_syntax_p(v)) {
return pic_symbol_value(sym);
}
else {
return v;
}
} }
static pic_value static pic_value
@ -793,6 +747,7 @@ ir_macro_compare(pic_state *pic)
{ {
pic_value a, b; pic_value a, b;
struct pic_senv *use_env; struct pic_senv *use_env;
pic_sym m, n;
pic_get_args(pic, "oo", &a, &b); pic_get_args(pic, "oo", &a, &b);
@ -801,10 +756,10 @@ ir_macro_compare(pic_state *pic)
use_env = pic_senv_ptr(pic_proc_cv_ref(pic, pic_get_proc(pic), 0)); use_env = pic_senv_ptr(pic_proc_cv_ref(pic, pic_get_proc(pic), 0));
a = macroexpand(pic, a, use_env); m = symbol_rename(pic, pic_sym(a), use_env);
b = macroexpand(pic, b, use_env); n = symbol_rename(pic, pic_sym(b), use_env);
return pic_bool_value(pic_eq_p(a, b)); return pic_bool_value(m == n);
} }
static pic_value static pic_value
@ -829,13 +784,13 @@ ir_macro_wrap(pic_state *pic, pic_value expr, struct pic_senv *use_env, pic_valu
static pic_value static pic_value
ir_macro_unwrap(pic_state *pic, pic_value expr, struct pic_senv *mac_env, pic_value *assoc) ir_macro_unwrap(pic_state *pic, pic_value expr, struct pic_senv *mac_env, pic_value *assoc)
{ {
if (pic_sym_p(expr) || pic_syntax_p(expr)) { if (pic_sym_p(expr) || pic_macro_p(expr)) {
pic_value r; pic_value r;
if (pic_test(r = pic_assq(pic, expr, *assoc))) { if (pic_test(r = pic_assq(pic, expr, *assoc))) {
return pic_cdr(pic, r); return pic_cdr(pic, r);
} }
r = macroexpand(pic, expr, mac_env); r = macroexpand(pic, expr, mac_env);
if (pic_syntax_p(r)) { if (pic_macro_p(r)) {
return expr; return expr;
} }
else { else {

View File

@ -72,6 +72,36 @@ pic_proc_cv_set(pic_state *pic, struct pic_proc *proc, size_t i, pic_value v)
proc->env->values[i] = v; proc->env->values[i] = v;
} }
static pic_value
papply_call(pic_state *pic)
{
size_t argc;
pic_value *argv, arg, arg_list;
struct pic_proc *proc;
pic_get_args(pic, "*", &argc, &argv);
proc = pic_proc_ptr(pic_proc_cv_ref(pic, pic_get_proc(pic), 0));
arg = pic_proc_cv_ref(pic, pic_get_proc(pic), 1);
arg_list = pic_list_by_array(pic, argc, argv);
arg_list = pic_cons(pic, arg, arg_list);
return pic_apply(pic, proc, arg_list);
}
struct pic_proc *
pic_papply(pic_state *pic, struct pic_proc *proc, pic_value arg)
{
struct pic_proc *pa_proc;
pa_proc = pic_proc_new(pic, papply_call);
pic_proc_cv_init(pic, pa_proc, 2);
pic_proc_cv_set(pic, pa_proc, 0, pic_obj_value(proc));
pic_proc_cv_set(pic, pa_proc, 1, arg);
return pa_proc;
}
static pic_value static pic_value
pic_proc_proc_p(pic_state *pic) pic_proc_proc_p(pic_state *pic)
{ {

View File

@ -64,6 +64,9 @@ pic_open(int argc, char *argv[], char **envp)
pic->glen = 0; pic->glen = 0;
pic->gcapa = PIC_GLOBALS_SIZE; pic->gcapa = PIC_GLOBALS_SIZE;
/* macros */
pic->macros = xh_new_int();
/* libraries */ /* libraries */
pic->lib_tbl = pic_nil_value(); pic->lib_tbl = pic_nil_value();
pic->lib = NULL; pic->lib = NULL;
@ -142,9 +145,13 @@ pic_close(pic_state *pic)
pic->arena_idx = 0; pic->arena_idx = 0;
pic->lib_tbl = pic_undef_value(); pic->lib_tbl = pic_undef_value();
xh_clear(pic->macros);
/* free all values */ /* free all values */
pic_gc_run(pic); pic_gc_run(pic);
xh_destroy(pic->macros);
/* free heaps */ /* free heaps */
finalize_heap(pic->heap); finalize_heap(pic->heap);
free(pic->heap); free(pic->heap);

View File

@ -134,8 +134,8 @@ write(pic_state *pic, pic_value obj, XFILE *file)
case PIC_TT_SENV: case PIC_TT_SENV:
xfprintf(file, "#<senv %p>", pic_ptr(obj)); xfprintf(file, "#<senv %p>", pic_ptr(obj));
break; break;
case PIC_TT_SYNTAX: case PIC_TT_MACRO:
xfprintf(file, "#<syntax %p>", pic_ptr(obj)); xfprintf(file, "#<macro %p>", pic_ptr(obj));
break; break;
case PIC_TT_SC: case PIC_TT_SC:
xfprintf(file, "#<sc %p: ", pic_ptr(obj)); xfprintf(file, "#<sc %p: ", pic_ptr(obj));