Skip to content

Commit

Permalink
Deprecate Error's to_display_text builtin methods (#6275)
Browse files Browse the repository at this point in the history
The primary motivation for this change was
#6248, which requested the possibility of defining `to_display_text` methods of common errors via regular method definitions. Until now one could only define them via builtins.

To be able to support that, polyglot invocation had to report `to_display_text` in the list of (invokable) members, which it didn't. Until now, it only considered fields of constructors and builtin methods. That is now fixed as indicated by the change in `Atom`.

Closes #6248.

# Important Notes
Once most of builtins have been translated to regular Enso code, it became apparent how the usage of `.` at the end of the message is not consistent and inflexible. The pure message should never follow with a dot or it makes it impossible to pretty print consistently for the purpose of error reporting. Otherwise we regularly end up with errors ending with `..` or worse. So I went medieval on the reasons for failures and removed all the dots.
The overall result is mostly the same except now we are much more consistent.

Finally, there was a bit of a good reason for using builtins as it simplified our testing.
Take for example `No_Such_Method.Error`. If we do not import `Errors.Common` module we only rely on builtin error types. The type obviously has the constructor but it **does not have** `to_display_text` in scope; the latter is no longer a builtin method but a regular method. This is not really a problem for users who will always import stdlib but our tests often don't. Hence the number of changes and sometimes lack of human-readable errors there.
  • Loading branch information
hubertp authored Apr 14, 2023
1 parent 4dcf5fa commit e163353
Show file tree
Hide file tree
Showing 44 changed files with 1,073 additions and 663 deletions.
92 changes: 90 additions & 2 deletions distribution/lib/Standard/Base/0.0.0-dev/src/Errors/Common.enso
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ type Syntax_Error
- message: A description of the erroneous syntax.
Error message

## PRIVATE
Convert the Syntax_Error error to a human-readable format.
to_display_text : Text
to_display_text self = "Syntax error: "+self.message+"."

@Builtin_Type
type Type_Error
## PRIVATE
Expand All @@ -49,6 +54,17 @@ type Type_Error
- name: The name of the argument whose type is mismatched.
Error expected actual name

## PRIVATE
Infer the type of the actual value in a human-readable format.
type_of_actual self =
tpe = Meta.type_of self.actual
if tpe.is_error then self.actual.to_display_text else tpe.to_display_text

## PRIVATE
Convert the Type_Error error to a human-readable format.
to_display_text : Text
to_display_text self = "Type error: expected `"+self.name+"` to be "+self.expected.to_display_text+", but got "+self.type_of_actual+"."

@Builtin_Type
type Compile_Error
## PRIVATE
Expand All @@ -58,6 +74,11 @@ type Compile_Error
- message: A description of the erroneous state.
Error message

## PRIVATE
Convert the Compile_Error error to a human-readable format.
to_display_text : Text
to_display_text self = "Compile error: "+self.message+"."

@Builtin_Type
type Inexhaustive_Pattern_Match
## PRIVATE
Expand All @@ -67,6 +88,11 @@ type Inexhaustive_Pattern_Match
- scrutinee: The scrutinee that failed to match.
Error scrutinee

## PRIVATE
Convert the Inexhaustive_Pattern_Match error to a human-readable format.
to_display_text : Text
to_display_text self = "Inexhaustive pattern match: no branch matches "+self.scrutinee.to_display_text+"."

@Builtin_Type
type Arity_Error
## PRIVATE
Expand All @@ -79,6 +105,16 @@ type Arity_Error
- actual: the actual number of arguments passed.
Error expected_min expected_max actual

## PRIVATE
Convert the Arity_Error error to a human-readable format.
to_display_text : Text
to_display_text self =
expected = self.expected_min.to_text
expectedRange = if (self.expected_min == self.expected_max) then expected else
if (self.expected_max == -1) then expected+"-" else expected+self.expected_max.to_text

"Wrong number of arguments. Expected "+expectedRange+", but got "+self.actual.to_text+"."

@Builtin_Type
type Uninitialized_State
## PRIVATE
Expand All @@ -89,6 +125,11 @@ type Uninitialized_State
- key: The key for the state slot that was not initialized.
Error key

## PRIVATE
Convert the Uninitialized_State error to a human-readable format.
to_display_text : Text
to_display_text self = "State is not initialized for type "+self.key.to_display_text+"."

