Example #1
0
// (job 'lst . prg) -> any
any doJob(any ex) {
   any x = cdr(ex);
   any y = EVAL(car(x));
   cell c1;
   struct {  // bindFrame
      struct bindFrame *link;
      int i, cnt;
      struct {any sym; any val;} bnd[length(y)];
   } f;

   Push(c1,y);
   f.link = Env.bind,  Env.bind = (bindFrame*)&f;
   f.i = f.cnt = 0;
   while (isCell(y)) {
      f.bnd[f.cnt].sym = caar(y);
      f.bnd[f.cnt].val = val(caar(y));
      val(caar(y)) = cdar(y);
      ++f.cnt,  y = cdr(y);
   }
   x = prog(cdr(x));
   for (f.cnt = 0, y = Pop(c1);  isCell(y);  ++f.cnt, y = cdr(y)) {
      cdar(y) = val(caar(y));
      val(caar(y)) = f.bnd[f.cnt].val;
   }
   Env.bind = f.link;
   return x;
}
Example #2
0
void lock_lease_exclusive(Worker *worker, Lease *lease) {
    List *cleanup = worker->cleanup;
    List *prev = NULL;

    worker_attempt_to_acquire(worker, lease->wait_for_update);

    /* clean out any regular locks that we hold on this lease */
    while (lease->inflight > 0 && !null(cleanup)) {
        if (caar(cleanup) == (void *) LOCK_LEASE && cdar(cleanup) == lease) {
            lease->inflight--;
            if (null(prev))
                worker->cleanup = cdr(cleanup);
            else
                setcdr(prev, cdr(cleanup));
        } else {
            prev = cleanup;
        }
        cleanup = cdr(cleanup);
    }

    /* prevent any new transactions starting and signal our interest */
    lease->wait_for_update = worker;

    /* want for existing inflight transactions to finish */
    if (lease->inflight > 0)
        longjmp(worker->jmp, WORKER_BLOCKED);

    /* only add to the cleanup list once we've succeeded */
    worker_cleanup_add(worker, LOCK_LEASE_EXCLUSIVE, lease);
}
Example #3
0
static void putSrc(any s, any k) {
   if (!isNil(val(Dbg)) && !isExt(s) && InFile && InFile->name) {
      any x, y;
      cell c1;

      Push(c1, boxCnt(InFile->src));
      data(c1) = cons(data(c1), mkStr(InFile->name));
      x = get(s, Dbg);
      if (!k) {
         if (isNil(x))
            put(s, Dbg, cons(data(c1), Nil));
         else
            car(x) = data(c1);
      }
      else if (isNil(x))
         put(s, Dbg, cons(Nil, cons(data(c1), Nil)));
      else {
         for (y = cdr(x); isCell(y); y = cdr(y))
            if (caar(y) == k) {
               cdar(y) = data(c1);
               drop(c1);
               return;
            }
         cdr(x) = cons(cons(k, data(c1)), cdr(x));
      }
      drop(c1);
   }
}
Example #4
0
/*
 * Transform
 *
 * (case-lambda
 *   ((<form1> <body1>)
 *    (<form2> <body2>)
 *    ...)
 *
 * to
 *
 * (lambda args
 *   (cond
 *     (((if (variadic? <form1>) >= =) (length args) <form1-min-args>)
 *      (apply (lambda (<form1>) <body1>) args))
 *     ...))
 */
cons_t* proc_case_lambda(cons_t* p, environment_t* e)
{
  cons_t *cond_cases = list();

  cons_t *cases = p;

  for ( cons_t* c = cases; !nullp(c); c = cdr(c) ) {
    cons_t *formals = caar(c);
    cons_t *body = cdar(c);

    // ((if (variadic? <form1>) >= =) argc <form1-min-args>)
    cons_t* cond_if =
      cons(symbol(variadicp(formals)? ">=" : "="),
      cons(cons(symbol("length"), cons(symbol("args"))),
      cons(integer(min_args(formals)))));

    // (apply (lambda (<form1>) <body1>) args)
    cons_t *cond_then =
      cons(symbol("apply"),
      cons(cons(symbol("lambda"),
           cons(formals, body)),
      cons(symbol("args"))));

    cond_cases = append(cond_cases, list(list(cond_if, cond_then)));
  }

  cond_cases = splice(cons(symbol("cond")), cond_cases);

  return make_closure(symbol("args"), cons(cond_cases), e);
}
Example #5
0
File: prim.c Project: l0stman/loot
/* Return the second element of a pair */
static exp_t *
prim_cdr(exp_t *args)
{
        chkargs("cdr", args, 1);
        if (!ispair(car(args)))
                everr("cdr: the argument isn't a pair", car(args));
        return cdar(args);
}
Example #6
0
// (nond ('any1 . prg1) ('any2 . prg2) ..) -> any
any doNond(any x) {
   any a;

   while (isCell(x = cdr(x))) {
      if (isNil(a = EVAL(caar(x))))
         return prog(cdar(x));
      val(At) = a;
   }
   return Nil;
}
Example #7
0
// (cond ('any1 . prg1) ('any2 . prg2) ..) -> any
any doCond(any x) {
   any a;

   while (isCell(x = cdr(x))) {
      if (!isNil(a = EVAL(caar(x)))) {
         val(At) = a;
         return prog(cdar(x));
      }
   }
   return Nil;
}
Example #8
0
// (dm sym . fun|cls2) -> sym
// (dm (sym . cls) . fun|cls2) -> sym
// (dm (sym sym2 [. cls]) . fun|cls2) -> sym
any doDm(any ex) {
   any x, y, msg, cls;

   x = cdr(ex);
   if (!isCell(car(x)))
      msg = car(x),  cls = val(Class);
   else {
      msg = caar(x);
      cls = !isCell(cdar(x))? cdar(x) :
         get(isNil(cddar(x))? val(Class) : cddar(x), cadar(x));
   }
   if (msg != T)
      redefine(ex, msg, val(Meth));
   if (isSym(cdr(x))) {
      y = val(cdr(x));
      for (;;) {
         if (!isCell(y) || !isCell(car(y)))
            err(ex, msg, "Bad message");
         if (caar(y) == msg) {
            x = car(y);
            break;
         }
         y = cdr(y);
      }
   }
   for (y = val(cls);  isCell(y) && isCell(car(y));  y = cdr(y))
      if (caar(y) == msg) {
         if (!equal(cdr(x), cdar(y)))
            redefMsg(msg, cls);
         cdar(y) = cdr(x);
         putSrc(cls, msg);
         return msg;
      }
   if (!isCell(car(x)))
      val(cls) = cons(x, val(cls));
   else
      val(cls) = cons(cons(msg, cdr(x)), val(cls));
   putSrc(cls, msg);
   return msg;
}
Example #9
0
END_TEST

START_TEST (test_pair_ops)
{
    make_singletons();
    object *o1 = cons (make_string ("testing"), make_boolean (true));
    object *o2 = cons (make_character ('a'), make_fixnum (5));
    object *o3 = cons (o1, o2);
    ck_assert (o3->type == PAIR);
    ck_assert (car(o3)->type == PAIR);
    ck_assert_str_eq (caar(o3)->data.string.value, "testing");
    ck_assert ((cdar(o3))->type == BOOLEAN);
}
Example #10
0
File: arc.c Project: wsxiaoys/carc
/*-------Environment-------*/
pointer environment_make2(VM, pointer rib, pointer env) {
  pointer t;
  save(vm, rib);
  save(vm, env);
  t = table_alloc(vm);
  
  while (!AR_ISNIL(rib)) {
    table_insert(vm, t, caar(rib), cdar(rib));
    rib = cdr(rib);
  }
  unsave(vm, 2);
  
  return tagged_alloc(vm, vm->s_environment, cons(t,AR_ISNIL(env)?vm->nil:rep(env)));
}
Example #11
0
// (bind 'sym|lst . prg) -> any
any doBind(any ex) {
   any x, y;

   x = cdr(ex);
   if (isNum(y = EVAL(car(x))))
      argError(ex, y);
   if (isNil(y))
      return prog(cdr(x));
   if (isSym(y)) {
      bindFrame f;

      Bind(y,f);
      x = prog(cdr(x));
      Unbind(f);
      return x;
   }
   {
      struct {  // bindFrame
         struct bindFrame *link;
         int i, cnt;
         struct {any sym; any val;} bnd[length(y)];
      } f;

      f.link = Env.bind,  Env.bind = (bindFrame*)&f;
      f.i = f.cnt = 0;
      do {
         if (isNum(car(y)))
            argError(ex, car(y));
         if (isSym(car(y))) {
            f.bnd[f.cnt].sym = car(y);
            f.bnd[f.cnt].val = val(car(y));
         }
         else {
            f.bnd[f.cnt].sym = caar(y);
            f.bnd[f.cnt].val = val(caar(y));
            val(caar(y)) = cdar(y);
         }
         ++f.cnt;
      } while (isCell(y = cdr(y)));
      x = prog(cdr(x));
      while (--f.cnt >= 0)
         val(f.bnd[f.cnt].sym) = f.bnd[f.cnt].val;
      Env.bind = f.link;
      return x;
   }
}
Example #12
0
void worker_cleanup(Worker *worker) {
    while (!null(worker->cleanup)) {
        enum lock_types type = (enum lock_types) caar(worker->cleanup);
        void *obj = cdar(worker->cleanup);
        worker->cleanup = cdr(worker->cleanup);

        switch (type) {
        case LOCK_DIRECTORY:
            cleanup(struct objectdir);
            break;
        case LOCK_OPENFILE:
            cleanup(struct openfile);
            break;
        case LOCK_FID:
            cleanup(Fid);
            break;
        case LOCK_WALK:
            cleanup(Walk);
            break;
        case LOCK_CLAIM:
            cleanup(Claim);
            claim_release((Claim *) obj);
            break;
        case LOCK_LEASE:
            unlock_lease_cleanup(worker, (Lease *) obj);
            break;
        case LOCK_LEASE_EXCLUSIVE:
            ((Lease *) obj)->wait_for_update = NULL;
            break;
        case LOCK_REMOTE_FID:
            if (vector_get(fid_remote_vector, (u32) obj) ==
                    (void *) 0xdeadbeef)
            {
                fid_release_remote((u32) obj);
            }
            break;
        case LOCK_RAW:
            raw_delete((u8 *) obj);
            break;
        default:
            assert(0);
        }
    }
}
Example #13
0
NODE *lsetwrite(NODE *arg) {
    FILE *tmp;
    NODE *margs;

    if (writestream == NULL) {
	/* Any setwrite finishes earlier write to string */
	*print_stringptr = '\0';
	writestream = stdout;
	if (find_file(writer_name, FALSE) == NULL) {
	    /* pre-5.4 compatibility mode, implicitly close string */
	    margs = cons(car(writer_name),
			 cons(make_strnode(write_buf, NULL, strlen(write_buf),
					   STRING, strnzcpy),
			      NIL));
	    lmake(margs);
	    free(write_buf);
	}
	writer_name = NIL;
    }
    if (car(arg) == NIL) {
	writestream = stdout;
	writer_name = NIL;
    } else if (is_list(car(arg))) { /* print to string */
	FIXNUM i = int_arg(cdar(arg));
	if ((tmp = find_file(car(arg), FALSE)) != NULL) {
	    writestream = NULL;
	    writer_name = car(arg);
	    print_stringptr = (char *)tmp + strlen((char *)tmp);
	    print_stringlen = i - strlen((char *)tmp);
	} else if (NOT_THROWING && i > 0 && cddr(car(arg)) == NIL) {
	    writestream = NULL;
	    writer_name = copy_list(car(arg));
	    print_stringptr = write_buf = (char *)malloc(i);
	    print_stringlen = i;
	} else err_logo(BAD_DATA_UNREC, car(arg));
    } else if ((tmp = find_file(car(arg), FALSE)) != NULL) {
	writestream = tmp;
	writer_name = car(arg);
    } else
	err_logo(NOT_OPEN_ERROR, car(arg));
    return(UNBOUND);
}
Example #14
0
void worker_cleanup_remove(Worker *worker, enum lock_types type, void *object) {
    List *prev = NULL;
    List *cur = worker->cleanup;

    while (!null(cur)) {
        if (caar(cur) == (void *) type && cdar(cur) == object) {
            if (prev == NULL)
                worker->cleanup = cdr(cur);
            else
                setcdr(prev, cdr(cur));

            return;
        }

        prev = cur;
        cur = cdr(cur);
    }

    /* fail if we didn't find the requested entry */
    assert(0);
}
Example #15
0
static pointer apply(pointer expr)
{
        pointer tmp_op, result, farg, expanded;
        int flags;
        tmp_op = eval(sexpr_get_op(expr));

        switch (op_type(tmp_op)) {
        case T_BUILT_IN_REGULAR_PROC:
                save_continuation(cont_env | cont_arg | cont_op);
                op = tmp_op;
                arg = eval_arg_list(sexpr_get_arg(expr));
                result = (op_get_bltin_proc_code(op))();
                restore_continuation(cont_env | cont_arg | cont_op);
                break;
        case T_BUILT_IN_SPECIAL_PROC:
                if (strcmp("set!", op_get_bltin_proc_name(tmp_op)) == 0 || 
                    strcmp("defmacro", op_get_bltin_proc_name(tmp_op)) == 0)
                        flags = cont_arg | cont_op;
                else
                        flags = cont_env | cont_arg | cont_op;
                save_continuation(flags);
                op = tmp_op;
                arg = sexpr_get_arg(expr);
                result = (op_get_bltin_proc_code(op))();
                restore_continuation(flags);
                break;
        case T_EXTEND_PROC:
                save_continuation(cont_env | cont_arg | cont_op);
                op = tmp_op;
                arg = eval_arg_list(sexpr_get_arg(expr));
                env = op_get_ext_proc_env(op);
                farg = op_get_ext_proc_farg(op);
                while (farg != NULL) {
                        if (ispair(car(farg))) {
                                add_new_binding(car(cdar(farg)), arg);
                                break;
                        }
                        add_new_binding(car(farg), car(arg));
                        farg = cdr(farg);
                        arg = cdr(arg);
                }
                result = eval(op_get_ext_proc_body(op));
                restore_continuation(cont_env | cont_arg | cont_op);
                break;
        case T_MACRO:
                save_continuation(cont_env | cont_arg | cont_op);
                op = tmp_op;
                arg = sexpr_get_arg(expr);

                env = op_get_macro_env(op);
                farg = op_get_macro_farg(op);
                while (farg != NULL) {
                        if (ispair(car(farg))) {
                                add_new_binding(car(cdar(farg)), arg);
                                break;
                        }
                        add_new_binding(car(farg), car(arg));
                        farg = cdr(farg);
                        arg = cdr(arg);
                }
                expanded = eval(op_get_macro_body(op));
                restore_continuation(cont_env | cont_arg | cont_op);
                result = eval(expanded);

                break;
        }


        return result;
}
Example #16
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;
}
Example #17
0
// (for sym 'num ['any | (NIL 'any . prg) | (T 'any . prg) ..]) -> any
// (for sym|(sym2 . sym) 'lst ['any | (NIL 'any . prg) | (T 'any . prg) ..]) -> any
// (for (sym|(sym2 . sym) 'any1 'any2 [. prg]) ['any | (NIL 'any . prg) | (T 'any . prg) ..]) -> any
any doFor(any x) {
   any y, body, cond, a;
   cell c1;
   struct {  // bindFrame
      struct bindFrame *link;
      int i, cnt;
      struct {any sym; any val;} bnd[2];
   } f;

   f.link = Env.bind,  Env.bind = (bindFrame*)&f;
   f.i = 0;
   if (!isCell(y = car(x = cdr(x))) || !isCell(cdr(y))) {
      if (!isCell(y)) {
         f.cnt = 1;
         f.bnd[0].sym = y;
         f.bnd[0].val = val(y);
      }
      else {
         f.cnt = 2;
         f.bnd[0].sym = cdr(y);
         f.bnd[0].val = val(cdr(y));
         f.bnd[1].sym = car(y);
         f.bnd[1].val = val(car(y));
         val(f.bnd[1].sym) = Zero;
      }
      y = Nil;
      x = cdr(x),  Push(c1, EVAL(car(x)));
      if (isNum(data(c1)))
         val(f.bnd[0].sym) = Zero;
      body = x = cdr(x);
      for (;;) {
         if (isNum(data(c1))) {
            val(f.bnd[0].sym) = bigCopy(val(f.bnd[0].sym));
            digAdd(val(f.bnd[0].sym), 2);
            if (bigCompare(val(f.bnd[0].sym), data(c1)) > 0)
               break;
         }
         else {
            if (!isCell(data(c1)))
               break;
            val(f.bnd[0].sym) = car(data(c1));
            if (!isCell(data(c1) = cdr(data(c1))))
               data(c1) = Nil;
         }
         if (f.cnt == 2) {
            val(f.bnd[1].sym) = bigCopy(val(f.bnd[1].sym));
            digAdd(val(f.bnd[1].sym), 2);
         }
         do {
            if (!isNum(y = car(x))) {
               if (isSym(y))
                  y = val(y);
               else if (isNil(car(y))) {
                  y = cdr(y);
                  if (isNil(a = EVAL(car(y)))) {
                     y = prog(cdr(y));
                     goto for1;
                  }
                  val(At) = a;
                  y = Nil;
               }
               else if (car(y) == T) {
                  y = cdr(y);
                  if (!isNil(a = EVAL(car(y)))) {
                     val(At) = a;
                     y = prog(cdr(y));
                     goto for1;
                  }
                  y = Nil;
               }
               else
                  y = evList(y);
            }
         } while (isCell(x = cdr(x)));
         x = body;
      }
   for1:
      drop(c1);
      if (f.cnt == 2)
         val(f.bnd[1].sym) = f.bnd[1].val;
      val(f.bnd[0].sym) = f.bnd[0].val;
      Env.bind = f.link;
      return y;
   }
   if (!isCell(car(y))) {
      f.cnt = 1;
      f.bnd[0].sym = car(y);
      f.bnd[0].val = val(car(y));
   }
   else {
      f.cnt = 2;
      f.bnd[0].sym = cdar(y);
      f.bnd[0].val = val(cdar(y));
      f.bnd[1].sym = caar(y);
      f.bnd[1].val = val(caar(y));
      val(f.bnd[1].sym) = Zero;
   }
   y = cdr(y);
   val(f.bnd[0].sym) = EVAL(car(y));
   y = cdr(y),  cond = car(y),  y = cdr(y);
   Push(c1,Nil);
   body = x = cdr(x);
   while (!isNil(a = EVAL(cond))) {
      val(At) = a;
      if (f.cnt == 2) {
         val(f.bnd[1].sym) = bigCopy(val(f.bnd[1].sym));
         digAdd(val(f.bnd[1].sym), 2);
      }
      do {
         if (!isNum(data(c1) = car(x))) {
            if (isSym(data(c1)))
               data(c1) = val(data(c1));
            else if (isNil(car(data(c1)))) {
               data(c1) = cdr(data(c1));
               if (isNil(a = EVAL(car(data(c1))))) {
                  data(c1) = prog(cdr(data(c1)));
                  goto for2;
               }
               val(At) = a;
               data(c1) = Nil;
            }
            else if (car(data(c1)) == T) {
               data(c1) = cdr(data(c1));
               if (!isNil(a = EVAL(car(data(c1))))) {
                  val(At) = a;
                  data(c1) = prog(cdr(data(c1)));
                  goto for2;
               }
               data(c1) = Nil;
            }
            else
               data(c1) = evList(data(c1));
         }
      } while (isCell(x = cdr(x)));
      if (isCell(y))
         val(f.bnd[0].sym) = prog(y);
      x = body;
   }
for2:
   if (f.cnt == 2)
      val(f.bnd[1].sym) = f.bnd[1].val;
   val(f.bnd[0].sym) = f.bnd[0].val;
   Env.bind = f.link;
   return Pop(c1);
}
Example #18
0
void load_library_index()
{
  if ( library_map != NULL )
    return;

  std::string filename = library_file(library_index_file);
  environment_t *env = null_environment();
  program_t *p = parse(slurp(open_file(filename)), env);

  cons_t *index = p->root;

  if ( !pairp(index) || !symbolp(caar(index)) )
    invalid_index_format(filename + ": no list with symbols");

  for ( ; !nullp(index); index = cdr(index) ) {
    if ( symbol_name(caar(index)) == "define-library-index" ) {
      if ( library_map != NULL )
        invalid_index_format(filename + ": only one define-library-index allowed");

      if ( !listp(cdar(index)) ) {
        invalid_index_format(filename
          + ": define-library-index is not a list");
      }

      size_t len = length(cdar(index));
      library_map = (library_map_t*) malloc((1+len)*sizeof(library_map_t));

      size_t i = 0;
      for ( cons_t *lib = cdar(index); !nullp(lib); lib = cdr(lib), ++i ) {
        cons_t *name = caar(lib);
        cons_t *file = cadar(lib);

        if ( !listp(name) || !stringp(file) )
          invalid_index_format(filename + ": not list/string pair");

        library_map[i].library_name = strdup(sprint(name).c_str());
        library_map[i].source_file = strdup(file->string);
      }

      // important to signal end of list:
      library_map[i].library_name = NULL;
      library_map[i].source_file = NULL;

      continue;
    } else if ( symbol_name(caar(index)) == "define-repl-imports" ) {
      if ( repl_libraries != NULL )
        invalid_index_format(filename + ": only one define-repl-imports allowed");

      if ( !listp(cdar(index)) ) {
        invalid_index_format(filename
          + ": define-repl-imports is not a list");
      }

      size_t len = length(cdar(index));
      repl_libraries = (const char**) malloc((1+len)*sizeof(char*));

      const char **s = repl_libraries;
      for ( cons_t *lib = cdar(index); !nullp(lib); lib = cdr(lib), ++s ) {
        cons_t *name = car(lib);
        *s = strdup(sprint(name).c_str());
      }
      *s = NULL;
      continue;
    } else
      invalid_index_format(filename + ": unknown label "
        + sprint(caar(index)));
  }
}
Example #19
0
object *cdr_proc(object *arguments) {
    return cdar(arguments);
}
Example #20
0
File: prim.c Project: mdbarr/vcsi
VCSI_OBJECT cddar(VCSI_CONTEXT vc,
		  VCSI_OBJECT x) {
  return cdr(vc,cdar(vc,x));
}