Skip to content

Commit 66d937f

Browse files
committed
cleaning up docs, adding auto converting contracts
1 parent 70a9165 commit 66d937f

File tree

9 files changed

+458
-182
lines changed

9 files changed

+458
-182
lines changed

doc/main/contracts.html

Lines changed: 135 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -118,28 +118,18 @@ <h1 class="title">Contracts.js Documentation</h1>
118118
<li><a href="#using"><span class="toc-section-number">3</span> Using</a></li>
119119
<li><a href="#contracts"><span class="toc-section-number">4</span> Contracts</a><ul>
120120
<li><a href="#basic-contracts"><span class="toc-section-number">4.1</span> Basic Contracts</a><ul>
121-
<li><a href="#num"><span class="toc-section-number">4.1.1</span> <code>Num</code></a></li>
122-
<li><a href="#str"><span class="toc-section-number">4.1.2</span> <code>Str</code></a></li>
123-
<li><a href="#bool"><span class="toc-section-number">4.1.3</span> <code>Bool</code></a></li>
124-
<li><a href="#odd"><span class="toc-section-number">4.1.4</span> <code>Odd</code></a></li>
125-
<li><a href="#even"><span class="toc-section-number">4.1.5</span> <code>Even</code></a></li>
126-
<li><a href="#pos"><span class="toc-section-number">4.1.6</span> <code>Pos</code></a></li>
127-
<li><a href="#nat"><span class="toc-section-number">4.1.7</span> <code>Nat</code></a></li>
128-
<li><a href="#neg"><span class="toc-section-number">4.1.8</span> <code>Neg</code></a></li>
129-
<li><a href="#any"><span class="toc-section-number">4.1.9</span> <code>Any</code></a></li>
130-
<li><a href="#none"><span class="toc-section-number">4.1.10</span> <code>None</code></a></li>
131-
<li><a href="#null"><span class="toc-section-number">4.1.11</span> <code>Null</code></a></li>
132-
<li><a href="#undefined"><span class="toc-section-number">4.1.12</span> <code>Undefined</code></a></li>
133-
<li><a href="#void"><span class="toc-section-number">4.1.13</span> <code>Void</code></a></li>
121+
<li><a href="#custom-predicate-contracts"><span class="toc-section-number">4.1.1</span> Custom Predicate Contracts</a></li>
134122
</ul></li>
135123
<li><a href="#function-contracts"><span class="toc-section-number">4.2</span> Function Contracts</a><ul>
136124
<li><a href="#optional-arguments"><span class="toc-section-number">4.2.1</span> Optional Arguments</a></li>
137125
<li><a href="#higher-order-arguments"><span class="toc-section-number">4.2.2</span> Higher-Order Arguments</a></li>
138-
<li><a href="#dependent-contracts"><span class="toc-section-number">4.2.3</span> Dependent Contracts</a></li>
126+
<li><a href="#contracts-on-this"><span class="toc-section-number">4.2.3</span> Contracts on <code>this</code></a></li>
127+
<li><a href="#dependent-contracts"><span class="toc-section-number">4.2.4</span> Dependent Contracts</a></li>
139128
</ul></li>
140129
<li><a href="#object-contracts"><span class="toc-section-number">4.3</span> Object Contracts</a><ul>
141130
<li><a href="#optional-properties"><span class="toc-section-number">4.3.1</span> Optional Properties</a></li>
142-
<li><a href="#proxied-objects"><span class="toc-section-number">4.3.2</span> Proxied Objects</a></li>
131+
<li><a href="#method-contracts"><span class="toc-section-number">4.3.2</span> Method Contracts</a></li>
132+
<li><a href="#proxied-objects"><span class="toc-section-number">4.3.3</span> Proxied Objects</a></li>
143133
</ul></li>
144134
<li><a href="#array-contracts"><span class="toc-section-number">4.4</span> Array Contracts</a><ul>
145135
<li><a href="#repeated-fields"><span class="toc-section-number">4.4.1</span> Repeated Fields</a></li>
@@ -193,39 +183,86 @@ <h1 id="contracts"><span class="header-section-number">4</span> Contracts</h1>
193183
blaming: (calling context for id)
194184
*/</code></pre>
195185
<h2 id="basic-contracts"><span class="header-section-number">4.1</span> Basic Contracts</h2>
196-
<h3 id="num"><span class="header-section-number">4.1.1</span> <code>Num</code></h3>
197-
<p>A value that is <code>typeof</code> number.</p>
198-
<h3 id="str"><span class="header-section-number">4.1.2</span> <code>Str</code></h3>
199-
<p>A value that is <code>typeof</code> string.</p>
200-
<h3 id="bool"><span class="header-section-number">4.1.3</span> <code>Bool</code></h3>
201-
<p>A value that is <code>typeof</code> boolean.</p>
202-
<h3 id="odd"><span class="header-section-number">4.1.4</span> <code>Odd</code></h3>
203-
<p>A number that is odd (<code>val % 2 === 1</code>).</p>
204-
<h3 id="even"><span class="header-section-number">4.1.5</span> <code>Even</code></h3>
205-
<p>A number that is even (<code>val % 2 !== 1</code>).</p>
206-
<h3 id="pos"><span class="header-section-number">4.1.6</span> <code>Pos</code></h3>
207-
<p>A positive number (<code>val &gt;= 0</code>).</p>
208-
<h3 id="nat"><span class="header-section-number">4.1.7</span> <code>Nat</code></h3>
209-
<p>A natural number (<code>val &gt; 0</code>).</p>
210-
<h3 id="neg"><span class="header-section-number">4.1.8</span> <code>Neg</code></h3>
211-
<p>A negative number (<code>val &lt; 0</code>).</p>
212-
<h3 id="any"><span class="header-section-number">4.1.9</span> <code>Any</code></h3>
213-
<p>Any value.</p>
214-
<h3 id="none"><span class="header-section-number">4.1.10</span> <code>None</code></h3>
215-
<p>No value (not terribly useful).</p>
216-
<h3 id="null"><span class="header-section-number">4.1.11</span> <code>Null</code></h3>
217-
<p>The <code>null</code> value.</p>
218-
<h3 id="undefined"><span class="header-section-number">4.1.12</span> <code>Undefined</code></h3>
219-
<p>The <code>undefined</code> value.</p>
220-
<h3 id="void"><span class="header-section-number">4.1.13</span> <code>Void</code></h3>
221-
<p>Either <code>null</code> or <code>undefined</code>.</p>
186+
<p>Contracts.js comes with a number of basic contracts that check for first-order properties (things like <code>typeof</code> checks).</p>
187+
<table>
188+
<thead>
189+
<tr class="header">
190+
<th style="text-align: left;">Contract</th>
191+
<th style="text-align: left;">Description</th>
192+
</tr>
193+
</thead>
194+
<tbody>
195+
<tr class="odd">
196+
<td style="text-align: left;"><code>Num</code></td>
197+
<td style="text-align: left;">A value that is <code>typeof</code> number</td>
198+
</tr>
199+
<tr class="even">
200+
<td style="text-align: left;"><code>Str</code></td>
201+
<td style="text-align: left;">A value that is <code>typeof</code> string</td>
202+
</tr>
203+
<tr class="odd">
204+
<td style="text-align: left;"><code>Bool</code></td>
205+
<td style="text-align: left;">A value that is <code>typeof</code> boolean</td>
206+
</tr>
207+
<tr class="even">
208+
<td style="text-align: left;"><code>Odd</code></td>
209+
<td style="text-align: left;">A value that is odd (<code>val % 2 === 1</code>)</td>
210+
</tr>
211+
<tr class="odd">
212+
<td style="text-align: left;"><code>Even</code></td>
213+
<td style="text-align: left;">A value that is even (<code>val % 1 === 0</code>)</td>
214+
</tr>
215+
<tr class="even">
216+
<td style="text-align: left;"><code>Pos</code></td>
217+
<td style="text-align: left;">A positive number(<code>val &gt;= 0</code>)</td>
218+
</tr>
219+
<tr class="odd">
220+
<td style="text-align: left;"><code>Nat</code></td>
221+
<td style="text-align: left;">A natural number (<code>val &gt; 0</code>)</td>
222+
</tr>
223+
<tr class="even">
224+
<td style="text-align: left;"><code>Neg</code></td>
225+
<td style="text-align: left;">A negative number (<code>val &lt; 0</code>)</td>
226+
</tr>
227+
<tr class="odd">
228+
<td style="text-align: left;"><code>Any</code></td>
229+
<td style="text-align: left;">Any value</td>
230+
</tr>
231+
<tr class="even">
232+
<td style="text-align: left;"><code>None</code></td>
233+
<td style="text-align: left;">No value (not terribly useful)</td>
234+
</tr>
235+
<tr class="odd">
236+
<td style="text-align: left;"><code>Null</code></td>
237+
<td style="text-align: left;">The <code>null</code> value</td>
238+
</tr>
239+
<tr class="even">
240+
<td style="text-align: left;"><code>Undefined</code></td>
241+
<td style="text-align: left;">The <code>undefined</code> value</td>
242+
</tr>
243+
<tr class="odd">
244+
<td style="text-align: left;"><code>Void</code></td>
245+
<td style="text-align: left;">Either <code>null</code> or <code>undefined</code></td>
246+
</tr>
247+
</tbody>
248+
</table>
249+
<h3 id="custom-predicate-contracts"><span class="header-section-number">4.1.1</span> Custom Predicate Contracts</h3>
250+
<p>All of the basic contracts are built with predicates (functions that take a single value and return a boolean) and you can make your own:</p>
251+
<pre class="js"><code>function MyNum(val) {
252+
return typeof val === &quot;number&quot;;
253+
}
254+
@ (MyNum) -&gt; MyNum
255+
function id(x) { return x; }</code></pre>
256+
<p>There is also ES6 arrow function shorthand syntax for defining predicate contracts inside of a function or object contract:</p>
257+
<pre class="js"><code>@ ((val) =&gt; typeof val === &quot;function&quot;) -&gt; Num
258+
function id(x) { return x; }</code></pre>
222259
<h2 id="function-contracts"><span class="header-section-number">4.2</span> Function Contracts</h2>
223260
<p>Function contracts take a comma delimited list of argument contracts and a single return value contract:</p>
224261
<pre class="js"><code>@ (Str, Num, Bool) -&gt; Bool
225262
function foo(s, n, b) { return b; }</code></pre>
226263
<h3 id="optional-arguments"><span class="header-section-number">4.2.1</span> Optional Arguments</h3>
227-
<p>You can make an argument optional with the <code>opt</code> prefix:</p>
228-
<pre class="js"><code>@ (Str, opt Bool) -&gt; Str
264+
<p>You can make an argument optional with the <code>?</code> prefix:</p>
265+
<pre class="js"><code>@ (Str, ?Bool) -&gt; Str
229266
function foo(s, b) { return s; }
230267

