in drools-model/drools-model-codegen/src/main/java/org/drools/model/codegen/execmodel/generator/expressiontyper/ExpressionTyper.java [176:391]
private Optional<TypedExpression> toTypedExpressionRec(Expression drlxExpr) {
Class<?> typeCursor = patternType;
if (drlxExpr instanceof FullyQualifiedInlineCastExpr ) {
return toTypedExpressionRec( transformFullyQualifiedInlineCastExpr( ruleContext.getTypeResolver(), (FullyQualifiedInlineCastExpr) drlxExpr ) );
}
if (drlxExpr instanceof EnclosedExpr) {
Expression inner = ((EnclosedExpr) drlxExpr).getInner();
Optional<TypedExpression> typedExpression = toTypedExpressionRec(inner);
return typedExpression.map(t -> t.cloneWithNewExpression(new EnclosedExpr(t.getExpression())));
}
if (drlxExpr instanceof MethodCallExpr methodExpr) {
Expression expr = methodExpr;
if (isEval(methodExpr.getNameAsString(), methodExpr.getScope(), methodExpr.getArguments())) {
expr = methodExpr.getArgument(0);
}
drlxExpr = expr;
}
if (drlxExpr instanceof NullSafeMethodCallExpr methodExpr) {
Expression expr = methodExpr;
if (isEval(methodExpr.getNameAsString(), methodExpr.getScope(), methodExpr.getArguments())) {
expr = methodExpr.getArgument(0);
}
drlxExpr = expr;
}
if (drlxExpr instanceof UnaryExpr unaryExpr) {
Optional<TypedExpression> optTypedExpr = toTypedExpressionRec(unaryExpr.getExpression());
return optTypedExpr.map(typedExpr -> new TypedExpression( new UnaryExpr( typedExpr.getExpression(), unaryExpr.getOperator() ), typedExpr.getType() ));
}
if (drlxExpr instanceof BinaryExpr binaryExpr) {
BinaryExpr.Operator operator = binaryExpr.getOperator();
Optional<TypedExpression> optLeft = toTypedExpressionRec(binaryExpr.getLeft());
Optional<TypedExpression> optRight = toTypedExpressionRec(binaryExpr.getRight());
if (optLeft.isEmpty() || optRight.isEmpty()) {
return empty();
}
TypedExpression left = optLeft.get();
TypedExpression right = optRight.get();
final BinaryExpr combo;
final Pair<TypedExpression, TypedExpression> numberAndStringCoercionResult =
NumberAndStringArithmeticOperationCoercion.coerceIfNeeded(operator, left, right);
if (numberAndStringCoercionResult.hasLeft()) {
left = numberAndStringCoercionResult.getLeft();
}
if (numberAndStringCoercionResult.hasRight()) {
right = numberAndStringCoercionResult.getRight();
}
combo = new BinaryExpr(left.getExpression(), right.getExpression(), operator);
if (shouldConvertArithmeticBinaryToMethodCall(operator, left.getType(), right.getType())) {
Expression expression = convertArithmeticBinaryToMethodCall(combo, of(typeCursor), ruleContext);
java.lang.reflect.Type binaryType = getBinaryTypeAfterConversion(left.getType(), right.getType());
return of(new TypedExpression(expression, binaryType));
} else {
return of(new TypedExpression(combo, left.getType()));
}
}
if (drlxExpr instanceof HalfBinaryExpr) {
final Expression binaryExpr = trasformHalfBinaryToBinary(drlxExpr, Optional.of(ruleContext));
if (binaryExpr instanceof BinaryExpr && ((BinaryExpr)binaryExpr).getLeft() == drlxExpr) {
throw new CannotTypeExpressionException("left leaf is the same : drlxExpr = " + drlxExpr + ", originalExpression = " + context.getOriginalExpression());
}
return toTypedExpressionRec(binaryExpr);
}
if (drlxExpr instanceof LiteralExpr) {
drlxExpr = normalizeDigit(drlxExpr);
return of(new TypedExpression(drlxExpr, getLiteralExpressionType( ( LiteralExpr ) drlxExpr )));
}
if (drlxExpr instanceof ThisExpr || (drlxExpr instanceof NameExpr && THIS_PLACEHOLDER.equals(printNode(drlxExpr)))) {
return of(new TypedExpression(new NameExpr(THIS_PLACEHOLDER), patternType, "this"));
}
if (drlxExpr instanceof CastExpr castExpr) {
Optional<TypedExpression> optTypedExpr = toTypedExpressionRec(castExpr.getExpression());
return optTypedExpr.map(typedExpr -> new TypedExpression(new CastExpr(castExpr.getType(), typedExpr.getExpression()), getClassFromContext(ruleContext.getTypeResolver(), castExpr.getType().asString())));
}
if (drlxExpr instanceof NameExpr) {
return nameExpr(((NameExpr)drlxExpr).getNameAsString(), typeCursor);
}
if (drlxExpr instanceof FieldAccessExpr || drlxExpr instanceof MethodCallExpr || drlxExpr instanceof ObjectCreationExpr
|| drlxExpr instanceof NullSafeFieldAccessExpr || drlxExpr instanceof NullSafeMethodCallExpr || drlxExpr instanceof MapCreationLiteralExpression || drlxExpr instanceof ListCreationLiteralExpression) {
return toTypedExpressionFromMethodCallOrField(drlxExpr).getTypedExpression();
}
if (drlxExpr instanceof PointFreeExpr pointFreeExpr) {
Optional<TypedExpression> optLeft = toTypedExpressionRec(pointFreeExpr.getLeft());
Optional<TypedExpression> optRight = pointFreeExpr.getRight().size() == 1 ? toTypedExpressionRec(pointFreeExpr.getRight().get( 0 )) : Optional.empty();
OperatorSpec opSpec = getOperatorSpec(pointFreeExpr.getRight(), pointFreeExpr.getOperator());
return optLeft.map(left -> new TypedExpression(opSpec.getExpression( ruleContext, pointFreeExpr, left, this), left.getType())
.setStatic(opSpec.isStatic())
.setLeft(left)
.setRight( optRight.orElse( null ) ) );
}
if (drlxExpr instanceof HalfPointFreeExpr halfPointFreeExpr) {
Expression parentLeft = findLeftLeafOfNameExprTraversingParent(halfPointFreeExpr);
if (parentLeft == halfPointFreeExpr) {
throw new CannotTypeExpressionException("left leaf is the same : halfPointFreeExpr = " + halfPointFreeExpr + ", originalExpression = " + context.getOriginalExpression());
}
Optional<TypedExpression> optLeft = toTypedExpressionRec(parentLeft);
OperatorSpec opSpec = getOperatorSpec(halfPointFreeExpr.getRight(), halfPointFreeExpr.getOperator());
final PointFreeExpr transformedToPointFree =
new PointFreeExpr(halfPointFreeExpr.getTokenRange().orElseThrow(() -> new IllegalStateException("Token range is not present!")),
parentLeft,
halfPointFreeExpr.getRight(),
halfPointFreeExpr.getOperator(),
halfPointFreeExpr.isNegated(),
halfPointFreeExpr.getArg1(),
halfPointFreeExpr.getArg2(),
halfPointFreeExpr.getArg3(),
halfPointFreeExpr.getArg4()
);
return optLeft.map(left ->
new TypedExpression(opSpec.getExpression(ruleContext, transformedToPointFree, left, this), left.getType())
.setStatic(opSpec.isStatic())
.setLeft(left));
}
if (drlxExpr instanceof ArrayAccessExpr arrayAccessExpr) {
if (Map.class.isAssignableFrom( typeCursor )) {
return createMapAccessExpression(arrayAccessExpr.getIndex(), arrayAccessExpr.getName() instanceof ThisExpr ? new NameExpr(THIS_PLACEHOLDER) : arrayAccessExpr.getName(), Object.class);
} else if (arrayAccessExpr.getName() instanceof FieldAccessExpr ) {
Optional<TypedExpression> typedExpression = toTypedExpressionFromMethodCallOrField(drlxExpr).getTypedExpression();
typedExpression.ifPresent(te -> {
final Expression originalExpression = te.getExpression();
DrlxParseUtil.removeRootNode(originalExpression);
});
return typedExpression;
} else {
Expression indexExpr = toTypedExpressionFromMethodCallOrField( arrayAccessExpr.getIndex() )
.getTypedExpression()
.orElseThrow(() -> new NoSuchElementException("TypedExpressionResult doesn't contain TypedExpression!"))
.getExpression();
return toTypedExpressionRec(drlxExpr.asArrayAccessExpr().getName())
.flatMap( te -> transformToArrayOrMapExpressionWithType(indexExpr, te));
}
}
if (drlxExpr instanceof InstanceOfExpr instanceOfExpr) {
ruleContext.addInlineCastType(printNode(instanceOfExpr.getExpression()), instanceOfExpr.getType());
return toTypedExpressionRec(instanceOfExpr.getExpression())
.map( e -> new TypedExpression(new InstanceOfExpr(e.getExpression(), instanceOfExpr.getType()), boolean.class) );
}
if (drlxExpr instanceof ClassExpr) {
return of(new TypedExpression(drlxExpr, Class.class));
}
if (drlxExpr instanceof InlineCastExpr) {
return toTypedExpressionFromMethodCallOrField(drlxExpr).getTypedExpression();
}
if (drlxExpr instanceof OOPathExpr) {
Class<?> type = patternType;
for (OOPathChunk chunk : ((OOPathExpr) drlxExpr).getChunks()) {
final String fieldName = chunk.getField().toString();
final TypedExpression callExpr = DrlxParseUtil.nameExprToMethodCallExpr(fieldName, type, null, ruleContext);
if (callExpr == null) {
return empty();
}
Class<?> fieldType = (chunk.getInlineCast() != null)
? DrlxParseUtil.getClassFromContext(ruleContext.getTypeResolver(), chunk.getInlineCast().toString())
: callExpr.getRawClass();
if ( !chunk.isSingleValue() && Iterable.class.isAssignableFrom(fieldType) || isDataSource(fieldType) ) {
type = extractGenericType(type, ((MethodCallExpr) callExpr.getExpression()).getName().toString());
} else {
type = fieldType;
}
}
return of(new TypedExpression(drlxExpr, type));
}
if (drlxExpr instanceof ConditionalExpr) {
return of(new TypedExpression(drlxExpr, Boolean.class));
}
if (drlxExpr.isAssignExpr()) {
AssignExpr assignExpr = drlxExpr.asAssignExpr();
final Expression rightSide = assignExpr.getValue();
return toTypedExpressionRec(rightSide)
.map(e -> {
final AssignExpr newExpression = new AssignExpr(assignExpr.getTarget(), e.getExpression(), assignExpr.getOperator());
return new TypedExpression(newExpression, e.getType());
});
}
throw new UnsupportedOperationException();
}