lval *builtin(lval *v, char *func) { if (strcmp("head", func) == 0) { return builtin_head(v); } if (strcmp("tail", func) == 0) { return builtin_tail(v); } if (strcmp("init", func) == 0) { return builtin_init(v); } if (strcmp("join", func) == 0) { return builtin_join(v); } if (strcmp("eval", func) == 0) { return builtin_eval(v); } if (strcmp("list", func) == 0) { return builtin_list(v); } if (strcmp("cons", func) == 0) { return builtin_cons(v); } if (strcmp("len", func) == 0) { return builtin_len(v); } return builtin_op(v, func); }
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); } }
lval* builtin(lval* a, char* func) { if (strcmp("join", func) == 0) { return builtin_join(a); } if (strcmp("list", func) == 0) { return builtin_list(a); } if (strcmp("eval", func) == 0) { return builtin_eval(a); } if (strcmp("tail", func) == 0) { return builtin_tail(a); } if (strcmp("head", func) == 0) { return builtin_head(a); } if (strstr("+-/*", func)) { return builtin_op(a, func); } lval_del(a); return lval_err("Unknown Function!"); }
lval *builtin(lenv *e, lval *a, char *func) { if (strcmp("eval", func) == 0) { return builtin_eval(e, a); } if (strcmp("head", func) == 0) { return builtin_head(e, a); } if (strcmp("join", func) == 0) { return builtin_join(e, a); } if (strcmp("list", func) == 0) { return builtin_list(e, a); } if (strcmp("tail", func) == 0) { return builtin_tail(e, a); } if (strstr("+-*%/", func)) { return builtin_op(e, a, func); } lval_del(a); return lval_err("Unknown function %s", func); }
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); } }
/** * Call a function in an environment, with arguments */ bval* bval_call(benv* e, bval* f, bval* 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) { bval_del(a); return bval_err( "Function passed too many arguments. " "Expected %i, Got %i.", total, given ); } bval* sym = bval_pop(f->formals, 0); // syntax for allowing remainder args if (strcmp(sym->sym, "::") == 0) { if (f->formals->count != 1) { bval_del(a); return bval_err( "Function format invalid." "Symbol '::' not followed by single symbol." ); } bval* nsym = bval_pop(f->formals, 0); benv_put(f->env, nsym, builtin_list(e, a)); bval_del(sym); bval_del(nsym); break; } bval* val = bval_pop(a, 0); // bind a copy of the val to the functions environment benv_put(f->env, sym, val); bval_del(sym); bval_del(val); } // deallocate arglist bval_del(a); if (f->formals->count > 0 && strcmp(f->formals->cell[0]->sym, "::") == 0) { if (f->formals->count != 2) { return bval_err( "Function format invalid." "Symbol '::' not followed by single symbol." ); } bval_del(bval_pop(f->formals, 0)); // no remaining args for vararg list, assign empty list bval* sym = bval_pop(f->formals, 0); bval* val = bval_qexpr(); benv_put(f->env, sym, val); bval_del(sym); bval_del(val); } // if all the functions parameters have been bound to arguments, // evaluate the function and return a result if (f->formals->count == 0) { f->env->parent = e; // evaluate the body of the function return builtin_eval(f->env, // copy the q-expression representing the function body into an s-expression, // using the environment of the function as context (with the newly found variables) bval_add(bval_sexpr(), bval_copy(f->body)) ); } else { // otherwise... curry the function return bval_copy(f); } }
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); } }
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); } }
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. Expected %i, Got %i.", total, given); } lval* sym = lval_pop(f->formals, 0); // Variadic operator if (strcmp(sym->sym, "&") == 0){ if (f->formals->count != 1) { lval_del(a); return lval_err("Function format invalid. " "Symbol '&' not followed by a 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(val); lval_del(sym); } lval_del(a); // If '&' remains in formal list bind to empty list if (f->formals->count > 0 && strcmp(f->formals->cell[0]->sym, "&") == 0) { if (f->formals->count != 2) { return lval_err("Function format invalid. " "Symbol '&' not followed by a single symbol"); } 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(val); lval_del(sym); } 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); } }
lval* lval_call(lenv* e, lval* f, lval* a) { /* If Builtin then simply apply that */ if (f->builtin) { return f->builtin(e, a); } /* Record Argument Counts */ int given = a->count; int total = f->formals->count; /* While arguments still remain to be processed */ while (a->count) { /* If we've ran out of formal arguments to bind */ if (f->formals->count == 0) { lval_del(a); return lval_err("Function passed too many arguments. Got %i, Expected %i.", given, total); } /* Pop the first symbol from the formals */ lval* sym = lval_pop(f->formals, 0); /* Special Case to deal with '&' */ if (strcmp(sym->sym, "&") == 0) { /* Ensure '&' is followed by another symbol */ if (f->formals->count != 1) { lval_del(a); return lval_err("Function format invalid. Symbol '&' not followed by single symbol."); } /* Next formal should be bound to remaining arguments */ lval* nsym = lval_pop(f->formals, 0); lenv_put(f->env, nsym, builtin_list(e, a)); lval_del(sym); lval_del(nsym); break; } /* Pop the next argument from the list */ lval* val = lval_pop(a, 0); /* Bind a copy into the function's environment */ lenv_put(f->env, sym, val); /* Delete symbol and value */ lval_del(sym); lval_del(val); } /* Argument list is now bound so can be cleaned up */ lval_del(a); /* If '&' remains in formal list it should be bound to empty list */ if (f->formals->count > 0 && strcmp(f->formals->cell[0]->sym, "&") == 0) { /* Check to ensure that & is not passed invalidly. */ if (f->formals->count != 2) { return lval_err("Function format invalid. Symbol '&' not followed by single symbol."); } /* Pop and delete '&' symbol */ lval_del(lval_pop(f->formals, 0)); /* Pop next symbol and create empty list */ lval* sym = lval_pop(f->formals, 0); lval* val = lval_qexpr(); /* Bind to environment and delete */ lenv_put(f->env, sym, val); lval_del(sym); lval_del(val); } /* If all formals have been bound evaluate */ if (f->formals->count == 0) { /* Set Function Environment parent to current evaluation Environment */ f->env->par = e; /* Evaluate and return */ return builtin_eval(f->env, lval_add(lval_sexpr(), lval_copy(f->body))); } else { /* Otherwise return partially evaluated function */ return lval_copy(f); } }
Value* tl_val_call(Env* e, Value* fn, Value* args) { if(fn->builtin) { return fn->builtin(e, args); } int given = args->count; int total = fn->formals->count; while (args->count) { if (fn->formals->count == 0) { tl_val_delete(args); return tl_val_error( "Function passed too many arguments. " "Got %i, expected %i.", given, total); } Value* sym = tl_val_pop(fn->formals, 0); if (strcmp(sym->sym, "&") == 0) { if (fn->formals->count != 1) { tl_val_delete(args); return tl_val_error("Function format invalid." "Symbol '&' not followed by single symbol"); } Value* symbols = tl_val_pop(fn->formals, 0); tl_env_put(fn->env, symbols, builtin_list(e, args)); tl_val_delete(sym); tl_val_delete(symbols); break; } Value* val = tl_val_pop(args, 0); tl_env_put(fn->env, sym, val); tl_val_delete(sym); tl_val_delete(val); } if (fn->formals->count > 0 && strcmp(fn->formals->cell[0]->sym, "&") == 0) { if (fn->formals->count != 2) { return tl_val_error("Function format invalid." "Symbol '&' not followed by single symbol"); } tl_val_delete(tl_val_pop(fn->formals, 0)); Value* symbol = tl_val_pop(fn->formals, 0); Value* value = tl_val_qexpr(); tl_env_put(e, symbol, value); tl_val_delete(symbol); tl_val_delete(value); } tl_val_delete(args); if (fn->formals->count == 0) { // Eval and return if all formals have been bound fn->env->parent = e; return builtin_eval(fn->env, tl_val_add(tl_val_sexpr(), tl_val_copy(fn->body))); } else { // Partially evaluated function return tl_val_copy(fn); } }