Skip to content
UniqueFool edited this page May 22, 2016 · 17 revisions

Welcome to the inductive.js wiki!

Table of Contents

Macros

as() has one of two purposes. Either it's used to label test cases, or it's inside of express, which is used to create building blocks from scratch (essentially via a macro system)

Here is an example of using as to label a test case:

specify('add',
  given(1, 2,
    shouldReturn(3),
    as('adding 1 and 2 should return 3')),
  use('Number+'))

Now, let's consider the following example

@Map<('a | undefined)>[@String]
@Map
is a map type. It is used to represent the hash table usage of objects in JavaScript.

Example:

var map = { key1: 'value1', key2: 'value2' }
console.log('key1 in map?', 'key1' in map) // true
console.log('key2 in map?', 'key2' in map) // true
console.log('key3 in map?', 'key3' in map) // false

Map takes a type argument. In the example I just gave, the type would be string. So we would write this as Map.

Inductive.js also supports union types. A union type is denoted like this: (Number | String). This signifies a value that can be one of several types.

Finally, inductive.js supports polymorphic types, call generic parameters in some languages. An example is an Array. Arrays can be of Numbers, Strings, or whatever. To represent this fact we have the ability to include type parameters. A type parameter looks like this: 'a. A generic array looks like Array<'a>.

In this case Map<('a | undefined)> represents a Map that takes optional 'a values, or undefined. The building block you are looking at (OptionMap.get) does a look up on the Map object for a specific key.

An example of an Map of option types might look like this:

var map = { key1: 'str1', key2: 'str2', key3: undefined }
This is a Map. To look up a value we can do map['key2']. map['key2'] will return a String or undefined depending on what the map looks like.

Composable specs

To use a spec in another spec, just assign it to a JavaScript variable, and refer to it in the use() call of the other spec.

For instance, consider the following snippet from tests/testSolves.i.js:

var doubleIt = specify('doubleIt',
given(1, shouldReturn(2)),
use('Number+'))

This makes the specified function available as doubleIt, so that it can be used later:

var double2 = specify('double2',
givenNoArgs(shouldReturn(4)),
use(doubleIt, value(2)))

Options

Options can be set/overridden per specification by adding a nested call to setOptions() which accepts a hash/object as its argument, e.g.:

setOptions({ maxAstNodes: 25 })

This will raise the maximum number of AST (abstrasct syntax tree) nodes to 25 (20 being the default value for this).

For debugging purposes, you can change the verbosity of the solver, using one of these values (see lib/verbosityLevels.js):

  • quiet
  • solution
  • scope
  • astNodes
  • solutionAst
  • candidate
  • candidateAst
  • test
  • candidateSandboxed
  • traversal
  • expression
  • diagnostic
setOptions({ verbosity: solutionAst })

testSolves.i.js

test/testSolves.i.js contains a bunch of tests that can be used as reference when creating new specifications. To actually run testSolves.i.js you also need to have the following modules installed via npm:

  • esprima
  • escodegen

buildingBlocks.js

This file contains the building blocks that are available for creating new specs

DeferredAPICall

The DeferredApiCall is used to translate the DSL syntactic sugar into OO-calls.

For example:

function declare(name) {
  return DeferredApiCall.callChildren(arguments, function() {
    return new Specification(name || '')
  })
}

declare('square',
  given(3, shouldReturn(9)),
  use('*'))

This effectively gets translated by DeferredApiCall into:

var square = declare('square')
var scenario = square.given(3)
var expectation = scenario.shouldReturn(9)
square.use('Number+')

The solver

The solver runs BFS, it is invoked in lib/specs/Specification.js and implemented in Solver.js

The traversal object

The traversal object is a singly-linked persistent list (like a cons list or ML list) with head and tail properties. head contains an expression and the location of the expression in the AST. The location is specified by giving the cell a id and a parentID. tail is the optional next cons cell.