@Override public Type getResultType() { return expression.getResultType(); }
public UnaryTestNode( UnaryOperator op, BaseNode value ) { super(); setText( op.symbol+" "+value.getText() ); this.operator = op; this.value = value; }
@Override public Object evaluate(EvaluationContext ctx) { ctx.notifyEvt( astEvent(Severity.ERROR, Msg.createMessage(Msg.BASE_NODE_EVALUATE_CALLED) ) ); return null; }
private UnaryTest createBooleanUnaryTest( ) { return (context, left) -> { Object right = value.evaluate( context ); if( right instanceof Boolean ) { return (Boolean) right; } else { context.notifyEvt( astEvent(Severity.ERROR, Msg.createMessage(Msg.EXTENDED_UNARY_TEST_MUST_BE_BOOLEAN, left.toString(), value.toString() ) ) ); return Boolean.FALSE; } }; }
@Override public Object evaluate(EvaluationContext ctx) { try { Object o = this.expression.evaluate( ctx ); if ( o instanceof List ) { List list = (List) o; // list of contexts/elements as defined in the spec, page 114 List results = new ArrayList(); for( Object element : list ) { Object r = fetchValue( element ); if( r != null ) { results.add( r ); } } return results; } else { return fetchValue( o ); } } catch ( Exception e ) { ctx.notifyEvt( astEvent(Severity.ERROR, Msg.createMessage(Msg.ERROR_EVALUATING_PATH_EXPRESSION, expression.getText(), name.getText()), e) ); } return null; }
@Test public void testIfExpression() { String inputExpression = "if applicant.age < 18 then \"declined\" else \"accepted\""; BaseNode ifBase = parse( inputExpression ); assertThat( ifBase, is( instanceOf( IfExpressionNode.class ) ) ); assertThat( ifBase.getText(), is( inputExpression ) ); assertThat( ifBase.getResultType(), is( BuiltInType.STRING ) ); IfExpressionNode ifExpr = (IfExpressionNode) ifBase; assertThat( ifExpr.getCondition().getText(), is( "applicant.age < 18" ) ); assertThat( ifExpr.getThenExpression().getText(), is( "\"declined\"" ) ); assertThat( ifExpr.getElseExpression().getText(), is( "\"accepted\"" ) ); }
private void assertLocation(String inputExpression, BaseNode number) { assertThat( number.getText(), is( inputExpression ) ); assertThat( number.getStartChar(), is( 0 ) ); assertThat( number.getStartLine(), is( 1 ) ); assertThat( number.getStartColumn(), is( 0 ) ); assertThat( number.getEndChar(), is( inputExpression.length() - 1 ) ); assertThat( number.getEndLine(), is( 1 ) ); assertThat( number.getEndColumn(), is( inputExpression.length() ) ); }
@Override public DirectCompilerResult visit(ForExpressionNode n) { DirectCompilerResult expr = n.getExpression().accept(this); HashSet<FieldDeclaration> fds = new HashSet<>(); Expressions.NamedLambda namedLambda = Expressions.namedLambda( expr.getExpression(), n.getExpression().getText()); fds.add(namedLambda.field()); fds.addAll(expr.getFieldDeclarations()); List<Expression> expressions = n.getIterationContexts() .stream() .map(iter -> iter.accept(this)) .peek(r -> fds.addAll(r.getFieldDeclarations())) .map(DirectCompilerResult::getExpression) .collect(Collectors.toList()); // .satisfies(expr) return DirectCompilerResult.of( Expressions.ffor(expressions, namedLambda.name()), expr.resultType, fds); }
@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 Object evaluate(EvaluationContext ctx) { // spec says: if FEEL(e1) is true then FEEL(e2) else FEEL(e3) Object cond = this.condition.evaluate( ctx ); if ( cond != null && cond instanceof Boolean && cond == Boolean.TRUE ) { return this.thenExpression.evaluate( ctx ); } else { return this.elseExpression.evaluate( ctx ); } }
return null; Object value = expression.evaluate( ctx ); if( filter.getResultType() != BuiltInType.BOOLEAN ) { Object f = filter.evaluate(new SilentWrappingEvaluationContextImpl(ctx)); // I need to try evaluate filter first, ignoring errors; only if evaluation fails, or is not a Number, it delegates to try `evaluateExpressionsInContext` if (f != null && f instanceof Number) {
public BaseNode rewriteToUnaryEqInExpr(BaseNode node) { if (node instanceof ListNode || node instanceof RangeNode) { return ASTBuilderFactory.newUnaryTestNode( node.getParserRuleContext(), "in", node); } else { return ASTBuilderFactory.newUnaryTestNode( node.getParserRuleContext(), "=", node); } }
@Test public void testParensWithLiteral() { String inputExpression = "(10.5 )"; BaseNode number = parse( inputExpression ); assertThat( number, is( instanceOf( NumberNode.class ) ) ); assertThat( number.getResultType(), is( BuiltInType.NUMBER ) ); assertThat( number.getText(), is( "10.5" ) ); }
@Override public DirectCompilerResult visit(QuantifiedExpressionNode n) { DirectCompilerResult expr = n.getExpression().accept(this); HashSet<FieldDeclaration> fds = new HashSet<>(); Expressions.NamedLambda namedLambda = Expressions.namedLambda( expr.getExpression(), n.getExpression().getText()); fds.add(namedLambda.field()); fds.addAll(expr.getFieldDeclarations()); List<Expression> expressions = n.getIterationContexts() .stream() .map(iter -> iter.accept(this)) .peek(r -> fds.addAll(r.getFieldDeclarations())) .map(DirectCompilerResult::getExpression) .collect(Collectors.toList()); // .satisfies(expr) return DirectCompilerResult.of( Expressions.quantifier(n.getQuantifier(), namedLambda.name(), expressions), expr.resultType, fds); }
@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); } }
if ( name instanceof NameRefNode ) { value = ctx.getValue( name.getText() ); } else if (name instanceof QualifiedNameNode) { QualifiedNameNode qn = (QualifiedNameNode) name; function = (FEELFunction) value; if ( function != null ) { Object[] p = params.getElements().stream().map( e -> e.evaluate( ctx ) ).toArray( Object[]::new ); List<String> functionNameParts = null; if (name instanceof NameRefNode) { functionNameParts = Arrays.asList(name.getText()); } else if (name instanceof QualifiedNameNode) { functionNameParts = Arrays.asList(((QualifiedNameNode) name).getPartsAsStringArray()); return result; } else { ctx.notifyEvt( astEvent(Severity.ERROR, Msg.createMessage(Msg.FUNCTION_NOT_FOUND, name.getText())) ); Object p = params.getElements().get( 0 ).evaluate( ctx ); return ((UnaryTest) value).apply( ctx, p ); } else {
@Override public Object evaluate(EvaluationContext ctx) { return value.evaluate( ctx ); }
private BaseNode rewriteToUnaryTestExpr(BaseNode node) { return ASTBuilderFactory.newUnaryTestNode( node.getParserRuleContext(), "test", node); }
@Test public void testLogicalNegation() { String inputExpression = "not ( true )"; BaseNode neg = parse( inputExpression ); assertThat( neg, is( instanceOf( FunctionInvocationNode.class ) ) ); assertThat( neg.getResultType(), is( BuiltInType.UNKNOWN ) ); assertThat( neg.getText(), is( "not ( true )" ) ); FunctionInvocationNode not = (FunctionInvocationNode) neg; assertThat( not.getParams().getElements().get( 0 ), is( instanceOf( BooleanNode.class ) ) ); assertThat( not.getParams().getElements().get( 0 ).getResultType(), is( BuiltInType.BOOLEAN ) ); assertThat( not.getParams().getElements().get( 0 ).getText(), is( "true" ) ); }
@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; }