// Creates a coat check service
contract MakeCoatCheck(ret) = {
new (portIn, portOut):iopair, hanger in {
ret!(*portOut) |
for (@method, ack, ...@rest <= portIn) {
match method {
// Initially checks the coat
case "new" => match rest {
case (initialCoat) => new ticket in {
ack!(*ticket) |
// Hang the coat on the hanger corresponding
// to the ticket
@(*ticket | *hanger)!(initialCoat)
}
}
// Retrieves the coat
case "get" => match rest {
case (ticket) => {
// Find the right hanger
for (@coat <! @(*ticket | *hanger)) {
// Return the coat
ack!(coat)
}
}
}
// Replaces the old coat with a new one.
case "set" => match rest {
case (store, @newCoat) => {
// Throw away the existing coat
for (_ <- @(*ticket | *hanger)) {
// Hang up the new one
@(*ticket | *hanger)!(newCoat) |
ack!()
}
}
}
}
}
}
}
// Attenuation of coat check for sealing and unsealing
contract MakeSealerUnsealer(ret) = {
new (sealerIn, sealerOut):iopair,
(unsealerIn, unsealerOut):iopair,
mapRet in {
ret!(*sealerOut, *unsealerOut) |
MakeCoatCheck(ccRet) |
for (cc <- ccRet) {
for (@value, ret <= sealerIn) {
cc!("new", *ret, value)
} |
for (ticket, ret <= unsealerIn) {
cc!("get", *ret, *ticket)
}
}
}
}
// MakeSealerUnsealer usage
new ret in {
MakeSealerUnsealer(ret) |
for (sign, validate <- ret) {
new signatureRet in {
sign("Hello", signatureRet) |
for (signature <- signatureRet) {
new ack in {
// Hangs if signature is invalid
validate(signature, ack) |
for (_ <- ack) {
// Act on signed message
}
}
}
}
}
}
contract MakeMint(ret) = {
new suRet in {
MakeSealerUnsealer(suRet) |
for (sealer, unsealer <- suRet) {
new (makeWalletIn, makeWalletOut):iopair in {
for (@initialBalance, walletRet <= makeWalletIn) {
new (walletIn, walletOut):iopair, balance,
(decrIn, decrOut):iopair in {
balance!(initialBalance) |
for (@amount, ack <= decrIn) {
for (@currentBalance <- balance) {
if (amount <= currentBalance) {
balance!(currentBalance - amount)
ack!(true)
} else {
balance!(currentBalance)
ack!(false)
}
}
} |
for (@method, methodRet, ...args <= walletIn) {
match method {
case "getBalance" => {
for (@currentBalance <! balance) {
methodRet!(currentBalance)
}
}
case "sprout" => {
makeWalletOut!(0, methodRet)
}
case "getDecr" => {
sealer!(decrOut, methodRet)
}
case "deposit" => {
args match {
(amount, src) => new decrRet in {
@src!("getDecr", decrRet) |
for (srcDecr <- decrRet) new unsealedRet in {
unsealer!(srcDecr, unsealedRet) |
for (unsealed <- unsealedRet;
@currentBalance <- balance) new ack in {
unsealed(amount, ack) |
for (@result <- ack) {
if (result) {
balance!(currentBalance + amount)
} else {
balance!(currentBalance)
} |
methodRet!()
}
}
}
}
}
}
}
}
} |
walletRet!(walletOut)
} |
ret!(*makeWalletOut)
}
}
}
}
// Usage
new mintRet in {
// Create a new currency/token/mint
MakeMint(mintRet) |
for (mint <- mintRet) new wallet1Ret, wallet2Ret in {
// Call mint with an initial balance to mint some money
// and put it in the wallet
mint(100, wallet1Ret) |
mint(200, wallet2Ret) |
for (wallet1 <- wallet1Ret; wallet2 <- wallet2Ret) {
// Move 50 tokens from wallet1 to wallet2
new ack in {
wallet2!("deposit", 50, wallet1, ack) |
for (_ <- ack) new balanceRet in {
wallet2!("getBalance", balanceRet) |
for (@balance <- balanceRet) {
// Prints 250
system!("print", balance)
}
}
}
}
}
}