diff options
| -rw-r--r-- | tnslc/compile/function.tnsl | 26 | ||||
| -rw-r--r-- | tnslc/compile/scope.tnsl | 45 | ||||
| -rw-r--r-- | tnslc/parse/ast.tnsl | 2 | ||||
| -rw-r--r-- | tnslc/utils/algo.tnsl | 19 |
4 files changed, 91 insertions, 1 deletions
diff --git a/tnslc/compile/function.tnsl b/tnslc/compile/function.tnsl index 5db1bd3..1f0fb3f 100644 --- a/tnslc/compile/function.tnsl +++ b/tnslc/compile/function.tnsl @@ -240,7 +240,33 @@ struct Function { /; if (utils.strcmp(n`.data, "return\0") == true) # Compute value and return self._compile_value(s, n) + ;; else if (utils.strcmp(n`.data, "continue\0") == true) + ~Scope lp = s`.closest_loop() + /; if (lp == NULL) + return + ;/ + + ~uint8 lab = lp`.rep_label() + s`.cb`.add_c(" jmp \0") + s`.cb`.add_c(lab) + s`.cb`.add_c("\n\0") + ;; else if (utils.strcmp(n`.data, "break\0") == true) + ~Scope br = s`.closest_break() + /; if (br == NULL) + return + ;/ + + ~uint8 lab = br`.rep_label() + s`.cb`.add_c(" jmp \0") + s`.cb`.add_c(lab) + s`.cb`.add_c("\n\0") ;/ + + _printf("COMPILER ERROR: The following was detected as flow control, but we do not handle it: '\0") + _printf(n`.data) + _printf("'\n\0") + _printf("COMPILER ERROR: this is likely a bug with the compiler, please report it along with the\n\0") + _printf("COMPILER ERROR: code snippit which caused the bug!\n\0") ;/ # Should handle computing a value, delegate to other funcs when needed diff --git a/tnslc/compile/scope.tnsl b/tnslc/compile/scope.tnsl index 900d626..b7df075 100644 --- a/tnslc/compile/scope.tnsl +++ b/tnslc/compile/scope.tnsl @@ -241,6 +241,51 @@ struct Scope { return out ;/ + # Get closest breakable scope + + /; _closest_break [~Scope] + /; if (utils.ends_with(self.name, "#wrap\0")) + return ~self + ;; else if (utils.ends_with(self.name, "#loop\0")) + return ~self + ;/ + + /; if (self.parent == NULL) + return NULL + ;/ + + return self.parent`.closest_loop() + ;/ + + /; closest_break [~Scope] + /; if (self.parent == NULL) + return NULL + ;/ + + ~uint8 pname = self.parent`.name + /; if (utils.ends_with(pname, "#wrap\0")) + ~Scope par2 = self.parent`.parent + /; if (par2 !== NULL) + return par2`._closest_break() + ;/ + ;/ + + return self._closest_break() + ;/ + + # Get closest loop + /; closest_loop [~Scope] + /; if (utils.ends_with(self.name, "#loop\0")) + return ~self + ;/ + + /; if (self.parent == NULL) + return NULL + ;/ + + return self.parent`.closest_loop() + ;/ + # # Label generation diff --git a/tnslc/parse/ast.tnsl b/tnslc/parse/ast.tnsl index e38c413..f9ad1f9 100644 --- a/tnslc/parse/ast.tnsl +++ b/tnslc/parse/ast.tnsl @@ -2096,7 +2096,7 @@ int errors_shown = 0 ;; else if (first._type == TTYPE_KEYTP || first._type == TTYPE_USRWD || first.eq("~\0") == true || first.eq("{\0") == true) _ast_decl(fin, mod, ~first) ;; else - _ast_print_err(fin, ~first, "Expected 'import', 'struct', 'asm', block, or declaration in top level\0") + _ast_print_err(fin, ~first, "Expected 'import', 'struct', 'asm', block (starts with '/;'), or type (for variable declaration) in top level\0") Token tmp = produce_next_token(fin, first) first.end() diff --git a/tnslc/utils/algo.tnsl b/tnslc/utils/algo.tnsl index 49c4636..bde7b57 100644 --- a/tnslc/utils/algo.tnsl +++ b/tnslc/utils/algo.tnsl @@ -15,6 +15,25 @@ return out ;/ +/; ends_with (~uint8 str, suffix) [bool] + int chk = strlen(suffix) + int counter = 0 + + /; loop (str` !== 0) [str++] + /; if (suffix{counter} !== 0) + /; if (suffix{counter} == str`) + counter++ + ;; else + counter = 0 + ;/ + ;; else + counter = 0 + ;/ + ;/ + + return chk == counter +;/ + /; base_for_char (uint8 c) [int] /; if (c == 'b' || c == 'B') return 2 |