diff options
| author | Kai Gunger <kgunger12@gmail.com> | 2026-04-29 02:21:38 -0400 |
|---|---|---|
| committer | Kai Gunger <kgunger12@gmail.com> | 2026-04-29 02:21:38 -0400 |
| commit | 84eb185812b70ec900ec8607bced68da440ae7a2 (patch) | |
| tree | f337f2f2bd42fdbd4b5dcb382a5c449e7d4e3327 | |
| parent | 3af75072c6226932f7dae48c6fc34c4177e42c18 (diff) | |
[tnslc] Basic statement comp
| -rw-r--r-- | tnslc/compile/function.tnsl | 421 | ||||
| -rw-r--r-- | tnslc/compile/scope.tnsl | 34 | ||||
| -rw-r--r-- | tnslc/compile/var.tnsl | 174 | ||||
| -rw-r--r-- | tnslc/test.tnsl | 8 |
4 files changed, 553 insertions, 84 deletions
diff --git a/tnslc/compile/function.tnsl b/tnslc/compile/function.tnsl index 69b069d..4735824 100644 --- a/tnslc/compile/function.tnsl +++ b/tnslc/compile/function.tnsl @@ -331,7 +331,7 @@ struct Function { out = self.outputs.get(i) tmp = s`.mk_tmp(out) - cmp = self._compile_value(s, val_node, out) + cmp = self._compile_value(s, val_node) tmp.set(s`.cb, ~cmp) cmp.end() tmps.push(~tmp) @@ -350,7 +350,7 @@ struct Function { tmps.end() ;; else out = self.outputs.get(0) - cmp = self._compile_value(s, n, out) + cmp = self._compile_value(s, n) out`.set(s`.cb, ~cmp) cmp.end() ;/ @@ -427,10 +427,18 @@ struct Function { _printf("'\n\0") return ;/ + + _printf("Looks like we found \"") + _printf(sub`.data) + _printf("\" for make setting\n\0") /; if (sub`.sub.count > 0) sub = sub`.sub.get(0) - Var val = self._compile_value(s, sub, v) + Var val = self._compile_value(s, sub) + # Need var name correct + _delete(val.name) + ~uint8 name = utils.strcpy(v`.name) + val.name = name s`.mk_set_var(~val) val.end() ;; else @@ -440,67 +448,349 @@ struct Function { ;/ ;/ - /; _compile_call(~Scope s, ~parse.Node n, ~Function f) [Var] + /; _compile_call(~Scope s, ~parse.Node params, ~Function f, ~Var self, bool mth) [Var] Var out return out ;/ - /; _compile_base_id (~Scope s, ~parse.Node n) [Var] - # First, check scope - ~Var found = s`.find_var(n`.data) + # Chain compilation functions get pretty long. Read at your own risk + + /; _compile_chain_r_post(~Scope s, ~parse.Node post, ~Var v) + # Post op type + /; if (utils.strcmp(post`.data, "(\0") == true) + _printf("TODO: tnslc does not yet support calling variables\n\0") + ;; else if (utils.strcmp(post`.data, "`\0") == true) + Var tmp = v`.de_ref() + v`.end() + v` = tmp + ;; else if (utils.strcmp(post`.data, "{\0") == true) + post = post`.sub.get(0) - # If that fails, do a search in the module - /; if (found == NULL) - utils.Vector v - v.init(8) - ~uint8 str = n`.data - v.push(~str) - found = s`.mod`.find(SEARCH_VAR, ~v) - v.end() + # make sure we store variable if it's in a register which may be overwritten + /; if (v`.loc > 0) + /; if (s`.is_tmp(v) == false) + Var tmp = s`.mk_tmp(v) + tmp.set(s`.cb, v) + v`.end() + v` = tmp + ;/ + ;/ + + # Compute index + Var idx = self._compile_value(s, post) + /; if (idx.loc == 6 || idx.loc == 5) + ~CompBuf buf = s`.cb + buf`.add_c(" mov rax, rdi\n\0") + idx.loc = 1 + ;/ + + # Take index and set result + Var tmp = v`.index(s`.cb, ~idx, 6) + + # Clear tmp + /; if (s`.is_tmp(v) == true) + s`.free_to(v, true) + ;/ + + v`.end() + idx.end() + v` = tmp + ;; else if (utils.strcmp(post`.data, "++\0") == true) + # Generate copy (make sure no refs) + Var copy = v`.copy() + /; loop (copy.is_ptr(0, 0) == true) + copy.ptr_pop() + ;/ + # Make tmp var + Var tmp = s`.mk_tmp(~copy) + copy.end() + # Set the new tmp to the value of the old + tmp.set(s`.cb, v) + # Increment the old + v`.inc(s`.cb) + v`.end() + v` = tmp + ;; else if (utils.strcmp(post`.data, "--\0") == true) + # Generate copy (make sure no refs) + Var copy = v`.copy() + /; loop (copy.is_ptr(0, 0) == true) + copy.ptr_pop() + ;/ + # Make tmp var + Var tmp = s`.mk_tmp(~copy) + copy.end() + # Set the new tmp to the value of the old + tmp.set(s`.cb, v) + # Decrement the old + v`.dec(s`.cb) + v`.end() + v` = tmp ;/ + ;/ - /; if (found !== NULL) - return found`.as_global() + /; _compile_chain_r_base (~Scope s, ~parse.Node base, ~utils.Vector v) [Var] + # Base case for dot chains + Var result + result.loc = 0 + + # Sanity + /; if (base`._type !== parse.NTYPE_ID) + _printf("TODO: tnslc does not currently support dot-chains with literals or non-identifiers as primary\n\0") + _printf(" will look into either intuiting the type from context or requiring a cast in the future\n\0") + v`.end() + v`.count = 0 + return result ;/ - ~Function f - utils.Vector v - v.init(8) - ~uint8 str = n`.data - v.push(~str) - /; if (s`.mod`.is_method() == true) - ~Module search_mod = s`.mod`.parent - f = search_mod`.find(SEARCH_FUNC, ~v) + # Check for var + ~Var vv = s`.find_var(base`.data) + /; if (vv == NULL) + # If could not find in scope then try to find in module + ~uint8 name = base`.data + v`.push(~name) + vv = s`.mod`.find(SEARCH_VAR, v) + /; if (vv !== NULL) + result = vv`.as_global() + v`.end() + v`.count = 0 + ;/ ;; else - f = s`.mod`.find(SEARCH_FUNC, ~v) + result = vv`.copy() + v`.end() + v`.count = 0 ;/ - v.end() - /; if (f !== NULL) - _printf("TODO: Function call\n\0") - Var out - return out + # If has a post op + /; if (base`.sub.count > 0) + ~parse.Node sub = base`.sub.get(0) + /; if (utils.strcmp(sub`.data, "(\0") == true) + /; if (vv !== NULL) + result.end() + result.loc = 0 + _printf("TODO: tnslc does not yet support calling variables\n\0") + return result + ;/ + + # Try to find function. Make sure scope not in method module first. + ~Module mod = s`.mod + /; if (mod`.is_method() == true) + mod = mod`.parent + ;/ + + # Already tried to find in module so can just use v for search. + ~Function to_call = mod`.find(SEARCH_FUNC, v) + + /; if (to_call == NULL) + _printf("ERROR: Unable to find function or variable with name \"\0") + _printf(base`.data) + _printf("\" in scope \"\0") + ~uint8 blab = s`.base_label() + _printf(blab) + _printf("\"\n\0") + _delete(blab) + v`.end() + v`.count = 0 + return result + ;/ + + # Do call + result = self._compile_call(s, sub, to_call, NULL, false) + + ;; else if (result.loc == 0) + # Exit + _printf("ERROR: Unable to find variable \"\0") + _printf(base`.data) + _printf("\" in scope \"\0") + ~uint8 blab = s`.base_label() + _printf(blab) + _printf("\"\n\0") + _delete(blab) + v`.end() + v`.count = 0 + return result + ;; else + self._compile_chain_r_post(s, sub, ~result) + ;/ ;/ - _printf("Could not find variable/function with identifier \"\0") - _printf(n`.data) - _printf("\" in scope \0") - ~uint8 bl = s`.base_label() - _printf(bl) - _delete(bl) - _printf("\n\0") - - Var out - return out + # Loop over all post-ops past the first + ~parse.Node post + /; loop (int i = 1; i < base`.sub.count) [i++] + post = base`.sub.get(i) + /; if (utils.strcmp(post`.data, "(\0") == true) + result.end() + result.loc = 0 + _printf("TODO: tnslc does not yet support calling variables\n\0") + v`.end() + v`.count = 0 + return result + ;/ + self._compile_chain_r_post(s, post, ~result) + ;/ + + return result ;/ - /; _compile_set (~Scope s, ~parse.Node n) [Var] - # TODO - Var out - return out + # Function: the very long one. + /; _compile_chain_r (~Scope s, ~parse.Node n, ~utils.Vector v) [Var] + ~parse.Node lhn = n`.sub.get(0) + Var working + working.loc = 0 + + /; if (utils.strcmp(lhn`.data, ".\0") == true) + working = self._compile_chain_r(s, lhn, v) + ;; else + working = self._compile_chain_r_base(s, lhn, v) + ;/ + + /; if (v`.count == 0) + /; if (working.loc == 0) + # If we have encountered an error or determined we could not find the variable for certain. + return working + ;/ + ;/ + + # Several points here: if have not found var or func yet need to try + # if we can't and there is a post-op, then we need to stop. + + ~parse.Node rhn = n`.sub.get(1) + # Sanity + /; if (rhn`._type !== parse.NTYPE_ID) + _printf("TODO: tnslc does not currently support dot-chains with literals or non-identifiers in the middle\n\0") + v`.end() + v`.count = 0 + working.loc = 0 + return working + ;/ + + /; if (v`.count !== 0) + # If we haven't yet found the var add to the vec and search the module + ~uint8 dat = rhn`.data + v`.push(~dat) + + ~Module mod = s`.mod + ~Var find = mod`.find(SEARCH_VAR, v) + + /; if (find !== NULL) + working = find`.as_global() + v`.end() + v`.count = 0 + ;/ + + # Then check for post-op. + /; if (rhn`.sub.count > 0) + ~parse.Node post_op = rhn`.sub.get(0) + /; if (utils.strcmp(post_op`.data, "(\0") == true) + # Try a call + /; if (find !== NULL) + _printf("TODO: TNSL doesn't currently have good support for function calling by value\n\0") + return working + ;/ + + # Try to find function. Does not matter if we are a module since this is multi-part search + ~Module mod = s`.mod + + # Already tried to find in module so can just use v for search. + ~Function to_call = mod`.find(SEARCH_FUNC, v) + + /; if (to_call == NULL) + _printf("ERROR: Unable to find function or variable with name \"\0") + _printf(rhn`.data) + _printf("\" in scope \"\0") + ~uint8 blab = s`.base_label() + _printf(blab) + _printf("\"\n\0") + _delete(blab) + v`.end() + v`.count = 0 + return working + ;/ + + # Do call + working = self._compile_call(s, post_op, to_call, NULL, false) + ;; else if (working.loc == 0) + # Didn't find a variable but there was a post op + _printf("ERROR: Failed to find variable (dot chain ends in \"\0") + _printf(rhn`.data) + _printf("\" in scope \"\0") + ~uint8 blab = s`.base_label() + _printf(blab) + _printf("\"\n\0") + _delete(blab) + v`.end() + v`.count = 0 + return working + ;; else + # Do the post op on the found variable + self._compile_chain_r_post(s, post_op, ~working) + ;/ + ;/ + ;; else + # We already have a var, not doing anything with the vector any more + + # Check method call + int post_idx = 0 + /; if (rhn`.sub.count > 0) + ~parse.Node post = rhn`.sub.get(0) + /; if (utils.strcmp(post`.data, "(\0") == true) + # Try method + post_idx++ + ~Function to_call = working.find_method(rhn`.data) + + /; if (to_call == NULL) + working.end() + working.loc = 0 + return working + ;/ + + # Create space for the variable in a tmp + Var result = self._compile_call(s, post, to_call, ~working, true) + working.end() + working = result + ;/ + ;/ + + /; if (post_idx == 0) + # Normal member + Var mbr = working.member(s`.cb, rhn`.data) + + /; if (mbr.loc == 0) + # If the member didn't exist we end here + # The member function already prints some info + working.end() + working.loc = 0 + return working + ;/ + + working.end() + working = mbr + + /; if (rhn`.sub.count > 0) + # Do first post-op after the member + ~parse.Node post = rhn`.sub.get(0) + self._compile_chain_r_post(s, post, ~working) + ;/ + ;/ + ;/ + + # Loop over rest of post ops + ~parse.Node post + /; loop (int i = 1; i < rhn`.sub.count) [i++] + post = rhn`.sub.get(i) + self._compile_chain_r_post(s, post, ~working) + ;/ + + return working ;/ /; _compile_chain(~Scope s, ~parse.Node n) [Var] + # FIND_VAR!!!!! + utils.Vector chain + chain.init(8) + return self._compile_chain_r(s, n, ~chain) + ;/ + + /; _compile_set (~Scope s, ~parse.Node n) [Var] Var out return out ;/ @@ -518,7 +808,7 @@ struct Function { /; if (utils.strcmp(n`.data, "=\0") == true) Var rhs = self._compile_value(s, rhn) # TODO: move rhs maybe if it is in rdi - Var lhs = self._compile_value(s, lhn) + Var lhs = self._compile_set(s, lhn) lhs.set(s`.cb, ~rhs) rhs.end() return lhs @@ -551,12 +841,16 @@ struct Function { ;; else if (utils.strcmp(n`.data, "^\0") == true) lhs.xor(s`.cb, ~rhs) ;/ + + /; if (s`.is_tmp(~rhs) == true) + s`.free_to(~rhs, true) + ;/ rhs.end() return lhs ;/ - /; _compile_pre (~Scope s, ~parse.Node n, ~Var type_hint) [Var] + /; _compile_pre (~Scope s, ~parse.Node n) [Var] Var out /; if (utils.strcmp(n`.data, "-\0") == true) @@ -568,18 +862,24 @@ struct Function { out = self._compile_value(s, sub) out.not(s`.cb) ;; else if (utils.strcmp(n`.data, "~\0") == true) - _printf("~ not impl\n\0") + ~parse.Node sub = n`.sub.get(0) + Var tmp = self._compile_value(s, sub) + out = tmp.take_ptr(s`.cb, 5) + tmp.end() ;; else if (utils.strcmp(n`.data, "--\0") == true) - _printf("-- not impl\n\0") + ~parse.Node sub = n`.sub.get(0) + out = self._compile_value(s, sub) + out.dec(s`.cb) ;; else if (utils.strcmp(n`.data, "++\0") == true) - _printf("++ not impl\n\0") + ~parse.Node sub = n`.sub.get(0) + out = self._compile_value(s, sub) + out.inc(s`.cb) ;; else if (utils.strcmp(n`.data, "len\0") == true) _printf("len not impl\n\0") ;; else _printf("COMPILER ERROR: \"\0") _printf(n`.data) _printf("\" NOT RECOGNIZED AS A VALID PREOP\n\0") - out = type_hint`.copy() ;/ return out @@ -613,6 +913,16 @@ struct Function { ~Struct t = self._find_literal_type(s, "void\0") out._init(t) out.offset = 0 + out.ptr_push(1) + ;; else if (n`.data{0} == '\'') + ~Struct t = self._find_literal_type(s, "uint8\0") + out._init(t) + ~uint8 dat = n`.data + dat++ + uint8 val = utils.unquote_cha(dat) + out.offset = val + ;; else if (n`.data{0} == '\"') + _printf("TODO: in-function strings\n\0") ;; else ~Struct t = self._find_literal_type(s, "int\0") out._init(t) @@ -632,7 +942,14 @@ struct Function { return self._compile_literal(s, n) ;; else if (n`._type == parse.NTYPE_ID) - return self._compile_base_id(s, n) + utils.Vector tmp + tmp.init(8) + Var out = self._compile_chain_r_base(s, n, ~tmp) + /; if (tmp.count !== 0) + tmp.end() + ;; else if (out.loc !== 0) + return out + ;/ ;; else if (n`._type == parse.NTYPE_PRE_OP) return self._compile_pre(s, n) diff --git a/tnslc/compile/scope.tnsl b/tnslc/compile/scope.tnsl index a9cbef7..81f4f4b 100644 --- a/tnslc/compile/scope.tnsl +++ b/tnslc/compile/scope.tnsl @@ -288,6 +288,11 @@ struct Scope { return out ;/ + _printf("ERROR: Found variable \"\0") + _printf(name) + _printf("\" but it doesn't look like it's been initialized yet!\n\0") + _print_num(" Loc: %d\n\0", out`.loc) + _print_num(" Offset: %d\n\0", out`.offset) return NULL ;/ @@ -330,6 +335,9 @@ struct Scope { ;/ /; mk_set_var (~Var src) [~Var] + _printf("Make setting \"\0") + _printf(src`.name) + _printf("\"\n\0") ~Var v = self.mk_var(src) /; if (v == NULL) @@ -417,6 +425,32 @@ struct Scope { return false ;/ + /; free_to (~Var tmp, bool code) + # TODO:DETERMINE HOW MANY TMPS + int tmps = 0 + ~Var v + /; loop (int i - 1; i !> self.tmps.count) [i++] + v = self.tmps.get(self.tmps.count - i) + /; if (v`.offset == tmp`.offset) + tmps = self.tmps.count + tmps = tmps - i + tmps = tmps + 1 + ;/ + ;/ + + /; if (tmps !== 0) + self.free_tmp(tmps, code) + ;; else + ~uint8 scope_name = self.base_label() + int off = tmp`.offset + _printf("COMPILER ERROR: Unable to find temp to free to in scope \"\0") + _printf(scope_name) + _printf("\"\n\0") + _print_num(" Was looking for tmp with offset %d but could not find one.\n\0", off) + ;/ + + ;/ + # # Sub scope # diff --git a/tnslc/compile/var.tnsl b/tnslc/compile/var.tnsl index 8d1c597..e5e6bae 100644 --- a/tnslc/compile/var.tnsl +++ b/tnslc/compile/var.tnsl @@ -312,6 +312,23 @@ struct Var { return self._type`.size ;/ + /; find_method (~uint8 name) [~Function] + ~int32 p + /; loop (int i = 0; i < self.ptrc.count) [i++] + p = self.ptrc.get(i) + /; if (p` !== 0) + _printf("ERROR: Tried to find method \"\0") + _printf(name) + _printf("\" on a variable but we had a pointer in the chain\n\0") + return false + ;/ + ;/ + + ~Module mod = self._type`.methods + ~Function out = mod`._find_func(name) + return out + ;/ + ##################################### # Variable manipulation (comp time) # ##################################### @@ -1203,9 +1220,9 @@ struct Var { /; take_ptr (~CompBuf buf, int reg) [Var] Var vcpy = self.copy() /; if (self.in_mem() == false) - _printf("COMPILER ERROR: UNABLE TO GET REFERENCE OF VAR \"\0") + _printf("ERROR: UNABLE TO GET REFERENCE OF VAR \"\0") _printf(self.name) - _printf("\" PLEASE REPORT THIS BUG!\n\0") + _printf("\"\n\0") return vcpy ;/ @@ -1248,6 +1265,97 @@ struct Var { return vcpy ;/ + /; _de_ref + uint idx = self.ptrc.count + ~int32 ptr + /; loop (idx > 0) + idx = idx - 1 + ptr = self.ptrc.get(idx) + /; if (ptr` !== 0) + /; if (ptr` > 0) + _printf("ERROR: Can't take direct de-ref of array variable, try an index (name: \"\0") + _printf(self.name) + _printf("\")\n\0") + ;; else + ptr` = 0 + ;/ + return + ;/ + ;/ + ;/ + + /; de_ref [Var] + Var out = self.copy() + out._de_ref() + return out + ;/ + + /; index (~CompBuf buf, ~Var idx, int reg) [Var] + buf`.add_c(" ; Gen index\n\0") + + # Create a literal with the size of the type + # Don't need to init or end this one + uint mul_sz = self.type_size() + Var oo + oo.offset = mul_sz + oo.loc = 0 + + # Generate output variable + Var out = self.copy() + out.offset = 0 + out.loc = reg + + # Strip off any refs + /; loop (out.is_ref() == true) + out.ptr_pop() + ;/ + + # Multiply index by size of type + out.set(buf, idx) + out.mul(buf, ~oo) + + # If we are an array, want to add 8 since the beginning encodes the length + /; if (out.is_arr() == true) + oo.offset = 8 + out.add(buf, ~oo) + ;/ + + # Get address in rsi + ~uint8 to_str = self._set_prim_l(buf) + + # If we are a "known length array" we need to lea instead of mov + ~int32 optrc = out.top_ptrc() + /; if (optrc !== NULL) + /; if (optrc` > 1) + buf`.add_c(" lea rsi, \0") + ;; else + buf`.add_c(" mov rsi, \0") + ;/ + ;; else + _printf("ERROR: Can't take index of non-array variable \"\0") + _printf(self.name) + _printf("\"\n\0") + _delete(to_str) + return out + ;/ + buf`.add_c(to_str) + buf`.add_c("\n\0") + _delete(to_str) + + # Add address to computed offset + to_str = out._set_prim_l(buf) + buf`.add_c(" add \0") + buf`.add_c(to_str) + buf`.add_c(", rsi\n\0") + + # deref + int32 ptr_ref = 0 + out.ptr_pop() + out.ptr_push(ptr_ref) + + return out + ;/ + ####################### # Standard operations # ####################### @@ -1455,14 +1563,11 @@ struct Var { self._div(buf, other, 4) ;/ - /; not (~CompBuf buf) - /; if (self.loc == VLOC_LITL) - self.offset = !self.offset - return - ;/ - + /; _unary (~CompBuf buf, ~uint8 op) ~uint8 to_str = self._set_prim_l(buf) - buf`.add_c(" not \0") + buf`.add_c(" \0") + buf`.add_c(op) + buf`.add_c(" \0") /; if (self.in_mem() == true) uint sz = self.type_size() /; if (sz == 1) @@ -1480,6 +1585,15 @@ struct Var { _delete(to_str) ;/ + /; not (~CompBuf buf) + /; if (self.loc == VLOC_LITL) + self.offset = !self.offset + return + ;/ + + self._unary(buf, "not\0") + ;/ + /; neg (~CompBuf buf) /; if (self.loc == VLOC_LITL) int off = 0 @@ -1487,23 +1601,25 @@ struct Var { return ;/ - ~uint8 to_str = self._set_prim_l(buf) - buf`.add_c(" neg \0") - /; if (self.in_mem() == true) - uint sz = self.type_size() - /; if (sz == 1) - buf`.add_c("byte \0") - ;; else if (sz == 2) - buf`.add_c("word \0") - ;; else if (sz == 4) - buf`.add_c("dword \0") - ;; else if (sz == 8) - buf`.add_c("qword \0") - ;/ + self._unary(buf, "neg\0") + ;/ + + /; inc (~CompBuf buf) + /; if (self.loc == VLOC_LITL) + self.offset++ + return ;/ - buf`.add_c(to_str) - buf`.add_c("\n\0") - _delete(to_str) + + self._unary(buf, "inc\0") + ;/ + + /; dec (~CompBuf buf) + /; if (self.loc == VLOC_LITL) + self.offset++ + return + ;/ + + self._unary(buf, "dec\0") ;/ /; member (~CompBuf buf, ~uint8 name) [Var] @@ -1514,7 +1630,9 @@ struct Var { _printf(self._type`.name) _printf("\"\n\0") _printf(" (If the previous type was in fact a structure then the variable was probably a pointer)\n\0") - return self.copy() + Var out + out.loc = 0 + return out ;/ ~Var mbr = self`._type`.get_member(name) @@ -1525,7 +1643,9 @@ struct Var { _printf("\" not found in struct \"\0") _printf(self._type`.name) _printf("\n\0") - return self.copy() + Var out + out.loc = 0 + return out ;/ Var out = mbr`.copy() diff --git a/tnslc/test.tnsl b/tnslc/test.tnsl index 7bf76ce..3c89339 100644 --- a/tnslc/test.tnsl +++ b/tnslc/test.tnsl @@ -1,9 +1,7 @@ -/; five [int] - return 5 -;/ -/; main (int argc, ~~uint8 argv) [int] - return five() +/; main [int] + int a = 0 + return a ;/ |