add eslint

This commit is contained in:
nora 2023-07-31 14:11:51 +02:00
parent e951cd5ee1
commit 12fcc4f1bb
11 changed files with 1237 additions and 26 deletions

27
.eslintrc.cjs Normal file
View file

@ -0,0 +1,27 @@
/* eslint-env node */
module.exports = {
ignorePatterns: ["/target/**", "/jest.config.js"],
extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
parser: "@typescript-eslint/parser",
plugins: ["@typescript-eslint"],
root: true,
rules: {
// Sometimes you just need a `while(true)`.
"no-constant-condition": "off",
// Typescript already checks problematic fallthrough.
// The eslint rule is a bit dumb and also complains about
// obvious clear fallthrough like `case "a": case "b"`.
"no-fallthrough": "off",
// Suppress no-unused-vars with leading underscores.
"@typescript-eslint/no-unused-vars": [
"warn",
{
varsIgnorePattern: "^_",
argsIgnorePattern: "^_",
},
],
// `any` is genrally bad, but sometimes it's the nicest solution
// Just let me use it without any ceremony.
"@typescript-eslint/no-explicit-any": "off",
},
};

1
eslintignore Normal file
View file

@ -0,0 +1 @@
/target

1181
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -13,6 +13,9 @@
"license": "ISC", "license": "ISC",
"devDependencies": { "devDependencies": {
"@types/jest": "^29.5.3", "@types/jest": "^29.5.3",
"@typescript-eslint/eslint-plugin": "^6.2.0",
"@typescript-eslint/parser": "^6.2.0",
"eslint": "^8.46.0",
"jest": "^29.6.1", "jest": "^29.6.1",
"node-dev": "^8.0.0", "node-dev": "^8.0.0",
"prettier": "^2.0.0", "prettier": "^2.0.0",

View file

@ -251,7 +251,7 @@ export function tokenize(input: string): Token[] {
i++; i++;
} }
const ident = input.slice(span.start, span.end); const ident = input.slice(span.start, span.end);
let kw = isKeyword(ident); const kw = isKeyword(ident);
if (kw) { if (kw) {
tokens.push({ kind: kw, span }); tokens.push({ kind: kw, span });
} else { } else {

View file

@ -331,7 +331,7 @@ function lowerExpr(fcx: FuncContext, instrs: wasm.Instr[], expr: Expr) {
} }
case "literal": { case "literal": {
switch (expr.value.kind) { switch (expr.value.kind) {
case "str": case "str": {
const utf8 = encodeUtf8(expr.value.value); const utf8 = encodeUtf8(expr.value.value);
const idx = appendData(fcx.cx, utf8); const idx = appendData(fcx.cx, utf8);
@ -339,6 +339,7 @@ function lowerExpr(fcx: FuncContext, instrs: wasm.Instr[], expr: Expr) {
instrs.push({ kind: "i32.const", imm: utf8.length }); instrs.push({ kind: "i32.const", imm: utf8.length });
break; break;
}
case "int": case "int":
switch (expr.value.type) { switch (expr.value.type) {
case "Int": case "Int":
@ -573,11 +574,9 @@ function lowerExpr(fcx: FuncContext, instrs: wasm.Instr[], expr: Expr) {
// TODO: Actually do this instead of being naive. // TODO: Actually do this instead of being naive.
const isPlace = (expr: Expr) => const _isPlace = (expr: Expr) =>
expr.kind === "ident" || expr.kind === "fieldAccess"; expr.kind === "ident" || expr.kind === "fieldAccess";
function project() {}
lowerExpr(fcx, instrs, expr.lhs); lowerExpr(fcx, instrs, expr.lhs);
switch (expr.lhs.ty!.kind) { switch (expr.lhs.ty!.kind) {

View file

@ -344,6 +344,7 @@ function parseExprCall(t: Token[]): [Token[], Expr] {
} }
function parseExprAtom(startT: Token[]): [Token[], Expr] { function parseExprAtom(startT: Token[]): [Token[], Expr] {
// eslint-disable-next-line prefer-const
let [t, tok] = next(startT); let [t, tok] = next(startT);
const span = tok.span; const span = tok.span;
@ -354,8 +355,7 @@ function parseExprAtom(startT: Token[]): [Token[], Expr] {
// This could be a block or a tuple literal. We can only know after // This could be a block or a tuple literal. We can only know after
// parsing the first expression and looking at the delimiter. // parsing the first expression and looking at the delimiter.
let peek; const [, peek] = next(t);
[, peek] = next(t);
// It's a single element, which we interpret as a block. // It's a single element, which we interpret as a block.
// `(0,)` is the one elem tuple. // `(0,)` is the one elem tuple.
if (peek.kind === ")") { if (peek.kind === ")") {
@ -579,11 +579,7 @@ function parseCommaSeparatedList<R>(
// () | (a) | (a,) | (a, b) // () | (a) | (a,) | (a, b)
while (true) { while (next(t)[1]?.kind !== terminator) {
if (next(t)[1]?.kind === terminator) {
break;
}
let nextValue; let nextValue;
[t, nextValue] = parser(t); [t, nextValue] = parser(t);

View file

@ -191,8 +191,8 @@ function resolveModule(
}; };
} }
case "let": { case "let": {
let rhs = this.expr(expr.rhs); const rhs = this.expr(expr.rhs);
let type = expr.type && this.type(expr.type); const type = expr.type && this.type(expr.type);
scopes.push(expr.name.name); scopes.push(expr.name.name);
const local = { name: expr.name.name, span: expr.name.span }; const local = { name: expr.name.name, span: expr.name.span };

View file

@ -1,4 +1,4 @@
import { TY_INT, TY_STRING, TY_UNIT, Ty } from "./ast"; import { TY_INT, TY_STRING, TY_UNIT } from "./ast";
import { DUMMY_SPAN as SPAN } from "./error"; import { DUMMY_SPAN as SPAN } from "./error";
import { InferContext } from "./typeck"; import { InferContext } from "./typeck";

View file

@ -1,6 +1,5 @@
import { import {
Ast, Ast,
binaryExprPrecedenceClass,
BuiltinName, BuiltinName,
COMPARISON_KINDS, COMPARISON_KINDS,
DEFAULT_FOLDER, DEFAULT_FOLDER,
@ -298,7 +297,7 @@ export function typeck(ast: Ast): Ast {
} }
case "mod": { case "mod": {
switch (item.node.modKind.kind) { switch (item.node.modKind.kind) {
case "inline": case "inline": {
const modKind: ModItemKind = { const modKind: ModItemKind = {
kind: "inline", kind: "inline",
contents: item.node.modKind.contents.map((item) => contents: item.node.modKind.contents.map((item) =>
@ -313,6 +312,7 @@ export function typeck(ast: Ast): Ast {
modKind, modKind,
}, },
}; };
}
case "extern": case "extern":
// Nothing to check. // Nothing to check.
return { return {
@ -417,7 +417,7 @@ export class InferContext {
* before calling this. * before calling this.
*/ */
private constrainVar(variable: number, ty: Ty) { private constrainVar(variable: number, ty: Ty) {
let root = this.findRoot(variable); const root = this.findRoot(variable);
if (ty.kind === "var") { if (ty.kind === "var") {
// Now we point our root to the other root to unify the two graphs. // Now we point our root to the other root to unify the two graphs.
@ -571,7 +571,9 @@ export function checkBody(
} }
case "let": { case "let": {
const loweredBindingTy = expr.type && lowerAstTy(expr.type); const loweredBindingTy = expr.type && lowerAstTy(expr.type);
let bindingTy = loweredBindingTy ? loweredBindingTy : infcx.newVar(); const bindingTy = loweredBindingTy
? loweredBindingTy
: infcx.newVar();
const rhs = this.expr(expr.rhs); const rhs = this.expr(expr.rhs);
infcx.assign(bindingTy, rhs.ty!, expr.span); infcx.assign(bindingTy, rhs.ty!, expr.span);
@ -772,7 +774,9 @@ export function checkBody(
} }
default: { default: {
throw new CompilerError( throw new CompilerError(
`cannot access field \`${field.value}\` on type \`${printTy(lhs.ty)}\``, `cannot access field \`${field.value}\` on type \`${printTy(
lhs.ty
)}\``,
expr.span expr.span
); );
} }
@ -854,7 +858,7 @@ export function checkBody(
const assignedFields = new Set(); const assignedFields = new Set();
fields.forEach(([name, field], i) => { fields.forEach(([name, field]) => {
const fieldTy = structTy.fields.find((def) => def[0] === name.name); const fieldTy = structTy.fields.find((def) => def[0] === name.name);
if (!fieldTy) { if (!fieldTy) {
throw new CompilerError( throw new CompilerError(
@ -928,8 +932,8 @@ export function checkBody(
} }
function checkBinary(expr: Expr & ExprBinary): Expr { function checkBinary(expr: Expr & ExprBinary): Expr {
let lhsTy = expr.lhs.ty!; const lhsTy = expr.lhs.ty!;
let rhsTy = expr.rhs.ty!; const rhsTy = expr.rhs.ty!;
if (COMPARISON_KINDS.includes(expr.binaryKind)) { if (COMPARISON_KINDS.includes(expr.binaryKind)) {
if (lhsTy.kind === "int" && rhsTy.kind === "int") { if (lhsTy.kind === "int" && rhsTy.kind === "int") {
@ -969,7 +973,7 @@ function checkBinary(expr: Expr & ExprBinary): Expr {
} }
function checkUnary(expr: Expr & ExprUnary): Expr { function checkUnary(expr: Expr & ExprUnary): Expr {
let rhsTy = expr.rhs.ty!; const rhsTy = expr.rhs.ty!;
if ( if (
expr.unaryKind === "!" && expr.unaryKind === "!" &&

View file

@ -629,12 +629,12 @@ function printStart(start: Start, f: FmtCtx) {
}); });
} }
function printElem(_elem: Elem, f: FmtCtx) { function printElem(_elem: Elem, _f: FmtCtx) {
todo(); todo();
} }
function printData(data: Data, f: FmtCtx) { function printData(data: Data, f: FmtCtx) {
let mode = data.mode; const mode = data.mode;
f.sexpr(() => { f.sexpr(() => {
f.keyword("data"); f.keyword("data");