mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Replace NodePath with SourceLocation
Removes all the `path: NodePath` values from various IR node types, replacing them with `loc: SourceLocation`. This type is an alias for babel's source location type plus a "generated" variant. The "OtherStatement" kind also used the `path` to print back the original AST (since we don't look into these); instead, we now capture the underlying `node` and emit that as-is during codegen. While I was doing this, i also fixed up the places where we had passed a null path; the vast majority have a clear place we can pull a location from. For example, `a ?? b` syntax creates some places/instructions for the `a != null`, but those can all point back to the `a` location.
This commit is contained in:
@@ -11,12 +11,14 @@ import { assertExhaustive } from "../Common/utils";
|
||||
import { invariant } from "../CompilerError";
|
||||
import {
|
||||
Effect,
|
||||
GeneratedSource,
|
||||
HIRFunction,
|
||||
IfTerminal,
|
||||
InstructionKind,
|
||||
InstructionValue,
|
||||
Place,
|
||||
ReturnTerminal,
|
||||
SourceLocation,
|
||||
Terminal,
|
||||
ThrowTerminal,
|
||||
} from "./HIR";
|
||||
@@ -66,7 +68,7 @@ export function lower(
|
||||
identifier,
|
||||
memberPath: null,
|
||||
effect: Effect.Unknown,
|
||||
path: null as any,
|
||||
loc: param.loc ?? GeneratedSource,
|
||||
};
|
||||
params.push(place);
|
||||
});
|
||||
@@ -81,10 +83,12 @@ export function lower(
|
||||
}
|
||||
|
||||
return {
|
||||
path: func,
|
||||
id,
|
||||
params,
|
||||
body: builder.build(),
|
||||
generator: func.node.generator === true,
|
||||
async: func.node.async === true,
|
||||
loc: func.node.loc ?? GeneratedSource,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -574,13 +578,13 @@ function lowerStatement(
|
||||
value = {
|
||||
kind: "Primitive",
|
||||
value: undefined,
|
||||
path: init as any, // TODO
|
||||
loc: id.loc,
|
||||
};
|
||||
}
|
||||
builder.push({
|
||||
lvalue: { place: id, kind },
|
||||
value,
|
||||
path: stmt,
|
||||
loc: declaration.node.loc ?? GeneratedSource,
|
||||
});
|
||||
}
|
||||
return;
|
||||
@@ -596,7 +600,7 @@ function lowerStatement(
|
||||
builder.push({
|
||||
lvalue: null,
|
||||
value,
|
||||
path: stmt,
|
||||
loc: stmt.node.loc ?? GeneratedSource,
|
||||
});
|
||||
return;
|
||||
}
|
||||
@@ -632,9 +636,13 @@ function lowerStatement(
|
||||
case "TSTypeAliasDeclaration":
|
||||
case "WithStatement": {
|
||||
builder.push({
|
||||
path: stmtPath,
|
||||
lvalue: null,
|
||||
value: { kind: "OtherStatement", path: stmtPath },
|
||||
loc: stmtPath.node.loc ?? GeneratedSource,
|
||||
value: {
|
||||
kind: "OtherStatement",
|
||||
loc: stmtPath.node.loc ?? GeneratedSource,
|
||||
node: stmtPath.node,
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
@@ -654,6 +662,7 @@ function lowerExpression(
|
||||
exprPath: NodePath<t.Expression>
|
||||
): InstructionValue {
|
||||
const exprNode = exprPath.node;
|
||||
const exprLoc = exprNode.loc ?? GeneratedSource;
|
||||
switch (exprNode.type) {
|
||||
case "Identifier": {
|
||||
const expr = exprPath as NodePath<t.Identifier>;
|
||||
@@ -663,7 +672,7 @@ function lowerExpression(
|
||||
return {
|
||||
kind: "Primitive",
|
||||
value: null,
|
||||
path: exprPath,
|
||||
loc: exprLoc,
|
||||
};
|
||||
}
|
||||
case "BooleanLiteral":
|
||||
@@ -676,7 +685,7 @@ function lowerExpression(
|
||||
return {
|
||||
kind: "Primitive",
|
||||
value,
|
||||
path: exprPath,
|
||||
loc: exprLoc,
|
||||
};
|
||||
}
|
||||
case "ObjectExpression": {
|
||||
@@ -701,7 +710,7 @@ function lowerExpression(
|
||||
return {
|
||||
kind: "ObjectExpression",
|
||||
properties,
|
||||
path: exprPath,
|
||||
loc: exprLoc,
|
||||
};
|
||||
}
|
||||
case "ArrayExpression": {
|
||||
@@ -716,7 +725,7 @@ function lowerExpression(
|
||||
return {
|
||||
kind: "ArrayExpression",
|
||||
elements,
|
||||
path: exprPath,
|
||||
loc: exprLoc,
|
||||
};
|
||||
}
|
||||
case "NewExpression": {
|
||||
@@ -739,7 +748,7 @@ function lowerExpression(
|
||||
kind: "NewExpression",
|
||||
callee,
|
||||
args,
|
||||
path: exprPath,
|
||||
loc: exprLoc,
|
||||
};
|
||||
}
|
||||
case "CallExpression": {
|
||||
@@ -762,7 +771,7 @@ function lowerExpression(
|
||||
kind: "CallExpression",
|
||||
callee,
|
||||
args,
|
||||
path: exprPath,
|
||||
loc: exprLoc,
|
||||
};
|
||||
}
|
||||
case "BinaryExpression": {
|
||||
@@ -780,7 +789,7 @@ function lowerExpression(
|
||||
operator,
|
||||
left,
|
||||
right,
|
||||
path: exprPath,
|
||||
loc: exprLoc,
|
||||
};
|
||||
}
|
||||
case "LogicalExpression": {
|
||||
@@ -797,6 +806,7 @@ function lowerExpression(
|
||||
return lowerConditional(
|
||||
builder,
|
||||
left,
|
||||
exprLoc,
|
||||
() => left,
|
||||
() => lowerExpression(builder, expr.get("right"))
|
||||
);
|
||||
@@ -806,6 +816,7 @@ function lowerExpression(
|
||||
return lowerConditional(
|
||||
builder,
|
||||
left,
|
||||
exprLoc,
|
||||
() => lowerExpression(builder, expr.get("right")),
|
||||
() => left
|
||||
);
|
||||
@@ -821,15 +832,15 @@ function lowerExpression(
|
||||
identifier: builder.makeTemporary(),
|
||||
memberPath: null,
|
||||
effect: Effect.Unknown,
|
||||
path: null as any,
|
||||
loc: left.loc,
|
||||
};
|
||||
builder.push({
|
||||
value: {
|
||||
kind: "Primitive",
|
||||
value: null,
|
||||
path: null as any,
|
||||
loc: GeneratedSource,
|
||||
},
|
||||
path: exprPath,
|
||||
loc: left.loc,
|
||||
lvalue: { place: { ...nullPlace }, kind: InstructionKind.Const },
|
||||
});
|
||||
|
||||
@@ -838,7 +849,7 @@ function lowerExpression(
|
||||
identifier: builder.makeTemporary(),
|
||||
memberPath: null,
|
||||
effect: Effect.Unknown,
|
||||
path: null as any,
|
||||
loc: left.loc,
|
||||
};
|
||||
builder.push({
|
||||
lvalue: {
|
||||
@@ -850,13 +861,14 @@ function lowerExpression(
|
||||
operator: "!=",
|
||||
left,
|
||||
right: nullPlace,
|
||||
path: null as any,
|
||||
loc: left.loc,
|
||||
},
|
||||
path: null as any,
|
||||
loc: left.loc,
|
||||
});
|
||||
return lowerConditional(
|
||||
builder,
|
||||
condPlace,
|
||||
exprLoc,
|
||||
() => left,
|
||||
() => lowerExpression(builder, expr.get("right"))
|
||||
);
|
||||
@@ -877,8 +889,8 @@ function lowerExpression(
|
||||
todoInvariant(operator === "=", "todo: support non-simple assignment");
|
||||
builder.push({
|
||||
lvalue: { place: left, kind: InstructionKind.Reassign },
|
||||
path: exprPath,
|
||||
value: right,
|
||||
loc: exprLoc,
|
||||
});
|
||||
return left;
|
||||
}
|
||||
@@ -896,7 +908,7 @@ function lowerExpression(
|
||||
identifier: object.identifier,
|
||||
memberPath: [...(object.memberPath ?? []), property.node.name],
|
||||
effect: Effect.Unknown,
|
||||
path: exprPath,
|
||||
loc: exprLoc,
|
||||
};
|
||||
return place;
|
||||
}
|
||||
@@ -933,10 +945,10 @@ function lowerExpression(
|
||||
});
|
||||
return {
|
||||
kind: "JsxExpression",
|
||||
path: exprPath,
|
||||
tag,
|
||||
props,
|
||||
children,
|
||||
loc: exprLoc,
|
||||
};
|
||||
}
|
||||
default: {
|
||||
@@ -952,6 +964,7 @@ function lowerExpression(
|
||||
function lowerConditional(
|
||||
builder: HIRBuilder,
|
||||
test: Place,
|
||||
loc: SourceLocation,
|
||||
consequent: () => InstructionValue,
|
||||
alternate: () => InstructionValue
|
||||
): Place {
|
||||
@@ -960,7 +973,7 @@ function lowerConditional(
|
||||
identifier: builder.makeTemporary(),
|
||||
memberPath: null,
|
||||
effect: Effect.Read,
|
||||
path: null as any, // TODO
|
||||
loc,
|
||||
};
|
||||
// Block for code following the if
|
||||
const continuationBlock = builder.reserve();
|
||||
@@ -970,7 +983,7 @@ function lowerConditional(
|
||||
builder.push({
|
||||
value,
|
||||
lvalue: { place: { ...place }, kind: InstructionKind.Const },
|
||||
path: value.path,
|
||||
loc: value.loc,
|
||||
});
|
||||
return {
|
||||
kind: "goto",
|
||||
@@ -983,7 +996,7 @@ function lowerConditional(
|
||||
builder.push({
|
||||
value,
|
||||
lvalue: { place: { ...place }, kind: InstructionKind.Const },
|
||||
path: value.path,
|
||||
loc: value.loc,
|
||||
});
|
||||
return {
|
||||
kind: "goto",
|
||||
@@ -1008,6 +1021,7 @@ function lowerJsxElementName(
|
||||
>
|
||||
): Place {
|
||||
todoInvariant(exprPath.isJSXIdentifier(), "handle non-identifier tags");
|
||||
const exprLoc = exprPath.node.loc ?? GeneratedSource;
|
||||
const tag: string = exprPath.node.name;
|
||||
if (tag.match(/^[A-Z]/)) {
|
||||
const binding =
|
||||
@@ -1023,7 +1037,7 @@ function lowerJsxElementName(
|
||||
identifier: identifier,
|
||||
memberPath: null,
|
||||
effect: Effect.Unknown,
|
||||
path: exprPath,
|
||||
loc: exprLoc,
|
||||
};
|
||||
return place;
|
||||
} else {
|
||||
@@ -1032,11 +1046,15 @@ function lowerJsxElementName(
|
||||
identifier: builder.makeTemporary(),
|
||||
memberPath: null,
|
||||
effect: Effect.Unknown,
|
||||
path: exprPath,
|
||||
loc: exprLoc,
|
||||
};
|
||||
builder.push({
|
||||
value: { kind: "Primitive", value: tag, path: exprPath },
|
||||
path: exprPath,
|
||||
value: {
|
||||
kind: "Primitive",
|
||||
value: tag,
|
||||
loc: exprLoc,
|
||||
},
|
||||
loc: exprLoc,
|
||||
lvalue: { place, kind: InstructionKind.Const },
|
||||
});
|
||||
return { ...place };
|
||||
@@ -1053,6 +1071,8 @@ function lowerJsxElement(
|
||||
| t.JSXFragment
|
||||
>
|
||||
): Place {
|
||||
const exprNode = exprPath.node;
|
||||
const exprLoc = exprNode.loc ?? GeneratedSource;
|
||||
if (exprPath.isJSXElement()) {
|
||||
return lowerExpressionToPlace(builder, exprPath);
|
||||
} else if (exprPath.isJSXExpressionContainer()) {
|
||||
@@ -1065,25 +1085,37 @@ function lowerJsxElement(
|
||||
identifier: builder.makeTemporary(),
|
||||
memberPath: null,
|
||||
effect: Effect.Unknown,
|
||||
path: exprPath,
|
||||
loc: exprLoc,
|
||||
};
|
||||
builder.push({
|
||||
value: { kind: "JSXText", value: exprPath.node.value, path: exprPath },
|
||||
path: exprPath,
|
||||
value: {
|
||||
kind: "JSXText",
|
||||
value: exprPath.node.value,
|
||||
loc: exprLoc,
|
||||
},
|
||||
loc: exprLoc,
|
||||
lvalue: { place: { ...place }, kind: InstructionKind.Const },
|
||||
});
|
||||
return place;
|
||||
} else {
|
||||
invariant(
|
||||
t.isJSXFragment(exprNode) || t.isJSXSpreadChild(exprNode),
|
||||
"Expected refinement to work"
|
||||
);
|
||||
const place: Place = {
|
||||
kind: "Identifier",
|
||||
identifier: builder.makeTemporary(),
|
||||
memberPath: null,
|
||||
effect: Effect.Unknown,
|
||||
path: exprPath,
|
||||
loc: exprLoc,
|
||||
};
|
||||
builder.push({
|
||||
value: { kind: "OtherStatement", path: exprPath },
|
||||
path: exprPath,
|
||||
value: {
|
||||
kind: "OtherStatement",
|
||||
node: exprNode,
|
||||
loc: exprLoc,
|
||||
},
|
||||
loc: exprLoc,
|
||||
lvalue: { place: { ...place }, kind: InstructionKind.Const },
|
||||
});
|
||||
return place;
|
||||
@@ -1098,16 +1130,17 @@ function lowerExpressionToPlace(
|
||||
if (instr.kind === "Identifier") {
|
||||
return instr;
|
||||
}
|
||||
const exprLoc = exprPath.node.loc ?? GeneratedSource;
|
||||
const place: Place = {
|
||||
kind: "Identifier",
|
||||
identifier: builder.makeTemporary(),
|
||||
memberPath: null,
|
||||
effect: Effect.Unknown,
|
||||
path: exprPath,
|
||||
loc: exprLoc,
|
||||
};
|
||||
builder.push({
|
||||
value: instr,
|
||||
path: exprPath,
|
||||
loc: exprLoc,
|
||||
lvalue: { place: { ...place }, kind: InstructionKind.Const },
|
||||
});
|
||||
return place;
|
||||
@@ -1115,6 +1148,7 @@ function lowerExpressionToPlace(
|
||||
|
||||
function lowerLVal(builder: HIRBuilder, exprPath: NodePath<t.LVal>): Place {
|
||||
const exprNode = exprPath.node;
|
||||
const exprLoc = exprNode.loc ?? GeneratedSource;
|
||||
switch (exprNode.type) {
|
||||
case "Identifier": {
|
||||
// const expr = exprPath as NodePath<t.Identifier>;
|
||||
@@ -1133,7 +1167,7 @@ function lowerLVal(builder: HIRBuilder, exprPath: NodePath<t.LVal>): Place {
|
||||
identifier: identifier,
|
||||
memberPath: null,
|
||||
effect: Effect.Unknown,
|
||||
path: exprPath,
|
||||
loc: exprLoc,
|
||||
};
|
||||
return place;
|
||||
}
|
||||
@@ -1152,7 +1186,7 @@ function lowerLVal(builder: HIRBuilder, exprPath: NodePath<t.LVal>): Place {
|
||||
identifier: object.identifier,
|
||||
memberPath: [...(object.memberPath ?? []), propertyPath.node.name],
|
||||
effect: Effect.Unknown,
|
||||
path: exprPath,
|
||||
loc: exprLoc,
|
||||
};
|
||||
return place;
|
||||
}
|
||||
|
||||
@@ -45,18 +45,13 @@ export default function codegen(fn: HIRFunction): t.Function {
|
||||
const entry = fn.body.blocks.get(fn.body.entry)!;
|
||||
const cx: Context = { ir: fn.body, temp: new Map() };
|
||||
const body = codegenBlock(cx, entry);
|
||||
const node = fn.path.node;
|
||||
todoInvariant(
|
||||
t.isFunctionDeclaration(node),
|
||||
"todo: handle other than function declaration"
|
||||
);
|
||||
const params = fn.params.map((param) => convertIdentifier(param.identifier));
|
||||
return t.functionDeclaration(
|
||||
fn.id !== null ? convertIdentifier(fn.id) : null,
|
||||
params,
|
||||
body,
|
||||
node.generator,
|
||||
node.async
|
||||
fn.generator,
|
||||
fn.async
|
||||
);
|
||||
}
|
||||
|
||||
@@ -158,7 +153,7 @@ function writeBlock(cx: Context, block: BasicBlock, body: Array<t.Statement>) {
|
||||
}
|
||||
|
||||
function writeInstr(cx: Context, instr: Instruction, body: Array<t.Statement>) {
|
||||
let value;
|
||||
let value: t.Expression;
|
||||
const instrValue = instr.value;
|
||||
switch (instrValue.kind) {
|
||||
case "ArrayExpression": {
|
||||
@@ -253,15 +248,13 @@ function writeInstr(cx: Context, instr: Instruction, body: Array<t.Statement>) {
|
||||
break;
|
||||
}
|
||||
case "OtherStatement": {
|
||||
const node = instrValue.path.node;
|
||||
if (node != null) {
|
||||
invariant(
|
||||
t.isStatement(node),
|
||||
"Expected node to be a statement if present"
|
||||
);
|
||||
const node = instrValue.node;
|
||||
if (t.isStatement(node)) {
|
||||
body.push(node);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
value = node as any; // TODO(josephsavona) complete handling of JSX fragment/spreadchild elements
|
||||
break;
|
||||
}
|
||||
case "Identifier": {
|
||||
value = codegenPlace(cx, instrValue);
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import { NodePath } from "@babel/core";
|
||||
import * as t from "@babel/types";
|
||||
import { invariant } from "../CompilerError";
|
||||
|
||||
@@ -22,6 +21,16 @@ import { invariant } from "../CompilerError";
|
||||
|
||||
// AST -> (lowering) -> HIR -> (dep analysis) -> Reactive Scopes -> (scheduling?) -> HIR -> (codegen) -> AST
|
||||
|
||||
/**
|
||||
* A location in a source file, intended to be used for providing diagnostic information and
|
||||
* transforming code while preserving source information (ie to emit source maps).
|
||||
*
|
||||
* `GeneratedSource` indicates that there is no single source location from which the code derives.
|
||||
*
|
||||
*/
|
||||
export const GeneratedSource = Symbol();
|
||||
export type SourceLocation = t.SourceLocation | typeof GeneratedSource;
|
||||
|
||||
/**
|
||||
* A React function defines a computation that takes some set of reactive
|
||||
* inputs (eg props, hook arguments) and returns a result (JSX, hook return
|
||||
@@ -37,7 +46,7 @@ import { invariant } from "../CompilerError";
|
||||
* may depend upon (transitively).
|
||||
*/
|
||||
export type ReactFunction = {
|
||||
path: NodePath<t.Function>;
|
||||
loc: SourceLocation;
|
||||
id: Identifier | null;
|
||||
params: Array<Place>;
|
||||
returnScope: ScopeId;
|
||||
@@ -59,10 +68,12 @@ export type ReactiveScope = {
|
||||
* A function declaration including its path
|
||||
*/
|
||||
export type HIRFunction = {
|
||||
path: NodePath<t.Function>;
|
||||
loc: SourceLocation;
|
||||
id: Identifier | null;
|
||||
params: Array<Place>;
|
||||
body: HIR;
|
||||
generator: boolean;
|
||||
async: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -140,7 +151,7 @@ export type SwitchTerminal = {
|
||||
export type Instruction = {
|
||||
lvalue: LValue | null;
|
||||
value: InstructionValue;
|
||||
path: NodePath;
|
||||
loc: SourceLocation;
|
||||
};
|
||||
|
||||
export type LValue = {
|
||||
@@ -162,7 +173,9 @@ export enum InstructionKind {
|
||||
*
|
||||
* Values are therefore only a Place or a primitive value.
|
||||
*/
|
||||
export type InstructionValue = (InstructionData & { path: NodePath }) | Place;
|
||||
export type InstructionValue =
|
||||
| (InstructionData & { loc: SourceLocation })
|
||||
| Place;
|
||||
|
||||
export type Phi = {
|
||||
kind: "Phi";
|
||||
@@ -199,7 +212,10 @@ export type InstructionData =
|
||||
* which are not directly represented, but included for completeness and to allow
|
||||
* passing through in codegen.
|
||||
*/
|
||||
| { kind: "OtherStatement" };
|
||||
| {
|
||||
kind: "OtherStatement";
|
||||
node: t.Statement | t.JSXSpreadChild | t.JSXFragment;
|
||||
};
|
||||
|
||||
/**
|
||||
* A place where data may be read from / written to:
|
||||
@@ -211,7 +227,7 @@ export type Place = {
|
||||
identifier: Identifier;
|
||||
memberPath: Array<string> | null;
|
||||
effect: Effect;
|
||||
path: NodePath;
|
||||
loc: SourceLocation;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -220,7 +236,7 @@ export type Place = {
|
||||
export type Primitive = {
|
||||
kind: "Primitive";
|
||||
value: number | boolean | string | null | undefined;
|
||||
path: NodePath<t.Node | null | undefined>;
|
||||
loc: SourceLocation;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -20,7 +20,7 @@ import {
|
||||
ValueKind,
|
||||
} from "./HIR";
|
||||
import { mapTerminalSuccessors } from "./HIRBuilder";
|
||||
import { printMixedHIR, printPlace } from "./PrintHIR";
|
||||
import { printMixedHIR, printPlace, printSourceLocation } from "./PrintHIR";
|
||||
|
||||
/**
|
||||
* For every usage of a value in the given function, infers the effect or action
|
||||
@@ -72,12 +72,12 @@ export default function inferReferenceEffects(fn: HIRFunction) {
|
||||
kind: "Identifier",
|
||||
memberPath: null,
|
||||
identifier: fn.id as any,
|
||||
path: null as any, // TODO
|
||||
loc: fn.loc,
|
||||
effect: Effect.Freeze,
|
||||
};
|
||||
const value: InstructionValue = {
|
||||
kind: "Primitive",
|
||||
path: null as any, // TODO
|
||||
loc: fn.loc,
|
||||
value: undefined,
|
||||
};
|
||||
initialEnvironment.initialize(value, ValueKind.Frozen);
|
||||
@@ -86,7 +86,7 @@ export default function inferReferenceEffects(fn: HIRFunction) {
|
||||
for (const param of fn.params) {
|
||||
const value: InstructionValue = {
|
||||
kind: "Primitive",
|
||||
path: null as any, // TODO
|
||||
loc: param.loc,
|
||||
value: undefined,
|
||||
};
|
||||
initialEnvironment.initialize(value, ValueKind.Frozen);
|
||||
@@ -189,7 +189,9 @@ class Environment {
|
||||
const values = this.#variables.get(place.identifier.id);
|
||||
invariant(
|
||||
values != null,
|
||||
`Expected value kind to be initialized at '${String(place.path)}'`
|
||||
`Expected value kind to be initialized at '${printSourceLocation(
|
||||
place.loc
|
||||
)}'`
|
||||
);
|
||||
let mergedKind: ValueKind | null = null;
|
||||
for (const value of values) {
|
||||
@@ -226,9 +228,7 @@ class Environment {
|
||||
);
|
||||
invariant(
|
||||
this.#values.has(value),
|
||||
`Expected value to be initialized at '${String(value.path)}' in '${String(
|
||||
value.path?.parentPath
|
||||
)}'`
|
||||
`Expected value to be initialized at '${printSourceLocation(value.loc)}'`
|
||||
);
|
||||
this.#variables.set(place.identifier.id, new Set([value]));
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import generate from "@babel/generator";
|
||||
import { assertExhaustive } from "../Common/utils";
|
||||
import {
|
||||
HIR,
|
||||
@@ -15,6 +16,7 @@ import {
|
||||
LValue,
|
||||
Phi,
|
||||
Place,
|
||||
SourceLocation,
|
||||
Terminal,
|
||||
} from "./HIR";
|
||||
|
||||
@@ -217,9 +219,7 @@ function printInstructionValue(instrValue: InstructionValue): string {
|
||||
break;
|
||||
}
|
||||
case "OtherStatement": {
|
||||
value = `Other(${instrValue.path?.node?.type}): \`${String(
|
||||
instrValue.path
|
||||
)}\``;
|
||||
value = `OtherStatement(${generate(instrValue.node).code})`;
|
||||
break;
|
||||
}
|
||||
case "Identifier": {
|
||||
@@ -270,3 +270,11 @@ export function printPlace(place: Place): string {
|
||||
export function printIdentifier(id: Identifier): string {
|
||||
return `${id.name ?? ""}\$${id.id}`;
|
||||
}
|
||||
|
||||
export function printSourceLocation(loc: SourceLocation): string {
|
||||
if (typeof loc === "symbol") {
|
||||
return "generated";
|
||||
} else {
|
||||
return `${loc.start.line}:${loc.start.column}:${loc.end.line}:${loc.end.column}`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ export default function analyzeScopes(fn: HIRFunction): ReactFunction {
|
||||
instructions: fn.body,
|
||||
});
|
||||
return {
|
||||
path: fn.path,
|
||||
loc: fn.loc,
|
||||
id: fn.id,
|
||||
params: fn.params,
|
||||
returnScope: returnScopeId,
|
||||
@@ -177,7 +177,7 @@ function analyze(fn: HIRFunction): ReactFunction {
|
||||
const scopes: Map<ScopeId, ReactiveScope> = new Map();
|
||||
|
||||
return {
|
||||
path: fn.path,
|
||||
loc: fn.loc,
|
||||
id: fn.id,
|
||||
params: fn.params,
|
||||
returnScope: returnScopeId,
|
||||
|
||||
Reference in New Issue
Block a user