@Override public DirectCompilerResult visit(InNode n) { DirectCompilerResult value = n.getValue().accept(this); DirectCompilerResult exprs = n.getExprs().accept(this); if (exprs.resultType == BuiltInType.LIST) { return DirectCompilerResult.of( Expressions.exists(exprs.getExpression(), value.getExpression()), BuiltInType.BOOLEAN).withFD(value).withFD(exprs); } else if (exprs.resultType == BuiltInType.RANGE) { return DirectCompilerResult.of( Expressions.includes(exprs.getExpression(), value.getExpression()), BuiltInType.BOOLEAN).withFD(value).withFD(exprs); } else { // this should be turned into a tree rewrite return DirectCompilerResult.of( Expressions.exists(exprs.getExpression(), value.getExpression()), BuiltInType.BOOLEAN).withFD(value).withFD(exprs); } }
@Override public DirectCompilerResult visitCondAnd(FEEL_1_1Parser.CondAndContext ctx) { DirectCompilerResult left = visit( ctx.left ); DirectCompilerResult right = visit( ctx.right ); MethodCallExpr result = new MethodCallExpr(null, "and"); result.addArgument(left.getExpression()); result.addArgument(right.getExpression()); return DirectCompilerResult.of(result, BuiltInType.BOOLEAN).withFD(left).withFD(right); }
@Override public DirectCompilerResult visit(FunctionInvocationNode n) { DirectCompilerResult functionName = n.getName().accept(this); DirectCompilerResult params = n.getParams().accept(this); return DirectCompilerResult.of( Expressions.invoke(functionName.getExpression(), params.getExpression()), functionName.resultType) .withFD(functionName) .withFD(params); }
@Override public DirectCompilerResult visit(NamedParameterNode n) { DirectCompilerResult name = n.getName().accept(this); DirectCompilerResult expr = n.getExpression().accept(this); return DirectCompilerResult.of( Expressions.namedParameter(name.getExpression(), expr.getExpression()), BuiltInType.UNKNOWN).withFD(name).withFD(expr); }
@Override public DirectCompilerResult visitCondOr(FEEL_1_1Parser.CondOrContext ctx) { DirectCompilerResult left = visit( ctx.left ); DirectCompilerResult right = visit( ctx.right ); MethodCallExpr result = new MethodCallExpr(null, "or"); result.addArgument(left.getExpression()); result.addArgument(right.getExpression()); return DirectCompilerResult.of(result, BuiltInType.BOOLEAN).withFD(left).withFD(right); }
@Override public DirectCompilerResult visitRelExpressionBetween(FEEL_1_1Parser.RelExpressionBetweenContext ctx) { DirectCompilerResult value = visit(ctx.val); DirectCompilerResult start = visit(ctx.start); DirectCompilerResult end = visit(ctx.end); MethodCallExpr betweenCall = new MethodCallExpr(null, "between"); betweenCall.addArgument(new NameExpr("feelExprCtx")); betweenCall.addArgument(value.getExpression()); betweenCall.addArgument(start.getExpression()); betweenCall.addArgument(end.getExpression()); return DirectCompilerResult.of(betweenCall, BuiltInType.BOOLEAN).withFD(value).withFD(start).withFD(end); }
@Override public DirectCompilerResult visit(BetweenNode n) { DirectCompilerResult value = n.getValue().accept(this); DirectCompilerResult start = n.getStart().accept(this); DirectCompilerResult end = n.getEnd().accept(this); return DirectCompilerResult.of( Expressions.between( value.getExpression(), start.getExpression(), end.getExpression()), BuiltInType.BOOLEAN) .withFD(value) .withFD(start) .withFD(end); }
@Override public DirectCompilerResult visit(FunctionDefNode n) { MethodCallExpr list = Expressions.list(); n.getFormalParameters() .stream() .map(fp -> fp.accept(this)) .map(DirectCompilerResult::getExpression) .forEach(list::addArgument); if (n.isExternal()) { List<String> paramNames = n.getFormalParameters().stream() .map(BaseNode::getText) .collect(Collectors.toList()); return Functions.declaration( n, list, Functions.external(paramNames, n.getBody())); } else { DirectCompilerResult body = n.getBody().accept(this); return Functions.declaration(n, list, body.getExpression()).withFD(body); } }
@Override public DirectCompilerResult visit(InfixOpNode n) { DirectCompilerResult left = n.getLeft().accept(this); DirectCompilerResult right = n.getRight().accept(this); MethodCallExpr expr = Expressions.binary( n.getOperator(), left.getExpression(), right.getExpression()); return DirectCompilerResult.of(expr, BuiltInType.UNKNOWN).withFD(left).withFD(right); }
private DirectCompilerResult buildFunctionCall(ParserRuleContext ctx, DirectCompilerResult name, ParseTree params) { DirectCompilerResult parameters = visit(params); MethodCallExpr invokeCall = new MethodCallExpr(new NameExpr(CompiledFEELSupport.class.getSimpleName()), "invoke"); invokeCall.addArgument(new NameExpr("feelExprCtx")); invokeCall.addArgument(name.getExpression()); invokeCall.addArgument(parameters.getExpression()); return DirectCompilerResult.of(invokeCall, name.resultType).withFD(name).withFD(parameters); }
@Override public DirectCompilerResult visit(PathExpressionNode n) { DirectCompilerResult expr = n.getExpression().accept(this); BaseNode nameNode = n.getName(); if (nameNode instanceof QualifiedNameNode) { QualifiedNameNode qualifiedNameNode = (QualifiedNameNode) n.getName(); List<Expression> exprs = qualifiedNameNode.getParts().stream() .map(name -> new StringLiteralExpr(name.getText())) .collect(Collectors.toList()); return DirectCompilerResult.of( Expressions.path(expr.getExpression(), exprs), // here we could still try to infer the result type, but presently use ANY BuiltInType.UNKNOWN).withFD(expr); } else { return DirectCompilerResult.of( Expressions.path(expr.getExpression(), new StringLiteralExpr(nameNode.getText())), // here we could still try to infer the result type, but presently use ANY BuiltInType.UNKNOWN).withFD(expr); } }
@Override public DirectCompilerResult visit(FilterExpressionNode n) { DirectCompilerResult expr = n.getExpression().accept(this); DirectCompilerResult filter = n.getFilter().accept(this); Expressions.NamedLambda lambda = Expressions.namedLambda(filter.getExpression(), n.getFilter().getText()); DirectCompilerResult r = DirectCompilerResult.of( Expressions.filter(expr.getExpression(), lambda.name()), // here we could still try to infer the result type, but presently use ANY BuiltInType.UNKNOWN).withFD(expr).withFD(filter); r.addFieldDesclaration(lambda.field()); return r; }
@Override public DirectCompilerResult visit(ListNode n) { MethodCallExpr list = Expressions.list(); DirectCompilerResult result = DirectCompilerResult.of(list, BuiltInType.LIST); for (BaseNode e : n.getElements()) { DirectCompilerResult r = e.accept(this); result.withFD(r.getFieldDeclarations()); list.addArgument(r.getExpression()); } return result; }
private DirectCompilerResult telescopePathAccessor(DirectCompilerResult scopeExpr, List<String> names) { MethodCallExpr pathCall = new MethodCallExpr(new NameExpr(CompiledFEELSupport.class.getSimpleName()), "path"); pathCall.addArgument(new NameExpr("feelExprCtx")); pathCall.addArgument(scopeExpr.getExpression()); MethodCallExpr filterPathCall = new MethodCallExpr(pathCall, "with"); for (String n : names) { filterPathCall.addArgument(new StringLiteralExpr(n)); } // here I could still try to infer the result type, but presently use ANY return DirectCompilerResult.of(filterPathCall, BuiltInType.UNKNOWN).withFD(scopeExpr); }
@Override public DirectCompilerResult visit(IfExpressionNode n) { DirectCompilerResult condition = n.getCondition().accept(this); DirectCompilerResult thenExpr = n.getThenExpression().accept(this); DirectCompilerResult elseExpr = n.getElseExpression().accept(this); return DirectCompilerResult.of( new ConditionalExpr( new BinaryExpr( Expressions.nativeInstanceOf( Constants.BooleanT, condition.getExpression()), Expressions.reflectiveCastTo( Constants.BooleanT, condition.getExpression()), BinaryExpr.Operator.AND), new EnclosedExpr(thenExpr.getExpression()), new EnclosedExpr(elseExpr.getExpression())), thenExpr.resultType // should find common type between then/else ).withFD(condition).withFD(thenExpr).withFD(elseExpr); }
private DirectCompilerResult declareInternalFunction(ExpressionContext bodyCtx, FEEL_1_1Parser.FormalParametersContext parametersCtx) { DirectCompilerResult body = visit(bodyCtx); DirectCompilerResult parameters = parametersCtx == null? null : visit(parametersCtx); ObjectCreationExpr functionDefExpr = new ObjectCreationExpr(); functionDefExpr.setType(TYPE_CUSTOM_FEEL_FUNCTION); functionDefExpr.addArgument(ANONYMOUS_STRING_LITERAL); functionDefExpr.addArgument((parameters != null) ? parameters.getExpression() : EMPTY_LIST); functionDefExpr.addArgument(anonFunctionEvaluationContext2Object(body.getExpression())); functionDefExpr.addArgument(new MethodCallExpr(new NameExpr("feelExprCtx"), "current")); DirectCompilerResult result = DirectCompilerResult.of(functionDefExpr, BuiltInType.FUNCTION).withFD(body); if (parameters != null) { result.withFD(parameters); } return result; }
@Override public DirectCompilerResult visitFilterPathExpression(FEEL_1_1Parser.FilterPathExpressionContext ctx) { if (ctx.filter != null) { DirectCompilerResult expr = visit(ctx.filterPathExpression()); DirectCompilerResult filter = visit(ctx.expression()); MethodCallExpr filterCall = new MethodCallExpr(new NameExpr(CompiledFEELSupport.class.getSimpleName()), "filter"); filterCall.addArgument(new NameExpr("feelExprCtx")); filterCall.addArgument(expr.getExpression()); MethodCallExpr filterWithCall = new MethodCallExpr(filterCall, "with"); // if (filter.resultType != BuiltInType.BOOLEAN) { // // Then is the case Table 54: Semantics of lists, ROW: e1 is a list and e2 is an integer (0 scale number) // filterWithCall.addArgument(filter.getExpression()); // } else // { // Then is the case Table 54: Semantics of lists, ROW: e1 is a list and type(FEEL(e2 , s')) is boolean // currently delegated to runtime instead: Expression anonFunctionClass = anonFunctionEvaluationContext2Object(filter.getExpression()); filterWithCall.addArgument(anonFunctionClass); // } return DirectCompilerResult.of(filterWithCall, BuiltInType.UNKNOWN).withFD(expr).withFD(filter); } else if (ctx.qualifiedName() != null) { DirectCompilerResult expr = visit(ctx.filterPathExpression()); List<String> names = ctx.qualifiedName().nameRef().stream().map(nameRefContext -> ParserHelper.getOriginalText(nameRefContext)).collect(Collectors.toList()); return telescopePathAccessor(expr, names); } else { return visit(ctx.unaryExpression()); } }
@Override public DirectCompilerResult visit(UnaryTestNode n) { DirectCompilerResult value = n.getValue().accept(this); Expression expr = Expressions.unary(n.getOperator(), value.getExpression()); Expressions.NamedLambda namedLambda = Expressions.namedUnaryLambda(expr, n.getText()); DirectCompilerResult r = DirectCompilerResult.of(namedLambda.name(), BuiltInType.UNARY_TEST) .withFD(value); r.addFieldDesclaration(namedLambda.field()); return r; } }