Beispiel #1
0
static obj_t *
lang_begin(obj_t **frame, obj_t **tailp)
{
    obj_t *expr = *frame_ref(frame, 0);
    *tailp = tail_token;
    obj_t *iter;

    for (iter = expr; pairp(iter); iter = pair_cdr(iter)) {
        // Eval each expression except the last.
        if (!pairp(pair_cdr(iter))) {
            break;
        }
        obj_t **expr_frame = frame_extend(frame, 1,
                FR_SAVE_PREV | FR_CONTINUE_ENV);
        *frame_ref(expr_frame, 0) = pair_car(iter);
        eval_frame(expr_frame);
    }
    if (nullp(iter)) {
        // Empty (begin) expression
        return unspec_wrap();
    }
    else if (!nullp(pair_cdr(iter))) {
        fatal_error("begin -- not a well-formed list", frame);
    }
    return pair_car(iter);
}
Beispiel #2
0
static void assert2_pair_addresses_mapped( msgc_context_t *context, word w )
{
    { 
#ifndef NDEBUG2
      if (isptr(pair_cdr(w)) &&
          ! gc_is_address_mapped( context->gc, 
                                  ptrof(pair_cdr(w)), FALSE )) {
        gc_is_address_mapped( context->gc, ptrof(pair_cdr(w)), TRUE );
        consolemsg("unmapped address, pair 0x%08x in gen %d, cdr = 0x%08x",
                   w, gen_of(w), pair_cdr(w));
        consolemsg("(gno count: %d)", context->gc->gno_count);
        assert2(0);
      }
      if (isptr(pair_car(w)) &&
          ! gc_is_address_mapped( context->gc, 
                                  ptrof(pair_car(w)), FALSE )) {
        gc_is_address_mapped( context->gc, ptrof(pair_car(w)), TRUE );
        consolemsg("unmapped address, pair 0x%08x in gen %d, car = 0x%08x",
                   w, gen_of(w), pair_car(w));
        consolemsg("(gno count: %d)", context->gc->gno_count);
        assert2(0);
      }
#endif
    }
}
Beispiel #3
0
    void print_env(obj_t *env)
    {
	if (!is_pair(env)) {
	    printf_unchecked("%O\n", env);
	    return;
	}
	const char *sep = "";
	while (env) {
	    printf("%s", sep);
	    if (pair_cdr(env)) {
		obj_t *f = pair_car(env);
		printf("[");
		sep = "";
		while (f) {
		    obj_t *binding = pair_car(f);
		    printf_unchecked("%s%O: %O", sep,
						 binding_name(binding),
						 binding_value(binding));
		    f = pair_cdr(f);
		    sep = ", ";
		}
		printf("]");
	    } else
		printf("[builtins]\n");
	    env = pair_cdr(env);
	    sep = " -> ";
	}
    }
