support let-syntax
This commit is contained in:
		
							parent
							
								
									730cfc8601
								
							
						
					
					
						commit
						6c45bb3c5d
					
				|  | @ -81,6 +81,7 @@ typedef struct { | |||
|   pic_sym sDEFINE, sLAMBDA, sIF, sBEGIN, sQUOTE, sSETBANG; | ||||
|   pic_sym sQUASIQUOTE, sUNQUOTE, sUNQUOTE_SPLICING; | ||||
|   pic_sym sDEFINE_SYNTAX, sDEFINE_MACRO; | ||||
|   pic_sym sLET_SYNTAX, sLETREC_SYNTAX; | ||||
|   pic_sym sDEFINE_LIBRARY, sIMPORT, sEXPORT; | ||||
|   pic_sym sCONS, sCAR, sCDR, sNILP; | ||||
|   pic_sym sADD, sSUB, sMUL, sDIV, sMINUS; | ||||
|  |  | |||
|  | @ -75,6 +75,8 @@ pic_init_core(pic_state *pic) | |||
|     pic_define_syntactic_keyword(pic, pic->lib->senv, pic->sIF); | ||||
|     pic_define_syntactic_keyword(pic, pic->lib->senv, pic->sBEGIN); | ||||
|     pic_define_syntactic_keyword(pic, pic->lib->senv, pic->sDEFINE_SYNTAX); | ||||
|     pic_define_syntactic_keyword(pic, pic->lib->senv, pic->sLET_SYNTAX); | ||||
|     pic_define_syntactic_keyword(pic, pic->lib->senv, pic->sLETREC_SYNTAX); | ||||
| 
 | ||||
|     pic_init_bool(pic); DONE; | ||||
|     pic_init_pair(pic); DONE; | ||||
|  |  | |||
							
								
								
									
										284
									
								
								src/macro.c
								
								
								
								
							
							
						
						
									
										284
									
								
								src/macro.c
								
								
								
								
							|  | @ -184,125 +184,6 @@ macroexpand_deflibrary(pic_state *pic, pic_value expr) | |||
|   return pic_none_value(); | ||||
| } | ||||
| 
 | ||||
| static pic_value | ||||
| macroexpand_defsyntax(pic_state *pic, pic_value expr, struct pic_senv *senv, struct pic_dict *cxt) | ||||
| { | ||||
|   pic_value var, val; | ||||
|   pic_sym sym, rename; | ||||
| 
 | ||||
|   if (pic_length(pic, expr) != 3) { | ||||
|     pic_error(pic, "syntax error"); | ||||
|   } | ||||
| 
 | ||||
|   var = pic_cadr(pic, expr); | ||||
|   if (! pic_sym_p(var)) { | ||||
|     var = macroexpand(pic, var, senv, cxt); | ||||
|   } | ||||
|   if (! pic_sym_p(var)) { | ||||
|     pic_error(pic, "binding to non-symbol object"); | ||||
|   } | ||||
|   sym = pic_sym(var); | ||||
|   if (! pic_find_rename(pic, senv, sym, &rename)) { | ||||
|     rename = pic_add_rename(pic, senv, sym); | ||||
|   } | ||||
| 
 | ||||
|   val = pic_cadr(pic, pic_cdr(pic, expr)); | ||||
| 
 | ||||
|   pic_try { | ||||
|     val = pic_eval(pic, val); | ||||
|   } pic_catch { | ||||
|     pic_errorf(pic, "macroexpand error: %s", pic_errmsg(pic)); | ||||
|   } | ||||
| 
 | ||||
|   if (! pic_proc_p(val)) { | ||||
|     pic_errorf(pic, "macro definition \"~s\" evaluates to non-procedure object", var); | ||||
|   } | ||||
| 
 | ||||
|   define_macro(pic, rename, pic_proc_ptr(val), senv); | ||||
| 
 | ||||
|   return pic_none_value(); | ||||
| } | ||||
| 
 | ||||
