Skip to content

Commit

Permalink
WIP: Add support for asynchronous assertions through logging
Browse files Browse the repository at this point in the history
For original implementation see 73ee48e.

Co-authored-by: Aldwin Vlasblom <[email protected]>
  • Loading branch information
davidchambers and Avaq committed Jan 4, 2024
1 parent aafc7f9 commit 51ae7a4
Show file tree
Hide file tree
Showing 37 changed files with 949 additions and 378 deletions.
1 change: 1 addition & 0 deletions bin/doctest
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ require ('child_process')
process.execPath,
['--experimental-import-meta-resolve',
'--experimental-vm-modules',
'--no-warnings',
...(flags ? args[idx + 1].split (/\s+/) : []),
'--',
path.resolve (__dirname, '..', 'lib', 'command.js'),
Expand Down
15 changes: 9 additions & 6 deletions lib/Effect.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,30 @@
import {Result} from './Output.js';


// Failure :: Any -> Effect
const Failure = exception => ({
tag: 'Failure',
exception,
});

// Success :: Any -> Effect
const Success = value => ({
// Success :: Output -> Effect
const Success = output => ({
tag: 'Success',
value,
output,
});

// effect :: (Any -> a) -> (Any -> a) -> Effect -> a
// effect :: (Any -> a) -> (Output -> a) -> Effect -> a
const effect = failure => success => effect => {
switch (effect.tag) {
case 'Failure': return failure (effect.exception);
case 'Success': return success (effect.value);
case 'Success': return success (effect.output);
}
};

// encase :: AnyFunction -> ...Any -> Effect
const encase = f => (...args) => {
try {
return Success (f (...args));
return Success (Result (f (...args)));
} catch (exception) {
return Failure (exception);
}
Expand Down
8 changes: 8 additions & 0 deletions lib/Output.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Channel :: String -> Any -> Output
const Channel = channel => value => ({channel, value});

// Result :: Any -> Output
const Result = Channel (null);


export {Channel, Result};
45 changes: 31 additions & 14 deletions lib/command.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,25 @@ import doctest from './doctest.js';
import program from './program.js';


const bold = text => '\u001B[1m' + text + '\u001B[22m';
const invert = text => '\u001B[7m' + text + '\u001B[0m';
const blue = text => '\u001B[34m' + text + '\u001B[0m';
const purple = text => '\u001B[35m' + text + '\u001B[0m';

// formatLine :: (String -> String) -> Array Line -> String
const formatLine = colour => line => `${
invert (` ${`${line.number}`.padStart (4)} `)
} ${
colour (line.text)
}`;

// formatEffect :: Effect -> String
const formatEffect = (
effect (x => `! ${x}`)
(show)
effect (e => `${bold ('throw')} ${show (e)}`)
(output =>
output.channel == null
? show (output.value)
: `${bold (output.channel)} (${show (output.value)})`)
);

(async () => {
Expand All @@ -27,25 +42,27 @@ const formatEffect = (
process.exit (0);
}

const messages = output.map (test =>
const failures = output.flatMap (test =>
comparison (actual => expected => [
`FAIL: expected ${
formatEffect (expected)
} on line ${
test.lines.output[0].number
} (got ${
formatEffect (actual)
})\n`,
[[''],
test.lines.input.map (formatLine (blue)),
test.lines.output.map (formatLine (purple)),
[''],
actual.map (a => blue (formatEffect (a))),
expected.map (e => purple (formatEffect (e))),
['']]
.flat ()
.join ('\n'),
])
(_ => [])
(test.comparison)
);
const failures = messages.flat ();

if (!program.silent) {
process.stdout.write (`running doctests in ${path}...
${(messages.map (m => m.length === 0 ? '.' : 'x')).join ('')}
${failures.join ('')}`);
process.stdout.write (`
Running doctests in ${bold (path)}...
${failures.join ('')}
`);
}

process.exit (failures.length > 0 ? 1 : 0);
Expand Down
Loading

0 comments on commit 51ae7a4

Please sign in to comment.