3030import java .io .IOException ;
3131import java .lang .reflect .InvocationTargetException ;
3232import java .lang .reflect .Method ;
33+ import java .util .ArrayList ;
3334import java .util .Arrays ;
35+ import java .util .List ;
3436import java .util .Objects ;
3537
3638/**
@@ -89,12 +91,21 @@ public static Value evalTree(final ExpressionTree tree, final PreprocessorContex
8991 return exp .eval (context );
9092 }
9193
92- private ExpressionTreeElement evalFunction (final ExpressionTreeElement functionElement ,
93- final PreprocessorContext context ) {
94- final AbstractFunction function = ( AbstractFunction ) functionElement . getItem ();
94+ private ExpressionTreeElement evalFunction (
95+ final ExpressionTreeElement treeElement ,
96+ final PreprocessorContext context ) {
9597
96- final int arity = function .getArity ();
97- final Value [] arguments = new Value [arity ];
98+ final AbstractFunction functionElement = (AbstractFunction ) treeElement .getItem ();
99+ final List <ExpressionTreeElement > children = treeElement .extractEffectiveChildren ();
100+
101+ if (!functionElement .getArity ().contains (children .size ())) {
102+ throw context
103+ .makeException (
104+ "Can't find '" + functionElement .getName () + "' for arity " + children .size (), null );
105+ }
106+
107+ final int arity = children .size ();
108+ final List <Value > arguments = new ArrayList <>();
98109 final Class <?>[] methodArguments = new Class <?>[arity + 1 ];
99110 methodArguments [0 ] = PreprocessorContext .class ;
100111
@@ -112,27 +123,27 @@ private ExpressionTreeElement evalFunction(final ExpressionTreeElement functionE
112123
113124 for (int i = 0 ; i < arity ; i ++) {
114125 final ExpressionTreeElement item =
115- this .calculateTreeElement (functionElement . getChildForIndex (i ), context );
126+ this .calculateTreeElement (children . get (i ), context );
116127
117128 final ExpressionItem itemValue = item .getItem ();
118129
119130 if (itemValue instanceof Value ) {
120- arguments [ i ] = ( Value ) itemValue ;
131+ arguments . add (( Value ) itemValue ) ;
121132 } else {
122133 throw context .makeException (
123- "[Expression]Wrong argument type detected for the '" + function .getName () +
134+ "[Expression]Wrong argument type detected for the '" + functionElement .getName () +
124135 "' function" , null );
125136 }
126137 }
127138
128- final ValueType [][] allowedSignatures = function .getAllowedArgumentTypes ();
129- ValueType [] allowed = null ;
130- for (final ValueType [] current : allowedSignatures ) {
139+ final List < List < ValueType >> allowedSignatures = functionElement .getAllowedArgumentTypes ();
140+ List < ValueType > allowed = null ;
141+ for (final List < ValueType > current : allowedSignatures ) {
131142 boolean allCompatible = true ;
132143
133144 int thatIndex = 0 ;
134145 for (final ValueType type : current ) {
135- if (!type .isCompatible (arguments [ thatIndex ] .getType ())) {
146+ if (!type .isCompatible (arguments . get ( thatIndex ) .getType ())) {
136147 allCompatible = false ;
137148 break ;
138149 }
@@ -150,11 +161,12 @@ private ExpressionTreeElement evalFunction(final ExpressionTreeElement functionE
150161
151162 if (allowed == null ) {
152163 throw context .makeException (
153- "[Expression]Unsupported argument detected for '" + function .getName () + '\'' , null );
164+ "[Expression]Unsupported argument detected for '" + functionElement .getName () + '\'' ,
165+ null );
154166 }
155167
156- if (function instanceof FunctionDefinedByUser ) {
157- final FunctionDefinedByUser userFunction = (FunctionDefinedByUser ) function ;
168+ if (functionElement instanceof FunctionDefinedByUser ) {
169+ final FunctionDefinedByUser userFunction = (FunctionDefinedByUser ) functionElement ;
158170 try {
159171 return new ExpressionTreeElement (userFunction .execute (context , arguments ), stack , sources );
160172 } catch (Exception unexpected ) {
@@ -164,15 +176,16 @@ private ExpressionTreeElement evalFunction(final ExpressionTreeElement functionE
164176 }
165177 } else {
166178 try {
167- final Method method = function .getClass ().getMethod (signature .toString (), methodArguments );
179+ final Method method =
180+ functionElement .getClass ().getMethod (signature .toString (), methodArguments );
168181
169182 final Object [] callArgs = new Object [arity + 1 ];
170183 callArgs [0 ] = context ;
171- System .arraycopy (arguments , 0 , callArgs , 1 , arity );
184+ System .arraycopy (arguments . toArray () , 0 , callArgs , 1 , arity );
172185
173- final Value result = (Value ) method .invoke (function , callArgs );
186+ final Value result = (Value ) method .invoke (functionElement , callArgs );
174187
175- if (!result .getType ().isCompatible (function .getResultType ())) {
188+ if (!result .getType ().isCompatible (functionElement .getResultType ())) {
176189 throw context .makeException ("[Expression]Unsupported function result detected [" +
177190 result .getType ().getSignature () + ']' , null );
178191 }
@@ -189,7 +202,7 @@ private ExpressionTreeElement evalFunction(final ExpressionTreeElement functionE
189202 }
190203 throw context .makeException (
191204 "[Expression]Can't execute a function method to process data [" +
192- function .getClass ().getName () + '.' + signature + ']' , unexpected );
205+ functionElement .getClass ().getName () + '.' + signature + ']' , unexpected );
193206 }
194207 }
195208 }
@@ -323,7 +336,7 @@ private ExpressionTreeElement calculateTreeElement(final ExpressionTreeElement e
323336 }
324337 break ;
325338 case FUNCTION : {
326- treeElement = evalFunction (element , context );
339+ treeElement = this . evalFunction (element , context );
327340 }
328341 break ;
329342 }
0 commit comments