231268
foo(&quot;foo&quot;); // fine
@@ -235,7 +272,31 @@ <h3 id="higher-order-arguments"><span class="header-section-number">4.2.2</span>
235272
<p>You can put contracts on functions to functions. And blaming the correct party at fault even works! <a href="what-about-blaming-modules">Mostly</a>.</p>
236273
<pre class="js"><code>@ (Num, (Num, Num) -&gt; Num) -&gt; Num
237274
function (x, f) { return f(x, x); }</code></pre>
238-
<h3 id="dependent-contracts"><span class="header-section-number">4.2.3</span> Dependent Contracts</h3>
275+
<h3 id="contracts-on-this"><span class="header-section-number">4.2.3</span> Contracts on <code>this</code></h3>
276+
<p>You can put a contract on the <code>this</code> object of a function:</p>
277+
<pre class="js"><code>@ () -&gt; Str
278+
| this: {name: Str}
279+
function f() { return this.name; }
280+
281+
var o = {
282+
nam: &quot;Bob&quot;, // typo
283+
f: f
284+
};
285+
o.f();</code></pre>
286+
<p>This will let you know you did something wrong:</p>
287+
<pre style="color: red">
288+
f: contract violation
289+
expected: Str
290+
given: undefined
291+
in: the name property of
292+
the this value of
293+
() -> Str
294+
| this: {name: Str}
295+
function f guarded at line: 3
296+
blaming: (calling context for f)
297+
</pre>
298+
299+
<h3 id="dependent-contracts"><span class="header-section-number">4.2.4</span> Dependent Contracts</h3>
239300
<p>You can also write a function contract who's result depends on the value of its arguments.</p>
240301
<pre class="js"><code>@ (x: Pos) -&gt; res: Num | res &lt;= x
241302
function square_root(x) { return Math.sqrt(x); }</code></pre>
@@ -273,10 +334,37 @@ <h2 id="object-contracts"><span class="header-section-number">4.3</span> Object
273334
<p>Note that objects are checked against their contract only once when they cross the contract barrier (in the above example this is when the <code>makePerson</code> function returns). Basic contracts (like <code>Str</code> and <code>Num</code>) are checked immediately while method contracts are deferred until the method is invoked.</p>
274335
<p>If you want to maintain the contract invariants throughout the object's lifetime, use <a href="#proxied-objects">proxied object contracts</a>.</p>
275336
<h3 id="optional-properties"><span class="header-section-number">4.3.1</span> Optional Properties</h3>
276-
<p>The <code>opt</code> prefix makes a property optional:</p>
277-
<pre class="js"><code>@ ({name: Str, age: opt Num}) -&gt; Str
337+
<p>The <code>?</code> prefix makes a property optional:</p>
338+
<pre class="js"><code>@ ({name: Str, age: ?Num}) -&gt; Str
278339
function get Name(o) { return o.name; }</code></pre>
279-
<h3 id="proxied-objects"><span class="header-section-number">4.3.2</span> Proxied Objects</h3>
340+
<h3 id="method-contracts"><span class="header-section-number">4.3.2</span> Method Contracts</h3>
341+
<p>Function contracts on an object contract will implicitly check that the <code>this</code> object bound to the function obeys the object contract:</p>
342+
<pre class="js"><code>@ ({name: Str, hi: () -&gt; Str}) -&gt; Str
343+
function foo(o) {
344+
var hi = o.hi;
345+
return hi(); // `this` is bound wrong
346+
}
347+
348+
foo({
349+
name: &quot;Bob&quot;,
350+
hi: function() {
351+
return this.name;
352+
}
353+
})</code></pre>
354+
<p>This code will give a nice error letting us know that the <code>this</code> object was wrong:</p>
355+
<pre style="color: red">
356+
foo: contract violation
357+
expected: an object with at least 2 keys
358+
given: undefined
359+
in: the this value of
360+
the hi property of
361+
the 1st argument of
362+
({name: Str, hi: () -> Str}) -> Str
363+
function foo guarded at line: 2
364+
blaming: function foo
365+
</pre>
366+
367+
<h3 id="proxied-objects"><span class="header-section-number">4.3.3</span> Proxied Objects</h3>
280368
<p>To maintain the object contract invariant for the entire lifetime of an object, use the <code>!</code> notation:</p>
281369
<pre class="js"><code>@ (Str, Num) -&gt; !{name: Str, age: Num}
282370
function makePerson(name, age) {

0 commit comments

Comments
 (0)