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

View file

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

View file

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

View file

@ -27,6 +27,7 @@ import {
ItemGlobal, ItemGlobal,
StructLiteralField, StructLiteralField,
TypeDefKind, TypeDefKind,
ItemUse,
} from "./ast"; } from "./ast";
import { GlobalContext } from "./context"; import { GlobalContext } from "./context";
import { CompilerError, ErrorEmitted, LoadedFile, Span } from "./error"; import { CompilerError, ErrorEmitted, LoadedFile, Span } from "./error";
@ -293,6 +294,33 @@ function parseItem(t: State): [State, Item<Parsed>] {
id: ItemId.dummy(), id: ItemId.dummy(),
}; };
return [t, global]; 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 { } else {
unexpectedToken(t, tok, "item"); unexpectedToken(t, tok, "item");
} }

View file

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

View file

@ -99,7 +99,14 @@ function resolveModule(
), ),
); );
} else { } 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, init: initChecked,
}; };
} }
case "use": {
return { ...item };
}
case "error": { case "error": {
return { ...item }; return { ...item };
} }

View file

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

View file

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