You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@systemml.apache.org by mb...@apache.org on 2018/07/27 01:32:54 UTC

systemml git commit: [SYSTEMML-2208] Functions with default scalar/matrix/frame parameters

Repository: systemml
Updated Branches:
  refs/heads/master eb182010b -> bfd495289


[SYSTEMML-2208] Functions with default scalar/matrix/frame parameters

This patch introduces support for default function arguments that are
used whenever the related argument is not provided by a function call.
To this end, this patch modified the parser to allow assignment
expressions in function signatures. Furthermore, we use a simple
compiler approach of adding these default expressions to all function
calls that do not provide certain arguments. Non-provided arguments
without defaults consistently result in compilation (not runtime)
errors.


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

Branch: refs/heads/master
Commit: bfd4952891a92af869965f8d16631c6e9aa156db
Parents: eb18201
Author: Matthias Boehm <mb...@gmail.com>
Authored: Thu Jul 26 18:33:57 2018 -0700
Committer: Matthias Boehm <mb...@gmail.com>
Committed: Thu Jul 26 18:34:22 2018 -0700

----------------------------------------------------------------------
 .../org/apache/sysml/parser/DMLTranslator.java  | 62 +++++++++++++++-----
 .../sysml/parser/FunctionCallIdentifier.java    |  8 ++-
 .../apache/sysml/parser/FunctionStatement.java  | 23 +++++++-
 .../java/org/apache/sysml/parser/dml/Dml.g4     |  4 +-
 .../sysml/parser/dml/DmlPreprocessor.java       |  7 +++
 .../sysml/parser/dml/DmlSyntacticValidator.java | 62 +++++++++++++-------
 .../functions/misc/FunctionPotpourriTest.java   | 30 +++++++++-
 .../misc/FunPotpourriDefaultArgMatrix.dml       | 31 ++++++++++
 .../misc/FunPotpourriDefaultArgScalar.dml       | 39 ++++++++++++
 .../FunPotpourriDefaultArgScalarMatrix1.dml     | 39 ++++++++++++
 .../FunPotpourriDefaultArgScalarMatrix2.dml     | 43 ++++++++++++++
 11 files changed, 303 insertions(+), 45 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/systemml/blob/bfd49528/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 d8698a7..22d152d 100644
--- a/src/main/java/org/apache/sysml/parser/DMLTranslator.java
+++ b/src/main/java/org/apache/sysml/parser/DMLTranslator.java
@@ -21,8 +21,8 @@ package org.apache.sysml.parser;
 
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.List;
@@ -1331,21 +1331,25 @@ public class DMLTranslator
 					}
 					
 					//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());
+					List<String> inputNames = new ArrayList<>(fci.getParamExprs().stream()
+						.map(e -> e.getName()).collect(Collectors.toList()));
+					List<Hop> finputs = new ArrayList<>(fci.getParamExprs().stream()
+						.map(e -> processExpression(e.getExpr(), null, ids)).collect(Collectors.toList()));
+					
+					//append default expression for missing arguments
+					appendDefaultArguments(fstmt, inputNames, finputs, ids);
 					
 					//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);
+					if( inputNames.stream().allMatch(n -> n==null) )
+						inputNames = fstmt._inputParams.stream().map(d -> d.getName()).collect(Collectors.toList());
 					
 					//create function op
+					String[] inputNames2 = inputNames.toArray(new String[0]);
 					FunctionType ftype = fsb.getFunctionOpType();
 					FunctionOp fcall = (target == null) ?
-						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);
+						new FunctionOp(ftype, fci.getNamespace(), fci.getName(), inputNames2, finputs, new String[]{}, false) :
+						new FunctionOp(ftype, fci.getNamespace(), fci.getName(), inputNames2, finputs, new String[]{target.getName()}, false);
 					fcall.setParseInfo(fci);
 					output.add(fcall);
 				}
@@ -1367,21 +1371,25 @@ public class DMLTranslator
 					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());
+					List<String> inputNames = new ArrayList<>(fci.getParamExprs().stream()
+						.map(e -> e.getName()).collect(Collectors.toList()));
+					List<Hop> finputs = new ArrayList<>(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);
+					if( inputNames.stream().allMatch(n -> n==null) )
+						inputNames = fstmt._inputParams.stream().map(d -> d.getName()).collect(Collectors.toList());
+					
+					//append default expression for missing arguments
+					appendDefaultArguments(fstmt, inputNames, finputs, ids);
 					
 					//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(), inputNames, finputs, foutputs, false);
+					FunctionOp fcall = new FunctionOp(ftype, fci.getNamespace(), fci.getName(),
+						inputNames.toArray(new String[0]), finputs, foutputs, false);
 					fcall.setParseInfo(fci);
 					output.add(fcall);
 				}
@@ -1405,6 +1413,28 @@ public class DMLTranslator
 
 	}
 	
+	private void appendDefaultArguments(FunctionStatement fstmt, List<String> inputNames, List<Hop> inputs, HashMap<String, Hop> ids) {
+		//NOTE: For default expressions of unspecified function arguments, we have two choices:
+		//either (a) compile ifelse(exist(argName),default, argName) into the function, or
+		//simply (b) add the default to the argument list of function calls when needed.
+		//We decided for (b) because it simplifies IPA and dynamic recompilation.
+		
+		if( fstmt.getInputParams().size() == inputs.size() )
+			return;
+		HashSet<String> probeNames = new HashSet<String>(inputNames);
+		for( DataIdentifier di : fstmt.getInputParams() ) {
+			if( probeNames.contains(di.getName()) ) continue;
+			Expression exp = fstmt.getInputDefault(di.getName());
+			if( exp == null ) {
+				throw new LanguageException("Missing default expression for unspecified "
+					+ "function argument '"+di.getName()+"' in call to function '"+fstmt.getName()+"'.");
+			}
+			//compile and add default expression
+			inputNames.add(di.getName());
+			inputs.add(processExpression(exp, null, ids));
+		}
+	}
+	
 	public void constructHopsForIfControlBlock(IfStatementBlock sb) {
 		IfStatement ifsb = (IfStatement) sb.getStatement(0);
 		ArrayList<StatementBlock> ifBody = ifsb.getIfBody();

http://git-wip-us.apache.org/repos/asf/systemml/blob/bfd49528/src/main/java/org/apache/sysml/parser/FunctionCallIdentifier.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/parser/FunctionCallIdentifier.java b/src/main/java/org/apache/sysml/parser/FunctionCallIdentifier.java
index 4ffe582..419bc81 100644
--- a/src/main/java/org/apache/sysml/parser/FunctionCallIdentifier.java
+++ b/src/main/java/org/apache/sysml/parser/FunctionCallIdentifier.java
@@ -120,13 +120,18 @@ public class FunctionCallIdentifier extends DataIdentifier
 					_name + " has both parameter types.", conditional);
 		}
 		
-		// Step 4: validate expressions for each passed parameter
+		// Step 4: validate expressions for each passed parameter and defaults
 		for( ParameterExpression paramExpr : _paramExprs ) {
 			if (paramExpr.getExpr() instanceof FunctionCallIdentifier) {
 				raiseValidateError("UDF function call not supported as parameter to function call", false);
 			}
 			paramExpr.getExpr().validateExpression(ids, constVars, conditional);
 		}
+		FunctionStatement fstmt = (FunctionStatement)fblock.getStatement(0);
+		for( Expression expDef : fstmt.getInputDefaults() ) {
+			if( expDef != null )
+				expDef.validateExpression(ids, constVars, conditional);
+		}
 		
 		// Step 5: constant propagation into function call statement
 		if( !conditional ) {
@@ -142,7 +147,6 @@ public class FunctionCallIdentifier extends DataIdentifier
 		}
 	
 		// Step 6: check correctness of number of arguments and their types 
