Commits

Dan Connolly  committed 0127bda Draft

let's try contracts

  • Participants
  • Parent commits 682d06f
  • Branches contracts

Comments (0)

Files changed (2)

File money.coffee

 
 # js doesn't have immutable function args, does it?
 # Guards can be translated to assert, but it's a little messy.
-
-assert = require('assert')
+# Let's try contracts.
 
 makeMint = (name) ->
   [sealer, unsealer] = makeBrandPair(name)
+
+  mint :: {
+    makePurse: (Num and (!(x) -> x >= 0)) -> Any
+  }
+
   mint = {
     __printOn: (out) ->
       out.print("<#{name}'s mint>")
 
     makePurse: (balance) ->
-      assert.ok(typeof balance == 'number' && balance >= 0)
 
+      decr :: (Num and (!(a) -> 0 < a && a < balance)) -> Undefined
       decr = (amount) ->
-        assert.ok(0 < amount && amount < balance)
         balance -= amount
 
+      purse :: {
+        deposit: (Num, Any) -> Undefined
+      }
+
       purse = {
         __printOn: (out) ->
           out.print("<has #{balance} #{name} bucks>")
         getDecr: () -> sealer.seal(decr)
 
         deposit: (amount, src) ->
-          assert.ok(typeof amount == 'number')
           unsealer.unseal(src.getDecr())(amount)
           balance += amount
         }
 bobMainPurse.__printOn(out)
 # value: <has 0 Carol bucks>
 
+bad1 = carolMint.makePurse(-5)
+bad2 = carolMint.makePurse('-5')
+
 
 # struggling to figure out node.js module conventions
 # I think module caching threw me off.
-(function() {
-  var aliceMainPurse, assert, bobMainPurse, carolMint, makeBrandPair, makeMint, out, s, u, x, _ref;
-  assert = require('assert');
+
+((function(cb) {
+  if (typeof(define) === 'function' && define.amd) {
+    require(['contracts'], cb);
+  } else if (typeof(require) === 'function') {
+    cb(require('contracts.js'));
+  } else {
+    cb(window.contracts);
+  }
+})(function(__contracts) {
+  var Undefined, Null, Num, Bool, Str, Odd, Even, Pos, Nat, Neg, Self, Any, None, __define, __require, __exports;
+
+Undefined =  __contracts.Undefined;
+Null      =  __contracts.Null;
+Num       =  __contracts.Num;
+Bool      =  __contracts.Bool;
+Str       =  __contracts.Str;
+Odd       =  __contracts.Odd;
+Even      =  __contracts.Even;
+Pos       =  __contracts.Pos;
+Nat       =  __contracts.Nat;
+Neg       =  __contracts.Neg;
+Self      =  __contracts.Self;
+Any       =  __contracts.Any;
+None      =  __contracts.None;
+
+if (typeof(define) === 'function' && define.amd) {
+  // we're using requirejs
+
+  // Allow for anonymous functions
+  __define = function(name, deps, callback) {
+    var cb, wrapped_callback;
+
+    if(typeof(name) !== 'string') {
+      cb = deps;
+    } else {
+      cb = callback;
+    }
+
+
+    wrapped_callback = function() {
+      var i, ret, used_arguments = [];
+      for (i = 0; i < arguments.length; i++) {
+        used_arguments[i] = __contracts.use(arguments[i], "money.coffee");
+      }
+      ret = cb.apply(this, used_arguments);
+      return __contracts.setExported(ret, "money.coffee");
+    };
+
+    if(!Array.isArray(deps)) {
+      deps = wrapped_callback;
+    }
+    define(name, deps, wrapped_callback);
+  };
+} else if (typeof(require) !== 'undefined' && typeof(exports) !== 'undefined') {
+  // we're using commonjs
+
+  __exports = __contracts.exports("money.coffee", exports)
+  __require = function(module) {
+    module = require.apply(this, arguments);
+    return __contracts.use(module, "money.coffee");
+  };
+}
+  (function(define, require, exports) {
+      var aliceMainPurse, bad1, bad2, bobMainPurse, carolMint, makeBrandPair, makeMint, out, s, u, x, _ref;
+
   makeMint = function(name) {
     var mint, sealer, unsealer, _ref;
     _ref = makeBrandPair(name), sealer = _ref[0], unsealer = _ref[1];
-    mint = {
+    mint = __contracts.guard(__contracts.object({
+      makePurse: __contracts.fun([
+        __contracts.and(Num, (function(x) {
+          return x >= 0;
+        }).toContract())
+      ], Any, {})
+    }, {}),{
       __printOn: function(out) {
         return out.print("<" + name + "'s mint>");
       },
       makePurse: function(balance) {
         var decr, purse;
-        assert.ok(typeof balance === 'number' && balance >= 0);
-        decr = function(amount) {
-          assert.ok(0 < amount && amount < balance);
+        decr = __contracts.guard(__contracts.fun([
+          __contracts.and(Num, (function(a) {
+            return 0 < a && a < balance;
+          }).toContract())
+        ], Undefined, {}),function(amount) {
           return balance -= amount;
-        };
-        purse = {
+        });
+        purse = __contracts.guard(__contracts.object({
+          deposit: __contracts.fun([Num, Any], Undefined, {})
+        }, {}),{
           __printOn: function(out) {
             return out.print("<has " + balance + " " + name + " bucks>");
           },
             return sealer.seal(decr);
           },
           deposit: function(amount, src) {
-            assert.ok(typeof amount === 'number');
             unsealer.unseal(src.getDecr())(amount);
             return balance += amount;
           }
-        };
+        });
         return purse;
       }
-    };
+    });
     return mint;
   };
+
   makeBrandPair = function(hint) {
     var content, makeSealedBox, noObject, sealer, shared, unsealer;
     noObject = new Object();
     };
     return [sealer, unsealer];
   };
+
   _ref = makeBrandPair('bob'), s = _ref[0], u = _ref[1];
+
   x = s.seal('abc');
+
   console.log(x);
+
   console.log(u.unseal(x));
+
   out = {
     print: function(s) {
       return console.log(s);
     }
   };
+
   carolMint = makeMint("Carol");
+
   carolMint.__printOn(out);
+
   aliceMainPurse = carolMint.makePurse(1000);
+
   aliceMainPurse.__printOn(out);
+
   bobMainPurse = carolMint.makePurse(0);
+
   bobMainPurse.__printOn(out);
+
+  bad1 = carolMint.makePurse(-5);
+
+  bad2 = carolMint.makePurse('-5');
+
   exports.makeBrandPair = makeBrandPair;
+
   exports.makeMint = makeMint;
-}).call(this);
+
+  }).call(this, __define, __require, __exports);
+}));