From 87f081a4feedfdd50210788994f4659ed956b285 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Wed, 26 Jul 2023 13:20:32 +0200 Subject: [PATCH] Start lowering --- src/ast.ts | 18 ++++++++++++++---- src/parser.ts | 2 +- src/printer.ts | 2 +- src/resolve.ts | 12 ++++++------ src/typeck.ts | 24 +++++++++++------------- 5 files changed, 33 insertions(+), 25 deletions(-) diff --git a/src/ast.ts b/src/ast.ts index 3e050fb..fa6d04a 100644 --- a/src/ast.ts +++ b/src/ast.ts @@ -20,9 +20,10 @@ export type Item = ItemKind & { export type FunctionDef = { name: string; - args: FunctionArg[]; + params: FunctionArg[]; body: Expr; returnType?: Type; + ty?: TyFn; }; export type FunctionArg = { @@ -253,6 +254,11 @@ export function tyIsUnit(ty: Ty): ty is TyUnit { return ty.kind === "tuple" && ty.elems.length === 0; } +export const TY_UNIT: Ty = { kind: "tuple", elems: [] }; +export const TY_STRING: Ty = { kind: "string" }; +export const TY_BOOL: Ty = { kind: "bool" }; +export const TY_INT: Ty = { kind: "int" }; + // folders export type FoldFn = (value: T) => T; @@ -279,14 +285,14 @@ export const DEFAULT_FOLDER: Folder = { }, }; -export function fold_ast(ast: Ast, folder: Folder): Ast { +export function foldAst(ast: Ast, folder: Folder): Ast { return ast.map((item) => folder.item(item)); } export function superFoldItem(item: Item, folder: Folder): Item { switch (item.kind) { case "function": { - const args = item.node.args.map(({ name, type, span }) => ({ + const args = item.node.params.map(({ name, type, span }) => ({ name, type: folder.type(type), span, @@ -297,7 +303,7 @@ export function superFoldItem(item: Item, folder: Folder): Item { span: item.span, node: { name: item.node.name, - args, + params: args, body: folder.expr(item.node.body), returnType: item.node.returnType && folder.type(item.node.returnType), }, @@ -399,3 +405,7 @@ export function superFoldType(type: Type, folder: Folder): Type { } } } + +export function varUnreachable(): never { + throw new Error("Type variables must not occur after type checking"); +} diff --git a/src/parser.ts b/src/parser.ts index 40e4c6b..2fcaa5c 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -76,7 +76,7 @@ function parseItem(t: Token[]): [Token[], Item] { const def: FunctionDef = { name: name.ident, - args, + params: args, returnType, body, }; diff --git a/src/printer.ts b/src/printer.ts index 0bb8860..2a9d803 100644 --- a/src/printer.ts +++ b/src/printer.ts @@ -23,7 +23,7 @@ function printItem(item: Item): string { } function printFunction(func: FunctionDef): string { - const args = func.args + const args = func.params .map(({ name, type }) => `${name}: ${printType(type)}`) .join(", "); const ret = func.returnType ? `: ${printType(func.returnType)}` : ""; diff --git a/src/resolve.ts b/src/resolve.ts index 32244a6..34da31d 100644 --- a/src/resolve.ts +++ b/src/resolve.ts @@ -4,7 +4,7 @@ import { Folder, Identifier, Resolution, - fold_ast, + foldAst, superFoldExpr, superFoldItem, } from "./ast"; @@ -78,7 +78,7 @@ export function resolve(ast: Ast): Ast { item(item) { switch (item.kind) { case "function": { - const args = item.node.args.map(({ name, span, type }) => ({ + const params = item.node.params.map(({ name, span, type }) => ({ name, span, type: this.type(type), @@ -86,16 +86,16 @@ export function resolve(ast: Ast): Ast { const returnType = item.node.returnType && this.type(item.node.returnType); - item.node.args.forEach(({ name }) => scopes.push(name)); + item.node.params.forEach(({ name }) => scopes.push(name)); const body = superFoldExpr(item.node.body, this); - item.node.args.forEach(({ name }) => popScope(name)); + item.node.params.forEach(({ name }) => popScope(name)); return { kind: "function", span: item.span, node: { name: item.node.name, - args, + params, returnType, body, }, @@ -132,7 +132,7 @@ export function resolve(ast: Ast): Ast { }, }; - const resolved = fold_ast(ast, resolver); + const resolved = foldAst(ast, resolver); return resolved; } diff --git a/src/typeck.ts b/src/typeck.ts index 64b2fb2..51e0e93 100644 --- a/src/typeck.ts +++ b/src/typeck.ts @@ -1,36 +1,35 @@ import { Ast, + binaryExprPrecedenceClass, COMPARISON_KINDS, DEFAULT_FOLDER, EQUALITY_KINDS, Expr, ExprBinary, ExprUnary, + foldAst, Folder, Identifier, LOGICAL_KINDS, Resolution, Ty, + TY_BOOL, + TY_INT, + TY_STRING, + TY_UNIT, TyFn, Type, - binaryExprPrecedenceClass, - fold_ast, } from "./ast"; import { CompilerError, Span } from "./error"; import { printTy } from "./printer"; -const TY_UNIT: Ty = { kind: "tuple", elems: [] }; -const TY_STRING: Ty = { kind: "string" }; -const TY_BOOL: Ty = { kind: "bool" }; -const TY_INT: Ty = { kind: "int" }; - function builtinAsTy(name: string, span: Span): Ty { switch (name) { case "String": { return TY_STRING; } case "Int": { - return TY_INT; + return TY_BOOL; } case "Bool": { return TY_BOOL; @@ -105,7 +104,7 @@ export function typeck(ast: Ast): Ast { const item = ast[index]; switch (item.kind) { case "function": { - const args = item.node.args.map((arg) => lowerAstTy(arg.type)); + const args = item.node.params.map((arg) => lowerAstTy(arg.type)); const returnTy: Ty = item.node.returnType ? lowerAstTy(item.node.returnType) : TY_UNIT; @@ -153,7 +152,7 @@ export function typeck(ast: Ast): Ast { kind: "function", node: { name: item.node.name, - args: item.node.args.map((arg, i) => ({ + params: item.node.params.map((arg, i) => ({ ...arg, type: { ...arg.type, ty: fnTy.params[i] }, })), @@ -162,15 +161,14 @@ export function typeck(ast: Ast): Ast { }, span: item.span, id: item.id, + ty: fnTy, }; } } }, }; - const withTypes = fold_ast(ast, checker); - - return withTypes; + return foldAst(ast, checker); } type TyVarRes =