ifc-expressions
Version:
Parsing and evaluation of IFC expressions
400 lines (399 loc) • 15 kB
JavaScript
import { ContextObjectType } from "../type/ContextObjectType.js";
import { IfcExpressionBuiltinConfigException } from "../error/IfcExpressionBuiltinConfigException.js";
import { Type, Types } from "../type/Types.js";
import { BuiltinRootReferenceExpr } from "../expression/reference/BuiltinRootReferenceExpr.js";
import { ElemObjectReferenceExpr } from "../expression/reference/ElemObjectReferenceExpr.js";
import { PropObjectReferenceExpr } from "../expression/reference/PropObjectReferenceExpr.js";
export function isBuiltinPropertyDefinition(definition) {
return definition?.kind === "property";
}
export function isBuiltinFunctionDefinition(definition) {
return definition?.kind === "function";
}
function normalizeBuiltinName(name) {
return name?.replace(/^\$/, "").toUpperCase();
}
function memberArg(labelKey, labelFallback, summaryKey, summaryFallback) {
return {
label: { key: labelKey, fallback: labelFallback },
documentation: { key: summaryKey, fallback: summaryFallback },
};
}
function createStandardIfcObjectTypes() {
const elementMembers = new Map();
const propertyMembers = new Map();
const propertySetMembers = new Map();
const typeObjectMembers = new Map();
const propertyType = new ContextObjectType(Type.IFC_PROPERTY_REF.getName(), Type.IFC_PROPERTY_REF, propertyMembers);
const propertySetType = new ContextObjectType(Type.IFC_PROPERTY_SET_REF.getName(), Type.IFC_PROPERTY_SET_REF, propertySetMembers);
const typeObjectType = new ContextObjectType(Type.IFC_TYPE_OBJECT_REF.getName(), Type.IFC_TYPE_OBJECT_REF, typeObjectMembers);
const elementType = new ContextObjectType(Type.IFC_ELEMENT_REF.getName(), Type.IFC_ELEMENT_REF, elementMembers);
standardIfcElementMembers({
elementType,
propertyType,
propertySetType,
typeObjectType,
}).forEach((member) => {
elementMembers.set(normalizeBuiltinName(member.name), member);
});
standardIfcPropertyMembers({
elementType,
propertyType,
propertySetType,
typeObjectType,
}).forEach((member) => {
propertyMembers.set(normalizeBuiltinName(member.name), member);
});
standardIfcPropertySetMembers({
elementType,
propertyType,
propertySetType,
typeObjectType,
}).forEach((member) => {
propertySetMembers.set(normalizeBuiltinName(member.name), member);
});
standardIfcTypeObjectMembers({
elementType,
propertyType,
propertySetType,
typeObjectType,
}).forEach((member) => {
typeObjectMembers.set(normalizeBuiltinName(member.name), member);
});
return {
elementType,
propertyType,
propertySetType,
typeObjectType,
};
}
function standardIfcElementMembers(types) {
return [
{
name: "name",
kind: "function",
returnType: Type.STRING,
argumentTypes: [],
documentation: {
key: "builtin.$element.name.summary",
fallback: "name(): name of the current IFC element",
},
},
{
name: "guid",
kind: "function",
returnType: Type.STRING,
argumentTypes: [],
documentation: {
key: "builtin.$element.guid.summary",
fallback: "guid(): globally unique identifier of the current IFC element",
},
},
{
name: "ifcClass",
kind: "function",
returnType: Type.STRING,
argumentTypes: [],
documentation: {
key: "builtin.$element.ifcClass.summary",
fallback: "ifcClass(): IFC class name of the current element",
},
},
{
name: "description",
kind: "function",
returnType: Type.STRING,
argumentTypes: [],
documentation: {
key: "builtin.$element.description.summary",
fallback: "description(): description of the current IFC element",
},
},
{
name: "property",
kind: "function",
returnType: types.propertyType,
argumentTypes: [Type.STRING],
documentation: {
key: "builtin.$element.property.summary",
fallback: "property(name): property of the current IFC element by name",
},
argumentDocumentation: [
memberArg("builtin.$element.property.arg.name.label", "name", "builtin.$element.property.arg.name.summary", "The name of the property to resolve"),
],
},
{
name: "propertySet",
kind: "function",
returnType: types.propertySetType,
argumentTypes: [Type.STRING],
documentation: {
key: "builtin.$element.propertySet.summary",
fallback: "propertySet(name): property set of the current IFC element by name",
},
argumentDocumentation: [
memberArg("builtin.$element.propertySet.arg.name.label", "name", "builtin.$element.propertySet.arg.name.summary", "The name of the property set to resolve"),
],
},
{
name: "type",
kind: "function",
returnType: types.typeObjectType,
argumentTypes: [],
documentation: {
key: "builtin.$element.type.summary",
fallback: "type(): type object of the current IFC element",
},
},
];
}
function standardIfcPropertyMembers(types) {
return [
{
name: "name",
kind: "function",
returnType: Type.STRING,
argumentTypes: [],
documentation: {
key: "builtin.$property.name.summary",
fallback: "name(): name of the current IFC property",
},
},
{
name: "ifcClass",
kind: "function",
returnType: Type.STRING,
argumentTypes: [],
documentation: {
key: "builtin.$property.ifcClass.summary",
fallback: "ifcClass(): IFC class name of the current property",
},
},
{
name: "description",
kind: "function",
returnType: Type.STRING,
argumentTypes: [],
documentation: {
key: "builtin.$property.description.summary",
fallback: "description(): description of the current IFC property",
},
},
{
name: "propertySet",
kind: "function",
returnType: types.propertySetType,
argumentTypes: [],
documentation: {
key: "builtin.$property.propertySet.summary",
fallback: "propertySet(): property set containing the current IFC property",
},
},
{
name: "value",
kind: "function",
returnType: Types.or(Type.STRING, Type.NUMERIC, Type.BOOLEAN, Type.ARRAY),
argumentTypes: [],
documentation: {
key: "builtin.$property.value.summary",
fallback: "value(): value of the current IFC property",
},
},
];
}
function standardIfcPropertySetMembers(types) {
return [
{
name: "name",
kind: "function",
returnType: Type.STRING,
argumentTypes: [],
documentation: {
key: "builtin.$propertySet.name.summary",
fallback: "name(): name of the current IFC property set",
},
},
{
name: "guid",
kind: "function",
returnType: Type.STRING,
argumentTypes: [],
documentation: {
key: "builtin.$propertySet.guid.summary",
fallback: "guid(): globally unique identifier of the current IFC property set",
},
},
{
name: "description",
kind: "function",
returnType: Type.STRING,
argumentTypes: [],
documentation: {
key: "builtin.$propertySet.description.summary",
fallback: "description(): description of the current IFC property set",
},
},
{
name: "property",
kind: "function",
returnType: types.propertyType,
argumentTypes: [Type.STRING],
documentation: {
key: "builtin.$propertySet.property.summary",
fallback: "property(name): property of the current IFC property set by name",
},
argumentDocumentation: [
memberArg("builtin.$propertySet.property.arg.name.label", "name", "builtin.$propertySet.property.arg.name.summary", "The name of the property to resolve"),
],
},
];
}
function standardIfcTypeObjectMembers(types) {
return [
{
name: "name",
kind: "function",
returnType: Type.STRING,
argumentTypes: [],
documentation: {
key: "builtin.$typeObject.name.summary",
fallback: "name(): name of the current IFC type object",
},
},
{
name: "guid",
kind: "function",
returnType: Type.STRING,
argumentTypes: [],
documentation: {
key: "builtin.$typeObject.guid.summary",
fallback: "guid(): globally unique identifier of the current IFC type object",
},
},
{
name: "description",
kind: "function",
returnType: Type.STRING,
argumentTypes: [],
documentation: {
key: "builtin.$typeObject.description.summary",
fallback: "description(): description of the current IFC type object",
},
},
{
name: "property",
kind: "function",
returnType: types.propertyType,
argumentTypes: [Type.STRING],
documentation: {
key: "builtin.$typeObject.property.summary",
fallback: "property(name): property of the current IFC type object by name",
},
argumentDocumentation: [
memberArg("builtin.$typeObject.property.arg.name.label", "name", "builtin.$typeObject.property.arg.name.summary", "The name of the property to resolve"),
],
},
{
name: "propertySet",
kind: "function",
returnType: types.propertySetType,
argumentTypes: [Type.STRING],
documentation: {
key: "builtin.$typeObject.propertySet.summary",
fallback: "propertySet(name): property set of the current IFC type object by name",
},
argumentDocumentation: [
memberArg("builtin.$typeObject.propertySet.arg.name.label", "name", "builtin.$typeObject.propertySet.arg.name.summary", "The name of the property set to resolve"),
],
},
];
}
const standardIfcObjectTypes = createStandardIfcObjectTypes();
export class BuiltinVariableRegistry {
constructor(definitions = []) {
this.builtinVariables = new Map();
definitions.forEach((definition) => this.register(definition));
}
static getDefaultRegistry() {
return this.defaultRegistry;
}
static normalizeName(name) {
return normalizeBuiltinName(name);
}
static isBuiltinVariable(name) {
return this.defaultRegistry.isBuiltinVariable(name);
}
static isReservedName(name) {
return this.defaultRegistry.isReservedName(name);
}
static getDefinition(name) {
return this.defaultRegistry.getDefinition(name);
}
isBuiltinVariable(name) {
return this.builtinVariables.has(BuiltinVariableRegistry.normalizeName(name));
}
isReservedName(name) {
return this.isBuiltinVariable(name);
}
getDefinition(name) {
return this.builtinVariables.get(BuiltinVariableRegistry.normalizeName(name));
}
getDefinitions() {
return [...this.builtinVariables.values()];
}
register(definition) {
const normalizedName = BuiltinVariableRegistry.normalizeName(definition.name);
if (this.builtinVariables.has(normalizedName)) {
throw new IfcExpressionBuiltinConfigException(`cannot register builtin variable with name '${definition.name}': name already in use`);
}
const members = this.registerMembers(definition);
const baseType = definition.type ??
(members.size > 0 ? Type.CONTEXT_OBJECT_REF : Type.ANY);
const resolvedType = members.size > 0
? new ContextObjectType(definition.name, baseType, members)
: baseType;
const createReferenceExpr = definition.createReferenceExpr ??
(() => new BuiltinRootReferenceExpr(definition.name, resolvedType));
this.builtinVariables.set(normalizedName, {
name: definition.name,
type: resolvedType,
documentation: definition.documentation,
members,
createReferenceExpr,
});
}
registerMembers(definition) {
const members = new Map();
definition.members?.forEach((member) => {
const normalizedMemberName = BuiltinVariableRegistry.normalizeName(member.name);
if (members.has(normalizedMemberName)) {
throw new IfcExpressionBuiltinConfigException(`cannot register member '${member.name}' for builtin '${definition.name}': name already in use`);
}
members.set(normalizedMemberName, member);
});
return members;
}
}
BuiltinVariableRegistry.defaultRegistry = new BuiltinVariableRegistry([
{
name: "element",
type: Type.IFC_ELEMENT_REF,
documentation: {
key: "builtin.$element.summary",
fallback: "$element: IFC element from the evaluation context",
},
members: standardIfcElementMembers(standardIfcObjectTypes),
createReferenceExpr: () => new ElemObjectReferenceExpr(),
},
{
name: "property",
type: Type.IFC_PROPERTY_REF,
documentation: {
key: "builtin.$property.summary",
fallback: "$property: IFC property from the evaluation context",
},
members: standardIfcPropertyMembers(standardIfcObjectTypes),
createReferenceExpr: () => new PropObjectReferenceExpr(),
},
]);
//# sourceMappingURL=BuiltinVariableRegistry.js.map