Skip to content

Commit

Permalink
implemented traits analysis
Browse files Browse the repository at this point in the history
  • Loading branch information
ascandone committed Jan 6, 2025
1 parent 2e60c5d commit cc8fa1f
Show file tree
Hide file tree
Showing 10 changed files with 254 additions and 139 deletions.
23 changes: 15 additions & 8 deletions src/analysis/analyse.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { test, expect, describe, vi } from "vitest";
import { AnalyseOptions, Analysis } from "./analyse";
import { test, expect, describe, vi, beforeEach } from "vitest";
import { AnalyseOptions, Analysis, resetTraitsRegistry } from "./analyse";
import {
AmbiguousTypeVar,
ArityMismatch,
Expand Down Expand Up @@ -1698,6 +1698,8 @@ describe("unused locals checks", () => {

describe("traits", () => {
test("fails to typecheck when a required trait is not implemented", () => {
resetTraitsRegistry([]);

const [a] = performAnalysis(
`
extern type String
Expand All @@ -1713,9 +1715,14 @@ describe("traits", () => {
});

test("succeeds to typecheck when a required trait is not implemented", () => {
// resetTraitsRegistry([
// { trait: "Show", moduleName: "Int", typeName: "Int" },
// ]);
resetTraitsRegistry([
{
packageName: "kestrel_core",
trait: "Show",
moduleName: "Int",
typeName: "Int",
},
]);

const [a] = performAnalysis(
`
Expand Down Expand Up @@ -3067,6 +3074,6 @@ function performAnalysis(
];
}

// beforeEach(() => {
// resetTraitsRegistry();
// });
beforeEach(() => {
resetTraitsRegistry();
});
49 changes: 2 additions & 47 deletions src/analysis/analyse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ import { bool, char, float, int, list, string } from "./coreTypes";
import { TypeAstsHydration } from "./typesHydration";
import { defaultMapGet } from "../data/defaultMap";
import { TraitImpl, defaultTraitImpls } from "../typecheck/defaultImports";
import { TraitImplDependency } from "../typecheck/type";

export type AnalyseOptions = {
getDependency?: (namespace: string) => Analysis | undefined;
Expand Down Expand Up @@ -439,45 +438,6 @@ export class Analysis {
}
}
}

private static namedTypesTraitImpls = new Map<
string,
TraitImplDependency[]
>();

public static resetTraitImpls() {
Analysis.namedTypesTraitImpls = new Map();
}

/**
* E.g.
* // impl Eq for Int
* registerTraitImpl("Basics", "Int", "Eq")
*
* // impl Eq for Result<a, b> where a: Eq, b: Eq
* registerTraitImpl("Basics", "Result", "Eq", [["Eq"], ["Eq"]])
*/
public static registerTraitImpl(
moduleName: string,
typeName: string,
trait: string,
dependencies: TraitImplDependency[],
) {
const id = getNamedTypeTraitId(moduleName, typeName, trait);
if (Analysis.namedTypesTraitImpls.has(id)) {
throw new Error("Cannot register trait twice for the same type");
}

Analysis.namedTypesTraitImpls.set(id, dependencies);
}
}

function getNamedTypeTraitId(
moduleName: string,
typeName: string,
trait: string,
): string {
return `${moduleName}.${typeName}:${trait}`;
}

// Keep this in sync with core
Expand All @@ -500,14 +460,9 @@ function getConstantType(lit: ConstLiteral): Type {
export function resetTraitsRegistry(
traitImpls: TraitImpl[] = defaultTraitImpls,
) {
Analysis.resetTraitImpls();
Unifier.resetTraitImpls();
for (const impl of traitImpls) {
TVar.registerTraitImpl(
impl.moduleName,
impl.typeName,
impl.trait,
impl.deps ?? [],
);
Unifier.registerTraitImpl(impl);
}
}

Expand Down
144 changes: 125 additions & 19 deletions src/compiler/compiler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2263,7 +2263,14 @@ describe("traits compilation", () => {
`,
{
allowDeriving: ["Eq"],
traitImpl: [{ typeName: "Int", moduleName: "Main", trait: "Eq" }],
traitImpl: [
{
packageName: "kestrel_core",
typeName: "Int",
moduleName: "Main",
trait: "Eq",
},
],
},
);

Expand Down Expand Up @@ -2293,15 +2300,17 @@ describe("traits compilation", () => {
{
traitImpl: [
{
packageName: "kestrel_core",
typeName: "Int",
moduleName: "Main",
trait: "FromJson",
},
{
packageName: "kestrel_core",
typeName: "Option",
moduleName: "Main",
trait: "FromJson",
deps: [["FromJson"]],
deps: [true],
},
],
},
Expand All @@ -2327,12 +2336,18 @@ describe("traits compilation", () => {
`,
{
traitImpl: [
{ typeName: "Int", moduleName: "Main", trait: "FromJson" },
{
packageName: "kestrel_core",
typeName: "Int",
moduleName: "Main",
trait: "FromJson",
},
{
packageName: "kestrel_core",
typeName: "Option",
moduleName: "Main",
trait: "FromJson",
deps: [["FromJson"]],
deps: [true],
},
],
},
Expand Down Expand Up @@ -2397,7 +2412,14 @@ describe("derive Eq instance for Adt", () => {
`,
{
allowDeriving: ["Eq"],
traitImpl: [{ moduleName: "Main", typeName: "Int", trait: "Eq" }],
traitImpl: [
{
packageName: "kestrel_core",
moduleName: "Main",
typeName: "Int",
trait: "Eq",
},
],
},
);
expect(out).toMatchInlineSnapshot(`
Expand All @@ -2418,7 +2440,14 @@ describe("derive Eq instance for Adt", () => {
`,
{
allowDeriving: ["Eq"],
traitImpl: [{ moduleName: "Main", typeName: "Int", trait: "Eq" }],
traitImpl: [
{
packageName: "kestrel_core",
moduleName: "Main",
typeName: "Int",
trait: "Eq",
},
],
},
);
expect(out).toMatchInlineSnapshot(`
Expand Down Expand Up @@ -2450,8 +2479,18 @@ describe("derive Eq instance for Adt", () => {
{
allowDeriving: ["Eq"],
traitImpl: [
{ moduleName: "Main", typeName: "Int", trait: "Eq" },
{ moduleName: "Main", typeName: "Bool", trait: "Eq" },
{
packageName: "kestrel_core",
moduleName: "Main",
typeName: "Int",
trait: "Eq",
},
{
packageName: "kestrel_core",
moduleName: "Main",
typeName: "Bool",
trait: "Eq",
},
],
},
);
Expand Down Expand Up @@ -2494,8 +2533,18 @@ describe("derive Eq instance for Adt", () => {
{
allowDeriving: ["Eq"],
traitImpl: [
{ moduleName: "Main", typeName: "Int", trait: "Eq" },
{ moduleName: "Main", typeName: "Bool", trait: "Eq" },
{
packageName: "kestrel_core",
moduleName: "Main",
typeName: "Int",
trait: "Eq",
},
{
packageName: "kestrel_core",
moduleName: "Main",
typeName: "Bool",
trait: "Eq",
},
],
},
);
Expand Down Expand Up @@ -2620,7 +2669,14 @@ describe("derive Eq instance for structs", () => {
`,
{
allowDeriving: ["Eq"],
traitImpl: [{ moduleName: "Main", typeName: "Int", trait: "Eq" }],
traitImpl: [
{
packageName: "kestrel_core",
moduleName: "Main",
typeName: "Int",
trait: "Eq",
},
],
},
);

Expand Down Expand Up @@ -2654,8 +2710,18 @@ describe("derive Eq instance for structs", () => {
{
allowDeriving: ["Eq"],
traitImpl: [
{ moduleName: "Main", typeName: "Int", trait: "Eq" },
{ moduleName: "Main", typeName: "Bool", trait: "Eq" },
{
packageName: "kestrel_core",
moduleName: "Main",
typeName: "Int",
trait: "Eq",
},
{
packageName: "kestrel_core",
moduleName: "Main",
typeName: "Bool",
trait: "Eq",
},
],
},
);
Expand Down Expand Up @@ -2749,7 +2815,14 @@ describe("Derive Show instance for Adts", () => {
`,
{
allowDeriving: ["Show"],
traitImpl: [{ moduleName: "Main", typeName: "Int", trait: "Show" }],
traitImpl: [
{
packageName: "kestrel_core",
moduleName: "Main",
typeName: "Int",
trait: "Show",
},
],
},
);

Expand All @@ -2771,7 +2844,14 @@ describe("Derive Show instance for Adts", () => {
`,
{
allowDeriving: ["Show"],
traitImpl: [{ moduleName: "Main", typeName: "Int", trait: "Show" }],
traitImpl: [
{
packageName: "kestrel_core",
moduleName: "Main",
typeName: "Int",
trait: "Show",
},
],
},
);

Expand All @@ -2790,7 +2870,12 @@ describe("Derive Show instance for Adts", () => {
{
allowDeriving: ["Show"],
traitImpl: [
{ moduleName: "Example/Namespace", typeName: "Int", trait: "Show" },
{
packageName: "kestrel_core",
moduleName: "Example/Namespace",
typeName: "Int",
trait: "Show",
},
],
ns: "Example/Namespace",
},
Expand Down Expand Up @@ -2828,7 +2913,14 @@ describe("Derive Show instance for Adts", () => {
`,
{
allowDeriving: ["Show"],
traitImpl: [{ moduleName: "Main", typeName: "Int", trait: "Show" }],
traitImpl: [
{
packageName: "kestrel_core",
moduleName: "Main",
typeName: "Int",
trait: "Show",
},
],
},
);

Expand Down Expand Up @@ -2971,7 +3063,14 @@ describe("Derive Show instance for structs", () => {
`,
{
allowDeriving: ["Show"],
traitImpl: [{ moduleName: "Main", typeName: "Int", trait: "Show" }],
traitImpl: [
{
packageName: "kestrel_core",
moduleName: "Main",
typeName: "Int",
trait: "Show",
},
],
},
);

Expand Down Expand Up @@ -3005,7 +3104,14 @@ describe("Derive Show instance for structs", () => {
`,
{
allowDeriving: ["Show"],
traitImpl: [{ moduleName: "Main", typeName: "Int", trait: "Show" }],
traitImpl: [
{
packageName: "kestrel_core",
moduleName: "Main",
typeName: "Int",
trait: "Show",
},
],
},
);

Expand Down
Loading

0 comments on commit cc8fa1f

Please sign in to comment.