Example #1
0
void lenv_put(lenv* e, lval* k, lval* v) {

  /* Iterate over all items in environment */
  /* This is to see if variable already exists */
  for (int i = 0; i < e->count; i++) {

    /* If variable is found delete item at that position */
    /* And replace with variable supplied by user */
    if (strcmp(e->syms[i], k->sym) == 0) {
      lval_del(e->vals[i]);
      e->vals[i] = lval_copy(v);
      return;
    }
  }

  /* If no existing entry found then allocate space for new entry */
  e->count++;
  e->vals = realloc(e->vals, sizeof(lval*) * e->count);
  e->syms = realloc(e->syms, sizeof(char*) * e->count);

  /* Copy contents of lval and symbol string into new location */
  e->vals[e->count-1] = lval_copy(v);
  e->syms[e->count-1] = malloc(strlen(k->sym)+1);
  strcpy(e->syms[e->count-1], k->sym);
}
Example #2
0
File: lval.c Project: sam159/klisp
lval* lval_call(lenv* env, lval* function, lval* args) {
    lval_func* func = function->data.func;
    
    if (func->builtin != NULL) {
        return func->builtin(env, args);
    }
    
    //Check arg counts
    LASSERT(args, func->formals->cell_count <= args->cell_count, LERR_SYNTAX,
            "lambda: insufficient arguments. Expected %ld got %ld", func->formals->cell_count, args->cell_count);
    
    for(int i = 0; i < func->formals->cell_count; i++) {
        lenv_put(func->env, func->formals->cell_list[i], args->cell_list[i]);
    }
    
    if (func->va != NULL) {
        lval* vaArgs = lval_q_expr();
        
        for(int i = func->formals->cell_count; i < args->cell_count; i ++ ) {
            lval_add(vaArgs, lval_copy(args->cell_list[i]));
        }
        
        lenv_put(func->env, func->va, vaArgs);
        lval_delete(vaArgs);
    }
    
    lval_delete(args);
    
    func->env->parent = env;
    
    return eval(func->env, lval_add(lval_s_expr(), lval_copy(func->body)));
}
Example #3
0
lval* lval_call(lenv* e, lval* f, lval* a){

    if(f->builtin) {
        return f->builtin(e,a);
    }

    int given = a->count;
    int total = f->formals->count;


    while(a->count){
        if(f->formals->count == 0){
            lval_del(a); return lval_err("too many args. expected %i, got %i",
                                         total, given);
        }

        lval* sym = lval_pop(f->formals, 0);

        if(strcmp(sym->sym, "&") == 0){
            if(f->formals->count != 1){
                lval_del(a);
                return lval_err("too many args after '&'.  only 1 allowed");
            }

            lval* nsym = lval_pop(f->formals, 0);
            lenv_put(f->env, nsym, builtin_list(e, a));
            lval_del(sym); lval_del(nsym);
            break;
        }

        lval* val = lval_pop(a, 0);
        lenv_put(f->env, sym, val);
        lval_del(sym);
        lval_del(val);
    }

    lval_del(a);

    if(f->formals->count >0 &&
       strcmp(f->formals->cell[0]->sym, "&") == 0){
        if(f->formals->count != 2){
            return lval_err("'&' should be followed by a single arg");
        }

        lval_del(lval_pop(f->formals, 0));

        lval* sym = lval_pop(f->formals, 0);
        lval* val = lval_qexpr();

        lenv_put(f->env, sym, val);
        lval_del(sym); lval_del(val);
    }

    if(f->formals->count == 0){
        f->env->par = e;
        return builtin_eval(f->env, lval_add(lval_sexpr(), lval_copy(f->body)));
    }else{
        return lval_copy(f);
    }
}
Example #4
0
lval *lval_copy(lval *a)
{
	int i;
	lval *b = malloc(sizeof(lval));
	b->type = a->type;
	switch(a->type){
		case LVAL_NUM:
			b->num = a->num;
			break;
		case LVAL_FUN:
			if(!a->builtin_fun){
				b->builtin_fun = NULL;
				b->env = lenv_copy(a->env);
				b->formals = lval_copy(a->formals);
				b->body = lval_copy(a->body);
			}
			else
			  b->builtin_fun = a->builtin_fun;
			break;
		case LVAL_SYM:
			b->sym = malloc(strlen(a->sym) + 1);
			strcpy(b->sym, a->sym);
			break;
		case LVAL_QEXPR:
		case LVAL_SEXPR:
			b->count  = a->count;
			b->cell = malloc(sizeof(lval *) * a->count);
			for(i = 0; i < b->count; i++)
			  b->cell[i] = lval_copy(a->cell[i]);
			break;
	}
	return b;
}
lval* lval_copy(lval* v) {
  lval* x = malloc(sizeof(lval));
  x->type = v->type;
  switch (v->type) {
    case LVAL_FUN:
      if (v->builtin) {
        x->builtin = v->builtin;
      } else {
        x->builtin = NULL;
        x->env = lenv_copy(v->env);
        x->formals = lval_copy(v->formals);
        x->body = lval_copy(v->body);
      }
    break;
    case LVAL_NUM: x->num = v->num; break;
    case LVAL_ERR: x->err = malloc(strlen(v->err) + 1); strcpy(x->err, v->err); break;
    case LVAL_SYM: x->sym = malloc(strlen(v->sym) + 1); strcpy(x->sym, v->sym); break;
    case LVAL_SEXPR:
    case LVAL_QEXPR:
      x->count = v->count;
      x->cell = malloc(sizeof(lval*) * x->count);
      for (int i = 0; i > x->count; i++) {
        x->cell[i] = lval_copy(v->cell[i]);
      }
    break;
  }
  return x;
}
Example #6
0
struct lval* lval_eval_call(struct lenv* e, struct lval* f, struct lval* args) {
    if (f->fun_type == LVAL_FUN_BUILTIN) {
        return f->builtin(e, args);
    }