| static pic_value | ||||
| macroexpand_defmacro(pic_state *pic, pic_value expr, struct pic_senv *senv) | ||||
| { | ||||
|   pic_value var, val; | ||||
|   pic_sym sym, rename; | ||||
| 
 | ||||
|   if (pic_length(pic, expr) < 2) { | ||||
|     pic_error(pic, "syntax error"); | ||||
|   } | ||||
| 
 | ||||
|   var = pic_car(pic, pic_cdr(pic, expr)); | ||||
|   if (pic_pair_p(var)) { | ||||
|     /* FIXME: unhygienic */ | ||||
|     val = pic_cons(pic, pic_sym_value(pic->sLAMBDA), | ||||
|                    pic_cons(pic, pic_cdr(pic, var), | ||||
|                             pic_cdr(pic, pic_cdr(pic, expr)))); | ||||
|     var = pic_car(pic, var); | ||||
|   } | ||||
|   else { | ||||
|     if (pic_length(pic, expr) != 3) { | ||||
|       pic_error(pic, "syntax_error"); | ||||
|     } | ||||
|     val = pic_car(pic, pic_cdr(pic, pic_cdr(pic, expr))); | ||||
|   } | ||||
|   if (! pic_sym_p(var)) { | ||||
|     pic_error(pic, "syntax error"); | ||||
|   } | ||||
|   sym = pic_sym(var); | ||||
|   if (! pic_find_rename(pic, senv, sym, &rename)) { | ||||
|     rename = pic_add_rename(pic, senv, sym); | ||||
|   } | ||||
| 
 | ||||
|   pic_try { | ||||
|     val = pic_eval(pic, val); | ||||
|   } pic_catch { | ||||
|     pic_errorf(pic, "macroexpand error: %s", pic_errmsg(pic)); | ||||
|   } | ||||
| 
 | ||||
|   if (! pic_proc_p(val)) { | ||||
|     pic_errorf(pic, "macro definition \"~s\" evaluates to non-procedure object", var); | ||||
|   } | ||||
| 
 | ||||
|   define_macro(pic, rename, pic_proc_ptr(val), NULL); | ||||
| 
 | ||||
|   return pic_none_value(); | ||||
| } | ||||
| 
 | ||||
| static pic_value | ||||
| macroexpand_macro(pic_state *pic, struct pic_macro *mac, pic_value expr, struct pic_senv *senv, struct pic_dict *cxt) | ||||
| { | ||||
|   pic_value v, args; | ||||
| 
 | ||||
| #if DEBUG | ||||
|   puts("before expand-1:"); | ||||
|   pic_debug(pic, expr); | ||||
|   puts(""); | ||||
| #endif | ||||
| 
 | ||||
|   if (mac->senv == NULL) { /* legacy macro */ | ||||
|     args = pic_cdr(pic, expr); | ||||
|   } | ||||
|   else { | ||||
|     args = pic_list3(pic, expr, pic_obj_value(senv), pic_obj_value(mac->senv)); | ||||
|   } | ||||
| 
 | ||||
|   pic_try { | ||||
|     v = pic_apply(pic, mac->proc, args); | ||||
|   } pic_catch { | ||||
|     pic_errorf(pic, "macroexpand error: %s", pic_errmsg(pic)); | ||||
|   } | ||||
| 
 | ||||
| #if DEBUG | ||||
|   puts("after expand-1:"); | ||||
|   pic_debug(pic, v); | ||||
|   puts(""); | ||||
| #endif | ||||
| 
 | ||||
|   return macroexpand(pic, v, senv, cxt); | ||||
| } | ||||
| 
 | ||||