@Builtin_Type
type No_Such_Method
## PRIVATE
Expand Down Expand Up @@ -117,6 +158,11 @@ type No_Such_Method
method_name self =
Meta.meta self.symbol . name

## PRIVATE
Convert the No_Such_Method error to a human-readable format.
to_display_text : Text
to_display_text self = "Method `"+self.method_name+"` of "+self.target.to_display_text+" could not be found."

@Builtin_Type
type No_Such_Field
## PRIVATE
Expand All @@ -128,10 +174,17 @@ type No_Such_Field
- field_name: The name of the field that was being accessed.
Error value field_name

## An error that occurs when the enso_project function is called in a file
that is not part of a project.

@Builtin_Type
type Module_Not_In_Package_Error
## An error that occurs when the enso_project function is called in a file
that is not part of a project.
Error

## PRIVATE
Convert the Module_Not_In_Package_Error error to a human-readable format.
to_display_text : Text
to_display_text self = "Module is not a part of a package."

@Builtin_Type
type Arithmetic_Error
Expand All @@ -142,6 +195,11 @@ type Arithmetic_Error
- message: A description of the error condition.
Error message

## PRIVATE
Convert the Arithmetic_Error error to a human-readable format.
to_display_text : Text
to_display_text self = "Arithmetic error: "+self.message+"."

@Builtin_Type
type Incomparable_Values
## An error that indicates that the two values are not comparable.
Expand Down Expand Up @@ -181,6 +239,11 @@ type Invalid_Array_Index
- index: The index that was out of bounds.
Error array index

## PRIVATE
Convert the Forbidden_Operation error to a human-readable format.
to_display_text : Text
to_display_text self = "Invalid array index: "+self.index.to_text+"."

@Builtin_Type
type Not_Invokable
## PRIVATE
Expand All @@ -191,6 +254,11 @@ type Not_Invokable
- target: The called object.
Error target

## PRIVATE
Convert the Not_Invokable error to a human-readable format.
to_display_text : Text
to_display_text self = "Type error: expected a function, but got "+self.target.to_display_text+"."

@Builtin_Type
type Unsupported_Argument_Types
## PRIVATE
Expand All @@ -202,6 +270,11 @@ type Unsupported_Argument_Types
- message: A detailed message.
Error arguments message

## PRIVATE
Convert the Unsupported_Argument_Types error to a human-readable format.
to_display_text : Text
to_display_text self = self.message.to_text

@Builtin_Type
type Module_Does_Not_Exist
## PRIVATE
Expand All @@ -211,6 +284,11 @@ type Module_Does_Not_Exist
- name: The module searched for.
Error name

## PRIVATE
Convert the Module_Does_Not_Exist error to a human-readable format.
to_display_text : Text
to_display_text self = "Module "+self.name+" does not exist."

@Builtin_Type
type Invalid_Conversion_Target
## PRIVATE
Expand All @@ -231,6 +309,11 @@ type No_Such_Conversion
- conversion: the conversion that was attempted.
Error target that conversion

## PRIVATE
Convert the No_Such_Conversion error to a human-readable format.
to_display_text : Text
to_display_text self = "Could not find a conversion from `"+self.that.to_display_text+"` to `"+self.target.to_display_text+"`."

@Builtin_Type
type Forbidden_Operation
## PRIVATE
Expand All @@ -239,3 +322,8 @@ type Forbidden_Operation
Arguments:
- operation: attempted context that is not allowed.
Error operation

## PRIVATE
Convert the Forbidden_Operation error to a human-readable format.
to_display_text : Text
to_display_text self = "Forbidden operation: "+self.operation+"."
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,27 @@ class ReplTest
executor.exit()
}
eval(code)
val errorMsg =
"Compile_Error.Error"
evalResult.left.value.getMessage shouldEqual errorMsg
}

"handle errors gracefully (pretty print)" in {
val code =
"""
|import Standard.Base.Runtime.Debug
|from Standard.Base.Errors.Common import all
|
|main =
| Debug.breakpoint
|""".stripMargin
var evalResult: Either[Exception, ObjectRepresentation] =
null
setSessionManager { executor =>
evalResult = executor.evaluate("1 + undefined")
executor.exit()
}
eval(code)
val errorMsg =
"Compile error: The name `undefined` could not be found."
evalResult.left.value.getMessage shouldEqual errorMsg
Expand Down
Loading

0 comments on commit e163353

Please sign in to comment.