From 81a54b5a06f37019544a139e363b058148ba637f Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Wed, 18 May 2022 01:28:49 -0400 Subject: [PATCH] Old .gitignore actually prevent the kraken versions of the benchmarks from being comitted, scarily enough - also some of the c fib tests --- .gitignore | 24 --- fib_test/fib.c | 14 ++ fib_test/fib_let.c | 16 ++ koka_bench/kraken/CMakeLists.txt | 22 +++ koka_bench/kraken/cfold.kp | 244 ++++++++++++++++++++++++ koka_bench/kraken/csc_out.wasm | Bin 0 -> 491613 bytes koka_bench/kraken/deriv.kp | 263 ++++++++++++++++++++++++++ koka_bench/kraken/nqueens.kp | 210 +++++++++++++++++++++ koka_bench/kraken/rbtree-opt.kp | 225 ++++++++++++++++++++++ koka_bench/kraken/rbtree.kp | 309 +++++++++++++++++++++++++++++++ working_files/fib.c | 17 ++ 11 files changed, 1320 insertions(+), 24 deletions(-) create mode 100644 fib_test/fib.c create mode 100644 fib_test/fib_let.c create mode 100644 koka_bench/kraken/CMakeLists.txt create mode 100644 koka_bench/kraken/cfold.kp create mode 100644 koka_bench/kraken/csc_out.wasm create mode 100644 koka_bench/kraken/deriv.kp create mode 100644 koka_bench/kraken/nqueens.kp create mode 100644 koka_bench/kraken/rbtree-opt.kp create mode 100644 koka_bench/kraken/rbtree.kp create mode 100644 working_files/fib.c diff --git a/.gitignore b/.gitignore index e9656d1..ea86051 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,6 @@ _site build build-ninja -*.comp -stats *.swp *.swm *.swn @@ -12,28 +10,6 @@ stats *.swj *.swk *.png -*krakout* -kraklist.txt .*.un~ -papers callgrind* -*.comp_new -*.comp_new.expr -*.comp_bac -bintest.bin -*.dot .stfolder -kraken -*.c -kraken_bac -kraken_deprecated -bootstrap_kalypso -kraken_bootstrap -compiler_version.krak -untracked_misc -k_prime - - -# Added by cargo - -/target diff --git a/fib_test/fib.c b/fib_test/fib.c new file mode 100644 index 0000000..7dd927b --- /dev/null +++ b/fib_test/fib.c @@ -0,0 +1,14 @@ + +int fib(n) { + if (n == 0) { + return 1; + } else if (n == 1) { + return 1; + } else { + return fib(n-1) + fib(n-2); + } +} +int main(int argc, char **argv) { + printf("%d\n", fib(atoi(argv[1]))); + return 0; +} diff --git a/fib_test/fib_let.c b/fib_test/fib_let.c new file mode 100644 index 0000000..85ef649 --- /dev/null +++ b/fib_test/fib_let.c @@ -0,0 +1,16 @@ + +int fib(n) { + if (n == 0) { + return 1; + } else if (n == 1) { + return 1; + } else { + int r1 = fib(n-1); + int r2 = fib(n-2); + return r1 + r2; + } +} +int main(int argc, char **argv) { + printf("%d\n", fib(atoi(argv[1]))); + return 0; +} diff --git a/koka_bench/kraken/CMakeLists.txt b/koka_bench/kraken/CMakeLists.txt new file mode 100644 index 0000000..81f65fe --- /dev/null +++ b/koka_bench/kraken/CMakeLists.txt @@ -0,0 +1,22 @@ +set(sources rbtree.kp rbtree-opt.kp nqueens.kp cfold.kp deriv.kp) + +set(kraken "../../kraken_wrapper.sh") + + +foreach (source IN LISTS sources) + get_filename_component(basename "${source}" NAME_WE) + set(name "kraken-${basename}") + + set(out_dir "${CMAKE_CURRENT_BINARY_DIR}/out/bench") + set(out_path "${out_dir}/${name}") + + add_custom_command( + OUTPUT ${out_path} + COMMAND ${kraken} "${CMAKE_CURRENT_SOURCE_DIR}/${source}" ${out_dir} ${name} + DEPENDS ${source} + VERBATIM) + + add_custom_target(update-${name} ALL DEPENDS "${out_path}") + add_executable(${name}-exe IMPORTED) + set_target_properties(${name}-exe PROPERTIES IMPORTED_LOCATION "${out_path}") +endforeach () diff --git a/koka_bench/kraken/cfold.kp b/koka_bench/kraken/cfold.kp new file mode 100644 index 0000000..526e15b --- /dev/null +++ b/koka_bench/kraken/cfold.kp @@ -0,0 +1,244 @@ +((wrap (vau root_env (quote) +((wrap (vau (let1) +(let1 lambda (vau se (p b1) (wrap (eval (array vau p b1) se))) +(let1 current-env (vau de () de) +(let1 cons (lambda (h t) (concat (array h) t)) +(let1 Y (lambda (f3) + ((lambda (x1) (x1 x1)) + (lambda (x2) (f3 (wrap (vau app_env (& y) (lapply (x2 x2) y app_env))))))) +(let1 vY (lambda (f) + ((lambda (x3) (x3 x3)) + (lambda (x4) (f (vau de1 (& y) (vapply (x4 x4) y de1)))))) +(let1 let (vY (lambda (recurse) (vau de2 (vs b) (cond (= (len vs) 0) (eval b de2) + true (vapply let1 (array (idx vs 0) (idx vs 1) (array recurse (slice vs 2 -1) b)) de2))))) + (let ( + lcompose (lambda (g f) (lambda (& args) (lapply g (array (lapply f args))))) + rec-lambda (vau se (n p b) (eval (array Y (array lambda (array n) (array lambda p b))) se)) + if (vau de (con than & else) (eval (array cond con than + true (cond (> (len else) 0) (idx else 0) + true false)) de)) + + map (lambda (f5 l5) + (let (helper (rec-lambda recurse (f4 l4 n4 i4) + (cond (= i4 (len l4)) n4 + (<= i4 (- (len l4) 4)) (recurse f4 l4 (concat n4 (array + (f4 (idx l4 (+ i4 0))) + (f4 (idx l4 (+ i4 1))) + (f4 (idx l4 (+ i4 2))) + (f4 (idx l4 (+ i4 3))) + )) (+ i4 4)) + true (recurse f4 l4 (concat n4 (array (f4 (idx l4 i4)))) (+ i4 1))))) + (helper f5 l5 (array) 0))) + + + map_i (lambda (f l) + (let (helper (rec-lambda recurse (f l n i) + (cond (= i (len l)) n + (<= i (- (len l) 4)) (recurse f l (concat n (array + (f (+ i 0) (idx l (+ i 0))) + (f (+ i 1) (idx l (+ i 1))) + (f (+ i 2) (idx l (+ i 2))) + (f (+ i 3) (idx l (+ i 3))) + )) (+ i 4)) + true (recurse f l (concat n (array (f i (idx l i)))) (+ i 1))))) + (helper f l (array) 0))) + + filter_i (lambda (f l) + (let (helper (rec-lambda recurse (f l n i) + (if (= i (len l)) + n + (if (f i (idx l i)) (recurse f l (concat n (array (idx l i))) (+ i 1)) + (recurse f l n (+ i 1)))))) + (helper f l (array) 0))) + filter (lambda (f l) (filter_i (lambda (i x) (f x)) l)) + + ; Huge thanks to Oleg Kiselyov for his fantastic website + ; http://okmij.org/ftp/Computation/fixed-point-combinators.html + Y* (lambda (& l) + ((lambda (u) (u u)) + (lambda (p) + (map (lambda (li) (lambda (& x) (lapply (lapply li (p p)) x))) l)))) + vY* (lambda (& l) + ((lambda (u) (u u)) + (lambda (p) + (map (lambda (li) (vau ide (& x) (vapply (lapply li (p p)) x ide))) l)))) + + let-rec (vau de (name_func body) + (let (names (filter_i (lambda (i x) (= 0 (% i 2))) name_func) + funcs (filter_i (lambda (i x) (= 1 (% i 2))) name_func) + overwrite_name (idx name_func (- (len name_func) 2))) + (eval (array let (concat (array overwrite_name (concat (array Y*) (map (lambda (f) (array lambda names f)) funcs))) + (lapply concat (map_i (lambda (i n) (array n (array idx overwrite_name i))) names))) + body) de))) + let-vrec (vau de (name_func body) + (let (names (filter_i (lambda (i x) (= 0 (% i 2))) name_func) + funcs (filter_i (lambda (i x) (= 1 (% i 2))) name_func) + overwrite_name (idx name_func (- (len name_func) 2))) + (eval (array let (concat (array overwrite_name (concat (array vY*) (map (lambda (f) (array lambda names f)) funcs))) + (lapply concat (map_i (lambda (i n) (array n (array idx overwrite_name i))) names))) + body) de))) + + flat_map (lambda (f l) + (let (helper (rec-lambda recurse (f l n i) + (if (= i (len l)) + n + (recurse f l (concat n (f (idx l i))) (+ i 1))))) + (helper f l (array) 0))) + flat_map_i (lambda (f l) + (let (helper (rec-lambda recurse (f l n i) + (if (= i (len l)) + n + (recurse f l (concat n (f i (idx l i))) (+ i 1))))) + (helper f l (array) 0))) + + ; with all this, we make a destrucutring-capable let + let (let ( + destructure_helper (rec-lambda recurse (vs i r) + (cond (= (len vs) i) r + (array? (idx vs i)) (let (bad_sym (str-to-symbol (str (idx vs i))) + new_vs (flat_map_i (lambda (i x) (array x (array idx bad_sym i))) (idx vs i)) + ) + (recurse (concat new_vs (slice vs (+ i 2) -1)) 0 (concat r (array bad_sym (idx vs (+ i 1)))))) + true (recurse vs (+ i 2) (concat r (slice vs i (+ i 2)))) + ))) (vau de (vs b) (vapply let (array (destructure_helper vs 0 (array)) b) de))) + + ; and a destructuring-capable lambda! + only_symbols (rec-lambda recurse (a i) (cond (= i (len a)) true + (symbol? (idx a i)) (recurse a (+ i 1)) + true false)) + + ; Note that if macro_helper is inlined, the mapping lambdas will close over + ; se, and then not be able to be taken in as values to the maps, and the vau + ; will fail to partially evaluate away. + lambda (let (macro_helper (lambda (p b) (let ( + sym_params (map (lambda (param) (if (symbol? param) param + (str-to-symbol (str param)))) p) + body (array let (flat_map_i (lambda (i x) (array (idx p i) x)) sym_params) b) + ) (array vau sym_params body)))) + (vau se (p b) (if (only_symbols p 0) (vapply lambda (array p b) se) + (wrap (eval (macro_helper p b) se))))) + + ; and rec-lambda - yes it's the same definition again + rec-lambda (vau se (n p b) (eval (array Y (array lambda (array n) (array lambda p b))) se)) + + nil (array) + not (lambda (x) (if x false true)) + or (let (macro_helper (rec-lambda recurse (bs i) (cond (= i (len bs)) false + (= (+ 1 i) (len bs)) (idx bs i) + true (array let (array 'tmp (idx bs i)) (array if 'tmp 'tmp (recurse bs (+ i 1))))))) + (vau se (& bs) (eval (macro_helper bs 0) se))) + and (let (macro_helper (rec-lambda recurse (bs i) (cond (= i (len bs)) true + (= (+ 1 i) (len bs)) (idx bs i) + true (array let (array 'tmp (idx bs i)) (array if 'tmp (recurse bs (+ i 1)) 'tmp))))) + (vau se (& bs) (eval (macro_helper bs 0) se))) + + + + foldl (let (helper (rec-lambda recurse (f z vs i) (if (= i (len (idx vs 0))) z + (recurse f (lapply f (cons z (map (lambda (x) (idx x i)) vs))) vs (+ i 1))))) + (lambda (f z & vs) (helper f z vs 0))) + foldr (let (helper (rec-lambda recurse (f z vs i) (if (= i (len (idx vs 0))) z + (lapply f (cons (recurse f z vs (+ i 1)) (map (lambda (x) (idx x i)) vs)))))) + (lambda (f z & vs) (helper f z vs 0))) + reverse (lambda (x) (foldl (lambda (acc i) (cons i acc)) (array) x)) + zip (lambda (& xs) (lapply foldr (concat (array (lambda (a & ys) (cons ys a)) (array)) xs))) + + match (let ( + evaluate_case (rec-lambda evaluate_case (access c) (cond + (symbol? c) (array true (lambda (b) (array let (array c access) b))) + (and (array? c) (= 2 (len c)) (= 'unquote (idx c 0))) (array (array = access (idx c 1)) (lambda (b) b)) + (and (array? c) (= 2 (len c)) (= 'quote (idx c 0))) (array (array = access c) (lambda (b) b)) + (array? c) (let ( + tests (array and (array array? access) (array = (len c) (array len access))) + (tests body_func) ((rec-lambda recurse (tests body_func i) (if (= i (len c)) + (array tests body_func) + (let ( (inner_test inner_body_func) (evaluate_case (array idx access i) (idx c i)) ) + (recurse (concat tests (array inner_test)) + (lambda (b) (body_func (inner_body_func b))) + (+ i 1))))) + tests (lambda (b) b) 0) + ) (array tests body_func)) + true (array (array = access c) (lambda (b) b)) + )) + helper (rec-lambda helper (x_sym cases i) (cond (< i (- (len cases) 1)) (let ( (test body_func) (evaluate_case x_sym (idx cases i)) ) + (concat (array test (body_func (idx cases (+ i 1)))) (helper x_sym cases (+ i 2)))) + true (array true (array error "none matched")))) + ) (vau de (x & cases) (eval (array let (array '___MATCH_SYM x) (concat (array cond) (helper '___MATCH_SYM cases 0))) de))) + + + Var (lambda (x) (array 'Var x)) + Val (lambda (x) (array 'Val x)) + Add (lambda (l r) (array 'Add l r)) + Mul (lambda (l r) (array 'Mul l r)) + + max (lambda (a b) (if (> a b) a b)) + + mk_expr (rec-lambda mk_expr (n v) + (if (= n 0) + (if (= v 0) (Var 1) (Val v)) + (Add (mk_expr (- n 1) (+ v 1)) (mk_expr (- n 1) (max (- v 1) 0))))) + + append_add (rec-lambda append_add (e0 e3) (match e0 + ('Add e1 e2) (Add e1 (append_add e2 e3)) + _ (Add e0 e3) + )) + + append_mul (rec-lambda append_mul (e0 e3) (match e0 + ('Mul e1 e2) (Mul e1 (append_mul e2 e3)) + _ (Mul e0 e3) + )) + + reassoc (rec-lambda reassoc (e) (match e + ('Add e1 e2) (append_add (reassoc e1) (reassoc e2)) + ('Mul e1 e2) (append_mul (reassoc e1) (reassoc e2)) + x x + )) + + cfold (rec-lambda cfold (e) (match e + ('Add l r) (let (lp (cfold l) + rp (cfold r)) + (match lp + ('Val lpv) (match rp + ('Val rpv) (Val (+ lpv rpv)) + ('Add f ('Val b)) (Add (Val (+ lpv b)) f) + ('Add ('Val b) f) (Add (Val (+ lpv b)) f) + rpo (Add lp rpo)) + lpo (Add lpo rp))) + ('Mul l r) (let (lp (cfold l) + rp (cfold r)) + (match lp + ('Val lpv) (match rp + ('Val rpv) (Val (* lpv rpv)) + ('Mul f ('Val b)) (Mul (Val (* lpv b)) f) + ('Mul ('Val b) f) (Mul (Val (* lpv b)) f) + rpo (Mul lp rpo)) + lpo (Mul lpo rp))) + x x + )) + + eval (rec-lambda eval (e) (match e + ('Var x) 0 + ('Val v) v + ('Add l r) (+ (eval l) (eval r)) + ('Mul l r) (* (eval l) (eval r)) + )) + + monad (array 'write 1 (str "running cfold") (vau (written code) + (array 'args (vau (args code) + (array 'exit (let ( + e (mk_expr (read-string (idx args 1)) 1) + v1 (eval e) + v2 (eval (cfold (reassoc e))) + _ (log v1) + _ (log v2) + ) 0)) + )) + )) + + ) monad) +; end of all lets +)))))) +; impl of let1 +)) (vau de (s v b) (eval (array (array wrap (array vau (array s) b)) v) de))) +; impl of quote +)) (vau (x5) x5)) diff --git a/koka_bench/kraken/csc_out.wasm b/koka_bench/kraken/csc_out.wasm new file mode 100644 index 0000000000000000000000000000000000000000..c4b06fb5ca7b55950fe41e1486fe0c15750bc0be GIT binary patch literal 491613 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 literal 0 HcmV?d00001 diff --git a/koka_bench/kraken/deriv.kp b/koka_bench/kraken/deriv.kp new file mode 100644 index 0000000..f6e6c29 --- /dev/null +++ b/koka_bench/kraken/deriv.kp @@ -0,0 +1,263 @@ +((wrap (vau root_env (quote) +((wrap (vau (let1) +(let1 lambda (vau se (p b1) (wrap (eval (array vau p b1) se))) +(let1 current-env (vau de () de) +(let1 cons (lambda (h t) (concat (array h) t)) +(let1 Y (lambda (f3) + ((lambda (x1) (x1 x1)) + (lambda (x2) (f3 (wrap (vau app_env (& y) (lapply (x2 x2) y app_env))))))) +(let1 vY (lambda (f) + ((lambda (x3) (x3 x3)) + (lambda (x4) (f (vau de1 (& y) (vapply (x4 x4) y de1)))))) +(let1 let (vY (lambda (recurse) (vau de2 (vs b) (cond (= (len vs) 0) (eval b de2) + true (vapply let1 (array (idx vs 0) (idx vs 1) (array recurse (slice vs 2 -1) b)) de2))))) + (let ( + lcompose (lambda (g f) (lambda (& args) (lapply g (array (lapply f args))))) + rec-lambda (vau se (n p b) (eval (array Y (array lambda (array n) (array lambda p b))) se)) + if (vau de (con than & else) (eval (array cond con than + true (cond (> (len else) 0) (idx else 0) + true false)) de)) + + map (lambda (f5 l5) + (let (helper (rec-lambda recurse (f4 l4 n4 i4) + (cond (= i4 (len l4)) n4 + (<= i4 (- (len l4) 4)) (recurse f4 l4 (concat n4 (array + (f4 (idx l4 (+ i4 0))) + (f4 (idx l4 (+ i4 1))) + (f4 (idx l4 (+ i4 2))) + (f4 (idx l4 (+ i4 3))) + )) (+ i4 4)) + true (recurse f4 l4 (concat n4 (array (f4 (idx l4 i4)))) (+ i4 1))))) + (helper f5 l5 (array) 0))) + + + map_i (lambda (f l) + (let (helper (rec-lambda recurse (f l n i) + (cond (= i (len l)) n + (<= i (- (len l) 4)) (recurse f l (concat n (array + (f (+ i 0) (idx l (+ i 0))) + (f (+ i 1) (idx l (+ i 1))) + (f (+ i 2) (idx l (+ i 2))) + (f (+ i 3) (idx l (+ i 3))) + )) (+ i 4)) + true (recurse f l (concat n (array (f i (idx l i)))) (+ i 1))))) + (helper f l (array) 0))) + + filter_i (lambda (f l) + (let (helper (rec-lambda recurse (f l n i) + (if (= i (len l)) + n + (if (f i (idx l i)) (recurse f l (concat n (array (idx l i))) (+ i 1)) + (recurse f l n (+ i 1)))))) + (helper f l (array) 0))) + filter (lambda (f l) (filter_i (lambda (i x) (f x)) l)) + + ; Huge thanks to Oleg Kiselyov for his fantastic website + ; http://okmij.org/ftp/Computation/fixed-point-combinators.html + Y* (lambda (& l) + ((lambda (u) (u u)) + (lambda (p) + (map (lambda (li) (lambda (& x) (lapply (lapply li (p p)) x))) l)))) + vY* (lambda (& l) + ((lambda (u) (u u)) + (lambda (p) + (map (lambda (li) (vau ide (& x) (vapply (lapply li (p p)) x ide))) l)))) + + let-rec (vau de (name_func body) + (let (names (filter_i (lambda (i x) (= 0 (% i 2))) name_func) + funcs (filter_i (lambda (i x) (= 1 (% i 2))) name_func) + overwrite_name (idx name_func (- (len name_func) 2))) + (eval (array let (concat (array overwrite_name (concat (array Y*) (map (lambda (f) (array lambda names f)) funcs))) + (lapply concat (map_i (lambda (i n) (array n (array idx overwrite_name i))) names))) + body) de))) + let-vrec (vau de (name_func body) + (let (names (filter_i (lambda (i x) (= 0 (% i 2))) name_func) + funcs (filter_i (lambda (i x) (= 1 (% i 2))) name_func) + overwrite_name (idx name_func (- (len name_func) 2))) + (eval (array let (concat (array overwrite_name (concat (array vY*) (map (lambda (f) (array lambda names f)) funcs))) + (lapply concat (map_i (lambda (i n) (array n (array idx overwrite_name i))) names))) + body) de))) + + flat_map (lambda (f l) + (let (helper (rec-lambda recurse (f l n i) + (if (= i (len l)) + n + (recurse f l (concat n (f (idx l i))) (+ i 1))))) + (helper f l (array) 0))) + flat_map_i (lambda (f l) + (let (helper (rec-lambda recurse (f l n i) + (if (= i (len l)) + n + (recurse f l (concat n (f i (idx l i))) (+ i 1))))) + (helper f l (array) 0))) + + ; with all this, we make a destrucutring-capable let + let (let ( + destructure_helper (rec-lambda recurse (vs i r) + (cond (= (len vs) i) r + (array? (idx vs i)) (let (bad_sym (str-to-symbol (str (idx vs i))) + new_vs (flat_map_i (lambda (i x) (array x (array idx bad_sym i))) (idx vs i)) + ) + (recurse (concat new_vs (slice vs (+ i 2) -1)) 0 (concat r (array bad_sym (idx vs (+ i 1)))))) + true (recurse vs (+ i 2) (concat r (slice vs i (+ i 2)))) + ))) (vau de (vs b) (vapply let (array (destructure_helper vs 0 (array)) b) de))) + + ; and a destructuring-capable lambda! + only_symbols (rec-lambda recurse (a i) (cond (= i (len a)) true + (symbol? (idx a i)) (recurse a (+ i 1)) + true false)) + + ; Note that if macro_helper is inlined, the mapping lambdas will close over + ; se, and then not be able to be taken in as values to the maps, and the vau + ; will fail to partially evaluate away. + lambda (let (macro_helper (lambda (p b) (let ( + sym_params (map (lambda (param) (if (symbol? param) param + (str-to-symbol (str param)))) p) + body (array let (flat_map_i (lambda (i x) (array (idx p i) x)) sym_params) b) + ) (array vau sym_params body)))) + (vau se (p b) (if (only_symbols p 0) (vapply lambda (array p b) se) + (wrap (eval (macro_helper p b) se))))) + + ; and rec-lambda - yes it's the same definition again + rec-lambda (vau se (n p b) (eval (array Y (array lambda (array n) (array lambda p b))) se)) + + nil (array) + not (lambda (x) (if x false true)) + or (let (macro_helper (rec-lambda recurse (bs i) (cond (= i (len bs)) false + (= (+ 1 i) (len bs)) (idx bs i) + true (array let (array 'tmp (idx bs i)) (array if 'tmp 'tmp (recurse bs (+ i 1))))))) + (vau se (& bs) (eval (macro_helper bs 0) se))) + and (let (macro_helper (rec-lambda recurse (bs i) (cond (= i (len bs)) true + (= (+ 1 i) (len bs)) (idx bs i) + true (array let (array 'tmp (idx bs i)) (array if 'tmp (recurse bs (+ i 1)) 'tmp))))) + (vau se (& bs) (eval (macro_helper bs 0) se))) + + + + foldl (let (helper (rec-lambda recurse (f z vs i) (if (= i (len (idx vs 0))) z + (recurse f (lapply f (cons z (map (lambda (x) (idx x i)) vs))) vs (+ i 1))))) + (lambda (f z & vs) (helper f z vs 0))) + foldr (let (helper (rec-lambda recurse (f z vs i) (if (= i (len (idx vs 0))) z + (lapply f (cons (recurse f z vs (+ i 1)) (map (lambda (x) (idx x i)) vs)))))) + (lambda (f z & vs) (helper f z vs 0))) + reverse (lambda (x) (foldl (lambda (acc i) (cons i acc)) (array) x)) + zip (lambda (& xs) (lapply foldr (concat (array (lambda (a & ys) (cons ys a)) (array)) xs))) + + match (let ( + evaluate_case (rec-lambda evaluate_case (access c) (cond + (symbol? c) (array true (lambda (b) (array let (array c access) b))) + (and (array? c) (= 2 (len c)) (= 'unquote (idx c 0))) (array (array = access (idx c 1)) (lambda (b) b)) + (and (array? c) (= 2 (len c)) (= 'quote (idx c 0))) (array (array = access c) (lambda (b) b)) + (array? c) (let ( + tests (array and (array array? access) (array = (len c) (array len access))) + (tests body_func) ((rec-lambda recurse (tests body_func i) (if (= i (len c)) + (array tests body_func) + (let ( (inner_test inner_body_func) (evaluate_case (array idx access i) (idx c i)) ) + (recurse (concat tests (array inner_test)) + (lambda (b) (body_func (inner_body_func b))) + (+ i 1))))) + tests (lambda (b) b) 0) + ) (array tests body_func)) + true (array (array = access c) (lambda (b) b)) + )) + helper (rec-lambda helper (x_sym cases i) (cond (< i (- (len cases) 1)) (let ( (test body_func) (evaluate_case x_sym (idx cases i)) ) + (concat (array test (body_func (idx cases (+ i 1)))) (helper x_sym cases (+ i 2)))) + true (array true (array error "none matched")))) + ) (vau de (x & cases) (eval (array let (array '___MATCH_SYM x) (concat (array cond) (helper '___MATCH_SYM cases 0))) de))) + + + Var (lambda (x) (array 'Var x)) + Val (lambda (x) (array 'Val x)) + Add (lambda (l r) (array 'Add l r)) + Mul (lambda (l r) (array 'Mul l r)) + Pow (lambda (l r) (array 'Pow l r)) + Ln (lambda (e) (array 'Ln e)) + + pown_helper (rec-lambda pown_helper (a b acc) (if (= b 0) acc + (pown_helper a (- b 1) (* a acc)))) + pown (lambda (a b) (pown_helper a b 1)) + + add (rec-lambda add (n0 m0) (match (array n0 m0) + (('Val n) ('Val m)) (Val (+ n m)) + (('Val 0) f) f + (f ('Val 0)) f + (f ('Val n)) (add (Val n) f) + (('Val n) ('Add ('Val m) f)) (add (Val (+ n m)) f) + (f ('Add ('Val n) g)) (add (Val n) (add f g)) + (('Add f g) h) (add f (add g h)) + (f g) (Add f g) + )) + + mul (rec-lambda mul (n0 m0) (match (array n0 m0) + (('Val n) ('Val m)) (Val (* n m)) + (('Val 0) _) (Val 0) + (_ ('Val 0)) (Val 0) + (f ('Val 1)) f + (('Val 1) f) f + + (f ('Val n)) (mul (Val n) f) + (('Val n) ('Mul ('Val m) f)) (mul (Val (* n m)) f) + (f ('Mul ('Val n) g)) (mul (Val n) (mul f g)) + (('Mul f g) h) (mul f (mul g h)) + (f g) (Mul f g) + )) + + powr (lambda (m0 n0) (match (array m0 n0) + (('Val m) ('Val n)) (Val (pown m n)) + (_ ('Val 0)) (Val 1) + (f ('Val 1)) f + (('Val 0) _) (Val 0) + (f g) (Pow f g) + )) + + ln (lambda (n) (match n + ('Val 1) (Val 0) + f (Ln f) + )) + + d (rec-lambda d (x e) (match e + ('Val _) (Val 0) + ('Var y) (if (= x y) (Val 1) (Val 0)) + ('Add f g) (add (d x f) (d x g)) + ('Mul f g) (add (mul f (d x g)) (mul g (d x f))) + ('Pow f g) (mul (powr f g) (add (mul (mul g (d x f)) (powr f (Val -1))) (mul (ln f) (d x g)))) + ('Ln f) (mul (d x f) (powr f (Val -1))) + )) + + count (rec-lambda count (e) (match e + ('Val _) 1 + ('Var y) 1 + ('Add f g) (+ (count f) (count g)) + ('Mul f g) (+ (count f) (count g)) + ('Pow f g) (+ (count f) (count g)) + ('Ln f) (count f) + )) + + nest_aux (rec-lambda nest_aux (s f n x) (if (= n 0) x + (nest_aux s f (- n 1) (f (- s n) x)))) + nest (lambda (f n e) (nest_aux n f n e)) + + deriv (lambda (i f) (let (d (d "x" f) + _ (log (+ i 1) " count: " (count d)) + ) d)) + + + monad (array 'write 1 (str "running deriv") (vau (written code) + (array 'args (vau (args code) + (array 'exit (let ( + n (read-string (idx args 1)) + x (Var "x") + f (powr x x) + _ (log (nest deriv n f)) + _ (log "done") + ) 0)) + )) + )) + + ) monad) +; end of all lets +)))))) +; impl of let1 +)) (vau de (s v b) (eval (array (array wrap (array vau (array s) b)) v) de))) +; impl of quote +)) (vau (x5) x5)) diff --git a/koka_bench/kraken/nqueens.kp b/koka_bench/kraken/nqueens.kp new file mode 100644 index 0000000..f3fd382 --- /dev/null +++ b/koka_bench/kraken/nqueens.kp @@ -0,0 +1,210 @@ +((wrap (vau root_env (quote) +((wrap (vau (let1) +(let1 lambda (vau se (p b1) (wrap (eval (array vau p b1) se))) +(let1 current-env (vau de () de) +(let1 cons (lambda (h t) (concat (array h) t)) +(let1 Y (lambda (f3) + ((lambda (x1) (x1 x1)) + (lambda (x2) (f3 (wrap (vau app_env (& y) (lapply (x2 x2) y app_env))))))) +(let1 vY (lambda (f) + ((lambda (x3) (x3 x3)) + (lambda (x4) (f (vau de1 (& y) (vapply (x4 x4) y de1)))))) +(let1 let (vY (lambda (recurse) (vau de2 (vs b) (cond (= (len vs) 0) (eval b de2) + true (vapply let1 (array (idx vs 0) (idx vs 1) (array recurse (slice vs 2 -1) b)) de2))))) + (let ( + lcompose (lambda (g f) (lambda (& args) (lapply g (array (lapply f args))))) + rec-lambda (vau se (n p b) (eval (array Y (array lambda (array n) (array lambda p b))) se)) + if (vau de (con than & else) (eval (array cond con than + true (cond (> (len else) 0) (idx else 0) + true false)) de)) + + map (lambda (f5 l5) + (let (helper (rec-lambda recurse (f4 l4 n4 i4) + (cond (= i4 (len l4)) n4 + (<= i4 (- (len l4) 4)) (recurse f4 l4 (concat n4 (array + (f4 (idx l4 (+ i4 0))) + (f4 (idx l4 (+ i4 1))) + (f4 (idx l4 (+ i4 2))) + (f4 (idx l4 (+ i4 3))) + )) (+ i4 4)) + true (recurse f4 l4 (concat n4 (array (f4 (idx l4 i4)))) (+ i4 1))))) + (helper f5 l5 (array) 0))) + + + map_i (lambda (f l) + (let (helper (rec-lambda recurse (f l n i) + (cond (= i (len l)) n + (<= i (- (len l) 4)) (recurse f l (concat n (array + (f (+ i 0) (idx l (+ i 0))) + (f (+ i 1) (idx l (+ i 1))) + (f (+ i 2) (idx l (+ i 2))) + (f (+ i 3) (idx l (+ i 3))) + )) (+ i 4)) + true (recurse f l (concat n (array (f i (idx l i)))) (+ i 1))))) + (helper f l (array) 0))) + + filter_i (lambda (f l) + (let (helper (rec-lambda recurse (f l n i) + (if (= i (len l)) + n + (if (f i (idx l i)) (recurse f l (concat n (array (idx l i))) (+ i 1)) + (recurse f l n (+ i 1)))))) + (helper f l (array) 0))) + filter (lambda (f l) (filter_i (lambda (i x) (f x)) l)) + + ; Huge thanks to Oleg Kiselyov for his fantastic website + ; http://okmij.org/ftp/Computation/fixed-point-combinators.html + Y* (lambda (& l) + ((lambda (u) (u u)) + (lambda (p) + (map (lambda (li) (lambda (& x) (lapply (lapply li (p p)) x))) l)))) + vY* (lambda (& l) + ((lambda (u) (u u)) + (lambda (p) + (map (lambda (li) (vau ide (& x) (vapply (lapply li (p p)) x ide))) l)))) + + let-rec (vau de (name_func body) + (let (names (filter_i (lambda (i x) (= 0 (% i 2))) name_func) + funcs (filter_i (lambda (i x) (= 1 (% i 2))) name_func) + overwrite_name (idx name_func (- (len name_func) 2))) + (eval (array let (concat (array overwrite_name (concat (array Y*) (map (lambda (f) (array lambda names f)) funcs))) + (lapply concat (map_i (lambda (i n) (array n (array idx overwrite_name i))) names))) + body) de))) + let-vrec (vau de (name_func body) + (let (names (filter_i (lambda (i x) (= 0 (% i 2))) name_func) + funcs (filter_i (lambda (i x) (= 1 (% i 2))) name_func) + overwrite_name (idx name_func (- (len name_func) 2))) + (eval (array let (concat (array overwrite_name (concat (array vY*) (map (lambda (f) (array lambda names f)) funcs))) + (lapply concat (map_i (lambda (i n) (array n (array idx overwrite_name i))) names))) + body) de))) + + flat_map (lambda (f l) + (let (helper (rec-lambda recurse (f l n i) + (if (= i (len l)) + n + (recurse f l (concat n (f (idx l i))) (+ i 1))))) + (helper f l (array) 0))) + flat_map_i (lambda (f l) + (let (helper (rec-lambda recurse (f l n i) + (if (= i (len l)) + n + (recurse f l (concat n (f i (idx l i))) (+ i 1))))) + (helper f l (array) 0))) + + ; with all this, we make a destrucutring-capable let + let (let ( + destructure_helper (rec-lambda recurse (vs i r) + (cond (= (len vs) i) r + (array? (idx vs i)) (let (bad_sym (str-to-symbol (str (idx vs i))) + new_vs (flat_map_i (lambda (i x) (array x (array idx bad_sym i))) (idx vs i)) + ) + (recurse (concat new_vs (slice vs (+ i 2) -1)) 0 (concat r (array bad_sym (idx vs (+ i 1)))))) + true (recurse vs (+ i 2) (concat r (slice vs i (+ i 2)))) + ))) (vau de (vs b) (vapply let (array (destructure_helper vs 0 (array)) b) de))) + + ; and a destructuring-capable lambda! + only_symbols (rec-lambda recurse (a i) (cond (= i (len a)) true + (symbol? (idx a i)) (recurse a (+ i 1)) + true false)) + + ; Note that if macro_helper is inlined, the mapping lambdas will close over + ; se, and then not be able to be taken in as values to the maps, and the vau + ; will fail to partially evaluate away. + lambda (let (macro_helper (lambda (p b) (let ( + sym_params (map (lambda (param) (if (symbol? param) param + (str-to-symbol (str param)))) p) + body (array let (flat_map_i (lambda (i x) (array (idx p i) x)) sym_params) b) + ) (array vau sym_params body)))) + (vau se (p b) (if (only_symbols p 0) (vapply lambda (array p b) se) + (wrap (eval (macro_helper p b) se))))) + + ; and rec-lambda - yes it's the same definition again + rec-lambda (vau se (n p b) (eval (array Y (array lambda (array n) (array lambda p b))) se)) + + nil (array) + not (lambda (x) (if x false true)) + or (let (macro_helper (rec-lambda recurse (bs i) (cond (= i (len bs)) false + (= (+ 1 i) (len bs)) (idx bs i) + true (array let (array 'tmp (idx bs i)) (array if 'tmp 'tmp (recurse bs (+ i 1))))))) + (vau se (& bs) (eval (macro_helper bs 0) se))) + and (let (macro_helper (rec-lambda recurse (bs i) (cond (= i (len bs)) true + (= (+ 1 i) (len bs)) (idx bs i) + true (array let (array 'tmp (idx bs i)) (array if 'tmp (recurse bs (+ i 1)) 'tmp))))) + (vau se (& bs) (eval (macro_helper bs 0) se))) + + + + foldl (let (helper (rec-lambda recurse (f z vs i) (if (= i (len (idx vs 0))) z + (recurse f (lapply f (cons z (map (lambda (x) (idx x i)) vs))) vs (+ i 1))))) + (lambda (f z & vs) (helper f z vs 0))) + foldr (let (helper (rec-lambda recurse (f z vs i) (if (= i (len (idx vs 0))) z + (lapply f (cons (recurse f z vs (+ i 1)) (map (lambda (x) (idx x i)) vs)))))) + (lambda (f z & vs) (helper f z vs 0))) + reverse (lambda (x) (foldl (lambda (acc i) (cons i acc)) (array) x)) + zip (lambda (& xs) (lapply foldr (concat (array (lambda (a & ys) (cons ys a)) (array)) xs))) + + match (let ( + evaluate_case (rec-lambda evaluate_case (access c) (cond + (symbol? c) (array true (lambda (b) (array let (array c access) b))) + (and (array? c) (= 2 (len c)) (= 'unquote (idx c 0))) (array (array = access (idx c 1)) (lambda (b) b)) + (and (array? c) (= 2 (len c)) (= 'quote (idx c 0))) (array (array = access c) (lambda (b) b)) + (array? c) (let ( + tests (array and (array array? access) (array = (len c) (array len access))) + (tests body_func) ((rec-lambda recurse (tests body_func i) (if (= i (len c)) + (array tests body_func) + (let ( (inner_test inner_body_func) (evaluate_case (array idx access i) (idx c i)) ) + (recurse (concat tests (array inner_test)) + (lambda (b) (body_func (inner_body_func b))) + (+ i 1))))) + tests (lambda (b) b) 0) + ) (array tests body_func)) + true (array (array = access c) (lambda (b) b)) + )) + helper (rec-lambda helper (x_sym cases i) (cond (< i (- (len cases) 1)) (let ( (test body_func) (evaluate_case x_sym (idx cases i)) ) + (concat (array test (body_func (idx cases (+ i 1)))) (helper x_sym cases (+ i 2)))) + true (array true (array error "none matched")))) + ) (vau de (x & cases) (eval (array let (array '___MATCH_SYM x) (concat (array cond) (helper '___MATCH_SYM cases 0))) de))) + + + safe (rec-lambda safe (queen diag i xs) + (if (= i (len xs)) + true + (let ( q (idx xs i) ) + (and (!= queen q) + (!= queen (+ q diag)) + (!= queen (- q diag)) + (safe queen (+ diag 1) (+ i 1) xs))))) + append-safe (rec-lambda append-safe (queen xs xss) + (cond (<= queen 0) xss + (safe queen 1 0 xs) (append-safe (- queen 1) + xs + (cons (cons queen xs) xss)) + true (append-safe (- queen 1) xs xss))) + extend (rec-lambda extend (queen acc xss i) + (if (= i (len xss)) + acc + (extend queen + (append-safe queen (idx xss i) acc) + xss + (+ i 1)))) + + find-solutions (rec-lambda find-solutions (n queen) + (if (= 0 queen) + (array nil) + (extend n nil (find-solutions n (- queen 1)) 0))) + nqueens (lambda (n) (len (find-solutions n n))) + + + monad (array 'write 1 (str "running nqueens") (vau (written code) + (array 'args (vau (args code) + (array 'exit (log (nqueens (read-string (idx args 1))))) + )) + )) + + ) monad) +; end of all lets +)))))) +; impl of let1 +)) (vau de (s v b) (eval (array (array wrap (array vau (array s) b)) v) de))) +; impl of quote +)) (vau (x5) x5)) diff --git a/koka_bench/kraken/rbtree-opt.kp b/koka_bench/kraken/rbtree-opt.kp new file mode 100644 index 0000000..90c79c3 --- /dev/null +++ b/koka_bench/kraken/rbtree-opt.kp @@ -0,0 +1,225 @@ +((wrap (vau root_env (quote) +((wrap (vau (let1) +(let1 lambda (vau se (p b1) (wrap (eval (array vau p b1) se))) +(let1 current-env (vau de () de) +(let1 cons (lambda (h t) (concat (array h) t)) +(let1 Y (lambda (f3) + ((lambda (x1) (x1 x1)) + (lambda (x2) (f3 (wrap (vau app_env (& y) (lapply (x2 x2) y app_env))))))) +(let1 vY (lambda (f) + ((lambda (x3) (x3 x3)) + (lambda (x4) (f (vau de1 (& y) (vapply (x4 x4) y de1)))))) +(let1 let (vY (lambda (recurse) (vau de2 (vs b) (cond (= (len vs) 0) (eval b de2) + true (vapply let1 (array (idx vs 0) (idx vs 1) (array recurse (slice vs 2 -1) b)) de2))))) + (let ( + lcompose (lambda (g f) (lambda (& args) (lapply g (array (lapply f args))))) + rec-lambda (vau se (n p b) (eval (array Y (array lambda (array n) (array lambda p b))) se)) + if (vau de (con than & else) (eval (array cond con than + true (cond (> (len else) 0) (idx else 0) + true false)) de)) + + map (lambda (f5 l5) + (let (helper (rec-lambda recurse (f4 l4 n4 i4) + (cond (= i4 (len l4)) n4 + (<= i4 (- (len l4) 4)) (recurse f4 l4 (concat n4 (array + (f4 (idx l4 (+ i4 0))) + (f4 (idx l4 (+ i4 1))) + (f4 (idx l4 (+ i4 2))) + (f4 (idx l4 (+ i4 3))) + )) (+ i4 4)) + true (recurse f4 l4 (concat n4 (array (f4 (idx l4 i4)))) (+ i4 1))))) + (helper f5 l5 (array) 0))) + + + map_i (lambda (f l) + (let (helper (rec-lambda recurse (f l n i) + (cond (= i (len l)) n + (<= i (- (len l) 4)) (recurse f l (concat n (array + (f (+ i 0) (idx l (+ i 0))) + (f (+ i 1) (idx l (+ i 1))) + (f (+ i 2) (idx l (+ i 2))) + (f (+ i 3) (idx l (+ i 3))) + )) (+ i 4)) + true (recurse f l (concat n (array (f i (idx l i)))) (+ i 1))))) + (helper f l (array) 0))) + + filter_i (lambda (f l) + (let (helper (rec-lambda recurse (f l n i) + (if (= i (len l)) + n + (if (f i (idx l i)) (recurse f l (concat n (array (idx l i))) (+ i 1)) + (recurse f l n (+ i 1)))))) + (helper f l (array) 0))) + filter (lambda (f l) (filter_i (lambda (i x) (f x)) l)) + + ; Huge thanks to Oleg Kiselyov for his fantastic website + ; http://okmij.org/ftp/Computation/fixed-point-combinators.html + Y* (lambda (& l) + ((lambda (u) (u u)) + (lambda (p) + (map (lambda (li) (lambda (& x) (lapply (lapply li (p p)) x))) l)))) + vY* (lambda (& l) + ((lambda (u) (u u)) + (lambda (p) + (map (lambda (li) (vau ide (& x) (vapply (lapply li (p p)) x ide))) l)))) + + let-rec (vau de (name_func body) + (let (names (filter_i (lambda (i x) (= 0 (% i 2))) name_func) + funcs (filter_i (lambda (i x) (= 1 (% i 2))) name_func) + overwrite_name (idx name_func (- (len name_func) 2))) + (eval (array let (concat (array overwrite_name (concat (array Y*) (map (lambda (f) (array lambda names f)) funcs))) + (lapply concat (map_i (lambda (i n) (array n (array idx overwrite_name i))) names))) + body) de))) + let-vrec (vau de (name_func body) + (let (names (filter_i (lambda (i x) (= 0 (% i 2))) name_func) + funcs (filter_i (lambda (i x) (= 1 (% i 2))) name_func) + overwrite_name (idx name_func (- (len name_func) 2))) + (eval (array let (concat (array overwrite_name (concat (array vY*) (map (lambda (f) (array lambda names f)) funcs))) + (lapply concat (map_i (lambda (i n) (array n (array idx overwrite_name i))) names))) + body) de))) + + flat_map (lambda (f l) + (let (helper (rec-lambda recurse (f l n i) + (if (= i (len l)) + n + (recurse f l (concat n (f (idx l i))) (+ i 1))))) + (helper f l (array) 0))) + flat_map_i (lambda (f l) + (let (helper (rec-lambda recurse (f l n i) + (if (= i (len l)) + n + (recurse f l (concat n (f i (idx l i))) (+ i 1))))) + (helper f l (array) 0))) + + ; with all this, we make a destrucutring-capable let + let (let ( + destructure_helper (rec-lambda recurse (vs i r) + (cond (= (len vs) i) r + (array? (idx vs i)) (let (bad_sym (str-to-symbol (str (idx vs i))) + new_vs (flat_map_i (lambda (i x) (array x (array idx bad_sym i))) (idx vs i)) + ) + (recurse (concat new_vs (slice vs (+ i 2) -1)) 0 (concat r (array bad_sym (idx vs (+ i 1)))))) + true (recurse vs (+ i 2) (concat r (slice vs i (+ i 2)))) + ))) (vau de (vs b) (vapply let (array (destructure_helper vs 0 (array)) b) de))) + + ; and a destructuring-capable lambda! + only_symbols (rec-lambda recurse (a i) (cond (= i (len a)) true + (symbol? (idx a i)) (recurse a (+ i 1)) + true false)) + + ; Note that if macro_helper is inlined, the mapping lambdas will close over + ; se, and then not be able to be taken in as values to the maps, and the vau + ; will fail to partially evaluate away. + lambda (let (macro_helper (lambda (p b) (let ( + sym_params (map (lambda (param) (if (symbol? param) param + (str-to-symbol (str param)))) p) + body (array let (flat_map_i (lambda (i x) (array (idx p i) x)) sym_params) b) + ) (array vau sym_params body)))) + (vau se (p b) (if (only_symbols p 0) (vapply lambda (array p b) se) + (wrap (eval (macro_helper p b) se))))) + + ; and rec-lambda - yes it's the same definition again + rec-lambda (vau se (n p b) (eval (array Y (array lambda (array n) (array lambda p b))) se)) + + nil (array) + not (lambda (x) (if x false true)) + or (let (macro_helper (rec-lambda recurse (bs i) (cond (= i (len bs)) false + (= (+ 1 i) (len bs)) (idx bs i) + true (array let (array 'tmp (idx bs i)) (array if 'tmp 'tmp (recurse bs (+ i 1))))))) + (vau se (& bs) (eval (macro_helper bs 0) se))) + and (let (macro_helper (rec-lambda recurse (bs i) (cond (= i (len bs)) true + (= (+ 1 i) (len bs)) (idx bs i) + true (array let (array 'tmp (idx bs i)) (array if 'tmp (recurse bs (+ i 1)) 'tmp))))) + (vau se (& bs) (eval (macro_helper bs 0) se))) + + + + foldl (let (helper (rec-lambda recurse (f z vs i) (if (= i (len (idx vs 0))) z + (recurse f (lapply f (cons z (map (lambda (x) (idx x i)) vs))) vs (+ i 1))))) + (lambda (f z & vs) (helper f z vs 0))) + foldr (let (helper (rec-lambda recurse (f z vs i) (if (= i (len (idx vs 0))) z + (lapply f (cons (recurse f z vs (+ i 1)) (map (lambda (x) (idx x i)) vs)))))) + (lambda (f z & vs) (helper f z vs 0))) + reverse (lambda (x) (foldl (lambda (acc i) (cons i acc)) (array) x)) + zip (lambda (& xs) (lapply foldr (concat (array (lambda (a & ys) (cons ys a)) (array)) xs))) + + match (let ( + evaluate_case (rec-lambda evaluate_case (access c) (cond + (symbol? c) (array true (lambda (b) (array let (array c access) b))) + (and (array? c) (= 2 (len c)) (= 'unquote (idx c 0))) (array (array = access (idx c 1)) (lambda (b) b)) + (and (array? c) (= 2 (len c)) (= 'quote (idx c 0))) (array (array = access c) (lambda (b) b)) + (array? c) (let ( + tests (array and (array array? access) (array = (len c) (array len access))) + (tests body_func) ((rec-lambda recurse (tests body_func i) (if (= i (len c)) + (array tests body_func) + (let ( (inner_test inner_body_func) (evaluate_case (array idx access i) (idx c i)) ) + (recurse (concat tests (array inner_test)) + (lambda (b) (body_func (inner_body_func b))) + (+ i 1))))) + tests (lambda (b) b) 0) + ) (array tests body_func)) + true (array (array = access c) (lambda (b) b)) + )) + helper (rec-lambda helper (x_sym cases i) (cond (< i (- (len cases) 1)) (let ( (test body_func) (evaluate_case x_sym (idx cases i)) ) + (concat (array test (body_func (idx cases (+ i 1)))) (helper x_sym cases (+ i 2)))) + true (array true (array error "none matched")))) + ) (vau de (x & cases) (eval (array let (array '___MATCH_SYM x) (concat (array cond) (helper '___MATCH_SYM cases 0))) de))) + + ; This is based on https://www.cs.cornell.edu/courses/cs3110/2020sp/a4/deletion.pdf + ; and the figure references refer to it + ; Insert is taken from the same paper, but is origional to Okasaki, I belive + + ; The tree has been modified slightly to take in a comparison function + ; and override if insert replaces or not to allow use as a set or as a map + + ; I think this is actually pretty cool - instead of having a bunch of seperate ['B] + ; be our leaf node, we use ['B] with all nils. This allows us to not use -B, as + ; both leaf and non-leaf 'BB has the same structure with children! Also, we make + ; sure to use empty itself so we don't make a ton of empties... + empty (array 'B nil nil nil) + E empty + EE (array 'BB nil nil nil) + + generic-foldl (rec-lambda recurse (f z t) (match t + ,E z + (c a x b) (recurse f (f (recurse f z a) x) b))) + + blacken (lambda (t) (match t + ('R a x b) (array 'B a x b) + t t)) + balance (lambda (t) (match t + ; figures 1 and 2 + ('B ('R ('R a x b) y c) z d) (array 'R (array 'B a x b) y (array 'B c z d)) + ('B ('R a x ('R b y c)) z d) (array 'R (array 'B a x b) y (array 'B c z d)) + ('B a x ('R ('R b y c) z d)) (array 'R (array 'B a x b) y (array 'B c z d)) + ('B a x ('R b y ('R c z d))) (array 'R (array 'B a x b) y (array 'B c z d)) + ; figure 8, double black cases + ('BB ('R a x ('R b y c)) z d) (array 'B (array 'B a x b) y (array 'B c z d)) + ('BB a x ('R ('R b y c) z d)) (array 'B (array 'B a x b) y (array 'B c z d)) + ; already balenced + t t)) + map-insert (lambda (t k v) (blacken ((rec-lambda ins (t) (match t + ,E (array 'R t (array k v) t) + (c a x b) (cond (< k (idx x 0)) (balance (array c (ins a) x b)) + (= k (idx x 0)) (array c a (array k v) b) + true (balance (array c a x (ins b)))))) t))) + + map-empty empty + + make-test-tree (rec-lambda make-test-tree (n t) (cond (<= n 0) t + true (make-test-tree (- n 1) (map-insert t n (= 0 (% n 10)))))) + reduce-test-tree (lambda (tree) (generic-foldl (lambda (a x) (if (idx x 1) (+ a 1) a)) 0 tree)) + + monad (array 'write 1 (str "running tree test") (vau (written code) + (array 'args (vau (args code) + (array 'exit (log (reduce-test-tree (make-test-tree (read-string (idx args 1)) map-empty)))) + )) + )) + + ) monad) +; end of all lets +)))))) +; impl of let1 +)) (vau de (s v b) (eval (array (array wrap (array vau (array s) b)) v) de))) +; impl of quote +)) (vau (x5) x5)) diff --git a/koka_bench/kraken/rbtree.kp b/koka_bench/kraken/rbtree.kp new file mode 100644 index 0000000..33808e1 --- /dev/null +++ b/koka_bench/kraken/rbtree.kp @@ -0,0 +1,309 @@ +((wrap (vau root_env (quote) +((wrap (vau (let1) +(let1 lambda (vau se (p b1) (wrap (eval (array vau p b1) se))) +(let1 current-env (vau de () de) +(let1 cons (lambda (h t) (concat (array h) t)) +(let1 Y (lambda (f3) + ((lambda (x1) (x1 x1)) + (lambda (x2) (f3 (wrap (vau app_env (& y) (lapply (x2 x2) y app_env))))))) +(let1 vY (lambda (f) + ((lambda (x3) (x3 x3)) + (lambda (x4) (f (vau de1 (& y) (vapply (x4 x4) y de1)))))) +(let1 let (vY (lambda (recurse) (vau de2 (vs b) (cond (= (len vs) 0) (eval b de2) + true (vapply let1 (array (idx vs 0) (idx vs 1) (array recurse (slice vs 2 -1) b)) de2))))) + (let ( + lcompose (lambda (g f) (lambda (& args) (lapply g (array (lapply f args))))) + rec-lambda (vau se (n p b) (eval (array Y (array lambda (array n) (array lambda p b))) se)) + if (vau de (con than & else) (eval (array cond con than + true (cond (> (len else) 0) (idx else 0) + true false)) de)) + + map (lambda (f5 l5) + (let (helper (rec-lambda recurse (f4 l4 n4 i4) + (cond (= i4 (len l4)) n4 + (<= i4 (- (len l4) 4)) (recurse f4 l4 (concat n4 (array + (f4 (idx l4 (+ i4 0))) + (f4 (idx l4 (+ i4 1))) + (f4 (idx l4 (+ i4 2))) + (f4 (idx l4 (+ i4 3))) + )) (+ i4 4)) + true (recurse f4 l4 (concat n4 (array (f4 (idx l4 i4)))) (+ i4 1))))) + (helper f5 l5 (array) 0))) + + + map_i (lambda (f l) + (let (helper (rec-lambda recurse (f l n i) + (cond (= i (len l)) n + (<= i (- (len l) 4)) (recurse f l (concat n (array + (f (+ i 0) (idx l (+ i 0))) + (f (+ i 1) (idx l (+ i 1))) + (f (+ i 2) (idx l (+ i 2))) + (f (+ i 3) (idx l (+ i 3))) + )) (+ i 4)) + true (recurse f l (concat n (array (f i (idx l i)))) (+ i 1))))) + (helper f l (array) 0))) + + filter_i (lambda (f l) + (let (helper (rec-lambda recurse (f l n i) + (if (= i (len l)) + n + (if (f i (idx l i)) (recurse f l (concat n (array (idx l i))) (+ i 1)) + (recurse f l n (+ i 1)))))) + (helper f l (array) 0))) + filter (lambda (f l) (filter_i (lambda (i x) (f x)) l)) + + ; Huge thanks to Oleg Kiselyov for his fantastic website + ; http://okmij.org/ftp/Computation/fixed-point-combinators.html + Y* (lambda (& l) + ((lambda (u) (u u)) + (lambda (p) + (map (lambda (li) (lambda (& x) (lapply (lapply li (p p)) x))) l)))) + vY* (lambda (& l) + ((lambda (u) (u u)) + (lambda (p) + (map (lambda (li) (vau ide (& x) (vapply (lapply li (p p)) x ide))) l)))) + + let-rec (vau de (name_func body) + (let (names (filter_i (lambda (i x) (= 0 (% i 2))) name_func) + funcs (filter_i (lambda (i x) (= 1 (% i 2))) name_func) + overwrite_name (idx name_func (- (len name_func) 2))) + (eval (array let (concat (array overwrite_name (concat (array Y*) (map (lambda (f) (array lambda names f)) funcs))) + (lapply concat (map_i (lambda (i n) (array n (array idx overwrite_name i))) names))) + body) de))) + let-vrec (vau de (name_func body) + (let (names (filter_i (lambda (i x) (= 0 (% i 2))) name_func) + funcs (filter_i (lambda (i x) (= 1 (% i 2))) name_func) + overwrite_name (idx name_func (- (len name_func) 2))) + (eval (array let (concat (array overwrite_name (concat (array vY*) (map (lambda (f) (array lambda names f)) funcs))) + (lapply concat (map_i (lambda (i n) (array n (array idx overwrite_name i))) names))) + body) de))) + + flat_map (lambda (f l) + (let (helper (rec-lambda recurse (f l n i) + (if (= i (len l)) + n + (recurse f l (concat n (f (idx l i))) (+ i 1))))) + (helper f l (array) 0))) + flat_map_i (lambda (f l) + (let (helper (rec-lambda recurse (f l n i) + (if (= i (len l)) + n + (recurse f l (concat n (f i (idx l i))) (+ i 1))))) + (helper f l (array) 0))) + + ; with all this, we make a destrucutring-capable let + let (let ( + destructure_helper (rec-lambda recurse (vs i r) + (cond (= (len vs) i) r + (array? (idx vs i)) (let (bad_sym (str-to-symbol (str (idx vs i))) + new_vs (flat_map_i (lambda (i x) (array x (array idx bad_sym i))) (idx vs i)) + ) + (recurse (concat new_vs (slice vs (+ i 2) -1)) 0 (concat r (array bad_sym (idx vs (+ i 1)))))) + true (recurse vs (+ i 2) (concat r (slice vs i (+ i 2)))) + ))) (vau de (vs b) (vapply let (array (destructure_helper vs 0 (array)) b) de))) + + ; and a destructuring-capable lambda! + only_symbols (rec-lambda recurse (a i) (cond (= i (len a)) true + (symbol? (idx a i)) (recurse a (+ i 1)) + true false)) + + ; Note that if macro_helper is inlined, the mapping lambdas will close over + ; se, and then not be able to be taken in as values to the maps, and the vau + ; will fail to partially evaluate away. + lambda (let (macro_helper (lambda (p b) (let ( + sym_params (map (lambda (param) (if (symbol? param) param + (str-to-symbol (str param)))) p) + body (array let (flat_map_i (lambda (i x) (array (idx p i) x)) sym_params) b) + ) (array vau sym_params body)))) + (vau se (p b) (if (only_symbols p 0) (vapply lambda (array p b) se) + (wrap (eval (macro_helper p b) se))))) + + ; and rec-lambda - yes it's the same definition again + rec-lambda (vau se (n p b) (eval (array Y (array lambda (array n) (array lambda p b))) se)) + + nil (array) + not (lambda (x) (if x false true)) + or (let (macro_helper (rec-lambda recurse (bs i) (cond (= i (len bs)) false + (= (+ 1 i) (len bs)) (idx bs i) + true (array let (array 'tmp (idx bs i)) (array if 'tmp 'tmp (recurse bs (+ i 1))))))) + (vau se (& bs) (eval (macro_helper bs 0) se))) + and (let (macro_helper (rec-lambda recurse (bs i) (cond (= i (len bs)) true + (= (+ 1 i) (len bs)) (idx bs i) + true (array let (array 'tmp (idx bs i)) (array if 'tmp (recurse bs (+ i 1)) 'tmp))))) + (vau se (& bs) (eval (macro_helper bs 0) se))) + + + + foldl (let (helper (rec-lambda recurse (f z vs i) (if (= i (len (idx vs 0))) z + (recurse f (lapply f (cons z (map (lambda (x) (idx x i)) vs))) vs (+ i 1))))) + (lambda (f z & vs) (helper f z vs 0))) + foldr (let (helper (rec-lambda recurse (f z vs i) (if (= i (len (idx vs 0))) z + (lapply f (cons (recurse f z vs (+ i 1)) (map (lambda (x) (idx x i)) vs)))))) + (lambda (f z & vs) (helper f z vs 0))) + reverse (lambda (x) (foldl (lambda (acc i) (cons i acc)) (array) x)) + zip (lambda (& xs) (lapply foldr (concat (array (lambda (a & ys) (cons ys a)) (array)) xs))) + + match (let ( + evaluate_case (rec-lambda evaluate_case (access c) (cond + (symbol? c) (array true (lambda (b) (array let (array c access) b))) + (and (array? c) (= 2 (len c)) (= 'unquote (idx c 0))) (array (array = access (idx c 1)) (lambda (b) b)) + (and (array? c) (= 2 (len c)) (= 'quote (idx c 0))) (array (array = access c) (lambda (b) b)) + (array? c) (let ( + tests (array and (array array? access) (array = (len c) (array len access))) + (tests body_func) ((rec-lambda recurse (tests body_func i) (if (= i (len c)) + (array tests body_func) + (let ( (inner_test inner_body_func) (evaluate_case (array idx access i) (idx c i)) ) + (recurse (concat tests (array inner_test)) + (lambda (b) (body_func (inner_body_func b))) + (+ i 1))))) + tests (lambda (b) b) 0) + ) (array tests body_func)) + true (array (array = access c) (lambda (b) b)) + )) + helper (rec-lambda helper (x_sym cases i) (cond (< i (- (len cases) 1)) (let ( (test body_func) (evaluate_case x_sym (idx cases i)) ) + (concat (array test (body_func (idx cases (+ i 1)))) (helper x_sym cases (+ i 2)))) + true (array true (array error "none matched")))) + ) (vau de (x & cases) (eval (array let (array '___MATCH_SYM x) (concat (array cond) (helper '___MATCH_SYM cases 0))) de))) + + ; This is based on https://www.cs.cornell.edu/courses/cs3110/2020sp/a4/deletion.pdf + ; and the figure references refer to it + ; Insert is taken from the same paper, but is origional to Okasaki, I belive + + ; The tree has been modified slightly to take in a comparison function + ; and override if insert replaces or not to allow use as a set or as a map + + ; I think this is actually pretty cool - instead of having a bunch of seperate ['B] + ; be our leaf node, we use ['B] with all nils. This allows us to not use -B, as + ; both leaf and non-leaf 'BB has the same structure with children! Also, we make + ; sure to use empty itself so we don't make a ton of empties... + empty (array 'B nil nil nil) + E empty + EE (array 'BB nil nil nil) + + size (rec-lambda recurse (t) (match t + ,E 0 + (c a x b) (+ 1 (recurse a) (recurse b)))) + + generic-foldl (rec-lambda recurse (f z t) (match t + ,E z + (c a x b) (recurse f (f (recurse f z a) x) b))) + + generic-contains? (rec-lambda recurse (t cmp v found not-found) (match t + ,E (not-found) + (c a x b) (match (cmp v x) '< (recurse a cmp v found not-found) + '= (found x) + '> (recurse b cmp v found not-found)))) + blacken (lambda (t) (match t + ('R a x b) (array 'B a x b) + t t)) + balance (lambda (t) (match t + ; figures 1 and 2 + ('B ('R ('R a x b) y c) z d) (array 'R (array 'B a x b) y (array 'B c z d)) + ('B ('R a x ('R b y c)) z d) (array 'R (array 'B a x b) y (array 'B c z d)) + ('B a x ('R ('R b y c) z d)) (array 'R (array 'B a x b) y (array 'B c z d)) + ('B a x ('R b y ('R c z d))) (array 'R (array 'B a x b) y (array 'B c z d)) + ; figure 8, double black cases + ('BB ('R a x ('R b y c)) z d) (array 'B (array 'B a x b) y (array 'B c z d)) + ('BB a x ('R ('R b y c) z d)) (array 'B (array 'B a x b) y (array 'B c z d)) + ; already balenced + t t)) + generic-insert (lambda (t cmp v replace) (let ( + ins (rec-lambda ins (t) (match t + ,E (array 'R t v t) + (c a x b) (match (cmp v x) '< (balance (array c (ins a) x b)) + '= (if replace (array c a v b) + t) + '> (balance (array c a x (ins b)))))) + ) (blacken (ins t)))) + + rotate (lambda (t) (match t + ; case 1, fig 6 + ('R ('BB a x b) y ('B c z d)) (balance (array 'B (array 'R (array 'B a x b) y c) z d)) + ('R ('B a x b) y ('BB c z d)) (balance (array 'B a x (array 'R b y (array 'B c z d)))) + ; case 2, figure 7 + ('B ('BB a x b) y ('B c z d)) (balance (array 'BB (array 'R (array 'B a x b) y c) z d)) + ('B ('B a x b) y ('BB c z d)) (balance (array 'BB a x (array 'R b y (array 'B c z d)))) + ; case 3, figure 9 + ('B ('BB a w b) x ('R ('B c y d) z e)) (array 'B (balance (array 'B (array 'R (array 'B a w b) x c) y d)) z e) + ('B ('R a w ('B b x c)) y ('BB d z e)) (array 'B a w (balance (array 'B b x (array 'R c y (array 'B d z e))))) + ; fall through + t t)) + + redden (lambda (t) (match t + ('B a x b) (if (and (= 'B (idx a 0)) (= 'B (idx b 0))) (array 'R a x b) + t) + t t)) + + min_delete (rec-lambda recurse (t) (match t + ,E (error "min_delete empty tree") + ('R ,E x ,E) (array x E) + ('B ,E x ,E) (array x EE) + ('B ,E x ('R a y b)) (array x (array 'B a y b)) + (c a x b) (let ((v ap) (recurse a)) (array v (rotate (array c ap x b)))))) + + generic-delete (lambda (t cmp v) (let ( + del (rec-lambda del (t v) (match t + ; figure 3 + ,E t + ; figure 4 + ('R ,E x ,E) (match (cmp v x) '= E + _ t) + ('B ('R a x b) y ,E) (match (cmp v y) '< (rotate (array 'B (del (array 'R a x b) v) y E)) + '= (array 'B a x b) + '> t) + ; figure 5 + ('B ,E x ,E) (match (cmp v x) '= EE + _ t) + (c a x b) (match (cmp v x) '< (rotate (array c (del a v) x b)) + '= (let ((array vp bp) (min_delete b)) + (rotate (array c a vp bp))) + '> (rotate (array c a x (del b v)))))) + ) (del (redden t) v))) + + set-cmp (lambda (a b) (cond (< a b) '< + (= a b) '= + true '>)) + set-empty empty + set-foldl generic-foldl + set-insert (lambda (t x) (generic-insert t set-cmp x false)) + set-contains? (lambda (t x) (generic-contains? t set-cmp x (lambda (f) true) (lambda () false))) + set-remove (lambda (t x) (generic-delete t set-cmp x)) + + map-cmp (lambda (a b) (let (ak (idx a 0) + bk (idx b 0)) + (cond (< ak bk) '< + (= ak bk) '= + true '>))) + map-empty empty + map-insert (lambda (t k v) (generic-insert t map-cmp (array k v) true)) + map-contains-key? (lambda (t k) (generic-contains? t map-cmp (array k nil) (lambda (f) true) (lambda () false))) + map-get (lambda (t k) (generic-contains? t map-cmp (array k nil) (lambda (f) (idx f 1)) (lambda () (error (str "didn't find key " k " in map " t))))) + map-get-or-default (lambda (t k d) (generic-contains? t map-cmp (array k nil) (lambda (f) (idx f 1)) (lambda () d))) + map-get-with-default (lambda (t k d) (generic-contains? t map-cmp (array k nil) (lambda (f) (idx f 1)) (lambda () (d)))) + map-remove (lambda (t k) (generic-delete t map-cmp (array k nil))) + + ; This could be 2x as efficent by being implmented on generic instead of map, + ; as we wouldn't have to traverse once to find and once to insert + multimap-empty map-empty + multimap-insert (lambda (t k v) (map-insert t k (set-insert (map-get-or-default t k set-empty) v))) + multimap-get (lambda (t k) (map-get-or-default t k set-empty)) + + + + make-test-tree (rec-lambda make-test-tree (n t) (cond (<= n 0) t + true (make-test-tree (- n 1) (map-insert t n (= 0 (% n 10)))))) + reduce-test-tree (lambda (tree) (generic-foldl (lambda (a x) (if (idx x 1) (+ a 1) a)) 0 tree)) + + monad (array 'write 1 (str "running tree test") (vau (written code) + (array 'args (vau (args code) + (array 'exit (log (reduce-test-tree (make-test-tree (read-string (idx args 1)) map-empty)))) + )) + )) + + ) monad) +; end of all lets +)))))) +; impl of let1 +)) (vau de (s v b) (eval (array (array wrap (array vau (array s) b)) v) de))) +; impl of quote +)) (vau (x5) x5)) diff --git a/working_files/fib.c b/working_files/fib.c new file mode 100644 index 0000000..54fea15 --- /dev/null +++ b/working_files/fib.c @@ -0,0 +1,17 @@ +#include + +int fib(int n) { + if (n == 0) { + return 0; + } else if (n == 1) { + return 1; + } else { + return fib(n-1) + fib(n-2); + } +} + +int main(int argc, char** argv) { + int n = 27; + printf("Fib(%d): %d\n", n, fib(n)); + return 0; +}