Sexpr* a_plus(Sexpr* b, Sexpr* rest, Sexpr* env) {
- if(ARITH_PLUS_ARGS != u64_get_num_args(b)) {
+ if(ARITH_ADD_ARGS != u64_get_num_args(b)) {
return cons(b, rest);
}
Sexpr* args = b->value.b.args;
return cons(from_uint(m + n), rest);
}
+Sexpr* a_minus(Sexpr* b, Sexpr* rest, Sexpr* env) {
+ if(ARITH_SUB_ARGS != u64_get_num_args(b)) {
+ return cons(b, rest);
+ }
+ Sexpr* args = b->value.b.args;
+ Sexpr* i = eval(clone(car(args)), env);
+ Sexpr* j = eval(clone(car(cdr(args))), env);
+ uint64_t m = unquote(i)->value.u;
+ uint64_t n = unquote(j)->value.u;
+ sexpr_free(b);
+ sexpr_free(i);
+ sexpr_free(j);
+ return cons(from_uint(n - m), rest);
+}
+
+Sexpr* a_mul(Sexpr* b, Sexpr* rest, Sexpr* env) {
+ if(ARITH_MUL_ARGS != u64_get_num_args(b)) {
+ return cons(b, rest);
+ }
+ Sexpr* args = b->value.b.args;
+ Sexpr* i = eval(clone(car(args)), env);
+ Sexpr* j = eval(clone(car(cdr(args))), env);
+ uint64_t m = unquote(i)->value.u;
+ uint64_t n = unquote(j)->value.u;
+ sexpr_free(b);
+ sexpr_free(i);
+ sexpr_free(j);
+ return cons(from_uint(m * n), rest);
+}
+
+Sexpr* a_div(Sexpr* b, Sexpr* rest, Sexpr* env) {
+ if(ARITH_DIV_ARGS != u64_get_num_args(b)) {
+ return cons(b, rest);
+ }
+ Sexpr* args = b->value.b.args;
+ Sexpr* i = eval(clone(car(args)), env);
+ Sexpr* j = eval(clone(car(cdr(args))), env);
+ uint64_t m = unquote(i)->value.u;
+ uint64_t n = unquote(j)->value.u;
+ sexpr_free(b);
+ sexpr_free(i);
+ sexpr_free(j);
+ return cons(from_uint(n / m), rest);
+}
+
+Sexpr* a_mod(Sexpr* b, Sexpr* rest, Sexpr* env) {
+ if(ARITH_MOD_ARGS != u64_get_num_args(b)) {
+ return cons(b, rest);
+ }
+ Sexpr* args = b->value.b.args;
+ Sexpr* i = eval(clone(car(args)), env);
+ Sexpr* j = eval(clone(car(cdr(args))), env);
+ uint64_t m = unquote(i)->value.u;
+ uint64_t n = unquote(j)->value.u;
+ sexpr_free(b);
+ sexpr_free(i);
+ sexpr_free(j);
+ return cons(from_uint(n % m), rest);
+}
+
+
Sexpr* x_arith_dispatch(Sexpr* b, Sexpr* rest, Sexpr* env) {
uint64_t code = b->value.b.opcode & 0xff;
switch(code) {
- case ARITH_PLUS:
+ case ARITH_ADD:
return a_plus(b, rest, env);
+ case ARITH_SUB:
+ return a_minus(b, rest, env);
+ case ARITH_MUL:
+ return a_mul(b, rest, env);
+ case ARITH_DIV:
+ return a_div(b, rest, env);
+ case ARITH_MOD:
+ return a_mod(b, rest, env);
default:
return from_nil();
}
Sexpr* load_arith_env(Sexpr* env) {
Sexpr* k;
+ Sexpr* v;
k = from_sym("+");
- Sexpr* a_plus = from_opcode((ARITH_PREFIX << 8) | ARITH_PLUS);
- append_to_dict(env, k, a_plus);
- sexpr_free(a_plus);
+ v = from_opcode((ARITH_PREFIX << 8) | ARITH_ADD);
+ append_to_dict(env, k, v);
+ sexpr_free(v);
+ sexpr_free(k);
+
+ k = from_sym("-");
+ v = from_opcode((ARITH_PREFIX << 8) | ARITH_SUB);
+ append_to_dict(env, k, v);
+ sexpr_free(v);
+ sexpr_free(k);
+
+ k = from_sym("*");
+ v = from_opcode((ARITH_PREFIX << 8) | ARITH_MUL);
+ append_to_dict(env, k, v);
+ sexpr_free(v);
+ sexpr_free(k);
+
+ k = from_sym("/");
+ v = from_opcode((ARITH_PREFIX << 8) | ARITH_DIV);
+ append_to_dict(env, k, v);
+ sexpr_free(v);
+ sexpr_free(k);
+
+ k = from_sym("%");
+ v = from_opcode((ARITH_PREFIX << 8) | ARITH_MOD);
+ append_to_dict(env, k, v);
+ sexpr_free(v);
sexpr_free(k);
return env;
}