move constant tys

This commit is contained in:
nora 2023-12-16 12:44:30 +01:00
parent d18ab34e9f
commit b4fb837efe
10 changed files with 71 additions and 75 deletions

View file

@ -508,7 +508,6 @@ export type LocalInfo = {
// types
// folders
export type FoldFn<From, To> = (value: From) => To;

View file

@ -1,6 +1,6 @@
import { ItemId } from "./ast";
import { layoutOfStruct } from "./codegen";
import { TY_I32, TY_INT, TyStruct } from "./types";
import { TYS, TyStruct } from "./types";
it("should compute struct layout correctly", () => {
const ty: TyStruct = {
@ -10,8 +10,8 @@ it("should compute struct layout correctly", () => {
params: [],
_name: "",
fields_no_subst: [
["uwu", TY_I32],
["owo", TY_INT],
["uwu", TYS.I32],
["owo", TYS.INT],
],
};
@ -56,7 +56,7 @@ it("should compute single field struct layout correctly", () => {
genericArgs: [],
params: [],
_name: "",
fields_no_subst: [["owo", TY_INT]],
fields_no_subst: [["owo", TYS.INT]],
};
const layout = layoutOfStruct(ty);

View file

@ -20,7 +20,14 @@ import {
import { GlobalContext } from "./context";
import { unreachable } from "./error";
import { printTy } from "./printer";
import { Ty, TyFn, TyRawPtr, TyStruct, TyTuple, structFieldsSubstituted } from "./types";
import {
Ty,
TyFn,
TyRawPtr,
TyStruct,
TyTuple,
structFieldsSubstituted,
} from "./types";
import { ComplexMap, encodeUtf8, unwrap } from "./utils";
import * as wasm from "./wasm/defs";

View file

@ -91,9 +91,7 @@ export const loadPkg: PkgLoader = (
span: Span,
): DepPkg => {
// If we've loaded the pkg already, great.
const existing = gcx.finalizedPkgs.find(
(pkg) => pkg.packageName === name,
);
const existing = gcx.finalizedPkgs.find((pkg) => pkg.packageName === name);
if (existing) {
return existing;
}

View file

@ -63,10 +63,7 @@ function resolveModItem(
return contents.get(name);
}
export function resolve(
gcx: GlobalContext,
ast: Pkg<Built>,
): Pkg<Resolved> {
export function resolve(gcx: GlobalContext, ast: Pkg<Built>): Pkg<Resolved> {
const cx: Context = {
ast,
gcx,

View file

@ -20,7 +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 { TYS, Ty, TyFn } from "../types";
import { INSTRS, Instr, VALTYPES, ValType } from "../wasm/defs";
import { TypeckCtx, emitError, mkTyFn, tyError, tyErrorFrom } from "./base";
import { InferContext } from "./infer";
@ -74,27 +74,27 @@ export function typeOfBuiltinValue(
switch (name) {
case "false":
case "true":
return TY_BOOL;
return TYS.BOOL;
case "print":
return mkTyFn([TY_STRING], TY_UNIT);
return mkTyFn([TYS.STRING], TYS.UNIT);
case "trap":
return mkTyFn([], TY_NEVER);
return mkTyFn([], TYS.NEVER);
case "__NULL":
return { kind: "rawptr", inner: fcx.infcx.newVar() };
case "__i32_store":
return mkTyFn([TY_I32, TY_I32], TY_UNIT);
return mkTyFn([TYS.I32, TYS.I32], TYS.UNIT);
case "__i64_store":
return mkTyFn([TY_I32, TY_INT], TY_UNIT);
return mkTyFn([TYS.I32, TYS.INT], TYS.UNIT);
case "__i32_load":
return mkTyFn([TY_I32], TY_I32);
return mkTyFn([TYS.I32], TYS.I32);
case "__i64_load":
return mkTyFn([TY_I32], TY_INT);
return mkTyFn([TYS.I32], TYS.INT);
case "__memory_size":
return mkTyFn([], TY_I32);
return mkTyFn([], TYS.I32);
case "__memory_grow":
return mkTyFn([TY_I32], TY_I32);
return mkTyFn([TYS.I32], TYS.I32);
case "__i32_extend_to_i64_u":
return mkTyFn([TY_I32], TY_INT);
return mkTyFn([TYS.I32], TYS.INT);
default: {
return tyError(
fcx.cx,
@ -134,7 +134,7 @@ export function checkBody(
expr(expr): Expr<Typecked> {
switch (expr.kind) {
case "empty": {
return { ...expr, ty: TY_UNIT };
return { ...expr, ty: TYS.UNIT };
}
case "let": {
const loweredBindingTy = expr.type && lowerAstTy(cx, expr.type);
@ -160,7 +160,7 @@ export function checkBody(
name: expr.name,
type,
rhs,
ty: TY_UNIT,
ty: TYS.UNIT,
span: expr.span,
};
}
@ -215,7 +215,7 @@ export function checkBody(
kind: "assign",
lhs,
rhs,
ty: TY_UNIT,
ty: TYS.UNIT,
};
}
case "block": {
@ -223,7 +223,7 @@ export function checkBody(
const exprs = expr.exprs.map((expr) => this.expr(expr));
const ty = exprs.length > 0 ? exprs[exprs.length - 1].ty : TY_UNIT;
const ty = exprs.length > 0 ? exprs[exprs.length - 1].ty : TYS.UNIT;
fcx.localTys.length = prevLocalTysLen;
@ -237,16 +237,16 @@ export function checkBody(
let ty;
switch (expr.value.kind) {
case "str": {
ty = TY_STRING;
ty = TYS.STRING;
break;
}
case "int": {
switch (expr.value.type) {
case "Int":
ty = TY_INT;
ty = TYS.INT;
break;
case "I32":
ty = TY_I32;
ty = TYS.I32;
break;
}
break;
@ -387,15 +387,15 @@ export function checkBody(
const then = this.expr(expr.then);
const elsePart = expr.else && this.expr(expr.else);
infcx.assign(TY_BOOL, cond.ty, cond.span);
infcx.assign(TYS.BOOL, cond.ty, cond.span);
let ty: Ty;
if (elsePart) {
infcx.assign(then.ty, elsePart.ty, elsePart.span);
ty = then.ty!;
} else {
infcx.assign(TY_UNIT, then.ty, then.span);
ty = TY_UNIT;
infcx.assign(TYS.UNIT, then.ty, then.span);
ty = TYS.UNIT;
}
return { ...expr, cond, then, else: elsePart, ty };
@ -407,10 +407,10 @@ export function checkBody(
});
const body = this.expr(expr.body);
infcx.assign(TY_UNIT, body.ty, body.span);
infcx.assign(TYS.UNIT, body.ty, body.span);
const hadBreak = fcx.loopState.pop();
const ty = hadBreak ? TY_UNIT : TY_NEVER;
const ty = hadBreak ? TYS.UNIT : TYS.NEVER;
return {
...expr,
@ -432,7 +432,7 @@ export function checkBody(
return {
...expr,
ty: TY_NEVER,
ty: TYS.NEVER,
target,
};
}
@ -648,39 +648,39 @@ function checkBinary(
if (COMPARISON_KINDS.includes(expr.binaryKind)) {
if (lhsTy.kind === "int" && rhsTy.kind === "int") {
return { ...expr, lhs, rhs, ty: TY_BOOL };
return { ...expr, lhs, rhs, ty: TYS.BOOL };
}
if (lhsTy.kind === "i32" && rhsTy.kind === "i32") {
return { ...expr, lhs, rhs, ty: TY_BOOL };
return { ...expr, lhs, rhs, ty: TYS.BOOL };
}
if (lhsTy.kind === "string" && rhsTy.kind === "string") {
return { ...expr, lhs, rhs, ty: TY_BOOL };
return { ...expr, lhs, rhs, ty: TYS.BOOL };
}
if (lhsTy.kind === "rawptr" && rhsTy.kind === "rawptr") {
fcx.infcx.assign(lhsTy.inner, rhsTy.inner, expr.span);
return { ...expr, lhs, rhs, ty: TY_BOOL };
return { ...expr, lhs, rhs, ty: TYS.BOOL };
}
if (EQUALITY_KINDS.includes(expr.binaryKind)) {
if (lhsTy.kind === "bool" && rhsTy.kind === "bool") {
return { ...expr, lhs, rhs, ty: TY_BOOL };
return { ...expr, lhs, rhs, ty: TYS.BOOL };
}
}
}
if (lhsTy.kind === "int" && rhsTy.kind === "int") {
return { ...expr, lhs, rhs, ty: TY_INT };
return { ...expr, lhs, rhs, ty: TYS.INT };
}
if (lhsTy.kind === "i32" && rhsTy.kind === "i32") {
return { ...expr, lhs, rhs, ty: TY_I32 };
return { ...expr, lhs, rhs, ty: TYS.I32 };
}
if (LOGICAL_KINDS.includes(expr.binaryKind)) {
if (lhsTy.kind === "bool" && rhsTy.kind === "bool") {
return { ...expr, lhs, rhs, ty: TY_BOOL };
return { ...expr, lhs, rhs, ty: TYS.BOOL };
}
}
@ -734,7 +734,7 @@ function checkCall(
const args = expr.args.map((arg) => fcx.checkExpr(arg));
const ret: Expr<Typecked> = {
...expr,
lhs: { ...expr.lhs, ty: TY_UNIT },
lhs: { ...expr.lhs, ty: TYS.UNIT },
args,
ty,
};

View file

@ -11,17 +11,14 @@ import {
} from "../ast";
import { GlobalContext } from "../context";
import { CompilerError, ErrorEmitted, Span } from "../error";
import { TY_I32, TY_INT, Ty, TyFn, tyIsUnit } from "../types";
import { TYS, Ty, TyFn, tyIsUnit } from "../types";
import { ComplexMap } from "../utils";
import { emitError } from "./base";
import { checkBody, exprError } from "./expr";
import { InferContext } from "./infer";
import { typeOfItem } from "./item";
export function typeck(
gcx: GlobalContext,
ast: Pkg<Resolved>,
): Pkg<Typecked> {
export function typeck(gcx: GlobalContext, ast: Pkg<Resolved>): Pkg<Typecked> {
const cx = {
gcx,
itemTys: new ComplexMap<ItemId, Ty | null>(),
@ -152,7 +149,7 @@ export function typeck(
);
initChecked = exprError(err, init.span);
} else {
const initTy = init.value.type === "I32" ? TY_I32 : TY_INT;
const initTy = init.value.type === "I32" ? TYS.I32 : TYS.INT;
const infcx = new InferContext(cx.gcx.error);
infcx.assign(ty, initTy, init.span);
initChecked = { ...init, ty };

View file

@ -1,5 +1,5 @@
import { Emitter, ErrorHandler, Span } from "../error";
import { TY_INT, TY_STRING, TY_UNIT } from "../types";
import { TYS } from "../types";
import { InferContext } from "./infer";
const SPAN: Span = Span.startOfFile({ content: "" });
@ -16,7 +16,7 @@ it("should infer types across assignments", () => {
infcx.assign(a, b, SPAN);
infcx.assign(b, c, SPAN);
infcx.assign(a, TY_INT, SPAN);
infcx.assign(a, TYS.INT, SPAN);
const aTy = infcx.resolveIfPossible(c);
const bTy = infcx.resolveIfPossible(c);
@ -36,11 +36,11 @@ it("should conflict assignments to resolvable type vars", () => {
const b = infcx.newVar();
infcx.assign(a, b, SPAN);
infcx.assign(b, TY_INT, SPAN);
infcx.assign(b, TYS.INT, SPAN);
expect(errorLines).toEqual(0);
infcx.assign(a, TY_STRING, SPAN);
infcx.assign(a, TYS.STRING, SPAN);
expect(errorLines).toBeGreaterThan(0);
});
@ -57,7 +57,7 @@ it("should not cycle", () => {
const aType = infcx.resolveIfPossible(a);
expect(aType.kind).toEqual("var");
infcx.assign(a, TY_UNIT, SPAN);
infcx.assign(a, TYS.UNIT, SPAN);
const bType = infcx.resolveIfPossible(b);
expect(bType.kind).toEqual("tuple");

View file

@ -1,26 +1,22 @@
import {
ItemId,
Resolved,
Type,
} from "../ast";
import { ItemId, Resolved, Type } 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 { TYS, Ty, substituteTy } from "../types";
import { TypeckCtx, tyError, tyErrorFrom } from "./base";
function builtinAsTy(cx: TypeckCtx, name: string, span: Span): Ty {
switch (name) {
case "String": {
return TY_STRING;
return TYS.STRING;
}
case "Int": {
return TY_INT;
return TYS.INT;
}
case "I32": {
return TY_I32;
return TYS.I32;
}
case "Bool": {
return TY_BOOL;
return TYS.BOOL;
}
default: {
return tyError(cx, new CompilerError(`\`${name}\` is not a type`, span));
@ -110,7 +106,7 @@ export function lowerAstTy(cx: TypeckCtx, type: Type<Resolved>): Ty {
return { kind: "rawptr", inner };
}
case "never": {
return TY_NEVER;
return TYS.NEVER;
}
case "error": {
return tyErrorFrom(type);
@ -180,7 +176,7 @@ export function typeOfItem(
const args = item.params.map((arg) => lowerAstTy(cx, arg.type));
const returnTy: Ty = item.returnType
? lowerAstTy(cx, item.returnType)
: TY_UNIT;
: TYS.UNIT;
ty = { kind: "fn", params: args, returnTy };
break;

View file

@ -98,12 +98,14 @@ 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 const TYS = {
UNIT: { kind: "tuple", elems: [] } as Ty,
STRING: { kind: "string" } as Ty,
BOOL: { kind: "bool" } as Ty,
INT: { kind: "int" } as Ty,
I32: { kind: "i32" } as Ty,
NEVER: { kind: "never" } as Ty,
} as const;
export type TypeckResults = {
main: Resolution | undefined;