"implement" use

This commit is contained in:
nora 2024-06-01 14:55:19 +02:00
parent d6123836e8
commit 8b33910aec
9 changed files with 66 additions and 6 deletions

View file

@ -107,6 +107,7 @@ export type ItemKind<P extends Phase> =
| ItemKindMod<P>
| ItemKindExtern
| ItemKindGlobal<P>
| ItemKindUse<P>
| ItemKindError;
type ItemVariant<Variant, P extends Phase> = Variant & Item<P>;
@ -117,6 +118,7 @@ export type ItemImport<P extends Phase> = ItemVariant<ItemKindImport<P>, P>;
export type ItemMod<P extends Phase> = ItemVariant<ItemKindMod<P>, P>;
export type ItemExtern<P extends Phase> = ItemVariant<ItemKindExtern, P>;
export type ItemGlobal<P extends Phase> = ItemVariant<ItemKindGlobal<P>, P>;
export type ItemUse<P extends Phase> = ItemVariant<ItemKindUse<P>, P>;
export type ItemError<P extends Phase> = ItemVariant<ItemKindError, P>;
export type Item<P extends Phase> = ItemKind<P> & {
@ -183,6 +185,11 @@ export type ItemKindGlobal<P extends Phase> = {
ty?: Ty;
};
export type ItemKindUse<P extends Phase> = {
kind: "use";
segments: Ident[];
} & P["res"];
export type ItemKindError = {
kind: "error";
err: ErrorEmitted;
@ -448,7 +455,7 @@ export type Resolution =
* ```
* When traversing resolutions, a stack of locals has to be kept.
* It's similar to a De Bruijn index.
*
*
* You generally want to index the stack as stack[stack.len - 1 - res.idx].
*/
index: number;
@ -652,6 +659,9 @@ export function superFoldItem<From extends Phase, To extends Phase>(
init: folder.expr(item.init),
};
}
case "use": {
return { ...item };
}
case "error": {
return { ...item };
}

View file

@ -209,6 +209,7 @@ export function lower(gcx: GlobalContext): wasm.Module {
}
case "extern":
case "type":
case "use":
break;
case "error":
unreachable("codegen should never see errors");

View file

@ -20,6 +20,7 @@ export type DatalessToken =
| "mod"
| "global"
| "struct"
| "use"
| "("
| ")"
| "{"
@ -364,6 +365,7 @@ const KEYOWRDS: DatalessToken[] = [
"mod",
"global",
"struct",
"use",
];
const KEYWORD_SET = new Set<string>(KEYOWRDS);

View file

@ -27,6 +27,7 @@ import {
ItemGlobal,
StructLiteralField,
TypeDefKind,
ItemUse,
} from "./ast";
import { GlobalContext } from "./context";
import { CompilerError, ErrorEmitted, LoadedFile, Span } from "./error";
@ -293,6 +294,33 @@ function parseItem(t: State): [State, Item<Parsed>] {
id: ItemId.dummy(),
};
return [t, global];
} else if (tok.kind === "use") {
let ident;
[t, ident] = expectNext<TokenIdent>(t, "identifier");
const segments: Ident[] = [{ name: ident.ident, span: ident.span }];
while (true) {
let semi;
[t, semi] = eat(t, ".");
if (!semi) {
break;
}
[t, ident] = expectNext<TokenIdent>(t, "identifier");
segments.push({ name: ident.ident, span: ident.span });
}
[t] = expectNext(t, ";");
const use: ItemUse<Parsed> = {
kind: "use",
name: segments[segments.length - 1].name,
segments,
span: tok.span,
id: ItemId.dummy(),
};
return [t, use];
} else {
unexpectedToken(t, tok, "item");
}

View file

@ -12,7 +12,7 @@ import {
Type,
ItemType,
} from "./ast";
import { Ty, substituteTy, tyIsUnit } from "./types";
import { Ty, tyIsUnit } from "./types";
export function printAst(ast: Pkg<AnyPhase>): string {
return ast.rootItems.map(printItem).join("\n");
@ -50,6 +50,9 @@ function printItem(item: Item<AnyPhase>): string {
)};`
);
}
case "use": {
return id + `use ${item.segments.map((ident) => ident.name).join(".")};`;
}
case "error":
return "<ERROR>";
}
@ -57,7 +60,7 @@ function printItem(item: Item<AnyPhase>): string {
function printFunction(func: ItemFunction<AnyPhase>): string {
const args = func.params
.map(({ ident: name, type }) => `${name}: ${printType(type)}`)
.map(({ ident: name, type }) => `${name.name}: ${printType(type)}`)
.join(", ");
const ret = func.returnType ? `: ${printType(func.returnType)}` : "";
return `function ${func.name}(${args})${ret} = ${printExpr(func.body, 0)};`;
@ -89,7 +92,7 @@ function printTypeDef(type: ItemType<AnyPhase>): string {
function printImportDef(def: ItemImport<AnyPhase>): string {
const args = def.params
.map(({ ident: name, type }) => `${name}: ${printType(type)}`)
.map(({ ident: name, type }) => `${name.name}: ${printType(type)}`)
.join(", ");
const ret = def.returnType ? `: ${printType(def.returnType)}` : "";

View file

@ -99,7 +99,14 @@ function resolveModule(
),
);
} else {
items.set(item.name, item.id);
// TODO: This is awful
if (item.kind === "use") {
cx.gcx.error.emitError(
new CompilerError("TODO: use is not properly implemented", item.span),
);
} else {
items.set(item.name, item.id);
}
}
});

View file

@ -162,6 +162,9 @@ export function typeck(gcx: GlobalContext, ast: Pkg<Resolved>): Pkg<Typecked> {
init: initChecked,
};
}
case "use": {
return { ...item };
}
case "error": {
return { ...item };
}

View file

@ -152,6 +152,7 @@ function itemGenerics(item: Item<Typecked> | Item<Resolved>): Generics {
case "global":
case "mod":
case "import":
case "use":
return none;
case "type":
return { kind: "some", params: item.genericParams };
@ -275,6 +276,11 @@ export function typeOfItem(cx: TypeckCtx, itemId: ItemId, cause: Span): Ty {
ty = lowerAstTy(cx, item.type);
break;
}
case "use": {
// TODO: use the power of typescript to eliminate `use` from this.
ty = TYS.UNIT;
break;
}
case "error": {
ty = tyErrorFrom(item);
}

View file

@ -1,3 +1,3 @@
function main() = (
let _l = list.new();
let _false, l = list.new();
);