move ty defs

This commit is contained in:
nora 2023-12-16 12:39:37 +01:00
parent a22cc15b59
commit d18ab34e9f
14 changed files with 173 additions and 192 deletions

View file

@ -1,5 +1,6 @@
import { ErrorEmitted, LoadedFile, Span, unreachable } from "./error";
import { LitIntType } from "./lexer";
import { Ty, TyFn, TypeckResults } from "./types";
import { ComplexMap } from "./utils";
import { Instr, ValType } from "./wasm/defs";
@ -507,161 +508,6 @@ export type LocalInfo = {
// 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

View file

@ -1,5 +1,6 @@
import { ItemId, TY_I32, TY_INT, TyStruct } from "./ast";
import { ItemId } from "./ast";
import { layoutOfStruct } from "./codegen";
import { TY_I32, TY_INT, TyStruct } from "./types";
it("should compute struct layout correctly", () => {
const ty: TyStruct = {

View file

@ -10,22 +10,17 @@ import {
ItemId,
LoopId,
Resolution,
Ty,
TyFn,
TyStruct,
TyTuple,
Typecked,
mkDefaultFolder,
superFoldExpr,
superFoldItem,
varUnreachable,
TyRawPtr,
paramUnreachable as codegenUnreachableTy,
structFieldsSubstituted,
} from "./ast";
import { GlobalContext } from "./context";
import { unreachable } from "./error";
import { printTy } from "./printer";
import { Ty, TyFn, TyRawPtr, TyStruct, TyTuple, structFieldsSubstituted } from "./types";
import { ComplexMap, encodeUtf8, unwrap } from "./utils";
import * as wasm from "./wasm/defs";

View file

@ -9,12 +9,10 @@ import {
ItemMod,
Resolution,
StringLiteral,
Ty,
Type,
ItemType,
tyIsUnit,
substituteTy,
} from "./ast";
import { Ty, substituteTy, tyIsUnit } from "./types";
export function printAst(ast: Pkg<AnyPhase>): string {
return ast.rootItems.map(printItem).join("\n");

View file

@ -1,6 +1,7 @@
import { ItemId, Pkg, Resolved, Ty } from "../ast";
import { ItemId, Pkg, Resolved } from "../ast";
import { GlobalContext } from "../context";
import { CompilerError, ErrorEmitted } from "../error";
import { Ty } from "../types";
import { ComplexMap } from "../utils";
export type TypeckCtx = {

View file

@ -13,14 +13,6 @@ import {
Resolution,
Resolved,
StructLiteralField,
TY_BOOL,
TY_I32,
TY_INT,
TY_NEVER,
TY_STRING,
TY_UNIT,
Ty,
TyFn,
Type,
Typecked,
mkDefaultFolder,
@ -28,6 +20,7 @@ import {
} from "../ast";
import { CompilerError, ErrorEmitted, Span, unreachable } from "../error";
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 { TypeckCtx, emitError, mkTyFn, tyError, tyErrorFrom } from "./base";
import { InferContext } from "./infer";

View file

@ -5,17 +5,13 @@ import {
Item,
ItemId,
Resolved,
TY_I32,
TY_INT,
Ty,
TyFn,
Typecked,
foldAst,
mkDefaultFolder,
tyIsUnit,
} from "../ast";
import { GlobalContext } from "../context";
import { CompilerError, ErrorEmitted, Span } from "../error";
import { TY_I32, TY_INT, Ty, TyFn, tyIsUnit } from "../types";
import { ComplexMap } from "../utils";
import { emitError } from "./base";
import { checkBody, exprError } from "./expr";

View file

@ -1,5 +1,5 @@
import { TY_INT, TY_STRING, TY_UNIT } from "../ast";
import { Emitter, ErrorHandler, Span } from "../error";
import { TY_INT, TY_STRING, TY_UNIT } from "../types";
import { InferContext } from "./infer";
const SPAN: Span = Span.startOfFile({ content: "" });

View file

@ -1,6 +1,6 @@
import { Ty } from "../ast";
import { CompilerError, ErrorHandler, Span } from "../error";
import { printTy } from "../printer";
import { Ty } from "../types";
type TyVarRes =
| {

View file

@ -1,18 +1,11 @@
import {
ItemId,
Resolved,
Ty,
TY_BOOL,
TY_I32,
TY_INT,
TY_NEVER,
TY_STRING,
TY_UNIT,
Type,
substituteTy,
} from "../ast";
import { CompilerError, Span } from "../error";
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";
function builtinAsTy(cx: TypeckCtx, name: string, span: Span): Ty {

158
src/types.ts Normal file
View 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;
}
}

View file

@ -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 foldAst (/home/nils/projects/riverdelta/target/ast.js:164:34)
Node.js v18.18.2
Node.js v20.10.0

View file

@ -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 foldAst (/home/nils/projects/riverdelta/target/ast.js:164:34)
Node.js v18.18.2
Node.js v20.10.0

View file

@ -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 foldAst (/home/nils/projects/riverdelta/target/ast.js:164:34)
Node.js v18.18.2
Node.js v20.10.0