summaryrefslogtreecommitdiff
path: root/tnslc/compile/function.tnsl
diff options
context:
space:
mode:
Diffstat (limited to 'tnslc/compile/function.tnsl')
-rw-r--r--tnslc/compile/function.tnsl253
1 files changed, 227 insertions, 26 deletions
diff --git a/tnslc/compile/function.tnsl b/tnslc/compile/function.tnsl
index cf42db1..eec65ed 100644
--- a/tnslc/compile/function.tnsl
+++ b/tnslc/compile/function.tnsl
@@ -1,36 +1,237 @@
struct Function {
- ~uint8 name,
- utils.Vector
- inputs,
- outputs,
- ~parse.Node body
+ ~uint8 name,
+ utils.Vector
+ inputs,
+ outputs,
+ ~parse.Node _up,
}
/; method Function
- /; init (~uint8 name)
- self.name = name
- Var v
- self.inputs.init(len v)
- self.outputs.init(len v)
- ;/
+ /; init (~parse.Node n)
+ self.name = utils.strcpy(n`.data)
+ self._up = n
+ Var v
+ self.inputs.init(len v)
+ self.outputs.init(len v)
+ ;/
- /; end
- _delete(self.name)
- self.body`.end()
+ /; _resolve_dlist (~Module parent, ~parse.Node dl)
+ ~parse.Node tn = NULL
+ ~parse.Node n
+ int reg = 1
+ int stack_down = 0
+ /; loop (int i = 0; i < dl`.sub.count) [i++]
+ n = dl`.sub.get(i)
+ /; if (n`._type == parse.NTYPE_TYPE)
+ tn = n
+ ;; else if (n`._type == parse.NTYPE_ID)
+ /; if (tn == NULL)
+ _printf("Identifier declared in parameter list before any type was found!\n\0")
+ return
+ ;/
+ Var p
+ p.init(tn, n)
+ p._resolve_type(parent)
+ /; if (p.is_reg_passed() == true && reg < 7)
+ p.loc = reg
+ reg++
+ ;; else
+ p.loc = 0
+ p.loc = p.loc - stack_down
+ stack_down = stack_down - p.actual_size()
+ ;/
+ self.inputs.push(~p)
+ ;/
+ ;/
+ ;/
- ~Var v
- /; loop (int i = 0; i < self.inputs.count) [i++]
- v = self.inputs.get(i)
- v`.end()
- ;/
- self.inputs.end()
+ /; _resolve_tlist (~Module parent, ~parse.Node tl)
+ ~parse.Node n
+ parse.Node dummy
+ dummy.data = "### OUTPUT ###\0"
+ /; loop (int i = 0; i < tl`.sub.count) [i++]
+ n = tl`.sub.get(i)
+ /; if (n`._type == parse.NTYPE_TYPE)
+ Var r
+ r.init(n, ~dummy)
+ r._resolve_type(parent)
+ self.outputs.push(~r)
+ ;/
+ ;/
+ ;/
- /; loop (int i = 0; i < self.outputs.count) [i++]
- v = self.outputs.get(i)
- v`.end()
- ;/
- self.outputs.end()
- ;/
+ /; _resolve_type (~Module parent)
+ ~parse.Node _up = self._up
+ /; if (_up`.sub.count < 1)
+ return
+ ;/
+
+ ~parse.Node lst = _up`.sub.get(0)
+ /; if (lst`._type == parse.NTYPE_DLIST)
+ self._resolve_dlist(parent, lst)
+ /; if (_up`.sub.count > 1)
+ lst = _up`.sub.get(1)
+ ;/
+ ;/
+
+ /; if (lst`._type == parse.NTYPE_TLIST)
+ self._resolve_tlist(parent, lst)
+ ;/
+ ;/
+
+ /; _build_func(~Module parent, ~CompBuf cb) [Scope]
+ Scope out
+ out.init(parent, cb, self.name)
+ out.parent = NULL
+
+ /; if (parent`.e == true)
+ # Add to the global exports if the parent is exported
+ ~uint8 bl = out.base_label()
+ cb`.add_h("global \0")
+ cb`.add_h(bl)
+ cb`.add_h("\n\0")
+ _delete(bl)
+ ;/
+
+ # Write label and opening
+ out.place_base_label()
+ cb`.add_c(" push rbp\n\0")
+ cb`.add_c(" lea rbp, [rsp + 8]\n\0")
+ cb`.add_c(" push r10\n\0")
+ cb`.add_c(" push r11\n\0")
+ cb`.add_c(" push r12\n\0")
+ cb`.add_c(" push r13\n\0")
+ cb`.add_c(" push r14\n\0")
+ cb`.add_c(" push r15 ; scope init\n\n\0")
+
+ # Add all params to the scope
+ ~Var in
+ /; loop (int i = 0; i < self.inputs.count) [i++]
+ in = self.inputs.get(i)
+ out.mk_set_var(in)
+ ;/
+
+ return out
+ ;/
+
+ /; _end_func(~Scope scope, ~CompBuf cb)
+ cb`.add_c(" lea rsp, [rbp - 56]\n\0")
+ cb`.add_c(" pop r15\n\0")
+ cb`.add_c(" pop r14\n\0")
+ cb`.add_c(" pop r13\n\0")
+ cb`.add_c(" pop r12\n\0")
+ cb`.add_c(" pop r11\n\0")
+ cb`.add_c(" pop r10\n\0")
+ cb`.add_c(" pop rbp\n\0")
+ cb`.add_c(" ret ; scope end\n\n\n\0")
+
+ scope`.end()
+ ;/
+
+ /; _compile (~Module parent, ~CompBuf cb)
+ # Sanity check
+ ~parse.Node _up = self._up
+ /; if (_up`.sub.count < 1)
+ ~Scope s = self._build_func(parent, cb)
+ self._end_func(s, cb)
+ return
+ ;/
+
+ # Skip past parameters and outputs
+ int i = 0
+ ~parse.Node n = _up`.sub.get(i)
+ /; if (n`._type == parse.NTYPE_DLIST)
+ i++
+ /; if (_up`.sub.count > 1)
+ n = _up`.sub.get(1)
+ ;/
+ ;/
+
+ /; if (n`._type == parse.NTYPE_TLIST)
+ i++
+ ;/
+
+ # Create scope
+ Scope fscope = self._build_func(parent, cb)
+
+
+ # Compile and then end scope
+ self._compile_statements(~fscope, i)
+ self._end_func(~fscope, cb)
+ ;/
+
+ #
+ # Compiling individual statements
+ #
+
+ /; _compile_statements (~Scope s, int off)
+ ~parse.Node _up = self._up
+ ~parse.Node n = NULL
+ /; loop (off < _up`.sub.count) [off++]
+ n = _up`.sub.get(off)
+ /; if (n`._type == parse.NTYPE_FLOW_CONTROL)
+ self._compile_flow_control(s, n)
+ ;; else if (n`._type == parse.NTYPE_ASM)
+ s`.cb`.add_c(" \0")
+ s`.cb`.add_c(n`.data)
+ s`.cb`.add_c(" ; User defined asm\n\0")
+ ;/
+ ;/
+ ;/
+
+ # Should handle break, continue, and return
+ /; _compile_flow_control (~Scope s, ~parse.Node n)
+ /; if (utils.strcmp(n`.data, "return\0") == true)
+ # Compute value and return
+ self._compile_value(s, n)
+ ;/
+ ;/
+
+ # Should handle computing a value, delegate to other funcs when needed
+ /; _compile_value (~Scope s, ~parse.Node n)
+ ;/
+
+ /; _print (int idt)
+ _indent(idt)
+ _printf("{ Function : \0")
+ _printf(self.name)
+ _printf("\n\0")
+
+ _indent(idt)
+ _printf(" inputs:\n\0")
+ ~Var prtv
+ /; loop (int i = 0; i < self.inputs.count) [i++]
+ prtv = self.inputs.get(i)
+ prtv`._print(idt + 1)
+ ;/
+
+ _indent(idt)
+ _printf(" outputs:\n\0")
+ /; loop (int i = 0; i < self.outputs.count) [i++]
+ prtv = self.outputs.get(i)
+ prtv`._print(idt + 1)
+ ;/
+
+ _indent(idt)
+ _printf("}\n\0")
+ ;/
+
+ /; end
+ _delete(self.name)
+
+ ~Var v
+ /; loop (int i = 0; i < self.inputs.count) [i++]
+ v = self.inputs.get(i)
+ v`.end()
+ ;/
+ self.inputs.end()
+
+ /; loop (int i = 0; i < self.outputs.count) [i++]
+ v = self.outputs.get(i)
+ v`.end()
+ ;/
+ self.outputs.end()
+ ;/
;/