Skip to content

Commit 2fb8dc4

Browse files
committed
adding and contract
1 parent 041e05f commit 2fb8dc4

File tree

6 files changed

+149
-12
lines changed

6 files changed

+149
-12
lines changed

macros/disabled.js

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,31 @@ let import = macro {
468468
function self() {
469469
var name = 'self';
470470
}
471+
function and(left, right) {
472+
if (!(left instanceof Contract)) {
473+
if (typeof left === 'function') {
474+
left = toContract(left);
475+
} else {
476+
throw new Error(left + ' is not a contract');
477+
}
478+
}
479+
if (!(right instanceof Contract)) {
480+
if (typeof right === 'function') {
481+
right = toContract(right);
482+
} else {
483+
throw new Error(right + ' is not a contract');
484+
}
485+
}
486+
var contractName = left + ' and ' + right;
487+
return new Contract(contractName, 'and', function (blame) {
488+
return function (val) {
489+
var leftProj = left.proj(blame.addExpected(contractName, true));
490+
var leftResult = leftProj(val);
491+
var rightProj = right.proj(blame.addExpected(contractName, true));
492+
return rightProj(leftResult);
493+
};
494+
});
495+
}
471496
function or(left, right) {
472497
if (!(left instanceof Contract)) {
473498
if (typeof left === 'function') {
@@ -548,6 +573,7 @@ let import = macro {
548573
check: check,
549574
fun: fun,
550575
or: or,
576+
and: and,
551577
self: new Contract('self', 'self', function (b) {
552578
return function () {
553579
};
@@ -706,7 +732,7 @@ macro predicate_contract {
706732
}
707733

708734

709-
macro non_or_contract {
735+
macro non_bin_contract {
710736
rule { $contract:predicate_contract } => { $contract }
711737
rule { $contract:function_contract } => { $contract }
712738
rule { $contract:object_contract } => { $contract }
@@ -717,14 +743,21 @@ macro non_or_contract {
717743
}
718744

719745
macro or_contract {
720-
rule { $left:non_or_contract or $right:any_contract } => {
746+
rule { $left:non_bin_contract or $right:any_contract } => {
721747
_c.or($left, $right)
722748
}
723749
}
724750

751+
macro and_contract {
752+
rule { $left:non_bin_contract and $right:any_contract } => {
753+
_c.and($left, $right)
754+
}
755+
}
756+
725757
macro any_contract {
726758
rule { $contract:or_contract } => { $contract }
727-
rule { $contract:non_or_contract } => { $contract }
759+
rule { $contract:and_contract } => { $contract }
760+
rule { $contract:non_bin_contract } => { $contract }
728761
}
729762

730763

macros/index.js

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,31 @@ let import = macro {
468468
function self() {
469469
var name = 'self';
470470
}
471+
function and(left, right) {
472+
if (!(left instanceof Contract)) {
473+
if (typeof left === 'function') {
474+
left = toContract(left);
475+
} else {
476+
throw new Error(left + ' is not a contract');
477+
}
478+
}
479+
if (!(right instanceof Contract)) {
480+
if (typeof right === 'function') {
481+
right = toContract(right);
482+
} else {
483+
throw new Error(right + ' is not a contract');
484+
}
485+
}
486+
var contractName = left + ' and ' + right;
487+
return new Contract(contractName, 'and', function (blame) {
488+
return function (val) {
489+
var leftProj = left.proj(blame.addExpected(contractName, true));
490+
var leftResult = leftProj(val);
491+
var rightProj = right.proj(blame.addExpected(contractName, true));
492+
return rightProj(leftResult);
493+
};
494+
});
495+
}
471496
function or(left, right) {
472497
if (!(left instanceof Contract)) {
473498
if (typeof left === 'function') {
@@ -548,6 +573,7 @@ let import = macro {
548573
check: check,
549574
fun: fun,
550575
or: or,
576+
and: and,
551577
self: new Contract('self', 'self', function (b) {
552578
return function () {
553579
};
@@ -706,7 +732,7 @@ macro predicate_contract {
706732
}
707733

708734

709-
macro non_or_contract {
735+
macro non_bin_contract {
710736
rule { $contract:predicate_contract } => { $contract }
711737
rule { $contract:function_contract } => { $contract }
712738
rule { $contract:object_contract } => { $contract }
@@ -717,14 +743,21 @@ macro non_or_contract {
717743
}
718744

719745
macro or_contract {
720-
rule { $left:non_or_contract or $right:any_contract } => {
746+
rule { $left:non_bin_contract or $right:any_contract } => {
721747
_c.or($left, $right)
722748
}
723749
}
724750

751+
macro and_contract {
752+
rule { $left:non_bin_contract and $right:any_contract } => {
753+
_c.and($left, $right)
754+
}
755+
}
756+
725757
macro any_contract {
726758
rule { $contract:or_contract } => { $contract }
727-
rule { $contract:non_or_contract } => { $contract }
759+
rule { $contract:and_contract } => { $contract }
760+
rule { $contract:non_bin_contract } => { $contract }
728761
}
729762

730763

src/contracts.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,33 @@
587587
var name = "self";
588588
}
589589

590+
function and(left, right) {
591+
if (!(left instanceof Contract)) {
592+
if (typeof left === "function") {
593+
left = toContract(left);
594+
} else {
595+
throw new Error(left + " is not a contract");
596+
}
597+
}
598+
if (!(right instanceof Contract)) {
599+
if (typeof right === "function") {
600+
right = toContract(right);
601+
} else {
602+
throw new Error(right + " is not a contract");
603+
}
604+
}
605+
606+
var contractName = left + " and " + right;
607+
return new Contract(contractName, "and", function(blame) {
608+
return function(val) {
609+
var leftProj = left.proj(blame.addExpected(contractName, true));
610+
var leftResult = leftProj(val);
611+
var rightProj = right.proj(blame.addExpected(contractName, true));
612+
return rightProj(leftResult);
613+
};
614+
})
615+
}
616+
590617
function or(left, right) {
591618
if (!(left instanceof Contract)) {
592619
if (typeof left === "function") {
@@ -649,6 +676,7 @@
649676
check: check,
650677
fun: fun,
651678
or: or,
679+
and: and,
652680
self: new Contract("self", "self", function(b) { return function() {}; }),
653681
repeat: repeat,
654682
optional: optional,

src/macros-disabled.js

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ macro predicate_contract {
146146
}
147147

148148

149-
macro non_or_contract {
149+
macro non_bin_contract {
150150
rule { $contract:predicate_contract } => { $contract }
151151
rule { $contract:function_contract } => { $contract }
152152
rule { $contract:object_contract } => { $contract }
@@ -157,14 +157,21 @@ macro non_or_contract {
157157
}
158158

159159
macro or_contract {
160-
rule { $left:non_or_contract or $right:any_contract } => {
160+
rule { $left:non_bin_contract or $right:any_contract } => {
161161
_c.or($left, $right)
162162
}
163163
}
164164

165+
macro and_contract {
166+
rule { $left:non_bin_contract and $right:any_contract } => {
167+
_c.and($left, $right)
168+
}
169+
}
170+
165171
macro any_contract {
166172
rule { $contract:or_contract } => { $contract }
167-
rule { $contract:non_or_contract } => { $contract }
173+
rule { $contract:and_contract } => { $contract }
174+
rule { $contract:non_bin_contract } => { $contract }
168175
}
169176

170177

src/macros.js

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ macro predicate_contract {
146146
}
147147

148148

149-
macro non_or_contract {
149+
macro non_bin_contract {
150150
rule { $contract:predicate_contract } => { $contract }
151151
rule { $contract:function_contract } => { $contract }
152152
rule { $contract:object_contract } => { $contract }
@@ -157,14 +157,21 @@ macro non_or_contract {
157157
}
158158

159159
macro or_contract {
160-
rule { $left:non_or_contract or $right:any_contract } => {
160+
rule { $left:non_bin_contract or $right:any_contract } => {
161161
_c.or($left, $right)
162162
}
163163
}
164164

165+
macro and_contract {
166+
rule { $left:non_bin_contract and $right:any_contract } => {
167+
_c.and($left, $right)
168+
}
169+
}
170+
165171
macro any_contract {
166172
rule { $contract:or_contract } => { $contract }
167-
rule { $contract:non_or_contract } => { $contract }
173+
rule { $contract:and_contract } => { $contract }
174+
rule { $contract:non_bin_contract } => { $contract }
168175
}
169176

170177

test/test_contracts.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -873,6 +873,35 @@ in: the a property of
873873
() -> Null or !{a: Num, b: MyObj}
874874
function bar guarded at line: 856
875875
blaming: (calling context for bar)
876+
`
877+
})
878+
879+
it("should work with the and contract", function() {
880+
@ (Num and (x) => x > 5) -> Num
881+
function foo(x) { return x; }
882+
883+
foo(10);
884+
885+
blame of {
886+
foo("string");
887+
} should be `foo: contract violation
888+
expected: Num and x > 5
889+
given: 'string'
890+
in: the 1st argument of
891+
(Num and x > 5) -> Num
892+
function foo guarded at line: 881
893+
blaming: (calling context for foo)
894+
`
895+
896+
blame of {
897+
foo(1);
898+
} should be `foo: contract violation
899+
expected: Num and x > 5
900+
given: 1
901+
in: the 1st argument of
902+
(Num and x > 5) -> Num
903+
function foo guarded at line: 881
904+
blaming: (calling context for foo)
876905
`
877906
})
878907
});

0 commit comments

Comments
 (0)