int repl() { global_env = null_import_environment(); environment_t *env = global_env; print_banner(env); #if HAVE_LIBREADLINE init_readline(); #endif for(;;) { static char *input = reinterpret_cast<char*>(1); /* * input == 1 is the ugliest hack ever to * disoplay the imported_defaults message below, * and also because of ANOTHER hack, the home-brewed * exception system using longjumps. I think I need to * rewrite... :) */ if ( input != reinterpret_cast<char*>(1) ) { if ( (input = readline("#; mickey> ")) == NULL ) break; // end of input stream if ( *trimr(input) == '\0' ) continue; // empty command #ifdef HAVE_LIBREADLINE add_history(input); #endif if ( exception_raised() ) { backtrace(); backtrace_clear(); continue; } } else input = strdup(""); TRY { /* * Must wrap import_defaults in try-catch */ { static bool imported_defaults = false; if ( !imported_defaults ) { printf("\n"); printf(" To quit, hit CTRL+D or type (exit). Use (help) for an introduction.\n"); printf(" Distributed under the LGPL 2.1; see LICENSE\n"); printf("\n"); printf(" WARNING: There's no garbage collector in Mickey yet!\n"); printf("|#\n\n"); import_defaults(env); imported_defaults = true; // import (help) and (top-level) etc. if ( !global_opts.empty_repl_env ) import(env, exports_repl, "(scheme repl)"); } } program_t *p = parse(input, env); if ( p->parens < 0 ) raise(runtime_exception(format( "parser: unbalanced parenthesis -> %ld", p->parens))); // Read until we have balanced parenthesis std::string s(input); while ( p->parens != 0 ) { if ( (input = readline("")) == NULL ) break; if ( *trimr(input) == '\0' ) continue; s += " "; s += input; delete p; #ifdef HAVE_LIBREADLINE free(input); input = NULL; #endif p = parse(s.c_str(), env); } #ifdef HAVE_LIBREADLINE if ( input ) free(input); #endif for ( cons_t *i = p->root; !nullp(i); i = cdr(i) ) { cons_t *result = eval(car(i), p->globals); if ( circularp(result) ) { fflush(stdout); fprintf(stderr, "Warning: List is circular\n"); cons_t *l = list(), *end = l; for ( int n=0; n < MAX_CIRCULAR_DISPLAY_ITEMS; ++n ) { end->car = car(result); end->cdr = cons(nil()); end = cdr(end); result = cdr(result); } end->car = symbol("...etc"); end->cdr = cons(nil()); printf("%s\n", sprint(l).c_str()); } else { std::string s = sprint(result); if ( !s.empty() ) printf("%s\n", s.c_str()); } } delete p; } CATCH (const exception_t& e) { if ( *e.what() != '\0' ) fprintf(stderr, "%s\n", e.what()); backtrace(); backtrace_clear(); } } printf("\n"); return 0; }
cons_t* proc_circularp(cons_t* p, environment_t*) { assert_length(p, 1); assert_type(PAIR, car(p)); return boolean(circularp(car(p))); }