Skip to content

Commit

Permalink
Test the scope of captured exception
Browse files Browse the repository at this point in the history
  • Loading branch information
melvic-ybanez committed Nov 17, 2023
1 parent a57153e commit 0be6c75
Show file tree
Hide file tree
Showing 5 changed files with 22 additions and 20 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ like this:
[Success] Ducks should quack!
[Success] Denji should say 'Woof!'
[Success] Class properties should be updated
Ran 178 tests. Successful: 178. Failed: 0.
Ran 179 tests. Successful: 179. Failed: 0.
```

The tests themselves are written in Dry (while the `testDry` command is written in Scala). You can see the directory
Expand Down
5 changes: 2 additions & 3 deletions src/main/scala/com/melvic/dry/interpreter/eval/EvalStmt.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import com.melvic.dry.aux.Nel.{Many, One}
import com.melvic.dry.interpreter.Value.{Returned, Unit => VUnit}
import com.melvic.dry.interpreter.eval.Context.implicits._
import com.melvic.dry.interpreter.eval.Evaluate.Out
import com.melvic.dry.interpreter.values.DException.NoArgDException
import com.melvic.dry.interpreter.values.Value.{ToValue, Types}
import com.melvic.dry.interpreter.values._
import com.melvic.dry.interpreter.{Env, ModuleManager, Run}
Expand Down Expand Up @@ -155,8 +154,8 @@ private[eval] trait EvalStmt {
.fold(
{
case One(failure @ Failure.Raised(_)) => handleException(failure)
case One(RuntimeError(kind, token, _)) =>
NoArgDException(kind, env).call(token)(Nil).flatMap { instance =>
case One(RuntimeError(kind, token, message)) =>
DException(kind, env).call(token)(Value.Str(message) :: Nil).flatMap { instance =>
handleException(Raised(instance.asInstanceOf[DInstance]))
}
case errors => Result.failAll(errors)
Expand Down
16 changes: 2 additions & 14 deletions src/main/scala/com/melvic/dry/interpreter/values/DException.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ class DException(val kind: Kind, val env: Env) extends DClass(kind.exceptionName

override def arity = 1

// TODO: Add support for the other exception constructors. This would
// make it more convenient to compare exception objects (no more direct message comparison)
override def call(token: Token) = {
case args @ ((message: Value.Str) :: _) =>
super.call(token)(args).flatMap { case instance: DInstance =>
Expand All @@ -29,20 +31,6 @@ class DException(val kind: Kind, val env: Env) extends DClass(kind.exceptionName
}

object DException {
class NoArgDException(override val kind: Kind, override val env: Env) extends DException(kind, env) {
override def arity = 0

override def call(token: Token) = {
case Nil => super.call(token)(Value.Str(kind.exceptionName) :: Nil)
case _ => RuntimeError.invalidArgument(s"${Types.String}", typeOf(Value.Unit), token.line).fail
}
}

object NoArgDException {
def apply(kind: Kind, env: Env): NoArgDException =
new NoArgDException(kind, env)
}

object Attributes {
val Message: String = "__message__"
val Kind: String = "__kind__"
Expand Down
4 changes: 3 additions & 1 deletion stdlib/asserts.dry
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ def assert_error(description, expected_error, code) {
try {
code();
} catch (error:) {
assert_equals(description, expected_error, error);
let expected_details = (expected_error.__kind__, expected_error.__message__);
let actual_details = (error.__kind__, error.__message__);
assert_equals(description, expected_details, actual_details);
}
}

Expand Down
15 changes: 14 additions & 1 deletion tests/test_try_catch.dry
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,22 @@ class TestTryCatch {
} catch (: IncorrectArityError) {} catch (: DivisionByZeroError) {}
});
}

def test_captured_error_scope() {
try {
10 / 0;
} catch (division_by_zero_error: DivisionByZeroError) {}

assert_error("Captured errors should not be visible outside of the catch block",
UndefinedVariableError("Undefined variable: division_by_zero_error"),
lambda() {
println(division_by_zero_error);
});
}
}

let try_catch = TestTryCatch();
try_catch.test_single_catch();
try_catch.test_multiple_catches();
try_catch.test_no_match();
try_catch.test_no_match();
try_catch.test_captured_error_scope();

0 comments on commit 0be6c75

Please sign in to comment.