247 lines
5.3 KiB
Rust
Raw Normal View History

import std::bitv;
export t;
export create_tritv;
export tritv_clone;
export tritv_set;
export to_vec;
export trit;
export dont_care;
export ttrue;
export tfalse;
export tritv_get;
export tritv_set_all;
export tritv_difference;
export tritv_union;
export tritv_intersect;
export tritv_copy;
export tritv_clear;
export tritv_doesntcare;
/* for a fixed index:
10 = "this constraint may or may not be true after execution"
01 = "this constraint is definitely true"
00 = "this constraint is definitely false"
11 should never appear
FIXME: typestate precondition (uncertain and val must
have the same length; 11 should never appear in a given position)
*/
type t = rec(bitv::t uncertain, bitv::t val, uint nbits);
tag trit {
ttrue;
tfalse;
dont_care;
}
fn create_tritv(uint len) -> t {
ret rec(uncertain=bitv::create(len, true),
val=bitv::create(len, false),
nbits=len);
}
fn trit_minus(trit a, trit b) -> trit {
/* 2 - anything = 2
1 - 1 = 2
1 - 0 is an error
1 - 2 = 1
0 - 1 is an error
0 - anything else - 0
*/
alt (a) {
case (dont_care) { dont_care }
case (ttrue) {
alt (b) {
case (ttrue) { dont_care }
case (tfalse) { ttrue } /* internally contradictory, but
I guess it'll get flagged? */
case (dont_care) { ttrue }
}
}
case (tfalse) {
alt (b) {
case (ttrue) { tfalse } /* see above comment */
case (_) { tfalse }
}
}
}
}
fn trit_or(trit a, trit b) -> trit {
alt (a) {
case (dont_care) { b }
case (ttrue) { ttrue }
case (tfalse) {
alt (b) {
case (ttrue) { dont_care } /* FIXME: ?????? */
case (_) { tfalse }
}
}
}
}
// FIXME: not sure about this
fn trit_and(trit a, trit b) -> trit {
alt (a) {
case (dont_care) { dont_care }
case (ttrue) {
alt (b) {
case (dont_care) { dont_care }
case (ttrue) { ttrue }
case (tfalse) { tfalse } // FIXME: ???
}
}
case (tfalse) { tfalse }
}
}
fn tritv_difference(&t p1, &t p2) -> bool {
let uint i = 0u;
assert (p1.nbits == p2.nbits);
let uint sz = p1.nbits;
auto changed = false;
while (i < sz) {
auto old = tritv_get(p1, i);
auto new = trit_minus(old, tritv_get(p2, i));
changed = changed || (old != new);
tritv_set(i, p1, new);
i += 1u;
}
ret changed;
}
fn tritv_union(&t p1, &t p2) -> bool {
let uint i = 0u;
assert (p1.nbits == p2.nbits);
let uint sz = p1.nbits;
auto changed = false;
while (i < sz) {
auto old = tritv_get(p1, i);
auto new = trit_or(old, tritv_get(p2, i));
changed = changed || (old != new);
tritv_set(i, p1, new);
i += 1u;
}
ret changed;
}
fn tritv_intersect(&t p1, &t p2) -> bool {
let uint i = 0u;
assert (p1.nbits == p2.nbits);
let uint sz = p1.nbits;
auto changed = false;
while (i < sz) {
auto old = tritv_get(p1, i);
auto new = trit_and(old, tritv_get(p2, i));
changed = changed || (old != new);
tritv_set(i, p1, new);
i += 1u;
}
ret changed;
}
fn tritv_get(&t v, uint i) -> trit {
auto b1 = bitv::get(v.uncertain, i);
auto b2 = bitv::get(v.val, i);
assert (! (b1 && b2));
if (b1) { dont_care }
else if (b2) { ttrue }
else { tfalse}
}
fn tritv_set(uint i, &t v, trit t) -> bool {
auto old = tritv_get(v, i);
alt (t) {
case (dont_care) {
bitv::set(v.uncertain, i, true);
bitv::set(v.val, i, false);
}
case (ttrue) {
bitv::set(v.uncertain, i, false);
bitv::set(v.val, i, true);
}
case (tfalse) {
bitv::set(v.uncertain, i, false);
bitv::set(v.val, i, false);
}
}
ret (old != t);
}
fn tritv_copy(&t target, &t source) -> bool {
let uint i = 0u;
assert (target.nbits == source.nbits);
auto changed = false;
auto old;
auto new;
while (i < target.nbits) {
old = bitv::get(target.uncertain, i);
new = bitv::get(source.uncertain, i);
bitv::set(target.uncertain, i, new);
changed = changed || (old != new);
old = bitv::get(target.val, i);
new = bitv::get(source.val, i);
bitv::set(target.val, i, new);
changed = changed || (old != new);
i += 1u;
}
ret changed;
}
fn tritv_set_all(&t v) {
let uint i = 0u;
while (i < v.nbits) {
tritv_set(i, v, ttrue);
i += 1u;
}
}
fn tritv_clear(&t v) {
let uint i = 0u;
while (i < v.nbits) {
tritv_set(i, v, dont_care);
i += 1u;
}
}
fn tritv_clone(&t v) -> t {
ret rec(uncertain=bitv::clone(v.uncertain),
val=bitv::clone(v.val),
nbits=v.nbits);
}
fn tritv_doesntcare(&t v) -> bool {
let uint i = 0u;
while (i < v.nbits) {
if (tritv_get(v, i) != dont_care) {
ret false;
}
i += 1u;
}
ret true;
}
fn to_vec(&t v) -> vec[uint] {
let uint i = 0u;
let vec[uint] rslt = [];
while (i < v.nbits) {
rslt += [alt (tritv_get(v, i)) {
case (dont_care) { 2u }
case (ttrue) { 1u }
case (tfalse) { 0u } }];
i += 1u;
}
ret rslt;
}
//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
//