mirror of
https://github.com/Noratrieb/riverdelta.git
synced 2026-01-14 16:35:03 +01:00
allocators and type aliases
This commit is contained in:
parent
60c743d656
commit
f05e5520f3
16 changed files with 283 additions and 121 deletions
36
src/ast.ts
36
src/ast.ts
|
|
@ -144,10 +144,20 @@ export type FunctionArg<P extends Phase> = {
|
|||
|
||||
export type TypeDef<P extends Phase> = {
|
||||
name: string;
|
||||
fields: FieldDef<P>[];
|
||||
type: TypeDefKind<P>;
|
||||
ty?: TyStruct;
|
||||
};
|
||||
|
||||
export type TypeDefKind<P extends Phase> =
|
||||
| {
|
||||
kind: "struct";
|
||||
fields: FieldDef<P>[];
|
||||
}
|
||||
| {
|
||||
kind: "alias";
|
||||
type: Type<P>;
|
||||
};
|
||||
|
||||
export type FieldDef<P extends Phase> = {
|
||||
name: Ident;
|
||||
type: Type<P>;
|
||||
|
|
@ -624,15 +634,29 @@ export function superFoldItem<From extends Phase, To extends Phase>(
|
|||
};
|
||||
}
|
||||
case "type": {
|
||||
const fields = item.node.fields.map(({ name, type }) => ({
|
||||
name,
|
||||
type: folder.type(type),
|
||||
}));
|
||||
const typeKind = item.node.type;
|
||||
let type: TypeDefKind<To>;
|
||||
switch (typeKind.kind) {
|
||||
case "struct": {
|
||||
const fields = typeKind.fields.map(({ name, type }) => ({
|
||||
name,
|
||||
type: folder.type(type),
|
||||
}));
|
||||
type = { kind: "struct", fields };
|
||||
break;
|
||||
}
|
||||
case "alias": {
|
||||
type = {
|
||||
kind: "alias",
|
||||
type: folder.type(typeKind.type),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
...item,
|
||||
kind: "type",
|
||||
node: { name: item.node.name, fields },
|
||||
node: { name: item.node.name, type },
|
||||
};
|
||||
}
|
||||
case "import": {
|
||||
|
|
|
|||
|
|
@ -36,8 +36,8 @@ const WASM_PAGE = 65536;
|
|||
|
||||
const DUMMY_IDX = 9999999;
|
||||
|
||||
const ALLOCATE_ITEM: string[] = ["std", "rt", "allocateItem"];
|
||||
const DEALLOCATE_ITEM: string[] = ["std", "rt", "deallocateItem"];
|
||||
const ALLOCATE_ITEM: string[] = ["std", "rt", "alloc", "allocateItem"];
|
||||
const DEALLOCATE_ITEM: string[] = ["std", "rt", "alloc", "deallocateItem"];
|
||||
|
||||
type RelocationKind =
|
||||
| {
|
||||
|
|
|
|||
|
|
@ -79,7 +79,11 @@ export function parseArgs(hardcodedInput: string): Options {
|
|||
}
|
||||
|
||||
input = fs.readFileSync(filename, { encoding: "utf-8" });
|
||||
packageName = path.basename(filename, ".nil");
|
||||
if (filename.endsWith(".mod.nil")) {
|
||||
packageName = path.basename(filename, ".mod.nil");
|
||||
} else {
|
||||
packageName = path.basename(filename, ".nil");
|
||||
}
|
||||
|
||||
const debugArg = process.argv.find((arg) => arg.startsWith("--debug="));
|
||||
if (debugArg !== undefined) {
|
||||
|
|
|
|||
13
src/index.ts
13
src/index.ts
|
|
@ -13,9 +13,14 @@ import { GlobalContext, parseArgs } from "./context";
|
|||
import { loadCrate } from "./loader";
|
||||
|
||||
const INPUT = `
|
||||
type A = { a: Int };
|
||||
type A = struct { a: Int };
|
||||
|
||||
type What = What;
|
||||
|
||||
type Uwu = (Int, Int);
|
||||
|
||||
function main() = (
|
||||
let a: What = 0;
|
||||
uwu();
|
||||
);
|
||||
|
||||
|
|
@ -28,7 +33,7 @@ function uwu() = (
|
|||
/*-1*/
|
||||
);
|
||||
|
||||
type B = {
|
||||
type B = struct {
|
||||
a: (Int, Int, Int, Int, Int),
|
||||
};
|
||||
|
||||
|
|
@ -59,7 +64,9 @@ function main() {
|
|||
() => {
|
||||
const start = Date.now();
|
||||
|
||||
gcx.crateLoader(gcx, "std", Span.startOfFile(file));
|
||||
if (packageName !== "std") {
|
||||
gcx.crateLoader(gcx, "std", Span.startOfFile(file));
|
||||
}
|
||||
|
||||
const tokens = tokenize(file);
|
||||
if (debug.has("tokens")) {
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ export type DatalessToken =
|
|||
| "extern"
|
||||
| "mod"
|
||||
| "global"
|
||||
| "struct"
|
||||
| "("
|
||||
| ")"
|
||||
| "{"
|
||||
|
|
@ -323,6 +324,7 @@ const KEYOWRDS: DatalessToken[] = [
|
|||
"extern",
|
||||
"mod",
|
||||
"global",
|
||||
"struct",
|
||||
];
|
||||
|
||||
const KEYWORD_SET = new Set<string>(KEYOWRDS);
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import {
|
|||
ItemId,
|
||||
GlobalItem,
|
||||
StructLiteralField,
|
||||
TypeDefKind,
|
||||
} from "./ast";
|
||||
import { CompilerError, LoadedFile, Span } from "./error";
|
||||
import {
|
||||
|
|
@ -107,32 +108,46 @@ function parseItem(t: State): [State, Item<Parsed>] {
|
|||
let name;
|
||||
[t, name] = expectNext<TokenIdent>(t, "identifier");
|
||||
[t] = expectNext(t, "=");
|
||||
[t] = expectNext(t, "{");
|
||||
|
||||
let fields;
|
||||
[t, fields] = parseCommaSeparatedList<FieldDef<Parsed>>(t, "}", (t) => {
|
||||
let name;
|
||||
[t, name] = expectNext<TokenIdent>(t, "identifier");
|
||||
[t] = expectNext(t, ":");
|
||||
let type;
|
||||
[t, type] = parseType(t);
|
||||
return [
|
||||
t,
|
||||
{
|
||||
name: {
|
||||
name: name.ident,
|
||||
span: name.span,
|
||||
let type: TypeDefKind<Parsed>;
|
||||
|
||||
let struct;
|
||||
[t, struct] = eat(t, "struct");
|
||||
if (struct) {
|
||||
[t] = expectNext(t, "{");
|
||||
|
||||
let fields;
|
||||
[t, fields] = parseCommaSeparatedList<FieldDef<Parsed>>(t, "}", (t) => {
|
||||
let name;
|
||||
[t, name] = expectNext<TokenIdent>(t, "identifier");
|
||||
[t] = expectNext(t, ":");
|
||||
let type;
|
||||
[t, type] = parseType(t);
|
||||
return [
|
||||
t,
|
||||
{
|
||||
name: {
|
||||
name: name.ident,
|
||||
span: name.span,
|
||||
},
|
||||
type,
|
||||
},
|
||||
type,
|
||||
},
|
||||
];
|
||||
});
|
||||
];
|
||||
});
|
||||
|
||||
type = { kind: "struct", fields };
|
||||
} else {
|
||||
let aliased: Type<Parsed>;
|
||||
[t, aliased] = parseType(t);
|
||||
|
||||
type = { kind: "alias", type: aliased };
|
||||
}
|
||||
|
||||
[t] = expectNext(t, ";");
|
||||
|
||||
const def: TypeDef<Parsed> = {
|
||||
name: name.ident,
|
||||
fields,
|
||||
type,
|
||||
};
|
||||
|
||||
return [
|
||||
|
|
|
|||
|
|
@ -63,14 +63,22 @@ function printFunction(func: FunctionDef<AnyPhase>): string {
|
|||
}
|
||||
|
||||
function printTypeDef(type: TypeDef<AnyPhase>): string {
|
||||
const fields = type.fields.map(
|
||||
({ name, type }) => `${ind(1)}${name.name}: ${printType(type)},`,
|
||||
);
|
||||
switch (type.type.kind) {
|
||||
case "struct": {
|
||||
const { fields } = type.type;
|
||||
|
||||
const fieldPart =
|
||||
type.fields.length === 0 ? "{}" : `{\n${fields.join("\n")}\n}`;
|
||||
const fieldStr = fields.map(
|
||||
({ name, type }) => `${ind(1)}${name.name}: ${printType(type)},`,
|
||||
);
|
||||
const fieldPart =
|
||||
fields.length === 0 ? "{}" : `{\n${fieldStr.join("\n")}\n}`;
|
||||
|
||||
return `type ${type.name} = ${fieldPart};`;
|
||||
return `type ${type.name} = ${fieldPart};`;
|
||||
}
|
||||
case "alias": {
|
||||
return `type ${type.name} = ${printType(type.type.type)}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function printImportDef(def: ImportDef<AnyPhase>): string {
|
||||
|
|
|
|||
|
|
@ -175,23 +175,29 @@ export function typeck(
|
|||
return ty;
|
||||
}
|
||||
case "type": {
|
||||
const ty: Ty = {
|
||||
kind: "struct",
|
||||
name: item.node.name,
|
||||
fields: [
|
||||
/*dummy*/
|
||||
],
|
||||
};
|
||||
switch (item.node.type.kind) {
|
||||
case "struct": {
|
||||
const ty: Ty = {
|
||||
kind: "struct",
|
||||
name: item.node.name,
|
||||
fields: [
|
||||
/*dummy*/
|
||||
],
|
||||
};
|
||||
|
||||
itemTys.set(item.id, ty);
|
||||
itemTys.set(item.id, ty);
|
||||
|
||||
const fields = item.node.fields.map<[string, Ty]>(({ name, type }) => [
|
||||
name.name,
|
||||
lowerAstTy(type),
|
||||
]);
|
||||
const fields = item.node.type.fields.map<[string, Ty]>(
|
||||
({ name, type }) => [name.name, lowerAstTy(type)],
|
||||
);
|
||||
|
||||
ty.fields = fields;
|
||||
return ty;
|
||||
ty.fields = fields;
|
||||
return ty;
|
||||
}
|
||||
case "alias": {
|
||||
return lowerAstTy(item.node.type.type);
|
||||
}
|
||||
}
|
||||
}
|
||||
case "mod": {
|
||||
throw new CompilerError(
|
||||
|
|
@ -313,32 +319,51 @@ export function typeck(
|
|||
};
|
||||
}
|
||||
case "type": {
|
||||
const fieldNames = new Set();
|
||||
item.node.fields.forEach(({ name }) => {
|
||||
if (fieldNames.has(name)) {
|
||||
throw new CompilerError(
|
||||
`type ${item.node.name} has a duplicate field: ${name.name}`,
|
||||
name.span,
|
||||
);
|
||||
}
|
||||
fieldNames.add(name);
|
||||
});
|
||||
switch (item.node.type.kind) {
|
||||
case "struct": {
|
||||
const fieldNames = new Set();
|
||||
item.node.type.fields.forEach(({ name }) => {
|
||||
if (fieldNames.has(name)) {
|
||||
throw new CompilerError(
|
||||
`type ${item.node.name} has a duplicate field: ${name.name}`,
|
||||
name.span,
|
||||
);
|
||||
}
|
||||
fieldNames.add(name);
|
||||
});
|
||||
|
||||
const ty = typeOfItem(item.id, item.span) as TyStruct;
|
||||
const ty = typeOfItem(item.id, item.span) as TyStruct;
|
||||
|
||||
return {
|
||||
...item,
|
||||
node: {
|
||||
name: item.node.name,
|
||||
fields: item.node.fields.map((field, i) => ({
|
||||
name: field.name,
|
||||
type: {
|
||||
...field.type,
|
||||
ty: ty.fields[i][1],
|
||||
return {
|
||||
...item,
|
||||
node: {
|
||||
name: item.node.name,
|
||||
type: {
|
||||
kind: "struct",
|
||||
fields: item.node.type.fields.map((field, i) => ({
|
||||
name: field.name,
|
||||
type: {
|
||||
...field.type,
|
||||
ty: ty.fields[i][1],
|
||||
},
|
||||
})),
|
||||
},
|
||||
},
|
||||
})),
|
||||
},
|
||||
};
|
||||
};
|
||||
}
|
||||
case "alias": {
|
||||
return {
|
||||
...item,
|
||||
node: {
|
||||
name: item.node.name,
|
||||
type: {
|
||||
kind: "alias",
|
||||
type: item.node.type.type,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
case "mod": {
|
||||
return {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue