interactive prompt can handle polymorphic types
This commit is contained in:
parent
a0e3aa0cb3
commit
4a4983f693
20 changed files with 485 additions and 276 deletions
|
|
@ -1,13 +1,76 @@
|
|||
import { Any } from "../typed.js";
|
||||
import { String } from "./list.js";
|
||||
import { sumType, prodType, fnType } from "./types.js";
|
||||
import { SymbolT, Type } from "../primitives/types.js";
|
||||
import { makeTypeConstructor } from "../type_constructor.js";
|
||||
import { Module, String } from "./list.js";
|
||||
import { prodType, fnType, lsType } from "./types.js";
|
||||
|
||||
function capitalizeFirstLetter(val) {
|
||||
return String(val).charAt(0).toUpperCase() + String(val).slice(1);
|
||||
}
|
||||
|
||||
export const createNominalADT = symbol => variants => {
|
||||
makeTypeConstructor(symbol, 0, )
|
||||
export const createStruct = (typeVars, symbol, fields) => {
|
||||
const makeConstructor = (remainingFields, obj={}) => {
|
||||
if (remainingFields.length===0) {
|
||||
return obj;
|
||||
}
|
||||
const {left: fieldName} = remainingFields[remainingFields.length-1];
|
||||
return v => makeConstructor(
|
||||
remainingFields.slice(0,-1),
|
||||
Object.assign({[fieldName]: v}, obj));
|
||||
};
|
||||
const constructor = makeConstructor(fields);
|
||||
|
||||
const type = makeTypeConstructor(symbol)(typeVars.size);
|
||||
const types = [ type ];
|
||||
const recordFnType = inType => outType => {
|
||||
const fnT = fnType(inType)(outType);
|
||||
types.push(fnT);
|
||||
return fnT;
|
||||
}
|
||||
|
||||
const makeConstructorType = (remainingFields, type) => {
|
||||
if (remainingFields.length===0) {
|
||||
return type;
|
||||
}
|
||||
const {right: fieldType} = remainingFields[remainingFields.length-1];
|
||||
return recordFnType(makeConstructorType(remainingFields.slice(0,-1)))(fieldType);
|
||||
};
|
||||
const constructorType = makeConstructorType(fields);
|
||||
|
||||
const functions = [
|
||||
["constructor", constructor, constructorType],
|
||||
...fields.map(({left: fieldName, right: fieldType}) => {
|
||||
const getterName = 'get'+capitalizeFirstLetter(fieldName);
|
||||
const getter = {
|
||||
// stupid trick to give the JS-function a computed name.
|
||||
// only important for debugging, so it says [Function: getAge] instead of [Function (anonymous)]:
|
||||
[getterName]: obj => obj[fieldName],
|
||||
}[getterName];
|
||||
if (typeVars.has(fieldType)) {
|
||||
// getterFnType = recordFnType(type)(fieldType)
|
||||
}
|
||||
const getterFnType = recordFnType(type)(fieldType);
|
||||
return [fieldName, getter, getterFnType];
|
||||
}),
|
||||
];
|
||||
|
||||
const module = {l:[
|
||||
{i: type, t: Type},
|
||||
|
||||
...functions.flatMap(([_, getter, getterFnType]) => [
|
||||
{i: getter , t: getterFnType},
|
||||
]),
|
||||
|
||||
...types.map(type => ({i: type, t: Type})),
|
||||
]};
|
||||
|
||||
return {
|
||||
module,
|
||||
constructor,
|
||||
functions: Object.fromEntries(functions),
|
||||
};
|
||||
};
|
||||
|
||||
export const createNominalADTFnType =
|
||||
fnType
|
||||
(Any)
|
||||
();
|
||||
export const createNominalADTModuleFnType =
|
||||
fnType(SymbolT)
|
||||
(fnType(lsType(prodType(String)(Type)))
|
||||
(Module));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue