From faa8eef0a89666dad5fb489162d1fe0a1b5836aa Mon Sep 17 00:00:00 2001 From: Lauren Tan Date: Fri, 10 Mar 2023 16:21:01 -0500 Subject: [PATCH] [be] Fix remaining lints and enable lint in CI --- compiler/.github/workflows/ci.yml | 2 ++ compiler/forget/.eslintrc.js | 1 + compiler/forget/src/CompilerError.ts | 2 +- .../forget/src/Inference/AnalyseFunctions.ts | 12 +++++++---- .../forget/src/Inference/DropMemoCalls.ts | 2 +- compiler/forget/src/Inference/InferAlias.ts | 5 ++++- .../forget/src/Inference/InferAliasForPhis.ts | 2 +- .../src/Inference/InferAliasForStores.ts | 2 +- .../src/Inference/InferMutableLifetimes.ts | 6 +++--- .../src/Inference/InferMutableRanges.ts | 2 +- .../Inference/InferMutableRangesForAlias.ts | 4 ++-- .../src/Inference/InferReferenceEffects.ts | 21 +++++++++---------- .../src/Optimization/ConstantPropagation.ts | 2 +- .../src/Optimization/DeadCodeElimination.ts | 3 +-- .../ReactiveScopes/CodegenReactiveFunction.ts | 3 --- .../DeriveMinimalDependencies.ts | 18 ++++++++-------- .../InferReactiveIdentifiers.ts | 2 +- .../PropagateScopeDependencies.ts | 4 ++-- .../forget/src/SSA/EliminateRedundantPhi.ts | 7 +++++-- .../forget/src/TypeInference/InferTypes.ts | 9 ++++---- compiler/forget/src/Utils/DisjointSet.ts | 1 - 21 files changed, 58 insertions(+), 52 deletions(-) diff --git a/compiler/.github/workflows/ci.yml b/compiler/.github/workflows/ci.yml index 85e7592960..3f154bf6c5 100644 --- a/compiler/.github/workflows/ci.yml +++ b/compiler/.github/workflows/ci.yml @@ -21,5 +21,7 @@ jobs: working-directory: forget - run: yarn build working-directory: forget + - run: yarn lint + working-directory: forget - run: yarn test working-directory: forget diff --git a/compiler/forget/.eslintrc.js b/compiler/forget/.eslintrc.js index 45040277cb..f00a91e235 100644 --- a/compiler/forget/.eslintrc.js +++ b/compiler/forget/.eslintrc.js @@ -56,6 +56,7 @@ module.exports = { "constructor", ], "@typescript-eslint/array-type": ["off", "generic"], + "@typescript-eslint/triple-slash-reference": "off", }, parser: "@typescript-eslint/parser", plugins: ["@typescript-eslint"], diff --git a/compiler/forget/src/CompilerError.ts b/compiler/forget/src/CompilerError.ts index 2695c0d7e1..af3343fc45 100644 --- a/compiler/forget/src/CompilerError.ts +++ b/compiler/forget/src/CompilerError.ts @@ -125,7 +125,7 @@ export class CompilerError extends Error { override set message(_message: string) {} - override toString() { + override toString(): string { return this.details.map((detail) => detail.toString()).join("\n\n"); } diff --git a/compiler/forget/src/Inference/AnalyseFunctions.ts b/compiler/forget/src/Inference/AnalyseFunctions.ts index 2a59edaf1a..42e9bd9f87 100644 --- a/compiler/forget/src/Inference/AnalyseFunctions.ts +++ b/compiler/forget/src/Inference/AnalyseFunctions.ts @@ -43,7 +43,7 @@ class State { } } -export default function analyseFunctions(func: HIRFunction) { +export default function analyseFunctions(func: HIRFunction): void { const state = new State(); for (const [_, block] of func.body.blocks) { @@ -73,7 +73,7 @@ export default function analyseFunctions(func: HIRFunction) { } } -function lower(func: HIRFunction) { +function lower(func: HIRFunction): void { mergeConsecutiveBlocks(func); enterSSA(func); eliminateRedundantPhi(func); @@ -85,7 +85,11 @@ function lower(func: HIRFunction) { logHIRFunction("AnalyseFunction (inner)", func); } -function infer(value: FunctionExpression, state: State, context: Place[]) { +function infer( + value: FunctionExpression, + state: State, + context: Place[] +): void { const mutations = new Set( value.loweredFunc.context .filter((dep) => isMutatedOrReassigned(dep.identifier)) @@ -127,7 +131,7 @@ function infer(value: FunctionExpression, state: State, context: Place[]) { } } -function isMutatedOrReassigned(id: Identifier) { +function isMutatedOrReassigned(id: Identifier): boolean { // This check checks for mutation and reassingnment, so the usual check for // mutation (ie, `mutableRange.end - mutableRange.start > 1`) isn't quite // enough. diff --git a/compiler/forget/src/Inference/DropMemoCalls.ts b/compiler/forget/src/Inference/DropMemoCalls.ts index 8c9353b768..e2d25407b2 100644 --- a/compiler/forget/src/Inference/DropMemoCalls.ts +++ b/compiler/forget/src/Inference/DropMemoCalls.ts @@ -1,6 +1,6 @@ import { Effect, HIRFunction, HookType, isHookType } from "../HIR"; -export default function (func: HIRFunction) { +export default function (func: HIRFunction): void { for (const [_, block] of func.body.blocks) { for (const instr of block.instructions) { switch (instr.value.kind) { diff --git a/compiler/forget/src/Inference/InferAlias.ts b/compiler/forget/src/Inference/InferAlias.ts index b2d127a7e3..7f37c0efab 100644 --- a/compiler/forget/src/Inference/InferAlias.ts +++ b/compiler/forget/src/Inference/InferAlias.ts @@ -20,7 +20,10 @@ export function inferAliases(func: HIRFunction): DisjointSet { return aliases; } -function inferInstr(instr: Instruction, aliases: DisjointSet) { +function inferInstr( + instr: Instruction, + aliases: DisjointSet +): void { const { lvalue, value: instrValue } = instr; let alias: Place | null = null; switch (instrValue.kind) { diff --git a/compiler/forget/src/Inference/InferAliasForPhis.ts b/compiler/forget/src/Inference/InferAliasForPhis.ts index 0059cd3003..cd57bdef58 100644 --- a/compiler/forget/src/Inference/InferAliasForPhis.ts +++ b/compiler/forget/src/Inference/InferAliasForPhis.ts @@ -10,7 +10,7 @@ import DisjointSet from "../Utils/DisjointSet"; export function inferAliasForPhis( func: HIRFunction, aliases: DisjointSet -) { +): void { for (const [_, block] of func.body.blocks) { for (const phi of block.phis) { const isPhiMutatedAfterCreation: boolean = diff --git a/compiler/forget/src/Inference/InferAliasForStores.ts b/compiler/forget/src/Inference/InferAliasForStores.ts index 1a3191ac15..ba787cbf2e 100644 --- a/compiler/forget/src/Inference/InferAliasForStores.ts +++ b/compiler/forget/src/Inference/InferAliasForStores.ts @@ -20,7 +20,7 @@ import DisjointSet from "../Utils/DisjointSet"; export function inferAliasForStores( func: HIRFunction, aliases: DisjointSet -) { +): void { for (const [_, block] of func.body.blocks) { for (const instr of block.instructions) { const { value, lvalue } = instr; diff --git a/compiler/forget/src/Inference/InferMutableLifetimes.ts b/compiler/forget/src/Inference/InferMutableLifetimes.ts index 8f222815ea..f2b2ebd74a 100644 --- a/compiler/forget/src/Inference/InferMutableLifetimes.ts +++ b/compiler/forget/src/Inference/InferMutableLifetimes.ts @@ -60,7 +60,7 @@ import { assertExhaustive } from "../Utils/utils"; * ``` */ -function infer(place: Place, instr: Instruction) { +function infer(place: Place, instr: Instruction): void { place.identifier.mutableRange.end = makeInstructionId(instr.id + 1); } @@ -68,7 +68,7 @@ function inferPlace( place: Place, instr: Instruction, inferMutableRangeForStores: boolean -) { +): void { switch (place.effect) { case Effect.Unknown: { throw new Error( @@ -98,7 +98,7 @@ function inferPlace( export function inferMutableLifetimes( func: HIRFunction, inferMutableRangeForStores: boolean -) { +): void { for (const [_, block] of func.body.blocks) { for (const phi of block.phis) { let start = Number.MAX_SAFE_INTEGER; diff --git a/compiler/forget/src/Inference/InferMutableRanges.ts b/compiler/forget/src/Inference/InferMutableRanges.ts index c5c168371f..cf6f0fa345 100644 --- a/compiler/forget/src/Inference/InferMutableRanges.ts +++ b/compiler/forget/src/Inference/InferMutableRanges.ts @@ -12,7 +12,7 @@ import { inferAliasForStores } from "./InferAliasForStores"; import { inferMutableLifetimes } from "./InferMutableLifetimes"; import { inferMutableRangesForAlias } from "./InferMutableRangesForAlias"; -export function inferMutableRanges(ir: HIRFunction) { +export function inferMutableRanges(ir: HIRFunction): void { // Infer mutable ranges for non fields inferMutableLifetimes(ir, false); diff --git a/compiler/forget/src/Inference/InferMutableRangesForAlias.ts b/compiler/forget/src/Inference/InferMutableRangesForAlias.ts index 4de85bec4b..c38e93bc3b 100644 --- a/compiler/forget/src/Inference/InferMutableRangesForAlias.ts +++ b/compiler/forget/src/Inference/InferMutableRangesForAlias.ts @@ -2,9 +2,9 @@ import { HIRFunction, Identifier, InstructionId } from "../HIR/HIR"; import DisjointSet from "../Utils/DisjointSet"; export function inferMutableRangesForAlias( - fn: HIRFunction, + _fn: HIRFunction, aliases: DisjointSet -) { +): void { const aliasSets = aliases.buildSets(); for (const aliasSet of aliasSets) { // Update mutableRange.end only if the identifiers have actually been diff --git a/compiler/forget/src/Inference/InferReferenceEffects.ts b/compiler/forget/src/Inference/InferReferenceEffects.ts index ef71ee4999..178ab940d4 100644 --- a/compiler/forget/src/Inference/InferReferenceEffects.ts +++ b/compiler/forget/src/Inference/InferReferenceEffects.ts @@ -76,7 +76,7 @@ import { assertExhaustive } from "../Utils/utils"; * 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 inferReferenceEffects(fn: HIRFunction) { +export default function inferReferenceEffects(fn: HIRFunction): void { // Initial state contains function params // TODO: include module declarations here as well const initialState = InferenceState.empty(); @@ -124,7 +124,7 @@ export default function inferReferenceEffects(fn: HIRFunction) { // so track the list of incoming state for each successor block. // These are merged when reaching that block again. const queuedStates: Map = new Map(); - function queue(blockId: BlockId, state: InferenceState) { + function queue(blockId: BlockId, state: InferenceState): void { let queuedState = queuedStates.get(blockId); if (queuedState != null) { // merge the queued states for this block @@ -187,7 +187,7 @@ class InferenceState { /** * (Re)initializes a @param value with its default @param kind. */ - initialize(value: InstructionValue, kind: ValueKind) { + initialize(value: InstructionValue, kind: ValueKind): void { invariant( value.kind !== "LoadLocal", "Expected all top-level identifiers to be defined as variables, not values" @@ -225,7 +225,7 @@ class InferenceState { /** * Updates the value at @param place to point to the same value as @param value. */ - alias(place: Place, value: Place) { + alias(place: Place, value: Place): void { const values = this.#variables.get(value.identifier.id); invariant( values != null, @@ -238,7 +238,7 @@ class InferenceState { /** * Defines (initializing or updating) a variable with a specific kind of value. */ - define(place: Place, value: InstructionValue) { + define(place: Place, value: InstructionValue): void { invariant( this.#values.has(value), `Expected value to be initialized at '${printSourceLocation(value.loc)}'` @@ -262,7 +262,7 @@ class InferenceState { * Similarly, a freeze reference is converted to readonly if the * value is already frozen or is immutable. */ - reference(place: Place, effectKind: Effect) { + reference(place: Place, effectKind: Effect): void { const values = this.#variables.get(place.identifier.id); if (values === undefined) { place.effect = effectKind === Effect.Mutate ? Effect.Mutate : Effect.Read; @@ -442,7 +442,7 @@ class InferenceState { return result; } - inferPhi(phi: Phi) { + inferPhi(phi: Phi): void { const values: Set = new Set(); for (const [_, operand] of phi.operands) { const operandValues = this.#variables.get(operand.id); @@ -554,11 +554,10 @@ function mergeValues(a: ValueKind, b: ValueKind): ValueKind { * recording references on the @param state according to JS semantics. */ function inferBlock( - env: Environment, - + _env: Environment, state: InferenceState, block: BasicBlock -) { +): void { for (const phi of block.phis) { state.inferPhi(phi); } @@ -876,7 +875,7 @@ function inferBlock( function hasContextRefOperand( state: InferenceState, instrValue: InstructionValue -) { +): boolean { for (const place of eachInstructionValueOperand(instrValue)) { if (state.isDefined(place) && state.kind(place) === ValueKind.Context) { return true; diff --git a/compiler/forget/src/Optimization/ConstantPropagation.ts b/compiler/forget/src/Optimization/ConstantPropagation.ts index 66dffffa37..ac124fc2ad 100644 --- a/compiler/forget/src/Optimization/ConstantPropagation.ts +++ b/compiler/forget/src/Optimization/ConstantPropagation.ts @@ -119,7 +119,7 @@ function applyConstantPropagation(fn: HIRFunction): boolean { const testValue = read(constants, terminal.test); if (testValue !== null) { hasChanges = true; - const targetBlockId = Boolean(testValue.value) + const targetBlockId = testValue.value ? terminal.consequent : terminal.alternate; block.terminal = { diff --git a/compiler/forget/src/Optimization/DeadCodeElimination.ts b/compiler/forget/src/Optimization/DeadCodeElimination.ts index eefbe504bc..7c1e97d200 100644 --- a/compiler/forget/src/Optimization/DeadCodeElimination.ts +++ b/compiler/forget/src/Optimization/DeadCodeElimination.ts @@ -60,7 +60,7 @@ export function deadCodeElimination(fn: HIRFunction): void { } for (const phi of block.phis) { if (used.has(phi.id)) { - for (const [pred, operand] of phi.operands) { + for (const [_pred, operand] of phi.operands) { used.add(operand); } } @@ -196,7 +196,6 @@ function pruneableValue( case "ArrayExpression": case "BinaryExpression": case "ComputedLoad": - case "ComputedStore": case "FunctionExpression": case "LoadLocal": case "JsxExpression": diff --git a/compiler/forget/src/ReactiveScopes/CodegenReactiveFunction.ts b/compiler/forget/src/ReactiveScopes/CodegenReactiveFunction.ts index c4cde0a172..b1464ffe55 100644 --- a/compiler/forget/src/ReactiveScopes/CodegenReactiveFunction.ts +++ b/compiler/forget/src/ReactiveScopes/CodegenReactiveFunction.ts @@ -498,9 +498,6 @@ function codegenInstruction( cx.temp.set(instr.lvalue.identifier.id, value); return t.emptyStatement(); } else { - const kind = cx.hasDeclared(instr.lvalue.identifier) - ? InstructionKind.Reassign - : InstructionKind.Const; if (cx.hasDeclared(instr.lvalue.identifier)) { return createExpressionStatement( instr.loc, diff --git a/compiler/forget/src/ReactiveScopes/DeriveMinimalDependencies.ts b/compiler/forget/src/ReactiveScopes/DeriveMinimalDependencies.ts index d62ef4e168..fda29326a5 100644 --- a/compiler/forget/src/ReactiveScopes/DeriveMinimalDependencies.ts +++ b/compiler/forget/src/ReactiveScopes/DeriveMinimalDependencies.ts @@ -1,5 +1,5 @@ import invariant from "invariant"; -import { Identifier, IdentifierId, ReactiveScopeDependency } from "../HIR"; +import { Identifier, ReactiveScopeDependency } from "../HIR"; import { printIdentifier } from "../HIR/PrintHIR"; import { assertExhaustive } from "../Utils/utils"; @@ -46,7 +46,7 @@ export class ReactiveScopeDependencyTree { return rootNode; } - add(dep: ReactiveScopeDependencyInfo) { + add(dep: ReactiveScopeDependencyInfo): void { const path = dep.path ?? []; let currNode = this.#getOrCreateRoot(dep.identifier); @@ -102,7 +102,7 @@ export class ReactiveScopeDependencyTree { depsFromInnerScope: ReactiveScopeDependencyTree, innerScopeInConditionalWithinParent: boolean, checkValidDepIdFn: (id: Identifier) => boolean - ) { + ): void { for (const [id, otherRoot] of depsFromInnerScope.#roots) { if (!checkValidDepIdFn(id)) { continue; @@ -119,7 +119,7 @@ export class ReactiveScopeDependencyTree { promoteDepsFromExhaustiveConditionals( trees: Array - ) { + ): void { invariant( trees.length > 1, "Expected trees to be at least 2 elements long." @@ -180,13 +180,13 @@ enum PropertyAccessType { UnconditionalDependency = "UnconditionalDependency", } -function isUnconditional(access: PropertyAccessType) { +function isUnconditional(access: PropertyAccessType): boolean { return ( access === PropertyAccessType.UnconditionalAccess || access === PropertyAccessType.UnconditionalDependency ); } -function isDependency(access: PropertyAccessType) { +function isDependency(access: PropertyAccessType): boolean { return ( access === PropertyAccessType.ConditionalDependency || access === PropertyAccessType.UnconditionalDependency @@ -318,7 +318,7 @@ function deriveMinimalDependenciesInSubtree( * conditional equivalent, mutating subtree in place. * @param subtree unconditional node representing a subtree of dependencies */ -function demoteSubtreeToConditional(subtree: DependencyNode) { +function demoteSubtreeToConditional(subtree: DependencyNode): void { const stack: Array = [subtree]; let node; @@ -355,7 +355,7 @@ function addSubtree( currNode: DependencyNode, otherNode: DependencyNode, demoteOtherNode: boolean -) { +): void { let otherType = otherNode.accessType; if (demoteOtherNode) { otherType = isDependency(otherType) @@ -405,7 +405,7 @@ function addSubtree( function addSubtreeIntersection( otherProperties: Array>, currProperties: Map -) { +): void { invariant( otherProperties.length > 1, "[DeriveMinimalDependencies] Expected otherProperties to be at least 2 elements long." diff --git a/compiler/forget/src/ReactiveScopes/InferReactiveIdentifiers.ts b/compiler/forget/src/ReactiveScopes/InferReactiveIdentifiers.ts index 3f1e020e9e..9cf3621d46 100644 --- a/compiler/forget/src/ReactiveScopes/InferReactiveIdentifiers.ts +++ b/compiler/forget/src/ReactiveScopes/InferReactiveIdentifiers.ts @@ -29,7 +29,7 @@ class State { } class Visitor extends ReactiveFunctionVisitor { - override visitInstruction(instr: ReactiveInstruction, state: State) { + override visitInstruction(instr: ReactiveInstruction, state: State): void { this.traverseInstruction(instr, state); const lval = instr.lvalue; if (lval == null) { diff --git a/compiler/forget/src/ReactiveScopes/PropagateScopeDependencies.ts b/compiler/forget/src/ReactiveScopes/PropagateScopeDependencies.ts index 0a2d34cc51..a97f87fe47 100644 --- a/compiler/forget/src/ReactiveScopes/PropagateScopeDependencies.ts +++ b/compiler/forget/src/ReactiveScopes/PropagateScopeDependencies.ts @@ -158,7 +158,7 @@ class Context { */ promoteDepsFromExhaustiveConditionals( depsInConditionals: Array - ) { + ): void { this.#dependencies.promoteDepsFromExhaustiveConditionals( depsInConditionals ); @@ -205,7 +205,7 @@ class Context { } // Checks if identifier is a valid dependency in the current scope - #checkValidDependencyId(identifier: Identifier) { + #checkValidDependencyId(identifier: Identifier): boolean { // If this operand is used in a scope, has a dynamic value, and was defined // before this scope, then its a dependency of the scope. const currentDeclaration = diff --git a/compiler/forget/src/SSA/EliminateRedundantPhi.ts b/compiler/forget/src/SSA/EliminateRedundantPhi.ts index 48b3964b5f..b9e4c036fc 100644 --- a/compiler/forget/src/SSA/EliminateRedundantPhi.ts +++ b/compiler/forget/src/SSA/EliminateRedundantPhi.ts @@ -27,7 +27,7 @@ import { * and phis rewrite all their identifiers based on this table. The algorithm loops over the CFG repeatedly * until there are no new rewrites: for a CFG without back-edges it completes in a single pass. */ -export function eliminateRedundantPhi(fn: HIRFunction) { +export function eliminateRedundantPhi(fn: HIRFunction): void { const ir = fn.body; const rewrites: Map = new Map(); @@ -111,7 +111,10 @@ export function eliminateRedundantPhi(fn: HIRFunction) { } while (rewrites.size > size && hasBackEdge); } -function rewritePlace(place: Place, rewrites: Map) { +function rewritePlace( + place: Place, + rewrites: Map +): void { const rewrite = rewrites.get(place.identifier); if (rewrite != null) { place.identifier = rewrite; diff --git a/compiler/forget/src/TypeInference/InferTypes.ts b/compiler/forget/src/TypeInference/InferTypes.ts index c33e9ec1ed..9fad30415c 100644 --- a/compiler/forget/src/TypeInference/InferTypes.ts +++ b/compiler/forget/src/TypeInference/InferTypes.ts @@ -11,7 +11,7 @@ import { } from "../HIR/HIR"; import { eachInstructionLValue, eachInstructionOperand } from "../HIR/visitors"; -function isPrimitiveBinaryOp(op: t.BinaryExpression["operator"]) { +function isPrimitiveBinaryOp(op: t.BinaryExpression["operator"]): boolean { switch (op) { case "+": case "-": @@ -22,7 +22,6 @@ function isPrimitiveBinaryOp(op: t.BinaryExpression["operator"]) { case "&": case "|": case ">>": - case ">>": case "<<": case "^": case ">": @@ -36,7 +35,7 @@ function isPrimitiveBinaryOp(op: t.BinaryExpression["operator"]) { } } -export default function (func: HIRFunction) { +export default function (func: HIRFunction): void { const unifier = new Unifier(); for (const e of generate(func)) { unifier.unify(e.left, e.right); @@ -44,7 +43,7 @@ export default function (func: HIRFunction) { apply(func, unifier); } -function apply(func: HIRFunction, unifier: Unifier) { +function apply(func: HIRFunction, unifier: Unifier): void { for (const [_, block] of func.body.blocks) { for (const phi of block.phis) { phi.type = unifier.get(phi.type); @@ -169,7 +168,7 @@ type Substitution = Map; class Unifier { substitutions: Substitution = new Map(); - unify(tA: Type, tB: Type) { + unify(tA: Type, tB: Type): void { if (typeEquals(tA, tB)) { return; } diff --git a/compiler/forget/src/Utils/DisjointSet.ts b/compiler/forget/src/Utils/DisjointSet.ts index 3f66105a77..6c7fa69ed9 100644 --- a/compiler/forget/src/Utils/DisjointSet.ts +++ b/compiler/forget/src/Utils/DisjointSet.ts @@ -80,7 +80,6 @@ export default class DisjointSet { canonicalize(): Map { const entries = new Map(); for (const item of this.#entries.keys()) { - const parent = this.#entries.get(item)!; const root = this.find(item)!; entries.set(item, root); }