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))
