## tuplebasex.pkg
#
# Just like
src/lib/src/tuplebase.pkg# except Atom(X) replaces Atom (etc).
# Compiled by:
#
src/lib/std/standard.libstipulate
package im1 = int_red_black_map; # int_red_black_map is from
src/lib/src/int-red-black-map.pkg package is1 = int_red_black_set; # int_red_black_set is from
src/lib/src/int-red-black-set.pkgherein
package tuplebasex
: Tuplebasex # Tuplebasex is from
src/lib/src/tuplebasex.api {
Atom_Datum(X) = NONE
| FLOAT Float
| STRING String
| OTHER X
;
Atom(X) = { id: Int,
datum: Atom_Datum(X)
};
Duple(X) = (Atom(X), Atom(X));
Triple(X) = (Atom(X), Atom(X), Atom(X));
fun compare_i2
( ( i1a: Int,
i1b: Int
),
( i2a: Int,
i2b: Int
)
)
=
case (int::compare (i1a, i2a))
#
GREATER => GREATER;
LESS => LESS;
EQUAL => int::compare (i1b, i2b);
esac;
fun compare_12of2
( ( { id => id1a, ... },
{ id => id1b, ... }
): Duple(X),
( { id => id2a, ... },
{ id => id2b, ... }
): Duple(X)
)
=
case (int::compare (id1a, id2a))
#
GREATER => GREATER;
LESS => LESS;
EQUAL => (int::compare (id1b, id2b));
esac;
fun compare_12of3
( ( { id => id1a, ... },
{ id => id1b, ... },
{ id => id1c, ... }
): Triple(X),
( { id => id2a, ... },
{ id => id2b, ... },
{ id => id2c, ... }
): Triple(X)
)
=
case (int::compare (id1a, id2a))
#
GREATER => GREATER;
LESS => LESS;
EQUAL => (int::compare (id1b, id2b));
esac;
fun compare_13of3
( ( { id => id1a, ... },
{ id => id1b, ... },
{ id => id1c, ... }
): Triple(X),
( { id => id2a, ... },
{ id => id2b, ... },
{ id => id2c, ... }
): Triple(X)
)
=
case (int::compare (id1a, id2a))
#
GREATER => GREATER;
LESS => LESS;
EQUAL => (int::compare (id1c, id2c));
esac;
fun compare_23of3
( ( { id => id1a, ... },
{ id => id1b, ... },
{ id => id1c, ... }
): Triple(X),
( { id => id2a, ... },
{ id => id2b, ... },
{ id => id2c, ... }
): Triple(X)
)
=
case (int::compare (id1b, id2b))
#
GREATER => GREATER;
LESS => LESS;
EQUAL => (int::compare (id1c, id2c));
esac;
fun compare_123of3
( ( { id => id1a, ... },
{ id => id1b, ... },
{ id => id1c, ... }
): Triple(X),
( { id => id2a, ... },
{ id => id2b, ... },
{ id => id2c, ... }
): Triple(X)
)
=
case (int::compare (id1a, id2a))
#
GREATER => GREATER;
LESS => LESS;
EQUAL => case (int::compare (id1b, id2b))
GREATER => GREATER;
LESS => LESS;
EQUAL => int::compare (id1c, id2c);
esac;
esac;
fun compare_123of3
( ( { id => id1a, ... },
{ id => id1b, ... },
{ id => id1c, ... }
): Triple(X),
( { id => id2a, ... },
{ id => id2b, ... },
{ id => id2c, ... }
): Triple(X)
)
=
case (int::compare (id1a, id2a))
#
GREATER => GREATER;
LESS => LESS;
EQUAL => case (int::compare (id1b, id2b))
GREATER => GREATER;
LESS => LESS;
EQUAL => int::compare (id1c, id2c);
esac;
esac;
package im2
=
red_black_map_g (
#
package {
Key = (Int, Int);
#
compare = compare_i2;
}
);
package ds # Sets of Duples
=
red_black_setx_g ( # red_black_setx_g is from
src/lib/src/red-black-setx-g.pkg #
package {
Key(X) = Duple(X);
#
compare = compare_12of2;
}
);
package ts # Sets of Triples
=
red_black_setx_g ( # red_black_setx_g is from
src/lib/src/red-black-setx-g.pkg #
package {
Key(X) = Triple(X);
#
compare = compare_123of3;
}
);
Tuplebase(X)
=
{ index_1of2: im1::Map( ds::Set(X) ),
index_2of2: im1::Map( ds::Set(X) ),
#
index_12of2: ds::Set(X),
#
#
index_1of3: im1::Map( ts::Set(X) ),
index_2of3: im1::Map( ts::Set(X) ),
index_3of3: im1::Map( ts::Set(X) ),
#
index_12of3: im2::Map( ts::Set(X) ),
index_13of3: im2::Map( ts::Set(X) ),
index_23of3: im2::Map( ts::Set(X) ),
#
index_123of3: ts::Set(X)
};
empty_tuplebase
=
{ index_1of2 => im1::empty: im1::Map( ds::Set(X) ),
index_2of2 => im1::empty: im1::Map( ds::Set(X) ),
#
index_12of2 => ds::empty: ds::Set(X),
#
#
index_1of3 => im1::empty: im1::Map( ts::Set(X) ),
index_2of3 => im1::empty: im1::Map( ts::Set(X) ),
index_3of3 => im1::empty: im1::Map( ts::Set(X) ),
#
index_12of3 => im2::empty: im2::Map( ts::Set(X) ),
index_13of3 => im2::empty: im2::Map( ts::Set(X) ),
index_23of3 => im2::empty: im2::Map( ts::Set(X) ),
#
index_123of3 => ts::empty: ts::Set(X)
};
fun put_duple
(
{ index_1of2,
index_2of2,
#
index_12of2,
#
#
index_1of3,
index_2of3,
index_3of3,
#
index_12of3,
index_13of3,
index_23of3,
#
index_123of3
}: Tuplebase(X),
duple as
( atom1 as { id => id1, ... },
atom2 as { id => id2, ... }
): Duple(X)
)
=
{ index_1of2
=
case (im1::get (index_1of2, id1))
#
THE set => im1::set (index_1of2, id1, ds::add (set, duple));
NULL => im1::set (index_1of2, id1, ds::singleton(duple));
esac;
index_2of2
=
case (im1::get (index_2of2, id2))
#
THE set => im1::set (index_2of2, id2, ds::add (set, duple));
NULL => im1::set (index_2of2, id2, ds::singleton(duple));
esac;
index_12of2
=
ds::add (index_12of2, duple);
{ index_1of2,
index_2of2,
#
index_12of2,
#
#
index_1of3,
index_2of3,
index_3of3,
#
index_12of3,
index_13of3,
index_23of3,
#
index_123of3
}: Tuplebase(X);
};
fun put_triple
(
{ index_1of2,
index_2of2,
#
index_12of2,
#
#
index_1of3,
index_2of3,
index_3of3,
#
index_12of3,
index_13of3,
index_23of3,
#
index_123of3
}: Tuplebase(X),
triple as
( atom1 as { id => id1, ... },
atom2 as { id => id2, ... },
atom3 as { id => id3, ... }
): Triple(X)
)
=
{ index_1of3
=
case (im1::get (index_1of3, id1))
#
THE set => im1::set (index_1of3, id1, ts::add (set, triple));
NULL => im1::set (index_1of3, id1, ts::singleton(triple));
esac;
index_2of3
=
case (im1::get (index_2of3, id2))
#
THE set => im1::set (index_2of3, id2, ts::add (set, triple));
NULL => im1::set (index_2of3, id2, ts::singleton(triple));
esac;
index_3of3
=
case (im1::get (index_3of3, id3))
#
THE set => im1::set (index_3of3, id3, ts::add (set, triple));
NULL => im1::set (index_3of3, id3, ts::singleton(triple));
esac;
index_12of3
=
case (im2::get (index_12of3, (id1, id2)))
#
THE set => im2::set (index_12of3, (id1, id2), ts::add (set, triple));
NULL => im2::set (index_12of3, (id1, id2), ts::singleton(triple));
esac;
index_13of3
=
case (im2::get (index_13of3, (id1, id3)))
#
THE set => im2::set (index_13of3, (id1, id3), ts::add (set, triple));
NULL => im2::set (index_13of3, (id1, id3), ts::singleton(triple));
esac;
index_23of3
=
case (im2::get (index_23of3, (id2, id3)))
#
THE set => im2::set (index_23of3, (id2, id3), ts::add (set, triple));
NULL => im2::set (index_23of3, (id2, id3), ts::singleton(triple));
esac;
index_123of3
=
ts::add (index_123of3, triple);
{ index_1of2,
index_2of2,
#
index_12of2,
#
#
index_1of3,
index_2of3,
index_3of3,
#
index_12of3,
index_13of3,
index_23of3,
#
index_123of3
}: Tuplebase(X);
};
fun drop_duple
(
{ index_1of2,
index_2of2,
#
index_12of2,
#
#
index_1of3,
index_2of3,
index_3of3,
#
index_12of3,
index_13of3,
index_23of3,
#
index_123of3
}: Tuplebase(X),
duple as
( atom1 as { id => id1, ... },
atom2 as { id => id2, ... }
): Duple(X)
)
=
{ index_1of2
=
case (im1::get (index_1of2, id1))
#
THE set => if (ds::vals_count(set) > 1) im1::set (index_1of2, id1, ds::drop (set, duple));
else im1::drop (index_1of2, id1);
fi;
NULL => index_1of2; # Duple isn't in tuplebase. Possibly we should raise an exception here.
esac;
index_2of2
=
case (im1::get (index_2of2, id2))
#
THE set => if (ds::vals_count(set) > 1) im1::set (index_2of2, id2, ds::drop (set, duple));
else im1::drop (index_1of2, id2);
fi;
NULL => index_2of2; # Duple isn't in tuplebase. Possibly we should raise an exception here.
esac;
index_12of2
=
ds::drop (index_12of2, duple);
{ index_1of2,
index_2of2,
#
index_12of2,
#
#
index_1of3,
index_2of3,
index_3of3,
#
index_12of3,
index_13of3,
index_23of3,
#
index_123of3
}: Tuplebase(X);
};
fun drop_triple
(
{ index_1of2,
index_2of2,
#
index_12of2,
#
#
index_1of3,
index_2of3,
index_3of3,
#
index_12of3,
index_13of3,
index_23of3,
#
index_123of3
}: Tuplebase(X),
triple as
( atom1 as { id => id1, ... },
atom2 as { id => id2, ... },
atom3 as { id => id3, ... }
): Triple(X)
)
=
{ index_1of3
=
case (im1::get (index_1of3, id1))
#
THE set => if (ts::vals_count(set) > 1) im1::set (index_1of3, id1, ts::drop (set, triple));
else im1::drop (index_1of3, id1);
fi;
NULL => index_1of3; # Triple isn't in tuplebase. Possibly we should raise an exception here.
esac;
index_2of3
=
case (im1::get (index_2of3, id2))
#
THE set => if (ts::vals_count(set) > 1) im1::set (index_2of3, id2, ts::drop (set, triple));
else im1::drop (index_2of3, id2);
fi;
NULL => index_2of3; # Triple isn't in tuplebase. Possibly we should raise an exception here.
esac;
index_3of3
=
case (im1::get (index_3of3, id3))
#
THE set => if (ts::vals_count(set) > 1) im1::set (index_3of3, id3, ts::drop (set, triple));
else im1::drop (index_3of3, id3);
fi;
NULL => index_3of3; # Triple isn't in tuplebase. Possibly we should raise an exception here.
esac;
index_12of3
=
case (im2::get (index_12of3, (id1, id2)))
#
THE set => if (ts::vals_count(set) > 1) im2::set (index_12of3, (id1, id2), ts::drop (set, triple));
else im2::drop (index_12of3, (id1, id2));
fi;
NULL => index_12of3; # Triple isn't in tuplebase. Possibly we should raise an exception here.
esac;
index_13of3
=
case (im2::get (index_13of3, (id1, id3)))
#
THE set => if (ts::vals_count(set) > 1) im2::set (index_13of3, (id1, id3), ts::drop (set, triple));
else im2::drop (index_13of3, (id1, id3));
fi;
NULL => index_13of3; # Triple isn't in tuplebase. Possibly we should raise an exception here.
esac;
index_23of3
=
case (im2::get (index_23of3, (id2, id3)))
#
THE set => if (ts::vals_count(set) > 1) im2::set (index_23of3, (id2, id3), ts::drop (set, triple));
else im2::drop (index_23of3, (id2, id3));
fi;
NULL => index_23of3; # Triple isn't in tuplebase. Possibly we should raise an exception here.
esac;
index_123of3
=
ts::drop (index_123of3, triple);
{ index_1of2,
index_2of2,
#
index_12of2,
#
#
index_1of3,
index_2of3,
index_3of3,
#
index_12of3,
index_13of3,
index_23of3,
#
index_123of3
}: Tuplebase(X);
};
fun get_duples (t: Tuplebase(X)) = t.index_12of2;
#
fun get_duples1 (t: Tuplebase(X), a: Atom(X)) = im1::get (t.index_1of2, a.id);
fun get_duples2 (t: Tuplebase(X), a: Atom(X)) = im1::get (t.index_2of2, a.id);
#
fun has_duple (t: Tuplebase(X), d: Duple(X)) = ds::member (t.index_12of2, d);
fun get_triples (t: Tuplebase(X)) = t.index_123of3;
#
fun get_triples1 (t: Tuplebase(X), a: Atom(X)) = im1::get (t.index_1of3, a.id);
fun get_triples2 (t: Tuplebase(X), a: Atom(X)) = im1::get (t.index_2of3, a.id);
fun get_triples3 (t: Tuplebase(X), a: Atom(X)) = im1::get (t.index_3of3, a.id);
#
fun get_triples12 (t: Tuplebase(X), a: Atom(X), b: Atom(X)) = im2::get (t.index_12of3, (a.id, b.id));
fun get_triples13 (t: Tuplebase(X), a: Atom(X), c: Atom(X)) = im2::get (t.index_13of3, (a.id, c.id));
fun get_triples23 (t: Tuplebase(X), b: Atom(X), c: Atom(X)) = im2::get (t.index_23of3, (b.id, c.id));
#
fun has_triple (t: Tuplebase(X), d: Triple(X)) = ts::member (t.index_123of3, d);
fun make_atom ()
=
{ id => id_to_int (issue_unique_id ()),
datum => NONE
};
fun make_string_atom (s: String)
=
{ id => id_to_int (issue_unique_id ()),
datum => STRING s
};
fun make_float_atom (f: Float)
=
{ id => id_to_int (issue_unique_id ()),
datum => FLOAT f
};
fun make_other_atom (x: X)
=
{ id => id_to_int (issue_unique_id ()),
datum => OTHER x
};
fun string_of ({ id, datum => STRING s }: Atom(X)) => THE s;
string_of _ => NULL;
end;
fun float_of ({ id, datum => FLOAT f }: Atom(X)) => THE f;
float_of _ => NULL;
end;
fun other_of ({ id, datum => OTHER x }: Atom(X)) => THE x;
other_of _ => NULL;
end;
fun atoms_apply # Apply do_atom to all Atoms in Tuplebase.
( { index_12of2,
index_123of3,
...
}: Tuplebase(X)
)
(do_atom: Atom(X) -> Void)
=
{ ds::apply do_duple index_12of2;
ts::apply do_triple index_123of3;
}
where
already_seen = REF is1::empty;
#
fun do_duple ((a1, a2): Duple(X))
=
{
if (not (is1::member (*already_seen, a1.id)))
#
already_seen := is1::add (*already_seen, a1.id);
do_atom a1;
fi;
if (not (is1::member (*already_seen, a2.id)))
#
already_seen := is1::add (*already_seen, a2.id);
do_atom a2;
fi;
};
fun do_triple ((a1, a2, a3): Triple(X))
=
{
if (not (is1::member (*already_seen, a1.id)))
#
already_seen := is1::add (*already_seen, a1.id);
do_atom a1;
fi;
if (not (is1::member (*already_seen, a2.id)))
#
already_seen := is1::add (*already_seen, a2.id);
do_atom a2;
fi;
if (not (is1::member (*already_seen, a3.id)))
#
already_seen := is1::add (*already_seen, a3.id);
do_atom a3;
fi;
};
end;
};
end;