Merge pull request #17 from aeternity/PT-163478903-builtin-bits-type
PT-163478903 builtin bits type
This commit is contained in:
commit
53299b9b17
@ -79,6 +79,7 @@ global_env() ->
|
||||
Event = {id, Ann, "event"},
|
||||
State = {id, Ann, "state"},
|
||||
Hash = {id, Ann, "hash"},
|
||||
Bits = {id, Ann, "bits"},
|
||||
Oracle = fun(Q, R) -> {app_t, Ann, {id, Ann, "oracle"}, [Q, R]} end,
|
||||
Query = fun(Q, R) -> {app_t, Ann, {id, Ann, "oracle_query"}, [Q, R]} end,
|
||||
Unit = {tuple_t, Ann, []},
|
||||
@ -159,6 +160,16 @@ global_env() ->
|
||||
{["String", "sha3"], Fun1(String, Hash)},
|
||||
{["String", "sha256"], Fun1(String, Hash)},
|
||||
{["String", "blake2b"], Fun1(String, Hash)},
|
||||
%% Bits
|
||||
{["Bits", "set"], Fun([Bits, Int], Bits)},
|
||||
{["Bits", "clear"], Fun([Bits, Int], Bits)},
|
||||
{["Bits", "test"], Fun([Bits, Int], Bool)},
|
||||
{["Bits", "sum"], Fun1(Bits, Int)},
|
||||
{["Bits", "intersection"], Fun([Bits, Bits], Bits)},
|
||||
{["Bits", "union"], Fun([Bits, Bits], Bits)},
|
||||
{["Bits", "difference"], Fun([Bits, Bits], Bits)},
|
||||
{["Bits", "none"], Bits},
|
||||
{["Bits", "all"], Bits},
|
||||
%% Conversion
|
||||
{["Int", "to_str"], Fun1(Int, String)},
|
||||
{["Address", "to_str"], Fun1(Address, String)}
|
||||
@ -691,8 +702,7 @@ infer_infix({BoolOp, As})
|
||||
{fun_t, As, [], [Bool,Bool], Bool};
|
||||
infer_infix({IntOp, As})
|
||||
when IntOp == '+'; IntOp == '-'; IntOp == '*'; IntOp == '/';
|
||||
IntOp == '^'; IntOp == 'mod'; IntOp == 'bsl'; IntOp == 'bsr';
|
||||
IntOp == 'band'; IntOp == 'bor'; IntOp == 'bxor' ->
|
||||
IntOp == '^'; IntOp == 'mod' ->
|
||||
Int = {id, As, "int"},
|
||||
{fun_t, As, [], [Int, Int], Int};
|
||||
infer_infix({RelOp, As})
|
||||
@ -714,8 +724,7 @@ infer_infix({'++', As}) ->
|
||||
infer_prefix({'!',As}) ->
|
||||
Bool = {id, As, "bool"},
|
||||
{fun_t, As, [], [Bool], Bool};
|
||||
infer_prefix({IntOp,As})
|
||||
when IntOp =:= '-'; IntOp =:= 'bnot' ->
|
||||
infer_prefix({IntOp,As}) when IntOp =:= '-' ->
|
||||
Int = {id, As, "int"},
|
||||
{fun_t, As, [], [Int], Int}.
|
||||
|
||||
|
@ -348,6 +348,33 @@ ast_body(?qid_app(["String", "concat"], [String1, String2], _, _), Icode) ->
|
||||
ast_body(?qid_app(["String", "sha3"], [String], _, _), Icode) ->
|
||||
#unop{ op = 'sha3', rand = ast_body(String, Icode) };
|
||||
|
||||
%% -- Bits
|
||||
ast_body(?qid_app(["Bits", Fun], Args, _, _), Icode)
|
||||
when Fun == "test"; Fun == "set"; Fun == "clear";
|
||||
Fun == "union"; Fun == "intersection"; Fun == "difference" ->
|
||||
C = fun(N) when is_integer(N) -> #integer{ value = N };
|
||||
(X) -> X end,
|
||||
Bin = fun(O) -> fun(A, B) -> #binop{ op = O, left = C(A), right = C(B) } end end,
|
||||
And = Bin('band'),
|
||||
Or = Bin('bor'),
|
||||
Bsl = fun(A, B) -> (Bin('bsl'))(B, A) end, %% flipped arguments
|
||||
Bsr = fun(A, B) -> (Bin('bsr'))(B, A) end,
|
||||
Neg = fun(A) -> #unop{ op = 'bnot', rand = C(A) } end,
|
||||
case [Fun | [ ast_body(Arg, Icode) || Arg <- Args ]] of
|
||||
["test", Bits, Ix] -> And(Bsr(Bits, Ix), 1);
|
||||
["set", Bits, Ix] -> Or(Bits, Bsl(1, Ix));
|
||||
["clear", Bits, Ix] -> And(Bits, Neg(Bsl(1, Ix)));
|
||||
["union", A, B] -> Or(A, B);
|
||||
["intersection", A, B] -> And(A, B);
|
||||
["difference", A, B] -> And(A, Neg(And(A, B)))
|
||||
end;
|
||||
ast_body({qid, _, ["Bits", "none"]}, _Icode) ->
|
||||
#integer{ value = 0 };
|
||||
ast_body({qid, _, ["Bits", "all"]}, _Icode) ->
|
||||
#integer{ value = 1 bsl 256 - 1 };
|
||||
ast_body(?qid_app(["Bits", "sum"], [Bits], _, _), Icode) ->
|
||||
builtin_call(popcount, [ast_body(Bits, Icode), #integer{ value = 0 }]);
|
||||
|
||||
%% -- Conversion
|
||||
ast_body(?qid_app(["Int", "to_str"], [Int], _, _), Icode) ->
|
||||
builtin_call(int_to_str, [ast_body(Int, Icode)]);
|
||||
@ -526,9 +553,6 @@ ast_binop(Op, Ann, {typed, _, A, Type}, B, Icode)
|
||||
ast_binop('++', _, A, B, Icode) ->
|
||||
#funcall{ function = #var_ref{ name = {builtin, list_concat} },
|
||||
args = [ast_body(A, Icode), ast_body(B, Icode)] };
|
||||
%% Bit shift operations takes their arguments backwards!?
|
||||
ast_binop(Op, _, A, B, Icode) when Op =:= 'bsl'; Op =:= 'bsr' ->
|
||||
#binop{op = Op, right = ast_body(A, Icode), left = ast_body(B, Icode)};
|
||||
ast_binop(Op, _, A, B, Icode) ->
|
||||
#binop{op = Op, left = ast_body(A, Icode), right = ast_body(B, Icode)}.
|
||||
|
||||
|
@ -148,6 +148,7 @@ builtin_function(BF) ->
|
||||
string_shift_copy -> bfun(BF, builtin_string_shift_copy());
|
||||
str_equal_p -> bfun(BF, builtin_str_equal_p());
|
||||
str_equal -> bfun(BF, builtin_str_equal());
|
||||
popcount -> bfun(BF, builtin_popcount());
|
||||
int_to_str -> bfun(BF, builtin_int_to_str());
|
||||
addr_to_str -> bfun(BF, builtin_addr_to_str());
|
||||
{baseX_int, X} -> bfun(BF, builtin_baseX_int(X));
|
||||
@ -398,6 +399,17 @@ builtin_str_equal() ->
|
||||
)),
|
||||
word}.
|
||||
|
||||
%% Count the number of 1s in a bit field.
|
||||
builtin_popcount() ->
|
||||
%% function popcount(bits, acc) =
|
||||
%% if (bits == 0) acc
|
||||
%% else popcount(bits bsr 1, acc + bits band 1)
|
||||
{[{"bits", word}, {"acc", word}],
|
||||
{ifte, ?EQ(bits, 0),
|
||||
?V(acc),
|
||||
?call(popcount, [op('bsr', 1, bits), ?ADD(acc, op('band', bits, 1))])
|
||||
}, word}.
|
||||
|
||||
builtin_int_to_str() ->
|
||||
{[{"i", word}], ?call({baseX_int, 10}, [?V(i)]), word}.
|
||||
|
||||
|
@ -59,6 +59,7 @@ builtin_types() ->
|
||||
Word = fun([]) -> word end,
|
||||
#{ "bool" => Word
|
||||
, "int" => Word
|
||||
, "bits" => Word
|
||||
, "string" => fun([]) -> string end
|
||||
, "address" => Word
|
||||
, "hash" => Word
|
||||
|
@ -176,11 +176,11 @@ expr200() -> infixr(expr300(), binop('||')).
|
||||
expr300() -> infixr(expr400(), binop('&&')).
|
||||
expr400() -> infix(expr500(), binop(['<', '>', '=<', '>=', '==', '!='])).
|
||||
expr500() -> infixr(expr600(), binop(['::', '++'])).
|
||||
expr600() -> infixl(expr650(), binop(['+', '-', 'bor', 'bxor', 'bsr', 'bsl'])).
|
||||
expr600() -> infixl(expr650(), binop(['+', '-'])).
|
||||
expr650() -> ?RULE(many(token('-')), expr700(), prefixes(_1, _2)).
|
||||
expr700() -> infixl(expr750(), binop(['*', '/', mod, 'band'])).
|
||||
expr700() -> infixl(expr750(), binop(['*', '/', mod])).
|
||||
expr750() -> infixl(expr800(), binop(['^'])).
|
||||
expr800() -> ?RULE(many(choice(token('!'), token('bnot'))), expr900(), prefixes(_1, _2)).
|
||||
expr800() -> ?RULE(many(token('!')), expr900(), prefixes(_1, _2)).
|
||||
expr900() -> ?RULE(exprAtom(), many(elim()), elim(_1, _2)).
|
||||
|
||||
exprAtom() ->
|
||||
|
@ -359,20 +359,14 @@ bin_prec('++') -> {500, 600, 500};
|
||||
bin_prec('::') -> {500, 600, 500};
|
||||
bin_prec('+') -> {600, 600, 650};
|
||||
bin_prec('-') -> {600, 600, 650};
|
||||
bin_prec('bor') -> {600, 600, 650};
|
||||
bin_prec('bxor') -> {600, 600, 650};
|
||||
bin_prec('bsl') -> {600, 600, 650};
|
||||
bin_prec('bsr') -> {600, 600, 650};
|
||||
bin_prec('*') -> {700, 700, 750};
|
||||
bin_prec('/') -> {700, 700, 750};
|
||||
bin_prec(mod) -> {700, 700, 750};
|
||||
bin_prec('band') -> {700, 700, 750};
|
||||
bin_prec('^') -> {750, 750, 800}.
|
||||
|
||||
-spec un_prec(aeso_syntax:un_op()) -> {integer(), integer()}.
|
||||
un_prec('-') -> {650, 650};
|
||||
un_prec('!') -> {800, 800};
|
||||
un_prec('bnot') -> {800, 800}.
|
||||
un_prec('!') -> {800, 800}.
|
||||
|
||||
equals(Ann, A, B) ->
|
||||
{app, [{format, infix} | Ann], {'=', Ann}, [A, B]}.
|
||||
|
@ -37,8 +37,7 @@ lexer() ->
|
||||
, {"[^/*]+|[/*]", skip()} ],
|
||||
|
||||
Keywords = ["contract", "import", "let", "rec", "switch", "type", "record", "datatype", "if", "elif", "else", "function",
|
||||
"stateful", "true", "false", "and", "mod", "public", "private", "indexed", "internal",
|
||||
"band", "bor", "bxor", "bsl", "bsr", "bnot"],
|
||||
"stateful", "true", "false", "and", "mod", "public", "private", "indexed", "internal"],
|
||||
KW = string:join(Keywords, "|"),
|
||||
|
||||
Rules =
|
||||
|
@ -75,10 +75,10 @@
|
||||
|
||||
-type op() :: bin_op() | un_op().
|
||||
|
||||
-type bin_op() :: '+' | '-' | '*' | '/' | mod | '^' | 'band' | 'bor' | 'bsl' | 'bsr' | 'bxor'
|
||||
-type bin_op() :: '+' | '-' | '*' | '/' | mod | '^'
|
||||
| '++' | '::' | '<' | '>' | '=<' | '>=' | '==' | '!='
|
||||
| '||' | '&&' | '..'.
|
||||
-type un_op() :: '-' | '!' | 'bnot'.
|
||||
-type un_op() :: '-' | '!'.
|
||||
|
||||
-type expr()
|
||||
:: {lam, ann(), [arg()], expr()}
|
||||
|
@ -36,8 +36,6 @@ contract AllSyntax =
|
||||
(x, [y, z]) => bar({x = z, y = -y + - -z * (-1)})
|
||||
(x, y :: _) => ()
|
||||
|
||||
function bitOperations(x, y) = bnot (0xff00 band x bsl 4 bxor 0xa5a5a5 bsr 4 bor y)
|
||||
|
||||
function mutual() =
|
||||
let rec recFun(x : int) = mutFun(x)
|
||||
and mutFun(x) = if(x =< 0) 1 else x * recFun(x - 1)
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
contract MultiSig =
|
||||
|
||||
record pending_state = { yetNeeded : uint, ownersDone : uint, index : uint }
|
||||
record pending_state = { yetNeeded : int, ownersDone : bits, index : int }
|
||||
|
||||
datatype event =
|
||||
Confirmation (address, hash) // of { .owner : Address, .operation : Hash }
|
||||
@ -13,18 +13,18 @@ contract MultiSig =
|
||||
| OwnerChanged (address, address) // of { .oldOwner : Address, .newOwner : Address }
|
||||
| OwnerAdded (address) // of { .newOwner : Address }
|
||||
| OwnerRemoved (address) // of { .removedOwner : Address }
|
||||
| ReqChanged (uint) // of { .newReq : uint }
|
||||
| ReqChanged (int) // of { .newReq : int }
|
||||
|
||||
let maxOwners : uint = 250
|
||||
let maxOwners : int = 250
|
||||
|
||||
record state = { nRequired : uint
|
||||
, nOwners : uint
|
||||
, owners : map(uint, address)
|
||||
, ownerIndex : map(address, uint)
|
||||
record state = { nRequired : int
|
||||
, nOwners : int
|
||||
, owners : map(int, address)
|
||||
, ownerIndex : map(address, int)
|
||||
, pending : map(hash, pending_state)
|
||||
, pendingIndex : list(address) }
|
||||
|
||||
function init (owners : list(address), nRequired : uint) : state =
|
||||
function init (owners : list(address), nRequired : int) : state =
|
||||
let n = length(owners) + 1
|
||||
{ nRequired = nRequired,
|
||||
nOwners = n,
|
||||
@ -39,10 +39,9 @@ contract MultiSig =
|
||||
function revoke(operation : hash) =
|
||||
let ownerIx = lookup(state.ownerIndex, caller())
|
||||
let pending = lookup(state.pendingIndex, operation)
|
||||
let ownerIxBit = 1 bsl (ownerIx - 1)
|
||||
let _ = require(pending.ownersDone band ownerIxBit > 0)
|
||||
let _ = require(Bits.test(pending.ownersDone, ownerIx))
|
||||
let pending' = pending { yetNeeded = pending.yetNeeded + 1
|
||||
, ownersDone = pending.ownersDone - ownerIxBit }
|
||||
, ownersDone = Bits.clear(pending.ownersDone, ownerIx - 1) }
|
||||
put(state{ pendingIndex.operator = pending' })
|
||||
event(Revoke(caller, operation))
|
||||
|
||||
@ -91,7 +90,7 @@ contract MultiSig =
|
||||
, pendingIx = [] },
|
||||
event = [OwnerRemoved(oldOwner)] }
|
||||
|
||||
function changeRequirement(newReq : uint) =
|
||||
function changeRequirement(newReq : int) =
|
||||
let _ = require(newReq =< state.nOwners)
|
||||
switch(check_pending(callhash()))
|
||||
CheckFail(state') => { state = state' }
|
||||
@ -102,7 +101,7 @@ contract MultiSig =
|
||||
event = [ReqChanged(newReq)] }
|
||||
|
||||
|
||||
function getOwner(ownerIx0 : uint) =
|
||||
function getOwner(ownerIx0 : int) =
|
||||
lookup(state.owners, ownerIx0 + 1)
|
||||
|
||||
function isOwner(owner : address) =
|
||||
@ -116,8 +115,7 @@ contract MultiSig =
|
||||
Some(pending) =>
|
||||
let _ = require(isOwner(owner))
|
||||
let ownerIx = lookup(state.ownerIndex, owner)
|
||||
let ownerIxBit = 1 bsl (ownerIx - 1)
|
||||
(pending.ownersDone band ownerIxBit) != 0
|
||||
Bits.test(pending.ownersDone, ownerIx - 1)
|
||||
|
||||
/* Leave the rest for now... */
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
// - + * / mod arithmetic operators
|
||||
// bnot band bor bxor bsl bsr bitwise operators
|
||||
// ! && || logical operators
|
||||
// == != < > =< >= comparison operators
|
||||
// :: ++ list operators
|
||||
@ -13,12 +12,6 @@ contract Operators =
|
||||
"/" => a / b
|
||||
"mod" => a mod b
|
||||
"^" => a ^ b
|
||||
"bnot" => bnot a
|
||||
"band" => a band b
|
||||
"bor" => a bor b
|
||||
"bxor" => a bxor b
|
||||
"bsl" => a bsl b
|
||||
"bsr" => a bsr b
|
||||
|
||||
function bool_op(a : bool, b : bool, op : string) =
|
||||
switch(op)
|
||||
|
Loading…
x
Reference in New Issue
Block a user