[be] Fix remaining lints and enable lint in CI

This commit is contained in:
Lauren Tan
2023-03-10 16:21:01 -05:00
parent 7813cfa52c
commit faa8eef0a8
21 changed files with 58 additions and 52 deletions
+2
View File
@@ -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
+1
View File
@@ -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"],
+1 -1
View File
@@ -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");
}
@@ -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.
@@ -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) {
+4 -1
View File
@@ -20,7 +20,10 @@ export function inferAliases(func: HIRFunction): DisjointSet<Identifier> {
return aliases;
}
function inferInstr(instr: Instruction, aliases: DisjointSet<Identifier>) {
function inferInstr(
instr: Instruction,
aliases: DisjointSet<Identifier>
): void {
const { lvalue, value: instrValue } = instr;
let alias: Place | null = null;
switch (instrValue.kind) {
@@ -10,7 +10,7 @@ import DisjointSet from "../Utils/DisjointSet";
export function inferAliasForPhis(
func: HIRFunction,
aliases: DisjointSet<Identifier>
) {
): void {
for (const [_, block] of func.body.blocks) {
for (const phi of block.phis) {
const isPhiMutatedAfterCreation: boolean =
@@ -20,7 +20,7 @@ import DisjointSet from "../Utils/DisjointSet";
export function inferAliasForStores(
func: HIRFunction,
aliases: DisjointSet<Identifier>
) {
): void {
for (const [_, block] of func.body.blocks) {
for (const instr of block.instructions) {
const { value, lvalue } = instr;
@@ -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;
@@ -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);
@@ -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<Identifier>
) {
): void {
const aliasSets = aliases.buildSets();
for (const aliasSet of aliasSets) {
// Update mutableRange.end only if the identifiers have actually been
@@ -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<BlockId, InferenceState> = 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<InstructionValue> = 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;
@@ -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 = {
@@ -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":
@@ -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,
@@ -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<ReactiveScopeDependencyTree>
) {
): 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<DependencyNode> = [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<Map<string, DependencyNode>>,
currProperties: Map<string, DependencyNode>
) {
): void {
invariant(
otherProperties.length > 1,
"[DeriveMinimalDependencies] Expected otherProperties to be at least 2 elements long."
@@ -29,7 +29,7 @@ class State {
}
class Visitor extends ReactiveFunctionVisitor<State> {
override visitInstruction(instr: ReactiveInstruction, state: State) {
override visitInstruction(instr: ReactiveInstruction, state: State): void {
this.traverseInstruction(instr, state);
const lval = instr.lvalue;
if (lval == null) {
@@ -158,7 +158,7 @@ class Context {
*/
promoteDepsFromExhaustiveConditionals(
depsInConditionals: Array<ReactiveScopeDependencyTree>
) {
): 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 =
@@ -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<Identifier, Identifier> = new Map();
@@ -111,7 +111,10 @@ export function eliminateRedundantPhi(fn: HIRFunction) {
} while (rewrites.size > size && hasBackEdge);
}
function rewritePlace(place: Place, rewrites: Map<Identifier, Identifier>) {
function rewritePlace(
place: Place,
rewrites: Map<Identifier, Identifier>
): void {
const rewrite = rewrites.get(place.identifier);
if (rewrite != null) {
place.identifier = rewrite;
@@ -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<TypeId, Type>;
class Unifier {
substitutions: Substitution = new Map();
unify(tA: Type, tB: Type) {
unify(tA: Type, tB: Type): void {
if (typeEquals(tA, tB)) {
return;
}
-1
View File
@@ -80,7 +80,6 @@ export default class DisjointSet<T> {
canonicalize(): Map<T, T> {
const entries = new Map<T, T>();
for (const item of this.#entries.keys()) {
const parent = this.#entries.get(item)!;
const root = this.find(item)!;
entries.set(item, root);
}