Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix the Array Visualisation #1588

Merged
merged 5 commits into from
Mar 17, 2021
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions distribution/std-lib/Standard/src/Base.enso
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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

13 changes: 13 additions & 0 deletions distribution/std-lib/Standard/src/Base/Data/Json.enso
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
7 changes: 7 additions & 0 deletions distribution/std-lib/Standard/src/Base/Data/Vector.enso
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 7 additions & 0 deletions distribution/std-lib/Standard/src/Base/Meta.enso
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 1 addition & 1 deletion distribution/std-lib/Standard/src/Base/System/File.enso
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 2 additions & 2 deletions distribution/std-lib/Standard/src/Test.enso
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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";
}
}
17 changes: 14 additions & 3 deletions engine/polyglot-api/src/main/scala/org/enso/polyglot/Module.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand All @@ -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
*/
Expand Down
19 changes: 13 additions & 6 deletions engine/runner/src/main/scala/org/enso/runner/Main.scala
Original file line number Diff line number Diff line change
@@ -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, _}
Expand All @@ -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

Expand Down Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
@@ -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));
}
}
Original file line number Diff line number Diff line change
@@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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));
}
}
14 changes: 11 additions & 3 deletions engine/runtime/src/main/resources/Builtins.enso
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down
10 changes: 6 additions & 4 deletions engine/runtime/src/main/scala/org/enso/compiler/core/IR.scala
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
}
}
Loading