UNPKG

ifc-expressions

Version:

Parsing and evaluation of IFC expressions

79 lines (78 loc) 4.71 kB
import { Func } from "../Func.js"; import { ExprEvalFunctionEvaluationErrorObj, ExprEvalMissingRequiredFunctionArgumentErrorObj, ExprEvalSpuriousFunctionArgumentErrorObj, ExprEvalStatus, ExprEvalSuccessObj, isExprEvalSuccess, } from "../../ExprEvalResult.js"; import { Type, Types } from "../../../type/Types.js"; import { FuncArgAny } from "../arg/FuncArgAny.js"; import { FuncArgLogicalOrBoolean } from "../arg/FuncArgLogicalOrBoolean.js"; import { ExprKind } from "../../ExprKind.js"; import { SpuriousFunctionArgumentException } from "../../../error/SpuriousFunctionArgumentException.js"; import { MissingFunctionArgumentException } from "../../../error/MissingFunctionArgumentException.js"; import { LogicalValue } from "../../../value/LogicalValue.js"; export class IF extends Func { constructor() { super("IF", [ new FuncArgLogicalOrBoolean(true, IF.ARG_NAME_CONDITION), new FuncArgAny(true, IF.ARG_NAME_THEN), new FuncArgAny(true, IF.ARG_NAME_ELSE), new FuncArgAny(false, IF.ARG_NAME_UNKNOWN), ]); } getReturnType(argumentTypes) { if (argumentTypes.length == 3) { return Types.or(argumentTypes[1], argumentTypes[2]); } if (argumentTypes.length == 4) { return Types.or(argumentTypes[1], argumentTypes[2], argumentTypes[3]); } throw new Error("Unexpected argument types: " + JSON.stringify(argumentTypes)); } checkArgumentTypes(providedArgumentTypes, ctx) { super.checkArgumentTypes(providedArgumentTypes, ctx); //extra check: if our value to be checked is a Logical, the unknownValue must be provided if (providedArgumentTypes[0][1].isSameTypeAs(Type.LOGICAL)) { if (providedArgumentTypes.length < 4) { throw new MissingFunctionArgumentException(this.name, IF.ARG_NAME_UNKNOWN, 3, ctx, `Argument ${IF.ARG_NAME_UNKNOWN} is required if the argument ${IF.ARG_NAME_CONDITION} is of type logical (i.e., can be true, false or unknown)`); } } else if (providedArgumentTypes[0][1].isSameTypeAs(Type.BOOLEAN)) { if (providedArgumentTypes.length > 3) { throw new SpuriousFunctionArgumentException(this.name, IF.ARG_NAME_UNKNOWN, 3, providedArgumentTypes[3][0], `Argument ${IF.ARG_NAME_UNKNOWN} is not allowed if the argument ${IF.ARG_NAME_CONDITION} is of type boolean (i.e., can only be true or false)`); } } } transformArguments(callingExpr, evaluatedArguments) { const cond = evaluatedArguments.get(IF.ARG_NAME_CONDITION); if (isExprEvalSuccess(cond)) { if (cond.result.getType().isSameTypeAs(Type.LOGICAL)) { if (evaluatedArguments.size < 4) { evaluatedArguments.set(IF.ARG_NAME_UNKNOWN, new ExprEvalMissingRequiredFunctionArgumentErrorObj(ExprKind.FUNCTION_ARGUMENTS, `Argument ${IF.ARG_NAME_UNKNOWN} is required if the argument ${IF.ARG_NAME_CONDITION} is of type logical (i.e., can be true, false or unknown)`, this.name, IF.ARG_NAME_UNKNOWN, 3, callingExpr.getTextSpan())); } } else if (cond.result.getType().isSameTypeAs(Type.BOOLEAN)) { if (evaluatedArguments.size > 3) { evaluatedArguments.set(IF.ARG_NAME_UNKNOWN, new ExprEvalSpuriousFunctionArgumentErrorObj(`Argument ${IF.ARG_NAME_UNKNOWN} is not allowed if the argument ${IF.ARG_NAME_CONDITION} is of type boolean (i.e., can only be true or false)`, this.name, IF.ARG_NAME_UNKNOWN, 3, callingExpr.getTextSpan())); } } } } calculateResult(callingExpr, evaluatedArguments) { const condition = evaluatedArguments.get(IF.ARG_NAME_CONDITION); if (condition.isTrue()) { const thenValue = evaluatedArguments.get(IF.ARG_NAME_THEN); return new ExprEvalSuccessObj(thenValue); } else if (condition.isFalse()) { const elseValue = evaluatedArguments.get(IF.ARG_NAME_ELSE); return new ExprEvalSuccessObj(elseValue); } else if (LogicalValue.isUnknown(condition.getValue())) { const unknownValue = evaluatedArguments.get(IF.ARG_NAME_UNKNOWN); return new ExprEvalSuccessObj(unknownValue); } return new ExprEvalFunctionEvaluationErrorObj(ExprKind.FUNCTION, ExprEvalStatus.ERROR, "Cannot handle value of condtition: " + JSON.stringify(condition), this.name, callingExpr.getTextSpan()); } } IF.ARG_NAME_CONDITION = "condition"; IF.ARG_NAME_THEN = "thenValue"; IF.ARG_NAME_ELSE = "elseValue"; IF.ARG_NAME_UNKNOWN = "unknownValue"; //# sourceMappingURL=IF.js.map