mirror of
https://github.com/enso-org/enso.git
synced 2024-12-22 21:01:37 +03:00
Properly expose stacktraces and related data to user code (#3271)
This commit is contained in:
parent
19b2064070
commit
67b4e59506
@ -38,6 +38,8 @@
|
||||
- [Implemented `Range.find`, `Table.rename_columns` and
|
||||
`Table.use_first_row_as_names` operations][3249]
|
||||
- [Implemented `Text.at` and `Text.is_digit` methods][3269]
|
||||
- [Implemented `Runtime.get_stack_trace` together with some utilities to process
|
||||
stack traces and code locations][3271]
|
||||
- [Implemented `Vector.flatten`][3259]
|
||||
|
||||
[debug-shortcuts]:
|
||||
@ -59,6 +61,7 @@
|
||||
[3249]: https://github.com/enso-org/enso/pull/3249
|
||||
[3264]: https://github.com/enso-org/enso/pull/3264
|
||||
[3269]: https://github.com/enso-org/enso/pull/3269
|
||||
[3271]: https://github.com/enso-org/enso/pull/3271
|
||||
[3259]: https://github.com/enso-org/enso/pull/3259
|
||||
|
||||
#### Enso Compiler
|
||||
|
@ -1,55 +1,57 @@
|
||||
import Standard.Base.Data.Any.Extensions
|
||||
import Standard.Base.Data.Array.Extensions
|
||||
import Standard.Base.Data.Interval
|
||||
import Standard.Base.Data.Json
|
||||
import Standard.Base.Data.List
|
||||
import Standard.Base.Data.Locale
|
||||
import Standard.Base.Data.Map
|
||||
import Standard.Base.Data.Maybe
|
||||
import Standard.Base.Data.Noise
|
||||
import Standard.Base.Data.Number.Extensions
|
||||
import Standard.Base.Data.Ordering
|
||||
import Standard.Base.Data.Ordering.Sort_Order
|
||||
import Standard.Base.Data.Pair
|
||||
import Standard.Base.Data.Range
|
||||
import Standard.Base.Data.Text.Extensions
|
||||
import Standard.Base.Data.Vector
|
||||
import Standard.Base.Error.Common
|
||||
import Standard.Base.Error.Extensions
|
||||
import Standard.Base.Math
|
||||
import Standard.Base.Meta
|
||||
import Standard.Base.Meta.Enso_Project
|
||||
import Standard.Base.Polyglot.Java
|
||||
import Standard.Base.System.File
|
||||
import Standard.Base.Data.Text.Regex.Mode as Regex_Mode
|
||||
import project.Data.Any.Extensions
|
||||
import project.Data.Array.Extensions
|
||||
import project.Data.Interval
|
||||
import project.Data.Json
|
||||
import project.Data.List
|
||||
import project.Data.Locale
|
||||
import project.Data.Map
|
||||
import project.Data.Maybe
|
||||
import project.Data.Noise
|
||||
import project.Data.Number.Extensions
|
||||
import project.Data.Ordering
|
||||
import project.Data.Ordering.Sort_Order
|
||||
import project.Data.Pair
|
||||
import project.Data.Range
|
||||
import project.Data.Text.Extensions
|
||||
import project.Data.Vector
|
||||
import project.Error.Common
|
||||
import project.Error.Extensions
|
||||
import project.Math
|
||||
import project.Meta
|
||||
import project.Meta.Enso_Project
|
||||
import project.Polyglot.Java
|
||||
import project.Runtime.Extensions
|
||||
import project.System.File
|
||||
import project.Data.Text.Regex.Mode as Regex_Mode
|
||||
|
||||
from Standard.Builtins import Nothing, Number, Integer, Any, True, False, Cons, Boolean, Arithmetic_Error
|
||||
|
||||
export Standard.Base.Data.Interval
|
||||
export Standard.Base.Data.Json
|
||||
export Standard.Base.Data.Locale
|
||||
export Standard.Base.Data.Map
|
||||
export Standard.Base.Data.Maybe
|
||||
export Standard.Base.Data.Ordering
|
||||
export Standard.Base.Data.Ordering.Sort_Order
|
||||
export Standard.Base.Data.Vector
|
||||
export Standard.Base.Math
|
||||
export Standard.Base.Meta
|
||||
export Standard.Base.System.File
|
||||
export Standard.Base.Data.Text.Regex.Mode as Regex_Mode
|
||||
export project.Data.Interval
|
||||
export project.Data.Json
|
||||
export project.Data.Locale
|
||||
export project.Data.Map
|
||||
export project.Data.Maybe
|
||||
export project.Data.Ordering
|
||||
export project.Data.Ordering.Sort_Order
|
||||
export project.Data.Vector
|
||||
export project.Math
|
||||
export project.Meta
|
||||
export project.System.File
|
||||
export project.Data.Text.Regex.Mode as Regex_Mode
|
||||
|
||||
from Standard.Base.Data.Any.Extensions export all
|
||||
from Standard.Base.Data.Array.Extensions export all
|
||||
from Standard.Base.Data.List export Nil, Cons
|
||||
from Standard.Base.Data.Number.Extensions export all hiding Math, String, Double
|
||||
from Standard.Base.Data.Noise export all hiding Noise
|
||||
from Standard.Base.Data.Pair export Pair
|
||||
from Standard.Base.Data.Range export Range
|
||||
from Standard.Base.Data.Text.Extensions export Text, Split_Kind, Line_Ending_Style
|
||||
from Standard.Base.Error.Common export all
|
||||
from Standard.Base.Error.Extensions export all
|
||||
from Standard.Base.Meta.Enso_Project export all
|
||||
from Standard.Base.Polyglot.Java export all
|
||||
from project.Data.Any.Extensions export all
|
||||
from project.Data.Array.Extensions export all
|
||||
from project.Data.List export Nil, Cons
|
||||
from project.Data.Number.Extensions export all hiding Math, String, Double
|
||||
from project.Data.Noise export all hiding Noise
|
||||
from project.Data.Pair export Pair
|
||||
from project.Data.Range export Range
|
||||
from project.Data.Text.Extensions export Text, Split_Kind, Line_Ending_Style
|
||||
from project.Error.Common export all
|
||||
from project.Error.Extensions export all
|
||||
from project.Meta.Enso_Project export all
|
||||
from project.Polyglot.Java export all
|
||||
from project.Runtime.Extensions export all
|
||||
|
||||
from Standard.Builtins export all hiding Meta, Less, Equal, Greater, Ordering
|
||||
|
||||
|
@ -9,7 +9,7 @@ import Standard.Builtins
|
||||
|
||||
Enso_Project.root
|
||||
Builtins.Project_Description.root : File.File
|
||||
Builtins.Project_Description.root = File.File this.prim_root_file
|
||||
Builtins.Project_Description.root = File.new this.prim_root_file.getPath
|
||||
|
||||
## Returns the root data directory of the project.
|
||||
|
||||
|
@ -0,0 +1,93 @@
|
||||
from Standard.Base import all
|
||||
|
||||
## ADVANCED
|
||||
UNSTABLE
|
||||
Represents a source location in Enso code. Contains information about the
|
||||
source file and code position within it.
|
||||
type Source_Location
|
||||
## PRIVATE
|
||||
type Source_Location prim_location
|
||||
|
||||
## UNSTABLE
|
||||
Pretty prints the location.
|
||||
to_text : Text
|
||||
to_text =
|
||||
'(Source_Location ' + this.formatted_coordinates + ')'
|
||||
|
||||
## UNSTABLE
|
||||
|
||||
Returns the 1-based line index of the start of this code range.
|
||||
start_line : Integer
|
||||
start_line = this.prim_location.getStartLine
|
||||
|
||||
## UNSTABLE
|
||||
|
||||
Returns the 1-based line index of the end of this code range.
|
||||
end_line : Integer
|
||||
end_line = this.prim_location.getEndLine
|
||||
|
||||
## UNSTABLE
|
||||
|
||||
Returns the 1-based column index of the start of this code range.
|
||||
start_column : Integer
|
||||
start_column = this.prim_location.getStartColumn
|
||||
|
||||
## UNSTABLE
|
||||
|
||||
Returns the 1-based column index of the end of this code range.
|
||||
end_column : Integer
|
||||
end_column = this.prim_location.getEndColumn
|
||||
|
||||
## UNSTABLE
|
||||
|
||||
Returns a pretty-printed location (file and line info).
|
||||
formatted_coordinates : Text
|
||||
formatted_coordinates =
|
||||
start_line = this.start_line
|
||||
end_line = this.end_line
|
||||
indices = case start_line == end_line of
|
||||
True ->
|
||||
row = start_line.to_text
|
||||
start = this.start_column.to_text
|
||||
end = this.end_column.to_text
|
||||
row + ":" + start + "-" + end
|
||||
False ->
|
||||
start_line + '-' + end_line
|
||||
cwd = File.current_directory
|
||||
file = this.file.absolute
|
||||
formatted_file = case file.is_child_of cwd of
|
||||
True -> cwd.relativize file . path
|
||||
_ -> file.path
|
||||
formatted_file + ":" + indices
|
||||
|
||||
## UNSTABLE
|
||||
|
||||
Return the source file corresponding to this location.
|
||||
file : File.File
|
||||
file = File.new this.prim_location.getSource.getPath
|
||||
|
||||
## ADVANCED
|
||||
UNSTABLE
|
||||
|
||||
Represents a single stack frame in an Enso stack trace.
|
||||
type Stack_Trace_Element
|
||||
## PRIVATE
|
||||
type Stack_Trace_Element name source_location
|
||||
|
||||
## ADVANCED
|
||||
UNSTABLE
|
||||
|
||||
Returns the execution stack trace of its call site. The ordering of the
|
||||
resulting vector is such that the top stack frame is the first element.
|
||||
Runtime.get_stack_trace : Vector.Vector Stack_Trace_Element
|
||||
Runtime.get_stack_trace =
|
||||
prim_stack = this.primitive_get_stack_trace
|
||||
stack_with_prims = Vector.Vector prim_stack
|
||||
stack = stack_with_prims.map el->
|
||||
loc = case Polyglot.has_source_location el of
|
||||
True -> Source_Location (Polyglot.get_source_location el)
|
||||
False -> Nothing
|
||||
name = Polyglot.get_executable_name el
|
||||
Stack_Trace_Element name loc
|
||||
# drop this frame and the one from `Runtime.primitive_get_stack_trace`
|
||||
stack.drop_start 2
|
@ -598,6 +598,16 @@ type File
|
||||
matcher.matches (Path.of pathStr)
|
||||
filtered
|
||||
|
||||
## UNSTABLE
|
||||
|
||||
Checks if `this` is a child path of `other`.
|
||||
is_child_of other = this.prim_file.startsWith other.prim_file
|
||||
|
||||
## UNSTABLE
|
||||
|
||||
Transforms `child` to a relative path with respect to `this`.
|
||||
relativize child = File (this.prim_file.relativize child.prim_file)
|
||||
|
||||
## An output stream, allowing for interactive writing of contents into an
|
||||
open file.
|
||||
type Output_Stream
|
||||
|
@ -14,6 +14,7 @@ code from modules.
|
||||
|
||||
<!-- MarkdownTOC levels="2,3" autolink="true" -->
|
||||
|
||||
- [Qualified Names](#qualified-names)
|
||||
- [Import Syntax](#import-syntax)
|
||||
- [Qualified Imports](#qualified-imports)
|
||||
- [Unqualified Imports](#unqualified-imports)
|
||||
@ -24,6 +25,21 @@ code from modules.
|
||||
|
||||
<!-- /MarkdownTOC -->
|
||||
|
||||
## Qualified Names
|
||||
|
||||
Both imports and exports require the use of qualified module names. A qualified
|
||||
name consists of the library namespace (usually organization under which its
|
||||
published) and the library name, followed by module names mirroring the source
|
||||
tree of the library. For example the file `src/Stuff/Things/Util.enso` inside
|
||||
the library `My_Lib` published by the user `wdanilo` would have the following
|
||||
qualified name: `wdanilo.My_Lib.Stuff.Things.Util`. To facilitate library
|
||||
renaming (or deciding on the publishing organization later in the development
|
||||
cycle, or working on a project that won't be published) it is possible to use
|
||||
the keyword `project` instead of namespace and project name, to import a file in
|
||||
the same project. Therefore, the file `src/Varia/Tools/Manager.enso` in `My_Lib`
|
||||
published (or not) by `wdanilo` may use `project.Stuff.Things.Util` to refer to
|
||||
the previously mentioned file.
|
||||
|
||||
## Import Syntax
|
||||
|
||||
There are two main ways of importing a module into the current scope.
|
||||
|
@ -0,0 +1,36 @@
|
||||
package org.enso.interpreter.node.expression.builtin.interop.generic;
|
||||
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.interop.UnsupportedMessageException;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.profiles.BranchProfile;
|
||||
import org.enso.interpreter.Constants;
|
||||
import org.enso.interpreter.Language;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.runtime.Context;
|
||||
import org.enso.interpreter.runtime.builtin.Builtins;
|
||||
import org.enso.interpreter.runtime.data.text.Text;
|
||||
import org.enso.interpreter.runtime.error.PanicException;
|
||||
|
||||
@BuiltinMethod(
|
||||
type = "Polyglot",
|
||||
name = "get_executable_name",
|
||||
description = "Returns the executable name of a polyglot object.")
|
||||
public class GetExecutableNameNode extends Node {
|
||||
private @Child InteropLibrary functionsLibrary =
|
||||
InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH);
|
||||
private @Child InteropLibrary stringsLibrary =
|
||||
InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH);
|
||||
private final BranchProfile err = BranchProfile.create();
|
||||
|
||||
Text execute(Object _this, Object function) {
|
||||
try {
|
||||
return Text.create(stringsLibrary.asString(functionsLibrary.getExecutableName(function)));
|
||||
} catch (UnsupportedMessageException e) {
|
||||
err.enter();
|
||||
Builtins builtins = Context.get(this).getBuiltins();
|
||||
throw new PanicException(
|
||||
builtins.error().makeTypeError(builtins.function(), function, "function"), this);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package org.enso.interpreter.node.expression.builtin.interop.generic;
|
||||
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.interop.UnsupportedMessageException;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.profiles.BranchProfile;
|
||||
import org.enso.interpreter.Constants;
|
||||
import org.enso.interpreter.Language;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.runtime.Context;
|
||||
import org.enso.interpreter.runtime.builtin.Builtins;
|
||||
import org.enso.interpreter.runtime.data.EnsoSourceSection;
|
||||
import org.enso.interpreter.runtime.error.PanicException;
|
||||
|
||||
@BuiltinMethod(
|
||||
type = "Polyglot",
|
||||
name = "get_source_location",
|
||||
description = "Returns the source location of a polyglot object.")
|
||||
public class GetSourceLocationNode extends Node {
|
||||
private @Child InteropLibrary library =
|
||||
InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH);
|
||||
private final BranchProfile err = BranchProfile.create();
|
||||
|
||||
Object execute(Object _this, Object value) {
|
||||
try {
|
||||
return Context.get(this)
|
||||
.getEnvironment()
|
||||
.asGuestValue(new EnsoSourceSection(library.getSourceLocation(value)));
|
||||
} catch (UnsupportedMessageException e) {
|
||||
err.enter();
|
||||
Builtins builtins = Context.get(this).getBuiltins();
|
||||
throw new PanicException(
|
||||
builtins.error().makeTypeError(builtins.function(), value, "function"), this);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package org.enso.interpreter.node.expression.builtin.interop.generic;
|
||||
|
||||
import com.oracle.truffle.api.interop.InteropLibrary;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import com.oracle.truffle.api.profiles.BranchProfile;
|
||||
import org.enso.interpreter.Constants;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
|
||||
@BuiltinMethod(
|
||||
type = "Polyglot",
|
||||
name = "has_source_location",
|
||||
description = "Checks if an object has a source location.")
|
||||
public class HasSourceLocationNode extends Node {
|
||||
private @Child InteropLibrary library =
|
||||
InteropLibrary.getFactory().createDispatched(Constants.CacheSizes.BUILTIN_INTEROP_DISPATCH);
|
||||
private final BranchProfile err = BranchProfile.create();
|
||||
|
||||
boolean execute(Object _this, Object value) {
|
||||
return library.hasSourceLocation(value);
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package org.enso.interpreter.node.expression.builtin.runtime;
|
||||
|
||||
import com.oracle.truffle.api.TruffleStackTrace;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||
import org.enso.interpreter.runtime.data.Array;
|
||||
import org.enso.interpreter.runtime.error.PanicException;
|
||||
|
||||
@BuiltinMethod(
|
||||
type = "Runtime",
|
||||
name = "primitive_get_stack_trace",
|
||||
description = "Gets the current execution stacktrace.")
|
||||
public class GetStackTraceNode extends Node {
|
||||
Array execute(Object _this) {
|
||||
var exception = new PanicException(null, this);
|
||||
TruffleStackTrace.fillIn(exception);
|
||||
var elements = TruffleStackTrace.getStackTrace(exception);
|
||||
var ret = new Array(elements.size());
|
||||
for (int i = 0; i < elements.size(); i++) {
|
||||
var element = elements.get(i);
|
||||
ret.getItems()[i] = element.getGuestObject();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ import com.oracle.truffle.api.TruffleFile;
|
||||
import com.oracle.truffle.api.TruffleLanguage;
|
||||
import com.oracle.truffle.api.TruffleLanguage.Env;
|
||||
import com.oracle.truffle.api.TruffleLogger;
|
||||
import com.oracle.truffle.api.nodes.Node;
|
||||
import org.enso.compiler.Compiler;
|
||||
import org.enso.compiler.PackageRepository;
|
||||
import org.enso.compiler.data.CompilerConfig;
|
||||
@ -37,6 +38,9 @@ import java.util.UUID;
|
||||
*/
|
||||
public class Context {
|
||||
|
||||
private static final TruffleLanguage.ContextReference<Context> REFERENCE =
|
||||
TruffleLanguage.ContextReference.create(Language.class);
|
||||
|
||||
private final Language language;
|
||||
private final Env environment;
|
||||
private @CompilationFinal Compiler compiler;
|
||||
@ -138,6 +142,15 @@ public class Context {
|
||||
pkg -> packageRepository.registerMainProjectPackage(pkg.libraryName(), pkg));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param node the location of context access. Pass {@code null} if not in a node.
|
||||
* @return the proper context instance for the current {@link
|
||||
* com.oracle.truffle.api.TruffleContext}.
|
||||
*/
|
||||
public static Context get(Node node) {
|
||||
return REFERENCE.get(node);
|
||||
}
|
||||
|
||||
/** Performs eventual cleanup before the context is disposed of. */
|
||||
public void shutdown() {
|
||||
threadManager.shutdown();
|
||||
|
@ -24,6 +24,7 @@ import org.enso.interpreter.node.expression.builtin.io.PrintErrMethodGen;
|
||||
import org.enso.interpreter.node.expression.builtin.io.PrintlnMethodGen;
|
||||
import org.enso.interpreter.node.expression.builtin.io.ReadlnMethodGen;
|
||||
import org.enso.interpreter.node.expression.builtin.runtime.GCMethodGen;
|
||||
import org.enso.interpreter.node.expression.builtin.runtime.GetStackTraceMethodGen;
|
||||
import org.enso.interpreter.node.expression.builtin.runtime.NoInlineMethodGen;
|
||||
import org.enso.interpreter.node.expression.builtin.runtime.NoInlineWithArgMethodGen;
|
||||
import org.enso.interpreter.node.expression.builtin.state.GetStateMethodGen;
|
||||
@ -157,6 +158,7 @@ public class Builtins {
|
||||
scope.registerMethod(
|
||||
runtime, "no_inline_with_arg", NoInlineWithArgMethodGen.makeFunction(language));
|
||||
scope.registerMethod(runtime, "gc", GCMethodGen.makeFunction(language));
|
||||
scope.registerMethod(runtime, "primitive_get_stack_trace", GetStackTraceMethodGen.makeFunction(language));
|
||||
|
||||
scope.registerMethod(panic, "throw", ThrowPanicMethodGen.makeFunction(language));
|
||||
scope.registerMethod(panic, "recover", RecoverPanicMethodGen.makeFunction(language));
|
||||
|
@ -31,6 +31,12 @@ public class Polyglot {
|
||||
scope.registerMethod(polyglot, "get_array_size", GetArraySizeMethodGen.makeFunction(language));
|
||||
scope.registerMethod(
|
||||
polyglot, "is_language_installed", IsLanguageInstalledMethodGen.makeFunction(language));
|
||||
scope.registerMethod(
|
||||
polyglot, "get_executable_name", GetExecutableNameMethodGen.makeFunction(language));
|
||||
scope.registerMethod(
|
||||
polyglot, "get_source_location", GetSourceLocationMethodGen.makeFunction(language));
|
||||
scope.registerMethod(
|
||||
polyglot, "has_source_location", HasSourceLocationMethodGen.makeFunction(language));
|
||||
}
|
||||
|
||||
/** @return the atom constructor for polyglot */
|
||||
|
@ -89,6 +89,10 @@ public class EnsoFile {
|
||||
truffleFile.delete();
|
||||
}
|
||||
|
||||
public boolean startsWith(EnsoFile parent) {
|
||||
return truffleFile.startsWith(parent.truffleFile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "(File " + truffleFile.getPath() + ")";
|
||||
|
@ -0,0 +1,45 @@
|
||||
package org.enso.interpreter.runtime.data;
|
||||
|
||||
import com.oracle.truffle.api.source.Source;
|
||||
import com.oracle.truffle.api.source.SourceSection;
|
||||
|
||||
/** Wrapper for exposing sources to Enso. Delegates to original methods with no behavior changes. */
|
||||
public class EnsoSource {
|
||||
private final Source source;
|
||||
|
||||
public EnsoSource(Source source) {
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
public String getLanguage() {
|
||||
return source.getLanguage();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return source.getName();
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return source.getPath();
|
||||
}
|
||||
|
||||
public boolean isInternal() {
|
||||
return source.isInternal();
|
||||
}
|
||||
|
||||
public CharSequence getCharacters() {
|
||||
return source.getCharacters();
|
||||
}
|
||||
|
||||
public int getLength() {
|
||||
return source.getLength();
|
||||
}
|
||||
|
||||
public CharSequence getCharacters(int lineNumber) {
|
||||
return source.getCharacters(lineNumber);
|
||||
}
|
||||
|
||||
public int getLineCount() {
|
||||
return source.getLineCount();
|
||||
}
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
package org.enso.interpreter.runtime.data;
|
||||
|
||||
import com.oracle.truffle.api.source.SourceSection;
|
||||
|
||||
/**
|
||||
* Wrapper for exposing source sections in Enso. Delegates to the original methods with no behaviour
|
||||
* changes.
|
||||
*/
|
||||
public class EnsoSourceSection {
|
||||
private final SourceSection sourceSection;
|
||||
|
||||
public EnsoSourceSection(SourceSection sourceSection) {
|
||||
this.sourceSection = sourceSection;
|
||||
}
|
||||
|
||||
public int getStartLine() {
|
||||
return sourceSection.getStartLine();
|
||||
}
|
||||
|
||||
public int getEndLine() {
|
||||
return sourceSection.getEndLine();
|
||||
}
|
||||
|
||||
public int getEndColumn() {
|
||||
return sourceSection.getEndColumn();
|
||||
}
|
||||
|
||||
public int getCharIndex() {
|
||||
return sourceSection.getCharIndex();
|
||||
}
|
||||
|
||||
public int getCharLength() {
|
||||
return sourceSection.getCharLength();
|
||||
}
|
||||
|
||||
public int getCharEndIndex() {
|
||||
return sourceSection.getCharEndIndex();
|
||||
}
|
||||
|
||||
public CharSequence getCharacters() {
|
||||
return sourceSection.getCharacters();
|
||||
}
|
||||
|
||||
public int getStartColumn() {
|
||||
return sourceSection.getStartColumn();
|
||||
}
|
||||
|
||||
public boolean isAvailable() {
|
||||
return sourceSection.isAvailable();
|
||||
}
|
||||
|
||||
public boolean hasLines() {
|
||||
return sourceSection.hasLines();
|
||||
}
|
||||
|
||||
public boolean hasColumns() {
|
||||
return sourceSection.hasColumns();
|
||||
}
|
||||
|
||||
public boolean hasCharIndex() {
|
||||
return sourceSection.hasCharIndex();
|
||||
}
|
||||
|
||||
public EnsoSource getSource() {
|
||||
return new EnsoSource(sourceSection.getSource());
|
||||
}
|
||||
}
|
@ -493,6 +493,28 @@ type Polyglot
|
||||
invoke : Any -> Text -> Vector -> Any
|
||||
invoke target name arguments = @Builtin_Method "Polyglot.invoke"
|
||||
|
||||
## ADVANCED
|
||||
UNSTABLE
|
||||
|
||||
Checks if `value` defines a source location.
|
||||
|
||||
Source locations are typically exposed by functions, classes, sometimes
|
||||
also other objects to specify their allocation sites.
|
||||
has_source_location : Any -> Boolean
|
||||
has_source_location value = @Builtin_Method "Polyglot.has_source_location"
|
||||
|
||||
## ADVANCED
|
||||
UNSTABLE
|
||||
|
||||
Gets the source location of `value`.
|
||||
|
||||
Source locations are typically exposed by functions, classes, sometimes
|
||||
also other objects to specify their allocation sites.
|
||||
This method will throw a polyglot exception if
|
||||
`Polyglot.has_source_location value` returns `False`.
|
||||
get_source_location : Any -> Source_Location
|
||||
get_source_location value = @Builtin_Method "Polyglot.get_source_location"
|
||||
|
||||
## Utilities for working with Java polyglot objects.
|
||||
type Java
|
||||
|
||||
@ -1794,6 +1816,15 @@ type Runtime
|
||||
no_inline_with_arg : Any -> Any
|
||||
no_inline_with_arg function arg = @Builtin_Method "Runtime.no_inline_with_arg"
|
||||
|
||||
## PRIVATE
|
||||
|
||||
Returns a raw representation of the current execution stack trace.
|
||||
You probably want `Runtime.get_stack_trace` instead.
|
||||
primitive_get_stack_trace : Array
|
||||
primitive_get_stack_trace = @Builtin_Method "Runtime.primitive_get_stack_trace"
|
||||
|
||||
|
||||
|
||||
## The runtime's integrated monadic state management.
|
||||
type State
|
||||
|
||||
|
@ -41,6 +41,8 @@ import project.Network.Http.Request_Spec as Http_Request_Spec
|
||||
import project.Network.Http_Spec
|
||||
import project.Network.Uri_Spec
|
||||
|
||||
import project.Runtime.Stack_Traces_Spec
|
||||
|
||||
import project.System.File_Spec
|
||||
import project.System.Process_Spec
|
||||
|
||||
@ -81,6 +83,7 @@ main = Test.Suite.run_main <|
|
||||
Regex_Spec.spec
|
||||
Runtime_Spec.spec
|
||||
Span_Spec.spec
|
||||
Stack_Traces_Spec.spec
|
||||
Text_Spec.spec
|
||||
Time_Spec.spec
|
||||
Uri_Spec.spec
|
||||
|
20
test/Tests/src/Runtime/Stack_Traces_Spec.enso
Normal file
20
test/Tests/src/Runtime/Stack_Traces_Spec.enso
Normal file
@ -0,0 +1,20 @@
|
||||
from Standard.Base import all
|
||||
import Standard.Test
|
||||
|
||||
type My_Type
|
||||
|
||||
bar = Runtime.get_stack_trace
|
||||
baz = here.bar
|
||||
Number.foo = here.baz
|
||||
foo x = x.foo
|
||||
My_Type.foo = here.foo 123
|
||||
|
||||
spec = Test.group "Stack traces" <|
|
||||
Test.specify "should capture traces correctly" <|
|
||||
modname = Meta.Constructor (Meta.meta here . constructor) . name
|
||||
stack = My_Type.foo
|
||||
names = [modname + ".bar", modname + ".baz", "Number.foo", modname + ".foo", "My_Type.foo"]
|
||||
stack.take_start 5 . map .name . should_equal names
|
||||
file = Enso_Project.root / 'src' / 'Runtime' / 'Stack_Traces_Spec.enso'
|
||||
stack.take_start 5 . map (.source_location >> .file) . each (_.should_equal file)
|
||||
|
Loading…
Reference in New Issue
Block a user