simplify: no distinction between generic types and 'normal' types.

This commit is contained in:
Joeri Exelmans 2025-05-08 16:58:07 +02:00
parent b4826605af
commit a664ddac8a
27 changed files with 535 additions and 360 deletions

View file

@ -1,25 +1,31 @@
import { add, emptySet, forEach } from "../../structures/set.js";
import { add, emptySet, forEach } from "../structures/set.js";
import { deepEqual } from "../util/util.js";
import {inspect} from "node:util";
import { compareSlots } from "../compare/versioning.js";
// UUID -> Value<a> -> Slot<a>
export const newSlot = uuid => value => ({
overwrites: uuid,
value,
depth: 1,
export const newSlot = uuid => ({
kind: "new",
uuid,
depth: 0,
[inspect.custom]: (depth, options, inspect) => `newSlot(${inspect(uuid)}, ${inspect(value)})`,
});
// Slot<a> -> Value<a> -> Slot<a>
export const overwrite = slot => value => ({
kind: "overwrite",
overwrites: slot,
value,
depth: slot.depth + 1,
// [inspect.custom]: (depth, options, inspect) => `overwrite(${inspect(slot)}, ${inspect(value)})`,
});
const slotsEqual = slotA => slotB => {
}
const findLCA = slotA => slotB => {
if (slotA.depth === slotB.depth) {
}
if (deepEqual(slotA, slotB)) {
return slotA;
}
@ -31,7 +37,6 @@ const findLCA = slotA => slotB => {
}
};
// Slot<a> -> Slot<a> -> MergeResult<a>
export const merge = compareElems => slotA => slotB => {
const lca = findLCA(slotA)(slotB);
if (lca === undefined) {
@ -49,7 +54,6 @@ export const merge = compareElems => slotA => slotB => {
// return new Set([slotA, slotB]);
};
// MergeResult<a> -> MergeResult<a> -> MergeResult<a>
export const merge2 = compareElems => mA => mB => {
let result = emptySet(compareSlots(compareElems));
forEach(mA)(slotOfA => {

View file

@ -1,27 +1,47 @@
import { Dynamic } from "../primitives/dynamic.js";
import { Int } from "../primitives/types.js";
import { enumType } from "../structures/enum.js";
import { makeGeneric } from "../generics/generics.js";
import { makeTypeConstructor } from "../meta/type_constructor.js";
import { Int, UUID } from "../primitives/primitive_types.js";
import { enumType, makeModuleEnum } from "../structures/enum.types.js";
import { newProduct } from "../structures/product.js";
import { structType } from "../structures/struct.js";
import { prodType } from "../structures/types.js";
import { structType } from "../structures/struct.types.js";
import { prettyT } from "../util/pretty.js";
const Slot = structType([
newProduct("value")(() => Value),
newProduct("depth")(() => Int),
newProduct("overwrites")(() => Slot),
const Slot = makeTypeConstructor("Slot__318d1c1a9336c141336c461c6a3207b0")(1);
const Value = makeTypeConstructor("Value__23fc00a2db1374bd3dc1a0ad2d8517ab")(1);
makeModuleEnum(Value)([
]);
// A Value is either:
// - a literal, without any dependencies.
// - read from a slot. the Value then has a read-dependency on that slot.
// - a transformation of another Value, by a function. the function is also a Value.
const variants = [
newProduct("literal", () => Dynamic),
newProduct("read", () => Slot),
newProduct("transformation", () => prodType(Value, Dynamic)),
];
const Value = enumType(variants);
const _slotType = a => Value => structType([
newProduct("value")(_ => Value || _valueType(a)(Slot)),
newProduct("rest" )(_ => enumType([
newProduct("new")(Slot => structType([
newProduct("uuid" )(_ => UUID),
newProduct("value")(_ => Value || _valueType(a)(Slot)),
])),
newProduct("overwrites")(Slot => structType([
newProduct("slot" )(_ => Slot),
newProduct("value")(_ => Value || _valueType(a)(Slot)),
newProduct("depth")(_ => Int),
])),
])),
]);
// console.log(prettyT(Slot));
// console.log(prettyT(Value));
const _valueType = a => Slot => enumType([
newProduct("literal" )(_ => a),
newProduct("read" )(Value => Slot || _slotType(a)(Value)),
newProduct("transform")(Value => structType([
newProduct("in" )(_ => Value),
newProduct("fn" )(_ => Value),
newProduct("out")(_ => a),
])),
]);
const slotType = makeGeneric(a => _slotType(a)(null));
const valueType = makeGeneric(a => _valueType(a)(null));
console.log("slotType:", prettyT(slotType));
console.log("valueType:", prettyT(valueType));
// const valueType = makeGeneric(a => _valueType(a)(_slotType));

View file

@ -1,4 +1,3 @@
import { fnType } from "../structures/types.js";
import { deepEqual } from "../util/util.js";
import { inspect } from "node:util";
@ -20,7 +19,7 @@ export const read = slot => ({
// Value<a> -> Value<a -> b> -> Value<b>
export const transform = input => fn => {
const output = fn.out(input.out);
const _inspect = (depth, options, inspect) => `transform(${inspect(input)}, ${inspect(fn)})`;
// const _inspect = (depth, options, inspect) => `transform(${inspect(input)}, ${inspect(fn)})`;
if (input.kind === "literal") {
// optimization: sandwich everything together
return {
@ -31,7 +30,7 @@ export const transform = input => fn => {
}
else {
return {
kind: "transformation",
kind: "transform",
in: input,
fn,
out: output,
@ -48,7 +47,7 @@ export const getReadDependencies = value => {
else if (value.kind === "read") {
return new Set([value.slot]);
}
else if (value.kind === "transformation") {
else if (value.kind === "transform") {
return new Set([
...getReadDependencies(value.in),
...getReadDependencies(value.fn),
@ -80,9 +79,9 @@ export const verifyValue = (value, indent = 0) => {
else if (value.kind === "read") {
compare(value.out, value.slot.value.out, "read");
}
else if (value.kind === "transformation") {
else if (value.kind === "transform") {
compare(value.fn.out(value.in.out),
value.out, "transformation");
value.out, "transform");
success &= verifyValue(value.in, indent + 1);
success &= verifyValue(value.fn, indent + 1);