com.powsybl.dsl.ExpressionDslLoader.groovy Maven / Gradle / Ivy
/**
* Copyright (c) 2017, RTE (http://www.rte-france.com)
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* SPDX-License-Identifier: MPL-2.0
*/
package com.powsybl.dsl
import com.powsybl.commons.PowsyblException
import com.powsybl.dsl.ast.*
import org.codehaus.groovy.control.CompilationFailedException
/**
* @author Geoffroy Jamgotchian {@literal }
*/
class ExpressionDslLoader extends DslLoader {
ExpressionDslLoader(GroovyCodeSource dslSrc) {
super(dslSrc)
}
ExpressionDslLoader(File dslFile) {
super(dslFile)
}
ExpressionDslLoader(String script) {
super(script)
}
static void prepareClosures(Binding binding) {
// operator overloading
for (op in [['plus', 'PLUS'],
['minus', 'MINUS'],
['multiply', 'MULTIPLY'],
['div', 'DIVIDE']]) {
def op0 = op[0]
def op1 = op[1]
// integer
ExpressionNode.metaClass."$op0" = { Integer value ->
ExpressionHelper.newArithmeticBinaryOperator(delegate as ExpressionNode, ExpressionHelper.newIntegerLiteral(value), ArithmeticBinaryOperator."$op1")
}
Integer.metaClass."$op0" = { ExpressionNode value ->
ExpressionHelper.newArithmeticBinaryOperator(ExpressionHelper.newIntegerLiteral(delegate as int), value, ArithmeticBinaryOperator."$op1")
}
// float
ExpressionNode.metaClass."$op0" = { Float value ->
ExpressionHelper.newArithmeticBinaryOperator(delegate as ExpressionNode, ExpressionHelper.newFloatLiteral(value), ArithmeticBinaryOperator."$op1")
}
Float.metaClass."$op0" = { ExpressionNode value ->
ExpressionHelper.newArithmeticBinaryOperator(ExpressionHelper.newFloatLiteral(delegate as float), value, ArithmeticBinaryOperator."$op1")
}
// double
ExpressionNode.metaClass."$op0" = { Double value ->
ExpressionHelper.newArithmeticBinaryOperator(delegate as ExpressionNode, ExpressionHelper.newDoubleLiteral(value), ArithmeticBinaryOperator."$op1")
}
Double.metaClass."$op0" = { ExpressionNode value ->
ExpressionHelper.newArithmeticBinaryOperator(ExpressionHelper.newDoubleLiteral(delegate as double), value, ArithmeticBinaryOperator."$op1")
}
// big decimal
ExpressionNode.metaClass."$op0" = { BigDecimal value ->
ExpressionHelper.newArithmeticBinaryOperator(delegate as ExpressionNode, ExpressionHelper.newBigDecimalLiteral(value), ArithmeticBinaryOperator."$op1")
}
BigDecimal.metaClass."$op0" = { ExpressionNode value ->
ExpressionHelper.newArithmeticBinaryOperator(ExpressionHelper.newBigDecimalLiteral(delegate), value, ArithmeticBinaryOperator."$op1")
}
}
// comparison
Object.metaClass.compareTo2 = { Object value, String op ->
switch (op) {
case ">":
return delegate > value
case ">=":
return delegate >= value
case "<":
return delegate < value
case "<=":
return delegate <= value
case "==":
return delegate == value
case "!=":
return delegate != value
default:
throw createUnexpectedOperatorException(op)
}
}
ExpressionNode.metaClass.compareTo2 = { ExpressionNode value, String op ->
nodeCompareToNode(delegate as ExpressionNode, value, op)
}
ExpressionNode.metaClass.compareTo2 = { Integer value, String op ->
nodeCompareToNode(delegate as ExpressionNode, ExpressionHelper.newIntegerLiteral(value), op)
}
Integer.metaClass.compareTo2 = { ExpressionNode value, String op ->
nodeCompareToNode(ExpressionHelper.newIntegerLiteral(delegate as int), value, op)
}
ExpressionNode.metaClass.compareTo2 = { Float value, String op ->
nodeCompareToNode(delegate as ExpressionNode, ExpressionHelper.newFloatLiteral(value), op)
}
Float.metaClass.compareTo2 = { ExpressionNode value, String op ->
nodeCompareToNode(ExpressionHelper.newFloatLiteral(delegate as float), value, op)
}
ExpressionNode.metaClass.compareTo2 = { Double value, String op ->
nodeCompareToNode(delegate as ExpressionNode, ExpressionHelper.newDoubleLiteral(value), op)
}
Double.metaClass.compareTo2 = { ExpressionNode value, String op ->
nodeCompareToNode(ExpressionHelper.newDoubleLiteral(delegate as double), value, op)
}
ExpressionNode.metaClass.compareTo2 = { BigDecimal value, String op ->
nodeCompareToNode(delegate as ExpressionNode, ExpressionHelper.newBigDecimalLiteral(value), op)
}
BigDecimal.metaClass.compareTo2 = { ExpressionNode value, String op ->
nodeCompareToNode(ExpressionHelper.newBigDecimalLiteral(delegate as BigDecimal), value, op)
}
// boolean
Boolean.metaClass.and2 = { Boolean value ->
delegate && value
}
ExpressionNode.metaClass.and2 = { Boolean value ->
ExpressionHelper.newLogicalBinaryOperator(delegate as ExpressionNode, ExpressionHelper.newBooleanLiteral(value), LogicalBinaryOperator.AND)
}
Boolean.metaClass.and2 = { ExpressionNode value ->
ExpressionHelper.newLogicalBinaryOperator(ExpressionHelper.newBooleanLiteral(delegate as boolean), value, LogicalBinaryOperator.AND)
}
ExpressionNode.metaClass.and2 = { ExpressionNode value ->
ExpressionHelper.newLogicalBinaryOperator(delegate as ExpressionNode, value, LogicalBinaryOperator.AND)
}
Boolean.metaClass.or2 = { Boolean value ->
delegate || value
}
ExpressionNode.metaClass.or2 = { Boolean value ->
ExpressionHelper.newLogicalBinaryOperator(delegate as ExpressionNode, ExpressionHelper.newBooleanLiteral(value), LogicalBinaryOperator.OR)
}
Boolean.metaClass.or2 = { ExpressionNode value ->
ExpressionHelper.newLogicalBinaryOperator(ExpressionHelper.newBooleanLiteral(delegate), value, LogicalBinaryOperator.OR)
}
ExpressionNode.metaClass.or2 = { ExpressionNode value ->
ExpressionHelper.newLogicalBinaryOperator(delegate as ExpressionNode, value, LogicalBinaryOperator.OR)
}
Boolean.metaClass.not = {
!delegate
}
ExpressionNode.metaClass.not = {
ExpressionHelper.newLogicalNotOperator(delegate as ExpressionNode)
}
}
private static ExpressionNode nodeCompareToNode(ExpressionNode left, ExpressionNode right, String op) {
switch (op) {
case ">":
return ExpressionHelper.newComparisonOperator(left, right, ComparisonOperator.GREATER_THAN)
case ">=":
return ExpressionHelper.newComparisonOperator(left, right, ComparisonOperator.GREATER_THAN_OR_EQUALS_TO)
case "<":
return ExpressionHelper.newComparisonOperator(left, right, ComparisonOperator.LESS_THAN)
case "<=":
return ExpressionHelper.newComparisonOperator(left, right, ComparisonOperator.LESS_THAN_OR_EQUALS_TO)
case "==":
return ExpressionHelper.newComparisonOperator(left, right, ComparisonOperator.EQUALS)
case "!=":
return ExpressionHelper.newComparisonOperator(left, right, ComparisonOperator.NOT_EQUALS)
default:
throw createUnexpectedOperatorException(op)
}
}
private static IllegalStateException createUnexpectedOperatorException(String operator) {
return new IllegalStateException("Unexpected operator: " + operator)
}
static ExpressionNode createExpressionNode(Object value) {
if (value instanceof ExpressionNode) {
value
} else if (value instanceof Integer){
ExpressionHelper.newIntegerLiteral(value)
} else if (value instanceof Float){
ExpressionHelper.newFloatLiteral(value)
} else if (value instanceof Double){
ExpressionHelper.newDoubleLiteral(value)
} else if (value instanceof BigDecimal){
ExpressionHelper.newBigDecimalLiteral(value)
} else if (value instanceof Boolean) {
ExpressionHelper.newBooleanLiteral(value)
} else if (value instanceof String) {
ExpressionHelper.newStringLiteral(value)
} else {
throw new IllegalStateException(value?.getClass() as String)
}
}
Object load() {
try {
Binding binding = new Binding()
prepareClosures(binding)
def shell = createShell(binding)
// Check for thread interruption right before beginning the evaluation
if (Thread.currentThread().isInterrupted()) throw new InterruptedException("Execution Interrupted")
def value = shell.evaluate(dslSrc)
createExpressionNode(value)
} catch (CompilationFailedException e) {
throw new PowsyblException(e.getMessage(), e)
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy