dope2/lib/versioning/static/value_slot.js
2025-06-08 14:29:08 +02:00

137 lines
4.6 KiB
JavaScript

import { makeGeneric } from "../../generics/generics.js";
import { makeTypeConstructor } from "../../meta/type_constructor.js";
import { makeTypeParser } from "../../parser/type_parser.js";
import { apply, newDynamic } from "../../primitives/dynamic.js";
import { Int, UUID } from "../../primitives/primitive_types.js";
import { makeModuleEnum } from "../../structures/enum.types.js";
import { makeModuleStruct } from "../../structures/struct.types.js";
import { fnType } from "../../structures/type_constructors.types.js";
export const symbolSlot = "Slot__318d1c1a9336c141336c461c6a3207b0";
export const symbolValue = "Value__23fc00a2db1374bd3dc1a0ad2d8517ab";
export const symbolTransformation = "Transformation__9eac70d7020c7c45d5a16f3f14b13083";
export const symbolWrite = "Write__abaef8ddb5c167b5d2cedac111fcefd3";
// Value and Slot each take 1 type parameter
export const Slot = makeTypeConstructor(symbolSlot)(1);
export const Value = makeTypeConstructor(symbolValue)(1);
// Transformation takes 2 type parameters
export const Transformation = makeTypeConstructor(symbolTransformation)(2);
// A Write-operation writes a value to a slot. The inner type of the Value and Slot must match.
export const Write = makeTypeConstructor(symbolWrite)(1);
// Enum: Value
const [
// constructors
[, {i: newValueLiteral}],
[, {i: newValueRead}],
[, {i: newValueTransform}],
// match function
[, {i: matchValue}],
] = makeGeneric((innerType, a) => makeModuleEnum(Value(_=>innerType))([
{l: "literal" , r: innerType},
{l: "read" , r: Write(_=>innerType)}, // <- a 'read' reads the result of a Write (to a Slot)
{l: "transform", r: Transformation(_=>a)(_=>innerType)}, // <- result of a function call
]));
// Enum: Slot
const [
// constructors
[, {i: newSlotNew}],
[, {i: newSlotWrite}],
// match function
[, {i: matchSlot}],
] = makeGeneric(innerType => makeModuleEnum(Slot(_=>innerType))([
{l: "new" , r: UUID },
{l: "write", r: Write},
]));
// Struct: Transformation (i.e., a function call)
const [
// constructor
[, {i: newTransformation}],
// getters
// [, {i: getInput}],
// [, {i: getFn}],
// [, {i: getOutput}],
] = makeGeneric((inType, outType) => makeModuleStruct(Transformation)([
{l: "input" , r: Value(_=>inType) }, // <- the input is a value (e.g., could be the result of a Transformation itself)
{l: "fn" , r: Value(_=>fnType(_=>inType)(_=>outType)) }, // <- the function is also a value (e.g., could also be result of a transformation, e.g., when currying)
{l: "output", r: outType}, // <- the result
]));
// Struct: Write
const [
// constructor
[, {i: newWrite}],
// getters
// [, {i: getDepth}],
// [, {i: getSlot}],
// [, {i: getValue}],
] = makeGeneric(innerType => makeModuleStruct(Write(_=>innerType))([
{l: "depth", r: Int }, // <- depth increases merge performance, and also comes first in the struct (this way, it is the first value compared upon comparison)
{l: "slot" , r: Slot(_=>innerType) },
{l: "value", r: Value(_=>innerType) },
]));
// shorthands
export const getDepth = slot =>
matchSlot(slot)
(_slotNew => 0n)
(slotWrite => slotWrite.depth);
// get the value from a Value
export const getVal = value =>
matchValue(value)
(literal => literal)
(read => read.value.value)
(transform => transform.output)
export const write = slot => value =>
newSlotWrite(
newWrite
(getDepth(slot)+1n)
(slot)
(value)
);
export const transform = inValue => fnValue =>
newValueTransform
(newTransformation
(inValue)
(fnValue)
(apply(getVal(fnValue))(getVal(inValue))) // <- call function
);
export const read = slot =>
matchSlot(slot)
(_slotNew => { throw new Error("cannot read empty slot"); })
(write => write.value);
export const newSlot = newSlotNew;
export const toSlot = newSlotWrite;
export const newLiteral = newValueLiteral;
const mkType = makeTypeParser({
extraBracketOperators: [
[':=', ['=:', Slot]],
['*=', ['=*', Value]],
],
extraInfixOperators: [
['===>', Transformation],
],
});
export const ModuleStaticVersioning = [
// slots
["newSlot" , newDynamic(newSlot )(mkType("UUID -> :=a=:" ))],
["write" , newDynamic(write )(mkType(":=a=: -> *=a=* -> :=a=:"))],
["getDepth" , newDynamic(getDepth )(mkType(":=a=: -> Int" ))],
// values
["newLiteral", newDynamic(newLiteral)(mkType("a -> *=a=*" ))],
["read" , newDynamic(read )(mkType(":=a=: -> *=a=*" ))],
["transform" , newDynamic(transform )(mkType("*=a=* -> *=(a->b)=* -> *=b=*"))],
];