Skip to content

Commit d061cc8

Browse files
committed
lua
1 parent a916f86 commit d061cc8

File tree

4 files changed

+109
-5
lines changed

4 files changed

+109
-5
lines changed

examples/exceptions.cal

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
include "cores/select.cal"
22
include "std/io.cal"
33

4-
func __rm86_exception begin
4+
func __lua_exception begin
55
&_cal_exception Exception.msg + "Unhandled exception: %s" printf new_line
66
1 exit
77
end

source/backends/lua.d

Lines changed: 102 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ private struct Word {
2222
WordType type;
2323
bool inline;
2424
Node[] inlineNodes;
25+
bool error;
2526
}
2627

2728
private struct StructEntry {
@@ -120,6 +121,11 @@ class BackendLua : CompilerBackend {
120121
foreach (ref type ; types) {
121122
NewConst(format("%s.sizeof", type.name), cast(long) type.size);
122123
}
124+
125+
globals ~= Global(
126+
"_cal_exception", GetType("Exception"), globalStack, false, 0
127+
);
128+
globalStack += globals[$ - 1].Size();
123129
}
124130

125131
override void NewConst(string name, long value, ErrorInfo error = ErrorInfo.init) {
@@ -217,6 +223,8 @@ class BackendLua : CompilerBackend {
217223
override void End() {
218224
// call destructors
219225
foreach (name, global ; globals) {
226+
if (!global.type.hasDeinit) continue;
227+
220228
output ~= format("mem[dsp] = %d\n", global.addr);
221229
output ~= "dsp = dsp + 1\n";
222230
output ~= format("type_deinit_%s()\n", global.type.name.Sanitise());
@@ -270,6 +278,19 @@ class BackendLua : CompilerBackend {
270278
else {
271279
output ~= format("func__%s();\n", node.name.Sanitise());
272280
}
281+
282+
if (word.error) {
283+
if ("__lua_exception" in words) {
284+
auto exception = GetGlobal("_cal_exception");
285+
286+
output ~= format("if mem[%d] ~= 0 then\n", exception.addr);
287+
output ~= format("func__%s()\n", Sanitise("__lua_exception"));
288+
output ~= "end\n";
289+
}
290+
else {
291+
Warn(node.error, "No exception handler");
292+
}
293+
}
273294
}
274295
else if (VariableExists(node.name)) {
275296
auto var = GetVariable(node.name);
@@ -326,16 +347,20 @@ class BackendLua : CompilerBackend {
326347
thisFunc = node.name;
327348

328349
if (node.inline) {
329-
words[node.name] = Word(WordType.Callisto, true, node.nodes);
350+
output ~= format("mem[%d] = 0\n", GetGlobal("_cal_exception").addr);
351+
352+
words[node.name] = Word(WordType.Callisto, true, node.nodes, node.errors);
330353
}
331354
else {
332355
assert(!inScope);
333356
inScope = true;
334357

335-
words[node.name] = Word(WordType.Callisto, false);
358+
words[node.name] = Word(WordType.Callisto, false, [], node.errors);
336359

337360
output ~= format("function func__%s()\n", node.name.Sanitise());
338361

362+
output ~= format("mem[%d] = 0\n", GetGlobal("_cal_exception").addr);
363+
339364
// allocate parameters
340365
size_t paramSize = node.params.length;
341366
foreach (ref type ; node.paramTypes) {
@@ -948,6 +973,79 @@ class BackendLua : CompilerBackend {
948973
}
949974
}
950975

951-
override void CompileTryCatch(TryCatchNode node) {}
952-
override void CompileThrow(WordNode node) {}
976+
override void CompileTryCatch(TryCatchNode node) {
977+
if (node.func !in words) {
978+
Error(node.error, "Function '%s' doesn't exist", node.func);
979+
}
980+
981+
auto word = words[node.func];
982+
983+
if (!word.error) {
984+
Error(node.error, "Function '%s' doesn't throw", node.func);
985+
}
986+
if (word.type != WordType.Callisto) {
987+
Error(node.error, "Non-callisto functions can't throw");
988+
}
989+
990+
if (word.inline) {
991+
foreach (inode ; word.inlineNodes) {
992+
compiler.CompileNode(inode);
993+
}
994+
}
995+
else {
996+
output ~= format("func__%s()\n", node.func.Sanitise());
997+
}
998+
999+
++ blockCounter;
1000+
1001+
output ~= format("if mem[%d] == 0 then\n", GetGlobal("_cal_exception").addr);
1002+
output ~= format("goto catch_%d_end\n", blockCounter);
1003+
output ~= "end\n";
1004+
1005+
// create scope
1006+
auto oldVars = variables.dup;
1007+
auto oldSize = GetStackSize();
1008+
1009+
foreach (inode ; node.catchBlock) {
1010+
compiler.CompileNode(inode);
1011+
}
1012+
1013+
// remove scope
1014+
foreach (ref var ; variables) {
1015+
if (oldVars.canFind(var)) continue;
1016+
if (!var.type.hasDeinit) continue;
1017+
1018+
output ~= format("mem[dsp] = vsp + %d\n", var.offset);
1019+
output ~= "dsp = dsp + 1\n";
1020+
output ~= format("type_deinit_%s()\n", var.type.name.Sanitise());
1021+
}
1022+
if (GetStackSize() - oldSize > 0) {
1023+
output ~= format("vsp = vsp + %d\n", GetStackSize() - oldSize);
1024+
}
1025+
variables = oldVars;
1026+
1027+
output ~= format("::catch_%d_end::\n", blockCounter);
1028+
}
1029+
1030+
override void CompileThrow(WordNode node) {
1031+
if (!inScope || (!words[thisFunc].error)) {
1032+
Error(node.error, "Not in a function that can throw");
1033+
}
1034+
if (words[thisFunc].inline) {
1035+
Error(node.error, "Can't use throw in an inline function");
1036+
}
1037+
1038+
// set exception error
1039+
output ~= format("mem[%d] = -1\n", GetGlobal("_cal_exception").addr);
1040+
1041+
// copy exception message
1042+
output ~= "dsp = dsp - 1\n";
1043+
output ~= "for i = 1, 3 do\n";
1044+
output ~= format(
1045+
"mem[%d + i] = mem[mem[dsp] + (i - 1)]\n", GetGlobal("_cal_exception").addr
1046+
);
1047+
output ~= "end\n";
1048+
1049+
CompileReturn(node);
1050+
}
9531051
}

source/backends/rm86.d

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1169,6 +1169,9 @@ class BackendRM86 : CompilerBackend {
11691169
if (!inScope || (!words[thisFunc].error)) {
11701170
Error(node.error, "Not in a function that can throw");
11711171
}
1172+
if (words[thisFunc].inline) {
1173+
Error(node.error, "Can't use throw in an inline function");
1174+
}
11721175

11731176
// set exception error
11741177
output ~= format("mov word [__global_%s], 0xFFFF\n", Sanitise("_cal_exception"));

source/backends/x86_64.d

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1410,6 +1410,9 @@ class BackendX86_64 : CompilerBackend {
14101410
if (!inScope || (!words[thisFunc].error)) {
14111411
Error(node.error, "Not in a function that can throw");
14121412
}
1413+
if (words[thisFunc].inline) {
1414+
Error(node.error, "Can't use throw in an inline function");
1415+
}
14131416

14141417
// set exception error
14151418
output ~= format("mov rbx, __global_%s\n", Sanitise("_cal_exception"));

0 commit comments

Comments
 (0)