Skip to content

Commit 3aa4ba4

Browse files
authored
Merge pull request #16 from comroid-git/dev-stmt
Implement try-catch statements
2 parents d589752 + 8943f54 commit 3aa4ba4

File tree

10 files changed

+161
-47
lines changed

10 files changed

+161
-47
lines changed

examples/PrintNumbers.kscr

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,14 +69,20 @@ public class PrintNumbers implements Throwable {
6969
stdio <<- "look at my cool object: " + obj.toString(0) + endl;
7070
stdio <<- "and of course i can access it this way too: " + obj.StackValue + endl;
7171

72-
stdio <<- "let's test for-loop recursion with an 8x8 matrix:" + endl;
72+
try {
73+
obj.callThroingMethod();
74+
} catch (Throwable t) {
75+
stdio <<- "no this time yet, tho! we caught it" + t + endl;
76+
} finally {
77+
stdio <<- "and another time, finalization blocks" + endl;
78+
}
79+
80+
stdio <<- "now we're doing some recursion shit with a 8x8 table:" + endl;
7381
for (int y = 1; y < 9; y++) {
7482
for (int x = 1; x < 9; x++)
75-
//throw x + (y * 9);
7683
stdio <<- " " + x + y + " -";
7784
stdio <<- endl;
78-
}// finally stdio <<- "finally, we finish throwing:";
79-
85+
} finally stdio <<- "finally, we finish throwing:" + endl;
8086
obj.callThroingMethod();
8187
}
8288

kscr-bytecode/Adapter/BytecodeAdapterV0_10.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ void WriteArray<T>(T[] arr) where T : IBytecode
137137
WriteByte((byte)comp.VariableContext);
138138
WriteULong(comp.ByteArg);
139139
WriteString(comp.Arg ?? string.Empty);
140+
WriteArray(comp.Args.Select(IBytecode.String).ToArray());
140141
Write(strings, stream, comp.SourcefilePosition);
141142
var memberState = comp.GetComponentMember();
142143
WriteByte((byte)memberState);
@@ -343,6 +344,7 @@ T2[] ReadArray<T2>()
343344
var varctx = (VariableContext)ReadByte();
344345
var byteArg = ReadULong();
345346
sArg = ReadString();
347+
var sArgs = ReadArray<string>();
346348
srcPos = Load<SourcefilePosition>(vm, strings, stream, pkg, cls);
347349
var memberState = (ComponentMember)ReadByte();
348350
Statement? subStmt, altStmt = subStmt = null;
@@ -367,6 +369,7 @@ T2[] ReadArray<T2>()
367369
VariableContext = varctx,
368370
ByteArg = byteArg,
369371
Arg = sArg,
372+
Args = sArgs.ToList(),
370373
SubStatement = subStmt,
371374
AltStatement = altStmt,
372375
SubComponent = subComp,

kscr-compiler/KScr/Compiler/AbstractVisitor.cs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.Linq;
34
using Antlr4.Runtime;
45
using Antlr4.Runtime.Tree;
@@ -166,20 +167,24 @@ protected Statement VisitPipeListen(KScrParser.ExprContext pipe, KScrParser.Expr
166167
{
167168
Type = StatementComponentType.Code,
168169
CodeType = BytecodeType.StmtCatch,
169-
Arg = katchow.type() == null
170-
? string.Empty
171-
: string.Join(";", katchow.type()
172-
.Select(x => VisitTypeInfo(x).FullDetailedName)
173-
.Append(katchow.idPart().GetText())),
174-
InnerCode = VisitCode(katchow.codeBlock())
170+
Arg = katchow.idPart().GetText(),
171+
Args = katchow.type() == null
172+
? new List<string>()
173+
: katchow.type()
174+
.Select(x => VisitTypeInfo(x).CanonicalName)
175+
.Append(katchow.idPart().GetText())
176+
.ToList(),
177+
InnerCode = VisitCode(katchow.codeBlock()),
178+
SourcefilePosition = ToSrcPos(katchow)
175179
});
180+
// finally
176181
if (context.finallyBlock() is { } finalli)
177182
comp.AltComponent = new StatementComponent()
178183
{
179184
Type = StatementComponentType.Code,
180185
CodeType = BytecodeType.StmtFinally,
181-
InnerCode = VisitCode(finalli.codeBlock())
182-
186+
InnerCode = VisitCode(finalli.codeBlock()),
187+
SourcefilePosition = ToSrcPos(finalli)
183188
};
184189
return comp;
185190
}

kscr-compiler/KScr/Compiler/Code/StatementVisitor.cs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -151,14 +151,18 @@ public override Statement VisitStmtTryCatch(KScrParser.StmtTryCatchContext conte
151151
{
152152
Type = StatementComponentType.Code,
153153
CodeType = BytecodeType.StmtTry,
154-
CatchFinally = context.catchBlocks() == null ? null : VisitCatchBlocks(context.catchBlocks())
154+
CatchFinally = context.catchBlocks() == null ? null : VisitCatchBlocks(context.catchBlocks()),
155+
Main =
156+
{
157+
new StatementComponent()
158+
{
159+
Type = StatementComponentType.Code,
160+
CodeType = BytecodeType.StmtTry,
161+
ByteArg = 0,
162+
InnerCode = VisitCode(context.tryCatchStatement().codeBlock())
163+
}
164+
}
155165
};
156-
stmt.Main.Add(new StatementComponent()
157-
{
158-
Type = StatementComponentType.Code,
159-
CodeType = BytecodeType.StmtTry,
160-
InnerCode = VisitCode(context.tryCatchStatement().codeBlock())
161-
});
162166
return stmt;
163167
}
164168

@@ -182,14 +186,15 @@ public override Statement VisitStmtTryWithRes(KScrParser.StmtTryWithResContext c
182186
{
183187
Type = StatementComponentType.Code,
184188
CodeType = BytecodeType.StmtTry,
185-
Arg = decl.type().GetText() + ';' + decl.idPart().GetText(),
189+
Args = { ctx.FindType(vm, decl.type().GetText())!.FullDetailedName, decl.idPart().GetText() },
186190
SubComponent = VisitExpression(decl.expr())
187191
});
188192
}
189193
stmt.Main.Add(new StatementComponent()
190194
{
191195
Type = StatementComponentType.Code,
192196
CodeType = BytecodeType.StmtTry,
197+
ByteArg = 1,
193198
SubStatement = defs,
194199
InnerCode = VisitCode(context.tryWithResourcesStatement().codeBlock())
195200
});

kscr-compiler/KScr/Compiler/Utils.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using Antlr4.Runtime;
2+
using KScr.Antlr;
23
using KScr.Core.Model;
34

45
namespace KScr.Compiler;

kscr-core/Bytecode/Statement.cs

Lines changed: 79 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ public class Statement : IBytecode, IStatement<StatementComponent>
3737

3838
public Stack Evaluate(RuntimeBase vm, Stack stack)
3939
{
40+
bool caught = false;
4041
try
4142
{
4243
foreach (var component in Main)
@@ -51,6 +52,57 @@ public Stack Evaluate(RuntimeBase vm, Stack stack)
5152
stack[Default]![vm, stack, i] = stack.Bet?[vm, stack, 0] ?? IObject.Null;
5253
}
5354

55+
break;
56+
case (StatementComponentType.Code, BytecodeType.StmtTry):
57+
(string name, IObject value)[]? resources = null;
58+
var comp = Main[0];
59+
try
60+
{
61+
if (comp.ByteArg == 1) // try-with-resources
62+
resources = comp.SubStatement!.Main.Select(x => (x.Args[1],
63+
x.SubComponent!.Evaluate(vm, stack.Output()).Copy()![vm, stack, 0])).ToArray();
64+
65+
var resourcesF = resources;
66+
var compF = comp;
67+
stack.StepInside(vm, comp.SourcefilePosition, "try", stack =>
68+
{
69+
foreach (var resource in resourcesF ?? Array.Empty<(string, IObject)>())
70+
vm.PutLocal(stack, resource.name, resource.value);
71+
compF.InnerCode!.Evaluate(vm, stack);
72+
});
73+
}
74+
catch (StackTraceException trace)
75+
{
76+
var innerCause = trace.InnerCause.Obj;
77+
foreach (var catchBlock in CatchFinally!.SubStatement!.Main
78+
.Where(x => x.Args.Select(t => vm.FindType(t))
79+
.Any(x => x!.CanHold(innerCause.Type)))
80+
.Select(x => (x.Arg, x.InnerCode)))
81+
{
82+
stack.StepInside(vm, CatchFinally.SourcefilePosition, "catch", stack =>
83+
{
84+
vm.PutLocal(stack, catchBlock.Arg, innerCause);
85+
catchBlock.InnerCode!.Evaluate(vm, stack);
86+
});
87+
}
88+
caught = true;
89+
}
90+
finally
91+
{
92+
try
93+
{
94+
if (resources != null)
95+
foreach (var resource in resources.Select(x => x.value))
96+
Class.CloseableType.DeclaredMembers["close"].Invoke(vm, stack, resource);
97+
CatchFinally!.AltComponent!.InnerCode!.Evaluate(vm, stack);
98+
caught = true;
99+
}
100+
catch (StackTraceException fatal)
101+
{
102+
throw new FatalException("Inner exception during finalization", fatal);
103+
}
104+
}
105+
54106
break;
55107
default:
56108
component.Evaluate(vm, stack);
@@ -63,16 +115,23 @@ public Stack Evaluate(RuntimeBase vm, Stack stack)
63115
}
64116
catch (InternalException codeEx)
65117
{
66-
if (CatchFinally != null)
67-
CatchFinally.Evaluate(vm, stack);
118+
stack[Tau] = new ObjectRef(Class.ThrowableType.DefaultInstance, codeEx.Obj);
119+
CatchFinally?.Evaluate(vm, stack);
120+
caught = true;
68121
throw codeEx;
69122
}
70123
catch (StackTraceException codeEx)
71124
{
72-
if (CatchFinally != null)
73-
CatchFinally.Evaluate(vm, stack);
125+
stack[Tau] = new ObjectRef(Class.ThrowableType.DefaultInstance, codeEx.InnerCause.Obj);
126+
CatchFinally?.Evaluate(vm, stack);
127+
caught = true;
74128
throw codeEx;
75129
}
130+
finally
131+
{
132+
if (!caught)
133+
CatchFinally?.AltComponent?.InnerCode!.Evaluate(vm, stack);
134+
}
76135

77136
return stack;
78137
}
@@ -88,6 +147,7 @@ public class StatementComponent : IBytecode, IStatementComponent
88147
public Statement Statement { get; set; } = null!;
89148
public VariableContext VariableContext { get; set; }
90149
public string Arg { get; set; } = string.Empty;
150+
public List<string> Args { get; set; } = new();
91151
public ulong ByteArg { get; set; }
92152
public SourcefilePosition SourcefilePosition { get; set; }
93153
public Statement? SubStatement { get; set; }
@@ -223,6 +283,7 @@ public virtual Stack Evaluate(RuntimeBase vm, Stack stack)
223283
SubComponent.Evaluate(vm, stack.Output()).Copy(output: Alp | Omg);
224284
//Console.WriteLine(stack[Alp]);
225285
stack.State = State.Throw;
286+
Stack.StackTrace.Clear();
226287
break;
227288
case (StatementComponentType.Code, BytecodeType.StmtIf):
228289
stack.StepInside(vm, SourcefilePosition, "if", stack =>
@@ -283,6 +344,20 @@ public virtual Stack Evaluate(RuntimeBase vm, Stack stack)
283344
} while (SubComponent.Evaluate(vm, stack.Output(Phi)).Copy(Phi).ToBool());
284345
});
285346
break;
347+
case (StatementComponentType.Code, BytecodeType.StmtCatch):
348+
IObject ex = stack[Tau]![vm, stack, 0];
349+
IClassInfo exType = ex.Type;
350+
try
351+
{
352+
SubStatement!.Main
353+
.FirstOrDefault(comp => comp.Args.Any(exClsName => exClsName == exType.CanonicalName))
354+
?.InnerCode!.Evaluate(vm, stack);
355+
}
356+
finally
357+
{
358+
AltComponent?.InnerCode!.Evaluate(vm, stack);
359+
}
360+
break;
286361
case (StatementComponentType.Operator, _):
287362
var op = (Operator)ByteArg;
288363
var compound = (op & Operator.Compound) == Operator.Compound;
Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,37 @@
1-
using KScr.Core.Model;
1+
using System;
2+
using System.IO;
23
using KScr.Core.Std;
34
using KScr.Core.Store;
4-
using String = System.String;
55

66
namespace KScr.Core.Exception;
77

88
public class InternalException : System.Exception
99
{
10-
public IClass Type { get; init; } = Class.ThrowableType;
11-
public InternalException(string? message) : base(message)
10+
internal readonly IObject Obj;
11+
12+
public InternalException(string? message, IObject? obj = null) : base(message)
1213
{
14+
Obj = obj ?? IObject.Null;
1315
}
1416

15-
public InternalException(string? message, System.Exception? innerException) : base(message, innerException)
17+
public InternalException(string? message, System.Exception? innerException) : base(message ?? innerException?.Message, innerException)
1618
{
19+
Obj = IObject.Null;
1720
}
18-
19-
public string BaseMessage => base.Message;
20-
public override string Message => $"An internal {Type.DetailedName} occurred: {BaseMessage}";
21-
22-
public static InternalException npe(string? message = null!) => new(message ?? String.Empty) { Type = Class.NullPointerExceptionType };
2321
}
2422

25-
public class FatalException : System.Exception
23+
public class FatalException :
24+
#if DEBUG
25+
System.Exception
26+
#else
27+
InternalException
28+
#endif
2629
{
2730
public FatalException(string? message) : base(message)
2831
{
2932
}
3033

31-
public FatalException(string? message, System.Exception? innerException) : base(message, innerException)
34+
public FatalException(string? message, System.Exception? innerException) : base(message ?? innerException?.Message, innerException)
3235
{
3336
}
3437
}
@@ -41,13 +44,13 @@ public interface IStackTrace
4144

4245
public class StackTraceException : System.Exception, IStackTrace
4346
{
44-
public StackTraceException(CallLocation srcPos, string local, System.Exception innerTrace,
47+
public StackTraceException(CallLocation srcPos, string local, InternalException innerCause,
4548
string? message = null)
46-
: base(message ?? "<...>", innerTrace)
49+
: base(message ?? "<...>", innerCause)
4750
{
4851
CallLoc = srcPos;
4952
Local = local;
50-
InnerTrace = innerTrace;
53+
InnerCause = innerCause;
5154
}
5255

5356
public StackTraceException(CallLocation srcPos, string local, StackTraceException innerTrace,
@@ -56,14 +59,23 @@ public StackTraceException(CallLocation srcPos, string local, StackTraceExceptio
5659
{
5760
CallLoc = srcPos;
5861
Local = local;
62+
InnerCause = innerTrace.InnerCause;
5963
}
6064

61-
public System.Exception? InnerTrace { get; }
65+
public InternalException InnerCause { get; }
6266
public string Local { get; }
6367
public string BaseMessage => base.Message;
6468
public CallLocation CallLoc { get; }
6569

6670
public override string Message => $"{CallLoc.SourceName}" + (CallLoc.SourceLine == 0
6771
? string.Empty
6872
: $" [line {CallLoc.SourceLine} pos {CallLoc.SourceCursor}]");// + BaseMessage;
73+
74+
public void PrintStackTrace() => WriteStackTrace(Console.Out);
75+
public void WriteStackTrace(TextWriter @out)
76+
{
77+
@out.WriteLine($"An exception occurred:\t{InnerCause.Message}");
78+
foreach (var stackTraceElement in Stack.StackTrace)
79+
@out.WriteLine($"\tat\t{stackTraceElement.Message}");
80+
}
6981
}

kscr-core/RuntimeBase.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -253,9 +253,7 @@ public Stack Execute()
253253
}
254254
catch (StackTraceException stc)
255255
{
256-
Console.WriteLine($"An exception occurred:\t{stc.InnerTrace.Message}");
257-
foreach (var stackTraceElement in Stack.StackTrace)
258-
Console.WriteLine($"\tat\t{stackTraceElement.Message}");
256+
stc.PrintStackTrace();
259257
}
260258

261259
return stack;

0 commit comments

Comments
 (0)