Skip to content

Commit 8809352

Browse files
committed
try/catch statements, ExceptionInfo method
1 parent 1e2037b commit 8809352

4 files changed

Lines changed: 208 additions & 0 deletions

File tree

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
using JetBrains.Annotations;
2+
using SER.Code.ContextSystem.BaseContexts;
3+
using SER.Code.ContextSystem.Interfaces;
4+
using SER.Code.ContextSystem.Structures;
5+
using SER.Code.Extensions;
6+
using SER.Code.Helpers.ResultSystem;
7+
using SER.Code.TokenSystem.Tokens;
8+
using SER.Code.TokenSystem.Tokens.VariableTokens;
9+
using SER.Code.ValueSystem;
10+
using SER.Code.VariableSystem.Bases;
11+
using SER.Code.VariableSystem.Variables;
12+
13+
namespace SER.Code.ContextSystem.Contexts.Control;
14+
15+
[UsedImplicitly]
16+
public class CatchStatement : StatementContext, IStatementExtender, IKeywordContext, IAcceptOptionalVariableDefinitionsContext
17+
{
18+
public string KeywordName => "catch";
19+
public string Description => "Catches an exception thrown inside of a " +
20+
typeof(TryStatement).FriendlyTypeName(true);
21+
public string[] Arguments => [];
22+
public string? Example =>
23+
"""
24+
&collection = EmptyCollection
25+
try
26+
Print {CollectionFetch &collection 2}
27+
# throws because there's nothing at index 2
28+
catch
29+
with *exception
30+
31+
Print "Error!: {ExceptionInfo *exception message}"
32+
end
33+
""";
34+
35+
public IExtendableStatement.Signal Extends => IExtendableStatement.Signal.ThrewException;
36+
protected override string FriendlyName => "'catch' statement";
37+
38+
public Exception? Exception
39+
{
40+
get;
41+
set
42+
{
43+
if (field is not null)
44+
return;
45+
field = value;
46+
}
47+
}
48+
private VariableToken? _variableToken;
49+
private Variable? _variable;
50+
51+
public override TryAddTokenRes TryAddToken(BaseToken token)
52+
{
53+
return TryAddTokenRes.Error($"A {FriendlyName} does not expect any arguments.");
54+
}
55+
56+
public override Result VerifyCurrentState()
57+
{
58+
return true;
59+
}
60+
61+
public Result SetOptionalVariables(params VariableToken[] variableTokens)
62+
{
63+
if (variableTokens.Length > 1)
64+
return $"Too many arguments provided for {FriendlyName}, only 1 is allowed.";
65+
var token = variableTokens.FirstOrDefault();
66+
if (token is null) return true;
67+
68+
if (token is not ReferenceVariableToken)
69+
return $"Variable {token.RawRepr} cannot be used for a {FriendlyName} as it's not a " +
70+
$"{typeof(ReferenceVariable).FriendlyTypeName(true)}.";
71+
72+
_variableToken = token;
73+
return true;
74+
}
75+
76+
protected override IEnumerator<float> Execute()
77+
{
78+
if (_variableToken is not null)
79+
{
80+
_variable = Variable.Create(_variableToken.Name, Value.Parse(Exception!, Script));
81+
Script.AddLocalVariable(_variable);
82+
}
83+
84+
var coro = RunChildren();
85+
while (coro.MoveNext())
86+
yield return coro.Current;
87+
88+
if (_variable is not null) Script.RemoveLocalVariable(_variable);
89+
}
90+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
using JetBrains.Annotations;
2+
using SER.Code.ContextSystem.BaseContexts;
3+
using SER.Code.ContextSystem.Interfaces;
4+
using SER.Code.ContextSystem.Structures;
5+
using SER.Code.Extensions;
6+
using SER.Code.Helpers.ResultSystem;
7+
using SER.Code.TokenSystem.Tokens;
8+
9+
namespace SER.Code.ContextSystem.Contexts.Control;
10+
11+
[UsedImplicitly]
12+
public class TryStatement : StatementContext, IExtendableStatement, IKeywordContext
13+
{
14+
public string KeywordName => "try";
15+
public string Description => "Runs everything inside the statement, and if something throws an exception (error), " +
16+
"the statement skips everything after it and jumps straight to the " +
17+
$"{typeof(CatchStatement).FriendlyTypeName(true)} " +
18+
"after it if provided.";
19+
public string[] Arguments => [];
20+
public string? Example =>
21+
"""
22+
&collection = EmptyCollection
23+
# swallows the error (doesn't stop the script)
24+
try
25+
Print {CollectionFetch &collection 2}
26+
# throws because there's nothing at index 2
27+
end
28+
""";
29+
30+
public IExtendableStatement.Signal AllowedSignals => IExtendableStatement.Signal.ThrewException;
31+
public Dictionary<IExtendableStatement.Signal, StatementContext> RegisteredSignals { get; } = [];
32+
protected override string FriendlyName => "'try' statement";
33+
34+
private Exception? _exception;
35+
36+
public override TryAddTokenRes TryAddToken(BaseToken token)
37+
{
38+
return TryAddTokenRes.Error($"A {FriendlyName} does not expect any arguments.");
39+
}
40+
41+
public override Result VerifyCurrentState()
42+
{
43+
return true;
44+
}
45+
46+
protected override IEnumerator<float> Execute()
47+
{
48+
var coro = RunChildren();
49+
while (true)
50+
{
51+
bool isRunning;
52+
try
53+
{
54+
isRunning = coro.MoveNext();
55+
}
56+
catch (Exception ex)
57+
{
58+
_exception = ex;
59+
break;
60+
}
61+
62+
if (!isRunning) yield break;
63+
yield return coro.Current;
64+
}
65+
66+
if (!RegisteredSignals.TryGetValue(IExtendableStatement.Signal.ThrewException, out var statement))
67+
yield break;
68+
69+
if (statement is CatchStatement catchStatement)
70+
{
71+
catchStatement.Exception = _exception;
72+
}
73+
var catchCoro = statement.Run();
74+
while (catchCoro.MoveNext())
75+
yield return catchCoro.Current;
76+
}
77+
}

Code/ContextSystem/Interfaces/IExtendableStatement.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ public enum Signal
1212
None = 0,
1313
DidntExecute = 1 << 0,
1414
EndedExecution = 1 << 1,
15+
ThrewException = 1 << 2,
1516
}
1617

