Ejemplo n.º 1
0
cons_t* proc_boundp(cons_t* p, environment_t* e)
{
  assert_length(p, 1);
  assert_type(SYMBOL, car(p));
  return boolean(e->lookup(*car(p)->symbol) != NULL);
}
Ejemplo n.º 2
0
cons_t* proc_env_has_parentp(cons_t* p, environment_t*)
{
  assert_length(p, 1);
  assert_type(ENVIRONMENT, car(p));
  return boolean(car(p)->environment->outer != NULL);
}
Ejemplo n.º 3
0
cons_t* proc_oddp(cons_t* p, environment_t*)
{
  assert_length(p, 1);
  assert_type(INTEGER, car(p));
  return boolean(car(p)->number.integer & 1);
}
Ejemplo n.º 4
0
cons_t* proc_closure_source(cons_t* p, environment_t*)
{
  assert_type(CLOSURE, car(p));
  closure_t *c = car(p)->closure;
  return cons(symbol("lambda"), list(c->args, c->body));
}
Ejemplo n.º 5
0
cons_t* proc_circularp(cons_t* p, environment_t*)
{
  assert_length(p, 1);
  assert_type(PAIR, car(p));
  return boolean(circularp(car(p)));
}
Ejemplo n.º 6
0
/*
 * Parse (define-library ...) form into given environment, with the
 * following format:
 *
 * (define-library <library name>
 *   <library declaration> ...)
 *
 * where <library declaration> is any of:
 *
 * - (export <export spec> ...)
 * - (import <import set> ...)
 * - (begin <command or definition> ...)
 * - (include <filename1> <filename2> ...)
 * - (include-ci <filename1> <filename2> ...)
 * - (cond-expand <cond-expand clause> ...)
 */
static library_t* define_library(cons_t* p, const char* file)
{
  library_t *r = new library_t();
  cons_t *exports = nil();

  // find current dir for resolving include and include-ci
  std::string curdir = sdirname(file);

  // define-library
  if ( symbol_name(caar(p)) != "define-library" )
    raise(syntax_error(format(
      "Imported file does not begin with define-library: %s", file)));

  // <library name>
  r->name = verify_library_name(cadar(p));

  // A <library declaration> can be either ...
  for ( p = cdr(cdar(p)); !nullp(p); p = cdr(p) ) {
    cons_t *id   = caar(p);
    cons_t *body = cdar(p);
    std::string s = symbol_name(id);

    if ( s == "export" ) {
      exports = body;
      continue;
    }

    if ( s == "import" ) {
      // TODO: Make sure that proc_import does not override
      //       r->internals->outer
      proc_import(body, r->internals);
      continue;
    }

    if ( s == "begin" ) {
      eval(car(p), r->internals);
      continue;
    }

    if ( s == "include" ) {
      eval(splice(list(symbol("begin")),
                  include(body, r->internals, curdir.c_str())),
           r->internals);
      continue;
    }

    if ( s == "include-ci" ) {
      eval(splice(list(symbol("begin")),
                  include_ci(body, r->internals, curdir.c_str())),
           r->internals);
      continue;
    }

    if ( s == "cond-expand" ) {
      eval(cond_expand(body, r->internals), r->internals);
      continue;
    }
  }

  // copy exports into exports-environemnt
  for ( p = exports; !nullp(p); p = cdr(p) ) {

    // handle renaming
    if ( listp(car(p)) && length(car(p))==3 &&
         symbol_name(caar(p))=="rename" )
    {
      assert_type(SYMBOL, cadar(p));
      assert_type(SYMBOL, caddar(p));

      std::string internal_name = symbol_name(cadar(p));
      std::string external_name = symbol_name(caddar(p));

      r->exports->define(external_name,
                         r->internals->lookup(internal_name));
    } else if ( listp(car(p)) )
      raise(syntax_error("(export <spec> ...) only allows (rename x y)"));
    else if ( type_of(car(p)) == SYMBOL ) {
      r->exports->define(symbol_name(car(p)),
                         r->internals->lookup(symbol_name(car(p))));
    } else
      raise(syntax_error(
        "(export <spec> ...) requires <spec> to be "
        "either an identifier or a pair of them."));
  }

  return r;
}
Ejemplo n.º 7
0
/*
 * (call <tag_ffi_cif>
 *       <closure w/C function pointer>
 *       <rvalue size in bytes>
 * )
 */
cons_t* proc_ffi_call(cons_t* p, environment_t*)
{
  assert_length(p, 2, 4);
  assert_pointer(tag_ffi_cif, car(p));
  assert_type(CLOSURE, cadr(p));
  assert_type(INTEGER, caddr(p));

  /*
   * libffi description of function.
   */

  ffi_cif *cif = static_cast<ffi_cif*>(car(p)->pointer->value);

  /*
   * Pointer to function to call.
   */

  if ( cadr(p)->closure->function == NULL )
    raise(runtime_exception(
      "Can only call foreign C functions; not Scheme procedures"));

  void (*funptr)() =
    reinterpret_cast<void(*)()>(cadr(p)->closure->function);

  /*
   * Size of return value.
   */
  integer_t size = 0;

  if ( length(p)>2 )
    size = caddr(p)->number.integer;

  if ( size < 0 )
    raise(runtime_exception(format(
      "Cannot allocate a negative number of bytes: %d", size)));

  /*
   * Allocate enough memory necessary to hold return data.
   */
  value_t *retval = new value_t(size);

  /*
   * Function arguments (currently unsupported).
   */
  void **funargs = NULL;

  if ( !nullp(cadddr(p)) ) {
    cons_t *args = cadddr(p);

    if ( length(args) != cif->nargs )
      raise(runtime_exception(format(
        "Foreign function expects %d arguments",
        cif->nargs)));

    funargs = static_cast<void**>(malloc(sizeof(void*)*(cif->nargs+1)));

    size_t n=0;
    for ( cons_t *a = args; !nullp(a); a = cdr(a), ++n ) {
      funargs[n] = make_arg(cif->arg_types[n], car(a));
    }

    funargs[cif->nargs] = NULL; // TODO: is this necessary?
  }

  /*
   * TODO: Destroy allocated funargs data after ffi_call, unless those are
   * pointer values used to store returned data.
   */

  ffi_call(cif, funptr, &retval->data, funargs);
  return pointer(tag_ffi_retval, retval);
}