mirror of
https://github.com/Noratrieb/riverdelta.git
synced 2026-01-14 16:35:03 +01:00
fix generics and stuff
This commit is contained in:
parent
537c924a68
commit
1a0828bd32
8 changed files with 63 additions and 63 deletions
62
src/ast.ts
62
src/ast.ts
|
|
@ -411,10 +411,6 @@ export type TypeKind<P extends Phase> =
|
|||
generics: Type<P>[];
|
||||
value: IdentWithRes<P>;
|
||||
}
|
||||
| {
|
||||
kind: "list";
|
||||
elem: Type<P>;
|
||||
}
|
||||
| {
|
||||
kind: "tuple";
|
||||
elems: Type<P>[];
|
||||
|
|
@ -517,11 +513,6 @@ export type TyBool = {
|
|||
kind: "bool";
|
||||
};
|
||||
|
||||
export type TyList = {
|
||||
kind: "list";
|
||||
elem: Ty;
|
||||
};
|
||||
|
||||
export type TyTuple = {
|
||||
kind: "tuple";
|
||||
elems: Ty[];
|
||||
|
|
@ -549,7 +540,7 @@ export type TyStruct = {
|
|||
params: string[];
|
||||
args: Ty[];
|
||||
_name: string;
|
||||
fields: [string, Ty][];
|
||||
fields_no_subst: [string, Ty][];
|
||||
};
|
||||
|
||||
export type TyRawPtr = {
|
||||
|
|
@ -582,7 +573,6 @@ export type Ty =
|
|||
| TyInt
|
||||
| TyI32
|
||||
| TyBool
|
||||
| TyList
|
||||
| TyTuple
|
||||
| TyFn
|
||||
| TyVar
|
||||
|
|
@ -607,6 +597,49 @@ export type TypeckResults = {
|
|||
main: Resolution | undefined;
|
||||
};
|
||||
|
||||
export function structFieldsSubstituted(ty: TyStruct): [string, Ty][] {
|
||||
const args = ty.args;
|
||||
return ty.fields_no_subst.map(([name, type]) => [
|
||||
name,
|
||||
substituteTy(args, type),
|
||||
]);
|
||||
}
|
||||
|
||||
// Substitute the parameter of a type. We are only able to handle one
|
||||
// level of generic definitions, for example for fields the struct def or for exprs the function generics.
|
||||
export function substituteTy(params: Ty[], ty: Ty): Ty {
|
||||
const subst = (ty: Ty) => substituteTy(params, ty);
|
||||
|
||||
switch (ty.kind) {
|
||||
case "param":
|
||||
return params[ty.idx];
|
||||
case "tuple":
|
||||
return { ...ty, elems: ty.elems.map(subst) };
|
||||
case "fn":
|
||||
return {
|
||||
...ty,
|
||||
returnTy: subst(ty.returnTy),
|
||||
params: ty.params.map(subst),
|
||||
};
|
||||
case "struct":
|
||||
return {
|
||||
...ty,
|
||||
args: ty.args.map(subst),
|
||||
};
|
||||
case "rawptr":
|
||||
return { ...ty, inner: subst(ty.inner) };
|
||||
// Primitives
|
||||
case "var":
|
||||
case "string":
|
||||
case "int":
|
||||
case "i32":
|
||||
case "bool":
|
||||
case "never":
|
||||
case "error":
|
||||
return ty;
|
||||
}
|
||||
}
|
||||
|
||||
// folders
|
||||
|
||||
export type FoldFn<From, To> = (value: From) => To;
|
||||
|
|
@ -894,13 +927,6 @@ export function superFoldType<From extends Phase, To extends Phase>(
|
|||
span,
|
||||
};
|
||||
}
|
||||
case "list": {
|
||||
return {
|
||||
kind: "list",
|
||||
elem: folder.type(type.elem),
|
||||
span,
|
||||
};
|
||||
}
|
||||
case "tuple": {
|
||||
return {
|
||||
kind: "tuple",
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ it("should compute struct layout correctly", () => {
|
|||
args: [],
|
||||
params: [],
|
||||
_name: "",
|
||||
fields: [
|
||||
fields_no_subst: [
|
||||
["uwu", TY_I32],
|
||||
["owo", TY_INT],
|
||||
],
|
||||
|
|
@ -55,7 +55,7 @@ it("should compute single field struct layout correctly", () => {
|
|||
args: [],
|
||||
params: [],
|
||||
_name: "",
|
||||
fields: [["owo", TY_INT]],
|
||||
fields_no_subst: [["owo", TY_INT]],
|
||||
};
|
||||
|
||||
const layout = layoutOfStruct(ty);
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import {
|
|||
varUnreachable,
|
||||
TyRawPtr,
|
||||
paramUnreachable,
|
||||
structFieldsSubstituted,
|
||||
} from "./ast";
|
||||
import { GlobalContext } from "./context";
|
||||
import { unreachable } from "./error";
|
||||
|
|
@ -1247,8 +1248,6 @@ function argRetAbi(param: Ty): ArgRetAbi {
|
|||
return ["i32"];
|
||||
case "bool":
|
||||
return ["i32"];
|
||||
case "list":
|
||||
todo("list abi");
|
||||
case "tuple":
|
||||
return param.elems.flatMap(argRetAbi);
|
||||
case "struct":
|
||||
|
|
@ -1304,8 +1303,6 @@ function wasmTypeForBody(ty: Ty): wasm.ValType[] {
|
|||
return ["i32"];
|
||||
case "bool":
|
||||
return ["i32"];
|
||||
case "list":
|
||||
todo("list types");
|
||||
case "tuple":
|
||||
return ty.elems.flatMap(wasmTypeForBody);
|
||||
case "fn":
|
||||
|
|
@ -1344,7 +1341,8 @@ export function layoutOfStruct(ty_: TyStruct | TyRawPtr): StructLayout {
|
|||
if (ty.kind !== "struct") {
|
||||
unreachable("must be struct");
|
||||
}
|
||||
const fieldWasmTys = ty.fields.map(([, field]) => wasmTypeForBody(field));
|
||||
const fieldTys = structFieldsSubstituted(ty).map(([_, ty]) => ty);
|
||||
const fieldWasmTys = fieldTys.map((field) => wasmTypeForBody(field));
|
||||
|
||||
// TODO: Use the max alignment instead.
|
||||
const align = fieldWasmTys.some((field) =>
|
||||
|
|
@ -1359,7 +1357,7 @@ export function layoutOfStruct(ty_: TyStruct | TyRawPtr): StructLayout {
|
|||
const fields: StructFieldLayout[] = fieldWasmTys.map((field, i) => {
|
||||
const value: StructFieldLayout = {
|
||||
types: [],
|
||||
ty: ty.fields[i][1],
|
||||
ty: fieldTys[i],
|
||||
};
|
||||
|
||||
const types = field.map((type) => {
|
||||
|
|
@ -1457,8 +1455,6 @@ function needsRefcount(ty: Ty): StructLayout | "string" | undefined {
|
|||
return undefined;
|
||||
case "struct":
|
||||
return layoutOfStruct(ty);
|
||||
case "list":
|
||||
todo("no lists yet");
|
||||
case "var":
|
||||
varUnreachable();
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -700,12 +700,6 @@ function parseType(t: State): [State, Type<Parsed>] {
|
|||
},
|
||||
];
|
||||
}
|
||||
case "[": {
|
||||
let elem;
|
||||
[t, elem] = parseType(t);
|
||||
[t] = expectNext(t, "]");
|
||||
return [t, { kind: "list", elem, span }];
|
||||
}
|
||||
case "(": {
|
||||
// `()` is a the unit type, an empty tuple.
|
||||
// `(T)` is just `T`
|
||||
|
|
|
|||
|
|
@ -219,8 +219,6 @@ function printType(type: Type<AnyPhase>): string {
|
|||
switch (type.kind) {
|
||||
case "ident":
|
||||
return printIdent(type.value);
|
||||
case "list":
|
||||
return `[${printType(type.elem)}]`;
|
||||
case "tuple":
|
||||
return `(${type.elems.map(printType).join(", ")})`;
|
||||
case "rawptr":
|
||||
|
|
@ -269,9 +267,6 @@ export function printTy(ty: Ty): string {
|
|||
case "bool": {
|
||||
return "Bool";
|
||||
}
|
||||
case "list": {
|
||||
return `[${printTy(ty.elem)}]`;
|
||||
}
|
||||
case "tuple": {
|
||||
return `(${ty.elems.map(printTy).join(", ")})`;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -183,12 +183,6 @@ function lowerAstTy(cx: TypeckCtx, type: Type<Resolved>): Ty {
|
|||
|
||||
return ty;
|
||||
}
|
||||
case "list": {
|
||||
return {
|
||||
kind: "list",
|
||||
elem: lowerAstTy(cx, type.elem),
|
||||
};
|
||||
}
|
||||
case "tuple": {
|
||||
return {
|
||||
kind: "tuple",
|
||||
|
|
@ -286,7 +280,7 @@ function typeOfItem(cx: TypeckCtx, itemId: ItemId, cause: Span): Ty {
|
|||
params: item.generics.map((ident) => ident.name),
|
||||
itemId: item.id,
|
||||
_name: item.name,
|
||||
fields: [
|
||||
fields_no_subst: [
|
||||
/*dummy*/
|
||||
],
|
||||
};
|
||||
|
|
@ -297,7 +291,7 @@ function typeOfItem(cx: TypeckCtx, itemId: ItemId, cause: Span): Ty {
|
|||
({ name, type }) => [name.name, lowerAstTy(cx, type)],
|
||||
);
|
||||
|
||||
ty.fields = fields;
|
||||
ty.fields_no_subst = fields;
|
||||
break;
|
||||
}
|
||||
case "alias": {
|
||||
|
|
@ -667,13 +661,6 @@ export class InferContext {
|
|||
if (rhs.kind === "bool") return;
|
||||
break;
|
||||
}
|
||||
case "list": {
|
||||
if (rhs.kind === "list") {
|
||||
this.assign(lhs.elem, rhs.elem, span);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "tuple": {
|
||||
if (rhs.kind === "tuple" && lhs.elems.length === rhs.elems.length) {
|
||||
lhs.elems.forEach((lhs, i) => this.assign(lhs, rhs.elems[i], span));
|
||||
|
|
@ -953,7 +940,7 @@ export function checkBody(
|
|||
case "rawptr": {
|
||||
let fields: [string, Ty][];
|
||||
if (lhs.ty.kind === "struct") {
|
||||
fields = lhs.ty.fields;
|
||||
fields = lhs.ty.fields_no_subst;
|
||||
} else if (lhs.ty.kind === "rawptr") {
|
||||
let inner = fcx.infcx.resolveIfPossible(lhs.ty.inner);
|
||||
if (inner.kind !== "struct") {
|
||||
|
|
@ -967,7 +954,7 @@ export function checkBody(
|
|||
ty = inner;
|
||||
break;
|
||||
} else {
|
||||
fields = inner.fields;
|
||||
fields = inner.fields_no_subst;
|
||||
}
|
||||
} else {
|
||||
fields = [];
|
||||
|
|
@ -1100,7 +1087,7 @@ export function checkBody(
|
|||
const assignedFields = new Set();
|
||||
|
||||
fields.forEach(({ name, expr: field }, i) => {
|
||||
const fieldIdx = structTy.fields.findIndex(
|
||||
const fieldIdx = structTy.fields_no_subst.findIndex(
|
||||
(def) => def[0] === name.name,
|
||||
);
|
||||
if (fieldIdx == -1) {
|
||||
|
|
@ -1112,14 +1099,14 @@ export function checkBody(
|
|||
),
|
||||
);
|
||||
}
|
||||
const fieldTy = structTy.fields[fieldIdx];
|
||||
const fieldTy = structTy.fields_no_subst[fieldIdx];
|
||||
infcx.assign(fieldTy[1], field.ty, field.span);
|
||||
assignedFields.add(name.name);
|
||||
fields[i].fieldIdx = fieldIdx;
|
||||
});
|
||||
|
||||
const missing: string[] = [];
|
||||
structTy.fields.forEach(([name]) => {
|
||||
structTy.fields_no_subst.forEach(([name]) => {
|
||||
if (!assignedFields.has(name)) {
|
||||
missing.push(name);
|
||||
}
|
||||
|
|
|
|||
10
test.nil
10
test.nil
|
|
@ -1,4 +1,6 @@
|
|||
function main() = (
|
||||
let list = std.list.new();
|
||||
std.list.push(list, 0);
|
||||
);
|
||||
//@check-pass
|
||||
type A[T] = struct { a: T };
|
||||
|
||||
function main() = ;
|
||||
|
||||
function test(a: A[I32]) = ;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue