import { makeTypeConstructor } from "../meta/type_constructor.js"; import { makeTypeParser } from "../parser/type_parser.js"; import { apply, newDynamic } from "../primitives/dynamic.js"; import { Dynamic, Int, UUID } from "../primitives/primitive_types.js"; import { makeModuleEnum } from "../structures/enum.types.js"; import { makeModuleStruct } from "../structures/struct.types.js"; export const Slot = makeTypeConstructor("Slot__318d1c1a9336c141336c461c6a3207b0")(0); export const Value = makeTypeConstructor("Value__23fc00a2db1374bd3dc1a0ad2d8517ab")(0); export const Transformation = makeTypeConstructor("Transformation__9eac70d7020c7c45d5a16f3f14b13083")(0); export const Write = makeTypeConstructor("Write__abaef8ddb5c167b5d2cedac111fcefd3")(0); // Enum: Value const [ // constructors [, {i: newValueLiteral}], [, {i: newValueRead}], [, {i: newValueTransform}], // match function [, {i: matchValue}], ] = makeModuleEnum(Value)([ {l: "literal" , r: Dynamic}, {l: "read" , r: Write}, // a 'read' reads the result of a Write {l: "transform", r: Transformation}, ]); // Enum: Slot const [ // constructors [, {i: newSlotNew}], [, {i: newSlotWrite}], // match function [, {i: matchSlot}], ] = makeModuleEnum(Slot)([ {l: "new" , r: UUID }, {l: "write", r: Write}, ]); // Struct: Transformation const [ // constructor [, {i: newTransformation}], // getters // [, {i: getInput}], // [, {i: getFn}], // [, {i: getOutput}], ] = makeModuleStruct(Transformation)([ {l: "input" , r: Value }, {l: "fn" , r: Value }, {l: "output", r: Dynamic}, ]); // Struct: Write const [ // constructor [, {i: newWrite}], // getters // [, {i: getDepth}], // [, {i: getSlot}], // [, {i: getValue}], ] = makeModuleStruct(Write)([ {l: "depth", r: Int }, // <- depth comes first, for performance {l: "slot" , r: Slot }, {l: "value", r: Value}, ]); // 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({ extraPrimitives: [ ["Value", Value], ["Slot" , Slot ], ["Write", Write], ], }); export const ModuleVersioning = [ // slots ["newSlot" , newDynamic(newSlot )(mkType("UUID -> Slot" ))], ["write" , newDynamic(write )(mkType("Slot -> Value -> Slot" ))], ["getDepth" , newDynamic(getDepth )(mkType("Slot -> Int" ))], // values ["newLiteral", newDynamic(newLiteral)(mkType("Dynamic -> Value" ))], ["read" , newDynamic(read )(mkType("Slot -> Value" ))], ["transform" , newDynamic(transform )(mkType("Value -> Value -> Value"))], ];