1718
public abstract Signal AllowedSignals { get; }
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using JetBrains.Annotations;
2+
using SER.Code.ArgumentSystem.Arguments;
3+
using SER.Code.ArgumentSystem.BaseArguments;
4+
using SER.Code.Exceptions;
5+
using SER.Code.Extensions;
6+
using SER.Code.MethodSystem.BaseMethods.Synchronous;
7+
using SER.Code.MethodSystem.MethodDescriptors;
8+
using SER.Code.ValueSystem;
9+
10+
namespace SER.Code.MethodSystem.Methods.ScriptMethods;
11+
12+
[UsedImplicitly]
13+
public class ExceptionInfoMethod : ReturningMethod<TextValue>, IReferenceResolvingMethod
14+
{
15+
public override string Description => IReferenceResolvingMethod.Desc.Get(this);
16+
17+
public Type ResolvesReference => typeof(Exception);
18+
19+
public override Argument[] ExpectedArguments { get; } =
20+
[
21+
new ReferenceArgument<Exception>("exception reference"),
22+
new OptionsArgument("info to get",
23+
"type",
24+
"message",
25+
"stackTrace")
26+
];
27+
28+
public override void Execute()
29+
{
30+
var exception = Args.GetReference<Exception>("exception reference");
31+
32+
ReturnValue = new StaticTextValue(Args.GetOption("info to get") switch
33+
{
34+
"type" => exception.GetType().AccurateName,
35+
"message" => exception.Message,
36+
"stacktrace" => exception.StackTrace,
37+
_ => throw new TosoksFuckedUpException("out of order")
38+
});
39+
}
40+
}

0 commit comments

Comments
 (0)