use of org.drools.modelcompiler.builder.generator.expressiontyper.ExpressionTyper in project drools by kiegroup.
the class ConstraintParser method getDrlxParseResult.
private DrlxParseResult getDrlxParseResult(Class<?> patternType, String bindingId, String expression, DrlxExpression drlx, boolean isPositional) {
Expression drlxExpr = drlx.getExpr();
boolean isEnclosed = false;
while (drlxExpr instanceof EnclosedExpr) {
drlxExpr = ((EnclosedExpr) drlxExpr).getInner();
isEnclosed = true;
}
if (drlxExpr instanceof MethodCallExpr && !((MethodCallExpr) drlxExpr).getScope().isPresent() && ((MethodCallExpr) drlxExpr).getNameAsString().equals("eval")) {
drlxExpr = ((MethodCallExpr) drlxExpr).getArgument(0);
}
String exprId;
if (GENERATE_EXPR_ID) {
exprId = context.getExprId(patternType, expression);
}
if (drlxExpr instanceof BinaryExpr) {
BinaryExpr binaryExpr = (BinaryExpr) drlxExpr;
BinaryExpr.Operator operator = binaryExpr.getOperator();
IndexUtil.ConstraintType decodeConstraintType = DrlxParseUtil.toConstraintType(operator);
final ExpressionTyperContext expressionTyperContext = new ExpressionTyperContext();
final ExpressionTyper expressionTyper = new ExpressionTyper(context, patternType, bindingId, isPositional, expressionTyperContext);
TypedExpressionResult leftTypedExpressionResult = expressionTyper.toTypedExpression(binaryExpr.getLeft());
Optional<TypedExpression> optLeft = leftTypedExpressionResult.getTypedExpression();
if (!optLeft.isPresent()) {
return new DrlxParseFail();
}
List<String> usedDeclarationsOnLeft = drlx.getBind() == null ? null : new ArrayList<>(expressionTyperContext.getUsedDeclarations());
TypedExpressionResult rightExpressionResult = expressionTyper.toTypedExpression(binaryExpr.getRight());
Optional<TypedExpression> optRight = rightExpressionResult.getTypedExpression();
if (!optRight.isPresent()) {
context.addCompilationError(new ParseExpressionErrorResult(drlxExpr));
return new DrlxParseFail();
}
TypedExpression left = optLeft.get();
TypedExpression right = optRight.get();
Expression combo;
if (left.isPrimitive()) {
if (!right.getType().isPrimitive() && !Number.class.isAssignableFrom(right.getType()) && !Boolean.class.isAssignableFrom(right.getType()) && !String.class.isAssignableFrom(right.getType())) {
context.addCompilationError(new InvalidExpressionErrorResult("Comparison operation requires compatible types. Found " + left.getType() + " and " + right.getType()));
return new DrlxParseFail();
}
if (right.getExpression() instanceof StringLiteralExpr) {
right.setExpression(new IntegerLiteralExpr(((StringLiteralExpr) right.getExpression()).asString()));
} else if (right.getExpression() instanceof LiteralStringValueExpr) {
right.setExpression(coerceLiteralExprToType((LiteralStringValueExpr) right.getExpression(), left.getType()));
}
combo = new BinaryExpr(left.getExpression(), right.getExpression(), operator);
} else {
coerceRightExpression(left, right);
switch(operator) {
case EQUALS:
case NOT_EQUALS:
combo = getEqualityExpression(left, right, operator);
break;
default:
if (left.getExpression() == null || right.getExpression() == null) {
context.addCompilationError(new ParseExpressionErrorResult(drlxExpr));
return new DrlxParseFail();
}
combo = handleSpecialComparisonCases(operator, left, right);
}
}
for (Expression e : leftTypedExpressionResult.getPrefixExpressions()) {
combo = new BinaryExpr(e, combo, BinaryExpr.Operator.AND);
}
boolean isBetaNode = false;
if (right.getExpression() instanceof BinaryExpr) {
if (((BinaryExpr) right.getExpression()).getRight() instanceof MethodCallExpr) {
isBetaNode = true;
}
} else if (right.getExpression() instanceof NameExpr) {
isBetaNode = true;
}
if (isEnclosed) {
combo = new EnclosedExpr(combo);
}
return new DrlxParseSuccess(patternType, exprId, bindingId, combo, left.getType()).setDecodeConstraintType(decodeConstraintType).setUsedDeclarations(expressionTyperContext.getUsedDeclarations()).setUsedDeclarationsOnLeft(usedDeclarationsOnLeft).setReactOnProperties(expressionTyperContext.getReactOnProperties()).setLeft(left).setRight(right).setBetaNode(isBetaNode);
}
if (drlxExpr instanceof UnaryExpr) {
UnaryExpr unaryExpr = (UnaryExpr) drlxExpr;
TypedExpressionResult typedExpressionResult = new ExpressionTyper(context, patternType, bindingId, isPositional).toTypedExpression(unaryExpr);
return typedExpressionResult.getTypedExpression().<DrlxParseResult>map(left -> {
return new DrlxParseSuccess(patternType, exprId, bindingId, left.getExpression(), left.getType()).setUsedDeclarations(typedExpressionResult.getUsedDeclarations()).setReactOnProperties(typedExpressionResult.getReactOnProperties()).setLeft(left);
}).orElse(new DrlxParseFail());
}
if (drlxExpr instanceof PointFreeExpr) {
PointFreeExpr pointFreeExpr = (PointFreeExpr) drlxExpr;
TypedExpressionResult typedExpressionResult = new ExpressionTyper(context, patternType, bindingId, isPositional).toTypedExpression(pointFreeExpr);
final Optional<TypedExpression> optTypedExpression = typedExpressionResult.getTypedExpression();
return optTypedExpression.<DrlxParseResult>map(typedExpression -> {
final Expression returnExpression = typedExpression.getExpression();
final Class<?> returnType = typedExpression.getType();
return new DrlxParseSuccess(patternType, exprId, bindingId, returnExpression, returnType).setUsedDeclarations(typedExpressionResult.getUsedDeclarations()).setReactOnProperties(typedExpressionResult.getReactOnProperties()).setLeft(typedExpression.getLeft()).setStatic(typedExpression.isStatic()).setValidExpression(true);
}).orElse(new DrlxParseFail());
}
if (drlxExpr instanceof MethodCallExpr) {
MethodCallExpr methodCallExpr = (MethodCallExpr) drlxExpr;
// when the methodCallExpr will be placed in the model/DSL, any parameter being a "this" need to be implemented as _this by convention.
List<ThisExpr> rewriteThisExprs = recurseCollectArguments(methodCallExpr).stream().filter(ThisExpr.class::isInstance).map(ThisExpr.class::cast).collect(Collectors.toList());
for (ThisExpr t : rewriteThisExprs) {
methodCallExpr.replace(t, new NameExpr("_this"));
}
Optional<MethodDeclaration> functionCall = packageModel.getFunctions().stream().filter(m -> m.getName().equals(methodCallExpr.getName())).findFirst();
if (functionCall.isPresent()) {
Class<?> returnType = DrlxParseUtil.getClassFromContext(context.getTypeResolver(), functionCall.get().getType().asString());
NodeList<Expression> arguments = methodCallExpr.getArguments();
List<String> usedDeclarations = new ArrayList<>();
for (Expression arg : arguments) {
if (arg instanceof NameExpr && !arg.toString().equals("_this")) {
usedDeclarations.add(arg.toString());
} else if (arg instanceof MethodCallExpr) {
TypedExpressionResult typedExpressionResult = new ExpressionTyper(context, null, bindingId, isPositional).toTypedExpression(arg);
usedDeclarations.addAll(typedExpressionResult.getUsedDeclarations());
}
}
return new DrlxParseSuccess(patternType, exprId, bindingId, methodCallExpr, returnType).setUsedDeclarations(usedDeclarations);
} else if (methodCallExpr.getScope().isPresent() && methodCallExpr.getScope().get() instanceof StringLiteralExpr) {
TypedExpressionResult typedExpressionResult = new ExpressionTyper(context, String.class, bindingId, isPositional).toTypedExpression(methodCallExpr);
Optional<TypedExpression> optConverted = typedExpressionResult.getTypedExpression();
return optConverted.<DrlxParseResult>map(converted -> {
return new DrlxParseSuccess(String.class, exprId, bindingId, converted.getExpression(), converted.getType()).setLeft(converted).setUsedDeclarations(typedExpressionResult.getUsedDeclarations());
}).orElse(new DrlxParseFail());
} else if (patternType != null) {
NameExpr _this = new NameExpr("_this");
TypedExpression converted = DrlxParseUtil.toMethodCallWithClassCheck(context, methodCallExpr, bindingId, patternType, context.getTypeResolver());
Expression withThis = DrlxParseUtil.prepend(_this, converted.getExpression());
return new DrlxParseSuccess(patternType, exprId, bindingId, withThis, converted.getType()).setLeft(converted);
} else {
return new DrlxParseSuccess(patternType, exprId, bindingId, methodCallExpr, null);
}
}
if (drlxExpr instanceof FieldAccessExpr) {
FieldAccessExpr fieldCallExpr = (FieldAccessExpr) drlxExpr;
NameExpr _this = new NameExpr("_this");
TypedExpression converted = DrlxParseUtil.toMethodCallWithClassCheck(context, fieldCallExpr, bindingId, patternType, context.getTypeResolver());
Expression withThis = DrlxParseUtil.prepend(_this, converted.getExpression());
return new DrlxParseSuccess(patternType, exprId, bindingId, withThis, converted.getType()).setLeft(converted);
}
if (drlxExpr instanceof NameExpr) {
NameExpr nameExpr = (NameExpr) drlxExpr;
NameExpr _this = new NameExpr("_this");
TypedExpression converted = DrlxParseUtil.toMethodCallWithClassCheck(context, nameExpr, bindingId, patternType, context.getTypeResolver());
Expression withThis = DrlxParseUtil.prepend(_this, converted.getExpression());
if (drlx.getBind() != null) {
return new DrlxParseSuccess(patternType, exprId, bindingId, null, converted.getType()).setLeft(new TypedExpression(withThis, converted.getType())).addReactOnProperty(lcFirst(nameExpr.getNameAsString()));
} else {
return new DrlxParseSuccess(patternType, exprId, bindingId, withThis, converted.getType()).addReactOnProperty(nameExpr.getNameAsString());
}
}
if (drlxExpr instanceof OOPathExpr) {
return new DrlxParseSuccess(patternType, exprId, bindingId, drlxExpr, null);
}
if (drlxExpr instanceof LiteralExpr) {
return new DrlxParseSuccess(patternType, exprId, bindingId, drlxExpr, getLiteralExpressionType(((LiteralExpr) drlxExpr)));
}
// TODO
throw new UnsupportedOperationException("Unknown expression: " + toDrlx(drlxExpr));
}
use of org.drools.modelcompiler.builder.generator.expressiontyper.ExpressionTyper in project drools by kiegroup.
the class ToTypedExpressionTest method pointFreeTest.
@Test
public void pointFreeTest() {
final PointFreeExpr expression = new PointFreeExpr(null, new NameExpr("name"), NodeList.nodeList(new StringLiteralExpr("[A-Z]")), new SimpleName("matches"), false, null, null, null, null);
TypedExpressionResult typedExpressionResult = new ExpressionTyper(ruleContext, Person.class, null, true).toTypedExpression(expression);
final TypedExpression actual = typedExpressionResult.getTypedExpression().get();
final TypedExpression expected = typedResult("eval(org.drools.model.operators.MatchesOperator.INSTANCE, _this.getName(), \"[A-Z]\")", String.class);
assertEquals(expected, actual);
}
Aggregations