Add set operations on bit fields (union, isect, diff)

This commit is contained in:
Ulf Norell 2019-01-25 14:10:12 +01:00
parent a367d5040a
commit 9c77622c7c
2 changed files with 22 additions and 18 deletions

View File

@ -165,6 +165,9 @@ global_env() ->
{["Bits", "clear"], Fun([Bits, Int], Bits)}, {["Bits", "clear"], Fun([Bits, Int], Bits)},
{["Bits", "test"], Fun([Bits, Int], Bool)}, {["Bits", "test"], Fun([Bits, Int], Bool)},
{["Bits", "sum"], Fun1(Bits, Int)}, {["Bits", "sum"], Fun1(Bits, Int)},
{["Bits", "intersection"], Fun([Bits, Bits], Bits)},
{["Bits", "union"], Fun([Bits, Bits], Bits)},
{["Bits", "difference"], Fun([Bits, Bits], Bits)},
{["Bits", "zero"], Bits}, {["Bits", "zero"], Bits},
%% Conversion %% Conversion
{["Int", "to_str"], Fun1(Int, String)}, {["Int", "to_str"], Fun1(Int, String)},

View File

@ -349,24 +349,25 @@ ast_body(?qid_app(["String", "sha3"], [String], _, _), Icode) ->
#unop{ op = 'sha3', rand = ast_body(String, Icode) }; #unop{ op = 'sha3', rand = ast_body(String, Icode) };
%% -- Bits %% -- Bits
ast_body(?qid_app(["Bits", "test"], [Bits, Ix], _, _), Icode) -> ast_body(?qid_app(["Bits", Fun], Args, _, _), Icode)
%% (Bits bsr Ix) band 1 when Fun == "test"; Fun == "set"; Fun == "clear";
#binop{ op = 'band' Fun == "union"; Fun == "intersection"; Fun == "difference" ->
, left = #binop{ op = 'bsr', left = ast_body(Ix, Icode), right = ast_body(Bits, Icode) } C = fun(N) when is_integer(N) -> #integer{ value = N };
, right = #integer{ value = 1 } }; (AST) -> ast_body(AST, Icode) end,
ast_body(?qid_app(["Bits", "set"], [Bits, Ix], _, _), Icode) -> Bin = fun(O) -> fun(A, B) -> #binop{ op = O, left = C(A), right = C(B) } end end,
%% Bits bor (1 bsl Ix) And = Bin('band'),
#binop{ op = 'bor' Or = Bin('bor'),
, left = ast_body(Bits, Icode) Bsl = fun(A, B) -> (Bin('bsl'))(B, A) end, %% flipped arguments
, right = #binop{ op = 'bsl', left = ast_body(Ix, Icode), right = #integer{ value = 1 } } }; Bsr = fun(A, B) -> (Bin('bsr'))(B, A) end,
ast_body(?qid_app(["Bits", "clear"], [Bits, Ix], _, _), Icode) -> Neg = fun(A) -> #unop{ op = 'bnot', rand = C(A) } end,
%% Bits band (bnot (1 bsl Ix)) case [Fun | Args] of
#binop{ op = 'band' ["test", Bits, Ix] -> And(Bsr(Bits, Ix), 1);
, left = ast_body(Bits, Icode) ["set", Bits, Ix] -> Or(Bits, Bsl(1, Ix));
, right = #unop{ op = 'bnot' ["clear", Bits, Ix] -> And(Bits, Neg(Bsl(1, Ix)));
, rand = #binop{ op = 'bsl' ["union", A, B] -> Or(A, B);
, left = ast_body(Ix, Icode) ["intersection", A, B] -> And(A, B);
, right = #integer{ value = 1 } } } }; ["difference", A, B] -> And(A, Neg(And(A, B)))
end;
ast_body({qid, _, ["Bits", "zero"]}, _Icode) -> ast_body({qid, _, ["Bits", "zero"]}, _Icode) ->
#integer{ value = 0 }; #integer{ value = 0 };
ast_body(?qid_app(["Bits", "sum"], [Bits], _, _), Icode) -> ast_body(?qid_app(["Bits", "sum"], [Bits], _, _), Icode) ->