Skip to content

Commit

Permalink
DROOLS-1697 Augment FEEL AST node at compilation with standard return…
Browse files Browse the repository at this point in the history
… type (apache#1411)

* Start implement some FEEL node result type

* Implement InfixOpNode.getResultType()

* Add AST node return type inference for QualifiedName node.

* Refactorings and implementation of negated unary test.

* Extending result type support to additional AST nodes.

* Limited support for result type for inner AST nodes in Contexts.

* Rebased

* Complete support for type inference for ContextNode

* Extend AST node return type coverage

* cleanup

* cleanup

* .
  • Loading branch information
tarilabs authored and etirelli committed Aug 12, 2017
1 parent cc3e015 commit 06bc3db
Show file tree
Hide file tree
Showing 28 changed files with 409 additions and 63 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package org.kie.dmn.feel.lang.ast;

import org.antlr.v4.runtime.ParserRuleContext;
import org.kie.dmn.feel.lang.Type;

import java.util.ArrayList;
import java.util.List;
Expand Down Expand Up @@ -95,12 +96,12 @@ public static ForExpressionNode newForExpression(ParserRuleContext ctx, ListNode
return new ForExpressionNode( ctx, list, expr );
}

public static NameRefNode newNameRefNode( ParserRuleContext ctx ) {
return new NameRefNode( ctx );
public static NameRefNode newNameRefNode( ParserRuleContext ctx, Type type ) {
return new NameRefNode( ctx, type );
}

public static QualifiedNameNode newQualifiedNameNode(ParserRuleContext ctx, ArrayList<NameRefNode> parts) {
return new QualifiedNameNode( ctx, parts );
public static QualifiedNameNode newQualifiedNameNode(ParserRuleContext ctx, ArrayList<NameRefNode> parts, Type type ) {
return new QualifiedNameNode( ctx, parts, type );
}

public static IfExpressionNode newIfExpression(ParserRuleContext ctx, BaseNode c, BaseNode t, BaseNode e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,12 @@
import java.util.function.Supplier;

import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.misc.Interval;
import org.kie.dmn.api.feel.runtime.events.FEELEvent;
import org.kie.dmn.api.feel.runtime.events.FEELEvent.Severity;
import org.kie.dmn.feel.lang.EvaluationContext;
import org.kie.dmn.feel.lang.Type;
import org.kie.dmn.feel.lang.impl.EvaluationContextImpl;
import org.kie.dmn.feel.lang.types.BuiltInType;
import org.kie.dmn.feel.parser.feel11.ParserHelper;
import org.kie.dmn.feel.runtime.events.ASTEventBase;
import org.kie.dmn.feel.util.Msg;

Expand All @@ -50,7 +49,7 @@ public BaseNode( ParserRuleContext ctx ) {
this.setEndChar( ctx.getStop().getStopIndex() );
this.setEndLine( ctx.getStop().getLine() );
this.setEndColumn( ctx.getStop().getCharPositionInLine() + ctx.getStop().getText().length() );
this.setText( getOriginalText( ctx ) );
this.setText( ParserHelper.getOriginalText( ctx ) );
}

@Override
Expand Down Expand Up @@ -139,11 +138,4 @@ public Object evaluate(EvaluationContext ctx) {
return null;
}

private String getOriginalText( ParserRuleContext ctx ) {
int a = ctx.start.getStartIndex();
int b = ctx.stop.getStopIndex();
Interval interval = new Interval(a,b);
return ctx.getStart().getInputStream().getText(interval);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import org.antlr.v4.runtime.ParserRuleContext;
import org.kie.dmn.api.feel.runtime.events.FEELEvent.Severity;
import org.kie.dmn.feel.lang.EvaluationContext;
import org.kie.dmn.feel.lang.Type;
import org.kie.dmn.feel.lang.types.BuiltInType;
import org.kie.dmn.feel.util.Msg;

public class BetweenNode
Expand Down Expand Up @@ -88,4 +90,9 @@ public Object evaluate(EvaluationContext ctx) {

return val.compareTo( s ) >= 0 && val.compareTo( e ) <= 0;
}

@Override
public Type getResultType() {
return BuiltInType.BOOLEAN;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

import org.antlr.v4.runtime.ParserRuleContext;
import org.kie.dmn.feel.lang.EvaluationContext;
import org.kie.dmn.feel.lang.Type;
import org.kie.dmn.feel.lang.types.BuiltInType;

public class BooleanNode
extends BaseNode {
Expand All @@ -37,4 +39,9 @@ public Boolean getValue() {
public Object evaluate(EvaluationContext ctx) {
return value;
}

@Override
public Type getResultType() {
return BuiltInType.BOOLEAN;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import org.antlr.v4.runtime.ParserRuleContext;
import org.kie.dmn.feel.lang.EvaluationContext;
import org.kie.dmn.feel.lang.Type;

public class ContextEntryNode
extends BaseNode {
Expand Down Expand Up @@ -59,4 +60,9 @@ public String evaluateName( EvaluationContext ctx ) {
public Object evaluate(EvaluationContext ctx) {
return value.evaluate( ctx );
}

@Override
public Type getResultType() {
return value.getResultType();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@

import org.antlr.v4.runtime.ParserRuleContext;
import org.kie.dmn.feel.lang.EvaluationContext;
import org.kie.dmn.feel.lang.Type;
import org.kie.dmn.feel.lang.impl.MapBackedType;
import org.kie.dmn.feel.lang.types.BuiltInType;
import org.kie.dmn.feel.runtime.functions.CustomFEELFunction;
import org.kie.dmn.feel.runtime.functions.DTInvokerFunction;
import org.kie.dmn.feel.runtime.functions.JavaFunction;
Expand All @@ -29,6 +32,7 @@ public class ContextNode
extends BaseNode {

private List<ContextEntryNode> entries = new ArrayList<>();
private MapBackedType parsedResultType = new MapBackedType();

public ContextNode(ParserRuleContext ctx) {
super( ctx );
Expand All @@ -37,7 +41,9 @@ public ContextNode(ParserRuleContext ctx) {
public ContextNode(ParserRuleContext ctx, ListNode list) {
super( ctx );
for( BaseNode node : list.getElements() ) {
entries.add( (ContextEntryNode) node );
ContextEntryNode entry = (ContextEntryNode) node;
entries.add( entry );
parsedResultType.addField(entry.getName().getText(), entry.getResultType());
}
}

Expand Down Expand Up @@ -75,4 +81,9 @@ public Object evaluate(EvaluationContext ctx) {
}
}

@Override
public Type getResultType() {
return parsedResultType;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

import org.antlr.v4.runtime.ParserRuleContext;
import org.kie.dmn.feel.lang.EvaluationContext;
import org.kie.dmn.feel.lang.Type;
import org.kie.dmn.feel.lang.types.BuiltInType;
import org.kie.dmn.feel.runtime.UnaryTest;

public class DashNode
Expand Down Expand Up @@ -49,4 +51,9 @@ public String toString() {
return "UnaryTest{-}";
}
}

@Override
public Type getResultType() {
return BuiltInType.BOOLEAN;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

import org.antlr.v4.runtime.ParserRuleContext;
import org.kie.dmn.feel.lang.EvaluationContext;
import org.kie.dmn.feel.lang.Type;
import org.kie.dmn.feel.lang.types.BuiltInType;

import java.util.ArrayList;
import java.util.Collections;
Expand Down Expand Up @@ -88,6 +90,11 @@ private boolean nextIteration( EvaluationContext ctx, ForIteration[] ictx ) {
private void setValueIntoContext(EvaluationContext ctx, ForIteration forIteration) {
ctx.setValue( forIteration.getName(), forIteration.getNextValue() );
}

@Override
public Type getResultType() {
return BuiltInType.LIST;
}

private ForIteration[] initializeContexts(EvaluationContext ctx, List<IterationContextNode> iterationContexts) {
ForIteration[] ictx = new ForIteration[iterationContexts.size()];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import org.antlr.v4.runtime.ParserRuleContext;
import org.kie.dmn.api.feel.runtime.events.FEELEvent.Severity;
import org.kie.dmn.feel.lang.EvaluationContext;
import org.kie.dmn.feel.lang.Type;
import org.kie.dmn.feel.lang.types.BuiltInType;
import org.kie.dmn.feel.runtime.functions.CustomFEELFunction;
import org.kie.dmn.feel.runtime.functions.JavaFunction;
import org.kie.dmn.feel.util.Msg;
Expand Down Expand Up @@ -189,5 +191,9 @@ public static Class<?> convertPrimitiveNameToType( String typeName ) {
return null;
}


@Override
public Type getResultType() {
// TODO when built-in type can be parametrized as FUNCTION<type>
return BuiltInType.FUNCTION;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.antlr.v4.runtime.ParserRuleContext;
import org.kie.dmn.api.feel.runtime.events.FEELEvent.Severity;
import org.kie.dmn.feel.lang.EvaluationContext;
import org.kie.dmn.feel.lang.Type;
import org.kie.dmn.feel.runtime.FEELFunction;
import org.kie.dmn.feel.runtime.UnaryTest;
import org.kie.dmn.feel.util.Msg;
Expand Down Expand Up @@ -84,4 +85,8 @@ public Object evaluate(EvaluationContext ctx) {
return null;
}

@Override
public Type getResultType() {
return name.getResultType();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import org.antlr.v4.runtime.ParserRuleContext;
import org.kie.dmn.api.feel.runtime.events.FEELEvent.Severity;
import org.kie.dmn.feel.lang.EvaluationContext;
import org.kie.dmn.feel.lang.Type;
import org.kie.dmn.feel.lang.types.BuiltInType;
import org.kie.dmn.feel.util.Msg;

public class IfExpressionNode
Expand Down Expand Up @@ -72,4 +74,14 @@ public Object evaluate(EvaluationContext ctx) {
ctx.notifyEvt( astEvent(Severity.ERROR, Msg.createMessage(Msg.CONDITION_WAS_NOT_A_BOOLEAN)) );
return null;
}

@Override
public Type getResultType() {
if ( thenExpression.getResultType().equals(elseExpression.getResultType()) ) {
return thenExpression.getResultType();
} else {
return BuiltInType.UNKNOWN;
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import org.antlr.v4.runtime.ParserRuleContext;
import org.kie.dmn.api.feel.runtime.events.FEELEvent.Severity;
import org.kie.dmn.feel.lang.EvaluationContext;
import org.kie.dmn.feel.lang.Type;
import org.kie.dmn.feel.lang.types.BuiltInType;
import org.kie.dmn.feel.runtime.Range;
import org.kie.dmn.feel.runtime.UnaryTest;
import org.kie.dmn.feel.util.Msg;
Expand Down Expand Up @@ -94,4 +96,9 @@ private Boolean in(EvaluationContext ctx, Object value, Object expr) {
return Boolean.FALSE;
}
}

@Override
public Type getResultType() {
return BuiltInType.BOOLEAN;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,47 @@ public void setRight(BaseNode right) {

@Override
public Type getResultType() {
// bellow is not exactly correct, as the result type depends on both
// left and right
return operator.isBoolean() ? BuiltInType.BOOLEAN : this.left.getResultType();
// see FEEL spec Table 45.
if ( operator.isBoolean() ) { return BuiltInType.BOOLEAN; }
switch ( operator ) {
case ADD:
case SUB: {
if ( left.getResultType() == BuiltInType.NUMBER && right.getResultType() == BuiltInType.NUMBER ) {
return BuiltInType.NUMBER;
} else if ( left.getResultType() == BuiltInType.DATE_TIME && right.getResultType() == BuiltInType.DATE_TIME ) {
return BuiltInType.DATE_TIME;
} else if ( left.getResultType() == BuiltInType.TIME && right.getResultType() == BuiltInType.TIME ) {
return BuiltInType.TIME;
} else if ( left.getResultType() == BuiltInType.DURATION || right.getResultType() == BuiltInType.DURATION ) {
if ( left.getResultType() == BuiltInType.DATE_TIME || right.getResultType() == BuiltInType.DATE_TIME ) {
return BuiltInType.DATE_TIME;
} else if ( left.getResultType() == BuiltInType.TIME || right.getResultType() == BuiltInType.TIME ) {
return BuiltInType.TIME;
} else if ( left.getResultType() == BuiltInType.DURATION && right.getResultType() == BuiltInType.DURATION ) {
return BuiltInType.DURATION;
}
} else if ( left.getResultType() == BuiltInType.STRING && right.getResultType() == BuiltInType.STRING ) {
return BuiltInType.STRING;
}
}
case MULT:
case DIV: {
if ( left.getResultType() == BuiltInType.NUMBER && right.getResultType() == BuiltInType.NUMBER ) {
return BuiltInType.NUMBER;
} else if ( left.getResultType() == BuiltInType.DURATION || right.getResultType() == BuiltInType.DURATION ) {
if ( left.getResultType() == BuiltInType.NUMBER || right.getResultType() == BuiltInType.NUMBER ) {
return BuiltInType.NUMBER;
}
}
}
case POW: {
if ( left.getResultType() == BuiltInType.NUMBER && right.getResultType() == BuiltInType.NUMBER ) {
return BuiltInType.NUMBER;
}
}
default:
return BuiltInType.UNKNOWN;
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,9 @@ public Object evaluate(EvaluationContext ctx) {
Type t = type.evaluate( ctx );
return t.isInstanceOf( value );
}

@Override
public Type getResultType() {
return BuiltInType.BOOLEAN;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@

import org.antlr.v4.runtime.ParserRuleContext;
import org.kie.dmn.feel.lang.EvaluationContext;
import org.kie.dmn.feel.lang.Type;
import org.kie.dmn.feel.lang.impl.EvaluationContextImpl;
import org.kie.dmn.feel.lang.types.BuiltInType;

import java.util.ArrayList;
import java.util.List;
Expand Down Expand Up @@ -51,4 +53,9 @@ public void setElements(List<BaseNode> elements) {
public List evaluate(EvaluationContext ctx) {
return elements.stream().map( e -> e != null ? e.evaluate( ctx ) : null ).collect( Collectors.toList() );
}

@Override
public Type getResultType() {
return BuiltInType.LIST;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.antlr.v4.runtime.ParserRuleContext;
import org.kie.dmn.api.feel.runtime.events.FEELEvent;
import org.kie.dmn.feel.lang.EvaluationContext;
import org.kie.dmn.feel.lang.Type;
import org.kie.dmn.feel.lang.impl.FEELEventListenersManager;
import org.kie.dmn.feel.runtime.events.SyntaxErrorEvent;
import org.kie.dmn.feel.runtime.events.UnknownVariableErrorEvent;
Expand All @@ -28,8 +29,11 @@
public class NameRefNode
extends BaseNode {

public NameRefNode(ParserRuleContext ctx) {
private Type resultType;

public NameRefNode(ParserRuleContext ctx, Type type) {
super( ctx );
this.resultType = type;
}

@Override
Expand All @@ -41,4 +45,11 @@ public Object evaluate(EvaluationContext ctx) {
}
return ctx.getValue( varName );
}

@Override
public Type getResultType() {
return resultType;
}


}
Loading

0 comments on commit 06bc3db

Please sign in to comment.