mirror of
https://github.com/Noratrieb/riverdelta.git
synced 2026-01-15 00:45:04 +01:00
start implementing module res
This commit is contained in:
parent
2da011caf4
commit
cbbda39688
9 changed files with 389 additions and 95 deletions
|
|
@ -14,6 +14,7 @@ import {
|
|||
ItemId,
|
||||
LOGICAL_KINDS,
|
||||
LoopId,
|
||||
ModItemKind,
|
||||
Resolution,
|
||||
Ty,
|
||||
TY_BOOL,
|
||||
|
|
@ -29,6 +30,7 @@ import {
|
|||
} from "./ast";
|
||||
import { CompilerError, Span } from "./error";
|
||||
import { printTy } from "./printer";
|
||||
import { unwrap } from "./utils";
|
||||
|
||||
function mkTyFn(params: Ty[], returnTy: Ty): Ty {
|
||||
return { kind: "fn", params, returnTy };
|
||||
|
|
@ -81,10 +83,11 @@ function typeOfBuiltinValue(name: BuiltinName, span: Span): Ty {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: Cleanup, maybe get the ident switch into this function because typeOfItem is unused.
|
||||
function lowerAstTyBase(
|
||||
type: Type,
|
||||
lowerIdentTy: (ident: Identifier) => Ty,
|
||||
typeOfItem: (index: number) => Ty
|
||||
typeOfItem: (index: number, cause: Span) => Ty
|
||||
): Ty {
|
||||
switch (type.kind) {
|
||||
case "ident": {
|
||||
|
|
@ -112,8 +115,8 @@ function lowerAstTyBase(
|
|||
|
||||
export function typeck(ast: Ast): Ast {
|
||||
const itemTys = new Map<number, Ty | null>();
|
||||
function typeOfItem(index: ItemId): Ty {
|
||||
const item = ast.items[index];
|
||||
function typeOfItem(index: ItemId, cause: Span): Ty {
|
||||
const item = unwrap(ast.itemsById.get(index));
|
||||
|
||||
const ty = itemTys.get(index);
|
||||
if (ty) {
|
||||
|
|
@ -154,6 +157,12 @@ export function typeck(ast: Ast): Ast {
|
|||
ty.fields = fields;
|
||||
return ty;
|
||||
}
|
||||
case "mod": {
|
||||
throw new CompilerError(
|
||||
`module ${item.node.name} is not a type`,
|
||||
cause
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -167,7 +176,7 @@ export function typeck(ast: Ast): Ast {
|
|||
throw new Error("Item type cannot refer to local variable");
|
||||
}
|
||||
case "item": {
|
||||
return typeOfItem(res.index);
|
||||
return typeOfItem(res.id, type.span);
|
||||
}
|
||||
case "builtin": {
|
||||
return builtinAsTy(res.name, ident.span);
|
||||
|
|
@ -183,7 +192,7 @@ export function typeck(ast: Ast): Ast {
|
|||
item(item) {
|
||||
switch (item.kind) {
|
||||
case "function": {
|
||||
const fnTy = typeOfItem(item.id) as TyFn;
|
||||
const fnTy = typeOfItem(item.id, item.span) as TyFn;
|
||||
const body = checkBody(item.node.body, fnTy, typeOfItem);
|
||||
|
||||
const returnType = item.node.returnType && {
|
||||
|
|
@ -205,7 +214,7 @@ export function typeck(ast: Ast): Ast {
|
|||
};
|
||||
}
|
||||
case "import": {
|
||||
const fnTy = typeOfItem(item.id) as TyFn;
|
||||
const fnTy = typeOfItem(item.id, item.span) as TyFn;
|
||||
|
||||
fnTy.params.forEach((param, i) => {
|
||||
switch (param.kind) {
|
||||
|
|
@ -268,7 +277,7 @@ export function typeck(ast: Ast): Ast {
|
|||
fieldNames.add(name);
|
||||
});
|
||||
|
||||
const ty = typeOfItem(item.id) as TyStruct;
|
||||
const ty = typeOfItem(item.id, item.span) as TyStruct;
|
||||
|
||||
return {
|
||||
...item,
|
||||
|
|
@ -284,13 +293,38 @@ export function typeck(ast: Ast): Ast {
|
|||
},
|
||||
};
|
||||
}
|
||||
case "mod": {
|
||||
switch (item.node.modKind.kind) {
|
||||
case "inline":
|
||||
const modKind: ModItemKind = {
|
||||
kind: "inline",
|
||||
contents: item.node.modKind.contents.map((item) =>
|
||||
this.item(item)
|
||||
),
|
||||
};
|
||||
|
||||
return {
|
||||
...item,
|
||||
node: {
|
||||
...item.node,
|
||||
modKind,
|
||||
},
|
||||
};
|
||||
case "extern":
|
||||
// Nothing to check.
|
||||
return {
|
||||
...item,
|
||||
node: { ...item.node, modKind: { ...item.node.modKind } },
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
const typecked = foldAst(ast, checker);
|
||||
|
||||
const main = typecked.items.find((item) => {
|
||||
const main = typecked.rootItems.find((item) => {
|
||||
if (item.kind === "function" && item.node.name === "main") {
|
||||
const func = item.node;
|
||||
if (func.returnType !== undefined) {
|
||||
|
|
@ -316,7 +350,7 @@ export function typeck(ast: Ast): Ast {
|
|||
}
|
||||
|
||||
typecked.typeckResults = {
|
||||
main: { kind: "item", index: main.id },
|
||||
main: { kind: "item", id: main.id },
|
||||
};
|
||||
|
||||
return typecked;
|
||||
|
|
@ -483,7 +517,7 @@ export class InferContext {
|
|||
export function checkBody(
|
||||
body: Expr,
|
||||
fnTy: TyFn,
|
||||
typeOfItem: (index: number) => Ty
|
||||
typeOfItem: (index: number, cause: Span) => Ty
|
||||
): Expr {
|
||||
const localTys = [...fnTy.params];
|
||||
const loopState: { hasBreak: boolean; loopId: LoopId }[] = [];
|
||||
|
|
@ -497,7 +531,7 @@ export function checkBody(
|
|||
return localTys[idx];
|
||||
}
|
||||
case "item": {
|
||||
return typeOfItem(res.index);
|
||||
return typeOfItem(res.id, span);
|
||||
}
|
||||
case "builtin":
|
||||
return typeOfBuiltinValue(res.name, span);
|
||||
|
|
@ -515,7 +549,7 @@ export function checkBody(
|
|||
return localTys[idx];
|
||||
}
|
||||
case "item": {
|
||||
return typeOfItem(res.index);
|
||||
return typeOfItem(res.id, type.span);
|
||||
}
|
||||
case "builtin":
|
||||
return builtinAsTy(res.name, ident.span);
|
||||
|
|
@ -629,6 +663,10 @@ export function checkBody(
|
|||
|
||||
return { ...expr, ty };
|
||||
}
|
||||
case "path": {
|
||||
const ty = typeOf(expr.res, expr.span);
|
||||
return { ...expr, ty };
|
||||
}
|
||||
case "binary": {
|
||||
const lhs = this.expr(expr.lhs);
|
||||
const rhs = this.expr(expr.rhs);
|
||||
|
|
@ -731,7 +769,7 @@ export function checkBody(
|
|||
}
|
||||
default: {
|
||||
throw new CompilerError(
|
||||
"only tuples and structs have fields",
|
||||
`cannot access field \`${field.value}\` on type \`${printTy(lhs.ty)}\``,
|
||||
expr.span
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue