This repository has been archived on 2021-10-31. You can view files and clone it, but cannot push or open issues or pull requests.
SA3/hw5/Claudio_Maggioni/public/resources/jsverify.standalone.js
2019-10-21 18:56:21 +02:00

5588 lines
141 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.jsc = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
"use strict";
var arbitrary = require("./arbitrary.js");
var bless = require("./bless.js");
var dict = require("./dict.js");
var generator = require("./generator.js");
var json = require("./json.js");
var primitive = require("./primitive.js");
var record = require("./record.js");
var recordWithEnv = require("./recordWithEnv.js");
var shrink = require("./shrink.js");
var small = require("./small.js");
var string = require("./string.js");
var api = {
arbitrary: {
small: small.arbitrary,
bless: bless,
record: recordWithEnv,
nonshrink: arbitrary.nonshrink,
pair: arbitrary.pair,
either: arbitrary.either,
unit: arbitrary.unit,
dict: arbitrary.dict,
json: arbitrary.json,
nearray: arbitrary.nearray,
array: arbitrary.array,
tuple: arbitrary.tuple,
sum: arbitrary.sum,
oneof: arbitrary.oneof,
recursive: arbitrary.recursive,
letrec: arbitrary.letrec,
},
generator: {
dict: dict.generator,
json: json.json.generator,
small: small.generator,
record: record.generator,
},
shrink: {
record: record.shrink,
},
};
// Re-export stuff from internal modules
/* eslint-disable guard-for-in */
var k;
for (k in primitive) {
api.arbitrary[k] = primitive[k];
}
for (k in string) {
api.arbitrary[k] = string[k];
}
for (k in shrink) {
api.shrink[k] = shrink[k];
}
for (k in generator) {
api.generator[k] = generator[k];
}
module.exports = api;
},{"./arbitrary.js":2,"./bless.js":6,"./dict.js":7,"./generator.js":13,"./json.js":14,"./primitive.js":17,"./record.js":19,"./recordWithEnv.js":20,"./shrink.js":22,"./small.js":23,"./string.js":24}],2:[function(require,module,exports){
/* @flow weak */
"use strict";
var arbitraryAssert = require("./arbitraryAssert.js");
var arbitraryBless = require("./arbitraryBless.js");
var array = require("./array.js");
var assert = require("assert");
var dict = require("./dict.js");
var generator = require("./generator.js");
var json = require("./json.js");
var pair = require("./pair.js");
var show = require("./show.js");
var shrink = require("./shrink.js");
var utils = require("./utils.js");
/**
### Arbitrary combinators
*/
/**
- `nonshrink(arb: arbitrary a): arbitrary a`
Non shrinkable version of arbitrary `arb`.
*/
function nonshrink(arb) {
arb = utils.force(arb);
return arbitraryBless({
generator: arb.generator,
shrink: shrink.noop,
show: arb.show,
});
}
/**
- `unit: arbitrary ()`
*/
var unit = arbitraryBless({
generator: generator.unit,
shrink: shrink.noop,
show: show.def,
});
/**
- `either(arbA: arbitrary a, arbB : arbitrary b): arbitrary (either a b)`
*/
function either(a, b) {
a = utils.force(a || json.json);
b = utils.force(b || json.json);
arbitraryAssert(a);
arbitraryAssert(b);
return arbitraryBless({
generator: generator.either(a.generator, b.generator),
shrink: shrink.either(a.shrink, b.shrink),
show: show.either(a.show, b.show),
});
}
/**
- `pair(arbA: arbitrary a, arbB : arbitrary b): arbitrary (pair a b)`
If not specified `a` and `b` are equal to `value()`.
*/
function pairArb(a, b) {
return pair.pair(a || json.json, b || json.json);
}
/**
- `tuple(arbs: (arbitrary a, arbitrary b...)): arbitrary (a, b...)`
*/
function tuple(arbs) {
arbs = arbs.map(utils.force);
return arbitraryBless({
generator: generator.tuple(utils.pluck(arbs, "generator")),
shrink: shrink.tuple(utils.pluck(arbs, "shrink")),
show: show.tuple(utils.pluck(arbs, "show")),
});
}
/**
- `sum(arbs: (arbitrary a, arbitrary b...)): arbitrary (a | b ...)`
*/
function sum(arbs) {
arbs = arbs.map(utils.force);
return arbitraryBless({
generator: generator.sum(utils.pluck(arbs, "generator")),
shrink: shrink.sum(utils.pluck(arbs, "shrink")),
show: show.sum(utils.pluck(arbs, "show")),
});
}
/**
- `dict(arb: arbitrary a): arbitrary (dict a)`
Generates a JavaScript object with properties of type `A`.
*/
function dictArb(arb) {
return dict.arbitrary(arb || json.json);
}
/**
- `array(arb: arbitrary a): arbitrary (array a)`
*/
function arrayArb(arb) {
return array.array(arb || json.json);
}
/**
- `nearray(arb: arbitrary a): arbitrary (array a)`
*/
function nearrayArb(arb) {
return array.nearray(arb || json.json);
}
/**
- `json: arbitrary json`
JavaScript Objects: boolean, number, string, null, array of `json` values or object with `json` values.
*/
var jsonArb = json.json;
/**
- `oneof(gs : array (arbitrary a)...) : arbitrary a`
Randomly uses one of the given arbitraries.
*/
function oneof() {
assert(arguments.length !== 0, "oneof: at least one parameter expected");
// TODO: write this in more functional way
var generators = [];
var append = function (a) {
generators.push(utils.force(a).generator);
};
for (var i = 0; i < arguments.length; i++) {
var arg = arguments[i];
if (utils.isArray(arg)) {
arg.forEach(append);
} else {
append(arg);
}
}
return arbitraryBless({
generator: generator.oneof(generators),
// TODO: make shrink
shrink: shrink.noop,
show: show.def,
});
}
// Return a lazy arbitrary that delegates to another arbitrary at its
// 'strict' property. An arbitrary must be assigned to that property before
// this arbitrary can generate anything.
function lazyArbitrary() {
var arb = {};
// This function must be pure because it will not be called with
// meaningful context.
arb.generator = generator.bless(function (size) {
return arb.strict.generator(size);
});
arb.shrink = shrink.noop;
arb.show = show.def;
arb = arbitraryBless(arb);
return arb;
}
/**
- ```js
letrec(
(tie: key -> (arbitrary a | arbitrary b | ...))
-> { key: arbitrary a, key: arbitrary b, ... }):
{ key: arbitrary a, key: arbitrary b, ... }
```
Mutually recursive definitions. Every reference to a sibling arbitrary
should go through the `tie` function.
```js
{ arb1, arb2 } = jsc.letrec(function (tie) {
return {
arb1: jsc.tuple(jsc.int, jsc.oneof(jsc.const(null), tie("arb2"))),
arb2: jsc.tuple(jsc.bool, jsc.oneof(jsc.const(null), tie("arb1"))),
}
});
```
*/
function letrec(definition) {
// We must use a lazy dictionary because we do not know the key set
// before calling the definition.
var lazyArbs = {};
function tie(name) {
if (!lazyArbs.hasOwnProperty(name)) {
lazyArbs[name] = lazyArbitrary();
}
return lazyArbs[name];
}
var strictArbs = definition(tie);
Object.keys(lazyArbs).forEach(function (key) {
var strictArb = strictArbs[key];
if (!strictArb) {
throw new Error("undefined lazy arbitrary: " + key);
}
lazyArbs[key].strict = strictArb;
});
return strictArbs;
}
function recursive(arbZ, arbS) {
var genZ = arbZ.generator;
var genS = function (recGen) {
var recArb = arbitraryBless({
generator: recGen,
shrink: shrink.noop,
show: show.def,
});
return arbS(recArb).generator;
};
var gen = generator.recursive(genZ, genS);
return arbitraryBless({
generator: gen,
shrink: shrink.noop,
show: show.def,
});
}
module.exports = {
nonshrink: nonshrink,
pair: pairArb,
either: either,
unit: unit,
dict: dictArb,
json: jsonArb,
nearray: nearrayArb,
array: arrayArb,
tuple: tuple,
sum: sum,
oneof: oneof,
recursive: recursive,
letrec: letrec,
};
},{"./arbitraryAssert.js":3,"./arbitraryBless.js":4,"./array.js":5,"./dict.js":7,"./generator.js":13,"./json.js":14,"./pair.js":16,"./show.js":21,"./shrink.js":22,"./utils.js":28,"assert":29}],3:[function(require,module,exports){
"use strict";
var assert = require("assert");
function arbitraryAssert(arb) {
assert(arb !== undefined && arb !== null && typeof arb === "object", "arb should be an object");
assert(typeof arb.generator === "function" && typeof arb.generator.map === "function",
"arb.generator should be a function");
assert(typeof arb.shrink === "function" && typeof arb.shrink.smap === "function",
"arb.shrink should be a function");
assert(typeof arb.show === "function", "arb.show should be a function");
assert(typeof arb.smap === "function", "arb.smap should be a function");
}
module.exports = arbitraryAssert;
},{"assert":29}],4:[function(require,module,exports){
"use strict";
var show = require("./show.js");
/**
### Arbitrary data
*/
// Blessing: i.e adding prototype
/* eslint-disable no-use-before-define */
function arbitraryProtoSMap(f, g, newShow) {
/* jshint validthis:true */
var arb = this; // eslint-disable-line no-invalid-this
return arbitraryBless({
generator: arb.generator.map(f),
shrink: arb.shrink.smap(f, g),
show: newShow || show.def,
});
}
/* eslint-enable no-use-before-define */
/**
- `.smap(f: a -> b, g: b -> a, newShow: (b -> string)?): arbitrary b`
Transform `arbitrary a` into `arbitrary b`. For example:
`g` should be a [right inverse](http://en.wikipedia.org/wiki/Surjective_function#Surjections_as_right_invertible_functions) of `f`, but doesn't need to be complete inverse.
i.e. i.e. `f` doesn't need to be invertible, only surjective.
```js
var positiveIntegersArb = nat.smap(
function (x) { return x + 1; },
function (x) { return x - 1; });
```
```js
var setNatArb = jsc.array(jsc.nat).smap(_.uniq, _.identity);
```
Right inverse means that *f(g(y)) = y* for all *y* in *Y*. Here *Y* is a type of **arrays of unique natural numbers**. For them
```js
_.uniq(_.identity(y)) = _.uniq(y) = y
```
Opposite: *g(f(x))* for all *x* in *X*, doesn't need to hold. *X* is **arrays of natural numbers**:
```js
_.identity(_uniq([0, 0])) = [0]] != [0, 0]
```
We need an inverse for shrinking, and there right inverse is enough. We can always *pull back* `smap`ped value, shrink the preimage, and *map* or *push forward* shrunken preimages again.
*/
function arbitraryBless(arb) {
arb.smap = arbitraryProtoSMap;
return arb;
}
module.exports = arbitraryBless;
},{"./show.js":21}],5:[function(require,module,exports){
"use strict";
var arbitraryAssert = require("./arbitraryAssert.js");
var arbitraryBless = require("./arbitraryBless.js");
var generator = require("./generator.js");
var show = require("./show.js");
var shrink = require("./shrink.js");
var utils = require("./utils.js");
function makeArray(flavour) {
return function arrayImpl(arb) {
arb = utils.force(arb);
arbitraryAssert(arb);
return arbitraryBless({
generator: generator[flavour](arb.generator),
shrink: shrink[flavour](arb.shrink),
show: show.array(arb.show),
});
};
}
var array = makeArray("array");
var nearray = makeArray("nearray");
module.exports = {
array: array,
nearray: nearray,
};
},{"./arbitraryAssert.js":3,"./arbitraryBless.js":4,"./generator.js":13,"./show.js":21,"./shrink.js":22,"./utils.js":28}],6:[function(require,module,exports){
"use strict";
var assert = require("assert");
var arbitraryBless = require("./arbitraryBless.js");
var generator = require("./generator.js");
var show = require("./show.js");
var shrink = require("./shrink.js");
/**
- `bless(arb: {...}): arbitrary a`
Bless almost arbitrary structure to be proper arbitrary. *Note*: this function mutates argument.
#### Example:
```js
var arbTokens = jsc.bless({
generator: function () {
switch (jsc.random(0, 2)) {
case 0: return "foo";
case 1: return "bar";
case 2: return "quux";
}
}
});
```
*/
function bless(arb) {
assert(arb !== null && typeof arb === "object", "bless: arb should be an object");
assert(typeof arb.generator === "function", "bless: arb.generator should be a function");
// default shrink
if (typeof arb.shrink !== "function") {
arb.shrink = shrink.noop;
}
// default show
if (typeof arb.show !== "function") {
arb.show = show.def;
}
generator.bless(arb.generator);
shrink.bless(arb.shrink);
arbitraryBless(arb);
return arb;
}
module.exports = bless;
},{"./arbitraryBless.js":4,"./generator.js":13,"./show.js":21,"./shrink.js":22,"assert":29}],7:[function(require,module,exports){
/* @flow weak */
"use strict";
var arbitraryAssert = require("./arbitraryAssert.js");
var array = require("./array.js");
var generator = require("./generator.js");
var pair = require("./pair.js");
var string = require("./string.js");
var utils = require("./utils.js");
function makeMapShow(elShow) {
return function (m) {
return "{" + Object.keys(m).map(function (k) {
return k + ": " + elShow(m[k]);
}).join(", ") + "}";
};
}
/**
- `dict.generator(gen: generator a): generator (dict a)`
*/
function generateDict(gen) {
var pairGen = generator.pair(string.string.generator, gen);
var arrayGen = generator.array(pairGen);
var result = arrayGen.map(utils.pairArrayToDict);
return utils.curried2(result, arguments);
}
function dict(arb) {
arb = utils.force(arb);
arbitraryAssert(arb);
var pairArbitrary = pair.pair(string.string, arb);
var arrayArbitrary = array.array(pairArbitrary);
return arrayArbitrary.smap(utils.pairArrayToDict, utils.dictToPairArray, makeMapShow(arb.show));
}
module.exports = {
arbitrary: dict,
generator: generateDict,
};
},{"./arbitraryAssert.js":3,"./array.js":5,"./generator.js":13,"./pair.js":16,"./string.js":24,"./utils.js":28}],8:[function(require,module,exports){
"use strict";
var assert = require("assert");
/**
### either
*/
function Left(value) {
this.value = value;
}
function Right(value) {
this.value = value;
}
/**
- `either.left(value: a): either a b`
*/
function left(value) {
return new Left(value);
}
/**
- `either.right(value: b): either a b`
*/
function right(value) {
return new Right(value);
}
/**
- `either.either(l: a -> x, r: b -> x): x`
*/
Left.prototype.either = function lefteither(l) {
return l(this.value);
};
Right.prototype.either = function righteither(l, r) {
return r(this.value);
};
/**
- `either.isEqual(other: either a b): bool`
TODO: add `eq` optional parameter
*/
Left.prototype.isEqual = function leftIsEqual(other) {
assert(other instanceof Left || other instanceof Right, "isEqual: `other` parameter should be either");
return other instanceof Left && this.value === other.value;
};
Right.prototype.isEqual = function rightIsEqual(other) {
assert(other instanceof Left || other instanceof Right, "isEqual: `other` parameter should be either");
return other instanceof Right && this.value === other.value;
};
/**
- `either.bimap(f: a -> c, g: b -> d): either c d`
```js
either.bimap(compose(f, g), compose(h, i)) ≡ either.bimap(g, i).bimap(f, h);
```
*/
Left.prototype.bimap = function leftBimap(f) {
return new Left(f(this.value));
};
Right.prototype.bimap = function rightBimap(f, g) {
return new Right(g(this.value));
};
/**
- `either.first(f: a -> c): either c b`
```js
either.first(f) ≡ either.bimap(f, utils.identity)
```
*/
Left.prototype.first = function leftFirst(f) {
return new Left(f(this.value));
};
Right.prototype.first = function rightFirst() {
return this;
};
/**
- `either.second(g: b -> d): either a d`
```js
either.second(g) === either.bimap(utils.identity, g)
```
*/
Left.prototype.second = function leftSecond() {
return this;
};
Right.prototype.second = function rightSecond(g) {
return new Right(g(this.value));
};
module.exports = {
left: left,
right: right,
};
},{"assert":29}],9:[function(require,module,exports){
/* @flow weak */
"use strict";
var arbitrary = require("./arbitrary.js");
var fn = require("./fn.js");
var primitive = require("./primitive.js");
var small = require("./small.js");
var string = require("./string.js");
var utils = require("./utils.js");
var environment = utils.merge(primitive, string, {
pair: arbitrary.pair,
unit: arbitrary.unit,
either: arbitrary.either,
dict: arbitrary.dict,
array: arbitrary.array,
nearray: arbitrary.nearray,
json: arbitrary.json,
fn: fn.fn,
fun: fn.fn,
nonshrink: arbitrary.nonshrink,
small: small.arbitrary,
});
module.exports = environment;
},{"./arbitrary.js":2,"./fn.js":11,"./primitive.js":17,"./small.js":23,"./string.js":24,"./utils.js":28}],10:[function(require,module,exports){
/* @flow weak */
"use strict";
var utils = require("./utils.js");
/*
#### FMap (eq : a -> a -> bool) : FMap a
Finite map, with any object a key.
Short summary of member functions:
- FMap.insert (key : a) (value : any) : void
- FMap.get (key : a) : any
- FMap.contains (key : a) : obool
*/
function FMap(eq) {
this.eq = eq || utils.isEqual;
this.data = [];
}
FMap.prototype.contains = function FMapContains(key) {
for (var i = 0; i < this.data.length; i++) {
if (this.eq(this.data[i][0], key)) {
return true;
}
}
return false;
};
FMap.prototype.insert = function FMapInsert(key, value) {
for (var i = 0; i < this.data.length; i++) {
if (this.eq(this.data[i][0], key)) {
this.data[i] = [key, value];
return;
}
}
this.data.push([key, value]);
};
FMap.prototype.get = function FMapGet(key) { // eslint-disable-line consistent-return
for (var i = 0; i < this.data.length; i++) {
if (this.eq(this.data[i][0], key)) {
return this.data[i][1];
}
}
};
module.exports = FMap;
},{"./utils.js":28}],11:[function(require,module,exports){
/* @flow weak */
"use strict";
var arbitraryBless = require("./arbitraryBless.js");
var generator = require("./generator.js");
var FMap = require("./finitemap.js");
var json = require("./json.js");
var shrink = require("./shrink.js");
var utils = require("./utils.js");
/**
### Arbitrary functions
- `fn(arb: arbitrary a): arbitrary (b -> a)`
- `fun(arb: arbitrary a): arbitrary (b -> a)`
*/
function fn(arb) {
arb = utils.force(arb || json.json);
return arbitraryBless({
generator: generator.bless(function (size) {
var m = new FMap();
var f = function (arg) {
if (!m.contains(arg)) {
var value = arb.generator(size);
m.insert(arg, value);
}
return m.get(arg);
};
f.internalMap = m;
return f;
}),
shrink: shrink.noop,
show: function (f) {
return "[" + f.internalMap.data.map(function (item) {
return "" + item[0] + ": " + arb.show(item[1]);
}).join(", ") + "]";
},
});
}
module.exports = {
fn: fn,
fun: fn,
};
},{"./arbitraryBless.js":4,"./finitemap.js":10,"./generator.js":13,"./json.js":14,"./shrink.js":22,"./utils.js":28}],12:[function(require,module,exports){
/* @flow weak */
"use strict";
var trampa = require("trampa");
/**
#### isPromise p : bool
Optimistic duck-type check for promises.
Returns `true` if p is an object with `.then` function property.
*/
function isPromise(p) {
/* eslint-disable no-new-object */
return new Object(p) === p && typeof p.then === "function";
/* eslint-enable non-new-object */
}
/**
#### map (Functor f) => (p : f a) (g : a -> b) : f b
This is functor map, known as `map` or `fmap`.
Essentially `f(p)`. If `p` is promise, returns new promise.
Using `map` makes code look very much [CPS-style](http://en.wikipedia.org/wiki/Continuation-passing_style).
*/
function map(p, g) {
if (isPromise(p)) {
return p.then(function (x) {
return map(x, g);
});
} else if (trampa.isTrampoline(p)) {
return p.jump(function (x) {
return map(x, g);
});
} else {
return g(p);
}
}
/**
#### bind (Functor f) => (k : a -> f b) (xs : a) (h : b -> f c) -> f c
This is almost monadic bind.
*/
function bind(f, xs, h) {
var r;
var exc;
try {
r = f.apply(undefined, xs);
} catch (e) {
r = false;
exc = e;
}
if (isPromise(r)) {
return r.then(
h,
function (e) {
// exc is always unset here
return h(false, e);
}
);
} else {
return h(r, exc);
}
}
// recursively unwrap trampoline and promises
function run(x) {
if (isPromise(x)) {
return x.then(run);
} else if (trampa.isTrampoline(x)) {
return run(x.run());
} else {
return x;
}
}
function pure(x) {
if (isPromise(x)) {
return x;
} else {
return trampa.wrap(x);
}
}
module.exports = {
isPromise: isPromise,
map: map,
pure: pure,
bind: bind,
run: run,
};
},{"trampa":32}],13:[function(require,module,exports){
/* @flow weak */
"use strict";
var assert = require("assert");
var either = require("./either.js");
var random = require("./random.js");
var sum = require("./sum.js");
var utils = require("./utils.js");
/**
### Generator functions
A generator function, `generator a`, is a function `(size: nat) -> a`, which generates a value of given size.
Generator combinators are auto-curried:
```js
var xs = jsc.generator.array(jsc.nat.generator, 1); // ≡
var ys = jsc.generator.array(jsc.nat.generator)(1);
```
In purely functional approach `generator a` would be explicitly stateful computation:
`(size: nat, rng: randomstate) -> (a, randomstate)`.
*JSVerify* uses an implicit random number generator state,
but the value generation is deterministic (tests are reproducible),
if the primitives from *random* module are used.
*/
// Blessing: i.e adding prototype
/* eslint-disable no-use-before-define */
function generatorProtoMap(f) {
/* jshint validthis:true */
var generator = this; // eslint-disable-line no-invalid-this
generatorAssert(generator);
return generatorBless(function (size) {
return f(generator(size));
});
}
function generatorProtoFlatMap(f) {
/* jshint validthis:true */
var generator = this; // eslint-disable-line no-invalid-this
generatorAssert(generator);
return generatorBless(function (size) {
return f(generator(size))(size);
});
}
/* eslint-enable no-use-before-define */
function generatorAssert(generator) {
assert(typeof generator === "function", "generator should be a function");
assert(generator.map === generatorProtoMap, "generator.map should be a function");
assert(generator.flatmap === generatorProtoFlatMap, "generator.flatmap should be a function");
assert(generator.flatMap === generatorProtoFlatMap, "generator.flatMap should be a function");
}
/**
- `generator.bless(f: nat -> a): generator a`
Bless function with `.map` and `.flatmap` properties.
- `.map(f: a -> b): generator b`
Map `generator a` into `generator b`. For example:
```js
positiveIntegersGenerator = nat.generator.map(
function (x) { return x + 1; });
```
- `.flatmap(f: a -> generator b): generator b`
Monadic bind for generators. Also `flatMap` version is supported.
*/
function generatorBless(generator) {
generator.map = generatorProtoMap;
generator.flatmap = generatorProtoFlatMap;
generator.flatMap = generatorProtoFlatMap;
return generator;
}
/**
- `generator.constant(x: a): generator a`
*/
function generateConstant(x) {
return generatorBless(function () {
return x;
});
}
/**
- `generator.combine(gen: generator a..., f: a... -> b): generator b`
*/
function generatorCombine() {
var generators = Array.prototype.slice.call(arguments, 0, -1);
var f = arguments[arguments.length - 1];
return generatorBless(function (size) {
var values = generators.map(function (gen) {
return gen(size);
});
return f.apply(undefined, values);
});
}
/**
- `generator.oneof(gens: list (generator a)): generator a`
*/
function generateOneof(generators) {
// TODO: generator
generators.forEach(function (gen) {
assert(typeof gen === "function");
});
var result = generatorBless(function (size) {
var idx = random(0, generators.length - 1);
var gen = generators[idx];
return gen(size);
});
return utils.curried2(result, arguments);
}
// Helper, essentially: log2(size + 1)
function logsize(size) {
return Math.max(Math.round(Math.log(size + 1) / Math.log(2), 0));
}
/**
- `generator.recursive(genZ: generator a, genS: generator a -> generator a): generator a`
*/
function generatorRecursive(genZ, genS) {
return generatorBless(function (size) {
function rec(n, sizep) {
if (n <= 0 || random(0, 3) === 0) {
return genZ(sizep);
} else {
return genS(generatorBless(function (sizeq) {
return rec(n - 1, sizeq);
}))(sizep);
}
}
return rec(logsize(size), size);
});
}
/**
- `generator.pair(genA: generator a, genB: generator b): generator (a, b)`
*/
function generatePair(genA, genB) {
var result = generatorBless(function (size) {
return [genA(size), genB(size)];
});
return utils.curried3(result, arguments);
}
/**
- `generator.either(genA: generator a, genB: generator b): generator (either a b)`
*/
function generateEither(genA, genB) {
var result = generatorBless(function (size) { // eslint-disable-line consistent-return
var n = random(0, 1);
switch (n) {
case 0: return either.left(genA(size));
case 1: return either.right(genB(size));
// no default
}
});
return utils.curried3(result, arguments);
}
/**
- `generator.unit: generator ()`
`unit` is an empty tuple, i.e. empty array in JavaScript representation. This is useful as a building block.
*/
var generateUnit = generatorBless(function () {
return [];
});
/**
- `generator.tuple(gens: (generator a, generator b...)): generator (a, b...)`
*/
function generateTuple(gens) {
var len = gens.length;
var result = generatorBless(function (size) {
var r = [];
for (var i = 0; i < len; i++) {
r[i] = gens[i](size);
}
return r;
});
return utils.curried2(result, arguments);
}
/**
- `generator.sum(gens: (generator a, generator b...)): generator (a | b...)`
*/
function generateSum(gens) {
var len = gens.length;
var result = generatorBless(function (size) {
var idx = random(0, len - 1);
return sum.addend(idx, len, gens[idx](size));
});
return utils.curried2(result, arguments);
}
/**
- `generator.array(gen: generator a): generator (array a)`
*/
function generateArray(gen) {
var result = generatorBless(function (size) {
var arrsize = random(0, logsize(size));
var arr = new Array(arrsize);
for (var i = 0; i < arrsize; i++) {
arr[i] = gen(size);
}
return arr;
});
return utils.curried2(result, arguments);
}
/**
- `generator.nearray(gen: generator a): generator (array a)`
*/
function generateNEArray(gen) {
var result = generatorBless(function (size) {
var arrsize = random(1, Math.max(logsize(size), 1));
var arr = new Array(arrsize);
for (var i = 0; i < arrsize; i++) {
arr[i] = gen(size);
}
return arr;
});
return utils.curried2(result, arguments);
}
/**
- `generator.dict(gen: generator a): generator (dict a)`
*/
module.exports = {
pair: generatePair,
either: generateEither,
unit: generateUnit,
tuple: generateTuple,
sum: generateSum,
array: generateArray,
nearray: generateNEArray,
oneof: generateOneof,
constant: generateConstant,
bless: generatorBless,
combine: generatorCombine,
recursive: generatorRecursive,
};
},{"./either.js":8,"./random.js":18,"./sum.js":26,"./utils.js":28,"assert":29}],14:[function(require,module,exports){
"use strict";
var assert = require("assert");
var arbitraryBless = require("./arbitraryBless.js");
var dict = require("./dict.js");
var generator = require("./generator.js");
var primitive = require("./primitive.js");
var show = require("./show.js");
var shrink = require("./shrink.js");
var string = require("./string.js");
var utils = require("./utils.js");
var nullArb = primitive.constant(null);
var generateInteger = primitive.integer.generator;
var generateNumber = primitive.number.generator;
var generateBool = primitive.bool.generator;
var generateString = string.string.generator;
var generateNull = nullArb.generator;
var generateJson = generator.recursive(
generator.oneof([
generateInteger,
generateNumber,
generateBool,
generateString,
generateNull,
]),
function (gen) {
return generator.oneof([generator.array(gen), dict.generator(gen)]);
});
// Forward declaration
var shrinkDictJson;
var shrinkJson;
function shrinkRecJson(json) {
if (Array.isArray(json)) {
return shrink.array(shrinkJson, json);
} else {
return shrinkDictJson(json);
}
}
shrinkJson = shrink.bless(function (json) {
assert(typeof json !== "function");
if (json === null) {
return nullArb.shrink(json);
}
switch (typeof json) {
case "boolean": return primitive.bool.shrink(json);
case "number": return primitive.number.shrink(json);
case "string": return string.string.shrink(json);
default: return shrinkRecJson(json);
}
});
shrinkDictJson = (function () {
var pairShrink = shrink.pair(string.string.shrink, shrinkJson);
var arrayShrink = shrink.array(pairShrink);
return arrayShrink.smap(utils.pairArrayToDict, utils.dictToPairArray);
}());
var json = arbitraryBless({
generator: generateJson,
shrink: shrinkJson,
show: show.def,
});
module.exports = {
json: json,
};
},{"./arbitraryBless.js":4,"./dict.js":7,"./generator.js":13,"./primitive.js":17,"./show.js":21,"./shrink.js":22,"./string.js":24,"./utils.js":28,"assert":29}],15:[function(require,module,exports){
/* @flow weak */
/**
# JSVerify
<img src="https://raw.githubusercontent.com/jsverify/jsverify/master/jsverify-300.png" align="right" height="100" />
> Property-based checking. Like QuickCheck.
[![Build Status](https://secure.travis-ci.org/jsverify/jsverify.svg?branch=master)](http://travis-ci.org/jsverify/jsverify)
[![NPM version](https://badge.fury.io/js/jsverify.svg)](http://badge.fury.io/js/jsverify)
[![Dependency Status](https://david-dm.org/jsverify/jsverify.svg)](https://david-dm.org/jsverify/jsverify)
[![devDependency Status](https://david-dm.org/jsverify/jsverify/dev-status.svg)](https://david-dm.org/jsverify/jsverify#info=devDependencies)
[![Code Climate](https://img.shields.io/codeclimate/github/jsverify/jsverify.svg)](https://codeclimate.com/github/jsverify/jsverify)
## Getting Started
Install the module with: `npm install jsverify`
## Synopsis
```js
var jsc = require("jsverify");
// forall (f : bool -> bool) (b : bool), f (f (f b)) = f(b).
var boolFnAppliedThrice =
jsc.forall("bool -> bool", "bool", function (f, b) {
return f(f(f(b))) === f(b);
});
jsc.assert(boolFnAppliedThrice);
// OK, passed 100 tests
```
*/
"use strict";
/**
## Documentation
### Usage with [mocha](http://mochajs.org/)
Using jsverify with mocha is easy, just define the properties and use `jsverify.assert`.
Starting from version 0.4.3 you can write your specs without any boilerplate:
```js
describe("sort", function () {
jsc.property("idempotent", "array nat", function (arr) {
return _.isEqual(sort(sort(arr)), sort(arr));
});
});
```
Starting from version 0.8.0 you can write the specs in TypeScript. There are
typings provided. The drawback is that you cannot use type DSL:
```typescript
describe("basic jsverify usage", () => {
jsc.property("(b && b) === b", jsc.bool, b => (b && b) === b);
jsc.property("boolean fn thrice", jsc.fn(jsc.bool), jsc.bool, (f, b) =>
f(f(f(b))) === f(b)
);
});
```
You can also provide `--jsverifyRngState state` command line argument, to run tests with particular random generator state.
```
$ mocha examples/nat.js
1) natural numbers are less than 90:
Error: Failed after 49 tests and 1 shrinks. rngState: 074e9b5f037a8c21d6; Counterexample: 90;
$ mocha examples/nat.js --grep 'are less than' --jsverifyRngState 074e9b5f037a8c21d6
1) natural numbers are less than 90:
Error: Failed after 1 tests and 1 shrinks. rngState: 074e9b5f037a8c21d6; Counterexample: 90;
```
Erroneous case is found with first try.
### Usage with [jasmine](https://jasmine.github.io/)
Check [jasmineHelpers.js](helpers/jasmineHelpers.js) and [jasmineHelpers2.js](helpers/jasmineHelpers2.js) for jasmine 1.3 and 2.0 respectively.
## API Reference
> _Testing shows the presence, not the absence of bugs._
>
> Edsger W. Dijkstra
To show that propositions hold, we need to construct proofs.
There are two extremes: proof by example (unit tests) and formal (machine-checked) proof.
Property-based testing is somewhere in between.
We formulate propositions, invariants or other properties we believe to hold, but
only test it to hold for numerous (randomly generated) values.
Types and function signatures are written in [Coq](http://coq.inria.fr/)/[Haskell](http://www.haskell.org/haskellwiki/Haskell)-influenced style:
C# -style `List<T> filter(List<T> v, Func<T, bool> predicate)` is represented by
`filter(v: array T, predicate: T -> bool): array T` in our style.
Methods and objects live in `jsc` object, e.g. `shrink.bless` method is used by
```js
var jsc = require("jsverify");
var foo = jsc.shrink.bless(...);
```
Methods starting with `.dot` are prototype methods:
```js
var arb = jsc.nat;
var arb2 = jsc.nat.smap(f, g);
```
`jsverify` can operate with both synchronous and asynchronous-promise properties.
Generally every property can be wrapped inside [functor](http://learnyouahaskell.com/functors-applicative-functors-and-monoids),
for now in either identity or promise functor, for synchronous and promise properties respectively.
*/
var assert = require("assert");
var lazyseq = require("lazy-seq");
var api = require("./api.js");
var either = require("./either.js");
var environment = require("./environment.js");
var FMap = require("./finitemap.js");
var fn = require("./fn.js");
var functor = require("./functor.js");
var random = require("./random.js");
var show = require("./show.js");
var shrink = require("./shrink.js");
var suchthat = require("./suchthat.js");
var sum = require("./sum.js");
var typify = require("./typify.js");
var utils = require("./utils.js");
/**
### Properties
*/
function shrinkResult(arbs, x, test, size, shrinksN, exc, transform) {
assert(arbs.length === x.length, "shrinkResult: arbs and x has to be of same size");
assert(typeof size === "number", "shrinkResult: size should be number");
assert(typeof shrinksN === "number", "shrinkResult: shrinkN should be number");
var shrinks = utils.pluck(arbs, "shrink");
var shows = utils.pluck(arbs, "show");
var shrinked = shrink.tuple(shrinks, x);
var shrinkP = lazyseq.fold(shrinked, true, function (y, rest) {
var t = test(size, y, shrinksN + 1);
return functor.map(t, function (tprime) {
return tprime !== true ? tprime : rest();
});
});
return functor.map(shrinkP, function (shrinkPPrime) {
if (shrinkPPrime === true) {
var res = {
counterexample: x,
counterexamplestr: show.tuple(shows, x),
shrinks: shrinksN,
exc: exc,
};
return transform(res);
} else {
return shrinkPPrime;
}
});
}
function isArbitrary(arb) {
return (typeof arb === "object" || typeof arb === "function") &&
typeof arb.generator === "function" &&
typeof arb.shrink === "function" &&
typeof arb.show === "function";
}
/**
- `forall(arbs: arbitrary a ..., userenv: (map arbitrary)?, prop : a -> property): property`
Property constructor
*/
function forall() {
var args = Array.prototype.slice.call(arguments);
var gens = args.slice(0, -1);
var property = args[args.length - 1];
var env;
var lastgen = gens[gens.length - 1];
if (!isArbitrary(lastgen) && typeof lastgen !== "string") {
env = utils.merge(environment, lastgen);
gens = gens.slice(0, -1);
} else {
env = environment;
}
assert(gens.length > 0, "forall requires at least single generator");
// Map typify-dsl to hard generators
gens = gens.map(function (g) {
g = typeof g === "string" ? typify.parseTypify(env, g) : g;
return utils.force(g);
});
assert(typeof property === "function", "property should be a function");
function test(size, x, shrinks) {
assert(Array.isArray(x), "generators results should be always tuple");
return functor.bind(property, x, function (r, exc) {
if (r === true) {
return true;
} else if (typeof r === "function") {
var rRec = r(size);
return functor.map(rRec, function (rRecPrime) {
if (rRecPrime === true) {
return true;
} else {
return shrinkResult(gens, x, test, size, shrinks, exc, function (rr) {
return {
counterexample: rr.counterexample.concat(rRecPrime.counterexample),
counterexamplestr: rr.counterexamplestr, // + "; " + rRec.counterexamplestr,
shrinks: rr.shrinks,
exc: rr.exc || rRecPrime.exc,
};
});
}
});
} else {
return shrinkResult(gens, x, test, size, shrinks, exc || r, utils.identity);
}
});
}
return function (size) {
var x = gens.map(function (arb) { return arb.generator(size); });
var r = test(size, x, 0);
return r;
};
}
function formatFailedCase(r, state, includeStack) {
var msg = "Failed after " + r.tests + " tests and " + r.shrinks + " shrinks. ";
msg += "rngState: " + (r.rngState || state) + "; ";
msg += "Counterexample: " + r.counterexamplestr + "; ";
if (r.exc) {
if (r.exc instanceof Error) {
msg += "Exception: " + r.exc.message;
if (includeStack) {
msg += "\nStack trace: " + r.exc.stack;
}
} else {
msg += "Error: " + r.exc;
}
}
return msg;
}
function findRngState(argv) { // eslint-disable-line consistent-return
for (var i = 0; i < argv.length - 1; i++) {
if (argv[i] === "--jsverifyRngState") {
return argv[i + 1];
}
}
}
/**
- `check (prop: property, opts: checkoptions?): result`
Run random checks for given `prop`. If `prop` is promise based, result is also wrapped in promise.
Options:
- `opts.tests` - test count to run, default 100
- `opts.size` - maximum size of generated values, default 50
- `opts.quiet` - do not `console.log`
- `opts.rngState` - state string for the rng
The `result` is `true` if check succeeds, otherwise it's an object with various fields:
- `counterexample` - an input for which property fails.
- `tests` - number of tests run before failing case is found
- `shrinks` - number of shrinks performed
- `exc` - an optional exception thrown by property function
- `rngState` - random number generator's state before execution of the property
*/
function check(property, opts) {
opts = opts || {};
opts.size = opts.size || 50;
opts.tests = opts.tests || 100;
opts.quiet = opts.quiet || false;
assert(typeof property === "function", "property should be a function");
var state;
if (opts.rngState) {
random.setStateString(opts.rngState);
} else if (typeof process !== "undefined") {
var argvState = findRngState(process.argv);
if (argvState) {
random.setStateString(argvState);
}
}
function loop(i) {
state = random.currentStateString();
if (i > opts.tests) {
return true;
}
var size = random(0, opts.size);
// wrap non-promises in trampoline
var r = functor.pure(property(size));
return functor.map(r, function (rPrime) {
if (rPrime === true) {
return loop(i + 1);
} else {
rPrime.tests = i;
/* global console */
if (!opts.quiet) {
console.error(formatFailedCase(rPrime, state, true), rPrime.counterexample);
}
return rPrime;
}
});
}
return functor.run(functor.map(loop(1), function (r) {
if (r === true) {
if (!opts.quiet) { console.info("OK, passed " + opts.tests + " tests"); }
} else {
r.rngState = state;
}
return r;
}));
}
/**
- `assert(prop: property, opts: checkoptions?) : void`
Same as `check`, but throw exception if property doesn't hold.
*/
function checkThrow(property, opts) {
opts = opts || {};
if (opts.quiet === undefined) {
opts.quiet = true;
}
return functor.run(functor.map(check(property, opts), function (r) {
if (r !== true) {
if (r.exc instanceof Error) {
r.exc.message = formatFailedCase(r);
throw r.exc;
} else {
throw new Error(formatFailedCase(r));
}
}
}));
}
/**
- `property(name: string, ...)`
Assuming there is globally defined `it`, the same as:
```js
it(name, function () {
jsc.assert(jsc.forall(...));
}
```
You can use `property` to write facts too:
```js
jsc.property("+0 === -0", function () {
return +0 === -0;
});
```
*/
function bddProperty(name) {
/* global it: true */
var args = Array.prototype.slice.call(arguments, 1);
if (args.length === 1) {
it(name, function () {
return functor.run(functor.map(args[0](), function (result) { // eslint-disable-line consistent-return
if (typeof result === "function") {
return checkThrow(result);
} else if (result !== true) {
throw new Error(name + " doesn't hold");
}
}));
});
} else {
var prop = forall.apply(undefined, args);
it(name, function () {
return checkThrow(prop);
});
}
/* global it: false */
}
/**
- `compile(desc: string, env: typeEnv?): arbitrary a`
Compile the type description in provided type environment, or default one.
*/
function compile(str, env) {
env = env ? utils.merge(environment, env) : environment;
return typify.parseTypify(env, str);
}
/**
- `sampler(arb: arbitrary a, genSize: nat = 10): (sampleSize: nat?) -> a`
Create a sampler for a given arbitrary with an optional size. Handy when used in
a REPL:
```
> jsc = require('jsverify') // or require('./lib/jsverify') w/in the project
...
> jsonSampler = jsc.sampler(jsc.json, 4)
[Function]
> jsonSampler()
0.08467432763427496
> jsonSampler()
[ [ [] ] ]
> jsonSampler()
''
> sampledJson(2)
[-0.4199344692751765, false]
```
*/
function sampler(arb, size) {
size = typeof size === "number" ? Math.abs(size) : 10;
return function (count) {
if (typeof count === "number") {
var acc = [];
count = Math.abs(count);
for (var i = 0; i < count; i++) {
acc.push(arb.generator(size));
}
return acc;
} else {
return arb.generator(size);
}
};
}
/**
- `throws(block: () -> a, error: class?, message: string?): bool`
Executes nullary function `block`. Returns `true` if `block` throws. See [assert.throws](https://nodejs.org/api/assert.html#assert_assert_throws_block_error_message)
*/
function throws(block, error, message) {
assert(error === undefined || typeof error === "function", "throws: error parameter must be a constructor");
assert(message === undefined || typeof message === "string", "throws: message parameter must be a string");
try {
block();
return false;
} catch (e) {
if (error !== undefined) {
if (e instanceof error) {
return message === undefined || e.message === message;
} else {
return false;
}
} else {
return true;
}
}
}
/**
- `assertForall(arbs: arbitrary a ..., userenv: (map arbitrary)?, prop : a -> property): void`
Combines 'assert' and 'forall'.
Constructs a property with forall from arguments, then throws an exception if the property doesn't hold.
Options for 'assert' cannot be set here - use assert(forall(...)) if you need that.
*/
function assertForall() {
return checkThrow(forall.apply(null, arguments));
}
/**
- `checkForall(arbs: arbitrary a ..., userenv: (map arbitrary)?, prop : a -> property): result`
Combines 'check' and 'forall'.
Constructs a property with forall from arguments, and returns a value based on if the property holds or not.
See 'check' for description of return value.
Options for 'check' cannot be set here - use check(forall(...)) if you need that.
*/
function checkForall() {
return check(forall.apply(null, arguments));
}
/**
### Types
- `generator a` is a function `(size: nat) -> a`.
- `show` is a function `a -> string`.
- `shrink` is a function `a -> [a]`, returning *smaller* values.
- `arbitrary a` is a triple of generator, shrink and show functions.
- `{ generator: nat -> a, shrink : a -> array a, show: a -> string }`
### Blessing
We chose to represent generators and shrinks by functions, yet we would
like to have additional methods on them. Thus we *bless* objects with
additional properties.
Usually you don't need to bless anything explicitly, as all combinators
return blessed values.
See [perldoc for bless](http://perldoc.perl.org/functions/bless.html).
*/
/// include ./typify.js
/// include ./arbitraryBless.js
/// include ./bless.js
/// include ./primitive.js
/// include ./arbitrary.js
/// include ./recordWithEnv.js
/// include ./record.js
/// include ./string.js
/// include ./fn.js
/// include ./small.js
/// include ./suchthat.js
/// include ./generator.js
/// include ./shrink.js
/// include ./show.js
/// include ./random.js
/// include ./either.js
/// include ./utils.js
// Export
var jsc = {
forall: forall,
check: check,
assert: checkThrow,
assertForall: assertForall,
checkForall: checkForall,
property: bddProperty,
sampler: sampler,
throws: throws,
// generators
fn: fn.fn,
fun: fn.fn,
suchthat: suchthat.suchthat,
// either
left: either.left,
right: either.right,
// sum
addend: sum.addend,
// compile
compile: compile,
generator: api.generator,
shrink: api.shrink,
// internal utility lib
random: random,
show: show,
utils: utils,
_: {
FMap: FMap,
},
};
/* primitives */
/* eslint-disable guard-for-in */
for (var k in api.arbitrary) {
jsc[k] = api.arbitrary[k];
}
/* eslint-enable guard-for-in */
module.exports = jsc;
/// plain ../FAQ.md
/// plain ../CONTRIBUTING.md
/// plain ../CHANGELOG.md
/// plain ../related-work.md
/// plain ../LICENSE
},{"./api.js":1,"./either.js":8,"./environment.js":9,"./finitemap.js":10,"./fn.js":11,"./functor.js":12,"./random.js":18,"./show.js":21,"./shrink.js":22,"./suchthat.js":25,"./sum.js":26,"./typify.js":27,"./utils.js":28,"assert":29,"lazy-seq":30}],16:[function(require,module,exports){
"use strict";
var arbitraryAssert = require("./arbitraryAssert.js");
var arbitraryBless = require("./arbitraryBless.js");
var generator = require("./generator.js");
var show = require("./show.js");
var shrink = require("./shrink.js");
var utils = require("./utils.js");
function pair(a, b) {
a = utils.force(a);
b = utils.force(b);
arbitraryAssert(a);
arbitraryAssert(b);
return arbitraryBless({
generator: generator.pair(a.generator, b.generator),
shrink: shrink.pair(a.shrink, b.shrink),
show: show.pair(a.show, b.show),
});
}
module.exports = {
pair: pair,
};
},{"./arbitraryAssert.js":3,"./arbitraryBless.js":4,"./generator.js":13,"./show.js":21,"./shrink.js":22,"./utils.js":28}],17:[function(require,module,exports){
/* @flow weak */
"use strict";
var arbitraryBless = require("./arbitraryBless");
var assert = require("assert");
var generator = require("./generator.js");
var random = require("./random.js");
var show = require("./show.js");
var shrink = require("./shrink.js");
var utils = require("./utils.js");
/**
### Primitive arbitraries
*/
function extendWithDefault(arb) {
var def = arb();
arb.generator = def.generator;
arb.shrink = def.shrink;
arb.show = def.show;
arb.smap = def.smap;
}
function numeric(impl) {
return function (minsize, maxsize) {
if (arguments.length === 2) {
var arb = arbitraryBless(impl(maxsize - minsize));
var to = function to(x) {
return Math.abs(x) + minsize;
};
var from = function from(x) {
return x - minsize;
};
return arb.smap(to, from);
} else if (arguments.length === 1) {
return arbitraryBless(impl(minsize /* as maxsize */));
} else {
return arbitraryBless(impl());
}
};
}
/**
- `integer: arbitrary integer`
- `integer(maxsize: nat): arbitrary integer`
- `integer(minsize: integer, maxsize: integer): arbitrary integer`
Integers,
*/
var integer = numeric(function integer(maxsize) {
return {
generator: generator.bless(function (size) {
size = maxsize === undefined ? size : maxsize;
return random(-size, size);
}),
shrink: shrink.bless(function (i) {
assert(typeof i === "number", "integer.shrink have to be a number");
i = Math.abs(i);
if (i === 0) {
return [];
} else {
var arr = [0];
var j = utils.div2(i);
var k = Math.max(j, 1);
while (j < i) {
arr.push(j);
arr.push(-j);
k = Math.max(utils.div2(k), 1);
j += k;
}
return arr;
}
}),
show: show.def,
};
});
extendWithDefault(integer);
/**
- `nat: arbitrary nat`
- `nat(maxsize: nat): arbitrary nat`
Natural numbers, (0, 1, 2...)
*/
function nat(maxsize) {
return arbitraryBless({
generator: generator.bless(function (size) {
size = maxsize === undefined ? size : maxsize;
return random(0, size);
}),
shrink: shrink.bless(function (i) {
assert(typeof i === "number", "nat.shrink have to be a number");
var arr = [];
var j = utils.div2(i);
var k = Math.max(j, 1);
while (j < i) {
arr.push(j);
k = Math.max(utils.div2(k), 1);
j += k;
}
return arr;
}),
show: show.def,
});
}
extendWithDefault(nat);
/**
- `number: arbitrary number`
- `number(maxsize: number): arbitrary number`
- `number(min: number, max: number): arbitrary number`
JavaScript numbers, "doubles", . `NaN` and `Infinity` are not included.
*/
var number = numeric(function number(maxsize) {
return {
generator: generator.bless(function (size) {
size = maxsize === undefined ? size : maxsize;
return random.number(-size, size);
}),
shrink: shrink.bless(function (x) {
assert(typeof x === "number", "number.shrink have to be a number");
if (Math.abs(x) > 1e-6) {
return [0, x / 2, -x / 2];
} else {
return [];
}
}),
show: show.def,
};
});
extendWithDefault(number);
/**
- `uint8: arbitrary nat`
- `uint16: arbitrary nat`
- `uint32: arbitrary nat`
*/
var uint8 = nat(0xff);
var uint16 = nat(0xffff);
var uint32 = nat(0xffffffff);
/**
- `int8: arbitrary integer`
- `int16: arbitrary integer`
- `int32: arbitrary integer`
*/
var int8 = integer(-0x80, 0x7f);
var int16 = integer(-0x8000, 0x7fff);
var int32 = integer(-0x80000000, 0x7fffffff);
/**
- `bool: arbitrary bool`
Booleans, `true` or `false`.
*/
var bool = arbitraryBless({
generator: generator.bless(function (/* size */) {
var i = random(0, 1);
return i === 1;
}),
shrink: shrink.bless(function (b) {
assert(b === true || b === false, "bool.shrink excepts true or false");
return b === true ? [false] : [];
}),
show: show.def,
});
/**
- `datetime: arbitrary datetime`
Random datetime
*/
var datetimeConst = 1416499879495; // arbitrary datetime
function datetime(from, to) {
var toDate;
var fromDate;
var arb;
if (arguments.length === 2) {
toDate = function toDateFn(x) {
return new Date(x);
};
fromDate = function fromDateFn(x) {
return x.getTime();
};
from = fromDate(from);
to = fromDate(to);
arb = number(from, to);
return arb.smap(toDate, fromDate);
} else {
toDate = function toDateFn(x) {
return new Date(x * 768000000 + datetimeConst);
};
arb = number;
return arbitraryBless({
generator: arb.generator.map(toDate),
shrink: shrink.noop,
show: show.def,
});
}
}
extendWithDefault(datetime);
/**
- `elements(args: array a): arbitrary a`
Random element of `args` array.
*/
function elements(args) {
assert(args.length !== 0, "elements: at least one parameter expected");
return arbitraryBless({
generator: generator.bless(function (/* size */) {
var i = random(0, args.length - 1);
return args[i];
}),
shrink: shrink.bless(function (x) {
var idx = args.indexOf(x);
if (idx <= 0) {
return [];
} else {
return args.slice(0, idx);
}
}),
show: show.def,
});
}
/**
- `falsy: arbitrary *`
Generates falsy values: `false`, `null`, `undefined`, `""`, `0`, and `NaN`.
*/
var falsy = elements([false, null, undefined, "", 0, NaN]);
falsy.show = function (v) {
if (v !== v) {
return "falsy: NaN";
} else if (v === "") {
return "falsy: empty string";
} else if (v === undefined) {
return "falsy: undefined";
} else {
return "falsy: " + v;
}
};
/**
- `constant(x: a): arbitrary a`
Returns an unshrinkable arbitrary that yields the given object.
*/
function constant(x) {
return arbitraryBless({
generator: generator.constant(x),
shrink: shrink.noop,
show: show.def,
});
}
module.exports = {
integer: integer,
nat: nat,
int8: int8,
int16: int16,
int32: int32,
uint8: uint8,
uint16: uint16,
uint32: uint32,
number: number,
elements: elements,
bool: bool,
falsy: falsy,
constant: constant,
datetime: datetime,
};
},{"./arbitraryBless":4,"./generator.js":13,"./random.js":18,"./show.js":21,"./shrink.js":22,"./utils.js":28,"assert":29}],18:[function(require,module,exports){
/* @flow weak */
"use strict";
var rc4 = new (require("rc4").RC4small)();
/**
### Random functions
*/
/**
- `random(min: int, max: int): int`
Returns random int from `[min, max]` range inclusively.
```js
getRandomInt(2, 3) // either 2 or 3
```
*/
function randomInteger(min, max) {
return rc4.random(min, max);
}
/**
- `random.number(min: number, max: number): number`
Returns random number from `[min, max)` range.
*/
function randomNumber(min, max) {
return rc4.randomFloat() * (max - min) + min;
}
randomInteger.integer = randomInteger;
randomInteger.number = randomNumber;
randomInteger.currentStateString = rc4.currentStateString.bind(rc4);
randomInteger.setStateString = rc4.setStateString.bind(rc4);
module.exports = randomInteger;
},{"rc4":31}],19:[function(require,module,exports){
"use strict";
var arbitraryBless = require("./arbitraryBless.js");
var generator = require("./generator.js");
var utils = require("./utils.js");
var shrink = require("./shrink.js");
/**
- `generator.record(gen: { key: generator a... }): generator { key: a... }`
*/
function generatorRecord(spec) {
var keys = Object.keys(spec);
var result = generator.bless(function (size) {
var res = {};
keys.forEach(function (k) {
res[k] = spec[k](size);
});
return res;
});
return utils.curried2(result, arguments);
}
/**
- `shrink.record(shrs: { key: shrink a... }): shrink { key: a... }`
*/
function shrinkRecord(shrinksRecord) {
var keys = Object.keys(shrinksRecord);
var shrinks = keys.map(function (k) { return shrinksRecord[k]; });
var result = shrink.bless(function (rec) {
var values = keys.map(function (k) { return rec[k]; });
var shrinked = shrink.tuple(shrinks, values);
return shrinked.map(function (s) {
var res = {};
keys.forEach(function (k, i) {
res[k] = s[i];
});
return res;
});
});
return utils.curried2(result, arguments);
}
function arbitraryRecord(spec) {
var generatorSpec = {};
var shrinkSpec = {};
var showSpec = {};
Object.keys(spec).forEach(function (k) {
var arb = utils.force(spec[k]);
generatorSpec[k] = arb.generator;
shrinkSpec[k] = arb.shrink;
showSpec[k] = arb.show;
});
return arbitraryBless({
generator: generatorRecord(generatorSpec),
shrink: shrinkRecord(shrinkSpec),
show: function (m) {
return "{" + Object.keys(m).map(function (k) {
return k + ": " + showSpec[k](m[k]);
}).join(", ") + "}";
},
});
}
module.exports = {
generator: generatorRecord,
arbitrary: arbitraryRecord,
shrink: shrinkRecord,
};
},{"./arbitraryBless.js":4,"./generator.js":13,"./shrink.js":22,"./utils.js":28}],20:[function(require,module,exports){
"use strict";
var environment = require("./environment.js");
var record = require("./record.js");
var typify = require("./typify.js");
var utils = require("./utils.js");
/**
### Arbitrary records
- `record(spec: { key: arbitrary a... }, userenv: env?): arbitrary { key: a... }`
Generates a javascript object with given record spec.
*/
function recordWithEnv(spec, userenv) {
var env = userenv ? utils.merge(environment, userenv) : environment;
var parsedSpec = {};
Object.keys(spec).forEach(function (k) {
var arb = spec[k];
parsedSpec[k] = typeof arb === "string" ? typify.parseTypify(env, arb) : arb;
});
return record.arbitrary(parsedSpec);
}
module.exports = recordWithEnv;
},{"./environment.js":9,"./record.js":19,"./typify.js":27,"./utils.js":28}],21:[function(require,module,exports){
/* @flow weak */
"use strict";
/**
### Show functions
*/
var utils = require("./utils.js");
/**
- `show.def(x : a): string`
Currently implemented as `JSON.stringify`.
*/
function showDef(obj) {
return JSON.stringify(obj);
}
/**
- `show.pair(showA: a -> string, showB: b -> string, x: (a, b)): string`
*/
function showPair(showA, showB) {
var result = function (p) {
return "(" + showA(p[0]) + ", " + showB(p[1]) + ")";
};
return utils.curried3(result, arguments);
}
/**
- `show.either(showA: a -> string, showB: b -> string, e: either a b): string`
*/
function showEither(showA, showB) {
function showLeft(value) {
return "Left(" + showA(value) + ")";
}
function showRight(value) {
return "Right(" + showB(value) + ")";
}
var result = function (e) {
return e.either(showLeft, showRight);
};
return utils.curried3(result, arguments);
}
/**
- `show.tuple(shrinks: (a -> string, b -> string...), x: (a, b...)): string`
*/
function showTuple(shows) {
var result = function (objs) {
var strs = [];
for (var i = 0; i < shows.length; i++) {
strs.push(shows[i](objs[i]));
}
return strs.join("; ");
};
return utils.curried2(result, arguments);
}
/**
- `show.sum(shrinks: (a -> string, b -> string...), x: (a | b ...)): string`
*/
function showSum(shows) {
var result = function (sum) {
return sum.fold(function (idx, n, value) {
return "Sum(" + idx + "/" + n + ": " + shows[idx](value) + ")";
});
};
return utils.curried2(result, arguments);
}
/**
- `show.array(shrink: a -> string, x: array a): string`
*/
function showArray(show) {
var result = function (arr) {
return "[" + arr.map(show).join(", ") + "]";
};
return utils.curried2(result, arguments);
}
module.exports = {
def: showDef,
pair: showPair,
either: showEither,
tuple: showTuple,
sum: showSum,
array: showArray,
};
},{"./utils.js":28}],22:[function(require,module,exports){
/* @flow weak */
"use strict";
var assert = require("assert");
var either = require("./either.js");
var lazyseq = require("lazy-seq");
var sum = require("./sum.js");
var utils = require("./utils.js");
/**
### Shrink functions
A shrink function, `shrink a`, is a function `a -> [a]`, returning an array of *smaller* values.
Shrink combinators are auto-curried:
```js
var xs = jsc.shrink.array(jsc.nat.shrink, [1]); // ≡
var ys = jsc.shrink.array(jsc.nat.shrink)([1]);
```
*/
// Blessing: i.e adding prototype
/* eslint-disable no-use-before-define */
function shrinkProtoIsoMap(f, g) {
/* jshint validthis:true */
var shrink = this; // eslint-disable-line no-invalid-this
return shrinkBless(function (value) {
return shrink(g(value)).map(f);
});
}
/* eslint-enable no-use-before-define */
/**
- `shrink.bless(f: a -> [a]): shrink a`
Bless function with `.smap` property.
- `.smap(f: a -> b, g: b -> a): shrink b`
Transform `shrink a` into `shrink b`. For example:
```js
positiveIntegersShrink = nat.shrink.smap(
function (x) { return x + 1; },
function (x) { return x - 1; });
```
*/
function shrinkBless(shrink) {
shrink.smap = shrinkProtoIsoMap;
return shrink;
}
/**
- `shrink.noop: shrink a`
*/
var shrinkNoop = shrinkBless(function shrinkNoop() {
return [];
});
/**
- `shrink.pair(shrA: shrink a, shrB: shrink b): shrink (a, b)`
*/
function shrinkPair(shrinkA, shrinkB) {
var result = shrinkBless(function (pair) {
assert(pair.length === 2, "shrinkPair: pair should be an Array of length 2");
var a = pair[0];
var b = pair[1];
var shrinkedA = shrinkA(a);
var shrinkedB = shrinkB(b);
var pairA = shrinkedA.map(function (ap) {
return [ap, b];
});
if (Array.isArray(pairA)) {
pairA = lazyseq.fromArray(pairA);
}
return pairA.append(function () {
var pairB = shrinkedB.map(function (bp) {
return [a, bp];
});
return pairB;
});
});
return utils.curried3(result, arguments);
}
/**
- `shrink.either(shrA: shrink a, shrB: shrink b): shrink (either a b)`
*/
function shrinkEither(shrinkA, shrinkB) {
function shrinkLeft(value) {
return shrinkA(value).map(either.left);
}
function shrinkRight(value) {
return shrinkB(value).map(either.right);
}
var result = shrinkBless(function (e) {
return e.either(shrinkLeft, shrinkRight);
});
return utils.curried3(result, arguments);
}
// We represent non-empty linked list as
// singl x = [x]
// cons h t = [h, t]
function fromLinkedList(ll) {
assert(ll.length === 1 || ll.length === 2, "linked list must be either [] or [x, linkedlist]");
if (ll.length === 1) {
return [ll[0]];
} else {
return [ll[0]].concat(fromLinkedList(ll[1]));
}
}
function toLinkedList(arr) {
assert(Array.isArray(arr) && arr.length > 0, "toLinkedList expects non-empty array");
if (arr.length === 1) {
return [arr[0]];
} else {
return [arr[0], toLinkedList(arr.slice(1))];
}
}
function toSingleton(x) {
return [x];
}
// Vec a 1 → a
function fromSingleton(a) {
return a[0];
}
function flattenShrink(shrinksLL) {
if (shrinksLL.length === 1) {
return shrinksLL[0].smap(toSingleton, fromSingleton);
} else {
var head = shrinksLL[0];
var tail = shrinksLL[1];
return shrinkPair(head, flattenShrink(tail));
}
}
/**
- `shrink.tuple(shrs: (shrink a, shrink b...)): shrink (a, b...)`
*/
function shrinkTuple(shrinks) {
assert(shrinks.length > 0, "shrinkTuple needs > 0 values");
var shrinksLL = toLinkedList(shrinks);
var shrink = flattenShrink(shrinksLL);
var result = shrinkBless(function (tuple) {
assert(tuple.length === shrinks.length, "shrinkTuple: not-matching params");
var ll = toLinkedList(tuple);
return shrink(ll).map(fromLinkedList);
});
return utils.curried2(result, arguments);
}
/**
- `shrink.sum(shrs: (shrink a, shrink b...)): shrink (a | b...)`
*/
function shrinkSum(shrinks) {
assert(shrinks.length > 0, "shrinkTuple needs > 0 values");
var result = shrinkBless(function (s) {
return s.fold(function (idx, len, value) {
assert(len === shrinks.length, "shrinkSum: not-matching params");
return shrinks[idx](value).map(function (shrinked) {
return sum.addend(idx, len, shrinked);
});
});
});
return utils.curried2(result, arguments);
}
function shrinkArrayWithMinimumSize(size) {
function shrinkArrayImpl(shrink) {
var result = shrinkBless(function (arr) {
assert(Array.isArray(arr), "shrinkArrayImpl() expects array, got: " + arr);
if (arr.length <= size) {
return lazyseq.nil;
} else {
var x = arr[0];
var xs = arr.slice(1);
return lazyseq.cons(xs, lazyseq.nil)
.append(shrink(x).map(function (xp) { return [xp].concat(xs); }))
.append(shrinkArrayImpl(shrink, xs).map(function (xsp) { return [x].concat(xsp); }));
}
});
return utils.curried2(result, arguments);
}
return shrinkArrayImpl;
}
/**
- `shrink.array(shr: shrink a): shrink (array a)`
*/
var shrinkArray = shrinkArrayWithMinimumSize(0);
/**
- `shrink.nearray(shr: shrink a): shrink (nearray a)`
*/
var shrinkNEArray = shrinkArrayWithMinimumSize(1);
module.exports = {
noop: shrinkNoop,
pair: shrinkPair,
either: shrinkEither,
tuple: shrinkTuple,
sum: shrinkSum,
array: shrinkArray,
nearray: shrinkNEArray,
bless: shrinkBless,
};
},{"./either.js":8,"./sum.js":26,"./utils.js":28,"assert":29,"lazy-seq":30}],23:[function(require,module,exports){
"use strict";
var generator = require("./generator.js");
var arbitraryBless = require("./arbitraryBless.js");
var arbitraryAssert = require("./arbitraryAssert.js");
var utils = require("./utils.js");
/**
### Small arbitraries
- `generator.small(gen: generator a): generator a`
- `small(arb: arbitrary a): arbitrary a`
Create a generator (abitrary) which will generate smaller values, i.e. generator's `size` parameter is decreased logarithmically.
```js
jsc.property("small array of small natural numbers", "small (array nat)", function (arr) {
return Array.isArray(arr);
});
jsc.property("small array of normal natural numbers", "(small array) nat", function (arr) {
return Array.isArray(arr);
});
```
*/
function smallGenerator(gen) {
// TODO: assertGenerator(gen)
return generator.bless(function (size) {
return gen(utils.ilog2(size));
});
}
function smallArbitraryImpl(arb) {
arbitraryAssert(arb);
return arbitraryBless({
generator: smallGenerator(arb.generator),
shrink: arb.shrink,
show: arb.show,
});
}
function smallArbitrary(arb) {
if (typeof arb === "function") {
return function () {
var resArb = arb.apply(arb, arguments);
return smallArbitraryImpl(resArb);
};
} else { /* if (typeof arb === "object") */
return smallArbitraryImpl(arb);
}
}
module.exports = {
generator: smallGenerator,
arbitrary: smallArbitrary,
};
},{"./arbitraryAssert.js":3,"./arbitraryBless.js":4,"./generator.js":13,"./utils.js":28}],24:[function(require,module,exports){
"use strict";
var array = require("./array.js");
var primitive = require("./primitive.js");
var utils = require("./utils.js");
/**
### Arbitrary strings
*/
function fromCode(code) {
return String.fromCharCode(code);
}
function toCode(c) {
return c.charCodeAt(0);
}
/**
- `char: arbitrary char` &mdash; Single character
*/
var char = primitive.nat(0xff).smap(fromCode, toCode);
/**
- `asciichar: arbitrary char` &mdash; Single ascii character (0x20-0x7e inclusive, no DEL)
*/
var asciichar = primitive.integer(0x20, 0x7e).smap(fromCode, toCode);
/**
- `string: arbitrary string`
*/
var string = array.array(char).smap(utils.charArrayToString, utils.stringToCharArray);
/**
- `nestring: arbitrary string` &mdash; Generates strings which are not empty.
*/
var nestring = array.nearray(char).smap(utils.charArrayToString, utils.stringToCharArray);
/**
- `asciistring: arbitrary string`
*/
var asciistring = array.array(asciichar).smap(utils.charArrayToString, utils.stringToCharArray);
/**
- `asciinestring: arbitrary string`
*/
var asciinestring = array.nearray(asciichar).smap(utils.charArrayToString, utils.stringToCharArray);
module.exports = {
char: char,
asciichar: asciichar,
string: string,
nestring: nestring,
asciistring: asciistring,
asciinestring: asciinestring,
};
},{"./array.js":5,"./primitive.js":17,"./utils.js":28}],25:[function(require,module,exports){
/* @flow weak */
"use strict";
var environment = require("./environment.js");
var typify = require("./typify.js");
var utils = require("./utils.js");
var generator = require("./generator.js");
var shrink = require("./shrink.js");
var arbitraryBless = require("./arbitraryBless.js");
/**
### Restricting arbitraries
- `suchthat(arb: arbitrary a, userenv: env?, p : a -> bool): arbitrary a`
Arbitrary of values that satisfy `p` predicate. It's advised that `p`'s accept rate is high.
*/
function suchthat(arb, userenv, predicate) {
var env;
if (arguments.length === 2) {
predicate = userenv;
env = environment;
} else {
env = utils.merge(environment, userenv);
}
arb = typeof arb === "string" ? typify.parseTypify(env, arb) : arb;
arb = utils.force(arb);
return arbitraryBless({
generator: generator.bless(function (size) {
for (var i = 0; ; i++) {
// if 5 tries failed, increase size
if (i > 5) {
i = 0;
size += 1;
}
var x = arb.generator(size);
if (predicate(x)) {
return x;
}
}
}),
shrink: shrink.bless(function (x) {
return arb.shrink(x).filter(predicate);
}),
show: arb.show,
});
}
module.exports = {
suchthat: suchthat,
};
},{"./arbitraryBless.js":4,"./environment.js":9,"./generator.js":13,"./shrink.js":22,"./typify.js":27,"./utils.js":28}],26:[function(require,module,exports){
"use strict";
var assert = require("assert");
/**
### sum (n-ary either)
See: [Wikipedia](https://en.wikipedia.org/wiki/Tagged_union)
*/
function Addend(idx, len, value) {
assert(len > 0, "Addend: 0 < len"); // empty sum is void - cannot create such
assert(idx >= 0 && idx < len, "Addend: 0 <= idx < len");
this.idx = idx;
this.len = len;
this.value = value;
}
/**
- `sum.addend(idx: nat, n: nat, value: a): sum (... a ...)`
*/
function addend(idx, len, value) {
return new Addend(idx, len, value);
}
/**
- `.fold(f: (idx: nat, n: nat, value: a) -> b): b`
*/
Addend.prototype.fold = function (f) {
return f(this.idx, this.len, this.value);
};
module.exports = {
addend: addend,
};
},{"assert":29}],27:[function(require,module,exports){
/* @flow weak */
"use strict";
/**
### DSL for input parameters
There is a small DSL to help with `forall`. For example the two definitions below are equivalent:
```js
var bool_fn_applied_thrice = jsc.forall("bool -> bool", "bool", check);
var bool_fn_applied_thrice = jsc.forall(jsc.fn(jsc.bool), jsc.bool, check);
```
The DSL is based on a subset of language recognized by [typify-parser](https://github.com/phadej/typify-parser):
- *identifiers* are fetched from the predefined environment.
- *applications* are applied as one could expect: `"array bool"` is evaluated to `jsc.array(jsc.bool)`.
- *functions* are supported: `"bool -> bool"` is evaluated to `jsc.fn(jsc.bool)`.
- *square brackets* are treated as a shorthand for the array type: `"[nat]"` is evaluated to `jsc.array(jsc.nat)`.
- *union*: `"bool | nat"` is evaluated to `jsc.sum([jsc.bool, jsc.nat])`.
- **Note** `oneof` cannot be shrunk, because the union is untagged, we don't know which shrink to use.
- *conjunction*: `"bool & nat"` is evaluated to `jsc.tuple(jsc.bool, jsc.nat)`.
- *anonymous records*: `"{ b: bool; n: nat }"` is evaluated to `jsc.record({ b: jsc.bool, n: jsc.nat })`.
- *EXPERIMENTAL: recursive types*: `"rec list -> unit | (nat & list)"`.
*/
var arbitrary = require("./arbitrary.js");
var assert = require("assert");
var record = require("./record.js");
var array = require("./array.js");
var fn = require("./fn.js");
var typifyParser = require("typify-parser");
var utils = require("./utils.js");
// Forward declarations
var compileType;
var compileTypeArray;
function compileIdent(env, type) {
var g = env[type.value];
if (!g) {
throw new Error("Unknown arbitrary: " + type.value);
}
return g;
}
function compileApplication(env, type) {
var callee = compileType(env, type.callee);
var args = compileTypeArray(env, type.args);
return callee.apply(undefined, args);
}
function compileFunction(env, type) {
// we don't care about argument type
var result = compileType(env, type.result);
return fn.fn(result);
}
function compileBrackets(env, type) {
var arg = compileType(env, type.arg);
return array.array(arg);
}
function compileDisjunction(env, type) {
var args = compileTypeArray(env, type.args);
return arbitrary.sum(args);
}
function compileConjunction(env, type) {
var args = compileTypeArray(env, type.args);
return arbitrary.tuple(args);
}
function compileRecord(env, type) {
// TODO: use mapValues
var spec = {};
Object.keys(type.fields).forEach(function (key) {
spec[key] = compileType(env, type.fields[key]);
});
return record.arbitrary(spec);
}
function compileRecursive(env, type) {
assert(type.arg.type === "disjunction", "recursive type's argument should be disjunction");
// bound variable
var name = type.name;
var par = utils.partition(type.arg.args, function (t) {
return typifyParser.freeVars(t).indexOf(name) === -1;
});
var terminal = par[0];
if (terminal.length === 0) {
throw new Error("Recursive type without non-recursive branch");
}
var terminalArb = compileType(env, {
type: "disjunction",
args: terminal,
});
return arbitrary.recursive(terminalArb, function (arb) {
var arbEnv = {};
arbEnv[name] = arb;
var newEnv = utils.merge(env, arbEnv);
return compileType(newEnv, type.arg);
});
}
compileType = function compileTypeFn(env, type) {
switch (type.type) {
case "ident": return compileIdent(env, type);
case "application": return compileApplication(env, type);
case "function": return compileFunction(env, type);
case "brackets": return compileBrackets(env, type);
case "disjunction": return compileDisjunction(env, type);
case "conjunction": return compileConjunction(env, type);
case "record": return compileRecord(env, type);
case "number": return type.value;
case "recursive": return compileRecursive(env, type);
default: throw new Error("Unsupported typify ast type: " + type.type);
}
};
compileTypeArray = function compileTypeArrayFn(env, types) {
return types.map(function (type) {
return compileType(env, type);
});
};
function parseTypify(env, str) {
var type = typifyParser(str);
return compileType(env, type);
}
module.exports = {
parseTypify: parseTypify,
};
},{"./arbitrary.js":2,"./array.js":5,"./fn.js":11,"./record.js":19,"./utils.js":28,"assert":29,"typify-parser":33}],28:[function(require,module,exports){
/* @flow weak */
"use strict";
var isArray = Array.isArray;
function isObject(o) {
/* eslint-disable no-new-object */
return new Object(o) === o;
/* eslint-enable no-new-object */
}
/* undefined-safe isNaN */
function isNaN(n) {
return typeof n === "number" && n !== n;
}
/**
### Utility functions
Utility functions are exposed (and documented) only to make contributions to jsverify more easy.
The changes here don't follow semver, i.e. there might be backward-incompatible changes even in patch releases.
Use [underscore.js](http://underscorejs.org/), [lodash](https://lodash.com/), [ramda](http://ramda.github.io/ramdocs/docs/), [lazy.js](http://danieltao.com/lazy.js/) or some other utility belt.
*/
/* Simple sort */
function sort(arr) {
var res = arr.slice();
res.sort();
return res;
}
/**
- `utils.isEqual(x: json, y: json): bool`
Equality test for `json` objects.
*/
function isEqual(a, b) {
var i;
if (isNaN(a) && isNaN(b)) {
return true;
}
if (a === b) {
return true;
} else if (isArray(a) && isArray(b) && a.length === b.length) {
for (i = 0; i < a.length; i++) {
if (!isEqual(a[i], b[i])) {
return false;
}
}
return true;
} else if (isObject(a) && isObject(b) && !isArray(a) && !isArray(b)) {
var akeys = Object.keys(a);
var bkeys = Object.keys(b);
if (!isEqual(sort(akeys), sort(bkeys))) {
return false;
}
for (i = 0; i < akeys.length; i++) {
if (!isEqual(a[akeys[i]], b[akeys[i]])) {
return false;
}
}
return true;
}
return false;
}
/**
- `utils.isApproxEqual(x: a, y: b, opts: obj): bool`
Tests whether two objects are approximately and optimistically equal.
Returns `false` only if they are distinguishable not equal.
Returns `true` when `x` and `y` are `NaN`.
This function works with cyclic data.
Takes optional 'opts' parameter with properties:
- `fnEqual` - whether all functions are considered equal (default: yes)
- `depth` - how deep to recurse until treating as equal (default: 5)
*/
function isApproxEqual(x, y, opts) {
opts = opts || {};
var fnEqual = opts.fnEqual !== false;
var depth = opts.depth || 5; // totally arbitrary
// state contains pairs we checked (or are still checking, but assume equal!)
var state = [];
function loop(a, b, n) {
if (isNaN(a) && isNaN(b)) {
return true;
}
// trivial check
if (a === b) {
return true;
}
// depth check
if (n >= depth) {
return true;
}
var i;
// check if pair already occured
for (i = 0; i < state.length; i++) {
if (state[i][0] === a && state[i][1] === b) {
return true;
}
}
// add to state
state.push([a, b]);
if (typeof a === "function" && typeof b === "function") {
return fnEqual;
}
if (isArray(a) && isArray(b) && a.length === b.length) {
for (i = 0; i < a.length; i++) {
if (!loop(a[i], b[i], n + 1)) {
return false;
}
}
return true;
} else if (isObject(a) && isObject(b) && !isArray(a) && !isArray(b)) {
var akeys = Object.keys(a);
var bkeys = Object.keys(b);
if (!loop(sort(akeys), sort(bkeys), n + 1)) {
return false;
}
for (i = 0; i < akeys.length; i++) {
if (!loop(a[akeys[i]], b[akeys[i]], n + 1)) {
return false;
}
}
return true;
}
return false;
}
return loop(x, y, 0);
}
function identity(x) {
return x;
}
function pluck(arr, key) {
return arr.map(function (e) {
return e[key];
});
}
/**
- `utils.force(x: a | () -> a) : a`
Evaluate `x` as nullary function, if it is one.
*/
function force(arb) {
return (typeof arb === "function") ? arb() : arb;
}
/**
- `utils.merge(x... : obj): obj`
Merge two objects, a bit like `_.extend({}, x, y)`.
*/
function merge() {
var res = {};
for (var i = 0; i < arguments.length; i++) {
var arg = arguments[i];
var keys = Object.keys(arg);
for (var j = 0; j < keys.length; j++) {
var key = keys[j];
res[key] = arg[key];
}
}
return res;
}
function div2(x) {
return Math.floor(x / 2);
}
function log2(x) {
return Math.log(x) / Math.log(2);
}
function ilog2(x) {
return x <= 0 ? 0 : Math.floor(log2(x));
}
function curriedN(n) {
var n1 = n - 1;
return function curriedNInstance(result, args) {
if (args.length === n) {
return result(args[n1]);
} else {
return result;
}
};
}
var curried2 = curriedN(2);
var curried3 = curriedN(3);
function charArrayToString(arr) {
return arr.join("");
}
function stringToCharArray(str) {
return str.split("");
}
function pairArrayToDict(arrayOfPairs) {
var res = {};
arrayOfPairs.forEach(function (p) {
res[p[0]] = p[1];
});
return res;
}
function dictToPairArray(m) {
var res = [];
Object.keys(m).forEach(function (k) {
res.push([k, m[k]]);
});
return res;
}
function partition(arr, pred) {
var truthy = [];
var falsy = [];
for (var i = 0; i < arr.length; i++) {
var x = arr[i];
if (pred(x)) {
truthy.push(x);
} else {
falsy.push(x);
}
}
return [truthy, falsy];
}
module.exports = {
isArray: isArray,
isObject: isObject,
isEqual: isEqual,
isApproxEqual: isApproxEqual,
identity: identity,
pluck: pluck,
force: force,
merge: merge,
div2: div2,
ilog2: ilog2,
curried2: curried2,
curried3: curried3,
charArrayToString: charArrayToString,
stringToCharArray: stringToCharArray,
pairArrayToDict: pairArrayToDict,
dictToPairArray: dictToPairArray,
partition: partition,
};
},{}],29:[function(require,module,exports){
'use strict';
// compare and isBuffer taken from https://github.com/feross/buffer/blob/680e9e5e488f22aac27599a57dc844a6315928dd/index.js
// original notice:
/*!
* The buffer module from node.js, for the browser.
*
* @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
* @license MIT
*/
function compare(a, b) {
if (a === b) {
return 0;
}
var x = a.length;
var y = b.length;
for (var i = 0, len = Math.min(x, y); i < len; ++i) {
if (a[i] !== b[i]) {
x = a[i];
y = b[i];
break;
}
}
if (x < y) {
return -1;
}
if (y < x) {
return 1;
}
return 0;
}
function isBuffer(b) {
if (global.Buffer && typeof global.Buffer.isBuffer === 'function') {
return global.Buffer.isBuffer(b);
}
return !!(b != null && b._isBuffer);
}
// based on node assert, original notice:
// http://wiki.commonjs.org/wiki/Unit_Testing/1.0
//
// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!
//
// Originally from narwhal.js (http://narwhaljs.org)
// Copyright (c) 2009 Thomas Robinson <280north.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the 'Software'), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
var util = require('util/');
var hasOwn = Object.prototype.hasOwnProperty;
var pSlice = Array.prototype.slice;
var functionsHaveNames = (function () {
return function foo() {}.name === 'foo';
}());
function pToString (obj) {
return Object.prototype.toString.call(obj);
}
function isView(arrbuf) {
if (isBuffer(arrbuf)) {
return false;
}
if (typeof global.ArrayBuffer !== 'function') {
return false;
}
if (typeof ArrayBuffer.isView === 'function') {
return ArrayBuffer.isView(arrbuf);
}
if (!arrbuf) {
return false;
}
if (arrbuf instanceof DataView) {
return true;
}
if (arrbuf.buffer && arrbuf.buffer instanceof ArrayBuffer) {
return true;
}
return false;
}
// 1. The assert module provides functions that throw
// AssertionError's when particular conditions are not met. The
// assert module must conform to the following interface.
var assert = module.exports = ok;
// 2. The AssertionError is defined in assert.
// new assert.AssertionError({ message: message,
// actual: actual,
// expected: expected })
var regex = /\s*function\s+([^\(\s]*)\s*/;
// based on https://github.com/ljharb/function.prototype.name/blob/adeeeec8bfcc6068b187d7d9fb3d5bb1d3a30899/implementation.js
function getName(func) {
if (!util.isFunction(func)) {
return;
}
if (functionsHaveNames) {
return func.name;
}
var str = func.toString();
var match = str.match(regex);
return match && match[1];
}
assert.AssertionError = function AssertionError(options) {
this.name = 'AssertionError';
this.actual = options.actual;
this.expected = options.expected;
this.operator = options.operator;
if (options.message) {
this.message = options.message;
this.generatedMessage = false;
} else {
this.message = getMessage(this);
this.generatedMessage = true;
}
var stackStartFunction = options.stackStartFunction || fail;
if (Error.captureStackTrace) {
Error.captureStackTrace(this, stackStartFunction);
} else {
// non v8 browsers so we can have a stacktrace
var err = new Error();
if (err.stack) {
var out = err.stack;
// try to strip useless frames
var fn_name = getName(stackStartFunction);
var idx = out.indexOf('\n' + fn_name);
if (idx >= 0) {
// once we have located the function frame
// we need to strip out everything before it (and its line)
var next_line = out.indexOf('\n', idx + 1);
out = out.substring(next_line + 1);
}
this.stack = out;
}
}
};
// assert.AssertionError instanceof Error
util.inherits(assert.AssertionError, Error);
function truncate(s, n) {
if (typeof s === 'string') {
return s.length < n ? s : s.slice(0, n);
} else {
return s;
}
}
function inspect(something) {
if (functionsHaveNames || !util.isFunction(something)) {
return util.inspect(something);
}
var rawname = getName(something);
var name = rawname ? ': ' + rawname : '';
return '[Function' + name + ']';
}
function getMessage(self) {
return truncate(inspect(self.actual), 128) + ' ' +
self.operator + ' ' +
truncate(inspect(self.expected), 128);
}
// At present only the three keys mentioned above are used and
// understood by the spec. Implementations or sub modules can pass
// other keys to the AssertionError's constructor - they will be
// ignored.
// 3. All of the following functions must throw an AssertionError
// when a corresponding condition is not met, with a message that
// may be undefined if not provided. All assertion methods provide
// both the actual and expected values to the assertion error for
// display purposes.
function fail(actual, expected, message, operator, stackStartFunction) {
throw new assert.AssertionError({
message: message,
actual: actual,
expected: expected,
operator: operator,
stackStartFunction: stackStartFunction
});
}
// EXTENSION! allows for well behaved errors defined elsewhere.
assert.fail = fail;
// 4. Pure assertion tests whether a value is truthy, as determined
// by !!guard.
// assert.ok(guard, message_opt);
// This statement is equivalent to assert.equal(true, !!guard,
// message_opt);. To test strictly for the value true, use
// assert.strictEqual(true, guard, message_opt);.
function ok(value, message) {
if (!value) fail(value, true, message, '==', assert.ok);
}
assert.ok = ok;
// 5. The equality assertion tests shallow, coercive equality with
// ==.
// assert.equal(actual, expected, message_opt);
assert.equal = function equal(actual, expected, message) {
if (actual != expected) fail(actual, expected, message, '==', assert.equal);
};
// 6. The non-equality assertion tests for whether two objects are not equal
// with != assert.notEqual(actual, expected, message_opt);
assert.notEqual = function notEqual(actual, expected, message) {
if (actual == expected) {
fail(actual, expected, message, '!=', assert.notEqual);
}
};
// 7. The equivalence assertion tests a deep equality relation.
// assert.deepEqual(actual, expected, message_opt);
assert.deepEqual = function deepEqual(actual, expected, message) {
if (!_deepEqual(actual, expected, false)) {
fail(actual, expected, message, 'deepEqual', assert.deepEqual);
}
};
assert.deepStrictEqual = function deepStrictEqual(actual, expected, message) {
if (!_deepEqual(actual, expected, true)) {
fail(actual, expected, message, 'deepStrictEqual', assert.deepStrictEqual);
}
};
function _deepEqual(actual, expected, strict, memos) {
// 7.1. All identical values are equivalent, as determined by ===.
if (actual === expected) {
return true;
} else if (isBuffer(actual) && isBuffer(expected)) {
return compare(actual, expected) === 0;
// 7.2. If the expected value is a Date object, the actual value is
// equivalent if it is also a Date object that refers to the same time.
} else if (util.isDate(actual) && util.isDate(expected)) {
return actual.getTime() === expected.getTime();
// 7.3 If the expected value is a RegExp object, the actual value is
// equivalent if it is also a RegExp object with the same source and
// properties (`global`, `multiline`, `lastIndex`, `ignoreCase`).
} else if (util.isRegExp(actual) && util.isRegExp(expected)) {
return actual.source === expected.source &&
actual.global === expected.global &&
actual.multiline === expected.multiline &&
actual.lastIndex === expected.lastIndex &&
actual.ignoreCase === expected.ignoreCase;
// 7.4. Other pairs that do not both pass typeof value == 'object',
// equivalence is determined by ==.
} else if ((actual === null || typeof actual !== 'object') &&
(expected === null || typeof expected !== 'object')) {
return strict ? actual === expected : actual == expected;
// If both values are instances of typed arrays, wrap their underlying
// ArrayBuffers in a Buffer each to increase performance
// This optimization requires the arrays to have the same type as checked by
// Object.prototype.toString (aka pToString). Never perform binary
// comparisons for Float*Arrays, though, since e.g. +0 === -0 but their
// bit patterns are not identical.
} else if (isView(actual) && isView(expected) &&
pToString(actual) === pToString(expected) &&
!(actual instanceof Float32Array ||
actual instanceof Float64Array)) {
return compare(new Uint8Array(actual.buffer),
new Uint8Array(expected.buffer)) === 0;
// 7.5 For all other Object pairs, including Array objects, equivalence is
// determined by having the same number of owned properties (as verified
// with Object.prototype.hasOwnProperty.call), the same set of keys
// (although not necessarily the same order), equivalent values for every
// corresponding key, and an identical 'prototype' property. Note: this
// accounts for both named and indexed properties on Arrays.
} else if (isBuffer(actual) !== isBuffer(expected)) {
return false;
} else {
memos = memos || {actual: [], expected: []};
var actualIndex = memos.actual.indexOf(actual);
if (actualIndex !== -1) {
if (actualIndex === memos.expected.indexOf(expected)) {
return true;
}
}
memos.actual.push(actual);
memos.expected.push(expected);
return objEquiv(actual, expected, strict, memos);
}
}
function isArguments(object) {
return Object.prototype.toString.call(object) == '[object Arguments]';
}
function objEquiv(a, b, strict, actualVisitedObjects) {
if (a === null || a === undefined || b === null || b === undefined)
return false;
// if one is a primitive, the other must be same
if (util.isPrimitive(a) || util.isPrimitive(b))
return a === b;
if (strict && Object.getPrototypeOf(a) !== Object.getPrototypeOf(b))
return false;
var aIsArgs = isArguments(a);
var bIsArgs = isArguments(b);
if ((aIsArgs && !bIsArgs) || (!aIsArgs && bIsArgs))
return false;
if (aIsArgs) {
a = pSlice.call(a);
b = pSlice.call(b);
return _deepEqual(a, b, strict);
}
var ka = objectKeys(a);
var kb = objectKeys(b);
var key, i;
// having the same number of owned properties (keys incorporates
// hasOwnProperty)
if (ka.length !== kb.length)
return false;
//the same set of keys (although not necessarily the same order),
ka.sort();
kb.sort();
//~~~cheap key test
for (i = ka.length - 1; i >= 0; i--) {
if (ka[i] !== kb[i])
return false;
}
//equivalent values for every corresponding key, and
//~~~possibly expensive deep test
for (i = ka.length - 1; i >= 0; i--) {
key = ka[i];
if (!_deepEqual(a[key], b[key], strict, actualVisitedObjects))
return false;
}
return true;
}
// 8. The non-equivalence assertion tests for any deep inequality.
// assert.notDeepEqual(actual, expected, message_opt);
assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
if (_deepEqual(actual, expected, false)) {
fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual);
}
};
assert.notDeepStrictEqual = notDeepStrictEqual;
function notDeepStrictEqual(actual, expected, message) {
if (_deepEqual(actual, expected, true)) {
fail(actual, expected, message, 'notDeepStrictEqual', notDeepStrictEqual);
}
}
// 9. The strict equality assertion tests strict equality, as determined by ===.
// assert.strictEqual(actual, expected, message_opt);
assert.strictEqual = function strictEqual(actual, expected, message) {
if (actual !== expected) {
fail(actual, expected, message, '===', assert.strictEqual);
}
};
// 10. The strict non-equality assertion tests for strict inequality, as
// determined by !==. assert.notStrictEqual(actual, expected, message_opt);
assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
if (actual === expected) {
fail(actual, expected, message, '!==', assert.notStrictEqual);
}
};
function expectedException(actual, expected) {
if (!actual || !expected) {
return false;
}
if (Object.prototype.toString.call(expected) == '[object RegExp]') {
return expected.test(actual);
}
try {
if (actual instanceof expected) {
return true;
}
} catch (e) {
// Ignore. The instanceof check doesn't work for arrow functions.
}
if (Error.isPrototypeOf(expected)) {
return false;
}
return expected.call({}, actual) === true;
}
function _tryBlock(block) {
var error;
try {
block();
} catch (e) {
error = e;
}
return error;
}
function _throws(shouldThrow, block, expected, message) {
var actual;
if (typeof block !== 'function') {
throw new TypeError('"block" argument must be a function');
}
if (typeof expected === 'string') {
message = expected;
expected = null;
}
actual = _tryBlock(block);
message = (expected && expected.name ? ' (' + expected.name + ').' : '.') +
(message ? ' ' + message : '.');
if (shouldThrow && !actual) {
fail(actual, expected, 'Missing expected exception' + message);
}
var userProvidedMessage = typeof message === 'string';
var isUnwantedException = !shouldThrow && util.isError(actual);
var isUnexpectedException = !shouldThrow && actual && !expected;
if ((isUnwantedException &&
userProvidedMessage &&
expectedException(actual, expected)) ||
isUnexpectedException) {
fail(actual, expected, 'Got unwanted exception' + message);
}
if ((shouldThrow && actual && expected &&
!expectedException(actual, expected)) || (!shouldThrow && actual)) {
throw actual;
}
}
// 11. Expected to throw an error:
// assert.throws(block, Error_opt, message_opt);
assert.throws = function(block, /*optional*/error, /*optional*/message) {
_throws(true, block, error, message);
};
// EXTENSION! This is annoying to write outside this module.
assert.doesNotThrow = function(block, /*optional*/error, /*optional*/message) {
_throws(false, block, error, message);
};
assert.ifError = function(err) { if (err) throw err; };
var objectKeys = Object.keys || function (obj) {
var keys = [];
for (var key in obj) {
if (hasOwn.call(obj, key)) keys.push(key);
}
return keys;
};
},{"util/":36}],30:[function(require,module,exports){
/**
# lazy-seq
> Lazy sequences
[![Build Status](https://secure.travis-ci.org/phadej/lazy-seq.svg?branch=master)](http://travis-ci.org/phadej/lazy-seq)
[![NPM version](https://badge.fury.io/js/lazy-seq.svg)](http://badge.fury.io/js/lazy-seq)
[![Dependency Status](https://david-dm.org/phadej/lazy-seq.svg)](https://david-dm.org/phadej/lazy-seq)
[![devDependency Status](https://david-dm.org/phadej/lazy-seq/dev-status.svg)](https://david-dm.org/phadej/lazy-seq#info=devDependencies)
[![Code Climate](https://img.shields.io/codeclimate/github/phadej/lazy-seq.svg)](https://codeclimate.com/github/phadej/lazy-seq)
## Lazy?
The list structure could be defined as
```hs
data Seq a = Nil | Cons a (Seq a)
```
The `Cons` constuctor takes two arguments, so there are four different laziness variants:
```hs
Cons (Strict a) (Strict (Seq a)) -- 1. fully strict
Cons (Lazy a) (Strict (Seq a)) -- 2. lazy values
Cons (Strict a) (Lazy (Seq a)) -- 3. lazy structure
Cons (Lazy a) (Lazy (Seq a)) -- 4. fully lazy
```
This module implements the third variant: lazy structure, but strict values.
## Example
```js
var ones = lazyseq.cons(1, function () { return ones; });
console.log(ones === ones.tail()); // true!
```
## Why?
This package is originally made to optimise shrink operations in [jsverify](http://jsverify.github.io/), a property-based testing library.
## API
*/
"use strict";
var assert = require("assert");
/**
- *nil : Seq a* &mdash; Empty sequence.
- *cons : (head : a, tail : Array a | Seq a | () → Array a | () → Seq a) → Seq a* : Cons a value to the front of a sequence (list or thunk).
*/
var nil = {};
/**
- *.isNil : Boolean* &mdash; Constant time check, whether the sequence is empty.
*/
nil.isNil = true;
/**
- *.toString : () → String* &mdash; String representation. Doesn't force the tail.
*/
nil.toString = function () {
return "nil";
};
/**
- *.length : () → Nat* &mdash; Return the length of the sequene. Forces the structure.
*/
nil.length = function () {
return 0;
};
/**
- *.toArray : () → Array a* &mdash; Convert the sequence to JavaScript array.
*/
nil.toArray = function nilToArray() {
return [];
};
/**
- *.fold : (z : b, f : (a, () → b) → b) → b* &mdash; Fold from right.
```hs
fold nil x f = x
fold (cons h t) x f = f x (fold t x f)
```
*/
nil.fold = function nilFold(x /*, f */) {
return x;
};
/**
- *.head : () → a* &mdash; Extract the first element of a sequence, which must be non-empty.
*/
nil.head = function nilHead() {
throw new Error("nil.head");
};
/**
- *.tail : () → Seq a* &mdash; Return the tail of the sequence.
```hs
tail nil = nil
tail (cons h t) = t
```
*/
nil.tail = function nilTail() {
return nil;
};
/**
- *.nth : (n : Nat) → a* &mdash; Return nth value of the sequence.
*/
nil.nth = function nilNth(n) {
assert(typeof n === "number");
throw new Error("Can't get " + n + "th value of the nil");
};
/**
- *.take : (n : Nat) → Seq a* &mdash; Take `n` first elements of the sequence.
*/
nil.take = function (n) {
assert(typeof n === "number");
return nil;
};
/**
- *.drop : (n : Nat) → Seq a* &mdash; Drop `n` first elements of the sequence.
*/
nil.drop = function (n) {
assert(typeof n === "number");
return nil;
};
/**
- *.map : (f : a → b) : Seq b* &mdash; The sequence obtained by applying `f` to each element of the original sequence.
*/
nil.map = function (f) {
assert(typeof f === "function");
return nil;
};
/**
- *.append : (ys : Seq a | Array a) : Seq a* &mdash; Append `ys` sequence.
*/
nil.append = function (seq) {
if (typeof seq === "function") {
seq = seq();
}
if (Array.isArray(seq)) {
/* eslint-disable no-use-before-define */
return fromArray(seq);
/* eslint-enable no-use-before-define */
} else {
return seq;
}
};
/**
- *.filter : (p : a -> bool) : Seq a* &mdash; filter using `p` predicate.
*/
nil.filter = function () {
return nil;
};
/**
- *.every : (p = identity: a -> b) : b | true &mdash; return first falsy value in the sequence, true otherwise. *N.B.* behaves slightly differently from `Array::every`.
*/
nil.every = function () {
return true;
};
/**
- *.some : (p = identity: a -> b) : b | false &mdash; return first truthy value in the sequence, false otherwise. *N.B.* behaves slightly differently from `Array::some`.
*/
nil.some = function () {
return false;
};
/**
- *.contains : (x : a) : bool &mdash; Returns `true` if `x` is in the sequence.
*/
nil.contains = function () {
return false;
};
/**
- *.containsNot : (x : a) : bool &mdash; Returns `true` if `x` is not in the sequence.
*/
nil.containsNot = function () {
return true;
};
// Default cons values are with strict semantics
function Cons(head, tail) {
this.headValue = head;
this.tailValue = tail;
}
Cons.prototype.isNil = false;
Cons.prototype.toString = function () {
return "Cons(" + this.headValue + ", " + this.tailValue + ")";
};
Cons.prototype.length = function () {
return 1 + this.tail().length();
};
Cons.prototype.toArray = function () {
var ptr = this;
var acc = [];
while (ptr !== nil) {
acc.push(ptr.headValue);
ptr = ptr.tail();
}
return acc;
};
Cons.prototype.fold = function consFold(x, f) {
var self = this;
return f(this.headValue, function () {
return self.tail().fold(x, f);
});
};
Cons.prototype.head = function consHead() {
return this.headValue;
};
Cons.prototype.tail = function consTail() {
return this.tailValue;
};
// But when cons is created, it's overloaded with lazy ones
// Force tail to whnf.
function lazyConsForce() {
/* jshint validthis:true */
var val = this.tailFn();
/* eslint-disable no-use-before-define */
this.tailValue = Array.isArray(val) ? fromArray(val) : val;
/* eslint-enable no-use-before-define */
delete this.tail;
delete this.force;
return this;
}
function lazyConsTail() {
/* jshint validthis:true */
this.force();
return this.tailValue;
}
function delay(head, tail) {
assert(typeof tail === "function");
head.tailFn = tail;
head.tail = lazyConsTail;
head.force = lazyConsForce;
return head;
}
function cons(head, tail) {
if (typeof tail === "function") {
return delay(new Cons(head), tail);
} else if (Array.isArray(tail)) {
return delay(cons(head), function () {
/* eslint-disable no-use-before-define */
return fromArray(tail);
/* eslint-enable no-use-before-define */
});
} else {
return new Cons(head, tail);
}
}
// Rest of the functions. They might use cons
Cons.prototype.nth = function consNth(n) {
assert(typeof n === "number");
return n === 0 ? this.headValue : this.tail().nth(n - 1);
};
Cons.prototype.take = function consTake(n) {
assert(typeof n === "number");
var that = this;
return n === 0 ? nil : cons(this.headValue, function () {
return that.tail().take(n - 1);
});
};
Cons.prototype.drop = function consDrop(n) {
assert(typeof n === "number");
return n === 0 ? this : this.tail().drop(n - 1);
};
Cons.prototype.map = function consMap(f) {
assert(typeof f === "function");
var that = this;
return cons(f(that.headValue), function () {
return that.tail().map(f);
});
};
Cons.prototype.append = function consAppend(seq) {
// Short circuit decidable: (++ []) ≡ id
if (seq === nil || (Array.isArray(seq) && seq.length === 0)) {
return this;
}
var that = this;
return cons(that.headValue, function () {
return that.tail().append(seq);
});
};
Cons.prototype.filter = function consFilter(p) {
assert(typeof p === "function");
var that = this;
if (p(that.headValue)) {
return cons(that.headValue, function () {
return that.tail().filter(p);
});
} else {
return that.tail().filter(p);
}
};
Cons.prototype.every = function consEvery(p) {
p = p || function (x) { return x; };
assert(typeof p === "function");
var that = this;
var pHead = p(that.headValue);
if (!pHead) {
return pHead;
} else {
return that.tail().every(p);
}
};
Cons.prototype.some = function consSome(p) {
p = p || function (x) { return x; };
assert(typeof p === "function");
var that = this;
var pHead = p(that.headValue);
if (pHead) {
return pHead;
} else {
return that.tail().some(p);
}
};
Cons.prototype.contains = function consContains(x) {
var that = this;
if (x === that.headValue) {
return true;
} else {
return that.tail().contains(x);
}
};
Cons.prototype.containsNot = function consContainsNot(x) {
var that = this;
if (x === that.headValue) {
return false;
} else {
return that.tail().containsNot(x);
}
};
// Constructors
/**
- *fromArray: (arr : Array a) → Seq a* &mdash; Convert a JavaScript array into lazy sequence.
*/
function fromArrayIter(arr, n) {
if (n < arr.length) {
return cons(arr[n], function () {
return fromArrayIter(arr, n + 1);
});
} else {
return nil;
}
}
function fromArray(arr) {
assert(Array.isArray(arr));
return fromArrayIter(arr, 0);
}
/**
- *singleton: (x : a) → Seq a* &mdash; Create a singleton sequence.
*/
function singleton(x) {
return fromArray([x]);
}
/**
- *append : (xs... : Array a | Seq a | () → Array a | () → Seq a) → Seq a* : Append one sequence-like to another.
*/
function append() {
var acc = nil;
for (var i = 0; i < arguments.length; i++) {
acc = acc.append(arguments[i]);
}
return acc;
}
/**
- *iterate : (x : a, f : a → a) → Seq a* &mdash; Create an infinite sequence of repeated applications of `f` to `x`: *x, f(x), f(f(x))&hellip;*.
*/
function iterate(x, f) {
return cons(x, function () {
return iterate(f(x), f);
});
}
/**
- *fold : (seq : Seq a | Array a, z : b, f : (a, () → b) → b) : b* &mdash; polymorphic version of fold. Works with arrays too.
*/
function listFold(list, z, f, n) {
if (n < list.length) {
return f(list[n], function () {
return listFold(list, z, f, n + 1);
});
} else {
return z;
}
}
function fold(list, z, f) {
if (Array.isArray(list)) {
return listFold(list, z, f, 0);
} else {
return list.fold(z, f);
}
}
module.exports = {
nil: nil,
cons: cons,
append: append,
fromArray: fromArray,
singleton: singleton,
iterate: iterate,
fold: fold,
};
/// plain CHANGELOG.md
/// plain CONTRIBUTING.md
},{"assert":29}],31:[function(require,module,exports){
"use strict";
// Based on RC4 algorithm, as described in
// http://en.wikipedia.org/wiki/RC4
function isInteger(n) {
return parseInt(n, 10) === n;
}
function createRC4(N) {
function identityPermutation() {
var s = new Array(N);
for (var i = 0; i < N; i++) {
s[i] = i;
}
return s;
}
// :: string | array integer -> array integer
function seed(key) {
if (key === undefined) {
key = new Array(N);
for (var k = 0; k < N; k++) {
key[k] = Math.floor(Math.random() * N);
}
} else if (typeof key === "string") {
// to string
key = "" + key;
key = key.split("").map(function (c) { return c.charCodeAt(0) % N; });
} else if (Array.isArray(key)) {
if (!key.every(function (v) {
return typeof v === "number" && v === (v | 0);
})) {
throw new TypeError("invalid seed key specified: not array of integers");
}
} else {
throw new TypeError("invalid seed key specified");
}
var keylen = key.length;
// resed state
var s = identityPermutation();
var j = 0;
for (var i = 0; i < N; i++) {
j = (j + s[i] + key[i % keylen]) % N;
var tmp = s[i];
s[i] = s[j];
s[j] = tmp;
}
return s;
}
/* eslint-disable no-shadow */
function RC4(key) {
this.s = seed(key);
this.i = 0;
this.j = 0;
}
/* eslint-enable no-shadow */
RC4.prototype.randomNative = function () {
this.i = (this.i + 1) % N;
this.j = (this.j + this.s[this.i]) % N;
var tmp = this.s[this.i];
this.s[this.i] = this.s[this.j];
this.s[this.j] = tmp;
var k = this.s[(this.s[this.i] + this.s[this.j]) % N];
return k;
};
RC4.prototype.randomUInt32 = function () {
var a = this.randomByte();
var b = this.randomByte();
var c = this.randomByte();
var d = this.randomByte();
return ((a * 256 + b) * 256 + c) * 256 + d;
};
RC4.prototype.randomFloat = function () {
return this.randomUInt32() / 0x100000000;
};
RC4.prototype.random = function () {
var a;
var b;
if (arguments.length === 1) {
a = 0;
b = arguments[0];
} else if (arguments.length === 2) {
a = arguments[0];
b = arguments[1];
} else {
throw new TypeError("random takes one or two integer arguments");
}
if (!isInteger(a) || !isInteger(b)) {
throw new TypeError("random takes one or two integer arguments");
}
return a + this.randomUInt32() % (b - a + 1);
};
RC4.prototype.currentState = function () {
return {
i: this.i,
j: this.j,
s: this.s.slice(), // copy
};
};
RC4.prototype.setState = function (state) {
var s = state.s;
var i = state.i;
var j = state.j;
/* eslint-disable yoda */
if (!(i === (i | 0) && 0 <= i && i < N)) {
throw new Error("state.i should be integer [0, " + (N - 1) + "]");
}
if (!(j === (j | 0) && 0 <= j && j < N)) {
throw new Error("state.j should be integer [0, " + (N - 1) + "]");
}
/* eslint-enable yoda */
// check length
if (!Array.isArray(s) || s.length !== N) {
throw new Error("state should be array of length " + N);
}
// check that all params are there
for (var k = 0; k < N; k++) {
if (s.indexOf(k) === -1) {
throw new Error("state should be permutation of 0.." + (N - 1) + ": " + k + " is missing");
}
}
this.i = i;
this.j = j;
this.s = s.slice(); // assign copy
};
return RC4;
}
var RC4 = createRC4(256);
RC4.prototype.randomByte = RC4.prototype.randomNative;
var RC4small = createRC4(16);
RC4small.prototype.randomByte = function () {
var a = this.randomNative();
var b = this.randomNative();
return a * 16 + b;
};
var ordA = "a".charCodeAt(0);
var ord0 = "0".charCodeAt(0);
function toHex(n) {
return n < 10 ? String.fromCharCode(ord0 + n) : String.fromCharCode(ordA + n - 10);
}
function fromHex(c) {
return parseInt(c, 16);
}
RC4small.prototype.currentStateString = function () {
var state = this.currentState();
var i = toHex(state.i);
var j = toHex(state.j);
var res = i + j + state.s.map(toHex).join("");
return res;
};
RC4small.prototype.setStateString = function (stateString) {
if (!stateString.match(/^[0-9a-f]{18}$/)) {
throw new TypeError("RC4small stateString should be 18 hex character string");
}
var i = fromHex(stateString[0]);
var j = fromHex(stateString[1]);
var s = stateString.split("").slice(2).map(fromHex);
this.setState({
i: i,
j: j,
s: s,
});
};
RC4.RC4small = RC4small;
module.exports = RC4;
},{}],32:[function(require,module,exports){
"use strict";
/**
# trampa
Trampolines, to emulate tail-call recursion.
[![Build Status](https://secure.travis-ci.org/phadej/trampa.svg?branch=master)](http://travis-ci.org/phadej/trampa)
[![NPM version](https://badge.fury.io/js/trampa.svg)](http://badge.fury.io/js/trampa)
[![Dependency Status](https://david-dm.org/trampa/trampa.svg)](https://david-dm.org/trampa/trampa)
[![devDependency Status](https://david-dm.org/trampa/trampa/dev-status.svg)](https://david-dm.org/trampa/trampa#info=devDependencies)
[![Code Climate](https://img.shields.io/codeclimate/github/phadej/trampa.svg)](https://codeclimate.com/github/phadej/trampa)
## Synopsis
```js
var trampa = require("trampa");
function loop(n, acc) {
return n === 0 ? trampa.wrap(acc) : trampa.lazy(function () {
return loop(n - 1, acc + 1);
});
}
loop(123456789, 0).run(); // doesn't cause stack overflow!
```
## API
*/
// loosely based on https://apocalisp.wordpress.com/2011/10/26/tail-call-elimination-in-scala-monads/
var assert = require("assert");
function Done(x) {
this.x = x;
}
function Cont(tramp, cont) {
assert(typeof cont === "function");
this.tramp = tramp;
this.cont = cont;
}
/**
- `isTrampoline(t: obj): bool` &mdash; Returns, whether `t` is a trampolined object.
*/
function isTrampoline(t) {
return t instanceof Done || t instanceof Cont;
}
/**
- `wrap(t: Trampoline a | a): Trampoline a` &mdash; Wrap `t` into trampoline, if it's not already one.
*/
function wrap(t) {
return isTrampoline(t) ? t : new Done(t);
}
/**
- `lazy(t : () -> Trampoline a | a)` &mdash; Wrap lazy computation into trampoline. Useful when constructing computations.
*/
function lazy(computation) {
assert(typeof computation === "function", "lazy: computation should be function");
return wrap().jump(computation);
}
/**
- `Trampoline.jump(f : a -> b | Trampoline b)` &mdash; *map* or *flatmap* trampoline computation. Like `.then` for promises.
*/
Done.prototype.jump = function (f) {
return new Cont(this, function (x) {
return wrap(f(x));
});
};
Cont.prototype.jump = Done.prototype.jump;
function execute(curr, params) {
params = params || {};
var debug = params.debug || false;
var log = params.log || console.log;
var stack = [];
while (true) { // eslint-disable-line no-constant-condition
if (debug) {
log("trampoline execute: stack size " + stack.length);
}
if (curr instanceof Done) {
if (stack.length === 0) {
return curr.x;
} else {
curr = stack[stack.length - 1](curr.x);
stack.pop();
}
} else {
assert(curr instanceof Cont);
stack.push(curr.cont);
curr = curr.tramp;
}
}
}
/**
- `Trampoline.run(): a` &mdash; Run the trampoline synchronously resulting a value.
*/
Done.prototype.run = Cont.prototype.run = function (params) {
return execute(this, params);
};
module.exports = {
isTrampoline: isTrampoline,
wrap: wrap,
lazy: lazy,
};
/**
## Changelog
- **1.0.0** &mdash; *2015-07-14* &mdash; Initial release
*/
},{"assert":29}],33:[function(require,module,exports){
/**
# typify type parser
> Type signature parser for typify
[![Build Status](https://secure.travis-ci.org/phadej/typify-parser.svg?branch=master)](http://travis-ci.org/phadej/typify-parser)
[![NPM version](https://badge.fury.io/js/typify-parser.svg)](http://badge.fury.io/js/typify-parser)
[![Dependency Status](https://david-dm.org/phadej/typify-parser.svg)](https://david-dm.org/phadej/typify-parser)
[![devDependency Status](https://david-dm.org/phadej/typify-parser/dev-status.svg)](https://david-dm.org/phadej/typify-parser#info=devDependencies)
[![Code Climate](https://img.shields.io/codeclimate/github/phadej/typify-parser.svg)](https://codeclimate.com/github/phadej/typify-parser)
Turns `(foo, bar 42) -> quux` into
```js
{
"type": "function",
"arg": {
"type": "product",
"args": [
{
"type": "ident",
"value": "foo"
},
{
"type": "application",
"callee": {
"type": "ident",
"value": "bar"
},
"args": [
{
"type": "number",
"value": 42
}
]
}
]
},
"result": {
"type": "ident",
"value": "quux"
}
}
```
## Synopsis
```js
var parser = require("typify-parser");
// Example from above
var t = parser("(foo, bar 42) -> quux");
// Free vars
p.freeVars(t); // ['bar', 'foo', 'quux']
p.freeVars(p("rec list -> () | a & list")) // ['a']
```
*/
"use strict";
function unescapeString(str) {
return str.replace(/\\(?:'|"|\\|n|x[0-9a-fA-F]{2})/g, function (match) {
switch (match[1]) {
case "'": return "'";
case "\"": return "\"";
case "\\": return "\\";
case "n": return "\n";
case "x": return String.fromCharCode(parseInt(match.substr(2), 16));
}
});
}
function lex(input) {
// Unicode
// top: 22a4
// bottom: 22a5
// and: 2227
// or: 2228
// times: \u00d7
// to: 2192
// ellipsis: 2026
// blackboard 1: d835 dfd9
var m = input.match(/^([ \t\r\n]+|[\u22a4\u22a5\u2227\u2228\u00d7\u2192\u2026]|\ud835\udfd9|_\|_|\*|\(\)|"(?:[^"\\]|\\[\\'"n]|\\x[0-9a-fA-F]{2})*"|'(?:[^'\\]|\\[\\'"n]|\\x[0-9a-fA-F]{2})*'|[0-9a-zA-Z_\$@]+|,|->|:|;|&|\||\.\.\.|\(|\)|\[|\]|\{|\}|\?)*$/);
if (m === null) {
throw new SyntaxError("Cannot lex type signature");
}
m = input.match(/([ \t\r\n]+|[\u22a4\u22a5\u2227\u2228\u00d7\u2192\u2026]|\ud835\udfd9|_\|_|\*|\(\)|"(?:[^"\\]|\\[\\'"n]|\\x[0-9a-fA-F]{2})*"|'(?:[^'\\]|\\[\\'"n]|\\x[0-9a-fA-F]{2})*'|[0-9a-zA-Z_\$@]+|,|->|:|;|&|\||\.\.\.|\(|\)|\[|\]|\{|\}|\?)/g);
return m
.map(function (token) {
switch (token) {
case "_|_": return { type: "false" };
case "\u22a5": return { type: "false" };
case "*": return { type: "true" };
case "\u22a4": return { type: "true" };
case "()": return { type: "unit" };
case "\ud835\udfd9": return { type: "unit" };
case "true": return { type: "bool", value: true };
case "false": return { type: "bool", value: false };
case "rec": return { type: "rec" };
case "&": return { type: "&" };
case "\u2227": return { type: "&" };
case "|": return { type: "|" };
case "\u2228": return { type: "|" };
case ",": return { type: "," };
case "\u00d7": return { type: "," };
case ";": return { type: ";" };
case ":": return { type: ":" };
case "(": return { type: "(" };
case ")": return { type: ")" };
case "[": return { type: "[" };
case "]": return { type: "]" };
case "{": return { type: "{" };
case "}": return { type: "}" };
case "?": return { type: "?" };
case "->": return { type: "->" };
case "\u2192": return { type: "->" };
case "...": return { type: "..." };
case "\u2026": return { type: "..." };
}
// Whitespace
if (token.match(/^[ \r\r\n]+$/)) {
return null;
}
if (token.match(/^[0-9]+/)) {
return { type: "number", value: parseInt(token, 10) };
}
if (token[0] === "'" || token[0] === "\"") {
token = token.slice(1, -1);
return { type: "string", value: unescapeString(token) };
}
return { type: "ident", value: token };
})
.filter(function (token) {
return token !== null;
});
}
function makePunctParser(type) {
return function (state) {
if (state.pos >= state.len) {
throw new SyntaxError("Expecting identifier, end-of-input found");
}
var token = state.tokens[state.pos];
if (token.type !== type) {
throw new SyntaxError("Expecting '" + type + "', found: " + token.type);
}
state.pos += 1;
return type;
};
}
var colonParser = makePunctParser(":");
var openCurlyParser = makePunctParser("{");
var closeCurlyParser = makePunctParser("}");
var semicolonParser = makePunctParser(";");
var openParenParser = makePunctParser("(");
var closeParenParser = makePunctParser(")");
var openBracketParser = makePunctParser("[");
var closeBracketParser = makePunctParser("]");
var recKeywordParser = makePunctParser("rec");
var arrowParser = makePunctParser("->");
function nameParser(state) {
if (state.pos >= state.len) {
throw new SyntaxError("Expecting identifier, end-of-input found");
}
var token = state.tokens[state.pos];
if (token.type !== "ident") {
throw new SyntaxError("Expecting 'ident', found: " + token.type);
}
state.pos += 1;
return token.value;
}
function recursiveParser(state) {
recKeywordParser(state);
var name = nameParser(state);
arrowParser(state);
var value = typeParser(state); // eslint-disable-line no-use-before-define
return {
type: "recursive",
name: name,
arg: value,
};
}
function recordParser(state) {
openCurlyParser(state);
var token = state.tokens[state.pos];
if (token && token.type === "}") {
closeCurlyParser(state);
return { type: "record", fields: {} };
}
var fields = {};
while (true) { // eslint-disable-line no-constant-condition
// read
var name = nameParser(state);
colonParser(state);
var value = typeParser(state); // eslint-disable-line no-use-before-define
// assign to fields
fields[name] = value;
// ending token
token = state.tokens[state.pos];
// break if }
if (token && token.type === "}") {
closeCurlyParser(state);
break;
} else if (token && token.type === ";") {
semicolonParser(state);
} else {
throw new SyntaxError("Expecting '}' or ';', found: " + token.type);
}
}
return { type: "record", fields: fields };
}
function postfix(parser, postfixToken, constructor) {
return function (state) {
var arg = parser(state);
var token = state.tokens[state.pos];
if (token && token.type === postfixToken) {
state.pos += 1;
return {
type: constructor,
arg: arg,
};
} else {
return arg;
}
};
}
// this ties the knot
var optionalParser = postfix(terminalParser, "?", "optional"); // eslint-disable-line no-use-before-define
function applicationParser(state) {
var rator = optionalParser(state);
var rands = [];
while (true) { // eslint-disable-line no-constant-condition
var pos = state.pos;
// XXX: we shouldn't use exceptions for this
try {
var arg = optionalParser(state);
rands.push(arg);
} catch (err) {
state.pos = pos;
break;
}
}
if (rands.length === 0) {
return rator;
} else {
return {
type: "application",
callee: rator,
args: rands,
};
}
}
function separatedBy(parser, separator, constructor) {
return function (state) {
var list = [parser(state)];
while (true) { // eslint-disable-line no-constant-condition
// separator
var token = state.tokens[state.pos];
if (token && token.type === separator) {
state.pos += 1;
} else {
break;
}
// right argument
list.push(parser(state));
}
if (list.length === 1) {
return list[0];
} else {
return {
type: constructor,
args: list,
};
}
};
}
var conjunctionParser = separatedBy(applicationParser, "&", "conjunction");
var disjunctionParser = separatedBy(conjunctionParser, "|", "disjunction");
// TODO: combine with optional
var variadicParser = postfix(disjunctionParser, "...", "variadic");
function namedParser(state) {
var token1 = state.tokens[state.pos];
var token2 = state.tokens[state.pos + 1];
if (token1 && token2 && token1.type === "ident" && token2.type === ":") {
state.pos += 2;
var arg = namedParser(state);
return {
type: "named",
name: token1.value,
arg: arg,
};
} else {
return variadicParser(state);
}
}
var productParser = separatedBy(namedParser, ",", "product");
function functionParser(state) {
var v = productParser(state);
var token = state.tokens[state.pos];
if (token && token.type === "->") {
state.pos += 1;
var result = functionParser(state);
return {
type: "function",
arg: v,
result: result,
};
} else {
return v;
}
}
function typeParser(state) {
return functionParser(state);
}
function parenthesesParser(state) {
openParenParser(state);
var type = typeParser(state);
closeParenParser(state);
return type;
}
function bracketParser(state) {
openBracketParser(state);
var type = typeParser(state);
closeBracketParser(state);
return {
type: "brackets",
arg: type,
};
}
function terminalParser(state) {
if (state.pos >= state.len) {
throw new SyntaxError("Expecting terminal, end-of-input found");
}
var token = state.tokens[state.pos];
switch (token.type) {
case "false":
case "true":
case "unit":
case "string":
case "number":
case "bool":
case "ident":
state.pos += 1;
return token;
case "{":
return recordParser(state);
case "(":
return parenthesesParser(state);
case "[":
return bracketParser(state);
case "rec":
return recursiveParser(state);
default:
throw new SyntaxError("Expecting terminal, " + token.type + " found");
}
}
function parse(input) {
// console.log(input);
var tokens = lex(input);
// console.log(tokens);
var state = {
pos: 0,
len: tokens.length,
tokens: tokens,
};
var res = typeParser(state);
// console.log(state);
if (state.pos !== state.len) {
throw new SyntaxError("expecting end-of-input, " + tokens[state.pos].type + " found");
}
return res;
}
function recordFreeVars(fields) {
var res = [];
for (var k in fields) {
var t = fields[k];
res = res.concat(freeVarsImpl(t)); // eslint-disable-line no-use-before-define
}
return res;
}
function concatFreeVars(ts) {
var res = [];
for (var i = 0; i < ts.length; i++) {
var t = ts[i];
res = res.concat(freeVarsImpl(t)); // eslint-disable-line no-use-before-define
}
return res;
}
function freeVarsImpl(t) {
switch (t.type) {
case "false":
case "true":
case "unit":
case "string":
case "number":
case "bool":
return [];
case "ident": return [t.value];
case "record": return recordFreeVars(t.fields);
case "named": return freeVarsImpl(t.arg);
case "conjunction": return concatFreeVars(t.args);
case "disjunction": return concatFreeVars(t.args);
case "product": return concatFreeVars(t.args);
case "recursive": return freeVarsImpl(t.arg).filter(function (n) {
return n !== t.name;
});
case "optional": return freeVarsImpl(t.arg);
case "brackets": return freeVarsImpl(t.arg);
case "variadic": return freeVarsImpl(t.arg);
case "application": return freeVarsImpl(t.callee).concat(concatFreeVars(t.args));
case "function": return freeVarsImpl(t.arg).concat(freeVarsImpl(t.result));
//default: throw new Error("Unknown type " + t.type);
}
}
function uniq(arr) {
var res = [];
for (var i = 0; i < arr.length; i++) {
var x = arr[i];
if (res.indexOf(x) === -1) {
res.push(x);
}
}
return res;
}
function freeVars(t) {
var fvs = freeVarsImpl(t);
fvs.sort();
return uniq(fvs);
}
parse.freeVars = freeVars;
module.exports = parse;
},{}],34:[function(require,module,exports){
if (typeof Object.create === 'function') {
// implementation from standard node.js 'util' module
module.exports = function inherits(ctor, superCtor) {
ctor.super_ = superCtor
ctor.prototype = Object.create(superCtor.prototype, {
constructor: {
value: ctor,
enumerable: false,
writable: true,
configurable: true
}
});
};
} else {
// old school shim for old browsers
module.exports = function inherits(ctor, superCtor) {
ctor.super_ = superCtor
var TempCtor = function () {}
TempCtor.prototype = superCtor.prototype
ctor.prototype = new TempCtor()
ctor.prototype.constructor = ctor
}
}
},{}],35:[function(require,module,exports){
module.exports = function isBuffer(arg) {
return arg && typeof arg === 'object'
&& typeof arg.copy === 'function'
&& typeof arg.fill === 'function'
&& typeof arg.readUInt8 === 'function';
}
},{}],36:[function(require,module,exports){
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
var formatRegExp = /%[sdj%]/g;
exports.format = function(f) {
if (!isString(f)) {
var objects = [];
for (var i = 0; i < arguments.length; i++) {
objects.push(inspect(arguments[i]));
}
return objects.join(' ');
}
var i = 1;
var args = arguments;
var len = args.length;
var str = String(f).replace(formatRegExp, function(x) {
if (x === '%%') return '%';
if (i >= len) return x;
switch (x) {
case '%s': return String(args[i++]);
case '%d': return Number(args[i++]);
case '%j':
try {
return JSON.stringify(args[i++]);
} catch (_) {
return '[Circular]';
}
default:
return x;
}
});
for (var x = args[i]; i < len; x = args[++i]) {
if (isNull(x) || !isObject(x)) {
str += ' ' + x;
} else {
str += ' ' + inspect(x);
}
}
return str;
};
// Mark that a method should not be used.
// Returns a modified function which warns once by default.
// If --no-deprecation is set, then it is a no-op.
exports.deprecate = function(fn, msg) {
// Allow for deprecating things in the process of starting up.
if (isUndefined(global.process)) {
return function() {
return exports.deprecate(fn, msg).apply(this, arguments);
};
}
if (process.noDeprecation === true) {
return fn;
}
var warned = false;
function deprecated() {
if (!warned) {
if (process.throwDeprecation) {
throw new Error(msg);
} else if (process.traceDeprecation) {
console.trace(msg);
} else {
console.error(msg);
}
warned = true;
}
return fn.apply(this, arguments);
}
return deprecated;
};
var debugs = {};
var debugEnviron;
exports.debuglog = function(set) {
if (isUndefined(debugEnviron))
debugEnviron = process.env.NODE_DEBUG || '';
set = set.toUpperCase();
if (!debugs[set]) {
if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
var pid = process.pid;
debugs[set] = function() {
var msg = exports.format.apply(exports, arguments);
console.error('%s %d: %s', set, pid, msg);
};
} else {
debugs[set] = function() {};
}
}
return debugs[set];
};
/**
* Echos the value of a value. Trys to print the value out
* in the best way possible given the different types.
*
* @param {Object} obj The object to print out.
* @param {Object} opts Optional options object that alters the output.
*/
/* legacy: obj, showHidden, depth, colors*/
function inspect(obj, opts) {
// default options
var ctx = {
seen: [],
stylize: stylizeNoColor
};
// legacy...
if (arguments.length >= 3) ctx.depth = arguments[2];
if (arguments.length >= 4) ctx.colors = arguments[3];
if (isBoolean(opts)) {
// legacy...
ctx.showHidden = opts;
} else if (opts) {
// got an "options" object
exports._extend(ctx, opts);
}
// set default options
if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
if (isUndefined(ctx.depth)) ctx.depth = 2;
if (isUndefined(ctx.colors)) ctx.colors = false;
if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
if (ctx.colors) ctx.stylize = stylizeWithColor;
return formatValue(ctx, obj, ctx.depth);
}
exports.inspect = inspect;
// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
inspect.colors = {
'bold' : [1, 22],
'italic' : [3, 23],
'underline' : [4, 24],
'inverse' : [7, 27],
'white' : [37, 39],
'grey' : [90, 39],
'black' : [30, 39],
'blue' : [34, 39],
'cyan' : [36, 39],
'green' : [32, 39],
'magenta' : [35, 39],
'red' : [31, 39],
'yellow' : [33, 39]
};
// Don't use 'blue' not visible on cmd.exe
inspect.styles = {
'special': 'cyan',
'number': 'yellow',
'boolean': 'yellow',
'undefined': 'grey',
'null': 'bold',
'string': 'green',
'date': 'magenta',
// "name": intentionally not styling
'regexp': 'red'
};
function stylizeWithColor(str, styleType) {
var style = inspect.styles[styleType];
if (style) {
return '\u001b[' + inspect.colors[style][0] + 'm' + str +
'\u001b[' + inspect.colors[style][1] + 'm';
} else {
return str;
}
}
function stylizeNoColor(str, styleType) {
return str;
}
function arrayToHash(array) {
var hash = {};
array.forEach(function(val, idx) {
hash[val] = true;
});
return hash;
}
function formatValue(ctx, value, recurseTimes) {
// Provide a hook for user-specified inspect functions.
// Check that value is an object with an inspect function on it
if (ctx.customInspect &&
value &&
isFunction(value.inspect) &&
// Filter out the util module, it's inspect function is special
value.inspect !== exports.inspect &&
// Also filter out any prototype objects using the circular check.
!(value.constructor && value.constructor.prototype === value)) {
var ret = value.inspect(recurseTimes, ctx);
if (!isString(ret)) {
ret = formatValue(ctx, ret, recurseTimes);
}
return ret;
}
// Primitive types cannot have properties
var primitive = formatPrimitive(ctx, value);
if (primitive) {
return primitive;
}
// Look up the keys of the object.
var keys = Object.keys(value);
var visibleKeys = arrayToHash(keys);
if (ctx.showHidden) {
keys = Object.getOwnPropertyNames(value);
}
// IE doesn't make error fields non-enumerable
// http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
if (isError(value)
&& (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {
return formatError(value);
}
// Some type of object without properties can be shortcutted.
if (keys.length === 0) {
if (isFunction(value)) {
var name = value.name ? ': ' + value.name : '';
return ctx.stylize('[Function' + name + ']', 'special');
}
if (isRegExp(value)) {
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
}
if (isDate(value)) {
return ctx.stylize(Date.prototype.toString.call(value), 'date');
}
if (isError(value)) {
return formatError(value);
}
}
var base = '', array = false, braces = ['{', '}'];
// Make Array say that they are Array
if (isArray(value)) {
array = true;
braces = ['[', ']'];
}
// Make functions say that they are functions
if (isFunction(value)) {
var n = value.name ? ': ' + value.name : '';
base = ' [Function' + n + ']';
}
// Make RegExps say that they are RegExps
if (isRegExp(value)) {
base = ' ' + RegExp.prototype.toString.call(value);
}
// Make dates with properties first say the date
if (isDate(value)) {
base = ' ' + Date.prototype.toUTCString.call(value);
}
// Make error with message first say the error
if (isError(value)) {
base = ' ' + formatError(value);
}
if (keys.length === 0 && (!array || value.length == 0)) {
return braces[0] + base + braces[1];
}
if (recurseTimes < 0) {
if (isRegExp(value)) {
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
} else {
return ctx.stylize('[Object]', 'special');
}
}
ctx.seen.push(value);
var output;
if (array) {
output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
} else {
output = keys.map(function(key) {
return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
});
}
ctx.seen.pop();
return reduceToSingleString(output, base, braces);
}
function formatPrimitive(ctx, value) {
if (isUndefined(value))
return ctx.stylize('undefined', 'undefined');
if (isString(value)) {
var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
.replace(/'/g, "\\'")
.replace(/\\"/g, '"') + '\'';
return ctx.stylize(simple, 'string');
}
if (isNumber(value))
return ctx.stylize('' + value, 'number');
if (isBoolean(value))
return ctx.stylize('' + value, 'boolean');
// For some reason typeof null is "object", so special case here.
if (isNull(value))
return ctx.stylize('null', 'null');
}
function formatError(value) {
return '[' + Error.prototype.toString.call(value) + ']';
}
function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
var output = [];
for (var i = 0, l = value.length; i < l; ++i) {
if (hasOwnProperty(value, String(i))) {
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
String(i), true));
} else {
output.push('');
}
}
keys.forEach(function(key) {
if (!key.match(/^\d+$/)) {
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
key, true));
}
});
return output;
}
function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
var name, str, desc;
desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
if (desc.get) {
if (desc.set) {
str = ctx.stylize('[Getter/Setter]', 'special');
} else {
str = ctx.stylize('[Getter]', 'special');
}
} else {
if (desc.set) {
str = ctx.stylize('[Setter]', 'special');
}
}
if (!hasOwnProperty(visibleKeys, key)) {
name = '[' + key + ']';
}
if (!str) {
if (ctx.seen.indexOf(desc.value) < 0) {
if (isNull(recurseTimes)) {
str = formatValue(ctx, desc.value, null);
} else {
str = formatValue(ctx, desc.value, recurseTimes - 1);
}
if (str.indexOf('\n') > -1) {
if (array) {
str = str.split('\n').map(function(line) {
return ' ' + line;
}).join('\n').substr(2);
} else {
str = '\n' + str.split('\n').map(function(line) {
return ' ' + line;
}).join('\n');
}
}
} else {
str = ctx.stylize('[Circular]', 'special');
}
}
if (isUndefined(name)) {
if (array && key.match(/^\d+$/)) {
return str;
}
name = JSON.stringify('' + key);
if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
name = name.substr(1, name.length - 2);
name = ctx.stylize(name, 'name');
} else {
name = name.replace(/'/g, "\\'")
.replace(/\\"/g, '"')
.replace(/(^"|"$)/g, "'");
name = ctx.stylize(name, 'string');
}
}
return name + ': ' + str;
}
function reduceToSingleString(output, base, braces) {
var numLinesEst = 0;
var length = output.reduce(function(prev, cur) {
numLinesEst++;
if (cur.indexOf('\n') >= 0) numLinesEst++;
return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
}, 0);
if (length > 60) {
return braces[0] +
(base === '' ? '' : base + '\n ') +
' ' +
output.join(',\n ') +
' ' +
braces[1];
}
return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
}
// NOTE: These type checking functions intentionally don't use `instanceof`
// because it is fragile and can be easily faked with `Object.create()`.
function isArray(ar) {
return Array.isArray(ar);
}
exports.isArray = isArray;
function isBoolean(arg) {
return typeof arg === 'boolean';
}
exports.isBoolean = isBoolean;
function isNull(arg) {
return arg === null;
}
exports.isNull = isNull;
function isNullOrUndefined(arg) {
return arg == null;
}
exports.isNullOrUndefined = isNullOrUndefined;
function isNumber(arg) {
return typeof arg === 'number';
}
exports.isNumber = isNumber;
function isString(arg) {
return typeof arg === 'string';
}
exports.isString = isString;
function isSymbol(arg) {
return typeof arg === 'symbol';
}
exports.isSymbol = isSymbol;
function isUndefined(arg) {
return arg === void 0;
}
exports.isUndefined = isUndefined;
function isRegExp(re) {
return isObject(re) && objectToString(re) === '[object RegExp]';
}
exports.isRegExp = isRegExp;
function isObject(arg) {
return typeof arg === 'object' && arg !== null;
}
exports.isObject = isObject;
function isDate(d) {
return isObject(d) && objectToString(d) === '[object Date]';
}
exports.isDate = isDate;
function isError(e) {
return isObject(e) &&
(objectToString(e) === '[object Error]' || e instanceof Error);
}
exports.isError = isError;
function isFunction(arg) {
return typeof arg === 'function';
}
exports.isFunction = isFunction;
function isPrimitive(arg) {
return arg === null ||
typeof arg === 'boolean' ||
typeof arg === 'number' ||
typeof arg === 'string' ||
typeof arg === 'symbol' || // ES6 symbol
typeof arg === 'undefined';
}
exports.isPrimitive = isPrimitive;
exports.isBuffer = require('./support/isBuffer');
function objectToString(o) {
return Object.prototype.toString.call(o);
}
function pad(n) {
return n < 10 ? '0' + n.toString(10) : n.toString(10);
}
var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
'Oct', 'Nov', 'Dec'];
// 26 Feb 16:19:34
function timestamp() {
var d = new Date();
var time = [pad(d.getHours()),
pad(d.getMinutes()),
pad(d.getSeconds())].join(':');
return [d.getDate(), months[d.getMonth()], time].join(' ');
}
// log is just a thin wrapper to console.log that prepends a timestamp
exports.log = function() {
console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
};
/**
* Inherit the prototype methods from one constructor into another.
*
* The Function.prototype.inherits from lang.js rewritten as a standalone
* function (not on Function.prototype). NOTE: If this file is to be loaded
* during bootstrapping this function needs to be rewritten using some native
* functions as prototype setup using normal JavaScript does not work as
* expected during bootstrapping (see mirror.js in r114903).
*
* @param {function} ctor Constructor function which needs to inherit the
* prototype.
* @param {function} superCtor Constructor function to inherit prototype from.
*/
exports.inherits = require('inherits');
exports._extend = function(origin, add) {
// Don't do anything if add isn't an object
if (!add || !isObject(add)) return origin;
var keys = Object.keys(add);
var i = keys.length;
while (i--) {
origin[keys[i]] = add[keys[i]];
}
return origin;
};
function hasOwnProperty(obj, prop) {
return Object.prototype.hasOwnProperty.call(obj, prop);
}
},{"./support/isBuffer":35,"inherits":34}]},{},[15])(15)
});