Skip to content

Commit 7517b84

Browse files
authored
Added a fudged transformation (#102)
Many Stopify bugs are found in the transformations that occur before jumper. However, jumper makes the generated code very hard to debug. This transformation does everything except inserting logic to save and restore the stack around function calls. It will only work with "-y 0". In addition, successful programs terminate by throwing the exception "FudgedContinuationError(done)".
1 parent 8704759 commit 7517b84

File tree

4 files changed

+73
-2
lines changed

4 files changed

+73
-2
lines changed

src/callcc/fudgeRuntime.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import * as common from './runtime';
2+
export * from './runtime';
3+
4+
class FudgedContinuationError {
5+
6+
constructor(public v: any) { }
7+
8+
toString() {
9+
return `FudgedContinuationError(${this.v})`;
10+
}
11+
12+
}
13+
14+
/** This runtime system doesn't actually implement any control operators.
15+
* Functions such as 'captureCC' are defined and will call their argument,
16+
* but don't save the stack.
17+
*
18+
* Unfortunately, all our program end by invoking the top continuation with
19+
* "done". Therefore, a program that runs correctly will terminate with
20+
* 'FudgedContinuationError(done)'. This is unfortunate. But, this
21+
* transformation still helps with debugging.
22+
*/
23+
export class FudgeRuntime extends common.Runtime {
24+
constructor() {
25+
super();
26+
}
27+
28+
captureCC(f: (k: any) => any): void {
29+
throw new common.Capture(f, []);
30+
}
31+
32+
abortCC(f: () => any) {
33+
throw new common.Discard(f);
34+
}
35+
36+
makeCont(stack: common.Stack) {
37+
return (v: any) => {
38+
throw new FudgedContinuationError(v);
39+
};
40+
}
41+
42+
runtime(body: () => any): any {
43+
try {
44+
body();
45+
}
46+
catch (exn) {
47+
if (exn instanceof common.Capture) {
48+
return this.runtime(() => exn.f.call(global, this.makeCont(exn.stack)));
49+
} else if (exn instanceof common.Discard) {
50+
return this.runtime(() => exn.f());
51+
} else {
52+
throw exn; // userland exception
53+
}
54+
}
55+
}
56+
57+
handleNew(constr: any, ...args: any[]) {
58+
return new constr(...args);
59+
}
60+
}
61+
62+
export default FudgeRuntime;

src/callcc/jumper.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ type Labeled<T> = T & {
1212
}
1313
type CaptureFun = (path: NodePath<t.AssignmentExpression>) => void;
1414

15-
export type CaptureLogic = 'lazy' | 'eager' | 'retval';
15+
export type CaptureLogic = 'lazy' | 'eager' | 'retval' | 'fudge';
1616

1717
interface State {
1818
opts: {
@@ -24,6 +24,7 @@ const captureLogics: { [key: string]: CaptureFun } = {
2424
lazy: lazyCaptureLogic,
2525
eager: eagerCaptureLogic,
2626
retval: retvalCaptureLogic,
27+
fudge: fudgeCaptureLogic,
2728
};
2829

2930
function split<T>(arr: T[], index: number): { pre: T[], post: T[] } {
@@ -175,6 +176,10 @@ function reapplyExpr(path: NodePath<Labeled<t.Function>>): t.Expression {
175176
}
176177
}
177178

179+
function fudgeCaptureLogic(path: NodePath<t.AssignmentExpression>): void {
180+
return;
181+
}
182+
178183
/**
179184
* Wrap callsites in try/catch block, lazily building the stack on catching a
180185
* Capture exception, then rethrowing.

src/compile.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const srcPath = args._[0];
1616
const dstPath = args._[1];
1717
const transform = args.transform;
1818

19-
const validTransforms = [ 'eager', 'lazy', 'retval', 'original' ];
19+
const validTransforms = [ 'eager', 'lazy', 'retval', 'original', 'fudge' ];
2020
if (validTransforms.includes(transform) === false) {
2121
stderr.write(`--transform must be one of ${validTransforms.join(', ')}, got ${transform}.\n`);
2222
process.exit(1);

src/rts.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { Runtime, YieldInterval, Latency } from './callcc/runtime';
44
import eager from './callcc/eagerRuntime';
55
import lazy from './callcc/lazyRuntime';
66
import retval from './callcc/retvalRuntime';
7+
import fudge from './callcc/fudgeRuntime';
78

89
function modeToBase(mode: string) {
910
if (mode === 'eager') {
@@ -15,6 +16,9 @@ function modeToBase(mode: string) {
1516
else if (mode === 'retval') {
1617
return retval;
1718
}
19+
else if (mode === 'fudge') {
20+
return fudge;
21+
}
1822
else {
1923
throw new Error(`unknown runtime system mode: ${mode}`);
2024
}

0 commit comments

Comments
 (0)