Beispiel #4
0
static obj_t *
lang_define(obj_t **frame, obj_t **tailp)
{
    obj_t *expr = *frame_ref(frame, 0);
    obj_t *first, *name, *result;
    *tailp = NULL;
    first = pair_car(expr);
    if (symbolp(first)) {
        // Binding an expression
        // XXX: check for expr length?
        obj_t *to_eval = pair_car(pair_cdr(expr));
        // Get the value of the expression before binding.
        obj_t **expr_frame = frame_extend(
                frame, 1, FR_CONTINUE_ENV | FR_SAVE_PREV);
        *frame_ref(expr_frame, 0) = to_eval;
        result = eval_frame(expr_frame);
        name = first;
    }
    else if (pairp(first)) {
        // short hand for (define name (lambda ...))
        // x: the formals, v: the body
        obj_t *formals, *body;
        name = pair_car(first);
        formals = pair_cdr(first);
        body = pair_cdr(expr);
        result = closure_wrap(frame, frame_env(frame), formals, body);
    }
    else {
        fatal_error("define -- first argument is neither a "
                    "symbol nor a pair", frame);
    }
    environ_def(frame, frame_env(frame), name, result);
    return unspec_wrap();
}
Beispiel #5
0
void print_object(pointer P, symbol_table* table)
{
    FILE* out = stdout;
    if(P == NIL)
    {
        fputs("NIL", out);
        return;
    }

    switch(get_type_id(P))
    {
    case DT_Pair:
        if(is_type(pair_car(P), DT_Pair))
        {
            putc('(', out);
            print_object(pair_car(P), table);
            putc(')', out);
        }
        else
            print_object(pair_car(P), table);

        putc(' ', out);
        if(pair_cdr(P) != NIL)
        {
            if(!is_type(pair_cdr(P), DT_Pair))
                fputs(". ", out);

            print_object(pair_cdr(P), table);
        }
        break;
    case DT_Symbol:
        fputs(string_from_symbol(table, *get_symbol(P)), out);
        break;
    case DT_Int:
        fprintf(out, "%d", get_int(P));
        break;
    case DT_Real:
        fprintf(out, "%f", get_real(P));
        break;
    case DT_String:
        fputs(get_string(P), out);
        break;
    case DT_Char:
        putc(get_char(P), out);
        break;
    case DT_TypeInfo:
        print_typeinfo(P, table, out);
        break;
    case DT_Invalid:
        fputs("#INVALID#", out);
        break;
    case DT_Any:
        fputs("#ANY#", out);
        break;
    }
}
Beispiel #6
0
void destroy_list(pointer P)
{
    if(is_type(P, DT_Pair))
    {
        if(pair_car(P) != NIL)
            destroy_list(pair_car(P));
        if(pair_cdr(P) != NIL)
            destroy_list(pair_cdr(P));
    }
    ploy_free(P);
}
Beispiel #7
0
obj_t make_vector_from_list(obj_t list)
{
    obj_t p = list;
    size_t i, size = 0;
    while (!is_null(p)) {
	size++;
	p = pair_cdr(p);
    }
    obj_t vec = make_vector_uninitialized(size);
    for (i = 0, p = list; i < size; i++) {
	vector_set(vec, i, pair_car(p));
	p = pair_cdr(p);
    }
    return vec;
}
Beispiel #8
0
    static const wchar_t *block_name(C_procedure_t *block, obj_t *env)
    {
	if (block == b_eval)
	    return L"b_eval";
	if (block == b_accum_operator)
	    return L"b_accum_operator";
	if (block == b_accum_arg)
	    return L"b_accum_arg";
	if (block == b_eval_sequence)
	    return L"b_eval_sequence";
	if (block == NULL)
	    return L"NULL";
	/* XXX Move this code into env.c. */
	if (!env)
	    env = library_env(r6rs_library());
	if (is_pair(env)) {
	    obj_t *frame = pair_car(env);
	    while (frame) {
		obj_t *binding = pair_car(frame);
		obj_t *value = binding_value(binding);
		if (is_procedure(value) && procedure_is_C(value)) {
		    C_procedure_t *body;
		    body = (C_procedure_t *)procedure_body(value);
		    if (body == block) {
			obj_t *name = symbol_name(binding_name(binding));
			return string_value(name);
		    }
		}
		frame = pair_cdr(frame);
	    }
	}
	return L"<some-proc>";
    }
