diff --git a/lib/structures/struct.js b/lib/structures/struct.js index 51c9d33..35fa11d 100644 --- a/lib/structures/struct.js +++ b/lib/structures/struct.js @@ -1,33 +1,30 @@ import { unit } from "../primitives/unit.js"; import { capitalizeFirstLetter } from "../util/util.js"; -import { newProduct, getLeft, getRight } from "./product.js"; -export const makeConstructor = nParams => { - const internal = (nParams, ret) => { - if (nParams === 0) { +export const makeConstructor = fieldNames => { + const internal = (fieldNames, ret) => { + if (fieldNames.length === 0) { const result = ret(unit); return result; } return nextParam => { - const wrappedName = 'wrapped_' + ret.name; + const [fieldName, ...rest] = fieldNames; + const wrappedName = 'ctor_' + fieldName; const newRet = { - [wrappedName]: inner => newProduct(nextParam)(ret(inner)), + [wrappedName]: inner => ({[fieldName]: nextParam, ...ret(inner)}), }[wrappedName]; - return internal(nParams-1, newRet); + return internal(rest, newRet); } }; const id = x => x; - return internal(nParams, id); + return internal(fieldNames, id); }; export const makeGetters = fieldNames => { - if (fieldNames.length === 0) { - return []; - } - const [fieldName, ...rest] = fieldNames; - const getterName = `get${capitalizeFirstLetter(fieldName)}`; - return [ - { [getterName]: obj => getLeft(obj) }[getterName], - ...makeGetters(rest).map(getter => ({[getter.name]: obj => getter(getRight(obj))}[getter.name])), - ]; + return fieldNames.map(fieldName => { + const getterName = `get${capitalizeFirstLetter(fieldName)}`; + return { + [getterName]: obj => obj[fieldName], + }[getterName]; + }) }; diff --git a/lib/structures/struct.types.js b/lib/structures/struct.types.js index c7c445c..54939e4 100644 --- a/lib/structures/struct.types.js +++ b/lib/structures/struct.types.js @@ -1,40 +1,14 @@ import { getDefaultTypeParser } from "../parser/type_parser.js"; import { newDynamic } from "../primitives/dynamic.js"; -import { Type, Unit } from "../primitives/primitive_types.js"; import { zip } from "../util/util.js"; import { map } from "./list.js"; import { getLeft, getRight } from "./product.js"; import { makeConstructor, makeGetters } from "./struct.js"; -import { fnType, prodType } 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); - }); -}; +import { fnType } from "./type_constructors.types.js"; export const makeConstructorType = type => fields => { if (fields.length === 0) { return type; - // return structType(fields); } const [field, ...rest] = fields; const fieldType = getRight(field); @@ -42,7 +16,6 @@ export const makeConstructorType = type => fields => { }; export const makeGettersTypes = type => fields => { - // const type = structType(fields); return fields.map(field => { const fieldType = getRight(field); return fnType(_ => type)(_ => fieldType); @@ -51,14 +24,11 @@ export const makeGettersTypes = type => fields => { export const makeModuleStruct = type => fields => { const fieldNames = map(fields)(getLeft); - // const type = structType(fields); - const ctor = makeConstructor(fields.length); - const ctorType = makeConstructorType(fields); - const getterTypes = makeGettersTypes(fields); + const ctor = makeConstructor(fieldNames); + const ctorType = makeConstructorType(type)(fields); + const getterTypes = makeGettersTypes(type)(fields); const getters = makeGetters(fieldNames); const module = [ - // ["type", newDynamic(type)(Type)], - // constructor ["ctor", newDynamic(ctor)(ctorType)], @@ -72,6 +42,6 @@ export const makeModuleStruct = type => fields => { const mkType = getDefaultTypeParser(); export const ModuleStruct = [ - ["structType" , newDynamic(structType )(mkType("[String*Type] -> Type" ))], + // ["structType" , newDynamic(structType )(mkType("[String*Type] -> Type" ))], ["makeModuleStruct", newDynamic(makeModuleStruct)(mkType("[String*Type] -> [Dynamic]"))], ]; diff --git a/tests/struct.js b/tests/struct.js new file mode 100644 index 0000000..998e577 --- /dev/null +++ b/tests/struct.js @@ -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);