Repository: systemml
Updated Branches:
  refs/heads/master 99b1c2e25 -> 49f9eeaa3


[SYSTEMML-2463] Function calls w/ named function arguments

This patch generalizes the existing framework of dml-bodied functions by
optionally allowing named function arguments (and thus, permutations of
input arguments). For function calls without name bindings, we simply
use the argument names of the function signature in declaration order.
During compilation and runtime, we then can always assume named bindings
which simplifies the runtime integration.

Furthermore, this patch also generalizes the function inlining in the
parser and during IPA to be robust with regard to permutations of the
input argument list.


Project: http://git-wip-us.apache.org/repos/asf/systemml/repo
Commit: http://git-wip-us.apache.org/repos/asf/systemml/commit/49f9eeaa
Tree: http://git-wip-us.apache.org/repos/asf/systemml/tree/49f9eeaa
Diff: http://git-wip-us.apache.org/repos/asf/systemml/diff/49f9eeaa

Branch: refs/heads/master
Commit: 49f9eeaa371b6da8c7b22f912d6fcc843da8f5b6
Parents: 99b1c2e
Author: Matthias Boehm <[email protected]>
Authored: Tue Jul 24 22:47:02 2018 -0700
Committer: Matthias Boehm <[email protected]>
Committed: Tue Jul 24 22:47:02 2018 -0700

----------------------------------------------------------------------
 .../java/org/apache/sysml/hops/FunctionOp.java  |  40 ++++---
 .../apache/sysml/hops/cost/CostEstimator.java   |   3 +-
 .../sysml/hops/ipa/IPAPassInlineFunctions.java  |  12 +-
 .../hops/rewrite/RewriteGPUSpecificOps.java     |   4 +-
 .../org/apache/sysml/lops/FunctionCallCP.java   |  41 +++----
 .../org/apache/sysml/parser/DMLTranslator.java  | 116 +++++++++++--------
 .../apache/sysml/parser/FunctionStatement.java  |  15 ++-
 .../org/apache/sysml/parser/StatementBlock.java |  22 ++--
 .../controlprogram/FunctionProgramBlock.java    |  25 ++--
 .../controlprogram/paramserv/PSWorker.java      |   3 +-
 .../controlprogram/paramserv/ParamServer.java   |   3 +-
 .../instructions/cp/EvalNaryCPInstruction.java  |   6 +-
 .../cp/FunctionCallCPInstruction.java           |  41 ++++---
 .../org/apache/sysml/udf/lib/EvalFunction.java  |   7 +-
 .../functions/misc/FunctionPotpourriTest.java   |  48 +++++++-
 .../misc/FunPotpourriNamedArgsMulti.dml         |  36 ++++++
 .../misc/FunPotpourriNamedArgsPartial.dml       |  32 +++++
 .../misc/FunPotpourriNamedArgsSingle.dml        |  34 ++++++
 .../misc/FunPotpourriNamedArgsUnknown1.dml      |  31 +++++
 .../misc/FunPotpourriNamedArgsUnknown2.dml      |  32 +++++
 20 files changed, 407 insertions(+), 144 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/systemml/blob/49f9eeaa/src/main/java/org/apache/sysml/hops/FunctionOp.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/hops/FunctionOp.java 
b/src/main/java/org/apache/sysml/hops/FunctionOp.java
index aedaf81..148b39d 100644
--- a/src/main/java/org/apache/sysml/hops/FunctionOp.java
+++ b/src/main/java/org/apache/sysml/hops/FunctionOp.java
@@ -20,6 +20,7 @@
 package org.apache.sysml.hops;
 
 import java.util.ArrayList;
+import java.util.List;
 
 import org.apache.sysml.api.DMLScript;
 import org.apache.sysml.lops.FunctionCallCP;
@@ -53,7 +54,9 @@ public class FunctionOp extends Hop
        private FunctionType _type = null;
        private String _fnamespace = null;
        private String _fname = null; 
-       private String[] _outputs = null; 
+       
+       private String[] _inputNames = null;  // A,B in C = foo(A=X, B=Y)
+       private String[] _outputNames = null; // C in C = foo(A=X, B=Y)
        private ArrayList<Hop> _outputHops = null;
        private boolean _singleOutFun = false;
        
@@ -61,22 +64,23 @@ public class FunctionOp extends Hop
                //default constructor for clone
        }
 
