lc-test
To run tests for Lambda Calculus programs, Codewars uses a custom compiling and testing framework, published and available in this GitHub repository.
The framework is hosted in Javascript, and as such, both the sample and submission tests of Kata must be written in Javascript, while the preloaded section, example solution and user solution are Lambda Calculus.
Please refer to specific documentation for further information on the modules which lc-test utilizes.
- Chai for assertions
- Lambda Calculus for compilation
Basic Usage
Example tests
import { assert, config, LC, getSolution } from "./lc-test.js";
LC.configure({purity: "Let", numEncoding: "Church"});
const { multiply } = LC.compile(getSolution());
describe("Fixed tests", () => {
it("can multiply church numbers", () => {
assert.numEql(multiply(5)(0), 0);
assert.numEql(multiply(1)(8), 8);
assert.numEql(multiply(7)(9), 63);
});
});import { assert, config, LC, getSolution } from "./lc-test.js";
LC.configure({purity: "Let", numEncoding: "Church"});
const { multiply } = LC.compile(getSolution());
describe("Fixed tests", () => {
it("can multiply church numbers", () => {
assert.numEql(multiply(5)(0), 0);
assert.numEql(multiply(1)(8), 8);
assert.numEql(multiply(7)(9), 63);
});
});Components
lc-test provides the following utilities:
chai.assertasassertchai.configasconfigLC = { compile, configure, fromInt, toInt }getSolution,getPreloadedandgetSolutionWithPreloaded
assert
assert is the standard chai.assert, extended with the following additional assertion:
assert.numEql(actual, expected [ , message ] )
actual and expected are automatically decoded according to the current numEncoding, if necessary, before making an equality assertion between them. A custom failure message can optionally be set with message.
config
config is merely a re-export of chai.config. A notable use case is allowing arrays to be displayed fully in assertion messages, using config.truncateThreshold = 0.
getSolution / getPreloaded / getSolutionWithPreloaded
getSolution() returns the user Solution code, getPreloaded returns the author Preloaded code, getSolutionWithPreloaded() returns a safe version of Preloaded and Solution code, concatenated.
LC.compile
LC.compile(getSolution()) returns a JavaScript Object with all top level definitions from the compiled Lambda Calculus source code. Each definition is a Function which can be directly called.
note
Use destructuring to conveniently extract the desired definitions, renaming them to valid Javascript identifiers.
const solution = LC.compile(getSolution());
const { "is-empty": isEmpty } = solution;const solution = LC.compile(getSolution());
const { "is-empty": isEmpty } = solution;Note that definitions in Lambda Calculus source code can be overwritten; for each name defined multiple times, only the last definition will be exported.
LC.configure
Default configuration is
{ verbosity: "Calm" // Calm | Concise | Loquacious | Verbose
, purity: "PureLC" // Let | LetRec | PureLC
, numEncoding: "None" // None | Church | Scott | BinaryScott
}{ verbosity: "Calm" // Calm | Concise | Loquacious | Verbose
, purity: "PureLC" // Let | LetRec | PureLC
, numEncoding: "None" // None | Church | Scott | BinaryScott
}LC.configure can be used to change the settings, by passing an object with key-values of the settings to be changed. For example LC.configure({purity: "Let", numEncoding: "Scott"});
verbosity controls the amount of debug and error information displayed.
purity controls the strictness/purity of the Lambda Calculus syntax allowed.
PureLCensures that all terms must be self-contained, using no external definitions, including itself.Letallows defined terms to be used in later terms.LetRecallows defined terms to be used in later terms, and additionally allows a term to reference itself (direct recursion).
numEncoding selects the specific number encoding to be used when compiling number literals, or conversion functions such as toInt. The encoding may be one of the predefined encodings, a custom encoding, or "None".
- Custom encodings can be set by assigning to
numEncodingan object with bothtoIntandfromIntattribute functions to perform conversion. "None"will cause number literals in code to throw an error.
toInt / fromInt
These functions use the current numEncoding for converting between functions (i.e. Lambda Calculus terms), and Javascript numbers.
toInt converts a function to a Javascript number.
fromInt converts a Javascript number to a function.
Acknowledgements
lc-test and lambda-calculus was authored by @JohanWiltink and @Kacarott.