From 29328190afcde05f0a9c782010752177a31b9d30 Mon Sep 17 00:00:00 2001 From: Ara Adkins Date: Wed, 17 Mar 2021 16:34:53 +0000 Subject: [PATCH] Fix the array visualisation and misc crashes (#1588) --- distribution/std-lib/Standard/src/Base.enso | 2 + .../src/Base/Data/Array/Extensions.enso | 8 ++++ .../std-lib/Standard/src/Base/Data/Json.enso | 13 +++++++ .../Standard/src/Base/Data/Vector.enso | 7 ++++ .../std-lib/Standard/src/Base/Meta.enso | 7 ++++ .../Standard/src/Base/System/File.enso | 2 +- distribution/std-lib/Standard/src/Test.enso | 4 +- .../java/org/enso/polyglot/MethodNames.java | 11 +++--- .../main/scala/org/enso/polyglot/Module.scala | 17 +++++++-- .../scala/org/enso/polyglot/ApiTest.scala | 4 +- .../enso/polyglot/ModuleManagementTest.scala | 18 ++++----- .../src/main/scala/org/enso/runner/Main.scala | 19 +++++++--- .../builtin/meta/DisplayTypeNode.java | 16 ++++++++ .../builtin/meta/GetPolyglotLanguageNode.java | 1 - .../text/util/TypeToDisplayTextNode.java | 9 +++++ .../org/enso/interpreter/runtime/Module.java | 6 ++- .../interpreter/runtime/builtin/Meta.java | 4 +- .../runtime/src/main/resources/Builtins.enso | 14 +++++-- .../scala/org/enso/compiler/core/IR.scala | 10 +++-- .../compiler/pass/desugar/ComplexType.scala | 1 + .../test/pass/desugar/ComplexTypeTest.scala | 38 +++++++++++++++++++ .../interpreter/test/InterpreterTest.scala | 2 +- .../enso/interpreter/test/PackageTest.scala | 2 +- .../test/semantic/CodeLocationsTest.scala | 2 +- test/Tests/src/Data/Array_Spec.enso | 12 ++++++ test/Tests/src/Data/Vector_Spec.enso | 7 ++++ test/Tests/src/Main.enso | 2 + 27 files changed, 197 insertions(+), 41 deletions(-) create mode 100644 distribution/std-lib/Standard/src/Base/Data/Array/Extensions.enso create mode 100644 engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/DisplayTypeNode.java create mode 100644 test/Tests/src/Data/Array_Spec.enso diff --git a/distribution/std-lib/Standard/src/Base.enso b/distribution/std-lib/Standard/src/Base.enso index 79ebf709ba09..fd8422a0f7ca 100644 --- a/distribution/std-lib/Standard/src/Base.enso +++ b/distribution/std-lib/Standard/src/Base.enso @@ -1,4 +1,5 @@ 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 @@ -34,6 +35,7 @@ export Standard.Base.Meta export Standard.Base.System.File 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 diff --git a/distribution/std-lib/Standard/src/Base/Data/Array/Extensions.enso b/distribution/std-lib/Standard/src/Base/Data/Array/Extensions.enso new file mode 100644 index 000000000000..e6ddc39cf7e4 --- /dev/null +++ b/distribution/std-lib/Standard/src/Base/Data/Array/Extensions.enso @@ -0,0 +1,8 @@ +from Standard.Base import all + +## Transform the array into text for displaying as part of its default + visualization. +Array.to_default_visualization_data : Text +Array.to_default_visualization_data = + Vector.Vector this . to_default_visualization_data + diff --git a/distribution/std-lib/Standard/src/Base/Data/Json.enso b/distribution/std-lib/Standard/src/Base/Data/Json.enso index 93c8db40cf92..9fd40a067f3b 100644 --- a/distribution/std-lib/Standard/src/Base/Data/Json.enso +++ b/distribution/std-lib/Standard/src/Base/Data/Json.enso @@ -81,6 +81,10 @@ type Json Check the `message` field for detailed information on the specific failure. type Parse_Error message +## Converts the error to a display representation. +Parse_Error.to_display_text : Text +Parse_Error.to_display_text = "Parse error in parsing JSON: " + this.message.to_text + "." + ## Gets the value associated with the given key in this object. Returns `Nothing` if the associated key is not defined. Object.get : Text -> Json | Nothing @@ -110,6 +114,15 @@ type Marshalling_Error when the JSON does not contain all the fields required by the atom. type Missing_Field_Error json field format + to_display_text : Text + to_display_text = case this of + Type_Mismatch_Error json format -> + json_text = Meta.type_to_display_text json + format_text = Meta.type_to_display_text format + "Type mismatch error: the json with type `" + json_text + "` did not match the format `" + format_text + "`." + Missing_Field_Error _ field _ -> + "Missing field in Json: the field `" + field.to_text "` was missing in the json." + ## Generically converts an atom into a JSON object. The input atom is converted into a JSON object, with a `"type"` field set to diff --git a/distribution/std-lib/Standard/src/Base/Data/Vector.enso b/distribution/std-lib/Standard/src/Base/Data/Vector.enso index 3090de358a18..aba98b382284 100644 --- a/distribution/std-lib/Standard/src/Base/Data/Vector.enso +++ b/distribution/std-lib/Standard/src/Base/Data/Vector.enso @@ -523,6 +523,13 @@ type Vector Vector new_vec_arr + ## Transform the vector into text for displaying as part of its default + visualization. + to_default_visualization_data : Text + to_default_visualization_data = + json = this.take_start 100 . to_json + json.to_text + ## A builder type for Enso vectors. A vector builder is a mutable data structure, that allows to gather a diff --git a/distribution/std-lib/Standard/src/Base/Meta.enso b/distribution/std-lib/Standard/src/Base/Meta.enso index 9c571a07e5ae..36341e442b5c 100644 --- a/distribution/std-lib/Standard/src/Base/Meta.enso +++ b/distribution/std-lib/Standard/src/Base/Meta.enso @@ -147,3 +147,10 @@ is_same_object value_1 value_2 = Builtins.Meta.is_same_object value_1 value_2 get_source_location : Integer -> Text get_source_location skip_frames = Builtins.Meta.get_source_location skip_frames+1 + +## Displays the type of the provided value as text. + + Arguments: + - value: The value for which to display the type. +type_to_display_text : Any -> Text +type_to_display_text value = Builtins.Meta.type_to_display_text value diff --git a/distribution/std-lib/Standard/src/Base/System/File.enso b/distribution/std-lib/Standard/src/Base/System/File.enso index dc3318b24111..2ff2f387e018 100644 --- a/distribution/std-lib/Standard/src/Base/System/File.enso +++ b/distribution/std-lib/Standard/src/Base/System/File.enso @@ -300,7 +300,7 @@ new path = File (Prim_Io.get_file path) > Example Read the `data.csv` file in the project directory. - File.open (Enso_Project.data / "data.csv") + File.read (Enso_Project.data / "data.csv") read : Text -> Text read path = (here.new path).read diff --git a/distribution/std-lib/Standard/src/Test.enso b/distribution/std-lib/Standard/src/Test.enso index bc21cc6475be..dcd4422d704f 100644 --- a/distribution/std-lib/Standard/src/Test.enso +++ b/distribution/std-lib/Standard/src/Test.enso @@ -179,8 +179,8 @@ run_spec ~behavior = case ex of Failure _ -> ex Finished_With_Error err stack_trace_text -> - Failure ("An unexpected error was returned: " + err.to_text + '\n' + stack_trace_text) - _ -> Failure ("An unexpected panic was thrown: " + ex.to_text + '\n' + maybeExc.get_stack_trace_text) + Failure ("An unexpected error was returned: " + err.to_display_text + '\n' + stack_trace_text) + _ -> Failure ("An unexpected panic was thrown: " + ex.to_display_text + '\n' + maybeExc.get_stack_trace_text) result ## Creates a new test group, desribing properties of the object diff --git a/engine/polyglot-api/src/main/java/org/enso/polyglot/MethodNames.java b/engine/polyglot-api/src/main/java/org/enso/polyglot/MethodNames.java index d7224374e1e4..d6dacf73391e 100644 --- a/engine/polyglot-api/src/main/java/org/enso/polyglot/MethodNames.java +++ b/engine/polyglot-api/src/main/java/org/enso/polyglot/MethodNames.java @@ -3,26 +3,27 @@ /** Container for polyglot method names */ public class MethodNames { public static class TopScope { - public static final String GET_MODULE = "get_module"; public static final String CREATE_MODULE = "create_module"; + public static final String GET_MODULE = "get_module"; + public static final String LEAK_CONTEXT = "leak_context"; public static final String REGISTER_MODULE = "register_module"; public static final String UNREGISTER_MODULE = "unregister_module"; - public static final String LEAK_CONTEXT = "leak_context"; } public static class Module { + public static final String EVAL_EXPRESSION = "eval_expression"; public static final String GET_ASSOCIATED_CONSTRUCTOR = "get_associated_constructor"; - public static final String GET_METHOD = "get_method"; public static final String GET_CONSTRUCTOR = "get_constructor"; + public static final String GET_METHOD = "get_method"; + public static final String GET_NAME = "get_name"; public static final String REPARSE = "reparse"; public static final String SET_SOURCE = "set_source"; public static final String SET_SOURCE_FILE = "set_source_file"; - public static final String EVAL_EXPRESSION = "eval_expression"; } public static class Function { public static final String EQUALS = "equals"; - public static final String GET_SOURCE_START = "get_source_start"; public static final String GET_SOURCE_LENGTH = "get_source_length"; + public static final String GET_SOURCE_START = "get_source_start"; } } diff --git a/engine/polyglot-api/src/main/scala/org/enso/polyglot/Module.scala b/engine/polyglot-api/src/main/scala/org/enso/polyglot/Module.scala index 37a08edfb0ac..b65be560b2a1 100644 --- a/engine/polyglot-api/src/main/scala/org/enso/polyglot/Module.scala +++ b/engine/polyglot-api/src/main/scala/org/enso/polyglot/Module.scala @@ -9,12 +9,17 @@ import org.graalvm.polyglot.Value class Module(private val value: Value) { import MethodNames.Module._ + /** @return the name of the module + */ + def getName: String = value.invokeMember(GET_NAME).asString() + /** @return the associated type of this module */ def getAssociatedConstructor: Value = value.invokeMember(GET_ASSOCIATED_CONSTRUCTOR) - /** Gets a constructor definition by name + /** Gets a constructor definition by name. + * * @param name the constructor name * @return the polyglot representation of the constructor. */ @@ -27,11 +32,17 @@ class Module(private val value: Value) { * @param name the name of the method * @return the runtime representation of the method */ - def getMethod(constructor: Value, name: String): Function = - new Function(value.invokeMember(GET_METHOD, constructor, name)) + def getMethod(constructor: Value, name: String): Option[Function] = { + val newVal = value.invokeMember(GET_METHOD, constructor, name); + if (newVal.isNull) { None } + else { + Some(new Function(newVal)) + } + } /** Evaluates an arbitrary expression as if it were placed in a function * body inside this module. + * * @param code the expression to evaluate * @return the return value of the expression */ diff --git a/engine/polyglot-api/src/test/scala/org/enso/polyglot/ApiTest.scala b/engine/polyglot-api/src/test/scala/org/enso/polyglot/ApiTest.scala index 22cbd0f12e47..308faa3d9e32 100644 --- a/engine/polyglot-api/src/test/scala/org/enso/polyglot/ApiTest.scala +++ b/engine/polyglot-api/src/test/scala/org/enso/polyglot/ApiTest.scala @@ -16,7 +16,7 @@ class ApiTest extends AnyFlatSpec with Matchers { |""".stripMargin val module = executionContext.evalModule(code, "Test") val associatedConstructor = module.getAssociatedConstructor - val barFunction = module.getMethod(associatedConstructor, "bar") + val barFunction = module.getMethod(associatedConstructor, "bar").get val result = barFunction.execute( associatedConstructor.newInstance(), 10L.asInstanceOf[AnyRef] @@ -39,7 +39,7 @@ class ApiTest extends AnyFlatSpec with Matchers { |""".stripMargin val module = executionContext.evalModule(code, "Test") val vectorCons = module.getConstructor("Vector") - val squareNorm = module.getMethod(vectorCons, "squareNorm") + val squareNorm = module.getMethod(vectorCons, "squareNorm").get val testVector = vectorCons.newInstance( 1L.asInstanceOf[AnyRef], 2L.asInstanceOf[AnyRef], diff --git a/engine/polyglot-api/src/test/scala/org/enso/polyglot/ModuleManagementTest.scala b/engine/polyglot-api/src/test/scala/org/enso/polyglot/ModuleManagementTest.scala index a0e82388e8a1..f3a05e9f4e8e 100644 --- a/engine/polyglot-api/src/test/scala/org/enso/polyglot/ModuleManagementTest.scala +++ b/engine/polyglot-api/src/test/scala/org/enso/polyglot/ModuleManagementTest.scala @@ -44,7 +44,7 @@ class ModuleManagementTest extends AnyFlatSpec with Matchers { val mainModule = ctx.executionContext.getTopScope.getModule("Test.Main") val assocCons = mainModule.getAssociatedConstructor - val mainFun1 = mainModule.getMethod(assocCons, "main") + val mainFun1 = mainModule.getMethod(assocCons, "main").get mainFun1.execute(assocCons).asLong() shouldEqual 12345L @@ -53,7 +53,7 @@ class ModuleManagementTest extends AnyFlatSpec with Matchers { |""".stripMargin) mainModule.reparse() - val mainFun2 = mainModule.getMethod(assocCons, "main") + val mainFun2 = mainModule.getMethod(assocCons, "main").get mainFun2.execute(assocCons).asLong() shouldEqual 4567L } @@ -66,20 +66,20 @@ class ModuleManagementTest extends AnyFlatSpec with Matchers { val mainModule = ctx.executionContext.getTopScope.getModule("Test.Main") val assocCons = mainModule.getAssociatedConstructor - val mainFun1 = mainModule.getMethod(assocCons, "main") + val mainFun1 = mainModule.getMethod(assocCons, "main").get mainFun1.execute(assocCons).asLong() shouldEqual 123L mainModule.setSource(""" |main = 456 |""".stripMargin) - val mainFun2 = mainModule.getMethod(assocCons, "main") + val mainFun2 = mainModule.getMethod(assocCons, "main").get mainFun2.execute(assocCons).asLong() shouldEqual 456L mainModule.setSource(""" |main = 789 |""".stripMargin) - val mainFun3 = mainModule.getMethod(assocCons, "main") + val mainFun3 = mainModule.getMethod(assocCons, "main").get mainFun3.execute(assocCons).asLong() shouldEqual 789L ctx.writeMain(""" @@ -87,7 +87,7 @@ class ModuleManagementTest extends AnyFlatSpec with Matchers { |""".stripMargin) mainModule.setSourceFile(ctx.pkg.mainFile.getAbsolutePath) - val mainFun4 = mainModule.getMethod(assocCons, "main") + val mainFun4 = mainModule.getMethod(assocCons, "main").get mainFun4.execute(assocCons).asLong() shouldEqual 987L } @@ -111,7 +111,7 @@ class ModuleManagementTest extends AnyFlatSpec with Matchers { val mainModule = topScope.getModule("Test.Main") val assocCons = mainModule.getAssociatedConstructor - val mainFun = mainModule.getMethod(assocCons, "main") + val mainFun = mainModule.getMethod(assocCons, "main").get mainFun.execute(assocCons).asLong shouldEqual 11L } @@ -141,7 +141,7 @@ class ModuleManagementTest extends AnyFlatSpec with Matchers { val mainModule = topScope.getModule("Test.Main") val assocCons = mainModule.getAssociatedConstructor - val mainFun = mainModule.getMethod(assocCons, "main") + val mainFun = mainModule.getMethod(assocCons, "main").get mainFun.execute(assocCons).asLong shouldEqual 21L } @@ -161,7 +161,7 @@ class ModuleManagementTest extends AnyFlatSpec with Matchers { "X" ) val mod1AssocCons = mod1.getAssociatedConstructor - val mod1Main = mod1.getMethod(mod1AssocCons, "bar") + val mod1Main = mod1.getMethod(mod1AssocCons, "bar").get mod1Main.execute(mod1AssocCons).asLong shouldEqual 124 ctx.executionContext.getTopScope.unregisterModule("Test.Main") diff --git a/engine/runner/src/main/scala/org/enso/runner/Main.scala b/engine/runner/src/main/scala/org/enso/runner/Main.scala index d918a754a235..7c7c8de26a5b 100644 --- a/engine/runner/src/main/scala/org/enso/runner/Main.scala +++ b/engine/runner/src/main/scala/org/enso/runner/Main.scala @@ -1,8 +1,5 @@ package org.enso.runner -import java.io.File -import java.util.UUID - import akka.http.scaladsl.model.{IllegalUriException, Uri} import cats.implicits._ import org.apache.commons.cli.{Option => CliOption, _} @@ -12,8 +9,11 @@ import org.enso.loggingservice.LogLevel import org.enso.pkg.{Contact, PackageManager, SemVerEnsoVersion} import org.enso.polyglot.{LanguageInfo, Module, PolyglotContext} import org.enso.version.VersionDescription -import org.graalvm.polyglot.{PolyglotException, Value} +import org.graalvm.polyglot.PolyglotException +import java.io.File +import java.util.UUID +import scala.Console.err import scala.jdk.CollectionConverters._ import scala.util.Try @@ -382,11 +382,18 @@ object Main { mainModule: Module, rootPkgPath: Option[File], mainMethodName: String = "main" - ): Value = { + ): Unit = { val mainCons = mainModule.getAssociatedConstructor val mainFun = mainModule.getMethod(mainCons, mainMethodName) try { - mainFun.execute(mainCons.newInstance()) + mainFun match { + case Some(main) => main.execute(mainCons.newInstance()) + case None => + err.println( + s"The module ${mainModule.getName} does not contain a `main` " + + s"function. It could not be run." + ) + } } catch { case e: PolyglotException => printPolyglotException(e, rootPkgPath) diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/DisplayTypeNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/DisplayTypeNode.java new file mode 100644 index 000000000000..295bbf9b66b3 --- /dev/null +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/DisplayTypeNode.java @@ -0,0 +1,16 @@ +package org.enso.interpreter.node.expression.builtin.meta; + +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +import com.oracle.truffle.api.nodes.Node; +import org.enso.interpreter.dsl.BuiltinMethod; +import org.enso.interpreter.node.expression.builtin.text.util.TypeToDisplayTextNode; +import org.enso.interpreter.runtime.data.text.Text; + +@BuiltinMethod(type = "Meta", name = "type_to_display_text", description = "Pretty prints a type.") +public class DisplayTypeNode extends Node { + @Child @CompilationFinal TypeToDisplayTextNode displayTypeNode = TypeToDisplayTextNode.build(); + + Text execute(Object _this, Object value) { + return Text.create(displayTypeNode.execute(value)); + } +} diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/GetPolyglotLanguageNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/GetPolyglotLanguageNode.java index 74a07566e3b4..e150c0f11589 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/GetPolyglotLanguageNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/GetPolyglotLanguageNode.java @@ -1,6 +1,5 @@ package org.enso.interpreter.node.expression.builtin.meta; -import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.CachedContext; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.nodes.Node; diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/text/util/TypeToDisplayTextNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/text/util/TypeToDisplayTextNode.java index 1d18eb2b8203..3fa7fb269dc0 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/text/util/TypeToDisplayTextNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/text/util/TypeToDisplayTextNode.java @@ -13,6 +13,15 @@ public abstract class TypeToDisplayTextNode extends Node { public abstract String execute(Object o); + /** + * Create a node that can display types as text. + * + * @return a new type display node + */ + public static TypeToDisplayTextNode build() { + return TypeToDisplayTextNodeGen.create(); + } + @Specialization @CompilerDirectives.TruffleBoundary String doDisplay( diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/Module.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/Module.java index a07115e3ce86..e2702e58f70b 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/Module.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/Module.java @@ -15,6 +15,7 @@ import java.io.File; import java.io.IOException; +import java.util.Map; import org.enso.compiler.core.IR; import org.enso.compiler.phase.StubIrBuilder; import org.enso.interpreter.Language; @@ -404,8 +405,11 @@ static Object doInvoke( throws UnknownIdentifierException, ArityException, UnsupportedTypeException { ModuleScope scope = module.compileScope(context); switch (member) { + case MethodNames.Module.GET_NAME: + return module.getName().toString(); case MethodNames.Module.GET_METHOD: - return getMethod(scope, arguments); + Function result = getMethod(scope, arguments); + return result == null ? context.getBuiltins().nothing().newInstance() : result; case MethodNames.Module.GET_CONSTRUCTOR: return getConstructor(scope, arguments); case MethodNames.Module.REPARSE: diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/Meta.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/Meta.java index dbc39a3b4909..ebdd280f9db4 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/Meta.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/builtin/Meta.java @@ -18,6 +18,7 @@ public Meta(Language language, ModuleScope scope) { AtomConstructor meta = new AtomConstructor("Meta", scope).initializeFields(); scope.registerConstructor(meta); + scope.registerMethod(meta, "type_to_display_text", DisplayTypeMethodGen.makeFunction(language)); scope.registerMethod( meta, "is_unresolved_symbol", IsUnresolvedSymbolMethodGen.makeFunction(language)); scope.registerMethod( @@ -50,6 +51,7 @@ public Meta(Language language, ModuleScope scope) { meta, "get_polyglot_language", GetPolyglotLanguageMethodGen.makeFunction(language)); scope.registerMethod(meta, "is_same_object", IsSameObjectMethodGen.makeFunction(language)); - scope.registerMethod(meta, "get_source_location", GetSourceLocationMethodGen.makeFunction(language)); + scope.registerMethod( + meta, "get_source_location", GetSourceLocationMethodGen.makeFunction(language)); } } diff --git a/engine/runtime/src/main/resources/Builtins.enso b/engine/runtime/src/main/resources/Builtins.enso index 3046eb48b3b1..14a1024f21da 100644 --- a/engine/runtime/src/main/resources/Builtins.enso +++ b/engine/runtime/src/main/resources/Builtins.enso @@ -224,7 +224,7 @@ type Error catch_primitive : (Error -> Any) -> Any catch_primitive handler = @Builtin_Method "Any.catch" - ## PRIVATE + ## PRIVATE UNSTABLE Returns a textual representation of the stack trace attached to an error. @@ -728,8 +728,16 @@ type Meta Arguments: - frames_to_skip: how many frames on the stack to skip. Called with 0 will return exact location of the call. - get_source_location : Integer -> Text - get_source_location frames_to_skip = @Builtin_Method "Meta.get_source_location" + get_source_location : Integer -> Text + get_source_location frames_to_skip = @Builtin_Method "Meta.get_source_location" + + ## Pretty-prints the type of the provided value using the interpreter's + internal logic for printing types. + + Arguments: + - value: The value whose type should be printed. + type_to_display_text : Any -> Text + type_to_display_text value = @Builtin_Method "Meta.display_type" ## Utilities for working with primitive arrays. type Array diff --git a/engine/runtime/src/main/scala/org/enso/compiler/core/IR.scala b/engine/runtime/src/main/scala/org/enso/compiler/core/IR.scala index eda8714376b5..049100ad1aeb 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/core/IR.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/core/IR.scala @@ -1,16 +1,15 @@ package org.enso.compiler.core -import java.util.UUID - import org.enso.compiler.core.IR.{Expression, IdentifiedLocation} -import org.enso.compiler.core.ir.{DiagnosticStorage, MetadataStorage} import org.enso.compiler.core.ir.MetadataStorage.MetadataPair +import org.enso.compiler.core.ir.{DiagnosticStorage, MetadataStorage} import org.enso.compiler.data.BindingsMap import org.enso.compiler.exception.CompilerError import org.enso.compiler.pass.IRPass import org.enso.interpreter.epb.EpbParser import org.enso.syntax.text.{AST, Debug, Location} +import java.util.UUID import scala.annotation.unused /** [[IR]] is a temporary and fairly unsophisticated internal representation @@ -5337,7 +5336,10 @@ object IR { // === Errors =============================================================== /** A trait for all errors in Enso's IR. */ - sealed trait Error extends Expression with Diagnostic { + sealed trait Error + extends Expression + with IR.Module.Scope.Definition + with Diagnostic { override def mapExpressions(fn: Expression => Expression): Error override def setLocation(location: Option[IdentifiedLocation]): Error override def duplicate( diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/desugar/ComplexType.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/desugar/ComplexType.scala index 5b6c600cc94a..e2e157543cf1 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/desugar/ComplexType.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/pass/desugar/ComplexType.scala @@ -169,6 +169,7 @@ case object ComplexType extends IRPass { matchSignaturesAndGenerate(name, binding) case funSugar @ IR.Function.Binding(name, _, _, _, _, _, _) => matchSignaturesAndGenerate(name, funSugar) + case err: IR.Error => Seq(err) case _ => throw new CompilerError("Unexpected IR node in complex type body.") } diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/desugar/ComplexTypeTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/desugar/ComplexTypeTest.scala index 659a23f3f241..1caced035b5f 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/desugar/ComplexTypeTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/desugar/ComplexTypeTest.scala @@ -209,4 +209,42 @@ class ComplexTypeTest extends CompilerTest { .name shouldEqual "bad_trailing_sig" } } + + "Invalid complex types" should { + implicit val ctx: ModuleContext = mkModuleContext + + val ir = + """ + |type Foo + | Bar + | type Baz + | + | g a = this + a + | + | f a = + |""".stripMargin.preprocessModule.desugar + + "have their types translated untouched" in { + ir.bindings.head shouldBe a[Definition.Atom] + val atom = ir.bindings.head.asInstanceOf[Definition.Atom] + atom.name.name shouldEqual "Baz" + } + + "have their errors translated untouched" in { + ir.bindings.last shouldBe an[IR.Error.Syntax] + val err = ir.bindings.last.asInstanceOf[IR.Error.Syntax] + err.reason shouldBe an[IR.Error.Syntax.UnexpectedDeclarationInType.type] + } + + "have their valid methods desugared" in { + ir.bindings(1) shouldBe a[Definition.Method.Binding] + ir.bindings(2) shouldBe a[Definition.Method.Binding] + val methodOnBar = ir.bindings(1).asInstanceOf[Definition.Method.Binding] + val methodOnBaz = ir.bindings(2).asInstanceOf[Definition.Method.Binding] + methodOnBar.typeName.name shouldEqual "Bar" + methodOnBar.methodName.name shouldEqual "g" + methodOnBaz.typeName.name shouldEqual "Baz" + methodOnBaz.methodName.name shouldEqual "g" + } + } } diff --git a/engine/runtime/src/test/scala/org/enso/interpreter/test/InterpreterTest.scala b/engine/runtime/src/test/scala/org/enso/interpreter/test/InterpreterTest.scala index 1a0f7ac23e74..3b916cb7aaa2 100644 --- a/engine/runtime/src/test/scala/org/enso/interpreter/test/InterpreterTest.scala +++ b/engine/runtime/src/test/scala/org/enso/interpreter/test/InterpreterTest.scala @@ -159,7 +159,7 @@ trait InterpreterRunner { interpreterContext.executionContext.evalModule(code, "Test") ) val assocCons = module.getAssociatedConstructor - val mainFunction = module.getMethod(assocCons, "main") + val mainFunction = module.getMethod(assocCons, "main").get MainMethod(assocCons, mainFunction) } diff --git a/engine/runtime/src/test/scala/org/enso/interpreter/test/PackageTest.scala b/engine/runtime/src/test/scala/org/enso/interpreter/test/PackageTest.scala index b8ce1814fe29..028703c453e2 100644 --- a/engine/runtime/src/test/scala/org/enso/interpreter/test/PackageTest.scala +++ b/engine/runtime/src/test/scala/org/enso/interpreter/test/PackageTest.scala @@ -32,7 +32,7 @@ trait PackageTest extends AnyFlatSpec with Matchers with ValueEquality { val topScope = executionContext.getTopScope val mainModuleScope = topScope.getModule(mainModule.toString) val assocCons = mainModuleScope.getAssociatedConstructor - val mainFun = mainModuleScope.getMethod(assocCons, "main") + val mainFun = mainModuleScope.getMethod(assocCons, "main").get mainFun.execute(assocCons) } } diff --git a/engine/runtime/src/test/scala/org/enso/interpreter/test/semantic/CodeLocationsTest.scala b/engine/runtime/src/test/scala/org/enso/interpreter/test/semantic/CodeLocationsTest.scala index c3b853d4b060..1de4cf96ca28 100644 --- a/engine/runtime/src/test/scala/org/enso/interpreter/test/semantic/CodeLocationsTest.scala +++ b/engine/runtime/src/test/scala/org/enso/interpreter/test/semantic/CodeLocationsTest.scala @@ -216,7 +216,7 @@ class CodeLocationsTest extends InterpreterTest { val mod = interpreterContext.executionContext.evalModule(code, "Test") val tpe = mod.getAssociatedConstructor - val method = mod.getMethod(tpe, "foo") + val method = mod.getMethod(tpe, "foo").get method.value.invokeMember( MethodNames.Function.GET_SOURCE_START ) shouldEqual 1 diff --git a/test/Tests/src/Data/Array_Spec.enso b/test/Tests/src/Data/Array_Spec.enso new file mode 100644 index 000000000000..5c468d368487 --- /dev/null +++ b/test/Tests/src/Data/Array_Spec.enso @@ -0,0 +1,12 @@ +from Standard.Base import all + +import Standard.Test + +spec = Test.group "Arrays" <| + Test.specify "should be able to be converted to a visualization rep" <| + arr = Vector.fill 1000 0 . to_array + text = arr.to_default_visualization_data + json = Json.parse text + as_vec = json.into (Vector.Vector Number) + as_vec.should_equal <| Vector.fill 100 0 + diff --git a/test/Tests/src/Data/Vector_Spec.enso b/test/Tests/src/Data/Vector_Spec.enso index 95d663282628..d5c25fa0829c 100644 --- a/test/Tests/src/Data/Vector_Spec.enso +++ b/test/Tests/src/Data/Vector_Spec.enso @@ -169,3 +169,10 @@ spec = Test.group "Vectors" <| fail a = Error.throw <| My_Error a [fail 1].map (x -> x.catch (x -> x.a)) . should_equal [1] [1].map fail . map .catch . should_equal [My_Error 1] + Test.specify "should be able to be efficiently converted to a visualisation" <| + vec = Vector.fill 1000 0 + text = vec.to_default_visualization_data + json = Json.parse text + as_vec = json.into (Vector.Vector Number) + as_vec.should_equal <| Vector.fill 100 0 + diff --git a/test/Tests/src/Main.enso b/test/Tests/src/Main.enso index 46661cfee48f..20da743e9711 100644 --- a/test/Tests/src/Main.enso +++ b/test/Tests/src/Main.enso @@ -15,6 +15,7 @@ import Tests.Semantic.Js_Interop_Spec import Tests.Semantic.Python_Interop_Spec import Tests.Semantic.R_Interop_Spec +import Tests.Data.Array_Spec import Tests.Data.Interval_Spec import Tests.Data.Json_Spec import Tests.Data.List_Spec @@ -40,6 +41,7 @@ import Tests.System.Process_Spec main = Test.Suite.runMain <| Any_Spec.spec + Array_Spec.spec Case_Spec.spec Deep_Export_Spec.spec Error_Spec.spec