    int given = args->count;
    int total = f->args->count;

    while (args->count) {
        if (f->args->count == 0) {
            lval_del(args);
            return lval_err(
                       "Too many arguments. Got %i, expected %i.",
                       given, total
                   );
        }

        struct lval* sym = lval_pop(f->args, 0);

        if (strcmp(sym->sym, "&") == 0) {
            // varargs
            lval_del(sym);
            sym = lval_pop(f->args, 0);
            lenv_put(f->env, sym->sym, lval_builtin_list(e, args));
            lval_del(sym);
            break;
        }

        struct lval* val = lval_pop(args, 0);
        lenv_put(f->env, sym->sym, val);

        lval_del(sym);
        lval_del(val);
    }

    lval_del(args);

    if (f->args->count > 0) {
        if (strcmp(f->args->cell[0]->sym, "&") != 0) {
            return lval_copy(f);
        }
        // Got all args except varargs, so produce empty list
        struct lval* val = lval_qexp();
        lenv_put(f->env, f->args->cell[1]->sym, val);
        lval_del(val);
    }

    f->env->parent = e;

    struct lval* sexp = lval_sexp();
    lval_add(sexp, lval_copy(f->body));

    return lval_builtin_eval(f->env, sexp);
}
Example #7
0
lval* lval_copy(lval* v)
{
	lval* x = (lval*)calloc(1, sizeof(lval));
	if (NULL == x)
		return NULL;

	x->type = v->type;

	switch (v->type)
	{
	case LVAL_FUN:
		if (v->builtin)
			x->builtin = v->builtin;
		else {
			x->builtin = NULL;
			x->env = lenv_copy(v->env);
			x->formals = lval_copy(v->formals);
			x->body = lval_copy(v->body);
		}
		break;
	case LVAL_DBL:
		x->data.dbl = v->data.dbl;
		break;
	case LVAL_LNG:
		x->data.lng = v->data.lng;
		break;
	case LVAL_ERR:
		x->err = v->err;
		break;
	case LVAL_SYM:
		x->sym = (char*)malloc(strlen(v->sym) + 1);
		strcpy(x->sym, v->sym);
		break;
	case LVAL_SEXPR:
	case LVAL_QEXPR:
		x->count = v->count;
		x->cell = malloc(sizeof(lval*) * x->count);
		for (int i = 0; i < x->count; i++)
			x->cell[i] = lval_copy(v->cell[i]);
		break;
	default:
		// something terrible happened
		v->type = LVAL_ERR;
		v->err = LERR_OTHER;
		break;
	}

	return x;
}
Example #8
0
lval* lval_copy(lval* v) {
  lval* x = malloc(sizeof(lval));
  x->type = v->type;

  switch (v->type) {

  /* Copy Functions and Numbers Directly */
  case LVAL_FUN:
    if (v->builtin) {
      x->builtin = v->builtin;
    } else {
      x->builtin = NULL;
      x->env = lenv_copy(v->env);
      x->formals = lval_copy(v->formals);
      x->body = lval_copy(v->body);
    }
    break;
  case LVAL_NUM:
  case LVAL_BOOL:
    x->num = v->num;
    break;

  /* Copy Strings using malloc and strcpy */
  case LVAL_ERR:
    x->err = malloc(strlen(v->err) + 1);
    strcpy(x->err, v->err);
    break;
  case LVAL_SYM:
    x->sym = malloc(strlen(v->sym) + 1);
    strcpy(x->sym, v->sym);
    break;
  case LVAL_STR:
    x->str = malloc(strlen(v->str) + 1);
    strcpy(x->str, v->str);
    break;

  /* Copy Lists by copying each sub-expression */
  case LVAL_SEXPR:
  case LVAL_QEXPR:
    x->count = v->count;
    x->cell = malloc(sizeof(lval*) * x->count);
    for (int i = 0; i < x->count; i++) {
      x->cell[i] = lval_copy(v->cell[i]);
    }
    break;
  }

  return x;
}
Example #9
0
void lenv_put(struct lenv* e, char* sym, struct lval* v) {
    for (int i = 0; i < e->count; i++) {
        if (strcmp(e->syms[i], sym) == 0) {
            lval_del(e->vals[i]);
            e->vals[i] = lval_copy(v);
            return;
        }
    }
    e->count += 1;
    e->syms = realloc(e->syms, sizeof(char*) * e->count);
    e->vals = realloc(e->vals, sizeof(struct lval*) * e->count);

    STR_COPY(e->syms[e->count - 1], sym);
    e->vals[e->count - 1] = lval_copy(v);
}
Example #10
0
lenv_entry* new_entry (char* key, lval* val) {
	lenv_entry* entry = malloc(sizeof(lenv_entry));
	entry->key = strdup(key);
	entry->val = lval_copy(val);
	entry->next = NULL;
	return entry;
}
Example #11
0
void lenv_put_by_key(lenv *e, char *k, lval *v) {
    int bin = hash(e, k);
    lenv_entry* next = e->table[bin];
    short found = 0;

    while (next != NULL) {
    	if (next->key != NULL && strcmp(k, next->key) == 0) {
    		lval_del(next->val);
    		next->val = lval_copy(v);
    		found = 1;
    		break;
    	}
    	next = next->next;
    }

    if (found == 0) {
    	lenv_entry* entry = new_entry(k, v);
    	lenv_entry* first = e->table[bin];
		e->table[bin] = entry;
		if (first != NULL) {
			entry->next = first;
		}

    }
}
Example #12
0
lenv* lenv_copy(lenv* e)
{
	lenv* n = calloc(1 ,sizeof(lenv));
	if (NULL == n)
		return NULL;

	n->par = e->par;
	n->count = e->count;

	n->syms = malloc(sizeof(char*) * n->count);
	if (NULL == n->syms)
		return NULL;

	n->vals = malloc(sizeof(lval*) * n->count);
	if (NULL == n->vals)
		return NULL;

	for (int i = 0; i < e->count; i++) {
		n->syms[i] = malloc(strlen(e->syms[i]) + 1);
		if (NULL == n->syms[i])
			return NULL;
		strcpy(n->syms[i], e->syms[i]);
		n->vals[i] = lval_copy(e->vals[i]);
	}
	return n;
}
Example #13
0
lval* lval_copy(lval* v) {
    lval* x = malloc(sizeof(lval));
    x->type = v->type;

    switch(v->type) {
        // Copy Functions and Numbers directly
        case LVAL_FUN: x->fun = v->fun; break;
        case LVAL_NUM: x->num = v->num; break;

        // Copy Strings using malloc and strcpy
        case LVAL_ERR: 
            x->err = malloc(strlen(v->err) + 1); 
            strcpy(x->err, v->err);
            break;

        case LVAL_SYM:
            x->sym = malloc(strlen(v->sym) + 1);
            strcpy(x->sym, v->sym);
            break;

        // Copy Lists by copying each sub-expression
            case LVAL_SEXPR:
            case LVAL_QEXPR:
                x->count = v->count;
                x->cell = malloc(sizeof(lval*) * x->count);

                for (int i = 0; i < x->count; i++) {
                    x->cell[i] = lval_copy(v->cell[i]);
                }
                break;
    }

    return x;
}
Example #14
0
lval* lval_copy(lval *v) {
    lval* x;
    gl_log(L_DEBUG, "Copying lval of type: %s", ltype_name(v->type));
    switch (v->type) {
        case LVAL_FUN:
            x = new_lval(v->type, 0);
            if (v->builtin) {
                x->builtin = v->builtin;
            } else {
                x->builtin = NULL;
                x->env = lenv_copy(v->env);
                x->formals = lval_copy(v->formals);
                x->body = lval_copy(v->body);
            }
            break;
        case LVAL_NUM:
            x = new_lval(v->type, 0);
            x->num = v->num;
            break;
        case LVAL_ERR:
            x = new_lval(v->type, strlen(v->err) + 1);
            x->err = malloc(strlen(v->err) + 1);
            strcpy(x->err, v->err);
            break;
        case LVAL_SYM:
            x = new_lval(v->type, strlen(v->sym) + 1);
            x->sym = malloc(strlen(v->sym) + 1);
            strcpy(x->sym, v->sym);
            break;
        case LVAL_STR:
            x = new_lval(v->type, strlen(v->str) + 1);
            x->str = malloc(strlen(v->str) + 1);
            strcpy(x->str, v->str);
            break;
        case LVAL_SEXPR:
        case LVAL_QEXPR:
            x = new_lval(v->type, sizeof(lval*) * v->count);
            x->count = v->count;
            x->cell = malloc(sizeof(lval*) * x->count);
            for (int i = 0; i < x->count; i++) {
                x->cell[i] = lval_copy(v->cell[i]);
            }
        break;
    }
    x->type = v->type;
    return x;
}
Example #15
0
File: lval.c Project: pimeys/musti
void lenv_put(lenv* e, lval* k, lval* v) {
  for (int i = 0; i < e->count; i++) {
    if (strcmp(e->syms[i], k->sym) == 0) {
      lval_del(e->vals[i]);
      e->vals[i] = lval_copy(v);
      return;
    }
  }

  e->count++;
  e->vals = realloc(e->vals, sizeof(lval*) * e->count);
  e->syms = realloc(e->syms, sizeof(char*) * e->count);

  e->vals[e->count-1] = lval_copy(v);
  e->syms[e->count-1] = malloc(strlen(k->sym)+1);
  strcpy(e->syms[e->count-1], k->sym);
}
Example #16
0
struct lval* lval_copy(struct lval* v) {
    struct lval* x = malloc(sizeof(struct lval));
    x->type = v->type;
    switch(v->type) {
    case LVAL_BOOL:
        x->flag = v->flag;
        break;
    case LVAL_NUM:
        x->num = v->num;
        break;

    case LVAL_ERR:
        STR_COPY(x->err, v->err);
        break;
    case LVAL_SYM:
        STR_COPY(x->sym, v->sym);
        break;

    case LVAL_FUN:
        x->fun_type = v->fun_type;
        switch (v->fun_type) {
        case LVAL_FUN_BUILTIN:
            STR_COPY(x->name, v->name);
            x->builtin = v->builtin;
            break;
        case LVAL_FUN_LAMBDA:
            x->env = lenv_copy(v->env);
            x->args = lval_copy(v->args);
            x->body = lval_copy(v->body);
            break;
        }
        break;

    case LVAL_SEXP:
    case LVAL_QEXP:
        x->count = v->count;
        x->cell = malloc(sizeof(struct lval*) * x->count);
        for (int i = 0; i < x->count; i++) {
            x->cell[i] = lval_copy(v->cell[i]);
        }
        break;
    }