Beispiel #9
0
static obj_t *
lang_if(obj_t **frame, obj_t **tailp)
{
    obj_t *expr = *frame_ref(frame, 0);
    obj_t *pred, *todo, *otherwise;
    *tailp = tail_token;

    pred = pair_car(expr);
    todo = pair_cadr(expr);
    otherwise = pair_cddr(expr);
    if (nullp(otherwise)) {
        otherwise = unspec_wrap();
    }
    else if (!nullp(pair_cdr(otherwise))) {
        fatal_error("if -- too many arguments", frame);
    }
    else {
        otherwise = pair_car(otherwise);
    }

    {
        // start to evaluate the predicate.
        obj_t **pred_frame = frame_extend(
                frame, 1, FR_CONTINUE_ENV | FR_SAVE_PREV);
        *frame_ref(pred_frame, 0) = pred;
        pred = eval_frame(pred_frame);
    }
    if (to_boolean(pred)) {
        return todo;
    }
    else {
        return otherwise;
    }
}
Beispiel #10
0
obj_t *env_lookup(env_t *env, obj_t *var)
{
    /*
     * for frame in env:
     *     for binding in frame:
     *         if binding.name == var:
     *             return binding
     * assert False, 'unbound variable'
     */

    assert(is_symbol(var));
#if ENV_TRACE
    printf_unchecked("lookup(%ls, %O)\n", string_value(symbol_name(var)), env);
#endif
    while (!is_null(env)) {
	obj_t *frame = pair_car(env);
#if ENV_TRACE
	if (pair_cdr(env)) {
	    printf("   FRAME");
	    obj_t *p = frame;
	    while (!is_null(p)) {
		printf_unchecked(" %O: %O", binding_name(pair_car(p)),
				            binding_value(pair_car(p)));
		p = pair_cdr(p);
	    }
	    printf("\n");
	} else {
	    printf("   FRAME [builtins]\n");
	}
#endif
	while (!is_null(frame)) {
	    obj_t *binding = pair_car(frame);
	    assert(is_binding(binding));
	    if (binding_name(binding) == var) {
#if ENV_TRACE
		printf("   found\n\n");
#endif
		return binding;
	    }
	    frame = pair_cdr(frame);
	}
	env = pair_cdr(env);
    }
    fprintf(stderr, "unbound variable \"%ls\"\n",
	    string_value(symbol_name(var)));
    assert(false && "unbound variable");
}
Beispiel #11
0
static obj_t *
lang_lambda(obj_t **frame, obj_t **tailp)
{
    obj_t *expr = *frame_ref(frame, 0);
    *tailp = NULL;
    return closure_wrap(frame, frame_env(frame),
                        pair_car(expr), pair_cdr(expr));
}
Beispiel #12
0
/* Build a vector from a list.  XXX move this to obj_bytevec.c. */
static obj_t *build_bytevec(obj_t *list)
{
    PUSH_ROOT(list);
    obj_t *p = list;
    size_t i, size = 0;
    while (!is_null(p)) {
	size++;
	p = pair_cdr(p);
    }
    AUTO_ROOT(bvec, make_bytevector(size, 0));
    for (i = 0, p = list; i < size; i++) {
	bytevector_set(bvec, i, fixnum_value(pair_car(p)));
	p = pair_cdr(p);
    }
    POP_FUNCTION_ROOTS();
    return bvec;
}
Beispiel #13
0
/* Build a vector from a list.  XXX move this to obj_vector.c. */
static obj_t *build_vector(obj_t *list)
{
    PUSH_ROOT(list);
    obj_t *p = list;
    size_t i, size = 0;
    while (!is_null(p)) {
	size++;
	p = pair_cdr(p);
    }
    AUTO_ROOT(vec, make_vector(size, NIL));
    for (i = 0, p = list; i < size; i++) {
	vector_set(vec, i, pair_car(p));
	p = pair_cdr(p);
    }
    POP_FUNCTION_ROOTS();
    return vec;
}
Beispiel #14
0
int list_length(NodeType* param_lst) {
  int counter = 0;
  while (param_lst != NULL) {
    counter += 1;
    param_lst = pair_cdr(param_lst);
  }
  return counter;
}
Beispiel #15
0
static int slot_list_delq( obj owner, UINT_32 slot, obj key )
{
  obj p, prev = FALSE_OBJ;
  p = gvec_ref( owner, slot );
  
  while (PAIR_P( p )) {
    if (EQ( pair_car( p ), key )) {
      if (EQ( prev, FALSE_OBJ )) {
        gvec_set( owner, slot, pair_cdr( p ) );
      } else {
        pair_set_cdr( prev, pair_cdr( p ) );
      }
      return 1;
    }
    prev = p;
    p = pair_cdr( p );
  }
  return 0;
}
Beispiel #16
0
obj_t *join_envs(env_t *an_env, env_t *other_env)
{
    PUSH_ROOT(an_env);
    AUTO_ROOT(env, other_env);
    while (!is_null(an_env)) {
	other_env = make_pair(pair_car(an_env), other_env);
	an_env = pair_cdr(an_env);
    }
    POP_FUNCTION_ROOTS();
    return other_env;
}
Beispiel #17
0
static obj_t *
lang_quote(obj_t **frame, obj_t **tailp)
{
    obj_t *expr = *frame_ref(frame, 0);
    *tailp = NULL;

    if (nullp(expr) || !nullp(pair_cdr(expr))) {
        fatal_error("quote -- wrong number of argument", frame);
    }
    return pair_car(expr);
}
Beispiel #18
0
obj SOP_flush( obj port, int closeq )
{
  int len;
  obj dst, overflow;
  char *endptr;
  const char *src;
  
  len = fx2int( gvec_read( port, SOP_INDEX ) );
  overflow = gvec_read( port, SOP_OVERFLOW );
  
  while (!EQ( overflow, NIL_OBJ ))
    {
      len += SIZEOF_PTR( pair_car( overflow ) );
      overflow = pair_cdr( overflow );
    }
  
  dst = bvec_alloc( len+1, string_class );
  endptr = ((char *)string_text( dst )) + len;
  *endptr = 0;
  
  src = (const char *)PTR_TO_DATAPTR( gvec_read( port, SOP_BUFFER ) );
  len = fx2int( gvec_read( port, SOP_INDEX ) );
  overflow = gvec_read( port, SOP_OVERFLOW );
  
  while (1)
    {
      endptr -= len;
      memcpy( endptr, src, len );
      if (EQ( overflow, NIL_OBJ ))
	break;
      
      src = (const char *)PTR_TO_DATAPTR( pair_car( overflow ) );
      len = SIZEOF_PTR( pair_car( overflow ) );
      overflow = pair_cdr( overflow );
    }
  if (closeq) {
    gvec_write( port, SOP_BUFFER, FALSE_OBJ );
    gvec_write( port, SOP_OVERFLOW, FALSE_OBJ );
  }
  return dst;
}
Beispiel #19
0
static obj_t *
lang_lambda_syntax(obj_t **frame, obj_t **tailp)
{
    obj_t *expr = *frame_ref(frame, 0);
    obj_t *clos;
    *tailp = NULL;

    // LOL!!!
    clos = closure_wrap(frame, frame_env(frame),
                        pair_car(expr), pair_cdr(expr));
    SGC_ROOT1(frame, clos);
    return macro_wrap(frame, clos);
}
Beispiel #20
0
obj_t *apply_procedure(obj_t *proc, obj_t *args)
{
    PUSH_ROOT(proc);
    PUSH_ROOT(args);
    AUTO_ROOT(body, procedure_body(proc));
    if (procedure_is_C(proc)) {
	obj_t *env = F_ENV;
	if (!procedure_is_special_form(proc))
	    env = procedure_env(proc);
	GOTO_FRAME(make_short_frame, (C_procedure_t *)body, args, env);
    }
    AUTO_ROOT(new_env, make_env(procedure_env(proc)));
    AUTO_ROOT(formals, procedure_args(proc));
    AUTO_ROOT(actuals, args);
    while (!is_null(formals) || !is_null(actuals)) {
	if (is_null(formals)) {
	    printf_unchecked("calling %O\n", proc);
	    RAISE("too many args");
	}
	obj_t *formal, *actual;
	if (is_pair(formals)) {
	    if (is_null(actuals)) {
		printf_unchecked("proc=%O\n", proc);
		RAISE("not enough args");
	    }
	    formal  = pair_car(formals);
	    formals = pair_cdr(formals);
	    actual  = pair_car(actuals);
	    actuals = pair_cdr(actuals);
	} else {
	    formal  = formals;
	    actual  = actuals;
	    formals = actuals = NIL;
	}
	env_bind(new_env, formal, BT_LEXICAL, M_MUTABLE, actual);
    }
    GOTO(b_eval_sequence, body, new_env);
}
Beispiel #21
0
static obj_t *
lang_quasiquote(obj_t **frame, obj_t **tailp)
{
    obj_t *expr = *frame_ref(frame, 0);
    obj_t *content;
    *tailp = NULL;
    if (nullp(expr) || !nullp(pair_cdr(expr))) {
        fatal_error("quasiquote -- wrong number of argument", frame);
    }

    // Expand...
    content = pair_car(expr);
    return expand_quasiquote(frame, content, NULL);
}
Beispiel #22
0
void krelease_joiners( obj t )
{
  obj p;

  for (p=gvec_ref( t, THREAD_JOINS ); !NULL_P(p); p=pair_cdr(p))
   {
     obj jt = pair_car(p);
     assert( EQ( gvec_ref( jt, THREAD_BLOCKED_ON ), t ));
     UNBLOCK_THREAD( jt );

     store_resume_value( jt, REG0 );
     mark_thread_ready( jt );
   }
  gvec_write_non_ptr( t, THREAD_JOINS, NIL_OBJ );
}
Beispiel #23
0
unsigned expand_last( void )
{
obj list = ZERO;
unsigned N = 0;

  switch (arg_count_reg)
    {
    case 0:
      scheme_error( "expand_list: no arguments", 0 );
      break;

      STAGE(0,1);
      STAGE(1,2);
      STAGE(2,3);
      STAGE(3,4);
      STAGE(4,5);
      STAGE(5,6);
      STAGE(6,7);
      STAGE(7,8);
      STAGE(8,9);
      STAGE(9,10);
    default:
      /* this is for cases 11, 12, ..., since STAGE(9,10) is case 10
       * hence, N = (arg_count_reg - 1) is at least 10
       */
      N = arg_count_reg - 1;
      list = REG(N);
    filled_10:
      while (PAIR_P(list))
	{
	  REG(N) = pair_car( list );
	  list = pair_cdr( list );
	  N++;
	  if (N >= IMPL_ARG_LIMIT)
	    scheme_error( "expand_last: list of args too long at: ~#*@40s",
			  1, list );
	}
      break;
    }
    if (!NULL_P(list))
    {
	scheme_error( "expand_last: last arg not a proper list at ~a",
		      1,
		      list );
    }
    return N;
}
Beispiel #24
0
static obj_t find_symbol(obj_t name)
{
    obj_t p, sym;
    obj_t sym_name;

    CHECK(is_string(name), "must be string", name);
    for (p = all_symbols_list; !is_null(p); p = pair_cdr(p)) {
	assert(is_pair(p));
	sym = pair_car(p);
	assert(is_symbol(sym));
	sym_name = symbol_name(sym);
	assert(is_string(sym_name));
	if (strings_are_equal(sym_name, name))
	    return sym;
    }
    return EMPTY_LIST;
}
Beispiel #25
0
static const char *scheme_generator( char *text, int state )
{
static obj current;
static int len;
obj item;
const char *name;

    if (state == 0)	/* restarting generation */
    {
	current = the_completions;
	len = strlen( text );
    }
    
    while (!EQ( current, NIL_OBJ ))
    {
        assert( PAIR_P(current) );
	item = pair_car( current );
	current = pair_cdr( current );

	if (STRING_P(item))
	{
	    name = string_text(item);
	}
	else
	{
	    assert( SYMBOL_P(item) );
	    name = symbol_text(item);
	}

	if (strncmp( name, text, len ) == 0)
	{
	char *name2;
	
	    name2 = (char *)malloc( strlen( name ) + 1 );
	    strcpy( name2, name );
	    return name2;
	}
    }
    return NULL;
}
Beispiel #26
0
// eval the command in current process
int eval_cmd_in_proc(NodeType *pn) {
  char *cmd = cmd_cmd_str(pn);
  NodeType *params = cmd_params(pn);
  int len = list_length(params);
  char **param_arr = (char**)malloc((len+2) * sizeof(char*));
  int i = 0;
  param_arr[0] = cmd;
  param_arr[len+1] = NULL;
  NodeType *head = params;
  for(i = 0; i < len; i++) {
    param_arr[i+1] = param_str(pair_car(head));
    head = pair_cdr(head);
  }
  if (execvp(cmd, param_arr) < 0) {
    err_sys("execvp failed");
    free(param_arr);
    return -1;
  } else {
    free(param_arr);
    return 0;
  }
}
Beispiel #27
0
static int push_constituents( msgc_context_t *context, word w )
{
  int i, n;

  switch (tagof(w)) {
  case PAIR_TAG :
    PUSH( context, pair_cdr( w ) ); /* Do the CDR last */
    PUSH( context, pair_car( w ) ); /* Do the CAR first */
    return 2;
  case VEC_TAG :
  case PROC_TAG :
    n = bytes2words( sizefield(*ptrof(w)) );
    if (n > LARGE_OBJECT_LIMIT)
      LOS_PUSH( context, 0, w );    /* Treat large objects specially */
    else
      for ( i=0 ; i < n ; i++ )
        PUSH( context, vector_ref( w, i ) );
    return n+1;
  default :
    return 0;
  }
}
Beispiel #28
0
static obj_t *
lang_set(obj_t **frame, obj_t **tailp)
{
    obj_t *expr = *frame_ref(frame, 0);
    obj_t *first, *name, *result;
    *tailp = NULL;
    first = pair_car(expr);
    if (symbolp(first)) {
        // Binding an expression
        // XXX: check for expr length?
        obj_t *to_eval = pair_car(pair_cdr(expr));
        // Get the value of the expression before binding.
        obj_t **expr_frame = frame_extend(
                frame, 1, FR_CONTINUE_ENV | FR_SAVE_PREV);
        *frame_ref(expr_frame, 0) = to_eval;
        result = eval_frame(expr_frame);
        name = first;
    }
    else {
        fatal_error("set! -- first argument is not a symbol", frame);
    }
    environ_set(frame_env(frame), name, result);
    return unspec_wrap();
}
Beispiel #29
0
static int push_pair_constiuents( msgc_context_t *context, word w ) 
{
  PUSH( context, pair_cdr( w ), w, 1 ); /* Do the CDR last */
  PUSH( context, pair_car( w ), w, 0 ); /* Do the CAR first */
  return 2;
}
Beispiel #30
0
static obj_t *
expand_quasiquote(obj_t **frame, obj_t *content,
                  enum quasiquote_return_flag *flag)
{
    if (!pairp(content)) {
        return content;
    }

