lama_byterun/stdlib/Data.lama

137 lines
3 KiB
Text
Raw Normal View History

2020-08-06 14:56:41 +03:00
-- Data.
-- (C) Dmitry Boulytchev, JetBrains Research, St. Petersburg State University, 2020
--
-- This unit provides a set of generic operations on data structures.
import Collection;
import Ref;
-- Generic comparison for shared/cyclic data structures
2022-01-31 23:46:18 +03:00
public fun trace (x) {
fun tracerec (s, x) {
case x of
#val -> skip -- printf ("unboxed:%d;", x)
| _ ->
if memSet (s, x)
then printf ("<knot: 0x%.8x>", x)
else
var s_ = addSet (s, x);
printf ("[0x%.8x: ", x);
case x of
#array -> printf ("a; ")
| #fun -> printf ("f<0x%.8x>; ", x[0])
| #sexp -> printf ("s; ")
| #str -> printf ("c<%s>; ", x)
esac;
for var i = case x of #fun -> 1 | _ -> 0 esac;, i<x.length, i := i+1
do
tracerec (s_, x[i])
od;
printf ("]")
fi
esac
}
tracerec (emptySet (flatCompare), x)
}
2020-08-06 14:56:41 +03:00
public infix =?= at < (x, y) {
var m = ref (emptyMap (flatCompare));
2020-08-06 14:56:41 +03:00
fun alreadyEq (x, y) {
fun find (x) {
fun walk (r) {
2020-08-10 20:55:10 +03:00
fun walkrec (p1, p2, r) {
case p2 of
[_] -> p2 [0] := r
| _ -> skip
esac;
case r of
2021-01-31 21:07:17 +03:00
[#val] -> r
| [x] -> walkrec (r, p1, x)
2020-08-10 20:55:10 +03:00
esac
}
walkrec ({}, {}, r)
2020-08-06 14:56:41 +03:00
}
case findMap (deref (m), x) of
Some (r) -> Some (walk (r))
| x -> x
esac
}
case [find (x), find (y)] of
[None, None] ->
var v = [1];
2020-08-06 14:56:41 +03:00
m ::= addMap (addMap (deref (m), x, v), y, v);
false
| [None, Some (ry)] ->
m ::= addMap (deref (m), x, ry);
false
| [Some (rx), None] ->
m ::= addMap (deref (m), y, rx);
false
| [Some (rx), Some (ry)] ->
if rx == ry
then true
else
2020-08-10 20:55:10 +03:00
if rx[0] < ry[0]
then
ry [0] := ry [0] + rx [0];
rx [0] := ry
else
rx [0] := rx [0] + ry [0];
ry [0] := rx
fi;
2020-08-06 14:56:41 +03:00
false
fi
esac
}
fun cmpargs (x, y, from) {
var diff = x.length - y.length;
2020-08-06 14:56:41 +03:00
for var i = from;, i < x.length && diff == 0, i := i + 1 do
2020-08-06 14:56:41 +03:00
diff := cmprec (x[i], y[i])
od;
diff
}
fun cmprec (x, y) {
if alreadyEq (x, y)
then 0
else
var diff = x.kindOf - y.kindOf;
2020-08-06 14:56:41 +03:00
if diff != 0 then diff
else
case x of
#array -> cmpargs (x, y, 0)
| #fun -> if (diff := x[0] - y[0]) == 0
then cmpargs (x, y, 1)
else diff
fi
| #sexp -> if (diff := compareTags (x, y)) == 0
then cmpargs (x, y, 0)
else diff
fi
| _ -> compare (x, y)
esac
fi
fi
}
cmprec (x, y)
}
-- Generic equaliry for shared/cyclic data structures
public infix === at == (x, y) {
(x =?= y) == 0
}