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 Runtime.assert #8742

Merged
merged 6 commits into from
Jan 12, 2024
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
17 changes: 12 additions & 5 deletions distribution/lib/Standard/Base/0.0.0-dev/src/Runtime.enso
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ import project.Errors.Common.Assertion_Error
import project.Errors.Common.Forbidden_Operation
import project.Errors.Common.Type_Error
import project.Function.Function
import project.IO
import project.Nothing.Nothing
import project.Panic.Panic
import project.Polyglot.Polyglot
import project.Runtime.Source_Location.Source_Location
import project.System
from project.Data.Index_Sub_Range.Index_Sub_Range import First, Last
from project.Data.Text.Extensions import all
from project.Runtime.Context import Input, Output
Expand Down Expand Up @@ -58,13 +60,18 @@ gc = @Builtin_Method "Runtime.gc"
Asserts that the given action succeeds, otherwise throws a panic.

Assertions are disable by default, meaning that call to this method is
a no-op. To enable assertions, set the environment variable
`ENSO_ENABLE_ASSERTIONS=true`
assert : Boolean -> Text -> Nothing ! Assertion_Error
assert ~action message="" = assert_builtin action message
a no-op. To enable assertions, either set the environment variable
`ENSO_ENABLE_ASSERTIONS=true` or enable JVM assertions by passing `-ea`
cmd line option to java.
assert : Boolean -> Text -> Nothing
assert (~action : Boolean) (message : Text = "") =
if assertions_enabled.not then Nothing else
if action then Nothing else
Panic.throw <| Assertion_Error.Error message

## PRIVATE
assert_builtin ~action message = @Builtin_Method "Runtime.assert_builtin"
Returns True if assertions are enabled.
assertions_enabled = @Builtin_Method "Runtime.assertions_enabled"

## PRIVATE
ADVANCED
Expand Down
25 changes: 22 additions & 3 deletions engine/runner/src/main/scala/org/enso/runner/Main.scala
Original file line number Diff line number Diff line change
Expand Up @@ -787,6 +787,24 @@ object Main {
runMain(mainModule, Some(file), additionalArgs)
}

/** If the stack trace ends with `Assertion_Error`, drops the internal assertion frames.
*/
private def dropAssertionError(
stack: List[PolyglotException#StackFrame]
): List[PolyglotException#StackFrame] = {
if (
stack.size > 1 && stack(0).getRootName.contains("Panic.throw") && stack(
1
).getRootName.contains("Runtime.assert")
) {
stack
.slice(1, stack.size)
.dropWhile(_.getRootName.contains("Runtime.assert"))
} else {
stack
}
}

private def printPolyglotException(
exception: PolyglotException,
relativeTo: Option[File]
Expand All @@ -795,7 +813,8 @@ object Main {
val dropInitJava = fullStack.reverse
.dropWhile(_.getLanguage.getId != LanguageInfo.ID)
.reverse
val msg: String = HostEnsoUtils.findExceptionMessage(exception)
val dropAssertError = dropAssertionError(dropInitJava)
val msg: String = HostEnsoUtils.findExceptionMessage(exception)
println(s"Execution finished with an error: ${msg}")
def printFrame(frame: PolyglotException#StackFrame): Unit = {
val langId =
Expand Down Expand Up @@ -840,10 +859,10 @@ object Main {
}
if (exception.isSyntaxError()) {
// no stack
} else if (dropInitJava.isEmpty) {
} else if (dropAssertError.isEmpty) {
fullStack.foreach(printFrame)
} else {
dropInitJava.foreach(printFrame)
dropAssertError.foreach(printFrame)
}
}

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.enso.interpreter.node.expression.builtin.runtime;

import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.Node;
import org.enso.interpreter.dsl.BuiltinMethod;
import org.enso.interpreter.runtime.EnsoContext;

@BuiltinMethod(
type = "Runtime",
name = "assertions_enabled",
description = "Returns True iff assertions are enabled")
public class IsAssertionEnabledNode extends Node {
public static IsAssertionEnabledNode build() {
return new IsAssertionEnabledNode();
}

public boolean execute(VirtualFrame frame) {
return EnsoContext.get(this).isAssertionsEnabled();
}
}
17 changes: 7 additions & 10 deletions test/Tests/src/Runtime/Asserts_Spec.enso
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,8 @@ import Standard.Test.Extensions
foreign js js_check = """
return (4 == 2 + 2)

on_ci = if Environment.get "ENSO_RUNNER_CONTAINER_NAME" . is_nothing . not then Nothing else "Not in CI"

spec = Test.group "Asserts" pending=on_ci <|
Test.specify "should be enabled on the CI" <|
spec = Test.group "Asserts" <|
Test.specify "should be enabled in tests" <|
p = Panic.catch Assertion_Error (Runtime.assert False) err->
err.payload
Meta.type_of p . should_be_a Assertion_Error
Expand All @@ -26,15 +24,14 @@ spec = Test.group "Asserts" pending=on_ci <|
4 == 2 + 2
ret . should_be_a Nothing

Test.specify "should fail with type error when given dataflow error as expression" <|
p = Panic.catch Assertion_Error (Runtime.assert (Error.throw "foo")) err->
err.payload
Meta.type_of p . should_be_a Assertion_Error
p.message . should_start_with "Result of assert action is a dataflow error"

Test.specify "should be able to take values with warnings" <|
foo x = Warning.attach "My warning" (x+2)
Runtime.assert (foo 2 > 2) . should_be_a Nothing

Test.specify "should fail with Type_Error if action does not return Boolean" <|
p = Panic.catch Type_Error (Runtime.assert 42) err->
err
Meta.type_of p.payload . should_be_a Type_Error


main = Test_Suite.run_main spec
Loading