summaryrefslogtreecommitdiff
path: root/tnslc/compile
diff options
context:
space:
mode:
Diffstat (limited to 'tnslc/compile')
-rw-r--r--tnslc/compile/codegen.tnsl118
-rw-r--r--tnslc/compile/compbuf.tnsl45
-rw-r--r--tnslc/compile/compile.tnsl10
-rw-r--r--tnslc/compile/function.tnsl442
-rw-r--r--tnslc/compile/generate.tnsl6
-rw-r--r--tnslc/compile/module.tnsl444
-rw-r--r--tnslc/compile/scope.tnsl502
-rw-r--r--tnslc/compile/struct.tnsl281
-rw-r--r--tnslc/compile/type.tnsl360
-rw-r--r--tnslc/compile/var.tnsl547
10 files changed, 2387 insertions, 368 deletions
diff --git a/tnslc/compile/codegen.tnsl b/tnslc/compile/codegen.tnsl
new file mode 100644
index 0000000..05d0fb7
--- /dev/null
+++ b/tnslc/compile/codegen.tnsl
@@ -0,0 +1,118 @@
+/; _indent (int idt)
+ /; loop (int i = 0; i < idt) [i++]
+ _printf(" \0")
+ ;/
+;/
+
+/; parse_tree(~utils.File fin)
+ # Parse files into AST
+ parse.Node ast = parse.generate_ast(fin)
+ ast.update_children()
+
+ # Print parse tree
+ parse.print_ast(~ast)
+
+ ast.end()
+;/
+
+/; mod_tree(~utils.File fin)
+ # Parse files into AST
+ parse.Node ast = parse.generate_ast(fin)
+ ast.update_children()
+
+ # Create output buffer
+ CompBuf buffer
+ buffer.init()
+
+ Module mod
+ mod.init(~ast, ~buffer)
+ _gen_prims(~mod)
+ mod.update_children()
+ mod.collect_methods(~ast)
+
+ # Compile code
+ mod.compile(~buffer)
+
+ mod.print()
+
+ # Free all structs
+ mod.end()
+ buffer.end()
+ ast.end()
+;/
+
+/; generate (~utils.File fin, fout)
+ # Parse files into AST
+ parse.Node ast = parse.generate_ast(fin)
+ ast.update_children()
+
+ # Create output buffer
+ CompBuf buffer
+ buffer.init()
+
+ # Transform into a module tree
+ Module mod
+ mod.init(~ast, ~buffer)
+ _gen_prims(~mod)
+ mod.update_children()
+ mod.collect_methods(~ast)
+
+ # Compile code
+ mod.compile(~buffer)
+
+ # Write assembly to output file
+ fout.create()
+ buffer.write_to(fout)
+ fout.close()
+
+ # Free all structs
+ mod.end()
+ buffer.end()
+ ast.end()
+;/
+
+# Generate a primitive type with the specified size and specified name
+/; _gen_prim(~Module m, int size, ~uint8 id)
+ ~Module mds = m`._create_methods(id)
+
+ Var t
+
+ Struct s
+ s.size = size
+ s.methods = NULL
+ s.members.init(len t)
+ s.name = utils.strcpy(id)
+ s._up = NULL
+
+ m`.structs.push(~s)
+;/
+
+# This function generates the generic language primitives on
+# the root module so that resolution will work when creating
+# a variable or struct
+/; _gen_prims (~Module m)
+
+ # One byte prims
+ _gen_prim(m, 1, "bool\0")
+ _gen_prim(m, 1, "uint8\0")
+ _gen_prim(m, 1, "int8\0")
+
+ # Two byte prims
+ _gen_prim(m, 2, "uint16\0")
+ _gen_prim(m, 2, "int16\0")
+
+ # Four byte prims
+ _gen_prim(m, 4, "uint32\0")
+ _gen_prim(m, 4, "int32\0")
+ _gen_prim(m, 4, "float32\0")
+
+ # Eight byte prims
+ _gen_prim(m, 8, "uint64\0")
+ _gen_prim(m, 8, "int64\0")
+ _gen_prim(m, 8, "float64\0")
+ _gen_prim(m, 8, "uint\0")
+ _gen_prim(m, 8, "int\0")
+ _gen_prim(m, 8, "float\0")
+ _gen_prim(m, 8, "void\0")
+;/
+
diff --git a/tnslc/compile/compbuf.tnsl b/tnslc/compile/compbuf.tnsl
new file mode 100644
index 0000000..d4bc640
--- /dev/null
+++ b/tnslc/compile/compbuf.tnsl
@@ -0,0 +1,45 @@
+
+struct CompBuf {
+ utils.Vector
+ sec_head,
+ sec_data,
+ sec_code
+}
+
+/; method CompBuf
+ /; init
+ self.sec_head.init(1)
+ self.sec_data.init(1)
+ self.sec_code.init(1)
+ ;/
+
+ /; add_h(~uint8 text)
+ self.sec_head.push_cstr(text)
+ ;/
+
+ /; add_d(~uint8 text)
+ self.sec_data.push_cstr(text)
+ ;/
+
+ /; add_c(~uint8 text)
+ self.sec_code.push_cstr(text)
+ ;/
+
+ /; write_to(~utils.File fout)
+ fout`.write_cstr("BITS 64\n\0")
+ fout`.write_cstr(self.sec_head.as_cstr())
+
+ fout`.write_cstr("\nsection .data\n\n\0")
+ fout`.write_cstr(self.sec_data.as_cstr())
+
+ fout`.write_cstr("\nsection .text\n\n\0")
+ fout`.write_cstr(self.sec_code.as_cstr())
+ ;/
+
+ /; end
+ self.sec_head.end()
+ self.sec_data.end()
+ self.sec_code.end()
+ ;/
+;/
+
diff --git a/tnslc/compile/compile.tnsl b/tnslc/compile/compile.tnsl
index 3560f48..fbb9670 100644
--- a/tnslc/compile/compile.tnsl
+++ b/tnslc/compile/compile.tnsl
@@ -1,4 +1,10 @@
/; module compile
- :import "type.tnsl"
- :import "generate.tnsl"
+ :import "compbuf.tnsl"
+ :import "struct.tnsl"
+ :import "var.tnsl"
+ :import "function.tnsl"
+ :import "module.tnsl"
+ :import "codegen.tnsl"
+ :import "scope.tnsl"
;/
+
diff --git a/tnslc/compile/function.tnsl b/tnslc/compile/function.tnsl
new file mode 100644
index 0000000..6f7fceb
--- /dev/null
+++ b/tnslc/compile/function.tnsl
@@ -0,0 +1,442 @@
+
+struct Function {
+ ~uint8 name,
+ utils.Vector
+ inputs,
+ outputs,
+ ~parse.Node _up,
+ bool m
+}
+
+/; method Function
+ /; init (~parse.Node n)
+ self.name = utils.strcpy(n`.data)
+ self._up = n
+ self.m = false
+ Var v
+ self.inputs.init(len v)
+ self.outputs.init(len v)
+ ;/
+
+ /; _resolve_dlist (~Module parent, ~parse.Node dl)
+ ~parse.Node tn = NULL
+ ~parse.Node n
+ int reg = 1
+ int stack_up = 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)
+ # TODO: This is wrong
+ /; if (p.regable() == true && reg < 7)
+ p.loc = reg
+ reg++
+ ;; else
+ p.loc = 0 - 1
+ p.offset = stack_up
+ stack_up = stack_up + p.actual_size()
+ ;/
+ self.inputs.push(~p)
+ ;/
+ ;/
+ ;/
+
+ /; _resolve_tlist (~Module parent, ~parse.Node tl)
+ ~parse.Node n
+ parse.Node dummy
+ dummy.data = "### OUTPUT ###\0"
+
+ int reg = 1
+ int stack = 0
+ /; loop (int i = 0; i < tl`.sub.count) [i++]
+ n = tl`.sub.get(i)
+ /; if (n`._type == parse.NTYPE_TYPE)
+ # TODO: also wrong
+ Var r
+ r.init(n, ~dummy)
+ r._resolve_type(parent)
+
+ /; if (r.regable() == true && reg < 7)
+ r.loc = reg
+ /; if (reg > 4)
+ r.loc = r.loc + 4
+ ;/
+ reg++
+ ;; else
+ r.loc = 0 - 1
+ r.offset = stack
+ stack = stack + r.actual_size()
+ ;/
+
+ self.outputs.push(~r)
+ ;/
+ ;/
+ ;/
+
+ /; _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)
+ ;/
+ ;/
+
+ /; _compute_scope_vars(~Scope s)
+
+ ~Var in
+ /; loop (int i = 0; i < self.inputs.count) [i++]
+ in = self.inputs.get(i)
+ s`.mk_aware(in)
+ ;/
+
+ int i = self._first_stmt_off()
+ /; if (i < 0)
+ return
+ ;/
+
+ ~parse.Node _up = self._up
+ ~parse.Node n
+ /; loop (i < _up`.sub.count) [i++]
+ n = _up`.sub.get(i)
+ /; if (n`._type == parse.NTYPE_DECL)
+ s`.mk_aware_node(n)
+ ;; else
+ s`.precheck_stmt(n)
+ ;/
+ ;/
+ ;/
+
+ /; _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")
+
+ self._compute_scope_vars(~out)
+
+ # 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("\n\0")
+ scope`.place_end_label()
+ 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()
+ ;/
+
+ /; _first_stmt_off [int]
+ int i = 0
+ ~parse.Node _up = self._up
+
+ /; if (_up`.sub.count < 1)
+ return i - 1
+ ;/
+
+ ~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++
+ ;/
+
+ return i
+ ;/
+
+ /; _compile (~Module parent, ~CompBuf cb)
+ # Sanity check
+ int i = self._first_stmt_off()
+
+ # Create scope
+ Scope fscope = self._build_func(parent, cb)
+
+ /; if (i !< 0)
+ self._compile_statements(~fscope, i)
+ ;/
+
+ # Compile and then end scope
+ 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")
+ ;; else if (n`._type == parse.NTYPE_DECL)
+ self._compile_decl(s, n)
+ ;/
+ ;/
+ ;/
+
+ /; _check_return (~parse.Node n) [bool]
+ int expected = self.outputs.count
+ int have = 0
+
+ ~parse.Node val
+ /; if (n`.sub.count > 0)
+ val = n`.sub.get(0)
+ val = val`.sub.get(0)
+ /; if (expected > 1 && val`._type == parse.NTYPE_VLIST)
+ have = val`.sub.count
+ ;; else
+ have = 1
+ ;/
+ ;/
+
+ /; if (have == expected)
+ return true
+ ;/
+
+ _print_num("ERROR: Number of return values (%d) does not match expected (\0", have)
+ _print_num("%d)\n\0", expected)
+ _printf("ERROR: A list of return values should be enclosed by {}\n\0")
+
+ return false
+ ;/
+
+ /; _compile_return_vals (~Scope s, ~parse.Node n)
+ _printf("Compiling return vals!\n\0")
+ /; if (self.outputs.count == 0)
+ return
+ ;/
+
+ /; if (self.outputs.count > 1)
+ n = n`.sub.get(0)
+ n = n`.sub.get(0)
+ ;/
+
+ ~Var out
+ Var tmp, cmp
+ utils.Vector tmps
+ tmps.init(len cmp)
+
+ s`.cb`.add_c("\n ; STARTING RETURN\n\0")
+
+ # Compile all values
+ ~parse.Node val_node
+ /; loop (int i = 0; i < self.outputs.count) [i++]
+ val_node = n`.sub.get(i)
+ out = self.outputs.get(i)
+
+ tmp = s`.mk_tmp(out)
+ cmp = self._compile_value(s, val_node, out)
+ tmp.set(s`.cb, ~cmp)
+ cmp.end()
+ tmps.push(~tmp)
+ ;/
+
+ # Set all outputs
+ ~Var tt
+ /; loop (int i = 0; i < self.outputs.count) [i++]
+ out = self.outputs.get(i)
+ tt = tmps.get(i)
+ out`.set(s`.cb, tt)
+ tt`.end()
+ ;/
+
+ s`.free_tmp(tmps.count, false)
+ tmps.end()
+ ;/
+
+ /; _return (~Scope s, ~parse.Node n)
+ /; if (self._check_return(n) !== true)
+ return
+ ;/
+
+ # Compute all return values and set the output variables properly
+ self._compile_return_vals(s, n)
+
+ # Find root scope of function
+ /; loop (s`.parent !== NULL)
+ s = s`.parent
+ ;/
+
+ # Generate jump instruction
+ ~uint8 lab = s`.end_label()
+ s`.cb`.add_c(" jmp \0")
+ s`.cb`.add_c(lab)
+ s`.cb`.add_c("\n\0")
+ _delete(lab)
+ ;/
+
+ # 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._return(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")
+ _delete(lab)
+ ;; 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")
+ _delete(lab)
+ ;; else
+ _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 variable declarations
+ /; _compile_decl(~Scope s, ~parse.Node n)
+ ~parse.Node sub
+ /; loop (int i = 0; i < n`.sub.count) [i++]
+ sub = n`.sub.get(i)
+ /; if (sub`._type == parse.NTYPE_ID)
+ ~Var v = s`._find_var(sub`.data)
+
+ /; if (v == NULL)
+ _printf("Failed to find variable '\0")
+ _printf(sub`.data)
+ _printf("'\n\0")
+ return
+ ;/
+
+ /; if (sub`.sub.count > 0)
+ sub = sub`.sub.get(0)
+ Var val = self._compile_value(s, sub, v)
+ s`.mk_set_var(~val)
+ val.end()
+ ;; else
+ s`.mk_var(v)
+ ;/
+ ;/
+ ;/
+ ;/
+
+ # Should handle computing a value, delegate to other funcs when needed
+ /; _compile_value (~Scope s, ~parse.Node n, ~Var type_hint) [Var]
+ Var out = type_hint`.copy()
+ return out
+ ;/
+
+ /; _print (int idt)
+ _indent(idt)
+ _printf("{ Function : \0")
+ _printf(self.name)
+ _printf("\n\0")
+
+ _indent(idt + 1)
+ _printf("inputs:\n\0")
+ ~Var prtv
+ /; loop (int i = 0; i < self.inputs.count) [i++]
+ prtv = self.inputs.get(i)
+ prtv`._print(idt + 2)
+ ;/
+
+ _indent(idt + 1)
+ _printf("outputs:\n\0")
+ /; loop (int i = 0; i < self.outputs.count) [i++]
+ prtv = self.outputs.get(i)
+ prtv`._print(idt + 2)
+ ;/
+
+ _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()
+ ;/
+;/
+
diff --git a/tnslc/compile/generate.tnsl b/tnslc/compile/generate.tnsl
deleted file mode 100644
index ef6a76c..0000000
--- a/tnslc/compile/generate.tnsl
+++ /dev/null
@@ -1,6 +0,0 @@
-/; generate (~utils.File fin, fout)
- parse.Node n = parse.generate_ast(fin)
- n.update_children()
- parse.print_ast(~n)
- n.end()
-;/
diff --git a/tnslc/compile/module.tnsl b/tnslc/compile/module.tnsl
new file mode 100644
index 0000000..f20b84b
--- /dev/null
+++ b/tnslc/compile/module.tnsl
@@ -0,0 +1,444 @@
+
+int SEARCH_VAR = 0
+int SEARCH_STRUCT = 1
+int SEARCH_FUNC = 2
+int SEARCH_SUB = 3
+
+struct Module {
+ # Text name of module
+ ~uint8 name,
+
+ # Various contained elements
+ utils.Vector
+ vars,
+ structs,
+ funcs,
+ subs,
+
+ # Whether we export or not
+ bool e,
+
+ # Parent module
+ ~Module parent
+}
+
+/; method Module
+
+ /; _init
+ Var v
+ Struct s
+ Function f
+ Module m
+
+ self.parent = NULL
+
+ self.vars.init(len v)
+ self.structs.init(len s)
+ self.funcs.init(len f)
+ self.subs.init(len m)
+ ;/
+
+ /; init (~parse.Node mod, ~CompBuf buf)
+ self._init()
+ self.name = utils.strcpy(mod`.data)
+ self.e = mod`._type == parse.NTYPE_EXPORT
+
+ self._from_tree(mod, buf)
+ ;/
+
+ /; update_children
+ ~Module sub
+ /; loop (int i = 0; i < self.subs.count) [i++]
+ sub = self.subs.get(i)
+ sub`.update_children()
+ sub`.parent = ~self
+ ;/
+
+ ~Struct str
+ utils.Vector n
+ /; loop (int i = 0; i < self.structs.count) [i++]
+ str = self.structs.get(i)
+
+ n.from_cstr("_#\0")
+ n.push_cstr(str`.name)
+
+ sub = self._find_sub(n.as_cstr())
+ str`.methods = sub
+
+ n.end()
+ ;/
+ ;/
+
+ /; _create_methods (~uint8 name) [~Module]
+ utils.Vector n
+ n.from_cstr("_#\0")
+ n.push_cstr(name)
+
+ Module m
+ m._init()
+ m.name = n.as_cstr()
+ m.e = self.e
+ self.subs.push(~m)
+
+ int i = self.subs.count - 1
+ ~Module out = self.subs.get(i)
+ return out
+ ;/
+
+ /; _from_tree (~parse.Node mod, ~CompBuf buf)
+ ~parse.Node sub
+ /; loop (int i = 0; i < mod`.sub.count) [i++]
+ sub = mod`.sub.get(i)
+
+ # TODO: Vars, Enums, Method blocks
+
+ /; if (sub`._type == parse.NTYPE_MODULE)
+ Module m
+ m.init(sub, buf)
+ self.subs.push(~m)
+ ;; else if (sub`._type == parse.NTYPE_EXPORT)
+ Module m
+ m.init(sub, buf)
+ self.subs.push(~m)
+ ;; else if (sub`._type == parse.NTYPE_STRUCT)
+ ~Module m = self._create_methods(sub`.data)
+ Struct s
+ s.init(sub)
+ self.structs.push(~s)
+ ;; else if (sub`._type == parse.NTYPE_FUNCTION)
+ Function f
+ f.init(sub)
+ self.funcs.push(~f)
+ ;; else if (sub`._type == parse.NTYPE_DECL)
+ self._decl(sub)
+ ;; else if (sub`._type == parse.NTYPE_ASM)
+ buf`.add_h(sub`.data)
+ buf`.add_h("\n\0")
+ ;/
+ ;/
+ ;/
+
+ /; _method_id (~uint8 id) [utils.Vector]
+ utils.Vector tmp
+ tmp.init(1)
+ utils.Vector out
+ out.init(8)
+
+ ~uint8 str
+
+ /; loop (id` !== 0) [id++]
+ /; if (id` == '.')
+ str = tmp.as_cstr()
+ out.push(~str)
+ tmp.init(1)
+ ;; else
+ tmp.push(id)
+ ;/
+ ;/
+
+ str = tmp.as_cstr()
+ ~uint8 last = utils.stradd("_#\0", str)
+ _delete(str)
+ out.push(~last)
+
+ return out
+ ;/
+
+ /; _method_id_end(~utils.Vector v)
+ ~~uint8 str
+ /; loop (int i = 0; i < v`.count) [i++]
+ str = v`.get(i)
+ _delete(str`)
+ ;/
+ v`.end()
+ ;/
+
+ /; _collect_methods(~parse.Node m)
+ ~parse.Node sub
+ /; loop (int i = 0; i < m`.sub.count) [i++]
+ sub = m`.sub.get(i)
+
+ /; if (sub`._type == parse.NTYPE_FUNCTION)
+ Function f
+ f.init(sub)
+ f.m = true
+ self.funcs.push(~f)
+ ;/
+ ;/
+ ;/
+
+ /; collect_methods (~parse.Node mod)
+ ~parse.Node sub
+ /; loop (int i = 0; i < mod`.sub.count) [i++]
+ sub = mod`.sub.get(i)
+ /; if (sub`._type == parse.NTYPE_METHOD)
+ utils.Vector id = self._method_id(sub`.data)
+ ~Module m = self.find(SEARCH_SUB, ~id)
+ /; if (m !== NULL)
+ _printf("Found module for method\n\0")
+ m`._collect_methods(sub)
+ ;; else
+ _printf("Failed to find module for method\n\0")
+ ;/
+ _method_id_end(~id)
+ ;; else if (sub`._type == parse.NTYPE_MODULE)
+ ~Module m = self._find_sub(sub`.data)
+ /; if (m !== NULL)
+ m`.collect_methods(sub)
+ ;/
+ ;; else if (sub`._type == parse.NTYPE_EXPORT)
+ ~Module m = self._find_sub(sub`.data)
+ /; if (m !== NULL)
+ m`.collect_methods(sub)
+ ;/
+ ;/
+ ;/
+ ;/
+
+ /; _decl (~parse.Node decl)
+ /; if (decl`.sub.count < 1)
+ return
+ ;/
+
+ ~parse.Node tn = decl`.sub.get(0)
+ /; if (tn`._type !== parse.NTYPE_TYPE)
+ # Type must be first
+ return
+ ;/
+
+ ~parse.Node id
+ /; loop (int i = 1; i < decl`.sub.count) [i++]
+ id = decl`.sub.get(i)
+ /; if (tn`._type == parse.NTYPE_ID)
+ # Add a new variable to the list
+ Var v
+ v.init(tn, id)
+ self.vars.push(~v)
+ ;/
+ ;/
+ ;/
+
+ /; compile (~CompBuf cb)
+ # First, since all the types are in place, we need to size all of them.
+ self._size_structs()
+
+ # Finally, write all functions to the code section
+ self._compile(cb)
+ ;/
+
+ /; _size_structs
+ ~Struct s
+ /; loop (int i = 0; i < self.structs.count) [i++]
+ s = self.structs.get(i)
+ /; if (s`.size == 0)
+ s`._compute_size()
+ ;/
+ ;/
+
+ ~Var v
+ /; loop (int i = 0; i < self.vars.count) [i++]
+ v = self.vars.get(i)
+ v`._resolve_type(~self)
+ ;/
+
+ ~Function f
+ /; loop (int i = 0; i < self.funcs.count) [i++]
+ f = self.funcs.get(i)
+ f`._resolve_type(~self)
+ ;/
+
+ ~Module m
+ /; loop (int i = 0; i < self.subs.count) [i++]
+ m = self.subs.get(i)
+ m`._size_structs()
+ ;/
+ ;/
+
+ /; _compile (~CompBuf cb)
+ ~Var v
+ /; loop (int i = 0; i < self.vars.count) [i++]
+ v = self.vars.get(i)
+ v`._static_compile(~self, cb)
+ ;/
+
+ ~Function f
+ /; loop (int i = 0; i < self.funcs.count) [i++]
+ f = self.funcs.get(i)
+ f`._compile(~self, cb)
+ ;/
+
+ ~Module m
+ /; loop (int i = 0; i < self.subs.count) [i++]
+ m = self.subs.get(i)
+ m`._compile(cb)
+ ;/
+ ;/
+
+ #
+ # Functions to search sub-modules
+ #
+
+ /; find (int stype, ~utils.Vector key) [~void]
+ /; if (key`.count < 1)
+ return NULL
+ ;/
+ return self._find(stype, key, 0)
+ ;/
+
+ /; _find (int stype, ~utils.Vector key, int lvl) [~void]
+
+ /; if ((lvl + 1) < key`.count)
+ ~Module m
+ ~~uint8 str = key`.get(lvl)
+
+ /; loop (int i = 0; i < self.subs.count) [i++]
+ m = self.subs.get(i)
+ /; if (utils.strcmp(str`, m`.name) == true)
+ ~void v = m._find(stype, key, lvl + 1)
+ /; if (v !== NULL)
+ return v
+ ;/
+ ;/
+ ;/
+ ;; else
+ ~~uint8 str = key`.get(key`.count - 1)
+ ~void out = NULL
+ /; if (stype == SEARCH_VAR)
+ out = self._find_var(str`)
+ ;; else if (stype == SEARCH_STRUCT)
+ out = self._find_struct(str`)
+ ;; else if (stype == SEARCH_FUNC)
+ out = self._find_func(str`)
+ ;; else if (stype == SEARCH_SUB)
+ out = self._find_sub(str`)
+ ;/
+
+ /; if (out !== NULL)
+ return out
+ ;/
+ ;/
+
+ /; if (lvl == 0 && self.parent !== NULL)
+ return self.parent`._find(stype, key, 0)
+ ;/
+
+ return NULL
+ ;/
+
+ /; _find_var (~uint8 name) [~void]
+ ~Var v
+ /; loop (int i = 0; i < self.vars.count) [i++]
+ v = self.vars.get(i)
+ /; if (utils.strcmp(name, v`.name) == true)
+ return v
+ ;/
+ ;/
+ return NULL
+ ;/
+
+ /; _find_struct (~uint8 name) [~void]
+ ~Struct s
+ /; loop (int i = 0; i < self.structs.count) [i++]
+ s = self.structs.get(i)
+ /; if (utils.strcmp(name, s`.name) == true)
+ return s
+ ;/
+ ;/
+ return NULL
+ ;/
+
+ /; _find_func (~uint8 name) [~void]
+ ~Function f
+ /; loop (int i = 0; i < self.funcs.count) [i++]
+ f = self.funcs.get(i)
+ /; if (utils.strcmp(name, f`.name) == true)
+ return f
+ ;/
+ ;/
+ return NULL
+ ;/
+
+ /; _find_sub (~uint8 name) [~void]
+ ~Module m
+ /; loop (int i = 0; i < self.subs.count) [i++]
+ m = self.subs.get(i)
+ /; if (utils.strcmp(name, m`.name) == true)
+ return m
+ ;/
+ ;/
+ return NULL
+ ;/
+
+ /; print
+ self._print(0)
+ ;/
+
+ /; _print (int indent)
+
+ _indent(indent)
+ _printf("{ Module : \0")
+ _printf(self.name)
+ _printf("\n\0")
+
+ ~Var v
+ /; loop (int i = 0; i < self.vars.count) [i++]
+ v = self.vars.get(i)
+ v`._print(indent + 1)
+ ;/
+
+ ~Struct s
+ /; loop (int i = 0; i < self.structs.count) [i++]
+ s = self.structs.get(i)
+ s`._print(indent + 1)
+ ;/
+
+ ~Function f
+ /; loop (int i = 0; i < self.funcs.count) [i++]
+ f = self.funcs.get(i)
+ f`._print(indent + 1)
+ ;/
+
+ ~Module m
+ /; loop (int i = 0; i < self.subs.count) [i++]
+ m = self.subs.get(i)
+ m`._print(indent + 1)
+ ;/
+
+ _indent(indent)
+ _printf("}\n\0")
+ ;/
+
+ /; end
+ _delete(self.name)
+
+ ~Var v
+ /; loop (int i = 0; i < self.vars.count) [i++]
+ v = self.vars.get(i)
+ v`.end()
+ ;/
+ self.vars.end()
+
+ ~Struct s
+ /; loop (int i = 0; i < self.structs.count) [i++]
+ s = self.structs.get(i)
+ s`.end()
+ ;/
+ self.structs.end()
+
+ ~Function f
+ /; loop (int i = 0; i < self.funcs.count) [i++]
+ f = self.funcs.get(i)
+ f`.end()
+ ;/
+ self.funcs.end()
+
+ ~Module m
+ /; loop (int i = 0; i < self.subs.count) [i++]
+ m = self.subs.get(i)
+ m`.end()
+ ;/
+ self.subs.end()
+ ;/
+
+;/
+
diff --git a/tnslc/compile/scope.tnsl b/tnslc/compile/scope.tnsl
new file mode 100644
index 0000000..d3f86a9
--- /dev/null
+++ b/tnslc/compile/scope.tnsl
@@ -0,0 +1,502 @@
+struct Scope {
+ ~uint8 name,
+ ~Module mod,
+ ~CompBuf cb,
+
+ ~Scope parent,
+
+ utils.Vector vars, tmps,
+
+ int unique
+}
+
+/; _recursive_mod_name(~Module mod, ~utils.Vector vec)
+ ~Module p = mod`.parent
+ /; if (p !== NULL)
+ _recursive_mod_name(p, vec)
+ /; if (vec`.count !== 0)
+ vec`.push_char('.')
+ ;/
+ ;/
+ vec`.push_cstr(mod`.name)
+;/
+
+/; _recursive_scope_name(~Scope s, ~utils.Vector vec)
+ ~void p = s`.parent
+ /; if (p == NULL)
+ ~void m = s`.mod
+ /; if (m !== NULL)
+ _recursive_mod_name(m, vec)
+ /; if (vec`.count > 0)
+ vec`.push_char('.')
+ ;/
+ ;/
+ ;; else
+ _recursive_scope_name(p, vec)
+ ;/
+ vec`.push_cstr(s`.name)
+;/
+
+/; method Scope
+ /; init (~Module mod, ~CompBuf cb, ~uint8 name)
+ self.name = utils.strcpy(name)
+ self.mod = mod
+ self.cb = cb
+ self.parent = NULL
+ self.unique = 0
+
+ Var v
+ self.vars.init(len v)
+ self.tmps.init(len v)
+ ;/
+
+ /; end
+ _delete(self.name)
+
+ ~Var v
+ /; loop (int i = 0; i < self.vars.count) [i++]
+ v = self.vars.get(i)
+ v`.end()
+ ;/
+ self.vars.end()
+
+ /; loop (int i = 0; i < self.tmps.count) [i++]
+ v = self.tmps.get(i)
+ v`.end()
+ ;/
+ self.tmps.end()
+ ;/
+
+ #
+ # Make variables
+ #
+
+ /; _next_reg_slot [int]
+ int out = 11
+ /; if (self.parent !== NULL)
+ out = self.parent`._next_reg_slot()
+ ;/
+
+ /; if (out < 0)
+ return out
+ ;/
+
+ ~Var v
+ /; loop (int i = 0; i < self.vars.count) [i++]
+ v = self.vars.get(i)
+ /; if (v`.loc > 1)
+ out++
+ /; if (out > 16)
+ out = 0
+ out = out - 1
+ return out
+ ;/
+ ;/
+ ;/
+
+ return out
+ ;/
+
+ /; _next_tmp_slot [int]
+ int out = 2
+ /; if (self.parent !== NULL)
+ out = self.parent`._next_tmp_slot()
+ ;/
+
+ /; if (out < 0)
+ return out
+ ;/
+
+ ~Var v
+ /; loop (int i = 0; i < self.tmps.count) [i++]
+ v = self.vars.get(i)
+ /; if (v`.loc > 1)
+ out++
+ /; if (out > 4)
+ out = 0
+ out = out - 1
+ return out
+ ;/
+ ;/
+ ;/
+
+ return out
+ ;/
+
+ /; _next_stack_slot [int]
+ int out = 0
+ out = out - 56
+ /; if (self.parent !== NULL)
+ out = self.parent`._next_stack_slot()
+ ;/
+
+ ~Var v
+ /; loop (int i = 0; i < self.vars.count) [i++]
+ v = self.vars.get(i)
+ /; if (v`.loc < 0 && v`.offset !== 0)
+ int off = v`.offset - v`.actual_size()
+ /; if (off < out)
+ out = off
+ ;/
+ ;/
+ ;/
+
+ /; loop (int i = 0; i < self.tmps.count) [i++]
+ v = self.tmps.get(i)
+ /; if (v`.loc < 0 && v`.offset !== 0)
+ int off = v`.offset - v`.actual_size()
+ /; if (off < out)
+ out = off
+ ;/
+ ;/
+ ;/
+
+ return out
+ ;/
+
+ /; mk_aware (~Var v)
+ Var mk = v`.copy()
+ mk.offset = 0
+
+ # TODO: Make sure this works properly
+ /; if (mk.loc > 0)
+ mk.loc = 1
+ ;/
+
+ self.vars.push(~mk)
+ ;/
+
+ /; mk_aware_node (~parse.Node n)
+ ~parse.Node sub
+ ~parse.Node tp = NULL
+ /; loop (int i = 0; i < n`.sub.count) [i++]
+ sub = n`.sub.get(i)
+ /; if (sub`._type == parse.NTYPE_TYPE)
+ tp = sub
+ ;; else if (sub`._type == parse.NTYPE_ID)
+ /; if (tp == NULL)
+ _printf("COMPILER ERROR: Should have type node before first id in decl node\n\0")
+ return
+ ;/
+
+ # Part 1: Add var
+ Var v
+ v.init(tp, sub)
+ v._resolve_type(self.mod)
+
+ # TODO: Make sure this works properly
+ /; if (v.regable() == true)
+ v.loc = 1
+ ;; else
+ v.loc = 0 - 1
+ ;/
+ v.offset = 0
+
+ self.vars.push(~v)
+
+ # Part 2: Compute via value (if exists)
+ /; if (sub`.sub.count > 0)
+ sub = sub`.sub.get(0)
+ /; if (sub`._type == parse.NTYPE_VALUE)
+ self.precheck_stmt(n)
+ ;/
+ ;/
+ ;/
+ ;/
+ ;/
+
+ /; precheck_stmt (~parse.Node n)
+ ;/
+
+ /; _find_var (~uint8 name) [~Var]
+ ~Var v
+ /; loop (int i = 0; i < self.vars.count) [i++]
+ v = self.vars.get(i)
+ /; if (utils.strcmp(v`.name, name) == true)
+ return v
+ ;/
+ ;/
+
+ /; if (self.parent !== NULL)
+ return self.parent`.find_var(name)
+ ;/
+
+ return NULL
+ ;/
+
+ /; find_var (~uint8 name) [~Var]
+ ~Var out = self._find_var(name)
+
+ /; if (out == NULL)
+ return NULL
+ ;/
+
+ /; if (out`.loc > 1 || out`.offset !== 0)
+ return out
+ ;/
+
+ return NULL
+ ;/
+
+ /; mk_var (~Var src) [~Var]
+ ~Var v = self._find_var(src`.name)
+
+ /; if (v == NULL)
+ return NULL
+ ;/
+
+ int tmp = 0
+ /; if (v`.loc == 1)
+ int tmp = self._next_reg_slot()
+ v`.loc = tmp
+ /; if (v`.loc + 1 == 0)
+ tmp = self._next_stack_slot()
+ v`.offset = tmp
+ ;/
+ ;; else if (v`.loc + 1 == 0)
+ /; if (v`.offset == 0)
+ tmp = self._next_stack_slot()
+ v`.offset = tmp
+ ;/
+ ;/
+
+ return v
+ ;/
+
+ /; mk_set_var (~Var src) [~Var]
+ ~Var v = self.mk_var(src)
+
+ /; if (v == NULL)
+ return NULL
+ ;/
+
+ ~int32 p = v`.top_ptrc()
+ /; if (p == NULL)
+ v`.set(self.cb, src)
+ ;; else if (p` == 0)
+ v`.set_ref(self.cb, src)
+ ;; else
+ v`.set(self.cb, src)
+ ;/
+
+ /; if (v`.loc < 0)
+ int stk = v`.actual_size()
+ ~uint8 stk_str = utils.int_to_str(stk)
+ self.cb`.add_c(" sub rsp, \0")
+ self.cb`.add_c(stk_str)
+ self.cb`.add_c("\n\0")
+ _delete(stk_str)
+ ;/
+
+ return v
+ ;/
+
+ # Make a temp variable in register or stack for use in computations
+ /; mk_tmp (~Var base) [Var]
+ Var v = base`.copy()
+ v.offset = 0
+
+ int tmp = 0
+ /; if (v.regable() == true)
+ int tmp = self._next_tmp_slot()
+ v.loc = tmp
+ /; if (v.loc + 1 == 0)
+ tmp = self._next_stack_slot()
+ v.offset = tmp
+ ;; else if (v.loc > 2)
+ v.loc = v.loc + 6
+ ;/
+ ;; else
+ tmp = self._next_stack_slot()
+ v.offset = tmp
+ ;/
+
+ /; if (v.loc < 0)
+ int stk = v.actual_size()
+ ~uint8 stk_str = utils.int_to_str(stk)
+ self.cb`.add_c(" sub rsp, \0")
+ self.cb`.add_c(stk_str)
+ self.cb`.add_c("\n\0")
+ _delete(stk_str)
+ ;/
+
+ self.tmps.push(~v)
+
+ return v.copy()
+ ;/
+
+ # Free n tmp variables (starts from most recently created)
+ # If you want to generate code to set the stack pointer then
+ # set code to true
+ /; free_tmp (int tmps, bool code)
+ /; if (self.tmps.count < tmps)
+ tmps = self.tmps.count
+ ;/
+
+ int stk_mv = 0
+
+ ~Var tmp
+ /; loop (int i = 1; i !> tmps) [i++]
+ tmp = self.tmps.get(self.tmps.count - i)
+ /; if (tmp`.loc < 0)
+ stk_mv = stk_mv + tmp`.actual_size()
+ ;/
+ tmp`.end()
+ self.tmps.pop()
+ ;/
+
+ /; if (stk_mv > 0)
+ ~uint8 stk_mv_str = utils.int_to_str(stk_mv)
+ self.cb`.add_c(" add rsp, \0")
+ self.cb`.add_c(stk_mv_str)
+ self.cb`.add_c("\n\0")
+ _delete(stk_mv_str)
+ ;/
+ ;/
+
+ #
+ # Sub scope
+ #
+
+ /; mk_sub (~uint8 name) [Scope]
+ Scope out
+ out.init(self.mod, self.cb, name)
+ out.parent = ~self
+ return out
+ ;/
+
+ # Generate a garantueed unique name for the sub scope, using
+ # the provided name as a base
+ /; gen_sub(~uint8 name) [Scope]
+ utils.Vector true_name
+ true_name.init(1)
+
+ # Append a 'unique' number
+ ~uint8 u = utils.int_to_str(self.unique)
+ true_name.push_char('#')
+ true_name.push_cstr(u)
+ true_name.push_char('#')
+ true_name.push_cstr(name)
+ _delete(u)
+
+ Scope out = self.mk_sub(true_name.as_cstr())
+ true_name.end()
+
+ # Inc for subsequent names
+ self.unique++
+
+ 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
+ #
+
+
+ /; _base_label [utils.Vector]
+ utils.Vector out
+ out.init(1)
+
+ _recursive_scope_name(~self, ~out)
+
+ return out
+ ;/
+
+ /; base_label [~uint8]
+ utils.Vector v = self._base_label()
+ return v.as_cstr()
+ ;/
+
+ /; place_base_label
+ ~uint8 bl = self.base_label()
+ self.cb`.add_c(bl)
+ self.cb`.add_c(":\n\0")
+ _delete(bl)
+ ;/
+
+ /; start_label [~uint8]
+ utils.Vector v = self._base_label()
+ v.push_cstr("#start\0")
+ return v.as_cstr()
+ ;/
+
+ /; place_start_label
+ ~uint8 sl = self.start_label()
+ self.cb`.add_c(sl)
+ self.cb`.add_c(":\n\0")
+ _delete(sl)
+ ;/
+
+ /; rep_label [~uint8]
+ utils.Vector v = self._base_label()
+ v.push_cstr("#rep\0")
+ return v.as_cstr()
+ ;/
+
+ /; place_rep_label
+ ~uint8 rl = self.rep_label()
+ self.cb`.add_c(rl)
+ self.cb`.add_c(":\n\0")
+ _delete(rl)
+ ;/
+
+ /; end_label [~uint8]
+ utils.Vector v = self._base_label()
+ v.push_cstr("#end\0")
+ return v.as_cstr()
+ ;/
+
+ /; place_end_label
+ ~uint8 el = self.end_label()
+ self.cb`.add_c(el)
+ self.cb`.add_c(":\n\0")
+ _delete(el)
+ ;/
+;/
+
diff --git a/tnslc/compile/struct.tnsl b/tnslc/compile/struct.tnsl
new file mode 100644
index 0000000..5eded31
--- /dev/null
+++ b/tnslc/compile/struct.tnsl
@@ -0,0 +1,281 @@
+
+struct Struct {
+ ~uint8 name,
+ ~Module methods,
+ utils.Vector members,
+ int size,
+
+ ~parse.Node _up
+}
+
+~uint8 PRIMITIVE_1 = "bool,uint8,int8\0"
+~uint8 PRIMITIVE_2 = "uint16,int16\0"
+~uint8 PRIMITIVE_4 = "uint32,int32,float32\0"
+~uint8 PRIMITIVE_8 = "uint64,int64,float64,int,uint,float,void\0"
+
+/; _is_primitive(~uint8 str) [int]
+ /; if (parse._in_csv(PRIMITIVE_1, str) == true)
+ return 1
+ ;; else if (parse._in_csv(PRIMITIVE_2, str) == true)
+ return 2
+ ;; else if (parse._in_csv(PRIMITIVE_4, str) == true)
+ return 4
+ ;; else if (parse._in_csv(PRIMITIVE_8, str) == true)
+ return 8
+ ;/
+ return 0
+;/
+
+/; is_primitive (~parse.Node tn) [int]
+ /; if (tn`.sub.count < 1)
+ return 0
+ ;/
+
+ ~parse.Node n = tn`.sub.get(0)
+
+ # Check for pointer, array
+ /; if (n`._type == parse.NTYPE_PRE_OP)
+ return 8
+ ;/
+
+ # Check for ref
+ n = tn`.sub.get(tn`.sub.count - 1)
+ /; if (n`._type == parse.NTYPE_POST_OP)
+ return 8
+ ;/
+
+ int id = 0 - 1
+ /; loop (int i = 0; i < tn`.sub.count) [i++]
+ n = tn`.sub.get(i)
+ /; if (n`._type == parse.NTYPE_ID)
+ /; if (id < 0)
+ id = i
+ ;; else
+ return 0
+ ;/
+ ;/
+ ;/
+
+ /; if (id < 0)
+ return 0
+ ;/
+
+ n = tn`.sub.get(id)
+ return _is_primitive(n`.data)
+;/
+
+/; _print_type(~parse.Node tn)
+ ~parse.Node n
+ bool seen_id = false
+ /; loop (int i = 0; i < tn`.sub.count) [i++]
+
+ n = tn`.sub.get(i)
+
+ /; if (n`._type == parse.NTYPE_ID)
+ /; if (seen_id == true)
+ _printf(".\0")
+ ;/
+ _printf(n`.data)
+ seen_id = true
+ ;; else
+ return
+ ;/
+ ;/
+;/
+
+# Might be wrong
+/; _type_is_ptr (~parse.Node n) [bool]
+ # Sanity
+ /; if (n`.sub.count < 1)
+ return false
+ ;/
+
+ ~parse.Node op = n`.sub.get(0)
+ /; if (op`._type == parse.NTYPE_PRE_OP)
+ return true
+ ;/
+
+ op = n`.sub.get(n`.sub.count - 1)
+ /; if (op`._type == parse.NTYPE_POST_OP)
+ return true
+ ;/
+
+ return false
+;/
+
+/; method Struct
+
+ /; init (~parse.Node node)
+ self._up = node
+ self.size = 0
+ self.methods = NULL
+ self.name = utils.strcpy(node`.data)
+ Var v
+ self.members.init(len v)
+ ;/
+
+ /; _print (int idt)
+ _indent(idt)
+ _printf("{ Struct : \0")
+ _printf(self.name)
+ _printf("\n\0")
+
+ _indent(idt + 1)
+ _print_num("size: %d\n\0", self.size)
+
+ _indent(idt + 1)
+ _printf("members:\n\0")
+
+ ~Var v
+ /; loop (int i = 0; i < self.members.count) [i++]
+ v = self.members.get(i)
+ v`._print(idt + 2)
+ ;/
+
+ _indent(idt)
+ _printf("}\n\0")
+ ;/
+
+ /; add_member(~parse.Node tn, ~parse.Node id)
+ Var v
+ v.init(tn, id)
+ v._resolve_type(self.methods)
+ self.members.push(~v)
+ ;/
+
+ /; get_member(~uint8 name) [~Var]
+ ~Var out = NULL
+
+ ~Var v
+ /; loop (int i = 0; i < self.members.count) [i++]
+ v = self.members.get(i)
+ /; if (utils.strcmp(v`.name, name) == true)
+ return v
+ ;/
+ ;/
+
+ return out
+ ;/
+
+ /; _dlist [~parse.Node]
+ ~parse.Node up = self._up
+ ~parse.Node n
+ /; loop (int i = 0; i < up`.sub.count) [i++]
+ n = up`.sub.get(i)
+ /; if (n`._type == parse.NTYPE_DLIST)
+ return n
+ ;/
+ ;/
+ return NULL
+ ;/
+
+ /; _compute_size
+ /; if (self.size !== 0)
+ return
+ ;/
+
+ self.size = self.size - 1
+
+ int total = 0
+ ~parse.Node up = self._dlist()
+ ~parse.Node tn = NULL
+ ~parse.Node n = NULL
+ int add_size = 0
+ /; loop (int i = 0; i < up`.sub.count) [i++]
+ n = up`.sub.get(i)
+
+ /; if (n`._type == parse.NTYPE_TYPE)
+ # Store for generating new variables
+ tn = n
+ add_size = self._compute_type_size(n)
+ /; if (add_size == 0)
+ return
+ ;/
+ ;; else if (n`._type == parse.NTYPE_ID)
+ /; if (tn == NULL)
+ _printf("ERROR: Unable to find type when trying to create member for struct '\0")
+ _printf(self.name)
+ _printf("\n\0")
+ return
+ ;/
+ self.add_member(tn, n)
+ total = total + add_size
+ ;/
+ ;/
+
+ self.size = total
+ ;/
+
+ /; _compute_type_size(~parse.Node tn) [int]
+ ~Struct ft = self._find_type(tn)
+
+ /; if (ft == NULL)
+ # Type not found
+ _printf("ERROR: Unable to find type '\0")
+ _print_type(tn)
+ _printf("' for use in struct '\0")
+ _printf(self.name)
+ _printf("'\n\0")
+ return 0
+ ;/
+
+ /; if (_type_is_ptr(tn) == true)
+ return 8
+ ;/
+
+ /; if (ft !== NULL && ft`.size == 0)
+ ft`._compute_size()
+ ;/
+
+ /; if (ft`.size < 0)
+ # Cyclical dependency
+ _printf("ERROR: Cyclic struct definition: '\0")
+ _printf(ft`.name)
+ _printf("' imported from '\0")
+ _printf(self.name)
+ _printf("'\n\0")
+ return 0
+ ;/
+
+ return ft`.size
+ ;/
+
+ /; _find_type (~parse.Node tn) [~Struct]
+
+ # Init vector of strings
+ utils.Vector sv
+ sv.init(8)
+
+ ~uint8 str
+ ~parse.Node n
+ bool seen_id = false
+
+ /; loop (int i = 0; i < tn`.sub.count) [i++]
+ n = tn`.sub.get(i)
+ /; if (n`._type == parse.NTYPE_ID)
+ str = n`.data
+ sv.push(~str)
+ seen_id = true
+ ;; else if (seen_id == true)
+ i = tn`.sub.count
+ ;/
+ ;/
+
+ # Find struct and compute its size
+ ~Struct out = self.methods`.find(SEARCH_STRUCT, ~sv)
+ sv.end()
+ return out
+ ;/
+
+ /; end
+ _delete(self.name)
+ ~Var v
+ /; loop (int i = 0; i < self.members.count) [i++]
+ v = self.members.get(i)
+ v`.end()
+ ;/
+ self.members.end()
+ ;/
+
+;/
+
diff --git a/tnslc/compile/type.tnsl b/tnslc/compile/type.tnsl
deleted file mode 100644
index 474f705..0000000
--- a/tnslc/compile/type.tnsl
+++ /dev/null
@@ -1,360 +0,0 @@
-struct Variable {
- ~uint8 name,
- ~Type _type,
- utils.Vector ptr
-}
-
-/; method Variable
- /; init (~uint8 name)
- self.name = name
- self.ptr.init(8)
- ;/
-
- /; add_ptr(uint ptp)
- self.ptr.push(~ptp)
- ;/
-
- /; get_ptr [uint]
- /; if (self.ptr.count == 0)
- return 0
- ;/
- ~uint p = self.ptr.get(self.ptr.count - 1)
- return p`
- ;/
-
- /; pop_ptr [uint]
- /; if (self.ptr.count == 0)
- return 0
- ;/
- ~uint p = self.ptr.get(self.ptr.count - 1)
- uint out = p`
- self.ptr.pop()
- return out
- ;/
-
- /; end
- _delete(self.name)
- self.ptr.end()
- ;/
-;/
-
-struct Type {
- ~uint8 name,
- uint size,
- utils.Vector vars,
- ~Module methods,
-}
-
-/; method Type
- /; init(~uint8 name)
- self.name = name
- Variable tmp
- self.vars.init(len tmp)
- ;/
-
- /; add_var (~Variable v)
- self.vars.push(v)
- ;/
-
- /; end
- _delete(self.name)
- /; loop (int i = 0; i < self.vars.count) [i++]
- ~Variable v = self.vars.get(i)
- v`.end()
- ;/
- self.vars.end()
- ;/
-;/
-
-struct Function {
- ~uint8
- name,
- ~parse.Node
- body,
- utils.Vector
- inputs,
- outputs
-}
-
-/; method Function
- /; init (~uint8 name)
- self.name = name
- Variable vtmp
- ~uint i
- self.inputs.init(len vtmp)
- self.outputs.init(len i)
- ;/
-
- /; add_input (~Variable v)
- self.inputs.push(v)
- ;/
-
- /; add_output (~Type t)
- self.outputs.push(~t)
- ;/
-
- /; end
- _delete(self.name)
-
- /; loop (int i = 0; i < self.inputs.count) [i++]
- ~Variable v = self.inputs.get(i)
- v`.end()
- ;/
- self.inputs.end()
-
- self.outputs.end()
- ;/
-;/
-
-struct Enum {
- ~uint8 name,
- ~Type _type,
- utils.Vector vals
-}
-
-/; method Enum
- /; init (~uint8 name)
- self.name = name
- Variable vtmp
- self.vals.init(len vtmp)
- ;/
-
- /; end
- _delete(self.name)
- /; loop (int i = 0; i < self.vals.count) [i++]
- ~Variable v = self.vals.get(i)
- v`.end()
- ;/
- self.vals.end()
- ;/
-;/
-
-struct Module {
- ~uint8 name,
- ~Module parent,
- bool exp,
- utils.Vector
- sub,
- vars,
- types,
- funcs,
- enums
-
-}
-
-uint8 MOD_FIND_SUB = 0
-uint8 MOD_FIND_VAR = 1
-uint8 MOD_FIND_TYP = 2
-uint8 MOD_FIND_FUN = 3
-uint8 MOD_FIND_ENM = 4
-
-/; method Module
- /; init (~uint8 name)
- self.name = name
- Module mtmp
- Variable vtmp
- Type ttmp
- Function ftmp
- Enum etmp
- self.sub.init(len mtmp)
- self.vars.init(len vtmp)
- self.types.init(len ttmp)
- self.funcs.init(len ftmp)
- self.enums.init(len etmp)
- ;/
-
- /; update_children
- /; loop (int i = 0; i < self.sub.count) [i++]
- ~Module s = self.sub.get(i)
- s`.parent = ~self
- ;/
- ;/
-
- /; add_sub(~Module m) [~Module]
- self.sub.push(m)
- /; loop (int i = 0; i < self.sub.count) [i++]
- ~Module s = self.sub.get(i)
- s`.update_children()
- ;/
- return self.sub.get(self.sub.count - 1)
- ;/
-
- /; add_var (~Variable v)
- self.vars.push(v)
- ;/
-
- /; add_type (~Type t)
- self.types.push(t)
- ;/
-
- /; add_funcs (~Function f)
- self.funcs.push(f)
- ;/
-
- /; add_enum (~Enum e)
- self.enums.push(e)
- ;/
-
- /; _find_rec (utils.Artifact pth, uint8 typ, int sub) [~void]
- /; if (sub !< pth.count)
- return NULL
- ;; else if ((sub + 1) < pth.count)
- /; loop (int i = 0; i < self.sub.count) [i++]
- ~Module m = self.sub.get(i)
- /; if (utils.strcmp(pth.get(sub), m`.name) == true)
- return _find_rec(pth, typ, sub + 1)
- ;/
- ;/
- ;; else
- /; if (typ == MOD_FIND_SUB)
- /; loop (int i = 0; i < self.sub.count) [i++]
- ~Module m = self.sub.get(i)
- /; if (utils.strcmp(pth.get(sub), m`.name) == true)
- return self.sub.get(i)
- ;/
- ;/
- ;; else if (typ == MOD_FIND_VAR)
- /; loop (int i = 0; i < self.vars.count) [i++]
- ~Variable v = self.vars.get(i)
- /; if (utils.strcmp(pth.get(sub), v`.name) == true)
- return self.vars.get(i)
- ;/
- ;/
- ;; else if (typ == MOD_FIND_TYP)
- /; loop (int i = 0; i < self.types.count) [i++]
- ~Type t = self.types.get(i)
- /; if (utils.strcmp(pth.get(sub), t`.name) == true)
- return self.types.get(i)
- ;/
- ;/
- ;; else if (typ == MOD_FIND_FUN)
- /; loop (int i = 0; i < self.funcs.count) [i++]
- ~Function f = self.funcs.get(i)
- /; if (utils.strcmp(pth.get(sub), f`.name) == true)
- return self.funcs.get(i)
- ;/
- ;/
- ;; else if (typ == MOD_FIND_ENM)
- /; loop (int i = 0; i < self.enums.count) [i++]
- ~Enum e = self.enums.get(i)
- /; if (utils.strcmp(pth.get(sub), e`.name) == true)
- return self.enums.get(i)
- ;/
- ;/
- ;/
- ;/
-
- /; if (self.parent == NULL || sub !== 0)
- return NULL
- ;/
-
- return self.parent._find_rec(pth, typ, 0)
- ;/
-
- /; find (utils.Artifact pth, uint8 typ) [~void]
- return _find_rec(pth, typ, 0)
- ;/
-
- /; end
- _delete(self.name)
-
- /; loop (int i = 0; i < self.sub.count) [i++]
- ~Module m = self.sub.get(i)
- m`.end()
- ;/
- self.sub.end()
-
- /; loop (int i = 0; i < self.vars.count) [i++]
- ~Variable v = self.vars.get(i)
- v`.end()
- ;/
- self.vars.end()
-
- /; loop (int i = 0; i < self.types.count) [i++]
- ~Type t = self.types.get(i)
- t`.end()
- ;/
- self.types.end()
-
- /; loop (int i = 0; i < self.funcs.count) [i++]
- ~Function f = self.funcs.get(i)
- f`.end()
- ;/
- self.funcs.end()
-
- /; loop (int i = 0; i < self.enums.count) [i++]
- ~Enum e = self.enums.get(i)
- e`.end()
- ;/
- self.enums.end()
- ;/
-;/
-
-{}~uint8 GEN_VAR_NAMES = { "int\0", "int8\0", "int16\0", "int32\0", "int64\0", "uint\0", "uint8\0", "uint16\0", "uint32\0", "uint64\0", "float\0", "float32\0", "float64\0", "vect\0", "bool\0", "void\0" }
-
-{}uint GEN_VAR_SIZES = { 8, 1, 2, 4, 8, 8, 1, 2, 4, 8, 8, 4, 8, 0, 1, 8}
-
-/; find_type(utils.Artifact a, ~parse.Node n) [~parse.Node]
- return NULL
-;/
-
-/; transform_struct(~parse.Node n, ~Module parent)
-;/
-
-/; _tfn_mod_loop (~parse.Node n, ~Module m)
- /; loop (int i = 0; i < n`.sub.count) [i++]
- ~parse.Node s = n`.sub.get(i)
- /; if (s`._type == parse.NTYPE_MODULE || s`._type == parse.NTYPE_EXPORT)
- transform_module(s, m)
- ;; else if (s`._type == parse.NTYPE_STRUCT)
- transform_struct(s, m)
- ;/
- ;/
-;/
-
-/; transform_module (~parse.Node n, ~Module parent)
- ~Module s = NULL
-
- /; loop (int i = 0; i < parent`.sub.count) [i++]
- ~Module tmp = parent`.sub.get(i)
- /; if (utils.strcmp(n`.data, tmp`.name) == true)
- s = tmp
- ;/
- ;/
-
- ~int cmp = s
- /; if (cmp == NULL)
- Module out
- out.init(utils.strcpy(n`.data))
-
- /; if (n`._type == parse.NTYPE_EXPORT)
- out.exp = true
- ;; else
- out.exp = false
- ;/
-
- s = parent`.add_sub(~out)
- ;/
-
- _tfn_mod_loop(n, s)
-;/
-
-/; _tfn_gen_default_types (~Module m)
- /; loop (int i = 0; i < len GEN_VAR_NAMES) [i++]
- Type t
- t.init(utils.strcpy(GEN_VAR_NAMES{i}))
- t.size = GEN_VAR_SIZES{i}
- m`.add_type(~t)
- ;/
-;/
-
-/; transform_tree (~parse.Node n) [Module]
- Module out
- out.init(utils.strcpy(n`.data))
- out.exp = true
-
- _tfn_gen_default_types(~out)
- _tfn_mod_loop(n, ~out)
-
- return out
-;/
diff --git a/tnslc/compile/var.tnsl b/tnslc/compile/var.tnsl
new file mode 100644
index 0000000..a47e182
--- /dev/null
+++ b/tnslc/compile/var.tnsl
@@ -0,0 +1,547 @@
+
+# Location enum
+int VLOC_DATA = 2
+int VLOC_STCK = 1
+int VLOC_LITL = 0
+
+# Should be -2
+int32 PTYPE_NONE = 2
+# Should be -1
+int32 PTYPE_PTR = 1
+int32 PTYPE_REF = 0
+# 1 Arr is ptr to arr, larger #s are static size arrs
+int32 PTYPE_ARR = 1
+
+~uint8 PRIM_CSV_BOO = "bool\0"
+~uint8 PRIM_CSV_INT = "int,int8,int16,int32,int64,uint,uint8,uint16,uint32,uint64\0"
+~uint8 PRIM_CSV_FLT = "float,float32,float64\0"
+
+# Should dispose of this constructed string
+# 1-8 are ax, bx, cx, dx, si, di, sp, bp
+# 9-16 are r8, r9, r10, r11, r12, r13, r14, r15
+# 17-32 are xmm0, xmm1, xmm2, ..., xmm15
+/; reg_string (int r, int size) [~uint8]
+ utils.Vector out
+ out.init(1)
+ uint8 add
+
+ /; if (r < 9)
+ /; if (size == 4)
+ add = 'e'
+ out.push(~add)
+ ;; else if (size == 8)
+ add = 'r'
+ out.push(~add)
+ ;/
+
+ add = 'a'
+ /; if (r < 5)
+ add = add + r - 1
+ ;; else if (r == 5 || r == 7)
+ add = 's'
+ ;; else if (r == 6)
+ add = 'd'
+ ;; else if (r == 8)
+ add = 'b'
+ ;/
+ out.push(~add)
+
+ /; if (r == 5 || r == 6)
+ add = 'i'
+ out.push(~add)
+ ;; else if (r == 7 || r == 8)
+ add = 'p'
+ out.push(~add)
+ ;; else if (size !== 1)
+ add = 'x'
+ out.push(~add)
+ ;/
+
+ /; if (size == 1)
+ add = 'l'
+ out.push(~add)
+ ;/
+ ;; else if (r < 17)
+ add = 'r'
+ out.push(~add)
+
+ ~uint8 num = utils.int_to_str(r - 1)
+ out.push_cstr(num)
+ _delete(num)
+ /; if (size == 1)
+ add = 'b'
+ out.push(~add)
+ ;; else if (size == 2)
+ add = 'w'
+ out.push(~add)
+ ;; else if (size == 4)
+ add = 'd'
+ out.push(~add)
+ ;/
+ ;; else if (r < 33)
+ out.push_cstr("xmm\0")
+ ~uint8 num = utils.int_to_str(r - 17)
+ out.push_cstr(num)
+ _delete(num)
+ ;/
+
+ return out.as_cstr()
+;/
+
+struct Var {
+ ~uint8 name,
+ ~Struct _type,
+ utils.Vector ptrc,
+ int loc, offset,
+
+ ~parse.Node _tn, _id
+}
+
+/; method Var
+ # Initial init function, requires type node and
+ # identifier node
+ /; init (~parse.Node tn, id)
+ self.name = utils.strcpy(id`.data)
+ self.ptrc.init(4)
+ self.loc = 0
+ self.offset = 0
+
+ self._tn = tn
+ self._id = id
+ ;/
+
+ /; copy [Var]
+ Var out
+ out.init(self._tn, self._id)
+ out._type = self._type
+ out.loc = self.loc
+ out.offset = self.offset
+
+ /; loop (int i = 0; i < self.ptrc.count) [i++]
+ ~int32 p = self.ptrc.get(i)
+ out.ptrc.push(p)
+ ;/
+
+ return out
+ ;/
+
+ /; top_ptrc [~int32]
+ # Sanity
+ /; if (self.ptrc.count < 1)
+ return NULL
+ ;/
+ ~int32 out = self.ptrc.get(self.ptrc.count - 1)
+ return out
+ ;/
+
+ /; _print (int idt)
+ _indent(idt)
+ _printf("{ Var : \0")
+ _printf(self.name)
+ _printf("\n\0")
+
+ _indent(idt + 1)
+ _printf("type: \0")
+ /; if (self._type !== NULL)
+ _printf(self._type`.name)
+ ;; else
+ _printf("(nil)\0")
+ ;/
+ _printf("\n\0")
+
+ _indent(idt + 1)
+ _printf("ptrc: \0")
+ ~int32 istr
+ /; loop (int i = 0; i < self.ptrc.count) [i++]
+ istr = self.ptrc.get(i)
+ _print_num("%d \0", istr`)
+ ;/
+ _printf("\n\0")
+
+ _indent(idt + 1)
+ _print_num("loc: %d\n\0", self.loc)
+
+ _indent(idt + 1)
+ _print_num("off: %d\n\0", self.offset)
+
+ _indent(idt)
+ _printf("}\n\0")
+ ;/
+
+ /; _arr_ptr(~parse.Node a)
+ int32 ptr = 1
+ /; if (a`.sub.count > 0)
+ ~parse.Node l = a`.sub.get(0)
+ ptr = utils.cstr_to_int(l`.data)
+ /; if (ptr < 2)
+ return
+ ;/
+ ;/
+ self.ptrc.push(~ptr)
+ ;/
+
+ # Whether the variable can be stored within a register
+ /; regable [bool]
+ ~int p
+ /; loop (int i = 0; i < self.ptrc.count) [i++]
+ p = self.ptrc.get(i)
+ /; if (p` !== 0)
+ return true
+ ;/
+ ;/
+ return _is_primitive(self._type`.name) !== 0
+ ;/
+
+ /; actual_size [uint]
+ /; if (self.ptrc.count > 0)
+ return 8
+ ;; else if (self._type == NULL)
+ return 0
+ ;/
+
+ return self._type`.size
+ ;/
+
+ /; _reverse_ptrc
+ int max = self.ptrc.count / 2
+ ~int32 l, r
+ /; loop (int i = 0; i < max) [i++]
+ l = self.ptrc.get(i)
+ r = self.ptrc.get(self.ptrc.count - (i + 1))
+ int32 tmp = l`
+ l` = r`
+ r` = tmp
+ ;/
+ ;/
+
+ # Sets up both the ptrc and the _type members, requires
+ # parent module for resolution of types
+ /; _resolve_type (~Module parent)
+ int idx = 0
+ bool running = true
+ ~parse.Node t, _tn
+ _tn = self._tn
+
+ # Pre-op pointer
+ /; loop (running == true)
+ /; if (idx !< _tn`.sub.count)
+ running = false
+ ;; else
+ t = _tn`.sub.get(idx)
+ /; if (t`._type == parse.NTYPE_PRE_OP)
+ /; if (utils.strcmp(t`.data, "~\0") == true)
+ int32 ptr = 0
+ ptr = ptr - PTYPE_PTR
+ self.ptrc.push(~ptr)
+ ;; else
+ self._arr_ptr(t)
+ ;/
+ ;; else
+ running = false
+ ;/
+ ;/
+
+ /; if (running == true)
+ idx++
+ ;/
+ ;/
+
+ self._reverse_ptrc()
+
+ # After pre-ops comes id
+ utils.Vector strv
+ strv.init(8)
+ running = true
+ /; loop (running == true)
+ /; if (idx !< _tn`.sub.count)
+ running = false
+ ;; else
+ t = _tn`.sub.get(idx)
+ /; if (t`._type == parse.NTYPE_ID)
+ ~uint8 str = t`.data
+ strv.push(~str)
+ ;; else
+ running = false
+ ;/
+ ;/
+
+ /; if (running == true)
+ idx++
+ ;/
+ ;/
+
+ # Main type resolution
+ # TODO: FUNCTION POINTER
+ self._type = parent`.find(SEARCH_STRUCT, ~strv)
+ strv.end()
+
+ # Post-op pointer
+ running = true
+ /; loop (running == true)
+ /; if (idx !< _tn`.sub.count)
+ running = false
+ ;; else
+ t = _tn`.sub.get(idx)
+ /; if (t`._type == parse.NTYPE_POST_OP)
+ int32 ptr = 0
+ self.ptrc.push(~ptr)
+ ;/
+ ;/
+
+ /; if (running == true)
+ idx++
+ ;/
+ ;/
+ ;/
+
+ /; _static_compile (~Module parent, ~CompBuf buf)
+ # TODO:
+ ;/
+
+ /; ptr [int32]
+ ~int32 i
+ i = self.ptrc.get(self.ptrc.count - 1)
+ return i`
+ ;/
+
+ /; ptr_push (int32 p)
+ self.ptrc.push(~p)
+ ;/
+
+ /; ptr_pop
+ self.ptrc.pop()
+ ;/
+
+ /; end
+ _delete(self.name)
+ self.ptrc.end()
+ ;/
+
+ ###################################
+ # Variable manipulation functions #
+ ###################################
+
+ /; gen_loc [~uint8]
+ /; if (self.loc == 0)
+ return utils.int_to_str(self.offset)
+ ;/
+
+ utils.Vector out
+ out.init(1)
+
+ /; if (self.in_mem() == true)
+ out.push_char('[')
+ ;/
+
+ ~uint8 str
+ /; if (self.loc + 1 < 0)
+ out.push_cstr("rel \0")
+ str = utils.strcpy(self.name)
+ ;; else if (self.loc < 0)
+ str = reg_string(8, 8)
+ ;; else
+ str = reg_string(self.loc, self.actual_size())
+ ;/
+ out.push_cstr(str)
+ _delete(str)
+
+
+ /; if (self.in_mem() == true)
+ /; if (self.loc + 1 == 0)
+ int stk = 0 - self.offset
+ /; if (stk > 0)
+ out.push_cstr(" - \0")
+ str = utils.int_to_str(stk)
+ out.push_cstr(str)
+ _delete(str)
+ ;; else if (stk < 0)
+ out.push_cstr(" + \0")
+ str = utils.int_to_str(self.offset)
+ out.push_cstr(str)
+ _delete(str)
+ ;/
+ ;/
+ out.push_char(']')
+ ;/
+
+ return out.as_cstr()
+ ;/
+
+ # Returns true if the variable is known to be stored in memory
+ /; in_mem [bool]
+ /; if (self.loc < 0)
+ return true
+ ;/
+
+ ~int32 ptr = self.top_ptrc()
+ /; if (ptr !== NULL)
+ /; if (ptr` == 0)
+ return true
+ ;; else if (ptr` > 1)
+ return true
+ ;/
+ ;/
+
+ return false
+ ;/
+
+ # Set this variable to the value of a literal
+ /; set_literal (~CompBuf buf, ~Var other)
+ ;/
+
+ /; _set_mem(~CompBuf buf, ~Var other)
+
+ ~uint8 to_str = self.gen_loc()
+ ~uint8 from_str = other`.gen_loc()
+
+ ~uint8 str
+
+ str = utils.int_to_str(self.actual_size())
+ buf`.add_c(" mov rcx, \0")
+ buf`.add_c(str)
+ buf`.add_c("\n")
+ _delete(str)
+
+ buf`.add_c(" rep movsb\0")
+
+ _delete(to_str)
+ _delete(from_str)
+ ;/
+
+ # Set this Variable to the value of other
+ /; set (~CompBuf buf, ~Var other)
+ self.standard_op(buf, other, "mov\0")
+ ;/
+
+ # Set the address which this reference points to
+ /; set_ref(~CompBuf buf, ~Var other)
+ ;/
+
+ # Generate a variable which can actually be used for operations
+ /; strip_refs (~CompBuf buf, bool from) [Var]
+ Var out = self.copy()
+ ~int32 p = out.top_ptrc()
+ /; if (p == NULL)
+ return out
+ ;; else if (p` !== 0)
+ return out
+ ;/
+
+ ~uint8 gen = out.gen_loc()
+
+ out.ptr_pop()
+ p = out.top_ptrc()
+ /; loop (p` == 0)
+ buf`.add_c(" mov rsi, \0")
+ buf`.add_c(gen)
+ buf`.add_c("\n\0")
+ out.loc = 5
+ _delete(gen)
+ gen = out.gen_loc()
+ out.ptr_pop()
+ p = out.top_ptrc()
+ ;/
+
+ /; if (from == false)
+ buf`.add_c(" mov rdi, \0")
+ out.loc = 6
+ ;; else
+ buf`.add_c(" mov rsi, \0")
+ out.loc = 5
+ ;/
+ buf`.add_c(gen)
+ buf`.add_c("\n\0")
+ _delete(gen)
+
+ return out
+ ;/
+
+ /; standard_op (~CompBuf buf, ~Var other, ~uint8 op_str)
+ ~uint8 to_str = self.gen_loc()
+ ~uint8 from_str = other`.gen_loc()
+
+ buf`.add_c(" \0")
+ buf`.add_c(op_str)
+ buf`.add_c(" \0")
+ buf`.add_c(to_str)
+ buf`.add_c(", \0")
+ buf`.add_c(from_str)
+ buf`.add_c("\n\0")
+
+ _delete(from_str)
+ _delete(to_str)
+ ;/
+
+ /; product_op (~CompBuf buf, ~Var other, ~uint8 op_str, int read_reg)
+
+ ;/
+
+ /; add (~CompBuf buf, ~Var other)
+ /; if (self.loc == VLOC_LITL && other`.loc == VLOC_LITL)
+ self.offset = self.offset + other`.offset
+ return
+ ;/
+ self.standard_op(buf, other, "add")
+ ;/
+
+ /; sub (~CompBuf buf, ~Var other)
+ /; if (self.loc == VLOC_LITL && other`.loc == VLOC_LITL)
+ self.offset = self.offset - other`.offset
+ return
+ ;/
+ self.standard_op(buf, other, "sub")
+ ;/
+
+ /; mul (~CompBuf buf, ~Var other)
+ /; if (self.loc == VLOC_LITL && other`.loc == VLOC_LITL)
+ self.offset = self.offset * other`.offset
+ return
+ ;/
+ self.product_op(buf, other, "imul", 1)
+ ;/
+
+ /; div (~CompBuf buf, ~Var other)
+ /; if (self.loc == VLOC_LITL && other`.loc == VLOC_LITL)
+ self.offset = self.offset / other`.offset
+ return
+ ;/
+
+ /; if ("signed")
+ self.product_op(buf, other, "idiv", 1)
+ ;; else
+ self.product_op(buf, other, "div", 1)
+ ;/
+ ;/
+
+ /; mod (~CompBuf buf, ~Var other)
+ /; if (self.loc == VLOC_LITL && other`.loc == VLOC_LITL)
+ self.offset = self.offset % other`.offset
+ return
+ ;/
+
+ /; if ("signed")
+ self.product_op(buf, other, "idiv", 4)
+ ;; else
+ self.product_op(buf, other, "div", 4)
+ ;/
+ ;/
+
+ /; and (~CompBuf buf, ~Var other)
+ self.standard_op(buf, other, "and")
+ ;/
+
+ /; or (~CompBuf buf, ~Var other)
+ self.standard_op(buf, other, "or")
+ ;/
+
+ /; xor (~CompBuf buf, ~Var other)
+ self.standard_op(buf, other, "xor")
+ ;/
+
+ /; member (~CompBuf buf, ~uint8 name) [Var]
+ Var out
+ return out
+ ;/
+;/
+
+