From f9d73ddc30582e9aa8880b66fecedcfd9b37c67d Mon Sep 17 00:00:00 2001 From: Alex Shinn Date: Fri, 4 Oct 2013 12:04:50 +0900 Subject: [PATCH] Adding the -R option to run "main" procedures directly from modules, analogous to Python's -m. With no argument, runs chibi.repl. --- doc/chibi-scheme.1 | 10 +++++-- doc/chibi.scrbl | 4 +-- lib/chibi/repl.scm | 19 +++++++------ main.c | 71 +++++++++++++++++++++++++++++----------------- 4 files changed, 65 insertions(+), 39 deletions(-) diff --git a/doc/chibi-scheme.1 b/doc/chibi-scheme.1 index e9901ae2..f2eaf5db 100644 --- a/doc/chibi-scheme.1 +++ b/doc/chibi-scheme.1 @@ -6,7 +6,7 @@ chibi-scheme \- a tiny Scheme interpreter .SH SYNOPSIS .B chibi-scheme -[-qQrfV] +[-qQrRfV] [-I .I path ] @@ -103,9 +103,15 @@ The resulting environment will only contain the core syntactic forms and primitives coded in C. This is very fast and guaranteed not to load any external files, but is also very limited. .TP -.BI -r +.BI -r [main] Run the "main" procedure when the script finishes loading as in SRFI-22. .TP +.BI -R [module] +Loads the given module and runs the "main" procedure it defines (which +need not be exported) with a single argument of the list of command-line +arguments as in SRFI-22. The name "main" can be overridden with the -r +option. +.TP .BI -s Strict mode, escalating warnings to fatal errors. .TP diff --git a/doc/chibi.scrbl b/doc/chibi.scrbl index bacef2b1..8d25abc5 100755 --- a/doc/chibi.scrbl +++ b/doc/chibi.scrbl @@ -110,8 +110,8 @@ are listed below. The command-line programs \ccode{chibi-scheme}, \ccode{chibi-doc} and \ccode{chibi-ffi} are installed by default, along with manpages. -\ccode{chibi-scheme} provides a REPL and way to run scripts. In the -interest of size it has no --help option - see the man page for usage. +\ccode{chibi-scheme} provides a REPL and way to run scripts. Run -? +for a brief list of options, or see the man page for more details. \ccode{chibi-doc} is the command-line interface to the literate documentation system described in \hyperlink["lib/chibi/scribble.html"]{(chibi scribble)}, and used to diff --git a/lib/chibi/repl.scm b/lib/chibi/repl.scm index 2c61e372..dd1e1e3e 100644 --- a/lib/chibi/repl.scm +++ b/lib/chibi/repl.scm @@ -2,15 +2,13 @@ ;; Copyright (c) 2012-2013 Alex Shinn. All rights reserved. ;; BSD-style license: http://synthcode.com/license.txt -;;> A user-friendly REPL with line editing and signal handling. -;;> The default REPL provided by chibi-scheme is very minimal, -;;> meant primarily to be small and work on any platform. This -;;> module provides an advanced REPL that handles vt100 line -;;> editing and signal handling, so that C-c will interrupt a -;;> computation and bring you back to the REPL prompt. To use -;;> this repl, run -;;> \command{chibi-scheme -mchibi.repl -e'(repl)'} -;;> from the command line or within Emacs. +;;> A user-friendly REPL with line editing and signal handling. The +;;> default REPL provided by chibi-scheme is very minimal, meant +;;> primarily to be small and work on any platform. This module +;;> provides an advanced REPL that handles vt100 line editing and +;;> signal handling, so that C-c will interrupt a computation and +;;> bring you back to the REPL prompt. To use this repl, run +;;> \command{chibi-scheme -R} from the command line or within Emacs. (define (with-signal-handler sig handler thunk) (let ((old-handler #f)) @@ -448,3 +446,6 @@ (newline (current-error-port))))) (call-with-output-file (repl-history-file rp) (lambda (out) (write (history->list (repl-history rp)) out))))))) + +(define (main args) + (repl)) diff --git a/main.c b/main.c index af1eb3b5..ca46d5bd 100644 --- a/main.c +++ b/main.c @@ -27,26 +27,27 @@ void sexp_usage(int err) { printf("usage: chibi-scheme [ ...] [ ...]\n" #if SEXP_USE_FOLD_CASE_SYMS - " -f - case-fold symbols\n" + " -f - case-fold symbols\n" #endif - " -q - \"quick\" load, use the core -xchibi language\n" - " -Q - extra \"quick\" load, -xchibi.primitive\n" - " -V - print version information\n" + " -q - \"quick\" load, use the core -xchibi language\n" + " -Q - extra \"quick\" load, -xchibi.primitive\n" + " -V - print version information\n" #if ! SEXP_USE_BOEHM - " -h - specify the initial heap size\n" + " -h - specify the initial heap size\n" #endif #if SEXP_USE_MODULES - " -A - append a module search directory\n" - " -I - prepend a module search directory\n" - " -m - import a module\n" - " -x - import only a module\n" + " -A - append a module search directory\n" + " -I - prepend a module search directory\n" + " -m - import a module\n" + " -x - import only a module\n" #endif - " -e - evaluate an expression\n" - " -p - evaluate and print an expression\n" - " -r[
] - run a SRFI-22 main\n" + " -e - evaluate an expression\n" + " -p - evaluate and print an expression\n" + " -r[
] - run a SRFI-22 main\n" + " -R[] - run main from a module\n" #if SEXP_USE_IMAGE_LOADING - " -d - dump an image file and exit\n" - " -i - load an image file\n" + " -d - dump an image file and exit\n" + " -i - load an image file\n" #endif ); if (err == 0) exit_success(); @@ -261,6 +262,18 @@ static sexp_uint_t multiplier (char c) { } #endif +static char* make_import(const char* prefix, const char* mod, const char* suffix) { + int len = strlen(mod) + strlen(prefix) + strlen(suffix); + char *p, *impmod = (char*) malloc(len+1); + strcpy(impmod, prefix); + strcpy(impmod+strlen(prefix), mod); + strcpy(impmod+len-+strlen(suffix), suffix); + impmod[len] = '\0'; + for (p=impmod; *p; p++) + if (*p == '.') *p=' '; + return impmod; +} + static void check_nonull_arg (int c, char *arg) { if (! arg) { fprintf(stderr, "chibi-scheme: option '%c' requires an argument\n", c); @@ -341,10 +354,9 @@ static void do_init_context (sexp* ctx, sexp* env, sexp_uint_t heap_size, void run_main (int argc, char **argv) { #if SEXP_USE_MODULES - char *impmod, *p; - sexp_sint_t len; + char *impmod; #endif - char *arg, *prefix=NULL, *suffix=NULL, *main_symbol=NULL; + char *arg, *prefix=NULL, *suffix=NULL, *main_symbol=NULL, *main_module=NULL; sexp_sint_t i, j, c, quit=0, print=0, init_loaded=0, mods_loaded=0, no_script=0, fold_case=SEXP_DEFAULT_FOLD_CASE_SYMS; sexp_uint_t heap_size=0, heap_max_size=SEXP_MAXIMUM_HEAP_SIZE; @@ -400,14 +412,7 @@ void run_main (int argc, char **argv) { /* explicitly setting a language */ #if SEXP_USE_MODULES check_nonull_arg(c, arg); - len = strlen(arg)+strlen(prefix)+strlen(suffix); - impmod = (char*) malloc(len+1); - strcpy(impmod, prefix); - strcpy(impmod+strlen(prefix), arg); - strcpy(impmod+len-+strlen(suffix), suffix); - impmod[len] = '\0'; - for (p=impmod; *p; p++) - if (*p == '.') *p=' '; + impmod = make_import(prefix, arg, suffix); tmp = check_exception(ctx, sexp_eval_string(ctx, impmod, -1, (c=='x' ? sexp_global(ctx, SEXP_G_META_ENV) : env))); free(impmod); if (c == 'x') { @@ -502,6 +507,10 @@ void run_main (int argc, char **argv) { sexp_global(ctx, SEXP_G_FOLD_CASE_P) = SEXP_TRUE; break; #endif + case 'R': + main_module = argv[i][2] == '\0' ? "chibi.repl" : argv[i]+2; + if (main_symbol == NULL) main_symbol = "main"; + break; case 'r': main_symbol = argv[i][2] == '\0' ? "main" : argv[i]+2; break; @@ -530,6 +539,15 @@ void run_main (int argc, char **argv) { /* no script or main, run interactively */ repl(ctx, env); } else { +#if SEXP_USE_MODULES + /* load the module or script */ + if (main_module != NULL) { + impmod = make_import("(load-module '(", main_module, "))"); + env = check_exception(ctx, sexp_eval_string(ctx, impmod, -1, sexp_global(ctx, SEXP_G_META_ENV))); + if (sexp_vectorp(env)) env = sexp_vector_ref(env, SEXP_ONE); + free(impmod); + } else +#endif if (i < argc && !no_script) { /* script usage */ #if SEXP_USE_MODULES /* reset the environment to have only the `import' and */ @@ -548,7 +566,6 @@ void run_main (int argc, char **argv) { sexp_env_define(ctx, env, sym, tmp); } #endif - /* load the script */ sexp_context_tracep(ctx) = 1; tmp = sexp_env_bindings(env); #if SEXP_USE_MODULES @@ -573,6 +590,8 @@ void run_main (int argc, char **argv) { if (sexp_procedurep(tmp)) { args = sexp_list1(ctx, args); check_exception(ctx, sexp_apply(ctx, tmp, args)); + } else { + fprintf(stderr, "couldn't find main binding: %s in %s\n", main_symbol, main_module ? main_module : argv[i]); } } }