From 93f478546e46f3b463aea590d34f8895d8c61fff Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Mon, 31 Jul 2023 16:41:03 +0200 Subject: [PATCH] Also use AST phases for ty --- src/ast.ts | 42 +++++++++++++++++++-------- src/lower.ts | 32 ++++++++++----------- src/typeck.ts | 79 +++++++++++++++++++++++++-------------------------- 3 files changed, 84 insertions(+), 69 deletions(-) diff --git a/src/ast.ts b/src/ast.ts index 500ffbe..85c5ce2 100644 --- a/src/ast.ts +++ b/src/ast.ts @@ -3,32 +3,53 @@ import { LitIntType } from "./lexer"; export type Ast

= { rootItems: Item

[]; - typeckResults?: TypeckResults; itemsById: Map>; packageName: string; -}; +} & P["typeckResults"]; export type Phase = { res: unknown; + defPath: unknown; + ty: unknown; + typeckResults: unknown; }; -type NoRes = object; +type No = object; + type HasRes = { res: Resolution }; +type HasDefPath = { defPath: string[] }; +type HasTy = { ty: Ty }; +type HasTypeckResults = { typeckResults: TypeckResults }; export type Parsed = { - res: NoRes; + res: No; + defPath: No; + ty: No; + typeckResults: No; }; export type Built = { - res: NoRes; + res: No; + defPath: No; + ty: No; + typeckResults: No; }; export type Resolved = { res: HasRes; + defPath: HasDefPath; + ty: No; + typeckResults: No; }; export type Typecked = { res: HasRes; + defPath: HasDefPath; + ty: HasTy; + typeckResults: HasTypeckResults; }; export type AnyPhase = { - res: NoRes | HasRes; + res: No | HasRes; + defPath: No | HasDefPath; + ty: No | HasTy; + typeckResults: No | HasTypeckResults; }; export type Ident = { @@ -64,8 +85,7 @@ export type ItemKind

= export type Item

= ItemKind

& { span: Span; id: ItemId; - defPath?: string[]; -}; +} & P["defPath"]; export type FunctionDef

