ifc-expressions
Version:
Parsing and evaluation of IFC expressions
125 lines (124 loc) • 5.46 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getBuiltinMemberValue = exports.unwrapExpressionValue = exports.inferExpressionValue = exports.toExpressionValue = void 0;
const ContextObjectType_js_1 = require("../type/ContextObjectType.js");
const ArrayType_js_1 = require("../type/ArrayType.js");
const TupleType_js_1 = require("../type/TupleType.js");
const Types_js_1 = require("../type/Types.js");
const TypeDisjunction_js_1 = require("../type/TypeDisjunction.js");
const NumericValue_js_1 = require("../value/NumericValue.js");
const StringValue_js_1 = require("../value/StringValue.js");
const BooleanValue_js_1 = require("../value/BooleanValue.js");
const LogicalValue_js_1 = require("../value/LogicalValue.js");
const ArrayValue_js_1 = require("../value/ArrayValue.js");
const ContextObjectValue_js_1 = require("../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();
}
function toExpressionValue(value, expectedType) {
if (isValue(value)) {
return value;
}
if (expectedType instanceof TypeDisjunction_js_1.TypeDisjunction) {
for (const option of expectedType.getTypes()) {
try {
return toExpressionValue(value, option);
}
catch {
// try next
}
}
}
if (expectedType instanceof ContextObjectType_js_1.ContextObjectType) {
if (typeof value !== "object" || value === null) {
throw new Error(`Expected context object value for type ${expectedType.getName()}`);
}
return new ContextObjectValue_js_1.ContextObjectValue(value, expectedType);
}
if (expectedType instanceof TupleType_js_1.TupleType) {
if (!Array.isArray(value)) {
throw new Error(`Expected tuple value for type ${expectedType.getName()}`);
}
const itemTypes = expectedType.getTypes();
return ArrayValue_js_1.ArrayValue.of(value.map((item, index) => toExpressionValue(item, itemTypes[index] ?? Types_js_1.Type.ANY)));
}
if (expectedType instanceof ArrayType_js_1.ArrayType) {
if (!Array.isArray(value)) {
throw new Error(`Expected array value for type ${expectedType.getName()}`);
}
return ArrayValue_js_1.ArrayValue.of(value.map((item) => toExpressionValue(item, expectedType.getElementType())));
}
if (expectedType.isSameTypeAs(Types_js_1.Type.NUMERIC)) {
return NumericValue_js_1.NumericValue.of(value);
}
if (expectedType.isSameTypeAs(Types_js_1.Type.STRING)) {
return StringValue_js_1.StringValue.of(value);
}
if (expectedType.isSameTypeAs(Types_js_1.Type.BOOLEAN)) {
return BooleanValue_js_1.BooleanValue.of(value);
}
if (expectedType.isSameTypeAs(Types_js_1.Type.LOGICAL)) {
return LogicalValue_js_1.LogicalValue.of(value);
}
if (expectedType.isSameTypeAs(Types_js_1.Type.ARRAY)) {
if (!Array.isArray(value)) {
throw new Error(`Expected array value for type ${expectedType.getName()}`);
}
return ArrayValue_js_1.ArrayValue.of(value.map((item) => inferExpressionValue(item)));
}
return inferExpressionValue(value, expectedType);
}
exports.toExpressionValue = toExpressionValue;
function inferExpressionValue(value, fallbackType = Types_js_1.Type.ANY) {
if (isValue(value)) {
return value;
}
if (typeof value === "number" || typeof value === "string") {
if (typeof value === "number") {
return NumericValue_js_1.NumericValue.of(value);
}
return StringValue_js_1.StringValue.of(value);
}
if (typeof value === "boolean") {
return BooleanValue_js_1.BooleanValue.of(value);
}
if (value === LogicalValue_js_1.LogicalValue.UNKNOWN_VALUE) {
return LogicalValue_js_1.LogicalValue.unknown();
}
if (Array.isArray(value)) {
return ArrayValue_js_1.ArrayValue.of(value.map((item) => inferExpressionValue(item)));
}
if (typeof value === "object" && value !== null) {
return new ContextObjectValue_js_1.ContextObjectValue(value, fallbackType);
}
throw new Error(`Cannot convert runtime context value '${value}' to expression value`);
}
exports.inferExpressionValue = inferExpressionValue;
function unwrapExpressionValue(value) {
const raw = value.getValue();
if (value instanceof ArrayValue_js_1.ArrayValue) {
const arrayValue = raw;
return arrayValue.map((item) => unwrapExpressionValue(item));
}
return raw;
}
exports.unwrapExpressionValue = unwrapExpressionValue;
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];
}
exports.getBuiltinMemberValue = getBuiltinMemberValue;
//# sourceMappingURL=BuiltinRuntimeValueConverter.js.map