UNPKG

ifc-expressions

Version:

Parsing and evaluation of IFC expressions

118 lines (117 loc) 4.57 kB
import { ContextObjectType } from "../type/ContextObjectType.js"; import { ArrayType } from "../type/ArrayType.js"; import { TupleType } from "../type/TupleType.js"; import { Type } from "../type/Types.js"; import { TypeDisjunction } from "../type/TypeDisjunction.js"; import { NumericValue } from "../value/NumericValue.js"; import { StringValue } from "../value/StringValue.js"; import { BooleanValue } from "../value/BooleanValue.js"; import { LogicalValue } from "../value/LogicalValue.js"; import { ArrayValue } from "../value/ArrayValue.js"; import { ContextObjectValue } from "../value/ContextObjectValue.js"; function isValue(candidate) { return (typeof candidate === "object" && candidate !== null && typeof candidate["getValue"] === "function" && typeof candidate["getType"] === "function"); } function normalizeName(name) { return name?.replace(/^\$/, "").toUpperCase(); } export function toExpressionValue(value, expectedType) { if (isValue(value)) { return value; } if (expectedType instanceof TypeDisjunction) { for (const option of expectedType.getTypes()) { try { return toExpressionValue(value, option); } catch { // try next } } } if (expectedType instanceof ContextObjectType) { if (typeof value !== "object" || value === null) { throw new Error(`Expected context object value for type ${expectedType.getName()}`); } return new ContextObjectValue(value, expectedType); } if (expectedType instanceof TupleType) { if (!Array.isArray(value)) { throw new Error(`Expected tuple value for type ${expectedType.getName()}`); } const itemTypes = expectedType.getTypes(); return ArrayValue.of(value.map((item, index) => toExpressionValue(item, itemTypes[index] ?? Type.ANY))); } if (expectedType instanceof ArrayType) { if (!Array.isArray(value)) { throw new Error(`Expected array value for type ${expectedType.getName()}`); } return ArrayValue.of(value.map((item) => toExpressionValue(item, expectedType.getElementType()))); } if (expectedType.isSameTypeAs(Type.NUMERIC)) { return NumericValue.of(value); } if (expectedType.isSameTypeAs(Type.STRING)) { return StringValue.of(value); } if (expectedType.isSameTypeAs(Type.BOOLEAN)) { return BooleanValue.of(value); } if (expectedType.isSameTypeAs(Type.LOGICAL)) { return LogicalValue.of(value); } if (expectedType.isSameTypeAs(Type.ARRAY)) { if (!Array.isArray(value)) { throw new Error(`Expected array value for type ${expectedType.getName()}`); } return ArrayValue.of(value.map((item) => inferExpressionValue(item))); } return inferExpressionValue(value, expectedType); } export function inferExpressionValue(value, fallbackType = Type.ANY) { if (isValue(value)) { return value; } if (typeof value === "number" || typeof value === "string") { if (typeof value === "number") { return NumericValue.of(value); } return StringValue.of(value); } if (typeof value === "boolean") { return BooleanValue.of(value); } if (value === LogicalValue.UNKNOWN_VALUE) { return LogicalValue.unknown(); } if (Array.isArray(value)) { return ArrayValue.of(value.map((item) => inferExpressionValue(item))); } if (typeof value === "object" && value !== null) { return new ContextObjectValue(value, fallbackType); } throw new Error(`Cannot convert runtime context value '${value}' to expression value`); } export function unwrapExpressionValue(value) { const raw = value.getValue(); if (value instanceof ArrayValue) { const arrayValue = raw; return arrayValue.map((item) => unwrapExpressionValue(item)); } return raw; } export function getBuiltinMemberValue(value, memberName) { const objectValue = value.getValue(); if (Object.prototype.hasOwnProperty.call(objectValue, memberName)) { return objectValue[memberName]; } const normalizedMemberName = normalizeName(memberName); const matchingKey = Object.keys(objectValue).find((key) => normalizeName(key) === normalizedMemberName); return typeof matchingKey === "undefined" ? undefined : objectValue[matchingKey]; } //# sourceMappingURL=BuiltinRuntimeValueConverter.js.map