| static pic_value | ||||
| macroexpand_list(pic_state *pic, pic_value obj, struct pic_senv *senv, struct pic_dict *cxt) | ||||
| { | ||||
|  | @ -402,6 +283,165 @@ macroexpand_define(pic_state *pic, pic_value expr, struct pic_senv *senv, struct | |||
|   return pic_list3(pic, pic_sym_value(pic->sDEFINE), macroexpand_symbol(pic, sym, senv, cxt), val); | ||||
| } | ||||
| 
 | ||||
| static pic_value | ||||
| macroexpand_defsyntax(pic_state *pic, pic_value expr, struct pic_senv *senv, struct pic_dict *cxt) | ||||
| { | ||||
|   pic_value var, val; | ||||
|   pic_sym sym, rename; | ||||
| 
 | ||||
|   if (pic_length(pic, expr) != 3) { | ||||
|     pic_error(pic, "syntax error"); | ||||
|   } | ||||
| 
 | ||||
|   var = pic_cadr(pic, expr); | ||||
|   if (! pic_sym_p(var)) { | ||||
|     var = macroexpand(pic, var, senv, cxt); | ||||
|   } | ||||
|   if (! pic_sym_p(var)) { | ||||
|     pic_error(pic, "binding to non-symbol object"); | ||||
|   } | ||||
|   sym = pic_sym(var); | ||||
|   if (! pic_find_rename(pic, senv, sym, &rename)) { | ||||
|     rename = pic_add_rename(pic, senv, sym); | ||||
|   } | ||||
| 
 | ||||
|   val = pic_cadr(pic, pic_cdr(pic, expr)); | ||||
| 
 | ||||
|   pic_try { | ||||
|     val = pic_eval(pic, val); | ||||
|   } pic_catch { | ||||
|     pic_errorf(pic, "macroexpand error: %s", pic_errmsg(pic)); | ||||
|   } | ||||
| 
 | ||||
|   if (! pic_proc_p(val)) { | ||||
|     pic_errorf(pic, "macro definition \"~s\" evaluates to non-procedure object", var); | ||||
|   } | ||||
| 
 | ||||
|   define_macro(pic, rename, pic_proc_ptr(val), senv); | ||||
| 
 | ||||
|   return pic_none_value(); | ||||
| } | ||||
| 
 | ||||
| static pic_value | ||||
| macroexpand_defmacro(pic_state *pic, pic_value expr, struct pic_senv *senv) | ||||
| { | ||||
|   pic_value var, val; | ||||
|   pic_sym sym, rename; | ||||
| 
 | ||||
|   if (pic_length(pic, expr) < 2) { | ||||
|     pic_error(pic, "syntax error"); | ||||
|   } | ||||
| 
 | ||||
|   var = pic_car(pic, pic_cdr(pic, expr)); | ||||
|   if (pic_pair_p(var)) { | ||||
|     /* FIXME: unhygienic */ | ||||
|     val = pic_cons(pic, pic_sym_value(pic->sLAMBDA), | ||||
|                    pic_cons(pic, pic_cdr(pic, var), | ||||
|                             pic_cdr(pic, pic_cdr(pic, expr)))); | ||||
|     var = pic_car(pic, var); | ||||
|   } | ||||
|   else { | ||||
|     if (pic_length(pic, expr) != 3) { | ||||
|       pic_error(pic, "syntax_error"); | ||||
|     } | ||||
|     val = pic_car(pic, pic_cdr(pic, pic_cdr(pic, expr))); | ||||
|   } | ||||
|   if (! pic_sym_p(var)) { | ||||
|     pic_error(pic, "syntax error"); | ||||
|   } | ||||
|   sym = pic_sym(var); | ||||
|   if (! pic_find_rename(pic, senv, sym, &rename)) { | ||||
|     rename = pic_add_rename(pic, senv, sym); | ||||
|   } | ||||
| 
 | ||||
|   pic_try { | ||||
|     val = pic_eval(pic, val); | ||||
|   } pic_catch { | ||||
|     pic_errorf(pic, "macroexpand error: %s", pic_errmsg(pic)); | ||||
|   } | ||||
| 
 | ||||
|   if (! pic_proc_p(val)) { | ||||
|     pic_errorf(pic, "macro definition \"~s\" evaluates to non-procedure object", var); | ||||
|   } | ||||
| 
 | ||||
|   define_macro(pic, rename, pic_proc_ptr(val), NULL); | ||||
| 
 | ||||
|   return pic_none_value(); | ||||
| } | ||||
| 
 | ||||
| static pic_value | ||||
| macroexpand_let_syntax(pic_state *pic, pic_value expr, struct pic_senv *senv, struct pic_dict *cxt) | ||||
| { | ||||
|   struct pic_senv *in; | ||||
|   pic_value formal, v, var, val; | ||||
|   pic_sym sym, rename; | ||||
| 
 | ||||
|   in = (struct pic_senv *)pic_obj_alloc(pic, sizeof(struct pic_senv), PIC_TT_SENV); | ||||
|   in->up = senv; | ||||
|   xh_init_int(&in->renames, sizeof(pic_sym)); | ||||
| 
 | ||||
|   if (pic_length(pic, expr) < 2) { | ||||
|     pic_error(pic, "syntax error"); | ||||
|   } | ||||
| 
 | ||||
|   formal = pic_cadr(pic, expr); | ||||
|   if (! pic_list_p(formal)) { | ||||
|     pic_error(pic, "syntax error"); | ||||
|   } | ||||
|   pic_for_each (v, formal) { | ||||
|     var = pic_car(pic, v); | ||||
|     if (! pic_sym_p(var)) { | ||||
|       var = macroexpand(pic, var, senv, cxt); | ||||
|     } | ||||
|     if (! pic_sym_p(var)) { | ||||
|       pic_error(pic, "binding to non-symbol object"); | ||||
|     } | ||||
|     sym = pic_sym(var); | ||||
|     if (! pic_find_rename(pic, in, sym, &rename)) { | ||||
|       rename = pic_add_rename(pic, in, sym); | ||||
|     } | ||||
|     val = pic_eval(pic, pic_cadr(pic, v)); | ||||
|     if (! pic_proc_p(val)) { | ||||
|       pic_errorf(pic, "macro definition \"~s\" evaluated to non-procedure object", var); | ||||
|     } | ||||
|     define_macro(pic, rename, pic_proc_ptr(val), senv); | ||||
|   } | ||||
|   return pic_cons(pic, pic_sym_value(pic->sBEGIN), macroexpand_list(pic, pic_cddr(pic, expr), in, cxt)); | ||||
| } | ||||
| 
 | ||||
| static pic_value | ||||
| macroexpand_macro(pic_state *pic, struct pic_macro *mac, pic_value expr, struct pic_senv *senv, struct pic_dict *cxt) | ||||
| { | ||||
|   pic_value v, args; | ||||
| 
 | ||||
| #if DEBUG | ||||
|   puts("before expand-1:"); | ||||
|   pic_debug(pic, expr); | ||||
|   puts(""); | ||||
| #endif | ||||
| 
 | ||||
|   if (mac->senv == NULL) { /* legacy macro */ | ||||
|     args = pic_cdr(pic, expr); | ||||
|   } | ||||
|   else { | ||||
|     args = pic_list3(pic, expr, pic_obj_value(senv), pic_obj_value(mac->senv)); | ||||
|   } | ||||
| 
 | ||||
|   pic_try { | ||||
|     v = pic_apply(pic, mac->proc, args); | ||||
|   } pic_catch { | ||||
|     pic_errorf(pic, "macroexpand error: %s", pic_errmsg(pic)); | ||||
|   } | ||||
| 
 | ||||
| #if DEBUG | ||||
|   puts("after expand-1:"); | ||||
|   pic_debug(pic, v); | ||||
|   puts(""); | ||||
| #endif | ||||
| 
 | ||||
|   return macroexpand(pic, v, senv, cxt); | ||||
| } | ||||
| 
 | ||||
| static pic_value | ||||
| macroexpand_node(pic_state *pic, pic_value expr, struct pic_senv *senv, struct pic_dict *cxt) | ||||
| { | ||||
|  | @ -445,6 +485,12 @@ macroexpand_node(pic_state *pic, pic_value expr, struct pic_senv *senv, struct p | |||
|       else if (tag == pic->sDEFINE_MACRO) { | ||||
|         return macroexpand_defmacro(pic, expr, senv); | ||||
|       } | ||||
|       else if (tag == pic->sLET_SYNTAX) { | ||||
|         return macroexpand_let_syntax(pic, expr, senv, cxt); | ||||
|       } | ||||
|       /* else if (tag == pic->sLETREC_SYNTAX) { */ | ||||
|       /*   return macroexpand_letrec_syntax(pic, expr, senv, cxt); */ | ||||
|       /* } */ | ||||
|       else if (tag == pic->sLAMBDA) { | ||||
|         return macroexpand_lambda(pic, expr, senv, cxt); | ||||
|       } | ||||
|  |  | |||
|  | @ -96,6 +96,8 @@ pic_open(int argc, char *argv[], char **envp) | |||
|   register_core_symbol(pic, sUNQUOTE_SPLICING, "unquote-splicing"); | ||||
|   register_core_symbol(pic, sDEFINE_SYNTAX, "define-syntax"); | ||||
|   register_core_symbol(pic, sDEFINE_MACRO, "define-macro"); | ||||
|   register_core_symbol(pic, sLET_SYNTAX, "let-syntax"); | ||||
|   register_core_symbol(pic, sLETREC_SYNTAX, "letrec-syntax"); | ||||
|   register_core_symbol(pic, sDEFINE_LIBRARY, "define-library"); | ||||
|   register_core_symbol(pic, sIMPORT, "import"); | ||||
|   register_core_symbol(pic, sEXPORT, "export"); | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Yuichi Nishiwaki
						Yuichi Nishiwaki