    // Manually compare each item with unquote/unquote-splicing
    obj_t *qq = symbol_quasiquote;
    obj_t *uq = symbol_unquote;
    obj_t *spl = symbol_unquote_splicing;

    if (pair_car(content) == qq) {
        if (flag)
            flag = QQ_DEFAULT;
        return content;
        // XXX: NESTED QQ...
        /*
        obj_t *body = pair_cadr(content);
        frame = frame_extend(frame, 1, FR_SAVE_PREV | FR_CONTINUE_ENV);
        *frame_ref(frame, 0) = content;
        obj_t *res = expand_quasiquote(frame, body, NULL);  // nested QQ
        obj_t *wrap = pair_wrap(frame, res, nil_wrap());
        return pair_wrap(frame, qq, wrap);
        */
    }
    else if (pair_car(content) == uq) {
        obj_t *uq_body = pair_cadr(content);
        frame = frame_extend(frame, 1, FR_SAVE_PREV | FR_CONTINUE_ENV);
        *frame_ref(frame, 0) = uq_body;
        if (flag)
            *flag = QQ_UNQUOTE;
        return eval_frame(frame);
    }
    else if (pair_car(content) == spl) {
        obj_t *spl_body = pair_cadr(content);
        obj_t *retval;
        frame = frame_extend(frame, 1, FR_SAVE_PREV | FR_CONTINUE_ENV);
        *frame_ref(frame, 0) = spl_body;
        retval = eval_frame(frame);
        if (flag)
            *flag = QQ_SPLICING;
        return retval;
    }
    else {
        // Copy the pair content.
        content = pair_copy_list(frame, content);
        // Append a dummy header for unquote-splicing to use.
        content = pair_wrap(frame, nil_wrap(), content);

        // Mark the content.
        frame = frame_extend(frame, 1, FR_SAVE_PREV | FR_CONTINUE_ENV);
        *frame_ref(frame, 0) = content;

        // For linking unquote-splicing, we look at the next item of
        // the iterator. That's why we need a dummy header here.
        obj_t *iter, *next, *got;
        enum quasiquote_return_flag ret_flag;

        for (iter = content; pairp(iter); iter = pair_cdr(iter)) {
            // `next` will always be null or pair, since `content` is a list.
loop_begin:
            next = pair_cdr(iter);
            if (nullp(next))  // we are done.
                break;

            // XXX: this is strange. why do we need to initialize it?
            ret_flag = QQ_DEFAULT;
            got = expand_quasiquote(frame, pair_car(next), &ret_flag);
            if (ret_flag & QQ_SPLICING) {
                // Special handling for unquote-splicing
                // WARNING: messy code below!
                got = pair_copy_list(frame, got);

                if (nullp(got)) {
                    pair_set_cdr(iter, pair_cdr(next));
                }
                else {
                    pair_set_cdr(iter, got);  // iter -> got
                    while (pairp(pair_cdr(got))) {
                        got = pair_cdr(got);
                    }
                    pair_set_cdr(got, pair_cdr(next));  // got -> (next->next)
                    iter = got;  // make sure the next iteration is correct
                    goto loop_begin;  // And this...
                }
            }
            else {
                // Not unquote-splicing, easy...
                pair_set_car(next, got);
            }
        }
        if (flag)
            *flag = QQ_DEFAULT;
        return pair_cdr(content);
    }
}