Files
DiceCloud/app/imports/parser/parseTree/array.ts
2024-04-12 17:05:20 +02:00

73 lines
2.3 KiB
TypeScript

import { serialMap } from '/imports/api/utility/asyncMap';
import constant from '/imports/parser/parseTree/constant';
import ParseNode from '/imports/parser/parseTree/ParseNode';
import ResolveFunction from '/imports/parser/types/ResolveFunction';
import MapFunction from '/imports/parser/types/MapFunction';
import TraverseFunction from '/imports/parser/types/TraverseFunction';
import ToStringFunction from '/imports/parser/types/ToStringFunction';
export type ArrayNode = {
parseType: 'array';
values: ParseNode[];
}
type ArrayFactory = {
create(node: Partial<ArrayNode>): ArrayNode;
fromConstantArray(array: (string | number | boolean | undefined)[]): ArrayNode;
resolve: ResolveFunction<ArrayNode>;
toString: ToStringFunction<ArrayNode>;
traverse: TraverseFunction<ArrayNode>;
map: MapFunction<ArrayNode>;
}
const arrayFactory: ArrayFactory = {
create({ values }: { values: ParseNode[] }) {
return {
parseType: 'array',
values,
};
},
fromConstantArray(constantArray) {
const values = constantArray.map(value => {
if (
typeof value === 'string' ||
typeof value === 'number' ||
typeof value === 'boolean'
) {
return constant.create({ value });
} else {
// Gracefully create an empty constant in the array for unsupported types
return constant.create({ value: 0, isUndefined: true });
}
});
return arrayFactory.create({ values });
},
async resolve(fn, node, scope, context, inputProvider, resolveOthers) {
const values: ParseNode[] = [];
for (const val of node.values) {
const { result } = await resolveOthers(fn, val, scope, context, inputProvider);
values.push(result);
}
return {
result: arrayFactory.create({ values }),
context,
};
},
toString(node, toStringOthers) {
return `[${node.values.map(value => toStringOthers(value)).join(', ')}]`;
},
traverse(node, fn, traverseOthers) {
fn(node);
node.values.forEach(value => traverseOthers(value, fn));
},
async map(node, fn, mapOthers) {
const resultingNode = await fn(node);
if (resultingNode === node) {
node.values = await serialMap(node.values, async value => await mapOthers(value, fn));
}
return resultingNode;
},
}
export default arrayFactory;