return cons(from_uint(n % m), rest);
}
+ Sexpr* a_gt(Sexpr* b, Sexpr* rest, Sexpr* env) {
+ if(ARITH_GT_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);
+#ifdef TYPECHECK
+ if((unquote(i)->type != UINT) || (unquote(j)->type != UINT)) {
+ ERR("%: ", "arguments not uints");
+ sexpr_free(b);
+ sexpr_free(i);
+ sexpr_free(j);
+ return cons(from_nil(), rest);
+ }
+#endif
+ K_UINT_TYPE m = unquote(i)->value.u;
+ K_UINT_TYPE n = unquote(j)->value.u;
+ sexpr_free(b);
+ sexpr_free(i);
+ sexpr_free(j);
+ return cons(m > n ? from_nil(): from_t(), rest);
+}
+
+Sexpr* a_lt(Sexpr* b, Sexpr* rest, Sexpr* env) {
+ if(ARITH_LT_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);
+#ifdef TYPECHECK
+ if((unquote(i)->type != UINT) || (unquote(j)->type != UINT)) {
+ ERR("%: ", "arguments not uints");
+ sexpr_free(b);
+ sexpr_free(i);
+ sexpr_free(j);
+ return cons(from_nil(), rest);
+ }
+#endif
+ K_UINT_TYPE m = unquote(i)->value.u;
+ K_UINT_TYPE n = unquote(j)->value.u;
+ sexpr_free(b);
+ sexpr_free(i);
+ sexpr_free(j);
+ return cons(m < n ? from_nil() : from_t(), rest);
+}
+
Sexpr* x_arith_dispatch(Sexpr* b, Sexpr* rest, Sexpr* env) {
uint64_t code = b->value.b.opcode & 0xff;
return a_div(b, rest, env);
case ARITH_MOD:
return a_mod(b, rest, env);
+ case ARITH_GT:
+ return a_gt(b, rest, env);
+ case ARITH_LT:
+ return a_lt(b, rest, env);
default:
return from_nil();
}
load_builtin(ARITH_MUL_STR, (ARITH_PREFIX << 8) | ARITH_MUL, env);
load_builtin(ARITH_DIV_STR, (ARITH_PREFIX << 8) | ARITH_DIV, env);
load_builtin(ARITH_MOD_STR, (ARITH_PREFIX << 8) | ARITH_MOD, env);
+ load_builtin(ARITH_GT_STR, (ARITH_PREFIX << 8) | ARITH_GT, env);
+ load_builtin(ARITH_LT_STR, (ARITH_PREFIX << 8) | ARITH_LT, env);
return env;
}
#include "dict.h"
#include "eval.h"
#include "builtins.h"
+#include "util.h"
void assert_eq(Sexpr* env, char* a, char* b) {
Sexpr* ap = parse(a);
}
else {
printf("\033[1m\033[31mFAILED\033[0m: %s != %s\n", a, b);
+ printf("got %s and %s\n", ao, bo);
}
sexpr_free(av);
sexpr_free(bv);
void many_asserts() {
Sexpr* env = init_dict();
env = load_env(env);
+ env = load_file(env, "demos.kl");
+ // copy-paste this thing as needed
+ assert_eq(env, "", "");
+
+ printf("basics\n");
assert_eq(env, "(+ 4 4)", "8");
- assert_eq(env, "(* 3 4)", "8");
+ assert_eq(env, "(* 3 4)", "12");
+ assert_eq(env, "((+ 3) 7)", "10");
+ assert_eq(env, "atom 55", "t");
+ assert_eq(env, "atom (quote (1 2 3))", "nil");
+ assert_eq(env, "(cons 1 (cons 2 nil))", "(list 1 2)");
+ // the following two are problems... maybe
+ assert_eq(env, "(car (cons 1 2))","quote 1"); // PROBLEM
+ assert_eq(env, "(cdr (cons 1 2))", "quote 2"); // PROBLEM
+ assert_eq(env, "(eq 1 1)", "t");
+ assert_eq(env, "(eq 1 2)", "nil");
+ assert_eq(env, "(eq 1 (quote 1))", "t"); // PROBLEM
+ assert_eq(env, "eq (cons 1 2) (cons 1 2)", "t");
+ assert_eq(env, "eq (cons 1 2) (cons 1 3)", "nil");
+ assert_eq(env, "eq (quote (1 2)) (cons 1 (cons 2 nil))", "t"); // PROBLEM
+ assert_eq(env, "not 54", "nil");
+ assert_eq(env, "not nil", "t");
+ assert_eq(env, "def asdf 545", "545");
+ assert_eq(env, "asdf", "545");
+ //assert_eq(env, "notyetdefined", "nil"); // it's fine don't worry, just suppressing a message
+ assert_eq(env, "- 100 20", "* 10 8");
+ assert_eq(env, "/ 100 19", "% 13 8");
+
+ printf("combinators\n");
+ assert_eq(env, "I + 4 5", "9");
+ assert_eq(env, "S + (+ 4) 3", "10");
+ assert_eq(env, "K 5 6", "5");
+ assert_eq(env, "K I 5 6", "6");
+ assert_eq(env, "S K I 5", "5");
+ assert_eq(env, "K S (I (S K S I)) + (+ 4) 3", "10");
+ assert_eq(env, "B car cdr (quote (1 2 3))", "quote 2"); // PROBLEM
+ assert_eq(env, "C - 3 10", "7");
+ assert_eq(env, "W * 3", "9");
+ assert_eq(env, "R 5 * 3", "15");
+ assert_eq(env, "t 4 5", "4");
+ assert_eq(env, "nil 4 5", "5");
+ assert_eq(env, "5 (+ 3) 4", "19");
+
+ assert_eq(env, "t (cons 1 2) (cons 2 1)", "(cons 1 2)");
+ assert_eq(env, "(Z (B B S (C (eq 0) 1) (B B S * (C B (C - 1)))) 6)", "720");
+
+
+ printf("strings\n");
+ assert_eq(env, "strlen \"hi\"", "2");
+ assert_eq(env, "strcat \"hi \" \"there\"", "\"hi there\"");
+ assert_eq(env, "strat 5 \"hello world\"", "\"o\"");
+ assert_eq(env, "strexpand \"test\"", "list \"t\" \"e\" \"s\" \"t\"");
+ assert_eq(env, "substr \"oo\" \"looopy", "list 2 3");
+ assert_eq(env, "strtok \" /\" \"this is/a test\"", "list \"this\" \"is\" \"a\" \"test\"");
+
+ printf("meta\n");
+ assert_eq(env, "utob 512", "+");
+ assert_eq(env, "btou +", "512");
+ assert_eq(env, "parse \"cons 4 5\"", "quote (cons 4 5)"); // PROBLEM
+ assert_eq(env, "getargs +", "B car list nil"); // PROBLEM
+ assert_eq(env, "getargs (+ 5)", "list 5");
+
+ printf("with demos\n");
+ assert_eq(env, "fac 5", "120");
+ assert_eq(env, "range 5", "list 1 2 3 4 5");
+ assert_eq(env, "reverse (range 3)", "(list 3 2 1)");
+ assert_eq(env, "nth 5 (range 10)", "5");
+ assert_eq(env, "len (range 10)", "10");
+ assert_eq(env, "map (+ 4) (range 10)", "(list 5 6 7 8 9 10 11 12 13 14)");
+ assert_eq(env, "fold + (range 10)", "55");
+ assert_eq(env, "", "");
+ assert_eq(env, "", "");
+ assert_eq(env, "", "");
+ assert_eq(env, "", "");
+
+
+
sexpr_free(env);
}
void run_tests(){
//isolating_problem();
//test_string_parsing();
- eval_tests();
+ //eval_tests();
many_asserts();
//memtest_eval();
//mem_testing();