dope2/structures/list_common.js
2025-03-19 15:43:45 +01:00

69 lines
2 KiB
JavaScript

import { fnType, lsType } from "../type_registry.js";
import {Type, Function} from "../metacircular.js";
import {Int, Byte} from "../primitives/symbols.js";
// 'normal' implementation
const emptyList = {l:[]};
const get = ls => i => ls.l[i];
const put = ls => i => elem => ({l: ls.l.with(Number(i), elem)});
// const push = ls => elem => ({l:ls.l.concat([elem])});
const byteListImpl = {
// specialization
emptyList: new Uint8Array(),
get: ls => i => ls[i],
put: ls => i => elem => {
res = new Uint8Array(ls); // creates copy
res[i] = elem;
return res;
}
}
export const makeListModule = elementType => {
// List<elementType> type depends on elementType
// generating it another time, will give the same type (structurally equivalent):
const ListOfElement = lsType(elementType);
const getFnType1 = fnType({in: Int , out: elementType});
const getFnType = fnType({in: ListOfElement, out: getFnType1});
const putFnType2 = fnType({in: elementType , out: ListOfElement});
const putFnType1 = fnType({in: Int , out: putFnType2});
const putFnType = fnType({in: ListOfElement, out: putFnType1});
// const pushFnType1 = fnType({in: elementType , out: ListOfElement});
// const pushFnType = fnType({in: ListOfElement, out: pushFnType1});
const common = [
{i: ListOfElement, t: Type},
{i: getFnType , t: Function},
{i: getFnType1 , t: Function},
{i: putFnType , t: Function},
{i: putFnType1, t: Function},
{i: putFnType2, t: Function},
// {i: pushFnType , t: Function},
// {i: pushFnType1, t: Function},
];
if (elementType === Byte) {
// specialization: use Uint8Array instead of JS array
return [
...common,
{i: byteListImpl.emptyList , t: ListOfElement},
{i: byteListImpl.get , t: getFnType},
{i: byteListImpl.put , t: putFnType},
];
}
else {
return [
...common,
{i: emptyList , t: ListOfElement},
{i: get , t: getFnType},
{i: put , t: putFnType},
// {i: push , t: pushFnType},
];
}
};