mirror of
https://github.com/enso-org/enso.git
synced 2024-11-22 11:52:59 +03:00
Run node in a different execution environment (#11173)
close #10719 Changelog: - add: optional `expressionConfigs` parameter to the `executionContext/recompute` request - update: `IdExecutionInstrument` allowing to run a single node in a specified execution environment - refactor: move tests related to the recompute request to a separate test suite. Otherwise the `RuntimeServerTest` is becoming too bloated # Important Notes The updated `executionContext/recompute` request. ```typescript interface ExecutionContextRecomputeParameters { /** The execution context identifier. */ contextId: ContextId; /** The expressions that will be invalidated before the execution. * * Only the provided expression ids are invalidated excluding the dependencies. */ invalidatedExpressions?: "all" | ExpressionId[]; /** The execution environment that will be used in the execution. */ executionEnvironment?: ExecutionEnvironment; /** The execution configurations for particular expressions. * * The provided expressions will be invalidated from the cache with the * dependencies. The result of the execution will stay in the cache until the * cache is invalidated by editing the node or other means. */ expressionConfigs?: ExpressionConfig[]; } interface ExpressionConfig { /** The expression identifier. */ expressionId: ExpressionId; /** The execution environment that should be used to run this expression. */ executionEnvironment?: ExecutionEnvironment; } ``` #### Use cases - to re-run a single node without re-running the dependent nodes (subtree), put the node id in the `invalidatedExpressions` parameter. - to re-run a node with dependent nodes (subtree), put the node id in the `expressionConfigs` parameter with empty `executionEnvironment` - to re-run a node in a different execution environment, put the node id in the `expressionConfigs` and specify the `executionEnvieronment`
This commit is contained in:
parent
9d9c03eeaa
commit
78993a0d1a
@ -25,6 +25,8 @@ transport formats, please look [here](./protocol-architecture).
|
|||||||
- [`MethodCall`](#methodcall)
|
- [`MethodCall`](#methodcall)
|
||||||
- [`MethodPointer`](#methodpointer)
|
- [`MethodPointer`](#methodpointer)
|
||||||
- [`ProfilingInfo`](#profilinginfo)
|
- [`ProfilingInfo`](#profilinginfo)
|
||||||
|
- [`ExecutionEnvironment`](#executionenvironment)
|
||||||
|
- [`ExpressionConfig`](#expressionConfig)
|
||||||
- [`ExpressionUpdate`](#expressionupdate)
|
- [`ExpressionUpdate`](#expressionupdate)
|
||||||
- [`ExpressionUpdatePayload`](#expressionupdatepayload)
|
- [`ExpressionUpdatePayload`](#expressionupdatepayload)
|
||||||
- [`VisualizationConfiguration`](#visualizationconfiguration)
|
- [`VisualizationConfiguration`](#visualizationconfiguration)
|
||||||
@ -343,6 +345,19 @@ The execution environment of Enso runtime.
|
|||||||
type ExecutionEnvironment = Design | Live;
|
type ExecutionEnvironment = Design | Live;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### `ExpressionConfig`
|
||||||
|
|
||||||
|
The expression configuration used in the recompute request.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface ExpressionConfig {
|
||||||
|
/** The expression identifier. */
|
||||||
|
expressionId: ExpressionId;
|
||||||
|
/** The execution environment that should be used to run this expression. */
|
||||||
|
executionEnvironment?: ExecutionEnvironment;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### `ExpressionUpdate`
|
### `ExpressionUpdate`
|
||||||
|
|
||||||
An update about the computed expression.
|
An update about the computed expression.
|
||||||
@ -3633,10 +3648,23 @@ May include a list of expressions for which caches should be invalidated.
|
|||||||
interface ExecutionContextRecomputeParameters {
|
interface ExecutionContextRecomputeParameters {
|
||||||
/** The execution context identifier. */
|
/** The execution context identifier. */
|
||||||
contextId: ContextId;
|
contextId: ContextId;
|
||||||
/** The expressions that will be invalidated before the execution. */
|
|
||||||
|
/** The expressions that will be invalidated before the execution.
|
||||||
|
*
|
||||||
|
* Only the provided expression ids are invalidated excluding the dependencies.
|
||||||
|
*/
|
||||||
invalidatedExpressions?: "all" | ExpressionId[];
|
invalidatedExpressions?: "all" | ExpressionId[];
|
||||||
|
|
||||||
/** The execution environment that will be used in the execution. */
|
/** The execution environment that will be used in the execution. */
|
||||||
executionEnvironment?: ExecutionEnvironment;
|
executionEnvironment?: ExecutionEnvironment;
|
||||||
|
|
||||||
|
/** The execution configurations for particular expressions.
|
||||||
|
*
|
||||||
|
* The provided expressions will be invalidated from the cache with the
|
||||||
|
* dependencies. The result of the execution will stay in the cache until the
|
||||||
|
* cache is invalidated by editing the node or other means.
|
||||||
|
*/
|
||||||
|
expressionConfigs?: ExpressionConfig[];
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -48,7 +48,8 @@ class RecomputeHandler(
|
|||||||
session,
|
session,
|
||||||
msg.params.contextId,
|
msg.params.contextId,
|
||||||
msg.params.invalidatedExpressions,
|
msg.params.invalidatedExpressions,
|
||||||
msg.params.executionEnvironment
|
msg.params.executionEnvironment,
|
||||||
|
msg.params.expressionConfigs.getOrElse(Seq())
|
||||||
)
|
)
|
||||||
|
|
||||||
override protected def positiveResponse(
|
override protected def positiveResponse(
|
||||||
|
@ -193,7 +193,8 @@ final class ContextRegistry(
|
|||||||
client,
|
client,
|
||||||
contextId,
|
contextId,
|
||||||
expressions,
|
expressions,
|
||||||
environment
|
environment,
|
||||||
|
expressionConfigs
|
||||||
) =>
|
) =>
|
||||||
if (store.hasContext(client.clientId, contextId)) {
|
if (store.hasContext(client.clientId, contextId)) {
|
||||||
val handler =
|
val handler =
|
||||||
@ -210,7 +211,8 @@ final class ContextRegistry(
|
|||||||
Api.RecomputeContextRequest(
|
Api.RecomputeContextRequest(
|
||||||
contextId,
|
contextId,
|
||||||
invalidatedExpressions,
|
invalidatedExpressions,
|
||||||
environment.map(ExecutionEnvironments.toApi)
|
environment.map(ExecutionEnvironments.toApi),
|
||||||
|
expressionConfigs.map(_.toApi)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
@ -98,12 +98,14 @@ object ContextRegistryProtocol {
|
|||||||
* @param contextId execution context identifier
|
* @param contextId execution context identifier
|
||||||
* @param invalidatedExpressions the expressions that should be invalidated
|
* @param invalidatedExpressions the expressions that should be invalidated
|
||||||
* @param executionEnvironment the environment that should be used for execution
|
* @param executionEnvironment the environment that should be used for execution
|
||||||
|
* @param expressionConfigs the execution configurations for particular expressions
|
||||||
*/
|
*/
|
||||||
case class RecomputeContextRequest(
|
case class RecomputeContextRequest(
|
||||||
rpcSession: JsonSession,
|
rpcSession: JsonSession,
|
||||||
contextId: ContextId,
|
contextId: ContextId,
|
||||||
invalidatedExpressions: Option[InvalidatedExpressions],
|
invalidatedExpressions: Option[InvalidatedExpressions],
|
||||||
executionEnvironment: Option[ExecutionEnvironments.ExecutionEnvironment]
|
executionEnvironment: Option[ExecutionEnvironments.ExecutionEnvironment],
|
||||||
|
expressionConfigs: Seq[ExpressionConfig]
|
||||||
)
|
)
|
||||||
|
|
||||||
/** A response about recomputing the context.
|
/** A response about recomputing the context.
|
||||||
|
@ -108,7 +108,8 @@ object ExecutionApi {
|
|||||||
case class Params(
|
case class Params(
|
||||||
contextId: ContextId,
|
contextId: ContextId,
|
||||||
invalidatedExpressions: Option[InvalidatedExpressions],
|
invalidatedExpressions: Option[InvalidatedExpressions],
|
||||||
executionEnvironment: Option[ExecutionEnvironments.ExecutionEnvironment]
|
executionEnvironment: Option[ExecutionEnvironments.ExecutionEnvironment],
|
||||||
|
expressionConfigs: Option[Seq[ExpressionConfig]]
|
||||||
)
|
)
|
||||||
|
|
||||||
implicit
|
implicit
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
package org.enso.languageserver.runtime
|
||||||
|
|
||||||
|
import org.enso.polyglot.runtime.Runtime.Api
|
||||||
|
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
/** The expression configuration used in the recompute request.
|
||||||
|
*
|
||||||
|
* @param expressionId the expression identifier
|
||||||
|
* @param executionEnvironment the execution environment used to run this expression
|
||||||
|
*/
|
||||||
|
case class ExpressionConfig(
|
||||||
|
expressionId: UUID,
|
||||||
|
executionEnvironment: Option[ExecutionEnvironments.ExecutionEnvironment]
|
||||||
|
) {
|
||||||
|
|
||||||
|
/** Convert this expression config to the runtime API. */
|
||||||
|
def toApi: Api.ExpressionConfig =
|
||||||
|
Api.ExpressionConfig(
|
||||||
|
expressionId,
|
||||||
|
executionEnvironment.map(ExecutionEnvironments.toApi)
|
||||||
|
)
|
||||||
|
}
|
@ -3,8 +3,7 @@ package org.enso.languageserver.runtime
|
|||||||
import io.circe.syntax._
|
import io.circe.syntax._
|
||||||
import io.circe.{Decoder, DecodingFailure, Encoder}
|
import io.circe.{Decoder, DecodingFailure, Encoder}
|
||||||
|
|
||||||
/** A request to invalidate expressions.
|
/** A request to invalidate expressions. */
|
||||||
*/
|
|
||||||
sealed trait InvalidatedExpressions
|
sealed trait InvalidatedExpressions
|
||||||
|
|
||||||
object InvalidatedExpressions {
|
object InvalidatedExpressions {
|
||||||
|
@ -449,7 +449,8 @@ class ContextRegistryTest extends BaseServerTest with ReportLogsOnFailure {
|
|||||||
Api.RecomputeContextRequest(
|
Api.RecomputeContextRequest(
|
||||||
`contextId`,
|
`contextId`,
|
||||||
Some(Api.InvalidatedExpressions.All()),
|
Some(Api.InvalidatedExpressions.All()),
|
||||||
None
|
None,
|
||||||
|
Seq()
|
||||||
)
|
)
|
||||||
) =>
|
) =>
|
||||||
requestId
|
requestId
|
||||||
@ -527,7 +528,92 @@ class ContextRegistryTest extends BaseServerTest with ReportLogsOnFailure {
|
|||||||
Vector(`expressionId`)
|
Vector(`expressionId`)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
None
|
None,
|
||||||
|
Seq()
|
||||||
|
)
|
||||||
|
) =>
|
||||||
|
requestId
|
||||||
|
case msg =>
|
||||||
|
fail(s"Unexpected message: $msg")
|
||||||
|
}
|
||||||
|
runtimeConnectorProbe.lastSender ! Api.Response(
|
||||||
|
requestId3,
|
||||||
|
Api.RecomputeContextResponse(contextId)
|
||||||
|
)
|
||||||
|
client.expectJson(json.ok(3))
|
||||||
|
}
|
||||||
|
|
||||||
|
"recompute with expression configs" in {
|
||||||
|
val client = getInitialisedWsClient()
|
||||||
|
|
||||||
|
// create context
|
||||||
|
client.send(json.executionContextCreateRequest(1))
|
||||||
|
val (requestId, contextId) =
|
||||||
|
runtimeConnectorProbe.receiveN(1).head match {
|
||||||
|
case Api.Request(requestId, Api.CreateContextRequest(contextId)) =>
|
||||||
|
(requestId, contextId)
|
||||||
|
case msg =>
|
||||||
|
fail(s"Unexpected message: $msg")
|
||||||
|
}
|
||||||
|
runtimeConnectorProbe.lastSender ! Api.Response(
|
||||||
|
requestId,
|
||||||
|
Api.CreateContextResponse(contextId)
|
||||||
|
)
|
||||||
|
client.expectJson(json.executionContextCreateResponse(1, contextId))
|
||||||
|
|
||||||
|
// push stack item
|
||||||
|
val expressionId = UUID.randomUUID()
|
||||||
|
client.send(json.executionContextPushRequest(2, contextId, expressionId))
|
||||||
|
val requestId2 =
|
||||||
|
runtimeConnectorProbe.receiveN(1).head match {
|
||||||
|
case Api.Request(
|
||||||
|
requestId,
|
||||||
|
Api.PushContextRequest(
|
||||||
|
`contextId`,
|
||||||
|
Api.StackItem.LocalCall(`expressionId`)
|
||||||
|
)
|
||||||
|
) =>
|
||||||
|
requestId
|
||||||
|
case msg =>
|
||||||
|
fail(s"Unexpected message: $msg")
|
||||||
|
}
|
||||||
|
runtimeConnectorProbe.lastSender ! Api.Response(
|
||||||
|
requestId2,
|
||||||
|
Api.PushContextResponse(contextId)
|
||||||
|
)
|
||||||
|
client.expectJson(json.ok(2))
|
||||||
|
|
||||||
|
// recompute
|
||||||
|
client.send(
|
||||||
|
json"""
|
||||||
|
{ "jsonrpc": "2.0",
|
||||||
|
"method": "executionContext/recompute",
|
||||||
|
"id": 3,
|
||||||
|
"params": {
|
||||||
|
"contextId": $contextId,
|
||||||
|
"expressionConfigs": [
|
||||||
|
{ "expressionId": $expressionId,
|
||||||
|
"executionEnvironment": "Live"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
val requestId3 =
|
||||||
|
runtimeConnectorProbe.receiveN(1).head match {
|
||||||
|
case Api.Request(
|
||||||
|
requestId,
|
||||||
|
Api.RecomputeContextRequest(
|
||||||
|
`contextId`,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
Seq(
|
||||||
|
Api.ExpressionConfig(
|
||||||
|
`expressionId`,
|
||||||
|
Some(Api.ExecutionEnvironment.Live())
|
||||||
|
)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
) =>
|
) =>
|
||||||
requestId
|
requestId
|
||||||
|
@ -69,6 +69,8 @@ public interface IdExecutionService {
|
|||||||
* the execution and return the value as a result.
|
* the execution and return the value as a result.
|
||||||
*/
|
*/
|
||||||
Object onFunctionReturn(Info info);
|
Object onFunctionReturn(Info info);
|
||||||
|
|
||||||
|
Object getExecutionEnvironment(Info info);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -691,6 +691,16 @@ object Runtime {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** The configuration of how to execute the expression.
|
||||||
|
*
|
||||||
|
* @param expressionId the expression identifier
|
||||||
|
* @param executionEnvironment the execution environment for the expression
|
||||||
|
*/
|
||||||
|
sealed case class ExpressionConfig(
|
||||||
|
expressionId: ExpressionId,
|
||||||
|
executionEnvironment: Option[ExecutionEnvironment]
|
||||||
|
)
|
||||||
|
|
||||||
/** The notification about the execution status.
|
/** The notification about the execution status.
|
||||||
*
|
*
|
||||||
* @param contextId the context's id
|
* @param contextId the context's id
|
||||||
@ -914,12 +924,14 @@ object Runtime {
|
|||||||
* @param expressions the selector specifying which expressions should be
|
* @param expressions the selector specifying which expressions should be
|
||||||
* recomputed.
|
* recomputed.
|
||||||
* @param executionEnvironment the environment used for execution
|
* @param executionEnvironment the environment used for execution
|
||||||
|
* @param expressionConfigs execution configurations for selected expressions
|
||||||
*/
|
*/
|
||||||
@named("recomputeContextRequest")
|
@named("recomputeContextRequest")
|
||||||
final case class RecomputeContextRequest(
|
final case class RecomputeContextRequest(
|
||||||
contextId: ContextId,
|
contextId: ContextId,
|
||||||
expressions: Option[InvalidatedExpressions],
|
expressions: Option[InvalidatedExpressions],
|
||||||
executionEnvironment: Option[ExecutionEnvironment]
|
executionEnvironment: Option[ExecutionEnvironment],
|
||||||
|
expressionConfigs: Seq[ExpressionConfig]
|
||||||
) extends ApiRequest
|
) extends ApiRequest
|
||||||
|
|
||||||
/** A response sent from the server upon handling the
|
/** A response sent from the server upon handling the
|
||||||
|
@ -0,0 +1,55 @@
|
|||||||
|
package org.enso.interpreter.instrument;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
import org.enso.interpreter.runtime.state.ExecutionEnvironment;
|
||||||
|
import org.enso.polyglot.runtime.Runtime$Api$ExecutionEnvironment;
|
||||||
|
import org.enso.polyglot.runtime.Runtime$Api$ExpressionConfig;
|
||||||
|
import scala.Option;
|
||||||
|
import scala.collection.immutable.Seq;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The program execution config.
|
||||||
|
*
|
||||||
|
* @param executionEnvironment the global execution environment of the program
|
||||||
|
* @param expressionConfigs execution configs for each expression
|
||||||
|
*/
|
||||||
|
public record ExecutionConfig(
|
||||||
|
ExecutionEnvironment executionEnvironment, Map<UUID, ExecutionEnvironment> expressionConfigs) {
|
||||||
|
|
||||||
|
public static ExecutionConfig empty() {
|
||||||
|
return new ExecutionConfig(null, Collections.emptyMap());
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static ExecutionConfig create(
|
||||||
|
Object executionEnvironmentOption1, Object expressionConfigs1) {
|
||||||
|
Map<UUID, ExecutionEnvironment> expressionConfigsBuilder = new HashMap<>();
|
||||||
|
Option<Runtime$Api$ExecutionEnvironment> executionEnvironmentOption =
|
||||||
|
(Option<Runtime$Api$ExecutionEnvironment>) executionEnvironmentOption1;
|
||||||
|
Seq<Runtime$Api$ExpressionConfig> expressionConfigs =
|
||||||
|
(Seq<Runtime$Api$ExpressionConfig>) expressionConfigs1;
|
||||||
|
expressionConfigs.foreach(
|
||||||
|
expressionConfig -> {
|
||||||
|
expressionConfig
|
||||||
|
.executionEnvironment()
|
||||||
|
.foreach(
|
||||||
|
executionEnvironment -> {
|
||||||
|
expressionConfigsBuilder.put(
|
||||||
|
expressionConfig.expressionId(),
|
||||||
|
ExecutionEnvironment.forName(executionEnvironment.name()));
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
|
ExecutionEnvironment executionEnvironment =
|
||||||
|
executionEnvironmentOption
|
||||||
|
.map(env -> ExecutionEnvironment.forName(env.name()))
|
||||||
|
.getOrElse(() -> null);
|
||||||
|
|
||||||
|
return new ExecutionConfig(executionEnvironment, expressionConfigsBuilder);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package org.enso.interpreter.instrument;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
import org.enso.interpreter.runtime.state.ExecutionEnvironment;
|
||||||
|
|
||||||
|
public final class ExpressionExecutionState {
|
||||||
|
|
||||||
|
private final Map<UUID, ExecutionEnvironment> expressionConfigs;
|
||||||
|
|
||||||
|
public ExpressionExecutionState() {
|
||||||
|
this.expressionConfigs = new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExpressionExecutionState(Map<UUID, ExecutionEnvironment> expressionConfigs) {
|
||||||
|
this.expressionConfigs = expressionConfigs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExpressionConfigs(Map<UUID, ExecutionEnvironment> expressionConfigs) {
|
||||||
|
this.expressionConfigs.putAll(expressionConfigs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExpressionExecuted(UUID expressionId) {
|
||||||
|
expressionConfigs.remove(expressionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExecutionEnvironment getExecutionEnvironment(UUID expressionId) {
|
||||||
|
return expressionConfigs.get(expressionId);
|
||||||
|
}
|
||||||
|
}
|
@ -48,7 +48,7 @@ public class SetExecutionEnvironmentCommand extends AsynchronousCommand {
|
|||||||
this.getClass(),
|
this.getClass(),
|
||||||
() -> {
|
() -> {
|
||||||
var oldEnvironmentName =
|
var oldEnvironmentName =
|
||||||
ctx.executionService().getContext().getExecutionEnvironment().getName();
|
ctx.executionService().getContext().getGlobalExecutionEnvironment().getName();
|
||||||
if (!oldEnvironmentName.equals(executionEnvironment.name())) {
|
if (!oldEnvironmentName.equals(executionEnvironment.name())) {
|
||||||
ctx.jobControlPlane()
|
ctx.jobControlPlane()
|
||||||
.abortJobs(
|
.abortJobs(
|
||||||
@ -58,10 +58,21 @@ public class SetExecutionEnvironmentCommand extends AsynchronousCommand {
|
|||||||
this.getClass(),
|
this.getClass(),
|
||||||
() -> {
|
() -> {
|
||||||
Stack<InstrumentFrame> stack = ctx.contextManager().getStack(contextId);
|
Stack<InstrumentFrame> stack = ctx.contextManager().getStack(contextId);
|
||||||
ctx.executionService()
|
ctx.state()
|
||||||
.getContext()
|
.executionHooks()
|
||||||
.setExecutionEnvironment(
|
.add(
|
||||||
ExecutionEnvironment.forName(executionEnvironment.name()));
|
() ->
|
||||||
|
ctx.locking()
|
||||||
|
.withWriteCompilationLock(
|
||||||
|
this.getClass(),
|
||||||
|
() -> {
|
||||||
|
ctx.executionService()
|
||||||
|
.getContext()
|
||||||
|
.setExecutionEnvironment(
|
||||||
|
ExecutionEnvironment.forName(
|
||||||
|
executionEnvironment.name()));
|
||||||
|
return null;
|
||||||
|
}));
|
||||||
CacheInvalidation.invalidateAll(stack);
|
CacheInvalidation.invalidateAll(stack);
|
||||||
ctx.jobProcessor().run(ExecuteJob.apply(contextId, stack.toList()));
|
ctx.jobProcessor().run(ExecuteJob.apply(contextId, stack.toList()));
|
||||||
reply(new Runtime$Api$SetExecutionEnvironmentResponse(contextId), ctx);
|
reply(new Runtime$Api$SetExecutionEnvironmentResponse(contextId), ctx);
|
||||||
|
@ -5,6 +5,7 @@ import java.util.HashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
import org.enso.interpreter.instrument.ExpressionExecutionState;
|
||||||
import org.enso.interpreter.instrument.MethodCallsCache;
|
import org.enso.interpreter.instrument.MethodCallsCache;
|
||||||
import org.enso.interpreter.instrument.OneshotExpression;
|
import org.enso.interpreter.instrument.OneshotExpression;
|
||||||
import org.enso.interpreter.instrument.RuntimeCache;
|
import org.enso.interpreter.instrument.RuntimeCache;
|
||||||
@ -31,6 +32,7 @@ final class ExecutionCallbacks implements IdExecutionService.Callbacks {
|
|||||||
private final MethodCallsCache methodCallsCache;
|
private final MethodCallsCache methodCallsCache;
|
||||||
private final UpdatesSynchronizationState syncState;
|
private final UpdatesSynchronizationState syncState;
|
||||||
private final Map<UUID, FunctionCallInfo> calls = new HashMap<>();
|
private final Map<UUID, FunctionCallInfo> calls = new HashMap<>();
|
||||||
|
private final ExpressionExecutionState expressionExecutionState;
|
||||||
private final Consumer<ExpressionValue> onCachedCallback;
|
private final Consumer<ExpressionValue> onCachedCallback;
|
||||||
private final Consumer<ExpressionValue> onComputedCallback;
|
private final Consumer<ExpressionValue> onComputedCallback;
|
||||||
private final Consumer<ExpressionCall> functionCallCallback;
|
private final Consumer<ExpressionCall> functionCallCallback;
|
||||||
@ -39,13 +41,16 @@ final class ExecutionCallbacks implements IdExecutionService.Callbacks {
|
|||||||
/**
|
/**
|
||||||
* Creates callbacks instance.
|
* Creates callbacks instance.
|
||||||
*
|
*
|
||||||
|
* @param visualizationHolder the holder of all visualizations attached to an execution context.
|
||||||
|
* @param nextExecutionItem the next item scheduled for execution.
|
||||||
* @param cache the precomputed expression values.
|
* @param cache the precomputed expression values.
|
||||||
* @param methodCallsCache the storage tracking the executed updateCachedResult calls.
|
* @param methodCallsCache the storage tracking the executed updateCachedResult calls.
|
||||||
* @param syncState the synchronization state of runtime updates.
|
* @param syncState the synchronization state of runtime updates.
|
||||||
* @param nextExecutionItem the next item scheduled for execution.
|
* @param expressionExecutionState the execution state for each expression.
|
||||||
* @param functionCallCallback the consumer of function call events.
|
|
||||||
* @param onComputedCallback the consumer of the computed value events.
|
* @param onComputedCallback the consumer of the computed value events.
|
||||||
* @param onCachedCallback the consumer of the cached value events.
|
* @param onCachedCallback the consumer of the cached value events.
|
||||||
|
* @param functionCallCallback the consumer of function call events.
|
||||||
|
* @param onExecutedVisualizationCallback the consumer of an executed visualization result.
|
||||||
*/
|
*/
|
||||||
ExecutionCallbacks(
|
ExecutionCallbacks(
|
||||||
VisualizationHolder visualizationHolder,
|
VisualizationHolder visualizationHolder,
|
||||||
@ -53,6 +58,7 @@ final class ExecutionCallbacks implements IdExecutionService.Callbacks {
|
|||||||
RuntimeCache cache,
|
RuntimeCache cache,
|
||||||
MethodCallsCache methodCallsCache,
|
MethodCallsCache methodCallsCache,
|
||||||
UpdatesSynchronizationState syncState,
|
UpdatesSynchronizationState syncState,
|
||||||
|
ExpressionExecutionState expressionExecutionState,
|
||||||
Consumer<ExpressionValue> onCachedCallback,
|
Consumer<ExpressionValue> onCachedCallback,
|
||||||
Consumer<ExpressionValue> onComputedCallback,
|
Consumer<ExpressionValue> onComputedCallback,
|
||||||
Consumer<ExpressionCall> functionCallCallback,
|
Consumer<ExpressionCall> functionCallCallback,
|
||||||
@ -62,6 +68,7 @@ final class ExecutionCallbacks implements IdExecutionService.Callbacks {
|
|||||||
this.cache = cache;
|
this.cache = cache;
|
||||||
this.methodCallsCache = methodCallsCache;
|
this.methodCallsCache = methodCallsCache;
|
||||||
this.syncState = syncState;
|
this.syncState = syncState;
|
||||||
|
this.expressionExecutionState = expressionExecutionState;
|
||||||
this.onCachedCallback = onCachedCallback;
|
this.onCachedCallback = onCachedCallback;
|
||||||
this.onComputedCallback = onComputedCallback;
|
this.onComputedCallback = onComputedCallback;
|
||||||
this.functionCallCallback = functionCallCallback;
|
this.functionCallCallback = functionCallCallback;
|
||||||
@ -141,6 +148,12 @@ final class ExecutionCallbacks implements IdExecutionService.Callbacks {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@CompilerDirectives.TruffleBoundary
|
||||||
|
public Object getExecutionEnvironment(IdExecutionService.Info info) {
|
||||||
|
return expressionExecutionState.getExecutionEnvironment(info.getId());
|
||||||
|
}
|
||||||
|
|
||||||
@CompilerDirectives.TruffleBoundary
|
@CompilerDirectives.TruffleBoundary
|
||||||
private void callOnComputedCallback(ExpressionValue expressionValue) {
|
private void callOnComputedCallback(ExpressionValue expressionValue) {
|
||||||
onComputedCallback.accept(expressionValue);
|
onComputedCallback.accept(expressionValue);
|
||||||
|
@ -29,6 +29,7 @@ import org.enso.common.LanguageInfo;
|
|||||||
import org.enso.common.MethodNames;
|
import org.enso.common.MethodNames;
|
||||||
import org.enso.compiler.suggestions.SimpleUpdate;
|
import org.enso.compiler.suggestions.SimpleUpdate;
|
||||||
import org.enso.interpreter.instrument.Endpoint;
|
import org.enso.interpreter.instrument.Endpoint;
|
||||||
|
import org.enso.interpreter.instrument.ExpressionExecutionState;
|
||||||
import org.enso.interpreter.instrument.MethodCallsCache;
|
import org.enso.interpreter.instrument.MethodCallsCache;
|
||||||
import org.enso.interpreter.instrument.RuntimeCache;
|
import org.enso.interpreter.instrument.RuntimeCache;
|
||||||
import org.enso.interpreter.instrument.UpdatesSynchronizationState;
|
import org.enso.interpreter.instrument.UpdatesSynchronizationState;
|
||||||
@ -157,9 +158,11 @@ public final class ExecutionService {
|
|||||||
* @param methodCallsCache the storage tracking the executed method calls.
|
* @param methodCallsCache the storage tracking the executed method calls.
|
||||||
* @param syncState the synchronization state of runtime updates.
|
* @param syncState the synchronization state of runtime updates.
|
||||||
* @param nextExecutionItem the next item scheduled for execution.
|
* @param nextExecutionItem the next item scheduled for execution.
|
||||||
|
* @param expressionExecutionState the execution state for each expression.
|
||||||
* @param funCallCallback the consumer for function call events.
|
* @param funCallCallback the consumer for function call events.
|
||||||
* @param onComputedCallback the consumer of the computed value events.
|
* @param onComputedCallback the consumer of the computed value events.
|
||||||
* @param onCachedCallback the consumer of the cached value events.
|
* @param onCachedCallback the consumer of the cached value events.
|
||||||
|
* @param onExecutedVisualizationCallback the consumer of an executed visualization result.
|
||||||
*/
|
*/
|
||||||
public void execute(
|
public void execute(
|
||||||
VisualizationHolder visualizationHolder,
|
VisualizationHolder visualizationHolder,
|
||||||
@ -169,6 +172,7 @@ public final class ExecutionService {
|
|||||||
MethodCallsCache methodCallsCache,
|
MethodCallsCache methodCallsCache,
|
||||||
UpdatesSynchronizationState syncState,
|
UpdatesSynchronizationState syncState,
|
||||||
UUID nextExecutionItem,
|
UUID nextExecutionItem,
|
||||||
|
ExpressionExecutionState expressionExecutionState,
|
||||||
Consumer<ExecutionService.ExpressionCall> funCallCallback,
|
Consumer<ExecutionService.ExpressionCall> funCallCallback,
|
||||||
Consumer<ExecutionService.ExpressionValue> onComputedCallback,
|
Consumer<ExecutionService.ExpressionValue> onComputedCallback,
|
||||||
Consumer<ExecutionService.ExpressionValue> onCachedCallback,
|
Consumer<ExecutionService.ExpressionValue> onCachedCallback,
|
||||||
@ -188,6 +192,7 @@ public final class ExecutionService {
|
|||||||
cache,
|
cache,
|
||||||
methodCallsCache,
|
methodCallsCache,
|
||||||
syncState,
|
syncState,
|
||||||
|
expressionExecutionState,
|
||||||
onCachedCallback,
|
onCachedCallback,
|
||||||
onComputedCallback,
|
onComputedCallback,
|
||||||
funCallCallback,
|
funCallCallback,
|
||||||
@ -220,9 +225,11 @@ public final class ExecutionService {
|
|||||||
* @param methodCallsCache the storage tracking the executed method calls.
|
* @param methodCallsCache the storage tracking the executed method calls.
|
||||||
* @param syncState the synchronization state of runtime updates.
|
* @param syncState the synchronization state of runtime updates.
|
||||||
* @param nextExecutionItem the next item scheduled for execution.
|
* @param nextExecutionItem the next item scheduled for execution.
|
||||||
|
* @param expressionExecutionState the execution state for each expression.
|
||||||
* @param funCallCallback the consumer for function call events.
|
* @param funCallCallback the consumer for function call events.
|
||||||
* @param onComputedCallback the consumer of the computed value events.
|
* @param onComputedCallback the consumer of the computed value events.
|
||||||
* @param onCachedCallback the consumer of the cached value events.
|
* @param onCachedCallback the consumer of the cached value events.
|
||||||
|
* @param onExecutedVisualizationCallback the consumer of an executed visualization result.
|
||||||
*/
|
*/
|
||||||
public void execute(
|
public void execute(
|
||||||
String moduleName,
|
String moduleName,
|
||||||
@ -233,6 +240,7 @@ public final class ExecutionService {
|
|||||||
MethodCallsCache methodCallsCache,
|
MethodCallsCache methodCallsCache,
|
||||||
UpdatesSynchronizationState syncState,
|
UpdatesSynchronizationState syncState,
|
||||||
UUID nextExecutionItem,
|
UUID nextExecutionItem,
|
||||||
|
ExpressionExecutionState expressionExecutionState,
|
||||||
Consumer<ExecutionService.ExpressionCall> funCallCallback,
|
Consumer<ExecutionService.ExpressionCall> funCallCallback,
|
||||||
Consumer<ExecutionService.ExpressionValue> onComputedCallback,
|
Consumer<ExecutionService.ExpressionValue> onComputedCallback,
|
||||||
Consumer<ExecutionService.ExpressionValue> onCachedCallback,
|
Consumer<ExecutionService.ExpressionValue> onCachedCallback,
|
||||||
@ -255,6 +263,7 @@ public final class ExecutionService {
|
|||||||
methodCallsCache,
|
methodCallsCache,
|
||||||
syncState,
|
syncState,
|
||||||
nextExecutionItem,
|
nextExecutionItem,
|
||||||
|
expressionExecutionState,
|
||||||
funCallCallback,
|
funCallCallback,
|
||||||
onComputedCallback,
|
onComputedCallback,
|
||||||
onCachedCallback,
|
onCachedCallback,
|
||||||
@ -360,6 +369,7 @@ public final class ExecutionService {
|
|||||||
Consumer<ExpressionValue> onCachedCallback =
|
Consumer<ExpressionValue> onCachedCallback =
|
||||||
(value) -> context.getLogger().finest("_ON_CACHED_VALUE " + value.getExpressionId());
|
(value) -> context.getLogger().finest("_ON_CACHED_VALUE " + value.getExpressionId());
|
||||||
Consumer<ExecutedVisualization> onExecutedVisualizationCallback = (value) -> {};
|
Consumer<ExecutedVisualization> onExecutedVisualizationCallback = (value) -> {};
|
||||||
|
ExpressionExecutionState expressionExecutionState = new ExpressionExecutionState();
|
||||||
|
|
||||||
var callbacks =
|
var callbacks =
|
||||||
new ExecutionCallbacks(
|
new ExecutionCallbacks(
|
||||||
@ -368,6 +378,7 @@ public final class ExecutionService {
|
|||||||
cache,
|
cache,
|
||||||
methodCallsCache,
|
methodCallsCache,
|
||||||
syncState,
|
syncState,
|
||||||
|
expressionExecutionState,
|
||||||
onCachedCallback,
|
onCachedCallback,
|
||||||
onComputedCallback,
|
onComputedCallback,
|
||||||
funCallCallback,
|
funCallCallback,
|
||||||
|
@ -1,13 +1,20 @@
|
|||||||
package org.enso.interpreter.instrument.command
|
package org.enso.interpreter.instrument.command
|
||||||
|
|
||||||
import org.enso.interpreter.instrument.{CacheInvalidation, InstrumentFrame}
|
import org.enso.compiler.core.Implicits.AsMetadata
|
||||||
|
import org.enso.compiler.pass.analyse.DataflowAnalysis
|
||||||
|
import org.enso.compiler.refactoring.IRUtils
|
||||||
|
import org.enso.interpreter.instrument.command.RecomputeContextCmd.InvalidateExpressions
|
||||||
|
import org.enso.interpreter.instrument.{
|
||||||
|
CacheInvalidation,
|
||||||
|
ExecutionConfig,
|
||||||
|
InstrumentFrame
|
||||||
|
}
|
||||||
import org.enso.interpreter.instrument.execution.RuntimeContext
|
import org.enso.interpreter.instrument.execution.RuntimeContext
|
||||||
import org.enso.interpreter.instrument.job.{EnsureCompiledJob, ExecuteJob}
|
import org.enso.interpreter.instrument.job.{EnsureCompiledJob, ExecuteJob}
|
||||||
import org.enso.polyglot.runtime.Runtime.Api
|
import org.enso.polyglot.runtime.Runtime.Api
|
||||||
import org.enso.polyglot.runtime.Runtime.Api.RequestId
|
import org.enso.polyglot.runtime.Runtime.Api.RequestId
|
||||||
|
|
||||||
import scala.concurrent.{ExecutionContext, Future}
|
import scala.concurrent.{ExecutionContext, Future}
|
||||||
import scala.jdk.CollectionConverters._
|
|
||||||
|
|
||||||
/** A command that forces a recomputation of the current position.
|
/** A command that forces a recomputation of the current position.
|
||||||
*
|
*
|
||||||
@ -41,56 +48,19 @@ class RecomputeContextCmd(
|
|||||||
reply(Api.EmptyStackError(request.contextId))
|
reply(Api.EmptyStackError(request.contextId))
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
val cacheInvalidationCommands = request.expressions.toSeq
|
ctx.state.executionHooks.add(
|
||||||
.map(CacheInvalidation.Command(_))
|
InvalidateExpressions(
|
||||||
.map(CacheInvalidation(CacheInvalidation.StackSelector.Top, _))
|
request.contextId,
|
||||||
CacheInvalidation.runAll(
|
request.expressions,
|
||||||
stack,
|
request.expressionConfigs
|
||||||
cacheInvalidationCommands
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
sendPendingUpdates(stack)
|
|
||||||
reply(Api.RecomputeContextResponse(request.contextId))
|
reply(Api.RecomputeContextResponse(request.contextId))
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private def sendPendingUpdates(
|
|
||||||
stack: Iterable[InstrumentFrame]
|
|
||||||
)(implicit ctx: RuntimeContext): Unit = {
|
|
||||||
val invalidatedExpressions =
|
|
||||||
request.expressions
|
|
||||||
.map {
|
|
||||||
case expressions: Api.InvalidatedExpressions.Expressions =>
|
|
||||||
expressions.value.toSet
|
|
||||||
case _: Api.InvalidatedExpressions.All =>
|
|
||||||
stack.headOption
|
|
||||||
.map { frame =>
|
|
||||||
frame.cache.getWeights.keySet().asScala.toSet
|
|
||||||
}
|
|
||||||
.getOrElse(Set())
|
|
||||||
}
|
|
||||||
.getOrElse(Set())
|
|
||||||
if (invalidatedExpressions.nonEmpty) {
|
|
||||||
val updates = invalidatedExpressions.collect {
|
|
||||||
case expressionId if expressionId ne null =>
|
|
||||||
Api.ExpressionUpdate(
|
|
||||||
expressionId,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
Vector.empty,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
Api.ExpressionUpdate.Payload.Pending(None, None)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
ctx.endpoint.sendToClient(
|
|
||||||
Api.Response(Api.ExpressionUpdates(request.contextId, updates))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private def doesContextExist(implicit ctx: RuntimeContext): Boolean = {
|
private def doesContextExist(implicit ctx: RuntimeContext): Boolean = {
|
||||||
ctx.contextManager.contains(request.contextId)
|
ctx.contextManager.contains(request.contextId)
|
||||||
}
|
}
|
||||||
@ -109,6 +79,13 @@ class RecomputeContextCmd(
|
|||||||
): Future[Unit] = {
|
): Future[Unit] = {
|
||||||
if (isStackNonEmpty) {
|
if (isStackNonEmpty) {
|
||||||
val stack = ctx.contextManager.getStack(request.contextId)
|
val stack = ctx.contextManager.getStack(request.contextId)
|
||||||
|
val executionConfig =
|
||||||
|
ExecutionConfig.create(
|
||||||
|
request.executionEnvironment,
|
||||||
|
request.expressionConfigs
|
||||||
|
)
|
||||||
|
ctx.state.expressionExecutionState
|
||||||
|
.setExpressionConfigs(executionConfig.expressionConfigs)
|
||||||
for {
|
for {
|
||||||
_ <- ctx.jobProcessor.run(EnsureCompiledJob(stack))
|
_ <- ctx.jobProcessor.run(EnsureCompiledJob(stack))
|
||||||
_ <- ctx.jobProcessor.run(
|
_ <- ctx.jobProcessor.run(
|
||||||
@ -125,3 +102,114 @@ class RecomputeContextCmd(
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object RecomputeContextCmd {
|
||||||
|
|
||||||
|
/** Invalidate caches for the request. */
|
||||||
|
sealed private case class InvalidateExpressions(
|
||||||
|
contextId: Api.ContextId,
|
||||||
|
expressions: Option[Api.InvalidatedExpressions],
|
||||||
|
expressionConfigs: Seq[Api.ExpressionConfig]
|
||||||
|
)(implicit ctx: RuntimeContext)
|
||||||
|
extends Runnable {
|
||||||
|
|
||||||
|
override def run(): Unit = {
|
||||||
|
val stack = ctx.contextManager.getStack(contextId)
|
||||||
|
|
||||||
|
val invalidationCommands =
|
||||||
|
ctx.locking.withWriteCompilationLock(
|
||||||
|
classOf[RecomputeContextCmd],
|
||||||
|
() => {
|
||||||
|
val expressionsInvalidationCommands = expressions.toSeq
|
||||||
|
.map(CacheInvalidation.Command(_))
|
||||||
|
.map(CacheInvalidation(CacheInvalidation.StackSelector.All, _))
|
||||||
|
val expressionConfigsDependentInvalidationCommands =
|
||||||
|
expressionConfigs
|
||||||
|
.map(_.expressionId)
|
||||||
|
.flatMap(RecomputeContextCmd.invalidateDependent)
|
||||||
|
val allInvalidationCommands =
|
||||||
|
expressionsInvalidationCommands ++ expressionConfigsDependentInvalidationCommands
|
||||||
|
|
||||||
|
CacheInvalidation.runAll(stack, allInvalidationCommands)
|
||||||
|
|
||||||
|
allInvalidationCommands
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
sendPendingUpdates(stack, contextId, invalidationCommands)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Invalidate dependent nodes of the provided expression.
|
||||||
|
*
|
||||||
|
* @param expressionId the expression id
|
||||||
|
* @return commands to invalidate dependent nodes of the provided expression
|
||||||
|
*/
|
||||||
|
private def invalidateDependent(
|
||||||
|
expressionId: Api.ExpressionId
|
||||||
|
)(implicit ctx: RuntimeContext): Seq[CacheInvalidation] = {
|
||||||
|
val builder = Vector.newBuilder[CacheInvalidation]
|
||||||
|
ctx.executionService.getContext
|
||||||
|
.findModuleByExpressionId(expressionId)
|
||||||
|
.ifPresent { module =>
|
||||||
|
module.getIr
|
||||||
|
.getMetadata(DataflowAnalysis)
|
||||||
|
.foreach { metadata =>
|
||||||
|
val dependents =
|
||||||
|
IRUtils
|
||||||
|
.findByExternalId(module.getIr, expressionId)
|
||||||
|
.map { ir =>
|
||||||
|
DataflowAnalysis.DependencyInfo.Type
|
||||||
|
.Static(ir.getId, ir.getExternalId)
|
||||||
|
}
|
||||||
|
.flatMap { expressionKey =>
|
||||||
|
metadata.dependents.getExternal(expressionKey)
|
||||||
|
}
|
||||||
|
.fold(Set(expressionId))(_ + expressionId)
|
||||||
|
builder += CacheInvalidation(
|
||||||
|
CacheInvalidation.StackSelector.All,
|
||||||
|
CacheInvalidation.Command.InvalidateKeys(dependents)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.result()
|
||||||
|
}
|
||||||
|
|
||||||
|
private def sendPendingUpdates(
|
||||||
|
stack: Iterable[InstrumentFrame],
|
||||||
|
contextId: Api.ContextId,
|
||||||
|
cacheInvalidations: Seq[CacheInvalidation]
|
||||||
|
)(implicit ctx: RuntimeContext): Unit = {
|
||||||
|
val builder = Set.newBuilder[Api.ExpressionId]
|
||||||
|
cacheInvalidations.map(_.command).foreach {
|
||||||
|
case CacheInvalidation.Command.InvalidateAll =>
|
||||||
|
stack.headOption
|
||||||
|
.map { frame =>
|
||||||
|
frame.cache.getWeights.keySet().forEach(builder.addOne)
|
||||||
|
}
|
||||||
|
case CacheInvalidation.Command.InvalidateKeys(expressionIds) =>
|
||||||
|
builder ++= expressionIds
|
||||||
|
case _ =>
|
||||||
|
}
|
||||||
|
|
||||||
|
val invalidatedExpressions = builder.result()
|
||||||
|
if (invalidatedExpressions.nonEmpty) {
|
||||||
|
val updates = invalidatedExpressions.collect {
|
||||||
|
case expressionId if expressionId ne null =>
|
||||||
|
Api.ExpressionUpdate(
|
||||||
|
expressionId,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
Vector.empty,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
Api.ExpressionUpdate.Payload.Pending(None, None)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
ctx.endpoint.sendToClient(
|
||||||
|
Api.Response(Api.ExpressionUpdates(contextId, updates))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package org.enso.interpreter.instrument.execution
|
package org.enso.interpreter.instrument.execution
|
||||||
|
|
||||||
|
import org.enso.interpreter.instrument.ExpressionExecutionState
|
||||||
|
|
||||||
/** The state of the runtime */
|
/** The state of the runtime */
|
||||||
final class ExecutionState {
|
final class ExecutionState {
|
||||||
|
|
||||||
@ -8,5 +10,7 @@ final class ExecutionState {
|
|||||||
|
|
||||||
val executionHooks: ExecutionHooks = new RuntimeExecutionHooks
|
val executionHooks: ExecutionHooks = new RuntimeExecutionHooks
|
||||||
|
|
||||||
|
val expressionExecutionState = new ExpressionExecutionState()
|
||||||
|
|
||||||
val suggestions: ModuleIndexing = ModuleIndexing.createInstance()
|
val suggestions: ModuleIndexing = ModuleIndexing.createInstance()
|
||||||
}
|
}
|
||||||
|
@ -70,7 +70,9 @@ class ExecuteJob(
|
|||||||
() => {
|
() => {
|
||||||
val context = ctx.executionService.getContext
|
val context = ctx.executionService.getContext
|
||||||
val originalExecutionEnvironment =
|
val originalExecutionEnvironment =
|
||||||
executionEnvironment.map(_ => context.getExecutionEnvironment)
|
executionEnvironment.map(_ =>
|
||||||
|
context.getGlobalExecutionEnvironment
|
||||||
|
)
|
||||||
executionEnvironment.foreach(env =>
|
executionEnvironment.foreach(env =>
|
||||||
context.setExecutionEnvironment(
|
context.setExecutionEnvironment(
|
||||||
ExecutionEnvironment.forName(env.name)
|
ExecutionEnvironment.forName(env.name)
|
||||||
|
@ -49,6 +49,7 @@ import java.io.File
|
|||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import java.util.function.Consumer
|
import java.util.function.Consumer
|
||||||
import java.util.logging.Level
|
import java.util.logging.Level
|
||||||
|
|
||||||
import scala.jdk.OptionConverters.RichOptional
|
import scala.jdk.OptionConverters.RichOptional
|
||||||
import scala.util.Try
|
import scala.util.Try
|
||||||
|
|
||||||
@ -57,7 +58,7 @@ import scala.util.Try
|
|||||||
*/
|
*/
|
||||||
object ProgramExecutionSupport {
|
object ProgramExecutionSupport {
|
||||||
|
|
||||||
/** Runs an Enso program.
|
/** Runs the program.
|
||||||
*
|
*
|
||||||
* @param contextId an identifier of an execution context
|
* @param contextId an identifier of an execution context
|
||||||
* @param executionFrame an execution frame
|
* @param executionFrame an execution frame
|
||||||
@ -142,6 +143,7 @@ object ProgramExecutionSupport {
|
|||||||
methodCallsCache,
|
methodCallsCache,
|
||||||
syncState,
|
syncState,
|
||||||
callStack.headOption.map(_.expressionId).orNull,
|
callStack.headOption.map(_.expressionId).orNull,
|
||||||
|
ctx.state.expressionExecutionState,
|
||||||
callablesCallback,
|
callablesCallback,
|
||||||
onComputedValueCallback,
|
onComputedValueCallback,
|
||||||
onCachedValueCallback,
|
onCachedValueCallback,
|
||||||
@ -183,6 +185,7 @@ object ProgramExecutionSupport {
|
|||||||
methodCallsCache,
|
methodCallsCache,
|
||||||
syncState,
|
syncState,
|
||||||
callStack.headOption.map(_.expressionId).orNull,
|
callStack.headOption.map(_.expressionId).orNull,
|
||||||
|
ctx.state.expressionExecutionState,
|
||||||
callablesCallback,
|
callablesCallback,
|
||||||
onComputedValueCallback,
|
onComputedValueCallback,
|
||||||
onCachedValueCallback,
|
onCachedValueCallback,
|
||||||
@ -226,7 +229,7 @@ object ProgramExecutionSupport {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Runs an Enso program.
|
/** Runs the program.
|
||||||
*
|
*
|
||||||
* @param contextId an identifier of an execution context
|
* @param contextId an identifier of an execution context
|
||||||
* @param stack a call stack
|
* @param stack a call stack
|
||||||
@ -271,7 +274,9 @@ object ProgramExecutionSupport {
|
|||||||
Some(Api.ExecutionResult.Failure("Execution stack is empty.", None))
|
Some(Api.ExecutionResult.Failure("Execution stack is empty.", None))
|
||||||
)
|
)
|
||||||
_ <-
|
_ <-
|
||||||
Try(executeProgram(contextId, stackItem, localCalls)).toEither.left
|
Try(
|
||||||
|
executeProgram(contextId, stackItem, localCalls)
|
||||||
|
).toEither.left
|
||||||
.map(onExecutionError(stackItem.item, _))
|
.map(onExecutionError(stackItem.item, _))
|
||||||
} yield ()
|
} yield ()
|
||||||
logger.log(Level.FINEST, s"Execution finished: $executionResult")
|
logger.log(Level.FINEST, s"Execution finished: $executionResult")
|
||||||
@ -514,6 +519,7 @@ object ProgramExecutionSupport {
|
|||||||
}
|
}
|
||||||
|
|
||||||
syncState.setExpressionSync(expressionId)
|
syncState.setExpressionSync(expressionId)
|
||||||
|
ctx.state.expressionExecutionState.setExpressionExecuted(expressionId)
|
||||||
if (methodCall.isDefined) {
|
if (methodCall.isDefined) {
|
||||||
syncState.setMethodPointerSync(expressionId)
|
syncState.setMethodPointerSync(expressionId)
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,7 @@ import org.enso.interpreter.runtime.error.DataflowError;
|
|||||||
import org.enso.interpreter.runtime.error.PanicException;
|
import org.enso.interpreter.runtime.error.PanicException;
|
||||||
import org.enso.interpreter.runtime.error.PanicSentinel;
|
import org.enso.interpreter.runtime.error.PanicSentinel;
|
||||||
import org.enso.interpreter.runtime.instrument.Timer;
|
import org.enso.interpreter.runtime.instrument.Timer;
|
||||||
|
import org.enso.interpreter.runtime.state.ExecutionEnvironment;
|
||||||
import org.enso.interpreter.runtime.state.State;
|
import org.enso.interpreter.runtime.state.State;
|
||||||
import org.enso.interpreter.runtime.tag.AvoidIdInstrumentationTag;
|
import org.enso.interpreter.runtime.tag.AvoidIdInstrumentationTag;
|
||||||
import org.enso.interpreter.runtime.tag.IdentifiedTag;
|
import org.enso.interpreter.runtime.tag.IdentifiedTag;
|
||||||
@ -182,6 +183,7 @@ public class IdExecutionInstrument extends TruffleInstrument implements IdExecut
|
|||||||
|
|
||||||
private final EventContext context;
|
private final EventContext context;
|
||||||
private long nanoTimeElapsed = 0;
|
private long nanoTimeElapsed = 0;
|
||||||
|
private ExecutionEnvironment originalExecutionEnvironment = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new event node.
|
* Creates a new event node.
|
||||||
@ -209,6 +211,8 @@ public class IdExecutionInstrument extends TruffleInstrument implements IdExecut
|
|||||||
if (result != null) {
|
if (result != null) {
|
||||||
throw context.createUnwind(result);
|
throw context.createUnwind(result);
|
||||||
}
|
}
|
||||||
|
setExecutionEnvironment(info);
|
||||||
|
|
||||||
nanoTimeElapsed = timer.getTime();
|
nanoTimeElapsed = timer.getTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,10 +254,13 @@ public class IdExecutionInstrument extends TruffleInstrument implements IdExecut
|
|||||||
frame == null ? null : frame.materialize(),
|
frame == null ? null : frame.materialize(),
|
||||||
node);
|
node);
|
||||||
callbacks.updateCachedResult(info);
|
callbacks.updateCachedResult(info);
|
||||||
|
resetExecutionEnvironment();
|
||||||
|
|
||||||
if (info.isPanic()) {
|
if (info.isPanic()) {
|
||||||
throw context.createUnwind(result);
|
throw context.createUnwind(result);
|
||||||
}
|
}
|
||||||
|
} else if (node instanceof ExpressionNode) {
|
||||||
|
resetExecutionEnvironment();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -312,6 +319,23 @@ public class IdExecutionInstrument extends TruffleInstrument implements IdExecut
|
|||||||
});
|
});
|
||||||
return result == null;
|
return result == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setExecutionEnvironment(IdExecutionService.Info info) {
|
||||||
|
ExecutionEnvironment nodeEnvironment =
|
||||||
|
(ExecutionEnvironment) callbacks.getExecutionEnvironment(info);
|
||||||
|
if (nodeEnvironment != null && originalExecutionEnvironment == null) {
|
||||||
|
EnsoContext context = EnsoContext.get(this);
|
||||||
|
originalExecutionEnvironment = context.getGlobalExecutionEnvironment();
|
||||||
|
context.setExecutionEnvironment(nodeEnvironment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resetExecutionEnvironment() {
|
||||||
|
if (originalExecutionEnvironment != null) {
|
||||||
|
EnsoContext.get(this).setExecutionEnvironment(originalExecutionEnvironment);
|
||||||
|
originalExecutionEnvironment = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ import org.enso.polyglot.runtime.Runtime.Api.{
|
|||||||
MethodPointer
|
MethodPointer
|
||||||
}
|
}
|
||||||
import org.enso.text.{ContentVersion, Sha3_224VersionCalculator}
|
import org.enso.text.{ContentVersion, Sha3_224VersionCalculator}
|
||||||
|
import org.enso.text.editing.model
|
||||||
import org.graalvm.polyglot.Context
|
import org.graalvm.polyglot.Context
|
||||||
import org.scalatest.BeforeAndAfterEach
|
import org.scalatest.BeforeAndAfterEach
|
||||||
import org.scalatest.flatspec.AnyFlatSpec
|
import org.scalatest.flatspec.AnyFlatSpec
|
||||||
@ -262,6 +263,153 @@ class RuntimeAsyncCommandsTest
|
|||||||
diagnostic.stack should not be empty
|
diagnostic.stack should not be empty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
it should "recompute expression in context after interruption" in {
|
||||||
|
val moduleName = "Enso_Test.Test.Main"
|
||||||
|
val contextId = UUID.randomUUID()
|
||||||
|
val requestId = UUID.randomUUID()
|
||||||
|
|
||||||
|
val metadata = new Metadata
|
||||||
|
val idOut = metadata.addItem(179, 17, "aa")
|
||||||
|
|
||||||
|
val code =
|
||||||
|
"""from Standard.Base import all
|
||||||
|
|from Standard.Base.Runtime.Context import Input, Output
|
||||||
|
|polyglot java import java.lang.Thread
|
||||||
|
|
|
||||||
|
|main =
|
||||||
|
| IO.println "started"
|
||||||
|
| loop 50
|
||||||
|
| out = Output.is_enabled
|
||||||
|
| IO.println out
|
||||||
|
|
|
||||||
|
|loop n=0 s=0 =
|
||||||
|
| if (s > n) then s else
|
||||||
|
| Thread.sleep 100
|
||||||
|
| loop n s+1
|
||||||
|
|""".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 the new file
|
||||||
|
context.send(
|
||||||
|
Api.Request(requestId, Api.OpenFileRequest(mainFile, contents))
|
||||||
|
)
|
||||||
|
context.receive shouldEqual Some(
|
||||||
|
Api.Response(Some(requestId), Api.OpenFileResponse)
|
||||||
|
)
|
||||||
|
|
||||||
|
// push main
|
||||||
|
val item1 = Api.StackItem.ExplicitCall(
|
||||||
|
Api.MethodPointer(moduleName, moduleName, "main"),
|
||||||
|
None,
|
||||||
|
Vector()
|
||||||
|
)
|
||||||
|
context.send(
|
||||||
|
Api.Request(requestId, Api.PushContextRequest(contextId, item1))
|
||||||
|
)
|
||||||
|
context.receiveNIgnoreStdLib(
|
||||||
|
3
|
||||||
|
) should contain theSameElementsAs Seq(
|
||||||
|
Api.Response(requestId, Api.PushContextResponse(contextId)),
|
||||||
|
TestMessages.update(
|
||||||
|
contextId,
|
||||||
|
idOut,
|
||||||
|
ConstantsGen.BOOLEAN,
|
||||||
|
methodCall = Some(
|
||||||
|
Api.MethodCall(
|
||||||
|
Api.MethodPointer(
|
||||||
|
"Standard.Base.Runtime",
|
||||||
|
"Standard.Base.Runtime.Context",
|
||||||
|
"is_enabled"
|
||||||
|
),
|
||||||
|
Vector(1)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
context.executionComplete(contextId)
|
||||||
|
)
|
||||||
|
context.consumeOut shouldEqual List("started", "False")
|
||||||
|
|
||||||
|
// recompute
|
||||||
|
context.send(
|
||||||
|
Api.Request(
|
||||||
|
requestId,
|
||||||
|
Api.RecomputeContextRequest(
|
||||||
|
contextId,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
Seq(
|
||||||
|
Api.ExpressionConfig(idOut, Some(Api.ExecutionEnvironment.Live()))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
val responses = context.receiveNIgnorePendingExpressionUpdates(1)
|
||||||
|
responses should contain(
|
||||||
|
Api.Response(requestId, Api.RecomputeContextResponse(contextId))
|
||||||
|
)
|
||||||
|
|
||||||
|
// wait for program to start and interrupt
|
||||||
|
var isProgramStarted = false
|
||||||
|
var iteration = 0
|
||||||
|
while (!isProgramStarted && iteration < 100) {
|
||||||
|
val out = context.consumeOut
|
||||||
|
Thread.sleep(200)
|
||||||
|
isProgramStarted = out == List("started")
|
||||||
|
iteration += 1
|
||||||
|
}
|
||||||
|
if (!isProgramStarted) {
|
||||||
|
fail("Program start timed out")
|
||||||
|
}
|
||||||
|
context.consumeOut shouldEqual List()
|
||||||
|
|
||||||
|
// trigger re-computation
|
||||||
|
context.send(
|
||||||
|
Api.Request(
|
||||||
|
Api.EditFileNotification(
|
||||||
|
mainFile,
|
||||||
|
Seq(
|
||||||
|
model.TextEdit(
|
||||||
|
model.Range(model.Position(10, 7), model.Position(10, 8)),
|
||||||
|
"0"
|
||||||
|
)
|
||||||
|
),
|
||||||
|
execute = true,
|
||||||
|
idMap = None
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
val responses1 = context.receiveNIgnorePendingExpressionUpdates(3)
|
||||||
|
responses1 should contain allOf (
|
||||||
|
TestMessages.update(
|
||||||
|
contextId,
|
||||||
|
idOut,
|
||||||
|
ConstantsGen.BOOLEAN,
|
||||||
|
fromCache = false,
|
||||||
|
typeChanged = false,
|
||||||
|
methodCall = Some(
|
||||||
|
Api.MethodCall(
|
||||||
|
Api.MethodPointer(
|
||||||
|
"Standard.Base.Runtime",
|
||||||
|
"Standard.Base.Runtime.Context",
|
||||||
|
"is_enabled"
|
||||||
|
),
|
||||||
|
Vector(1)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
context.executionComplete(contextId)
|
||||||
|
)
|
||||||
|
context.consumeOut should contain("True")
|
||||||
|
}
|
||||||
|
|
||||||
it should "interrupt running execution context without sending Panic in expression updates" in {
|
it should "interrupt running execution context without sending Panic in expression updates" in {
|
||||||
val moduleName = "Enso_Test.Test.Main"
|
val moduleName = "Enso_Test.Test.Main"
|
||||||
val contextId = UUID.randomUUID()
|
val contextId = UUID.randomUUID()
|
||||||
@ -330,7 +478,10 @@ class RuntimeAsyncCommandsTest
|
|||||||
|
|
||||||
// recompute/interrupt
|
// recompute/interrupt
|
||||||
context.send(
|
context.send(
|
||||||
Api.Request(requestId, Api.RecomputeContextRequest(contextId, None, None))
|
Api.Request(
|
||||||
|
requestId,
|
||||||
|
Api.RecomputeContextRequest(contextId, None, None, Seq())
|
||||||
|
)
|
||||||
)
|
)
|
||||||
val responses = context.receiveNIgnoreStdLib(
|
val responses = context.receiveNIgnoreStdLib(
|
||||||
3
|
3
|
||||||
@ -486,7 +637,8 @@ class RuntimeAsyncCommandsTest
|
|||||||
Api.RecomputeContextRequest(
|
Api.RecomputeContextRequest(
|
||||||
contextId,
|
contextId,
|
||||||
Some(InvalidatedExpressions.Expressions(Vector(idOp1, idOp2))),
|
Some(InvalidatedExpressions.Expressions(Vector(idOp1, idOp2))),
|
||||||
None
|
None,
|
||||||
|
Seq()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -196,7 +196,7 @@ class RuntimeExecutionEnvironmentTest
|
|||||||
context.executionComplete(contextId)
|
context.executionComplete(contextId)
|
||||||
)
|
)
|
||||||
context.consumeOut shouldEqual List()
|
context.consumeOut shouldEqual List()
|
||||||
context.languageContext.getExecutionEnvironment.getName shouldEqual Api.ExecutionEnvironment
|
context.languageContext.getGlobalExecutionEnvironment.getName shouldEqual Api.ExecutionEnvironment
|
||||||
.Design()
|
.Design()
|
||||||
.name
|
.name
|
||||||
|
|
||||||
@ -232,7 +232,7 @@ class RuntimeExecutionEnvironmentTest
|
|||||||
context.executionComplete(contextId)
|
context.executionComplete(contextId)
|
||||||
)
|
)
|
||||||
context.consumeOut shouldEqual List("Hello World!")
|
context.consumeOut shouldEqual List("Hello World!")
|
||||||
context.languageContext.getExecutionEnvironment.getName shouldEqual Api.ExecutionEnvironment
|
context.languageContext.getGlobalExecutionEnvironment.getName shouldEqual Api.ExecutionEnvironment
|
||||||
.Live()
|
.Live()
|
||||||
.name
|
.name
|
||||||
}
|
}
|
||||||
@ -300,7 +300,7 @@ class RuntimeExecutionEnvironmentTest
|
|||||||
context.executionComplete(contextId)
|
context.executionComplete(contextId)
|
||||||
)
|
)
|
||||||
context.consumeOut shouldEqual List()
|
context.consumeOut shouldEqual List()
|
||||||
context.languageContext.getExecutionEnvironment.getName shouldEqual Api.ExecutionEnvironment
|
context.languageContext.getGlobalExecutionEnvironment.getName shouldEqual Api.ExecutionEnvironment
|
||||||
.Design()
|
.Design()
|
||||||
.name
|
.name
|
||||||
|
|
||||||
@ -318,7 +318,7 @@ class RuntimeExecutionEnvironmentTest
|
|||||||
context.receiveNIgnoreStdLib(1) should contain theSameElementsAs Seq(
|
context.receiveNIgnoreStdLib(1) should contain theSameElementsAs Seq(
|
||||||
Api.Response(requestId, Api.SetExecutionEnvironmentResponse(contextId))
|
Api.Response(requestId, Api.SetExecutionEnvironmentResponse(contextId))
|
||||||
)
|
)
|
||||||
context.languageContext.getExecutionEnvironment.getName shouldEqual Api.ExecutionEnvironment
|
context.languageContext.getGlobalExecutionEnvironment.getName shouldEqual Api.ExecutionEnvironment
|
||||||
.Design()
|
.Design()
|
||||||
.name
|
.name
|
||||||
|
|
||||||
@ -353,7 +353,7 @@ class RuntimeExecutionEnvironmentTest
|
|||||||
),
|
),
|
||||||
context.executionComplete(contextId)
|
context.executionComplete(contextId)
|
||||||
)
|
)
|
||||||
context.languageContext.getExecutionEnvironment.getName shouldEqual Api.ExecutionEnvironment
|
context.languageContext.getGlobalExecutionEnvironment.getName shouldEqual Api.ExecutionEnvironment
|
||||||
.Live()
|
.Live()
|
||||||
.name
|
.name
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -33,7 +33,8 @@ class RuntimeServerTest
|
|||||||
var context: TestContext = _
|
var context: TestContext = _
|
||||||
|
|
||||||
class TestContext(packageName: String)
|
class TestContext(packageName: String)
|
||||||
extends InstrumentTestContext(packageName) {
|
extends InstrumentTestContext(packageName)
|
||||||
|
with RuntimeServerTest.TestMain {
|
||||||
|
|
||||||
val out: ByteArrayOutputStream = new ByteArrayOutputStream()
|
val out: ByteArrayOutputStream = new ByteArrayOutputStream()
|
||||||
val logOut: ByteArrayOutputStream = new ByteArrayOutputStream()
|
val logOut: ByteArrayOutputStream = new ByteArrayOutputStream()
|
||||||
@ -113,286 +114,6 @@ class RuntimeServerTest
|
|||||||
|
|
||||||
def executionComplete(contextId: UUID): Api.Response =
|
def executionComplete(contextId: UUID): Api.Response =
|
||||||
Api.Response(Api.ExecutionComplete(contextId))
|
Api.Response(Api.ExecutionComplete(contextId))
|
||||||
|
|
||||||
// === The Tests ==========================================================
|
|
||||||
|
|
||||||
object Main {
|
|
||||||
|
|
||||||
val metadata = new Metadata
|
|
||||||
|
|
||||||
val idMainX = metadata.addItem(63, 1, "aa1")
|
|
||||||
val idMainY = metadata.addItem(73, 7, "aa2")
|
|
||||||
val idMainZ = metadata.addItem(89, 5, "aa3")
|
|
||||||
val idFooY = metadata.addItem(133, 8, "ff2")
|
|
||||||
val idFooZ = metadata.addItem(150, 5, "ff3")
|
|
||||||
|
|
||||||
def code =
|
|
||||||
metadata.appendToCode(
|
|
||||||
"""
|
|
||||||
|from Standard.Base.Data.Numbers import all
|
|
||||||
|
|
|
||||||
|main =
|
|
||||||
| x = 6
|
|
||||||
| y = x.foo 5
|
|
||||||
| z = y + 5
|
|
||||||
| z
|
|
||||||
|
|
|
||||||
|Number.foo self = x ->
|
|
||||||
| y = self + 3
|
|
||||||
| z = y * x
|
|
||||||
| z
|
|
||||||
|""".stripMargin.linesIterator.mkString("\n")
|
|
||||||
)
|
|
||||||
|
|
||||||
object Update {
|
|
||||||
|
|
||||||
def mainX(
|
|
||||||
contextId: UUID,
|
|
||||||
fromCache: Boolean = false,
|
|
||||||
typeChanged: Boolean = true
|
|
||||||
): Api.Response =
|
|
||||||
Api.Response(
|
|
||||||
Api.ExpressionUpdates(
|
|
||||||
contextId,
|
|
||||||
Set(
|
|
||||||
Api.ExpressionUpdate(
|
|
||||||
Main.idMainX,
|
|
||||||
Some(ConstantsGen.INTEGER),
|
|
||||||
None,
|
|
||||||
Vector(Api.ProfilingInfo.ExecutionTime(0)),
|
|
||||||
fromCache,
|
|
||||||
typeChanged,
|
|
||||||
Api.ExpressionUpdate.Payload.Value()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
def pendingZ(): Api.ExpressionUpdate =
|
|
||||||
Api.ExpressionUpdate(
|
|
||||||
Main.idFooZ,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
Vector(),
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
Api.ExpressionUpdate.Payload.Pending(None, None)
|
|
||||||
)
|
|
||||||
|
|
||||||
def pendingY(): Api.ExpressionUpdate =
|
|
||||||
Api.ExpressionUpdate(
|
|
||||||
Main.idFooY,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
Vector(),
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
Api.ExpressionUpdate.Payload.Pending(None, None)
|
|
||||||
)
|
|
||||||
|
|
||||||
def mainY(
|
|
||||||
contextId: UUID,
|
|
||||||
fromCache: Boolean = false,
|
|
||||||
typeChanged: Boolean = true
|
|
||||||
): Api.Response =
|
|
||||||
Api.Response(
|
|
||||||
Api.ExpressionUpdates(
|
|
||||||
contextId,
|
|
||||||
Set(
|
|
||||||
Api.ExpressionUpdate(
|
|
||||||
Main.idMainY,
|
|
||||||
Some(ConstantsGen.INTEGER),
|
|
||||||
Some(
|
|
||||||
Api.MethodCall(
|
|
||||||
Api.MethodPointer(
|
|
||||||
"Enso_Test.Test.Main",
|
|
||||||
ConstantsGen.NUMBER,
|
|
||||||
"foo"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
Vector(Api.ProfilingInfo.ExecutionTime(0)),
|
|
||||||
fromCache,
|
|
||||||
typeChanged,
|
|
||||||
Api.ExpressionUpdate.Payload.Value()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
def mainZ(
|
|
||||||
contextId: UUID,
|
|
||||||
fromCache: Boolean = false,
|
|
||||||
typeChanged: Boolean = true
|
|
||||||
): Api.Response =
|
|
||||||
Api.Response(
|
|
||||||
Api.ExpressionUpdates(
|
|
||||||
contextId,
|
|
||||||
Set(
|
|
||||||
Api.ExpressionUpdate(
|
|
||||||
Main.idMainZ,
|
|
||||||
Some(ConstantsGen.INTEGER),
|
|
||||||
Some(
|
|
||||||
Api.MethodCall(
|
|
||||||
Api.MethodPointer(
|
|
||||||
"Standard.Base.Data.Numbers",
|
|
||||||
ConstantsGen.INTEGER,
|
|
||||||
"+"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
Vector(Api.ProfilingInfo.ExecutionTime(0)),
|
|
||||||
fromCache,
|
|
||||||
typeChanged,
|
|
||||||
Api.ExpressionUpdate.Payload.Value()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
def fooY(
|
|
||||||
contextId: UUID,
|
|
||||||
fromCache: Boolean = false,
|
|
||||||
typeChanged: Boolean = true
|
|
||||||
): Api.Response =
|
|
||||||
Api.Response(
|
|
||||||
Api.ExpressionUpdates(
|
|
||||||
contextId,
|
|
||||||
Set(
|
|
||||||
Api.ExpressionUpdate(
|
|
||||||
Main.idFooY,
|
|
||||||
Some(ConstantsGen.INTEGER),
|
|
||||||
Some(
|
|
||||||
Api.MethodCall(
|
|
||||||
Api.MethodPointer(
|
|
||||||
"Standard.Base.Data.Numbers",
|
|
||||||
ConstantsGen.INTEGER,
|
|
||||||
"+"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
Vector(Api.ProfilingInfo.ExecutionTime(0)),
|
|
||||||
fromCache,
|
|
||||||
typeChanged,
|
|
||||||
Api.ExpressionUpdate.Payload.Value()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
def fooZ(
|
|
||||||
contextId: UUID,
|
|
||||||
fromCache: Boolean = false,
|
|
||||||
typeChanged: Boolean = true
|
|
||||||
): Api.Response =
|
|
||||||
Api.Response(
|
|
||||||
Api.ExpressionUpdates(
|
|
||||||
contextId,
|
|
||||||
Set(
|
|
||||||
Api.ExpressionUpdate(
|
|
||||||
Main.idFooZ,
|
|
||||||
Some(ConstantsGen.INTEGER),
|
|
||||||
Some(
|
|
||||||
Api.MethodCall(
|
|
||||||
Api.MethodPointer(
|
|
||||||
"Standard.Base.Data.Numbers",
|
|
||||||
ConstantsGen.INTEGER,
|
|
||||||
"*"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
Vector(Api.ProfilingInfo.ExecutionTime(0)),
|
|
||||||
fromCache,
|
|
||||||
typeChanged,
|
|
||||||
Api.ExpressionUpdate.Payload.Value()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
object Main2 {
|
|
||||||
|
|
||||||
val metadata = new Metadata
|
|
||||||
val idMainY = metadata.addItem(178, 5)
|
|
||||||
val idMainZ = metadata.addItem(192, 5)
|
|
||||||
|
|
||||||
val code = metadata.appendToCode(
|
|
||||||
"""from Standard.Base import all
|
|
||||||
|
|
|
||||||
|foo = arg ->
|
|
||||||
| IO.println "I'm expensive!"
|
|
||||||
| arg + 5
|
|
||||||
|
|
|
||||||
|bar = arg ->
|
|
||||||
| IO.println "I'm more expensive!"
|
|
||||||
| arg * 5
|
|
||||||
|
|
|
||||||
|main =
|
|
||||||
| x = 10
|
|
||||||
| y = foo x
|
|
||||||
| z = bar y
|
|
||||||
| z
|
|
||||||
|""".stripMargin.linesIterator.mkString("\n")
|
|
||||||
)
|
|
||||||
|
|
||||||
object Update {
|
|
||||||
|
|
||||||
def mainY(contextId: UUID) =
|
|
||||||
Api.Response(
|
|
||||||
Api.ExpressionUpdates(
|
|
||||||
contextId,
|
|
||||||
Set(
|
|
||||||
Api.ExpressionUpdate(
|
|
||||||
idMainY,
|
|
||||||
Some(ConstantsGen.INTEGER),
|
|
||||||
Some(
|
|
||||||
Api.MethodCall(
|
|
||||||
Api.MethodPointer(
|
|
||||||
"Enso_Test.Test.Main",
|
|
||||||
"Enso_Test.Test.Main",
|
|
||||||
"foo"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
Vector(Api.ProfilingInfo.ExecutionTime(0)),
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
Api.ExpressionUpdate.Payload.Value()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
def mainZ(contextId: UUID) =
|
|
||||||
Api.Response(
|
|
||||||
Api.ExpressionUpdates(
|
|
||||||
contextId,
|
|
||||||
Set(
|
|
||||||
Api.ExpressionUpdate(
|
|
||||||
idMainZ,
|
|
||||||
Some(ConstantsGen.INTEGER),
|
|
||||||
Some(
|
|
||||||
Api.MethodCall(
|
|
||||||
Api.MethodPointer(
|
|
||||||
"Enso_Test.Test.Main",
|
|
||||||
"Enso_Test.Test.Main",
|
|
||||||
"bar"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
Vector(Api.ProfilingInfo.ExecutionTime(0)),
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
Api.ExpressionUpdate.Payload.Value()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override protected def beforeEach(): Unit = {
|
override protected def beforeEach(): Unit = {
|
||||||
@ -5011,251 +4732,6 @@ class RuntimeServerTest
|
|||||||
context.consumeOut shouldEqual List()
|
context.consumeOut shouldEqual List()
|
||||||
}
|
}
|
||||||
|
|
||||||
it should "recompute expressions without invalidation" in {
|
|
||||||
val contents = context.Main.code
|
|
||||||
val mainFile = context.writeMain(contents)
|
|
||||||
val moduleName = "Enso_Test.Test.Main"
|
|
||||||
val contextId = UUID.randomUUID()
|
|
||||||
val requestId = UUID.randomUUID()
|
|
||||||
|
|
||||||
// create context
|
|
||||||
context.send(Api.Request(requestId, Api.CreateContextRequest(contextId)))
|
|
||||||
context.receive shouldEqual Some(
|
|
||||||
Api.Response(requestId, Api.CreateContextResponse(contextId))
|
|
||||||
)
|
|
||||||
|
|
||||||
// Set sources for the module
|
|
||||||
context.send(
|
|
||||||
Api.Request(requestId, Api.OpenFileRequest(mainFile, contents))
|
|
||||||
)
|
|
||||||
context.receive shouldEqual Some(
|
|
||||||
Api.Response(Some(requestId), Api.OpenFileResponse)
|
|
||||||
)
|
|
||||||
|
|
||||||
// push main
|
|
||||||
val item1 = Api.StackItem.ExplicitCall(
|
|
||||||
Api.MethodPointer(moduleName, moduleName, "main"),
|
|
||||||
None,
|
|
||||||
Vector()
|
|
||||||
)
|
|
||||||
context.send(
|
|
||||||
Api.Request(requestId, Api.PushContextRequest(contextId, item1))
|
|
||||||
)
|
|
||||||
context.receiveNIgnoreStdLib(5) should contain theSameElementsAs Seq(
|
|
||||||
Api.Response(requestId, Api.PushContextResponse(contextId)),
|
|
||||||
context.Main.Update.mainX(contextId),
|
|
||||||
context.Main.Update.mainY(contextId),
|
|
||||||
context.Main.Update.mainZ(contextId),
|
|
||||||
context.executionComplete(contextId)
|
|
||||||
)
|
|
||||||
|
|
||||||
// recompute
|
|
||||||
context.send(
|
|
||||||
Api.Request(requestId, Api.RecomputeContextRequest(contextId, None, None))
|
|
||||||
)
|
|
||||||
context.receiveN(2) should contain theSameElementsAs Seq(
|
|
||||||
Api.Response(requestId, Api.RecomputeContextResponse(contextId)),
|
|
||||||
context.executionComplete(contextId)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
it should "recompute expressions invalidating all" in {
|
|
||||||
val contents = context.Main.code
|
|
||||||
val mainFile = context.writeMain(contents)
|
|
||||||
val moduleName = "Enso_Test.Test.Main"
|
|
||||||
val contextId = UUID.randomUUID()
|
|
||||||
val requestId = UUID.randomUUID()
|
|
||||||
|
|
||||||
// create context
|
|
||||||
context.send(Api.Request(requestId, Api.CreateContextRequest(contextId)))
|
|
||||||
context.receive shouldEqual Some(
|
|
||||||
Api.Response(requestId, Api.CreateContextResponse(contextId))
|
|
||||||
)
|
|
||||||
|
|
||||||
// Set sources for the module
|
|
||||||
context.send(
|
|
||||||
Api.Request(requestId, Api.OpenFileRequest(mainFile, contents))
|
|
||||||
)
|
|
||||||
context.receive shouldEqual Some(
|
|
||||||
Api.Response(Some(requestId), Api.OpenFileResponse)
|
|
||||||
)
|
|
||||||
|
|
||||||
// push main
|
|
||||||
val item1 = Api.StackItem.ExplicitCall(
|
|
||||||
Api.MethodPointer(moduleName, moduleName, "main"),
|
|
||||||
None,
|
|
||||||
Vector()
|
|
||||||
)
|
|
||||||
context.send(
|
|
||||||
Api.Request(requestId, Api.PushContextRequest(contextId, item1))
|
|
||||||
)
|
|
||||||
context.receiveNIgnoreStdLib(5) should contain theSameElementsAs Seq(
|
|
||||||
Api.Response(requestId, Api.PushContextResponse(contextId)),
|
|
||||||
context.Main.Update.mainX(contextId),
|
|
||||||
context.Main.Update.mainY(contextId),
|
|
||||||
context.Main.Update.mainZ(contextId),
|
|
||||||
context.executionComplete(contextId)
|
|
||||||
)
|
|
||||||
|
|
||||||
// recompute
|
|
||||||
context.send(
|
|
||||||
Api.Request(
|
|
||||||
requestId,
|
|
||||||
Api.RecomputeContextRequest(
|
|
||||||
contextId,
|
|
||||||
Some(Api.InvalidatedExpressions.All()),
|
|
||||||
None
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
context.receiveN(6) should contain theSameElementsAs Seq(
|
|
||||||
Api.Response(requestId, Api.RecomputeContextResponse(contextId)),
|
|
||||||
TestMessages.pending(
|
|
||||||
contextId,
|
|
||||||
context.Main.idMainX,
|
|
||||||
context.Main.idMainY,
|
|
||||||
context.Main.idMainZ,
|
|
||||||
context.Main.idFooY,
|
|
||||||
context.Main.idFooZ
|
|
||||||
),
|
|
||||||
context.Main.Update.mainX(contextId, typeChanged = false),
|
|
||||||
context.Main.Update.mainY(contextId, typeChanged = false),
|
|
||||||
context.Main.Update.mainZ(contextId, typeChanged = false),
|
|
||||||
context.executionComplete(contextId)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
it should "recompute expressions invalidating some" in {
|
|
||||||
val contents = context.Main.code
|
|
||||||
val mainFile = context.writeMain(contents)
|
|
||||||
val moduleName = "Enso_Test.Test.Main"
|
|
||||||
val contextId = UUID.randomUUID()
|
|
||||||
val requestId = UUID.randomUUID()
|
|
||||||
|
|
||||||
// create context
|
|
||||||
context.send(Api.Request(requestId, Api.CreateContextRequest(contextId)))
|
|
||||||
context.receive shouldEqual Some(
|
|
||||||
Api.Response(requestId, Api.CreateContextResponse(contextId))
|
|
||||||
)
|
|
||||||
|
|
||||||
// Set sources for the module
|
|
||||||
context.send(
|
|
||||||
Api.Request(requestId, Api.OpenFileRequest(mainFile, contents))
|
|
||||||
)
|
|
||||||
context.receive shouldEqual Some(
|
|
||||||
Api.Response(Some(requestId), Api.OpenFileResponse)
|
|
||||||
)
|
|
||||||
context.receiveNone shouldEqual None
|
|
||||||
// push main
|
|
||||||
val item1 = Api.StackItem.ExplicitCall(
|
|
||||||
Api.MethodPointer(moduleName, moduleName, "main"),
|
|
||||||
None,
|
|
||||||
Vector()
|
|
||||||
)
|
|
||||||
context.send(
|
|
||||||
Api.Request(requestId, Api.PushContextRequest(contextId, item1))
|
|
||||||
)
|
|
||||||
context.receiveNIgnoreStdLib(5) should contain theSameElementsAs Seq(
|
|
||||||
Api.Response(requestId, Api.PushContextResponse(contextId)),
|
|
||||||
context.Main.Update.mainX(contextId),
|
|
||||||
context.Main.Update.mainY(contextId),
|
|
||||||
context.Main.Update.mainZ(contextId),
|
|
||||||
context.executionComplete(contextId)
|
|
||||||
)
|
|
||||||
|
|
||||||
// recompute
|
|
||||||
context.send(
|
|
||||||
Api.Request(
|
|
||||||
requestId,
|
|
||||||
Api.RecomputeContextRequest(
|
|
||||||
contextId,
|
|
||||||
Some(
|
|
||||||
Api.InvalidatedExpressions.Expressions(Vector(context.Main.idMainZ))
|
|
||||||
),
|
|
||||||
None
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
context.receiveN(4) should contain theSameElementsAs Seq(
|
|
||||||
Api.Response(requestId, Api.RecomputeContextResponse(contextId)),
|
|
||||||
TestMessages.pending(contextId, context.Main.idMainZ),
|
|
||||||
context.Main.Update.mainZ(contextId, typeChanged = false),
|
|
||||||
context.executionComplete(contextId)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
it should "recompute expressions changing an execution environment" in {
|
|
||||||
val contents = context.Main.code
|
|
||||||
val mainFile = context.writeMain(contents)
|
|
||||||
val moduleName = "Enso_Test.Test.Main"
|
|
||||||
val contextId = UUID.randomUUID()
|
|
||||||
val requestId = UUID.randomUUID()
|
|
||||||
|
|
||||||
// create context
|
|
||||||
context.send(Api.Request(requestId, Api.CreateContextRequest(contextId)))
|
|
||||||
context.receive shouldEqual Some(
|
|
||||||
Api.Response(requestId, Api.CreateContextResponse(contextId))
|
|
||||||
)
|
|
||||||
|
|
||||||
// Set sources for the module
|
|
||||||
context.send(
|
|
||||||
Api.Request(requestId, Api.OpenFileRequest(mainFile, contents))
|
|
||||||
)
|
|
||||||
context.receive shouldEqual Some(
|
|
||||||
Api.Response(Some(requestId), Api.OpenFileResponse)
|
|
||||||
)
|
|
||||||
|
|
||||||
// push main
|
|
||||||
val item1 = Api.StackItem.ExplicitCall(
|
|
||||||
Api.MethodPointer(moduleName, moduleName, "main"),
|
|
||||||
None,
|
|
||||||
Vector()
|
|
||||||
)
|
|
||||||
context.send(
|
|
||||||
Api.Request(requestId, Api.PushContextRequest(contextId, item1))
|
|
||||||
)
|
|
||||||
context.receiveNIgnoreStdLib(5) should contain theSameElementsAs Seq(
|
|
||||||
Api.Response(requestId, Api.PushContextResponse(contextId)),
|
|
||||||
context.Main.Update.mainX(contextId),
|
|
||||||
context.Main.Update.mainY(contextId),
|
|
||||||
context.Main.Update.mainZ(contextId),
|
|
||||||
context.executionComplete(contextId)
|
|
||||||
)
|
|
||||||
|
|
||||||
// recompute
|
|
||||||
context.languageContext.getExecutionEnvironment.getName shouldEqual Api.ExecutionEnvironment
|
|
||||||
.Design()
|
|
||||||
.name
|
|
||||||
context.send(
|
|
||||||
Api.Request(
|
|
||||||
requestId,
|
|
||||||
Api.RecomputeContextRequest(
|
|
||||||
contextId,
|
|
||||||
Some(Api.InvalidatedExpressions.All()),
|
|
||||||
Some(Api.ExecutionEnvironment.Live())
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
context.receiveN(6) should contain theSameElementsAs Seq(
|
|
||||||
Api.Response(requestId, Api.RecomputeContextResponse(contextId)),
|
|
||||||
TestMessages.pending(
|
|
||||||
contextId,
|
|
||||||
context.Main.idMainX,
|
|
||||||
context.Main.idMainY,
|
|
||||||
context.Main.idMainZ,
|
|
||||||
context.Main.idFooY,
|
|
||||||
context.Main.idFooZ
|
|
||||||
),
|
|
||||||
context.Main.Update.mainX(contextId, typeChanged = false),
|
|
||||||
context.Main.Update.mainY(contextId, typeChanged = false),
|
|
||||||
context.Main.Update.mainZ(contextId, typeChanged = false),
|
|
||||||
context.executionComplete(contextId)
|
|
||||||
)
|
|
||||||
context.languageContext.getExecutionEnvironment.getName shouldEqual Api.ExecutionEnvironment
|
|
||||||
.Design()
|
|
||||||
.name
|
|
||||||
}
|
|
||||||
|
|
||||||
it should "return error when module not found" in {
|
it should "return error when module not found" in {
|
||||||
val contents = context.Main.code
|
val contents = context.Main.code
|
||||||
val mainFile = context.writeMain(context.Main.code)
|
val mainFile = context.writeMain(context.Main.code)
|
||||||
@ -6667,7 +6143,10 @@ class RuntimeServerTest
|
|||||||
|
|
||||||
// recompute
|
// recompute
|
||||||
context.send(
|
context.send(
|
||||||
Api.Request(requestId, Api.RecomputeContextRequest(contextId, None, None))
|
Api.Request(
|
||||||
|
requestId,
|
||||||
|
Api.RecomputeContextRequest(contextId, None, None, Seq())
|
||||||
|
)
|
||||||
)
|
)
|
||||||
context.receiveN(2) should contain theSameElementsAs Seq(
|
context.receiveN(2) should contain theSameElementsAs Seq(
|
||||||
Api.Response(requestId, Api.RecomputeContextResponse(contextId)),
|
Api.Response(requestId, Api.RecomputeContextResponse(contextId)),
|
||||||
@ -6757,7 +6236,10 @@ class RuntimeServerTest
|
|||||||
|
|
||||||
// recompute existing stack
|
// recompute existing stack
|
||||||
context.send(
|
context.send(
|
||||||
Api.Request(requestId, Api.RecomputeContextRequest(contextId, None, None))
|
Api.Request(
|
||||||
|
requestId,
|
||||||
|
Api.RecomputeContextRequest(contextId, None, None, Seq())
|
||||||
|
)
|
||||||
)
|
)
|
||||||
context.receiveN(2) should contain theSameElementsAs Seq(
|
context.receiveN(2) should contain theSameElementsAs Seq(
|
||||||
Api.Response(requestId, Api.RecomputeContextResponse(contextId)),
|
Api.Response(requestId, Api.RecomputeContextResponse(contextId)),
|
||||||
@ -6771,7 +6253,8 @@ class RuntimeServerTest
|
|||||||
Api.RecomputeContextRequest(
|
Api.RecomputeContextRequest(
|
||||||
contextId,
|
contextId,
|
||||||
Some(Api.InvalidatedExpressions.All()),
|
Some(Api.InvalidatedExpressions.All()),
|
||||||
None
|
None,
|
||||||
|
Seq()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -7468,7 +6951,7 @@ class RuntimeServerTest
|
|||||||
context.executionComplete(contextId)
|
context.executionComplete(contextId)
|
||||||
)
|
)
|
||||||
context.consumeOut shouldEqual List("Hello World!")
|
context.consumeOut shouldEqual List("Hello World!")
|
||||||
context.languageContext.getExecutionEnvironment.getName shouldEqual Api.ExecutionEnvironment
|
context.languageContext.getGlobalExecutionEnvironment.getName shouldEqual Api.ExecutionEnvironment
|
||||||
.Design()
|
.Design()
|
||||||
.name
|
.name
|
||||||
|
|
||||||
@ -7489,7 +6972,7 @@ class RuntimeServerTest
|
|||||||
context.executionComplete(contextId)
|
context.executionComplete(contextId)
|
||||||
)
|
)
|
||||||
context.consumeOut shouldEqual List("Hello World!")
|
context.consumeOut shouldEqual List("Hello World!")
|
||||||
context.languageContext.getExecutionEnvironment.getName shouldEqual Api.ExecutionEnvironment
|
context.languageContext.getGlobalExecutionEnvironment.getName shouldEqual Api.ExecutionEnvironment
|
||||||
.Live()
|
.Live()
|
||||||
.name
|
.name
|
||||||
}
|
}
|
||||||
@ -7724,3 +7207,284 @@ class RuntimeServerTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
object RuntimeServerTest {
|
||||||
|
|
||||||
|
trait TestMain {
|
||||||
|
object Main {
|
||||||
|
|
||||||
|
val metadata = new Metadata
|
||||||
|
|
||||||
|
val idMainX = metadata.addItem(63, 1, "aa1")
|
||||||
|
val idMainY = metadata.addItem(73, 7, "aa2")
|
||||||
|
val idMainZ = metadata.addItem(89, 5, "aa3")
|
||||||
|
val idFooY = metadata.addItem(133, 8, "ff2")
|
||||||
|
val idFooZ = metadata.addItem(150, 5, "ff3")
|
||||||
|
|
||||||
|
def code =
|
||||||
|
metadata.appendToCode(
|
||||||
|
"""
|
||||||
|
|from Standard.Base.Data.Numbers import all
|
||||||
|
|
|
||||||
|
|main =
|
||||||
|
| x = 6
|
||||||
|
| y = x.foo 5
|
||||||
|
| z = y + 5
|
||||||
|
| z
|
||||||
|
|
|
||||||
|
|Number.foo self = x ->
|
||||||
|
| y = self + 3
|
||||||
|
| z = y * x
|
||||||
|
| z
|
||||||
|
|""".stripMargin.linesIterator.mkString("\n")
|
||||||
|
)
|
||||||
|
|
||||||
|
object Update {
|
||||||
|
|
||||||
|
def mainX(
|
||||||
|
contextId: UUID,
|
||||||
|
fromCache: Boolean = false,
|
||||||
|
typeChanged: Boolean = true
|
||||||
|
): Api.Response =
|
||||||
|
Api.Response(
|
||||||
|
Api.ExpressionUpdates(
|
||||||
|
contextId,
|
||||||
|
Set(
|
||||||
|
Api.ExpressionUpdate(
|
||||||
|
Main.idMainX,
|
||||||
|
Some(ConstantsGen.INTEGER),
|
||||||
|
None,
|
||||||
|
Vector(Api.ProfilingInfo.ExecutionTime(0)),
|
||||||
|
fromCache,
|
||||||
|
typeChanged,
|
||||||
|
Api.ExpressionUpdate.Payload.Value()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def pendingZ(): Api.ExpressionUpdate =
|
||||||
|
Api.ExpressionUpdate(
|
||||||
|
Main.idFooZ,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
Vector(),
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
Api.ExpressionUpdate.Payload.Pending(None, None)
|
||||||
|
)
|
||||||
|
|
||||||
|
def pendingY(): Api.ExpressionUpdate =
|
||||||
|
Api.ExpressionUpdate(
|
||||||
|
Main.idFooY,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
Vector(),
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
Api.ExpressionUpdate.Payload.Pending(None, None)
|
||||||
|
)
|
||||||
|
|
||||||
|
def mainY(
|
||||||
|
contextId: UUID,
|
||||||
|
fromCache: Boolean = false,
|
||||||
|
typeChanged: Boolean = true
|
||||||
|
): Api.Response =
|
||||||
|
Api.Response(
|
||||||
|
Api.ExpressionUpdates(
|
||||||
|
contextId,
|
||||||
|
Set(
|
||||||
|
Api.ExpressionUpdate(
|
||||||
|
Main.idMainY,
|
||||||
|
Some(ConstantsGen.INTEGER),
|
||||||
|
Some(
|
||||||
|
Api.MethodCall(
|
||||||
|
Api.MethodPointer(
|
||||||
|
"Enso_Test.Test.Main",
|
||||||
|
ConstantsGen.NUMBER,
|
||||||
|
"foo"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
Vector(Api.ProfilingInfo.ExecutionTime(0)),
|
||||||
|
fromCache,
|
||||||
|
typeChanged,
|
||||||
|
Api.ExpressionUpdate.Payload.Value()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def mainZ(
|
||||||
|
contextId: UUID,
|
||||||
|
fromCache: Boolean = false,
|
||||||
|
typeChanged: Boolean = true
|
||||||
|
): Api.Response =
|
||||||
|
Api.Response(
|
||||||
|
Api.ExpressionUpdates(
|
||||||
|
contextId,
|
||||||
|
Set(
|
||||||
|
Api.ExpressionUpdate(
|
||||||
|
Main.idMainZ,
|
||||||
|
Some(ConstantsGen.INTEGER),
|
||||||
|
Some(
|
||||||
|
Api.MethodCall(
|
||||||
|
Api.MethodPointer(
|
||||||
|
"Standard.Base.Data.Numbers",
|
||||||
|
ConstantsGen.INTEGER,
|
||||||
|
"+"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
Vector(Api.ProfilingInfo.ExecutionTime(0)),
|
||||||
|
fromCache,
|
||||||
|
typeChanged,
|
||||||
|
Api.ExpressionUpdate.Payload.Value()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def fooY(
|
||||||
|
contextId: UUID,
|
||||||
|
fromCache: Boolean = false,
|
||||||
|
typeChanged: Boolean = true
|
||||||
|
): Api.Response =
|
||||||
|
Api.Response(
|
||||||
|
Api.ExpressionUpdates(
|
||||||
|
contextId,
|
||||||
|
Set(
|
||||||
|
Api.ExpressionUpdate(
|
||||||
|
Main.idFooY,
|
||||||
|
Some(ConstantsGen.INTEGER),
|
||||||
|
Some(
|
||||||
|
Api.MethodCall(
|
||||||
|
Api.MethodPointer(
|
||||||
|
"Standard.Base.Data.Numbers",
|
||||||
|
ConstantsGen.INTEGER,
|
||||||
|
"+"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
Vector(Api.ProfilingInfo.ExecutionTime(0)),
|
||||||
|
fromCache,
|
||||||
|
typeChanged,
|
||||||
|
Api.ExpressionUpdate.Payload.Value()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def fooZ(
|
||||||
|
contextId: UUID,
|
||||||
|
fromCache: Boolean = false,
|
||||||
|
typeChanged: Boolean = true
|
||||||
|
): Api.Response =
|
||||||
|
Api.Response(
|
||||||
|
Api.ExpressionUpdates(
|
||||||
|
contextId,
|
||||||
|
Set(
|
||||||
|
Api.ExpressionUpdate(
|
||||||
|
Main.idFooZ,
|
||||||
|
Some(ConstantsGen.INTEGER),
|
||||||
|
Some(
|
||||||
|
Api.MethodCall(
|
||||||
|
Api.MethodPointer(
|
||||||
|
"Standard.Base.Data.Numbers",
|
||||||
|
ConstantsGen.INTEGER,
|
||||||
|
"*"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
Vector(Api.ProfilingInfo.ExecutionTime(0)),
|
||||||
|
fromCache,
|
||||||
|
typeChanged,
|
||||||
|
Api.ExpressionUpdate.Payload.Value()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object Main2 {
|
||||||
|
|
||||||
|
val metadata = new Metadata
|
||||||
|
val idMainY = metadata.addItem(178, 5)
|
||||||
|
val idMainZ = metadata.addItem(192, 5)
|
||||||
|
|
||||||
|
val code = metadata.appendToCode(
|
||||||
|
"""from Standard.Base import all
|
||||||
|
|
|
||||||
|
|foo = arg ->
|
||||||
|
| IO.println "I'm expensive!"
|
||||||
|
| arg + 5
|
||||||
|
|
|
||||||
|
|bar = arg ->
|
||||||
|
| IO.println "I'm more expensive!"
|
||||||
|
| arg * 5
|
||||||
|
|
|
||||||
|
|main =
|
||||||
|
| x = 10
|
||||||
|
| y = foo x
|
||||||
|
| z = bar y
|
||||||
|
| z
|
||||||
|
|""".stripMargin.linesIterator.mkString("\n")
|
||||||
|
)
|
||||||
|
|
||||||
|
object Update {
|
||||||
|
|
||||||
|
def mainY(contextId: UUID) =
|
||||||
|
Api.Response(
|
||||||
|
Api.ExpressionUpdates(
|
||||||
|
contextId,
|
||||||
|
Set(
|
||||||
|
Api.ExpressionUpdate(
|
||||||
|
idMainY,
|
||||||
|
Some(ConstantsGen.INTEGER),
|
||||||
|
Some(
|
||||||
|
Api.MethodCall(
|
||||||
|
Api.MethodPointer(
|
||||||
|
"Enso_Test.Test.Main",
|
||||||
|
"Enso_Test.Test.Main",
|
||||||
|
"foo"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
Vector(Api.ProfilingInfo.ExecutionTime(0)),
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
Api.ExpressionUpdate.Payload.Value()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def mainZ(contextId: UUID) =
|
||||||
|
Api.Response(
|
||||||
|
Api.ExpressionUpdates(
|
||||||
|
contextId,
|
||||||
|
Set(
|
||||||
|
Api.ExpressionUpdate(
|
||||||
|
idMainZ,
|
||||||
|
Some(ConstantsGen.INTEGER),
|
||||||
|
Some(
|
||||||
|
Api.MethodCall(
|
||||||
|
Api.MethodPointer(
|
||||||
|
"Enso_Test.Test.Main",
|
||||||
|
"Enso_Test.Test.Main",
|
||||||
|
"bar"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
Vector(Api.ProfilingInfo.ExecutionTime(0)),
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
Api.ExpressionUpdate.Payload.Value()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1414,7 +1414,10 @@ class RuntimeSuggestionUpdatesTest
|
|||||||
|
|
||||||
// recompute
|
// recompute
|
||||||
context.send(
|
context.send(
|
||||||
Api.Request(requestId, Api.RecomputeContextRequest(contextId, None, None))
|
Api.Request(
|
||||||
|
requestId,
|
||||||
|
Api.RecomputeContextRequest(contextId, None, None, Seq())
|
||||||
|
)
|
||||||
)
|
)
|
||||||
val updates2 = context.receiveNIgnoreExpressionUpdates(3)
|
val updates2 = context.receiveNIgnoreExpressionUpdates(3)
|
||||||
updates2.length shouldEqual 3
|
updates2.length shouldEqual 3
|
||||||
|
@ -423,7 +423,7 @@ class RuntimeVisualizationsTest extends AnyFlatSpec with Matchers {
|
|||||||
context.send(
|
context.send(
|
||||||
Api.Request(
|
Api.Request(
|
||||||
requestId,
|
requestId,
|
||||||
Api.RecomputeContextRequest(contextId, None, None)
|
Api.RecomputeContextRequest(contextId, None, None, Seq())
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -551,7 +551,7 @@ class RuntimeVisualizationsTest extends AnyFlatSpec with Matchers {
|
|||||||
context.send(
|
context.send(
|
||||||
Api.Request(
|
Api.Request(
|
||||||
requestId,
|
requestId,
|
||||||
Api.RecomputeContextRequest(contextId, None, None)
|
Api.RecomputeContextRequest(contextId, None, None, Seq())
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
context.receiveNIgnoreExpressionUpdates(2) should contain allOf (
|
context.receiveNIgnoreExpressionUpdates(2) should contain allOf (
|
||||||
@ -570,7 +570,8 @@ class RuntimeVisualizationsTest extends AnyFlatSpec with Matchers {
|
|||||||
Vector(context.Main.idMainX)
|
Vector(context.Main.idMainX)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
None
|
None,
|
||||||
|
Seq()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -1577,7 +1578,7 @@ class RuntimeVisualizationsTest extends AnyFlatSpec with Matchers {
|
|||||||
context.send(
|
context.send(
|
||||||
Api.Request(
|
Api.Request(
|
||||||
requestId,
|
requestId,
|
||||||
Api.RecomputeContextRequest(contextId, None, None)
|
Api.RecomputeContextRequest(contextId, None, None, Seq())
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
context.receiveNIgnoreExpressionUpdates(
|
context.receiveNIgnoreExpressionUpdates(
|
||||||
@ -1598,7 +1599,8 @@ class RuntimeVisualizationsTest extends AnyFlatSpec with Matchers {
|
|||||||
Vector(context.Main.idMainX)
|
Vector(context.Main.idMainX)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
None
|
None,
|
||||||
|
Seq()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -2905,7 +2907,7 @@ class RuntimeVisualizationsTest extends AnyFlatSpec with Matchers {
|
|||||||
context.send(
|
context.send(
|
||||||
Api.Request(
|
Api.Request(
|
||||||
requestId,
|
requestId,
|
||||||
Api.RecomputeContextRequest(contextId, None, None)
|
Api.RecomputeContextRequest(contextId, None, None, Seq())
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -3079,7 +3081,7 @@ class RuntimeVisualizationsTest extends AnyFlatSpec with Matchers {
|
|||||||
context.send(
|
context.send(
|
||||||
Api.Request(
|
Api.Request(
|
||||||
requestId,
|
requestId,
|
||||||
Api.RecomputeContextRequest(contextId, None, None)
|
Api.RecomputeContextRequest(contextId, None, None, Seq())
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -3218,7 +3220,7 @@ class RuntimeVisualizationsTest extends AnyFlatSpec with Matchers {
|
|||||||
context.send(
|
context.send(
|
||||||
Api.Request(
|
Api.Request(
|
||||||
requestId,
|
requestId,
|
||||||
Api.RecomputeContextRequest(contextId, None, None)
|
Api.RecomputeContextRequest(contextId, None, None, Seq())
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -3402,7 +3404,7 @@ class RuntimeVisualizationsTest extends AnyFlatSpec with Matchers {
|
|||||||
context.send(
|
context.send(
|
||||||
Api.Request(
|
Api.Request(
|
||||||
requestId,
|
requestId,
|
||||||
Api.RecomputeContextRequest(contextId, None, None)
|
Api.RecomputeContextRequest(contextId, None, None, Seq())
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package org.enso.interpreter;
|
package org.enso.interpreter;
|
||||||
|
|
||||||
import com.oracle.truffle.api.CallTarget;
|
import com.oracle.truffle.api.CallTarget;
|
||||||
|
import com.oracle.truffle.api.ContextThreadLocal;
|
||||||
import com.oracle.truffle.api.Option;
|
import com.oracle.truffle.api.Option;
|
||||||
import com.oracle.truffle.api.TruffleLanguage;
|
import com.oracle.truffle.api.TruffleLanguage;
|
||||||
import com.oracle.truffle.api.TruffleLogger;
|
import com.oracle.truffle.api.TruffleLogger;
|
||||||
@ -87,6 +88,9 @@ public final class EnsoLanguage extends TruffleLanguage<EnsoContext> {
|
|||||||
private static final LanguageReference<EnsoLanguage> REFERENCE =
|
private static final LanguageReference<EnsoLanguage> REFERENCE =
|
||||||
LanguageReference.create(EnsoLanguage.class);
|
LanguageReference.create(EnsoLanguage.class);
|
||||||
|
|
||||||
|
private final ContextThreadLocal<ExecutionEnvironment[]> executionEnvironment =
|
||||||
|
locals.createContextThreadLocal((ctx, thread) -> new ExecutionEnvironment[1]);
|
||||||
|
|
||||||
public static EnsoLanguage get(Node node) {
|
public static EnsoLanguage get(Node node) {
|
||||||
return REFERENCE.get(node);
|
return REFERENCE.get(node);
|
||||||
}
|
}
|
||||||
@ -362,6 +366,7 @@ public final class EnsoLanguage extends TruffleLanguage<EnsoContext> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Conversions of primitive values */
|
/** Conversions of primitive values */
|
||||||
|
@Override
|
||||||
protected Object getLanguageView(EnsoContext context, Object value) {
|
protected Object getLanguageView(EnsoContext context, Object value) {
|
||||||
if (value instanceof Boolean b) {
|
if (value instanceof Boolean b) {
|
||||||
var bool = context.getBuiltins().bool();
|
var bool = context.getBuiltins().bool();
|
||||||
@ -370,4 +375,12 @@ public final class EnsoLanguage extends TruffleLanguage<EnsoContext> {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ExecutionEnvironment getExecutionEnvironment() {
|
||||||
|
return executionEnvironment.get()[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExecutionEnvironment(ExecutionEnvironment executionEnvironment) {
|
||||||
|
this.executionEnvironment.get()[0] = executionEnvironment;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -120,4 +120,9 @@ final class Instrumentor implements EnsoObject, IdExecutionService.Callbacks {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getExecutionEnvironment(IdExecutionService.Info info) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -108,7 +108,7 @@ public final class EnsoContext {
|
|||||||
private final AtomicLong clock = new AtomicLong();
|
private final AtomicLong clock = new AtomicLong();
|
||||||
|
|
||||||
private final Shape rootStateShape = Shape.newBuilder().layout(State.Container.class).build();
|
private final Shape rootStateShape = Shape.newBuilder().layout(State.Container.class).build();
|
||||||
private ExecutionEnvironment executionEnvironment;
|
private ExecutionEnvironment globalExecutionEnvironment;
|
||||||
|
|
||||||
private final int warningsLimit;
|
private final int warningsLimit;
|
||||||
|
|
||||||
@ -144,7 +144,7 @@ public final class EnsoContext {
|
|||||||
getOption(RuntimeOptions.DISABLE_IR_CACHES_KEY) || isParallelismEnabled;
|
getOption(RuntimeOptions.DISABLE_IR_CACHES_KEY) || isParallelismEnabled;
|
||||||
this.isPrivateCheckDisabled = getOption(RuntimeOptions.DISABLE_PRIVATE_CHECK_KEY);
|
this.isPrivateCheckDisabled = getOption(RuntimeOptions.DISABLE_PRIVATE_CHECK_KEY);
|
||||||
this.isStaticTypeAnalysisEnabled = getOption(RuntimeOptions.ENABLE_STATIC_ANALYSIS_KEY);
|
this.isStaticTypeAnalysisEnabled = getOption(RuntimeOptions.ENABLE_STATIC_ANALYSIS_KEY);
|
||||||
this.executionEnvironment = getOption(EnsoLanguage.EXECUTION_ENVIRONMENT);
|
this.globalExecutionEnvironment = getOption(EnsoLanguage.EXECUTION_ENVIRONMENT);
|
||||||
this.assertionsEnabled = shouldAssertionsBeEnabled();
|
this.assertionsEnabled = shouldAssertionsBeEnabled();
|
||||||
this.shouldWaitForPendingSerializationJobs =
|
this.shouldWaitForPendingSerializationJobs =
|
||||||
getOption(RuntimeOptions.WAIT_FOR_PENDING_SERIALIZATION_JOBS_KEY);
|
getOption(RuntimeOptions.WAIT_FOR_PENDING_SERIALIZATION_JOBS_KEY);
|
||||||
@ -869,13 +869,19 @@ public final class EnsoContext {
|
|||||||
return clock.getAndIncrement();
|
return clock.getAndIncrement();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ExecutionEnvironment getGlobalExecutionEnvironment() {
|
||||||
|
return globalExecutionEnvironment;
|
||||||
|
}
|
||||||
|
|
||||||
public ExecutionEnvironment getExecutionEnvironment() {
|
public ExecutionEnvironment getExecutionEnvironment() {
|
||||||
return executionEnvironment;
|
ExecutionEnvironment env = language.getExecutionEnvironment();
|
||||||
|
return env == null ? getGlobalExecutionEnvironment() : env;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set the runtime execution environment of this context. */
|
/** Set the runtime execution environment of this context. */
|
||||||
public void setExecutionEnvironment(ExecutionEnvironment executionEnvironment) {
|
public void setExecutionEnvironment(ExecutionEnvironment executionEnvironment) {
|
||||||
this.executionEnvironment = executionEnvironment;
|
this.globalExecutionEnvironment = executionEnvironment;
|
||||||
|
language.setExecutionEnvironment(executionEnvironment);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -883,11 +889,12 @@ public final class EnsoContext {
|
|||||||
*
|
*
|
||||||
* @param context the execution context
|
* @param context the execution context
|
||||||
* @param environmentName the execution environment name
|
* @param environmentName the execution environment name
|
||||||
|
* @return the execution environment version before modification
|
||||||
*/
|
*/
|
||||||
public ExecutionEnvironment enableExecutionEnvironment(Atom context, String environmentName) {
|
public ExecutionEnvironment enableExecutionEnvironment(Atom context, String environmentName) {
|
||||||
ExecutionEnvironment original = executionEnvironment;
|
ExecutionEnvironment original = globalExecutionEnvironment;
|
||||||
if (executionEnvironment.getName().equals(environmentName)) {
|
if (original.getName().equals(environmentName)) {
|
||||||
executionEnvironment = executionEnvironment.withContextEnabled(context);
|
setExecutionEnvironment(original.withContextEnabled(context));
|
||||||
}
|
}
|
||||||
return original;
|
return original;
|
||||||
}
|
}
|
||||||
@ -897,11 +904,12 @@ public final class EnsoContext {
|
|||||||
*
|
*
|
||||||
* @param context the execution context
|
* @param context the execution context
|
||||||
* @param environmentName the execution environment name
|
* @param environmentName the execution environment name
|
||||||
|
* @return the execution environment version before modification
|
||||||
*/
|
*/
|
||||||
public ExecutionEnvironment disableExecutionEnvironment(Atom context, String environmentName) {
|
public ExecutionEnvironment disableExecutionEnvironment(Atom context, String environmentName) {
|
||||||
ExecutionEnvironment original = executionEnvironment;
|
ExecutionEnvironment original = globalExecutionEnvironment;
|
||||||
if (executionEnvironment.getName().equals(environmentName)) {
|
if (original.getName().equals(environmentName)) {
|
||||||
executionEnvironment = executionEnvironment.withContextDisabled(context);
|
setExecutionEnvironment(original.withContextDisabled(context));
|
||||||
}
|
}
|
||||||
return original;
|
return original;
|
||||||
}
|
}
|
||||||
|
@ -105,7 +105,7 @@ public class ExecutionEnvironment {
|
|||||||
case DESIGN_ENVIRONMENT_NAME:
|
case DESIGN_ENVIRONMENT_NAME:
|
||||||
return DESIGN;
|
return DESIGN;
|
||||||
default:
|
default:
|
||||||
throw new RuntimeException("Unsupported Execution Environment `" + name + "`");
|
throw new IllegalArgumentException("Unsupported Execution Environment `" + name + "`");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ export project.Data.Numbers.Number
|
|||||||
export project.Data.Numbers.Integer
|
export project.Data.Numbers.Integer
|
||||||
export project.Data.Vector.Vector
|
export project.Data.Vector.Vector
|
||||||
export project.Function.Function
|
export project.Function.Function
|
||||||
|
export project.Nothing.Nothing
|
||||||
export project.Polyglot.Java
|
export project.Polyglot.Java
|
||||||
export project.Polyglot.Polyglot
|
export project.Polyglot.Polyglot
|
||||||
export project.Runtime
|
export project.Runtime
|
||||||
|
@ -23,13 +23,13 @@ type Context
|
|||||||
Output -> "Output"
|
Output -> "Output"
|
||||||
|
|
||||||
if_enabled : Any -> Text -> Text -> Boolean -> Any ! Forbidden_Operation
|
if_enabled : Any -> Text -> Text -> Boolean -> Any ! Forbidden_Operation
|
||||||
if_enabled self ~action environment="design" disabled_message="The "+self.name+" context is disabled." panic=True =
|
if_enabled self ~action environment=Runtime.current_execution_environment disabled_message="The "+self.name+" context is disabled." panic=True =
|
||||||
if self.is_enabled environment then action else
|
if self.is_enabled environment then action else
|
||||||
error = Forbidden_Operation.Error disabled_message
|
error = Forbidden_Operation.Error disabled_message
|
||||||
if panic then Panic.throw error else Error.throw error
|
if panic then Panic.throw error else Error.throw error
|
||||||
|
|
||||||
is_enabled : Text -> Boolean
|
is_enabled : Text -> Boolean
|
||||||
is_enabled self environment="design" =
|
is_enabled self environment=Runtime.current_execution_environment =
|
||||||
self.is_enabled_builtin environment
|
self.is_enabled_builtin environment
|
||||||
|
|
||||||
## PRIVATE
|
## PRIVATE
|
||||||
|
Loading…
Reference in New Issue
Block a user