-		FunctionStatement fstmt = (FunctionStatement)fblock.getStatement(0);
 		if (fstmt.getInputParams().size() < _paramExprs.size()) { 
 			raiseValidateError("function " + _name 
 					+ " has incorrect number of parameters. Function requires " 

http://git-wip-us.apache.org/repos/asf/systemml/blob/bfd49528/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 50bb2d3..a24cb1a 100644
--- a/src/main/java/org/apache/sysml/parser/FunctionStatement.java
+++ b/src/main/java/org/apache/sysml/parser/FunctionStatement.java
@@ -26,8 +26,9 @@ public class FunctionStatement extends Statement
 {
 	private ArrayList<StatementBlock> _body;
 	protected String _name;
-	protected ArrayList <DataIdentifier> _inputParams;
-	protected ArrayList <DataIdentifier> _outputParams;
+	protected ArrayList<DataIdentifier> _inputParams;
+	protected ArrayList<Expression> _inputDefaults;
+	protected ArrayList<DataIdentifier> _outputParams;
 	
 	@Override
 	public Statement rewriteStatement(String prefix) {
@@ -38,6 +39,7 @@ public class FunctionStatement extends Statement
 		_body = new ArrayList<>();
 		_name = null;
 		_inputParams = new ArrayList<>();
+		_inputDefaults = new ArrayList<>();
 		_outputParams = new ArrayList<>();
 	}
 	
@@ -51,14 +53,29 @@ public class FunctionStatement extends Statement
 			.findFirst().orElse(null);
 	}
 	
+	public ArrayList<Expression> getInputDefaults() {
+		return _inputDefaults;
+	}
+	
+	public Expression getInputDefault(String name) {
+		for(int i=0; i<_inputParams.size(); i++)
+			if( _inputParams.get(i).getName().equals(name) )
+				return _inputDefaults.get(i);
+		return null;
+	}
+	
 	public ArrayList<DataIdentifier> getOutputParams(){
 		return _outputParams;
 	}
 	
-	public void setInputParams(ArrayList<DataIdentifier> inputParams){
+	public void setInputParams(ArrayList<DataIdentifier> inputParams) {
 		_inputParams = inputParams;
 	}
 	
+	public void setInputDefaults(ArrayList<Expression> inputDefaults) {
+		_inputDefaults = inputDefaults;
+	}
+	
 	public void setOutputParams(ArrayList<DataIdentifier> outputParams){
 		_outputParams = outputParams;
 	}

http://git-wip-us.apache.org/repos/asf/systemml/blob/bfd49528/src/main/java/org/apache/sysml/parser/dml/Dml.g4
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/parser/dml/Dml.g4 b/src/main/java/org/apache/sysml/parser/dml/Dml.g4
index e5c1f2c..46ee178 100644
--- a/src/main/java/org/apache/sysml/parser/dml/Dml.g4
+++ b/src/main/java/org/apache/sysml/parser/dml/Dml.g4
@@ -99,7 +99,7 @@ functionStatement returns [ org.apache.sysml.parser.common.StatementInfo info ]
     // ------------------------------------------
     // FunctionStatement & ExternalFunctionStatement
     // small change: only allow typed arguments here ... instead of data identifier
-    name=ID ('<-'|'=') 'function' '(' ( inputParams+=typedArgNoAssign (',' inputParams+=typedArgNoAssign)* )? ')'  ( 'return' '(' ( outputParams+=typedArgNoAssign (',' outputParams+=typedArgNoAssign)* )? ')' )? '{' (body+=statement ';'*)* '}' ';'* # InternalFunctionDefExpression
+    name=ID ('<-'|'=') 'function' '(' ( inputParams+=typedArgAssign (',' inputParams+=typedArgAssign)* )? ')'  ( 'return' '(' ( outputParams+=typedArgNoAssign (',' outputParams+=typedArgNoAssign)* )? ')' )? '{' (body+=statement ';'*)* '}' ';'* # InternalFunctionDefExpression
     | name=ID ('<-'|'=') 'externalFunction' '(' ( inputParams+=typedArgNoAssign (',' inputParams+=typedArgNoAssign)* )? ')'  ( 'return' '(' ( outputParams+=typedArgNoAssign (',' outputParams+=typedArgNoAssign)* )? ')' )?   'implemented' 'in' '(' ( otherParams+=strictParameterizedKeyValueString (',' otherParams+=strictParameterizedKeyValueString)* )? ')' ';'*    # ExternalFunctionDefExpression
     // ------------------------------------------
 ;
@@ -176,6 +176,8 @@ expression returns [ org.apache.sysml.parser.common.ExpressionInfo info ]
 ;
 
 typedArgNoAssign : paramType=ml_type paramName=ID;
+typedArgAssign : paramType=ml_type (paramName=ID | (paramName=ID '=')? paramVal=expression);
+
 parameterizedExpression : (paramName=ID '=')? paramVal=expression;
 strictParameterizedExpression : paramName=ID '=' paramVal=expression ;
 strictParameterizedKeyValueString : paramName=ID '=' paramVal=STRING ;

http://git-wip-us.apache.org/repos/asf/systemml/blob/bfd49528/src/main/java/org/apache/sysml/parser/dml/DmlPreprocessor.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/parser/dml/DmlPreprocessor.java b/src/main/java/org/apache/sysml/parser/dml/DmlPreprocessor.java
index 00473c0..56eb8ca 100644
--- a/src/main/java/org/apache/sysml/parser/dml/DmlPreprocessor.java
+++ b/src/main/java/org/apache/sysml/parser/dml/DmlPreprocessor.java
@@ -69,6 +69,7 @@ import org.apache.sysml.parser.dml.DmlParser.RelationalExpressionContext;
 import org.apache.sysml.parser.dml.DmlParser.SimpleDataIdentifierExpressionContext;
 import org.apache.sysml.parser.dml.DmlParser.StrictParameterizedExpressionContext;
 import org.apache.sysml.parser.dml.DmlParser.StrictParameterizedKeyValueStringContext;
+import org.apache.sysml.parser.dml.DmlParser.TypedArgAssignContext;
 import org.apache.sysml.parser.dml.DmlParser.TypedArgNoAssignContext;
 import org.apache.sysml.parser.dml.DmlParser.UnaryExpressionContext;
 import org.apache.sysml.parser.dml.DmlParser.ValueTypeContext;
@@ -177,6 +178,12 @@ public class DmlPreprocessor implements DmlListener {
 	public void exitTypedArgNoAssign(TypedArgNoAssignContext ctx) {}
 
 	@Override
+	public void enterTypedArgAssign(TypedArgAssignContext ctx) {}
+
+	@Override
+	public void exitTypedArgAssign(TypedArgAssignContext ctx) {}
+	
+	@Override
 	public void enterWhileStatement(WhileStatementContext ctx) {}
 
 	@Override

http://git-wip-us.apache.org/repos/asf/systemml/blob/bfd49528/src/main/java/org/apache/sysml/parser/dml/DmlSyntacticValidator.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/parser/dml/DmlSyntacticValidator.java b/src/main/java/org/apache/sysml/parser/dml/DmlSyntacticValidator.java
index 5624f2a..d87ccbb 100644
--- a/src/main/java/org/apache/sysml/parser/dml/DmlSyntacticValidator.java
+++ b/src/main/java/org/apache/sysml/parser/dml/DmlSyntacticValidator.java
@@ -25,6 +25,7 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 import org.antlr.v4.runtime.ParserRuleContext;
 import org.antlr.v4.runtime.Token;
@@ -104,6 +105,7 @@ import org.apache.sysml.parser.dml.DmlParser.SimpleDataIdentifierExpressionConte
 import org.apache.sysml.parser.dml.DmlParser.StatementContext;
 import org.apache.sysml.parser.dml.DmlParser.StrictParameterizedExpressionContext;
 import org.apache.sysml.parser.dml.DmlParser.StrictParameterizedKeyValueStringContext;
+import org.apache.sysml.parser.dml.DmlParser.TypedArgAssignContext;
 import org.apache.sysml.parser.dml.DmlParser.TypedArgNoAssignContext;
 import org.apache.sysml.parser.dml.DmlParser.UnaryExpressionContext;
 import org.apache.sysml.parser.dml.DmlParser.ValueTypeContext;
@@ -667,8 +669,8 @@ public class DmlSyntacticValidator extends CommonSyntacticValidator implements D
 		ctx.info.stmt = parForStmt;
 	}
 
-	private ArrayList<DataIdentifier> getFunctionParameters(List<TypedArgNoAssignContext> ctx) {
-		ArrayList<DataIdentifier> retVal = new ArrayList<>();
+	private ArrayList<DataIdentifier> getFunctionParametersNoAssign(List<TypedArgNoAssignContext> ctx) {
+		ArrayList<DataIdentifier> retVal = new ArrayList<>(ctx.size());
 		for(TypedArgNoAssignContext paramCtx : ctx) {
 			DataIdentifier dataId = new DataIdentifier(paramCtx.paramName.getText());
 			String dataType = (paramCtx.paramType == null || paramCtx.paramType.dataType() == null
@@ -684,6 +686,29 @@ public class DmlSyntacticValidator extends CommonSyntacticValidator implements D
 		}
 		return retVal;
 	}
+	
+	private ArrayList<DataIdentifier> getFunctionParametersAssign(List<TypedArgAssignContext> ctx) {
+		ArrayList<DataIdentifier> retVal = new ArrayList<>(ctx.size());
+		for(TypedArgAssignContext paramCtx : ctx) {
+			DataIdentifier dataId = new DataIdentifier(paramCtx.paramName.getText());
+			String dataType = (paramCtx.paramType == null || paramCtx.paramType.dataType() == null
+				|| paramCtx.paramType.dataType().getText() == null || paramCtx.paramType.dataType().getText().isEmpty()) ?
+				"scalar" : paramCtx.paramType.dataType().getText();
+			String valueType = paramCtx.paramType.valueType().getText();
+			
+			//check and assign data type
+			checkValidDataType(dataType, paramCtx.start);
+			if( !setDataAndValueType(dataId, dataType, valueType, paramCtx.start, false, true) )
+				return null;
+			retVal.add(dataId);
+		}
+		return retVal;
+	}
+	
+	private ArrayList<Expression> getFunctionDefaults(List<TypedArgAssignContext> ctx) {
+		return new ArrayList<>(ctx.stream().map(arg -> 
+			(arg.paramVal!=null)?arg.paramVal.info.expr:null).collect(Collectors.toList()));
+	}
 
 	@Override
 	public void exitIterablePredicateColonExpression(IterablePredicateColonExpressionContext ctx) {
@@ -706,23 +731,18 @@ public class DmlSyntacticValidator extends CommonSyntacticValidator implements D
 
 
 	// -----------------------------------------------------------------
-	// 				Internal & External Functions Definitions
+	//            Internal & External Functions Definitions
 	// -----------------------------------------------------------------
 
 	@Override
 	public void exitInternalFunctionDefExpression(InternalFunctionDefExpressionContext ctx) {
+		//populate function statement
 		FunctionStatement functionStmt = new FunctionStatement();
-
-		ArrayList<DataIdentifier> functionInputs  = getFunctionParameters(ctx.inputParams);
-		functionStmt.setInputParams(functionInputs);
-
-		// set function outputs
-		ArrayList<DataIdentifier> functionOutputs = getFunctionParameters(ctx.outputParams);
-		functionStmt.setOutputParams(functionOutputs);
-
-		// set function name
 		functionStmt.setName(ctx.name.getText());
-
+		functionStmt.setInputParams(getFunctionParametersAssign(ctx.inputParams));
+		functionStmt.setInputDefaults(getFunctionDefaults(ctx.inputParams));
+		functionStmt.setOutputParams(getFunctionParametersNoAssign(ctx.outputParams));
+		
 		if(ctx.body.size() > 0) {
 			// handle function body
 			// Create arraylist of one statement block
@@ -745,17 +765,11 @@ public class DmlSyntacticValidator extends CommonSyntacticValidator implements D
 
 	@Override
 	public void exitExternalFunctionDefExpression(ExternalFunctionDefExpressionContext ctx) {
+		//populate function statement
 		ExternalFunctionStatement functionStmt = new ExternalFunctionStatement();
-
-		ArrayList<DataIdentifier> functionInputs  = getFunctionParameters(ctx.inputParams);
-		functionStmt.setInputParams(functionInputs);
-
-		// set function outputs
-		ArrayList<DataIdentifier> functionOutputs = getFunctionParameters(ctx.outputParams);
-		functionStmt.setOutputParams(functionOutputs);
-
-		// set function name
 		functionStmt.setName(ctx.name.getText());
+		functionStmt.setInputParams(getFunctionParametersNoAssign(ctx.inputParams));
+		functionStmt.setOutputParams(getFunctionParametersNoAssign(ctx.outputParams));
 
 		// set other parameters
 		HashMap<String, String> otherParams = new HashMap<>();
@@ -949,6 +963,10 @@ public class DmlSyntacticValidator extends CommonSyntacticValidator implements D
 
 	@Override public void exitTypedArgNoAssign(TypedArgNoAssignContext ctx) {}
 
+	@Override public void enterTypedArgAssign(TypedArgAssignContext ctx) {}
+
+	@Override public void exitTypedArgAssign(TypedArgAssignContext ctx) {}
+
 	@Override public void enterStrictParameterizedExpression(StrictParameterizedExpressionContext ctx) {}
 
 	@Override public void exitStrictParameterizedExpression(StrictParameterizedExpressionContext ctx) {}

http://git-wip-us.apache.org/repos/asf/systemml/blob/bfd49528/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 f1d2493..36ce70a 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
@@ -40,6 +40,10 @@ public class FunctionPotpourriTest extends AutomatedTestBase
 	private final static String TEST_NAME10 = "FunPotpourriNamedArgsUnknown1";
 	private final static String TEST_NAME11 = "FunPotpourriNamedArgsUnknown2";
 	private final static String TEST_NAME12 = "FunPotpourriNamedArgsIPA";
+	private final static String TEST_NAME13 = "FunPotpourriDefaultArgScalar";
+	private final static String TEST_NAME14 = "FunPotpourriDefaultArgMatrix";
+	private final static String TEST_NAME15 = "FunPotpourriDefaultArgScalarMatrix1";
+	private final static String TEST_NAME16 = "FunPotpourriDefaultArgScalarMatrix2";
 	
 	private final static String TEST_DIR = "functions/misc/";
 	private final static String TEST_CLASS_DIR = TEST_DIR + FunctionPotpourriTest.class.getSimpleName() + "/";
@@ -59,6 +63,10 @@ public class FunctionPotpourriTest extends AutomatedTestBase
 		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" }) );
 		addTestConfiguration( TEST_NAME12, new TestConfiguration(TEST_CLASS_DIR, TEST_NAME12, new String[] { "R" }) );
+		addTestConfiguration( TEST_NAME13, new TestConfiguration(TEST_CLASS_DIR, TEST_NAME13, new String[] { "R" }) );
+		addTestConfiguration( TEST_NAME14, new TestConfiguration(TEST_CLASS_DIR, TEST_NAME14, new String[] { "R" }) );
+		addTestConfiguration( TEST_NAME15, new TestConfiguration(TEST_CLASS_DIR, TEST_NAME15, new String[] { "R" }) );
+		addTestConfiguration( TEST_NAME16, new TestConfiguration(TEST_CLASS_DIR, TEST_NAME16, new String[] { "R" }) );
 	}
 
 	@Test
@@ -131,6 +139,26 @@ public class FunctionPotpourriTest extends AutomatedTestBase
 		runFunctionTest( TEST_NAME12, false );
 	}
 	
+	@Test
+	public void testFunctionDefaultArgsScalar() {
+		runFunctionTest( TEST_NAME13, false );
+	}
+	
+	@Test
+	public void testFunctionDefaultArgsMatrix() {
+		runFunctionTest( TEST_NAME14, false );
+	}
+	
+	@Test
+	public void testFunctionDefaultArgsScalarMatrix1() {
+		runFunctionTest( TEST_NAME15, false );
+	}
+	
+	@Test
+	public void testFunctionDefaultArgsScalarMatrix2() {
+		runFunctionTest( TEST_NAME16, false );
+	}
+	
 	private void runFunctionTest(String testName, boolean error) {
 		TestConfiguration config = getTestConfiguration(testName);
 		loadTestConfiguration(config);
@@ -141,6 +169,6 @@ public class FunctionPotpourriTest extends AutomatedTestBase
 			"-args", String.valueOf(error).toUpperCase()};
 
 		//run script and compare output
-		runTest(true, error, DMLException.class, -1); 
+		runTest(true, error, DMLException.class, -1);
 	}
 }

http://git-wip-us.apache.org/repos/asf/systemml/blob/bfd49528/src/test/scripts/functions/misc/FunPotpourriDefaultArgMatrix.dml
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/misc/FunPotpourriDefaultArgMatrix.dml b/src/test/scripts/functions/misc/FunPotpourriDefaultArgMatrix.dml
new file mode 100644
index 0000000..cadef10
--- /dev/null
+++ b/src/test/scripts/functions/misc/FunPotpourriDefaultArgMatrix.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(1,300,500), Matrix[Double] B) return (Matrix[Double] C) {
+  while(FALSE){} # no inlining
+  C = A %*% B + 7;
+}
+
+X2 = matrix(2, 500, 200)
+
+C = foo1(B=X2);
+
+print("out:  " + sum(C))

http://git-wip-us.apache.org/repos/asf/systemml/blob/bfd49528/src/test/scripts/functions/misc/FunPotpourriDefaultArgScalar.dml
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/misc/FunPotpourriDefaultArgScalar.dml b/src/test/scripts/functions/misc/FunPotpourriDefaultArgScalar.dml
new file mode 100644
index 0000000..6bb6ad3
--- /dev/null
+++ b/src/test/scripts/functions/misc/FunPotpourriDefaultArgScalar.dml
@@ -0,0 +1,39 @@
+#-------------------------------------------------------------
+#
+# 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, Double s = 7) return (Matrix[Double] C) {
+  while(FALSE){} # no inlining
+  C = A %*% B + s;
+}
+
+foo2 = function(Matrix[Double] A, Matrix[Double] B) return (Matrix[Double] C) {
+  while(FALSE){} # no inlining
+  C = A %*% B + 7;
+}
+
+X1 = matrix(1, 300, 500)
+X2 = matrix(2, 500, 200)
+
+C = foo1(B=X2, A=X1);
+D = foo2(X1, X2);
+
+if( sum(C!=D) > 0 )
+  print("ERROR: "+sum(C!=D)+" differences.")

http://git-wip-us.apache.org/repos/asf/systemml/blob/bfd49528/src/test/scripts/functions/misc/FunPotpourriDefaultArgScalarMatrix1.dml
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/misc/FunPotpourriDefaultArgScalarMatrix1.dml b/src/test/scripts/functions/misc/FunPotpourriDefaultArgScalarMatrix1.dml
new file mode 100644
index 0000000..c44f3ef
--- /dev/null
+++ b/src/test/scripts/functions/misc/FunPotpourriDefaultArgScalarMatrix1.dml
@@ -0,0 +1,39 @@
+#-------------------------------------------------------------
+#
+# 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(1, 300, 500), Matrix[Double] B, Double s = 7) return (Matrix[Double] C) {
+  while(FALSE){} # no inlining
+  C = A %*% B + s;
+}
+
+foo2 = function(Matrix[Double] A, Matrix[Double] B) return (Matrix[Double] C) {
+  while(FALSE}{) # no inlining
+  C = A %*% B + 7;
+}
+
+X1 = matrix(1, 300, 500)
+X2 = matrix(2, 500, 200)
+
+C = foo1(B=X2);
+D = foo2(X1, X2);
+
+if( sum(C!=D) > 0 )
+  print("ERROR: "+sum(C!=D)+" differences.")

http://git-wip-us.apache.org/repos/asf/systemml/blob/bfd49528/src/test/scripts/functions/misc/FunPotpourriDefaultArgScalarMatrix2.dml
----------------------------------------------------------------------
diff --git a/src/test/scripts/functions/misc/FunPotpourriDefaultArgScalarMatrix2.dml b/src/test/scripts/functions/misc/FunPotpourriDefaultArgScalarMatrix2.dml
new file mode 100644
index 0000000..d565a97
--- /dev/null
+++ b/src/test/scripts/functions/misc/FunPotpourriDefaultArgScalarMatrix2.dml
@@ -0,0 +1,43 @@
+#-------------------------------------------------------------
+#
+# 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(1, 300, 500), Matrix[Double] B, Double s = 7) return (Matrix[Double] C, Matrix[Double] D) {
+  while(FALSE){} # no inlining
+  C = A %*% B + s;
+  D = C + 7;
+}
+
+foo2 = function(Matrix[Double] A, Matrix[Double] B) return (Matrix[Double] C, Matrix[Double] D) {
+  while(FALSE}{) # no inlining
+  C = A %*% B + 7;
+  D = C + 7;
+}
+
+X1 = matrix(1, 300, 500)
+X2 = matrix(2, 500, 200)
+
+[C1,C2] = foo1(B=X2);
+[D1,D2] = foo2(X1, X2);
+
+if( sum(C1!=D1) > 0 )
+  print("ERROR1: "+sum(C1!=D1)+" differences.")
+if( sum(C2!=D2) > 0 )
+  print("ERROR2: "+sum(C2!=D2)+" differences.")