mirror of
https://github.com/enso-org/enso.git
synced 2024-11-22 11:52:59 +03:00
Provide missing arguments when stepping into a function (#10879)
close #10792 Changelog: - update: replace missing arguments with `Nothing` when schedule a function execution in interactive mode
This commit is contained in:
parent
3d23e22c6f
commit
09722b36dc
@ -202,7 +202,7 @@ public final class ExecutionService {
|
||||
|
||||
Object p = context.getThreadManager().enter();
|
||||
try {
|
||||
execute.getCallTarget().call(call);
|
||||
execute.getCallTarget().call(substituteMissingArguments(call));
|
||||
} finally {
|
||||
context.getThreadManager().leave(p);
|
||||
eventNodeFactory.ifPresent(EventBinding::dispose);
|
||||
@ -261,6 +261,28 @@ public final class ExecutionService {
|
||||
onExecutedVisualizationCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace missing arguments of the provided function call with {@link
|
||||
* org.enso.interpreter.node.expression.builtin.Nothing} to make sure that the function call can
|
||||
* be invoked.
|
||||
*
|
||||
* @param functionCall the function call to update
|
||||
* @return a function call with the updated arguments
|
||||
*/
|
||||
private FunctionCallInstrumentationNode.FunctionCall substituteMissingArguments(
|
||||
FunctionCallInstrumentationNode.FunctionCall functionCall) {
|
||||
var arguments = functionCall.getArguments().clone();
|
||||
var argumentInfos = functionCall.getFunction().getSchema().getArgumentInfos();
|
||||
for (var i = 0; i < arguments.length; i++) {
|
||||
if (arguments[i] == null && !argumentInfos[i].hasDefaultValue()) {
|
||||
arguments[i] = context.getBuiltins().nothing();
|
||||
}
|
||||
}
|
||||
|
||||
return new FunctionCallInstrumentationNode.FunctionCall(
|
||||
functionCall.getFunction(), functionCall.getState(), arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates an expression in the scope of the provided module.
|
||||
*
|
||||
|
@ -489,6 +489,96 @@ class RuntimeServerTest
|
||||
)
|
||||
}
|
||||
|
||||
it should "substitute Nothing when pushing method with unapplied arguments" in {
|
||||
val contextId = UUID.randomUUID()
|
||||
val requestId = UUID.randomUUID()
|
||||
val moduleName = "Enso_Test.Test.Main"
|
||||
|
||||
val metadata = new Metadata
|
||||
val identityResultId = metadata.addItem(13, 1, "aa")
|
||||
val identityCallId = metadata.addItem(27, 8, "ab")
|
||||
|
||||
val code =
|
||||
"""identity x = x
|
||||
|
|
||||
|main =
|
||||
| identity
|
||||
|""".stripMargin.linesIterator.mkString("\n")
|
||||
val contents = metadata.appendToCode(code)
|
||||
val mainFile = context.writeMain(contents)
|
||||
|
||||
// create context
|
||||
context.send(Api.Request(requestId, Api.CreateContextRequest(contextId)))
|
||||
context.receive shouldEqual Some(
|
||||
Api.Response(requestId, Api.CreateContextResponse(contextId))
|
||||
)
|
||||
|
||||
// open file
|
||||
context.send(
|
||||
Api.Request(requestId, Api.OpenFileRequest(mainFile, contents))
|
||||
)
|
||||
context.receive shouldEqual Some(
|
||||
Api.Response(Some(requestId), Api.OpenFileResponse)
|
||||
)
|
||||
|
||||
// push main
|
||||
context.send(
|
||||
Api.Request(
|
||||
requestId,
|
||||
Api.PushContextRequest(
|
||||
contextId,
|
||||
Api.StackItem.ExplicitCall(
|
||||
Api.MethodPointer(moduleName, moduleName, "main"),
|
||||
None,
|
||||
Vector()
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
context.receiveN(3) should contain theSameElementsAs Seq(
|
||||
Api.Response(requestId, Api.PushContextResponse(contextId)),
|
||||
TestMessages.update(
|
||||
contextId,
|
||||
identityCallId,
|
||||
ConstantsGen.FUNCTION_BUILTIN,
|
||||
methodCall = Some(
|
||||
Api.MethodCall(
|
||||
Api.MethodPointer(moduleName, moduleName, "identity"),
|
||||
Vector(0)
|
||||
)
|
||||
),
|
||||
payload = Api.ExpressionUpdate.Payload.Value(
|
||||
functionSchema = Some(
|
||||
Api.FunctionSchema(
|
||||
Api.MethodPointer(moduleName, moduleName, "identity"),
|
||||
Vector(0)
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
context.executionComplete(contextId)
|
||||
)
|
||||
context.consumeOut shouldEqual List()
|
||||
|
||||
// push identity
|
||||
context.send(
|
||||
Api.Request(
|
||||
requestId,
|
||||
Api.PushContextRequest(
|
||||
contextId,
|
||||
Api.StackItem.LocalCall(identityCallId)
|
||||
)
|
||||
)
|
||||
)
|
||||
context.receiveN(3) should contain theSameElementsAs Seq(
|
||||
Api.Response(requestId, Api.PushContextResponse(contextId)),
|
||||
TestMessages
|
||||
.update(contextId, identityResultId, ConstantsGen.NOTHING_BUILTIN),
|
||||
context.executionComplete(contextId)
|
||||
)
|
||||
context.consumeOut shouldEqual List()
|
||||
}
|
||||
|
||||
it should "push method with default arguments on top of the stack" in {
|
||||
val contextId = UUID.randomUUID()
|
||||
val requestId = UUID.randomUUID()
|
||||
@ -7244,4 +7334,5 @@ class RuntimeServerTest
|
||||
)
|
||||
context.consumeOut shouldEqual List("Hello World!")
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -120,7 +120,12 @@ public class FunctionCallInstrumentationNode extends Node implements Instrumenta
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the arguments passed to the function in this call.
|
||||
* Get the arguments passed to the function in this call.
|
||||
*
|
||||
* <p>The {@code null} value in the arguments array indicates that the corresponding argument
|
||||
* was not provided, and the default value should be used.
|
||||
*
|
||||
* @return the function arguments provided to this call
|
||||
*/
|
||||
public Object[] getArguments() {
|
||||
return arguments;
|
||||
|
Loading…
Reference in New Issue
Block a user