示例#1
0
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;
}
示例#2
0
cons_t* proc_circularp(cons_t* p, environment_t*)
{
  assert_length(p, 1);
  assert_type(PAIR, car(p));
  return boolean(circularp(car(p)));
}