Add builtin bit field type
This commit is contained in:
parent
d8bf0bda45
commit
a367d5040a
@ -79,6 +79,7 @@ global_env() ->
|
|||||||
Event = {id, Ann, "event"},
|
Event = {id, Ann, "event"},
|
||||||
State = {id, Ann, "state"},
|
State = {id, Ann, "state"},
|
||||||
Hash = {id, Ann, "hash"},
|
Hash = {id, Ann, "hash"},
|
||||||
|
Bits = {id, Ann, "bits"},
|
||||||
Oracle = fun(Q, R) -> {app_t, Ann, {id, Ann, "oracle"}, [Q, R]} end,
|
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,
|
Query = fun(Q, R) -> {app_t, Ann, {id, Ann, "oracle_query"}, [Q, R]} end,
|
||||||
Unit = {tuple_t, Ann, []},
|
Unit = {tuple_t, Ann, []},
|
||||||
@ -159,6 +160,12 @@ global_env() ->
|
|||||||
{["String", "sha3"], Fun1(String, Hash)},
|
{["String", "sha3"], Fun1(String, Hash)},
|
||||||
{["String", "sha256"], Fun1(String, Hash)},
|
{["String", "sha256"], Fun1(String, Hash)},
|
||||||
{["String", "blake2b"], 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", "zero"], Bits},
|
||||||
%% Conversion
|
%% Conversion
|
||||||
{["Int", "to_str"], Fun1(Int, String)},
|
{["Int", "to_str"], Fun1(Int, String)},
|
||||||
{["Address", "to_str"], Fun1(Address, String)}
|
{["Address", "to_str"], Fun1(Address, String)}
|
||||||
|
@ -348,6 +348,30 @@ ast_body(?qid_app(["String", "concat"], [String1, String2], _, _), Icode) ->
|
|||||||
ast_body(?qid_app(["String", "sha3"], [String], _, _), Icode) ->
|
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
|
||||||
|
ast_body(?qid_app(["Bits", "test"], [Bits, Ix], _, _), Icode) ->
|
||||||
|
%% (Bits bsr Ix) band 1
|
||||||
|
#binop{ op = 'band'
|
||||||
|
, left = #binop{ op = 'bsr', left = ast_body(Ix, Icode), right = ast_body(Bits, Icode) }
|
||||||
|
, right = #integer{ value = 1 } };
|
||||||
|
ast_body(?qid_app(["Bits", "set"], [Bits, Ix], _, _), Icode) ->
|
||||||
|
%% Bits bor (1 bsl Ix)
|
||||||
|
#binop{ op = 'bor'
|
||||||
|
, left = ast_body(Bits, Icode)
|
||||||
|
, right = #binop{ op = 'bsl', left = ast_body(Ix, Icode), right = #integer{ value = 1 } } };
|
||||||
|
ast_body(?qid_app(["Bits", "clear"], [Bits, Ix], _, _), Icode) ->
|
||||||
|
%% Bits band (bnot (1 bsl Ix))
|
||||||
|
#binop{ op = 'band'
|
||||||
|
, left = ast_body(Bits, Icode)
|
||||||
|
, right = #unop{ op = 'bnot'
|
||||||
|
, rand = #binop{ op = 'bsl'
|
||||||
|
, left = ast_body(Ix, Icode)
|
||||||
|
, right = #integer{ value = 1 } } } };
|
||||||
|
ast_body({qid, _, ["Bits", "zero"]}, _Icode) ->
|
||||||
|
#integer{ value = 0 };
|
||||||
|
ast_body(?qid_app(["Bits", "sum"], [Bits], _, _), Icode) ->
|
||||||
|
builtin_call(popcount, [ast_body(Bits, Icode), #integer{ value = 0 }]);
|
||||||
|
|
||||||
%% -- Conversion
|
%% -- Conversion
|
||||||
ast_body(?qid_app(["Int", "to_str"], [Int], _, _), Icode) ->
|
ast_body(?qid_app(["Int", "to_str"], [Int], _, _), Icode) ->
|
||||||
builtin_call(int_to_str, [ast_body(Int, Icode)]);
|
builtin_call(int_to_str, [ast_body(Int, Icode)]);
|
||||||
|
@ -148,6 +148,7 @@ builtin_function(BF) ->
|
|||||||
string_shift_copy -> bfun(BF, builtin_string_shift_copy());
|
string_shift_copy -> bfun(BF, builtin_string_shift_copy());
|
||||||
str_equal_p -> bfun(BF, builtin_str_equal_p());
|
str_equal_p -> bfun(BF, builtin_str_equal_p());
|
||||||
str_equal -> bfun(BF, builtin_str_equal());
|
str_equal -> bfun(BF, builtin_str_equal());
|
||||||
|
popcount -> bfun(BF, builtin_popcount());
|
||||||
int_to_str -> bfun(BF, builtin_int_to_str());
|
int_to_str -> bfun(BF, builtin_int_to_str());
|
||||||
addr_to_str -> bfun(BF, builtin_addr_to_str());
|
addr_to_str -> bfun(BF, builtin_addr_to_str());
|
||||||
{baseX_int, X} -> bfun(BF, builtin_baseX_int(X));
|
{baseX_int, X} -> bfun(BF, builtin_baseX_int(X));
|
||||||
@ -398,6 +399,17 @@ builtin_str_equal() ->
|
|||||||
)),
|
)),
|
||||||
word}.
|
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() ->
|
builtin_int_to_str() ->
|
||||||
{[{"i", word}], ?call({baseX_int, 10}, [?V(i)]), word}.
|
{[{"i", word}], ?call({baseX_int, 10}, [?V(i)]), word}.
|
||||||
|
|
||||||
|
@ -59,6 +59,7 @@ builtin_types() ->
|
|||||||
Word = fun([]) -> word end,
|
Word = fun([]) -> word end,
|
||||||
#{ "bool" => Word
|
#{ "bool" => Word
|
||||||
, "int" => Word
|
, "int" => Word
|
||||||
|
, "bits" => Word
|
||||||
, "string" => fun([]) -> string end
|
, "string" => fun([]) -> string end
|
||||||
, "address" => Word
|
, "address" => Word
|
||||||
, "hash" => Word
|
, "hash" => Word
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
contract MultiSig =
|
contract MultiSig =
|
||||||
|
|
||||||
record pending_state = { yetNeeded : uint, ownersDone : uint, index : uint }
|
record pending_state = { yetNeeded : int, ownersDone : bits, index : int }
|
||||||
|
|
||||||
datatype event =
|
datatype event =
|
||||||
Confirmation (address, hash) // of { .owner : Address, .operation : Hash }
|
Confirmation (address, hash) // of { .owner : Address, .operation : Hash }
|
||||||
@ -13,18 +13,18 @@ contract MultiSig =
|
|||||||
| OwnerChanged (address, address) // of { .oldOwner : Address, .newOwner : Address }
|
| OwnerChanged (address, address) // of { .oldOwner : Address, .newOwner : Address }
|
||||||
| OwnerAdded (address) // of { .newOwner : Address }
|
| OwnerAdded (address) // of { .newOwner : Address }
|
||||||
| OwnerRemoved (address) // of { .removedOwner : 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
|
record state = { nRequired : int
|
||||||
, nOwners : uint
|
, nOwners : int
|
||||||
, owners : map(uint, address)
|
, owners : map(int, address)
|
||||||
, ownerIndex : map(address, uint)
|
, ownerIndex : map(address, int)
|
||||||
, pending : map(hash, pending_state)
|
, pending : map(hash, pending_state)
|
||||||
, pendingIndex : list(address) }
|
, pendingIndex : list(address) }
|
||||||
|
|
||||||
function init (owners : list(address), nRequired : uint) : state =
|
function init (owners : list(address), nRequired : int) : state =
|
||||||
let n = length(owners) + 1
|
let n = length(owners) + 1
|
||||||
{ nRequired = nRequired,
|
{ nRequired = nRequired,
|
||||||
nOwners = n,
|
nOwners = n,
|
||||||
@ -39,10 +39,9 @@ contract MultiSig =
|
|||||||
function revoke(operation : hash) =
|
function revoke(operation : hash) =
|
||||||
let ownerIx = lookup(state.ownerIndex, caller())
|
let ownerIx = lookup(state.ownerIndex, caller())
|
||||||
let pending = lookup(state.pendingIndex, operation)
|
let pending = lookup(state.pendingIndex, operation)
|
||||||
let ownerIxBit = 1 bsl (ownerIx - 1)
|
let _ = require(Bits.test(pending.ownersDone, ownerIx))
|
||||||
let _ = require(pending.ownersDone band ownerIxBit > 0)
|
|
||||||
let pending' = pending { yetNeeded = pending.yetNeeded + 1
|
let pending' = pending { yetNeeded = pending.yetNeeded + 1
|
||||||
, ownersDone = pending.ownersDone - ownerIxBit }
|
, ownersDone = Bits.clear(pending.ownersDone, ownerIx - 1) }
|
||||||
put(state{ pendingIndex.operator = pending' })
|
put(state{ pendingIndex.operator = pending' })
|
||||||
event(Revoke(caller, operation))
|
event(Revoke(caller, operation))
|
||||||
|
|
||||||
@ -91,7 +90,7 @@ contract MultiSig =
|
|||||||
, pendingIx = [] },
|
, pendingIx = [] },
|
||||||
event = [OwnerRemoved(oldOwner)] }
|
event = [OwnerRemoved(oldOwner)] }
|
||||||
|
|
||||||
function changeRequirement(newReq : uint) =
|
function changeRequirement(newReq : int) =
|
||||||
let _ = require(newReq =< state.nOwners)
|
let _ = require(newReq =< state.nOwners)
|
||||||
switch(check_pending(callhash()))
|
switch(check_pending(callhash()))
|
||||||
CheckFail(state') => { state = state' }
|
CheckFail(state') => { state = state' }
|
||||||
@ -102,7 +101,7 @@ contract MultiSig =
|
|||||||
event = [ReqChanged(newReq)] }
|
event = [ReqChanged(newReq)] }
|
||||||
|
|
||||||
|
|
||||||
function getOwner(ownerIx0 : uint) =
|
function getOwner(ownerIx0 : int) =
|
||||||
lookup(state.owners, ownerIx0 + 1)
|
lookup(state.owners, ownerIx0 + 1)
|
||||||
|
|
||||||
function isOwner(owner : address) =
|
function isOwner(owner : address) =
|
||||||
@ -116,8 +115,7 @@ contract MultiSig =
|
|||||||
Some(pending) =>
|
Some(pending) =>
|
||||||
let _ = require(isOwner(owner))
|
let _ = require(isOwner(owner))
|
||||||
let ownerIx = lookup(state.ownerIndex, owner)
|
let ownerIx = lookup(state.ownerIndex, owner)
|
||||||
let ownerIxBit = 1 bsl (ownerIx - 1)
|
Bits.test(pending.ownersDone, ownerIx - 1)
|
||||||
(pending.ownersDone band ownerIxBit) != 0
|
|
||||||
|
|
||||||
/* Leave the rest for now... */
|
/* Leave the rest for now... */
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user