Experimenting with fungll optimization, implement the okmij.org poly-variadic fix-point combinator for mutual recursion

This commit is contained in:
Nathan Braswell
2020-10-17 11:59:54 -04:00
parent 45ecb25bb1
commit d689a59097
8 changed files with 58 additions and 16 deletions

View File

@@ -2,6 +2,7 @@ import vec:*
import vec_literals:* import vec_literals:*
import map:* import map:*
import set:* import set:*
import hash_set
import util:* import util:*
import str:* import str:*
import regex:* 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 var to_ret.construct(nonterminal, rule_idx, idx_into_rule, left): Pending
return to_ret return to_ret
} }
obj Descriptor (Object) { obj Descriptor (Object, Hashable) {
var nonterminal: int var nonterminal: int
var rule_idx: int var rule_idx: int
var idx_into_rule: int var idx_into_rule: int
@@ -248,6 +249,10 @@ obj Descriptor (Object) {
fun operator==(rhs: ref Descriptor): bool { 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 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 { 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 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<T,K>(grammar: ref Grammer<T,K>, start_symbol: int, input: ref str): set<BS> { fun fungll<T,K>(grammar: ref Grammer<T,K>, start_symbol: int, input: ref str): set<BS> {
var R = descend(grammar, start_symbol, 0) var R = descend(grammar, start_symbol, 0)
var U = set<Descriptor>()
var G = map<pair<int, int>, set<Pending>>() var G = map<pair<int, int>, set<Pending>>()
var P = map<pair<int,int>, set<int>>() var P = map<pair<int,int>, set<int>>()
var Y = set<BS>() var Y = set<BS>()
while R.size() != 0 {
var d = R.pop() R.chaotic_closure(fun(d: Descriptor): set<Descriptor> {
var it = process(grammar, input, d, G, P) 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 Gp = it.second
var Pp = it.third var Pp = it.third
U.add(d)
var nextR = R.union(Rp) - U
R = nextR
for (var i = 0; i < Gp.keys.size; i++;) { for (var i = 0; i < Gp.keys.size; i++;) {
if G.contains_key(Gp.keys[i]) { if G.contains_key(Gp.keys[i]) {
G[Gp.keys[i]].add(Gp.values[i]) G[Gp.keys[i]].add(Gp.values[i])
@@ -334,8 +334,10 @@ fun fungll<T,K>(grammar: ref Grammer<T,K>, start_symbol: int, input: ref str): s
P[Pp.keys[i]] = Pp.values[i] P[Pp.keys[i]] = Pp.values[i]
} }
} }
Y += Yp
} // Rp
return it.first.first
})
return Y return Y
} }
fun descend<T,K>(grammar: ref Grammer<T,K>, symbol: int, l: int): set<Descriptor> { fun descend<T,K>(grammar: ref Grammer<T,K>, symbol: int, l: int): set<Descriptor> {

View File

@@ -42,6 +42,14 @@
(do (set-idx! n i (f (idx l i))) (do (set-idx! n i (f (idx l i)))
(recurse f l n (+ i 1)))))) (recurse f l n (+ i 1))))))
(helper f l (array-with-len (len l)) 0))) (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) flat_map (lambda (f l)
(let (helper (rec-lambda (f l n i) (let (helper (rec-lambda (f l n i)
(if (= i (len l)) (if (= i (len l))
@@ -86,9 +94,11 @@
vapply vapply
Y Y
vY vY
Y*
quote quote
quasiquote quasiquote
provide 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)))) 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 ; Gotta insert with_import into scope_let via vY combinator so it can use itself

View File

@@ -6,5 +6,7 @@ mkShell {
nativeBuildInputs = [ nativeBuildInputs = [
emscripten emscripten
nodejs nodejs
valgrind
kcachegrind
]; ];
} }

View File

@@ -110,5 +110,11 @@ obj hash_map<T,U> (Object, Serializable) {
size = 0 size = 0
data.add(map::map<T,U>()) data.add(map::map<T,U>())
} }
fun pop(): util::pair<T,U> {
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")
}
} }

View File

@@ -127,5 +127,21 @@ obj hash_set<T> (Object, Serializable) {
} }
} }
fun pop(): T {
return data.pop().first
}
fun union(other: hash_set<T>): hash_set<T> {
for_each(fun(i: T) {
other.add(i)
})
return other
}
fun operator-(items: ref hash_set<T>): hash_set<T> {
var to_ret.copy_construct(this): hash_set<T>
items.for_each(fun(i: T) {
to_ret.remove(i)
})
return to_ret
}
} }

View File

@@ -96,7 +96,7 @@ obj map<T,U> (Object, Serializable) {
fun remove(key: ref T) { fun remove(key: ref T) {
var idx = keys.find(key) var idx = keys.find(key)
if (idx < 0) if (idx < 0)
util::error("trying to remove nonexistant key-value!") return;
keys.remove(idx) keys.remove(idx)
values.remove(idx) values.remove(idx)
} }
@@ -123,5 +123,8 @@ obj map<T,U> (Object, Serializable) {
} }
return to_ret return to_ret
} }
fun pop(): util::pair<T,U> {
return util::make_pair(keys.pop(), values.pop())
}
} }

View File

@@ -149,9 +149,7 @@ obj set<T> (Object, Serializable) {
} }
fun pop(): T { fun pop(): T {
var to_ret = data.last() return data.pop()
data.remove(data.size-1)
return to_ret
} }
fun union(other: set<T>): set<T> { fun union(other: set<T>): set<T> {
for (var i = 0; i < data.size; i++;) for (var i = 0; i < data.size; i++;)

View File

@@ -384,5 +384,10 @@ obj vec<T> (Object, Serializable) {
return to_ret return to_ret
} }
} }
fun pop(): T {
var to_ret = data[size-1]
remove(size-1)
return to_ret
}
}; };