From d689a590979b5765b2b2e61e778a105b4d78c157 Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Sat, 17 Oct 2020 11:59:54 -0400 Subject: [PATCH] Experimenting with fungll optimization, implement the okmij.org poly-variadic fix-point combinator for mutual recursion --- fungll.krak | 26 ++++++++++++++------------ new_kraken.kp | 10 ++++++++++ shell.nix | 2 ++ stdlib/hash_map.krak | 6 ++++++ stdlib/hash_set.krak | 16 ++++++++++++++++ stdlib/map.krak | 5 ++++- stdlib/set.krak | 4 +--- stdlib/vec.krak | 5 +++++ 8 files changed, 58 insertions(+), 16 deletions(-) diff --git a/fungll.krak b/fungll.krak index 962a632..ea0d1dd 100644 --- a/fungll.krak +++ b/fungll.krak @@ -2,6 +2,7 @@ import vec:* import vec_literals:* import map:* import set:* +import hash_set import util:* import str:* import regex:* @@ -216,7 +217,7 @@ fun pending(nonterminal: int, rule_idx: int, idx_into_rule: int, left: int): Pen var to_ret.construct(nonterminal, rule_idx, idx_into_rule, left): Pending return to_ret } -obj Descriptor (Object) { +obj Descriptor (Object, Hashable) { var nonterminal: int var rule_idx: int var idx_into_rule: int @@ -248,6 +249,10 @@ obj Descriptor (Object) { fun operator==(rhs: ref Descriptor): bool { return nonterminal == rhs.nonterminal && rule_idx == rhs.rule_idx && idx_into_rule == rhs.idx_into_rule && left == rhs.left && pivot == rhs.pivot } + fun hash():ulong { + //return hash(nonterminal) ^ hash(rule_idx) ^ hash(idx_into_rule) ^ hash(left) ^ hash(pivot) + return nonterminal*3 + rule_idx*5 + idx_into_rule*7 + left*11 + pivot*13 + } } fun descriptor(nonterminal: int, rule_idx: int, idx_into_rule: int, left: int, pivot: int): Descriptor { var to_ret.construct(nonterminal, rule_idx, idx_into_rule, left, pivot): Descriptor @@ -304,22 +309,17 @@ fun bs(nonterminal: int, rule_idx: int, idx_into_rule: int, left: int, pivot: in /*}*/ fun fungll(grammar: ref Grammer, start_symbol: int, input: ref str): set { var R = descend(grammar, start_symbol, 0) - var U = set() var G = map, set>() var P = map, set>() var Y = set() - while R.size() != 0 { - var d = R.pop() + + R.chaotic_closure(fun(d: Descriptor): set { var it = process(grammar, input, d, G, P) - var Rp = it.first.first - var Yp = it.first.second + //var Yp = it.first.second + Y += it.first.second var Gp = it.second var Pp = it.third - U.add(d) - var nextR = R.union(Rp) - U - R = nextR - for (var i = 0; i < Gp.keys.size; i++;) { if G.contains_key(Gp.keys[i]) { G[Gp.keys[i]].add(Gp.values[i]) @@ -334,8 +334,10 @@ fun fungll(grammar: ref Grammer, start_symbol: int, input: ref str): s P[Pp.keys[i]] = Pp.values[i] } } - Y += Yp - } + + // Rp + return it.first.first + }) return Y } fun descend(grammar: ref Grammer, symbol: int, l: int): set { diff --git a/new_kraken.kp b/new_kraken.kp index 58f6fd5..25d4dd1 100644 --- a/new_kraken.kp +++ b/new_kraken.kp @@ -42,6 +42,14 @@ (do (set-idx! n i (f (idx l i))) (recurse f l n (+ i 1)))))) (helper f l (array-with-len (len l)) 0))) + + ; 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)))) + flat_map (lambda (f l) (let (helper (rec-lambda (f l n i) (if (= i (len l)) @@ -86,9 +94,11 @@ vapply Y vY + Y* quote quasiquote provide + print_through ) insert_into_scope_let (lambda (scope_let name item) (array (idx scope_let 0) (concat (idx scope_let 1) (array name item)))) ; Gotta insert with_import into scope_let via vY combinator so it can use itself diff --git a/shell.nix b/shell.nix index e0f7202..9be631e 100644 --- a/shell.nix +++ b/shell.nix @@ -6,5 +6,7 @@ mkShell { nativeBuildInputs = [ emscripten nodejs + valgrind + kcachegrind ]; } diff --git a/stdlib/hash_map.krak b/stdlib/hash_map.krak index b9c0920..41f945e 100644 --- a/stdlib/hash_map.krak +++ b/stdlib/hash_map.krak @@ -110,5 +110,11 @@ obj hash_map (Object, Serializable) { size = 0 data.add(map::map()) } + fun pop(): util::pair { + for (var i = 0; i < data.size; i++;) + if (data[i].size() > 0) + return data[i].pop() + io::println("trying to pop out of an empty hash_map") + } } diff --git a/stdlib/hash_set.krak b/stdlib/hash_set.krak index a310cfc..586924f 100644 --- a/stdlib/hash_set.krak +++ b/stdlib/hash_set.krak @@ -127,5 +127,21 @@ obj hash_set (Object, Serializable) { } } + fun pop(): T { + return data.pop().first + } + fun union(other: hash_set): hash_set { + for_each(fun(i: T) { + other.add(i) + }) + return other + } + fun operator-(items: ref hash_set): hash_set { + var to_ret.copy_construct(this): hash_set + items.for_each(fun(i: T) { + to_ret.remove(i) + }) + return to_ret + } } diff --git a/stdlib/map.krak b/stdlib/map.krak index 12dab08..1c06c74 100644 --- a/stdlib/map.krak +++ b/stdlib/map.krak @@ -96,7 +96,7 @@ obj map (Object, Serializable) { fun remove(key: ref T) { var idx = keys.find(key) if (idx < 0) - util::error("trying to remove nonexistant key-value!") + return; keys.remove(idx) values.remove(idx) } @@ -123,5 +123,8 @@ obj map (Object, Serializable) { } return to_ret } + fun pop(): util::pair { + return util::make_pair(keys.pop(), values.pop()) + } } diff --git a/stdlib/set.krak b/stdlib/set.krak index f090cd7..f28dea5 100644 --- a/stdlib/set.krak +++ b/stdlib/set.krak @@ -149,9 +149,7 @@ obj set (Object, Serializable) { } fun pop(): T { - var to_ret = data.last() - data.remove(data.size-1) - return to_ret + return data.pop() } fun union(other: set): set { for (var i = 0; i < data.size; i++;) diff --git a/stdlib/vec.krak b/stdlib/vec.krak index 443c2a9..4e64fcf 100644 --- a/stdlib/vec.krak +++ b/stdlib/vec.krak @@ -384,5 +384,10 @@ obj vec (Object, Serializable) { return to_ret } } + fun pop(): T { + var to_ret = data[size-1] + remove(size-1) + return to_ret + } };