mirror of
https://github.com/zebrajr/react.git
synced 2026-01-15 12:15:22 +00:00
[new-arch] Improve reference-kind analysis
This implements an alternative approach to reference kind inference in the new
architecture based on feedback. Here, we track an environment that maps
top-level identifiers (IdentifierId) to the "kind" of value stored: immutable,
mutable, frozen, or maybe-frozen. We then do a forward data flow analysis
updating this environment based on the semantics of each instruction combined
with the types of values present. For example a reference of a value in a
"mutable" position is inferred as readonly if the value is known to be frozen or
immutable. Similarly, a usage of a reference in a "freeze" position is inferred
as a freeze if the value is not yet definitively frozen, and inferred as
readonly if the value is already frozen.
When multiple control paths converge we merge the previous and new incoming
environments, and only reprocess the block if the environment changed relative
to the previous value. This has some noticeable benefits over the previous
version:
* We now infer precisely where `makeReadOnly()` calls need to be inserted, aka
points where a value needs to be frozen may not yet be frozen.
* We track immutable values and can infer their usage as readonly rather than
mutable.
* The system handles aliasing by representing values as distinct from variables,
so that we can handle situations such as:
```javascript
const a = []; // env: {a: value0; value0: mutable}
const b = a; // env: {a: value0, b: value0; value0: mutable}
freeze(a); // env: {a: value0, b: value0; value0: frozen}
mayMutate(b); // ordinarily inferred as a mutable reference, but we know its
readonly
```
This commit is contained in:
@@ -22,8 +22,8 @@ import { mapTerminalSuccessors } from "./HIRBuilder";
|
||||
import { printMixedHIR, printPlace } from "./PrintHIR";
|
||||
|
||||
const HOOKS: Map<string, Hook> = new Map([
|
||||
["useState", { kind: "State", capability: Capability.Frozen }],
|
||||
["useRef", { kind: "Ref", capability: Capability.Frozen }],
|
||||
["useState", { kind: "State", capability: Capability.Freeze }],
|
||||
["useRef", { kind: "Ref", capability: Capability.Freeze }],
|
||||
]);
|
||||
|
||||
type HookKind = { kind: "State" } | { kind: "Ref" } | { kind: "Custom" };
|
||||
@@ -86,7 +86,7 @@ export default function buildDefUseGraph(fn: HIRFunction): Array<Vertex> {
|
||||
memberPath: null,
|
||||
value: param,
|
||||
path: null as any, // TODO
|
||||
capability: Capability.Frozen,
|
||||
capability: Capability.Freeze,
|
||||
};
|
||||
preambleBuilder.init(place, null, true);
|
||||
}
|
||||
@@ -131,7 +131,7 @@ export default function buildDefUseGraph(fn: HIRFunction): Array<Vertex> {
|
||||
// Vertices derived from a frozen value are also frozen
|
||||
if (
|
||||
vertex.place !== null &&
|
||||
vertex.place.capability === Capability.Frozen
|
||||
vertex.place.capability === Capability.Freeze
|
||||
) {
|
||||
flowFrozennessForwards(vertex, 0);
|
||||
}
|
||||
@@ -157,7 +157,7 @@ function flowFrozennessForwards(vertex: Vertex, epoch: number) {
|
||||
}
|
||||
vertex.epoch = epoch;
|
||||
if (vertex.place !== null) {
|
||||
vertex.place.capability = Capability.Frozen;
|
||||
vertex.place.capability = Capability.Freeze;
|
||||
}
|
||||
for (const outgoing of vertex.outgoing) {
|
||||
flowFrozennessForwards(outgoing, epoch);
|
||||
@@ -260,7 +260,7 @@ function buildInputsOutputsForBlock(
|
||||
let valueCapability = Capability.Readonly;
|
||||
switch (instrValue.kind) {
|
||||
case "BinaryExpression": {
|
||||
valueCapability = Capability.Frozen;
|
||||
valueCapability = Capability.Freeze;
|
||||
builder.reference(instrValue.left, instrValue, Capability.Readonly);
|
||||
builder.reference(instrValue.right, instrValue, Capability.Readonly);
|
||||
break;
|
||||
@@ -301,7 +301,7 @@ function buildInputsOutputsForBlock(
|
||||
break;
|
||||
}
|
||||
case "UnaryExpression": {
|
||||
valueCapability = Capability.Frozen; // TODO check that value must be a primitive, or make conditional based on the operator
|
||||
valueCapability = Capability.Freeze; // TODO check that value must be a primitive, or make conditional based on the operator
|
||||
builder.reference(instrValue.value, instrValue, Capability.Readonly);
|
||||
break;
|
||||
}
|
||||
@@ -310,13 +310,13 @@ function buildInputsOutputsForBlock(
|
||||
break;
|
||||
}
|
||||
case "JsxExpression": {
|
||||
builder.reference(instrValue.tag, instrValue, Capability.Frozen);
|
||||
builder.reference(instrValue.tag, instrValue, Capability.Freeze);
|
||||
for (const [_prop, value] of Object.entries(instrValue.props)) {
|
||||
builder.reference(value, instrValue, Capability.Frozen);
|
||||
builder.reference(value, instrValue, Capability.Freeze);
|
||||
}
|
||||
if (instrValue.children !== null) {
|
||||
for (const child of instrValue.children) {
|
||||
builder.reference(child, instrValue, Capability.Frozen);
|
||||
builder.reference(child, instrValue, Capability.Freeze);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -354,7 +354,7 @@ function buildInputsOutputsForBlock(
|
||||
builder.reference(
|
||||
block.terminal.value,
|
||||
block.terminal,
|
||||
Capability.Frozen
|
||||
Capability.Freeze
|
||||
);
|
||||
break;
|
||||
}
|
||||
@@ -363,7 +363,7 @@ function buildInputsOutputsForBlock(
|
||||
builder.reference(
|
||||
block.terminal.value,
|
||||
block.terminal,
|
||||
Capability.Frozen
|
||||
Capability.Freeze
|
||||
);
|
||||
}
|
||||
break;
|
||||
@@ -416,7 +416,7 @@ function parseHookCall(place: Place): Hook | null {
|
||||
if (hook != null) {
|
||||
return hook;
|
||||
}
|
||||
return { kind: "Custom", capability: Capability.Frozen };
|
||||
return { kind: "Custom", capability: Capability.Freeze };
|
||||
}
|
||||
|
||||
type BlockResult = {
|
||||
|
||||
@@ -221,12 +221,11 @@ export type Identifier = {
|
||||
export enum Capability {
|
||||
// Default value: not allowed after lifetime inference
|
||||
Unknown = "<unknown>",
|
||||
// The value is known to be deeply, permanently mutable at this point.
|
||||
Frozen = "frozen",
|
||||
// The value is not modified at this point or thereafter, but is not guaranteed to be
|
||||
// frozen. It would be safe to freeze the value at this point.
|
||||
// The value is made frozen at this point.
|
||||
Freeze = "freeze",
|
||||
// The value is not modified at this point.
|
||||
Readonly = "readonly",
|
||||
// The value is mutated at this point or at some later point.
|
||||
// The value is modified at this point.
|
||||
Mutable = "mutable",
|
||||
}
|
||||
|
||||
|
||||
@@ -1,676 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import invariant from "invariant";
|
||||
import { assertExhaustive } from "../Common/utils";
|
||||
import {
|
||||
BasicBlock,
|
||||
BlockId,
|
||||
Capability,
|
||||
HIRFunction,
|
||||
IdentifierId,
|
||||
Instruction,
|
||||
InstructionValue,
|
||||
Place,
|
||||
Terminal,
|
||||
} from "./HIR";
|
||||
import { printMixedHIR, printPlace } from "./PrintHIR";
|
||||
|
||||
const HOOKS: Map<string, Hook> = new Map([
|
||||
["useState", { kind: "State", capability: Capability.Frozen }],
|
||||
["useRef", { kind: "Ref", capability: Capability.Frozen }],
|
||||
]);
|
||||
|
||||
type HookKind = { kind: "State" } | { kind: "Ref" } | { kind: "Custom" };
|
||||
type Hook = HookKind & { capability: Capability };
|
||||
|
||||
/**
|
||||
* For every usage of a value, infers whether the value is accessed as frozen, mutable,
|
||||
* or readonly:
|
||||
* - Frozen: the value is known to be deeply immutable. This usage cannot alter the value,
|
||||
* and the value cannot change after this usage. The usage can therefore safely memoize
|
||||
* based on the value.
|
||||
* - Mutable: the value may be modified by this or a subsequent usage.
|
||||
* - Readonly: the value is not modified by this or any subsequent usage, but was previously
|
||||
* mutable. Thus the first usage of a value as readonly (after a previous mutable usage)
|
||||
* is a point at which the value could safely frozen.
|
||||
*
|
||||
* In general usages default to be inferred as readonly (for operations that read) or mutable
|
||||
* (for operations that may write). Usages can only be inferred as frozen when:
|
||||
* - The value is derived from a reactive input: props, a hook argument. Derived here means
|
||||
* that the value is itself a reactive input (`props`) or statically known to be extracted
|
||||
* purely from a reactive input (`props.a`, `props.a[1]` etc).
|
||||
* - The value is "moved" into a reactive ouput, ie is captured into a component/hook return
|
||||
* value.
|
||||
* - The value is known to be a primitive (boolean, number, string, null, or undefined). This
|
||||
* is only the case when the value is a constant primitive *or* is the result of an
|
||||
* operation that, under JS semantics, must produce a primitive. Examples are binary
|
||||
* expressions.
|
||||
*
|
||||
* ## Algorithm
|
||||
* Fixpoint iteration of the CFG to construct use-use chains (graphs) in which nodes
|
||||
* are usages of a particular value and the required capability (frozen/read/write),
|
||||
* and each "usage" node points to predecessor node(s). Iteration stops once no new
|
||||
* edges/nodes need to be added to the graph.
|
||||
*
|
||||
* After construction, walk the graph to propagate frozenness forward and mutability
|
||||
* backward:
|
||||
* - If a usage of a value is frozen, then any subsequent usage of that value must be
|
||||
* frozen as well. Flow the frozenness forward through the graph, following only
|
||||
* use chains (outoing edges, but not captures).
|
||||
* - If a usage of a vale is mutable, then any prior readonly references of that value
|
||||
* must be marked as mutable as well (since there is a subsequent mutation). Again,
|
||||
* usages only remain readonly if there is no subsequent mutation.
|
||||
* - Finally, any value that is *initialized* as readonly and never modified (ie, that is
|
||||
* still readonly in the graph) can be marked frozen (and all of its usages as frozen),
|
||||
* since it is never ever modified.
|
||||
*/
|
||||
export default function inferLifetimes(fn: HIRFunction): Map<Place, Vertex> {
|
||||
const graph = UseGraph.empty();
|
||||
for (const param of fn.params) {
|
||||
const place: Place = {
|
||||
kind: "Identifier",
|
||||
memberPath: null,
|
||||
value: param,
|
||||
path: null as any, // TODO
|
||||
capability: Capability.Frozen,
|
||||
};
|
||||
graph.init(place, null);
|
||||
}
|
||||
|
||||
const queue: Array<QueueEntry> = [{ block: fn.body.entry, graph }];
|
||||
const blockMemory: Map<BlockId, UseGraph> = new Map();
|
||||
while (queue.length !== 0) {
|
||||
const { block: blockId, graph: inputGraph } = queue.shift()!;
|
||||
const prevGraph = blockMemory.get(blockId);
|
||||
let nextGraph = null;
|
||||
if (prevGraph == null) {
|
||||
blockMemory.set(blockId, inputGraph);
|
||||
nextGraph = inputGraph.snapshot();
|
||||
} else {
|
||||
const merged = prevGraph.snapshot();
|
||||
const hasChanges = merged.merge(inputGraph);
|
||||
if (!hasChanges) {
|
||||
continue;
|
||||
}
|
||||
blockMemory.set(blockId, merged);
|
||||
nextGraph = prevGraph.snapshot();
|
||||
}
|
||||
|
||||
const block = fn.body.blocks.get(blockId)!;
|
||||
inferBlock(nextGraph, block);
|
||||
|
||||
const terminal = block.terminal;
|
||||
switch (terminal.kind) {
|
||||
case "throw": {
|
||||
nextGraph.reference(terminal.value, terminal, Capability.Frozen);
|
||||
break;
|
||||
}
|
||||
case "return": {
|
||||
if (terminal.value !== null) {
|
||||
nextGraph.reference(terminal.value, terminal, Capability.Frozen);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "goto": {
|
||||
queue.push({ block: terminal.block, graph: nextGraph });
|
||||
break;
|
||||
}
|
||||
case "if": {
|
||||
nextGraph.reference(terminal.test, terminal, Capability.Readonly);
|
||||
queue.push({ block: terminal.consequent, graph: nextGraph });
|
||||
queue.push({ block: terminal.alternate, graph: nextGraph });
|
||||
break;
|
||||
}
|
||||
case "switch": {
|
||||
nextGraph.reference(terminal.test, terminal, Capability.Readonly);
|
||||
for (const case_ of terminal.cases) {
|
||||
if (case_.test !== null) {
|
||||
nextGraph.reference(case_.test, terminal, Capability.Readonly);
|
||||
}
|
||||
queue.push({ block: case_.block, graph: nextGraph.snapshot() });
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
assertExhaustive(terminal, "Unexpected terminal kind");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// perform inference over the constructed graph and return it
|
||||
return analyzeGraph(graph);
|
||||
}
|
||||
|
||||
type QueueEntry = {
|
||||
block: BlockId;
|
||||
graph: UseGraph;
|
||||
};
|
||||
|
||||
function analyzeGraph(graph: UseGraph): Map<Place, Vertex> {
|
||||
const vertices = graph.build();
|
||||
let epoch = 0;
|
||||
|
||||
// First flow frozen values forward through the graph
|
||||
for (const vertex of vertices.values()) {
|
||||
if (vertex.place.capability === Capability.Frozen) {
|
||||
flowFrozennessForwards(vertex, epoch++);
|
||||
}
|
||||
}
|
||||
// Then flow mutability backward through the graph
|
||||
for (const vertex of vertices.values()) {
|
||||
if (vertex.place.capability === Capability.Mutable) {
|
||||
flowMutabilityBackwards(vertex, epoch++);
|
||||
}
|
||||
}
|
||||
// Finally, any *entry* nodes that are readonly are now known to never be mutated,
|
||||
// so convert them to frozen (and flow that frozenness forward)
|
||||
for (const vertex of vertices.values()) {
|
||||
invariant(
|
||||
vertex.place.capability !== Capability.Unknown,
|
||||
"Expected capability to have been inferred as frozen, readonly, or mutable"
|
||||
);
|
||||
if (
|
||||
vertex.place.capability === Capability.Readonly &&
|
||||
vertex.incoming.size === 0
|
||||
) {
|
||||
flowFrozennessForwards(vertex, epoch);
|
||||
}
|
||||
}
|
||||
return vertices;
|
||||
}
|
||||
|
||||
/**
|
||||
* Once a value is known to be frozen, all usages forward of that point must be frozen too.
|
||||
*/
|
||||
function flowFrozennessForwards(vertex: Vertex, epoch: number) {
|
||||
if (vertex.epoch === epoch) {
|
||||
return;
|
||||
}
|
||||
vertex.epoch = epoch;
|
||||
vertex.place.capability = Capability.Frozen;
|
||||
for (const outgoing of vertex.outgoing) {
|
||||
flowFrozennessForwards(outgoing, epoch);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If a value is known to be mutable, any previous readonly references must be mutable too.
|
||||
*/
|
||||
function flowMutabilityBackwards(vertex: Vertex, epoch: number) {
|
||||
if (vertex.epoch === epoch) {
|
||||
return;
|
||||
}
|
||||
vertex.epoch = epoch;
|
||||
if (vertex.place.capability === Capability.Frozen) {
|
||||
return;
|
||||
}
|
||||
vertex.place.capability = Capability.Mutable;
|
||||
for (const incoming of vertex.incoming) {
|
||||
flowMutabilityBackwards(incoming, epoch);
|
||||
}
|
||||
for (const [id, capture] of vertex.captures) {
|
||||
flowMutabilityBackwards(capture, epoch);
|
||||
}
|
||||
}
|
||||
|
||||
function inferBlock(graph: UseGraph, block: BasicBlock) {
|
||||
for (const instr of block.instructions) {
|
||||
if (instr.lvalue !== null) {
|
||||
if (instr.lvalue.place.memberPath == null) {
|
||||
graph.init(instr.lvalue.place, instr);
|
||||
} else {
|
||||
graph.reference(instr.lvalue.place, instr, Capability.Mutable);
|
||||
}
|
||||
}
|
||||
const instrValue = instr.value;
|
||||
let valueCapability = Capability.Readonly;
|
||||
switch (instrValue.kind) {
|
||||
case "BinaryExpression": {
|
||||
valueCapability = Capability.Frozen;
|
||||
graph.reference(instrValue.left, instrValue, Capability.Readonly);
|
||||
graph.reference(instrValue.right, instrValue, Capability.Readonly);
|
||||
break;
|
||||
}
|
||||
case "ArrayExpression": {
|
||||
for (const element of instrValue.elements) {
|
||||
graph.reference(element, instrValue, Capability.Readonly);
|
||||
if (instr.lvalue !== null) {
|
||||
graph.capture(instr.lvalue.place, instr, element);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "NewExpression": {
|
||||
graph.reference(instrValue.callee, instrValue, Capability.Mutable);
|
||||
let prevArg: Place | null = null;
|
||||
for (const arg of instrValue.args) {
|
||||
graph.reference(arg, instrValue, Capability.Mutable);
|
||||
if (instr.lvalue !== null) {
|
||||
graph.capture(instr.lvalue.place, instr, arg);
|
||||
}
|
||||
if (prevArg !== null) {
|
||||
graph.capture(prevArg, instr, arg);
|
||||
}
|
||||
prevArg = arg;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "CallExpression": {
|
||||
let capability = Capability.Mutable;
|
||||
const hook = parseHookCall(instrValue.callee);
|
||||
if (hook !== null) {
|
||||
capability = hook.capability;
|
||||
valueCapability = hook.capability;
|
||||
}
|
||||
graph.reference(instrValue.callee, instrValue, capability);
|
||||
let prevArg: Place | null = null;
|
||||
for (const arg of instrValue.args) {
|
||||
graph.reference(arg, instrValue, capability);
|
||||
if (instr.lvalue !== null) {
|
||||
graph.capture(instr.lvalue.place, instr, arg);
|
||||
}
|
||||
if (prevArg !== null) {
|
||||
graph.capture(prevArg, instr, arg);
|
||||
}
|
||||
prevArg = arg;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "ObjectExpression": {
|
||||
// Object construction captures but does not modify the key/property values
|
||||
if (instrValue.properties !== null) {
|
||||
for (const [_key, value] of Object.entries(instrValue.properties)) {
|
||||
graph.reference(value, instrValue, Capability.Readonly);
|
||||
if (instr.lvalue !== null) {
|
||||
graph.capture(instr.lvalue.place, instr, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "UnaryExpression": {
|
||||
valueCapability = Capability.Frozen; // TODO check that value must be a primitive, or make conditional based on the operator
|
||||
graph.reference(instrValue.value, instrValue, Capability.Readonly);
|
||||
break;
|
||||
}
|
||||
case "OtherStatement": {
|
||||
// TODO: handle other statement kinds
|
||||
break;
|
||||
}
|
||||
case "JsxExpression": {
|
||||
graph.reference(instrValue.tag, instrValue, Capability.Readonly);
|
||||
for (const [_prop, value] of Object.entries(instrValue.props)) {
|
||||
graph.reference(value, instrValue, Capability.Readonly);
|
||||
if (instr.lvalue !== null) {
|
||||
graph.capture(instr.lvalue.place, instr, value);
|
||||
}
|
||||
}
|
||||
if (instrValue.children !== null) {
|
||||
for (const child of instrValue.children) {
|
||||
graph.reference(child, instrValue, Capability.Readonly);
|
||||
if (instr.lvalue !== null) {
|
||||
graph.capture(instr.lvalue.place, instr, child);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "JSXText":
|
||||
case "Primitive": {
|
||||
valueCapability = Capability.Frozen;
|
||||
break;
|
||||
}
|
||||
case "Identifier": {
|
||||
graph.reference(instrValue, instrValue, Capability.Readonly);
|
||||
if (instr.lvalue !== null) {
|
||||
graph.assign(instr.lvalue.place, instr, instrValue);
|
||||
}
|
||||
valueCapability = instrValue.capability;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
assertExhaustive(instrValue, "Unexpected instruction kind");
|
||||
}
|
||||
}
|
||||
if (instr.lvalue !== null) {
|
||||
instr.lvalue.place.capability = valueCapability;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function parseHookCall(place: Place): Hook | null {
|
||||
if (place.memberPath !== null) {
|
||||
// Hook calls must be statically resolved
|
||||
return null;
|
||||
}
|
||||
const name = place.value.name;
|
||||
if (name === null || !name.match(/^_?use/)) {
|
||||
return null;
|
||||
}
|
||||
const hook = HOOKS.get(name);
|
||||
if (hook != null) {
|
||||
return hook;
|
||||
}
|
||||
return { kind: "Custom", capability: Capability.Frozen };
|
||||
}
|
||||
|
||||
/**
|
||||
* A graph of usages of references within a program.
|
||||
*/
|
||||
class UseGraph {
|
||||
/**
|
||||
* Represents the last usage for each top-level identifier (by IdentifierId)
|
||||
* in the program. So after `let x = []`, there will be an entry mapping
|
||||
* `x` to a vertex. A subsequent `x.y` reference will update the mapping
|
||||
* for `x` to point to a new vertex, with the previous `let x = []` as
|
||||
* an incoming edge. Note again that vertices are always created based
|
||||
* on the top-level identifier id and ignore member paths.
|
||||
*/
|
||||
#nodes: Map<IdentifierId, Vertex>;
|
||||
|
||||
/**
|
||||
* A mapping of places to vertices, allowing repeated operations against
|
||||
* the same place (eg referencing, assigning, etc) to update the single
|
||||
* vertex for that place.
|
||||
*
|
||||
* NOTE: this algorithm and data structure relies on `Place` instances
|
||||
* being unique, hence BuildHIR is careful to clone Place instances rather
|
||||
* than use structural sharing.
|
||||
*/
|
||||
#vertices: Map<Place, Vertex>;
|
||||
|
||||
static empty(): UseGraph {
|
||||
return new UseGraph(new Map(), new Map());
|
||||
}
|
||||
|
||||
constructor(nodes: Map<IdentifierId, Vertex>, vertices: Map<Place, Vertex>) {
|
||||
this.#nodes = nodes;
|
||||
this.#vertices = vertices;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup the current vertex for a given identifier.
|
||||
*/
|
||||
lookup(id: IdentifierId): Vertex | null {
|
||||
return this.#nodes.get(id) ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents assignment of a value to a Place. Unlike with `reference()`,
|
||||
* this does *not* establish an edge between this usage of the place and
|
||||
* previous usages, because the value is not the same.
|
||||
*/
|
||||
init(place: Place, instr: Instruction | null) {
|
||||
let vertex = this.#vertices.get(place);
|
||||
if (vertex == null) {
|
||||
vertex = new Vertex(place, instr);
|
||||
this.#vertices.set(place, vertex);
|
||||
}
|
||||
this.#nodes.set(place.value.id, vertex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents assigning a (new) value to @param target via the given @param instr,
|
||||
* with @param value as the value being assigned.
|
||||
*
|
||||
* This breaks the use chain, such that this and subsequent usages of @param target
|
||||
* are not associated to previous usages. This replicates SSA semantics, conceptually
|
||||
* @param target is a new place now.
|
||||
*/
|
||||
assign(target: Place, instr: Instruction, value: Place) {
|
||||
this.init(target, instr);
|
||||
if (value.capability === Capability.Frozen) {
|
||||
target.capability = Capability.Frozen;
|
||||
}
|
||||
this.capture(target, instr, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents data flow in which two places capture references to each other,
|
||||
* such that a mutation of one place may affect data accessible via the other
|
||||
* place or vice versa. This includes assignment (`x = y`) but also things like
|
||||
* array or object construction, where `x = [y]` means that modifying either
|
||||
* `x` or `y` _could_ be visible through either refernece (eg `x[0].foo = ...`)
|
||||
* would modify `y`.
|
||||
*/
|
||||
capture(target: Place, instr: Instruction, value: Place) {
|
||||
const targetVertex = this.#vertices.get(target)!;
|
||||
const valueVertex = this.#vertices.get(value)!;
|
||||
|
||||
if (
|
||||
targetVertex.place.capability === Capability.Frozen ||
|
||||
valueVertex.place.capability === Capability.Frozen
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
targetVertex.captures.set(value.value.id, valueVertex);
|
||||
valueVertex.captures.set(target.value.id, targetVertex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a reference (usage of) a Place. This establishes an edge
|
||||
* with this usage and the previous usage
|
||||
*/
|
||||
reference(
|
||||
place: Place,
|
||||
instr: Instruction | InstructionValue | Terminal,
|
||||
capability: Capability
|
||||
) {
|
||||
place.capability = capability;
|
||||
let vertex = this.#vertices.get(place);
|
||||
if (vertex == null) {
|
||||
vertex = new Vertex(place, instr);
|
||||
this.#vertices.set(place, vertex);
|
||||
}
|
||||
|
||||
let prev = this.#nodes.get(place.value.id);
|
||||
if (prev != null) {
|
||||
vertex.incoming.add(prev);
|
||||
prev.outgoing.add(vertex);
|
||||
|
||||
for (const [id, _vertex] of prev.captures) {
|
||||
const capture = this.#nodes.get(id)!;
|
||||
if (capture.captures.has(place.value.id)) {
|
||||
vertex.captures.set(id, capture);
|
||||
}
|
||||
}
|
||||
|
||||
if (prev.place.capability === Capability.Frozen) {
|
||||
vertex.place.capability = Capability.Frozen;
|
||||
}
|
||||
}
|
||||
this.#nodes.set(place.value.id, vertex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a snapshot of the graph that can be used to represent different
|
||||
* control flows paths, and which later may merge together (see `merge()`).
|
||||
*
|
||||
* The snapshot contains a distinct mapping of the most recent vertex per
|
||||
* identifier, but *shares* the mapping of places to vertices (vertices are
|
||||
* stable across different control flow paths).
|
||||
*
|
||||
* The intent is that fixpoint iteration relies on updating the `#nodes`
|
||||
* mapping of identifiers to most recent vertex, but the underlying graph
|
||||
* of vertices is intended to be shared across control flow paths.
|
||||
*/
|
||||
snapshot(): UseGraph {
|
||||
const nodes = new Map(this.#nodes);
|
||||
return new UseGraph(nodes, this.#vertices);
|
||||
}
|
||||
|
||||
/**
|
||||
* Giver some @param other use graph that shares an ancestor with @param this,
|
||||
* merges the graphs together and returns whether there were any changes to
|
||||
* the underlying edges (if any new edges were added).
|
||||
*
|
||||
* Note that @param this and @param other must share an ancestor, ie one must
|
||||
* be derived from a `snapshot()` of the other, or they must both be derived
|
||||
* from a `snapshot()` of the same instance.
|
||||
*/
|
||||
merge(other: UseGraph): boolean {
|
||||
let hasChange = false;
|
||||
for (const [id, newIncoming] of other.#nodes) {
|
||||
const prevIncoming = this.#nodes.get(id);
|
||||
if (prevIncoming == null || newIncoming === prevIncoming) {
|
||||
continue;
|
||||
}
|
||||
for (const prevOutgoing of prevIncoming.outgoing) {
|
||||
hasChange =
|
||||
hasChange ||
|
||||
!prevOutgoing.incoming.has(newIncoming) ||
|
||||
!newIncoming.outgoing.has(prevOutgoing);
|
||||
prevOutgoing.incoming.add(newIncoming);
|
||||
newIncoming.outgoing.add(prevOutgoing);
|
||||
}
|
||||
}
|
||||
return hasChange;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the mapping of places to vertices.
|
||||
*/
|
||||
build(): Map<Place, Vertex> {
|
||||
return this.#vertices;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a distinct usage of a `Place` within a program. Note that
|
||||
* vertices are only created for top-level identifiers, not for points
|
||||
* within an object. So both `x` and `x.y` create vertices for `x`,
|
||||
* though this is enforced by the _construction_ of vertices in UseGraph,
|
||||
* not the implementation of Vertex itself.
|
||||
*/
|
||||
class Vertex {
|
||||
/**
|
||||
* A set of vertices whose values are captured into this vertex, keyed
|
||||
* by the identifier of the captured value. This represents any form
|
||||
* of capturing, including:
|
||||
* - direct assignment: `x = y`, `x.y = y`, `x[0] = y` all captures
|
||||
* x into y and vice-versa.
|
||||
* - composition of objects into arrays, object, jsx: `<foo>{x}{y}</div>`,
|
||||
* `{k1: x, k2: y}`, and `[x, y]` all capture x and y into the outer
|
||||
* value (jsx, object, array, respectively).
|
||||
* - Mutation that could cause values to take references into each other:
|
||||
* `foo(x, y)` could modify x and/or y in a way that they are assigned
|
||||
* into each other (eg it could internally do `x.y = y`, `y.x = x` etc).
|
||||
*
|
||||
* Note that the representation only stores *one* vertex for each identifier,
|
||||
* so eg `y.x = x` the `y` vertex can only store a capture of *one* vertex
|
||||
* for `x`. If there are multiple potentially prior usages of x when this
|
||||
* occurs, we have to take care that they are both represnted as captured:
|
||||
*
|
||||
* ```javascript
|
||||
* let x;
|
||||
* if (cond) {
|
||||
* x = [1];
|
||||
* } else {
|
||||
* x = [2]
|
||||
* }
|
||||
* y = x;
|
||||
* ```
|
||||
* The final line must reflect that y captures *either* of the two possible
|
||||
* values of `x`. This is achieved by *first* using `x`, *then* capturing.
|
||||
* The usage will create a single new `x` vertex in the final scope, to which
|
||||
* there are two incoming edges. Then the capture of `x` into `y` references
|
||||
* that single x vertex with two incoming edges. Thus the data model can capture
|
||||
* this case, but the order of construction is important.
|
||||
*
|
||||
* The result is a graph such as:
|
||||
*
|
||||
* [x @ let x] -> [ x @ x = [1] ] -> [ x @ y = x]
|
||||
* └--> [ x @ x = [2] ] ---┘ ↑
|
||||
* | capture
|
||||
* ↓
|
||||
* [ y @ y - x]
|
||||
*
|
||||
* Note that it's possible to walk from `y` to both of the possible x values.
|
||||
*/
|
||||
captures: Map<IdentifierId, Vertex> = new Map();
|
||||
|
||||
/**
|
||||
* the set of vertices where *this* place was previously referenced
|
||||
*/
|
||||
incoming: Set<Vertex> = new Set();
|
||||
|
||||
/**
|
||||
* the set of vertices where *this* place is subseqently referenced
|
||||
*/
|
||||
outgoing: Set<Vertex> = new Set();
|
||||
|
||||
/**
|
||||
* The place that is using the value.
|
||||
*/
|
||||
place: Place;
|
||||
|
||||
/**
|
||||
* The instruction where the reference occurs (for debugging)
|
||||
*/
|
||||
instr: Instruction | InstructionValue | Terminal | null;
|
||||
|
||||
/**
|
||||
* The last epoch in which this vertex was visited. This is used during
|
||||
* data-flow analysis post construction of the graph to ensure termination
|
||||
* by avoiding revisiting the same nodes in a given pass.
|
||||
*/
|
||||
epoch: number | null = null;
|
||||
|
||||
constructor(
|
||||
place: Place,
|
||||
instr: Instruction | InstructionValue | Terminal | null
|
||||
) {
|
||||
this.place = place;
|
||||
this.instr = instr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the graph into GraphViz DOT format.
|
||||
* https://graphviz.org/doc/info/lang.html
|
||||
*/
|
||||
export function printGraph(vertices: Map<Place, Vertex>): string {
|
||||
const output = [];
|
||||
|
||||
// Maps vertices to short string names. Note that multiple vertex instances
|
||||
// can share the same Place, so we can't use the place (identifier/path etc).
|
||||
// Instead we create an auto-incrementing index.
|
||||
const indices: Map<Vertex, string> = new Map();
|
||||
function identify(vertex: Vertex): string {
|
||||
let id = indices.get(vertex);
|
||||
if (id == null) {
|
||||
id = `v${indices.size}`;
|
||||
indices.set(vertex, id);
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
for (const [place, vertex] of vertices) {
|
||||
const vertexId = identify(vertex);
|
||||
output.push(
|
||||
`${vertexId} [ label="${vertexId} (${printPlace(vertex.place)} @ ${
|
||||
vertex.instr
|
||||
? printMixedHIR(vertex.instr).replaceAll('"', '\\"')
|
||||
: "<no-instr>"
|
||||
})", shape="box" ]`
|
||||
);
|
||||
for (const outgoing of vertex.outgoing) {
|
||||
const outgoingId = identify(outgoing);
|
||||
output.push(`${vertexId} -> ${outgoingId}`);
|
||||
}
|
||||
for (const [id, capture] of vertex.captures) {
|
||||
const captureId = identify(capture);
|
||||
output.push(`${captureId} -> ${vertexId} [ label="capture" ]`);
|
||||
}
|
||||
}
|
||||
const lines = output.map((line) => " " + line);
|
||||
lines.unshift("digraph InferMutability {");
|
||||
lines.push("}");
|
||||
return lines.join("\n");
|
||||
}
|
||||
705
compiler/forget/src/HIR/InferReferenceCapability.ts
Normal file
705
compiler/forget/src/HIR/InferReferenceCapability.ts
Normal file
@@ -0,0 +1,705 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import { assertExhaustive } from "../Common/utils";
|
||||
import { invariant } from "../CompilerError";
|
||||
import {
|
||||
BasicBlock,
|
||||
BlockId,
|
||||
Capability,
|
||||
HIRFunction,
|
||||
IdentifierId,
|
||||
Instruction,
|
||||
InstructionValue,
|
||||
Place,
|
||||
Terminal,
|
||||
} from "./HIR";
|
||||
import { mapTerminalSuccessors } from "./HIRBuilder";
|
||||
import { printMixedHIR } from "./PrintHIR";
|
||||
|
||||
/**
|
||||
* For every usage of a value in the given function, infers the capability or action
|
||||
* taken at that reference. Each reference is inferred as exactly one of:
|
||||
* - freeze: this usage freezes the value, ie converts it to frozen. This is only inferred
|
||||
* when the value *may* not already be frozen.
|
||||
* - frozen: the value is known to already be "owned" by React and is therefore already
|
||||
* frozen (permanently and transitively immutable).
|
||||
* - immutable: the value is not owned by React, but is known to be an immutable value
|
||||
* that therefore cannot ever change.
|
||||
* - readonly: the value is not frozen or immutable, but this usage of the value does
|
||||
* not modify it. the value may be mutated by a subsequent reference. Examples include
|
||||
* referencing the operands of a binary expression, or referencing the items/properties
|
||||
* of an array or object literal.
|
||||
* - mutable: the value is not frozen or immutable, and this usage *may* modify it.
|
||||
* Examples include passing a value to as a function argument or assigning into an object.
|
||||
*
|
||||
* Note that the inference follows variable assignment, so assigning a frozen value
|
||||
* to a different value will infer usages of the other variable as frozen as well.
|
||||
*
|
||||
* The inference assumes that the code follows the rules of React:
|
||||
* - React function arguments are frozen (component props, hook arguments).
|
||||
* - Hook arguments are frozen at the point the hook is invoked.
|
||||
* - React function return values are frozen at the point of being returned,
|
||||
* thus the return value of a hook call is frozen.
|
||||
* - JSX represents invocation of a React function (the component) and
|
||||
* therefore all values passed to JSX become frozen at the point the JSX
|
||||
* is created.
|
||||
*
|
||||
* Internally, the inference tracks the approximate type of value held by each variable,
|
||||
* and iterates over the control flow graph. The inferred capability of reach reference is
|
||||
* a combination of the operation performed (ie, assignment into an object mutably uses the
|
||||
* object; an if condition reads the condition) and the type of the value. The types of values
|
||||
* are:
|
||||
* - frozen: can be any type so long as the value is known to be owned by React, permanently
|
||||
* and transitively immutable
|
||||
* - maybe-frozen: the value may or may not be frozen, conditionally depending on control flow.
|
||||
* - immutable: a type with value semantics: primitives, records/tuples when standardized.
|
||||
* - mutable: a type with reference semantics eg array, object, class instance, etc.
|
||||
*
|
||||
* When control flow paths converge the types of values are merged together, with the value
|
||||
* types forming a lattice to ensure convergence.
|
||||
*/
|
||||
export default function inferReferenceCapability(fn: HIRFunction) {
|
||||
// Initial environment contains function params
|
||||
// TODO: include module declarations here as well
|
||||
const initialEnvironment = Environment.empty();
|
||||
const id: Place = {
|
||||
kind: "Identifier",
|
||||
memberPath: null,
|
||||
value: fn.id as any,
|
||||
path: null as any, // TODO
|
||||
capability: Capability.Freeze,
|
||||
};
|
||||
const value: InstructionValue = {
|
||||
kind: "Primitive",
|
||||
path: null as any, // TODO
|
||||
value: undefined,
|
||||
};
|
||||
initialEnvironment.initialize(value, ValueKind.Frozen);
|
||||
initialEnvironment.define(id, value);
|
||||
|
||||
for (const param of fn.params) {
|
||||
const place: Place = {
|
||||
kind: "Identifier",
|
||||
memberPath: null,
|
||||
value: param,
|
||||
path: null as any, // TODO
|
||||
capability: Capability.Freeze,
|
||||
};
|
||||
const value: InstructionValue = {
|
||||
kind: "Primitive",
|
||||
path: null as any, // TODO
|
||||
value: undefined,
|
||||
};
|
||||
initialEnvironment.initialize(value, ValueKind.Frozen);
|
||||
initialEnvironment.define(place, value);
|
||||
}
|
||||
|
||||
// Queue of blocks to visit, with block and the incoming Environment value
|
||||
const queue: Array<QueueEntry> = [
|
||||
{ blockId: fn.body.entry, environment: initialEnvironment },
|
||||
];
|
||||
// Map of blocks to the last incoming environment that was processed
|
||||
const environmentsByBlock: Map<BlockId, Environment> = new Map();
|
||||
|
||||
while (queue.length !== 0) {
|
||||
const { blockId, environment: incomingEnvironment } = queue.shift()!;
|
||||
|
||||
let previousEnvironment = environmentsByBlock.get(blockId);
|
||||
let nextEnvironment: Environment | null = null;
|
||||
if (previousEnvironment === undefined) {
|
||||
// If no previous environment, save the incoming environment and
|
||||
// infer the block with this environment
|
||||
environmentsByBlock.set(blockId, incomingEnvironment);
|
||||
nextEnvironment = incomingEnvironment.clone();
|
||||
} else {
|
||||
// If there's a previous environment, merge the previous/new incoming
|
||||
// environments. If there are no changes, then the block can be skipped.
|
||||
// otherwise save the merged environment and revisit the block with it.
|
||||
const mergedEnvironment = previousEnvironment.merge(incomingEnvironment);
|
||||
if (mergedEnvironment !== null) {
|
||||
environmentsByBlock.set(blockId, mergedEnvironment);
|
||||
nextEnvironment = mergedEnvironment.clone();
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
const environment = nextEnvironment; // rebind to preserve the non-null refinement
|
||||
const block = fn.body.blocks.get(blockId)!;
|
||||
inferBlock(environment, block);
|
||||
|
||||
// TODO: add a `forEachTerminalSuccessor` helper, we don't actually want the result
|
||||
// here
|
||||
const _ = mapTerminalSuccessors(
|
||||
block.terminal,
|
||||
(nextBlockId, isFallthrough) => {
|
||||
if (!isFallthrough) {
|
||||
queue.push({ blockId: nextBlockId, environment });
|
||||
}
|
||||
return nextBlockId;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
type QueueEntry = {
|
||||
blockId: BlockId;
|
||||
environment: Environment;
|
||||
};
|
||||
|
||||
/**
|
||||
* Maintains a mapping of top-level variables to the kind of value they hold
|
||||
*/
|
||||
class Environment {
|
||||
// The kind of reach value, based on its allocation site
|
||||
#values: Map<InstructionValue, ValueKind>;
|
||||
// The set of values pointed to by each identifier. This is a set
|
||||
// to accomodate phi points (where a variable may have different
|
||||
// values from different control flow paths).
|
||||
#variables: Map<IdentifierId, Set<InstructionValue>>;
|
||||
|
||||
constructor(
|
||||
values: Map<InstructionValue, ValueKind>,
|
||||
variables: Map<IdentifierId, Set<InstructionValue>>
|
||||
) {
|
||||
this.#values = values;
|
||||
this.#variables = variables;
|
||||
}
|
||||
|
||||
static empty(): Environment {
|
||||
return new Environment(new Map(), new Map());
|
||||
}
|
||||
|
||||
/**
|
||||
* (Re)initializes a @param value with its default @param kind.
|
||||
*/
|
||||
initialize(
|
||||
value: InstructionValue,
|
||||
kind: ValueKind,
|
||||
instr: Instruction | null = null
|
||||
) {
|
||||
invariant(
|
||||
value.kind !== "Identifier" || value.memberPath !== null,
|
||||
"Expected all top-level identifiers to be defined as variables, not values"
|
||||
);
|
||||
this.#values.set(value, kind);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup the kind of the given @param value.
|
||||
*/
|
||||
kind(place: Place): ValueKind {
|
||||
const values = this.#variables.get(place.value.id);
|
||||
invariant(
|
||||
values != null,
|
||||
`Expected value kind to be initialized at '${String(place.path)}'`
|
||||
);
|
||||
let mergedKind: ValueKind | null = null;
|
||||
for (const value of values) {
|
||||
const kind = this.#values.get(value)!;
|
||||
mergedKind = mergedKind !== null ? mergeValues(mergedKind, kind) : kind;
|
||||
}
|
||||
invariant(mergedKind !== null, "Expected at least value");
|
||||
return mergedKind;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the value at @param place to point to the same value as @param value.
|
||||
*/
|
||||
alias(place: Place, value: Place) {
|
||||
const values = this.#variables.get(value.value.id);
|
||||
invariant(
|
||||
values != null,
|
||||
`Expected value to be populated at '${String(value.path)}' in '${String(
|
||||
value.path.parentPath
|
||||
)}'`
|
||||
);
|
||||
this.#variables.set(place.value.id, new Set(values));
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines (initializing or updating) a variable with a specific kind of value.
|
||||
*/
|
||||
define(place: Place, value: InstructionValue) {
|
||||
invariant(
|
||||
place.memberPath === null,
|
||||
"Expected a top-level identifier, not a member path"
|
||||
);
|
||||
invariant(
|
||||
this.#values.has(value),
|
||||
`Expected value to be initialized at '${String(value.path)}' in '${String(
|
||||
value.path?.parentPath
|
||||
)}'`
|
||||
);
|
||||
this.#variables.set(place.value.id, new Set([value]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Records that a given Place was accessed with the given kind and:
|
||||
* - Updates the capability of @param place based on the kind of value
|
||||
* and the kind of reference (@param effectKind).
|
||||
* - Updates the value kind to reflect the effect of the reference.
|
||||
*
|
||||
* Notably, a mutable reference is downgraded to readonly if the
|
||||
* value unless the value is known to be mutable.
|
||||
*
|
||||
* Similarly, a freeze reference is converted to readonly if the
|
||||
* value is already frozen or is immutable.
|
||||
*/
|
||||
reference(place: Place, effectKind: EffectKind) {
|
||||
const values = this.#variables.get(place.value.id);
|
||||
if (values === undefined) {
|
||||
place.capability =
|
||||
effectKind === EffectKind.Write
|
||||
? Capability.Mutable
|
||||
: Capability.Readonly;
|
||||
return;
|
||||
}
|
||||
let capability: Capability | null = null;
|
||||
switch (effectKind) {
|
||||
case EffectKind.Freeze: {
|
||||
values.forEach((value) => {
|
||||
const valueKind = this.#values.get(value)!;
|
||||
if (
|
||||
valueKind === ValueKind.Mutable ||
|
||||
valueKind === ValueKind.MaybeFrozen
|
||||
) {
|
||||
this.#values.set(value, ValueKind.Frozen);
|
||||
capability = Capability.Freeze;
|
||||
}
|
||||
});
|
||||
capability = capability ?? Capability.Readonly;
|
||||
break;
|
||||
}
|
||||
case EffectKind.Write: {
|
||||
let maybeFrozen = false;
|
||||
let maybeMutable = false;
|
||||
values.forEach((value) => {
|
||||
const valueKind = this.#values.get(value)!;
|
||||
if (
|
||||
valueKind === ValueKind.Frozen ||
|
||||
valueKind === ValueKind.MaybeFrozen
|
||||
) {
|
||||
maybeFrozen = true;
|
||||
} else if (valueKind === ValueKind.Mutable) {
|
||||
maybeMutable = true;
|
||||
}
|
||||
});
|
||||
capability = maybeFrozen
|
||||
? Capability.Readonly
|
||||
: maybeMutable
|
||||
? Capability.Mutable
|
||||
: Capability.Readonly;
|
||||
break;
|
||||
}
|
||||
case EffectKind.Read: {
|
||||
capability = Capability.Readonly;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
assertExhaustive(
|
||||
effectKind,
|
||||
`Unexpected reference kind '${effectKind as any as string}'`
|
||||
);
|
||||
}
|
||||
}
|
||||
invariant(capability !== null, "Expected capability to be set");
|
||||
place.capability = capability;
|
||||
}
|
||||
|
||||
/**
|
||||
* Combine the contents of @param this and @param other, returning a new
|
||||
* instance with the combined changes _if_ there are any changes, or
|
||||
* returning null if no changes would occur. Changes include:
|
||||
* - new entries in @param other that did not exist in @param this
|
||||
* - entries whose values differ in @param this and @param other,
|
||||
* and where joining the values produces a different value than
|
||||
* what was in @param this.
|
||||
*
|
||||
* Note that values are joined using a lattice operation to ensure
|
||||
* termination.
|
||||
*/
|
||||
merge(other: Environment): Environment | null {
|
||||
let nextValues: Map<InstructionValue, ValueKind> | null = null;
|
||||
let nextVariables: Map<IdentifierId, Set<InstructionValue>> | null = null;
|
||||
|
||||
for (const [id, thisValue] of this.#values) {
|
||||
const otherValue = other.#values.get(id);
|
||||
if (otherValue !== undefined) {
|
||||
const mergedValue = mergeValues(thisValue, otherValue);
|
||||
if (mergedValue !== thisValue) {
|
||||
nextValues = nextValues ?? new Map(this.#values);
|
||||
nextValues.set(id, mergedValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const [id, otherValue] of other.#values) {
|
||||
if (this.#values.has(id)) {
|
||||
// merged above
|
||||
continue;
|
||||
}
|
||||
nextValues = nextValues ?? new Map(this.#values);
|
||||
nextValues.set(id, otherValue);
|
||||
}
|
||||
|
||||
for (const [id, thisValues] of this.#variables) {
|
||||
const otherValues = other.#variables.get(id);
|
||||
if (otherValues !== undefined) {
|
||||
let mergedValues: Set<InstructionValue> | null = null;
|
||||
for (const otherValue of otherValues) {
|
||||
if (!thisValues.has(otherValue)) {
|
||||
mergedValues = mergedValues ?? new Set(thisValues);
|
||||
mergedValues.add(otherValue);
|
||||
}
|
||||
}
|
||||
if (mergedValues !== null) {
|
||||
nextVariables = nextVariables ?? new Map(this.#variables);
|
||||
nextVariables.set(id, mergedValues);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const [id, otherValues] of other.#variables) {
|
||||
if (this.#variables.has(id)) {
|
||||
continue;
|
||||
}
|
||||
nextVariables = nextVariables ?? new Map(this.#variables);
|
||||
nextVariables.set(id, new Set(otherValues));
|
||||
}
|
||||
|
||||
if (nextVariables === null && nextValues === null) {
|
||||
return null;
|
||||
} else {
|
||||
return new Environment(
|
||||
nextValues ?? new Map(this.#values),
|
||||
nextVariables ?? new Map(this.#variables)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this environment.
|
||||
* TODO: consider using persistent data structures to make
|
||||
* clone cheaper.
|
||||
*/
|
||||
clone(): Environment {
|
||||
return new Environment(new Map(this.#values), new Map(this.#variables));
|
||||
}
|
||||
|
||||
/**
|
||||
* For debugging purposes, dumps the environment to a plain
|
||||
* object so that it can printed as JSON.
|
||||
*/
|
||||
debug(): any {
|
||||
const result: any = { values: {}, variables: {} };
|
||||
const objects: Map<InstructionValue, number> = new Map();
|
||||
function identify(value: InstructionValue): number {
|
||||
let id = objects.get(value);
|
||||
if (id == null) {
|
||||
id = objects.size;
|
||||
objects.set(value, id);
|
||||
}
|
||||
return id;
|
||||
}
|
||||
for (const [value, kind] of this.#values) {
|
||||
const id = identify(value);
|
||||
result.values[id] = { kind, value: printMixedHIR(value) };
|
||||
}
|
||||
for (const [variable, values] of this.#variables) {
|
||||
result.variables[variable] = [...values].map(identify);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Joins two values using the following rules:
|
||||
* == Effect Transitions ==
|
||||
*
|
||||
* Freezing an immutable value has not effect:
|
||||
* ┌───────────────┐
|
||||
* │ │
|
||||
* ▼ │ Freeze
|
||||
* ┌──────────────────────────┐ │
|
||||
* │ Immutable │──┘
|
||||
* └──────────────────────────┘
|
||||
*
|
||||
* Freezing a mutable or maybe-frozen value makes it frozen. Freezing a frozen
|
||||
* value has no effect:
|
||||
* ┌───────────────┐
|
||||
* ┌─────────────────────────┐ Freeze │ │
|
||||
* │ MaybeFrozen │────┐ ▼ │ Freeze
|
||||
* └─────────────────────────┘ │ ┌──────────────────────────┐ │
|
||||
* ├────▶│ Frozen │──┘
|
||||
* │ └──────────────────────────┘
|
||||
* ┌─────────────────────────┐ │
|
||||
* │ Mutable │────┘
|
||||
* └─────────────────────────┘
|
||||
*
|
||||
* == Join Lattice ==
|
||||
* - immutable | frozen => frozen
|
||||
* - frozen | mutable => maybe-frozen
|
||||
* - <any> | maybe-frozen => maybe-frozen
|
||||
*
|
||||
* ┌──────────────────────────┐
|
||||
* │ Immutable │───┐
|
||||
* └──────────────────────────┘ │
|
||||
* │ ┌─────────────────────────┐
|
||||
* ├───▶│ Frozen │──┐
|
||||
* ┌──────────────────────────┐ │ └─────────────────────────┘ │
|
||||
* │ Frozen │───┤ │ ┌─────────────────────────┐
|
||||
* └──────────────────────────┘ │ ├─▶│ MaybeFrozen │
|
||||
* │ ┌─────────────────────────┐ │ └─────────────────────────┘
|
||||
* ├───▶│ MaybeFrozen │──┘
|
||||
* ┌──────────────────────────┐ │ └─────────────────────────┘
|
||||
* │ Mutable │───┘
|
||||
* └──────────────────────────┘
|
||||
*/
|
||||
function mergeValues(a: ValueKind, b: ValueKind): ValueKind {
|
||||
if (a === b) {
|
||||
return a;
|
||||
} else if (a === ValueKind.MaybeFrozen || b === ValueKind.MaybeFrozen) {
|
||||
return ValueKind.MaybeFrozen;
|
||||
// after this a and b differ and neither are MaybeFrozen
|
||||
} else if (a === ValueKind.Mutable || b === ValueKind.Mutable) {
|
||||
if (a === ValueKind.Frozen || b === ValueKind.Frozen) {
|
||||
// frozen | mutable
|
||||
return ValueKind.MaybeFrozen;
|
||||
} else {
|
||||
// mutable | immutable
|
||||
return ValueKind.Mutable;
|
||||
}
|
||||
} else {
|
||||
// frozen | immutable
|
||||
return ValueKind.Frozen;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Distinguish between different kinds of values relevant to inference purposes:
|
||||
* see the main docblock for the module for details.
|
||||
*/
|
||||
enum ValueKind {
|
||||
MaybeFrozen = "MaybeFrozen",
|
||||
Frozen = "Frozen",
|
||||
Immutable = "Immutable",
|
||||
Mutable = "Mutable",
|
||||
}
|
||||
|
||||
/**
|
||||
* Distinguish between different kinds of references.
|
||||
*/
|
||||
enum EffectKind {
|
||||
Write = "Write",
|
||||
Read = "Read",
|
||||
Freeze = "Freeze",
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates over the given @param block, defining variables and
|
||||
* recording references on the @param env according to JS semantics.
|
||||
*/
|
||||
function inferBlock(env: Environment, block: BasicBlock) {
|
||||
for (const instr of block.instructions) {
|
||||
const instrValue = instr.value;
|
||||
let valueKind: ValueKind;
|
||||
switch (instrValue.kind) {
|
||||
case "BinaryExpression": {
|
||||
valueKind = ValueKind.Immutable;
|
||||
env.reference(instrValue.left, EffectKind.Read);
|
||||
env.reference(instrValue.right, EffectKind.Read);
|
||||
break;
|
||||
}
|
||||
case "ArrayExpression": {
|
||||
valueKind = ValueKind.Mutable;
|
||||
for (const element of instrValue.elements) {
|
||||
env.reference(element, EffectKind.Read);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "NewExpression": {
|
||||
valueKind = ValueKind.Mutable;
|
||||
env.reference(instrValue.callee, EffectKind.Write);
|
||||
for (const arg of instrValue.args) {
|
||||
env.reference(arg, EffectKind.Write);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "CallExpression": {
|
||||
let effectKind = EffectKind.Write;
|
||||
valueKind = ValueKind.Mutable;
|
||||
const hook = parseHookCall(instrValue.callee);
|
||||
if (hook !== null) {
|
||||
effectKind = hook.effectKind;
|
||||
valueKind = hook.valueKind;
|
||||
}
|
||||
env.reference(instrValue.callee, effectKind);
|
||||
for (const arg of instrValue.args) {
|
||||
env.reference(arg, effectKind);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "ObjectExpression": {
|
||||
valueKind = ValueKind.Mutable;
|
||||
// Object construction captures but does not modify the key/property values
|
||||
if (instrValue.properties !== null) {
|
||||
for (const [_key, value] of Object.entries(instrValue.properties)) {
|
||||
env.reference(value, EffectKind.Read);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "UnaryExpression": {
|
||||
// TODO check that value must be a primitive, or make conditional based on the operator
|
||||
valueKind = ValueKind.Immutable;
|
||||
env.reference(instrValue.value, EffectKind.Read);
|
||||
break;
|
||||
}
|
||||
case "OtherStatement": {
|
||||
// TODO: handle other statement kinds
|
||||
valueKind = ValueKind.Mutable;
|
||||
break;
|
||||
}
|
||||
case "JsxExpression": {
|
||||
valueKind = ValueKind.Frozen;
|
||||
env.reference(instrValue.tag, EffectKind.Freeze);
|
||||
for (const [_prop, value] of Object.entries(instrValue.props)) {
|
||||
env.reference(value, EffectKind.Freeze);
|
||||
}
|
||||
if (instrValue.children !== null) {
|
||||
for (const child of instrValue.children) {
|
||||
env.reference(child, EffectKind.Freeze);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "JSXText":
|
||||
case "Primitive": {
|
||||
valueKind = ValueKind.Immutable;
|
||||
break;
|
||||
}
|
||||
case "Identifier": {
|
||||
env.reference(instrValue, EffectKind.Read);
|
||||
const lvalue = instr.lvalue;
|
||||
if (lvalue !== null) {
|
||||
lvalue.place.capability = Capability.Mutable;
|
||||
if (
|
||||
lvalue.place.memberPath === null &&
|
||||
instrValue.memberPath === null
|
||||
) {
|
||||
// direct aliasing: `a = b`;
|
||||
env.alias(lvalue.place, instrValue);
|
||||
} else if (lvalue.place.memberPath === null) {
|
||||
// redefine lvalue: `a = b.c.d`
|
||||
env.initialize(instrValue, env.kind(instrValue));
|
||||
env.define(lvalue.place, instrValue);
|
||||
} else if (instrValue.memberPath === null) {
|
||||
// no-op: `a.b.c = d`
|
||||
env.reference(lvalue.place, EffectKind.Write);
|
||||
} else {
|
||||
// no-op: `a.b.c = d.e.f`
|
||||
env.reference(lvalue.place, EffectKind.Write);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
default: {
|
||||
assertExhaustive(instrValue, "Unexpected instruction kind");
|
||||
}
|
||||
}
|
||||
env.initialize(instrValue, valueKind, instr);
|
||||
if (instr.lvalue !== null) {
|
||||
if (instr.lvalue.place.memberPath === null) {
|
||||
env.define(instr.lvalue.place, instrValue);
|
||||
} else {
|
||||
env.reference(instr.lvalue.place, EffectKind.Write);
|
||||
}
|
||||
instr.lvalue.place.capability = Capability.Mutable;
|
||||
}
|
||||
}
|
||||
switch (block.terminal.kind) {
|
||||
case "throw": {
|
||||
env.reference(block.terminal.value, EffectKind.Freeze);
|
||||
break;
|
||||
}
|
||||
case "return": {
|
||||
if (block.terminal.value !== null) {
|
||||
env.reference(block.terminal.value, EffectKind.Freeze);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "if": {
|
||||
env.reference(block.terminal.test, EffectKind.Read);
|
||||
break;
|
||||
}
|
||||
case "switch": {
|
||||
for (const case_ of block.terminal.cases) {
|
||||
if (case_.test !== null) {
|
||||
env.reference(case_.test, EffectKind.Read);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "goto": {
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
assertExhaustive(
|
||||
block.terminal,
|
||||
`Unexpected terminal kind '${(block.terminal as any as Terminal).kind}'`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const GLOBALS: Map<string, ValueKind> = new Map([
|
||||
["Map", ValueKind.Mutable],
|
||||
["Set", ValueKind.Mutable],
|
||||
["Math.max", ValueKind.Immutable],
|
||||
]);
|
||||
|
||||
const HOOKS: Map<string, Hook> = new Map([
|
||||
[
|
||||
"useState",
|
||||
{
|
||||
kind: "State",
|
||||
effectKind: EffectKind.Freeze,
|
||||
valueKind: ValueKind.Frozen,
|
||||
},
|
||||
],
|
||||
[
|
||||
"useRef",
|
||||
{
|
||||
kind: "Ref",
|
||||
effectKind: EffectKind.Read,
|
||||
valueKind: ValueKind.Mutable,
|
||||
},
|
||||
],
|
||||
]);
|
||||
|
||||
type HookKind = { kind: "State" } | { kind: "Ref" } | { kind: "Custom" };
|
||||
type Hook = HookKind & { effectKind: EffectKind; valueKind: ValueKind };
|
||||
|
||||
function parseHookCall(place: Place): Hook | null {
|
||||
if (place.memberPath !== null) {
|
||||
// Hook calls must be statically resolved
|
||||
return null;
|
||||
}
|
||||
const name = place.value.name;
|
||||
if (name === null || !name.match(/^_?use/)) {
|
||||
return null;
|
||||
}
|
||||
const hook = HOOKS.get(name);
|
||||
if (hook != null) {
|
||||
return hook;
|
||||
}
|
||||
return {
|
||||
kind: "Custom",
|
||||
effectKind: EffectKind.Freeze,
|
||||
valueKind: ValueKind.Frozen,
|
||||
};
|
||||
}
|
||||
@@ -66,7 +66,7 @@ export default function analyzeScopes(fn: HIRFunction): ReactFunction {
|
||||
kind: "Identifier",
|
||||
value: param,
|
||||
memberPath: null,
|
||||
capability: Capability.Frozen,
|
||||
capability: Capability.Freeze,
|
||||
path: null as any,
|
||||
}))
|
||||
),
|
||||
|
||||
@@ -4,721 +4,721 @@
|
||||
<!-- Generated by graphviz version 6.0.1 (20220924.0800)
|
||||
-->
|
||||
<!-- Title: BuildDefUseGraph Pages: 1 -->
|
||||
<svg width="13574pt" height="482pt"
|
||||
viewBox="0.00 0.00 13573.52 481.60" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<svg width="13456pt" height="482pt"
|
||||
viewBox="0.00 0.00 13455.59 481.60" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 477.6)">
|
||||
<title>BuildDefUseGraph</title>
|
||||
<polygon fill="white" stroke="none" points="-4,4 -4,-477.6 13569.52,-477.6 13569.52,4 -4,4"/>
|
||||
<polygon fill="white" stroke="none" points="-4,4 -4,-477.6 13451.59,-477.6 13451.59,4 -4,4"/>
|
||||
<!-- v0 -->
|
||||
<g id="node1" class="node">
|
||||
<title>v0</title>
|
||||
<polygon fill="none" stroke="black" points="627.43,-396 272.01,-396 272.01,-360 627.43,-360 627.43,-396"/>
|
||||
<text text-anchor="middle" x="449.72" y="-373.8" font-family="Times,serif" font-size="14.00">v0 (frozen props$1.items @ frozen props$1.items) <update></text>
|
||||
<polygon fill="none" stroke="black" points="622.43,-396 270.29,-396 270.29,-360 622.43,-360 622.43,-396"/>
|
||||
<text text-anchor="middle" x="446.36" y="-373.8" font-family="Times,serif" font-size="14.00">v0 (freeze props$1.items @ freeze props$1.items) <update></text>
|
||||
</g>
|
||||
<!-- v1 -->
|
||||
<g id="node2" class="node">
|
||||
<title>v1</title>
|
||||
<polygon fill="none" stroke="black" points="453.66,-324 -0.22,-324 -0.22,-288 453.66,-288 453.66,-324"/>
|
||||
<text text-anchor="middle" x="226.72" y="-301.8" font-family="Times,serif" font-size="14.00">v1 (frozen items$2 @ Const frozen items$2 = frozen props$1.items) <assign></text>
|
||||
<polygon fill="none" stroke="black" points="448.58,-324 0.14,-324 0.14,-288 448.58,-288 448.58,-324"/>
|
||||
<text text-anchor="middle" x="224.36" y="-301.8" font-family="Times,serif" font-size="14.00">v1 (freeze items$2 @ Const freeze items$2 = freeze props$1.items) <assign></text>
|
||||
</g>
|
||||
<!-- v0->v1 -->
|
||||
<g id="edge1" class="edge">
|
||||
<title>v0->v1</title>
|
||||
<path fill="none" stroke="black" d="M395.45,-359.97C363.89,-350.06 323.93,-337.51 290.82,-327.12"/>
|
||||
<polygon fill="black" stroke="black" points="291.82,-323.77 281.23,-324.11 289.72,-330.45 291.82,-323.77"/>
|
||||
<path fill="none" stroke="black" d="M392.34,-359.97C360.91,-350.06 321.13,-337.51 288.17,-327.12"/>
|
||||
<polygon fill="black" stroke="black" points="289.22,-323.78 278.63,-324.11 287.11,-330.46 289.22,-323.78"/>
|
||||
</g>
|
||||
<!-- v2 -->
|
||||
<g id="node3" class="node">
|
||||
<title>v2</title>
|
||||
<polygon fill="none" stroke="black" points="887.68,-324 481.76,-324 481.76,-288 887.68,-288 887.68,-324"/>
|
||||
<text text-anchor="middle" x="684.72" y="-301.8" font-family="Times,serif" font-size="14.00">v2 (frozen props$1.maxItems @ frozen props$1.maxItems) <update></text>
|
||||
<polygon fill="none" stroke="black" points="880.68,-324 478.04,-324 478.04,-288 880.68,-288 880.68,-324"/>
|
||||
<text text-anchor="middle" x="679.36" y="-301.8" font-family="Times,serif" font-size="14.00">v2 (freeze props$1.maxItems @ freeze props$1.maxItems) <update></text>
|
||||
</g>
|
||||
<!-- v0->v2 -->
|
||||
<g id="edge2" class="edge">
|
||||
<title>v0->v2</title>
|
||||
<path fill="none" stroke="black" d="M506.91,-359.97C540.31,-350.01 582.64,-337.41 617.62,-326.99"/>
|
||||
<polygon fill="black" stroke="black" points="618.69,-330.32 627.28,-324.11 616.69,-323.61 618.69,-330.32"/>
|
||||
<path fill="none" stroke="black" d="M503.06,-359.97C536.04,-350.06 577.79,-337.51 612.39,-327.12"/>
|
||||
<polygon fill="black" stroke="black" points="613.84,-330.34 622.41,-324.11 611.82,-323.64 613.84,-330.34"/>
|
||||
</g>
|
||||
<!-- v12 -->
|
||||
<g id="node4" class="node">
|
||||
<title>v12</title>
|
||||
<polygon fill="none" stroke="black" points="425.01,-252 6.43,-252 6.43,-216 425.01,-216 425.01,-252"/>
|
||||
<text text-anchor="middle" x="215.72" y="-229.8" font-family="Times,serif" font-size="14.00">v12 (frozen items$2 @ If (frozen items$2) then:bb3 else:bb2) <update></text>
|
||||
<polygon fill="none" stroke="black" points="421,-252 5.72,-252 5.72,-216 421,-216 421,-252"/>
|
||||
<text text-anchor="middle" x="213.36" y="-229.8" font-family="Times,serif" font-size="14.00">v12 (freeze items$2 @ If (freeze items$2) then:bb3 else:bb2) <update></text>
|
||||
</g>
|
||||
<!-- v1->v12 -->
|
||||
<g id="edge3" class="edge">
|
||||
<title>v1->v12</title>
|
||||
<path fill="none" stroke="black" d="M224,-287.7C222.79,-279.98 221.33,-270.71 219.98,-262.11"/>
|
||||
<polygon fill="black" stroke="black" points="223.42,-261.44 218.41,-252.1 216.5,-262.53 223.42,-261.44"/>
|
||||
<path fill="none" stroke="black" d="M221.64,-287.7C220.43,-279.98 218.97,-270.71 217.62,-262.11"/>
|
||||
<polygon fill="black" stroke="black" points="221.06,-261.44 216.05,-252.1 214.14,-262.53 221.06,-261.44"/>
|
||||
</g>
|
||||
<!-- v3 -->
|
||||
<g id="node5" class="node">
|
||||
<title>v3</title>
|
||||
<polygon fill="none" stroke="black" points="970.79,-252 442.65,-252 442.65,-216 970.79,-216 970.79,-252"/>
|
||||
<text text-anchor="middle" x="706.72" y="-229.8" font-family="Times,serif" font-size="14.00">v3 (frozen maxItems$3 @ Const frozen maxItems$3 = frozen props$1.maxItems) <assign></text>
|
||||
<polygon fill="none" stroke="black" points="962.21,-252 438.51,-252 438.51,-216 962.21,-216 962.21,-252"/>
|
||||
<text text-anchor="middle" x="700.36" y="-229.8" font-family="Times,serif" font-size="14.00">v3 (freeze maxItems$3 @ Const freeze maxItems$3 = freeze props$1.maxItems) <assign></text>
|
||||
</g>
|
||||
<!-- v2->v3 -->
|
||||
<g id="edge4" class="edge">
|
||||
<title>v2->v3</title>
|
||||
<path fill="none" stroke="black" d="M690.16,-287.7C692.61,-279.9 695.56,-270.51 698.29,-261.83"/>
|
||||
<polygon fill="black" stroke="black" points="701.68,-262.69 701.34,-252.1 695.01,-260.59 701.68,-262.69"/>
|
||||
<path fill="none" stroke="black" d="M684.55,-287.7C686.89,-279.9 689.71,-270.51 692.31,-261.83"/>
|
||||
<polygon fill="black" stroke="black" points="695.71,-262.69 695.23,-252.1 689,-260.68 695.71,-262.69"/>
|
||||
</g>
|
||||
<!-- v10 -->
|
||||
<g id="node6" class="node">
|
||||
<title>v10</title>
|
||||
<polygon fill="none" stroke="black" points="990.97,-180 422.47,-180 422.47,-144 990.97,-144 990.97,-180"/>
|
||||
<text text-anchor="middle" x="706.72" y="-157.8" font-family="Times,serif" font-size="14.00">v10 (frozen maxItems$3 @ Call mutable Math$8.max(mutable $9, frozen maxItems$3)) <update></text>
|
||||
<polygon fill="none" stroke="black" points="982.96,-180 417.76,-180 417.76,-144 982.96,-144 982.96,-180"/>
|
||||
<text text-anchor="middle" x="700.36" y="-157.8" font-family="Times,serif" font-size="14.00">v10 (freeze maxItems$3 @ Call mutable Math$8.max(mutable $9, freeze maxItems$3)) <update></text>
|
||||
</g>
|
||||
<!-- v3->v10 -->
|
||||
<g id="edge5" class="edge">
|
||||
<title>v3->v10</title>
|
||||
<path fill="none" stroke="black" d="M706.72,-215.7C706.72,-207.98 706.72,-198.71 706.72,-190.11"/>
|
||||
<polygon fill="black" stroke="black" points="710.22,-190.1 706.72,-180.1 703.22,-190.1 710.22,-190.1"/>
|
||||
<path fill="none" stroke="black" d="M700.36,-215.7C700.36,-207.98 700.36,-198.71 700.36,-190.11"/>
|
||||
<polygon fill="black" stroke="black" points="703.86,-190.1 700.36,-180.1 696.86,-190.1 703.86,-190.1"/>
|
||||
</g>
|
||||
<!-- v4 -->
|
||||
<g id="node7" class="node">
|
||||
<title>v4</title>
|
||||
<polygon fill="none" stroke="black" points="1725.87,-470.8 1219.57,-470.8 1219.57,-434.8 1725.87,-434.8 1725.87,-470.8"/>
|
||||
<text text-anchor="middle" x="1472.72" y="-448.6" font-family="Times,serif" font-size="14.00">v4 (readonly renderedItems$4 @ Const readonly renderedItems$4 = Array []) <assign></text>
|
||||
<polygon fill="none" stroke="black" points="1716.51,-470.8 1210.21,-470.8 1210.21,-434.8 1716.51,-434.8 1716.51,-470.8"/>
|
||||
<text text-anchor="middle" x="1463.36" y="-448.6" font-family="Times,serif" font-size="14.00">v4 (readonly renderedItems$4 @ Const readonly renderedItems$4 = Array []) <assign></text>
|
||||
</g>
|
||||
<!-- v18 -->
|
||||
<g id="node8" class="node">
|
||||
<title>v18</title>
|
||||
<polygon fill="none" stroke="black" points="1927.13,-180 1430.31,-180 1430.31,-144 1927.13,-144 1927.13,-180"/>
|
||||
<text text-anchor="middle" x="1678.72" y="-157.8" font-family="Times,serif" font-size="14.00">v18 (readonly renderedItems$4.length @ readonly renderedItems$4.length) <update></text>
|
||||
<polygon fill="none" stroke="black" points="1917.77,-180 1420.95,-180 1420.95,-144 1917.77,-144 1917.77,-180"/>
|
||||
<text text-anchor="middle" x="1669.36" y="-157.8" font-family="Times,serif" font-size="14.00">v18 (readonly renderedItems$4.length @ readonly renderedItems$4.length) <update></text>
|
||||
</g>
|
||||
<!-- v4->v18 -->
|
||||
<g id="edge6" class="edge">
|
||||
<title>v4->v18</title>
|
||||
<path fill="none" stroke="black" d="M1658.17,-434.74C1713.55,-426.26 1765.05,-413.87 1785.72,-396 1846.43,-343.53 1848.15,-279.98 1799.72,-216 1789.25,-202.17 1774.4,-191.88 1758.67,-184.25"/>
|
||||
<polygon fill="black" stroke="black" points="1759.89,-180.97 1749.34,-180.06 1757.03,-187.35 1759.89,-180.97"/>
|
||||
<path fill="none" stroke="black" d="M1648.81,-434.74C1704.2,-426.26 1755.69,-413.87 1776.36,-396 1837.07,-343.53 1838.79,-279.98 1790.36,-216 1779.89,-202.17 1765.04,-191.88 1749.31,-184.25"/>
|
||||
<polygon fill="black" stroke="black" points="1750.54,-180.97 1739.98,-180.06 1747.67,-187.35 1750.54,-180.97"/>
|
||||
</g>
|
||||
<!-- v49 -->
|
||||
<g id="node9" class="node">
|
||||
<title>v49</title>
|
||||
<polygon fill="none" stroke="black" points="1743.52,-396 1165.91,-396 1165.91,-360 1743.52,-360 1743.52,-396"/>
|
||||
<text text-anchor="middle" x="1454.72" y="-373.8" font-family="Times,serif" font-size="14.00">v49 (mutable renderedItems$4.push @ Call mutable renderedItems$4.push(mutable $15)) <update></text>
|
||||
<polygon fill="none" stroke="black" points="1734.17,-396 1156.56,-396 1156.56,-360 1734.17,-360 1734.17,-396"/>
|
||||
<text text-anchor="middle" x="1445.36" y="-373.8" font-family="Times,serif" font-size="14.00">v49 (mutable renderedItems$4.push @ Call mutable renderedItems$4.push(mutable $15)) <update></text>
|
||||
</g>
|
||||
<!-- v4->v49 -->
|
||||
<g id="edge7" class="edge">
|
||||
<title>v4->v49</title>
|
||||
<path fill="none" stroke="black" d="M1468.45,-434.55C1466.35,-426.03 1463.76,-415.55 1461.39,-405.99"/>
|
||||
<polygon fill="black" stroke="black" points="1464.75,-405 1458.95,-396.13 1457.96,-406.68 1464.75,-405"/>
|
||||
<path fill="none" stroke="black" d="M1459.1,-434.55C1456.99,-426.03 1454.4,-415.55 1452.03,-405.99"/>
|
||||
<polygon fill="black" stroke="black" points="1455.39,-405 1449.6,-396.13 1448.6,-406.68 1455.39,-405"/>
|
||||
</g>
|
||||
<!-- v62 -->
|
||||
<g id="node10" class="node">
|
||||
<title>v62</title>
|
||||
<polygon fill="none" stroke="black" points="1790.46,-252 1566.98,-252 1566.98,-216 1790.46,-216 1790.46,-252"/>
|
||||
<text text-anchor="middle" x="1678.72" y="-229.8" font-family="Times,serif" font-size="14.00">v62 (<join> @ <no-instr>) <update></text>
|
||||
<polygon fill="none" stroke="black" points="1781.1,-252 1557.62,-252 1557.62,-216 1781.1,-216 1781.1,-252"/>
|
||||
<text text-anchor="middle" x="1669.36" y="-229.8" font-family="Times,serif" font-size="14.00">v62 (<join> @ <no-instr>) <update></text>
|
||||
</g>
|
||||
<!-- v4->v62 -->
|
||||
<g id="edge8" class="edge">
|
||||
<title>v4->v62</title>
|
||||
<path fill="none" stroke="black" d="M1616.67,-434.75C1673.44,-425.66 1730.41,-412.83 1752.72,-396 1793.22,-365.44 1816.79,-330.92 1789.72,-288 1781.09,-274.31 1767.84,-264.09 1753.47,-256.47"/>
|
||||
<polygon fill="black" stroke="black" points="1754.93,-253.29 1744.4,-252.05 1751.86,-259.58 1754.93,-253.29"/>
|
||||
<path fill="none" stroke="black" d="M1607.31,-434.75C1664.08,-425.66 1721.05,-412.83 1743.36,-396 1783.86,-365.44 1807.43,-330.92 1780.36,-288 1771.73,-274.31 1758.48,-264.09 1744.11,-256.47"/>
|
||||
<polygon fill="black" stroke="black" points="1745.57,-253.29 1735.05,-252.05 1742.5,-259.58 1745.57,-253.29"/>
|
||||
</g>
|
||||
<!-- v71 -->
|
||||
<g id="node11" class="node">
|
||||
<title>v71</title>
|
||||
<polygon fill="none" stroke="black" points="1212.46,-252 988.98,-252 988.98,-216 1212.46,-216 1212.46,-252"/>
|
||||
<text text-anchor="middle" x="1100.72" y="-229.8" font-family="Times,serif" font-size="14.00">v71 (<join> @ <no-instr>) <update></text>
|
||||
<polygon fill="none" stroke="black" points="1203.1,-252 979.62,-252 979.62,-216 1203.1,-216 1203.1,-252"/>
|
||||
<text text-anchor="middle" x="1091.36" y="-229.8" font-family="Times,serif" font-size="14.00">v71 (<join> @ <no-instr>) <update></text>
|
||||
</g>
|
||||
<!-- v4->v71 -->
|
||||
<g id="edge9" class="edge">
|
||||
<title>v4->v71</title>
|
||||
<path fill="none" stroke="black" d="M1317.95,-434.8C1252.32,-425.49 1184.6,-412.47 1156.72,-396 1121.34,-375.09 1112.39,-362.75 1098.72,-324 1091.75,-304.23 1092.72,-280.43 1095.18,-262.42"/>
|
||||
<polygon fill="black" stroke="black" points="1098.68,-262.72 1096.8,-252.3 1091.77,-261.62 1098.68,-262.72"/>
|
||||
<path fill="none" stroke="black" d="M1308.59,-434.8C1242.96,-425.49 1175.24,-412.47 1147.36,-396 1111.98,-375.09 1103.03,-362.75 1089.36,-324 1082.39,-304.23 1083.37,-280.43 1085.83,-262.42"/>
|
||||
<polygon fill="black" stroke="black" points="1089.32,-262.72 1087.44,-252.3 1082.41,-261.62 1089.32,-262.72"/>
|
||||
</g>
|
||||
<!-- v19 -->
|
||||
<g id="node31" class="node">
|
||||
<title>v19</title>
|
||||
<polygon fill="none" stroke="black" points="1590.51,-108 1020.93,-108 1020.93,-72 1590.51,-72 1590.51,-108"/>
|
||||
<text text-anchor="middle" x="1305.72" y="-85.8" font-family="Times,serif" font-size="14.00">v19 (readonly count$17 @ Const readonly count$17 = readonly renderedItems$4.length) <assign></text>
|
||||
<polygon fill="none" stroke="black" points="1585.15,-108 1015.57,-108 1015.57,-72 1585.15,-72 1585.15,-108"/>
|
||||
<text text-anchor="middle" x="1300.36" y="-85.8" font-family="Times,serif" font-size="14.00">v19 (readonly count$17 @ Const readonly count$17 = readonly renderedItems$4.length) <assign></text>
|
||||
</g>
|
||||
<!-- v18->v19 -->
|
||||
<g id="edge21" class="edge">
|
||||
<title>v18->v19</title>
|
||||
<path fill="none" stroke="black" d="M1587.95,-143.97C1533.13,-133.68 1463.16,-120.55 1406.61,-109.93"/>
|
||||
<polygon fill="black" stroke="black" points="1407.05,-106.45 1396.57,-108.05 1405.75,-113.33 1407.05,-106.45"/>
|
||||
<path fill="none" stroke="black" d="M1579.57,-143.97C1525.33,-133.68 1456.11,-120.55 1400.17,-109.93"/>
|
||||
<polygon fill="black" stroke="black" points="1400.72,-106.48 1390.24,-108.05 1399.41,-113.35 1400.72,-106.48"/>
|
||||
</g>
|
||||
<!-- v34 -->
|
||||
<g id="node32" class="node">
|
||||
<title>v34</title>
|
||||
<polygon fill="none" stroke="black" points="2492.71,-108 1608.73,-108 1608.73,-72 2492.71,-72 2492.71,-108"/>
|
||||
<text text-anchor="middle" x="2050.72" y="-85.8" font-family="Times,serif" font-size="14.00">v34 (frozen renderedItems$4 @ JSX <frozen $18>{frozen $19}{frozen $22}{frozen $23}{frozen renderedItems$4}{frozen $24}</frozen $18>) <update></text>
|
||||
<polygon fill="none" stroke="black" points="2474.28,-108 1602.45,-108 1602.45,-72 2474.28,-72 2474.28,-108"/>
|
||||
<text text-anchor="middle" x="2038.36" y="-85.8" font-family="Times,serif" font-size="14.00">v34 (freeze renderedItems$4 @ JSX <freeze $18>{freeze $19}{freeze $22}{freeze $23}{freeze renderedItems$4}{freeze $24}</freeze $18>) <update></text>
|
||||
</g>
|
||||
<!-- v18->v34 -->
|
||||
<g id="edge22" class="edge">
|
||||
<title>v18->v34</title>
|
||||
<path fill="none" stroke="black" d="M1769.24,-143.97C1823.92,-133.68 1893.7,-120.55 1950.1,-109.93"/>
|
||||
<polygon fill="black" stroke="black" points="1950.93,-113.34 1960.11,-108.05 1949.64,-106.46 1950.93,-113.34"/>
|
||||
<path fill="none" stroke="black" d="M1759.16,-143.97C1813.39,-133.68 1882.61,-120.55 1938.56,-109.93"/>
|
||||
<polygon fill="black" stroke="black" points="1939.31,-113.35 1948.48,-108.05 1938.01,-106.48 1939.31,-113.35"/>
|
||||
</g>
|
||||
<!-- v51 -->
|
||||
<g id="node59" class="node">
|
||||
<title>v51</title>
|
||||
<polygon fill="none" stroke="black" points="1780.61,-324 1128.83,-324 1128.83,-288 1780.61,-288 1780.61,-324"/>
|
||||
<text text-anchor="middle" x="1454.72" y="-301.8" font-family="Times,serif" font-size="14.00">v51 (readonly renderedItems$4.length @ Binary readonly renderedItems$4.length >= readonly max$7) <update></text>
|
||||
<polygon fill="none" stroke="black" points="1771.25,-324 1119.47,-324 1119.47,-288 1771.25,-288 1771.25,-324"/>
|
||||
<text text-anchor="middle" x="1445.36" y="-301.8" font-family="Times,serif" font-size="14.00">v51 (readonly renderedItems$4.length @ Binary readonly renderedItems$4.length >= readonly max$7) <update></text>
|
||||
</g>
|
||||
<!-- v49->v51 -->
|
||||
<g id="edge43" class="edge">
|
||||
<title>v49->v51</title>
|
||||
<path fill="none" stroke="black" d="M1454.72,-359.7C1454.72,-351.98 1454.72,-342.71 1454.72,-334.11"/>
|
||||
<polygon fill="black" stroke="black" points="1458.22,-334.1 1454.72,-324.1 1451.22,-334.1 1458.22,-334.1"/>
|
||||
<path fill="none" stroke="black" d="M1445.36,-359.7C1445.36,-351.98 1445.36,-342.71 1445.36,-334.11"/>
|
||||
<polygon fill="black" stroke="black" points="1448.86,-334.1 1445.36,-324.1 1441.86,-334.1 1448.86,-334.1"/>
|
||||
</g>
|
||||
<!-- v62->v18 -->
|
||||
<g id="edge54" class="edge">
|
||||
<title>v62->v18</title>
|
||||
<path fill="none" stroke="black" d="M1678.72,-215.7C1678.72,-207.98 1678.72,-198.71 1678.72,-190.11"/>
|
||||
<polygon fill="black" stroke="black" points="1682.22,-190.1 1678.72,-180.1 1675.22,-190.1 1682.22,-190.1"/>
|
||||
<path fill="none" stroke="black" d="M1669.36,-215.7C1669.36,-207.98 1669.36,-198.71 1669.36,-190.11"/>
|
||||
<polygon fill="black" stroke="black" points="1672.86,-190.1 1669.36,-180.1 1665.86,-190.1 1672.86,-190.1"/>
|
||||
</g>
|
||||
<!-- v71->v49 -->
|
||||
<g id="edge55" class="edge">
|
||||
<title>v71->v49</title>
|
||||
<path fill="none" stroke="black" d="M1099.11,-252.13C1098.24,-272.34 1100.23,-305.52 1119.72,-324 1136.11,-339.54 1172.75,-350.52 1216.03,-358.28"/>
|
||||
<polygon fill="black" stroke="black" points="1215.51,-361.75 1225.96,-359.99 1216.7,-354.85 1215.51,-361.75"/>
|
||||
<path fill="none" stroke="black" d="M1089.75,-252.13C1088.89,-272.34 1090.87,-305.52 1110.36,-324 1126.75,-339.54 1163.39,-350.52 1206.67,-358.28"/>
|
||||
<polygon fill="black" stroke="black" points="1206.15,-361.75 1216.6,-359.99 1207.34,-354.85 1206.15,-361.75"/>
|
||||
</g>
|
||||
<!-- v5 -->
|
||||
<g id="node12" class="node">
|
||||
<title>v5</title>
|
||||
<polygon fill="none" stroke="black" points="2081.28,-470.8 1762.16,-470.8 1762.16,-434.8 2081.28,-434.8 2081.28,-470.8"/>
|
||||
<text text-anchor="middle" x="1921.72" y="-448.6" font-family="Times,serif" font-size="14.00">v5 (mutable Set$6 @ New mutable Set$6()) <update></text>
|
||||
<polygon fill="none" stroke="black" points="2071.92,-470.8 1752.8,-470.8 1752.8,-434.8 2071.92,-434.8 2071.92,-470.8"/>
|
||||
<text text-anchor="middle" x="1912.36" y="-448.6" font-family="Times,serif" font-size="14.00">v5 (mutable Set$6 @ New mutable Set$6()) <update></text>
|
||||
</g>
|
||||
<!-- v6 -->
|
||||
<g id="node13" class="node">
|
||||
<title>v6</title>
|
||||
<polygon fill="none" stroke="black" points="2605.75,-470.8 2135.68,-470.8 2135.68,-434.8 2605.75,-434.8 2605.75,-470.8"/>
|
||||
<text text-anchor="middle" x="2370.72" y="-448.6" font-family="Times,serif" font-size="14.00">v6 (readonly seen$5 @ Const readonly seen$5 = New mutable Set$6()) <assign></text>
|
||||
<polygon fill="none" stroke="black" points="2595.4,-470.8 2125.33,-470.8 2125.33,-434.8 2595.4,-434.8 2595.4,-470.8"/>
|
||||
<text text-anchor="middle" x="2360.36" y="-448.6" font-family="Times,serif" font-size="14.00">v6 (readonly seen$5 @ Const readonly seen$5 = New mutable Set$6()) <assign></text>
|
||||
</g>
|
||||
<!-- v39 -->
|
||||
<g id="node14" class="node">
|
||||
<title>v39</title>
|
||||
<polygon fill="none" stroke="black" points="2604.1,-396 2137.33,-396 2137.33,-360 2604.1,-360 2604.1,-396"/>
|
||||
<text text-anchor="middle" x="2370.72" y="-373.8" font-family="Times,serif" font-size="14.00">v39 (mutable seen$5.has @ Call mutable seen$5.has(frozen item$10)) <update></text>
|
||||
<polygon fill="none" stroke="black" points="2593.17,-396 2127.55,-396 2127.55,-360 2593.17,-360 2593.17,-396"/>
|
||||
<text text-anchor="middle" x="2360.36" y="-373.8" font-family="Times,serif" font-size="14.00">v39 (mutable seen$5.has @ Call mutable seen$5.has(freeze item$10)) <update></text>
|
||||
</g>
|
||||
<!-- v6->v39 -->
|
||||
<g id="edge10" class="edge">
|
||||
<title>v6->v39</title>
|
||||
<path fill="none" stroke="black" d="M2370.72,-434.55C2370.72,-426.12 2370.72,-415.77 2370.72,-406.3"/>
|
||||
<polygon fill="black" stroke="black" points="2374.22,-406.13 2370.72,-396.13 2367.22,-406.13 2374.22,-406.13"/>
|
||||
<path fill="none" stroke="black" d="M2360.36,-434.55C2360.36,-426.12 2360.36,-415.77 2360.36,-406.3"/>
|
||||
<polygon fill="black" stroke="black" points="2363.86,-406.13 2360.36,-396.13 2356.86,-406.13 2363.86,-406.13"/>
|
||||
</g>
|
||||
<!-- v56 -->
|
||||
<g id="node15" class="node">
|
||||
<title>v56</title>
|
||||
<polygon fill="none" stroke="black" points="2221.46,-324 1997.98,-324 1997.98,-288 2221.46,-288 2221.46,-324"/>
|
||||
<text text-anchor="middle" x="2109.72" y="-301.8" font-family="Times,serif" font-size="14.00">v56 (<join> @ <no-instr>) <update></text>
|
||||
<polygon fill="none" stroke="black" points="2211.1,-324 1987.62,-324 1987.62,-288 2211.1,-288 2211.1,-324"/>
|
||||
<text text-anchor="middle" x="2099.36" y="-301.8" font-family="Times,serif" font-size="14.00">v56 (<join> @ <no-instr>) <update></text>
|
||||
</g>
|
||||
<!-- v6->v56 -->
|
||||
<g id="edge11" class="edge">
|
||||
<title>v6->v56</title>
|
||||
<path fill="none" stroke="black" d="M2241.91,-434.79C2193.23,-425.81 2145.5,-413.06 2128.72,-396 2112.92,-379.94 2108.83,-354.16 2108.3,-334.47"/>
|
||||
<polygon fill="black" stroke="black" points="2111.8,-334.26 2108.32,-324.26 2104.8,-334.25 2111.8,-334.26"/>
|
||||
<path fill="none" stroke="black" d="M2231.55,-434.79C2182.87,-425.81 2135.14,-413.06 2118.36,-396 2102.56,-379.94 2098.47,-354.16 2097.94,-334.47"/>
|
||||
<polygon fill="black" stroke="black" points="2101.44,-334.26 2097.96,-324.26 2094.44,-334.25 2101.44,-334.26"/>
|
||||
</g>
|
||||
<!-- v59 -->
|
||||
<g id="node16" class="node">
|
||||
<title>v59</title>
|
||||
<polygon fill="none" stroke="black" points="2493.46,-180 2269.98,-180 2269.98,-144 2493.46,-144 2493.46,-180"/>
|
||||
<text text-anchor="middle" x="2381.72" y="-157.8" font-family="Times,serif" font-size="14.00">v59 (<join> @ <no-instr>) <update></text>
|
||||
<polygon fill="none" stroke="black" points="2482.1,-180 2258.62,-180 2258.62,-144 2482.1,-144 2482.1,-180"/>
|
||||
<text text-anchor="middle" x="2370.36" y="-157.8" font-family="Times,serif" font-size="14.00">v59 (<join> @ <no-instr>) <update></text>
|
||||
</g>
|
||||
<!-- v6->v59 -->
|
||||
<g id="edge12" class="edge">
|
||||
<title>v6->v59</title>
|
||||
<path fill="none" stroke="black" d="M2510.26,-434.76C2556,-426.1 2598.73,-413.59 2612.72,-396 2680.39,-310.95 2518.87,-223.25 2432.21,-184.09"/>
|
||||
<polygon fill="black" stroke="black" points="2433.61,-180.89 2423.05,-180.01 2430.76,-187.28 2433.61,-180.89"/>
|
||||
<path fill="none" stroke="black" d="M2499.9,-434.76C2545.64,-426.1 2588.37,-413.59 2602.36,-396 2670.09,-310.88 2508.44,-223.38 2421.37,-184.21"/>
|
||||
<polygon fill="black" stroke="black" points="2422.73,-180.98 2412.17,-180.12 2419.88,-187.38 2422.73,-180.98"/>
|
||||
</g>
|
||||
<!-- v39->v56 -->
|
||||
<g id="edge33" class="edge">
|
||||
<title>v39->v56</title>
|
||||
<path fill="none" stroke="black" d="M2307.21,-359.97C2269.79,-349.93 2222.29,-337.19 2183.25,-326.72"/>
|
||||
<polygon fill="black" stroke="black" points="2184.08,-323.32 2173.52,-324.11 2182.27,-330.08 2184.08,-323.32"/>
|
||||
<path fill="none" stroke="black" d="M2296.85,-359.97C2259.43,-349.93 2211.93,-337.19 2172.89,-326.72"/>
|
||||
<polygon fill="black" stroke="black" points="2173.73,-323.32 2163.16,-324.11 2171.91,-330.08 2173.73,-323.32"/>
|
||||
</g>
|
||||
<!-- v39->v59 -->
|
||||
<g id="edge34" class="edge">
|
||||
<title>v39->v59</title>
|
||||
<path fill="none" stroke="black" d="M2367.72,-359.85C2366.09,-322.83 2370.32,-235.18 2375.62,-190.39"/>
|
||||
<polygon fill="black" stroke="black" points="2379.12,-190.6 2376.95,-180.23 2372.18,-189.69 2379.12,-190.6"/>
|
||||
<path fill="none" stroke="black" d="M2357.28,-359.85C2355.48,-322.83 2359.3,-235.18 2364.39,-190.39"/>
|
||||
<polygon fill="black" stroke="black" points="2367.89,-190.59 2365.67,-180.23 2360.95,-189.72 2367.89,-190.59"/>
|
||||
</g>
|
||||
<!-- v43 -->
|
||||
<g id="node52" class="node">
|
||||
<title>v43</title>
|
||||
<polygon fill="none" stroke="black" points="2344.71,-252 1874.73,-252 1874.73,-216 2344.71,-216 2344.71,-252"/>
|
||||
<text text-anchor="middle" x="2109.72" y="-229.8" font-family="Times,serif" font-size="14.00">v43 (mutable seen$5.add @ Call mutable seen$5.add(frozen item$10)) <update></text>
|
||||
<polygon fill="none" stroke="black" points="2333.78,-252 1864.94,-252 1864.94,-216 2333.78,-216 2333.78,-252"/>
|
||||
<text text-anchor="middle" x="2099.36" y="-229.8" font-family="Times,serif" font-size="14.00">v43 (mutable seen$5.add @ Call mutable seen$5.add(freeze item$10)) <update></text>
|
||||
</g>
|
||||
<!-- v56->v43 -->
|
||||
<g id="edge50" class="edge">
|
||||
<title>v56->v43</title>
|
||||
<path fill="none" stroke="black" d="M2103.8,-287.7C2103.01,-279.98 2102.78,-270.71 2103.12,-262.11"/>
|
||||
<polygon fill="black" stroke="black" points="2106.62,-262.32 2103.82,-252.1 2099.63,-261.84 2106.62,-262.32"/>
|
||||
<path fill="none" stroke="black" d="M2093.45,-287.7C2092.65,-279.98 2092.42,-270.71 2092.77,-262.11"/>
|
||||
<polygon fill="black" stroke="black" points="2096.26,-262.32 2093.47,-252.1 2089.28,-261.84 2096.26,-262.32"/>
|
||||
</g>
|
||||
<!-- v59->v39 -->
|
||||
<g id="edge53" class="edge">
|
||||
<title>v59->v39</title>
|
||||
<path fill="none" stroke="black" d="M2384.72,-180.23C2386.34,-217.32 2382.1,-304.98 2376.81,-349.71"/>
|
||||
<polygon fill="black" stroke="black" points="2373.31,-349.48 2375.48,-359.85 2380.25,-350.39 2373.31,-349.48"/>
|
||||
<path fill="none" stroke="black" d="M2373.44,-180.23C2375.24,-217.32 2371.41,-304.98 2366.32,-349.71"/>
|
||||
<polygon fill="black" stroke="black" points="2362.82,-349.49 2365.04,-359.85 2369.77,-350.37 2362.82,-349.49"/>
|
||||
</g>
|
||||
<!-- v7 -->
|
||||
<g id="node17" class="node">
|
||||
<title>v7</title>
|
||||
<polygon fill="none" stroke="black" points="3071.76,-470.8 2763.68,-470.8 2763.68,-434.8 3071.76,-434.8 3071.76,-470.8"/>
|
||||
<text text-anchor="middle" x="2917.72" y="-448.6" font-family="Times,serif" font-size="14.00">v7 (readonly $9 @ Const readonly $9 = 0) <assign></text>
|
||||
<polygon fill="none" stroke="black" points="3060.4,-470.8 2752.32,-470.8 2752.32,-434.8 3060.4,-434.8 3060.4,-470.8"/>
|
||||
<text text-anchor="middle" x="2906.36" y="-448.6" font-family="Times,serif" font-size="14.00">v7 (readonly $9 @ Const readonly $9 = 0) <assign></text>
|
||||
</g>
|
||||
<!-- v9 -->
|
||||
<g id="node18" class="node">
|
||||
<title>v9</title>
|
||||
<polygon fill="none" stroke="black" points="3175.6,-396 2659.83,-396 2659.83,-360 3175.6,-360 3175.6,-396"/>
|
||||
<text text-anchor="middle" x="2917.72" y="-373.8" font-family="Times,serif" font-size="14.00">v9 (mutable $9 @ Call mutable Math$8.max(mutable $9, frozen maxItems$3)) <update></text>
|
||||
<polygon fill="none" stroke="black" points="3163.67,-396 2649.05,-396 2649.05,-360 3163.67,-360 3163.67,-396"/>
|
||||
<text text-anchor="middle" x="2906.36" y="-373.8" font-family="Times,serif" font-size="14.00">v9 (mutable $9 @ Call mutable Math$8.max(mutable $9, freeze maxItems$3)) <update></text>
|
||||
</g>
|
||||
<!-- v7->v9 -->
|
||||
<g id="edge13" class="edge">
|
||||
<title>v7->v9</title>
|
||||
<path fill="none" stroke="black" d="M2917.72,-434.55C2917.72,-426.12 2917.72,-415.77 2917.72,-406.3"/>
|
||||
<polygon fill="black" stroke="black" points="2921.22,-406.13 2917.72,-396.13 2914.22,-406.13 2921.22,-406.13"/>
|
||||
<path fill="none" stroke="black" d="M2906.36,-434.55C2906.36,-426.12 2906.36,-415.77 2906.36,-406.3"/>
|
||||
<polygon fill="black" stroke="black" points="2909.86,-406.13 2906.36,-396.13 2902.86,-406.13 2909.86,-406.13"/>
|
||||
</g>
|
||||
<!-- v8 -->
|
||||
<g id="node19" class="node">
|
||||
<title>v8</title>
|
||||
<polygon fill="none" stroke="black" points="3663.26,-470.8 3090.18,-470.8 3090.18,-434.8 3663.26,-434.8 3663.26,-470.8"/>
|
||||
<text text-anchor="middle" x="3376.72" y="-448.6" font-family="Times,serif" font-size="14.00">v8 (mutable Math$8.max @ Call mutable Math$8.max(mutable $9, frozen maxItems$3)) <update></text>
|
||||
<polygon fill="none" stroke="black" points="3650.33,-470.8 3078.39,-470.8 3078.39,-434.8 3650.33,-434.8 3650.33,-470.8"/>
|
||||
<text text-anchor="middle" x="3364.36" y="-448.6" font-family="Times,serif" font-size="14.00">v8 (mutable Math$8.max @ Call mutable Math$8.max(mutable $9, freeze maxItems$3)) <update></text>
|
||||
</g>
|
||||
<!-- v11 -->
|
||||
<g id="node20" class="node">
|
||||
<title>v11</title>
|
||||
<polygon fill="none" stroke="black" points="4371.93,-470.8 3681.51,-470.8 3681.51,-434.8 4371.93,-434.8 4371.93,-470.8"/>
|
||||
<text text-anchor="middle" x="4026.72" y="-448.6" font-family="Times,serif" font-size="14.00">v11 (readonly max$7 @ Const readonly max$7 = Call mutable Math$8.max(mutable $9, frozen maxItems$3)) <assign></text>
|
||||
<polygon fill="none" stroke="black" points="4356.5,-470.8 3668.23,-470.8 3668.23,-434.8 4356.5,-434.8 4356.5,-470.8"/>
|
||||
<text text-anchor="middle" x="4012.36" y="-448.6" font-family="Times,serif" font-size="14.00">v11 (readonly max$7 @ Const readonly max$7 = Call mutable Math$8.max(mutable $9, freeze maxItems$3)) <assign></text>
|
||||
</g>
|
||||
<!-- v52 -->
|
||||
<g id="node21" class="node">
|
||||
<title>v52</title>
|
||||
<polygon fill="none" stroke="black" points="4147.15,-396 3590.29,-396 3590.29,-360 4147.15,-360 4147.15,-396"/>
|
||||
<text text-anchor="middle" x="3868.72" y="-373.8" font-family="Times,serif" font-size="14.00">v52 (readonly max$7 @ Binary readonly renderedItems$4.length >= readonly max$7) <update></text>
|
||||
<polygon fill="none" stroke="black" points="4131.79,-396 3574.93,-396 3574.93,-360 4131.79,-360 4131.79,-396"/>
|
||||
<text text-anchor="middle" x="3853.36" y="-373.8" font-family="Times,serif" font-size="14.00">v52 (readonly max$7 @ Binary readonly renderedItems$4.length >= readonly max$7) <update></text>
|
||||
</g>
|
||||
<!-- v11->v52 -->
|
||||
<g id="edge14" class="edge">
|
||||
<title>v11->v52</title>
|
||||
<path fill="none" stroke="black" d="M3989.68,-434.73C3967.37,-424.45 3938.78,-411.28 3915,-400.32"/>
|
||||
<polygon fill="black" stroke="black" points="3916.35,-397.09 3905.8,-396.09 3913.42,-403.45 3916.35,-397.09"/>
|
||||
<path fill="none" stroke="black" d="M3975.08,-434.73C3952.64,-424.45 3923.87,-411.28 3899.93,-400.32"/>
|
||||
<polygon fill="black" stroke="black" points="3901.23,-397.07 3890.68,-396.09 3898.32,-403.43 3901.23,-397.07"/>
|
||||
</g>
|
||||
<!-- v72 -->
|
||||
<g id="node22" class="node">
|
||||
<title>v72</title>
|
||||
<polygon fill="none" stroke="black" points="3980.46,-324 3756.98,-324 3756.98,-288 3980.46,-288 3980.46,-324"/>
|
||||
<text text-anchor="middle" x="3868.72" y="-301.8" font-family="Times,serif" font-size="14.00">v72 (<join> @ <no-instr>) <update></text>
|
||||
<polygon fill="none" stroke="black" points="3965.1,-324 3741.62,-324 3741.62,-288 3965.1,-288 3965.1,-324"/>
|
||||
<text text-anchor="middle" x="3853.36" y="-301.8" font-family="Times,serif" font-size="14.00">v72 (<join> @ <no-instr>) <update></text>
|
||||
</g>
|
||||
<!-- v11->v72 -->
|
||||
<g id="edge15" class="edge">
|
||||
<title>v11->v72</title>
|
||||
<path fill="none" stroke="black" d="M4104.56,-434.72C4124.57,-426.42 4143.79,-414.15 4155.72,-396 4164.5,-382.63 4165.95,-372.3 4155.72,-360 4134.33,-334.29 4058.68,-321.01 3990.43,-314.16"/>
|
||||
<polygon fill="black" stroke="black" points="3990.71,-310.68 3980.42,-313.2 3990.03,-317.64 3990.71,-310.68"/>
|
||||
<path fill="none" stroke="black" d="M4089.28,-434.72C4109.25,-426.43 4128.47,-414.15 4140.36,-396 4149.13,-382.62 4150.6,-372.3 4140.36,-360 4118.97,-334.29 4043.32,-321.01 3975.07,-314.16"/>
|
||||
<polygon fill="black" stroke="black" points="3975.35,-310.68 3965.06,-313.2 3974.68,-317.64 3975.35,-310.68"/>
|
||||
</g>
|
||||
<!-- v52->v72 -->
|
||||
<g id="edge47" class="edge">
|
||||
<title>v52->v72</title>
|
||||
<path fill="none" stroke="black" d="M3862.8,-359.7C3862.01,-351.98 3861.78,-342.71 3862.12,-334.11"/>
|
||||
<polygon fill="black" stroke="black" points="3865.62,-334.32 3862.82,-324.1 3858.63,-333.84 3865.62,-334.32"/>
|
||||
<path fill="none" stroke="black" d="M3847.45,-359.7C3846.65,-351.98 3846.42,-342.71 3846.77,-334.11"/>
|
||||
<polygon fill="black" stroke="black" points="3850.26,-334.32 3847.47,-324.1 3843.28,-333.84 3850.26,-334.32"/>
|
||||
</g>
|
||||
<!-- v72->v52 -->
|
||||
<g id="edge56" class="edge">
|
||||
<title>v72->v52</title>
|
||||
<path fill="none" stroke="black" d="M3874.61,-324.1C3875.42,-331.79 3875.66,-341.05 3875.32,-349.67"/>
|
||||
<polygon fill="black" stroke="black" points="3871.83,-349.48 3874.63,-359.7 3878.81,-349.96 3871.83,-349.48"/>
|
||||
<path fill="none" stroke="black" d="M3859.26,-324.1C3860.06,-331.79 3860.3,-341.05 3859.96,-349.67"/>
|
||||
<polygon fill="black" stroke="black" points="3856.47,-349.48 3859.28,-359.7 3863.45,-349.96 3856.47,-349.48"/>
|
||||
</g>
|
||||
<!-- v13 -->
|
||||
<g id="node23" class="node">
|
||||
<title>v13</title>
|
||||
<polygon fill="none" stroke="black" points="4733.54,-470.8 4389.9,-470.8 4389.9,-434.8 4733.54,-434.8 4733.54,-470.8"/>
|
||||
<text text-anchor="middle" x="4561.72" y="-448.6" font-family="Times,serif" font-size="14.00">v13 (readonly $11 @ Const readonly $11 = null) <assign></text>
|
||||
<polygon fill="none" stroke="black" points="4718.18,-470.8 4374.54,-470.8 4374.54,-434.8 4718.18,-434.8 4718.18,-470.8"/>
|
||||
<text text-anchor="middle" x="4546.36" y="-448.6" font-family="Times,serif" font-size="14.00">v13 (readonly $11 @ Const readonly $11 = null) <assign></text>
|
||||
</g>
|
||||
<!-- v15 -->
|
||||
<g id="node24" class="node">
|
||||
<title>v15</title>
|
||||
<polygon fill="none" stroke="black" points="4773.03,-396 4350.41,-396 4350.41,-360 4773.03,-360 4773.03,-396"/>
|
||||
<text text-anchor="middle" x="4561.72" y="-373.8" font-family="Times,serif" font-size="14.00">v15 (readonly $11 @ Binary frozen item$10 == readonly $11) <update></text>
|
||||
<polygon fill="none" stroke="black" points="4757.1,-396 4335.62,-396 4335.62,-360 4757.1,-360 4757.1,-396"/>
|
||||
<text text-anchor="middle" x="4546.36" y="-373.8" font-family="Times,serif" font-size="14.00">v15 (readonly $11 @ Binary freeze item$10 == readonly $11) <update></text>
|
||||
</g>
|
||||
<!-- v13->v15 -->
|
||||
<g id="edge16" class="edge">
|
||||
<title>v13->v15</title>
|
||||
<path fill="none" stroke="black" d="M4561.72,-434.55C4561.72,-426.12 4561.72,-415.77 4561.72,-406.3"/>
|
||||
<polygon fill="black" stroke="black" points="4565.22,-406.13 4561.72,-396.13 4558.22,-406.13 4565.22,-406.13"/>
|
||||
<path fill="none" stroke="black" d="M4546.36,-434.55C4546.36,-426.12 4546.36,-415.77 4546.36,-406.3"/>
|
||||
<polygon fill="black" stroke="black" points="4549.86,-406.13 4546.36,-396.13 4542.86,-406.13 4549.86,-406.13"/>
|
||||
</g>
|
||||
<!-- v14 -->
|
||||
<g id="node25" class="node">
|
||||
<title>v14</title>
|
||||
<polygon fill="none" stroke="black" points="5488.19,-470.8 5053.25,-470.8 5053.25,-434.8 5488.19,-434.8 5488.19,-470.8"/>
|
||||
<text text-anchor="middle" x="5270.72" y="-448.6" font-family="Times,serif" font-size="14.00">v14 (frozen item$10 @ Binary frozen item$10 == readonly $11) <update></text>
|
||||
<polygon fill="none" stroke="black" points="5467.19,-470.8 5035.54,-470.8 5035.54,-434.8 5467.19,-434.8 5467.19,-470.8"/>
|
||||
<text text-anchor="middle" x="5251.36" y="-448.6" font-family="Times,serif" font-size="14.00">v14 (freeze item$10 @ Binary freeze item$10 == readonly $11) <update></text>
|
||||
</g>
|
||||
<!-- v40 -->
|
||||
<g id="node26" class="node">
|
||||
<title>v40</title>
|
||||
<polygon fill="none" stroke="black" points="5234.1,-396 4791.33,-396 4791.33,-360 5234.1,-360 5234.1,-396"/>
|
||||
<text text-anchor="middle" x="5012.72" y="-373.8" font-family="Times,serif" font-size="14.00">v40 (frozen item$10 @ Call mutable seen$5.has(frozen item$10)) <update></text>
|
||||
<polygon fill="none" stroke="black" points="5214.1,-396 4774.62,-396 4774.62,-360 5214.1,-360 5214.1,-396"/>
|
||||
<text text-anchor="middle" x="4994.36" y="-373.8" font-family="Times,serif" font-size="14.00">v40 (freeze item$10 @ Call mutable seen$5.has(freeze item$10)) <update></text>
|
||||
</g>
|
||||
<!-- v14->v40 -->
|
||||
<g id="edge17" class="edge">
|
||||
<title>v14->v40</title>
|
||||
<path fill="none" stroke="black" d="M5210.23,-434.73C5172.12,-423.98 5122.76,-410.05 5082.92,-398.81"/>
|
||||
<polygon fill="black" stroke="black" points="5083.85,-395.43 5073.28,-396.09 5081.95,-402.17 5083.85,-395.43"/>
|
||||
<path fill="none" stroke="black" d="M5191.11,-434.73C5153.22,-424 5104.18,-410.11 5064.55,-398.88"/>
|
||||
<polygon fill="black" stroke="black" points="5065.26,-395.45 5054.68,-396.09 5063.35,-402.18 5065.26,-395.45"/>
|
||||
</g>
|
||||
<!-- v57 -->
|
||||
<g id="node27" class="node">
|
||||
<title>v57</title>
|
||||
<polygon fill="none" stroke="black" points="5382.46,-324 5158.98,-324 5158.98,-288 5382.46,-288 5382.46,-324"/>
|
||||
<text text-anchor="middle" x="5270.72" y="-301.8" font-family="Times,serif" font-size="14.00">v57 (<join> @ <no-instr>) <update></text>
|
||||
<polygon fill="none" stroke="black" points="5363.1,-324 5139.62,-324 5139.62,-288 5363.1,-288 5363.1,-324"/>
|
||||
<text text-anchor="middle" x="5251.36" y="-301.8" font-family="Times,serif" font-size="14.00">v57 (<join> @ <no-instr>) <update></text>
|
||||
</g>
|
||||
<!-- v14->v57 -->
|
||||
<g id="edge18" class="edge">
|
||||
<title>v14->v57</title>
|
||||
<path fill="none" stroke="black" d="M5266.16,-434.62C5263.56,-409.8 5263.27,-363.66 5265.31,-334.19"/>
|
||||
<polygon fill="black" stroke="black" points="5268.8,-334.42 5266.17,-324.16 5261.83,-333.82 5268.8,-334.42"/>
|
||||
<path fill="none" stroke="black" d="M5246.81,-434.62C5244.2,-409.8 5243.91,-363.66 5245.95,-334.19"/>
|
||||
<polygon fill="black" stroke="black" points="5249.45,-334.42 5246.81,-324.16 5242.47,-333.82 5249.45,-334.42"/>
|
||||
</g>
|
||||
<!-- v40->v57 -->
|
||||
<g id="edge35" class="edge">
|
||||
<title>v40->v57</title>
|
||||
<path fill="none" stroke="black" d="M5075.5,-359.97C5112.34,-349.97 5159.05,-337.3 5197.54,-326.85"/>
|
||||
<polygon fill="black" stroke="black" points="5198.92,-330.11 5207.65,-324.11 5197.09,-323.35 5198.92,-330.11"/>
|
||||
<path fill="none" stroke="black" d="M5056.9,-359.97C5093.59,-349.97 5140.12,-337.3 5178.47,-326.85"/>
|
||||
<polygon fill="black" stroke="black" points="5179.81,-330.12 5188.54,-324.11 5177.97,-323.36 5179.81,-330.12"/>
|
||||
</g>
|
||||
<!-- v57->v14 -->
|
||||
<g id="edge52" class="edge">
|
||||
<title>v57->v14</title>
|
||||
<path fill="none" stroke="black" d="M5275.27,-324.16C5277.88,-348.96 5278.17,-395.1 5276.13,-424.58"/>
|
||||
<polygon fill="black" stroke="black" points="5272.64,-424.36 5275.27,-434.62 5279.61,-424.95 5272.64,-424.36"/>
|
||||
<path fill="none" stroke="black" d="M5255.91,-324.16C5258.52,-348.96 5258.81,-395.1 5256.77,-424.58"/>
|
||||
<polygon fill="black" stroke="black" points="5253.28,-424.36 5255.92,-434.62 5260.25,-424.95 5253.28,-424.36"/>
|
||||
</g>
|
||||
<!-- v44 -->
|
||||
<g id="node53" class="node">
|
||||
<title>v44</title>
|
||||
<polygon fill="none" stroke="black" points="5367.66,-252 4923.78,-252 4923.78,-216 5367.66,-216 5367.66,-252"/>
|
||||
<text text-anchor="middle" x="5145.72" y="-229.8" font-family="Times,serif" font-size="14.00">v44 (frozen item$10 @ Call mutable seen$5.add(frozen item$10)) <update></text>
|
||||
<polygon fill="none" stroke="black" points="5347.65,-252 4907.07,-252 4907.07,-216 5347.65,-216 5347.65,-252"/>
|
||||
<text text-anchor="middle" x="5127.36" y="-229.8" font-family="Times,serif" font-size="14.00">v44 (freeze item$10 @ Call mutable seen$5.add(freeze item$10)) <update></text>
|
||||
</g>
|
||||
<!-- v57->v44 -->
|
||||
<g id="edge51" class="edge">
|
||||
<title>v57->v44</title>
|
||||
<path fill="none" stroke="black" d="M5240.14,-287.88C5223.65,-278.64 5203.1,-267.13 5185.38,-257.21"/>
|
||||
<polygon fill="black" stroke="black" points="5186.85,-254.02 5176.42,-252.19 5183.43,-260.13 5186.85,-254.02"/>
|
||||
<path fill="none" stroke="black" d="M5221.03,-287.88C5204.66,-278.64 5184.28,-267.13 5166.71,-257.21"/>
|
||||
<polygon fill="black" stroke="black" points="5168.24,-254.06 5157.81,-252.19 5164.8,-260.15 5168.24,-254.06"/>
|
||||
</g>
|
||||
<!-- v16 -->
|
||||
<g id="node28" class="node">
|
||||
<title>v16</title>
|
||||
<polygon fill="none" stroke="black" points="6024.81,-470.8 5506.63,-470.8 5506.63,-434.8 6024.81,-434.8 6024.81,-470.8"/>
|
||||
<text text-anchor="middle" x="5765.72" y="-448.6" font-family="Times,serif" font-size="14.00">v16 (frozen $12 @ Const frozen $12 = Binary frozen item$10 == readonly $11) <assign></text>
|
||||
<polygon fill="none" stroke="black" points="5999.24,-470.8 5485.49,-470.8 5485.49,-434.8 5999.24,-434.8 5999.24,-470.8"/>
|
||||
<text text-anchor="middle" x="5742.36" y="-448.6" font-family="Times,serif" font-size="14.00">v16 (freeze $12 @ Const freeze $12 = Binary freeze item$10 == readonly $11) <assign></text>
|
||||
</g>
|
||||
<!-- v17 -->
|
||||
<g id="node29" class="node">
|
||||
<title>v17</title>
|
||||
<polygon fill="none" stroke="black" points="5951.35,-396 5580.09,-396 5580.09,-360 5951.35,-360 5951.35,-396"/>
|
||||
<text text-anchor="middle" x="5765.72" y="-373.8" font-family="Times,serif" font-size="14.00">v17 (frozen $12 @ If (frozen $12) then:bb8 else:bb9) <update></text>
|
||||
<polygon fill="none" stroke="black" points="5926.84,-396 5557.88,-396 5557.88,-360 5926.84,-360 5926.84,-396"/>
|
||||
<text text-anchor="middle" x="5742.36" y="-373.8" font-family="Times,serif" font-size="14.00">v17 (freeze $12 @ If (freeze $12) then:bb8 else:bb9) <update></text>
|
||||
</g>
|
||||
<!-- v16->v17 -->
|
||||
<g id="edge19" class="edge">
|
||||
<title>v16->v17</title>
|
||||
<path fill="none" stroke="black" d="M5765.72,-434.55C5765.72,-426.12 5765.72,-415.77 5765.72,-406.3"/>
|
||||
<polygon fill="black" stroke="black" points="5769.22,-406.13 5765.72,-396.13 5762.22,-406.13 5769.22,-406.13"/>
|
||||
<path fill="none" stroke="black" d="M5742.36,-434.55C5742.36,-426.12 5742.36,-415.77 5742.36,-406.3"/>
|
||||
<polygon fill="black" stroke="black" points="5745.86,-406.13 5742.36,-396.13 5738.86,-406.13 5745.86,-406.13"/>
|
||||
</g>
|
||||
<!-- v38 -->
|
||||
<g id="node30" class="node">
|
||||
<title>v38</title>
|
||||
<polygon fill="none" stroke="black" points="5943.55,-324 5587.88,-324 5587.88,-288 5943.55,-288 5943.55,-324"/>
|
||||
<text text-anchor="middle" x="5765.72" y="-301.8" font-family="Times,serif" font-size="14.00">v38 (frozen $13 @ Const frozen $13 = frozen $12) <assign></text>
|
||||
<polygon fill="none" stroke="black" points="5917.98,-324 5566.74,-324 5566.74,-288 5917.98,-288 5917.98,-324"/>
|
||||
<text text-anchor="middle" x="5742.36" y="-301.8" font-family="Times,serif" font-size="14.00">v38 (freeze $13 @ Const freeze $13 = freeze $12) <assign></text>
|
||||
</g>
|
||||
<!-- v17->v38 -->
|
||||
<g id="edge20" class="edge">
|
||||
<title>v17->v38</title>
|
||||
<path fill="none" stroke="black" d="M5765.72,-359.7C5765.72,-351.98 5765.72,-342.71 5765.72,-334.11"/>
|
||||
<polygon fill="black" stroke="black" points="5769.22,-334.1 5765.72,-324.1 5762.22,-334.1 5769.22,-334.1"/>
|
||||
<path fill="none" stroke="black" d="M5742.36,-359.7C5742.36,-351.98 5742.36,-342.71 5742.36,-334.11"/>
|
||||
<polygon fill="black" stroke="black" points="5745.86,-334.1 5742.36,-324.1 5738.86,-334.1 5745.86,-334.1"/>
|
||||
</g>
|
||||
<!-- v42 -->
|
||||
<g id="node50" class="node">
|
||||
<title>v42</title>
|
||||
<polygon fill="none" stroke="black" points="6187.35,-252 5816.09,-252 5816.09,-216 6187.35,-216 6187.35,-252"/>
|
||||
<text text-anchor="middle" x="6001.72" y="-229.8" font-family="Times,serif" font-size="14.00">v42 (frozen $13 @ If (frozen $13) then:bb1 else:bb4) <update></text>
|
||||
<polygon fill="none" stroke="black" points="6160.84,-252 5791.88,-252 5791.88,-216 6160.84,-216 6160.84,-252"/>
|
||||
<text text-anchor="middle" x="5976.36" y="-229.8" font-family="Times,serif" font-size="14.00">v42 (freeze $13 @ If (freeze $13) then:bb1 else:bb4) <update></text>
|
||||
</g>
|
||||
<!-- v38->v42 -->
|
||||
<g id="edge32" class="edge">
|
||||
<title>v38->v42</title>
|
||||
<path fill="none" stroke="black" d="M5823.15,-287.97C5856.7,-278.01 5899.21,-265.41 5934.33,-254.99"/>
|
||||
<polygon fill="black" stroke="black" points="5935.44,-258.31 5944.03,-252.11 5933.45,-251.6 5935.44,-258.31"/>
|
||||
<path fill="none" stroke="black" d="M5799.3,-287.97C5832.57,-278.01 5874.72,-265.41 5909.55,-254.99"/>
|
||||
<polygon fill="black" stroke="black" points="5910.58,-258.33 5919.16,-252.11 5908.58,-251.62 5910.58,-258.33"/>
|
||||
</g>
|
||||
<!-- v25 -->
|
||||
<g id="node33" class="node">
|
||||
<title>v25</title>
|
||||
<polygon fill="none" stroke="black" points="1595.21,-36 1016.23,-36 1016.23,0 1595.21,0 1595.21,-36"/>
|
||||
<text text-anchor="middle" x="1305.72" y="-13.8" font-family="Times,serif" font-size="14.00">v25 (frozen count$17 @ JSX <frozen $20>{frozen count$17}{frozen $21}</frozen $20>) <update></text>
|
||||
<polygon fill="none" stroke="black" points="1585.99,-36 1014.73,-36 1014.73,0 1585.99,0 1585.99,-36"/>
|
||||
<text text-anchor="middle" x="1300.36" y="-13.8" font-family="Times,serif" font-size="14.00">v25 (freeze count$17 @ JSX <freeze $20>{freeze count$17}{freeze $21}</freeze $20>) <update></text>
|
||||
</g>
|
||||
<!-- v19->v25 -->
|
||||
<g id="edge23" class="edge">
|
||||
<title>v19->v25</title>
|
||||
<path fill="none" stroke="black" d="M1305.72,-71.7C1305.72,-63.98 1305.72,-54.71 1305.72,-46.11"/>
|
||||
<polygon fill="black" stroke="black" points="1309.22,-46.1 1305.72,-36.1 1302.22,-46.1 1309.22,-46.1"/>
|
||||
<path fill="none" stroke="black" d="M1300.36,-71.7C1300.36,-63.98 1300.36,-54.71 1300.36,-46.11"/>
|
||||
<polygon fill="black" stroke="black" points="1303.86,-46.1 1300.36,-36.1 1296.86,-46.1 1303.86,-46.1"/>
|
||||
</g>
|
||||
<!-- v20 -->
|
||||
<g id="node34" class="node">
|
||||
<title>v20</title>
|
||||
<polygon fill="none" stroke="black" points="6550.58,-470.8 6198.86,-470.8 6198.86,-434.8 6550.58,-434.8 6550.58,-470.8"/>
|
||||
<text text-anchor="middle" x="6374.72" y="-448.6" font-family="Times,serif" font-size="14.00">v20 (readonly $18 @ Const readonly $18 = "div") <assign></text>
|
||||
<polygon fill="none" stroke="black" points="6519.22,-470.8 6167.5,-470.8 6167.5,-434.8 6519.22,-434.8 6519.22,-470.8"/>
|
||||
<text text-anchor="middle" x="6343.36" y="-448.6" font-family="Times,serif" font-size="14.00">v20 (readonly $18 @ Const readonly $18 = "div") <assign></text>
|
||||
</g>
|
||||
<!-- v30 -->
|
||||
<g id="node35" class="node">
|
||||
<title>v30</title>
|
||||
<polygon fill="none" stroke="black" points="6780.14,-396 5969.3,-396 5969.3,-360 6780.14,-360 6780.14,-396"/>
|
||||
<text text-anchor="middle" x="6374.72" y="-373.8" font-family="Times,serif" font-size="14.00">v30 (frozen $18 @ JSX <frozen $18>{frozen $19}{frozen $22}{frozen $23}{frozen renderedItems$4}{frozen $24}</frozen $18>) <update></text>
|
||||
<polygon fill="none" stroke="black" points="6742.71,-396 5944.02,-396 5944.02,-360 6742.71,-360 6742.71,-396"/>
|
||||
<text text-anchor="middle" x="6343.36" y="-373.8" font-family="Times,serif" font-size="14.00">v30 (freeze $18 @ JSX <freeze $18>{freeze $19}{freeze $22}{freeze $23}{freeze renderedItems$4}{freeze $24}</freeze $18>) <update></text>
|
||||
</g>
|
||||
<!-- v20->v30 -->
|
||||
<g id="edge24" class="edge">
|
||||
<title>v20->v30</title>
|
||||
<path fill="none" stroke="black" d="M6374.72,-434.55C6374.72,-426.12 6374.72,-415.77 6374.72,-406.3"/>
|
||||
<polygon fill="black" stroke="black" points="6378.22,-406.13 6374.72,-396.13 6371.22,-406.13 6378.22,-406.13"/>
|
||||
<path fill="none" stroke="black" d="M6343.36,-434.55C6343.36,-426.12 6343.36,-415.77 6343.36,-406.3"/>
|
||||
<polygon fill="black" stroke="black" points="6346.86,-406.13 6343.36,-396.13 6339.86,-406.13 6346.86,-406.13"/>
|
||||
</g>
|
||||
<!-- v21 -->
|
||||
<g id="node36" class="node">
|
||||
<title>v21</title>
|
||||
<polygon fill="none" stroke="black" points="7338.02,-473.4 7069.42,-473.4 7069.42,-432.2 7338.02,-432.2 7338.02,-473.4"/>
|
||||
<text text-anchor="middle" x="7203.72" y="-457" font-family="Times,serif" font-size="14.00">v21 (readonly $19 @ Const readonly $19 = "</text>
|
||||
<text text-anchor="middle" x="7203.72" y="-440.2" font-family="Times,serif" font-size="14.00">      ") <assign></text>
|
||||
<polygon fill="none" stroke="black" points="7293.66,-473.4 7025.06,-473.4 7025.06,-432.2 7293.66,-432.2 7293.66,-473.4"/>
|
||||
<text text-anchor="middle" x="7159.36" y="-457" font-family="Times,serif" font-size="14.00">v21 (readonly $19 @ Const readonly $19 = "</text>
|
||||
<text text-anchor="middle" x="7159.36" y="-440.2" font-family="Times,serif" font-size="14.00">      ") <assign></text>
|
||||
</g>
|
||||
<!-- v31 -->
|
||||
<g id="node37" class="node">
|
||||
<title>v31</title>
|
||||
<polygon fill="none" stroke="black" points="7609.14,-396 6798.3,-396 6798.3,-360 7609.14,-360 7609.14,-396"/>
|
||||
<text text-anchor="middle" x="7203.72" y="-373.8" font-family="Times,serif" font-size="14.00">v31 (frozen $19 @ JSX <frozen $18>{frozen $19}{frozen $22}{frozen $23}{frozen renderedItems$4}{frozen $24}</frozen $18>) <update></text>
|
||||
<polygon fill="none" stroke="black" points="7558.71,-396 6760.02,-396 6760.02,-360 7558.71,-360 7558.71,-396"/>
|
||||
<text text-anchor="middle" x="7159.36" y="-373.8" font-family="Times,serif" font-size="14.00">v31 (freeze $19 @ JSX <freeze $18>{freeze $19}{freeze $22}{freeze $23}{freeze renderedItems$4}{freeze $24}</freeze $18>) <update></text>
|
||||
</g>
|
||||
<!-- v21->v31 -->
|
||||
<g id="edge25" class="edge">
|
||||
<title>v21->v31</title>
|
||||
<path fill="none" stroke="black" d="M7203.72,-431.91C7203.72,-424.09 7203.72,-414.99 7203.72,-406.56"/>
|
||||
<polygon fill="black" stroke="black" points="7207.22,-406.39 7203.72,-396.39 7200.22,-406.39 7207.22,-406.39"/>
|
||||
<path fill="none" stroke="black" d="M7159.36,-431.91C7159.36,-424.09 7159.36,-414.99 7159.36,-406.56"/>
|
||||
<polygon fill="black" stroke="black" points="7162.86,-406.39 7159.36,-396.39 7155.86,-406.39 7162.86,-406.39"/>
|
||||
</g>
|
||||
<!-- v22 -->
|
||||
<g id="node38" class="node">
|
||||
<title>v22</title>
|
||||
<polygon fill="none" stroke="black" points="8074.69,-470.8 7726.75,-470.8 7726.75,-434.8 8074.69,-434.8 8074.69,-470.8"/>
|
||||
<text text-anchor="middle" x="7900.72" y="-448.6" font-family="Times,serif" font-size="14.00">v22 (readonly $20 @ Const readonly $20 = "h1") <assign></text>
|
||||
<polygon fill="none" stroke="black" points="8020.33,-470.8 7672.39,-470.8 7672.39,-434.8 8020.33,-434.8 8020.33,-470.8"/>
|
||||
<text text-anchor="middle" x="7846.36" y="-448.6" font-family="Times,serif" font-size="14.00">v22 (readonly $20 @ Const readonly $20 = "h1") <assign></text>
|
||||
</g>
|
||||
<!-- v24 -->
|
||||
<g id="node39" class="node">
|
||||
<title>v24</title>
|
||||
<polygon fill="none" stroke="black" points="8174.6,-396 7626.84,-396 7626.84,-360 8174.6,-360 8174.6,-396"/>
|
||||
<text text-anchor="middle" x="7900.72" y="-373.8" font-family="Times,serif" font-size="14.00">v24 (frozen $20 @ JSX <frozen $20>{frozen count$17}{frozen $21}</frozen $20>) <update></text>
|
||||
<polygon fill="none" stroke="black" points="8116.38,-396 7576.34,-396 7576.34,-360 8116.38,-360 8116.38,-396"/>
|
||||
<text text-anchor="middle" x="7846.36" y="-373.8" font-family="Times,serif" font-size="14.00">v24 (freeze $20 @ JSX <freeze $20>{freeze count$17}{freeze $21}</freeze $20>) <update></text>
|
||||
</g>
|
||||
<!-- v22->v24 -->
|
||||
<g id="edge26" class="edge">
|
||||
<title>v22->v24</title>
|
||||
<path fill="none" stroke="black" d="M7900.72,-434.55C7900.72,-426.12 7900.72,-415.77 7900.72,-406.3"/>
|
||||
<polygon fill="black" stroke="black" points="7904.22,-406.13 7900.72,-396.13 7897.22,-406.13 7904.22,-406.13"/>
|
||||
<path fill="none" stroke="black" d="M7846.36,-434.55C7846.36,-426.12 7846.36,-415.77 7846.36,-406.3"/>
|
||||
<polygon fill="black" stroke="black" points="7849.86,-406.13 7846.36,-396.13 7842.86,-406.13 7849.86,-406.13"/>
|
||||
</g>
|
||||
<!-- v23 -->
|
||||
<g id="node40" class="node">
|
||||
<title>v23</title>
|
||||
<polygon fill="none" stroke="black" points="8650.79,-470.8 8282.65,-470.8 8282.65,-434.8 8650.79,-434.8 8650.79,-470.8"/>
|
||||
<text text-anchor="middle" x="8466.72" y="-448.6" font-family="Times,serif" font-size="14.00">v23 (readonly $21 @ Const readonly $21 = " Items") <assign></text>
|
||||
<polygon fill="none" stroke="black" points="8588.43,-470.8 8220.29,-470.8 8220.29,-434.8 8588.43,-434.8 8588.43,-470.8"/>
|
||||
<text text-anchor="middle" x="8404.36" y="-448.6" font-family="Times,serif" font-size="14.00">v23 (readonly $21 @ Const readonly $21 = " Items") <assign></text>
|
||||
</g>
|
||||
<!-- v26 -->
|
||||
<g id="node41" class="node">
|
||||
<title>v26</title>
|
||||
<polygon fill="none" stroke="black" points="8740.6,-396 8192.84,-396 8192.84,-360 8740.6,-360 8740.6,-396"/>
|
||||
<text text-anchor="middle" x="8466.72" y="-373.8" font-family="Times,serif" font-size="14.00">v26 (frozen $21 @ JSX <frozen $20>{frozen count$17}{frozen $21}</frozen $20>) <update></text>
|
||||
<polygon fill="none" stroke="black" points="8674.38,-396 8134.34,-396 8134.34,-360 8674.38,-360 8674.38,-396"/>
|
||||
<text text-anchor="middle" x="8404.36" y="-373.8" font-family="Times,serif" font-size="14.00">v26 (freeze $21 @ JSX <freeze $20>{freeze count$17}{freeze $21}</freeze $20>) <update></text>
|
||||
</g>
|
||||
<!-- v23->v26 -->
|
||||
<g id="edge27" class="edge">
|
||||
<title>v23->v26</title>
|
||||
<path fill="none" stroke="black" d="M8466.72,-434.55C8466.72,-426.12 8466.72,-415.77 8466.72,-406.3"/>
|
||||
<polygon fill="black" stroke="black" points="8470.22,-406.13 8466.72,-396.13 8463.22,-406.13 8470.22,-406.13"/>
|
||||
<path fill="none" stroke="black" d="M8404.36,-434.55C8404.36,-426.12 8404.36,-415.77 8404.36,-406.3"/>
|
||||
<polygon fill="black" stroke="black" points="8407.86,-406.13 8404.36,-396.13 8400.86,-406.13 8407.86,-406.13"/>
|
||||
</g>
|
||||
<!-- v27 -->
|
||||
<g id="node42" class="node">
|
||||
<title>v27</title>
|
||||
<polygon fill="none" stroke="black" points="9505.56,-470.8 8821.87,-470.8 8821.87,-434.8 9505.56,-434.8 9505.56,-470.8"/>
|
||||
<text text-anchor="middle" x="9163.72" y="-448.6" font-family="Times,serif" font-size="14.00">v27 (readonly $22 @ Const readonly $22 = JSX <frozen $20>{frozen count$17}{frozen $21}</frozen $20>) <assign></text>
|
||||
<polygon fill="none" stroke="black" points="9429.92,-470.8 8752.81,-470.8 8752.81,-434.8 9429.92,-434.8 9429.92,-470.8"/>
|
||||
<text text-anchor="middle" x="9091.36" y="-448.6" font-family="Times,serif" font-size="14.00">v27 (readonly $22 @ Const readonly $22 = JSX <freeze $20>{freeze count$17}{freeze $21}</freeze $20>) <assign></text>
|
||||
</g>
|
||||
<!-- v32 -->
|
||||
<g id="node43" class="node">
|
||||
<title>v32</title>
|
||||
<polygon fill="none" stroke="black" points="9569.14,-396 8758.3,-396 8758.3,-360 9569.14,-360 9569.14,-396"/>
|
||||
<text text-anchor="middle" x="9163.72" y="-373.8" font-family="Times,serif" font-size="14.00">v32 (frozen $22 @ JSX <frozen $18>{frozen $19}{frozen $22}{frozen $23}{frozen renderedItems$4}{frozen $24}</frozen $18>) <update></text>
|
||||
<polygon fill="none" stroke="black" points="9490.71,-396 8692.02,-396 8692.02,-360 9490.71,-360 9490.71,-396"/>
|
||||
<text text-anchor="middle" x="9091.36" y="-373.8" font-family="Times,serif" font-size="14.00">v32 (freeze $22 @ JSX <freeze $18>{freeze $19}{freeze $22}{freeze $23}{freeze renderedItems$4}{freeze $24}</freeze $18>) <update></text>
|
||||
</g>
|
||||
<!-- v27->v32 -->
|
||||
<g id="edge28" class="edge">
|
||||
<title>v27->v32</title>
|
||||
<path fill="none" stroke="black" d="M9163.72,-434.55C9163.72,-426.12 9163.72,-415.77 9163.72,-406.3"/>
|
||||
<polygon fill="black" stroke="black" points="9167.22,-406.13 9163.72,-396.13 9160.22,-406.13 9167.22,-406.13"/>
|
||||
<path fill="none" stroke="black" d="M9091.36,-434.55C9091.36,-426.12 9091.36,-415.77 9091.36,-406.3"/>
|
||||
<polygon fill="black" stroke="black" points="9094.86,-406.13 9091.36,-396.13 9087.86,-406.13 9094.86,-406.13"/>
|
||||
</g>
|
||||
<!-- v28 -->
|
||||
<g id="node44" class="node">
|
||||
<title>v28</title>
|
||||
<polygon fill="none" stroke="black" points="10127.02,-473.4 9858.42,-473.4 9858.42,-432.2 10127.02,-432.2 10127.02,-473.4"/>
|
||||
<text text-anchor="middle" x="9992.72" y="-457" font-family="Times,serif" font-size="14.00">v28 (readonly $23 @ Const readonly $23 = "</text>
|
||||
<text text-anchor="middle" x="9992.72" y="-440.2" font-family="Times,serif" font-size="14.00">      ") <assign></text>
|
||||
<polygon fill="none" stroke="black" points="10041.66,-473.4 9773.06,-473.4 9773.06,-432.2 10041.66,-432.2 10041.66,-473.4"/>
|
||||
<text text-anchor="middle" x="9907.36" y="-457" font-family="Times,serif" font-size="14.00">v28 (readonly $23 @ Const readonly $23 = "</text>
|
||||
<text text-anchor="middle" x="9907.36" y="-440.2" font-family="Times,serif" font-size="14.00">      ") <assign></text>
|
||||
</g>
|
||||
<!-- v33 -->
|
||||
<g id="node45" class="node">
|
||||
<title>v33</title>
|
||||
<polygon fill="none" stroke="black" points="10398.14,-396 9587.3,-396 9587.3,-360 10398.14,-360 10398.14,-396"/>
|
||||
<text text-anchor="middle" x="9992.72" y="-373.8" font-family="Times,serif" font-size="14.00">v33 (frozen $23 @ JSX <frozen $18>{frozen $19}{frozen $22}{frozen $23}{frozen renderedItems$4}{frozen $24}</frozen $18>) <update></text>
|
||||
<polygon fill="none" stroke="black" points="10306.71,-396 9508.02,-396 9508.02,-360 10306.71,-360 10306.71,-396"/>
|
||||
<text text-anchor="middle" x="9907.36" y="-373.8" font-family="Times,serif" font-size="14.00">v33 (freeze $23 @ JSX <freeze $18>{freeze $19}{freeze $22}{freeze $23}{freeze renderedItems$4}{freeze $24}</freeze $18>) <update></text>
|
||||
</g>
|
||||
<!-- v28->v33 -->
|
||||
<g id="edge29" class="edge">
|
||||
<title>v28->v33</title>
|
||||
<path fill="none" stroke="black" d="M9992.72,-431.91C9992.72,-424.09 9992.72,-414.99 9992.72,-406.56"/>
|
||||
<polygon fill="black" stroke="black" points="9996.22,-406.39 9992.72,-396.39 9989.22,-406.39 9996.22,-406.39"/>
|
||||
<path fill="none" stroke="black" d="M9907.36,-431.91C9907.36,-424.09 9907.36,-414.99 9907.36,-406.56"/>
|
||||
<polygon fill="black" stroke="black" points="9910.86,-406.39 9907.36,-396.39 9903.86,-406.39 9910.86,-406.39"/>
|
||||
</g>
|
||||
<!-- v29 -->
|
||||
<g id="node46" class="node">
|
||||
<title>v29</title>
|
||||
<polygon fill="none" stroke="black" points="10956.02,-473.4 10687.42,-473.4 10687.42,-432.2 10956.02,-432.2 10956.02,-473.4"/>
|
||||
<text text-anchor="middle" x="10821.72" y="-457" font-family="Times,serif" font-size="14.00">v29 (readonly $24 @ Const readonly $24 = "</text>
|
||||
<text text-anchor="middle" x="10821.72" y="-440.2" font-family="Times,serif" font-size="14.00">    ") <assign></text>
|
||||
<polygon fill="none" stroke="black" points="10857.66,-473.4 10589.06,-473.4 10589.06,-432.2 10857.66,-432.2 10857.66,-473.4"/>
|
||||
<text text-anchor="middle" x="10723.36" y="-457" font-family="Times,serif" font-size="14.00">v29 (readonly $24 @ Const readonly $24 = "</text>
|
||||
<text text-anchor="middle" x="10723.36" y="-440.2" font-family="Times,serif" font-size="14.00">    ") <assign></text>
|
||||
</g>
|
||||
<!-- v35 -->
|
||||
<g id="node47" class="node">
|
||||
<title>v35</title>
|
||||
<polygon fill="none" stroke="black" points="11227.14,-396 10416.3,-396 10416.3,-360 11227.14,-360 11227.14,-396"/>
|
||||
<text text-anchor="middle" x="10821.72" y="-373.8" font-family="Times,serif" font-size="14.00">v35 (frozen $24 @ JSX <frozen $18>{frozen $19}{frozen $22}{frozen $23}{frozen renderedItems$4}{frozen $24}</frozen $18>) <update></text>
|
||||
<polygon fill="none" stroke="black" points="11122.71,-396 10324.02,-396 10324.02,-360 11122.71,-360 11122.71,-396"/>
|
||||
<text text-anchor="middle" x="10723.36" y="-373.8" font-family="Times,serif" font-size="14.00">v35 (freeze $24 @ JSX <freeze $18>{freeze $19}{freeze $22}{freeze $23}{freeze renderedItems$4}{freeze $24}</freeze $18>) <update></text>
|
||||
</g>
|
||||
<!-- v29->v35 -->
|
||||
<g id="edge30" class="edge">
|
||||
<title>v29->v35</title>
|
||||
<path fill="none" stroke="black" d="M10821.72,-431.91C10821.72,-424.09 10821.72,-414.99 10821.72,-406.56"/>
|
||||
<polygon fill="black" stroke="black" points="10825.22,-406.39 10821.72,-396.39 10818.22,-406.39 10825.22,-406.39"/>
|
||||
<path fill="none" stroke="black" d="M10723.36,-431.91C10723.36,-424.09 10723.36,-414.99 10723.36,-406.56"/>
|
||||
<polygon fill="black" stroke="black" points="10726.86,-406.39 10723.36,-396.39 10719.86,-406.39 10726.86,-406.39"/>
|
||||
</g>
|
||||
<!-- v36 -->
|
||||
<g id="node48" class="node">
|
||||
<title>v36</title>
|
||||
<polygon fill="none" stroke="black" points="11921.1,-470.8 10974.33,-470.8 10974.33,-434.8 11921.1,-434.8 11921.1,-470.8"/>
|
||||
<text text-anchor="middle" x="11447.72" y="-448.6" font-family="Times,serif" font-size="14.00">v36 (readonly $25 @ Const readonly $25 = JSX <frozen $18>{frozen $19}{frozen $22}{frozen $23}{frozen renderedItems$4}{frozen $24}</frozen $18>) <assign></text>
|
||||
<polygon fill="none" stroke="black" points="11811.24,-470.8 10875.48,-470.8 10875.48,-434.8 11811.24,-434.8 11811.24,-470.8"/>
|
||||
<text text-anchor="middle" x="11343.36" y="-448.6" font-family="Times,serif" font-size="14.00">v36 (readonly $25 @ Const readonly $25 = JSX <freeze $18>{freeze $19}{freeze $22}{freeze $23}{freeze renderedItems$4}{freeze $24}</freeze $18>) <assign></text>
|
||||
</g>
|
||||
<!-- v37 -->
|
||||
<g id="node49" class="node">
|
||||
<title>v37</title>
|
||||
<polygon fill="none" stroke="black" points="11592.15,-396 11303.29,-396 11303.29,-360 11592.15,-360 11592.15,-396"/>
|
||||
<text text-anchor="middle" x="11447.72" y="-373.8" font-family="Times,serif" font-size="14.00">v37 (frozen $25 @ Return frozen $25) <update></text>
|
||||
<polygon fill="none" stroke="black" points="11486.15,-396 11200.57,-396 11200.57,-360 11486.15,-360 11486.15,-396"/>
|
||||
<text text-anchor="middle" x="11343.36" y="-373.8" font-family="Times,serif" font-size="14.00">v37 (freeze $25 @ Return freeze $25) <update></text>
|
||||
</g>
|
||||
<!-- v36->v37 -->
|
||||
<g id="edge31" class="edge">
|
||||
<title>v36->v37</title>
|
||||
<path fill="none" stroke="black" d="M11447.72,-434.55C11447.72,-426.12 11447.72,-415.77 11447.72,-406.3"/>
|
||||
<polygon fill="black" stroke="black" points="11451.22,-406.13 11447.72,-396.13 11444.22,-406.13 11451.22,-406.13"/>
|
||||
<path fill="none" stroke="black" d="M11343.36,-434.55C11343.36,-426.12 11343.36,-415.77 11343.36,-406.3"/>
|
||||
<polygon fill="black" stroke="black" points="11346.86,-406.13 11343.36,-396.13 11339.86,-406.13 11346.86,-406.13"/>
|
||||
</g>
|
||||
<!-- v41 -->
|
||||
<g id="node51" class="node">
|
||||
<title>v41</title>
|
||||
<polygon fill="none" stroke="black" points="6514.18,-324 5961.26,-324 5961.26,-288 6514.18,-288 6514.18,-324"/>
|
||||
<text text-anchor="middle" x="6237.72" y="-301.8" font-family="Times,serif" font-size="14.00">v41 (readonly $13 @ Const readonly $13 = Call mutable seen$5.has(frozen item$10)) <assign></text>
|
||||
<polygon fill="none" stroke="black" points="6487.25,-324 5935.47,-324 5935.47,-288 6487.25,-288 6487.25,-324"/>
|
||||
<text text-anchor="middle" x="6211.36" y="-301.8" font-family="Times,serif" font-size="14.00">v41 (readonly $13 @ Const readonly $13 = Call mutable seen$5.has(freeze item$10)) <assign></text>
|
||||
</g>
|
||||
<!-- v41->v42 -->
|
||||
<g id="edge36" class="edge">
|
||||
<title>v41->v42</title>
|
||||
<path fill="none" stroke="black" d="M6180.29,-287.97C6146.74,-278.01 6104.23,-265.41 6069.11,-254.99"/>
|
||||
<polygon fill="black" stroke="black" points="6069.99,-251.6 6059.41,-252.11 6068,-258.31 6069.99,-251.6"/>
|
||||
<path fill="none" stroke="black" d="M6154.17,-287.97C6120.77,-278.01 6078.44,-265.41 6043.46,-254.99"/>
|
||||
<polygon fill="black" stroke="black" points="6044.39,-251.61 6033.8,-252.11 6042.39,-258.32 6044.39,-251.61"/>
|
||||
</g>
|
||||
<!-- v43->v56 -->
|
||||
<g id="edge38" class="edge">
|
||||
<title>v43->v56</title>
|
||||
<path fill="none" stroke="black" d="M2115.61,-252.1C2116.42,-259.79 2116.66,-269.05 2116.32,-277.67"/>
|
||||
<polygon fill="black" stroke="black" points="2112.83,-277.48 2115.63,-287.7 2119.81,-277.96 2112.83,-277.48"/>
|
||||
<path fill="none" stroke="black" d="M2105.26,-252.1C2106.06,-259.79 2106.3,-269.05 2105.96,-277.67"/>
|
||||
<polygon fill="black" stroke="black" points="2102.47,-277.48 2105.28,-287.7 2109.45,-277.96 2102.47,-277.48"/>
|
||||
</g>
|
||||
<!-- v43->v59 -->
|
||||
<g id="edge37" class="edge">
|
||||
<title>v43->v59</title>
|
||||
<path fill="none" stroke="black" d="M2175.91,-215.97C2214.99,-205.91 2264.62,-193.14 2305.35,-182.65"/>
|
||||
<polygon fill="black" stroke="black" points="2306.42,-185.99 2315.23,-180.11 2304.67,-179.21 2306.42,-185.99"/>
|
||||
<path fill="none" stroke="black" d="M2165.31,-215.97C2204.24,-205.91 2253.69,-193.14 2294.27,-182.65"/>
|
||||
<polygon fill="black" stroke="black" points="2295.31,-186 2304.12,-180.11 2293.56,-179.22 2295.31,-186"/>
|
||||
</g>
|
||||
<!-- v47 -->
|
||||
<g id="node54" class="node">
|
||||
<title>v47</title>
|
||||
<polygon fill="none" stroke="black" points="5517.07,-180 5024.36,-180 5024.36,-144 5517.07,-144 5517.07,-180"/>
|
||||
<text text-anchor="middle" x="5270.72" y="-157.8" font-family="Times,serif" font-size="14.00">v47 (frozen item$10 @ JSX <frozen $14>{frozen item$10}</frozen $14>) <update></text>
|
||||
<polygon fill="none" stroke="black" points="5494.43,-180 5008.3,-180 5008.3,-144 5494.43,-144 5494.43,-180"/>
|
||||
<text text-anchor="middle" x="5251.36" y="-157.8" font-family="Times,serif" font-size="14.00">v47 (freeze item$10 @ JSX <freeze $14>{freeze item$10}</freeze $14>) <update></text>
|
||||
</g>
|
||||
<!-- v44->v47 -->
|
||||
<g id="edge39" class="edge">
|
||||
<title>v44->v47</title>
|
||||
<path fill="none" stroke="black" d="M5176.3,-215.88C5192.79,-206.64 5213.34,-195.13 5231.06,-185.21"/>
|
||||
<polygon fill="black" stroke="black" points="5233.01,-188.13 5240.02,-180.19 5229.59,-182.02 5233.01,-188.13"/>
|
||||
<path fill="none" stroke="black" d="M5157.69,-215.88C5174.06,-206.64 5194.44,-195.13 5212.01,-185.21"/>
|
||||
<polygon fill="black" stroke="black" points="5213.92,-188.15 5220.91,-180.19 5210.48,-182.06 5213.92,-188.15"/>
|
||||
</g>
|
||||
<!-- v47->v57 -->
|
||||
<g id="edge41" class="edge">
|
||||
<title>v47->v57</title>
|
||||
<path fill="none" stroke="black" d="M5332.12,-180.05C5349.56,-188.03 5366.55,-199.55 5376.72,-216 5385.13,-229.61 5385.13,-238.39 5376.72,-252 5368.38,-265.5 5355.45,-275.67 5341.44,-283.3"/>
|
||||
<polygon fill="black" stroke="black" points="5339.51,-280.35 5332.12,-287.95 5342.63,-286.62 5339.51,-280.35"/>
|
||||
<path fill="none" stroke="black" d="M5311.93,-180.04C5329.29,-188.04 5346.25,-199.57 5356.36,-216 5364.75,-229.63 5364.75,-238.37 5356.36,-252 5348.06,-265.48 5335.16,-275.66 5321.21,-283.29"/>
|
||||
<polygon fill="black" stroke="black" points="5319.29,-280.34 5311.93,-287.96 5322.43,-286.6 5319.29,-280.34"/>
|
||||
</g>
|
||||
<!-- v45 -->
|
||||
<g id="node55" class="node">
|
||||
<title>v45</title>
|
||||
<polygon fill="none" stroke="black" points="12290.58,-470.8 11938.86,-470.8 11938.86,-434.8 12290.58,-434.8 12290.58,-470.8"/>
|
||||
<text text-anchor="middle" x="12114.72" y="-448.6" font-family="Times,serif" font-size="14.00">v45 (readonly $14 @ Const readonly $14 = "div") <assign></text>
|
||||
<polygon fill="none" stroke="black" points="12180.22,-470.8 11828.5,-470.8 11828.5,-434.8 12180.22,-434.8 12180.22,-470.8"/>
|
||||
<text text-anchor="middle" x="12004.36" y="-448.6" font-family="Times,serif" font-size="14.00">v45 (readonly $14 @ Const readonly $14 = "div") <assign></text>
|
||||
</g>
|
||||
<!-- v46 -->
|
||||
<g id="node56" class="node">
|
||||
<title>v46</title>
|
||||
<polygon fill="none" stroke="black" points="12348.69,-396 11880.75,-396 11880.75,-360 12348.69,-360 12348.69,-396"/>
|
||||
<text text-anchor="middle" x="12114.72" y="-373.8" font-family="Times,serif" font-size="14.00">v46 (frozen $14 @ JSX <frozen $14>{frozen item$10}</frozen $14>) <update></text>
|
||||
<polygon fill="none" stroke="black" points="12235.04,-396 11773.68,-396 11773.68,-360 12235.04,-360 12235.04,-396"/>
|
||||
<text text-anchor="middle" x="12004.36" y="-373.8" font-family="Times,serif" font-size="14.00">v46 (freeze $14 @ JSX <freeze $14>{freeze item$10}</freeze $14>) <update></text>
|
||||
</g>
|
||||
<!-- v45->v46 -->
|
||||
<g id="edge40" class="edge">
|
||||
<title>v45->v46</title>
|
||||
<path fill="none" stroke="black" d="M12114.72,-434.55C12114.72,-426.12 12114.72,-415.77 12114.72,-406.3"/>
|
||||
<polygon fill="black" stroke="black" points="12118.22,-406.13 12114.72,-396.13 12111.22,-406.13 12118.22,-406.13"/>
|
||||
<path fill="none" stroke="black" d="M12004.36,-434.55C12004.36,-426.12 12004.36,-415.77 12004.36,-406.3"/>
|
||||
<polygon fill="black" stroke="black" points="12007.86,-406.13 12004.36,-396.13 12000.86,-406.13 12007.86,-406.13"/>
|
||||
</g>
|
||||
<!-- v48 -->
|
||||
<g id="node57" class="node">
|
||||
<title>v48</title>
|
||||
<polygon fill="none" stroke="black" points="12911.65,-470.8 12307.79,-470.8 12307.79,-434.8 12911.65,-434.8 12911.65,-470.8"/>
|
||||
<text text-anchor="middle" x="12609.72" y="-448.6" font-family="Times,serif" font-size="14.00">v48 (readonly $15 @ Const readonly $15 = JSX <frozen $14>{frozen item$10}</frozen $14>) <assign></text>
|
||||
<polygon fill="none" stroke="black" points="12796.58,-470.8 12198.14,-470.8 12198.14,-434.8 12796.58,-434.8 12796.58,-470.8"/>
|
||||
<text text-anchor="middle" x="12497.36" y="-448.6" font-family="Times,serif" font-size="14.00">v48 (readonly $15 @ Const readonly $15 = JSX <freeze $14>{freeze item$10}</freeze $14>) <assign></text>
|
||||
</g>
|
||||
<!-- v50 -->
|
||||
<g id="node58" class="node">
|
||||
<title>v50</title>
|
||||
<polygon fill="none" stroke="black" points="12847.01,-396 12372.43,-396 12372.43,-360 12847.01,-360 12847.01,-396"/>
|
||||
<text text-anchor="middle" x="12609.72" y="-373.8" font-family="Times,serif" font-size="14.00">v50 (mutable $15 @ Call mutable renderedItems$4.push(mutable $15)) <update></text>
|
||||
<polygon fill="none" stroke="black" points="12734.65,-396 12260.07,-396 12260.07,-360 12734.65,-360 12734.65,-396"/>
|
||||
<text text-anchor="middle" x="12497.36" y="-373.8" font-family="Times,serif" font-size="14.00">v50 (mutable $15 @ Call mutable renderedItems$4.push(mutable $15)) <update></text>
|
||||
</g>
|
||||
<!-- v48->v50 -->
|
||||
<g id="edge42" class="edge">
|
||||
<title>v48->v50</title>
|
||||
<path fill="none" stroke="black" d="M12609.72,-434.55C12609.72,-426.12 12609.72,-415.77 12609.72,-406.3"/>
|
||||
<polygon fill="black" stroke="black" points="12613.22,-406.13 12609.72,-396.13 12606.22,-406.13 12613.22,-406.13"/>
|
||||
<path fill="none" stroke="black" d="M12497.36,-434.55C12497.36,-426.12 12497.36,-415.77 12497.36,-406.3"/>
|
||||
<polygon fill="black" stroke="black" points="12500.86,-406.13 12497.36,-396.13 12493.86,-406.13 12500.86,-406.13"/>
|
||||
</g>
|
||||
<!-- v51->v18 -->
|
||||
<g id="edge44" class="edge">
|
||||
<title>v51->v18</title>
|
||||
<path fill="none" stroke="black" d="M1471.31,-287.84C1490.68,-268.51 1524.34,-237.06 1557.72,-216 1577.57,-203.48 1600.88,-192.5 1621.72,-183.83"/>
|
||||
<polygon fill="black" stroke="black" points="1623.16,-187.03 1631.1,-180.01 1620.52,-180.54 1623.16,-187.03"/>
|
||||
<path fill="none" stroke="black" d="M1461.95,-287.84C1481.32,-268.51 1514.98,-237.06 1548.36,-216 1568.21,-203.48 1591.52,-192.5 1612.36,-183.83"/>
|
||||
<polygon fill="black" stroke="black" points="1613.8,-187.03 1621.74,-180.01 1611.16,-180.54 1613.8,-187.03"/>
|
||||
</g>
|
||||
<!-- v51->v62 -->
|
||||
<g id="edge45" class="edge">
|
||||
<title>v51->v62</title>
|
||||
<path fill="none" stroke="black" d="M1509.23,-287.97C1540.94,-278.06 1581.07,-265.51 1614.33,-255.12"/>
|
||||
<polygon fill="black" stroke="black" points="1615.46,-258.43 1623.96,-252.11 1613.38,-251.75 1615.46,-258.43"/>
|
||||
<path fill="none" stroke="black" d="M1499.87,-287.97C1531.58,-278.06 1571.72,-265.51 1604.97,-255.12"/>
|
||||
<polygon fill="black" stroke="black" points="1606.11,-258.43 1614.61,-252.11 1604.02,-251.75 1606.11,-258.43"/>
|
||||
</g>
|
||||
<!-- v51->v71 -->
|
||||
<g id="edge46" class="edge">
|
||||
<title>v51->v71</title>
|
||||
<path fill="none" stroke="black" d="M1368.57,-287.97C1316.65,-277.7 1250.42,-264.6 1196.8,-254"/>
|
||||
<polygon fill="black" stroke="black" points="1197.43,-250.56 1186.94,-252.05 1196.07,-257.42 1197.43,-250.56"/>
|
||||
<path fill="none" stroke="black" d="M1359.22,-287.97C1307.29,-277.7 1241.06,-264.6 1187.44,-254"/>
|
||||
<polygon fill="black" stroke="black" points="1188.07,-250.56 1177.59,-252.05 1186.72,-257.42 1188.07,-250.56"/>
|
||||
</g>
|
||||
<!-- v53 -->
|
||||
<g id="node60" class="node">
|
||||
<title>v53</title>
|
||||
<polygon fill="none" stroke="black" points="13565.32,-470.8 12930.12,-470.8 12930.12,-434.8 13565.32,-434.8 13565.32,-470.8"/>
|
||||
<text text-anchor="middle" x="13247.72" y="-448.6" font-family="Times,serif" font-size="14.00">v53 (frozen $16 @ Const frozen $16 = Binary readonly renderedItems$4.length >= readonly max$7) <assign></text>
|
||||
<polygon fill="none" stroke="black" points="13447.82,-470.8 12814.9,-470.8 12814.9,-434.8 13447.82,-434.8 13447.82,-470.8"/>
|
||||
<text text-anchor="middle" x="13131.36" y="-448.6" font-family="Times,serif" font-size="14.00">v53 (freeze $16 @ Const freeze $16 = Binary readonly renderedItems$4.length >= readonly max$7) <assign></text>
|
||||
</g>
|
||||
<!-- v54 -->
|
||||
<g id="node61" class="node">
|
||||
<title>v54</title>
|
||||
<polygon fill="none" stroke="black" points="13433.35,-396 13062.09,-396 13062.09,-360 13433.35,-360 13433.35,-396"/>
|
||||
<text text-anchor="middle" x="13247.72" y="-373.8" font-family="Times,serif" font-size="14.00">v54 (frozen $16 @ If (frozen $16) then:bb2 else:bb1) <update></text>
|
||||
<polygon fill="none" stroke="black" points="13315.84,-396 12946.88,-396 12946.88,-360 13315.84,-360 13315.84,-396"/>
|
||||
<text text-anchor="middle" x="13131.36" y="-373.8" font-family="Times,serif" font-size="14.00">v54 (freeze $16 @ If (freeze $16) then:bb2 else:bb1) <update></text>
|
||||
</g>
|
||||
<!-- v53->v54 -->
|
||||
<g id="edge48" class="edge">
|
||||
<title>v53->v54</title>
|
||||
<path fill="none" stroke="black" d="M13247.72,-434.55C13247.72,-426.12 13247.72,-415.77 13247.72,-406.3"/>
|
||||
<polygon fill="black" stroke="black" points="13251.22,-406.13 13247.72,-396.13 13244.22,-406.13 13251.22,-406.13"/>
|
||||
<path fill="none" stroke="black" d="M13131.36,-434.55C13131.36,-426.12 13131.36,-415.77 13131.36,-406.3"/>
|
||||
<polygon fill="black" stroke="black" points="13134.86,-406.13 13131.36,-396.13 13127.86,-406.13 13134.86,-406.13"/>
|
||||
</g>
|
||||
<!-- v55 -->
|
||||
<g id="node62" class="node">
|
||||
<title>v55</title>
|
||||
<polygon fill="none" stroke="black" points="583.43,-470.8 316.01,-470.8 316.01,-434.8 583.43,-434.8 583.43,-470.8"/>
|
||||
<text text-anchor="middle" x="449.72" y="-448.6" font-family="Times,serif" font-size="14.00">v55 (frozen props$1 @ <no-instr>) <assign></text>
|
||||
<polygon fill="none" stroke="black" points="579.5,-470.8 313.22,-470.8 313.22,-434.8 579.5,-434.8 579.5,-470.8"/>
|
||||
<text text-anchor="middle" x="446.36" y="-448.6" font-family="Times,serif" font-size="14.00">v55 (freeze props$1 @ <no-instr>) <assign></text>
|
||||
</g>
|
||||
<!-- v55->v0 -->
|
||||
<g id="edge49" class="edge">
|
||||
<title>v55->v0</title>
|
||||
<path fill="none" stroke="black" d="M449.72,-434.55C449.72,-426.12 449.72,-415.77 449.72,-406.3"/>
|
||||
<polygon fill="black" stroke="black" points="453.22,-406.13 449.72,-396.13 446.22,-406.13 453.22,-406.13"/>
|
||||
<path fill="none" stroke="black" d="M446.36,-434.55C446.36,-426.12 446.36,-415.77 446.36,-406.3"/>
|
||||
<polygon fill="black" stroke="black" points="449.86,-406.13 446.36,-396.13 442.86,-406.13 449.86,-406.13"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 41 KiB |
@@ -4,70 +4,70 @@
|
||||
<!-- Generated by graphviz version 6.0.1 (20220924.0800)
|
||||
-->
|
||||
<!-- Title: BuildDefUseGraph Pages: 1 -->
|
||||
<svg width="5435pt" height="476pt"
|
||||
viewBox="0.00 0.00 5434.75 476.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<svg width="5406pt" height="476pt"
|
||||
viewBox="0.00 0.00 5405.61 476.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 472)">
|
||||
<title>BuildDefUseGraph</title>
|
||||
<polygon fill="white" stroke="none" points="-4,4 -4,-472 5430.75,-472 5430.75,4 -4,4"/>
|
||||
<polygon fill="white" stroke="none" points="-4,4 -4,-472 5401.61,-472 5401.61,4 -4,4"/>
|
||||
<!-- v0 -->
|
||||
<g id="node1" class="node">
|
||||
<title>v0</title>
|
||||
<polygon fill="none" stroke="black" points="866.19,-468 519.21,-468 519.21,-432 866.19,-432 866.19,-468"/>
|
||||
<text text-anchor="middle" x="692.7" y="-445.8" font-family="Times,serif" font-size="14.00">v0 (readonly x$2 @ Let readonly x$2 = Array []) <assign></text>
|
||||
<polygon fill="none" stroke="black" points="863.19,-468 516.21,-468 516.21,-432 863.19,-432 863.19,-468"/>
|
||||
<text text-anchor="middle" x="689.7" y="-445.8" font-family="Times,serif" font-size="14.00">v0 (readonly x$2 @ Let readonly x$2 = Array []) <assign></text>
|
||||
</g>
|
||||
<!-- v7 -->
|
||||
<g id="node2" class="node">
|
||||
<title>v7</title>
|
||||
<polygon fill="none" stroke="black" points="665.13,-396 208.26,-396 208.26,-360 665.13,-360 665.13,-396"/>
|
||||
<text text-anchor="middle" x="436.7" y="-373.8" font-family="Times,serif" font-size="14.00">v7 (mutable x$2.push @ Call mutable x$2.push(frozen props$1.p2)) <update></text>
|
||||
<polygon fill="none" stroke="black" points="662.06,-396 207.34,-396 207.34,-360 662.06,-360 662.06,-396"/>
|
||||
<text text-anchor="middle" x="434.7" y="-373.8" font-family="Times,serif" font-size="14.00">v7 (mutable x$2.push @ Call mutable x$2.push(freeze props$1.p2)) <update></text>
|
||||
</g>
|
||||
<!-- v0->v7 -->
|
||||
<g id="edge1" class="edge">
|
||||
<title>v0->v7</title>
|
||||
<path fill="none" stroke="black" d="M630.4,-431.97C593.85,-421.97 547.5,-409.3 509.31,-398.85"/>
|
||||
<polygon fill="black" stroke="black" points="509.84,-395.37 499.27,-396.11 508,-402.12 509.84,-395.37"/>
|
||||
<path fill="none" stroke="black" d="M627.64,-431.97C591.24,-421.97 545.07,-409.3 507.02,-398.85"/>
|
||||
<polygon fill="black" stroke="black" points="507.6,-395.38 497.03,-396.11 505.75,-402.13 507.6,-395.38"/>
|
||||
</g>
|
||||
<!-- v12 -->
|
||||
<g id="node3" class="node">
|
||||
<title>v12</title>
|
||||
<polygon fill="none" stroke="black" points="637.48,-252 363.91,-252 363.91,-216 637.48,-216 637.48,-252"/>
|
||||
<text text-anchor="middle" x="500.7" y="-229.8" font-family="Times,serif" font-size="14.00">v12 (readonly x$2 @ readonly x$2) <update></text>
|
||||
<polygon fill="none" stroke="black" points="635.48,-252 361.91,-252 361.91,-216 635.48,-216 635.48,-252"/>
|
||||
<text text-anchor="middle" x="498.7" y="-229.8" font-family="Times,serif" font-size="14.00">v12 (readonly x$2 @ readonly x$2) <update></text>
|
||||
</g>
|
||||
<!-- v0->v12 -->
|
||||
<g id="edge2" class="edge">
|
||||
<title>v0->v12</title>
|
||||
<path fill="none" stroke="black" d="M696.22,-431.62C701.7,-399.31 708.32,-329.49 673.7,-288 662.06,-274.06 646.86,-263.72 630.3,-256.05"/>
|
||||
<polygon fill="black" stroke="black" points="631.55,-252.77 620.98,-252.06 628.8,-259.21 631.55,-252.77"/>
|
||||
<path fill="none" stroke="black" d="M693.21,-431.63C698.68,-399.32 705.29,-329.52 670.7,-288 659.05,-274.02 643.81,-263.66 627.2,-256"/>
|
||||
<polygon fill="black" stroke="black" points="628.43,-252.71 617.85,-252.01 625.68,-259.15 628.43,-252.71"/>
|
||||
</g>
|
||||
<!-- v15 -->
|
||||
<g id="node4" class="node">
|
||||
<title>v15</title>
|
||||
<polygon fill="none" stroke="black" points="1029.66,-180 431.73,-180 431.73,-144 1029.66,-144 1029.66,-180"/>
|
||||
<text text-anchor="middle" x="730.7" y="-157.8" font-family="Times,serif" font-size="14.00">v15 (frozen x$2 @ JSX <frozen Component$0 data={frozen x$2} ></frozen Component$0>) <update></text>
|
||||
<polygon fill="none" stroke="black" points="1023.37,-180 432.02,-180 432.02,-144 1023.37,-144 1023.37,-180"/>
|
||||
<text text-anchor="middle" x="727.7" y="-157.8" font-family="Times,serif" font-size="14.00">v15 (freeze x$2 @ JSX <freeze Component$0 data={freeze x$2} ></freeze Component$0>) <update></text>
|
||||
</g>
|
||||
<!-- v0->v15 -->
|
||||
<g id="edge3" class="edge">
|
||||
<title>v0->v15</title>
|
||||
<path fill="none" stroke="black" d="M701.51,-431.81C706.28,-421.66 711.78,-408.41 714.7,-396 731.81,-323.23 732.57,-234.42 731.66,-190.42"/>
|
||||
<polygon fill="black" stroke="black" points="735.15,-190.15 731.4,-180.24 728.16,-190.32 735.15,-190.15"/>
|
||||
<path fill="none" stroke="black" d="M698.51,-431.81C703.28,-421.66 708.78,-408.41 711.7,-396 728.81,-323.23 729.57,-234.42 728.66,-190.42"/>
|
||||
<polygon fill="black" stroke="black" points="732.15,-190.15 728.4,-180.24 725.16,-190.32 732.15,-190.15"/>
|
||||
</g>
|
||||
<!-- v9 -->
|
||||
<g id="node15" class="node">
|
||||
<title>v9</title>
|
||||
<polygon fill="none" stroke="black" points="665.13,-324 208.26,-324 208.26,-288 665.13,-288 665.13,-324"/>
|
||||
<text text-anchor="middle" x="436.7" y="-301.8" font-family="Times,serif" font-size="14.00">v9 (mutable x$2.push @ Call mutable x$2.push(frozen props$1.p3)) <update></text>
|
||||
<polygon fill="none" stroke="black" points="662.06,-324 207.34,-324 207.34,-288 662.06,-288 662.06,-324"/>
|
||||
<text text-anchor="middle" x="434.7" y="-301.8" font-family="Times,serif" font-size="14.00">v9 (mutable x$2.push @ Call mutable x$2.push(freeze props$1.p3)) <update></text>
|
||||
</g>
|
||||
<!-- v7->v9 -->
|
||||
<g id="edge10" class="edge">
|
||||
<title>v7->v9</title>
|
||||
<path fill="none" stroke="black" d="M436.7,-359.7C436.7,-351.98 436.7,-342.71 436.7,-334.11"/>
|
||||
<polygon fill="black" stroke="black" points="440.2,-334.1 436.7,-324.1 433.2,-334.1 440.2,-334.1"/>
|
||||
<path fill="none" stroke="black" d="M434.7,-359.7C434.7,-351.98 434.7,-342.71 434.7,-334.11"/>
|
||||
<polygon fill="black" stroke="black" points="438.2,-334.1 434.7,-324.1 431.2,-334.1 438.2,-334.1"/>
|
||||
</g>
|
||||
<!-- v12->v15 -->
|
||||
<g id="edge15" class="edge">
|
||||
<title>v12->v15</title>
|
||||
<path fill="none" stroke="black" d="M556.67,-215.97C589.22,-206.06 630.44,-193.51 664.58,-183.12"/>
|
||||
<polygon fill="black" stroke="black" points="665.93,-186.37 674.48,-180.11 663.89,-179.67 665.93,-186.37"/>
|
||||
<path fill="none" stroke="black" d="M554.42,-215.97C586.84,-206.06 627.87,-193.51 661.87,-183.12"/>
|
||||
<polygon fill="black" stroke="black" points="663.18,-186.38 671.72,-180.11 661.13,-179.69 663.18,-186.38"/>
|
||||
</g>
|
||||
<!-- v13 -->
|
||||
<g id="node18" class="node">
|
||||
@@ -78,224 +78,224 @@
|
||||
<!-- v12->v13 -->
|
||||
<g id="edge14" class="edge">
|
||||
<title>v12->v13</title>
|
||||
<path fill="none" stroke="black" d="M429.15,-215.97C386.57,-205.83 332.39,-192.93 288.16,-182.4"/>
|
||||
<polygon fill="black" stroke="black" points="288.85,-178.96 278.31,-180.05 287.22,-185.77 288.85,-178.96"/>
|
||||
<path fill="none" stroke="black" d="M427.64,-215.97C385.34,-205.83 331.53,-192.93 287.61,-182.4"/>
|
||||
<polygon fill="black" stroke="black" points="288.36,-178.98 277.82,-180.05 286.73,-185.78 288.36,-178.98"/>
|
||||
</g>
|
||||
<!-- v1 -->
|
||||
<g id="node5" class="node">
|
||||
<title>v1</title>
|
||||
<polygon fill="none" stroke="black" points="1404.19,-180 1047.2,-180 1047.2,-144 1404.19,-144 1404.19,-180"/>
|
||||
<text text-anchor="middle" x="1225.7" y="-157.8" font-family="Times,serif" font-size="14.00">v1 (readonly y$3 @ Let readonly y$3 = undefined) <assign></text>
|
||||
<polygon fill="none" stroke="black" points="1398.19,-180 1041.2,-180 1041.2,-144 1398.19,-144 1398.19,-180"/>
|
||||
<text text-anchor="middle" x="1219.7" y="-157.8" font-family="Times,serif" font-size="14.00">v1 (readonly y$3 @ Let readonly y$3 = undefined) <assign></text>
|
||||
</g>
|
||||
<!-- v17 -->
|
||||
<g id="node6" class="node">
|
||||
<title>v17</title>
|
||||
<polygon fill="none" stroke="black" points="948.63,-108 484.76,-108 484.76,-72 948.63,-72 948.63,-108"/>
|
||||
<text text-anchor="middle" x="716.7" y="-85.8" font-family="Times,serif" font-size="14.00">v17 (mutable y$3.push @ Call mutable y$3.push(frozen props$1.p4)) <update></text>
|
||||
<polygon fill="none" stroke="black" points="944.56,-108 482.84,-108 482.84,-72 944.56,-72 944.56,-108"/>
|
||||
<text text-anchor="middle" x="713.7" y="-85.8" font-family="Times,serif" font-size="14.00">v17 (mutable y$3.push @ Call mutable y$3.push(freeze props$1.p4)) <update></text>
|
||||
</g>
|
||||
<!-- v1->v17 -->
|
||||
<g id="edge4" class="edge">
|
||||
<title>v1->v17</title>
|
||||
<path fill="none" stroke="black" d="M1101.83,-143.97C1025.93,-133.53 928.77,-120.17 851.03,-109.47"/>
|
||||
<polygon fill="black" stroke="black" points="851.06,-105.95 840.68,-108.05 850.1,-112.88 851.06,-105.95"/>
|
||||
<path fill="none" stroke="black" d="M1096.56,-143.97C1021.11,-133.53 924.52,-120.17 847.23,-109.47"/>
|
||||
<polygon fill="black" stroke="black" points="847.33,-105.95 836.94,-108.05 846.37,-112.89 847.33,-105.95"/>
|
||||
</g>
|
||||
<!-- v20 -->
|
||||
<g id="node23" class="node">
|
||||
<title>v20</title>
|
||||
<polygon fill="none" stroke="black" points="1062.85,-36 370.55,-36 370.55,0 1062.85,0 1062.85,-36"/>
|
||||
<text text-anchor="middle" x="716.7" y="-13.8" font-family="Times,serif" font-size="14.00">v20 (frozen y$3 @ JSX <frozen Component$0 data={frozen y$3} >{frozen child$6}</frozen Component$0>) <update></text>
|
||||
<polygon fill="none" stroke="black" points="1055.98,-36 371.41,-36 371.41,0 1055.98,0 1055.98,-36"/>
|
||||
<text text-anchor="middle" x="713.7" y="-13.8" font-family="Times,serif" font-size="14.00">v20 (freeze y$3 @ JSX <freeze Component$0 data={freeze y$3} >{freeze child$6}</freeze Component$0>) <update></text>
|
||||
</g>
|
||||
<!-- v17->v20 -->
|
||||
<g id="edge19" class="edge">
|
||||
<title>v17->v20</title>
|
||||
<path fill="none" stroke="black" d="M716.7,-71.7C716.7,-63.98 716.7,-54.71 716.7,-46.11"/>
|
||||
<polygon fill="black" stroke="black" points="720.2,-46.1 716.7,-36.1 713.2,-46.1 720.2,-46.1"/>
|
||||
<path fill="none" stroke="black" d="M713.7,-71.7C713.7,-63.98 713.7,-54.71 713.7,-46.11"/>
|
||||
<polygon fill="black" stroke="black" points="717.2,-46.1 713.7,-36.1 710.2,-46.1 717.2,-46.1"/>
|
||||
</g>
|
||||
<!-- v2 -->
|
||||
<g id="node7" class="node">
|
||||
<title>v2</title>
|
||||
<polygon fill="none" stroke="black" points="1274.66,-468 946.73,-468 946.73,-432 1274.66,-432 1274.66,-468"/>
|
||||
<text text-anchor="middle" x="1110.7" y="-445.8" font-family="Times,serif" font-size="14.00">v2 (readonly $4 @ Const readonly $4 = false) <assign></text>
|
||||
<polygon fill="none" stroke="black" points="1270.66,-468 942.73,-468 942.73,-432 1270.66,-432 1270.66,-468"/>
|
||||
<text text-anchor="middle" x="1106.7" y="-445.8" font-family="Times,serif" font-size="14.00">v2 (readonly $4 @ Const readonly $4 = false) <assign></text>
|
||||
</g>
|
||||
<!-- v6 -->
|
||||
<g id="node8" class="node">
|
||||
<title>v6</title>
|
||||
<polygon fill="none" stroke="black" points="1462.78,-396 758.61,-396 758.61,-360 1462.78,-360 1462.78,-396"/>
|
||||
<text text-anchor="middle" x="1110.7" y="-373.8" font-family="Times,serif" font-size="14.00">v6 (readonly $4 @ Switch (frozen props$1.p0);   Case readonly $5: bb4;   Case readonly $4: bb2;   Default: bb1) <update></text>
|
||||
<polygon fill="none" stroke="black" points="1457.71,-396 755.68,-396 755.68,-360 1457.71,-360 1457.71,-396"/>
|
||||
<text text-anchor="middle" x="1106.7" y="-373.8" font-family="Times,serif" font-size="14.00">v6 (readonly $4 @ Switch (freeze props$1.p0);   Case readonly $5: bb4;   Case readonly $4: bb2;   Default: bb1) <update></text>
|
||||
</g>
|
||||
<!-- v2->v6 -->
|
||||
<g id="edge5" class="edge">
|
||||
<title>v2->v6</title>
|
||||
<path fill="none" stroke="black" d="M1110.7,-431.7C1110.7,-423.98 1110.7,-414.71 1110.7,-406.11"/>
|
||||
<polygon fill="black" stroke="black" points="1114.2,-406.1 1110.7,-396.1 1107.2,-406.1 1114.2,-406.1"/>
|
||||
<path fill="none" stroke="black" d="M1106.7,-431.7C1106.7,-423.98 1106.7,-414.71 1106.7,-406.11"/>
|
||||
<polygon fill="black" stroke="black" points="1110.2,-406.1 1106.7,-396.1 1103.2,-406.1 1110.2,-406.1"/>
|
||||
</g>
|
||||
<!-- v3 -->
|
||||
<g id="node9" class="node">
|
||||
<title>v3</title>
|
||||
<polygon fill="none" stroke="black" points="1994,-468 1671.39,-468 1671.39,-432 1994,-432 1994,-468"/>
|
||||
<text text-anchor="middle" x="1832.7" y="-445.8" font-family="Times,serif" font-size="14.00">v3 (readonly $5 @ Const readonly $5 = true) <assign></text>
|
||||
<polygon fill="none" stroke="black" points="1989,-468 1666.39,-468 1666.39,-432 1989,-432 1989,-468"/>
|
||||
<text text-anchor="middle" x="1827.7" y="-445.8" font-family="Times,serif" font-size="14.00">v3 (readonly $5 @ Const readonly $5 = true) <assign></text>
|
||||
</g>
|
||||
<!-- v5 -->
|
||||
<g id="node10" class="node">
|
||||
<title>v5</title>
|
||||
<polygon fill="none" stroke="black" points="2184.78,-396 1480.61,-396 1480.61,-360 2184.78,-360 2184.78,-396"/>
|
||||
<text text-anchor="middle" x="1832.7" y="-373.8" font-family="Times,serif" font-size="14.00">v5 (readonly $5 @ Switch (frozen props$1.p0);   Case readonly $5: bb4;   Case readonly $4: bb2;   Default: bb1) <update></text>
|
||||
<polygon fill="none" stroke="black" points="2178.71,-396 1476.68,-396 1476.68,-360 2178.71,-360 2178.71,-396"/>
|
||||
<text text-anchor="middle" x="1827.7" y="-373.8" font-family="Times,serif" font-size="14.00">v5 (readonly $5 @ Switch (freeze props$1.p0);   Case readonly $5: bb4;   Case readonly $4: bb2;   Default: bb1) <update></text>
|
||||
</g>
|
||||
<!-- v3->v5 -->
|
||||
<g id="edge6" class="edge">
|
||||
<title>v3->v5</title>
|
||||
<path fill="none" stroke="black" d="M1832.7,-431.7C1832.7,-423.98 1832.7,-414.71 1832.7,-406.11"/>
|
||||
<polygon fill="black" stroke="black" points="1836.2,-406.1 1832.7,-396.1 1829.2,-406.1 1836.2,-406.1"/>
|
||||
<path fill="none" stroke="black" d="M1827.7,-431.7C1827.7,-423.98 1827.7,-414.71 1827.7,-406.11"/>
|
||||
<polygon fill="black" stroke="black" points="1831.2,-406.1 1827.7,-396.1 1824.2,-406.1 1831.2,-406.1"/>
|
||||
</g>
|
||||
<!-- v4 -->
|
||||
<g id="node11" class="node">
|
||||
<title>v4</title>
|
||||
<polygon fill="none" stroke="black" points="2942.66,-396 2202.73,-396 2202.73,-360 2942.66,-360 2942.66,-396"/>
|
||||
<text text-anchor="middle" x="2572.7" y="-373.8" font-family="Times,serif" font-size="14.00">v4 (frozen props$1.p0 @ Switch (frozen props$1.p0);   Case readonly $5: bb4;   Case readonly $4: bb2;   Default: bb1) <update></text>
|
||||
<polygon fill="none" stroke="black" points="2933.02,-396 2196.37,-396 2196.37,-360 2933.02,-360 2933.02,-396"/>
|
||||
<text text-anchor="middle" x="2564.7" y="-373.8" font-family="Times,serif" font-size="14.00">v4 (freeze props$1.p0 @ Switch (freeze props$1.p0);   Case readonly $5: bb4;   Case readonly $4: bb2;   Default: bb1) <update></text>
|
||||
</g>
|
||||
<!-- v8 -->
|
||||
<g id="node12" class="node">
|
||||
<title>v8</title>
|
||||
<polygon fill="none" stroke="black" points="2542.95,-324 2084.45,-324 2084.45,-288 2542.95,-288 2542.95,-324"/>
|
||||
<text text-anchor="middle" x="2313.7" y="-301.8" font-family="Times,serif" font-size="14.00">v8 (frozen props$1.p2 @ Call mutable x$2.push(frozen props$1.p2)) <update></text>
|
||||
<polygon fill="none" stroke="black" points="2535.3,-324 2080.09,-324 2080.09,-288 2535.3,-288 2535.3,-324"/>
|
||||
<text text-anchor="middle" x="2307.7" y="-301.8" font-family="Times,serif" font-size="14.00">v8 (freeze props$1.p2 @ Call mutable x$2.push(freeze props$1.p2)) <update></text>
|
||||
</g>
|
||||
<!-- v4->v8 -->
|
||||
<g id="edge7" class="edge">
|
||||
<title>v4->v8</title>
|
||||
<path fill="none" stroke="black" d="M2509.67,-359.97C2472.54,-349.93 2425.4,-337.19 2386.66,-326.72"/>
|
||||
<polygon fill="black" stroke="black" points="2387.57,-323.34 2377.01,-324.11 2385.75,-330.1 2387.57,-323.34"/>
|
||||
<path fill="none" stroke="black" d="M2502.16,-359.97C2465.47,-349.97 2418.94,-337.3 2380.59,-326.85"/>
|
||||
<polygon fill="black" stroke="black" points="2381.09,-323.36 2370.52,-324.11 2379.25,-330.12 2381.09,-323.36"/>
|
||||
</g>
|
||||
<!-- v18 -->
|
||||
<g id="node13" class="node">
|
||||
<title>v18</title>
|
||||
<polygon fill="none" stroke="black" points="2773.45,-108 2307.95,-108 2307.95,-72 2773.45,-72 2773.45,-108"/>
|
||||
<text text-anchor="middle" x="2540.7" y="-85.8" font-family="Times,serif" font-size="14.00">v18 (frozen props$1.p4 @ Call mutable y$3.push(frozen props$1.p4)) <update></text>
|
||||
<polygon fill="none" stroke="black" points="2763.8,-108 2301.59,-108 2301.59,-72 2763.8,-72 2763.8,-108"/>
|
||||
<text text-anchor="middle" x="2532.7" y="-85.8" font-family="Times,serif" font-size="14.00">v18 (freeze props$1.p4 @ Call mutable y$3.push(freeze props$1.p4)) <update></text>
|
||||
</g>
|
||||
<!-- v4->v18 -->
|
||||
<g id="edge8" class="edge">
|
||||
<title>v4->v18</title>
|
||||
<path fill="none" stroke="black" d="M2580.59,-359.75C2584.8,-349.58 2589.55,-336.33 2591.7,-324 2605.4,-245.18 2621.6,-218.2 2591.7,-144 2587.35,-133.21 2579.63,-123.39 2571.5,-115.21"/>
|
||||
<polygon fill="black" stroke="black" points="2573.69,-112.46 2564,-108.18 2568.91,-117.57 2573.69,-112.46"/>
|
||||
<path fill="none" stroke="black" d="M2572.59,-359.75C2576.8,-349.58 2581.55,-336.33 2583.7,-324 2597.4,-245.18 2613.6,-218.2 2583.7,-144 2579.35,-133.21 2571.63,-123.39 2563.5,-115.21"/>
|
||||
<polygon fill="black" stroke="black" points="2565.69,-112.46 2556,-108.18 2560.91,-117.57 2565.69,-112.46"/>
|
||||
</g>
|
||||
<!-- v25 -->
|
||||
<g id="node14" class="node">
|
||||
<title>v25</title>
|
||||
<polygon fill="none" stroke="black" points="2582.44,-180 2358.96,-180 2358.96,-144 2582.44,-144 2582.44,-180"/>
|
||||
<text text-anchor="middle" x="2470.7" y="-157.8" font-family="Times,serif" font-size="14.00">v25 (<join> @ <no-instr>) <update></text>
|
||||
<polygon fill="none" stroke="black" points="2574.44,-180 2350.96,-180 2350.96,-144 2574.44,-144 2574.44,-180"/>
|
||||
<text text-anchor="middle" x="2462.7" y="-157.8" font-family="Times,serif" font-size="14.00">v25 (<join> @ <no-instr>) <update></text>
|
||||
</g>
|
||||
<!-- v4->v25 -->
|
||||
<g id="edge9" class="edge">
|
||||
<title>v4->v25</title>
|
||||
<path fill="none" stroke="black" d="M2575.17,-359.94C2578.77,-328.75 2582.25,-261.55 2553.7,-216 2545.8,-203.41 2533.7,-193.25 2521.15,-185.34"/>
|
||||
<polygon fill="black" stroke="black" points="2522.84,-182.27 2512.44,-180.21 2519.29,-188.3 2522.84,-182.27"/>
|
||||
<path fill="none" stroke="black" d="M2567.17,-359.94C2570.77,-328.75 2574.25,-261.55 2545.7,-216 2537.8,-203.41 2525.7,-193.25 2513.15,-185.34"/>
|
||||
<polygon fill="black" stroke="black" points="2514.84,-182.27 2504.44,-180.21 2511.29,-188.3 2514.84,-182.27"/>
|
||||
</g>
|
||||
<!-- v10 -->
|
||||
<g id="node16" class="node">
|
||||
<title>v10</title>
|
||||
<polygon fill="none" stroke="black" points="2544.45,-252 2078.95,-252 2078.95,-216 2544.45,-216 2544.45,-252"/>
|
||||
<text text-anchor="middle" x="2311.7" y="-229.8" font-family="Times,serif" font-size="14.00">v10 (frozen props$1.p3 @ Call mutable x$2.push(frozen props$1.p3)) <update></text>
|
||||
<polygon fill="none" stroke="black" points="2536.8,-252 2074.59,-252 2074.59,-216 2536.8,-216 2536.8,-252"/>
|
||||
<text text-anchor="middle" x="2305.7" y="-229.8" font-family="Times,serif" font-size="14.00">v10 (freeze props$1.p3 @ Call mutable x$2.push(freeze props$1.p3)) <update></text>
|
||||
</g>
|
||||
<!-- v8->v10 -->
|
||||
<g id="edge11" class="edge">
|
||||
<title>v8->v10</title>
|
||||
<path fill="none" stroke="black" d="M2313.2,-287.7C2312.98,-279.98 2312.72,-270.71 2312.47,-262.11"/>
|
||||
<polygon fill="black" stroke="black" points="2315.97,-262 2312.19,-252.1 2308.97,-262.2 2315.97,-262"/>
|
||||
<path fill="none" stroke="black" d="M2307.2,-287.7C2306.98,-279.98 2306.72,-270.71 2306.47,-262.11"/>
|
||||
<polygon fill="black" stroke="black" points="2309.97,-262 2306.19,-252.1 2302.97,-262.2 2309.97,-262"/>
|
||||
</g>
|
||||
<!-- v25->v18 -->
|
||||
<g id="edge22" class="edge">
|
||||
<title>v25->v18</title>
|
||||
<path fill="none" stroke="black" d="M2488,-143.7C2496.56,-135.14 2507.04,-124.66 2516.39,-115.3"/>
|
||||
<polygon fill="black" stroke="black" points="2519,-117.65 2523.59,-108.1 2514.05,-112.7 2519,-117.65"/>
|
||||
<path fill="none" stroke="black" d="M2480,-143.7C2488.56,-135.14 2499.04,-124.66 2508.39,-115.3"/>
|
||||
<polygon fill="black" stroke="black" points="2511,-117.65 2515.59,-108.1 2506.05,-112.7 2511,-117.65"/>
|
||||
</g>
|
||||
<!-- v9->v12 -->
|
||||
<g id="edge12" class="edge">
|
||||
<title>v9->v12</title>
|
||||
<path fill="none" stroke="black" d="M452.52,-287.7C460.27,-279.22 469.74,-268.86 478.22,-259.58"/>
|
||||
<polygon fill="black" stroke="black" points="480.89,-261.85 485.06,-252.1 475.73,-257.12 480.89,-261.85"/>
|
||||
<path fill="none" stroke="black" d="M450.52,-287.7C458.27,-279.22 467.74,-268.86 476.22,-259.58"/>
|
||||
<polygon fill="black" stroke="black" points="478.89,-261.85 483.06,-252.1 473.73,-257.12 478.89,-261.85"/>
|
||||
</g>
|
||||
<!-- v10->v25 -->
|
||||
<g id="edge13" class="edge">
|
||||
<title>v10->v25</title>
|
||||
<path fill="none" stroke="black" d="M2350.59,-215.88C2372.33,-206.31 2399.6,-194.3 2422.66,-184.15"/>
|
||||
<polygon fill="black" stroke="black" points="2424.19,-187.3 2431.93,-180.07 2421.36,-180.89 2424.19,-187.3"/>
|
||||
<path fill="none" stroke="black" d="M2344.1,-215.88C2365.57,-206.31 2392.5,-194.3 2415.27,-184.15"/>
|
||||
<polygon fill="black" stroke="black" points="2416.71,-187.34 2424.41,-180.07 2413.86,-180.94 2416.71,-187.34"/>
|
||||
</g>
|
||||
<!-- v11 -->
|
||||
<g id="node17" class="node">
|
||||
<title>v11</title>
|
||||
<polygon fill="none" stroke="black" points="3110.58,-468 2724.81,-468 2724.81,-432 3110.58,-432 3110.58,-468"/>
|
||||
<text text-anchor="middle" x="2917.7" y="-445.8" font-family="Times,serif" font-size="14.00">v11 (readonly y$3 @ Reassign readonly y$3 = Array []) <assign></text>
|
||||
<polygon fill="none" stroke="black" points="3101.58,-468 2715.81,-468 2715.81,-432 3101.58,-432 3101.58,-468"/>
|
||||
<text text-anchor="middle" x="2908.7" y="-445.8" font-family="Times,serif" font-size="14.00">v11 (readonly y$3 @ Reassign readonly y$3 = Array []) <assign></text>
|
||||
</g>
|
||||
<!-- v13->v17 -->
|
||||
<g id="edge16" class="edge">
|
||||
<title>v13->v17</title>
|
||||
<path fill="none" stroke="black" d="M330.8,-143.97C406.85,-133.53 504.21,-120.17 582.1,-109.47"/>
|
||||
<polygon fill="black" stroke="black" points="583.04,-112.88 592.47,-108.05 582.09,-105.94 583.04,-112.88"/>
|
||||
<path fill="none" stroke="black" d="M330.07,-143.97C405.67,-133.53 502.46,-120.17 579.9,-109.47"/>
|
||||
<polygon fill="black" stroke="black" points="580.78,-112.88 590.21,-108.05 579.82,-105.95 580.78,-112.88"/>
|
||||
</g>
|
||||
<!-- v14 -->
|
||||
<g id="node19" class="node">
|
||||
<title>v14</title>
|
||||
<polygon fill="none" stroke="black" points="3784.99,-468 3128.4,-468 3128.4,-432 3784.99,-432 3784.99,-468"/>
|
||||
<text text-anchor="middle" x="3456.7" y="-445.8" font-family="Times,serif" font-size="14.00">v14 (frozen Component$0 @ JSX <frozen Component$0 data={frozen x$2} ></frozen Component$0>) <update></text>
|
||||
<polygon fill="none" stroke="black" points="3769.7,-468 3119.69,-468 3119.69,-432 3769.7,-432 3769.7,-468"/>
|
||||
<text text-anchor="middle" x="3444.7" y="-445.8" font-family="Times,serif" font-size="14.00">v14 (freeze Component$0 @ JSX <freeze Component$0 data={freeze x$2} ></freeze Component$0>) <update></text>
|
||||
</g>
|
||||
<!-- v19 -->
|
||||
<g id="node20" class="node">
|
||||
<title>v19</title>
|
||||
<polygon fill="none" stroke="black" points="3832.18,-396 3081.22,-396 3081.22,-360 3832.18,-360 3832.18,-396"/>
|
||||
<text text-anchor="middle" x="3456.7" y="-373.8" font-family="Times,serif" font-size="14.00">v19 (frozen Component$0 @ JSX <frozen Component$0 data={frozen y$3} >{frozen child$6}</frozen Component$0>) <update></text>
|
||||
<polygon fill="none" stroke="black" points="3816.31,-396 3073.08,-396 3073.08,-360 3816.31,-360 3816.31,-396"/>
|
||||
<text text-anchor="middle" x="3444.7" y="-373.8" font-family="Times,serif" font-size="14.00">v19 (freeze Component$0 @ JSX <freeze Component$0 data={freeze y$3} >{freeze child$6}</freeze Component$0>) <update></text>
|
||||
</g>
|
||||
<!-- v14->v19 -->
|
||||
<g id="edge17" class="edge">
|
||||
<title>v14->v19</title>
|
||||
<path fill="none" stroke="black" d="M3456.7,-431.7C3456.7,-423.98 3456.7,-414.71 3456.7,-406.11"/>
|
||||
<polygon fill="black" stroke="black" points="3460.2,-406.1 3456.7,-396.1 3453.2,-406.1 3460.2,-406.1"/>
|
||||
<path fill="none" stroke="black" d="M3444.7,-431.7C3444.7,-423.98 3444.7,-414.71 3444.7,-406.11"/>
|
||||
<polygon fill="black" stroke="black" points="3448.2,-406.1 3444.7,-396.1 3441.2,-406.1 3448.2,-406.1"/>
|
||||
</g>
|
||||
<!-- v16 -->
|
||||
<g id="node21" class="node">
|
||||
<title>v16</title>
|
||||
<polygon fill="none" stroke="black" points="4594.61,-468 3818.79,-468 3818.79,-432 4594.61,-432 4594.61,-468"/>
|
||||
<text text-anchor="middle" x="4206.7" y="-445.8" font-family="Times,serif" font-size="14.00">v16 (readonly child$6 @ Const readonly child$6 = JSX <frozen Component$0 data={frozen x$2} ></frozen Component$0>) <assign></text>
|
||||
<polygon fill="none" stroke="black" points="4571.89,-468 3801.5,-468 3801.5,-432 4571.89,-432 4571.89,-468"/>
|
||||
<text text-anchor="middle" x="4186.7" y="-445.8" font-family="Times,serif" font-size="14.00">v16 (readonly child$6 @ Const readonly child$6 = JSX <freeze Component$0 data={freeze x$2} ></freeze Component$0>) <assign></text>
|
||||
</g>
|
||||
<!-- v21 -->
|
||||
<g id="node22" class="node">
|
||||
<title>v21</title>
|
||||
<polygon fill="none" stroke="black" points="4563.34,-396 3850.06,-396 3850.06,-360 4563.34,-360 4563.34,-396"/>
|
||||
<text text-anchor="middle" x="4206.7" y="-373.8" font-family="Times,serif" font-size="14.00">v21 (frozen child$6 @ JSX <frozen Component$0 data={frozen y$3} >{frozen child$6}</frozen Component$0>) <update></text>
|
||||
<polygon fill="none" stroke="black" points="4539.48,-396 3833.92,-396 3833.92,-360 4539.48,-360 4539.48,-396"/>
|
||||
<text text-anchor="middle" x="4186.7" y="-373.8" font-family="Times,serif" font-size="14.00">v21 (freeze child$6 @ JSX <freeze Component$0 data={freeze y$3} >{freeze child$6}</freeze Component$0>) <update></text>
|
||||
</g>
|
||||
<!-- v16->v21 -->
|
||||
<g id="edge18" class="edge">
|
||||
<title>v16->v21</title>
|
||||
<path fill="none" stroke="black" d="M4206.7,-431.7C4206.7,-423.98 4206.7,-414.71 4206.7,-406.11"/>
|
||||
<polygon fill="black" stroke="black" points="4210.2,-406.1 4206.7,-396.1 4203.2,-406.1 4210.2,-406.1"/>
|
||||
<path fill="none" stroke="black" d="M4186.7,-431.7C4186.7,-423.98 4186.7,-414.71 4186.7,-406.11"/>
|
||||
<polygon fill="black" stroke="black" points="4190.2,-406.1 4186.7,-396.1 4183.2,-406.1 4190.2,-406.1"/>
|
||||
</g>
|
||||
<!-- v22 -->
|
||||
<g id="node24" class="node">
|
||||
<title>v22</title>
|
||||
<polygon fill="none" stroke="black" points="5426.81,-468 4612.59,-468 4612.59,-432 5426.81,-432 5426.81,-468"/>
|
||||
<text text-anchor="middle" x="5019.7" y="-445.8" font-family="Times,serif" font-size="14.00">v22 (readonly $7 @ Const readonly $7 = JSX <frozen Component$0 data={frozen y$3} >{frozen child$6}</frozen Component$0>) <assign></text>
|
||||
<polygon fill="none" stroke="black" points="5397.52,-468 4589.88,-468 4589.88,-432 5397.52,-432 5397.52,-468"/>
|
||||
<text text-anchor="middle" x="4993.7" y="-445.8" font-family="Times,serif" font-size="14.00">v22 (readonly $7 @ Const readonly $7 = JSX <freeze Component$0 data={freeze y$3} >{freeze child$6}</freeze Component$0>) <assign></text>
|
||||
</g>
|
||||
<!-- v23 -->
|
||||
<g id="node25" class="node">
|
||||
<title>v23</title>
|
||||
<polygon fill="none" stroke="black" points="5157.13,-396 4882.26,-396 4882.26,-360 5157.13,-360 5157.13,-396"/>
|
||||
<text text-anchor="middle" x="5019.7" y="-373.8" font-family="Times,serif" font-size="14.00">v23 (frozen $7 @ Return frozen $7) <update></text>
|
||||
<polygon fill="none" stroke="black" points="5129.49,-396 4857.91,-396 4857.91,-360 5129.49,-360 5129.49,-396"/>
|
||||
<text text-anchor="middle" x="4993.7" y="-373.8" font-family="Times,serif" font-size="14.00">v23 (freeze $7 @ Return freeze $7) <update></text>
|
||||
</g>
|
||||
<!-- v22->v23 -->
|
||||
<g id="edge20" class="edge">
|
||||
<title>v22->v23</title>
|
||||
<path fill="none" stroke="black" d="M5019.7,-431.7C5019.7,-423.98 5019.7,-414.71 5019.7,-406.11"/>
|
||||
<polygon fill="black" stroke="black" points="5023.2,-406.1 5019.7,-396.1 5016.2,-406.1 5023.2,-406.1"/>
|
||||
<path fill="none" stroke="black" d="M4993.7,-431.7C4993.7,-423.98 4993.7,-414.71 4993.7,-406.11"/>
|
||||
<polygon fill="black" stroke="black" points="4997.2,-406.1 4993.7,-396.1 4990.2,-406.1 4997.2,-406.1"/>
|
||||
</g>
|
||||
<!-- v24 -->
|
||||
<g id="node26" class="node">
|
||||
<title>v24</title>
|
||||
<polygon fill="none" stroke="black" points="2706.41,-468 2438.98,-468 2438.98,-432 2706.41,-432 2706.41,-468"/>
|
||||
<text text-anchor="middle" x="2572.7" y="-445.8" font-family="Times,serif" font-size="14.00">v24 (frozen props$1 @ <no-instr>) <assign></text>
|
||||
<polygon fill="none" stroke="black" points="2697.84,-468 2431.56,-468 2431.56,-432 2697.84,-432 2697.84,-468"/>
|
||||
<text text-anchor="middle" x="2564.7" y="-445.8" font-family="Times,serif" font-size="14.00">v24 (freeze props$1 @ <no-instr>) <assign></text>
|
||||
</g>
|
||||
<!-- v24->v4 -->
|
||||
<g id="edge21" class="edge">
|
||||
<title>v24->v4</title>
|
||||
<path fill="none" stroke="black" d="M2572.7,-431.7C2572.7,-423.98 2572.7,-414.71 2572.7,-406.11"/>
|
||||
<polygon fill="black" stroke="black" points="2576.2,-406.1 2572.7,-396.1 2569.2,-406.1 2576.2,-406.1"/>
|
||||
<path fill="none" stroke="black" d="M2564.7,-431.7C2564.7,-423.98 2564.7,-414.71 2564.7,-406.11"/>
|
||||
<polygon fill="black" stroke="black" points="2568.2,-406.1 2564.7,-396.1 2561.2,-406.1 2568.2,-406.1"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
@@ -34,15 +34,15 @@ function foo$0() {
|
||||
|
||||
```
|
||||
bb0:
|
||||
Const readonly a$2 = Array []
|
||||
Const readonly b$3 = Object { }
|
||||
Const mutable a$2 = Array []
|
||||
Const mutable b$3 = Object { }
|
||||
Call mutable foo$4(mutable a$2, mutable b$3)
|
||||
Const readonly $6 = "div"
|
||||
Let readonly _$5 = JSX <frozen $6 a={frozen a$2} ></frozen $6>
|
||||
Const mutable $6 = "div"
|
||||
Let mutable _$5 = JSX <readonly $6 a={freeze a$2} ></readonly $6>
|
||||
Call mutable foo$4(mutable b$3)
|
||||
Const readonly $7 = "div"
|
||||
Const readonly $8 = JSX <frozen $7 a={frozen a$2} b={frozen b$3} ></frozen $7>
|
||||
Return frozen $8
|
||||
Const mutable $7 = "div"
|
||||
Const mutable $8 = JSX <readonly $7 a={readonly a$2} b={freeze b$3} ></readonly $7>
|
||||
Return readonly $8
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
@@ -35,45 +35,45 @@ function Component(props) {
|
||||
|
||||
```
|
||||
bb0:
|
||||
Const frozen items$2 = frozen props$1.items
|
||||
Const frozen maxItems$3 = frozen props$1.maxItems
|
||||
Const readonly renderedItems$4 = Array []
|
||||
Const readonly seen$5 = New mutable Set$6()
|
||||
Const readonly $9 = 0
|
||||
Const readonly max$7 = Call mutable Math$8.max(mutable $9, frozen maxItems$3)
|
||||
Const mutable items$2 = readonly props$1.items
|
||||
Const mutable maxItems$3 = readonly props$1.maxItems
|
||||
Const mutable renderedItems$4 = Array []
|
||||
Const mutable seen$5 = New mutable Set$6()
|
||||
Const mutable $9 = 0
|
||||
Const mutable max$7 = Call mutable Math$8.max(readonly $9, readonly maxItems$3)
|
||||
Goto bb1
|
||||
bb1:
|
||||
If (frozen items$2) then:bb3 else:bb2
|
||||
If (readonly items$2) then:bb3 else:bb2
|
||||
bb3:
|
||||
Const readonly $11 = null
|
||||
Const frozen $12 = Binary frozen item$10 == readonly $11
|
||||
If (frozen $12) then:bb8 else:bb9
|
||||
Const mutable $11 = null
|
||||
Const mutable $12 = Binary readonly item$10 == readonly $11
|
||||
If (readonly $12) then:bb8 else:bb9
|
||||
bb2:
|
||||
Const readonly count$17 = readonly renderedItems$4.length
|
||||
Const readonly $18 = "div"
|
||||
Const readonly $19 = "\n "
|
||||
Const readonly $20 = "h1"
|
||||
Const readonly $21 = " Items"
|
||||
Const readonly $22 = JSX <frozen $20>{frozen count$17}{frozen $21}</frozen $20>
|
||||
Const readonly $23 = "\n "
|
||||
Const readonly $24 = "\n "
|
||||
Const readonly $25 = JSX <frozen $18>{frozen $19}{frozen $22}{frozen $23}{frozen renderedItems$4}{frozen $24}</frozen $18>
|
||||
Return frozen $25
|
||||
Const mutable count$17 = readonly renderedItems$4.length
|
||||
Const mutable $18 = "div"
|
||||
Const mutable $19 = "\n "
|
||||
Const mutable $20 = "h1"
|
||||
Const mutable $21 = " Items"
|
||||
Const mutable $22 = JSX <readonly $20>{freeze count$17}{readonly $21}</readonly $20>
|
||||
Const mutable $23 = "\n "
|
||||
Const mutable $24 = "\n "
|
||||
Const mutable $25 = JSX <readonly $18>{readonly $19}{readonly $22}{readonly $23}{freeze renderedItems$4}{readonly $24}</readonly $18>
|
||||
Return readonly $25
|
||||
bb8:
|
||||
Const frozen $13 = frozen $12
|
||||
Const mutable $13 = readonly $12
|
||||
Goto bb7
|
||||
bb9:
|
||||
Const readonly $13 = Call mutable seen$5.has(frozen item$10)
|
||||
Const mutable $13 = Call mutable seen$5.has(mutable item$10)
|
||||
Goto bb7
|
||||
bb7:
|
||||
If (frozen $13) then:bb1 else:bb4
|
||||
If (readonly $13) then:bb1 else:bb4
|
||||
bb4:
|
||||
Call mutable seen$5.add(frozen item$10)
|
||||
Const readonly $14 = "div"
|
||||
Const readonly $15 = JSX <frozen $14>{frozen item$10}</frozen $14>
|
||||
Call mutable renderedItems$4.push(mutable $15)
|
||||
Const frozen $16 = Binary readonly renderedItems$4.length >= readonly max$7
|
||||
If (frozen $16) then:bb2 else:bb1
|
||||
Call mutable seen$5.add(mutable item$10)
|
||||
Const mutable $14 = "div"
|
||||
Const mutable $15 = JSX <readonly $14>{readonly item$10}</readonly $14>
|
||||
Call mutable renderedItems$4.push(readonly $15)
|
||||
Const mutable $16 = Binary readonly renderedItems$4.length >= readonly max$7
|
||||
If (readonly $16) then:bb2 else:bb1
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
@@ -78,15 +78,15 @@ function Component(props) {
|
||||
|
||||
```
|
||||
bb0:
|
||||
Const readonly a_DEBUG$2 = Array []
|
||||
Call mutable a_DEBUG$2.push(frozen props$1.a)
|
||||
If (frozen props$1.b) then:bb2 else:bb1
|
||||
Const mutable a_DEBUG$2 = Array []
|
||||
Call mutable a_DEBUG$2.push(readonly props$1.a)
|
||||
If (readonly props$1.b) then:bb2 else:bb1
|
||||
bb2:
|
||||
Const readonly $3 = null
|
||||
Return frozen $3
|
||||
Const mutable $3 = null
|
||||
Return readonly $3
|
||||
bb1:
|
||||
Call mutable a_DEBUG$2.push(frozen props$1.d)
|
||||
Return frozen a_DEBUG$2
|
||||
Call mutable a_DEBUG$2.push(readonly props$1.d)
|
||||
Return freeze a_DEBUG$2
|
||||
```
|
||||
|
||||
## Code
|
||||
@@ -107,15 +107,15 @@ function Component$0(props$1) {
|
||||
|
||||
```
|
||||
bb0:
|
||||
Const readonly a$2 = Array []
|
||||
Call mutable a$2.push(frozen props$1.a)
|
||||
If (frozen props$1.b) then:bb2 else:bb1
|
||||
Const mutable a$2 = Array []
|
||||
Call mutable a$2.push(readonly props$1.a)
|
||||
If (readonly props$1.b) then:bb2 else:bb1
|
||||
bb2:
|
||||
Call mutable a$2.push(frozen props$1.c)
|
||||
Call mutable a$2.push(readonly props$1.c)
|
||||
Goto bb1
|
||||
bb1:
|
||||
Call mutable a$2.push(frozen props$1.d)
|
||||
Return frozen a$2
|
||||
Call mutable a$2.push(readonly props$1.d)
|
||||
Return freeze a$2
|
||||
```
|
||||
|
||||
## Code
|
||||
@@ -137,16 +137,16 @@ function Component$0(props$1) {
|
||||
|
||||
```
|
||||
bb0:
|
||||
Const readonly a$2 = Array []
|
||||
Call mutable a$2.push(frozen props$1.a)
|
||||
If (frozen props$1.b) then:bb2 else:bb1
|
||||
Const mutable a$2 = Array []
|
||||
Call mutable a$2.push(readonly props$1.a)
|
||||
If (readonly props$1.b) then:bb2 else:bb1
|
||||
bb2:
|
||||
Call mutable a$2.push(frozen props$1.c)
|
||||
Const readonly $3 = null
|
||||
Return frozen $3
|
||||
Call mutable a$2.push(readonly props$1.c)
|
||||
Const mutable $3 = null
|
||||
Return readonly $3
|
||||
bb1:
|
||||
Call mutable a$2.push(frozen props$1.d)
|
||||
Return frozen a$2
|
||||
Call mutable a$2.push(readonly props$1.d)
|
||||
Return freeze a$2
|
||||
```
|
||||
|
||||
## Code
|
||||
@@ -168,15 +168,15 @@ function Component$0(props$1) {
|
||||
|
||||
```
|
||||
bb0:
|
||||
Const readonly a$2 = Array []
|
||||
Call mutable a$2.push(frozen props$1.a)
|
||||
If (frozen props$1.b) then:bb2 else:bb1
|
||||
Const mutable a$2 = Array []
|
||||
Call mutable a$2.push(readonly props$1.a)
|
||||
If (readonly props$1.b) then:bb2 else:bb1
|
||||
bb2:
|
||||
Call mutable a$2.push(frozen props$1.c)
|
||||
Return frozen a$2
|
||||
Call mutable a$2.push(readonly props$1.c)
|
||||
Return freeze a$2
|
||||
bb1:
|
||||
Call mutable a$2.push(frozen props$1.d)
|
||||
Return frozen a$2
|
||||
Call mutable a$2.push(readonly props$1.d)
|
||||
Return freeze a$2
|
||||
```
|
||||
|
||||
## Code
|
||||
@@ -198,14 +198,14 @@ function Component$0(props$1) {
|
||||
|
||||
```
|
||||
bb0:
|
||||
Const readonly a$2 = Array []
|
||||
Call mutable a$2.push(frozen props$1.a)
|
||||
If (frozen props$1.b) then:bb1 else:bb2
|
||||
Const mutable a$2 = Array []
|
||||
Call mutable a$2.push(readonly props$1.a)
|
||||
If (readonly props$1.b) then:bb1 else:bb2
|
||||
bb1:
|
||||
Call mutable a$2.push(frozen props$1.d)
|
||||
Return frozen a$2
|
||||
Call mutable a$2.push(readonly props$1.d)
|
||||
Return freeze a$2
|
||||
bb2:
|
||||
Call mutable a$2.push(frozen props$1.c)
|
||||
Call mutable a$2.push(readonly props$1.c)
|
||||
Goto bb1
|
||||
```
|
||||
|
||||
|
||||
@@ -67,20 +67,20 @@ function mayMutate() {}
|
||||
|
||||
```
|
||||
bb0:
|
||||
Const readonly a$2 = Array []
|
||||
Const readonly b$3 = Array []
|
||||
Const mutable a$2 = Array []
|
||||
Const mutable b$3 = Array []
|
||||
If (readonly b$3) then:bb2 else:bb1
|
||||
bb2:
|
||||
Call mutable a$2.push(frozen props$1.p0)
|
||||
Call mutable a$2.push(readonly props$1.p0)
|
||||
Goto bb1
|
||||
bb1:
|
||||
If (frozen props$1.p1) then:bb4 else:bb3
|
||||
If (readonly props$1.p1) then:bb4 else:bb3
|
||||
bb4:
|
||||
Call mutable b$3.push(frozen props$1.p2)
|
||||
Call mutable b$3.push(readonly props$1.p2)
|
||||
Goto bb3
|
||||
bb3:
|
||||
Const readonly $5 = JSX <frozen Foo$4 a={frozen a$2} b={frozen b$3} ></frozen Foo$4>
|
||||
Return frozen $5
|
||||
Const mutable $5 = JSX <readonly Foo$4 a={freeze a$2} b={freeze b$3} ></readonly Foo$4>
|
||||
Return readonly $5
|
||||
```
|
||||
|
||||
## Code
|
||||
@@ -105,21 +105,21 @@ function Component$0(props$1) {
|
||||
|
||||
```
|
||||
bb0:
|
||||
Const readonly a$2 = Array []
|
||||
Const readonly b$3 = Array []
|
||||
Const readonly $5 = Call mutable mayMutate$4(mutable b$3)
|
||||
Const mutable a$2 = Array []
|
||||
Const mutable b$3 = Array []
|
||||
Const mutable $5 = Call mutable mayMutate$4(mutable b$3)
|
||||
If (readonly $5) then:bb2 else:bb1
|
||||
bb2:
|
||||
Call mutable a$2.push(frozen props$1.p0)
|
||||
Call mutable a$2.push(readonly props$1.p0)
|
||||
Goto bb1
|
||||
bb1:
|
||||
If (frozen props$1.p1) then:bb4 else:bb3
|
||||
If (readonly props$1.p1) then:bb4 else:bb3
|
||||
bb4:
|
||||
Call mutable b$3.push(frozen props$1.p2)
|
||||
Call mutable b$3.push(readonly props$1.p2)
|
||||
Goto bb3
|
||||
bb3:
|
||||
Const readonly $7 = JSX <frozen Foo$6 a={frozen a$2} b={frozen b$3} ></frozen Foo$6>
|
||||
Return frozen $7
|
||||
Const mutable $7 = JSX <readonly Foo$6 a={freeze a$2} b={freeze b$3} ></readonly Foo$6>
|
||||
Return readonly $7
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
@@ -34,15 +34,15 @@ function Foo$0() {
|
||||
|
||||
```
|
||||
bb0:
|
||||
Const readonly a$2 = Array []
|
||||
Const readonly b$3 = Object { }
|
||||
Const mutable a$2 = Array []
|
||||
Const mutable b$3 = Object { }
|
||||
New mutable Foo$4(mutable a$2, mutable b$3)
|
||||
Const readonly $6 = "div"
|
||||
Let readonly _$5 = JSX <frozen $6 a={frozen a$2} ></frozen $6>
|
||||
Const mutable $6 = "div"
|
||||
Let mutable _$5 = JSX <readonly $6 a={freeze a$2} ></readonly $6>
|
||||
New mutable Foo$4(mutable b$3)
|
||||
Const readonly $7 = "div"
|
||||
Const readonly $8 = JSX <frozen $7 a={frozen a$2} b={frozen b$3} ></frozen $7>
|
||||
Return frozen $8
|
||||
Const mutable $7 = "div"
|
||||
Const mutable $8 = JSX <readonly $7 a={readonly a$2} b={freeze b$3} ></readonly $7>
|
||||
Return readonly $8
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function Component() {
|
||||
const a = [];
|
||||
const b = a;
|
||||
useFreeze(a);
|
||||
foo(b); // should be readonly, value is guaranteed frozen via alias
|
||||
}
|
||||
|
||||
function useFreeze() {}
|
||||
function foo(x) {}
|
||||
|
||||
```
|
||||
|
||||
## HIR
|
||||
|
||||
```
|
||||
bb0:
|
||||
Const mutable a$1 = Array []
|
||||
Const mutable b$2 = readonly a$1
|
||||
Call readonly useFreeze$3(freeze a$1)
|
||||
Call mutable foo$4(readonly b$2)
|
||||
Return
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
function Component$0() {
|
||||
const a$1 = [];
|
||||
const b$2 = a$1;
|
||||
useFreeze$3(a$1);
|
||||
foo$4(b$2);
|
||||
return;
|
||||
}
|
||||
|
||||
```
|
||||
## HIR
|
||||
|
||||
```
|
||||
bb0:
|
||||
Return
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
function useFreeze$0() {
|
||||
return;
|
||||
}
|
||||
|
||||
```
|
||||
## HIR
|
||||
|
||||
```
|
||||
bb0:
|
||||
Return
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
function foo$0(x$1) {
|
||||
return;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
function Component() {
|
||||
const a = [];
|
||||
const b = a;
|
||||
useFreeze(a);
|
||||
foo(b); // should be readonly, value is guaranteed frozen via alias
|
||||
}
|
||||
|
||||
function useFreeze() {}
|
||||
function foo(x) {}
|
||||
@@ -53,14 +53,14 @@ function foo$0() {
|
||||
|
||||
```
|
||||
bb0:
|
||||
Const readonly x$2 = Array []
|
||||
Const frozen y$3 = Call frozen useFreeze$4(frozen x$2)
|
||||
Call mutable foo$5(frozen y$3, frozen x$2)
|
||||
Const readonly $6 = "\n "
|
||||
Const readonly $7 = "\n "
|
||||
Const readonly $8 = "\n "
|
||||
Const readonly $9 = JSX <frozen Component$0>{frozen $6}{frozen x$2}{frozen $7}{frozen y$3}{frozen $8}</frozen Component$0>
|
||||
Return frozen $9
|
||||
Const mutable x$2 = Array []
|
||||
Const mutable y$3 = Call readonly useFreeze$4(freeze x$2)
|
||||
Call mutable foo$5(readonly y$3, readonly x$2)
|
||||
Const mutable $6 = "\n "
|
||||
Const mutable $7 = "\n "
|
||||
Const mutable $8 = "\n "
|
||||
Const mutable $9 = JSX <readonly Component$0>{readonly $6}{readonly x$2}{readonly $7}{readonly y$3}{readonly $8}</readonly Component$0>
|
||||
Return readonly $9
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function Component() {
|
||||
const a = [];
|
||||
useFreeze(a); // should freeze
|
||||
useFreeze(a); // should be readonly
|
||||
call(a); // should be readonly
|
||||
return a;
|
||||
}
|
||||
|
||||
function useFreeze(x) {}
|
||||
function call(x) {}
|
||||
|
||||
```
|
||||
|
||||
## HIR
|
||||
|
||||
```
|
||||
bb0:
|
||||
Const mutable a$1 = Array []
|
||||
Call readonly useFreeze$2(freeze a$1)
|
||||
Call readonly useFreeze$2(readonly a$1)
|
||||
Call mutable call$3(readonly a$1)
|
||||
Return readonly a$1
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
function Component$0() {
|
||||
const a$1 = [];
|
||||
useFreeze$2(a$1);
|
||||
useFreeze$2(a$1);
|
||||
call$3(a$1);
|
||||
return a$1;
|
||||
}
|
||||
|
||||
```
|
||||
## HIR
|
||||
|
||||
```
|
||||
bb0:
|
||||
Return
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
function useFreeze$0(x$1) {
|
||||
return;
|
||||
}
|
||||
|
||||
```
|
||||
## HIR
|
||||
|
||||
```
|
||||
bb0:
|
||||
Return
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
function call$0(x$1) {
|
||||
return;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
function Component() {
|
||||
const a = [];
|
||||
useFreeze(a); // should freeze
|
||||
useFreeze(a); // should be readonly
|
||||
call(a); // should be readonly
|
||||
return a;
|
||||
}
|
||||
|
||||
function useFreeze(x) {}
|
||||
function call(x) {}
|
||||
@@ -0,0 +1,97 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
function Component(props) {
|
||||
const cond = props.cond;
|
||||
const x = props.x;
|
||||
let a;
|
||||
if (cond) {
|
||||
a = x;
|
||||
} else {
|
||||
a = [];
|
||||
}
|
||||
useFreeze(a); // should freeze, value *may* be mutable
|
||||
useFreeze(a); // should be readonly
|
||||
call(a); // should be readonly
|
||||
return a;
|
||||
}
|
||||
|
||||
function useFreeze(x) {}
|
||||
function call(x) {}
|
||||
|
||||
```
|
||||
|
||||
## HIR
|
||||
|
||||
```
|
||||
bb0:
|
||||
Const mutable cond$2 = readonly props$1.cond
|
||||
Const mutable x$3 = readonly props$1.x
|
||||
Let mutable a$4 = undefined
|
||||
If (readonly cond$2) then:bb2 else:bb3
|
||||
bb2:
|
||||
Reassign mutable a$4 = readonly x$3
|
||||
Goto bb1
|
||||
bb3:
|
||||
Reassign mutable a$4 = Array []
|
||||
Goto bb1
|
||||
bb1:
|
||||
Call readonly useFreeze$5(freeze a$4)
|
||||
Call readonly useFreeze$5(readonly a$4)
|
||||
Call mutable call$6(readonly a$4)
|
||||
Return readonly a$4
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
function Component$0(props$1) {
|
||||
const cond$2 = props$1.cond;
|
||||
const x$3 = props$1.x;
|
||||
let a$4 = undefined;
|
||||
if (cond$2) {
|
||||
a$4 = x$3;
|
||||
("<<TODO: handle complex control flow in codegen>>");
|
||||
} else {
|
||||
a$4 = [];
|
||||
("<<TODO: handle complex control flow in codegen>>");
|
||||
}
|
||||
useFreeze$5(a$4);
|
||||
useFreeze$5(a$4);
|
||||
call$6(a$4);
|
||||
return a$4;
|
||||
}
|
||||
|
||||
```
|
||||
## HIR
|
||||
|
||||
```
|
||||
bb0:
|
||||
Return
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
function useFreeze$0(x$1) {
|
||||
return;
|
||||
}
|
||||
|
||||
```
|
||||
## HIR
|
||||
|
||||
```
|
||||
bb0:
|
||||
Return
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
function call$0(x$1) {
|
||||
return;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
function Component(props) {
|
||||
const cond = props.cond;
|
||||
const x = props.x;
|
||||
let a;
|
||||
if (cond) {
|
||||
a = x;
|
||||
} else {
|
||||
a = [];
|
||||
}
|
||||
useFreeze(a); // should freeze, value *may* be mutable
|
||||
useFreeze(a); // should be readonly
|
||||
call(a); // should be readonly
|
||||
return a;
|
||||
}
|
||||
|
||||
function useFreeze(x) {}
|
||||
function call(x) {}
|
||||
@@ -97,16 +97,16 @@ function Foo$0() {
|
||||
|
||||
```
|
||||
bb0:
|
||||
Const readonly a$2 = Call mutable compute$3(frozen props$1.a)
|
||||
Const readonly b$4 = Call mutable compute$3(frozen props$1.b)
|
||||
If (frozen props$1.c) then:bb2 else:bb1
|
||||
Const mutable a$2 = Call mutable compute$3(readonly props$1.a)
|
||||
Const mutable b$4 = Call mutable compute$3(readonly props$1.b)
|
||||
If (readonly props$1.c) then:bb2 else:bb1
|
||||
bb2:
|
||||
Call mutable mutate$5(mutable a$2)
|
||||
Call mutable mutate$5(mutable b$4)
|
||||
Goto bb1
|
||||
bb1:
|
||||
Const readonly $7 = JSX <frozen Foo$6 a={frozen a$2} b={frozen b$4} ></frozen Foo$6>
|
||||
Return frozen $7
|
||||
Const mutable $7 = JSX <readonly Foo$6 a={freeze a$2} b={freeze b$4} ></readonly Foo$6>
|
||||
Return readonly $7
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
@@ -28,10 +28,10 @@ function Foo() {}
|
||||
|
||||
```
|
||||
bb0:
|
||||
Const readonly a$2 = Call mutable compute$3(frozen props$1.a)
|
||||
Const readonly b$4 = Call mutable compute$3(frozen props$1.b)
|
||||
Const readonly $6 = JSX <frozen Foo$5 a={frozen a$2} b={frozen b$4} ></frozen Foo$5>
|
||||
Return frozen $6
|
||||
Const mutable a$2 = Call mutable compute$3(readonly props$1.a)
|
||||
Const mutable b$4 = Call mutable compute$3(readonly props$1.b)
|
||||
Const mutable $6 = JSX <readonly Foo$5 a={freeze a$2} b={freeze b$4} ></readonly Foo$5>
|
||||
Return readonly $6
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
@@ -76,15 +76,15 @@ function Foo$0() {
|
||||
|
||||
```
|
||||
bb0:
|
||||
Const readonly a$2 = Call mutable compute$3(frozen props$1.a)
|
||||
Const readonly b$4 = Call mutable compute$3(frozen props$1.b)
|
||||
If (frozen props$1.c) then:bb2 else:bb1
|
||||
Const mutable a$2 = Call mutable compute$3(readonly props$1.a)
|
||||
Const mutable b$4 = Call mutable compute$3(readonly props$1.b)
|
||||
If (readonly props$1.c) then:bb2 else:bb1
|
||||
bb2:
|
||||
Call mutable foo$5(mutable a$2, mutable b$4)
|
||||
Goto bb1
|
||||
bb1:
|
||||
Const readonly $7 = JSX <frozen Foo$6 a={frozen a$2} b={frozen b$4} ></frozen Foo$6>
|
||||
Return frozen $7
|
||||
Const mutable $7 = JSX <readonly Foo$6 a={freeze a$2} b={freeze b$4} ></readonly Foo$6>
|
||||
Return readonly $7
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
@@ -28,11 +28,11 @@ function Foo() {}
|
||||
|
||||
```
|
||||
bb0:
|
||||
Const readonly a$2 = Call mutable compute$3(frozen props$1.a)
|
||||
Const readonly b$4 = Call mutable compute$3(frozen props$1.b)
|
||||
Const mutable a$2 = Call mutable compute$3(readonly props$1.a)
|
||||
Const mutable b$4 = Call mutable compute$3(readonly props$1.b)
|
||||
Call mutable foo$5(mutable a$2, mutable b$4)
|
||||
Const readonly $7 = JSX <frozen Foo$6 a={frozen a$2} b={frozen b$4} ></frozen Foo$6>
|
||||
Return frozen $7
|
||||
Const mutable $7 = JSX <readonly Foo$6 a={freeze a$2} b={freeze b$4} ></readonly Foo$6>
|
||||
Return readonly $7
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
@@ -17,13 +17,13 @@ function Component(props) {
|
||||
|
||||
```
|
||||
bb0:
|
||||
Const readonly x$2 = Object { }
|
||||
Const readonly y$3 = Array []
|
||||
Reassign readonly x$2.y = readonly y$3
|
||||
Const readonly child$4 = JSX <frozen Component$0 data={frozen y$3} ></frozen Component$0>
|
||||
Call mutable x$2.y.push(frozen props$1.p0)
|
||||
Const readonly $5 = JSX <frozen Component$0 data={frozen x$2} >{frozen child$4}</frozen Component$0>
|
||||
Return frozen $5
|
||||
Const mutable x$2 = Object { }
|
||||
Const mutable y$3 = Array []
|
||||
Reassign mutable x$2.y = readonly y$3
|
||||
Const mutable child$4 = JSX <readonly Component$0 data={freeze y$3} ></readonly Component$0>
|
||||
Call mutable x$2.y.push(readonly props$1.p0)
|
||||
Const mutable $5 = JSX <readonly Component$0 data={freeze x$2} >{readonly child$4}</readonly Component$0>
|
||||
Return readonly $5
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
@@ -23,18 +23,18 @@ function Component(props) {
|
||||
|
||||
```
|
||||
bb0:
|
||||
Let readonly x$2 = Array []
|
||||
Call mutable x$2.push(frozen props$1.p0)
|
||||
Let readonly y$3 = readonly x$2
|
||||
If (frozen props$1.p1) then:bb2 else:bb1
|
||||
Let mutable x$2 = Array []
|
||||
Call mutable x$2.push(readonly props$1.p0)
|
||||
Let mutable y$3 = readonly x$2
|
||||
If (readonly props$1.p1) then:bb2 else:bb1
|
||||
bb2:
|
||||
Reassign readonly x$2 = Array []
|
||||
Reassign mutable x$2 = Array []
|
||||
Goto bb1
|
||||
bb1:
|
||||
Let readonly _$4 = JSX <frozen Component$0 x={frozen x$2} ></frozen Component$0>
|
||||
Call mutable y$3.push(frozen props$1.p2)
|
||||
Const readonly $5 = JSX <frozen Component$0 x={frozen x$2} y={frozen y$3} ></frozen Component$0>
|
||||
Return frozen $5
|
||||
Let mutable _$4 = JSX <readonly Component$0 x={freeze x$2} ></readonly Component$0>
|
||||
Call readonly y$3.push(readonly props$1.p2)
|
||||
Const mutable $5 = JSX <readonly Component$0 x={readonly x$2} y={readonly y$3} ></readonly Component$0>
|
||||
Return readonly $5
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
@@ -21,14 +21,14 @@ function Component(props) {
|
||||
|
||||
```
|
||||
bb0:
|
||||
Let readonly x$2 = Array []
|
||||
Call mutable x$2.push(frozen props$1.p0)
|
||||
Let readonly y$3 = readonly x$2
|
||||
Reassign readonly x$2 = Array []
|
||||
Let readonly _$4 = JSX <frozen Component$0 x={frozen x$2} ></frozen Component$0>
|
||||
Call mutable y$3.push(frozen props$1.p1)
|
||||
Const readonly $5 = JSX <frozen Component$0 x={frozen x$2} y={frozen y$3} ></frozen Component$0>
|
||||
Return frozen $5
|
||||
Let mutable x$2 = Array []
|
||||
Call mutable x$2.push(readonly props$1.p0)
|
||||
Let mutable y$3 = readonly x$2
|
||||
Reassign mutable x$2 = Array []
|
||||
Let mutable _$4 = JSX <readonly Component$0 x={freeze x$2} ></readonly Component$0>
|
||||
Call mutable y$3.push(readonly props$1.p1)
|
||||
Const mutable $5 = JSX <readonly Component$0 x={readonly x$2} y={freeze y$3} ></readonly Component$0>
|
||||
Return readonly $5
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
@@ -15,16 +15,16 @@ function foo(x, y) {
|
||||
|
||||
```
|
||||
bb0:
|
||||
If (frozen x$1) then:bb2 else:bb1
|
||||
If (readonly x$1) then:bb2 else:bb1
|
||||
bb2:
|
||||
Const readonly $3 = false
|
||||
Const readonly $4 = Call mutable foo$0(mutable $3, frozen y$2)
|
||||
Return frozen $4
|
||||
Const mutable $3 = false
|
||||
Const mutable $4 = Call readonly foo$0(readonly $3, readonly y$2)
|
||||
Return freeze $4
|
||||
bb1:
|
||||
Const readonly $5 = 10
|
||||
Const frozen $6 = Binary frozen y$2 * readonly $5
|
||||
Const readonly $7 = Array [frozen $6]
|
||||
Return frozen $7
|
||||
Const mutable $5 = 10
|
||||
Const mutable $6 = Binary readonly y$2 * readonly $5
|
||||
Const mutable $7 = Array [readonly $6]
|
||||
Return freeze $7
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
@@ -32,27 +32,27 @@ function Component(props) {
|
||||
|
||||
```
|
||||
bb0:
|
||||
Let readonly x$2 = Array []
|
||||
Let readonly y$3 = undefined
|
||||
Const readonly $4 = false
|
||||
Const readonly $5 = true
|
||||
Const readonly $6 = 1
|
||||
Switch (frozen props$1.p0)
|
||||
Let mutable x$2 = Array []
|
||||
Let mutable y$3 = undefined
|
||||
Const mutable $4 = false
|
||||
Const mutable $5 = true
|
||||
Const mutable $6 = 1
|
||||
Switch (<unknown> props$1.p0)
|
||||
Case readonly $6: bb1
|
||||
Case readonly $5: bb6
|
||||
Default: bb1
|
||||
Case readonly $4: bb2
|
||||
bb1:
|
||||
Const readonly child$7 = JSX <frozen Component$0 data={frozen x$2} ></frozen Component$0>
|
||||
Call mutable y$3.push(frozen props$1.p4)
|
||||
Const readonly $8 = JSX <frozen Component$0 data={frozen y$3} >{frozen child$7}</frozen Component$0>
|
||||
Return frozen $8
|
||||
Const mutable child$7 = JSX <readonly Component$0 data={freeze x$2} ></readonly Component$0>
|
||||
Call readonly y$3.push(readonly props$1.p4)
|
||||
Const mutable $8 = JSX <readonly Component$0 data={freeze y$3} >{readonly child$7}</readonly Component$0>
|
||||
Return readonly $8
|
||||
bb6:
|
||||
Call mutable x$2.push(frozen props$1.p2)
|
||||
Reassign readonly y$3 = Array []
|
||||
Call mutable x$2.push(readonly props$1.p2)
|
||||
Reassign mutable y$3 = Array []
|
||||
Goto bb1
|
||||
bb2:
|
||||
Reassign readonly y$3 = readonly x$2
|
||||
Reassign mutable y$3 = readonly x$2
|
||||
Goto bb1
|
||||
```
|
||||
|
||||
|
||||
@@ -28,27 +28,27 @@ function Component(props) {
|
||||
|
||||
```
|
||||
bb0:
|
||||
Let readonly x$2 = Array []
|
||||
Let readonly y$3 = undefined
|
||||
Const readonly $4 = false
|
||||
Const readonly $5 = true
|
||||
Switch (frozen props$1.p0)
|
||||
Let mutable x$2 = Array []
|
||||
Let mutable y$3 = undefined
|
||||
Const mutable $4 = false
|
||||
Const mutable $5 = true
|
||||
Switch (<unknown> props$1.p0)
|
||||
Case readonly $5: bb4
|
||||
Case readonly $4: bb2
|
||||
Default: bb1
|
||||
bb4:
|
||||
Call mutable x$2.push(frozen props$1.p2)
|
||||
Call mutable x$2.push(frozen props$1.p3)
|
||||
Reassign readonly y$3 = Array []
|
||||
Call mutable x$2.push(readonly props$1.p2)
|
||||
Call mutable x$2.push(readonly props$1.p3)
|
||||
Reassign mutable y$3 = Array []
|
||||
Goto bb2
|
||||
bb2:
|
||||
Reassign readonly y$3 = readonly x$2
|
||||
Reassign mutable y$3 = readonly x$2
|
||||
Goto bb1
|
||||
bb1:
|
||||
Const readonly child$6 = JSX <frozen Component$0 data={frozen x$2} ></frozen Component$0>
|
||||
Call mutable y$3.push(frozen props$1.p4)
|
||||
Const readonly $7 = JSX <frozen Component$0 data={frozen y$3} >{frozen child$6}</frozen Component$0>
|
||||
Return frozen $7
|
||||
Const mutable child$6 = JSX <readonly Component$0 data={freeze x$2} ></readonly Component$0>
|
||||
Call readonly y$3.push(readonly props$1.p4)
|
||||
Const mutable $7 = JSX <readonly Component$0 data={readonly y$3} >{readonly child$6}</readonly Component$0>
|
||||
Return readonly $7
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
@@ -10,15 +10,14 @@
|
||||
import generate from "@babel/generator";
|
||||
import * as parser from "@babel/parser";
|
||||
import traverse from "@babel/traverse";
|
||||
import { graphviz, wasmFolder } from "@hpcc-js/wasm";
|
||||
import { existsSync, unlinkSync, writeFileSync } from "fs";
|
||||
import { wasmFolder } from "@hpcc-js/wasm";
|
||||
import invariant from "invariant";
|
||||
import path from "path";
|
||||
import prettier from "prettier";
|
||||
import buildDefUseGraph, { printGraph } from "../HIR/BuildDefUseGraph";
|
||||
import { lower } from "../HIR/BuildHIR";
|
||||
import codegen from "../HIR/Codegen";
|
||||
import { HIRFunction } from "../HIR/HIR";
|
||||
import inferReferenceCapability from "../HIR/InferReferenceCapability";
|
||||
import printHIR from "../HIR/PrintHIR";
|
||||
import generateTestsFromFixtures from "./test-utils/generateTestsFromFixtures";
|
||||
|
||||
@@ -45,22 +44,23 @@ describe("React Forget (HIR version)", () => {
|
||||
FunctionDeclaration: {
|
||||
enter(nodePath) {
|
||||
const ir: HIRFunction = lower(nodePath);
|
||||
const lifetimeGraph = buildDefUseGraph(ir);
|
||||
inferReferenceCapability(ir);
|
||||
// const lifetimeGraph = buildDefUseGraph(ir);
|
||||
const textHIR = printHIR(ir.body);
|
||||
const textLifetimeGraph = printGraph(lifetimeGraph);
|
||||
const graphvizFile = path.join(
|
||||
__dirname,
|
||||
"fixtures",
|
||||
"hir-svg",
|
||||
file + ".svg"
|
||||
);
|
||||
if (input.indexOf("@Out DefUseGraph") !== -1) {
|
||||
graphviz.layout(textLifetimeGraph, "svg", "dot").then((svg) => {
|
||||
writeFileSync(graphvizFile, svg);
|
||||
});
|
||||
} else if (existsSync(graphvizFile)) {
|
||||
unlinkSync(graphvizFile);
|
||||
}
|
||||
// const textLifetimeGraph = printGraph(lifetimeGraph);
|
||||
// const graphvizFile = path.join(
|
||||
// __dirname,
|
||||
// "fixtures",
|
||||
// "hir-svg",
|
||||
// file + ".svg"
|
||||
// );
|
||||
// if (input.indexOf("@Out DefUseGraph") !== -1) {
|
||||
// graphviz.layout(textLifetimeGraph, "svg", "dot").then((svg) => {
|
||||
// writeFileSync(graphvizFile, svg);
|
||||
// });
|
||||
// } else if (existsSync(graphvizFile)) {
|
||||
// unlinkSync(graphvizFile);
|
||||
// }
|
||||
|
||||
const ast = codegen(ir);
|
||||
const text = prettier.format(
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
json5 "^2.2.1"
|
||||
semver "^6.3.0"
|
||||
|
||||
"@babel/generator@7.2.0", "@babel/generator@^7.1.6", "@babel/generator@^7.19.3", "@babel/generator@^7.2.0", "@babel/generator@^7.7.2":
|
||||
"@babel/generator@7.2.0", "@babel/generator@^7.1.6", "@babel/generator@^7.19.4", "@babel/generator@^7.2.0", "@babel/generator@^7.7.2":
|
||||
version "7.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.2.0.tgz#eaf3821fa0301d9d4aef88e63d4bcc19b73ba16c"
|
||||
integrity sha512-BA75MVfRlFQG2EZgFYIwyT1r6xSkwfP2bdkY/kLZusEYWiJs4xCowab/alaEaT0wSvmVuXGqiefeBlP+7V1yKg==
|
||||
@@ -75,11 +75,11 @@
|
||||
trim-right "^1.0.1"
|
||||
|
||||
"@babel/generator@^7.19.0":
|
||||
version "7.19.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.19.3.tgz#d7f4d1300485b4547cb6f94b27d10d237b42bf59"
|
||||
integrity sha512-fqVZnmp1ncvZU757UzDheKZpfPgatqY59XtW2/j/18H7u76akb8xqvjw82f+i2UKd/ksYsSick/BCLQUUtJ/qQ==
|
||||
version "7.19.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.19.5.tgz#da3f4b301c8086717eee9cab14da91b1fa5dcca7"
|
||||
integrity sha512-DxbNz9Lz4aMZ99qPpO1raTbcrI1ZeYh+9NR9qhfkQIbFtVEqotHojEBxHzmxhVONkGt6VyrqVQcgpefMy9pqcg==
|
||||
dependencies:
|
||||
"@babel/types" "^7.19.3"
|
||||
"@babel/types" "^7.19.4"
|
||||
"@jridgewell/gen-mapping" "^0.3.2"
|
||||
jsesc "^2.5.1"
|
||||
|
||||
@@ -203,6 +203,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz#181f22d28ebe1b3857fa575f5c290b1aaf659b56"
|
||||
integrity sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==
|
||||
|
||||
"@babel/helper-string-parser@^7.19.4":
|
||||
version "7.19.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz#38d3acb654b4701a9b77fb0615a96f775c3a9e63"
|
||||
integrity sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==
|
||||
|
||||
"@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1":
|
||||
version "7.19.1"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2"
|
||||
@@ -241,11 +246,16 @@
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.19.1.tgz#6f6d6c2e621aad19a92544cc217ed13f1aac5b4c"
|
||||
integrity sha512-h7RCSorm1DdTVGJf3P2Mhj3kdnkmF/EiysUkzS2TdgAYqyjFdMQJbVuXOBej2SBJaXan/lIVtT6KkGbyyq753A==
|
||||
|
||||
"@babel/parser@^7.18.6", "@babel/parser@^7.19.3":
|
||||
"@babel/parser@^7.18.6":
|
||||
version "7.19.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.19.3.tgz#8dd36d17c53ff347f9e55c328710321b49479a9a"
|
||||
integrity sha512-pJ9xOlNWHiy9+FuFP09DEAFbAn4JskgRsVcc169w2xRBC3FRGuQEwjeIMMND9L2zc0iEhO/tGv4Zq+km+hxNpQ==
|
||||
|
||||
"@babel/parser@^7.19.4":
|
||||
version "7.19.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.19.4.tgz#03c4339d2b8971eb3beca5252bafd9b9f79db3dc"
|
||||
integrity sha512-qpVT7gtuOLjWeDTKLkJ6sryqLliBaFpAtGeqw5cs5giLldvh+Ch0plqnUMKoVAUS6ZEueQQiZV+p5pxtPitEsA==
|
||||
|
||||
"@babel/plugin-syntax-async-generators@^7.8.4":
|
||||
version "7.8.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d"
|
||||
@@ -465,18 +475,18 @@
|
||||
lodash "^4.17.10"
|
||||
|
||||
"@babel/traverse@^7.19.1":
|
||||
version "7.19.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.19.3.tgz#3a3c5348d4988ba60884e8494b0592b2f15a04b4"
|
||||
integrity sha512-qh5yf6149zhq2sgIXmwjnsvmnNQC2iw70UFjp4olxucKrWd/dvlUsBI88VSLUsnMNF7/vnOiA+nk1+yLoCqROQ==
|
||||
version "7.19.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.19.4.tgz#f117820e18b1e59448a6c1fa9d0ff08f7ac459a8"
|
||||
integrity sha512-w3K1i+V5u2aJUOXBFFC5pveFLmtq1s3qcdDNC2qRI6WPBQIDaKFqXxDEqDO/h1dQ3HjsZoZMyIy6jGLq0xtw+g==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.18.6"
|
||||
"@babel/generator" "^7.19.3"
|
||||
"@babel/generator" "^7.19.4"
|
||||
"@babel/helper-environment-visitor" "^7.18.9"
|
||||
"@babel/helper-function-name" "^7.19.0"
|
||||
"@babel/helper-hoist-variables" "^7.18.6"
|
||||
"@babel/helper-split-export-declaration" "^7.18.6"
|
||||
"@babel/parser" "^7.19.3"
|
||||
"@babel/types" "^7.19.3"
|
||||
"@babel/parser" "^7.19.4"
|
||||
"@babel/types" "^7.19.4"
|
||||
debug "^4.1.0"
|
||||
globals "^11.1.0"
|
||||
|
||||
@@ -506,12 +516,12 @@
|
||||
"@babel/helper-validator-identifier" "^7.18.6"
|
||||
to-fast-properties "^2.0.0"
|
||||
|
||||
"@babel/types@^7.19.3":
|
||||
version "7.19.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.19.3.tgz#fc420e6bbe54880bce6779ffaf315f5e43ec9624"
|
||||
integrity sha512-hGCaQzIY22DJlDh9CH7NOxgKkFjBk0Cw9xDO1Xmh2151ti7wiGfQ3LauXzL4HP1fmFlTX6XjpRETTpUcv7wQLw==
|
||||
"@babel/types@^7.19.4":
|
||||
version "7.19.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.19.4.tgz#0dd5c91c573a202d600490a35b33246fed8a41c7"
|
||||
integrity sha512-M5LK7nAeS6+9j7hAq+b3fQs+pNfUtTGq+yFFfHnauFA8zQtLRfmuipmsKDKKLuyG+wC8ABW43A153YNawNTEtw==
|
||||
dependencies:
|
||||
"@babel/helper-string-parser" "^7.18.10"
|
||||
"@babel/helper-string-parser" "^7.19.4"
|
||||
"@babel/helper-validator-identifier" "^7.19.1"
|
||||
to-fast-properties "^2.0.0"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user