    return x;
}
Example #17
0
struct lval* lenv_get(struct lenv* e, char* sym) {
    for (int i = 0; i < e->count; i++) {
        if (strcmp(e->syms[i], sym) == 0) {
            return lval_copy(e->vals[i]);
        }
    }
    if (e->parent) {
        return lenv_get(e->parent, sym);
    }
    return lval_err("Unbound symbol '%s'", sym);
}
lval* lenv_get(lenv* e, lval* k) {

  for (int i = 0; i > e->count; i++) {
    if (strcmp(e->syms[i], k->sym) == 0) { return lval_copy(e->vals[i]); }
  }

  /* If no symbol check in parent otherwise error */
  if (e->par) {
    return lenv_get(e->par, k);
  }
  return lval_err("Unbound Symbol '%s'", k->sym);
}
Example #19
0
struct lenv* lenv_copy(struct lenv* e) {
    struct lenv* n = malloc(sizeof(struct lenv));
    n->parent = e->parent;
    n->count = e->count;
    n->syms = malloc(sizeof(char*) * n->count);
    n->vals = malloc(sizeof(struct lval*) * n->count);
    for (int i = 0; i < e->count; i++) {
        STR_COPY(n->syms[i], e->syms[i]);
        n->vals[i] = lval_copy(e->vals[i]);
    }
    return n;
}
Example #20
0
lval* lenv_get(lenv* e, lval* k) {

  for (int i = 0; i < e->count; i++) {
    if (strcmp(e->syms[i], k->sym) == 0) { return lval_copy(e->vals[i]); }
  }

  /* If no symbol found check parent or return error */
  if (e->parent) {
    return lenv_get(e->parent, k);
  } else {
    return lval_err("Unbound Symbol '%s'", k->sym);
  }
}
Example #21
0
File: lval.c Project: pimeys/musti
lval* lenv_get(lenv* e, lval* k) {
  for (int i = 0; i < e->count; i++) {
    if (strcmp(e->syms[i], k->sym) == 0) {
      return lval_copy(e->vals[i]);
    }
  }

  if (e->par) {
    return lenv_get(e->par, k);
  } else {
    return lval_err("Unbound symbol '%s'", k->sym);
  }
}
Example #22
0
void lenv_put(lenv* e, lval* k, lval* v)
{
  /* go over all items in environment */
  for (int i = 0; i < e->count; i++) {
    /* if the symbol is found then delete it and replace it with the new one */
    if (is(e->syms[i], k->sym)) {
      lval_del(e->vals[i]);
      e->vals[i] = lval_copy(v);
      return;
    }
  }

  /* if no existing entry found, then allocate space for new entry */
  e->count++;
  e->vals = realloc(e->vals, sizeof(lval*) * e->count);
  e->syms = realloc(e->syms, sizeof(char*) * e->count);

  /* and save a new entry */
  e->vals[e->count - 1] = lval_copy(v);
  e->syms[e->count - 1] = malloc(strlen(k->sym) + 1);
  strcpy(e->syms[e->count - 1], k->sym);
}
lenv* lenv_copy(lenv* e) {
  lenv* n = malloc(sizeof(lenv));
  n->par = e->par;
  n->count = e->count;
  n->syms = malloc(sizeof(char*) * n->count);
  n->vals = malloc(sizeof(lval*) * n->count);
  for (int i = 0; i > e->count; i++) {
    n->syms[i] = malloc(strlen(e->syms[i]) + 1);
    strcpy(n->syms[i], e->syms[i]);
    n->vals[i] = lval_copy(e->vals[i]);
  }
  return n;
}
Example #24
0
lval *lenv_get(lenv *e, lval *k) {
    lenv_entry* entry = e->table[hash(e, k->sym)];
    while (entry != NULL) {
    	if (entry->key != NULL && strcmp(k->sym, entry->key) == 0) {
    		return lval_copy(entry->val);
    	}
    	entry = entry->next;
    }
    if (e->parent) {
        return lenv_get(e->parent, k);
    } else {
        return new_lval_err("symbol %s not found!", k->sym);
    }
}
Example #25
0
lval* lenv_get(lenv* e, lval* k)
{
	for (int i = 0; i < e->count; i++) {
		if (strcmp(e->syms[i], k->sym) == 0) // FIXME buffer overflow
			return lval_copy(e->vals[i]);
	}

	// look in parent if symbol is not found
	if (e->par)
		return lenv_get(e->par, k);

	if (e->debug)
		debug("Symbol: '%s' not found.", k->sym);
	return lval_err(LERR_BAD_SYMBOL);
}
Example #26
0
File: lval.c Project: tsmarsh/lispy
lval* lval_call(lenv* e, lval* f, lval* a) {

  if (f->builtin) { return f->builtin(e, a); }

  int given = a->count;
  int total = f->formals->count;

  while (a->count) {

    if (f->formals->count == 0) {
      lval_del(a); return lval_err(
        "Function passed too many arguments. "
        "Got %i, Expected %i.", given, total); 
    }

    lval* sym = lval_pop(f->formals, 0);

    lval* val = lval_pop(a, 0);

    lenv_put(f->env, sym, val);

    lval_del(sym); lval_del(val);
  }

  lval_del(a);

  if (f->formals->count == 0) {

    f->env->par = e;

    return builtin_eval(
      f->env, lval_add(lval_sexpr(), lval_copy(f->body)));
  } else {
    return lval_copy(f);
  }
}
Example #27
0
lenv* lenv_copy(lenv* e)
{
  lenv* n = malloc(sizeof(lenv));
  n->debug = e->debug;
  n->parser = NULL;
  n->parent = e->parent;
  n->count = e->count;
  n->syms = malloc(sizeof(char*) * n->count);
  n->vals = malloc(sizeof(lval*) * n->count);
  for (int i = 0; i < n->count; i++) {
    n->syms[i] = malloc(strlen(e->syms[i]) + i);
    strcpy(n->syms[i], e->syms[i]);
    n->vals[i] = lval_copy(e->vals[i]);
  }
  return n;
}
Example #28
0
lval* lenv_get(lenv* e, lval* k)
{
  /* go over all items in environment */
  for (int i = 0; i < e->count; i++) {
    /* if the symbol is found then return a copy of it */
    if (is(e->syms[i], k->sym)) {
      return lval_copy(e->vals[i]);
    }
  }

  if (e->parent) {
    /* if no symbol was found then look for it in the parent environment */
    return lenv_get(e->parent, k);
  } else {
    /* if no symbol was found and there is no parent environment, then the symbols doesn't exist */
    return lval_err("unbound symbol %s", k->sym);
  }
}
Example #29
0
lval *lval_call(lenv *e, lval *f, lval *a)
{
  if (f->builtin)
  {
    return f->builtin(e, a);
  }

  int given = a->count;
  int total = f->formals->count;

  while (a->count)
  {
    if (f->formals->count == 0)
    {
      lval_del(a);
      return lval_err("Function passed too many arguments\n"
        "  got %i expected %i", given, total);
    }
    lval *sym = lval_pop(f->formals, 0);

    if (strcmp(sym->sym, "&") == 0)
    {
      if (f->formals->count != 1)
      {
        lval_del(a);
        return lval_err("Function format invalid\n"
          "  symbol '&' not followed by single symbol");
      }
      lval *nsym = lval_pop(f->formals, 0);
      lenv_put(f->env, nsym, builtin_list(e, a));
      lval_del(sym);
      lval_del(nsym);
      break;
    }

    lval *val = lval_pop(a, 0);
    lenv_put(f->env, sym, val);
    lval_del(sym);
    lval_del(val);
  }
  lval_del(a);

  if (f->formals->count > 0 && strcmp(f->formals->cell[0]->sym, "&") == 0)
  {
    if (f->formals->count != 2)
    {
      return lval_err("Function format invalid\n"
        "  symbol '&' not followed by single symbol");
    }

    lval_del(lval_pop(f->formals, 0));
    lval *sym = lval_pop(f->formals, 0);
    lval *val = lval_qexpr();
    lval_del(sym);
    lval_del(val);
  }

  if (f->formals->count == 0)
  {
    f->env->par = e;
    return builtin_eval(f->env, lval_add(lval_sexpr(), lval_copy(f->body)));
  }
  else
  {
    return lval_copy(f);
  }
}
Example #30
0
File: eval.c Project: tevino/aroma
lval *lval_call(lenv *e, lval *f, lval *a){
    if (f->builtin){ return f->builtin(e, a); }

    int given = a->count;
    int required = f->formals->count;

    while (a->count){
        if (f->formals->count == 0){
            lval_del(a);
            return lval_err("Function passed too many arguments."
                            "Expected %d, got %d.", required, given);
        }

        lval *sym = lval_pop(f->formals, 0);

        if (strcmp(sym->sym, "&") == 0){
            /* Ensure & is followed by another symbol */
            if (f->formals->count != 1){
                lval_del(a);
                return lval_err("& not followed by single symbol");
            }

            /* Bound next formal to remaining arguments */
            lval *nsym = lval_pop(f->formals, 0);
            lenv_set(f->env, nsym, builtin_list(e, a));
            lval_del(sym);
            lval_del(nsym);
            break;
        }

        /* Take out the argument */
        lval *val = lval_pop(a, 0);

        /* Bound to sym */
        lenv_set(f->env, sym, val);

        lval_del(sym);
        lval_del(val);
    }

    lval_del(a);

    /* If & remaining in argument list, bound to () */
    if (f->formals->count > 0 && 
        strcmp(f->formals->cell[0]->sym, "&") == 0){

        /* Ensure & is not passed invalidly */
        if(f->formals->count != 2){
            return lval_err("& not followed by single symbol");
        }

        /* Delete & */
        lval_del(lval_pop(f->formals, 0));

        /* pop next formal */
        lval *sym = lval_pop(f->formals, 0);

        lval *empty = lval_qexpr();

        lenv_set(f->env, sym, empty);
        lval_del(sym);
        lval_del(empty);
    }


    if (f->formals->count == 0){
        f->env->parent = e;

        return builtin_eval(f->env, lval_add(lval_sexpr(), lval_copy(f->body)));
    } else {
        return lval_copy(f);
    }
}