diff options
Diffstat (limited to 'tnslc/compile')
| -rw-r--r-- | tnslc/compile/codegen.tnsl | 114 | ||||
| -rw-r--r-- | tnslc/compile/compbuf.tnsl | 6 | ||||
| -rw-r--r-- | tnslc/compile/compile.tnsl | 1 | ||||
| -rw-r--r-- | tnslc/compile/function.tnsl | 460 | ||||
| -rw-r--r-- | tnslc/compile/module.tnsl | 484 | ||||
| -rw-r--r-- | tnslc/compile/scope.tnsl | 553 | ||||
| -rw-r--r-- | tnslc/compile/struct.tnsl | 293 | ||||
| -rw-r--r-- | tnslc/compile/var.tnsl | 617 |
8 files changed, 2326 insertions, 202 deletions
diff --git a/tnslc/compile/codegen.tnsl b/tnslc/compile/codegen.tnsl index 165fe12..05d0fb7 100644 --- a/tnslc/compile/codegen.tnsl +++ b/tnslc/compile/codegen.tnsl @@ -1,4 +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 index b4ce261..d4bc640 100644 --- a/tnslc/compile/compbuf.tnsl +++ b/tnslc/compile/compbuf.tnsl @@ -26,13 +26,13 @@ struct CompBuf { ;/ /; write_to(~utils.File fout) - fout`.write_cstr("BITS 64\0\n") + fout`.write_cstr("BITS 64\n\0") fout`.write_cstr(self.sec_head.as_cstr()) - fout`.write_cstr("\nsection .data\0\n\n") + fout`.write_cstr("\nsection .data\n\n\0") fout`.write_cstr(self.sec_data.as_cstr()) - fout`.write_cstr("\nsection .text\0\n\n") + fout`.write_cstr("\nsection .text\n\n\0") fout`.write_cstr(self.sec_code.as_cstr()) ;/ diff --git a/tnslc/compile/compile.tnsl b/tnslc/compile/compile.tnsl index 338e28d..fbb9670 100644 --- a/tnslc/compile/compile.tnsl +++ b/tnslc/compile/compile.tnsl @@ -5,5 +5,6 @@ :import "function.tnsl" :import "module.tnsl" :import "codegen.tnsl" + :import "scope.tnsl" ;/ diff --git a/tnslc/compile/function.tnsl b/tnslc/compile/function.tnsl index cf42db1..a57aa76 100644 --- a/tnslc/compile/function.tnsl +++ b/tnslc/compile/function.tnsl @@ -1,36 +1,444 @@ struct Function { - ~uint8 name, - utils.Vector - inputs, - outputs, - ~parse.Node body + ~uint8 name, + utils.Vector + inputs, + outputs, + ~parse.Node _up, + bool m } /; 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 + self.m = false + 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_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) + ;/ + ;/ + ;/ - ~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 < self.outputs.count) [i++] - v = self.outputs.get(i) - v`.end() - ;/ - self.outputs.end() - ;/ + 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 + # Nieve implementation: r10-r15 are callee saved registers + # in the TNSL style ABI + 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/module.tnsl b/tnslc/compile/module.tnsl index 6dbef6c..d3380f4 100644 --- a/tnslc/compile/module.tnsl +++ b/tnslc/compile/module.tnsl @@ -1,68 +1,452 @@ +int SEARCH_VAR = 0 +int SEARCH_STRUCT = 1 +int SEARCH_FUNC = 2 +int SEARCH_SUB = 3 + struct Module { - # Text name of module - ~uint8 name, + # Text name of module + ~uint8 name, + + # Various contained elements + utils.Vector + vars, + structs, + funcs, + subs, - # Various contained elements - utils.Vector - vars, - structs, - funcs, - subs, + # Whether we export or not + bool e, - # Whether we export or not - bool e + # Parent module + ~Module parent } /; method Module - - /; init (~uint8 name, bool exp) - Var v - Struct s - Function f - Module m + + /; _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: Enums + + /; 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) + # Make function aware that it is in a method block + 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 + _printf("Failed to find module for method\n\0") + ;/ + ;; else if (sub`._type == parse.NTYPE_EXPORT) + ~Module m = self._find_sub(sub`.data) + /; if (m !== NULL) + m`.collect_methods(sub) + ;; else + _printf("Failed to find module for method\n\0") + ;/ + ;/ + ;/ + ;/ + + /; _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 (id`._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 and globals to the data 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) + # Static compile all global variables + ~Var v + /; loop (int i = 0; i < self.vars.count) [i++] + v = self.vars.get(i) + v`._static_compile(~self, cb) + ;/ + + # Write function to code section + ~Function f + /; loop (int i = 0; i < self.funcs.count) [i++] + f = self.funcs.get(i) + f`._compile(~self, cb) + ;/ + + # Recurse + ~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) + ;/ - self.vars.init(len v) - self.structs.init(len s) - self.funcs.init(len f) - self.subs.init(len m) + ~Function f + /; loop (int i = 0; i < self.funcs.count) [i++] + f = self.funcs.get(i) + f`._print(indent + 1) + ;/ - self.name = name - self.e = exp - ;/ + ~Module m + /; loop (int i = 0; i < self.subs.count) [i++] + m = self.subs.get(i) + m`._print(indent + 1) + ;/ - /; end - _delete(self.name) + _indent(indent) + _printf("}\n\0") + ;/ - ~Var v - /; loop (int i = 0; i < self.vars.count) [i++] - v = self.vars.get(i) - v`.end() - ;/ - self.vars.end() + /; end + _delete(self.name) - ~Struct s - /; loop (int i = 0; i < self.structs.count) [i++] - s = self.structs.get(i) - s`.end() - ;/ - self.structs.end() + ~Var v + /; loop (int i = 0; i < self.vars.count) [i++] + v = self.vars.get(i) + v`.end() + ;/ + self.vars.end() - ~Function f - /; loop (int i = 0; i < self.funcs.count) [i++] - f = self.funcs.get(i) - f`.end() - ;/ - self.funcs.end() + ~Struct s + /; loop (int i = 0; i < self.structs.count) [i++] + s = self.structs.get(i) + s`.end() + ;/ + self.structs.end() - ~Module m - /; loop (int i = 0; i < self.subs.count) [i++] - m = self.subs.get(i) - m`.end() - ;/ - self.subs.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 index 7822125..e3348dd 100644 --- a/tnslc/compile/scope.tnsl +++ b/tnslc/compile/scope.tnsl @@ -1,123 +1,534 @@ struct Scope { ~uint8 name, - - utils.Vector - stack_vars, - reg_vars, + ~Module mod, + ~CompBuf cb, ~Scope parent, + + utils.Vector vars, tmps, - int - next_const, - next_bool + # Used for generating unique sub-scope labels + int unique } -/; method Scope - /; init (~uint8 name) - self.name = name - - Variable v - self.stack_vars.init(len v) - self.reg_vars.init(len v) +/; _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) +;/ - self.next_const = 0 - self.next_bool = 0 +/; _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) - ~Variable v - /; loop (int i = 0; i < self.stack_vars.count) [i++] - v = self.stack_vars.get(i) + ~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.reg_vars.count) [i++] - v = self.reg_vars.get(i) + /; loop (int i = 0; i < self.tmps.count) [i++] + v = self.tmps.get(i) v`.end() ;/ + self.tmps.end() ;/ - /; _name_rec (~utils.Vector out) + # + # Make variables + # + + /; _next_reg_slot [int] + int out = 11 /; if (self.parent !== NULL) - self.parent`._name_rec(out) - out`.push_cstr("#") + 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 + ;/ + ;/ ;/ - out`.push_cstr(self.name) + return out ;/ - /; _base_label [utils.Vector] - utils.Vector out - out.init(1) + /; _next_tmp_slot [int] + int out = 2 + /; if (self.parent !== NULL) + out = self.parent`._next_tmp_slot() + ;/ - ~uint8 mod_str = self.current.label_prefix() - out.push_cstr(mod_str) - _delete(mod_str) + /; if (out < 0) + return out + ;/ - self._name_rec(~out) + ~Var v + /; loop (int i = 0; i < self.tmps.count) [i++] + v = self.tmps.get(i) + /; if (v`.loc > 1) + out++ + /; if (out > 4) + out = 0 + out = out - 1 + return out + ;/ + ;/ + ;/ return out ;/ - /; label_start [~uint8] - utils.Vector base = self._base_label() - base.push_cstr("#start\0") - return base.as_cstr() + /; _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 ;/ - /; label_rep [~uint8] - utils.Vector base = self._base_label() - base.push_cstr("#rep\0") - return base.as_cstr() + /; mk_aware (~Var v) + Var mk = v`.copy() + mk.offset = 0 + + /; if (mk.loc > 0) + mk.loc = 1 + ;/ + + self.vars.push(~mk) ;/ - /; label_end [~uint8] - utils.Vector base = self._base_label() - base.push_cstr("#end\0") - return base.as_cstr() + /; 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/dlist node\n\0") + return + ;/ + + # Part 1: Add var + Var v + v.init(tp, sub) + v._resolve_type(self.mod) + + # Compute weather we can put it in a register + /; if (v.regable() == true) + v.loc = 1 + ;; else + v.loc = 0 + v.loc = v.loc - 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(sub) + ;/ + ;/ + ;/ + ;/ ;/ - /; label_next_const [~uint8] - utils.Vector base = self._base_label() - base.push_cstr("#const\0") + /; try_move (~parse.Node n) + /; loop (n`._type == parse.NTYPE_PRE_OP) + /; if (n`.sub.count < 1) + return + ;/ + n = n`.sub.get(0) + ;/ + + /; if (n`._type == parse.NTYPE_ID) + ~Var to_move = self._find_var(n`.data) + /; if (to_move == NULL) + return + ;/ + + /; if (to_move`.loc > 0) + int negative = 0 + to_move`.loc = negative - 1 + ;/ + ;/ + ;/ + + /; precheck_stmt (~parse.Node n) + /; if (n`._type == parse.NTYPE_PRE_OP) + /; if (utils.strcmp(n`.data, "~\0") == true) + self.try_move(n) + return + ;/ + ;/ + + ~parse.Node sub + /; loop (int i = 0; i < n`.sub.count) [i++] + sub = n`.sub.get(i) + self.precheck_stmt(sub) + ;/ + ;/ + + /; _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 + ;/ + ;/ + + /; 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(" ; Create stack space for local variable \0") + self.cb`.add_c(v`.name) + self.cb`.add_c("\n\0") + _delete(stk_str) + ;/ + + return v + ;/ + + /; mk_set_var (~Var src) [~Var] + ~Var v = self.mk_var(src) + + /; if (v == NULL) + return NULL + ;/ + + /; if (v`.is_ref() == true) + v`.set_ref(self.cb, src) + ;; else + v`.set(self.cb, src) + ;/ + + 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(" ; Create stack space for tmp variable\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 - ~uint8 str = utils.int_to_str(self.next_const) - base.push_cstr(str) - self.next_const++ - _delete(str) + ~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() + ;/ - return base.as_cstr() + /; 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(" ; Free stack space (freeing tmp variables)\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 ;/ - /; label_bool [~uint8] - utils.Vector base = self._base_label() - base.push_cstr("#bool\0") + # 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) - ~uint8 str = utils.int_to_str(self.next_bool) - base.push_cstr(str) - self.next_bool++ - _delete(str) + _recursive_scope_name(~self, ~out) - return base.as_cstr() + return out ;/ - /; label_bool_adv - self.next_bool++ + /; base_label [~uint8] + utils.Vector v = self._base_label() + return v.as_cstr() ;/ - /; subscope (~uint8 name) [Scope] - Scope out - - utils.Vector str - str.from_cstr(name) - _delete(name) + /; place_base_label + ~uint8 bl = self.base_label() + self.cb`.add_c(bl) + self.cb`.add_c(":\n\0") + _delete(bl) + ;/ - out.init(str.as_cstr(), self.current) - out.parent = ~self + /; 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() + ;/ - return out + /; 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 index d175aef..5eded31 100644 --- a/tnslc/compile/struct.tnsl +++ b/tnslc/compile/struct.tnsl @@ -3,44 +3,279 @@ struct Struct { ~uint8 name, ~Module methods, utils.Vector members, - int size + 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 (~uint8 name) - self.name = name - Var v - self.members.init(len v) - ;/ + /; 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 + ;/ - /; add_member(~Var v) - self.members.push(v) - ;/ + /; _find_type (~parse.Node tn) [~Struct] + + # Init vector of strings + utils.Vector sv + sv.init(8) - /; get_member(~uint8 name) [~Var] - ~Var out = NULL + ~uint8 str + ~parse.Node n + bool seen_id = false - ~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 - ;/ - ;/ + /; 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 + ;/ + ;/ - return out - ;/ + # 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() - ;/ + /; 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/var.tnsl b/tnslc/compile/var.tnsl index 9526fc6..b684c33 100644 --- a/tnslc/compile/var.tnsl +++ b/tnslc/compile/var.tnsl @@ -1,33 +1,604 @@ +# 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 + ~uint8 name, + ~Struct _type, + utils.Vector ptrc, + int loc, offset, + + ~parse.Node _tn, _id } /; method Var - /; init (~uint8 name) - self.name = name - self.ptrc.init(4) - ;/ + # 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 + ;/ + + /; is_ref [bool] + ~int32 p = self.top_ptrc() + /; if (p == NULL) + return false + ;/ + + return p` == 0 + ;/ + + /; _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: everything + ;/ + + /; 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) - /; ptr [int32] - ~int32 i - i = self.ptrc.get(self.ptrc.count - 1) - return i` - ;/ + /; if (self.in_mem() == true) + out.push_char('[') + ;/ - /; ptr_push (int32 p) - self.ptrc.push(~p) - ;/ + ~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) - /; ptr_pop - self.ptrc.pop() - ;/ - /; end - _delete(self.name) - self.ptrc.end() - ;/ + /; 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) + # Options: + # - If builtin then move based on size (byte, word, dword, qword) + # - If pointer then move qword + # - If struct then move via rep movsb + + # Changes need to be made based on whether either is on the stack + # or if either is a reference + + # Can move to/from stack if only one is on stack/reference + # otherwise we must pre-mov the source into RSI and then + # we can move into the recipiant's address + + /; if () + ;/ + ;/ + + # 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) + + Var cpy = self.copy() + cpy.loc = 1 + cpy.offset = 0 + + # Set RAX register for product operation + cpy.set(buf, ~self) + + ~uint8 from_str = other`.gen_loc() + + buf`.add_c(" \0") + buf`.add_c(op_str) + buf`.add_c(" \0") + buf`.add_c(from_str) + buf`.add_c("\n\0") + + _delete(from_str) + + # Set back the var from the read_reg + cpy.loc = read_reg + self.set(buf, cpy) + + cpy.end() + ;/ + + /; 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 + ;/ + + /; if (self.name{0} == 'u') + self.product_op(buf, other, "mul", 1) + ;; else + 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 (self.name{0} == 'u') + self.product_op(buf, other, "div", 1) + ;; else + self.product_op(buf, other, "idiv", 1) + ;/ + ;/ + + /; mod (~CompBuf buf, ~Var other) + /; if (self.loc == VLOC_LITL && other`.loc == VLOC_LITL) + self.offset = self.offset % other`.offset + return + ;/ + + /; if (self.name{0} == 'u') + self.product_op(buf, other, "div", 4) + ;; else + self.product_op(buf, other, "idiv", 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") + ;/ + + /; not (~CompBuf buf) + ~uint8 to_str = self.gen_loc() + buf`.add_c(" not \0") + buf`.add_c(to_str) + buf`.add_c("\n\0") + _delete(to_str) + ;/ + + /; member (~CompBuf buf, ~uint8 name) [Var] + Var out + return out + ;/ ;/ + + |