diff --git a/edu.cuny.hunter.hybridize.core/src/edu/cuny/hunter/hybridize/core/analysis/Function.java b/edu.cuny.hunter.hybridize.core/src/edu/cuny/hunter/hybridize/core/analysis/Function.java index 121484ede..4d6564f8e 100644 --- a/edu.cuny.hunter.hybridize.core/src/edu/cuny/hunter/hybridize/core/analysis/Function.java +++ b/edu.cuny.hunter.hybridize.core/src/edu/cuny/hunter/hybridize/core/analysis/Function.java @@ -3,17 +3,21 @@ import static org.eclipse.core.runtime.Platform.getLog; import java.io.File; +import java.util.ArrayList; import java.util.Objects; +import java.util.Set; import org.eclipse.core.runtime.ILog; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; +import org.python.pydev.ast.codecompletion.revisited.visitors.Definition; import org.python.pydev.core.IPythonNature; import org.python.pydev.core.docutils.PySelection; import org.python.pydev.parser.jython.ast.Attribute; import org.python.pydev.parser.jython.ast.Call; import org.python.pydev.parser.jython.ast.FunctionDef; +import org.python.pydev.parser.jython.ast.Name; import org.python.pydev.parser.jython.ast.NameTok; import org.python.pydev.parser.jython.ast.argumentsType; import org.python.pydev.parser.jython.ast.decoratorsType; @@ -41,24 +45,54 @@ public class Function extends RefactorableProgramEntity { */ public class HybridizationParameters { + /** + * Available in TF version [2.4,2.11]. + */ private static final String EXPERIMENTAL_FOLLOW_TYPE_HINTS = "experimental_follow_type_hints"; + /** + * Available in TF version [2.0,2.11]. + */ private static final String EXPERIMENTAL_AUTOGRAPH_OPTIONS = "experimental_autograph_options"; + /** + * Available in TF version [2.1,2.11]. + */ private static final String EXPERIMENTAL_IMPLEMENTS = "experimental_implements"; + /** + * Available in TF version [2.9,2.11]. Previously, experimental_relax_shapes which is available TF version [2.0,2.11]. + */ private static final String REDUCE_RETRACING = "reduce_retracing"; + /** + * Available in TF version [2.0,2.11]. + */ private static final String EXPERIMENTAL_RELAX_SHAPES = "experimental_relax_shapes"; + /** + * Available in TF version [2.1,2.11]. + */ private static final String EXPERIMENTAL_COMPILE = "experimental_compile"; + /** + * Available in TF version [2.5,2.11]. Previously, experimental_compile which is available TF version [2.1,2.11]. + */ private static final String JIT_COMPILE = "jit_compile"; + /** + * Available in TF version [2.0,2.11]. + */ private static final String AUTOGRAPH = "autograph"; + /** + * Available in TF version [2.0,2.11]. + */ private static final String INPUT_SIGNATURE = "input_signature"; + /** + * Available in TF version [2.0,2.11]. + */ private static final String FUNC = "func"; /** @@ -108,6 +142,10 @@ public HybridizationParameters(IProgressMonitor monitor) throws BadLocationExcep // Will contain the last tf.function decorator decoratorsType tfFunctionDecorator = null; + // Declaring definitions of the decorator, if it contains multiple definitions there might be more than one in this set. Since + // we are dealing with tf.function, we check we it has one definition. + Definition declaringDefinition = null; + // Iterate through the decorators of the function for (decoratorsType decorator : decoratorArray) { IDocument document = Function.this.getContainingDocument(); @@ -116,19 +154,76 @@ public HybridizationParameters(IProgressMonitor monitor) throws BadLocationExcep // Save the hybrid decorator try { if (Function.isHybrid(decorator, Function.this.containingModuleName, Function.this.containingFile, selection, - Function.this.nature, monitor)) // TODO: Cache this from a previous call (#118). + Function.this.nature, monitor)) { // TODO: Cache this from a previous call (#118). tfFunctionDecorator = decorator; + // Returns the set of potential declaring definitions of the selection. + Set potentialDeclaringDefitinion = Util.getDeclaringDefinition(selection, + Function.this.containingModuleName, Function.this.containingFile, Function.this.nature, monitor); + + // If it has an element, we store the definition in a variable. + if (potentialDeclaringDefitinion.iterator().hasNext()) + declaringDefinition = potentialDeclaringDefitinion.iterator().next(); + else + throw new IllegalStateException(String.format( + "Can't find declaring definition for selection: %s in line: %s, file: %s, and project: %s.", + selection.getSelectedText(), selection.getLineWithoutCommentsOrLiterals().strip(), + Function.this.containingFile.getName(), Function.this.nature.getProject())); + } } catch (AmbiguousDeclaringModuleException e) { throw new IllegalStateException("Can't determine whether decorator: " + decorator + " is hybrid.", e); } } // We expect to have the last tf.function decorator in tfFunctionDecorator + // Getting tf.functions Python definition arguments. + ArrayList argumentIdDeclaringDefintion = getPythonDefinitionArguments(declaringDefinition); + if (tfFunctionDecorator != null) // tfFunctionDecorator must be an instance of Call, because that's the only way we have parameters. if (tfFunctionDecorator.func instanceof Call) { Call callFunction = (Call) tfFunctionDecorator.func; - // We only care about the actual keywords for now. - // TODO: Parse positional arguments (#108). + + exprType[] tfFunctionPositionalArgs = callFunction.args; + + // We iterate over the tf.function's parameters positions. + if (tfFunctionPositionalArgs.length <= argumentIdDeclaringDefintion.size()) { + for (int i = 0; i < tfFunctionPositionalArgs.length; i++) { + // From the position i, we use the tf.function's definition to verify which parameter we are analyzing. + String evaluatedArgument = argumentIdDeclaringDefintion.get(i); + + // Matching the arguments from the definition and the arguments from the code being analyzed. + if (evaluatedArgument.equals(FUNC)) + this.funcParamExists = true; + else if (evaluatedArgument.equals(INPUT_SIGNATURE)) + this.inputSignatureParamExists = true; + else if (evaluatedArgument.equals(AUTOGRAPH)) + this.autoGraphParamExists = true; + // In our accepted interval version ([2.0,2.11]) of the API allows parameter names jit_compile and + // deprecated name experimental_compile. + else if (evaluatedArgument.equals(JIT_COMPILE) || evaluatedArgument.equals(EXPERIMENTAL_COMPILE)) + this.jitCompileParamExists = true; + // In our accepted interval version ([2.0,2.11]) of the API allows parameter names reduce_retracing + // and deprecated name experimental_relax_shapes. + else if (evaluatedArgument.equals(REDUCE_RETRACING)) + this.reduceRetracingParamExists = true; + else if (evaluatedArgument.equals(EXPERIMENTAL_RELAX_SHAPES)) + this.reduceRetracingParamExists = true; + else if (evaluatedArgument.equals(EXPERIMENTAL_IMPLEMENTS)) + this.experimentalImplementsParamExists = true; + else if (evaluatedArgument.equals(EXPERIMENTAL_AUTOGRAPH_OPTIONS)) + this.experimentalAutographOptionsParamExists = true; + else if (evaluatedArgument.equals(EXPERIMENTAL_FOLLOW_TYPE_HINTS)) + this.experimentaFollowTypeHintsParamExists = true; + else + throw new IllegalArgumentException("Unable to process tf.function argument at position " + i); + } + } else + throw new IllegalArgumentException( + "Unable to process tf.function argument. The number of arguments " + tfFunctionPositionalArgs.length + + " exceeds the accepted number of argumets " + argumentIdDeclaringDefintion.size()); + + // Processing keywords arguments + // If we have keyword parameter, afterwards, we cannot have positional parameters because it would result in invalid + // Python code. This is why we check the keywords last. keywordType[] keywords = callFunction.keywords; for (keywordType keyword : keywords) { if (keyword.arg instanceof NameTok) { @@ -142,15 +237,13 @@ else if (name.id.equals(INPUT_SIGNATURE)) else if (name.id.equals(AUTOGRAPH)) // Found parameter autograph this.autoGraphParamExists = true; - // The version of the API we are using allows - // parameter names jit_compile and - // deprecated name experimental_compile + // In our accepted interval version ([2.0,2.11]) of the API allows parameter names jit_compile and + // deprecated name experimental_compile. else if (name.id.equals(JIT_COMPILE) || name.id.equals(EXPERIMENTAL_COMPILE)) // Found parameter jit_compile/experimental_compile this.jitCompileParamExists = true; - // The version of the API we are using allows - // parameter names reduce_retracing - // and deprecated name experimental_relax_shapes + // In our accepted interval version ([2.0,2.11]) of the API allows parameter names reduce_retracing + // and deprecated name experimental_relax_shapes. else if (name.id.equals(REDUCE_RETRACING) || name.id.equals(EXPERIMENTAL_RELAX_SHAPES)) // Found parameter reduce_retracing // or experimental_relax_shapes @@ -169,6 +262,41 @@ else if (name.id.equals(EXPERIMENTAL_FOLLOW_TYPE_HINTS)) } // else, tf.function is used without parameters. } + /** + * Get the parameter names from the {@link Definition}. + * + * @param declaringDefinition The Definition to use. + * @return An array with the names of the arguments given by {@link Definition}. + */ + private ArrayList getPythonDefinitionArguments(Definition declaringDefinition) { + // Python source arguments from the declaring definition + exprType[] declaringArguments = null; + + // Getting the arguments from TensorFlow source + if (declaringDefinition != null) { + if (declaringDefinition.ast instanceof FunctionDef) { + FunctionDef declaringFunctionDefinition = (FunctionDef) declaringDefinition.ast; + argumentsType declaringArgumentTypes = declaringFunctionDefinition.args; + declaringArguments = declaringArgumentTypes.args; + } + } + + // Python source arguments from the declaring definition + ArrayList argumentIdDeclaringDefintion = new ArrayList<>(); + + // Getting the arguments from the definition + if (declaringArguments != null) { + for (exprType declaredArgument : declaringArguments) { + if (declaredArgument instanceof Name) { + Name argumentName = (Name) declaredArgument; + argumentIdDeclaringDefintion.add(argumentName.id); + } + } + } + + return argumentIdDeclaringDefintion; + } + /** * True iff this {@link Function}'s {@link decoratorsType} has parameter autograph. * diff --git a/edu.cuny.hunter.hybridize.core/src/edu/cuny/hunter/hybridize/core/analysis/Util.java b/edu.cuny.hunter.hybridize.core/src/edu/cuny/hunter/hybridize/core/analysis/Util.java index bf7093abf..b85c0b12c 100644 --- a/edu.cuny.hunter.hybridize.core/src/edu/cuny/hunter/hybridize/core/analysis/Util.java +++ b/edu.cuny.hunter.hybridize.core/src/edu/cuny/hunter/hybridize/core/analysis/Util.java @@ -35,24 +35,19 @@ public class Util { private static final ILog LOG = getLog(Util.class); /** - * Get the name of the module defining the entity described in the given {@link PySelection}. + * Get the set of potential declaring definitions of the entity described in the given {@link PySelection}. * * @param selection The {@link PySelection} in question. * @param containingModName The name of the module containing the {@link PySelection}. * @param containingFile The {@link File} containing the module. * @param nature The {@link IPythonNature} to use. * @param monitor The IProgressMonitor to use. - * @return The name of the module defining the given {@link PySelection}. + * @return The definition of {@link PySelection}. * @throws AmbiguousDeclaringModuleException On ambiguous definitions found. * @throws BadLocationException On a parsing error. */ - public static String getDeclaringModuleName(PySelection selection, String containingModName, File containingFile, IPythonNature nature, - IProgressMonitor monitor) throws BadLocationException, AmbiguousDeclaringModuleException { - monitor.beginTask("Getting declaring module name.", 1); - - LOG.info(String.format("Getting declaring module name for selection: %s in line: %s, module: %s, file: %s, and project: %s.", - selection.getSelectedText(), selection.getLineWithoutCommentsOrLiterals().strip(), containingModName, containingFile, - nature.getProject())); + public static Set getDeclaringDefinition(PySelection selection, String containingModName, File containingFile, + IPythonNature nature, IProgressMonitor monitor) throws BadLocationException, AmbiguousDeclaringModuleException { RefactoringRequest request = new RefactoringRequest(containingFile, selection, nature); @@ -77,14 +72,49 @@ public static String getDeclaringModuleName(PySelection selection, String contai selection.getSelectedText(), selection.getLineWithoutCommentsOrLiterals().strip(), containingModName, containingFile.getName(), nature.getProject())); - // Collect the potential declaring module names. - Set potentialDeclaringModuleNames = new HashSet<>(); + // Collect the potential declaring definition names. + Set potentialDeclaringDefinitions = new HashSet<>(); // for each match. for (ItemPointer itemPointer : pointers) { Definition definition = itemPointer.definition; LOG.info("Found definition: " + definition + "."); + // add it to the set of found definition names. + potentialDeclaringDefinitions.add(definition); + } + + return potentialDeclaringDefinitions; + } + + /** + * Get the name of the module defining the entity described in the given {@link PySelection}. + * + * @param selection The {@link PySelection} in question. + * @param containingModName The name of the module containing the {@link PySelection}. + * @param containingFile The {@link File} containing the module. + * @param nature The {@link IPythonNature} to use. + * @param monitor The IProgressMonitor to use. + * @return The name of the module defining the given {@link PySelection}. + * @throws AmbiguousDeclaringModuleException On ambiguous definitions found. + * @throws BadLocationException On a parsing error. + */ + public static String getDeclaringModuleName(PySelection selection, String containingModName, File containingFile, IPythonNature nature, + IProgressMonitor monitor) throws BadLocationException, AmbiguousDeclaringModuleException { + monitor.beginTask("Getting declaring module name.", 1); + + LOG.info(String.format("Getting declaring module name for selection: %s in line: %s, module: %s, file: %s, and project: %s.", + selection.getSelectedText(), selection.getLineWithoutCommentsOrLiterals().strip(), containingModName, containingFile, + nature.getProject())); + + Set definitions = getDeclaringDefinition(selection, containingModName, containingFile, nature, monitor); + + // Collect the potential declaring module names. + Set potentialDeclaringModuleNames = new HashSet<>(); + + // for each definition. + for (Definition definition : definitions) { + IModule module = definition.module; LOG.info(String.format("Found module: %s.", module)); diff --git a/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters/in/A.py b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters/in/A.py new file mode 100644 index 000000000..a9556c002 --- /dev/null +++ b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters/in/A.py @@ -0,0 +1,10 @@ +import tensorflow as tf + + +@tf.function +def test(): + pass + + +if __name__ == '__main__': + test() diff --git a/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters/in/requirements.txt b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters/in/requirements.txt new file mode 100644 index 000000000..b154f958f --- /dev/null +++ b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters/in/requirements.txt @@ -0,0 +1 @@ +tensorflow==2.9.3 diff --git a/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters10/in/A.py b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters10/in/A.py new file mode 100644 index 000000000..d59e32ec4 --- /dev/null +++ b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters10/in/A.py @@ -0,0 +1,14 @@ +import tensorflow as tf + +# experimental_compile cannot be True or False because you get the following error ValueError: Cannot specify both 'experimental_compile' and 'jit_compile'. +# That is why I put the value as None. + + +@tf.function(None, (tf.TensorSpec(shape=[None], dtype=tf.float32),), False, True, True, "google.matmul_low_rank_matrix", tf.autograph.experimental.Feature.EQUALITY_OPERATORS, True, None) +def test(x): + return x + + +if __name__ == '__main__': + number = tf.constant([1.0]) + print(test(number)) diff --git a/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters10/in/requirements.txt b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters10/in/requirements.txt new file mode 100644 index 000000000..b154f958f --- /dev/null +++ b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters10/in/requirements.txt @@ -0,0 +1 @@ +tensorflow==2.9.3 diff --git a/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters11/in/A.py b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters11/in/A.py new file mode 100644 index 000000000..bb4f86a78 --- /dev/null +++ b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters11/in/A.py @@ -0,0 +1,9 @@ +import tensorflow as tf + +@tf.function(None, (tf.TensorSpec(shape=[None], dtype=tf.float32),), False, True, True, "google.matmul_low_rank_matrix", tf.autograph.experimental.Feature.EQUALITY_OPERATORS, True, None, False) +def test(x: tf.Tensor): + return x + +if __name__ == '__main__': + number = tf.constant([1.0, 1.0]) + print(test(number)) diff --git a/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters11/in/requirements.txt b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters11/in/requirements.txt new file mode 100644 index 000000000..b154f958f --- /dev/null +++ b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters11/in/requirements.txt @@ -0,0 +1 @@ +tensorflow==2.9.3 diff --git a/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters12/in/A.py b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters12/in/A.py new file mode 100644 index 000000000..f27c0fdf1 --- /dev/null +++ b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters12/in/A.py @@ -0,0 +1,10 @@ +import tensorflow as tf + + +@tf.function(None, None, True, None, False, None, None, None, None, None) +def test(): + pass + + +if __name__ == '__main__': + test() diff --git a/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters12/in/requirements.txt b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters12/in/requirements.txt new file mode 100644 index 000000000..b154f958f --- /dev/null +++ b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters12/in/requirements.txt @@ -0,0 +1 @@ +tensorflow==2.9.3 diff --git a/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters13/in/A.py b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters13/in/A.py new file mode 100644 index 000000000..1db4200bc --- /dev/null +++ b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters13/in/A.py @@ -0,0 +1,11 @@ +import tensorflow as tf + + +@tf.function(None, (tf.TensorSpec(shape=[None], dtype=tf.float32),), False, True, "google.matmul_low_rank_matrix") +def test(x): + return x + + +if __name__ == '__main__': + number = tf.constant([1.0, 1.0]) + test(number) diff --git a/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters13/in/requirements.txt b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters13/in/requirements.txt new file mode 100644 index 000000000..75f6aa974 --- /dev/null +++ b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters13/in/requirements.txt @@ -0,0 +1 @@ +tensorflow==2.8.0 diff --git a/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters14/in/A.py b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters14/in/A.py new file mode 100644 index 000000000..0148e095d --- /dev/null +++ b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters14/in/A.py @@ -0,0 +1,11 @@ +import tensorflow as tf + + +@tf.function(None, (tf.TensorSpec(shape=[None], dtype=tf.float32),), autograph=True) +def test(x): + return x + + +if __name__ == '__main__': + number = tf.constant([1.0, 1.0]) + test(number) diff --git a/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters14/in/requirements.txt b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters14/in/requirements.txt new file mode 100644 index 000000000..b154f958f --- /dev/null +++ b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters14/in/requirements.txt @@ -0,0 +1 @@ +tensorflow==2.9.3 diff --git a/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters2/in/A.py b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters2/in/A.py new file mode 100644 index 000000000..9ec0253d0 --- /dev/null +++ b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters2/in/A.py @@ -0,0 +1,10 @@ +import tensorflow as tf + + +@tf.function(None) +def test(): + pass + + +if __name__ == '__main__': + test() diff --git a/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters2/in/requirements.txt b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters2/in/requirements.txt new file mode 100644 index 000000000..b154f958f --- /dev/null +++ b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters2/in/requirements.txt @@ -0,0 +1 @@ +tensorflow==2.9.3 diff --git a/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters3/in/A.py b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters3/in/A.py new file mode 100644 index 000000000..9954b0f0b --- /dev/null +++ b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters3/in/A.py @@ -0,0 +1,11 @@ +import tensorflow as tf + + +@tf.function(None, (tf.TensorSpec(shape=[None], dtype=tf.float32),)) +def test(x): + return x + + +if __name__ == '__main__': + number = tf.constant([1.0, 1.0]) + print(test(number)) diff --git a/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters3/in/requirements.txt b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters3/in/requirements.txt new file mode 100644 index 000000000..b154f958f --- /dev/null +++ b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters3/in/requirements.txt @@ -0,0 +1 @@ +tensorflow==2.9.3 diff --git a/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters4/in/A.py b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters4/in/A.py new file mode 100644 index 000000000..3f5f57356 --- /dev/null +++ b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters4/in/A.py @@ -0,0 +1,11 @@ +import tensorflow as tf + + +@tf.function(None, (tf.TensorSpec(shape=[None], dtype=tf.float32),), False) +def test(x): + return x + + +if __name__ == '__main__': + number = tf.constant([1.0, 1.0]) + print(test(number)) diff --git a/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters4/in/requirements.txt b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters4/in/requirements.txt new file mode 100644 index 000000000..b154f958f --- /dev/null +++ b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters4/in/requirements.txt @@ -0,0 +1 @@ +tensorflow==2.9.3 diff --git a/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters5/in/A.py b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters5/in/A.py new file mode 100644 index 000000000..f99166ec0 --- /dev/null +++ b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters5/in/A.py @@ -0,0 +1,11 @@ +import tensorflow as tf + + +@tf.function(None, (tf.TensorSpec(shape=[None], dtype=tf.float32),), False, True) +def test(x): + return x + + +if __name__ == '__main__': + number = tf.constant([1.0, 1.0]) + print(test(number)) diff --git a/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters5/in/requirements.txt b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters5/in/requirements.txt new file mode 100644 index 000000000..b154f958f --- /dev/null +++ b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters5/in/requirements.txt @@ -0,0 +1 @@ +tensorflow==2.9.3 diff --git a/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters6/in/A.py b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters6/in/A.py new file mode 100644 index 000000000..23b756261 --- /dev/null +++ b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters6/in/A.py @@ -0,0 +1,11 @@ +import tensorflow as tf + + +@tf.function(None, (tf.TensorSpec(shape=[None], dtype=tf.float32),), False, True, True) +def test(x): + return x + + +if __name__ == '__main__': + number = tf.constant([1.0, 1.0]) + print(test(number)) diff --git a/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters6/in/requirements.txt b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters6/in/requirements.txt new file mode 100644 index 000000000..b154f958f --- /dev/null +++ b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters6/in/requirements.txt @@ -0,0 +1 @@ +tensorflow==2.9.3 diff --git a/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters7/in/A.py b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters7/in/A.py new file mode 100644 index 000000000..1b0f5e252 --- /dev/null +++ b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters7/in/A.py @@ -0,0 +1,11 @@ +import tensorflow as tf + + +@tf.function(None, (tf.TensorSpec(shape=[None], dtype=tf.float32),), False, True, True, "google.matmul_low_rank_matrix") +def test(x): + return x + + +if __name__ == '__main__': + number = tf.constant([1.0, 1.0]) + print(test(number)) diff --git a/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters7/in/requirements.txt b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters7/in/requirements.txt new file mode 100644 index 000000000..b154f958f --- /dev/null +++ b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters7/in/requirements.txt @@ -0,0 +1 @@ +tensorflow==2.9.3 diff --git a/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters8/in/A.py b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters8/in/A.py new file mode 100644 index 000000000..d5417224a --- /dev/null +++ b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters8/in/A.py @@ -0,0 +1,11 @@ +import tensorflow as tf + + +@tf.function(None, (tf.TensorSpec(shape=[None], dtype=tf.float32),), False, True, True, "google.matmul_low_rank_matrix", tf.autograph.experimental.Feature.EQUALITY_OPERATORS) +def test(x): + return x + + +if __name__ == '__main__': + number = tf.constant([1.0]) + print(test(number)) diff --git a/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters8/in/requirements.txt b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters8/in/requirements.txt new file mode 100644 index 000000000..b154f958f --- /dev/null +++ b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters8/in/requirements.txt @@ -0,0 +1 @@ +tensorflow==2.9.3 diff --git a/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters9/in/A.py b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters9/in/A.py new file mode 100644 index 000000000..56491ef55 --- /dev/null +++ b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters9/in/A.py @@ -0,0 +1,11 @@ +import tensorflow as tf + + +@tf.function(None, (tf.TensorSpec(shape=[None], dtype=tf.float32),), False, True, True, "google.matmul_low_rank_matrix", tf.autograph.experimental.Feature.EQUALITY_OPERATORS, True) +def test(x): + return x + + +if __name__ == '__main__': + number = tf.constant([1.0]) + print(test(number)) diff --git a/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters9/in/requirements.txt b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters9/in/requirements.txt new file mode 100644 index 000000000..b154f958f --- /dev/null +++ b/edu.cuny.hunter.hybridize.tests/resources/HybridizeFunction/testPositionalParameters9/in/requirements.txt @@ -0,0 +1 @@ +tensorflow==2.9.3 diff --git a/edu.cuny.hunter.hybridize.tests/test cases/edu/cuny/hunter/hybridize/tests/HybridizeFunctionRefactoringTest.java b/edu.cuny.hunter.hybridize.tests/test cases/edu/cuny/hunter/hybridize/tests/HybridizeFunctionRefactoringTest.java index 4f6f3ba50..abe3e36d2 100644 --- a/edu.cuny.hunter.hybridize.tests/test cases/edu/cuny/hunter/hybridize/tests/HybridizeFunctionRefactoringTest.java +++ b/edu.cuny.hunter.hybridize.tests/test cases/edu/cuny/hunter/hybridize/tests/HybridizeFunctionRefactoringTest.java @@ -569,7 +569,7 @@ public void testAmbiguousDefinition() throws Exception { } /** - * Test for #30. This simply tests whether we can parse the tf.function argument input_signature. + * Test for #30. This simply tests whether we can parse the tf.function keyword argument input_signature. */ @Test public void testComputeParameters() throws Exception { @@ -590,7 +590,7 @@ public void testComputeParameters() throws Exception { } /** - * Test for #30. This simply tests whether we can parse the tf.function argument experimental_autograph_options + * Test for #30. This simply tests whether we can parse the tf.function keyword argument experimental_autograph_options */ @Test public void testComputeParameters2() throws Exception { @@ -612,7 +612,7 @@ public void testComputeParameters2() throws Exception { } /** - * Test for #30. This simply tests whether we can parse the tf.function argument experimental_follow_type_hints. + * Test for #30. This simply tests whether we can parse the tf.function keyword argument experimental_follow_type_hints. */ @Test public void testComputeParameters3() throws Exception { @@ -633,7 +633,7 @@ public void testComputeParameters3() throws Exception { } /** - * Test for #30. This simply tests whether we can parse the tf.function argument experimental_implements. + * Test for #30. This simply tests whether we can parse the tf.function keyword argument experimental_implements. */ @Test public void testComputeParameters4() throws Exception { @@ -654,7 +654,7 @@ public void testComputeParameters4() throws Exception { } /** - * Test for #30. This simply tests whether we can parse the tf.function argument jit_compile. + * Test for #30. This simply tests whether we can parse the tf.function keyword argument jit_compile. */ @Test public void testComputeParameters5() throws Exception { @@ -675,7 +675,7 @@ public void testComputeParameters5() throws Exception { } /** - * Test for #30. This simply tests whether we can parse the tf.function argument reduce_retracing. + * Test for #30. This simply tests whether we can parse the tf.function keyword argument reduce_retracing. */ @Test public void testComputeParameters6() throws Exception { @@ -694,7 +694,7 @@ public void testComputeParameters6() throws Exception { } /** - * Test for #30. This simply tests whether we can parse the tf.function argument autograph. + * Test for #30. This simply tests whether we can parse the tf.function keyword argument autograph. */ @Test public void testComputeParameters7() throws Exception { @@ -736,7 +736,7 @@ public void testComputeParameters8() throws Exception { } /** - * Test for #30. This simply tests whether we can parse tf.function arguments when we have multiple. + * Test for #30. This simply tests whether we can parse tf.function keyword arguments when we have multiple. */ @Test public void testComputeParameters9() throws Exception { @@ -757,7 +757,7 @@ public void testComputeParameters9() throws Exception { } /** - * Test for #30. Test custom decorator with the same parameter names as tf.function. + * Test for #30. Test custom decorator with the same keyword parameter names as tf.function. */ @Test public void testComputeParameters10() throws Exception { @@ -780,8 +780,8 @@ public void testComputeParameters10() throws Exception { } /** - * Test for #30. Test custom decorator with the same parameter names as tf.function and a tf.function (total of two decorators) and only - * count the parameters from the tf.function decorator. + * Test for #30. Test custom decorator with the same keyword parameter names as tf.function and a tf.function (total: two decorators) + * and only count the keyword parameters from the tf.function decorator. */ @Test public void testComputeParameters11() throws Exception { @@ -805,7 +805,7 @@ public void testComputeParameters11() throws Exception { } /** - * Test for #30. Tests two different tf.functions. Should only count the parameters of the last one. + * Test for #30. Tests two different tf.functions. Should only count the keyword parameters of the last one. */ @Test public void testComputeParameters12() throws Exception { @@ -826,6 +826,274 @@ public void testComputeParameters12() throws Exception { } + /** + * Test for #108. This tests a tf.function with no arguments. + */ + @Test + public void testPositionalParameters() throws Exception { + Set functions = this.getFunctions(); + assertNotNull(functions); + assertEquals(1, functions.size()); + Function function = functions.iterator().next(); + assertNotNull(function); + + Function.HybridizationParameters args = function.getHybridizationParameters(); + assertNotNull(args); + + assertTrue(!args.hasFuncParam() && !args.hasInputSignatureParam() && !args.hasAutoGraphParam() && !args.hasJitCompileParam() + && !args.hasReduceRetracingParam() && !args.hasExperimentalImplementsParam() && !args.hasExperimentalAutographOptParam() + && !args.hasExperimentalFollowTypeHintsParam()); + } + + /** + * Test for #108. This tests whether we can parse one tf.function positional argument. + */ + @Test + public void testPositionalParameters2() throws Exception { + Set functions = this.getFunctions(); + assertNotNull(functions); + assertEquals(1, functions.size()); + Function function = functions.iterator().next(); + assertNotNull(function); + + Function.HybridizationParameters args = function.getHybridizationParameters(); + assertNotNull(args); + + // In this test, we have only the first positional argument `func`. If we want to use tf.function as a decorator, that first + // parameter should be None. + assertTrue(args.hasFuncParam() && !args.hasInputSignatureParam() && !args.hasAutoGraphParam() && !args.hasJitCompileParam() + && !args.hasReduceRetracingParam() && !args.hasExperimentalImplementsParam() && !args.hasExperimentalAutographOptParam() + && !args.hasExperimentalFollowTypeHintsParam()); + } + + /** + * Test for #108. This tests whether we can parse two tf.function positional arguments. + */ + @Test + public void testPositionalParameters3() throws Exception { + Set functions = this.getFunctions(); + assertNotNull(functions); + assertEquals(1, functions.size()); + Function function = functions.iterator().next(); + assertNotNull(function); + + Function.HybridizationParameters args = function.getHybridizationParameters(); + assertNotNull(args); + + assertTrue(args.hasFuncParam() && args.hasInputSignatureParam() && !args.hasAutoGraphParam() && !args.hasJitCompileParam() + && !args.hasReduceRetracingParam() && !args.hasExperimentalImplementsParam() && !args.hasExperimentalAutographOptParam() + && !args.hasExperimentalFollowTypeHintsParam()); + } + + /** + * Test for #108. This tests whether we can parse three tf.function positional arguments. + */ + @Test + public void testPositionalParameters4() throws Exception { + Set functions = this.getFunctions(); + assertNotNull(functions); + assertEquals(1, functions.size()); + Function function = functions.iterator().next(); + assertNotNull(function); + + Function.HybridizationParameters args = function.getHybridizationParameters(); + assertNotNull(args); + + assertTrue(args.hasFuncParam() && args.hasInputSignatureParam() && args.hasAutoGraphParam() && !args.hasJitCompileParam() + && !args.hasReduceRetracingParam() && !args.hasExperimentalImplementsParam() && !args.hasExperimentalAutographOptParam() + && !args.hasExperimentalFollowTypeHintsParam()); + } + + /** + * Test for #108. This tests whether we can parse four tf.function positional arguments. + */ + @Test + public void testPositionalParameters5() throws Exception { + Set functions = this.getFunctions(); + assertNotNull(functions); + assertEquals(1, functions.size()); + Function function = functions.iterator().next(); + assertNotNull(function); + + Function.HybridizationParameters args = function.getHybridizationParameters(); + assertNotNull(args); + + assertTrue(args.hasFuncParam() && args.hasInputSignatureParam() && args.hasAutoGraphParam() && args.hasJitCompileParam() + && !args.hasReduceRetracingParam() && !args.hasExperimentalImplementsParam() && !args.hasExperimentalAutographOptParam() + && !args.hasExperimentalFollowTypeHintsParam()); + } + + /** + * Test for #108. This tests whether we can parse five tf.function positional arguments. + */ + @Test + public void testPositionalParameters6() throws Exception { + Set functions = this.getFunctions(); + assertNotNull(functions); + assertEquals(1, functions.size()); + Function function = functions.iterator().next(); + assertNotNull(function); + + Function.HybridizationParameters args = function.getHybridizationParameters(); + assertNotNull(args); + + assertTrue(args.hasFuncParam() && args.hasInputSignatureParam() && args.hasAutoGraphParam() && args.hasJitCompileParam() + && args.hasReduceRetracingParam() && !args.hasExperimentalImplementsParam() && !args.hasExperimentalAutographOptParam() + && !args.hasExperimentalFollowTypeHintsParam()); + } + + /** + * Test for #108. This tests whether we can parse six tf.function positional arguments. + */ + @Test + public void testPositionalParameters7() throws Exception { + Set functions = this.getFunctions(); + assertNotNull(functions); + assertEquals(1, functions.size()); + Function function = functions.iterator().next(); + assertNotNull(function); + + Function.HybridizationParameters args = function.getHybridizationParameters(); + assertNotNull(args); + + assertTrue(args.hasFuncParam() && args.hasInputSignatureParam() && args.hasAutoGraphParam() && args.hasJitCompileParam() + && args.hasReduceRetracingParam() && args.hasExperimentalImplementsParam() && !args.hasExperimentalAutographOptParam() + && !args.hasExperimentalFollowTypeHintsParam()); + } + + /** + * Test for #108. This tests whether we can parse seven tf.function positional arguments. + */ + @Test + public void testPositionalParameters8() throws Exception { + Set functions = this.getFunctions(); + assertNotNull(functions); + assertEquals(1, functions.size()); + Function function = functions.iterator().next(); + assertNotNull(function); + + Function.HybridizationParameters args = function.getHybridizationParameters(); + assertNotNull(args); + + assertTrue(args.hasFuncParam() && args.hasInputSignatureParam() && args.hasAutoGraphParam() && args.hasJitCompileParam() + && args.hasReduceRetracingParam() && args.hasExperimentalImplementsParam() && args.hasExperimentalAutographOptParam() + && !args.hasExperimentalFollowTypeHintsParam()); + } + + /** + * Test for #108. This tests whether we can parse eight tf.function positional arguments. + */ + @Test + public void testPositionalParameters9() throws Exception { + Set functions = this.getFunctions(); + assertNotNull(functions); + assertEquals(1, functions.size()); + Function function = functions.iterator().next(); + assertNotNull(function); + + Function.HybridizationParameters args = function.getHybridizationParameters(); + assertNotNull(args); + + assertTrue(args.hasFuncParam() && args.hasInputSignatureParam() && args.hasAutoGraphParam() && args.hasJitCompileParam() + && args.hasReduceRetracingParam() && args.hasExperimentalImplementsParam() && args.hasExperimentalAutographOptParam() + && !args.hasExperimentalFollowTypeHintsParam()); + } + + /** + * Test for #108. This tests whether we can parse nine tf.function positional arguments. + */ + @Test + public void testPositionalParameters10() throws Exception { + Set functions = this.getFunctions(); + assertNotNull(functions); + assertEquals(1, functions.size()); + Function function = functions.iterator().next(); + assertNotNull(function); + + Function.HybridizationParameters args = function.getHybridizationParameters(); + assertNotNull(args); + + assertTrue(args.hasFuncParam() && args.hasInputSignatureParam() && args.hasAutoGraphParam() && args.hasJitCompileParam() + && args.hasReduceRetracingParam() && args.hasExperimentalImplementsParam() && args.hasExperimentalAutographOptParam() + && !args.hasExperimentalFollowTypeHintsParam()); + } + + /** + * Test for #108. This tests whether we can parse ten tf.function positional arguments. + */ + @Test + public void testPositionalParameters11() throws Exception { + Set functions = this.getFunctions(); + assertNotNull(functions); + assertEquals(1, functions.size()); + Function function = functions.iterator().next(); + assertNotNull(function); + + Function.HybridizationParameters args = function.getHybridizationParameters(); + assertNotNull(args); + + assertTrue(args.hasFuncParam() && args.hasInputSignatureParam() && args.hasAutoGraphParam() && args.hasJitCompileParam() + && args.hasReduceRetracingParam() && args.hasExperimentalImplementsParam() && args.hasExperimentalAutographOptParam() + && args.hasExperimentalFollowTypeHintsParam()); + } + + /** + * Test for #108. This tests that if tf.function has positional arguments set as default, we do count them as existing. + */ + @Test + public void testPositionalParameters12() throws Exception { + Set functions = this.getFunctions(); + assertNotNull(functions); + assertEquals(1, functions.size()); + Function function = functions.iterator().next(); + assertNotNull(function); + + Function.HybridizationParameters args = function.getHybridizationParameters(); + assertNotNull(args); + + assertTrue(args.hasFuncParam() && args.hasInputSignatureParam() && args.hasAutoGraphParam() && args.hasJitCompileParam() + && args.hasReduceRetracingParam() && args.hasExperimentalImplementsParam() && args.hasExperimentalAutographOptParam() + && args.hasExperimentalFollowTypeHintsParam()); + } + + /** + * Test for #108. This tests an earlier tf.function version that has different positional arguments as v2.9 (using v2.8). + */ + @Test + public void testPositionalParameters13() throws Exception { + Set functions = this.getFunctions(); + assertNotNull(functions); + assertEquals(1, functions.size()); + Function function = functions.iterator().next(); + assertNotNull(function); + + Function.HybridizationParameters args = function.getHybridizationParameters(); + assertNotNull(args); + + assertTrue(args.hasFuncParam() && args.hasInputSignatureParam() && args.hasAutoGraphParam() && args.hasJitCompileParam() + && !args.hasReduceRetracingParam() && args.hasExperimentalImplementsParam() && !args.hasExperimentalAutographOptParam() + && !args.hasExperimentalFollowTypeHintsParam()); + } + + /** + * Test for #125. This test mixing positional and keyword arguments. + */ + @Test + public void testPositionalParameters14() throws Exception { + Set functions = this.getFunctions(); + assertNotNull(functions); + assertEquals(1, functions.size()); + Function function = functions.iterator().next(); + assertNotNull(function); + + Function.HybridizationParameters args = function.getHybridizationParameters(); + assertNotNull(args); + + assertTrue(args.hasFuncParam() && args.hasInputSignatureParam() && args.hasAutoGraphParam() && !args.hasJitCompileParam() + && !args.hasReduceRetracingParam() && !args.hasExperimentalImplementsParam() && !args.hasExperimentalAutographOptParam() + && !args.hasExperimentalFollowTypeHintsParam()); + } + /** * This simply tests whether we have the correct qualified name. */