
* Added standard List library and list comprehensions Added List library. Flatmaps WIP Fixed dependency in flat_map fcode generation Updated tests to use custom list lib Added comprehension test Added stdlib sanity Test * Extended stdlib for lists. Added error message for redefinition of stdlibx * Fixed type template * Improved stdlib * More functions * Fixed cyclic includes * Refixed imports and added few tests * Added fail test * Undelete removed type spec * Remove typo * Fix iter function * Fixed typo * Added if guards and let statements in list comp * Added more fail tests * Option stliv * 2 and 3 tuple stdlib * Updated stdlib to new syntax. Added recursor and changed all/any functions * Fixed performance issues. Changed include management * Fixed hash type
127 lines
3.2 KiB
ReasonML
127 lines
3.2 KiB
ReasonML
|
|
open Rte;
|
|
|
|
/* Contract type */
|
|
module type Voting = {
|
|
type state;
|
|
type args = list(string);
|
|
let stateRep : state_rep(state);
|
|
|
|
let init : args => state;
|
|
let giveRightToVote : address => unit;
|
|
let delegate : address => unit;
|
|
let vote : int => unit;
|
|
let winnerName : unit => string;
|
|
let currentTally : unit => list((string, int));
|
|
};
|
|
|
|
/* Contract implementation */
|
|
module Voting : Voting = {
|
|
|
|
/* Not so nice */
|
|
module AddrKey = { type t = address; let compare = Pervasives.compare };
|
|
module AddrMap = Map.Make(AddrKey);
|
|
type addr_map('a) = AddrMap.t('a);
|
|
|
|
/* Types */
|
|
|
|
type proposal =
|
|
{ name: string
|
|
, mutable voteCount: uint
|
|
};
|
|
|
|
type voter =
|
|
{ mutable weight: int
|
|
, mutable delegate: option(address)
|
|
, mutable vote: option(int)
|
|
};
|
|
|
|
type state =
|
|
{ chairPerson: address
|
|
, mutable voters: addr_map(voter)
|
|
, proposals: list(proposal)
|
|
};
|
|
|
|
/* Initialization */
|
|
type args = list(string);
|
|
let init(proposalNames: args): state =
|
|
{ chairPerson: caller(),
|
|
voters: AddrMap.empty,
|
|
proposals: MyList.map((name) => {name: name, voteCount: 0}, proposalNames)
|
|
};
|
|
|
|
/* Boilerplate */
|
|
let stateRep = newStateRep();
|
|
let state() = getState(stateRep);
|
|
|
|
let initVoter() = { weight: 1, delegate: None, vote: None };
|
|
|
|
let giveRightToVote(voter: address) = {
|
|
require(caller() == state().chairPerson);
|
|
require(!AddrMap.mem(voter, state().voters));
|
|
state().voters = AddrMap.add(voter, initVoter(), state().voters);
|
|
()
|
|
};
|
|
|
|
let rec delegateChain(delegate: address) = {
|
|
require(delegate != caller()); /* Delegation loop! */
|
|
let voter = AddrMap.find(delegate, state().voters);
|
|
switch(voter.delegate) {
|
|
| None => delegate;
|
|
| Some(d) => delegateChain(d)
|
|
}
|
|
};
|
|
|
|
let addVote(candidate, weight) = {
|
|
let proposal = MyList.nth(state().proposals, candidate);
|
|
proposal.voteCount = proposal.voteCount + weight;
|
|
};
|
|
|
|
let delegateVote(delegateTo: address, weight: uint) = {
|
|
let voter = AddrMap.find(delegateTo, state().voters);
|
|
switch(voter.vote) {
|
|
| Some(vote) => addVote(vote, weight)
|
|
| None => voter.weight = voter.weight + weight
|
|
}
|
|
};
|
|
|
|
let delegate(delegateTo: address) = {
|
|
require(delegateTo != caller());
|
|
let voter = AddrMap.find(caller(), state().voters);
|
|
require(voter.vote == None);
|
|
let finalDelegate = delegateChain(delegateTo);
|
|
voter.vote = Some(0); /* Hm... */
|
|
voter.delegate = Some(finalDelegate);
|
|
delegateVote(finalDelegate, voter.weight)
|
|
};
|
|
|
|
let vote(candidate: uint) = {
|
|
let voter = AddrMap.find(caller(), state().voters);
|
|
require(voter.vote == None);
|
|
voter.vote = Some(candidate);
|
|
addVote(candidate, voter.weight);
|
|
};
|
|
|
|
let rec winningProposal'(current, rest) =
|
|
switch(rest) {
|
|
| [] => current;
|
|
| [p, ...ps] => winningProposal'(p.voteCount > current.voteCount ? p : current, ps)
|
|
};
|
|
|
|
/* const */
|
|
let winningProposal() : proposal = {
|
|
switch(state().proposals) {
|
|
| [] => abort()
|
|
| [p, ...ps] => winningProposal'(p, ps)
|
|
}
|
|
};
|
|
|
|
/* const */
|
|
let winnerName() = winningProposal().name;
|
|
|
|
/* const */
|
|
let currentTally() =
|
|
MyList.map((p) => (p.name, p.voteCount), state().proposals);
|
|
|
|
}
|