simplify 'struct'
This commit is contained in:
parent
43342e90d4
commit
366b1ec4e0
3 changed files with 57 additions and 52 deletions
|
|
@ -1,33 +1,30 @@
|
||||||
import { unit } from "../primitives/unit.js";
|
import { unit } from "../primitives/unit.js";
|
||||||
import { capitalizeFirstLetter } from "../util/util.js";
|
import { capitalizeFirstLetter } from "../util/util.js";
|
||||||
import { newProduct, getLeft, getRight } from "./product.js";
|
|
||||||
|
|
||||||
export const makeConstructor = nParams => {
|
export const makeConstructor = fieldNames => {
|
||||||
const internal = (nParams, ret) => {
|
const internal = (fieldNames, ret) => {
|
||||||
if (nParams === 0) {
|
if (fieldNames.length === 0) {
|
||||||
const result = ret(unit);
|
const result = ret(unit);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
return nextParam => {
|
return nextParam => {
|
||||||
const wrappedName = 'wrapped_' + ret.name;
|
const [fieldName, ...rest] = fieldNames;
|
||||||
|
const wrappedName = 'ctor_' + fieldName;
|
||||||
const newRet = {
|
const newRet = {
|
||||||
[wrappedName]: inner => newProduct(nextParam)(ret(inner)),
|
[wrappedName]: inner => ({[fieldName]: nextParam, ...ret(inner)}),
|
||||||
}[wrappedName];
|
}[wrappedName];
|
||||||
return internal(nParams-1, newRet);
|
return internal(rest, newRet);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const id = x => x;
|
const id = x => x;
|
||||||
return internal(nParams, id);
|
return internal(fieldNames, id);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const makeGetters = fieldNames => {
|
export const makeGetters = fieldNames => {
|
||||||
if (fieldNames.length === 0) {
|
return fieldNames.map(fieldName => {
|
||||||
return [];
|
const getterName = `get${capitalizeFirstLetter(fieldName)}`;
|
||||||
}
|
return {
|
||||||
const [fieldName, ...rest] = fieldNames;
|
[getterName]: obj => obj[fieldName],
|
||||||
const getterName = `get${capitalizeFirstLetter(fieldName)}`;
|
}[getterName];
|
||||||
return [
|
})
|
||||||
{ [getterName]: obj => getLeft(obj) }[getterName],
|
|
||||||
...makeGetters(rest).map(getter => ({[getter.name]: obj => getter(getRight(obj))}[getter.name])),
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,40 +1,14 @@
|
||||||
import { getDefaultTypeParser } from "../parser/type_parser.js";
|
import { getDefaultTypeParser } from "../parser/type_parser.js";
|
||||||
import { newDynamic } from "../primitives/dynamic.js";
|
import { newDynamic } from "../primitives/dynamic.js";
|
||||||
import { Type, Unit } from "../primitives/primitive_types.js";
|
|
||||||
import { zip } from "../util/util.js";
|
import { zip } from "../util/util.js";
|
||||||
import { map } from "./list.js";
|
import { map } from "./list.js";
|
||||||
import { getLeft, getRight } from "./product.js";
|
import { getLeft, getRight } from "./product.js";
|
||||||
import { makeConstructor, makeGetters } from "./struct.js";
|
import { makeConstructor, makeGetters } from "./struct.js";
|
||||||
import { fnType, prodType } from "./type_constructors.types.js";
|
import { fnType } from "./type_constructors.types.js";
|
||||||
|
|
||||||
|
|
||||||
// 'fields' is an array of (name: string, type: Type) pairs.
|
|
||||||
// e.g.:
|
|
||||||
// [{l: "x", r: Double}, {l: "y", r: Double}]
|
|
||||||
// results in the type (Double × (Double × Unit))
|
|
||||||
|
|
||||||
export const structType = (fields, rootSelf) => {
|
|
||||||
// console.log("structType..", fields);
|
|
||||||
if (fields.length === 0) {
|
|
||||||
return Unit;
|
|
||||||
}
|
|
||||||
const [field, ...rest] = fields;
|
|
||||||
const fieldType = getRight(field);
|
|
||||||
return prodType
|
|
||||||
(self => {
|
|
||||||
// console.log("requested left type (of structType)")
|
|
||||||
return fieldType(rootSelf || self);
|
|
||||||
})
|
|
||||||
(self => {
|
|
||||||
// console.log("requested right type (of structType)")
|
|
||||||
return structType(rest, self);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const makeConstructorType = type => fields => {
|
export const makeConstructorType = type => fields => {
|
||||||
if (fields.length === 0) {
|
if (fields.length === 0) {
|
||||||
return type;
|
return type;
|
||||||
// return structType(fields);
|
|
||||||
}
|
}
|
||||||
const [field, ...rest] = fields;
|
const [field, ...rest] = fields;
|
||||||
const fieldType = getRight(field);
|
const fieldType = getRight(field);
|
||||||
|
|
@ -42,7 +16,6 @@ export const makeConstructorType = type => fields => {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const makeGettersTypes = type => fields => {
|
export const makeGettersTypes = type => fields => {
|
||||||
// const type = structType(fields);
|
|
||||||
return fields.map(field => {
|
return fields.map(field => {
|
||||||
const fieldType = getRight(field);
|
const fieldType = getRight(field);
|
||||||
return fnType(_ => type)(_ => fieldType);
|
return fnType(_ => type)(_ => fieldType);
|
||||||
|
|
@ -51,14 +24,11 @@ export const makeGettersTypes = type => fields => {
|
||||||
|
|
||||||
export const makeModuleStruct = type => fields => {
|
export const makeModuleStruct = type => fields => {
|
||||||
const fieldNames = map(fields)(getLeft);
|
const fieldNames = map(fields)(getLeft);
|
||||||
// const type = structType(fields);
|
const ctor = makeConstructor(fieldNames);
|
||||||
const ctor = makeConstructor(fields.length);
|
const ctorType = makeConstructorType(type)(fields);
|
||||||
const ctorType = makeConstructorType(fields);
|
const getterTypes = makeGettersTypes(type)(fields);
|
||||||
const getterTypes = makeGettersTypes(fields);
|
|
||||||
const getters = makeGetters(fieldNames);
|
const getters = makeGetters(fieldNames);
|
||||||
const module = [
|
const module = [
|
||||||
// ["type", newDynamic(type)(Type)],
|
|
||||||
|
|
||||||
// constructor
|
// constructor
|
||||||
["ctor", newDynamic(ctor)(ctorType)],
|
["ctor", newDynamic(ctor)(ctorType)],
|
||||||
|
|
||||||
|
|
@ -72,6 +42,6 @@ export const makeModuleStruct = type => fields => {
|
||||||
const mkType = getDefaultTypeParser();
|
const mkType = getDefaultTypeParser();
|
||||||
|
|
||||||
export const ModuleStruct = [
|
export const ModuleStruct = [
|
||||||
["structType" , newDynamic(structType )(mkType("[String*Type] -> Type" ))],
|
// ["structType" , newDynamic(structType )(mkType("[String*Type] -> Type" ))],
|
||||||
["makeModuleStruct", newDynamic(makeModuleStruct)(mkType("[String*Type] -> [Dynamic]"))],
|
["makeModuleStruct", newDynamic(makeModuleStruct)(mkType("[String*Type] -> [Dynamic]"))],
|
||||||
];
|
];
|
||||||
|
|
|
||||||
38
tests/struct.js
Normal file
38
tests/struct.js
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
import assert from "node:assert";
|
||||||
|
|
||||||
|
import { makeTypeConstructor } from "../lib/meta/type_constructor.js";
|
||||||
|
import { Bool, Char, Int } from "../lib/primitives/primitive_types.js";
|
||||||
|
import { makeModuleStruct } from "../lib/structures/struct.types.js";
|
||||||
|
import { lsType } from "../lib/structures/type_constructors.types.js";
|
||||||
|
|
||||||
|
|
||||||
|
const symbolPerson = "Person__22a59ca589b4a7efdbe20b52f380e50f";
|
||||||
|
|
||||||
|
const Person = makeTypeConstructor(symbolPerson)(0);
|
||||||
|
|
||||||
|
const fields = [
|
||||||
|
{l: "name", r: lsType(_ => Char)},
|
||||||
|
{l: "age", r: Int},
|
||||||
|
{l: "isMale", r: Bool},
|
||||||
|
];
|
||||||
|
|
||||||
|
const [
|
||||||
|
[, {i: newPerson}],
|
||||||
|
[, {i: getName}],
|
||||||
|
[, {i: getAge}],
|
||||||
|
[, {i: getIsMale}],
|
||||||
|
] = makeModuleStruct(Person)(fields);
|
||||||
|
|
||||||
|
const expectedName = "billy";
|
||||||
|
const expectedAge = 99;
|
||||||
|
const expectedIsMale = true;
|
||||||
|
|
||||||
|
const billy = newPerson(expectedName)(expectedAge)(expectedIsMale);
|
||||||
|
|
||||||
|
const actualName = getName(billy);
|
||||||
|
const actualAge = getAge(billy);
|
||||||
|
const actualIsMale = getIsMale(billy);
|
||||||
|
|
||||||
|
assert.equal(actualName, expectedName);
|
||||||
|
assert.equal(actualAge, expectedAge);
|
||||||
|
assert.equal(actualIsMale, expectedIsMale);
|
||||||
Loading…
Add table
Add a link
Reference in a new issue