From 07b201c830a3f04a0fe1554b871fb6308ff35fcd Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Mon, 28 Jul 2014 00:41:20 +0900 Subject: [PATCH 1/7] undocument pic_defmacro --- include/picrin.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/picrin.h b/include/picrin.h index 5db83684..6f0184a8 100644 --- a/include/picrin.h +++ b/include/picrin.h @@ -145,7 +145,6 @@ pic_value pic_funcall(pic_state *pic, const char *name, pic_list args); struct pic_proc *pic_get_proc(pic_state *); int pic_get_args(pic_state *, const char *, ...); void pic_defun(pic_state *, const char *, pic_func_t); -void pic_defmacro(pic_state *, const char *, struct pic_proc *); bool pic_equal_p(pic_state *, pic_value, pic_value); From 9c1a397ead281bc8a9198fd2911e12259403bc4f Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Mon, 28 Jul 2014 00:48:13 +0900 Subject: [PATCH 2/7] define 'define-library' as a macro --- src/init.c | 2 ++ src/lib.c | 39 +++++++++++++++++++++++++++++++++++++++ src/macro.c | 44 +++++--------------------------------------- 3 files changed, 46 insertions(+), 39 deletions(-) diff --git a/src/init.c b/src/init.c index b11bd0d7..07fac1e3 100644 --- a/src/init.c +++ b/src/init.c @@ -32,6 +32,7 @@ void pic_init_write(pic_state *); void pic_init_read(pic_state *); void pic_init_dict(pic_state *); void pic_init_eval(pic_state *); +void pic_init_lib(pic_state *); void pic_init_contrib(pic_state *); void pic_load_piclib(pic_state *); @@ -94,6 +95,7 @@ pic_init_core(pic_state *pic) pic_init_read(pic); DONE; pic_init_dict(pic); DONE; pic_init_eval(pic); DONE; + pic_init_lib(pic); DONE; pic_load_piclib(pic); DONE; diff --git a/src/lib.c b/src/lib.c index 7a197c87..9061afbc 100644 --- a/src/lib.c +++ b/src/lib.c @@ -6,6 +6,7 @@ #include "picrin/lib.h" #include "picrin/pair.h" #include "picrin/macro.h" +#include "picrin/error.h" struct pic_lib * pic_make_library(pic_state *pic, pic_value name) @@ -113,3 +114,41 @@ pic_export_as(pic_state *pic, pic_sym sym, pic_sym as) xh_put_int(&pic->lib->exports, as, &rename); } + +static pic_value +pic_lib_define_library(pic_state *pic) +{ + struct pic_lib *prev = pic->lib; + size_t argc, i; + pic_value spec, *argv; + + pic_get_args(pic, "o*", &spec, &argc, &argv); + + pic_make_library(pic, spec); + + pic_try { + pic_in_library(pic, spec); + + for (i = 0; i < argc; ++i) { + pic_void(pic_eval(pic, argv[i], pic->lib)); + } + + pic_in_library(pic, prev->name); + } + pic_catch { + pic_in_library(pic, prev->name); /* restores pic->lib even if an error occurs */ + pic_throw_error(pic, pic->err); + } + + return pic_none_value(); +} + +void +pic_init_lib(pic_state *pic) +{ + void pic_defmacro(pic_state *, pic_sym, pic_sym, pic_func_t); + + /* pic_define_library_syntax(pic, "import", pic_lib_import); */ + /* pic_define_library_syntax(pic, "export", pic_lib_export); */ + pic_defmacro(pic, pic->sDEFINE_LIBRARY, pic->rDEFINE_LIBRARY, pic_lib_define_library); +} diff --git a/src/macro.c b/src/macro.c index 0603d232..191df9a0 100644 --- a/src/macro.c +++ b/src/macro.c @@ -152,35 +152,6 @@ macroexpand_export(pic_state *pic, pic_value expr) return pic_none_value(); } -static pic_value -macroexpand_deflibrary(pic_state *pic, pic_value expr) -{ - struct pic_lib *prev = pic->lib; - pic_value v; - - if (pic_length(pic, expr) < 2) { - pic_error(pic, "syntax error"); - } - - pic_make_library(pic, pic_cadr(pic, expr)); - - pic_try { - pic_in_library(pic, pic_cadr(pic, expr)); - - pic_for_each (v, pic_cddr(pic, expr)) { - pic_void(pic_eval(pic, v, pic->lib)); - } - - pic_in_library(pic, prev->name); - } - pic_catch { - pic_in_library(pic, prev->name); /* restores pic->lib even if an error occurs */ - pic_throw_error(pic, pic->err); - } - - return pic_none_value(); -} - static pic_value macroexpand_list(pic_state *pic, pic_value obj, struct pic_senv *senv) { @@ -359,10 +330,7 @@ macroexpand_node(pic_state *pic, pic_value expr, struct pic_senv *senv) if (pic_sym_p(car)) { pic_sym tag = pic_sym(car); - if (tag == pic->rDEFINE_LIBRARY) { - return macroexpand_deflibrary(pic, expr); - } - else if (tag == pic->rIMPORT) { + if (tag == pic->rIMPORT) { return macroexpand_import(pic, expr); } else if (tag == pic->rEXPORT) { @@ -519,17 +487,15 @@ pic_define_syntactic_keyword(pic_state *pic, struct pic_senv *senv, pic_sym sym, } void -pic_defmacro(pic_state *pic, const char *name, struct pic_proc *macro) +pic_defmacro(pic_state *pic, pic_sym name, pic_sym id, pic_func_t func) { - pic_sym sym, rename; + pic_put_rename(pic, pic->lib->env, name, id); /* symbol registration */ - sym = pic_intern_cstr(pic, name); - rename = pic_add_rename(pic, pic->lib->env, sym); - define_macro(pic, rename, macro, NULL); + define_macro(pic, id, pic_proc_new(pic, func, pic_symbol_name(pic, name)), NULL); /* auto export! */ - pic_export(pic, sym); + pic_export(pic, name); } bool From d31e20c25cda2f7cc122ef8afc1ad141717e9644 Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Mon, 28 Jul 2014 01:02:48 +0900 Subject: [PATCH 3/7] define 'import' and 'export' as macros --- src/lib.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++-- src/macro.c | 56 +---------------------------------------------------- 2 files changed, 53 insertions(+), 57 deletions(-) diff --git a/src/lib.c b/src/lib.c index 9061afbc..5946d061 100644 --- a/src/lib.c +++ b/src/lib.c @@ -115,6 +115,56 @@ pic_export_as(pic_state *pic, pic_sym sym, pic_sym as) xh_put_int(&pic->lib->exports, as, &rename); } +static pic_value +pic_lib_import(pic_state *pic) +{ + size_t argc, i; + pic_value *argv; + + pic_get_args(pic, "*", &argc, &argv); + + for (i = 0; i < argc; ++i) { + pic_import(pic, argv[i]); + } + + return pic_none_value(); +} + +static pic_value +pic_lib_export(pic_state *pic) +{ + const pic_sym sRENAME = pic_intern_cstr(pic, "rename"); + size_t argc, i; + pic_value *argv, spec, a, b; + + pic_get_args(pic, "*", &argc, &argv); + + for (i = 0; i < argc; ++i) { + spec = argv[i]; + if (pic_sym_p(spec)) { /* (export a) */ + pic_export(pic, pic_sym(spec)); + } + else { /* (export (rename a b)) */ + if (! pic_list_p(spec)) + goto fail; + if (! pic_length(pic, spec) == 3) + goto fail; + if (! pic_eq_p(pic_car(pic, spec), pic_sym_value(sRENAME))) + goto fail; + if (! pic_sym_p(a = pic_list_ref(pic, spec, 1))) + goto fail; + if (! pic_sym_p(b = pic_list_ref(pic, spec, 2))) + goto fail; + pic_export_as(pic, pic_sym(a), pic_sym(b)); + } + } + + return pic_none_value(); + + fail: + pic_errorf(pic, "illegal export spec: ~s", spec); +} + static pic_value pic_lib_define_library(pic_state *pic) { @@ -148,7 +198,7 @@ pic_init_lib(pic_state *pic) { void pic_defmacro(pic_state *, pic_sym, pic_sym, pic_func_t); - /* pic_define_library_syntax(pic, "import", pic_lib_import); */ - /* pic_define_library_syntax(pic, "export", pic_lib_export); */ + pic_defmacro(pic, pic->sIMPORT, pic->rIMPORT, pic_lib_import); + pic_defmacro(pic, pic->sEXPORT, pic->rEXPORT, pic_lib_export); pic_defmacro(pic, pic->sDEFINE_LIBRARY, pic->rDEFINE_LIBRARY, pic_lib_define_library); } diff --git a/src/macro.c b/src/macro.c index 191df9a0..0d59ccfe 100644 --- a/src/macro.c +++ b/src/macro.c @@ -104,54 +104,6 @@ macroexpand_quote(pic_state *pic, pic_value expr) return pic_cons(pic, pic_sym_value(pic->rQUOTE), pic_cdr(pic, expr)); } -static pic_value -macroexpand_import(pic_state *pic, pic_value expr) -{ - pic_value spec; - - pic_for_each (spec, pic_cdr(pic, expr)) { - pic_import(pic, spec); - } - - return pic_none_value(); -} - -static pic_value -macroexpand_export(pic_state *pic, pic_value expr) -{ - extern pic_value pic_export_as(pic_state *, pic_sym, pic_sym); - pic_value spec; - pic_sym sRENAME, sym, as; - - sRENAME = pic_intern_cstr(pic, "rename"); - - pic_for_each (spec, pic_cdr(pic, expr)) { - if (pic_sym_p(spec)) { - sym = as = pic_sym(spec); - } - else if (pic_list_p(spec) && pic_eq_p(pic_car(pic, spec), pic_sym_value(sRENAME))) { - if (pic_length(pic, spec) != 3) { - pic_error(pic, "syntax error"); - } - if (! pic_sym_p(pic_list_ref(pic, spec, 1))) { - pic_error(pic, "syntax error"); - } - sym = pic_sym(pic_list_ref(pic, spec, 1)); - if (! pic_sym_p(pic_list_ref(pic, spec, 2))) { - pic_error(pic, "syntax error"); - } - as = pic_sym(pic_list_ref(pic, spec, 2)); - } - else { - pic_error(pic, "syntax error"); - } - /* TODO: warn if symbol is shadowed by local variable */ - pic_export_as(pic, sym, as); - } - - return pic_none_value(); -} - static pic_value macroexpand_list(pic_state *pic, pic_value obj, struct pic_senv *senv) { @@ -330,13 +282,7 @@ macroexpand_node(pic_state *pic, pic_value expr, struct pic_senv *senv) if (pic_sym_p(car)) { pic_sym tag = pic_sym(car); - if (tag == pic->rIMPORT) { - return macroexpand_import(pic, expr); - } - else if (tag == pic->rEXPORT) { - return macroexpand_export(pic, expr); - } - else if (tag == pic->rDEFINE_SYNTAX) { + if (tag == pic->rDEFINE_SYNTAX) { return macroexpand_defsyntax(pic, expr, senv); } else if (tag == pic->rLAMBDA) { From c8918b8e6372453d65b8c84ad0f3fa4152f05a66 Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Mon, 28 Jul 2014 02:00:16 +0900 Subject: [PATCH 4/7] support renaming import (including 'only', 'rename', 'except', 'prefix' clauses) --- src/lib.c | 166 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 111 insertions(+), 55 deletions(-) diff --git a/src/lib.c b/src/lib.c index 5946d061..c4f87f3a 100644 --- a/src/lib.c +++ b/src/lib.c @@ -7,6 +7,8 @@ #include "picrin/pair.h" #include "picrin/macro.h" #include "picrin/error.h" +#include "picrin/dict.h" +#include "picrin/string.h" struct pic_lib * pic_make_library(pic_state *pic, pic_value name) @@ -62,57 +64,131 @@ pic_find_library(pic_state *pic, pic_value spec) return pic_lib_ptr(pic_cdr(pic, v)); } -void -pic_import(pic_state *pic, pic_value spec) +static struct pic_dict * +import_table(pic_state *pic, pic_value spec) { + const pic_sym sONLY = pic_intern_cstr(pic, "only"); + const pic_sym sRENAME = pic_intern_cstr(pic, "rename"); + const pic_sym sPREFIX = pic_intern_cstr(pic, "prefix"); + const pic_sym sEXCEPT = pic_intern_cstr(pic, "except"); struct pic_lib *lib; + struct pic_dict *imports, *dict; + pic_value val, id; xh_iter it; + imports = pic_dict_new(pic); + + if (pic_list_p(spec)) { + if (pic_eq_p(pic_car(pic, spec), pic_sym_value(sONLY))) { + dict = import_table(pic, pic_cadr(pic, spec)); + pic_for_each (val, pic_cddr(pic, spec)) { + pic_dict_set(pic, imports, pic_sym(val), pic_dict_ref(pic, dict, pic_sym(val))); + } + return imports; + } + if (pic_eq_p(pic_car(pic, spec), pic_sym_value(sRENAME))) { + imports = import_table(pic, pic_cadr(pic, spec)); + pic_for_each (val, pic_cddr(pic, spec)) { + id = pic_dict_ref(pic, imports, pic_sym(pic_car(pic, val))); + pic_dict_del(pic, imports, pic_sym(pic_car(pic, val))); + pic_dict_set(pic, imports, pic_sym(pic_cadr(pic, val)), id); + } + return imports; + } + if (pic_eq_p(pic_car(pic, spec), pic_sym_value(sPREFIX))) { + dict = import_table(pic, pic_cadr(pic, spec)); + xh_begin(&it, &dict->hash); + while (xh_next(&it)) { + pic_dict_set(pic, imports, pic_intern_cstr(pic, pic_str_cstr(pic_strcat(pic, pic_str_new_cstr(pic, pic_symbol_name(pic, pic_sym(pic_car(pic, pic_cddr(pic, spec))))), pic_str_new_cstr(pic, pic_symbol_name(pic, xh_key(it.e, pic_sym)))))), xh_val(it.e, pic_value)); + } + return imports; + } + if (pic_eq_p(pic_car(pic, spec), pic_sym_value(sEXCEPT))) { + imports = import_table(pic, pic_cadr(pic, spec)); + pic_for_each (val, pic_cddr(pic, spec)) { + pic_dict_del(pic, imports, pic_sym(val)); + } + return imports; + } + } lib = pic_find_library(pic, spec); if (! lib) { pic_errorf(pic, "library not found: ~a", spec); } xh_begin(&it, &lib->exports); while (xh_next(&it)) { + pic_dict_set(pic, imports, xh_key(it.e, pic_sym), pic_sym_value(xh_val(it.e, pic_sym))); + } + return imports; +} -#if DEBUG - printf("* importing %s as %s\n", pic_symbol_name(pic, xh_key(it.e, pic_sym)), pic_symbol_name(pic, xh_val(it.e, pic_sym))); +static void +import(pic_state *pic, pic_value spec) +{ + struct pic_dict *imports; + xh_iter it; + + imports = import_table(pic, spec); + + xh_begin(&it, &imports->hash); + while (xh_next(&it)) { + +#if 1 + printf("* importing %s as %s\n", pic_symbol_name(pic, xh_key(it.e, pic_sym)), pic_symbol_name(pic, pic_sym(xh_val(it.e, pic_value)))); #endif - pic_put_rename(pic, pic->lib->env, xh_key(it.e, pic_sym), xh_val(it.e, pic_sym)); + pic_put_rename(pic, pic->lib->env, xh_key(it.e, pic_sym), pic_sym(xh_val(it.e, pic_value))); } } +static void +export(pic_state *pic, pic_value spec) +{ + const pic_sym sRENAME = pic_intern_cstr(pic, "rename"); + pic_value a, b; + pic_sym rename; + + if (pic_sym_p(spec)) { /* (export a) */ + a = b = spec; + } else { /* (export (rename a b)) */ + if (! pic_list_p(spec)) + goto fail; + if (! pic_length(pic, spec) == 3) + goto fail; + if (! pic_eq_p(pic_car(pic, spec), pic_sym_value(sRENAME))) + goto fail; + if (! pic_sym_p(a = pic_list_ref(pic, spec, 1))) + goto fail; + if (! pic_sym_p(b = pic_list_ref(pic, spec, 2))) + goto fail; + } + + if (! pic_find_rename(pic, pic->lib->env, pic_sym(a), &rename)) { + pic_errorf(pic, "export: symbol not defined %s", pic_symbol_name(pic, pic_sym(a))); + } + +#if DEBUG + printf("* exporting %s as %s\n", pic_symbol_name(pic, pic_sym(b)), pic_symbol_name(pic, rename)); +#endif + + xh_put_int(&pic->lib->exports, pic_sym(b), &rename); + + return; + + fail: + pic_errorf(pic, "illegal export spec: ~s", spec); +} + +void +pic_import(pic_state *pic, pic_value spec) +{ + import(pic, spec); +} + void pic_export(pic_state *pic, pic_sym sym) { - pic_sym rename; - - if (! pic_find_rename(pic, pic->lib->env, sym, &rename)) { - pic_errorf(pic, "export: symbol not defined %s", pic_symbol_name(pic, sym)); - } - -#if DEBUG - printf("* exporting %s as %s\n", pic_symbol_name(pic, sym), pic_symbol_name(pic, rename)); -#endif - - xh_put_int(&pic->lib->exports, sym, &rename); -} - -void -pic_export_as(pic_state *pic, pic_sym sym, pic_sym as) -{ - pic_sym rename; - - if (! pic_find_rename(pic, pic->lib->env, sym, &rename)) { - pic_errorf(pic, "export: symbol not defined %s", pic_symbol_name(pic, sym)); - } - -#if DEBUG - printf("* exporting %s as %s\n", pic_symbol_name(pic, as), pic_symbol_name(pic, rename)); -#endif - - xh_put_int(&pic->lib->exports, as, &rename); + export(pic, pic_sym_value(sym)); } static pic_value @@ -124,7 +200,7 @@ pic_lib_import(pic_state *pic) pic_get_args(pic, "*", &argc, &argv); for (i = 0; i < argc; ++i) { - pic_import(pic, argv[i]); + import(pic, argv[i]); } return pic_none_value(); @@ -133,36 +209,16 @@ pic_lib_import(pic_state *pic) static pic_value pic_lib_export(pic_state *pic) { - const pic_sym sRENAME = pic_intern_cstr(pic, "rename"); size_t argc, i; - pic_value *argv, spec, a, b; + pic_value *argv; pic_get_args(pic, "*", &argc, &argv); for (i = 0; i < argc; ++i) { - spec = argv[i]; - if (pic_sym_p(spec)) { /* (export a) */ - pic_export(pic, pic_sym(spec)); - } - else { /* (export (rename a b)) */ - if (! pic_list_p(spec)) - goto fail; - if (! pic_length(pic, spec) == 3) - goto fail; - if (! pic_eq_p(pic_car(pic, spec), pic_sym_value(sRENAME))) - goto fail; - if (! pic_sym_p(a = pic_list_ref(pic, spec, 1))) - goto fail; - if (! pic_sym_p(b = pic_list_ref(pic, spec, 2))) - goto fail; - pic_export_as(pic, pic_sym(a), pic_sym(b)); - } + export(pic, argv[i]); } return pic_none_value(); - - fail: - pic_errorf(pic, "illegal export spec: ~s", spec); } static pic_value From d45ab8f9738e9addc8515442f5c950fd955526c9 Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Mon, 28 Jul 2014 02:00:54 +0900 Subject: [PATCH 5/7] add renaming-import test --- t/renaming-import.scm | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 t/renaming-import.scm diff --git a/t/renaming-import.scm b/t/renaming-import.scm new file mode 100644 index 00000000..628e3df4 --- /dev/null +++ b/t/renaming-import.scm @@ -0,0 +1,11 @@ +(define-library (foo) + (import (except (rename (prefix (only (scheme base) car cdr cons) my-) + (my-car my-kar) + (my-cdr my-kdr)) + my-kar)) + + ;; (import (rename (scheme base) + ;; (car my-kar) + ;; (cdr my-cdr))) + + (export my-kdr my-cons)) From 16c1330b1e0dfd06ddceb1ed04830efe37674956 Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Mon, 28 Jul 2014 02:03:29 +0900 Subject: [PATCH 6/7] update docs --- docs/lang.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/lang.rst b/docs/lang.rst index c1a79c7c..de380951 100644 --- a/docs/lang.rst +++ b/docs/lang.rst @@ -55,7 +55,7 @@ section status comments 4.3.2 Pattern language yes ``syntax-rules`` 4.3.3 Signaling errors in macro transformers yes 5.1 Programs yes -5.2 Import declarations incomplete only simple import declarations, no support for import with renaming. +5.2 Import declarations yes 5.3.1 Top level definitions yes 5.3.2 Internal definitions yes TODO: interreferential definitions 5.3.3 Multiple-value definitions yes @@ -71,7 +71,7 @@ section status comments 6.2.4 Implementation extensions yes 6.2.5 Syntax of numerical constants yes 6.2.6 Numerical operations yes ``denominator``, ``numerator``, and ``rationalize`` are not supported for now. Also, picrin does not provide complex library procedures. -6.2.7 Numerical input and output incomplete only partial support supplied. +6.2.7 Numerical input and output yes 6.3 Booleans yes 6.4 Pairs and lists yes ``list?`` is safe for using against circular list. 6.5 Symbols yes From 9b50d9133d2f20e5d5e41dc9f7c39d59a20a66e4 Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Mon, 28 Jul 2014 02:04:00 +0900 Subject: [PATCH 7/7] remove debug print --- src/lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.c b/src/lib.c index c4f87f3a..cb6ce5b2 100644 --- a/src/lib.c +++ b/src/lib.c @@ -133,7 +133,7 @@ import(pic_state *pic, pic_value spec) xh_begin(&it, &imports->hash); while (xh_next(&it)) { -#if 1 +#if DEBUG printf("* importing %s as %s\n", pic_symbol_name(pic, xh_key(it.e, pic_sym)), pic_symbol_name(pic, pic_sym(xh_val(it.e, pic_value)))); #endif