Skip to content

Commit 8166d83

Browse files
committed
ScriptModule: improve handling of return values
Whether the return value output is explicitly declared makes a big difference. The behavior we want is: implicit output explicit output /--------------------------------------------------\ | result = 2 | // @output int result | variable | 1 | result = 2 | assigned | | 1 | | | | | BEHAVIOR: result is 1 | BEHAVIOR: result is 2 | |-----------------------+--------------------------- | 1 | // @output int result | variable | | 1 | unassigned | | | | BEHAVIOR: result is 1 | BEHAVIOR: result is null | \--------------------------------------------------/ The thinking is that when the script writer declares an output called "result", their intuition will be that the final assignment to the variable called "result" should become the output value. But when they _don't_ explicitly declare that output, the implicitly added output called "result" refers to the return value of the script itself, not the value of the variable called "result" in the bindings.
1 parent a9dfd50 commit 8166d83

File tree

2 files changed

+18
-9
lines changed

2 files changed

+18
-9
lines changed

src/main/java/org/scijava/script/ScriptInfo.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,9 @@ public class ScriptInfo extends AbstractModuleInfo implements Contextual {
8787
@Parameter
8888
private ConvertService convertService;
8989

90+
/** True iff the return value is explicitly declared as an output. */
91+
private boolean returnValueDeclared;
92+
9093
/**
9194
* Creates a script metadata object which describes the given script file.
9295
*
@@ -207,6 +210,7 @@ public BufferedReader getReader() {
207210
@Override
208211
public void parseParameters() {
209212
clearParameters();
213+
returnValueDeclared = false;
210214

211215
try {
212216
final BufferedReader in;
@@ -233,7 +237,7 @@ public void parseParameters() {
233237
if (reader == null) in.close();
234238
else in.reset();
235239

236-
addReturnValue();
240+
if (!returnValueDeclared) addReturnValue();
237241
}
238242
catch (final IOException exc) {
239243
log.error("Error reading script: " + path, exc);
@@ -243,6 +247,11 @@ public void parseParameters() {
243247
}
244248
}
245249

250+
/** Gets whether the return value is explicitly declared as an output. */
251+
public boolean isReturnValueDeclared() {
252+
return returnValueDeclared;
253+
}
254+
246255
// -- ModuleInfo methods --
247256

248257
@Override
@@ -347,6 +356,7 @@ private void parseParam(final String param,
347356
}
348357
final Class<?> type = scriptService.lookupClass(typeName);
349358
addItem(varName, type, attrs);
359+
if (ScriptModule.RETURN_VALUE.equals(varName)) returnValueDeclared = true;
350360
}
351361

352362
/** Parses a comma-delimited list of {@code key=value} pairs into a map. */

src/main/java/org/scijava/script/ScriptModule.java

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -189,17 +189,16 @@ public void run() {
189189
for (final ModuleItem<?> item : getInfo().outputs()) {
190190
final String name = item.getName();
191191
if (isResolved(name)) continue;
192-
final Object value = engine.get(name);
192+
final Object value;
193+
if (RETURN_VALUE.equals(name) && !getInfo().isReturnValueDeclared()) {
194+
// NB: This is the special implicit return value output!
195+
value = returnValue;
196+
}
197+
else value = engine.get(name);
193198
final Object decoded = language.decode(value);
194199
final Object typed = conversionService.convert(decoded, item.getType());
195200
setOutput(name, typed);
196-
}
197-
198-
// populate the return value as a special output
199-
// NB: This only occurs if there was no declared output called "result".
200-
if (!isResolved(RETURN_VALUE)) {
201-
setOutput(RETURN_VALUE, language.decode(returnValue));
202-
setResolved(RETURN_VALUE, true);
201+
setResolved(name, true);
203202
}
204203

205204
// flush output and error streams

0 commit comments

Comments
 (0)