lama_byterun/stdlib/Collection.lama

388 lines
8.5 KiB
Text
Raw Normal View History

2020-02-20 12:43:52 +03:00
-- Collections.
-- (C) Dmitry Boulytchev, JetBrains Research, St. Petersburg State University, 2020
--
2020-02-20 12:43:52 +03:00
-- This unit provides a simplistic implementation of immutable set/map/hashtable
-- data structures.
2020-01-15 06:12:01 +03:00
import List;
import Ref;
2020-08-06 14:56:41 +03:00
import Array;
2020-01-15 06:12:01 +03:00
2020-08-06 14:56:41 +03:00
fun printColl ([m, _]) {
fun inner (off, curr) {
printf (off);
case curr of
{} -> printf ("** nil **\n")
| MNode (k, v, b, l, r) ->
printf ("** key = %s, bf = %d **\n", k.string, b);
printf (off);
printf (" values :\n");
iter (fun ([x, _]) {printf (off); printf (" %s\n", x.string)}, v);
inner (" " ++ off, l);
inner (" " ++ off, r)
esac
}
inner ("", m)
}
2020-08-06 14:56:41 +03:00
public fun validateColl ([t, compare]) {
2020-07-23 12:52:42 +03:00
fun inner (t, verify) {
case t of
{} -> 0
| MNode (k, _, bf, l, r) ->
if verify (k)
then
var lh = inner (l, fun (x) {compare (x, k) < 0}),
2020-08-06 14:56:41 +03:00
rh = inner (r, fun (x) {compare (x, k) > 0});
2020-07-23 12:52:42 +03:00
if bf == lh - rh
then 1 + if lh > rh then lh else rh fi
2020-08-06 14:56:41 +03:00
else failure ("Collection.validateColl: balance violation on key %s\nTree: %s\n", k.string, t.string)
2020-07-23 12:52:42 +03:00
fi
2020-08-06 14:56:41 +03:00
else failure ("Collection.validateColl: order violation on key %s\nTree: %s\n", k.string, t.string)
2020-07-23 12:52:42 +03:00
fi
esac
}
inner (t, fun (x) {true})
}
2020-08-06 14:56:41 +03:00
fun insertColl ([m, compare], pk, v, sort) {
fun append (v, vs) {
case sort of
Map -> v : vs
| Set -> v
esac
}
fun rot (left, node) {
if left
then case node of
2020-07-23 12:52:42 +03:00
MNode (k, v, x, l, MNode (rk, rv, y, ll, rr)) ->
var x0 = if y > 0 then x + 1 else x - y + 1 fi,
2020-07-23 12:52:42 +03:00
y0 = if x0 > 0
then
if y > 0
then x + y + 2
else x + 2
fi
else y + 1
fi;
MNode (rk, rv, y0, MNode (k, v, x0, l, ll), rr)
esac
else case node of
2020-07-23 12:52:42 +03:00
MNode (k, v, x, MNode (lk, lv, y, ll, rr), r) ->
var x0 = if y < 0 then x - 1 else x - y - 1 fi,
2020-07-23 12:52:42 +03:00
y0 = if x0 > 0
then y - 1
else
if y < 0
then y + x - 2
else x - 2
fi
fi;
MNode (lk, lv, y0, ll, MNode (k, v, x0, rr, r))
esac
fi
}
fun factor (x) {x [2]}
fun inner (m) {
case m of
2020-08-06 14:56:41 +03:00
{} -> [true, MNode (pk, append (v, {}), 0, {}, {})]
| MNode (kk, vv, bf, l, r) ->
var c = compare (pk, kk);
if c == 0
then [false, MNode (kk, append (v, vv), bf, l, r)]
else if c < 0
then
case inner (l) of
[true, ll] -> if bf < 0
then [false, MNode (kk, vv, bf + 1, ll, r)]
elif bf == 1
then if ll.factor > 0
2020-07-23 12:52:42 +03:00
then [false, rot (false, MNode (kk, vv, 2, ll, r))]
else [false, rot (false, MNode (kk, vv, 2, rot (true, ll), r))]
fi
else [true, MNode (kk, vv, bf + 1, ll, r)]
fi
| [false, ll] -> [false, MNode (kk, vv, bf, ll, r)]
esac
else
case inner (r) of
[true, rr] -> if bf > 0
then [false, MNode (kk, vv, bf - 1, l, rr)]
elif bf == -1
then if rr.factor < 0
2020-07-23 12:52:42 +03:00
then [false, rot (true, MNode (kk, vv, -2, l, rr))]
else [false, rot (true, MNode (kk, vv, -2, l, rot (false, rr)))]
fi
else [true, MNode (kk, vv, bf - 1, l, rr)]
fi
| [false, rr] -> [false, MNode (kk, vv, bf, l, rr)]
esac
fi
fi
esac
}
2020-08-06 14:56:41 +03:00
[inner (m).snd, compare]
}
2020-08-06 14:56:41 +03:00
fun findColl ([m, compare], pk, sort) {
fun extract (vv) {
case sort of
2020-01-16 06:59:34 +03:00
Map -> case vv of v : _ -> Some (v) | _ -> None esac
| Set -> Some (vv)
esac
}
fun inner (m) {
case m of
{} -> None
| MNode (kk, vv, _, l, r) ->
var c = compare (pk, kk);
if c == 0
then extract (vv)
else inner (if c < 0 then l else r fi)
fi
esac
}
inner (m)
}
2020-08-06 14:56:41 +03:00
fun removeColl ([m, compare], pk, sort) {
fun delete (vs) {
case sort of
2020-01-16 06:59:34 +03:00
Map -> case vs of {} -> {} | _ : vv -> vv esac
| Set -> false
esac
}
fun inner (m) {
case m of
{} -> m
| MNode (kk, vv, bf, l, r) ->
var c = compare (pk, kk);
if c == 0
then MNode (kk, delete (vv), bf, l, r)
else if c < 0
then MNode (kk, vv, bf, inner (l), r)
else MNode (kk, vv, bf, l, inner (r))
fi
fi
esac
}
2020-08-06 14:56:41 +03:00
[inner (m), compare]
}
2020-08-06 14:56:41 +03:00
fun contents ([m, _], sort) {
fun append (k, vs, acc) {
case sort of
Map -> case vs of {} -> acc | v : _ -> [k, v] : acc esac
| Set -> if vs then k : acc else acc fi
esac
}
fun inner (m, acc) {
case m of
2020-08-06 14:56:41 +03:00
{} -> acc
| MNode (k, vv, _, l, r) -> inner (l, append (k, vv, inner (r, acc)))
esac
}
inner (m, {})
}
2020-08-06 14:56:41 +03:00
-- Accessors
public fun internalOf (m) {
m [0]
2020-08-02 23:56:21 +03:00
}
2020-08-06 14:56:41 +03:00
public fun compareOf (m) {
m [1]
2020-08-02 23:56:21 +03:00
}
2020-01-15 21:42:59 +03:00
-- Map structure
2020-08-06 14:56:41 +03:00
public fun emptyMap (compare) {
[{}, compare]
}
2021-03-24 18:51:25 +07:00
public fun isEmptyMap ([l, _]) {
case l of {} -> true | _ -> false esac
}
public fun addMap (m, k, v) {
2020-01-15 21:42:59 +03:00
insertColl (m, k, v, Map)
}
public fun findMap (m, k) {
2020-01-15 21:42:59 +03:00
findColl (m, k, Map)
}
public fun removeMap (m, k) {
2020-01-15 21:42:59 +03:00
removeColl (m, k, Map)
}
public fun bindings (m) {
contents (m, Map)
}
2020-08-06 14:56:41 +03:00
public fun listMap (l, compare) {
foldl (fun (m, p) {addMap (m, p.fst, p.snd)}, emptyMap (compare), l)
2020-01-15 21:42:59 +03:00
}
public fun iterMap (f, m) {
iter (f, bindings (m))
}
public fun mapMap (f, m) {
2020-08-06 14:56:41 +03:00
listMap (map (fun (p) {[p.fst, f (p.snd)]}, bindings (m)), m[1])
2020-01-15 21:42:59 +03:00
}
public fun foldMap (f, acc, m) {
foldl (f, acc, bindings (m))
}
-- Set structure
2020-08-06 14:56:41 +03:00
public fun emptySet (compare) {
[{}, compare]
}
2021-03-24 18:51:25 +07:00
public fun isEmptySet (s) {
isEmptyMap (s)
}
public fun addSet (s, v) {
2020-01-15 21:42:59 +03:00
insertColl (s, v, true, Set)
}
public fun memSet (s, v) {
2020-01-15 21:42:59 +03:00
case findColl (s, v, Set) of
None -> false
| Some (f) -> f
esac
}
public fun removeSet (s, v) {
2020-01-15 21:42:59 +03:00
removeColl (s, v, Set)
}
public fun elements (m) {
contents (m, Set)
2020-01-15 06:12:01 +03:00
}
public fun union (a, b) {
foldl (addSet, a, elements (b))
}
public fun diff (a, b) {
foldl (removeSet, a, elements (b))
}
2020-08-06 14:56:41 +03:00
public fun listSet (l, compare) {
foldl (addSet, emptySet (compare), l)
2020-01-15 06:12:01 +03:00
}
public fun iterSet (f, s) {
iter (f, elements (s))
}
public fun mapSet (f, s) {
2020-08-06 14:56:41 +03:00
listSet (map (f, elements (s)),s[1])
2020-01-15 06:12:01 +03:00
}
public fun foldSet (f, acc, s) {
foldl (f, acc, elements (s))
2020-01-15 21:42:59 +03:00
}
2020-01-16 06:59:34 +03:00
-- Hash consing
2020-11-16 03:00:16 +03:00
public fun emptyCustomMemo (pred, compare) {
[pred, emptyMap (compare)]
}
2020-01-15 21:42:59 +03:00
public fun emptyMemo () {
2020-11-16 03:00:16 +03:00
emptyCustomMemo ({}, compare)
2020-01-15 21:42:59 +03:00
}
2020-11-16 03:00:16 +03:00
public fun lookupMemo (mm@[p, m], v) {
2022-01-31 23:46:18 +03:00
var f = case v of
[Right, _] : _ -> true
| _ -> false
esac;
if f then
skip -- printf ("Looked up 0x%.8x | 0x%.8x | %s\n", mm, v, v.string)
fi;
case
2021-01-31 19:11:03 +03:00
fun (x) {
case p of
#fun -> if p (v) then v else x () fi
| _ -> x ()
2022-01-31 23:46:18 +03:00
esac
}
(fun () {
case v of
#val -> v
| _ ->
case findMap (m, v) of
Some (w) -> w
| None ->
case v of
#str -> mm[1] := addMap (m, v, v); v
| _ ->
var v0 = v;
var vc = clone (v), i = case vc of #fun -> 1 | _ -> 0 esac;
-- printf ("Cloning: 0x%.8x\n", v);
for skip, i < v.length, i := i + 1 do
var vci = lookupMemo (mm, vc [i]);
vc [i] := vci
od;
mm [1] := addMap (m, vc, vc);
vc
esac
esac
esac}) of
r -> -- if f then printf ("Result | 0x%.8x | %s\n", r, r.string) fi;
r
esac
2020-01-16 06:59:34 +03:00
}
-- Maps of hashed pointers
2020-08-06 14:56:41 +03:00
public fun emptyHashTab (n, hash, compare) {
2020-08-10 20:55:10 +03:00
[initArray (n, fun (_) {{}}), compare, fun (x) {hash (x) % n}]
2020-01-16 06:59:34 +03:00
}
2020-08-10 20:55:10 +03:00
public fun addHashTab (ht@[a, compare, hash], k, v) {
var h = hash (k);
2020-08-06 14:56:41 +03:00
a [h] := [k, v] : a [h];
ht
2020-01-16 06:59:34 +03:00
}
2020-08-10 20:55:10 +03:00
public fun findHashTab ([a, compare, hash], k) {
2020-08-06 14:56:41 +03:00
case find (fun ([k0, _]) {compare (k, k0) == 0}, a[hash(k)]) of
Some ([_, v]) -> Some (v)
| _ -> None
esac
2020-01-16 06:59:34 +03:00
}
2020-08-10 20:55:10 +03:00
public fun removeHashTab (ht@[a, compare, hash], k) {
var h = hash (k);
2020-08-06 14:56:41 +03:00
a [h] := remove (fun ([k0, _]) {compare (k, k0) == 0}, a [h]);
ht
2020-08-10 20:55:10 +03:00
}
public fun hashOf (ht) {
ht [2]
}