Skip to content

Commit 9bc1db1

Browse files
authored
Merge pull request #104 from Kacarott/v1.1
Fix compiler bug
2 parents 0c44a2a + d8546b0 commit 9bc1db1

File tree

3 files changed

+28
-9
lines changed

3 files changed

+28
-9
lines changed

src/lambda-calculus.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -345,16 +345,16 @@ export function compile(code) {
345345
function evalLC(term) {
346346

347347
// builds function to return to user ( representing an abstraction awaiting input )
348-
function awaitArg(term, stack, env) {
348+
function awaitArg(term, env) {
349349
// callback function which will evaluate term.body in an env with the input
350350
function result(arg) {
351351
let argEnv;
352352
if ( arg?.term && arg?.env ) ({ term: arg, env: argEnv } = arg); // if callback is passed another callback, or a term
353353
const termVal = new Tuple( typeof arg === 'number' ? fromInt(arg) : arg , new Env(argEnv) );
354354
if ( term.name==="_" )
355-
return runEval( new Tuple(term.body, new Env(env)), stack );
355+
return runEval( new Tuple(term.body, new Env(env)) );
356356
else
357-
return runEval( new Tuple(term.body, new Env(env).setThunk(term.name, termVal)), stack );
357+
return runEval( new Tuple(term.body, new Env(env).setThunk(term.name, termVal)) );
358358
}
359359
return Object.assign( result, {term,env} );
360360
}
@@ -363,8 +363,8 @@ function evalLC(term) {
363363
// isRight :: bool (indicating whether the term is left or right side of an Application)
364364
// isEvaluated :: bool (indicating whether the current term should be stored in the Env)
365365
// callstack :: [String] (History of var lookups, for better error messages)
366-
function runEval({term,env},stack) { // stack: [[term, isRight, isEvaluated]], term: LC term, env = Env { name => term }
367-
const callstack = []; // Does not persist between requests for arguments
366+
function runEval({term,env}) { // stack: [[term, isRight, isEvaluated]], term: LC term, env = Env { name => term }
367+
const callstack = [], stack = []; // Does not persist between requests for arguments
368368
while ( ! ( term instanceof L ) || stack.length > 0 ) {
369369
if ( term instanceof V )
370370
if ( term.name==="()" )
@@ -377,7 +377,7 @@ function evalLC(term) {
377377
else {
378378
if (res.term instanceof V || res.term instanceof A)
379379
// Push a frame to the stack to indicate when the value should be stored back
380-
stack.push( [new Tuple( term, env ), false, true ] );
380+
stack.push( [new Tuple( term, env ), true, true ] );
381381
({term, env} = res);
382382
}
383383
}
@@ -395,7 +395,7 @@ function evalLC(term) {
395395
env = new Env(env).setThunk(term.name, new Tuple(lastTerm, lastEnv));
396396
term = term.body;
397397
} else { // Pass the function some other function.
398-
term = lastTerm(awaitArg(term, [], env));
398+
term = lastTerm(awaitArg(term, env));
399399
}
400400
} else if ( term instanceof Tuple ) {
401401
// for primitives
@@ -421,9 +421,9 @@ function evalLC(term) {
421421
}
422422
}
423423
// We need input
424-
return awaitArg(term, stack, env);
424+
return awaitArg(term, env);
425425
}
426-
return runEval(term, []);
426+
return runEval(term);
427427
}
428428

429429
// Print an error, with stack trace according to verbosity level

tests/known-bugs/solution.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
foo = \ x j c . x c ()

tests/known-bugs/test.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import {readFileSync} from "fs";
2+
import {assert, config as chaiConfig} from "chai";
3+
chaiConfig.truncateThreshold = 0;
4+
5+
import * as LC from "../../src/lambda-calculus.js";
6+
LC.configure({ purity: "Let", numEncoding: "None" });
7+
8+
const solutionText = readFileSync(new URL("./solution.txt", import.meta.url), {encoding: "utf8"});
9+
const { foo } = LC.compile(solutionText);
10+
11+
describe("No side effects", () => {
12+
it("The initial failed call used to cause the second call to behave weirdly", () => {
13+
try {
14+
foo("hi")("there")("world")
15+
} catch {}
16+
assert.strictEqual( foo(null).term.toString(), "\\ j c . x c ()" );
17+
});
18+
});

0 commit comments

Comments
 (0)