2020-01-15 05:24:35 +03:00
|
|
|
-- Collection package.
|
|
|
|
|
-- (C) Dmitry Boulytchev, JetBrains Research, St. Petersburg State University, 2020
|
|
|
|
|
--
|
|
|
|
|
-- This package provides a simplistic implementation of immutable set/map/hashtable
|
|
|
|
|
-- data structures.
|
2020-01-05 03:46:19 +03:00
|
|
|
|
2020-01-15 06:12:01 +03:00
|
|
|
import List;
|
|
|
|
|
|
2020-01-15 21:42:59 +03:00
|
|
|
fun insertColl (m, k, v, sort) {
|
2020-01-15 05:24:35 +03:00
|
|
|
fun append (v, vs) {
|
|
|
|
|
case sort of
|
|
|
|
|
Map -> v : vs
|
|
|
|
|
| Set -> v
|
2020-01-15 21:42:59 +03:00
|
|
|
| Hash -> case find (fun (x) {x == v}, vs) of
|
|
|
|
|
None -> v : vs
|
|
|
|
|
| _ -> vs
|
|
|
|
|
esac
|
2020-01-15 05:24:35 +03:00
|
|
|
esac
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-05 03:46:19 +03:00
|
|
|
fun rot (left, node) {
|
|
|
|
|
if left
|
|
|
|
|
then case node of
|
|
|
|
|
MNode (k, v, _, l, MNode (rk, rv, _, ll, rr)) ->
|
|
|
|
|
MNode (rk, rv, 0, MNode (k, v, 0, l, ll), rr)
|
|
|
|
|
esac
|
|
|
|
|
else case node of
|
|
|
|
|
MNode (k, v, _, MNode (lk, lv, _, ll, rr), r) ->
|
|
|
|
|
MNode (lk, lv, 0, ll, MNode (k, v, 0, rr, r))
|
|
|
|
|
esac
|
|
|
|
|
fi
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fun factor (x) {x [2]}
|
|
|
|
|
|
2020-01-15 05:24:35 +03:00
|
|
|
fun inner (m) {
|
2020-01-05 03:46:19 +03:00
|
|
|
case m of
|
2020-01-15 05:24:35 +03:00
|
|
|
{} -> [true, MNode (k, append (v, {}), 0, {}, {})]
|
2020-01-05 03:46:19 +03:00
|
|
|
| MNode (kk, vv, bf, l, r) ->
|
|
|
|
|
local c = compare (k, kk);
|
|
|
|
|
if c == 0
|
2020-01-15 05:24:35 +03:00
|
|
|
then [false, MNode (kk, append (v, vv), bf, l, r)]
|
2020-01-05 03:46:19 +03:00
|
|
|
else if c < 0
|
|
|
|
|
then
|
2020-01-15 05:24:35 +03:00
|
|
|
case inner (l) of
|
2020-01-05 03:46:19 +03:00
|
|
|
[true, ll] -> if bf < 0
|
|
|
|
|
then [false, MNode (kk, vv, bf + 1, ll, r)]
|
|
|
|
|
elif bf == 1
|
|
|
|
|
then if ll.factor > 0
|
|
|
|
|
then [false, rot (false, MNode (kk, vv, bf, ll, r))]
|
|
|
|
|
else [false, rot (false, MNode (kk, vv, bf, 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
|
2020-01-15 05:24:35 +03:00
|
|
|
case inner (r) of
|
2020-01-05 03:46:19 +03:00
|
|
|
[true, rr] -> if bf > 0
|
|
|
|
|
then [false, MNode (kk, vv, bf - 1, l, rr)]
|
|
|
|
|
elif bf == -1
|
|
|
|
|
then if rr.factor < 0
|
|
|
|
|
then [false, rot (true, MNode (kk, vv, bf, l, rr))]
|
|
|
|
|
else [false, rot (true, MNode (kk, vv, bf, 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-01-15 05:24:35 +03:00
|
|
|
inner (m).snd
|
2020-01-05 03:46:19 +03:00
|
|
|
}
|
|
|
|
|
|
2020-01-15 21:42:59 +03:00
|
|
|
fun findColl (m, k, sort) {
|
2020-01-15 05:24:35 +03:00
|
|
|
fun extract (vv) {
|
|
|
|
|
case sort of
|
|
|
|
|
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) ->
|
|
|
|
|
local c = compare (k, kk);
|
|
|
|
|
if c == 0
|
|
|
|
|
then extract (vv)
|
|
|
|
|
else inner (if c < 0 then l else r fi)
|
|
|
|
|
fi
|
|
|
|
|
esac
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inner (m)
|
2020-01-05 03:46:19 +03:00
|
|
|
}
|
|
|
|
|
|
2020-01-15 21:42:59 +03:00
|
|
|
fun removeColl (m, k, sort) {
|
2020-01-15 05:24:35 +03:00
|
|
|
fun delete (vs) {
|
|
|
|
|
case sort of
|
|
|
|
|
Map -> case vs of {} -> {} | _ : vv -> vv esac
|
|
|
|
|
| Set -> false
|
|
|
|
|
esac
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fun inner (m) {
|
|
|
|
|
case m of
|
|
|
|
|
{} -> m
|
|
|
|
|
| MNode (kk, vv, bf, l, r) ->
|
|
|
|
|
local c = compare (k, 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
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inner (m)
|
2020-01-05 03:46:19 +03:00
|
|
|
}
|
|
|
|
|
|
2020-01-15 05:24:35 +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
|
|
|
|
|
{} -> acc
|
|
|
|
|
| MNode (k, vv, _, l, r) -> inner (l, append (k, vv, inner (r, acc)))
|
|
|
|
|
esac
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inner (m, {})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public fun validateColl (t) {
|
2020-01-05 03:46:19 +03:00
|
|
|
fun inner (t, verify) {
|
|
|
|
|
case t of
|
|
|
|
|
{} -> 0
|
|
|
|
|
| MNode (k, _, bf, l, r) ->
|
|
|
|
|
if verify (k)
|
|
|
|
|
then
|
2020-01-15 05:24:35 +03:00
|
|
|
local lh = validateColl (l, fun (x) {x < k}),
|
|
|
|
|
rh = validateColl (r, fun (x) {x > k});
|
2020-01-05 03:46:19 +03:00
|
|
|
|
|
|
|
|
if bf == lh - rh
|
|
|
|
|
then 1 + if lh > rh then lh else rh fi
|
2020-01-15 05:24:35 +03:00
|
|
|
else failure ("Collection::validateColl: balance violation on key %s\n", k.string)
|
2020-01-05 03:46:19 +03:00
|
|
|
fi
|
2020-01-15 05:24:35 +03:00
|
|
|
else failure ("Collection::validateColl: order violation on key %s\n", k.string)
|
2020-01-05 03:46:19 +03:00
|
|
|
fi
|
|
|
|
|
esac
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inner (t, fun (x) {true})
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-15 21:42:59 +03:00
|
|
|
-- Map structure
|
2020-01-15 05:24:35 +03:00
|
|
|
public fun emptyMap () {
|
|
|
|
|
{}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public fun addMap (m, k, v) {
|
2020-01-15 21:42:59 +03:00
|
|
|
insertColl (m, k, v, Map)
|
2020-01-15 05:24:35 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public fun findMap (m, k) {
|
2020-01-15 21:42:59 +03:00
|
|
|
findColl (m, k, Map)
|
2020-01-15 05:24:35 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public fun removeMap (m, k) {
|
2020-01-15 21:42:59 +03:00
|
|
|
removeColl (m, k, Map)
|
2020-01-15 05:24:35 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public fun bindings (m) {
|
|
|
|
|
contents (m, Map)
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-15 21:42:59 +03:00
|
|
|
public fun listMap (l) {
|
|
|
|
|
foldl (fun (m, p) {addMap (m, p.fst, p.snd)}, emptyMap (), l)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public fun iterMap (f, m) {
|
|
|
|
|
iter (f, bindings (m))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public fun mapMap (f, m) {
|
|
|
|
|
listMap (map (fun (p) {[p.fst, f (p.snd)]}, bindings (m)))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public fun foldMap (f, acc, m) {
|
|
|
|
|
foldl (f, acc, bindings (m))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
-- Set structure
|
2020-01-15 05:24:35 +03:00
|
|
|
public fun emptySet () {
|
|
|
|
|
{}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public fun addSet (s, v) {
|
2020-01-15 21:42:59 +03:00
|
|
|
insertColl (s, v, true, Set)
|
2020-01-15 05:24:35 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public fun memSet (s, v) {
|
2020-01-15 21:42:59 +03:00
|
|
|
case findColl (s, v, Set) of
|
2020-01-15 05:24:35 +03:00
|
|
|
None -> false
|
|
|
|
|
| Some (f) -> f
|
|
|
|
|
esac
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public fun removeSet (s, v) {
|
2020-01-15 21:42:59 +03:00
|
|
|
removeColl (s, v, Set)
|
2020-01-15 05:24:35 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public fun listSet (l) {
|
|
|
|
|
foldl (addSet, emptySet (), l)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public fun iterSet (f, s) {
|
|
|
|
|
iter (f, elements (s))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public fun mapSet (f, s) {
|
|
|
|
|
listSet (map (f, elements (s)))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public fun foldSet (f, acc, s) {
|
|
|
|
|
foldl (f, acc, elements (s))
|
2020-01-15 21:42:59 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
-- Hash structure
|
|
|
|
|
public fun emptyMemo () {
|
|
|
|
|
[{}]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public fun lookupMemo (m, v) {
|
2020-01-15 22:33:46 +03:00
|
|
|
skip
|
2020-01-15 05:24:35 +03:00
|
|
|
}
|