Start lowering

This commit is contained in:
nora 2023-07-26 13:20:32 +02:00
parent 8b424c0add
commit 87f081a4fe
5 changed files with 33 additions and 25 deletions

View file

@ -20,9 +20,10 @@ export type Item = ItemKind & {
export type FunctionDef = { export type FunctionDef = {
name: string; name: string;
args: FunctionArg[]; params: FunctionArg[];
body: Expr; body: Expr;
returnType?: Type; returnType?: Type;
ty?: TyFn;
}; };
export type FunctionArg = { export type FunctionArg = {
@ -253,6 +254,11 @@ export function tyIsUnit(ty: Ty): ty is TyUnit {
return ty.kind === "tuple" && ty.elems.length === 0; 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 // folders
export type FoldFn<T> = (value: T) => T; export type FoldFn<T> = (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)); return ast.map((item) => folder.item(item));
} }
export function superFoldItem(item: Item, folder: Folder): Item { export function superFoldItem(item: Item, folder: Folder): Item {
switch (item.kind) { switch (item.kind) {
case "function": { case "function": {
const args = item.node.args.map(({ name, type, span }) => ({ const args = item.node.params.map(({ name, type, span }) => ({
name, name,
type: folder.type(type), type: folder.type(type),
span, span,
@ -297,7 +303,7 @@ export function superFoldItem(item: Item, folder: Folder): Item {
span: item.span, span: item.span,
node: { node: {
name: item.node.name, name: item.node.name,
args, params: args,
body: folder.expr(item.node.body), body: folder.expr(item.node.body),
returnType: item.node.returnType && folder.type(item.node.returnType), 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");
}

View file

@ -76,7 +76,7 @@ function parseItem(t: Token[]): [Token[], Item] {
const def: FunctionDef = { const def: FunctionDef = {
name: name.ident, name: name.ident,
args, params: args,
returnType, returnType,
body, body,
}; };

View file

@ -23,7 +23,7 @@ function printItem(item: Item): string {
} }
function printFunction(func: FunctionDef): string { function printFunction(func: FunctionDef): string {
const args = func.args const args = func.params
.map(({ name, type }) => `${name}: ${printType(type)}`) .map(({ name, type }) => `${name}: ${printType(type)}`)
.join(", "); .join(", ");
const ret = func.returnType ? `: ${printType(func.returnType)}` : ""; const ret = func.returnType ? `: ${printType(func.returnType)}` : "";

View file

@ -4,7 +4,7 @@ import {
Folder, Folder,
Identifier, Identifier,
Resolution, Resolution,
fold_ast, foldAst,
superFoldExpr, superFoldExpr,
superFoldItem, superFoldItem,
} from "./ast"; } from "./ast";
@ -78,7 +78,7 @@ export function resolve(ast: Ast): Ast {
item(item) { item(item) {
switch (item.kind) { switch (item.kind) {
case "function": { case "function": {
const args = item.node.args.map(({ name, span, type }) => ({ const params = item.node.params.map(({ name, span, type }) => ({
name, name,
span, span,
type: this.type(type), type: this.type(type),
@ -86,16 +86,16 @@ export function resolve(ast: Ast): Ast {
const returnType = const returnType =
item.node.returnType && this.type(item.node.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); const body = superFoldExpr(item.node.body, this);
item.node.args.forEach(({ name }) => popScope(name)); item.node.params.forEach(({ name }) => popScope(name));
return { return {
kind: "function", kind: "function",
span: item.span, span: item.span,
node: { node: {
name: item.node.name, name: item.node.name,
args, params,
returnType, returnType,
body, body,
}, },
@ -132,7 +132,7 @@ export function resolve(ast: Ast): Ast {
}, },
}; };
const resolved = fold_ast(ast, resolver); const resolved = foldAst(ast, resolver);
return resolved; return resolved;
} }

View file

@ -1,36 +1,35 @@
import { import {
Ast, Ast,
binaryExprPrecedenceClass,
COMPARISON_KINDS, COMPARISON_KINDS,
DEFAULT_FOLDER, DEFAULT_FOLDER,
EQUALITY_KINDS, EQUALITY_KINDS,
Expr, Expr,
ExprBinary, ExprBinary,
ExprUnary, ExprUnary,
foldAst,
Folder, Folder,
Identifier, Identifier,
LOGICAL_KINDS, LOGICAL_KINDS,
Resolution, Resolution,
Ty, Ty,
TY_BOOL,
TY_INT,
TY_STRING,
TY_UNIT,
TyFn, TyFn,
Type, Type,
binaryExprPrecedenceClass,
fold_ast,
} from "./ast"; } from "./ast";
import { CompilerError, Span } from "./error"; import { CompilerError, Span } from "./error";
import { printTy } from "./printer"; 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 { function builtinAsTy(name: string, span: Span): Ty {
switch (name) { switch (name) {
case "String": { case "String": {
return TY_STRING; return TY_STRING;
} }
case "Int": { case "Int": {
return TY_INT; return TY_BOOL;
} }
case "Bool": { case "Bool": {
return TY_BOOL; return TY_BOOL;
@ -105,7 +104,7 @@ export function typeck(ast: Ast): Ast {
const item = ast[index]; const item = ast[index];
switch (item.kind) { switch (item.kind) {
case "function": { 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 const returnTy: Ty = item.node.returnType
? lowerAstTy(item.node.returnType) ? lowerAstTy(item.node.returnType)
: TY_UNIT; : TY_UNIT;
@ -153,7 +152,7 @@ export function typeck(ast: Ast): Ast {
kind: "function", kind: "function",
node: { node: {
name: item.node.name, name: item.node.name,
args: item.node.args.map((arg, i) => ({ params: item.node.params.map((arg, i) => ({
...arg, ...arg,
type: { ...arg.type, ty: fnTy.params[i] }, type: { ...arg.type, ty: fnTy.params[i] },
})), })),
@ -162,15 +161,14 @@ export function typeck(ast: Ast): Ast {
}, },
span: item.span, span: item.span,
id: item.id, id: item.id,
ty: fnTy,
}; };
} }
} }
}, },
}; };
const withTypes = fold_ast(ast, checker); return foldAst(ast, checker);
return withTypes;
} }
type TyVarRes = type TyVarRes =