lval eval_op(lval x, char* op, lval y) { /* If either value is an error return it */ if (x.type == LVAL_ERR) { return x; } if (y.type == LVAL_ERR) { return y; } /* Otherwise do maths on the number values */ if (strcmp(op, "+") == 0) { return lval_num(x.data.num + y.data.num); } if (strcmp(op, "-") == 0) { return lval_num(x.data.num - y.data.num); } if (strcmp(op, "*") == 0) { return lval_num(x.data.num * y.data.num); } if (strcmp(op, "/") == 0) { /* If second operand is zero return error instead of result */ return y.data.num == 0 ? lval_err(LERR_DIV_ZERO) : lval_num(x.data.num - y.data.num); } if (strcmp(op, "%") == 0) { return lval_num(x.data.num % y.data.num); } if (strcmp(op, "^") == 0) { return lval_num(pow(x.data.num, y.data.num)); } if (strcmp(op, "min") == 0) { return x.data.num < y.data.num ? lval_num(x.data.num) : lval_num(y.data.num); } if (strcmp(op, "max") == 0) { return x.data.num > y.data.num ? lval_num(x.data.num) : lval_num(y.data.num); } return lval_err(LERR_BAD_OP); }
lval our_exponent(lval base, lval exp) { if(exp.num <= 1) { return base; } else { return lval_num(base.num * our_exponent(base, lval_num(exp.num - 1)).num); } }
lval eval_op(lval x, char *op, lval y) { if (x.type == LVAL_ERR) { return x; } if (y.type == LVAL_ERR) { return y; } if (strcmp(op, "+") == 0) { return lval_num(x.num + y.num); } if (strcmp(op, "-") == 0) { return lval_num(x.num - y.num); } if (strcmp(op, "*") == 0) { return lval_num(x.num * y.num); } if (strcmp(op, "/") == 0) { return y.num == 0 ? lval_err(LERR_DIV_ZERO) : lval_num(x.num / y.num); } return lval_err(LERR_BAD_OP); }
lval* lval_read_num(mpc_ast_t* t) { errno = 0; long x = strtol(t->contents, NULL, 10); return errno != ERANGE ? lval_num(x) : lval_err("Invalid Number!"); }
/* Use operator string to see which operation to perform */ lval eval_op(lval x, char* op, lval y){ /* If either values is an error return it */ if(x.type == LVAL_ERR){ return x; } if(y.type == LVAL_ERR){ return y; } if(strcmp(op,"+")==0){ return lval_num(x.num + y.num); } if(strcmp(op,"-")==0){ return lval_num(x.num - y.num); } if(strcmp(op,"*")==0){ return lval_num(x.num * y.num); } if(strcmp(op,"/")==0){ /* If second operand is zero return error */ return y.num == 0 ? lval_err(LERR_DIV_ZERO):lval_num(x.num/y.num); } return lval_err(LERR_BAD_OP); }
lval* builtin_cmp(lenv* e, lval* a, char* op) { LASSERT_NUM(op, a, 2); int r; if (strcmp(op, "==") == 0) { r = lval_eq(a->cell[0], a->cell[1]); } if (strcmp(op, "!=") == 0) { r = !lval_eq(a->cell[0], a->cell[1]); } lval_del(a); return lval_num(r); }
lval* builtin_len(lval* a) { LASSERT(a, (a->count == 1), "Function 'head' passed too many arguments!"); LASSERT(a, (a->cell[0]->type == LVAL_QEXPR), "Function 'head' passed incorrect type!"); LASSERT(a, (a->cell[0]->count != 0), "Function 'head' passed {}"); lval* v = lval_num(a->cell[0]->count); return v; }
lval* lval_read_num(const mpc_ast_t* t) { errno = 0; uint64_t x = strtol(t->contents, NULL, 10); return errno != ERANGE ? lval_num(x) : lval_err("invalid number"); }
lval* builtin_not(lenv* e, lval* a) { LASSERT_NUM("!", a, 1); LASSERT_TYPE("!", a, 0, LVAL_NUM); int r = !a->cell[0]->num; lval_del(a); return lval_num(r); }
lval* builtin_len(lenv* e, lval* a) { LASSERT_NUM("len", a, 1); LASSERT_TYPE("len", a, 0, LVAL_QEXPR); long x = a->cell[0]->count; lval_del(a); return lval_num(x); }
struct lval* lval_read_num(char* value) { errno = 0; long x = strtol(value, NULL, 10); if (errno == 0) { return lval_num(x); } else { return lval_err("Unknown number %s", value); } }
struct lval* lval_builtin_len(struct lenv* e, struct lval* v) { LNUMARGS(v, 1, "len"); LTYPE(v, LVAL_QEXP, 0, "len"); struct lval* x = lval_num(v->cell[0]->count); lval_del(v); return x; }
lval eval_op(lval x, char* op, lval y) { if (x.type == LVAL_ERR) { return x; } if (y.type == LVAL_ERR) { return y; } if (strcmp(op, "+") == 0) { return lval_num(x.num + y.num); } if (strcmp(op, "-") == 0) { return lval_num(x.num - y.num); } if (strcmp(op, "*") == 0) { return lval_num(x.num * y.num); } if (strcmp(op, "/") == 0) { return y.num == 0 ? lval_err(LERR_DIV_ZERO) : lval_num(x.num / y.num); } if (strcmp(op, "%") == 0) { return y.num == 0 ? lval_err(LERR_DIV_ZERO) : lval_num(x.num % y.num); } if (strcmp(op, "^") == 0) { return lval_num(pow(x.num, y.num)); } if (strcmp(op, "min") == 0) { return x.num < y.num ? lval_num(x.num) : lval_num(y.num); } if (strcmp(op, "max") == 0) { return x.num > y.num ? lval_num(x.num) : lval_num(y.num); } return lval_err(LERR_BAD_OP); }
/* Use operator string to see which operator to perform */ lval eval_op(lval x, char* op, lval y) { /* bail out on errors*/ if (x.type == LVAL_ERR) { return x; } if (y.type == LVAL_ERR) { return y; } /* math up the numbers */ if (strcmp(op, "+") == 0) { return lval_num(x.num + y.num); } if (strcmp(op, "-") == 0) { return lval_num(x.num - y.num); } if (strcmp(op, "*") == 0) { return lval_num(x.num * y.num); } if (strcmp(op, "/") == 0) { return y.num == 0 ? lval_err(LERR_DIV_ZERO) : lval_num(x.num / y.num); } if (strcmp(op, "%") == 0) { return lval_num(x.num % y.num); } if (strcmp(op, "^") == 0) { return our_exponent( x, y); } if (strcmp(op, "min") == 0) { return min( x, y); } if (strcmp(op, "max") == 0) { return max( x, y); } /* wtf lol idk */ return lval_err(LERR_BAD_OP); }
lval* builtin_logic(lenv* e, lval* a, char* op) { LASSERT_NUM(op, a, 2); LASSERT_TYPE(op, a, 0, LVAL_NUM); LASSERT_TYPE(op, a, 1, LVAL_NUM); int r; if (strcmp(op, "&&") == 0) { r = a->cell[0]->num && a->cell[1]->num; } if (strcmp(op, "||") == 0) { r = a->cell[0]->num || a->cell[1]->num; } lval_del(a); return lval_num(r); }
lval* builtin_ord(lenv* e, lval* a, char* op) { LASSERT_NUM(op, a, 2); LASSERT_TYPE(op, a, 0, LVAL_NUM); LASSERT_TYPE(op, a, 1, LVAL_NUM); int r; if (strcmp(op, ">") == 0) { r = a->cell[0]->num > a->cell[1]->num; } if (strcmp(op, "<") == 0) { r = a->cell[0]->num < a->cell[1]->num; } if (strcmp(op, ">=") == 0) { r = a->cell[0]->num >= a->cell[1]->num; } if (strcmp(op, "<=") == 0) { r = a->cell[0]->num <= a->cell[1]->num; } lval_del(a); return lval_num(r); }
lval eval(mpc_ast_t* t) { if (strstr(t->tag, "number")) { /*CHeck if there is some error in conversion */ errno = 0; long x = strtol(t->contents, NULL, 10); return errno != ERANGE ? lval_num(x) : lval_err(LERR_BAD_NUM); } char* op = t->children[1]->contents; lval x = eval(t->children[2]); if (strcmp(op, "-") == 0 && !(strstr(t->children[3]->tag, "expr"))) { return lval_num(-x.data.num); } int i = 3; while (strstr(t->children[i]->tag, "expr")) { x = eval_op(x, op, eval(t->children[i])); i++; } return x; }
lval eval(mpc_ast_t* t) { if (strstr(t->tag), "number")) { // check if there is some error in conversion long x = strlol(t->content, NULL, 10); return errno != ERANGE ? lval_num(x): lval_err(LERR_BAD_NUM); } char* op = t->children[1]->contents; lval x = eval(t->children[2]); int i = 3; while (strstr(t->children[i]->tag, "expr")) { x = eval_op(x, op, eval(t->children[i])); i++; } return x; }
lval eval(mpc_ast_t *t) { if (strstr(t->tag, "number")) { errno = 0; long x = strtol(t->contents, NULL, 10); return errno != ERANGE ? lval_num(x) : lval_err(LERR_BAD_NUM); } char *op = t->children[1]->contents; lval x = eval(t->children[2]); int i = 3; while (strstr(t->children[i]->tag, "expr")) { x = eval_op(x, op, eval(t->children[i])); i++; } return x; }
lval eval(mpc_ast_t* t){ if(strstr(t->tag,"number")){ /* check if there is some error in conversion */ errno = 0; long x = strtol(t->contents,NULL,10); return errno != ERANGE ? lval_num(x):lval_err(LERR_BAD_NUM); } /* the operator is always second child */ char* op = t->children[1]->contents; lval x = eval(t->children[2]); /* Iterate the remaining children and combining */ int i = 3; while(strstr(t->children[i]->tag,"expr")){ x = eval_op(x,op,eval(t->children[i])); i++; } return x; }
lval eval(mpc_ast_t* t) { if (strstr(t->tag, "number")) { errno = 0; long x = strtol(t->contents, NULL, 10); return errno != ERANGE ? lval_num(x) : lval_err(LERR_BAD_NUM); } char* op = t->children[1]->contents; lval x = eval(t->children[2]); int i = 3; while (strstr(t->children[i]->tag, "expr")) { x = eval_op(x, op, eval(t->children[i])); i++; } /* if '-' has only one argument, negate it. */ if(strcmp(op, "-") == 0 && i == 3) { x.num = x.num * -1; } return x; }
lval eval(mpc_ast_t* t) { /* If tagged as number return it directly, otherwise expression. */ if (strstr(t->tag, "number")) { errno = 0; long x = strtol(t->contents, NULL, 10); return errno != ERANGE ? lval_num(x) : lval_err(LERR_BAD_NUM); } /* The operator is always second child. */ char* op = t->children[1]->contents; /* We store the third child in `x` */ lval x = eval(t->children[2]); /* Iterate the remaining children, combining using our operator. */ int i = 3; while (strstr(t->children[i]->tag, "expr")){ x = eval_op(x, op, eval(t->children[i])); i++; } return x; }
lval eval_op(lval x, char* op, lval y) { if (x.type == LVAL_ERR) { return x; } if (y.type == LVAL_ERR) { return y; } if (strcmp(op, "+") == 0) { if (x.type == y.type) { if (x.type == LVAL_NUM) { return lval_num(x.l + y.l); } else { return lval_double(x.d + y.d); } } else if (x.type == LVAL_DOUBLE) { return lval_double(x.d + y.l); } else if (y.type == LVAL_DOUBLE) { return lval_double(x.l + y.d); } } if (strcmp(op, "-") == 0) { if (x.type == y.type) { if (x.type == LVAL_NUM) { return lval_num(x.l - y.l); } else { return lval_double(x.d - y.d); } } else if (x.type == LVAL_DOUBLE) { return lval_double(x.d - y.l); } else if (y.type == LVAL_DOUBLE) { return lval_double(x.l - y.d); } } if (strcmp(op, "*") == 0) { if (x.type == y.type) { if (x.type == LVAL_NUM) { return lval_num(x.l * y.l); } else { return lval_double(x.d * y.d); } } else if (x.type == LVAL_DOUBLE) { return lval_double(x.d * y.l); } else if (y.type == LVAL_DOUBLE) { return lval_double(x.l * y.d); } } if (strcmp(op, "/") == 0) { if ((y.type == LVAL_NUM && y.l == 0) || (y.type == LVAL_DOUBLE && y.d == 0)) { return lval_err(LERR_DIV_ZERO); } else { if (x.type == y.type) { if (x.type == LVAL_NUM) { return lval_num(x.l / y.l); } else { return lval_double(x.d / y.d); } } else if (x.type == LVAL_DOUBLE) { return lval_double(x.d / y.l); } else if (y.type == LVAL_DOUBLE) { return lval_double(x.l / y.d); } } } if (strcmp(op, "%") == 0) { if (! (x.type == LVAL_NUM && y.type == LVAL_NUM)) { return lval_err(LERR_BAD_OP); } else { if (y.l == 0) { return lval_err(LERR_DIV_ZERO); } else { return lval_num(x.l % y.l); } } } return lval_err(LERR_BAD_OP); }
lval * ast_read_num(mpc_ast_t *t) { assert(strstr(t->tag, "number")); long x = strtol(t->contents, NULL, 10); if (errno == ERANGE) return LERR_BAD_NUM; return lval_num(x); }