-       public FunctionOp(FunctionType type, String fnamespace, String fname, 
ArrayList<Hop> finputs, String[] outputs, ArrayList<Hop> outputHops) {
-               this(type, fnamespace, fname, finputs, outputs, false);
+       public FunctionOp(FunctionType type, String fnamespace, String fname, 
String[] inputNames, List<Hop> inputs, String[] outputNames, ArrayList<Hop> 
outputHops) {
+               this(type, fnamespace, fname, inputNames, inputs, outputNames, 
false);
                _outputHops = outputHops;
        }
 
-       public FunctionOp(FunctionType type, String fnamespace, String fname, 
ArrayList<Hop> finputs, String[] outputs, boolean singleOut) 
+       public FunctionOp(FunctionType type, String fnamespace, String fname, 
String[] inputNames, List<Hop> inputs, String[] outputNames, boolean singleOut) 
        {
                super(fnamespace + Program.KEY_DELIM + fname, DataType.UNKNOWN, 
ValueType.UNKNOWN );
                
                _type = type;
                _fnamespace = fnamespace;
                _fname = fname;
-               _outputs = outputs;
+               _inputNames = inputNames;
+               _outputNames = outputNames;
                _singleOutFun = singleOut;
                
-               for( Hop in : finputs ) {
+               for( Hop in : inputs ) {
                        getInput().add(in);
                        in.getParent().add(this);
                }
@@ -107,8 +111,12 @@ public class FunctionOp extends Hop
                return _outputHops;
        }
        
+       public String[] getInputVariableNames() {
+               return _inputNames;
+       }
+       
        public String[] getOutputVariableNames() {
-               return _outputs;
+               return _outputNames;
        }
        
        public FunctionType getFunctionType() {
@@ -264,10 +272,10 @@ public class FunctionOp extends Hop
                ArrayList<Lop> tmp = new ArrayList<>();
                for( Hop in : getInput() )
                        tmp.add( in.constructLops() );
-                
+               
                //construct function call
                Lop fcall = _singleOutFun ? new FunctionCallCPSingle( tmp, 
_fnamespace, _fname, et ) :
-                       new FunctionCallCP(tmp, _fnamespace, _fname, _outputs, 
_outputHops, et);
+                       new FunctionCallCP(tmp, _fnamespace, _fname, 
_inputNames, _outputNames, _outputHops, et);
                setLineNumbers(fcall);
                setLops(fcall);
                
@@ -328,16 +336,14 @@ public class FunctionOp extends Hop
        }
 
        @Override
-       public void refreshSizeInformation()
-       {
+       public void refreshSizeInformation() {
                //do nothing
        }
        
        @Override
        @SuppressWarnings("unchecked")
-       public Object clone() throws CloneNotSupportedException 
-       {
-               FunctionOp ret = new FunctionOp();      
+       public Object clone() throws CloneNotSupportedException {
+               FunctionOp ret = new FunctionOp();
                
                //copy generic attributes
                ret.clone(this, false);
@@ -346,7 +352,8 @@ public class FunctionOp extends Hop
                ret._type = _type;
                ret._fnamespace = _fnamespace;
                ret._fname = _fname;
-               ret._outputs = _outputs.clone();
+               ret._inputNames = (_inputNames!=null) ? _inputNames.clone() : 
null;
+               ret._outputNames = _outputNames.clone();
                if( _outputHops != null )
                        ret._outputHops = (ArrayList<Hop>) _outputHops.clone();
                
@@ -354,8 +361,7 @@ public class FunctionOp extends Hop
        }
        
        @Override
-       public boolean compare( Hop that )
-       {
+       public boolean compare(Hop that) {
                return false;
        }
 }

http://git-wip-us.apache.org/repos/asf/systemml/blob/49f9eeaa/src/main/java/org/apache/sysml/hops/cost/CostEstimator.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/hops/cost/CostEstimator.java 
b/src/main/java/org/apache/sysml/hops/cost/CostEstimator.java
index 05c6906..54faa43 100644
--- a/src/main/java/org/apache/sysml/hops/cost/CostEstimator.java
+++ b/src/main/java/org/apache/sysml/hops/cost/CostEstimator.java
@@ -294,8 +294,7 @@ public abstract class CostEstimator
                else if( inst instanceof FunctionCallCPInstruction )
                {
                        FunctionCallCPInstruction finst = 
(FunctionCallCPInstruction) inst;
-                       ArrayList<String> outVars = 
finst.getBoundOutputParamNames();
-                       for( String varname : outVars )
+                       for( String varname : finst.getBoundOutputParamNames() )
                                stats.put(varname, _unknownStats);
                }
        }

http://git-wip-us.apache.org/repos/asf/systemml/blob/49f9eeaa/src/main/java/org/apache/sysml/hops/ipa/IPAPassInlineFunctions.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/sysml/hops/ipa/IPAPassInlineFunctions.java 
b/src/main/java/org/apache/sysml/hops/ipa/IPAPassInlineFunctions.java
index 4c7998d..dd847f5 100644
--- a/src/main/java/org/apache/sysml/hops/ipa/IPAPassInlineFunctions.java
+++ b/src/main/java/org/apache/sysml/hops/ipa/IPAPassInlineFunctions.java
@@ -28,9 +28,11 @@ import org.apache.sysml.hops.FunctionOp;
 import org.apache.sysml.hops.Hop;
 import org.apache.sysml.hops.LiteralOp;
 import org.apache.sysml.hops.Hop.DataOpTypes;
+import org.apache.sysml.hops.HopsException;
 import org.apache.sysml.hops.recompile.Recompiler;
 import org.apache.sysml.hops.rewrite.HopRewriteUtils;
 import org.apache.sysml.parser.DMLProgram;
+import org.apache.sysml.parser.DataIdentifier;
 import org.apache.sysml.parser.FunctionStatement;
 import org.apache.sysml.parser.FunctionStatementBlock;
 import org.apache.sysml.parser.StatementBlock;
@@ -90,8 +92,14 @@ public class IPAPassInlineFunctions extends IPAPass
                                        
                                        //step 2: replace inputs
                                        HashMap<String,Hop> inMap = new 
HashMap<>();
-                                       for(int j=0; j<op.getInput().size(); 
j++)
-                                               
inMap.put(fstmt.getInputParams().get(j).getName(), op.getInput().get(j));
+                                       for(int j=0; j<op.getInput().size(); 
j++) {
+                                               String argName = 
op.getInputVariableNames()[j];
+                                               DataIdentifier di = 
fstmt.getInputParam(argName);
+                                               if( di == null )
+                                                       throw new 
HopsException("Non-existing named function argument: '"+argName
+                                                               +"' in function 
call '"+op.getFunctionKey()+"' (line "+op.getBeginLine()+").");
+                                               inMap.put(argName, 
op.getInput().get(j));
+                                       }
                                        replaceTransientReads(hops2, inMap);
                                        
                                        //step 3: replace outputs

http://git-wip-us.apache.org/repos/asf/systemml/blob/49f9eeaa/src/main/java/org/apache/sysml/hops/rewrite/RewriteGPUSpecificOps.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/sysml/hops/rewrite/RewriteGPUSpecificOps.java 
b/src/main/java/org/apache/sysml/hops/rewrite/RewriteGPUSpecificOps.java
index b946178..f2a0588 100644
--- a/src/main/java/org/apache/sysml/hops/rewrite/RewriteGPUSpecificOps.java
+++ b/src/main/java/org/apache/sysml/hops/rewrite/RewriteGPUSpecificOps.java
@@ -645,7 +645,7 @@ public class RewriteGPUSpecificOps extends HopRewriteRule {
                                                        LOG.debug("Applied 
batchNormTrain rewrite.");
                                                        ArrayList<Hop> outputs 
= getMultiOutputHops(roots, oldHops);
                                                        FunctionOp ret = new 
FunctionOp(FunctionType.MULTIRETURN_BUILTIN, DMLProgram.INTERNAL_NAMESPACE, 
"batch_norm2d_train", 
-                                                                       inHops, 
outputs.stream().map(h -> h.getName()).toArray(String[]::new), outputs);
+                                                               null, inHops, 
outputs.stream().map(h -> h.getName()).toArray(String[]::new), outputs);
                                                        
Collections.reverse(roots);
                                                        roots.add(ret);
                                                        
Collections.reverse(roots);
@@ -654,7 +654,7 @@ public class RewriteGPUSpecificOps extends HopRewriteRule {
                                        }
                                        
                                }
-                       }                       
+                       }
                }
                
                return hi;

http://git-wip-us.apache.org/repos/asf/systemml/blob/49f9eeaa/src/main/java/org/apache/sysml/lops/FunctionCallCP.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/lops/FunctionCallCP.java 
b/src/main/java/org/apache/sysml/lops/FunctionCallCP.java
index 711219a..50d43de 100644
--- a/src/main/java/org/apache/sysml/lops/FunctionCallCP.java
+++ b/src/main/java/org/apache/sysml/lops/FunctionCallCP.java
@@ -31,15 +31,17 @@ import org.apache.sysml.parser.DMLProgram;
 import org.apache.sysml.parser.Expression.DataType;
 import org.apache.sysml.parser.Expression.ValueType;
 
-public class FunctionCallCP extends Lop  
+public class FunctionCallCP extends Lop
 {      
        private String _fnamespace;
        private String _fname;
-       private String[] _outputs;
+       private String[] _inputNames;
+       private String[] _outputNames;
        private ArrayList<Lop> _outputLops = null;
 
-       public FunctionCallCP(ArrayList<Lop> inputs, String fnamespace, String 
fname, String[] outputs, ArrayList<Hop> outputHops, ExecType et) {
-               this(inputs, fnamespace, fname, outputs, et);
+       public FunctionCallCP(ArrayList<Lop> inputs, String fnamespace, String 
fname, 
+               String[] inputNames, String[] outputNames, ArrayList<Hop> 
outputHops, ExecType et) {
+               this(inputs, fnamespace, fname, inputNames, outputNames, et);
                if(outputHops != null) {
                        _outputLops = new ArrayList<>();
                        setLevel();
@@ -55,27 +57,25 @@ public class FunctionCallCP extends Lop
                }
        }
        
-       public FunctionCallCP(ArrayList<Lop> inputs, String fnamespace, String 
fname, String[] outputs, ExecType et) 
+       public FunctionCallCP(ArrayList<Lop> inputs, String fnamespace, String 
fname, String[] inputNames, String[] outputNames, ExecType et) 
        {
-               super(Lop.Type.FunctionCallCP, DataType.UNKNOWN, 
ValueType.UNKNOWN);    
+               super(Lop.Type.FunctionCallCP, DataType.UNKNOWN, 
ValueType.UNKNOWN);
                //note: data scalar in order to prevent generation of redundant 
createvar, rmvar
                
                _fnamespace = fnamespace;
                _fname = fname;
-               _outputs = outputs;
+               _inputNames = inputNames;
+               _outputNames = outputNames;
                
                //wire inputs
                for( Lop in : inputs ) {
                        addInput( in );
                        in.addOutput( this );
                }
-                       
+               
                //lop properties: always in CP
-               boolean breaksAlignment = false; 
-               boolean aligner = false;
-               boolean definesMRJob = false;
                lps.addCompatibility(JobType.INVALID);
-               lps.setProperties(inputs, et, ExecLocation.ControlProgram, 
breaksAlignment, aligner, definesMRJob );
+               lps.setProperties(inputs, et, ExecLocation.ControlProgram, 
false, false, false);
        }
 
        public ArrayList<Lop> getFunctionOutputs() {
@@ -99,9 +99,9 @@ public class FunctionCallCP extends Lop
                        sb.append( 
getInputs().get(i).prepInputOperand(inputs[i]) );
                }
                
-               for(int i=0; i< _outputs.length; i++) {
+               for(int i=0; i< _outputNames.length; i++) {
                        sb.append(Lop.OPERAND_DELIMITOR);
-                       sb.append(_outputs[i]);
+                       sb.append(_outputNames[i]);
                }
                
                return sb.toString();
@@ -118,11 +118,6 @@ public class FunctionCallCP extends Lop
                if (_fnamespace.equalsIgnoreCase(DMLProgram.INTERNAL_NAMESPACE) 
) {
                        return getInstructionsMultipleReturnBuiltins(inputs, 
outputs);
                }
-               
-               //Instruction format extFunct:::[FUNCTION 
NAMESPACE]:::[FUNCTION NAME]:::[num input params]:::[num output params]:::[list 
of delimited input params ]:::[list of delimited ouput params]
-               //These are the "bound names" for the inputs / outputs.  For 
example, out1 = ns::foo(in1, in2) yields
-               //extFunct:::ns:::foo:::2:::1:::in1:::in2:::out1
-               //NOTE: we have to append full input operand information to 
distinguish literals from variables w/ equal name
 
                StringBuilder inst = new StringBuilder();
                inst.append(getExecType());
@@ -136,19 +131,21 @@ public class FunctionCallCP extends Lop
                inst.append(Lop.OPERAND_DELIMITOR);
                inst.append(inputs.length);
                inst.append(Lop.OPERAND_DELIMITOR);
-               inst.append(_outputs.length);
+               inst.append(_outputNames.length);
                
                for(int i=0; i<inputs.length; i++) {
                        inst.append(Lop.OPERAND_DELIMITOR);
+                       inst.append(_inputNames[i]);
+                       inst.append("=");
                        inst.append( 
getInputs().get(i).prepInputOperand(inputs[i]) );
                }
 
                // TODO function output dataops (phase 3) - take 'outputs' into 
account
-               for( String out : _outputs ) {
+               for( String out : _outputNames ) {
                        inst.append(Lop.OPERAND_DELIMITOR);
                        inst.append(out);
                }
 
-               return inst.toString();                         
+               return inst.toString();
        }
 }

http://git-wip-us.apache.org/repos/asf/systemml/blob/49f9eeaa/src/main/java/org/apache/sysml/parser/DMLTranslator.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/parser/DMLTranslator.java 
b/src/main/java/org/apache/sysml/parser/DMLTranslator.java
index 7cf7418..d8698a7 100644
--- a/src/main/java/org/apache/sysml/parser/DMLTranslator.java
+++ b/src/main/java/org/apache/sysml/parser/DMLTranslator.java
@@ -21,10 +21,12 @@ package org.apache.sysml.parser;
 
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.stream.Collectors;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -1314,29 +1316,36 @@ public class DMLTranslator
                                        FunctionStatementBlock fsb = 
this._dmlProg.getFunctionStatementBlock(fci.getNamespace(),fci.getName());
                                        
                                        //error handling missing function
-                                       if (fsb == null){
-                                               String error = 
source.printErrorLocation() + "function " + fci.getName() + " is undefined in 
namespace " + fci.getNamespace(); 
-                                               throw new 
LanguageException(error);
+                                       if (fsb == null) { 
+                                               throw new 
LanguageException(source.printErrorLocation() + "function " 
+                                                       + fci.getName() + " is 
undefined in namespace " + fci.getNamespace());
                                        }
                                        
+                                       FunctionStatement fstmt = 
(FunctionStatement)fsb.getStatement(0);
+                                       String fkey = 
DMLProgram.constructFunctionKey(fci.getNamespace(),fci.getName());
+                                       
                                        //error handling unsupported function 
call in indexing expression
                                        if( target instanceof IndexedIdentifier 
) {
-                                               String fkey = 
DMLProgram.constructFunctionKey(fci.getNamespace(),fci.getName());
-                                               throw new 
LanguageException("Unsupported function call to '"+fkey+"' in left indexing 
expression. " +
-                                                               "Please, assign 
the function output to a variable.");
+                                               throw new 
LanguageException("Unsupported function call to '"+fkey+"' in left indexing "
+                                                       + "expression. Please, 
assign the function output to a variable.");
                                        }
                                        
-                                       ArrayList<Hop> finputs = new 
ArrayList<>();
-                                       for (ParameterExpression paramName : 
fci.getParamExprs()){
-                                               Hop in = 
processExpression(paramName.getExpr(), null, ids);
-                                               finputs.add(in);
-                                       }
-
+                                       //prepare function input names and 
inputs
+                                       String[] inputNames = 
fci.getParamExprs().stream()
+                                               .map(e -> 
e.getName()).toArray(String[]::new);
+                                       List<Hop> finputs = 
fci.getParamExprs().stream()
+                                               .map(e -> 
processExpression(e.getExpr(), null, ids)).collect(Collectors.toList());
+                                       
+                                       //use function signature to obtain 
names for unnamed args
+                                       //(note: consistent parameters already 
checked for functions in general)
+                                       if( 
Arrays.stream(inputNames).allMatch(n -> n==null) )
+                                               inputNames = 
fstmt._inputParams.stream().map(d -> d.getName()).toArray(String[]::new);
+                                       
                                        //create function op
                                        FunctionType ftype = 
fsb.getFunctionOpType();
                                        FunctionOp fcall = (target == null) ?
-                                               new FunctionOp(ftype, 
fci.getNamespace(), fci.getName(), finputs, new String[]{}, false) :
-                                               new FunctionOp(ftype, 
fci.getNamespace(), fci.getName(), finputs, new String[]{target.getName()}, 
false);
+                                               new FunctionOp(ftype, 
fci.getNamespace(), fci.getName(), inputNames, finputs, new String[]{}, false) :
+                                               new FunctionOp(ftype, 
fci.getNamespace(), fci.getName(), inputNames, finputs, new 
String[]{target.getName()}, false);
                                        fcall.setParseInfo(fci);
                                        output.add(fcall);
                                }
@@ -1350,22 +1359,29 @@ public class DMLTranslator
                                if ( source instanceof FunctionCallIdentifier ) 
{
                                        FunctionCallIdentifier fci = 
(FunctionCallIdentifier) source;
                                        FunctionStatementBlock fsb = 
this._dmlProg.getFunctionStatementBlock(fci.getNamespace(),fci.getName());
-                                       FunctionStatement fstmt = 
(FunctionStatement)fsb.getStatement(0);
-                                       if (fstmt == null){
-                                               throw new 
LanguageException(source.printErrorLocation() + "function " + fci.getName() + " 
is undefined in namespace " + fci.getNamespace());
+                                       if (fsb == null){
+                                               throw new 
LanguageException(source.printErrorLocation() + "function " 
+                                                       + fci.getName() + " is 
undefined in namespace " + fci.getNamespace());
                                        }
                                        
-                                       ArrayList<Hop> finputs = new 
ArrayList<>();
-                                       for (ParameterExpression paramName : 
fci.getParamExprs()){
-                                               Hop in = 
processExpression(paramName.getExpr(), null, ids);
-                                               finputs.add(in);
-                                       }
-
+                                       FunctionStatement fstmt = 
(FunctionStatement)fsb.getStatement(0);
+                                       
+                                       //prepare function input names and 
inputs
+                                       String[] inputNames = 
fci.getParamExprs().stream()
+                                               .map(e -> 
e.getName()).toArray(String[]::new);
+                                       List<Hop> finputs = 
fci.getParamExprs().stream()
+                                               .map(e -> 
processExpression(e.getExpr(), null, ids)).collect(Collectors.toList());
+                                       
+                                       //use function signature to obtain 
names for unnamed args
+                                       //(note: consistent parameters already 
checked for functions in general)
+                                       if( 
Arrays.stream(inputNames).allMatch(n -> n==null) )
+                                               inputNames = 
fstmt._inputParams.stream().map(d -> d.getName()).toArray(String[]::new);
+                                       
                                        //create function op
                                        String[] foutputs = 
mas.getTargetList().stream()
                                                .map(d -> 
d.getName()).toArray(String[]::new);
                                        FunctionType ftype = 
fsb.getFunctionOpType();
-                                       FunctionOp fcall = new 
FunctionOp(ftype, fci.getNamespace(), fci.getName(), finputs, foutputs, false);
+                                       FunctionOp fcall = new 
FunctionOp(ftype, fci.getNamespace(), fci.getName(), inputNames, finputs, 
foutputs, false);
                                        fcall.setParseInfo(fci);
                                        output.add(fcall);
                                }
@@ -2003,7 +2019,7 @@ public class DMLTranslator
                                outputs.add(new DataOp(outputNames[0], 
DataType.MATRIX, ValueType.DOUBLE, inputs.get(0), DataOpTypes.FUNCTIONOUTPUT, 
inputs.get(0).getFilename()));
                                outputs.add(new DataOp(outputNames[1], 
DataType.FRAME, ValueType.STRING, inputs.get(0), DataOpTypes.FUNCTIONOUTPUT, 
inputs.get(0).getFilename()));
                                
-                               currBuiltinOp = new FunctionOp(ftype, 
nameSpace, source.getOpCode().toString(), inputs, outputNames, outputs);
+                               currBuiltinOp = new FunctionOp(ftype, 
nameSpace, source.getOpCode().toString(), null, inputs, outputNames, outputs);
                                break;
                                
                        default:
@@ -2220,31 +2236,31 @@ public class DMLTranslator
                // Construct Hop for current builtin function expression based 
on its type
                Hop currBuiltinOp = null;
                switch (source.getOpCode()) {
-               case QR:
-               case LU:
-               case EIGEN:
-               case LSTM:
-               case LSTM_BACKWARD:
-               case BATCH_NORM2D:
-               case BATCH_NORM2D_BACKWARD:
-               case SVD:
-                       
-                       // Number of outputs = size of targetList = #of 
identifiers in source.getOutputs
-                       String[] outputNames = new String[targetList.size()]; 
-                       for ( int i=0; i < targetList.size(); i++ ) {
-                               outputNames[i] = 
((DataIdentifier)targetList.get(i)).getName();
-                               Hop output = new DataOp(outputNames[i], 
DataType.MATRIX, ValueType.DOUBLE, inputs.get(0), DataOpTypes.FUNCTIONOUTPUT, 
inputs.get(0).getFilename());
-                               outputs.add(output);
-                       }
-                       
-                       // Create the hop for current function call
-                       FunctionOp fcall = new FunctionOp(ftype, nameSpace, 
source.getOpCode().toString(), inputs, outputNames, outputs);
-                       currBuiltinOp = fcall;
-                       
-                       break;
-                       
-               default:
-                       throw new ParseException("Invaid Opcode in 
DMLTranslator:processMultipleReturnBuiltinFunctionExpression(): " + 
source.getOpCode());
+                       case QR:
+                       case LU:
+                       case EIGEN:
+                       case LSTM:
+                       case LSTM_BACKWARD:
+                       case BATCH_NORM2D:
+                       case BATCH_NORM2D_BACKWARD:
+                       case SVD:
+                               
+                               // Number of outputs = size of targetList = #of 
identifiers in source.getOutputs
+                               String[] outputNames = new 
String[targetList.size()]; 
+                               for ( int i=0; i < targetList.size(); i++ ) {
+                                       outputNames[i] = 
((DataIdentifier)targetList.get(i)).getName();
+                                       Hop output = new DataOp(outputNames[i], 
DataType.MATRIX, ValueType.DOUBLE, inputs.get(0), DataOpTypes.FUNCTIONOUTPUT, 
inputs.get(0).getFilename());
+                                       outputs.add(output);
+                               }
+                               
+                               // Create the hop for current function call
+                               FunctionOp fcall = new FunctionOp(ftype, 
nameSpace, source.getOpCode().toString(), null, inputs, outputNames, outputs);
+                               currBuiltinOp = fcall;
+                               
+                               break;
+                               
+                       default:
+                               throw new ParseException("Invaid Opcode in 
DMLTranslator:processMultipleReturnBuiltinFunctionExpression(): " + 
source.getOpCode());
                }
 
                // set properties for created hops based on outputs of source 
expression

http://git-wip-us.apache.org/repos/asf/systemml/blob/49f9eeaa/src/main/java/org/apache/sysml/parser/FunctionStatement.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/parser/FunctionStatement.java 
b/src/main/java/org/apache/sysml/parser/FunctionStatement.java
index fa3b86e..50bb2d3 100644
--- a/src/main/java/org/apache/sysml/parser/FunctionStatement.java
+++ b/src/main/java/org/apache/sysml/parser/FunctionStatement.java
@@ -24,7 +24,6 @@ import java.util.ArrayList;
 
 public class FunctionStatement extends Statement
 {
-               
        private ArrayList<StatementBlock> _body;
        protected String _name;
        protected ArrayList <DataIdentifier> _inputParams;
@@ -36,16 +35,22 @@ public class FunctionStatement extends Statement
        }
        
        public FunctionStatement(){
-                _body = new ArrayList<>();
-                _name = null;
-                _inputParams = new ArrayList<>();
-                _outputParams = new ArrayList<>();
+               _body = new ArrayList<>();
+               _name = null;
+               _inputParams = new ArrayList<>();
+               _outputParams = new ArrayList<>();
        }
        
        public ArrayList<DataIdentifier> getInputParams(){
                return _inputParams;
        }
        
+       public DataIdentifier getInputParam(String name) {
+               return _inputParams.stream()
+                       .filter(d -> d.getName().equals(name))
+                       .findFirst().orElse(null);
+       }
+       
        public ArrayList<DataIdentifier> getOutputParams(){
                return _outputParams;
        }

http://git-wip-us.apache.org/repos/asf/systemml/blob/49f9eeaa/src/main/java/org/apache/sysml/parser/StatementBlock.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/parser/StatementBlock.java 
b/src/main/java/org/apache/sysml/parser/StatementBlock.java
index 4140a2e..4498eaa 100644
--- a/src/main/java/org/apache/sysml/parser/StatementBlock.java
+++ b/src/main/java/org/apache/sysml/parser/StatementBlock.java
@@ -596,7 +596,6 @@ public class StatementBlock extends LiveVariableAnalysis 
implements ParseInfo
                                }
 
                                //MB: we cannot use the hash since multiple 
interleaved inlined functions should be independent.
-                               //String prefix = new 
Integer(fblock.hashCode()).toString() + "_";
                                String prefix = _seq.getNextID() + "_";
 
                                if (fstmt.getBody().size() > 1){
@@ -609,32 +608,35 @@ public class StatementBlock extends LiveVariableAnalysis 
implements ParseInfo
                                                fcall.getParamExprs().size() + 
" found, but " + fstmt.getInputParams().size()+" expected.");
                                }
 
-                               for (int i =0; i < 
fstmt.getInputParams().size(); i++) {
-                                       DataIdentifier currFormalParam = 
fstmt.getInputParams().get(i);
-
+                               for (int i =0; i < 
fcall.getParamExprs().size(); i++) {
+                                       ParameterExpression inputArg = 
fcall.getParamExprs().get(i);
+                                       DataIdentifier currFormalParam = 
(inputArg.getName()==null) ?
+                                               fstmt.getInputParams().get(i) : 
fstmt.getInputParam(inputArg.getName());
+                                       if( currFormalParam == null )
+                                               throw new 
LanguageException("Non-existing named function argument '"
+                                                       + inputArg.getName()+"' 
in call to "+fcall.getName()+".");
+                                       
                                        // create new assignment statement
                                        String newFormalParameterName = prefix 
+ currFormalParam.getName();
                                        DataIdentifier newTarget = new 
DataIdentifier(currFormalParam);
                                        
newTarget.setName(newFormalParameterName);
 
-                                       Expression currCallParam = 
fcall.getParamExprs().get(i).getExpr();
+                                       Expression currCallParam = 
inputArg.getExpr();
 
                                        //auto casting of inputs on inlining 
(if required)
                                        ValueType targetVT = 
newTarget.getValueType();
                                        if (newTarget.getDataType() == 
DataType.SCALAR && currCallParam.getOutput() != null
                                                        && targetVT != 
currCallParam.getOutput().getValueType() && targetVT != ValueType.STRING) {
                                                currCallParam = new 
BuiltinFunctionExpression(
-                                                               
BuiltinFunctionExpression.getValueTypeCastOperator(targetVT),
-                                                               new 
Expression[] { currCallParam }, newTarget);
+                                                       
BuiltinFunctionExpression.getValueTypeCastOperator(targetVT),
+                                                       new Expression[] { 
currCallParam }, newTarget);
                                        }
 
                                        // create the assignment statement to 
bind the call parameter to formal parameter
-                                       AssignmentStatement binding = new 
AssignmentStatement(newTarget, currCallParam, newTarget);
-                                       newStatements.add(binding);
+                                       newStatements.add(new 
AssignmentStatement(newTarget, currCallParam, newTarget));
                                }
 
                                for (Statement stmt : sblock._statements){
-
                                        // rewrite the statement to use the 
"rewritten" name
                                        Statement rewrittenStmt = 
stmt.rewriteStatement(prefix);
                                        newStatements.add(rewrittenStmt);

http://git-wip-us.apache.org/repos/asf/systemml/blob/49f9eeaa/src/main/java/org/apache/sysml/runtime/controlprogram/FunctionProgramBlock.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/sysml/runtime/controlprogram/FunctionProgramBlock.java
 
b/src/main/java/org/apache/sysml/runtime/controlprogram/FunctionProgramBlock.java
index 25b2017..91900ca 100644
--- 
a/src/main/java/org/apache/sysml/runtime/controlprogram/FunctionProgramBlock.java
+++ 
b/src/main/java/org/apache/sysml/runtime/controlprogram/FunctionProgramBlock.java
@@ -20,6 +20,8 @@
 package org.apache.sysml.runtime.controlprogram;
 
 import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
 
 import org.apache.sysml.api.DMLScript;
 import org.apache.sysml.conf.ConfigurationManager;
@@ -43,21 +45,27 @@ public class FunctionProgramBlock extends ProgramBlock
        
        private boolean _recompileOnce = false;
        
-       public FunctionProgramBlock( Program prog, ArrayList<DataIdentifier> 
inputParams, ArrayList<DataIdentifier> outputParams) 
-       {
+       public FunctionProgramBlock( Program prog, ArrayList<DataIdentifier> 
inputParams, ArrayList<DataIdentifier> outputParams) {
                super(prog);
                _childBlocks = new ArrayList<>();
                _inputParams = new ArrayList<>();
-               for (DataIdentifier id : inputParams){
+               for (DataIdentifier id : inputParams)
                        _inputParams.add(new DataIdentifier(id));
-                       
-               }
                _outputParams = new ArrayList<>();
-               for (DataIdentifier id : outputParams){
+               for (DataIdentifier id : outputParams)
                        _outputParams.add(new DataIdentifier(id));
-               }
        }
        
+       public DataIdentifier getInputParam(String name) {
+               return _inputParams.stream()
+                       .filter(d -> d.getName().equals(name))
+                       .findFirst().orElse(null);
+       }
+       
+       public List<String> getInputParamNames() {
+               return _inputParams.stream().map(d -> 
d.getName()).collect(Collectors.toList());
+       } 
+       
        public ArrayList<DataIdentifier> getInputParams(){
                return _inputParams;
        }
@@ -70,8 +78,7 @@ public class FunctionProgramBlock extends ProgramBlock
                _childBlocks.add(childBlock);
        }
        
-       public void setChildBlocks( ArrayList<ProgramBlock> pbs)
-       {
+       public void setChildBlocks( ArrayList<ProgramBlock> pbs) {
                _childBlocks = pbs;
        }
        

http://git-wip-us.apache.org/repos/asf/systemml/blob/49f9eeaa/src/main/java/org/apache/sysml/runtime/controlprogram/paramserv/PSWorker.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/sysml/runtime/controlprogram/paramserv/PSWorker.java 
b/src/main/java/org/apache/sysml/runtime/controlprogram/paramserv/PSWorker.java
index 464db9b..4b5c5c1 100644
--- 
a/src/main/java/org/apache/sysml/runtime/controlprogram/paramserv/PSWorker.java
+++ 
b/src/main/java/org/apache/sysml/runtime/controlprogram/paramserv/PSWorker.java
@@ -85,7 +85,8 @@ public abstract class PSWorker implements Serializable {
                        .collect(Collectors.toCollection(ArrayList::new));
                ArrayList<String> outputNames = 
outputs.stream().map(DataIdentifier::getName)
                        .collect(Collectors.toCollection(ArrayList::new));
-               _inst = new FunctionCallCPInstruction(ns, fname, boundInputs, 
inputNames, outputNames, "update function");
+               _inst = new FunctionCallCPInstruction(ns, fname, boundInputs,
+                       inputNames, func.getInputParamNames(), outputNames, 
"update function");
 
                // Check the inputs of the update function
                checkInput(false, inputs, Expression.DataType.MATRIX, 
Statement.PS_FEATURES);

http://git-wip-us.apache.org/repos/asf/systemml/blob/49f9eeaa/src/main/java/org/apache/sysml/runtime/controlprogram/paramserv/ParamServer.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/sysml/runtime/controlprogram/paramserv/ParamServer.java
 
b/src/main/java/org/apache/sysml/runtime/controlprogram/paramserv/ParamServer.java
index 2607036..0f5f70d 100644
--- 
a/src/main/java/org/apache/sysml/runtime/controlprogram/paramserv/ParamServer.java
+++ 
b/src/main/java/org/apache/sysml/runtime/controlprogram/paramserv/ParamServer.java
@@ -113,7 +113,8 @@ public abstract class ParamServer
                        .collect(Collectors.toCollection(ArrayList::new));
                ArrayList<String> outputNames = 
outputs.stream().map(DataIdentifier::getName)
                        .collect(Collectors.toCollection(ArrayList::new));
-               _inst = new FunctionCallCPInstruction(ns, fname, boundInputs, 
inputNames, outputNames, "aggregate function");
+               _inst = new FunctionCallCPInstruction(ns, fname, boundInputs,
+                       inputNames, func.getInputParamNames(), outputNames, 
"aggregate function");
        }
 
        public abstract void push(int workerID, ListObject value);

http://git-wip-us.apache.org/repos/asf/systemml/blob/49f9eeaa/src/main/java/org/apache/sysml/runtime/instructions/cp/EvalNaryCPInstruction.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/sysml/runtime/instructions/cp/EvalNaryCPInstruction.java
 
b/src/main/java/org/apache/sysml/runtime/instructions/cp/EvalNaryCPInstruction.java
index 02826ca..bd8d133 100644
--- 
a/src/main/java/org/apache/sysml/runtime/instructions/cp/EvalNaryCPInstruction.java
+++ 
b/src/main/java/org/apache/sysml/runtime/instructions/cp/EvalNaryCPInstruction.java
@@ -20,6 +20,7 @@
 package org.apache.sysml.runtime.instructions.cp;
 
 import org.apache.sysml.runtime.DMLRuntimeException;
+import org.apache.sysml.runtime.controlprogram.FunctionProgramBlock;
 import org.apache.sysml.runtime.controlprogram.Program;
 import org.apache.sysml.runtime.controlprogram.caching.FrameObject;
 import org.apache.sysml.runtime.controlprogram.caching.MatrixObject;
@@ -62,8 +63,9 @@ public class EvalNaryCPInstruction extends 
BuiltinNaryCPInstruction {
                MatrixObject outputMO = new 
MatrixObject(ec.getMatrixObject(output.getName()));
 
                //3. call the function
-               FunctionCallCPInstruction fcpi = new FunctionCallCPInstruction(
-                       null, funcName, boundInputs, boundInputNames, 
boundOutputNames, "eval func");
+               FunctionProgramBlock fpb = 
ec.getProgram().getFunctionProgramBlock(null, funcName);
+               FunctionCallCPInstruction fcpi = new 
FunctionCallCPInstruction(null, funcName,
+                       boundInputs, boundInputNames, fpb.getInputParamNames(), 
boundOutputNames, "eval func");
                fcpi.processInstruction(ec);
 
                //4. convert the result to matrix

http://git-wip-us.apache.org/repos/asf/systemml/blob/49f9eeaa/src/main/java/org/apache/sysml/runtime/instructions/cp/FunctionCallCPInstruction.java
----------------------------------------------------------------------
diff --git 
a/src/main/java/org/apache/sysml/runtime/instructions/cp/FunctionCallCPInstruction.java
 
b/src/main/java/org/apache/sysml/runtime/instructions/cp/FunctionCallCPInstruction.java
index 1c1ac30..5666d4f 100644
--- 
a/src/main/java/org/apache/sysml/runtime/instructions/cp/FunctionCallCPInstruction.java
+++ 
b/src/main/java/org/apache/sysml/runtime/instructions/cp/FunctionCallCPInstruction.java
@@ -21,6 +21,7 @@ package org.apache.sysml.runtime.instructions.cp;
 
 import java.util.ArrayList;
 import java.util.HashSet;
+import java.util.List;
 
 import org.apache.sysml.api.DMLScript;
 import org.apache.sysml.lops.Lop;
@@ -41,16 +42,18 @@ public class FunctionCallCPInstruction extends 
CPInstruction {
        private final String _functionName;
        private final String _namespace;
        private final CPOperand[] _boundInputs;
-       private final ArrayList<String> _boundInputNames;
-       private final ArrayList<String> _boundOutputNames;
+       private final List<String> _boundInputNames;
+       private final List<String> _funArgNames;
+       private final List<String> _boundOutputNames;
 
        public FunctionCallCPInstruction(String namespace, String functName, 
CPOperand[] boundInputs,
-               ArrayList<String> boundInputNames, ArrayList<String> 
boundOutputNames, String istr) {
+                       List<String> boundInputNames, List<String> funArgNames, 
List<String> boundOutputNames, String istr) {
                super(CPType.External, null, functName, istr);
                _functionName = functName;
                _namespace = namespace;
                _boundInputs = boundInputs;
                _boundInputNames = boundInputNames;
+               _funArgNames = funArgNames;
                _boundOutputNames = boundOutputNames;
        }
 
@@ -63,23 +66,26 @@ public class FunctionCallCPInstruction extends 
CPInstruction {
        }
        
        public static FunctionCallCPInstruction parseInstruction(String str) {
-               //schema: extfunct, fname, num inputs, num outputs, inputs, 
outputs
+               //schema: extfunct, fname, num inputs, num outputs, inputs 
(name-value pairs), outputs
                String[] parts = 
InstructionUtils.getInstructionPartsWithValueType ( str );
                String namespace = parts[1];
                String functionName = parts[2];
                int numInputs = Integer.valueOf(parts[3]);
                int numOutputs = Integer.valueOf(parts[4]);
                CPOperand[] boundInputs = new CPOperand[numInputs];
-               ArrayList<String> boundInputNames = new ArrayList<>();
-               ArrayList<String> boundOutputNames = new ArrayList<>();
+               List<String> boundInputNames = new ArrayList<>();
+               List<String> funArgNames = new ArrayList<>();
+               List<String> boundOutputNames = new ArrayList<>();
                for (int i = 0; i < numInputs; i++) {
-                       boundInputs[i] = new CPOperand(parts[5 + i]);
+                       String[] nameValue = parts[5 + i].split("=");
+                       boundInputs[i] = new CPOperand(nameValue[1]);
+                       funArgNames.add(nameValue[0]);
                        boundInputNames.add(boundInputs[i].getName());
                }
                for (int i = 0; i < numOutputs; i++)
                        boundOutputNames.add(parts[5 + numInputs + i]);
-               return new FunctionCallCPInstruction ( namespace,
-                       functionName, boundInputs, boundInputNames, 
boundOutputNames, str );
+               return new FunctionCallCPInstruction ( namespace, functionName,
+                       boundInputs, boundInputNames, funArgNames, 
boundOutputNames, str );
        }
        
        @Override
@@ -109,8 +115,7 @@ public class FunctionCallCPInstruction extends 
CPInstruction {
                // create bindings to formal parameters for given function call
                // These are the bindings passed to the FunctionProgramBlock 
for function execution 
                LocalVariableMap functionVariables = new LocalVariableMap();
-               for( int i=0; i<fpb.getInputParams().size(); i++) 
-               {
+               for( int i=0; i<_boundInputs.length; i++) {
                        //error handling non-existing variables
                        CPOperand input = _boundInputs[i];
                        if( !input.isLiteral() && 
!ec.containsVariable(input.getName()) ) {
@@ -118,7 +123,13 @@ public class FunctionCallCPInstruction extends 
CPInstruction {
                                        
DMLProgram.constructFunctionKey(_namespace, _functionName) + " (line 
"+getLineNum()+").");
                        }
                        //get input matrix/frame/scalar
-                       DataIdentifier currFormalParam = 
fpb.getInputParams().get(i);
+                       String argName = _funArgNames.get(i);
+                       DataIdentifier currFormalParam = 
fpb.getInputParam(argName);
+                       if( currFormalParam == null ) {
+                               throw new DMLRuntimeException("Non-existing 
named "
+                                       + "function argument: '"+argName+"' 
(line "+getLineNum()+").");
+                       }
+                       
                        Data value = ec.getVariable(input);
                        
                        //graceful value type conversion for scalar inputs with 
wrong type
@@ -210,12 +221,8 @@ public class FunctionCallCPInstruction extends 
CPInstruction {
        public void printMe() {
                LOG.debug("ExternalBuiltInFunction: " + this.toString());
        }
-
-       public ArrayList<String> getBoundInputParamNames() {
-               return _boundInputNames;
-       }
        
-       public ArrayList<String> getBoundOutputParamNames() {
+       public List<String> getBoundOutputParamNames() {
                return _boundOutputNames;
        }
 

http://git-wip-us.apache.org/repos/asf/systemml/blob/49f9eeaa/src/main/java/org/apache/sysml/udf/lib/EvalFunction.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/udf/lib/EvalFunction.java 
b/src/main/java/org/apache/sysml/udf/lib/EvalFunction.java
index c9d1028..993e33e 100644
--- a/src/main/java/org/apache/sysml/udf/lib/EvalFunction.java
+++ b/src/main/java/org/apache/sysml/udf/lib/EvalFunction.java
@@ -23,7 +23,7 @@ import java.util.ArrayList;
 
 import org.apache.commons.lang.NotImplementedException;
 import org.apache.sysml.parser.Expression.DataType;
-
+import org.apache.sysml.runtime.controlprogram.FunctionProgramBlock;
 import org.apache.sysml.runtime.controlprogram.caching.MatrixObject;
 import org.apache.sysml.runtime.controlprogram.context.ExecutionContext;
 import org.apache.sysml.runtime.controlprogram.context.ExecutionContextFactory;
@@ -69,8 +69,9 @@ public class EvalFunction extends PackageFunction
                CPOperand inName = new CPOperand("TMP", 
org.apache.sysml.parser.Expression.ValueType.DOUBLE, DataType.MATRIX);
                ec2.setVariable("TMP", in);
                
-               FunctionCallCPInstruction fcpi = new FunctionCallCPInstruction(
-                       null, fname, new CPOperand[]{inName}, inputs, outputs, 
"eval func");
+               FunctionProgramBlock fpb = 
ec.getProgram().getFunctionProgramBlock(null, fname);
+               FunctionCallCPInstruction fcpi = new 
FunctionCallCPInstruction(null, fname,
+                       new CPOperand[]{inName}, inputs, 
fpb.getInputParamNames(), outputs, "eval func");
                fcpi.processInstruction(ec2);
                
                MatrixObject out = (MatrixObject)ec2.getVariable("B");

http://git-wip-us.apache.org/repos/asf/systemml/blob/49f9eeaa/src/test/java/org/apache/sysml/test/integration/functions/misc/FunctionPotpourriTest.java
----------------------------------------------------------------------
diff --git 
a/src/test/java/org/apache/sysml/test/integration/functions/misc/FunctionPotpourriTest.java
 
b/src/test/java/org/apache/sysml/test/integration/functions/misc/FunctionPotpourriTest.java
index fda4c2f..34269e2 100644
--- 
a/src/test/java/org/apache/sysml/test/integration/functions/misc/FunctionPotpourriTest.java
+++ 
b/src/test/java/org/apache/sysml/test/integration/functions/misc/FunctionPotpourriTest.java
@@ -34,6 +34,11 @@ public class FunctionPotpourriTest extends AutomatedTestBase
        private final static String TEST_NAME4 = "FunPotpourriEval";
        private final static String TEST_NAME5 = "FunPotpourriSubsetReturn";
        private final static String TEST_NAME6 = "FunPotpourriSubsetReturnDead";
+       private final static String TEST_NAME7 = "FunPotpourriNamedArgsSingle";
+       private final static String TEST_NAME8 = "FunPotpourriNamedArgsMulti";
+       private final static String TEST_NAME9 = "FunPotpourriNamedArgsPartial";
+       private final static String TEST_NAME10 = 
"FunPotpourriNamedArgsUnknown1";
+       private final static String TEST_NAME11 = 
"FunPotpourriNamedArgsUnknown2";
        
        private final static String TEST_DIR = "functions/misc/";
        private final static String TEST_CLASS_DIR = TEST_DIR + 
FunctionPotpourriTest.class.getSimpleName() + "/";
@@ -47,6 +52,11 @@ public class FunctionPotpourriTest extends AutomatedTestBase
                addTestConfiguration( TEST_NAME4, new 
TestConfiguration(TEST_CLASS_DIR, TEST_NAME4, new String[] { "R" }) );
                addTestConfiguration( TEST_NAME5, new 
TestConfiguration(TEST_CLASS_DIR, TEST_NAME5, new String[] { "R" }) );
                addTestConfiguration( TEST_NAME6, new 
TestConfiguration(TEST_CLASS_DIR, TEST_NAME6, new String[] { "R" }) );
+               addTestConfiguration( TEST_NAME7, new 
TestConfiguration(TEST_CLASS_DIR, TEST_NAME7, new String[] { "R" }) );
+               addTestConfiguration( TEST_NAME8, new 
TestConfiguration(TEST_CLASS_DIR, TEST_NAME8, new String[] { "R" }) );
+               addTestConfiguration( TEST_NAME9, new 
TestConfiguration(TEST_CLASS_DIR, TEST_NAME9, new String[] { "R" }) );
+               addTestConfiguration( TEST_NAME10, new 
TestConfiguration(TEST_CLASS_DIR, TEST_NAME10, new String[] { "R" }) );
+               addTestConfiguration( TEST_NAME11, new 
TestConfiguration(TEST_CLASS_DIR, TEST_NAME11, new String[] { "R" }) );
        }
 
        @Test
@@ -79,13 +89,49 @@ public class FunctionPotpourriTest extends AutomatedTestBase
                runFunctionTest( TEST_NAME6, false );
        }
        
+       @Test
+       public void testFunctionNamedArgsSingle() {
+               runFunctionTest( TEST_NAME7, false );
+       }
+       
+       @Test
+       public void testFunctionNamedArgsSingleErr() {
+               runFunctionTest( TEST_NAME7, true );
+       }
+       
+       @Test
+       public void testFunctionNamedArgsMulti() {
+               runFunctionTest( TEST_NAME8, false );
+       }
+       
+       @Test
+       public void testFunctionNamedArgsMultiErr() {
+               runFunctionTest( TEST_NAME8, true );
+       }
+       
+       @Test
+       public void testFunctionNamedArgsPartial() {
+               runFunctionTest( TEST_NAME9, true );
+       }
+       
+       @Test
+       public void testFunctionNamedArgsUnkown1() {
+               runFunctionTest( TEST_NAME10, true );
+       }
+       
+       @Test
+       public void testFunctionNamedArgsUnkown2() {
+               runFunctionTest( TEST_NAME11, true );
+       }
+       
        private void runFunctionTest(String testName, boolean error) {
                TestConfiguration config = getTestConfiguration(testName);
                loadTestConfiguration(config);
                
                String HOME = SCRIPT_DIR + TEST_DIR;
                fullDMLScriptName = HOME + testName + ".dml";
-               programArgs = new String[]{"-explain", "-stats"};
+               programArgs = new String[]{"-explain", "-stats",
+                       "-args", String.valueOf(error).toUpperCase()};
 
                //run script and compare output
                runTest(true, error, DMLException.class, -1); 

http://git-wip-us.apache.org/repos/asf/systemml/blob/49f9eeaa/src/test/scripts/functions/misc/FunPotpourriNamedArgsMulti.dml
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/misc/FunPotpourriNamedArgsMulti.dml 
b/src/test/scripts/functions/misc/FunPotpourriNamedArgsMulti.dml
new file mode 100644
index 0000000..de819da
--- /dev/null
+++ b/src/test/scripts/functions/misc/FunPotpourriNamedArgsMulti.dml
@@ -0,0 +1,36 @@
+#-------------------------------------------------------------
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+#   http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+#-------------------------------------------------------------
+
+foo = function(Matrix[Double] A, Matrix[Double] B) return (Matrix[Double] C, 
Matrix[Double] D){
+  while(FALSE){} # no inlining
+  C = A %*% B + 7;
+  D = C + 3;
+}
+
+X1 = matrix(1, 300, 500)
+X2 = matrix(2, 500, 200)
+
+if( $1 )
+  [C,D] = foo(A=X2, B=X1);
+else
+  [C,D] = foo(B=X2, A=X1);
+
+print("out:  " + sum(C))

http://git-wip-us.apache.org/repos/asf/systemml/blob/49f9eeaa/src/test/scripts/functions/misc/FunPotpourriNamedArgsPartial.dml
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/misc/FunPotpourriNamedArgsPartial.dml 
b/src/test/scripts/functions/misc/FunPotpourriNamedArgsPartial.dml
new file mode 100644
index 0000000..868c92c
--- /dev/null
+++ b/src/test/scripts/functions/misc/FunPotpourriNamedArgsPartial.dml
@@ -0,0 +1,32 @@
+#-------------------------------------------------------------
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+#   http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+#-------------------------------------------------------------
+
+foo = function(Matrix[Double] A, Matrix[Double] B) return (Matrix[Double] C){
+  if(1==1){}
+  C = A %*% B + 7;
+}
+
+X1 = matrix(1, 300, 500)
+X2 = matrix(2, 500, 200)
+
+C = foo(B=X2, X1);
+
+print("out:  " + sum(C))

http://git-wip-us.apache.org/repos/asf/systemml/blob/49f9eeaa/src/test/scripts/functions/misc/FunPotpourriNamedArgsSingle.dml
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/misc/FunPotpourriNamedArgsSingle.dml 
b/src/test/scripts/functions/misc/FunPotpourriNamedArgsSingle.dml
new file mode 100644
index 0000000..dc542e6
--- /dev/null
+++ b/src/test/scripts/functions/misc/FunPotpourriNamedArgsSingle.dml
@@ -0,0 +1,34 @@
+#-------------------------------------------------------------
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+#   http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+#-------------------------------------------------------------
+
+foo = function(Matrix[Double] A, Matrix[Double] B) return (Matrix[Double] C){
+  C = A %*% B + 7;
+}
+
+X1 = matrix(1, 300, 500)
+X2 = matrix(2, 500, 200)
+
+if( $1 )
+  C = foo(A=X2, B=X1);
+else
+  C = foo(B=X2, A=X1);
+
+print("out:  " + sum(C))

http://git-wip-us.apache.org/repos/asf/systemml/blob/49f9eeaa/src/test/scripts/functions/misc/FunPotpourriNamedArgsUnknown1.dml
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/misc/FunPotpourriNamedArgsUnknown1.dml 
b/src/test/scripts/functions/misc/FunPotpourriNamedArgsUnknown1.dml
new file mode 100644
index 0000000..d2aa036
--- /dev/null
+++ b/src/test/scripts/functions/misc/FunPotpourriNamedArgsUnknown1.dml
@@ -0,0 +1,31 @@
+#-------------------------------------------------------------
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+#   http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+#-------------------------------------------------------------
+
+foo1 = function(Matrix[Double] A, Matrix[Double] B) return (Matrix[Double] C){
+  C = A %*% B + 7;
+}
+
+X1 = matrix(1, 300, 500)
+X2 = matrix(2, 500, 200)
+
+C = foo1(B=X2, E=X1);
+
+print("out:  " + sum(C))

http://git-wip-us.apache.org/repos/asf/systemml/blob/49f9eeaa/src/test/scripts/functions/misc/FunPotpourriNamedArgsUnknown2.dml
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/misc/FunPotpourriNamedArgsUnknown2.dml 
b/src/test/scripts/functions/misc/FunPotpourriNamedArgsUnknown2.dml
new file mode 100644
index 0000000..83f7155
--- /dev/null
+++ b/src/test/scripts/functions/misc/FunPotpourriNamedArgsUnknown2.dml
@@ -0,0 +1,32 @@
+#-------------------------------------------------------------
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+#   http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+#-------------------------------------------------------------
+
+foo2 = function(Matrix[Double] A, Matrix[Double] B) return (Matrix[Double] C){
+  if(1==1){}
+  C = A %*% B + 7;
+}
+
+X1 = matrix(1, 300, 500)
+X2 = matrix(2, 500, 200)
+
+C = foo2(A=X1, E=X2);
+
+print("out:  " + sum(C))

Reply via email to