summaryrefslogtreecommitdiff
path: root/tnslc
diff options
context:
space:
mode:
authorKai Gunger <kgunger12@gmail.com>2025-12-30 23:16:01 -0500
committerKai Gunger <kgunger12@gmail.com>2025-12-30 23:16:01 -0500
commitaef2a1e4fae812220b29ec939be239cee5225b1a (patch)
tree7464ef01fb4957b8a4e726ea2072ce57ec677077 /tnslc
parent3a98cbd4d96041e78cb8748d674e9d5ea311054e (diff)
finding parent scopes
Diffstat (limited to 'tnslc')
-rw-r--r--tnslc/compile/function.tnsl26
-rw-r--r--tnslc/compile/scope.tnsl45
-rw-r--r--tnslc/parse/ast.tnsl2
-rw-r--r--tnslc/utils/algo.tnsl19
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