mirror of
https://github.com/Noratrieb/riverdelta.git
synced 2026-01-14 16:35:03 +01:00
move ty defs
This commit is contained in:
parent
a22cc15b59
commit
d18ab34e9f
14 changed files with 173 additions and 192 deletions
156
src/ast.ts
156
src/ast.ts
|
|
@ -1,5 +1,6 @@
|
||||||
import { ErrorEmitted, LoadedFile, Span, unreachable } from "./error";
|
import { ErrorEmitted, LoadedFile, Span, unreachable } from "./error";
|
||||||
import { LitIntType } from "./lexer";
|
import { LitIntType } from "./lexer";
|
||||||
|
import { Ty, TyFn, TypeckResults } from "./types";
|
||||||
import { ComplexMap } from "./utils";
|
import { ComplexMap } from "./utils";
|
||||||
import { Instr, ValType } from "./wasm/defs";
|
import { Instr, ValType } from "./wasm/defs";
|
||||||
|
|
||||||
|
|
@ -507,161 +508,6 @@ export type LocalInfo = {
|
||||||
|
|
||||||
// types
|
// types
|
||||||
|
|
||||||
export type TyString = {
|
|
||||||
kind: "string";
|
|
||||||
};
|
|
||||||
|
|
||||||
export type TyInt = {
|
|
||||||
kind: "int";
|
|
||||||
};
|
|
||||||
|
|
||||||
export type TyI32 = {
|
|
||||||
kind: "i32";
|
|
||||||
};
|
|
||||||
|
|
||||||
export type TyBool = {
|
|
||||||
kind: "bool";
|
|
||||||
};
|
|
||||||
|
|
||||||
export type TyTuple = {
|
|
||||||
kind: "tuple";
|
|
||||||
elems: Ty[];
|
|
||||||
};
|
|
||||||
|
|
||||||
export type TyUnit = {
|
|
||||||
kind: "tuple";
|
|
||||||
elems: [];
|
|
||||||
};
|
|
||||||
|
|
||||||
export type TyFn = {
|
|
||||||
kind: "fn";
|
|
||||||
params: Ty[];
|
|
||||||
returnTy: Ty;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type TyVar = {
|
|
||||||
kind: "var";
|
|
||||||
index: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type TyStruct = {
|
|
||||||
kind: "struct";
|
|
||||||
itemId: ItemId;
|
|
||||||
params: string[];
|
|
||||||
genericArgs: Ty[];
|
|
||||||
_name: string;
|
|
||||||
fields_no_subst: [string, Ty][];
|
|
||||||
};
|
|
||||||
|
|
||||||
export type TyRawPtr = {
|
|
||||||
kind: "rawptr";
|
|
||||||
inner: Ty;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type TyNever = {
|
|
||||||
kind: "never";
|
|
||||||
};
|
|
||||||
|
|
||||||
export type TyParam = {
|
|
||||||
kind: "param";
|
|
||||||
/**
|
|
||||||
* The index of the type parameter of the parent.
|
|
||||||
* If the parent is `type A[T, U] = U;`
|
|
||||||
* then `U` will have index 1.
|
|
||||||
*/
|
|
||||||
idx: number;
|
|
||||||
name: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type TyAlias = {
|
|
||||||
kind: "alias";
|
|
||||||
actual: Ty;
|
|
||||||
genericArgs: Ty[];
|
|
||||||
params: string[];
|
|
||||||
};
|
|
||||||
|
|
||||||
export type TyError = {
|
|
||||||
kind: "error";
|
|
||||||
err: ErrorEmitted;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type Ty =
|
|
||||||
| TyString
|
|
||||||
| TyInt
|
|
||||||
| TyI32
|
|
||||||
| TyBool
|
|
||||||
| TyTuple
|
|
||||||
| TyFn
|
|
||||||
| TyVar
|
|
||||||
| TyStruct
|
|
||||||
| TyRawPtr
|
|
||||||
| TyNever
|
|
||||||
| TyParam
|
|
||||||
| TyAlias
|
|
||||||
| TyError;
|
|
||||||
|
|
||||||
export function tyIsUnit(ty: Ty): ty is TyUnit {
|
|
||||||
return ty.kind === "tuple" && ty.elems.length === 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const TY_UNIT: Ty = { kind: "tuple", elems: [] };
|
|
||||||
export const TY_STRING: Ty = { kind: "string" };
|
|
||||||
export const TY_BOOL: Ty = { kind: "bool" };
|
|
||||||
export const TY_INT: Ty = { kind: "int" };
|
|
||||||
export const TY_I32: Ty = { kind: "i32" };
|
|
||||||
export const TY_NEVER: Ty = { kind: "never" };
|
|
||||||
|
|
||||||
export type TypeckResults = {
|
|
||||||
main: Resolution | undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
export function structFieldsSubstituted(ty: TyStruct): [string, Ty][] {
|
|
||||||
const args = ty.genericArgs;
|
|
||||||
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(genericArgs: Ty[], ty: Ty): Ty {
|
|
||||||
const subst = (ty: Ty) => substituteTy(genericArgs, ty);
|
|
||||||
switch (ty.kind) {
|
|
||||||
case "param":
|
|
||||||
if (ty.idx >= genericArgs.length) {
|
|
||||||
throw new Error(
|
|
||||||
`substitution out of range, param index ${ty.idx} of param ${ty.name} out of range for length ${genericArgs.length}`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return genericArgs[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":
|
|
||||||
case "alias":
|
|
||||||
return {
|
|
||||||
...ty,
|
|
||||||
genericArgs: ty.genericArgs.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
|
// folders
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { ItemId, TY_I32, TY_INT, TyStruct } from "./ast";
|
import { ItemId } from "./ast";
|
||||||
import { layoutOfStruct } from "./codegen";
|
import { layoutOfStruct } from "./codegen";
|
||||||
|
import { TY_I32, TY_INT, TyStruct } from "./types";
|
||||||
|
|
||||||
it("should compute struct layout correctly", () => {
|
it("should compute struct layout correctly", () => {
|
||||||
const ty: TyStruct = {
|
const ty: TyStruct = {
|
||||||
|
|
|
||||||
|
|
@ -10,22 +10,17 @@ import {
|
||||||
ItemId,
|
ItemId,
|
||||||
LoopId,
|
LoopId,
|
||||||
Resolution,
|
Resolution,
|
||||||
Ty,
|
|
||||||
TyFn,
|
|
||||||
TyStruct,
|
|
||||||
TyTuple,
|
|
||||||
Typecked,
|
Typecked,
|
||||||
mkDefaultFolder,
|
mkDefaultFolder,
|
||||||
superFoldExpr,
|
superFoldExpr,
|
||||||
superFoldItem,
|
superFoldItem,
|
||||||
varUnreachable,
|
varUnreachable,
|
||||||
TyRawPtr,
|
|
||||||
paramUnreachable as codegenUnreachableTy,
|
paramUnreachable as codegenUnreachableTy,
|
||||||
structFieldsSubstituted,
|
|
||||||
} from "./ast";
|
} from "./ast";
|
||||||
import { GlobalContext } from "./context";
|
import { GlobalContext } from "./context";
|
||||||
import { unreachable } from "./error";
|
import { unreachable } from "./error";
|
||||||
import { printTy } from "./printer";
|
import { printTy } from "./printer";
|
||||||
|
import { Ty, TyFn, TyRawPtr, TyStruct, TyTuple, structFieldsSubstituted } from "./types";
|
||||||
import { ComplexMap, encodeUtf8, unwrap } from "./utils";
|
import { ComplexMap, encodeUtf8, unwrap } from "./utils";
|
||||||
import * as wasm from "./wasm/defs";
|
import * as wasm from "./wasm/defs";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,12 +9,10 @@ import {
|
||||||
ItemMod,
|
ItemMod,
|
||||||
Resolution,
|
Resolution,
|
||||||
StringLiteral,
|
StringLiteral,
|
||||||
Ty,
|
|
||||||
Type,
|
Type,
|
||||||
ItemType,
|
ItemType,
|
||||||
tyIsUnit,
|
|
||||||
substituteTy,
|
|
||||||
} from "./ast";
|
} from "./ast";
|
||||||
|
import { Ty, substituteTy, 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");
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { ItemId, Pkg, Resolved, Ty } from "../ast";
|
import { ItemId, Pkg, Resolved } from "../ast";
|
||||||
import { GlobalContext } from "../context";
|
import { GlobalContext } from "../context";
|
||||||
import { CompilerError, ErrorEmitted } from "../error";
|
import { CompilerError, ErrorEmitted } from "../error";
|
||||||
|
import { Ty } from "../types";
|
||||||
import { ComplexMap } from "../utils";
|
import { ComplexMap } from "../utils";
|
||||||
|
|
||||||
export type TypeckCtx = {
|
export type TypeckCtx = {
|
||||||
|
|
|
||||||
|
|
@ -13,14 +13,6 @@ import {
|
||||||
Resolution,
|
Resolution,
|
||||||
Resolved,
|
Resolved,
|
||||||
StructLiteralField,
|
StructLiteralField,
|
||||||
TY_BOOL,
|
|
||||||
TY_I32,
|
|
||||||
TY_INT,
|
|
||||||
TY_NEVER,
|
|
||||||
TY_STRING,
|
|
||||||
TY_UNIT,
|
|
||||||
Ty,
|
|
||||||
TyFn,
|
|
||||||
Type,
|
Type,
|
||||||
Typecked,
|
Typecked,
|
||||||
mkDefaultFolder,
|
mkDefaultFolder,
|
||||||
|
|
@ -28,6 +20,7 @@ import {
|
||||||
} from "../ast";
|
} from "../ast";
|
||||||
import { CompilerError, ErrorEmitted, Span, unreachable } from "../error";
|
import { CompilerError, ErrorEmitted, Span, unreachable } from "../error";
|
||||||
import { printTy } from "../printer";
|
import { printTy } from "../printer";
|
||||||
|
import { TY_BOOL, TY_I32, TY_INT, TY_NEVER, TY_STRING, TY_UNIT, Ty, TyFn } from "../types";
|
||||||
import { INSTRS, Instr, VALTYPES, ValType } from "../wasm/defs";
|
import { INSTRS, Instr, VALTYPES, ValType } from "../wasm/defs";
|
||||||
import { TypeckCtx, emitError, mkTyFn, tyError, tyErrorFrom } from "./base";
|
import { TypeckCtx, emitError, mkTyFn, tyError, tyErrorFrom } from "./base";
|
||||||
import { InferContext } from "./infer";
|
import { InferContext } from "./infer";
|
||||||
|
|
|
||||||
|
|
@ -5,17 +5,13 @@ import {
|
||||||
Item,
|
Item,
|
||||||
ItemId,
|
ItemId,
|
||||||
Resolved,
|
Resolved,
|
||||||
TY_I32,
|
|
||||||
TY_INT,
|
|
||||||
Ty,
|
|
||||||
TyFn,
|
|
||||||
Typecked,
|
Typecked,
|
||||||
foldAst,
|
foldAst,
|
||||||
mkDefaultFolder,
|
mkDefaultFolder,
|
||||||
tyIsUnit,
|
|
||||||
} from "../ast";
|
} from "../ast";
|
||||||
import { GlobalContext } from "../context";
|
import { GlobalContext } from "../context";
|
||||||
import { CompilerError, ErrorEmitted, Span } from "../error";
|
import { CompilerError, ErrorEmitted, Span } from "../error";
|
||||||
|
import { TY_I32, TY_INT, Ty, TyFn, tyIsUnit } from "../types";
|
||||||
import { ComplexMap } from "../utils";
|
import { ComplexMap } from "../utils";
|
||||||
import { emitError } from "./base";
|
import { emitError } from "./base";
|
||||||
import { checkBody, exprError } from "./expr";
|
import { checkBody, exprError } from "./expr";
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { TY_INT, TY_STRING, TY_UNIT } from "../ast";
|
|
||||||
import { Emitter, ErrorHandler, Span } from "../error";
|
import { Emitter, ErrorHandler, Span } from "../error";
|
||||||
|
import { TY_INT, TY_STRING, TY_UNIT } from "../types";
|
||||||
import { InferContext } from "./infer";
|
import { InferContext } from "./infer";
|
||||||
|
|
||||||
const SPAN: Span = Span.startOfFile({ content: "" });
|
const SPAN: Span = Span.startOfFile({ content: "" });
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { Ty } from "../ast";
|
|
||||||
import { CompilerError, ErrorHandler, Span } from "../error";
|
import { CompilerError, ErrorHandler, Span } from "../error";
|
||||||
import { printTy } from "../printer";
|
import { printTy } from "../printer";
|
||||||
|
import { Ty } from "../types";
|
||||||
|
|
||||||
type TyVarRes =
|
type TyVarRes =
|
||||||
| {
|
| {
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,11 @@
|
||||||
import {
|
import {
|
||||||
ItemId,
|
ItemId,
|
||||||
Resolved,
|
Resolved,
|
||||||
Ty,
|
|
||||||
TY_BOOL,
|
|
||||||
TY_I32,
|
|
||||||
TY_INT,
|
|
||||||
TY_NEVER,
|
|
||||||
TY_STRING,
|
|
||||||
TY_UNIT,
|
|
||||||
Type,
|
Type,
|
||||||
substituteTy,
|
|
||||||
} from "../ast";
|
} from "../ast";
|
||||||
import { CompilerError, Span } from "../error";
|
import { CompilerError, Span } from "../error";
|
||||||
import { printTy } from "../printer";
|
import { printTy } from "../printer";
|
||||||
|
import { TY_BOOL, TY_I32, TY_INT, TY_NEVER, TY_STRING, TY_UNIT, Ty, substituteTy } from "../types";
|
||||||
import { TypeckCtx, tyError, tyErrorFrom } from "./base";
|
import { TypeckCtx, tyError, tyErrorFrom } from "./base";
|
||||||
|
|
||||||
function builtinAsTy(cx: TypeckCtx, name: string, span: Span): Ty {
|
function builtinAsTy(cx: TypeckCtx, name: string, span: Span): Ty {
|
||||||
|
|
|
||||||
158
src/types.ts
Normal file
158
src/types.ts
Normal file
|
|
@ -0,0 +1,158 @@
|
||||||
|
import { ItemId, Resolution } from "./ast";
|
||||||
|
import { ErrorEmitted } from "./error";
|
||||||
|
|
||||||
|
export type TyString = {
|
||||||
|
kind: "string";
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TyInt = {
|
||||||
|
kind: "int";
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TyI32 = {
|
||||||
|
kind: "i32";
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TyBool = {
|
||||||
|
kind: "bool";
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TyTuple = {
|
||||||
|
kind: "tuple";
|
||||||
|
elems: Ty[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TyUnit = {
|
||||||
|
kind: "tuple";
|
||||||
|
elems: [];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TyFn = {
|
||||||
|
kind: "fn";
|
||||||
|
params: Ty[];
|
||||||
|
returnTy: Ty;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TyVar = {
|
||||||
|
kind: "var";
|
||||||
|
index: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TyStruct = {
|
||||||
|
kind: "struct";
|
||||||
|
itemId: ItemId;
|
||||||
|
params: string[];
|
||||||
|
genericArgs: Ty[];
|
||||||
|
_name: string;
|
||||||
|
fields_no_subst: [string, Ty][];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TyRawPtr = {
|
||||||
|
kind: "rawptr";
|
||||||
|
inner: Ty;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TyNever = {
|
||||||
|
kind: "never";
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TyParam = {
|
||||||
|
kind: "param";
|
||||||
|
/**
|
||||||
|
* The index of the type parameter of the parent.
|
||||||
|
* If the parent is `type A[T, U] = U;`
|
||||||
|
* then `U` will have index 1.
|
||||||
|
*/
|
||||||
|
idx: number;
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TyAlias = {
|
||||||
|
kind: "alias";
|
||||||
|
actual: Ty;
|
||||||
|
genericArgs: Ty[];
|
||||||
|
params: string[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type TyError = {
|
||||||
|
kind: "error";
|
||||||
|
err: ErrorEmitted;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Ty =
|
||||||
|
| TyString
|
||||||
|
| TyInt
|
||||||
|
| TyI32
|
||||||
|
| TyBool
|
||||||
|
| TyTuple
|
||||||
|
| TyFn
|
||||||
|
| TyVar
|
||||||
|
| TyStruct
|
||||||
|
| TyRawPtr
|
||||||
|
| TyNever
|
||||||
|
| TyParam
|
||||||
|
| TyAlias
|
||||||
|
| TyError;
|
||||||
|
|
||||||
|
export function tyIsUnit(ty: Ty): ty is TyUnit {
|
||||||
|
return ty.kind === "tuple" && ty.elems.length === 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const TY_UNIT: Ty = { kind: "tuple", elems: [] };
|
||||||
|
export const TY_STRING: Ty = { kind: "string" };
|
||||||
|
export const TY_BOOL: Ty = { kind: "bool" };
|
||||||
|
export const TY_INT: Ty = { kind: "int" };
|
||||||
|
export const TY_I32: Ty = { kind: "i32" };
|
||||||
|
export const TY_NEVER: Ty = { kind: "never" };
|
||||||
|
|
||||||
|
export type TypeckResults = {
|
||||||
|
main: Resolution | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function structFieldsSubstituted(ty: TyStruct): [string, Ty][] {
|
||||||
|
const args = ty.genericArgs;
|
||||||
|
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(genericArgs: Ty[], ty: Ty): Ty {
|
||||||
|
const subst = (ty: Ty) => substituteTy(genericArgs, ty);
|
||||||
|
switch (ty.kind) {
|
||||||
|
case "param":
|
||||||
|
if (ty.idx >= genericArgs.length) {
|
||||||
|
throw new Error(
|
||||||
|
`substitution out of range, param index ${ty.idx} of param ${ty.name} out of range for length ${genericArgs.length}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return genericArgs[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":
|
||||||
|
case "alias":
|
||||||
|
return {
|
||||||
|
...ty,
|
||||||
|
genericArgs: ty.genericArgs.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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -14,4 +14,4 @@ Error: substitution out of range, param index 0 of param T out of range for leng
|
||||||
at Array.map (<anonymous>)
|
at Array.map (<anonymous>)
|
||||||
at foldAst (/home/nils/projects/riverdelta/target/ast.js:164:34)
|
at foldAst (/home/nils/projects/riverdelta/target/ast.js:164:34)
|
||||||
|
|
||||||
Node.js v18.18.2
|
Node.js v20.10.0
|
||||||
|
|
|
||||||
|
|
@ -14,4 +14,4 @@ Error: substitution out of range, param index 0 of param T out of range for leng
|
||||||
at Array.map (<anonymous>)
|
at Array.map (<anonymous>)
|
||||||
at foldAst (/home/nils/projects/riverdelta/target/ast.js:164:34)
|
at foldAst (/home/nils/projects/riverdelta/target/ast.js:164:34)
|
||||||
|
|
||||||
Node.js v18.18.2
|
Node.js v20.10.0
|
||||||
|
|
|
||||||
|
|
@ -14,4 +14,4 @@ Error: substitution out of range, param index 0 of param T out of range for leng
|
||||||
at Array.map (<anonymous>)
|
at Array.map (<anonymous>)
|
||||||
at foldAst (/home/nils/projects/riverdelta/target/ast.js:164:34)
|
at foldAst (/home/nils/projects/riverdelta/target/ast.js:164:34)
|
||||||
|
|
||||||
Node.js v18.18.2
|
Node.js v20.10.0
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue