diff --git a/playground/src/examples/index.ts b/playground/src/examples/index.ts index 1887acad..e1db06b3 100644 --- a/playground/src/examples/index.ts +++ b/playground/src/examples/index.ts @@ -125,12 +125,39 @@ function main() returns (word) { { id: "option", name: "Option", - description: "A generic optional value: checked division returns an Option instead of reverting.", + description: "A reusable Option module and a splitter contract: checked division returns an Option instead of reverting.", entry: "main.sol", files: [ { path: "main.sol", content: `import * from std; +import * from std.dispatch; +import {Option, checkedDiv, unwrapOr} from option; + +contract Splitter { + // Each recipient's equal share of the pot; zero recipients yields + // zero instead of reverting on division. + function share(pot: uint256, recipients: uint256) public returns (uint256) { + return unwrapOr(checkedDiv(pot, recipients), uint256(0)); + } + + // What is left over after handing out equal shares. + function remainder(pot: uint256, recipients: uint256) public returns (uint256) { + match (checkedDiv(pot, recipients)) { + case Option.Some(perRecipient) { return pot - perRecipient * recipients; } + default { return pot; } + } + } +} +`, + }, + { + path: "option.sol", + content: `// Candidate standard-library inventory: this module should disappear once +// std provides Option. +import * from std; +import * from std.Generic; +import * from std.StorageGeneric; enum Option { None, @@ -138,24 +165,28 @@ enum Option { } // Division by zero yields Option.None instead of reverting. -function checkedDiv(a: word, b: word) returns (Option) { - if (b == 0) { +function checkedDiv(a: uint256, b: uint256) returns (Option) { + if (b == uint256(0)) { return Option.None; } return Option.Some(a / b); } -function unwrapOr(option: Option, orElse: word) returns (word) { +function unwrapOr(option: Option, orElse: a) returns (a) { match (option) { case Option.Some(value) { return value; } default { return orElse; } } } -function main() returns (word) { - // 84 / 2 succeeds with Some(42); 84 / 0 would fall back to 0. - return unwrapOr(checkedDiv(84, 2), 0); +function contains(option: Option, value: a) returns (bool) where a: Eq { + match (option) { + case Option.Some(inner) { return inner == value; } + default { return false; } + } } + +export { Option(*), checkedDiv, unwrapOr, contains }; `, }, ], @@ -234,29 +265,11 @@ contract Escrow { path: "main.sol", content: `import * from std; import * from std.dispatch; -import * from std.Generic; -import * from std.StorageGeneric; -import {caller} from std.opcodes; +import {Option, contains} from option; +import {sender} from context; // A token either has an owner or does not exist: unset mapping entries // read back as Option.None. -enum Option { - None, - Some(a) -} - -function contains(option: Option, value: a) returns (bool) where a: Eq { - match (option) { - case Option.Some(inner) { return inner == value; } - default { return false; } - } -} - -// msg.sender: the CALLER opcode lifted from word into address. -function sender() returns (address) { - return address(caller()); -} - contract MiniNFT { nextId : uint256; owners : mapping(uint256 => Option
); @@ -310,6 +323,59 @@ contract MiniNFT { } } } +`, + }, + { + path: "option.sol", + content: `// Candidate standard-library inventory: this module should disappear once +// std provides Option. +import * from std; +import * from std.Generic; +import * from std.StorageGeneric; + +enum Option { + None, + Some(a) +} + +// Division by zero yields Option.None instead of reverting. +function checkedDiv(a: uint256, b: uint256) returns (Option) { + if (b == uint256(0)) { + return Option.None; + } + return Option.Some(a / b); +} + +function unwrapOr(option: Option, orElse: a) returns (a) { + match (option) { + case Option.Some(value) { return value; } + default { return orElse; } + } +} + +function contains(option: Option, value: a) returns (bool) where a: Eq { + match (option) { + case Option.Some(inner) { return inner == value; } + default { return false; } + } +} + +export { Option(*), checkedDiv, unwrapOr, contains }; +`, + }, + { + path: "context.sol", + content: `// Candidate standard-library inventory: this module should disappear once +// std provides transaction context helpers. +import * from std; +import {caller} from std.opcodes; + +// msg.sender: the CALLER opcode lifted from word into address. +function sender() returns (address) { + return address(caller()); +} + +export { sender }; `, }, ],