Skip to content

Commit

Permalink
Print out warnings associated with local variables (#10842)
Browse files Browse the repository at this point in the history
Fixes #9749 by:
- [x] Adding `fn` option to `enso-debug-server` instrument - eb3b76e
- [x] Print warnings (if any) to stderr - 4fda04b
- [x] Improving output of `:list` to print out warnings - dbe3c45
- [x] Print errors to stderr - 1312546
- [x] Exiting on `DataflowError` - 2cc7ef5 and e6fbf73
- [x] Using all of that inside of `runner/*Main` - 7df58ef

The core of the change is in instrumentation that wraps the `main` method and at its end checks for _warnings or errors_ among local variables. When an error is found, it wraps the original return value of `main` with a proxy that delegates to the original value, but also pretends to be _exit exception_ with exit code 173. That one is detected in `Main` launcher to exit the process with exit code 173.

# Important Notes
As a side-effect of this change, one can request an invocation of REPL at the end of any method just by providing a property to the VM:
```bash
$ enso --vm.D=polyglot.enso-debug-server.method-break-point=err_test.main --run err_test.enso --repl
```
stops at the end of `main` method of `err_test.enso` file.
  • Loading branch information
JaroslavTulach authored Aug 21, 2024
1 parent 22263e8 commit e5f865f
Show file tree
Hide file tree
Showing 18 changed files with 726 additions and 106 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,13 @@
[10725]: https:/enso-org/enso/pull/10725
[10820]: https:/enso-org/enso/pull/10820

# Enso 2023.3
#### Enso Language & Runtime

- [Print out warnings associated with local variables][10842]

[10842]: https:/enso-org/enso/pull/10842

# Enso 2024.3

#### Enso Language & Runtime

Expand Down
21 changes: 20 additions & 1 deletion engine/common/src/main/java/org/enso/common/ContextFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
* @param options additional options for the Context
* @param executionEnvironment optional name of the execution environment to use during execution
* @param warningsLimit maximal number of warnings reported to the user
* @param checkForWarnings name of method to check for warnings
* @param enableDebugServer enable debug (e.g. REPL) server
*/
public final class ContextFactory {
private String projectRoot;
Expand All @@ -47,8 +49,10 @@ public final class ContextFactory {
private boolean useGlobalIrCacheLocation = true;
private boolean enableAutoParallelism;
private String executionEnvironment;
private String checkForWarnings;
private int warningsLimit = 100;
private java.util.Map<String, String> options = java.util.Collections.emptyMap();
private boolean enableDebugServer;

private ContextFactory() {}

Expand Down Expand Up @@ -141,6 +145,16 @@ public ContextFactory options(Map<String, String> options) {
return this;
}

public ContextFactory checkForWarnings(String fqnOfMethod) {
this.checkForWarnings = fqnOfMethod;
return this;
}

public ContextFactory enableDebugServer(boolean b) {
this.enableDebugServer = b;
return this;
}

public Context build() {
if (executionEnvironment != null) {
options.put("enso.ExecutionEnvironment", executionEnvironment);
Expand Down Expand Up @@ -169,6 +183,12 @@ public Context build() {
.out(out)
.err(err)
.in(in);
if (checkForWarnings != null) {
builder.option(DebugServerInfo.METHOD_BREAKPOINT_OPTION, checkForWarnings);
}
if (enableDebugServer) {
builder.option(DebugServerInfo.ENABLE_OPTION, "true");
}
if (messageTransport != null) {
builder.serverTransport(messageTransport);
}
Expand Down Expand Up @@ -239,5 +259,4 @@ private static HostAccess allWithTypeMapping() {
.allowAccessInheritance(true)
.build();
}

}
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package org.enso.polyglot.debugger;
package org.enso.common;

/** Container for Runtime Server related constants. */
/** Container for debug server related constants. */
public class DebugServerInfo {
private DebugServerInfo() {

}
public static final String URI = "enso://debug-server";
public static final String INSTRUMENT_NAME = "enso-debug-server";
public static final String ENABLE_OPTION = INSTRUMENT_NAME + ".enable";
public static final String METHOD_BREAKPOINT_OPTION = INSTRUMENT_NAME + ".method-break-point";
}
44 changes: 33 additions & 11 deletions engine/runner/src/main/java/org/enso/runner/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.apache.commons.cli.OptionGroup;
import org.apache.commons.cli.Options;
import org.enso.common.ContextFactory;
import org.enso.common.DebugServerInfo;
import org.enso.common.HostEnsoUtils;
import org.enso.common.LanguageInfo;
import org.enso.distribution.DistributionManager;
Expand All @@ -37,7 +38,6 @@
import org.enso.pkg.Template;
import org.enso.polyglot.Module;
import org.enso.polyglot.PolyglotContext;
import org.enso.polyglot.debugger.DebugServerInfo;
import org.enso.polyglot.debugger.DebuggerSessionManagerEndpoint;
import org.enso.profiling.sampler.NoopSampler;
import org.enso.profiling.sampler.OutputStreamSampler;
Expand Down Expand Up @@ -688,6 +688,24 @@ private void handleRun(
}
var projectMode = fileAndProject._1();
var file = fileAndProject._2();
var mainFile = file;
if (projectMode) {
var result = PackageManager$.MODULE$.Default().loadPackage(file);
if (result.isSuccess()) {
@SuppressWarnings("unchecked")
var pkg = (org.enso.pkg.Package<java.io.File>) result.get();

mainFile = pkg.mainFile();
if (!mainFile.exists()) {
println("Main file does not exist.");
throw exitFail();
}
} else {
println(result.failed().get().getMessage());
throw exitFail();
}
}

var projectRoot = fileAndProject._3();
var options = new HashMap<String, String>();

Expand All @@ -714,7 +732,9 @@ private void handleRun(
}
if (enableDebugServer) {
factory.messageTransport(replTransport());
options.put(DebugServerInfo.ENABLE_OPTION, "true");
factory.enableDebugServer(true);
} else {
factory.checkForWarnings(mainFile.getName().replace(".enso", "") + ".main");
}
var context = new PolyglotContext(factory.build());

Expand All @@ -724,12 +744,6 @@ private void handleRun(
var s = (scala.util.Success) result;
@SuppressWarnings("unchecked")
var pkg = (org.enso.pkg.Package<java.io.File>) s.get();
var main = pkg.mainFile();
if (!main.exists()) {
println("Main file does not exist.");
context.context().close();
throw exitFail();
}
var mainModuleName = pkg.moduleNameForFile(pkg.mainFile()).toString();
runPackage(context, mainModuleName, file, additionalArgs);
} else {
Expand Down Expand Up @@ -879,11 +893,20 @@ private void runMain(
if (!res.isNull()) {
var textRes = res.isString() ? res.asString() : res.toString();
println(textRes);
if (res.isException()) {
try {
throw res.throwException();
} catch (PolyglotException e) {
if (e.isExit()) {
throw doExit(e.getExitStatus());
}
}
}
}
}
} catch (PolyglotException e) {
if (e.isExit()) {
doExit(e.getExitStatus());
throw doExit(e.getExitStatus());
} else {
printPolyglotException(e, rootPkgPath);
throw exitFail();
Expand Down Expand Up @@ -917,14 +940,13 @@ private void runRepl(
.replace("$mainMethodName", mainMethodName);
var replModuleName = "Internal_Repl_Module___";
var projectRoot = projectPath != null ? projectPath : "";
var options = Collections.singletonMap(DebugServerInfo.ENABLE_OPTION, "true");

var context =
new PolyglotContext(
ContextFactory.create()
.projectRoot(projectRoot)
.messageTransport(replTransport())
.options(options)
.enableDebugServer(true)
.logLevel(logLevel)
.logMasking(logMasking)
.enableIrCaches(enableIrCaches)
Expand Down
Loading

0 comments on commit e5f865f

Please sign in to comment.