Record todo bailouts in CodegenReactiveFunction
Went over this pass and converted any todos to bailouts, otherwise we continue to throw an invariant if there's an internal error
Lauren Tan committed
Feb 1, 2023 at 14:49 UTC
8a0d3169fdb526ac68567ed9b3d6cd7b67d2ded3
6 files changed
+51
-27
compiler/forget/src/CompilerError.ts
+1
-1
@@ -13,7 +13,7 @@ export enum ErrorSeverity {
13
export type CompilerErrorOptions = {
14
reason: string;
15
severity: ErrorSeverity;
16
- nodePath: AnyNodePath;
16
+ nodePath: AnyNodePath | null;
17
};
18
type AnyNodePath = NodePath<Node | null | undefined>;
19
type CompilerErrorKind = typeof InvalidInputError | typeof TodoError;
compiler/forget/src/CompilerPipeline.ts
+2
-6
@@ -46,11 +46,7 @@ export type CompilerPipelineValue =
46
export function* run(
47
func: NodePath<t.FunctionDeclaration>
48
): Generator<CompilerPipelineValue, t.Function> {
49
- const lowering = lower(func).orElse((error) => {
50
- throw error;
51
- });
52
-
53
- const hir = lowering.unwrap();
49
+ const hir = lower(func).unwrap();
50
yield log({ kind: "hir", name: "HIR", value: hir });
51
52
mergeConsecutiveBlocks(hir);
@@ -153,7 +149,7 @@ export function* run(
149
value: reactiveFunction,
150
});
151
156
- const ast = codegenReactiveFunction(reactiveFunction);
152
+ const ast = codegenReactiveFunction(reactiveFunction).unwrap();
153
yield log({ kind: "ast", name: "Codegen", value: ast });
154
155
return ast;
compiler/forget/src/ReactiveScopes/CodegenReactiveFunction.ts
+32
-19
@@ -7,6 +7,7 @@
7
8
import * as t from "@babel/types";
9
import invariant from "invariant";
10
+import { CompilerError, ErrorSeverity } from "../CompilerError";
11
import {
12
BlockId,
13
GeneratedSource,
@@ -24,12 +25,12 @@ import {
25
ReactiveValue,
26
SourceLocation,
27
} from "../HIR/HIR";
27
-import { todoInvariant } from "../Utils/todo";
28
+import { Err, Ok, Result } from "../Utils/Result";
29
import { assertExhaustive } from "../Utils/utils";
30
31
export function codegenReactiveFunction(
32
fn: ReactiveFunction
32
-): t.FunctionDeclaration {
33
+): Result<t.FunctionDeclaration, CompilerError> {
34
const cx = new Context();
35
const params = fn.params.map((param) => convertIdentifier(param.identifier));
36
const body = codegenBlock(cx, fn.body);
@@ -56,13 +57,20 @@ export function codegenReactiveFunction(
57
])
58
);
59
}
59
- return createFunctionDeclaration(
60
- fn.loc,
61
- fn.id !== null ? convertIdentifier(fn.id) : null,
62
- params,
63
- body,
64
- fn.generator,
65
- fn.async
60
+
61
+ if (cx.errors.hasErrors()) {
62
+ return Err(cx.errors);
63
+ }
64
+
65
+ return Ok(
66
+ createFunctionDeclaration(
67
+ fn.loc,
68
+ fn.id !== null ? convertIdentifier(fn.id) : null,
69
+ params,
70
+ body,
71
+ fn.generator,
72
+ fn.async
73
+ )
74
);
75
}
76
@@ -70,6 +78,7 @@ class Context {
78
#nextCacheIndex: number = 0;
79
#identifiers: Set<Identifier> = new Set();
80
temp: Temporaries = new Map();
81
+ errors: CompilerError = new CompilerError();
82
83
get nextCacheIndex(): number {
84
return this.#nextCacheIndex++;
@@ -711,17 +720,22 @@ function codegenInstructionValue(
720
} else {
721
if (t.isVariableDeclaration(stmt)) {
722
const declarator = stmt.declarations[0];
714
- todoInvariant(
715
- false,
716
- `Cannot declare variables in a value block, tried to declare '${
723
+ cx.errors.push({
724
+ reason: `(CodegenReactiveFunction::codegenInstructionValue) Cannot declare variables in a value block, tried to declare '${
725
(declarator.id as t.Identifier).name
718
- }'`
719
- );
726
+ }'`,
727
+ severity: ErrorSeverity.Todo,
728
+ nodePath: null,
729
+ });
730
+ return t.stringLiteral(`TODO handle ${declarator.id}`);
731
+ } else {
732
+ cx.errors.push({
733
+ reason: `(CodegenReactiveFunction::codegenInstructionValue) Handle conversion of ${stmt.type} to expression`,
734
+ severity: ErrorSeverity.Todo,
735
+ nodePath: null,
736
+ });
737
+ return t.stringLiteral(`TODO handle ${stmt.type}`);
738
}
721
- todoInvariant(
722
- false,
723
- `Handle conversion of ${stmt.type} to expression`
724
- );
739
}
740
});
741
if (expressions.length === 0) {
@@ -788,7 +802,6 @@ function codegenValue(
802
}
803
804
function codegenPlace(cx: Context, place: Place): t.Expression {
791
- todoInvariant(place.kind === "Identifier", "support scope values");
805
let tmp = cx.temp.get(place.identifier.id);
806
if (tmp != null) {
807
return tmp;
compiler/forget/src/Utils/Result.ts
+6
@@ -167,6 +167,9 @@ class OkImpl<T> implements Result<T, never> {
167
}
168
169
unwrapErr(): never {
170
+ if (this.val instanceof Error) {
171
+ throw this.val;
172
+ }
173
throw new Error(`Can't unwrap \`Ok\` to \`Err\`: ${this.val}`);
174
}
175
}
@@ -227,6 +230,9 @@ class ErrImpl<E> implements Result<never, E> {
230
}
231
232
unwrap(): never {
233
+ if (this.val instanceof Error) {
234
+ throw this.val;
235
+ }
236
throw new Error(`Can't unwrap \`Err\` to \`Ok\`: ${this.val}`);
237
}
238
compiler/forget/src/__tests__/Result-test.ts
+9
@@ -1,3 +1,4 @@
1
+import { CompilerError } from "../CompilerError";
2
import { Err, Ok, Result } from "../Utils/Result";
3
4
function addMax10(a: number, b: number): Result<number, string> {
@@ -9,6 +10,8 @@ function onlyFoo(foo: string): Result<string, string> {
10
return foo === "foo" ? Ok(foo) : Err(foo);
11
}
12
13
+class CustomDummyError extends Error {}
14
+
15
describe("Result", () => {
16
test(".map", () => {
17
expect(addMax10(1, 1).map((n) => n * 2)).toEqual(Ok(4));
@@ -107,6 +110,9 @@ describe("Result", () => {
110
}).toThrowErrorMatchingInlineSnapshot(
111
`"Can't unwrap \`Err\` to \`Ok\`: 20 is too high"`
112
);
113
+ expect(() => {
114
+ Err(new CustomDummyError("oops")).unwrap();
115
+ }).toThrowErrorMatchingInlineSnapshot(`"oops"`);
116
});
117
118
test(".unwrapOr", () => {
@@ -126,5 +132,8 @@ describe("Result", () => {
132
`"Can't unwrap \`Ok\` to \`Err\`: 2"`
133
);
134
expect(addMax10(10, 10).unwrapErr()).toEqual("20 is too high");
135
+ expect(() => {
136
+ Ok(new CustomDummyError("oops")).unwrapErr();
137
+ }).toThrowErrorMatchingInlineSnapshot(`"oops"`);
138
});
139
});
compiler/forget/src/__tests__/fixtures/hir/error.while-with-assignment-in-test.expect.md
+1
-1
@@ -19,7 +19,7 @@ function f(reader) {
19
## Error
20
21
```
22
-TODO: Cannot declare variables in a value block, tried to declare 'value$0'
22
+[ReactForget] Todo: (CodegenReactiveFunction::codegenInstructionValue) Cannot declare variables in a value block, tried to declare 'value$0'
23
```
24
25
\ No newline at end of file