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 <mboe...@gmail.com> Authored: Thu Jul 26 18:33:57 2018 -0700 Committer: Matthias Boehm <mboe...@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.")