Skip to content

Commit 25b1e81

Browse files
committed
make break and continue safe
1 parent a78fea6 commit 25b1e81

File tree

2 files changed

+24
-3
lines changed

2 files changed

+24
-3
lines changed

source/parser.d

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ class FuncDefNode : Node {
108108
ret ~= format(" %s", type);
109109
}
110110

111+
ret ~= " begin\n";
112+
111113
foreach (ref node ; nodes) {
112114
ret ~= " " ~ node.toString() ~ '\n';
113115
}

source/stackCheck.d

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ class StackChecker {
3333
StackCell[] stack;
3434
string[] identifiers;
3535
string[][string] structs;
36+
size_t[] whileStacks;
3637

3738
this() {
3839
structs["Array"] = ["length", "memberSize", "elements"];
@@ -207,7 +208,8 @@ class StackChecker {
207208
Evaluate(node.condition);
208209
Pop(node.condition[$ - 1], 1);
209210

210-
size_t oldSize = stack.length;
211+
size_t oldSize = stack.length;
212+
whileStacks ~= stack.length;
211213
Evaluate(node.doWhile);
212214

213215
if (oldSize != stack.length) {
@@ -222,6 +224,19 @@ class StackChecker {
222224
stack = oldStack;
223225
}
224226

227+
void EvaluateBreakContinue(WordNode node) {
228+
if (whileStacks.length == 0) {
229+
Error(node.error, "Not in while loops");
230+
}
231+
232+
if (stack.length > whileStacks[$ - 1]) {
233+
StackOverflow(node, whileStacks[$ - 1]);
234+
}
235+
else if (stack.length < whileStacks[$ - 1]) {
236+
Error(node.error, "Stack underflow");
237+
}
238+
}
239+
225240
void EvaluateDef(LetNode node) {
226241
identifiers ~= node.name;
227242
}
@@ -233,6 +248,10 @@ class StackChecker {
233248
void EvaluateExtern(ExternNode node) {
234249
string name = node.asName == ""? node.func : node.asName;
235250

251+
if (name in words) {
252+
Error(node.error, "Word '%s' already exists", name);
253+
}
254+
236255
if (node.externType == ExternType.C) {
237256
words[name] = Word(
238257
Effect(node.retType == "void"? 0 : 1, node.types.length)
@@ -318,8 +337,8 @@ class StackChecker {
318337

319338
switch (wnode.name) {
320339
case "return": Pop(node, 1); break;
321-
case "continue": break;
322-
case "break": break;
340+
case "continue": EvaluateBreakContinue(wnode); break;
341+
case "break": EvaluateBreakContinue(wnode); break;
323342
case "call": Error(node.error, "Call is unsafe"); break;
324343
case "throw": Pop(node, 1); break;
325344
case "error": Error(node.error, "Error thrown by code"); break;

0 commit comments

Comments
 (0)