= { name: string; @@ -246,8 +266,7 @@ export type ExprKind

= export type Expr

= ExprKind

& { span: Span; - ty?: Ty; -}; +} & P["ty"]; export type StringLiteral = { kind: "str"; @@ -335,7 +354,6 @@ export type TypeKind

= export type Type

= TypeKind

& { span: Span; - ty?: Ty; }; // name resolution stuff @@ -526,7 +544,7 @@ export function foldAst( return { rootItems: ast.rootItems.map((item) => folder.item(item)), itemsById: folder.newItemsById, - typeckResults: ast.typeckResults, + typeckResults: "typeckResults" in ast ? ast.typeckResults : undefined, packageName: ast.packageName, }; } diff --git a/src/lower.ts b/src/lower.ts index f207c6e..1398ba8 100644 --- a/src/lower.ts +++ b/src/lower.ts @@ -231,7 +231,7 @@ function lowerFunc( const type = internFuncType(cx, wasmType); const wasmFunc: wasm.Func = { - _name: mangleDefPath(item.defPath!), + _name: mangleDefPath(item.defPath), type, locals: [], body: [], @@ -269,7 +269,7 @@ function lowerExpr( instrs: wasm.Instr[], expr: Expr ) { - const ty = expr.ty!; + const ty = expr.ty; exprKind: switch (expr.kind) { case "empty": { @@ -278,7 +278,7 @@ function lowerExpr( } case "let": { lowerExpr(fcx, instrs, expr.rhs); - const types = wasmTypeForBody(expr.rhs.ty!); + const types = wasmTypeForBody(expr.rhs.ty); const local = fcx.wasm.locals.length + fcx.wasmType.params.length; @@ -333,7 +333,7 @@ function lowerExpr( const instr: wasm.Instr = { kind: "block", instrs: lowerExprBlockBody(fcx, expr), - type: blockTypeForBody(fcx.cx, expr.ty!), + type: blockTypeForBody(fcx.cx, expr.ty), }; instrs.push(instr); @@ -404,8 +404,8 @@ function lowerExpr( lowerExpr(fcx, instrs, expr.lhs); lowerExpr(fcx, instrs, expr.rhs); - const lhsTy = expr.lhs.ty!; - const rhsTy = expr.rhs.ty!; + const lhsTy = expr.lhs.ty; + const rhsTy = expr.rhs.ty; if ( (lhsTy.kind === "int" && rhsTy.kind === "int") || (lhsTy.kind === "i32" && rhsTy.kind === "i32") @@ -592,11 +592,11 @@ function lowerExpr( lowerExpr(fcx, instrs, expr.lhs); - switch (expr.lhs.ty!.kind) { + switch (expr.lhs.ty.kind) { case "tuple": { // Tuples have a by-value ABI, so we can simply index. const lhsSize = argRetAbi(expr.lhs.ty).length; - const resultAbi = argRetAbi(expr.ty!); + const resultAbi = argRetAbi(expr.ty); const resultSize = resultAbi.length; const wasmIdx = wasmTypeIdxForTupleField( expr.lhs.ty, @@ -655,7 +655,7 @@ function lowerExpr( kind: "if", then: thenInstrs, else: elseInstrs, - type: blockTypeForBody(fcx.cx, expr.ty!), + type: blockTypeForBody(fcx.cx, expr.ty), }); break; @@ -669,7 +669,7 @@ function lowerExpr( lowerExpr(fcx, bodyInstrs, expr.body); // For diverging bodies, we don't need to bother creating the back edge. - if (expr.body.ty!.kind !== "never") { + if (expr.body.ty.kind !== "never") { bodyInstrs.push({ kind: "br", label: /*innermost control structure, the loop*/ 0, @@ -680,13 +680,13 @@ function lowerExpr( outerBlockInstrs.push({ kind: "loop", instrs: bodyInstrs, - type: blockTypeForBody(fcx.cx, expr.ty!), + type: blockTypeForBody(fcx.cx, expr.ty), }); instrs.push({ kind: "block", instrs: outerBlockInstrs, - type: blockTypeForBody(fcx.cx, expr.ty!), + type: blockTypeForBody(fcx.cx, expr.ty), }); fcx.loopDepths.delete(expr.loopId); @@ -695,8 +695,6 @@ function lowerExpr( case "break": { const loopDepth = unwrap(fcx.loopDepths.get(expr.target!)); - console.log(loopDepth, fcx.currentBlockDepth); - instrs.push({ kind: "br", label: fcx.currentBlockDepth - loopDepth - 1, @@ -733,11 +731,11 @@ function lowerExprBlockBody( for (const inner of headExprs) { lowerExpr(fcx, innerInstrs, inner); - if (inner.ty!.kind === "never") { + if (inner.ty.kind === "never") { // The rest of the block is unreachable, so we don't bother codegening it. break; } - const types = wasmTypeForBody(inner.ty!); + const types = wasmTypeForBody(inner.ty); types.forEach(() => innerInstrs.push({ kind: "drop" })); } @@ -872,7 +870,7 @@ function addRt(cx: Context, ast: Ast) { cx.relocations.push({ kind: "funccall", instr: mainCall, - res: ast.typeckResults!.main, + res: ast.typeckResults.main, }); const start: wasm.Func = { diff --git a/src/typeck.ts b/src/typeck.ts index 7970f1f..703a941 100644 --- a/src/typeck.ts +++ b/src/typeck.ts @@ -341,7 +341,7 @@ export function typeck(ast: Ast): Ast { if (item.kind === "function" && item.node.name === "main") { const func = item.node; if (func.returnType !== undefined) { - const ty = func.returnType.ty!; + const ty = func.body.ty; if (ty.kind !== "tuple" || ty.elems.length !== 0) { throw new CompilerError( `\`main\` has an invalid signature. main takes no arguments and returns nothing`, @@ -586,7 +586,7 @@ export function checkBody( : infcx.newVar(); const rhs = this.expr(expr.rhs); - infcx.assign(bindingTy, rhs.ty!, expr.span); + infcx.assign(bindingTy, rhs.ty, expr.span); // AST validation ensures that lets can only be in blocks, where // the types will be popped. @@ -596,7 +596,6 @@ export function checkBody( const type: Type | undefined = loweredBindingTy && { ...expr.type!, - ty: loweredBindingTy, }; return { @@ -612,7 +611,7 @@ export function checkBody( const lhs = this.expr(expr.lhs); const rhs = this.expr(expr.rhs); - infcx.assign(lhs.ty!, rhs.ty!, expr.span); + infcx.assign(lhs.ty, rhs.ty, expr.span); switch (lhs.kind) { case "ident": @@ -641,7 +640,7 @@ export function checkBody( const exprs = expr.exprs.map((expr) => this.expr(expr)); - const ty = exprs.length > 0 ? exprs[exprs.length - 1].ty! : TY_UNIT; + const ty = exprs.length > 0 ? exprs[exprs.length - 1].ty : TY_UNIT; localTys.length = prevLocalTysLen; @@ -686,19 +685,19 @@ export function checkBody( const lhs = this.expr(expr.lhs); const rhs = this.expr(expr.rhs); - lhs.ty = infcx.resolveIfPossible(lhs.ty!); - rhs.ty = infcx.resolveIfPossible(rhs.ty!); + lhs.ty = infcx.resolveIfPossible(lhs.ty); + rhs.ty = infcx.resolveIfPossible(rhs.ty); - return checkBinary({ ...expr, lhs, rhs }); + return checkBinary(expr, lhs, rhs); } case "unary": { const rhs = this.expr(expr.rhs); - rhs.ty = infcx.resolveIfPossible(rhs.ty!); - return checkUnary({ ...expr, rhs }); + rhs.ty = infcx.resolveIfPossible(rhs.ty); + return checkUnary(expr, rhs); } case "call": { const lhs = this.expr(expr.lhs); - lhs.ty = infcx.resolveIfPossible(lhs.ty!); + lhs.ty = infcx.resolveIfPossible(lhs.ty); const lhsTy = lhs.ty; if (lhsTy.kind !== "fn") { throw new CompilerError( @@ -718,7 +717,7 @@ export function checkBody( } const arg = checker.expr(args[i]); - infcx.assign(param, arg.ty!, args[i].span); + infcx.assign(param, arg.ty, args[i].span); }); if (args.length > lhsTy.params.length) { @@ -732,7 +731,7 @@ export function checkBody( } case "fieldAccess": { const lhs = this.expr(expr.lhs); - lhs.ty = infcx.resolveIfPossible(lhs.ty!); + lhs.ty = infcx.resolveIfPossible(lhs.ty); const { field } = expr; let ty: Ty; @@ -807,14 +806,14 @@ export function checkBody( const then = this.expr(expr.then); const elsePart = expr.else && this.expr(expr.else); - infcx.assign(TY_BOOL, cond.ty!, cond.span); + infcx.assign(TY_BOOL, cond.ty, cond.span); let ty: Ty; if (elsePart) { - infcx.assign(then.ty!, elsePart.ty!, elsePart.span); + infcx.assign(then.ty, elsePart.ty, elsePart.span); ty = then.ty!; } else { - infcx.assign(TY_UNIT, then.ty!, then.span); + infcx.assign(TY_UNIT, then.ty, then.span); ty = TY_UNIT; } @@ -827,7 +826,7 @@ export function checkBody( }); const body = this.expr(expr.body); - infcx.assign(TY_UNIT, body.ty!, body.span); + infcx.assign(TY_UNIT, body.ty, body.span); const hadBreak = loopState.pop(); const ty = hadBreak ? TY_UNIT : TY_NEVER; @@ -875,7 +874,7 @@ export function checkBody( name.span ); } - infcx.assign(fieldTy[1], field.ty!, field.span); + infcx.assign(fieldTy[1], field.ty, field.span); assignedFields.add(name.name); }); @@ -899,7 +898,7 @@ export function checkBody( const ty: Ty = { kind: "tuple", - elems: fields.map((field) => field.ty!), + elems: fields.map((field) => field.ty), }; return { ...expr, fields, ty }; @@ -919,7 +918,7 @@ export function checkBody( const checked = checker.expr(body); - infcx.assign(fnTy.returnTy, checked.ty!, body.span); + infcx.assign(fnTy.returnTy, checked.ty, body.span); const resolveTy = (ty: Ty, span: Span) => { const resTy = infcx.resolveIfPossible(ty); @@ -933,7 +932,7 @@ export function checkBody( const resolver: Folder = { ...mkDefaultFolder(), expr(expr) { - const ty = resolveTy(expr.ty!, expr.span); + const ty = resolveTy(expr.ty, expr.span); if (expr.kind === "block") { expr.locals!.forEach((local) => { @@ -944,8 +943,7 @@ export function checkBody( return { ...expr, ty }; }, type(type) { - const ty = resolveTy(type.ty!, type.span); - return { ...type, ty }; + return type; }, ident(ident) { return ident; @@ -958,58 +956,61 @@ export function checkBody( } function checkBinary( - expr: Expr & ExprBinary + expr: Expr & ExprBinary, + lhs: Expr, + rhs: Expr ): Expr { - const lhsTy = expr.lhs.ty!; - const rhsTy = expr.rhs.ty!; + const lhsTy = lhs.ty; + const rhsTy = rhs.ty; if (COMPARISON_KINDS.includes(expr.binaryKind)) { if (lhsTy.kind === "int" && rhsTy.kind === "int") { - return { ...expr, ty: TY_BOOL }; + return { ...expr, lhs, rhs, ty: TY_BOOL }; } if (lhsTy.kind === "string" && rhsTy.kind === "string") { - return { ...expr, ty: TY_BOOL }; + return { ...expr, lhs, rhs, ty: TY_BOOL }; } if (EQUALITY_KINDS.includes(expr.binaryKind)) { if (lhsTy.kind === "bool" && rhsTy.kind === "bool") { - return { ...expr, ty: TY_BOOL }; + return { ...expr, lhs, rhs, ty: TY_BOOL }; } } } if (lhsTy.kind === "int" && rhsTy.kind === "int") { - return { ...expr, ty: TY_INT }; + return { ...expr, lhs, rhs, ty: TY_INT }; } if (lhsTy.kind === "i32" && rhsTy.kind === "i32") { - return { ...expr, ty: TY_I32 }; + return { ...expr, lhs, rhs, ty: TY_I32 }; } if (LOGICAL_KINDS.includes(expr.binaryKind)) { if (lhsTy.kind === "bool" && rhsTy.kind === "bool") { - return { ...expr, ty: TY_BOOL }; + return { ...expr, lhs, rhs, ty: TY_BOOL }; } } throw new CompilerError( - `invalid types for binary operation: ${printTy(expr.lhs.ty!)} ${ + `invalid types for binary operation: ${printTy(lhs.ty)} ${ expr.binaryKind - } ${printTy(expr.rhs.ty!)}`, + } ${printTy(rhs.ty)}`, expr.span ); } function checkUnary( - expr: Expr & ExprUnary + expr: Expr & ExprUnary, + rhs: Expr ): Expr { - const rhsTy = expr.rhs.ty!; + const rhsTy = rhs.ty; if ( expr.unaryKind === "!" && (rhsTy.kind === "int" || rhsTy.kind === "bool") ) { - return { ...expr, ty: rhsTy }; + return { ...expr, rhs, ty: rhsTy }; } if (expr.unaryKind === "-" && rhsTy.kind == "int") { @@ -1017,9 +1018,7 @@ function checkUnary( } throw new CompilerError( - `invalid types for unary operation: ${expr.unaryKind} ${printTy( - expr.rhs.ty! - )}`, + `invalid types for unary operation: ${expr.unaryKind} ${printTy(rhs.ty)}`, expr.span ); }