Skip to content

Commit d7708d9

Browse files
committed
adding this contracts
1 parent e93be01 commit d7708d9

File tree

6 files changed

+185
-6
lines changed

6 files changed

+185
-6
lines changed

macros/disabled.js

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,8 @@ let import = macro {
211211
}).join(', ');
212212
var domName = '(' + domStr + ')';
213213
var rngStr = options && options.namesStr ? options.namesStr[options.namesStr.length - 1] + ': ' + rng : rng;
214-
var contractName = domName + ' -> ' + rngStr + (options && options.dependencyStr ? ' | ' + options.dependencyStr : '');
214+
var thisName = options && options.thisContract ? ' this ' + options.thisContract : '';
215+
var contractName = domName + thisName + ' -> ' + rngStr + (options && options.dependencyStr ? ' | ' + options.dependencyStr : '');
215216
var c = new Contract(contractName, 'fun', function (blame, unwrapTypeVar) {
216217
return function (f) {
217218
blame = blame.addParents(contractName);
@@ -236,8 +237,13 @@ let import = macro {
236237
}
237238
}
238239
checkedArgs = checkedArgs.concat(args.slice(i));
240+
var checkedThis = thisVal;
241+
if (options && options.thisContract) {
242+
var thisProj = options.thisContract.proj(blame.swap().addLocation('the this value of'));
243+
checkedThis = thisProj(thisVal);
244+
}
239245
assert(rng instanceof Contract, 'The range is not a contract');
240-
var rawResult = target.apply(thisVal, checkedArgs);
246+
var rawResult = target.apply(checkedThis, checkedArgs);
241247
var rngUnwrap = rng.type === 'fun' ? unwrapTypeVar : !unwrapTypeVar;
242248
var rngProj = rng.proj(blame.addLocation('the return of'), rngUnwrap);
243249
var rngResult = rngProj(rawResult);
@@ -477,7 +483,21 @@ macroclass named_contract {
477483
rule { $name $[:] $contract:any_contract }
478484
}
479485

486+
macro this_contract {
487+
rule { this $contract:object_contract } => { $contract }
488+
}
489+
480490
macro function_contract {
491+
rule { ($dom:named_contract (,) ...) this $this:object_contract -> $range:named_contract | { $guard ... } } => {
492+
_c.fun([$dom$contract (,) ...], $range$contract, {
493+
dependency: function($dom$name (,) ..., $range$name) {
494+
$guard ...
495+
},
496+
thisContract: $this,
497+
namesStr: [$(stringify (($dom$name))) (,) ..., stringify (($range$name))],
498+
dependencyStr: stringify (($guard ...))
499+
})
500+
}
481501
rule { ($dom:named_contract (,) ...) -> $range:named_contract | { $guard ... } } => {
482502
_c.fun([$dom$contract (,) ...], $range$contract, {
483503
dependency: function($dom$name (,) ..., $range$name) {
@@ -487,6 +507,16 @@ macro function_contract {
487507
dependencyStr: stringify (($guard ...))
488508
})
489509
}
510+
rule { ($dom:named_contract (,) ...) this $this:object_contract -> $range:named_contract | $guard:expr } => {
511+
_c.fun([$dom$contract (,) ...], $range$contract, {
512+
dependency: function($dom$name (,) ..., $range$name) {
513+
return $guard;
514+
},
515+
thisContract: $this,
516+
namesStr: [$(stringify (($dom$name))) (,) ..., stringify (($range$name))],
517+
dependencyStr: stringify ($guard)
518+
})
519+
}
490520
rule { ($dom:named_contract (,) ...) -> $range:named_contract | $guard:expr } => {
491521
_c.fun([$dom$contract (,) ...], $range$contract, {
492522
dependency: function($dom$name (,) ..., $range$name) {
@@ -496,6 +526,11 @@ macro function_contract {
496526
dependencyStr: stringify ($guard)
497527
})
498528
}
529+
rule { ($dom:any_contract (,) ...) this $this:object_contract -> $range:any_contract } => {
530+
_c.fun([$dom (,) ...], $range, {
531+
thisContract: $this
532+
})
533+
}
499534
rule { ($dom:any_contract (,) ...) -> $range:any_contract } => {
500535
_c.fun([$dom (,) ...], $range)
501536
}

macros/index.js

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,8 @@ let import = macro {
211211
}).join(', ');
212212
var domName = '(' + domStr + ')';
213213
var rngStr = options && options.namesStr ? options.namesStr[options.namesStr.length - 1] + ': ' + rng : rng;
214-
var contractName = domName + ' -> ' + rngStr + (options && options.dependencyStr ? ' | ' + options.dependencyStr : '');
214+
var thisName = options && options.thisContract ? ' this ' + options.thisContract : '';
215+
var contractName = domName + thisName + ' -> ' + rngStr + (options && options.dependencyStr ? ' | ' + options.dependencyStr : '');
215216
var c = new Contract(contractName, 'fun', function (blame, unwrapTypeVar) {
216217
return function (f) {
217218
blame = blame.addParents(contractName);
@@ -236,8 +237,13 @@ let import = macro {
236237
}
237238
}
238239
checkedArgs = checkedArgs.concat(args.slice(i));
240+
var checkedThis = thisVal;
241+
if (options && options.thisContract) {
242+
var thisProj = options.thisContract.proj(blame.swap().addLocation('the this value of'));
243+
checkedThis = thisProj(thisVal);
244+
}
239245
assert(rng instanceof Contract, 'The range is not a contract');
240-
var rawResult = target.apply(thisVal, checkedArgs);
246+
var rawResult = target.apply(checkedThis, checkedArgs);
241247
var rngUnwrap = rng.type === 'fun' ? unwrapTypeVar : !unwrapTypeVar;
242248
var rngProj = rng.proj(blame.addLocation('the return of'), rngUnwrap);
243249
var rngResult = rngProj(rawResult);
@@ -478,6 +484,16 @@ macroclass named_contract {
478484
}
479485

480486
macro function_contract {
487+
rule { ($dom:named_contract (,) ...) this $this:object_contract -> $range:named_contract | { $guard ... } } => {
488+
_c.fun([$dom$contract (,) ...], $range$contract, {
489+
dependency: function($dom$name (,) ..., $range$name) {
490+
$guard ...
491+
},
492+
thisContract: $this,
493+
namesStr: [$(stringify (($dom$name))) (,) ..., stringify (($range$name))],
494+
dependencyStr: stringify (($guard ...))
495+
})
496+
}
481497
rule { ($dom:named_contract (,) ...) -> $range:named_contract | { $guard ... } } => {
482498
_c.fun([$dom$contract (,) ...], $range$contract, {
483499
dependency: function($dom$name (,) ..., $range$name) {
@@ -487,6 +503,16 @@ macro function_contract {
487503
dependencyStr: stringify (($guard ...))
488504
})
489505
}
506+
rule { ($dom:named_contract (,) ...) this $this:object_contract -> $range:named_contract | $guard:expr } => {
507+
_c.fun([$dom$contract (,) ...], $range$contract, {
508+
dependency: function($dom$name (,) ..., $range$name) {
509+
return $guard;
510+
},
511+
thisContract: $this,
512+
namesStr: [$(stringify (($dom$name))) (,) ..., stringify (($range$name))],
513+
dependencyStr: stringify ($guard)
514+
})
515+
}
490516
rule { ($dom:named_contract (,) ...) -> $range:named_contract | $guard:expr } => {
491517
_c.fun([$dom$contract (,) ...], $range$contract, {
492518
dependency: function($dom$name (,) ..., $range$name) {
@@ -496,6 +522,11 @@ macro function_contract {
496522
dependencyStr: stringify ($guard)
497523
})
498524
}
525+
rule { ($dom:any_contract (,) ...) this $this:object_contract -> $range:any_contract } => {
526+
_c.fun([$dom (,) ...], $range, {
527+
thisContract: $this
528+
})
529+
}
499530
rule { ($dom:any_contract (,) ...) -> $range:any_contract } => {
500531
_c.fun([$dom (,) ...], $range)
501532
}

src/contracts.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -285,8 +285,9 @@
285285
var domName = "(" + domStr + ")";
286286

287287
var rngStr = options && options.namesStr ? options.namesStr[options.namesStr.length - 1] + ": " + rng : rng;
288+
var thisName = options && options.thisContract ? " this " + options.thisContract : "";
288289

289-
var contractName = domName + " -> " + rngStr +
290+
var contractName = domName + thisName + " -> " + rngStr +
290291
(options && options.dependencyStr ? " | " + options.dependencyStr : "");
291292

292293
var c = new Contract(contractName, "fun", function(blame, unwrapTypeVar) {
@@ -322,10 +323,16 @@
322323
}
323324
}
324325
checkedArgs = checkedArgs.concat(args.slice(i));
326+
var checkedThis = thisVal;
327+
if(options && options.thisContract) {
328+
var thisProj = options.thisContract.proj(blame.swap()
329+
.addLocation("the this value of"));
330+
checkedThis = thisProj(thisVal);
331+
}
325332

326333
assert(rng instanceof Contract, "The range is not a contract");
327334

328-
var rawResult = target.apply(thisVal, checkedArgs);
335+
var rawResult = target.apply(checkedThis, checkedArgs);
329336
var rngUnwrap = rng.type === "fun" ? unwrapTypeVar : !unwrapTypeVar;
330337
var rngProj = rng.proj(blame.addLocation("the return of"), rngUnwrap);
331338
var rngResult = rngProj(rawResult);

src/macros-disabled.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,21 @@ macroclass named_contract {
3636
rule { $name $[:] $contract:any_contract }
3737
}
3838

39+
macro this_contract {
40+
rule { this $contract:object_contract } => { $contract }
41+
}
42+
3943
macro function_contract {
44+
rule { ($dom:named_contract (,) ...) this $this:object_contract -> $range:named_contract | { $guard ... } } => {
45+
_c.fun([$dom$contract (,) ...], $range$contract, {
46+
dependency: function($dom$name (,) ..., $range$name) {
47+
$guard ...
48+
},
49+
thisContract: $this,
50+
namesStr: [$(stringify (($dom$name))) (,) ..., stringify (($range$name))],
51+
dependencyStr: stringify (($guard ...))
52+
})
53+
}
4054
rule { ($dom:named_contract (,) ...) -> $range:named_contract | { $guard ... } } => {
4155
_c.fun([$dom$contract (,) ...], $range$contract, {
4256
dependency: function($dom$name (,) ..., $range$name) {
@@ -46,6 +60,16 @@ macro function_contract {
4660
dependencyStr: stringify (($guard ...))
4761
})
4862
}
63+
rule { ($dom:named_contract (,) ...) this $this:object_contract -> $range:named_contract | $guard:expr } => {
64+
_c.fun([$dom$contract (,) ...], $range$contract, {
65+
dependency: function($dom$name (,) ..., $range$name) {
66+
return $guard;
67+
},
68+
thisContract: $this,
69+
namesStr: [$(stringify (($dom$name))) (,) ..., stringify (($range$name))],
70+
dependencyStr: stringify ($guard)
71+
})
72+
}
4973
rule { ($dom:named_contract (,) ...) -> $range:named_contract | $guard:expr } => {
5074
_c.fun([$dom$contract (,) ...], $range$contract, {
5175
dependency: function($dom$name (,) ..., $range$name) {
@@ -55,6 +79,11 @@ macro function_contract {
5579
dependencyStr: stringify ($guard)
5680
})
5781
}
82+
rule { ($dom:any_contract (,) ...) this $this:object_contract -> $range:any_contract } => {
83+
_c.fun([$dom (,) ...], $range, {
84+
thisContract: $this
85+
})
86+
}
5887
rule { ($dom:any_contract (,) ...) -> $range:any_contract } => {
5988
_c.fun([$dom (,) ...], $range)
6089
}

src/macros.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,16 @@ macroclass named_contract {
3737
}
3838

3939
macro function_contract {
40+
rule { ($dom:named_contract (,) ...) this $this:object_contract -> $range:named_contract | { $guard ... } } => {
41+
_c.fun([$dom$contract (,) ...], $range$contract, {
42+
dependency: function($dom$name (,) ..., $range$name) {
43+
$guard ...
44+
},
45+
thisContract: $this,
46+
namesStr: [$(stringify (($dom$name))) (,) ..., stringify (($range$name))],
47+
dependencyStr: stringify (($guard ...))
48+
})
49+
}
4050
rule { ($dom:named_contract (,) ...) -> $range:named_contract | { $guard ... } } => {
4151
_c.fun([$dom$contract (,) ...], $range$contract, {
4252
dependency: function($dom$name (,) ..., $range$name) {
@@ -46,6 +56,16 @@ macro function_contract {
4656
dependencyStr: stringify (($guard ...))
4757
})
4858
}
59+
rule { ($dom:named_contract (,) ...) this $this:object_contract -> $range:named_contract | $guard:expr } => {
60+
_c.fun([$dom$contract (,) ...], $range$contract, {
61+
dependency: function($dom$name (,) ..., $range$name) {
62+
return $guard;
63+
},
64+
thisContract: $this,
65+
namesStr: [$(stringify (($dom$name))) (,) ..., stringify (($range$name))],
66+
dependencyStr: stringify ($guard)
67+
})
68+
}
4969
rule { ($dom:named_contract (,) ...) -> $range:named_contract | $guard:expr } => {
5070
_c.fun([$dom$contract (,) ...], $range$contract, {
5171
dependency: function($dom$name (,) ..., $range$name) {
@@ -55,6 +75,11 @@ macro function_contract {
5575
dependencyStr: stringify ($guard)
5676
})
5777
}
78+
rule { ($dom:any_contract (,) ...) this $this:object_contract -> $range:any_contract } => {
79+
_c.fun([$dom (,) ...], $range, {
80+
thisContract: $this
81+
})
82+
}
5883
rule { ($dom:any_contract (,) ...) -> $range:any_contract } => {
5984
_c.fun([$dom (,) ...], $range)
6085
}

test/test_contracts.js

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -688,4 +688,56 @@ blaming: (calling context for id)
688688
`
689689
})
690690

691+
it("should allow you to specify this contracts", function() {
692+
@ (Num) this { name: Str} -> Str
693+
function f(n) { return this.name; }
694+
695+
var o = {
696+
nam: "Bob",
697+
f: f
698+
};
699+
700+
blame of {
701+
o.f(100);
702+
} should be `f: contract violation
703+
expected: Str
704+
given: undefined
705+
in: the name property of
706+
the this value of
707+
(Num) this {name: Str} -> Str
708+
function f guarded at line: 693
709+
blaming: (calling context for f)
710+
`
711+
})
712+
713+
// it("should allow you to use method contracts on objects", function() {
714+
// @ let Person = {
715+
// name: Str,
716+
// age: Num,
717+
// hello: () -> Str
718+
// }
719+
720+
// @ (Person) -> Str
721+
// function foo(p) { return p.hello(); }
722+
723+
// (foo({
724+
// name: "Bob",
725+
// age: 42,
726+
// hello: function() { return this.name; }
727+
// })).should.equal("Bob");
728+
729+
// var badPerson = {
730+
// nam: "Bob",
731+
// age: 100,
732+
// hello: function() { }
733+
// }
734+
735+
// var p = {
736+
// name: "Bob",
737+
// age: 42,
738+
// hello: function() { return this.name; }.bind(badPerson)
739+
// }
740+
// // foo(p);
741+
// })
742+
691743
});

0 commit comments

Comments
 (0)