Radosław Rowicki b669d2df1e Added list comprehensions and standard List, Option, Func, Pair, and Triple library (#105)
* 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
2019-08-14 13:53:58 +02:00

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);
}