prune-lang 0.2.3

Prune is a constraint logic programming language with branching heuristic.
Documentation
datatype Bit where
| O
| I
end

datatype BitVec2 where
| BV2(Bit, Bit)
end

datatype BitVec4 where
| BV4(BitVec2, BitVec2)
end

datatype BitVec8 where
| BV8(BitVec4, BitVec4)
end

datatype BitVec16 where
| BV16(BitVec8, BitVec8)
end

function zero_bv2() -> BitVec2
begin
    BV2(O, O)
end

function zero_bv4() -> BitVec4
begin
    BV4(BV2(O, O), BV2(O, O))
end

function zero_bv8() -> BitVec8
begin
    BV8(BV4(BV2(O, O), BV2(O, O)), BV4(BV2(O, O), BV2(O, O)))
end

// adder (Ci, A, B) -> (S, Co)
function full_adder_1(ci: Bit, x: Bit, y: Bit) -> (Bit, Bit) 
begin
    match (ci, x, y) with
    | (O, O, O) => (O, O)
    | (I, O, O) => (I, O)
    | (O, I, O) => (I, O)
    | (I, I, O) => (O, I)
    | (O, O, I) => (I, O)
    | (I, O, I) => (O, I)
    | (O, I, I) => (O, I)
    | (I, I, I) => (I, I)
    end
end

function full_adder_2(c: Bit, a: BitVec2, b: BitVec2) -> (BitVec2, Bit)
begin
    let BV2(ah, al) = a;
    let BV2(bh, bl) = b;
    let (sl, cl) = full_adder_1(c, al, bl);
    let (sh, ch) = full_adder_1(cl, ah, bh);
    (BV2(sh, sl), ch)
end

function full_adder_4(c: Bit, a: BitVec4, b: BitVec4) -> (BitVec4, Bit)
begin
    let BV4(ah, al) = a;
    let BV4(bh, bl) = b;
    let (sl, cl) = full_adder_2(c, al, bl);
    let (sh, ch) = full_adder_2(cl, ah, bh);
    (BV4(sh, sl), ch)
end

function full_adder_8(c: Bit, a: BitVec8, b: BitVec8) -> (BitVec8, Bit) 
begin
    let BV8(ah, al) = a;
    let BV8(bh, bl) = b;
    let (sl, cl) = full_adder_4(c, al, bl);
    let (sh, ch) = full_adder_4(cl, ah, bh);
    (BV8(sh, sl), ch)
end

function full_adder_16(c: Bit, a: BitVec16, b: BitVec16) -> (BitVec16, Bit) 
begin
    let BV16(ah, al) = a;
    let BV16(bh, bl) = b;
    let (sl, cl) = full_adder_8(c, al, bl);
    let (sh, ch) = full_adder_8(cl, ah, bh);
    (BV16(sh, sl), ch)
end

function add_bv1(a: Bit, b: Bit) -> Bit
begin
    let (s, c) = full_adder_1(O, a, b);
    guard c = O;
    s
end

function add_bv2(a: BitVec2, b: BitVec2) -> BitVec2
begin
    let (s, c) = full_adder_2(O, a, b);
    guard c = O;
    s
end

function add_bv4(a: BitVec4, b: BitVec4) -> BitVec4
begin
    let (s, c) = full_adder_4(O, a, b);
    guard c = O;
    s
end

function add_bv8(a: BitVec8, b: BitVec8) -> BitVec8
begin
    let (s, c) = full_adder_8(O, a, b);
    guard c = O;
    s
end

function add_bv16(a: BitVec16, b: BitVec16) -> BitVec16
begin
    let (s, c) = full_adder_16(O, a, b);
    guard c = O;
    s
end

function mul_bv1(a: Bit, b: Bit) -> BitVec2
begin
    match (a, b) with
    | (O, O) => BV2(O, O)
    | (O, I) => BV2(O, O)
    | (I, O) => BV2(O, O)
    | (I, I) => BV2(O, I)
    end
end

function mul_bv2(a: BitVec2, b: BitVec2) -> BitVec4
begin
    let BV2(ah, al) = a;
    let BV2(bh, bl) = b;
    let low = mul_bv1(al, bl);
    let high = mul_bv1(ah, bh);
    let BV2(mh, ml) = add_bv2(mul_bv1(ah, bl), mul_bv1(al, bh));
    let mid = BV4(BV2(O, mh), BV2(ml, O));
    add_bv4(BV4(high, low), mid)
end

function mul_bv4(a: BitVec4, b: BitVec4) -> BitVec8
begin
    let BV4(ah, al) = a;
    let BV4(bh, bl) = b;
    let low = mul_bv2(al, bl);
    let high = mul_bv2(ah, bh);
    let BV4(mh, ml) = add_bv4(mul_bv2(ah, bl), mul_bv2(al, bh));
    let mid = BV8(BV4(zero_bv2(), mh), BV4(ml, zero_bv2()));
    add_bv8(BV8(high, low), mid)
end

function mul_bv8(a: BitVec8, b: BitVec8) -> BitVec16
begin
    let BV8(ah, al) = a;
    let BV8(bh, bl) = b;
    let low = mul_bv4(al, bl);
    let high = mul_bv4(ah, bh);
    let BV8(mh, ml) = add_bv8(mul_bv4(ah, bl), mul_bv4(al, bh));
    let mid = BV16(BV8(zero_bv4(), mh), BV8(ml, zero_bv4()));
    add_bv16(BV16(high, low), mid)
end

function example(a: BitVec4, b: BitVec4, c: BitVec4)
begin
    fresh a2, b2;
    guard a = add_bv4(a2, BV4(BV2(O, O), BV2(O, I)));
    guard b = add_bv4(b2, BV4(BV2(O, O), BV2(O, I)));
    guard add_bv8(mul_bv4(a, a), mul_bv4(b, b)) = mul_bv4(c, c);
end

query example(depth_step=100, depth_limit=3000, answer_limit=6)