Scaffolding for OptionalCall
Adds a new `optional-call` terminal and sets up the appropriate handling in the visitors, with lowering/reactivefunction/codegen as todos for now and implemented in follow-ups.
Joe Savona committed
Mar 24, 2023 at 14:22 UTC
40bd9b060ce72b16d135018deec95bbf6b24e33f
7 files changed
+50
-1
compiler/forget/src/HIR/BuildHIR.ts
+7
@@ -11,6 +11,7 @@ import { Expression } from "@babel/types";
11
import invariant from "invariant";
12
import { CompilerError, ErrorSeverity } from "../CompilerError";
13
import { Err, Ok, Result } from "../Utils/Result";
14
+import todo from "../Utils/todo";
15
import { assertExhaustive } from "../Utils/utils";
16
import { Environment, EnvironmentOptions } from "./Environment";
17
import {
@@ -939,6 +940,12 @@ function lowerExpression(
940
loc: exprLoc,
941
};
942
}
943
+ case "OptionalCallExpression": {
944
+ const expr = exprPath as NodePath<t.OptionalCallExpression>;
945
+ const _optional = expr.get("optional");
946
+
947
+ return todo("OptionalCallExpression");
948
+ }
949
case "CallExpression": {
950
const expr = exprPath as NodePath<t.CallExpression>;
951
const calleePath = expr.get("callee");
compiler/forget/src/HIR/HIR.ts
+10
-1
@@ -251,7 +251,8 @@ export type Terminal =
251
| DoWhileTerminal
252
| WhileTerminal
253
| LogicalTerminal
254
- | TernaryTerminal;
254
+ | TernaryTerminal
255
+ | OptionalCallTerminal;
256
257
/**
258
* Terminal nodes allowed for a value block
@@ -352,6 +353,14 @@ export type TernaryTerminal = {
353
loc: SourceLocation;
354
};
355
356
+export type OptionalCallTerminal = {
357
+ kind: "optional-call";
358
+ test: BlockId;
359
+ fallthrough: BlockId;
360
+ id: InstructionId;
361
+ loc: SourceLocation;
362
+};
363
+
364
/**
365
* Instructions generally represent expressions but with all nesting flattened away,
366
* such that all operands to each instruction are either primitive values OR are
compiler/forget/src/HIR/HIRBuilder.ts
+1
@@ -624,6 +624,7 @@ export function reversePostorderBlocks(func: HIR): void {
624
}
625
break;
626
}
627
+ case "optional-call":
628
case "ternary":
629
case "logical": {
630
visit(terminal.test);
compiler/forget/src/HIR/PrintHIR.ts
+5
@@ -79,6 +79,7 @@ export function printMixedHIR(
79
return printInstruction(value);
80
}
81
switch (value.kind) {
82
+ case "optional-call":
83
case "branch":
84
case "if":
85
case "logical":
@@ -155,6 +156,10 @@ export function printTerminal(terminal: Terminal): Array<string> | string {
156
value = `[${terminal.id}] Ternary test:bb${terminal.test} fallthrough=bb${terminal.fallthrough}`;
157
break;
158
}
159
+ case "optional-call": {
160
+ value = `[${terminal.id}] OptionalCall test:bb${terminal.test} fallthrough=bb${terminal.fallthrough}`;
161
+ break;
162
+ }
163
case "throw": {
164
value = `[${terminal.id}] Throw ${printPlace(terminal.value)}`;
165
break;
compiler/forget/src/HIR/visitors.ts
+14
@@ -562,6 +562,17 @@ export function mapTerminalSuccessors(
562
loc: terminal.loc,
563
};
564
}
565
+ case "optional-call": {
566
+ const test = fn(terminal.test);
567
+ const fallthrough = fn(terminal.fallthrough);
568
+ return {
569
+ kind: "optional-call",
570
+ test,
571
+ fallthrough,
572
+ id: makeInstructionId(0),
573
+ loc: terminal.loc,
574
+ };
575
+ }
576
case "return": {
577
return {
578
kind: "return",
@@ -655,6 +666,7 @@ export function* eachTerminalSuccessor(terminal: Terminal): Iterable<BlockId> {
666
}
667
break;
668
}
669
+ case "optional-call":
670
case "ternary":
671
case "logical": {
672
yield terminal.test;
@@ -719,6 +731,7 @@ export function mapTerminalOperands(
731
}
732
break;
733
}
734
+ case "optional-call":
735
case "ternary":
736
case "logical":
737
case "do-while":
@@ -765,6 +778,7 @@ export function* eachTerminalOperand(terminal: Terminal): Iterable<Place> {
778
}
779
break;
780
}
781
+ case "optional-call":
782
case "ternary":
783
case "logical":
784
case "do-while":
compiler/forget/src/ReactiveScopes/BuildReactiveFunction.ts
+4
@@ -29,6 +29,7 @@ import {
29
ReactiveValue,
30
Terminal,
31
} from "../HIR/HIR";
32
+import todo from "../Utils/todo";
33
import { assertExhaustive } from "../Utils/utils";
34
35
/**
@@ -481,6 +482,9 @@ class Driver {
482
this.visitBlock(this.cx.ir.blocks.get(fallthroughId)!, blockValue);
483
break;
484
}
485
+ case "optional-call": {
486
+ todo("BuildReactiveFunction: support optional-call terminal");
487
+ }
488
case "goto": {
489
switch (terminal.variant) {
490
case GotoVariant.Break: {
compiler/forget/src/Utils/VisualizeHIRMermaid.ts
+9
@@ -107,6 +107,10 @@ function printTerminalLabel(terminal: Terminal): string {
107
buffer.push("Ternary");
108
break;
109
}
110
+ case "optional-call": {
111
+ buffer.push("OptionalCall");
112
+ break;
113
+ }
114
case "do-while": {
115
buffer.push("DoWhile");
116
break;
@@ -157,6 +161,11 @@ function printTerminalArrows(blockId: BlockId, terminal: Terminal): string {
161
buffer.push(printJumpArrow(blockId, terminal.fallthrough, "fallthrough"));
162
break;
163
}
164
+ case "optional-call": {
165
+ buffer.push(printJumpArrow(blockId, terminal.test, "test"));
166
+ buffer.push(printJumpArrow(blockId, terminal.fallthrough, "fallthrough"));
167
+ break;
168
+ }
169
case "goto": {
170
buffer.push(printJumpArrow(blockId, terminal.block, null));
171
break;