lval_t* builtin_op(lval_t* a, const char* op){ for(int i=0;i< a->count;i++){ if(a->cell[i]->type != LVAL_NUM){ lval_free(a); return lval_err("Cannot operator non number"); } } lval_t* x = lval_pop(a, 0); if((strcmp(op, "-")==0) && a->count == 0){ x->num = -(x->num); } while(a->count > 0){ lval_t* y = lval_pop(a, 0); if(strcmp(op , "+") == 0) x->num += y->num; if(strcmp(op , "-") == 0) x->num -= y->num; if(strcmp(op , "*") == 0) x->num *= y->num; if(strcmp(op , "/") == 0) { if(y->num == 0){ lval_free(x); lval_free(y); x = lval_err("Divison by Zero"); break; } x->num /= y->num; } } lval_free(a); return x; }
void lenv_add_builtin(lenv* e, char* name, lbuiltin func){ lval_t* k = lval_sym(name); lval_t* v = lval_fun(func); lenv_put(e, k, v); lval_free(k); lval_free(v); }
lval* lval_eval_sexpr(lval* v) { for (int i = 0; i < v->count; i++) { if (v->cell[i]->type != LVAL_ERR) { v->cell[i] = lval_eval(v->cell[i]); } else { return lval_take(v, i); } } if (v->count == 0) { return v; } if (v->count == 1) { return lval_take(v, 0); } lval* f = lval_pop(v, 0); if (f->type != LVAL_SYM) { lval_free(f); lval_free(v); return lval_err("S-Expression doesn't start with symbol!"); } lval* result = builtin_op(v, f->sym); lval_free(f); return result; }
lval_t* builtin(lval_t* a,const char* func){ if(strcmp("head", func) == 0) return builtin_head(a); if(strcmp("tail" ,func) == 0) return builtin_tail(a); if(strstr("+-/*", func) == 0) return builtin_op(a, func); lval_free(a); return lval_err("Unknown Function"); }
lval_t* builtin_tail(lval_t* a){ LASSERT(a, a->count==1, "Function 'tail' passed too many arguments!"); LASSERT(a, a->cell[0]->count != 0, "Function 'tail' passed {}"); lval_t* v = lval_take(a, 0); lval_free(lval_pop(v, 0)); return v; }
lval_t* builtin_head(lval_t* a){ LASSERT(a, a->count==1, "Function 'head' passed too many arguments!"); LASSERT(a, a->cell[0]->count != 0, "Function head passed {}"); lval_t* v = lval_take(a, 0); while(v->count > 1){ lval_free(lval_pop(v, 1)); } return v; }
lval* builtin_op(lval* a, char* op) { for (int i = 0; i < a->count; i++) { if (a->cell[i]->type != LVAL_NUM) { lval_free(a); return lval_err("Cannot operate on no-number!"); } } lval* x = lval_pop(a, 0); if (strcmp(op, "-") == 0 && a->count == 0) { x->num = -x->num; } while (a->count > 0) { lval* y = lval_pop(a, 0); if (strcmp(op, "+") == 0) { x->num += y->num; } if (strcmp(op, "-") == 0) { x->num -= y->num; } if (strcmp(op, "*") == 0) { x->num *= y->num; } if (strcmp(op, "/") == 0) { if (y->num == 0) { x = lval_err("Division by zero!"); break; } x->num /= y->num; } if (strcmp(op, "%") == 0) { if (y->num == 0) { x = lval_err("Division by zero!"); break; } x->num %= y->num; } lval_free(y); } lval_free(a); return x; }