dope2/structures/struct.js

65 lines
1.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Unit } from "../primitives/types.js";
import { unit } from "../primitives/unit.js";
import { capitalizeFirstLetter } from "../util/util.js";
import { newProduct, getLeft, getRight } from "./product.js";
import { fnType, prodType } from "./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 => {
if (fields.length === 0) {
return Unit;
}
const [field, ...rest] = fields;
const fieldType = getRight(field);
return prodType(fieldType)(structType(rest));
};
export const makeConstructor = fields => {
const internal = (nParams, ret) => {
if (nParams === 0) {
const result = ret(unit);
return result;
}
return nextParam => {
const wrappedName = 'wrapped_' + ret.name;
const newRet = {
[wrappedName]: inner => newProduct(nextParam)(ret(inner)),
}[wrappedName];
return internal(nParams-1, newRet);
}
};
const id = x => x;
return internal(fields.length, id);
};
export const makeConstructorType = type => fields => {
if (fields.length === 0) {
return type;
}
const [field, ...rest] = fields;
const fieldType = getRight(field);
return fnType(fieldType)(makeConstructorType(rest));
};
export const makeGetters = fields => {
if (fields.length === 0) {
return [];
}
const [field, ...rest] = fields;
const fieldName = getLeft(field);
const getterName = `get${capitalizeFirstLetter(fieldName)}`;
return [
{ [getterName]: obj => getLeft(obj) }[getterName],
...makeGetters(rest).map(getter => ({[getter.name]: obj => getter(getRight(obj))}[getter.name])),
];
};
export const makeGettersTypes = type => fields => {
return fields.map(field => {
const fieldType = getRight(field);
return fnType(type)(fieldType);
});
};