summaryrefslogtreecommitdiff
path: root/tnslc/compile/function.tnsl
diff options
context:
space:
mode:
authorKai Gunger <kgunger12@gmail.com>2026-04-29 02:21:38 -0400
committerKai Gunger <kgunger12@gmail.com>2026-04-29 02:21:38 -0400
commit84eb185812b70ec900ec8607bced68da440ae7a2 (patch)
treef337f2f2bd42fdbd4b5dcb382a5c449e7d4e3327 /tnslc/compile/function.tnsl
parent3af75072c6226932f7dae48c6fc34c4177e42c18 (diff)
[tnslc] Basic statement comp
Diffstat (limited to 'tnslc/compile/function.tnsl')
-rw-r--r--tnslc/compile/function.tnsl421
1 files changed, 369 insertions, 52 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)