Skip to content

Commit

Permalink
Allow selector expression arms to throw exceptions.
Browse files Browse the repository at this point in the history
  • Loading branch information
vddCore committed Apr 2, 2024
1 parent cc5d455 commit 9d5b9f6
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 33 deletions.
4 changes: 2 additions & 2 deletions Core/EVIL.Grammar/AST/Expressions/ByExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ public class ByExpression : Expression
public Expression Qualifier { get; }

public List<ByArmNode> Arms { get; }
public Expression? ElseArm { get; }
public AstNode? ElseArm { get; }

public ByExpression(Expression qualifier, List<ByArmNode> arms, Expression? elseArm)
public ByExpression(Expression qualifier, List<ByArmNode> arms, AstNode? elseArm)
{
Qualifier = qualifier;
Arms = arms;
Expand Down
8 changes: 4 additions & 4 deletions Core/EVIL.Grammar/AST/Miscellaneous/ByArmNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@ namespace EVIL.Grammar.AST.Miscellaneous
public class ByArmNode : AstNode
{
public Expression Selector { get; }
public Expression Value { get; }
public AstNode ValueArm { get; }
public bool DeepEquality { get; }

public ByArmNode(Expression selector, Expression value, bool deepEquality)
public ByArmNode(Expression selector, AstNode valueArm, bool deepEquality)
{
Selector = selector;
Value = value;
ValueArm = valueArm;
DeepEquality = deepEquality;

Reparent(Selector, Value);
Reparent(Selector, valueArm);
}
}
}
28 changes: 22 additions & 6 deletions Core/EVIL.Grammar/Parsing/Expressions/Parser.ByExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public Expression ByExpression()
Match(Token.LBrace);

var arms = new List<ByArmNode>();
Expression? elseArm = null;
AstNode? elseArm = null;

while (true)
{
Expand Down Expand Up @@ -56,8 +56,16 @@ public Expression ByExpression()

Match(Token.Else);
Match(Token.Colon);

elseArm = AssignmentExpression();

if (CurrentToken.Type == TokenType.Throw)
{
elseArm = ThrowStatement();
}
else
{
elseArm = AssignmentExpression();
}


if (CurrentToken.Type != TokenType.RBrace)
{
Expand Down Expand Up @@ -91,10 +99,18 @@ public Expression ByExpression()
(CurrentToken.Line, CurrentToken.Column)
);
}

var value = AssignmentExpression();

arms.Add(new ByArmNode(selector, value, deepEquality) { Line = armLine, Column = armCol });
AstNode valueArm;
if (CurrentToken.Type == TokenType.Throw)
{
valueArm = ThrowStatement();
}
else
{
valueArm = AssignmentExpression();
}

arms.Add(new ByArmNode(selector, valueArm, deepEquality) { Line = armLine, Column = armCol });
}

if (CurrentToken.Type == TokenType.RBrace)
Expand Down
12 changes: 9 additions & 3 deletions VirtualMachine/Ceres/TranslationEngine/Compiler.Expression.By.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using Ceres.ExecutionEngine.Diagnostics;
using Ceres.TranslationEngine.Diagnostics;
using EVIL.Grammar.AST.Base;
using EVIL.Grammar.AST.Expressions;
using EVIL.Grammar.AST.Statements;

namespace Ceres.TranslationEngine
{
Expand Down Expand Up @@ -32,10 +34,14 @@ public override void Visit(ByExpression byExpression)

Chunk.CodeGenerator.Emit(arms[i].DeepEquality ? OpCode.DEQ : OpCode.CEQ);
Chunk.CodeGenerator.Emit(OpCode.FJMP, labels[i]);

Visit(arms[i].ValueArm);

Visit(arms[i].Value);
Chunk.CodeGenerator.Emit(OpCode.JUMP, endLabel);
Chunk.UpdateLabel(labels[i], Chunk.CodeGenerator.IP);
if (arms[i].ValueArm is Expression)
{
Chunk.CodeGenerator.Emit(OpCode.JUMP, endLabel);
Chunk.UpdateLabel(labels[i], Chunk.CodeGenerator.IP);
}
}

if (elseArm != null)
Expand Down
67 changes: 49 additions & 18 deletions VirtualMachine/Tests/Ceres.LanguageTests/tests/023_try.vil
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
#[test]
fn try_catch_ok() {
rw val result;

try {
throw "hiii";
} catch(e) {
result = e;
}

assert.equal(result, "hiii");
}

Expand All @@ -19,40 +19,44 @@ loc fn throwing_inner(value) {
#[test]
fn try_invoked_throws() {
rw val result;

try {
throwing_inner({ msg: "yaaaay" });
} catch (e) {
result = e;
}

assert.is_true(result is Table);
assert.equal(result.msg, "yaaaay");
}

#[test]
fn nested_try_blocks_innermost() {
rw val result;

try {
try {
try { throw "this should happen!"; } catch (e) { result = e; }
} catch (e) { result = "should never ever happen!"; }
} catch (e) { result = "should never happen too."; }

try {
throw "this should happen!";
} catch (e) { result = e; }
} catch (e) { result = "should never ever happen! $e"; }
} catch (e) { result = "should never happen too. $e"; }

assert.equal(result, "this should happen!");
}

#[test]
fn nested_try_blocks_rethrow() {
rw val result;

try {
try {
try { throw "jp2gmd"; } catch (e) { throw e; }

try {
try {
try {
throw "jp2gmd";
} catch (e) { throw e; }
} catch (e) { throw e; }
} catch (e) { result = e; }

assert.equal(result, "jp2gmd");
}

Expand All @@ -76,23 +80,50 @@ fn try_invoked_ret_differs() {
#[test]
fn try_native_throws() {
rw val result;

try {
__throw_test("hello world");
} catch (e) {
result = e;
}

assert.equal(result, "hello world");
}

#[test]
fn try_require() {
rw val result = "hiii";

try { result = require("doesnt_exist"); }
catch (e) { result = e.msg; }

assert.is_true(#result > 70);
}

loc fn throwing_by(value) -> by typeof(value) {
Nil -> "It's a Nil!",
Number -> "It's a Number!",
Boolean -> "It's a Boolean!",
String -> "It's a String!",
Table -> "It's a Table!",
Array -> "It's an Array!",
Function -> "It's a Function!",
NativeFunction -> "It's a NativeFunction!",
NativeObject -> "It's a NativeObject!",
Type -> throw "It's a Type and it's not supported!",
else: throw "I don't know what the fuck that is!"
};

#[test]
fn try_by() {
rw val result;

try {
throwing_by(NativeObject);
result = throwing_by(nil);
} catch (e) {
result = e;
}

assert.equal(result, "It's a Type and it's not supported!");
}

0 comments on commit 9d5b9f6

Please sign in to comment.