From 3442a2c5bbbf5ec604ef104e9ab92912db98f222 Mon Sep 17 00:00:00 2001 From: Kyle Gunger Date: Fri, 24 Mar 2023 02:10:55 -0400 Subject: Update index solver --- tnslc/c_wrap.tnsl | 2 +- tnslc/simple.tnsl | 18 +- tnslc/tnslc.tnsl | 4634 +++++++++++++++++++++++++++-------------------------- 3 files changed, 2367 insertions(+), 2287 deletions(-) diff --git a/tnslc/c_wrap.tnsl b/tnslc/c_wrap.tnsl index 3d5fa02..7348417 100644 --- a/tnslc/c_wrap.tnsl +++ b/tnslc/c_wrap.tnsl @@ -74,7 +74,7 @@ struct Vector { ;/ /; set (uint i, ~void data) - ~void index = get(i) + ~void index = self.get(i) /; loop (i = 0; i < self.el_size) [index = index + 1; data = data + 1; i++] index = data ;/ diff --git a/tnslc/simple.tnsl b/tnslc/simple.tnsl index 6ac7f31..b55be2a 100644 --- a/tnslc/simple.tnsl +++ b/tnslc/simple.tnsl @@ -1,14 +1,12 @@ -struct Test { - int i -} - -/; method Test - /; whatever [int] - return self.i - ;/ -;/ +{}uint8 str1 = "abcd" +{}uint8 str2 = "abcd" /; main [int] + /; loop (int i = 0; i < 4) [i++] + /; if (str1{i} !== str2{i}) + return 1 + ;/ + ;/ return 0 -;/ \ No newline at end of file +;/ diff --git a/tnslc/tnslc.tnsl b/tnslc/tnslc.tnsl index ecc9e61..9853af6 100644 --- a/tnslc/tnslc.tnsl +++ b/tnslc/tnslc.tnsl @@ -360,2831 +360,2913 @@ ;/ ;/ -# General defs: -## Type defs -## Function defs -## Method defs -## Module defs -## Constant and variable defs +## +## Tokenizer funcs +## -# Module -## General defs -# Block -## Variable defs -## Control flow defs -## Value defs +/; is_whitespace (uint8 c) [bool] + ;return (c == '\n' || c == '\t' || c == ' ') +;/ -;enum PTYPE [int] { - POINTER = 0, - REFERENCE = 1, - ARRAY = 2 -} +;{}uint8 MULTI_PARENS = "/;:#" +;{}uint8 PARENS = "()[]{}" +;{}uint8 SEPS = "\n;:," +;{}uint8 RESERVED = "`~!%^&*()-+=[]{}|;:/?<>.,\"" +;{}uint8 AUGMENTS = "=~!<>&|^+-*/%`." -# Represents a data type -;struct Type { - int s, - {}uint8 - name, - mod_name, - {}int - ptr_chain, - {}Variable - members -} +;{}{}uint8 MULTI_AUGMENTS = { + "++", "--", -/; method Type - /; sprint [{}uint8] - ;{}uint8 out = string_join( {"{ ", int_to_string(self.s), ", ", self.name, ", ", self.mod_name, ", { "}, "") - ;{}{}uint8 pch = {} - /; loop (int i = 0; i < len(self.ptr_chain)) [i++] - ;pch.append(int_to_string(self.ptr_chain{i})) - ;/ - ;out = string_add(out, string_join(pch, ", ")) - ;out = string_add(out, " } }") - ;return out - ;/ + "==", "!==", "&&", "||", "^^", "<==", ">==", "!>", "!<", - /; size [int] - /; loop (int i = 0; i < len(self.ptr_chain)) [i++] - /; if (self.ptr_chain{i} !== PTYPE.REFERENCE) - ;return 8 - ;/ - ;/ - ;return self.s - ;/ -;/ + "~=", "`=", "%=", "^=", "&=", "*=", + "!=", "|=", "/=", -;{}{}uint8 PRIM_NAMES = { - "uint8", "uint16", "uint32", "uint64", "uint", - "int8", "int16", "int32", "int64", "int", - "float32", "float64", "float", - "bool", "void" + "<<", ">>", "!&", "!|", "!^" } -;{}int PRIM_SIZES = { - 1, 2, 4, 8, 8, - 1, 2, 4, 8, 8, - 4, 8, 8, - 1, - 8 -} -;Type NO_TYPE = {0, "", "", {}, {}} +;{}{}uint8 KEYWORDS = { + "len", + "is", -/; is_primitive ({}uint8 t) [int] - ;{}{}uint8 pn = PRIM_NAMES - ;{}int ps = PRIM_SIZES - /; loop (int i = 0; i < len pn) [i++] - /; if (string_equate(pn{i}, t)) - ;return ps{i} - ;/ - ;/ - ;return -1 -;/ + "if", + "else", + "loop", -/; get_primitive (int i) [Type] - ;{}{}uint8 pn = PRIM_NAMES - ;{}int ps = PRIM_SIZES - ;return {ps{i}, pn{i}, string_add("_", pn{i}), {}, {}} -;/ + "continue", + "break", + "return", -# Represents the place in memory where a variable is -;enum LOCATION [int] { - REGISTER = 0, - STACK = 1, - LABEL = 2, - LITERAL = 3 -} + "method", + "struct", + "enum", + "interface", -# Represents a variable -;struct Variable { - {}uint8 - name, - Type - data_type, - int - location, - loc_type + "export", + "module", + + "const", + "static", + "volatile", + "raw", + + "extends", + "override", + + "asm" } -# Get common register name by index -/; reg_by_num(int r) [{}uint8] - /; if (r == 0) - ;return "ax" - ;; if (r == 1) - ;return "bx" - ;; if (r == 2) - ;return "cx" - ;; if (r == 3) - ;return "dx" - ;; if (r == 4) - ;return "si" - ;; if (r == 5) - ;return "di" - ;; if (r == -1) - ;return "sp" - ;; if (r == -2) - ;return "bp" - ;/ - ;return int_to_string(r) -;/ +;{}{}uint8 KEYTYPES = { + "uint8", + "uint16", + "uint32", + "uint64", + "uint", -# Get common register by common name and size -/; reg_by_name_size ({}uint8 common, uint sz) [{}uint8] - ;{}uint8 out = "" - /; if (common{0} !< 'a') + "int8", + "int16", + "int32", + "int64", + "int", - /; if (sz == 1) - /; if(common{1} == 'x') - ;common{1} = 'l' - ;; else - ;common.append('l') - ;/ - ;; else if (sz == 4) - ;out.append('e') - ;; else if (sz == 8) - ;out.append('r') - ;/ + "float32", + "float64", + "float", - ;out = string_add(out, common) + "comp32", + "comp64", + "comp", - ;; else + "vect", + "bool", - ;out.append('r') - ;out = string_add(out, common) - /; if (sz == 1) - ;out.append('b') - ;; else if (sz == 2) - ;out.append('w') - ;; else if (sz == 4) - ;out.append('d') - ;/ - ;/ + "type", + "void" +} - ;return out -;/ +/; is_delimiter ({}uint8 str) [bool] + /; if (len str > 2 || len str < 1) + ;return false + ;/ -/; get_reg (int r, sz) [{}uint8] - ;return reg_by_name_size(reg_by_num(r), sz) + /; if (len str == 2) + ;return string_contains(MULTI_PARENS, str{0}) && string_contains(MULTI_PARENS, str{1}) + ;/ + + ;return string_contains(PARENS, str{0}) ;/ -/; mov_by_size(int sz)[{}uint8] - /; if (sz == 1) - ;return "byte " - ;; else if (sz == 2) - ;return "word " - ;; else if (sz == 4) - ;return "dword " - ;; else if (sz == 8) - ;return "qword " +/; is_separator ({}uint8 str) [bool] + /; if (len str < 1) + ;return false ;/ - ;return "" + ;return string_contains(SEPS, str{0}) ;/ -/; loc_from_str ({}uint8 str, offset, int sz) [{}uint8] - ;{}uint8 pre = "" - /; if (sz > 0) - ;pre = mov_by_size(sz) +/; is_reserved ({}uint8 str) [bool] + /; if (len str < 1) + ;return false ;/ - ;return string_join( {pre, "[", str, offset, "]" }, "") + ;return string_contains(RESERVED, str{0}) ;/ -/; strip_int({}int p) [{}int] - ;{}int out = {} - /; loop (int i = 0; i < len p - 1) [i++] - ;out.append(p{i}) +/; is_augment ({}uint8 str) [bool] + /; if (len str == 1) + ;return string_contains(AUGMENTS, str{0}) ;/ - ;return out + + ;return list_contains(MULTI_AUGMENTS, str) ;/ -/; to_jmp({}uint8 cmp) [{}uint8] - /; if (string_equate(cmp, "==")) - ;return "\tje " - ;; else if (string_equate(cmp, "!==")) - ;return "\tjne " - ;; else if (string_equate(cmp, "!<") || string_equate(cmp, ">==")) - ;return "\tjge " - ;; else if (string_equate(cmp, "!>") || string_equate(cmp, "<==")) - ;return "\tjle " - ;; else if (string_equate(cmp, ">")) - ;return "\tjg " - ;; else if (string_equate(cmp, "<")) - ;return "\tjl " +/; is_str_literal ({}uint8 str) [bool] + /; if (string_equate(str, "\"") || string_equate(str, "'")) + ;return true ;/ - ;return "\tjnz " -;/ -/; not_jmp({}uint8 cmp) [{}uint8] - /; if (string_equate(cmp, "==")) - ;return "\tjne " - ;; else if (string_equate(cmp, "!==")) - ;return "\tje " - ;; else if (string_equate(cmp, "!<") || string_equate(cmp, ">==")) - ;return "\tjl " - ;; else if (string_equate(cmp, "!>") || string_equate(cmp, "<==")) - ;return "\tjg " - ;; else if (string_equate(cmp, ">")) - ;return "\tjle " - ;; else if (string_equate(cmp, "<")) - ;return "\tjge " + /; if (len str < 2) + ;return false + ;; else if (str{0} !== '\'' && str{0} !== '"') + ;return false ;/ - ;return "\tjz " + + /; loop (int i = 1; i < len str) [i++] + /; if (str{i} == '\\') + ;i++ + ;; else if (str{i} == str{0}) + ;return i == len str - 1 + ;/ + ;/ + ;return true ;/ -# Methods on variables assume that the rax, rdx, rsi, and rdi registers are fair game. -# ONLY USES RDI ON SOME ASSIGNMENTS. SAFE FOR BOOLEAN STORAGE -/; method Variable - - /; sprint [{}uint8] - ;return string_join( { - "{ ", self.name, ", ", self.data_type.sprint(), ", ", int_to_string(self.location), ", ", int_to_string(self.loc_type), " }" - },"") +/; is_num_literal ({}uint8 str) [bool] + /; if (len str < 1) + ;return false + ;; if (len str == 1 && str{0} == '.') + ;return false ;/ - /; norm_loc (int sz) [{}uint8] - /; if (self.loc_type == LOCATION.LABEL) - ;return loc_from_str(string_add("rel ", self.name), string_add(" + ", int_to_string(self.location)), sz) - ;; else if (self.loc_type == LOCATION.REGISTER) - /; if (self.is_ref()) - ;return loc_from_str(get_reg(self.location, 8), "", sz) + ;bool dec = false + /; loop (int i = 0; i < len str) [i++] + /; if (str{i} == '.') + /; if (!dec) + ;dec = true + ;; else + ;return false ;/ - ;return get_reg(self.location, sz) - ;; else if (self.loc_type == LOCATION.STACK) - ;return string_join( { "[ rbp - ", int_to_string(self.location), " ]" }, "") - ;; else if (self.loc_type == LOCATION.LITERAL) - ;return int_to_string(self.location) + ;; else if (str{i} < '0' || str{i} > '9') + ;return false ;/ ;/ + ;return true +;/ - /; norm_size [int] - /; if (len (self.data_type.ptr_chain) > 1) - ;return 8 - ;; else if (len (self.data_type.ptr_chain) == 0) - ;return self.data_type.s - ;/ +/; is_literal({}uint8 str) [bool] + ;return is_str_literal(str) || is_num_literal(str) || string_equate(str, "true") || string_equate(str, "false") +;/ - /; if (self.data_type.ptr_chain{0} == PTYPE.REFERENCE) - ;return self.data_type.s - ;/ - ;return 8 +/; gen_type (Token t) [int] + /; if (is_separator(t.data)) + ;return TOKEN.SEPARATOR ;/ - # TODO: Match a type to another type if possible - # this is the type inference engine - /; match_types (Variable to_match, ~CompData data) [Variable] - /; if (to_match.loc_type == LOCATION.LITERAL) - ;return to_match - ;; if (!(to_match.is_prim()) || (len(to_match.data_type.ptr_chain) > 0 && !(to_match.is_ref()))) - ;return to_match - ;/ + /; if (is_literal(t.data)) + ;return TOKEN.LITERAL + ;/ - ;Variable out = {"#match", self.data_type, 4, LOCATION.REGISTER} - ;{}uint8 mov = "mov" - - /; if (self.data_type.name{0} == 'i' && out.norm_size() > to_match.norm_size()) - ;mov = string_add(mov, "sx") - /; if (out.norm_size() == 8 && to_match.norm_size() == 4) - ;mov.append('d') - ;/ - ;; else if (self.data_type.name{0} == 'u' && out.norm_size() > to_match.norm_size() && out.norm_size() !== 8) - ;mov = string_add(mov, "zx") - ;; else - ;return to_match + /; if (is_reserved(t.data)) + /; if (is_delimiter(t.data)) + ;return TOKEN.DELIMITER + ;; else if (is_augment(t.data)) + ;return TOKEN.AUGMENT ;/ + ;; else if (list_contains(KEYWORDS, t.data)) + ;return TOKEN.KEYWORD + ;; else if (list_contains(KEYTYPES, t.data)) + ;return TOKEN.KEYTYPE + ;/ - ;data`.csec = string_join( { - data`.csec, - "\t", mov, " ", out.norm_loc(out.norm_size()), ", ", to_match.norm_loc(to_match.norm_size()), "\n" - }, "") - - ;return out + ;return TOKEN.DEFWORD +;/ + +/; break_token (Token current, uint8 to_append) [bool] + /; if (is_literal(current.data)) + ;current.data.append(to_append) + ;return !(is_literal(current.data)) ;/ - - /; norm_op ({}uint8 op, int sz, Variable v, ~CompData data) - /; if (self.loc_type == LOCATION.LITERAL) - ;v.norm_op(op, sz, self, data) - ;; else - ;v = self.match_types(v, data) - /; if (self.loc_type == LOCATION.REGISTER || v.loc_type == LOCATION.REGISTER) - ;data`.csec = string_join( { - data`.csec, - "\t", op, " ", self.norm_loc(sz), ", ", v.norm_loc(sz), "\n" - }, "") - ;; else - ;data`.csec = string_join( { - data`.csec, - "\tmov ", get_reg(0, sz), ", ", v.norm_loc(sz), "\n", - "\t", op, " ", self.norm_loc(sz), ", ", get_reg(0, sz), "\n" - }, "") - ;/ - ;/ + + /; if (is_whitespace(to_append) || current.cmp("\n")) + ;return true ;/ - /; is_ref [bool] - ;int s = len (self.data_type.ptr_chain) - /; if (s > 0) - ;return self.data_type.ptr_chain{s - 1} == PTYPE.REFERENCE + /; if (is_reserved(current.data)) + /; if (is_reserved({to_append})) + ;current.data.append(to_append) + ;return gen_type(current) == TOKEN.DEFWORD ;/ - ;return false + ;return true + ;; else if (is_reserved({to_append})) + ;return true ;/ - /; is_prim [bool] - ;return len(self.data_type.ptr_chain) > 1 || is_primitive(self.data_type.name) !< 0 - ;/ + ;return false +;/ - /; strip_one (~CompData data) - ;data`.csec = string_join( { - data`.csec, - "\tmov rsi, [rsi]\n" - }, "") - ;self.data_type.ptr_chain = strip_int(self.data_type.ptr_chain) +/; handle_comment (tnsl.io.File fd, ~Token current, ~int line) [bool] + ;bool block = false + /; if (current`.cmp("/")) + ;block = true ;/ - /; strip_refs (~CompData data) [Variable] - ;Variable out = {"#ref", self.data_type, 4, LOCATION.REGISTER} + /; loop (int i = fd.read(); i !== -1) [i = fd.read()] + /; if (i == '\n') + ;line`++ + /; if (!block) + ;return true + ;/ + ;; else if (block && i == '#') + ;i = fd.read() + /; if (i == '/') + ;current` = {0, line, ""} + ;return false + ;; else if (i == ';' || i == ':') + ;current`.data.append(i) + ;return false + ;/ - /; if (self.loc_type == LOCATION.REGISTER) - ;data`.csec = string_join( { - data`.csec, - "\tmov rsi, ", get_reg(self.location, 8), "\n" - }, "") - ;; else - ;data`.csec = string_join( { - data`.csec, - "\tlea rsi, ", self.norm_loc(8), "\n" - }, "") - ;out.data_type.ptr_chain.append(PTYPE.REFERENCE) - ;/ + /; loop (i !== '\n' && i !== -1) [i = fd.read()] ;/ - ;int pc = len (out.data_type.ptr_chain) - /; loop (pc > 1) [pc = len (out.data_type.ptr_chain)] - /; if (out.data_type.ptr_chain{pc - 1} == PTYPE.REFERENCE && out.data_type.ptr_chain{pc - 2} !== PTYPE.ARRAY) - ;out.strip_one(data) - ;; else - ;break - ;/ - ;/ - ;return out - ;/ - - # functions that do work on this variable - /; add (Variable v, ~CompData data) - /; if (self.loc_type == LOCATION.LITERAL && v.loc_type == LOCATION.LITERAL) - ;self.location = self.location + v.location - ;; else - ;self.norm_op("add", self.norm_size(), v, data) + ;line`++ ;/ ;/ +;/ - /; sub (Variable v, ~CompData data) - /; if (self.loc_type == LOCATION.LITERAL && v.loc_type == LOCATION.LITERAL) - ;self.location = self.location - v.location - ;; else - ;self.norm_op("sub", self.norm_size(), v, data) - ;/ - ;/ +/; tokenize (Path f) [{}Token] + ;{}Token out = {} - /; or (Variable v, ~CompData data) - /; if (self.loc_type == LOCATION.LITERAL && v.loc_type == LOCATION.LITERAL) - ;self.location = self.location | v.location - ;; else - ;self.norm_op("or", self.norm_size(), v, data) + ;tnsl.io.File fd = f.open_read() + + ;Token current = {0, 0, ""} + ;int line = 1 + /; loop (int i = fd.read(); i > -1) [i = fd.read()] + /; if (i == '\r') + ;continue ;/ - ;/ - /; and (Variable v, ~CompData data) - /; if (self.loc_type == LOCATION.LITERAL && v.loc_type == LOCATION.LITERAL) - ;self.location = self.location & v.location - ;; else - ;self.norm_op("and", self.norm_size(), v, data) + /; if (i == '#' && (break_token(current, i) || gen_type(current) !== TOKEN.LITERAL)) + ;bool ln = handle_comment(fd, ~current, ~line) + /; if (ln) + ;current.tokenType = gen_type(current) + /; if (!(current.cmp(""))) + ;out.append(current) + ;/ + ;out.append({TOKEN.SEPARATOR, line - 1, "\n"}) + ;/ + ;continue ;/ - ;/ - /; xor (Variable v, ~CompData data) - /; if (self.loc_type == LOCATION.LITERAL && v.loc_type == LOCATION.LITERAL) - ;self.location = self.location ^ v.location + /; if (i == '\n' && (break_token(current, i) || gen_type(current) !== TOKEN.LITERAL)) + ;log_vis(".") + /; if (!(current.cmp("\n"))) + ;current.tokenType = gen_type(current) + /; if (!(current.cmp(""))) + ;out.append(current) + ;/ + ;current = {TOKEN.SEPARATOR, line, ""} + ;current.data.append(i) + ;/ + ;line++ + ;; else if (break_token(current, i)) + ;current.tokenType = gen_type(current) + /; if (!(current.cmp(""))) + ;out.append(current) + ;/ + ;current = {0, line, ""} + /; if (!(is_whitespace(i))) + ;current.data.append(i) + ;/ ;; else - ;self.norm_op("xor", self.norm_size(), v, data) + ;current.data.append(i) ;/ ;/ + ;log_vis("OK\n") - /; not (Variable v, ~CompData data) - /; if (self.loc_type == LOCATION.LITERAL && v.loc_type == LOCATION.LITERAL) - ;self.location = !v.location - ;; else if (string_equate(v.data_type.name, "bool") && len (v.data_type.ptr_chain) == 0) - - ;self.xor(literal_variable("true", "", data), data) - ;; else - ;v = self.match_types(v, data) - ;self.set(v, data) - ;data`.csec = string_join( { - data`.csec, - "\tnot ", self.norm_loc(self.norm_size()), "\n" - }, "") - ;/ + /; if (!(current.cmp("")) && !(current.cmp("\n"))) + ;current.tokenType = gen_type(current) + ;out.append(current) ;/ - /; cmp (Variable v, ~CompData data) - /; if (self.loc_type == LOCATION.LITERAL && v.loc_type == LOCATION.LITERAL) - /; if (self.location == v.location) - ;self.location = 1 - ;; else - ;self.location = 0 - ;/ - ;; else if (v.is_prim() && self.is_prim()) - ;self.norm_op("cmp", self.norm_size(), v, data) - ;/ - ;/ + ;fd.close() - /; negative (Variable v, ~CompData data) - ;int sz = self.norm_size() - /; if (v.loc_type == LOCATION.LITERAL) - ;data`.csec = string_join( { - data`.csec, - "\tmov ", mov_by_size(sz), self.norm_loc(sz), ", ", int_to_string(v.location), "\n" - }, "") - ;; else - ;v = self.match_types(v, data) - ;data`.csec = string_join( { - data`.csec, - "\tmov ", get_reg(0, sz), ", ", v.norm_loc(sz), "\n", - "\tnot ", get_reg(0, sz), "\n", - "\tmov ", self.norm_loc(sz), ", ", get_reg(0, sz), "\n" - }, "") - ;/ - ;/ + ;return out +;/ - /; ax_compute ({}uint8 op, int sz, Variable v, ~CompData data, int keep) - /; if (self.loc_type == LOCATION.LITERAL) - ;v.ax_compute(op, sz, self, data) - ;; else - ;v = self.match_types(v, data) +# General defs: +## Type defs +## Function defs +## Method defs +## Module defs +## Constant and variable defs - /; if (self.data_type.name{0} == 'i') - ;op = string_add("i", op) - ;/ +# Module +## General defs - /; if (self.loc_type !== LOCATION.REGISTER && v.loc_type !== LOCATION.REGISTER) - ;data`.csec = string_join( { - data`.csec, - "\t", op, " ", self.norm_loc(sz), v.norm_loc(sz), "\n" - }, "") - ;; else - ;data`.csec = string_join( { - data`.csec, - "\tmov ", get_reg(0, sz), ", ", v.norm_loc(sz), "\n", - "\t", op, " ", self.norm_loc(sz), "\n", - "\tmov ", self.norm_loc(sz), ", ", get_reg(keep, sz), "\n" - }, "") - ;/ - ;/ - ;/ +# Block +## Variable defs +## Control flow defs +## Value defs - /; div (Variable v, ~CompData data) - /; if (self.loc_type == LOCATION.LITERAL && v.loc_type == LOCATION.LITERAL) - ;self.location = self.location / v.location - ;; else - ;self.ax_compute("div", self.norm_size(), v, data, 0) - ;/ - ;/ +;enum PTYPE [int] { + POINTER = 0, + REFERENCE = 1, + ARRAY = 2 +} - /; mod (Variable v, ~CompData data) - /; if (self.loc_type == LOCATION.LITERAL && v.loc_type == LOCATION.LITERAL) - ;self.location = self.location % v.location - ;; else - ;self.ax_compute("div", self.norm_size(), v, data, 3) +# Represents a data type +;struct Type { + int s, + {}uint8 + name, + mod_name, + {}int + ptr_chain, + {}Variable + members +} + +/; method Type + /; sprint [{}uint8] + ;{}uint8 out = string_join( {"{ ", int_to_string(self.s), ", ", self.name, ", ", self.mod_name, ", { "}, "") + ;{}{}uint8 pch = {} + /; loop (int i = 0; i < len(self.ptr_chain)) [i++] + ;pch.append(int_to_string(self.ptr_chain{i})) ;/ + ;out = string_add(out, string_join(pch, ", ")) + ;out = string_add(out, " } }") + ;return out ;/ - /; mul (Variable v, ~CompData data) - /; if (self.loc_type == LOCATION.LITERAL && v.loc_type == LOCATION.LITERAL) - ;self.location = self.location * v.location - ;; else - ;self.ax_compute("mul", self.norm_size(), v, data, 0) + /; size [int] + /; loop (int i = 0; i < len(self.ptr_chain)) [i++] + /; if (self.ptr_chain{i} !== PTYPE.REFERENCE) + ;return 8 + ;/ ;/ + ;return self.s ;/ +;/ - # Todo: Make sure this works well. - /; set (Variable v, ~CompData data) - ;int sz = self.norm_size() - ;v = self.match_types(v, data) - /; if (self.loc_type == LOCATION.LITERAL && v.loc_type == LOCATION.LITERAL) - ;self.location = v.location - ;; else if (self.is_prim()) - /;if (self.is_ref() && v.is_ref()) - ;data`.csec = string_join( { - data`.csec, - "\tmov ", get_reg(4, sz), ", ", v.norm_loc(sz), "\n", - "\tmov ", self.norm_loc(sz), ", ", get_reg(4, sz), "\n" - }, "") - ;; else - ;data`.csec = string_join( { - data`.csec, - "\tmov ", self.norm_loc(sz), ", ",v.norm_loc(sz), "\n" - }, "") - ;/ - ;; else - /; if (self.is_ref()) - ;data`.csec = string_join( { - data`.csec, - "\tmov rdi, ", self.norm_loc(8), "\n" - }, "") - ;; else - ;data`.csec = string_join( { - data`.csec, - "\tlea rdi, ", self.norm_loc(8), "\n" - }, "") - ;/ +;{}{}uint8 PRIM_NAMES = { + "uint8", "uint16", "uint32", "uint64", "uint", + "int8", "int16", "int32", "int64", "int", + "float32", "float64", "float", + "bool", "void" +} - /; if (v.is_ref()) - ;data`.csec = string_join( { - data`.csec, - "\tmov rsi, ", v.norm_loc(8), "\n" - }, "") - ;; else - ;data`.csec = string_join( { - data`.csec, - "\tlea rsi, ", v.norm_loc(8), "\n" - }, "") - ;/ +;{}int PRIM_SIZES = { + 1, 2, 4, 8, 8, + 1, 2, 4, 8, 8, + 4, 8, 8, + 1, + 8 +} - ;data`.csec = string_join( { - data`.csec, - "\tmov rcx, ", int_to_string(sz), "\n", - "\trep movsb\n" - }, "") +;Type NO_TYPE = {0, "", "", {}, {}} + +/; is_primitive ({}uint8 t) [int] + ;{}{}uint8 pn = PRIM_NAMES + ;{}int ps = PRIM_SIZES + /; loop (int i = 0; i < len pn) [i++] + /; if (string_equate(pn{i}, t)) + ;return ps{i} ;/ ;/ + ;return -1 +;/ - # Only to be called from a boolean variable - /; bool_from (Variable v, ~CompData data, {}uint8 landing_pad) - ;int sz = v.norm_size() - ;data`.csec = string_join( { - data`.csec, - "\tmov ", get_reg(4, sz), ", ", v.norm_loc(sz), "\n", - "\ttest ", get_reg(4, sz), ", ", get_reg(4, sz), "\n", - "\tmov ", self.norm_loc(1), ", 1\n", - "\tjnz ", skip_pad, "\n", - "\tmov ", self.norm_loc(1), ", 0\n", - landing_pad, ":\n" - }, "") - ;/ +/; get_primitive (int i) [Type] + ;{}{}uint8 pn = PRIM_NAMES + ;{}int ps = PRIM_SIZES + ;return {ps{i}, pn{i}, string_add("_", pn{i}), {}, {}} +;/ - /; move_register (int new_reg, ~CompData data) - ;int sz = self.norm_size() - /; if (self.is_ref()) - ;sz = 8 - ;/ - ;data`.csec = string_join( { - data`.csec, - "\tmov ", get_reg(new_reg, sz), ", ", get_reg(self.location, sz), "\n" - }, "") - ;self.location = new_reg - ;/ +# Represents the place in memory where a variable is +;enum LOCATION [int] { + REGISTER = 0, + STACK = 1, + LABEL = 2, + LITERAL = 3 +} - /; ref (Variable to_ref, ~CompData data) - ;int l = len (to_ref.data_type.ptr_chain) - /; if (to_ref.is_ref()) - ;to_ref.data_type.ptr_chain{l - 1} = PTYPE.POINTER - ;self.set(to_ref, data) - ;; else if (to_ref.loc_type !== LOCATION.REGISTER && to_ref.loc_type !== LOCATION.LITERAL) - ;data`.csec = string_join( { - data`.csec, - "\tlea rsi, ", to_ref.norm_loc(0), "\n", - "\tmov ", self.norm_loc(8), ", rsi\n" - }, "") - ;; else - ;log_err(string_add("Failure to create reference from register or literal value ", to_ref.sprint())) - ;/ - ;/ +# Represents a variable +;struct Variable { + {}uint8 + name, + Type + data_type, + int + location, + loc_type +} - /; deref (~CompData data) [Variable] - ;Variable out = self.strip_refs(data) - ;int opc = len (out.data_type.ptr_chain) - /; if (opc == 0) - ;log_err("Can not deref a variable that is not a pointer (ERR: SNPTRC)") - ;/ - ;out.data_type.ptr_chain{opc - 1} = PTYPE.REFERENCE - ;return out - ;/ +# Get common register name by index +/; reg_by_num(int r) [{}uint8] + /; if (r == 0) + ;return "ax" + ;; if (r == 1) + ;return "bx" + ;; if (r == 2) + ;return "cx" + ;; if (r == 3) + ;return "dx" + ;; if (r == 4) + ;return "si" + ;; if (r == 5) + ;return "di" + ;; if (r == -1) + ;return "sp" + ;; if (r == -2) + ;return "bp" + ;/ + ;return int_to_string(r) +;/ - /; member ({}uint8 name, ~CompData data) [Variable] - ;Variable out = self.strip_refs(data) - ;int accum = 0 - ;int i = 0 - /; loop(i < len (out.data_type.members)) [i++] - /; if (string_equate(out.data_type.members{i}.name, name)) - ;break - ;/ - ;accum = accum + out.data_type.members{i}.data_type.s - ;/ - - ;out.data_type = out.data_type.members{i}.data_type - ;out.data_type.ptr_chain.append(PTYPE.REFERENCE) - - ;data`.csec = string_join( { - data`.csec, - "\tadd rsi, ", int_to_string(accum), "\n" - }, "") +# Get common register by common name and size +/; reg_by_name_size ({}uint8 common, uint sz) [{}uint8] + ;{}uint8 out = "" + /; if (common{0} !< 'a') - ;return out - ;/ + /; if (sz == 1) + /; if(common{1} == 'x') + ;common{1} = 'l' + ;; else + ;common.append('l') + ;/ + ;; else if (sz == 4) + ;out.append('e') + ;; else if (sz == 8) + ;out.append('r') + ;/ - /; index (Variable i, ~CompData data) [Variable] - ;Variable out = self.strip_refs(data) - - ;int sz = out.norm_size() - ;int opc = len (out.data_type.ptr_chain) + ;out = string_add(out, common) - /; if (opc == 0 || (out.is_ref() && opc == 1)) - ;log_err(string_add("Unable to index a type if it is not a pointer or array ", out.sprint())) - ;/ - - /; if (out.is_ref()) - ;data`.csec = string_join( { - data`.csec, - "\tadd rsi, 8\n" - }, "") - ;/ + ;; else - ;Variable t = {"#tmp", get_primitive(is_primitive("uint")), 0, LOCATION.REGISTER} - ;t.set({"#literal", t.data_type, sz, LOCATION.LITERAL}, data) - ;t.mul(i, data) - ;data`.csec = string_join( { - data`.csec, - "\tadd rsi, rax\n" - }, "") + ;out.append('r') + ;out = string_add(out, common) + /; if (sz == 1) + ;out.append('b') + ;; else if (sz == 2) + ;out.append('w') + ;; else if (sz == 4) + ;out.append('d') + ;/ + ;/ - /; if (out.is_ref()) - ;out.data_type.ptr_chain = strip_int(out.data_type.ptr_chain) - ;out.data_type.ptr_chain{len (out.data_type.ptr_chain) - 1} == PTYPE.REFERENCE - ;/ + ;return out +;/ - ;log_debug(string_add("Index returning: ", out.sprint())) - ;return out.deref(data) - ;/ +/; get_reg (int r, sz) [{}uint8] + ;return reg_by_name_size(reg_by_num(r), sz) +;/ - /; length_of (Variable a, ~CompData data) - ;a = a.strip_refs() - ;a.data_type.name = "uint" - ;a.data_type.s = 8 - ;a.data_type.ptr_chain = {PTYPE.REFERENCE} - ;self.set(a, data) +/; mov_by_size(int sz)[{}uint8] + /; if (sz == 1) + ;return "byte " + ;; else if (sz == 2) + ;return "word " + ;; else if (sz == 4) + ;return "dword " + ;; else if (sz == 8) + ;return "qword " ;/ + ;return "" +;/ - # Uses rax, does not resolve any ending state after function returns - /; call ({}uint8 name, ~CompData data) - /; if (self.is_ref()) - ;data`.csec = string_join( { - data`.csec, - "\tmov rax, ", self.norm_loc(8), "\n" - }, "") - ;; else - ;data`.csec = string_join( { - data`.csec, - "\tlea rax, ", self.norm_loc(8), "\n" - }, "") - ;/ - - ;data`.csec = string_join( { - data`.csec, - "\tcall ", self.data_type.mod_name, ".", name, "\n" - }, "") +/; loc_from_str ({}uint8 str, offset, int sz) [{}uint8] + ;{}uint8 pre = "" + /; if (sz > 0) + ;pre = mov_by_size(sz) ;/ + ;return string_join( {pre, "[", str, offset, "]" }, "") ;/ -;struct Scope { - int num, c, - ~Scope parent, - {}uint8 name, - {}Variable vars, - bool r -} - -/; method Scope - /; sprint [{}uint8] - ;{}uint8 out = string_join( { - "SCOPE PRINT [", self.name, "] num:", int_to_string(self.num), - " C:", int_to_string(self.c), - " vars:", int_to_string(len (self.vars)), " { " - }, "") - /; loop (int i = 0; i < len (self.vars)) [i++] - ;out = string_add(out, self.vars{i}.sprint()) - ;out.append(' ') - ;/ - ;return string_add(out, "}") +/; strip_int({}int p) [{}int] + ;{}int out = {} + /; loop (int i = 0; i < len p - 1) [i++] + ;out.append(p{i}) ;/ + ;return out +;/ - /; is_cf [bool] - /;if (len(self.name) < 1) - ;return false - ;/ - ;return self.name{0} == '#' +/; to_jmp({}uint8 cmp) [{}uint8] + /; if (string_equate(cmp, "==")) + ;return "\tje " + ;; else if (string_equate(cmp, "!==")) + ;return "\tjne " + ;; else if (string_equate(cmp, "!<") || string_equate(cmp, ">==")) + ;return "\tjge " + ;; else if (string_equate(cmp, "!>") || string_equate(cmp, "<==")) + ;return "\tjle " + ;; else if (string_equate(cmp, ">")) + ;return "\tjg " + ;; else if (string_equate(cmp, "<")) + ;return "\tjl " ;/ + ;return "\tjnz " +;/ - /; cf_type ({}uint8 cf) [bool] - ;{}{}uint8 split = string_split(self.name, '_') - /; if (len split !> 1) - ;return false - ;/ - ;return string_equate(split{0}, string_add("#", cf)) +/; not_jmp({}uint8 cmp) [{}uint8] + /; if (string_equate(cmp, "==")) + ;return "\tjne " + ;; else if (string_equate(cmp, "!==")) + ;return "\tje " + ;; else if (string_equate(cmp, "!<") || string_equate(cmp, ">==")) + ;return "\tjl " + ;; else if (string_equate(cmp, "!>") || string_equate(cmp, "<==")) + ;return "\tjg " + ;; else if (string_equate(cmp, ">")) + ;return "\tjle " + ;; else if (string_equate(cmp, "<")) + ;return "\tjge " ;/ + ;return "\tjz " +;/ - /; full_label [{}uint8] - ;{}uint8 out = "" - /; if (self.is_cf()) - ;out = self.parent`.full_label() - ;/ - ;out = string_add(out, self.name) - ;return out +# Methods on variables assume that the rax, rdx, rsi, and rdi registers are fair game. +# ONLY USES RDI ON SOME ASSIGNMENTS. SAFE FOR BOOLEAN STORAGE +/; method Variable + + /; sprint [{}uint8] + ;return string_join( { + "{ ", self.name, ", ", self.data_type.sprint(), ", ", int_to_string(self.location), ", ", int_to_string(self.loc_type), " }" + },"") ;/ - /; get_size [int] - ;int out = 0 - /; loop (int i = 0; i < len (self.vars)) [i++] - ;out = out + self.vars{i}.norm_size() + /; norm_loc (int sz) [{}uint8] + /; if (self.loc_type == LOCATION.LABEL) + ;return loc_from_str(string_add("rel ", self.name), string_add(" + ", int_to_string(self.location)), sz) + ;; else if (self.loc_type == LOCATION.REGISTER) + /; if (self.is_ref()) + ;return loc_from_str(get_reg(self.location, 8), "", sz) + ;/ + ;return get_reg(self.location, sz) + ;; else if (self.loc_type == LOCATION.STACK) + ;return string_join( { "[ rbp - ", int_to_string(self.location), " ]" }, "") + ;; else if (self.loc_type == LOCATION.LITERAL) + ;return int_to_string(self.location) ;/ - ;return out ;/ - /; next_register [int] - ;int out = 8 - /; if (self.is_cf()) - ;out = self.parent`.next_register() - ;/ - - /; loop (int i = 0; i < len (self.vars) && out < 16) [i++] - /; if (self.vars{i}.loc_type == LOCATION.REGISTER) - ;out++ - ;/ + /; norm_size [int] + /; if (len (self.data_type.ptr_chain) > 1) + ;return 8 + ;; else if (len (self.data_type.ptr_chain) == 0) + ;return self.data_type.s ;/ - /; if (out > 15) - ;out = -1 + /; if (self.data_type.ptr_chain{0} == PTYPE.REFERENCE) + ;return self.data_type.s ;/ - - ;return out + ;return 8 ;/ - /; get_stack [int] - ;int out = 0 + /; el_size [int] + ;int index = len(self.data_type.ptr_chain) - 1 + /; loop (index > 0 && self.data_type.ptr_chain{index} == PTYPE.REFERENCE) + ;index-- + ;/ - /; loop (int i = 0; i < len (self.vars)) [i++] - /; if (self.vars{i}.loc_type == LOCATION.STACK) - ;out = out + self.vars{i}.norm_size() + ;bool arr = false + /; loop (index !< 0) + /; if (self.data_type.ptr_chain{index} !== PTYPE.REFERENCE) + /; if (arr) + ;return 8 + ;/ + ;arr = true + ;index-- + ;; else + ;index-- ;/ ;/ - ;return out + ;return self.data_type.s ;/ - /; get_full_stack [int] - ;int out = 0 - /; if (self.is_cf()) - ;out = self.parent`.get_full_stack() + # TODO: Match a type to another type if possible + # this is the type inference engine + /; match_types (Variable to_match, ~CompData data) [Variable] + /; if (to_match.loc_type == LOCATION.LITERAL) + ;return to_match + ;; if (!(to_match.is_prim()) || (len(to_match.data_type.ptr_chain) > 0 && !(to_match.is_ref()))) + ;return to_match ;/ - /; loop (int i = 0; i < len (self.vars)) [i++] - /; if (self.vars{i}.loc_type == LOCATION.STACK) - ;out = out + self.vars{i}.norm_size() + ;Variable out = {"#match", self.data_type, 4, LOCATION.REGISTER} + ;{}uint8 mov = "mov" + + /; if (self.data_type.name{0} == 'i' && out.norm_size() > to_match.norm_size()) + ;mov = string_add(mov, "sx") + /; if (out.norm_size() == 8 && to_match.norm_size() == 4) + ;mov.append('d') ;/ + ;; else if (self.data_type.name{0} == 'u' && out.norm_size() > to_match.norm_size() && out.norm_size() !== 8) + ;mov = string_add(mov, "zx") + ;; else + ;return to_match ;/ + ;data`.csec = string_join( { + data`.csec, + "\t", mov, " ", out.norm_loc(out.norm_size()), ", ", to_match.norm_loc(to_match.norm_size()), "\n" + }, "") + ;return out ;/ - - /; next_loc (Type t) [int] - /; if (is_primitive(t.name) !< 0 || len (t.ptr_chain) > 0) - ;log_debug("Next reg") - ;return self.next_register() - ;/ - ;return -1 - ;/ - - /; begin_scope (~CompData out) - /; if (!(self.r)) - ;{}uint8 intro = "\tpush rbp\n\tlea rbp, [rsp + 8]\n\tpush r8\n\tpush r9\n\tpush r10\n\tpush r11\n\tpush r12\n\tpush r13\n\tpush r14\n\tpush r15\n" - ;out`.csec = string_add(out`.csec, intro) - ;/ - ;/ - /; end_scope (~CompData out) - /; if (!(self.r)) - ;{}uint8 outro = "\tlea rsp, [rbp - 72]\n\tpop r15\n\tpop r14\n\tpop r13\n\tpop r12\n\tpop r11\n\tpop r10\n\tpop r9\n\tpop r8\n\tpop rbp\n" - ;{}uint8 outro = "\tlea rsp, [rbp - 72]\n\tpop r15\n\tpop r14\n\tpop r13\n\tpop r12\n\tpop r11\n\tpop r10\n\tpop r9\n\tpop r8\n\tpop rbp\n" - - ;{}uint8 outro = "\tlea rsp, [rbp - 72]\n\tpop r15\n\tpop r14\n\tpop r13\n\tpop r12\n\tpop r11\n\tpop r10\n\tpop r9\n\tpop r8\n\tpop rbp\n" - - ;out`.csec = string_add(out`.csec, outro) - ;/ - ;/ - - /; scope_cleanup (~CompData out) - ;uint sz_to_clean = 0 - - /; loop (int i = 0; i < len (self.vars)) - /; if (self.vars{i}.loc_type == LOCATION.STACK) - ;sz_to_clean = sz_to_clean + self.vars{i}.s + /; norm_op ({}uint8 op, int sz, Variable v, ~CompData data) + /; if (self.loc_type == LOCATION.LITERAL) + ;v.norm_op(op, sz, self, data) + ;; else + ;v = self.match_types(v, data) + /; if (self.loc_type == LOCATION.REGISTER || v.loc_type == LOCATION.REGISTER) + ;data`.csec = string_join( { + data`.csec, + "\t", op, " ", self.norm_loc(sz), ", ", v.norm_loc(sz), "\n" + }, "") + ;; else + ;data`.csec = string_join( { + data`.csec, + "\tmov ", get_reg(0, sz), ", ", v.norm_loc(sz), "\n", + "\t", op, " ", self.norm_loc(sz), ", ", get_reg(0, sz), "\n" + }, "") ;/ ;/ - - /; if (sz_to_clean > 0) - ;out`.csec = string_add(out`.csec, string_add("\tadd rsp, ", int_to_string(sz_to_clean))) - ;/ ;/ - /; scope_start_label [{}uint8] - ;return string_add(self.full_label(), "_start") + /; is_ref [bool] + ;int s = len (self.data_type.ptr_chain) + /; if (s > 0) + ;return self.data_type.ptr_chain{s - 1} == PTYPE.REFERENCE + ;/ + ;return false ;/ - /; scope_rep_label [{}uint8] - ;return string_add(self.full_label(), "_rep") + /; is_prim [bool] + ;return len(self.data_type.ptr_chain) > 1 || is_primitive(self.data_type.name) !< 0 ;/ - /; scope_end_label [{}uint8] - ;return string_add(self.full_label(), "_end") + /; strip_one (~CompData data) + ;data`.csec = string_join( { + data`.csec, + "\tmov rsi, [rsi]\n" + }, "") + ;self.data_type.ptr_chain = strip_int(self.data_type.ptr_chain) ;/ - /; new_sub_cf ({}uint8 cf) [Scope] - ;cf = string_add("#", cf) - ;cf.append('_') - ;cf = string_add(cf, int_to_string(self.num)) - ;self.num++ + /; strip_refs (~CompData data) [Variable] + ;Variable out = {"#ref", self.data_type, 4, LOCATION.REGISTER} - ;return {0, 0, ~self, cf, {}, self.r} - ;/ + /; if (self.loc_type == LOCATION.REGISTER) + ;data`.csec = string_join( { + data`.csec, + "\tmov rsi, ", get_reg(self.location, 8), "\n" + }, "") + ;; else + ;data`.csec = string_join( { + data`.csec, + "\tlea rsi, ", self.norm_loc(8), "\n" + }, "") + ;out.data_type.ptr_chain.append(PTYPE.REFERENCE) + ;/ - /; get_continue (uint i) [{}uint8] - ;~Scope top = ~self - /; loop (i > 0 || top`.cf_type("")) - ;top = top`.parent - /; if (!(top`.cf_type(""))) - ;i = i - 1 + ;int pc = len (out.data_type.ptr_chain) + /; loop (pc > 1) [pc = len (out.data_type.ptr_chain)] + /; if (out.data_type.ptr_chain{pc - 1} == PTYPE.REFERENCE && out.data_type.ptr_chain{pc - 2} !== PTYPE.ARRAY) + ;out.strip_one(data) + ;; else + ;break ;/ ;/ + ;return out + ;/ + + # functions that do work on this variable + /; add (Variable v, ~CompData data) + /; if (self.loc_type == LOCATION.LITERAL && v.loc_type == LOCATION.LITERAL) + ;self.location = self.location + v.location + ;; else + ;self.norm_op("add", self.norm_size(), v, data) + ;/ ;/ - /; get_break (uint i) [{}uint8] - ;~Scope top = ~self - /; loop (i > 0 || top`.cf_type("")) - ;top = top`.parent - /; if (!(top`.cf_type(""))) - ;i = i - 1 - ;/ + /; sub (Variable v, ~CompData data) + /; if (self.loc_type == LOCATION.LITERAL && v.loc_type == LOCATION.LITERAL) + ;self.location = self.location - v.location + ;; else + ;self.norm_op("sub", self.norm_size(), v, data) ;/ ;/ - /; new_var (Type t, {}uint8 name, ~CompData out) - ;Variable new = {name, t, 0, 0} - /; if (self.next_loc(t) !< 0) - ;new.loc_type = LOCATION.REGISTER - ;new.location = self.next_loc(t) + /; or (Variable v, ~CompData data) + /; if (self.loc_type == LOCATION.LITERAL && v.loc_type == LOCATION.LITERAL) + ;self.location = self.location | v.location ;; else - ;new.loc_type = LOCATION.STACK - ;new.location = self.get_full_stack() + new.norm_size() - ;out`.csec = string_join( { - out`.csec, - "\tsub rsp, ", int_to_string(new.norm_size()), "\n" - }, "") + ;self.norm_op("or", self.norm_size(), v, data) ;/ - ;log_debug(string_add("Created new variable ", new.sprint())) - ;self.vars.append(new) ;/ - /; find_var ({}{}uint8 artifact, ~Module current) [Variable] + /; and (Variable v, ~CompData data) + /; if (self.loc_type == LOCATION.LITERAL && v.loc_type == LOCATION.LITERAL) + ;self.location = self.location & v.location + ;; else + ;self.norm_op("and", self.norm_size(), v, data) + ;/ + ;/ - ;log_debug(string_join(artifact, ".")) - ;log_debug(string_add("Trying to find scope var in ", self.sprint())) - /; loop (int i = 0; i < len (self.vars)) [i++] - /; if (string_equate(self.vars{i}.name, artifact{0})) - ;return self.vars{i} - ;/ + /; xor (Variable v, ~CompData data) + /; if (self.loc_type == LOCATION.LITERAL && v.loc_type == LOCATION.LITERAL) + ;self.location = self.location ^ v.location + ;; else + ;self.norm_op("xor", self.norm_size(), v, data) ;/ + ;/ - /; if (!(self.is_cf())) - ;return current`.find_def(artifact) + /; not (Variable v, ~CompData data) + /; if (self.loc_type == LOCATION.LITERAL && v.loc_type == LOCATION.LITERAL) + ;self.location = !v.location + ;; else if (string_equate(v.data_type.name, "bool") && len (v.data_type.ptr_chain) == 0) + + ;self.xor(literal_variable("true", "", data), data) + ;; else + ;v = self.match_types(v, data) + ;self.set(v, data) + ;data`.csec = string_join( { + data`.csec, + "\tnot ", self.norm_loc(self.norm_size()), "\n" + }, "") ;/ - ;return self.parent`.find_var(artifact, current) ;/ - /; find_reg_variable (int reg) [~Variable] - /; loop (int i = 0; i < len (self.vars)) [i++] - /; if (self.vars{i}.loc_type == LOCATION.REGISTER && self.vars{i}.location == reg) - ;return ~(self.vars{i}) + /; cmp (Variable v, ~CompData data) + /; if (self.loc_type == LOCATION.LITERAL && v.loc_type == LOCATION.LITERAL) + /; if (self.location == v.location) + ;self.location = 1 + ;; else + ;self.location = 0 ;/ + ;; else if (v.is_prim() && self.is_prim()) + ;self.norm_op("cmp", self.norm_size(), v, data) ;/ + ;/ - /; if (!(self.is_cf())) - ;log_err(string_add("Can't move variable to stack as it does not exist in the current context ", int_to_string(reg))) + /; negative (Variable v, ~CompData data) + ;int sz = self.norm_size() + /; if (v.loc_type == LOCATION.LITERAL) + ;data`.csec = string_join( { + data`.csec, + "\tmov ", mov_by_size(sz), self.norm_loc(sz), ", ", int_to_string(v.location), "\n" + }, "") + ;; else + ;v = self.match_types(v, data) + ;data`.csec = string_join( { + data`.csec, + "\tmov ", get_reg(0, sz), ", ", v.norm_loc(sz), "\n", + "\tnot ", get_reg(0, sz), "\n", + "\tmov ", self.norm_loc(sz), ", ", get_reg(0, sz), "\n" + }, "") ;/ - ;return self.parent`.find_reg_variable(reg) ;/ - /; move_to_stack (int reg, ~CompData out) [Variable] - ;int last_var = self.next_register() - /; if (last_var < 0) - ;last_var = 16 + /; inc (~CompData data) + /; if (self.loc_type == LOCATION.LITERAL) + ;self.location++ + ;; else + ;data`.csec = string_join( { + data`.csec, + "\tinc ", self.norm_loc(self.norm_size()), "\n" + }, "") ;/ + ;/ - /; if (reg < 8 || reg > last_var - 1) - ;log_err(string_add("Can't move a register to stack as it is not in scope. ", int_to_string(reg))) + /; dec (~CompData data) + /; if (self.loc_type == LOCATION.LITERAL) + ;self.location-- + ;; else + ;data`.csec = string_join( { + data`.csec, + "\tdec ", self.norm_loc(self.norm_size()), "\n" + }, "") ;/ + ;/ - ;log_debug(string_join( { - "Attempting to move variable at register ", - int_to_string(reg), " to stack. last_var = ", int_to_string(last_var) - }, "")) + /; ax_compute ({}uint8 op, int sz, Variable v, ~CompData data, int keep) + /; if (self.loc_type == LOCATION.LITERAL) + ;v.ax_compute(op, sz, self, data) + ;; else + ;v = self.match_types(v, data) - ;~Variable rv = self.find_reg_variable(reg) - ;Variable copy = {rv`.name, rv`.data_type, 0, 0} - ;copy.loc_type = LOCATION.STACK - ;copy.location = self.get_full_stack() + copy.norm_size() - ;out`.csec = string_join( { - out`.csec, - "\tsub rsp, ", int_to_string(copy.norm_size()), "\n" - }, "") - ;copy.set(rv`, out) - ;rv` = copy + /; if (self.data_type.name{0} == 'i') + ;op = string_add("i", op) + ;/ - /; if (reg < last_var) - ;rv = self.find_reg_variable(last_var - 1) - ;log_debug(string_join({ - "Moving variable from ", int_to_string(last_var - 1), " to ", int_to_string(reg), ". ", - "Variable name: ", rv`.name - }, "")) - ;rv`.move_register(reg, out) + /; if (self.loc_type !== LOCATION.REGISTER && v.loc_type !== LOCATION.REGISTER) + ;data`.csec = string_join( { + data`.csec, + "\t", op, " ", self.norm_loc(sz), v.norm_loc(sz), "\n" + }, "") + ;; else + ;data`.csec = string_join( { + data`.csec, + "\tmov ", get_reg(0, sz), ", ", v.norm_loc(sz), "\n", + "\t", op, " ", self.norm_loc(sz), "\n", + "\tmov ", self.norm_loc(sz), ", ", get_reg(keep, sz), "\n" + }, "") + ;/ ;/ - - ;return copy ;/ - /; next_const [{}uint8] - ;{}uint8 out = string_add(self.full_label(), string_add("#const_", int_to_string(self.c))) - ;self.c++ - ;return out + /; div (Variable v, ~CompData data) + /; if (self.loc_type == LOCATION.LITERAL && v.loc_type == LOCATION.LITERAL) + ;self.location = self.location / v.location + ;; else + ;self.ax_compute("div", self.norm_size(), v, data, 0) + ;/ ;/ -;/ - -;struct Function { - {}uint8 name, - {}Type - inputs, - outputs -} -;struct Module { - # Parent module - ~Module parent, - # Export functions or not - bool exp, - # Name of module - {}uint8 name, - # Types defined in this module - {}Type types, - # Variables defined in this module - {}Variable defs, - # Functions defined in this module - {}Function functions, - # Sub modules - {}Module sub -} + /; mod (Variable v, ~CompData data) + /; if (self.loc_type == LOCATION.LITERAL && v.loc_type == LOCATION.LITERAL) + ;self.location = self.location % v.location + ;; else + ;self.ax_compute("div", self.norm_size(), v, data, 3) + ;/ + ;/ -/; method Module - # Internal recursive function - /; _find_type ({}{}uint8 artifact, int r) [~Type] - /; if (len artifact !> r) - ;return ~NO_TYPE + /; mul (Variable v, ~CompData data) + /; if (self.loc_type == LOCATION.LITERAL && v.loc_type == LOCATION.LITERAL) + ;self.location = self.location * v.location + ;; else + ;self.ax_compute("mul", self.norm_size(), v, data, 0) ;/ + ;/ - /; if (len artifact - 1 > r) - /; loop (int i = 0; i < len (self.sub)) [i++] - /; if (string_equate(artifact{r}, self.sub{i}.name)) - ;return self.sub{i}._find_type(artifact, r + 1) - ;/ + # Todo: Make sure this works well. + /; set (Variable v, ~CompData data) + ;int sz = self.norm_size() + ;v = self.match_types(v, data) + /; if (self.loc_type == LOCATION.LITERAL && v.loc_type == LOCATION.LITERAL) + ;self.location = v.location + ;; else if (self.is_prim()) + /;if (self.is_ref() && v.is_ref()) + ;data`.csec = string_join( { + data`.csec, + "\tmov ", get_reg(4, sz), ", ", v.norm_loc(sz), "\n", + "\tmov ", self.norm_loc(sz), ", ", get_reg(4, sz), "\n" + }, "") + ;; else + ;data`.csec = string_join( { + data`.csec, + "\tmov ", self.norm_loc(sz), ", ",v.norm_loc(sz), "\n" + }, "") + ;/ + ;; else + /; if (self.is_ref()) + ;data`.csec = string_join( { + data`.csec, + "\tmov rdi, ", self.norm_loc(8), "\n" + }, "") + ;; else + ;data`.csec = string_join( { + data`.csec, + "\tlea rdi, ", self.norm_loc(8), "\n" + }, "") ;/ - ;; else if (len artifact - 1 == r) - /; loop (int i = 0; i < len (self.types)) [i++] - /; if (string_equate(self.types{i}.name, artifact{r})) - ;return ~(self.types{i}) - ;/ + + /; if (v.is_ref()) + ;data`.csec = string_join( { + data`.csec, + "\tmov rsi, ", v.norm_loc(8), "\n" + }, "") + ;; else + ;data`.csec = string_join( { + data`.csec, + "\tlea rsi, ", v.norm_loc(8), "\n" + }, "") ;/ - ;/ - - /; if (string_equate(self.name, "")) - ;Type nt = {0, artifact{len artifact - 1}, "", {}, {}} - ;return ~nt - ;/ - ;~Module m = self.parent - /; loop (r > 0) [r = r - 1] - ;m = m.parent + ;data`.csec = string_join( { + data`.csec, + "\tmov rcx, ", int_to_string(sz), "\n", + "\trep movsb\n" + }, "") ;/ - ;return m`._find_type(artifact, 0) ;/ - # Consumer facing function - /; find_type ({}{}uint8 artifact) [~Type] - ;int p = is_primitive(artifact{0}) - /; if (p !< 0) - ;Type out = {p, artifact{0}, {}, {}, {}} - ;return ~out - ;/ + # Only to be called from a boolean variable + /; bool_from (Variable v, ~CompData data, {}uint8 landing_pad) + ;int sz = v.norm_size() + ;data`.csec = string_join( { + data`.csec, + "\tmov ", get_reg(4, sz), ", ", v.norm_loc(sz), "\n", + "\ttest ", get_reg(4, sz), ", ", get_reg(4, sz), "\n", + "\tmov ", self.norm_loc(1), ", 1\n", + "\tjnz ", skip_pad, "\n", + "\tmov ", self.norm_loc(1), ", 0\n", + landing_pad, ":\n" + }, "") + ;/ - ;return self._find_type(artifact, 0) + /; move_register (int new_reg, ~CompData data) + ;int sz = self.norm_size() + /; if (self.is_ref()) + ;sz = 8 + ;/ + ;data`.csec = string_join( { + data`.csec, + "\tmov ", get_reg(new_reg, sz), ", ", get_reg(self.location, sz), "\n" + }, "") + ;self.location = new_reg ;/ - /; _find_def ({}{}uint8 artifact, int r) [Variable] - /; if (len artifact !> r) - ;return {"", NO_TYPE, 0, 0} + /; ref (Variable to_ref, ~CompData data) + ;int l = len (to_ref.data_type.ptr_chain) + /; if (to_ref.is_ref()) + ;to_ref.data_type.ptr_chain{l - 1} = PTYPE.POINTER + ;self.set(to_ref, data) + ;; else if (to_ref.loc_type !== LOCATION.REGISTER && to_ref.loc_type !== LOCATION.LITERAL) + ;data`.csec = string_join( { + data`.csec, + "\tlea rsi, ", to_ref.norm_loc(0), "\n", + "\tmov ", self.norm_loc(8), ", rsi\n" + }, "") + ;; else + ;log_err(string_add("Failure to create reference from register or literal value ", to_ref.sprint())) ;/ + ;/ - /; if (len artifact - 1 > r) - /; loop (int i = 0; i < len (self.sub)) [i++] - /; if (string_equate(artifact{r}, self.sub{i}.name)) - ;log_debug(string_add("Artifact: ", artifact{r})) - ;return self.sub{i}._find_def(artifact, r + 1) - ;/ - ;/ - ;; else if (len artifact - 1 == r) - ;{}uint8 true_name = self.full_path() - /; if (len true_name > 0) - ;true_name.append('.') - ;/ - ;true_name = string_add(true_name, artifact{r}) - /; loop (int i = 0; i < len (self.defs)) [i++] - /; if (string_equate(self.defs{i}.name, true_name)) - ;return self.defs{i} - ;/ - ;/ + /; deref (~CompData data) [Variable] + ;Variable out = self.strip_refs(data) + ;int opc = len (out.data_type.ptr_chain) + /; if (opc == 0) + ;log_err("Can not deref a variable that is not a pointer (ERR: SNPTRC)") ;/ + ;out.data_type.ptr_chain{opc - 1} = PTYPE.REFERENCE + ;return out + ;/ - /; if (string_equate(self.name, "")) - ;return {"", NO_TYPE, 0, 0} + /; member ({}uint8 name, ~CompData data) [Variable] + ;Variable out = self.strip_refs(data) + ;int accum = 0 + ;int i = 0 + /; loop(i < len (out.data_type.members)) [i++] + /; if (string_equate(out.data_type.members{i}.name, name)) + ;break + ;/ + ;accum = accum + out.data_type.members{i}.data_type.s ;/ - ;~Module m = self.parent - /; loop (r > 0) [r = r - 1] - ;m = m.parent - ;/ - ;return m`._find_def(artifact, 0) - ;/ + ;out.data_type = out.data_type.members{i}.data_type + ;out.data_type.ptr_chain.append(PTYPE.REFERENCE) + + ;data`.csec = string_join( { + data`.csec, + "\tadd rsi, ", int_to_string(accum), "\n" + }, "") - /; find_def ({}{}uint8 artifact) [Variable] - ;return self._find_def(artifact, 0) + ;return out ;/ - /; _find_function ({}{}uint8 artifact, int r) [Variable] - /; if (len artifact !> r) - ;retirn {{}, "", 0, 0, 0} + /; index (Variable i, ~CompData data) [Variable] + ;int sz = self.el_size() + ;log_debug(string_add("Index starting: ", self.sprint())) + ;Variable out = self.strip_refs(data) + + ;int opc = len (out.data_type.ptr_chain) + + /; if (opc == 0 || (out.is_ref() && opc == 1)) + ;log_err(string_add("Unable to index a type if it is not a pointer or array ", out.sprint())) ;/ - /; if (len artifact - 1 > r) - /; loop (int i = 0; i < len (self.sub)) [i++] - /; if (string_equate(artifact{r}, self.sub{i}.name)) - ;return self._find_type(artifact, r + 1) - ;/ - ;/ + ;Variable ind = {"#index", {8, "void", "", {PTYPE.POINTER}, {}}, 3, LOCATION.REGISTER} + ;ind.set(i, data) + ;ind.mul({"#mul", {8, "uint", "", {}, {}}, sz, LOCATION.LITERAL}, data) + + /; if (out.is_ref()) + ;data`.csec = string_join( { + data`.csec, + "\tadd rsi, 8\n" + }, "") ;/ - /; loop (int i = 0; i < len (self.funcs)) [i++] - /; if (string_equate(self.funcs{i}.name, artifact{r})) - ;return self.funcs{i} - ;/ + ;data`.csec = string_join( { + data`.csec, + "\tlea rsi, [rsi + rdx]\n" + }, "") + + /; if (out.is_ref()) + ;out.data_type.ptr_chain = strip_int(out.data_type.ptr_chain) + ;out.data_type.ptr_chain{len (out.data_type.ptr_chain) - 1} = PTYPE.REFERENCE ;/ - - ;return {{}, "", 0, 0, 0} - ;/ - /; find_function ({}{}uint8 artifact) [Variable] - ;return _find_function(artifact, 0) + ;log_debug(string_add("Index returning: ", out.sprint())) + ;return out.deref(data) ;/ - /; _find_mod ({}{}uint8 artifact, int r) [~Module] - /; if (len artifact !> r) - ;return ~self - ;/ + /; length_of (Variable a, ~CompData data) + ;a = a.strip_refs() + ;a.data_type.name = "uint" + ;a.data_type.s = 8 + ;a.data_type.ptr_chain = {PTYPE.REFERENCE} + ;self.set(a, data) + ;/ - /; if (len artifact - 1 > r) - /; loop (int i = 0; i < len (self.sub)) [i++] - /; if (string_equate(artifact{r}, self.sub{i}.name)) - ;return self.sub{i}._find_mod(artifact, r + 1) - ;/ - ;/ - ;; else if (len artifact - 1 == r) - ;{}uint8 v1 = string_add("_#", artifact{r}), v2 = string_add("__#", artifact{r}) - /; loop (int i = 0; i < len (self.defs)) [i++] - /; if (string_equate(self.sub{i}.name, artifact{r}) ||string_equate(self.sub{i}.name, v1) || string_equate(self.sub{i}.name, v2)) - ;return ~(self.sub{i}) - ;/ - ;/ + # Uses rax, does not resolve any ending state after function returns + /; call ({}uint8 name, ~CompData data) + /; if (self.is_ref()) + ;data`.csec = string_join( { + data`.csec, + "\tmov rax, ", self.norm_loc(8), "\n" + }, "") + ;; else + ;data`.csec = string_join( { + data`.csec, + "\tlea rax, ", self.norm_loc(8), "\n" + }, "") ;/ - /; if (string_equate(self.name, "")) - ;return ~self - ;/ - - ;~Module m = self.parent - /; loop (r > 0) [r = r - 1] - ;m = m.parent - ;/ - ;return m`._find_mod(artifact, 0) + ;data`.csec = string_join( { + data`.csec, + "\tcall ", self.data_type.mod_name, ".", name, "\n" + }, "") ;/ +;/ - /; find_mod({}{}uint8 artifact) [~Module] - ;return self._find_mod(artifact, 0) +;struct Scope { + int num, c, + ~Scope parent, + {}uint8 name, + {}Variable vars, + bool r +} + +/; method Scope + /; sprint [{}uint8] + ;{}uint8 out = string_join( { + "SCOPE PRINT [", self.name, "] num:", int_to_string(self.num), + " C:", int_to_string(self.c), + " vars:", int_to_string(len (self.vars)), " { " + }, "") + /; loop (int i = 0; i < len (self.vars)) [i++] + ;out = string_add(out, self.vars{i}.sprint()) + ;out.append(' ') + ;/ + ;return string_add(out, "}") ;/ - /; find_sub ({}uint8 s_mod) [~Module] - ;{}uint8 v1 = string_add("_#", s_mod) - ;{}uint8 v2 = string_add("__#", s_mod) - /; loop (int i = 0; i < len (self.sub)) [i++] - /; if (string_equate(self.sub{i}.name, s_mod) || string_equate(self.sub{i}.name, v1) || string_equate(self.sub{i}.name, v2)) - ;return ~(self.sub{i}) - ;/ + /; is_cf [bool] + /;if (len(self.name) < 1) + ;return false ;/ - - ;return ~self + ;return self.name{0} == '#' ;/ - /; full_path [{}uint8] - /; if (string_equate(self.name, "")) - ;return "" + /; cf_type ({}uint8 cf) [bool] + ;{}{}uint8 split = string_split(self.name, '_') + /; if (len split !> 1) + ;return false ;/ - ;{}uint8 out = self.parent`.full_path() - /; if (len out > 0) - ;out = string_add(out, ".") + ;return string_equate(split{0}, string_add("#", cf)) + ;/ + + /; full_label [{}uint8] + ;{}uint8 out = "" + /; if (self.is_cf()) + ;out = self.parent`.full_label() ;/ ;out = string_add(out, self.name) ;return out ;/ -;/ - -## -## Compiler funcs -## - -/; get_artifact (~{}Token tok, ~int cur) [{}{}uint8] - ;{}{}uint8 out = {} - ;out.append(tok`{cur`}.data) - ;cur`++ - - /; loop (cur` < len tok` && tok`{cur`}.cmp(".")) [cur`++] - /; if (tok`{cur` + 1}.type_is(TOKEN.DEFWORD)) - ;out.append(tok`{cur` + 1}.data) - ;cur`++ + /; get_size [int] + ;int out = 0 + /; loop (int i = 0; i < len (self.vars)) [i++] + ;out = out + self.vars{i}.norm_size() ;/ + ;return out ;/ - ;return out -;/ - -/; is_call(~{}Token tok, int i) [bool] - ;get_artifact(tok, ~i) - ;return tok`{i}.cmp("(") -;/ -/; get_type (~{}Token tok, ~int cur, ~Module current) [Type] - ;{}int ptr_chain = {} + /; next_register [int] + ;int out = 8 + /; if (self.is_cf()) + ;out = self.parent`.next_register() + ;/ - /; loop (cur` < len tok`) [cur`++] - /; if (tok`{cur`}.cmp("{")) - ;ptr_chain.append(PTYPE.ARRAY) - ;cur`++ - ;; else if (tok`{cur`}.cmp("~")) - ;ptr_chain.append(PTYPE.POINTER) - ;; else - ;break + /; loop (int i = 0; i < len (self.vars) && out < 16) [i++] + /; if (self.vars{i}.loc_type == LOCATION.REGISTER) + ;out++ + ;/ ;/ - ;/ - - ;~Type pout = current`.find_type(get_artifact(tok, cur)) - ;Type out = pout` - /; if (string_equate(out.name, "")) - ;return out - ;/ - ;{}Type generics = {} - /; if (tok`{cur`}.cmp("(")) - ;int max = find_closing(tok, cur) - ;cur`++ - /; loop (cur` < max) [cur`++] - ;generics.append(get_type(tok, cur, current)) + /; if (out > 15) + ;out = -1 ;/ + + ;return out ;/ - # TODO: References - - ;out.ptr_chain = ptr_chain - ;return out -;/ + /; get_stack [int] + ;int out = 0 -/; is_definition (~{}Token tok, ~int cur, ~Module current) [bool] - ;int i = cur` - ;Type t = get_type(tok, ~i, current) - ;return tok`{i}.type_is(TOKEN.DEFWORD) && !string_equate(t.name, "") -;/ + /; loop (int i = 0; i < len (self.vars)) [i++] + /; if (self.vars{i}.loc_type == LOCATION.STACK) + ;out = out + self.vars{i}.norm_size() + ;/ + ;/ -/; compile_file_def (~{}Token tok, ~int cur, ~Module current, ~CompData out) - ;Type t = get_type(tok, cur, current) - ;{}uint8 base = current`.full_path() - - /; if (len base > 0) - ;base.append('.') + ;return out ;/ - /; loop (!(tok`{cur`}.cmp("\n"))) - /; loop (tok`{cur`}.cmp(",")) - ;cur`++ + /; get_full_stack [int] + ;int out = 0 + /; if (self.is_cf()) + ;out = self.parent`.get_full_stack() ;/ - ;{}uint8 l = string_add(base, tok`{cur`}.data) - ;Variable v = {l, t, 0, LOCATION.LABEL} - ;current`.defs.append(v) - - /; if (current`.exp) - ;out`.hsec = string_add(out`.hsec, "global ") - ;out`.hsec = string_add(out`.hsec, l) - ;out`.hsec.append('\n') + /; loop (int i = 0; i < len (self.vars)) [i++] + /; if (self.vars{i}.loc_type == LOCATION.STACK) + ;out = out + self.vars{i}.norm_size() + ;/ ;/ - ;l.append(':') - ;l.append('\n') - ;out`.dsec = string_add(out`.dsec, l) + ;return out + ;/ - ;cur`++ - /; if (tok`{cur`}.cmp("=")) - ;cur`++ - ;out`.dsec = string_add(out`.dsec, decompose_data(tok, cur, t)) - ;cur`++ - ;; else - ;out`.dsec = string_add(out`.dsec, decompose_empty(t)) + /; next_loc (Type t) [int] + /; if (is_primitive(t.name) !< 0 || len (t.ptr_chain) > 0) + ;log_debug("Next reg") + ;return self.next_register() ;/ + ;return -1 ;/ -;/ -/; next_non_nl (~{}Token tok, int c) [int] - /; if (len tok` !> c) - ;return c + /; begin_scope (~CompData out) + /; if (!(self.r)) + ;{}uint8 intro = "\tpush rbp\n\tlea rbp, [rsp + 8]\n\tpush r8\n\tpush r9\n\tpush r10\n\tpush r11\n\tpush r12\n\tpush r13\n\tpush r14\n\tpush r15\n" + ;out`.csec = string_add(out`.csec, intro) + ;/ ;/ - /; loop (tok`{c}.cmp("\n")) [c++] ;/ - ;return c -;/ + + /; end_scope (~CompData out) + /; if (!(self.r)) + ;{}uint8 outro = "\tlea rsp, [rbp - 72]\n\tpop r15\n\tpop r14\n\tpop r13\n\tpop r12\n\tpop r11\n\tpop r10\n\tpop r9\n\tpop r8\n\tpop rbp\n" + ;{}uint8 outro = "\tlea rsp, [rbp - 72]\n\tpop r15\n\tpop r14\n\tpop r13\n\tpop r12\n\tpop r11\n\tpop r10\n\tpop r9\n\tpop r8\n\tpop rbp\n" -/; parse_param_list (~{}Token tok, ~int cur, ~Module current) [{}Variable] - ;{}Variable out = {} + ;{}uint8 outro = "\tlea rsp, [rbp - 72]\n\tpop r15\n\tpop r14\n\tpop r13\n\tpop r12\n\tpop r11\n\tpop r10\n\tpop r9\n\tpop r8\n\tpop rbp\n" - ;int max = find_closing(tok, cur) - ;Type t = NO_TYPE - /; loop (cur` = next_non_nl(tok, cur` + 1); cur` < max) [cur` = next_non_nl(tok, cur` + 1)] - ;int nnl = next_non_nl(tok, cur` + 1) - /; if (tok`{nnl}.cmp(",") || nnl == max) - ;out.append({tok`{cur`}.data, t, 0, 0}) - /; if (tok`{nnl}.cmp(",")) - ;cur`++ - ;/ - ;; else - ;t = get_type(tok, cur, current) - ;cur` = cur` - 1 + ;out`.csec = string_add(out`.csec, outro) ;/ ;/ - ;return out -;/ -# Generates new type -/; new_type (~{}Token tok, ~int cur, ~Module current) - ;cur`++ - ;Type out = {0, tok`{cur`}.data, "", {}, {}} + /; scope_cleanup (~CompData out) + ;uint sz_to_clean = 0 + + /; loop (int i = 0; i < len (self.vars)) + /; if (self.vars{i}.loc_type == LOCATION.STACK) + ;sz_to_clean = sz_to_clean + self.vars{i}.s + ;/ + ;/ - ;out.mod_name = current`.full_path() - /; if (len (out.mod_name) > 0) - ;out.mod_name.append('.') + /; if (sz_to_clean > 0) + ;out`.csec = string_add(out`.csec, string_add("\tadd rsp, ", int_to_string(sz_to_clean))) + ;/ ;/ - ;out.mod_name = string_add(out.mod_name, "_#") - ;out.mod_name = string_add(out.mod_name, out.name) - ;current`.sub.append({current, current`.exp, string_add("_#", out.name), {}, {}, {}, {}}) - - /; loop (cur` < len tok`) [cur`++] - /; if (tok`{cur`}.cmp("{")) - ;break - ;/ + /; scope_start_label [{}uint8] + ;return string_add(self.full_label(), "_start") ;/ - ;out.members = parse_param_list(tok, cur, current) - /; loop (int i = 0; i < len (out.members)) [i++] - ;log_debug(string_join({"[", out.members{i}.name, ":", out.members{i}.data_type.name, "]"}, "")) + /; scope_rep_label [{}uint8] + ;return string_add(self.full_label(), "_rep") ;/ - - ;log_debug(string_add("Generated type ", string_add(out.name, string_add(":", out.mod_name)))) - ;current`.types.append(out) -;/ -/; decompose_empty (Type t) [{}uint8] - /; if (len (t.ptr_chain) > 0) - ;return "\tdq 0\n" + /; scope_end_label [{}uint8] + ;return string_add(self.full_label(), "_end") ;/ - ;{}uint8 out = "\tdb 0" - /; loop (int i = 1; i < t.s) [i++] - ;out = string_add(out, ", 0") + + /; new_sub_cf ({}uint8 cf) [Scope] + ;cf = string_add("#", cf) + ;cf.append('_') + ;cf = string_add(cf, int_to_string(self.num)) + ;self.num++ + + ;return {0, 0, ~self, cf, {}, self.r} ;/ - ;out.append('\n') - ;return out -;/ -# Used to take an array literal and make it into a label -/; decompose_array (~{}Token tok, ~int cur, Type t) [{}uint8] - ;int max = find_closing(tok, cur) - ;{}uint8 arr = "" - ;int alen = 0 + /; get_continue (uint i) [{}uint8] + ;~Scope top = ~self + /; loop (i > 0 || top`.cf_type("")) + ;top = top`.parent + /; if (!(top`.cf_type(""))) + ;i = i - 1 + ;/ + ;/ + ;/ - /; loop (cur` = next_non_nl(tok, cur` + 1); cur` < max) [cur` = next_non_nl(tok, cur` + 1)] - ;alen++ - /; if (tok`{cur`}.cmp("{")) - /; if (len(t.ptr_chain) > 0) - ;t.ptr_chain = strip_int(t.ptr_chain) - ;arr = string_add(arr, decompose_array(tok, cur, t)) - ;cur` = next_non_nl(tok, cur` + 1) - ;; else - ;decompose_struct(tok, cur, t) - ;cur` = next_non_nl(tok, cur` + 1) + /; get_break (uint i) [{}uint8] + ;~Scope top = ~self + /; loop (i > 0 || top`.cf_type("")) + ;top = top`.parent + /; if (!(top`.cf_type(""))) + ;i = i - 1 ;/ - ;; else - ;arr = string_add(arr, decompose_data(tok, cur, t)) - ;cur` = next_non_nl(tok, cur` + 1) ;/ ;/ - ;cur` = max - ;{}uint out = string_join( { "\tdq ", int_to_string(alen), "\n", arr, "\n" }, "") + /; new_var (Type t, {}uint8 name, ~CompData out) + ;Variable new = {name, t, 0, 0} + /; if (self.next_loc(t) !< 0) + ;new.loc_type = LOCATION.REGISTER + ;new.location = self.next_loc(t) + ;; else + ;new.loc_type = LOCATION.STACK + ;new.location = self.get_full_stack() + new.norm_size() + ;out`.csec = string_join( { + out`.csec, + "\tsub rsp, ", int_to_string(new.norm_size()), "\n" + }, "") + ;/ + ;log_debug(string_add("Created new variable ", new.sprint())) + ;self.vars.append(new) + ;/ - ;return out -;/ + /; find_var ({}{}uint8 artifact, ~Module current) [Variable] + /; loop (int i = 0; i < len (self.vars)) [i++] + /; if (string_equate(self.vars{i}.name, artifact{0})) + ;return self.vars{i} + ;/ + ;/ -# Used to take a struct literal and make it into a label -/; decompose_struct (~{}Token tok, ~int cur, Type t) [{}uint8] - ;int max = find_closing(tok, cur) - ;{}uint8 out = "" - ;int m = 0 - /; loop (cur` = next_non_nl(tok, cur` + 1); cur` < max) [cur` = next_non_nl(tok, cur` + 1)] - /; if (tok`{cur`}.cmp("}")) - ;break - ;; else if (tok`{cur`}.cmp(",")) - ;cur` = next_non_nl(tok, cur` + 1) + /; if (!(self.is_cf())) + ;return current`.find_def(artifact) ;/ - ;out = string_add(out, decompose_data(tok, cur, t.members{m}.data_type)) - ;m++ + ;return self.parent`.find_var(artifact, current) ;/ - /; if (m < len (t.members) - 1) - /; loop (m < len (t.members)) [m++] - ;out = string_add(out, decompose_empty(t.members{m})) + /; find_reg_variable (int reg) [~Variable] + /; loop (int i = 0; i < len (self.vars)) [i++] + /; if (self.vars{i}.loc_type == LOCATION.REGISTER && self.vars{i}.location == reg) + ;return ~(self.vars{i}) + ;/ + ;/ + + /; if (!(self.is_cf())) + ;log_err(string_add("Can't move variable to stack as it does not exist in the current context ", int_to_string(reg))) ;/ + ;return self.parent`.find_reg_variable(reg) ;/ - ;return out -;/ + /; move_to_stack (int reg, ~CompData out) [Variable] + ;int last_var = self.next_register() + /; if (last_var < 0) + ;last_var = 16 + ;/ -/; declare_size(int sz) [{}uint8] - ;{}uint8 out = "\tdb " + /; if (reg < 8 || reg > last_var - 1) + ;log_err(string_add("Can't move a register to stack as it is not in scope. ", int_to_string(reg))) + ;/ - /; if (sz == 2) - ;out{2} = 'w' - ;; if (sz == 4) - ;out{2} = 'd' - ;; if (sz == 8) - ;out{2} = 'q' + ;log_debug(string_join( { + "Attempting to move variable at register ", + int_to_string(reg), " to stack. last_var = ", int_to_string(last_var) + }, "")) + + ;~Variable rv = self.find_reg_variable(reg) + ;Variable copy = {rv`.name, rv`.data_type, 0, 0} + ;copy.loc_type = LOCATION.STACK + ;copy.location = self.get_full_stack() + copy.norm_size() + ;out`.csec = string_join( { + out`.csec, + "\tsub rsp, ", int_to_string(copy.norm_size()), "\n" + }, "") + ;copy.set(rv`, out) + ;rv` = copy + + /; if (reg < last_var) + ;rv = self.find_reg_variable(last_var - 1) + ;log_debug(string_join({ + "Moving variable from ", int_to_string(last_var - 1), " to ", int_to_string(reg), ". ", + "Variable name: ", rv`.name + }, "")) + ;rv`.move_register(reg, out) + ;/ + + ;return copy ;/ - ;return out + /; next_const [{}uint8] + ;{}uint8 out = string_add(self.full_label(), string_add("#const_", int_to_string(self.c))) + ;self.c++ + ;return out + ;/ ;/ -# Used to take data from a literal and make it into a label -/; decompose_data (~{}Token tok, ~int cur, Type t) [{}uint8] - /; if (tok`{cur`}.cmp("{")) - /; if (len (t.ptr_chain) > 0) - ;t.ptr_chain = strip_int(t.ptr_chain) - ;return decompose_array(tok, cur, t) - ;; else - ;return decompose_struct(tok, cur, t) +;struct Function { + {}uint8 name, + {}Type + inputs, + outputs +} + +;struct Module { + # Parent module + ~Module parent, + # Export functions or not + bool exp, + # Name of module + {}uint8 name, + # Types defined in this module + {}Type types, + # Variables defined in this module + {}Variable defs, + # Functions defined in this module + {}Function functions, + # Sub modules + {}Module sub +} + +/; method Module + # Internal recursive function + /; _find_type ({}{}uint8 artifact, int r) [~Type] + /; if (len artifact !> r) + ;return ~NO_TYPE ;/ - ;; if (tok`{cur`}.type_is(TOKEN.LITERAL)) - /; if (string_equate(t.name, "bool")) - ;{}uint data = "0" - /; if (!(tok`{cur`}.cmp("false"))) - ;data = "1" + + /; if (len artifact - 1 > r) + /; loop (int i = 0; i < len (self.sub)) [i++] + /; if (string_equate(artifact{r}, self.sub{i}.name)) + ;return self.sub{i}._find_type(artifact, r + 1) + ;/ + ;/ + ;; else if (len artifact - 1 == r) + /; loop (int i = 0; i < len (self.types)) [i++] + /; if (string_equate(self.types{i}.name, artifact{r})) + ;return ~(self.types{i}) + ;/ ;/ - ;return string_add(string_add(declare_size(t.s), data), "\n") + ;/ + + /; if (string_equate(self.name, "")) + ;Type nt = {0, artifact{len artifact - 1}, "", {}, {}} + ;return ~nt ;/ - /; if (tok`{cur`}.data{0} == '"') - ;return string_join({ - declare_size(8), int_to_string(len unquote_str(tok`{cur`}.data)), "\n", - declare_size(1), tok`{cur`}.data, "\n"}, "") - ;; else if (tok`{cur`}.data{0} == '\'') - ;return string_join({ - declare_size(1), tok`{cur`}.data, "\n"}, "") + ;~Module m = self.parent + /; loop (r > 0) [r = r - 1] + ;m = m.parent ;/ - ;return string_add(string_add(declare_size(t.s), tok`{cur`}.data), "\n") + ;return m`._find_type(artifact, 0) ;/ - ;return decompose_empty(t) -;/ -# Compiles new enum for the file -/; compile_enum (~{}Token tok, ~int cur, ~Module current, ~CompData out) - ;cur`++ - ;Type et = NO_TYPE - ;{}uint8 name = "" - - /; if (tok`{cur`}.cmp("[")) - ;cur`++ - ;et = get_type(tok, cur, current) - ;cur`++ - ;; if (!(tok`{cur`}.cmp("{"))) - ;name = tok`{cur`}.data - ;cur`++ - /; if (tok`{cur`}.cmp("[")) - ;cur`++ - ;et = get_type(tok, cur, current) - ;cur`++ + # Consumer facing function + /; find_type ({}{}uint8 artifact) [~Type] + ;int p = is_primitive(artifact{0}) + /; if (p !< 0) + ;Type out = {p, artifact{0}, {}, {}, {}} + ;return ~out ;/ - ;/ - /; if (string_equate(et.name, "")) - ;et = Primitives{3} + ;return self._find_type(artifact, 0) ;/ - /; loop (!(tok`{cur`}.cmp("{"))) [cur`++] ;/ - ;cur`++ - - ;Module enum_mod = {current, current`.exp, string_add("__#", name), {}, {}, {}, {}} - /; loop (cur` < len tok`) [cur`++] - /; if (tok`{cur`}.cmp("}")) - ;break + /; _find_def ({}{}uint8 artifact, int r) [Variable] + /; if (len artifact !> r) + ;return {"", NO_TYPE, 0, 0} ;/ - /; if (tok`{cur`}.type_is(TOKEN.DEFWORD)) - ;{}uint8 l = string_add(enum_mod.full_path(), ".") - ;l = string_add(l, tok`{cur`}.data) - - /; if (current`.exp) - ;out`.hsec = string_add(out`.hsec, "global ") - ;out`.hsec = string_add(out`.hsec, l) - ;out`.hsec.append('\n') + /; if (len artifact - 1 > r) + /; loop (int i = 0; i < len (self.sub)) [i++] + /; if (string_equate(artifact{r}, self.sub{i}.name)) + ;log_debug(string_add("Artifact: ", artifact{r})) + ;return self.sub{i}._find_def(artifact, r + 1) + ;/ + ;/ + ;; else if (len artifact - 1 == r) + ;{}uint8 true_name = self.full_path() + /; if (len true_name > 0) + ;true_name.append('.') + ;/ + ;true_name = string_add(true_name, artifact{r}) + /; loop (int i = 0; i < len (self.defs)) [i++] + /; if (string_equate(self.defs{i}.name, true_name)) + ;return self.defs{i} + ;/ ;/ - - ;Variable v = {l, et, 0, LOCATION.LABEL} - ;enum_mod.defs.append(v) - - ;l.append(':') - ;l.append('\n') - ;cur` = cur` + 2 - ;l = string_add(l, decompose_data(tok, cur, et)) - ;out`.dsec = string_add(out`.dsec, l) ;/ - ;/ - ;current`.sub.append(enum_mod) -;/ + /; if (string_equate(self.name, "")) + ;return {"", NO_TYPE, 0, 0} + ;/ + + ;~Module m = self.parent + /; loop (r > 0) [r = r - 1] + ;m = m.parent + ;/ + ;return m`._find_def(artifact, 0) + ;/ -# Generates opposite closing bracket -/; closing_for (Token d) [{}uint8] - /; if (d.cmp("(")) - ;return ")" - ;; else if (d.cmp("[")) - ;return "]" - ;; else if (d.cmp("{")) - ;return "}" - ;; else if (d.cmp("/;")) - ;return ";/" + /; find_def ({}{}uint8 artifact) [Variable] + ;return self._find_def(artifact, 0) ;/ - ;log_err(string_add("Error, unrecognized delim: ", d.data)) -;/ -# Finds closing bracket -/; find_closing (~{}Token tok, ~int cur) [int] - ;int bl = 0, p = 0, br = 0, c = 0 - ;{}uint8 cl = closing_for(tok`{cur`}) - /; loop (int i = cur` + 1; i < len tok`) [i++] - /; if (bl == 0 && p == 0 && br == 0 && c == 0) - /; if ((tok`{i}.cmp(";;") || tok`{i}.cmp(";:")) && string_equate(cl, ";/")) - ;return i - ;; else if (tok`{i}.cmp(cl)) - ;return i - ;/ + /; _find_function ({}{}uint8 artifact, int r) [Variable] + /; if (len artifact !> r) + ;retirn {{}, "", 0, 0, 0} ;/ - /; if (tok`{i}.cmp("(")) - ;p++ - ;; else if (tok`{i}.cmp("[")) - ;br++ - ;; else if (tok`{i}.cmp("{")) - ;c++ - ;; else if (tok`{i}.cmp("/;")) - ;bl++ + /; if (len artifact - 1 > r) + /; loop (int i = 0; i < len (self.sub)) [i++] + /; if (string_equate(artifact{r}, self.sub{i}.name)) + ;return self._find_type(artifact, r + 1) + ;/ + ;/ ;/ - /; if (tok`{i}.cmp(")")) - ;p = p - 1 - ;; else if (tok`{i}.cmp("]")) - ;br = br - 1 - ;; else if (tok`{i}.cmp("}")) - ;c = c - 1 - ;; else if (tok`{i}.cmp(";/") || tok`{i}.cmp(";:")) - ;bl = bl - 1 + /; loop (int i = 0; i < len (self.funcs)) [i++] + /; if (string_equate(self.funcs{i}.name, artifact{r})) + ;return self.funcs{i} + ;/ ;/ + + ;return {{}, "", 0, 0, 0} ;/ - ;return len tok` - 1 -;/ + /; find_function ({}{}uint8 artifact) [Variable] + ;return _find_function(artifact, 0) + ;/ -# Skips cur to the end of a struct -/; skip_struct (~{}Token tok, ~int cur) - /; loop (cur` < len tok`) [cur`++] - /; if (tok`{cur`}.cmp("{")) - ;cur` = find_closing(tok, cur) - ;break + /; _find_mod ({}{}uint8 artifact, int r) [~Module] + /; if (len artifact !> r) + ;return ~self ;/ - ;/ -;/ -# Counts number of components in a composite value -/; count_comp_el (~{}Token tok, int start) [int] - ;int max = find_closing(tok, ~start) - ;int out = 0 + /; if (len artifact - 1 > r) + /; loop (int i = 0; i < len (self.sub)) [i++] + /; if (string_equate(artifact{r}, self.sub{i}.name)) + ;return self.sub{i}._find_mod(artifact, r + 1) + ;/ + ;/ + ;; else if (len artifact - 1 == r) + ;{}uint8 v1 = string_add("_#", artifact{r}), v2 = string_add("__#", artifact{r}) + /; loop (int i = 0; i < len (self.defs)) [i++] + /; if (string_equate(self.sub{i}.name, artifact{r}) ||string_equate(self.sub{i}.name, v1) || string_equate(self.sub{i}.name, v2)) + ;return ~(self.sub{i}) + ;/ + ;/ + ;/ - /; loop (start++; start < max) [start++] - /; if (tok`{start}.type_is(TOKEN.DELIMITER)) - ;start = find_closing(tok, ~start) - ;; else if (tok`{start}.cmp(",")) - ;out++ + /; if (string_equate(self.name, "")) + ;return ~self ;/ + + ;~Module m = self.parent + /; loop (r > 0) [r = r - 1] + ;m = m.parent + ;/ + ;return m`._find_mod(artifact, 0) ;/ - ;return out -;/ - -# Priority -# 0 - deref -# 1 - get -# 2 - ref -# 3 - mul/div/mod -# 4 - add/sub -# 5 - bitwise -# 6 - boolean cmp -# 7 - boolean logic -# 8 - assignment -/; priority (Token tok) [int] - /; if (!(tok.type_is(TOKEN.AUGMENT))) - ;return -1 + /; find_mod({}{}uint8 artifact) [~Module] + ;return self._find_mod(artifact, 0) ;/ - /; if (tok.cmp(".")) - ;return 1 - ;; else if (len (tok.data) == 1) - /; if (tok.cmp("`")) - ;return 0 - ;; else if (tok.cmp("~")) - ;return 2 - ;; else if (tok.cmp("*") || tok.cmp("/") || tok.cmp("%")) - ;return 3 - ;; else if (tok.cmp("-") || tok.cmp("+")) - ;return 4 - ;; else if (tok.cmp("&") || tok.cmp("|") || tok.cmp("^") || tok.cmp("!")) - ;return 5 - ;; else if (tok.cmp("<") || tok.cmp(">")) - ;return 6 - ;; else if (tok.cmp("=")) - ;return 8 - ;/ - ;; else if (len (tok.data) == 2) - /; if (tok.data{0} == tok.data{1}) - /; if (tok.data{0} == '<' || tok.data{0} == '>') - ;return 5 - ;; else if (tok.data{0} == '=') - ;return 6 + /; find_sub ({}uint8 s_mod) [~Module] + ;{}uint8 v1 = string_add("_#", s_mod) + ;{}uint8 v2 = string_add("__#", s_mod) + /; loop (int i = 0; i < len (self.sub)) [i++] + /; if (string_equate(self.sub{i}.name, s_mod) || string_equate(self.sub{i}.name, v1) || string_equate(self.sub{i}.name, v2)) + ;return ~(self.sub{i}) ;/ - ;return 7 - ;; else if (tok.data{1} == '=') - ;return 8 - ;; else if (tok.data{1} == '<' || tok.data{1} == '>') - ;return 6 ;/ - ;return 5 - ;; else if (len (tok.data) == 3) - ;return 6 + + ;return ~self ;/ - ;return -1 + /; full_path [{}uint8] + /; if (string_equate(self.name, "")) + ;return "" + ;/ + ;{}uint8 out = self.parent`.full_path() + /; if (len out > 0) + ;out = string_add(out, ".") + ;/ + ;out = string_add(out, self.name) + ;return out + ;/ ;/ -/; first_match(~{}Token tok, ~int i, int max, ~Module current, ~Scope scope) [Variable] - ;Variable wk - ;{}{}uint8 art = {} - - ;log_debug(string_join( { - "Variable match with s:", int_to_string(i`), " m:", int_to_string(max), " first:", tok`{i`}.sprint() - }, "")) +## +## Compiler funcs +## - /; loop (tok`{i`}.type_is(TOKEN.DEFWORD) && i` < max) [i`++] - ;art.append(tok`{i`}.data) - ;wk = scope`.find_var(art, current) +/; get_artifact (~{}Token tok, ~int cur) [{}{}uint8] + ;{}{}uint8 out = {} - /; if (!string_equate(wk.name, "")) - ;i`++ - ;break + ;out.append(tok`{cur`}.data) + ;cur`++ + + /; loop (cur` < len tok` && tok`{cur`}.cmp(".")) [cur`++] + /; if (tok`{cur` + 1}.type_is(TOKEN.DEFWORD)) + ;out.append(tok`{cur` + 1}.data) + ;cur`++ ;/ + ;/ + ;return out +;/ - /; if (tok`{i` + 1}.cmp(".")) - ;i`++ +/; is_call(~{}Token tok, int i) [bool] + /; loop (i < len (tok`)) [i++] + /; if (tok`{i}.cmp("{")) + ;i = find_closing(tok, ~i) + ;; else if (tok`{i}.cmp("(")) + ;return true + ;; else if (tok`{i}.cmp(".") || tok`{i}.cmp("`") || tok`{i}.type_is(TOKEN.DEFWORD)) + ;continue ;; else - ;i`++ ;break ;/ ;/ - - /; if (string_equate(wk.name, "")) - ;log_err(string_add("Unable to find variable within artifact ", string_join(art, "."))) - ;/ - ;return wk + ;return false ;/ -/; _eval_dot (~{}Token tok, int start, max, ~CompData out, ~Module current, ~Scope scope, Type t, bool alt) [Variable] - ;Variable wk = first_match(tok, ~start, max, current, scope) - - /; if (start !< max) - ;return wk - ;/ - - ;log_debug(string_add("Eval dot initial val: ", wk.sprint())) - - /; if (tok`{start}.cmp(".")) - ;log_debug("Pre loop member") - ;wk = wk.member(tok`{start + 1}.data, out) - ;; else - ;log_debug("Pre loop deref") - ;wk = wk.deref(out) - ;/ +/; get_type (~{}Token tok, ~int cur, ~Module current) [Type] + ;{}int ptr_chain = {} - ;start = start + 2 - - /; loop (start < max) [start++] - /; if (tok`{start}.cmp("`")) - ;log_debug("Loop deref") - ;wk = wk.deref(out) - ;; else if (tok`{start}.cmp(".") && tok`{start + 1}.type_is(TOKEN.DEFWORD)) - ;log_debug("Loop member") - ;wk = wk.member(tok`{start + 1}.data, out) - ;start++ + /; loop (cur` < len tok`) [cur`++] + /; if (tok`{cur`}.cmp("{")) + ;ptr_chain.append(PTYPE.ARRAY) + ;cur`++ + ;; else if (tok`{cur`}.cmp("~")) + ;ptr_chain.append(PTYPE.POINTER) + ;; else + ;break ;/ ;/ + + ;~Type pout = current`.find_type(get_artifact(tok, cur)) + ;Type out = pout` + /; if (string_equate(out.name, "")) + ;return out + ;/ - /; if (alt) - ;wk.move_register(2, out) - ;; else - ;wk.move_register(1, out) + ;{}Type generics = {} + /; if (tok`{cur`}.cmp("(")) + ;int max = find_closing(tok, cur) + ;cur`++ + /; loop (cur` < max) [cur`++] + ;generics.append(get_type(tok, cur, current)) + ;/ ;/ - ;return wk + # TODO: References + + ;out.ptr_chain = ptr_chain + ;return out ;/ -# FIXME: Important last step before the language can be considered remotely usable -/; _eval_call (~{}Token tok, int start, max, ~CompData out, ~Module current, ~Scope scope, Type t) [Variable] - +/; is_definition (~{}Token tok, ~int cur, ~Module current) [bool] + ;int i = cur` + ;Type t = get_type(tok, ~i, current) + ;return tok`{i}.type_is(TOKEN.DEFWORD) && !string_equate(t.name, "") ;/ -/; literal_variable ({}uint8 data, l, ~CompData out) [Variable] - ;Variable v = {"#literal", NO_TYPE, 0, LOCATION.LITERAL} - /; if (data{0} == '"') - ;out`.dsec = string_join({ - out`.dsec, - l, ":\n", - declare_size(8), int_to_string(len unquote_str(data)), "\n", - declare_size(1), data, "\n"} - , "") - ;v.data_type = {1, "uint8", "", {POINTER.ARRAY}, {}} - ;v.loc_type = LOCATION.LABEL - ;v.name = l - ;; else if (data{0} == '\'') - ;v.data_type = {1, "uint8", "", {}, {}} - ;v.location = unqote_char(tok`{start}.data) - ;; else if (string_equate(data, "true")) - ;v.data_type = {1, "bool", "", {}, {}} - ;v.location = 1 - ;; else if (string_equate(data, "false")) - ;v.data_type = {1, "bool", "", {}, {}} - ;v.location = 0 - ;; else - ;v.data_type = {8, "int", "", {}, {}} - ;v.location = string_to_int(data) +/; compile_file_def (~{}Token tok, ~int cur, ~Module current, ~CompData out) + ;Type t = get_type(tok, cur, current) + ;{}uint8 base = current`.full_path() + + /; if (len base > 0) + ;base.append('.') ;/ - ;return v -;/ -/; num_elements(~{}Token tok, int start, max) [int] - ;int out = 1 - /; loop (start < max) [start++] - /; if (tok`{start}.type_is(TOKEN.DELIMITER)) - ;start = find_closing(tok, ~start) - ;; else if (tok`{start}.cmp(",")) - ;out++ + /; loop (!(tok`{cur`}.cmp("\n"))) + /; loop (tok`{cur`}.cmp(",")) + ;cur`++ + ;/ + + ;{}uint8 l = string_add(base, tok`{cur`}.data) + ;Variable v = {l, t, 0, LOCATION.LABEL} + ;current`.defs.append(v) + + /; if (current`.exp) + ;out`.hsec = string_add(out`.hsec, "global ") + ;out`.hsec = string_add(out`.hsec, l) + ;out`.hsec.append('\n') + ;/ + + ;l.append(':') + ;l.append('\n') + ;out`.dsec = string_add(out`.dsec, l) + + ;cur`++ + /; if (tok`{cur`}.cmp("=")) + ;cur`++ + ;out`.dsec = string_add(out`.dsec, decompose_data(tok, cur, t)) + ;cur`++ + ;; else + ;out`.dsec = string_add(out`.dsec, decompose_empty(t)) ;/ ;/ ;/ -/; element_end(~{}Token tok, int start, max) [int] - /; loop (out < max + 1 && !(tok`{start}.cmp(","))) [start++] ;/ - ;return start +/; next_non_nl (~{}Token tok, int c) [int] + /; if (len tok` !> c) + ;return c + ;/ + /; loop (tok`{c}.cmp("\n")) [c++] ;/ + ;return c ;/ -/; _eval_composite (~{}Token tok, int start, max, ~CompData out, mov, ~Module current, ~Scope scope, Type t, bool alt) [Variable] - ;{}uint8 l = scope`.next_const() - /; if (start == max - 1) - ;out`.dsec = string_join( { - out`.dsec, - l, - decompose_empty(t) - }, "") - ;return {l, t, 0, LOCATION.LABEL} - ;; else if (len(t.ptr_chain) > 0) - ;Variable vout = {l, t, 0, LOCATION.LABEL} - ;t.ptr_chain = strip_int(t.ptr_chain) - - ;int count = num_elements(tok, start, max) - ;{}uint8 out_text = string_join( { - l, - "\tdq ", int_to_string(count), "\n" - }, "") - - ;{}uint8 one_el = "\tdb 0" - /; loop (int i = 1; i < t.size()) [i++] - ;one_el = string_add(one_el, ", 0") - ;/ - ;one_el.append('\n') +/; parse_param_list (~{}Token tok, ~int cur, ~Module current) [{}Variable] + ;{}Variable out = {} - ;int ind = 0 - /; loop (start < max) [start = next_non_nl(tok, start + 1)] - ;Variable v = _eval_value(tok, start, element_end(tok, start, max), out, mov, current, scope, t, alt) - /; if (v.loc_type == LOCATION.LITERAL) - ;out_text = string_join( { - out_text, - declare_size(t.size()), int_to_string(v.location), "\n" - }, "") - ;; else - ;out_text = string_add(out_text, one_el) - ;Variable tos = vout.index({"#literal", get_primitive(is_primitive("uint")), ind, LOCATION.LITERAL}, out) - ;tos.set(v, out) + ;int max = find_closing(tok, cur) + ;Type t = NO_TYPE + /; loop (cur` = next_non_nl(tok, cur` + 1); cur` < max) [cur` = next_non_nl(tok, cur` + 1)] + ;int nnl = next_non_nl(tok, cur` + 1) + /; if (tok`{nnl}.cmp(",") || nnl == max) + ;out.append({tok`{cur`}.data, t, 0, 0}) + /; if (tok`{nnl}.cmp(",")) + ;cur`++ ;/ - ;ind++ + ;; else + ;t = get_type(tok, cur, current) + ;cur` = cur` - 1 ;/ - ;out`.dsec = string_add(out`.dsec, out_text) - ;return out ;/ + ;return out ;/ -/; _eval_value(~{}Token tok, int start, max, ~CompData out, mov, ~Module current, ~Scope scope, Type t, bool alt) [Variable] - /; if (start == max - 1) - /; if (tok`{start}.type_is(TOKEN.LITERAL)) - ;{}uint8 l = current`.full_path() - - /; if (len l > 0) - ;l.append('.') - ;/ +# Generates new type +/; new_type (~{}Token tok, ~int cur, ~Module current) + ;cur`++ + ;Type out = {0, tok`{cur`}.data, "", {}, {}} - ;l = string_add(l, scope`.next_const()) - ;return literal_variable(tok`{start}.data, l, out) - ;/ + ;out.mod_name = current`.full_path() + /; if (len (out.mod_name) > 0) + ;out.mod_name.append('.') ;/ + ;out.mod_name = string_add(out.mod_name, "_#") + ;out.mod_name = string_add(out.mod_name, out.name) - ;int first = -1, pr = -1, pa = -1 - /; loop (int i = start; i < max) [i++] - /; if (tok`{i}.type_is(TOKEN.AUGMENT) && priority(tok`{i}) !< pr) - ;first = i - ;pr = priority(tok`{i}) - ;; else if (tok`{i}.type_is(TOKEN.DELIMITER)) - ;pa = i - ;i = find_closing(tok, ~i) - ;/ - ;/ + ;current`.sub.append({current, current`.exp, string_add("_#", out.name), {}, {}, {}, {}}) - /; if (pa !< 0 && pr < 2) - /; if (tok`{pa}.cmp("(") && first == pa) - ;return _eval_value(tok, pa + 1, find_closing(tok, ~pa), out, mov, current, scope, t, alt) - ;; else if (tok`{pa}.cmp("{")) - /; if (pa !== first) - ;log_debug("Index") - ;Variable i = _eval_value(tok, pa + 1, find_closing(tok, ~pa), out, mov, current, scope, t, alt) - ;Variable vout = _eval_dot(tok, start, pa, out, current, scope, t, !alt) - ;return vout.index(i, out) - ;; else - ;log_debug("Composite") - ;return _eval_composite(tok, pa + 1, find_closing(tok, ~pa), out, current, scope, t, alt) - ;/ - ;; else if (tok`{pa}.cmp("[")) - # code for converting value to another type here + /; loop (cur` < len tok`) [cur`++] + /; if (tok`{cur`}.cmp("{")) + ;break ;/ ;/ - # This is all kinda garbage, to fix. - /; if (is_call(tok, start)) - ;log_debug("Attempt to invoke a call") - ;return _eval_call(tok, start, max, out, current, scope, t, alt) - ;; else if (pr < 2) - ;return _eval_dot(tok, start, max, out, current, scope, t, alt) + ;out.members = parse_param_list(tok, cur, current) + /; loop (int i = 0; i < len (out.members)) [i++] + ;log_debug(string_join({"[", out.members{i}.name, ":", out.members{i}.data_type.name, "]"}, "")) ;/ + ;log_debug(string_add("Generated type ", string_add(out.name, string_add(":", out.mod_name)))) + ;current`.types.append(out) +;/ - ;Variable s1, s2 - /; if (first == start) - ;s1 = _eval_value(tok, first + 1, max, out, mov, current, scope, t, alt) - ;; else if (first == max - 1) - ;s1 = _eval_value(tok, start, first, out, mov, current, scope, t, alt) - ;; else - ;s1 = _eval_value(tok, start, first, out, mov, current, scope, t, alt) - /; if (tok`{first}.cmp("=")) - ;t = s1.data_type +/; decompose_empty (Type t) [{}uint8] + /; if (len (t.ptr_chain) > 0) + ;return "\tdq 0\n" + ;/ + ;{}uint8 out = "\tdb 0" + /; loop (int i = 1; i < t.s) [i++] + ;out = string_add(out, ", 0") + ;/ + ;out.append('\n') + ;return out +;/ + +# Used to take an array literal and make it into a label +/; decompose_array (~{}Token tok, ~int cur, Type t) [{}uint8] + ;int max = find_closing(tok, cur) + ;{}uint8 arr = "" + ;int alen = 0 + + /; loop (cur` = next_non_nl(tok, cur` + 1); cur` < max) [cur` = next_non_nl(tok, cur` + 1)] + ;alen++ + /; if (tok`{cur`}.cmp("{")) + /; if (len(t.ptr_chain) > 0) + ;t.ptr_chain = strip_int(t.ptr_chain) + ;arr = string_add(arr, decompose_array(tok, cur, t)) + ;cur` = next_non_nl(tok, cur` + 1) + ;; else + ;decompose_struct(tok, cur, t) + ;cur` = next_non_nl(tok, cur` + 1) + ;/ + ;; else + ;arr = string_add(arr, decompose_data(tok, cur, t)) + ;cur` = next_non_nl(tok, cur` + 1) ;/ - ;s2 = _eval_value(tok, first + 1, max, out, mov, current, scope, t, !alt) - ;log_debug(string_add("Calculated s2 as ", s2.name)) ;/ + ;cur` = max - ;log_debug(string_add("Calculated s2 as ", s1.name)) + ;{}uint out = string_join( { "\tdq ", int_to_string(alen), "\n", arr, "\n" }, "") - /; if (tok`{first}.cmp("=")) - ;s1.set(s2, out) - ;return s1 - ;/ + ;return out +;/ - ;log_debug(string_join( { - "_eval_value called with following type info:", t.sprint() - }, " ")) +# Used to take a struct literal and make it into a label +/; decompose_struct (~{}Token tok, ~int cur, Type t) [{}uint8] + ;int max = find_closing(tok, cur) + ;{}uint8 out = "" + ;int m = 0 + /; loop (cur` = next_non_nl(tok, cur` + 1); cur` < max) [cur` = next_non_nl(tok, cur` + 1)] + /; if (tok`{cur`}.cmp("}")) + ;break + ;; else if (tok`{cur`}.cmp(",")) + ;cur` = next_non_nl(tok, cur` + 1) + ;/ + ;out = string_add(out, decompose_data(tok, cur, t.members{m}.data_type)) + ;m++ + ;/ - ;Variable wk = {"#wk", t, 1, LOCATION.REGISTER} - /; if (alt) - ;wk.location = 2 + /; if (m < len (t.members) - 1) + /; loop (m < len (t.members)) [m++] + ;out = string_add(out, decompose_empty(t.members{m})) + ;/ ;/ - # TODO: Boolean logic - /; if (pr == 6) - ;wk.set(s1, out) - ;wk.cmp(s2, out) - ;wk.data_type = {1, "bool", "_bool", {}, {}} + ;return out +;/ - ;wk.set(literal_variable("true", "", out), out) - ;{}uint8 l = scope`.next_const() - # ;log_debug(l) - ;out`.csec = string_join( { - out`.csec, - to_jmp(tok`{first}.data), l, "\n" - }, "") - ;wk.set(literal_variable("false", "", out), out) - ;out`.csec = string_join( { - out`.csec, - l, ":\n" - }, "") +/; declare_size(int sz) [{}uint8] + ;{}uint8 out = "\tdb " - ;return wk + /; if (sz == 2) + ;out{2} = 'w' + ;; if (sz == 4) + ;out{2} = 'd' + ;; if (sz == 8) + ;out{2} = 'q' ;/ - /; if (tok`{first}.cmp("+")) - ;wk.set(s1, out) - ;wk.add(s2, out) - ;; else if (tok`{first}.cmp("-")) - /; if (first == start) - ;wk.negative(s1, out) - ;return wk + ;return out +;/ + +# Used to take data from a literal and make it into a label +/; decompose_data (~{}Token tok, ~int cur, Type t) [{}uint8] + /; if (tok`{cur`}.cmp("{")) + /; if (len (t.ptr_chain) > 0) + ;t.ptr_chain = strip_int(t.ptr_chain) + ;return decompose_array(tok, cur, t) + ;; else + ;return decompose_struct(tok, cur, t) ;/ - ;wk.set(s1, out) - ;wk.sub(s2, out) - ;; else if (tok`{first}.cmp("|")) - ;wk.set(s1, out) - ;wk.mul(s2, out) - ;; else if (tok`{first}.cmp("&")) - ;wk.set(s1, out) - ;wk.mul(s2, out) - ;; else if (tok`{first}.cmp("^")) - ;wk.set(s1, out) - ;wk.mul(s2, out) - ;; else if (tok`{first}.cmp("*")) - ;wk.set(s1, out) - ;wk.mul(s2, out) - ;; else if (tok`{first}.cmp("*")) - ;wk.set(s1, out) - ;wk.mul(s2, out) - ;; else if (tok`{first}.cmp("/")) - ;wk.set(s1, out) - ;wk.div(s2, out) - ;; else if (tok`{first}.cmp("%")) - ;wk.set(s1, out) - ;wk.mod(s2, out) - ;; else if (tok`{first}.cmp("~")) - /; if (!(s1.is_ref()) && s1.loc_type == LOCATION.REGISTER) - ;s1 = scope`.move_to_stack(s1.location, mov) + ;; if (tok`{cur`}.type_is(TOKEN.LITERAL)) + /; if (string_equate(t.name, "bool")) + ;{}uint data = "0" + /; if (!(tok`{cur`}.cmp("false"))) + ;data = "1" + ;/ + ;return string_add(string_add(declare_size(t.s), data), "\n") ;/ - ;wk.ref(s1, out) - ;; else if (tok`{first}.cmp("!")) - ;wk.not(s1, out) - ;/ - ;return wk + /; if (tok`{cur`}.data{0} == '"') + ;return string_join({ + declare_size(8), int_to_string(len unquote_str(tok`{cur`}.data)), "\n", + declare_size(1), tok`{cur`}.data, "\n"}, "") + ;; else if (tok`{cur`}.data{0} == '\'') + ;return string_join({ + declare_size(1), tok`{cur`}.data, "\n"}, "") + ;/ + ;return string_add(string_add(declare_size(t.s), tok`{cur`}.data), "\n") + ;/ + ;return decompose_empty(t) ;/ -# ALWAYS put the value in rax -/; eval_value (~{}Token tok, ~int cur, ~CompData out, mov, ~Module current, ~Scope scope, Type t, bool save) [Variable] - ;int end = cur` - /; loop (end < len tok`) [end++] - /; if (tok`{end}.type_is(TOKEN.SEPARATOR) || tok`{end}.cmp(";/") || tok`{end}.cmp("]") || tok`{end}.cmp(")")) - ;break - ;; else if (tok`{end}.type_is(TOKEN.DELIMITER)) - ;end = find_closing(tok, ~end) +# Compiles new enum for the file +/; compile_enum (~{}Token tok, ~int cur, ~Module current, ~CompData out) + ;cur`++ + ;Type et = NO_TYPE + ;{}uint8 name = "" + + /; if (tok`{cur`}.cmp("[")) + ;cur`++ + ;et = get_type(tok, cur, current) + ;cur`++ + ;; if (!(tok`{cur`}.cmp("{"))) + ;name = tok`{cur`}.data + ;cur`++ + /; if (tok`{cur`}.cmp("[")) + ;cur`++ + ;et = get_type(tok, cur, current) + ;cur`++ ;/ ;/ - ;Variable val = _eval_value(tok, cur`, end, out, mov, current, scope, t, false) - ;cur` = end - /; if (save) - ;Variable set = {"#tmp", t, 0, LOCATION.REGISTER} - ;set.set(val, out) - ;return val + + /; if (string_equate(et.name, "")) + ;et = Primitives{3} ;/ - ;return { "", NO_TYPE, 0, 0 } -;/ -/; eval_def (~{}Token tok, ~int cur, ~CompData out, mov, ~Module current, ~Scope scope) - ;Type t = get_type(tok, cur, current) - /; loop (tok`{cur`}.type_is(TOKEN.DEFWORD)) - ;scope`.new_var(t, tok`{cur`}.data, out) - ;eval_value(tok, cur, out, mov, current, scope, t, false) + /; loop (!(tok`{cur`}.cmp("{"))) [cur`++] ;/ + ;cur`++ - /; if (tok`{cur`}.cmp(",")) - ;cur` = next_non_nl(tok, cur` + 1) - ;; else - ;break + ;Module enum_mod = {current, current`.exp, string_add("__#", name), {}, {}, {}, {}} + /; loop (cur` < len tok`) [cur`++] + /; if (tok`{cur`}.cmp("}")) + ;break ;/ - ;/ -;/ -/; is_bool_statement (~{}Token tok, int start, max, ~Module current, ~Scope parent) [bool] - ;int i = start - /; loop (i < max) [i++] - /; if (tok`{i}.type_is(TOKEN.AUGMENT)) - /; if (priority(tok`{i}) == 6 || priority(tok`{i}) == 7) - ;return true - ;/ - ;; else if (tok`{i}.type_is(TOKEN.LITERAL)) - /; if (string_equate(tok`{i}.data, "false") || string_equate(tok`{i}.data, "true")) - ;return true - ;/ - ;; else if (tok`{i}.type_is(TOKEN.DEFWORD)) - ;int j = i - ;Variable v = first_match(tok, ~j, max, current, parent) - /; if (string_equate(v.data_type.name, "bool")) - ;int j = len(v.data_type.ptr_chain) - /; if (j == 0 || (j == 1 && v.is_ref())) - ;return true - ;/ + /; if (tok`{cur`}.type_is(TOKEN.DEFWORD)) + ;{}uint8 l = string_add(enum_mod.full_path(), ".") + ;l = string_add(l, tok`{cur`}.data) + + /; if (current`.exp) + ;out`.hsec = string_add(out`.hsec, "global ") + ;out`.hsec = string_add(out`.hsec, l) + ;out`.hsec.append('\n') ;/ - ;; else if (tok`{i}.type_is(TOKEN.DELIMITER)) - ;i = find_closing(tok, ~i) - ;; else if (tok`{i}.cmp(";") || tok`{i}.cmp("\n")) - ;break + + ;Variable v = {l, et, 0, LOCATION.LABEL} + ;enum_mod.defs.append(v) + + ;l.append(':') + ;l.append('\n') + ;cur` = cur` + 2 + ;l = string_add(l, decompose_data(tok, cur, et)) + ;out`.dsec = string_add(out`.dsec, l) ;/ ;/ - ;return false + ;current`.sub.append(enum_mod) ;/ - -/; statement_list(~{}Token tok, int start, end, ~Module current, ~CompData out, mov, ~Scope parent) [{}uint8] - ;log_debug("Statement list!") - ;int b = -1 - ;CompData carry = {"", "", ""} - ;int s = next_non_nl(tok, start + 1) - /; loop (s < end) [s = next_non_nl(tok, s + 1)] - ;out`.add(carry) - ;carry = {"", "", ""} - ;b = -1 - /; if (is_definition(tok, ~s, current)) - - ;log_debug("Block def") - ;eval_def(tok, ~s, out, mov, current, parent) - ;; else - ;log_debug("Block val") - /; if (is_bool_statement(tok, s, end, current, parent)) - ;b = s - ;/ - ;Type t = NO_TYPE - /; if (b !< 0) - ;t = {1, "bool", "_bool", {}, {}} - ;log_debug("Boolish") +# Generates opposite closing bracket +/; closing_for (Token d) [{}uint8] + /; if (d.cmp("(")) + ;return ")" + ;; else if (d.cmp("[")) + ;return "]" + ;; else if (d.cmp("{")) + ;return "}" + ;; else if (d.cmp("/;")) + ;return ";/" + ;/ + ;log_err(string_add("Error, unrecognized delim: ", d.data)) +;/ + +# Finds closing bracket +/; find_closing (~{}Token tok, ~int cur) [int] + ;int bl = 0, p = 0, br = 0, c = 0 + ;{}uint8 cl = closing_for(tok`{cur`}) + /; loop (int i = cur` + 1; i < len tok`) [i++] + /; if (bl == 0 && p == 0 && br == 0 && c == 0) + /; if ((tok`{i}.cmp(";;") || tok`{i}.cmp(";:")) && string_equate(cl, ";/")) + ;return i + ;; else if (tok`{i}.cmp(cl)) + ;return i ;/ - ;eval_value(tok, ~s, out, mov, current, parent, t, b) ;/ - ;/ - ;{}uint str = "" + /; if (tok`{i}.cmp("(")) + ;p++ + ;; else if (tok`{i}.cmp("[")) + ;br++ + ;; else if (tok`{i}.cmp("{")) + ;c++ + ;; else if (tok`{i}.cmp("/;")) + ;bl++ + ;/ - /; if (b > 0) - ;str = int_to_string(b) + /; if (tok`{i}.cmp(")")) + ;p = p - 1 + ;; else if (tok`{i}.cmp("]")) + ;br = br - 1 + ;; else if (tok`{i}.cmp("}")) + ;c = c - 1 + ;; else if (tok`{i}.cmp(";/") || tok`{i}.cmp(";:")) + ;bl = bl - 1 + ;/ ;/ - ;return str + ;return len tok` - 1 ;/ -# FIXME: -# Need to impl: -# cf block scoping and contextual keywords such as -# continue, break, and return -/; _compile_block (~{}Token tok, ~int cur, ~Module current, ~CompData out, mov, ~Scope parent, Type ret) - ;int max = find_closing(tok, cur) - ;Scope cf = parent`.new_sub_cf("wrap") - - ;CompData outro = {"", "", ""} - ;{}uint8 condition = "" - - /; loop (cur`++; cur` < max) [cur`++] - /; if (tok`{cur`}.type_is(TOKEN.KEYWORD)) - /; if (tok`{cur` + 1}.cmp("if")) - ;cf = parent`.new_sub_cf("elif") - ;cur`++ - ;; else - ;cf = cf.new_sub_cf(tok`{cur`}.data) - ;/ - ;; else if (tok`{cur`}.cmp("(") || tok`{cur`}.cmp("[")) - ;int psl = find_closing(tok, cur) - /; if (tok`{cur`}.cmp("[")) - ;outro.csec = string_add(cf.scope_rep_label(), ":\n") - ;{}uint8 tmp = statement_list(tok, cur`, psl, current, ~outro, mov, ~cf) - - /; if (cf.cf_type("loop")) - /; if (len (tmp) == 0 && len (condition) > 0) - /; if (len (condition) > 0) - ;int tmps = string_to_int(condition) - ;eval_value(tok, ~tmps, ~outro, mov, current, ~cf, {1, "bool", "", {}, {}}, true) - ;; else - ;outro.csec = string_join( { - outro.csec, - "\tjmp ", cf.scope_start_label(), "\n" - }, "") - ;/ - ;/ - - /; if (len (tmp) > 0 || len(condition) > 0) - ;outro.csec = string_join( { - outro.csec, - "\ttest al, al\n", - "\tjnz ", cf.scope_start_label(), "\n", - "\tjmp ", cf.scope_end_label(), "\n" - }, "") - ;/ - ;/ - ;; else - ;condition = statement_list(tok, cur`, psl, current, out, mov, ~cf) - /; if (len (condition) == 0) - ;out`.csec = string_join( { - out`.csec, - "\tjmp ", cf.scope_start_label(), "\n" - }, "") - ;; else - ;out`.csec = string_join( { - out`.csec, - "\ttest al, al\n", - "\tjnz ", cf.scope_start_label(), "\n", - "\tjmp ", cf.scope_end_label(), "\n" - }, "") - ;/ - ;/ - ;cur` = psl - ;; else +# Skips cur to the end of a struct +/; skip_struct (~{}Token tok, ~int cur) + /; loop (cur` < len tok`) [cur`++] + /; if (tok`{cur`}.cmp("{")) + ;cur` = find_closing(tok, cur) ;break ;/ ;/ +;/ - ;out`.csec = string_join( { - out`.csec, - cf.scope_start_label(), ":\n" - }, "") - - /; if (tok`{cur`}.cmp("\n")) - ;cur` = next_non_nl(tok, cur` + 1) - ;/ - - ;bool returned = false - /; loop (cur` < max && !returned) [cur` = next_non_nl(tok, cur` + 1)] - /; if (tok`{cur`}.cmp("/;") || tok`{cur`}.cmp(";;")) - ;log_debug("Block in block") - ;_compile_block(tok, cur, current, out, mov, ~cf, ret) +# Counts number of components in a composite value +/; count_comp_el (~{}Token tok, int start) [int] + ;int max = find_closing(tok, ~start) + ;int out = 0 - /; if (tok`{cur`}.cmp(";;")) - ;cur` = cur` - 1 - ;/ - ;; else if (tok`{cur`}.type_is(TOKEN.KEYWORD)) - /; if (tok`{cur`}.cmp("return")) - ;cur`++ - ;eval_value(tok, cur, out, mov, current, ~cf, ret, true) - ;cf.end_scope(out) - ;out`.csec = string_add(out`.csec, "\tret\n") - ;returned = true - ;; else if (tok`{cur`}.cmp("raw") && tok`{cur` + 1}.cmp("return")) - /; if (!(cf.r)) - ;log_err("Unable to perform a raw return from a non-raw block.") - ;/ - ;cur` = cur` + 2 - ;eval_value(tok, cur, out, mov, current, ~cf, ret, true) - ;out`.csec = string_add(out`.csec, "\tret\n") - ;returned = true - ;; else if (tok`{cur`}.cmp("asm")) - ;cur`++ - ;out`.csec.append('\t') - ;out`.csec = string_add(out`.csec, unquote_str(tok`{cur`}.data)) - ;out`.csec.append('\n') - ;; else - ;log_err(string_add("Keyword not impl: ", tok`{cur`}.data)) - ;/ - ;; else if (is_definition(tok, cur, current)) - ;log_debug("Block def") - ;eval_def(tok, cur, out, mov, current, ~cf) - ;; else - ;log_debug("Block val") - ;eval_value(tok, cur, out, mov, current, ~cf, NO_TYPE, false) + /; loop (start++; start < max) [start++] + /; if (tok`{start}.type_is(TOKEN.DELIMITER)) + ;start = find_closing(tok, ~start) + ;; else if (tok`{start}.cmp(",")) + ;out++ ;/ ;/ - ;log_debug("Passing gauntlet 2") - /; if (len (outro.csec) > 0) - ;out`.add(outro) - ;; else - ;out`.csec = string_join( { - out`.csec, - cf.scope_rep_label(), ":\n" - }, "") + ;return out +;/ - /; if (cf.cf_type("loop")) - /; if (len (condition) > 0) - ;int tmps = string_to_int(condition) - ;eval_value(tok, ~tmps, out, mov, current, ~cf, {1, "bool", "", {}, {}}, true) - ;out`.csec = string_join( { - out`.csec, - "\ttest al, al\n", - "\tjnz ", cf.scope_start_label(), "\n", - "\tjmp ", cf.scope_end_label(), "\n" - }, "") - ;; else - ;out`.csec = string_join( { - out`.csec, - "\tjmp ", cf.scope_start_label(), "\n" - }, "") +# Priority +# 0 - deref +# 1 - get +# 2 - ref +# 3 - inc/dec +# 4 - mul/div/mod +# 5 - add/sub +# 6 - bitwise +# 7 - boolean cmp +# 8 - boolean logic +# 9 - assignment +/; priority (Token tok) [int] + /; if (!(tok.type_is(TOKEN.AUGMENT))) + ;return -1 + ;/ + + /; if (tok.cmp(".")) + ;return 1 + ;; else if (len (tok.data) == 1) + /; if (tok.cmp("`")) + ;return 0 + ;; else if (tok.cmp("~")) + ;return 2 + ;; else if (tok.cmp("*") || tok.cmp("/") || tok.cmp("%")) + ;return 4 + ;; else if (tok.cmp("-") || tok.cmp("+")) + ;return 5 + ;; else if (tok.cmp("&") || tok.cmp("|") || tok.cmp("^") || tok.cmp("!")) + ;return 6 + ;; else if (tok.cmp("<") || tok.cmp(">")) + ;return 7 + ;; else if (tok.cmp("=")) + ;return 9 + ;/ + ;; else if (len (tok.data) == 2) + /; if (tok.data{0} == tok.data{1}) + /; if (tok.data{0} == '<' || tok.data{0} == '>') + ;return 6 + ;; else if (tok.data{0} == '=') + ;return 7 + ;; else if (tok.data{0} == '+' || tok.data{0} == '-') + ;return 3 ;/ + ;return 8 + ;; else if (tok.data{1} == '=') + ;return 9 + ;; else if (tok.data{1} == '<' || tok.data{1} == '>') + ;return 7 ;/ + ;return 6 + ;; else if (len (tok.data) == 3) + ;return 7 ;/ - ;out`.csec = string_join( { - out`.csec, - cf.scope_end_label(), ":\n" - }, "") - - /; if (cf.is_cf()) - ;out`.csec = string_join( { - out`.csec, - "\t", cf.parent`.scope_end_label(), ":\n" - }, "") - ;/ + ;return -1 ;/ -/; compile_block (~{}Token tok, ~int cur, ~Module current, ~CompData out) - ;Scope root = {0, 0, 0, "", {}, false} - ;int max = find_closing(tok, cur) - ;bool m = false, returned = false - ;Type ret = NO_TYPE +/; first_match(~{}Token tok, ~int i, int max, ~Module current, ~Scope scope) [Variable] + ;Variable wk + ;{}{}uint8 art = {} - /; if (len (current`.name) > 2) - /; if (current`.name{0} == '_' && current`.name{1} == '#') - ;{}{}uint8 split = string_split(current`.name, '#') - ;Type st = current`.find_type( {split{1}} )` - ;st.ptr_chain = {PTYPE.REFERENCE} - ;root.vars.append({"self", st, 0, 0}) + ;log_debug(string_join( { + "Variable match with s:", int_to_string(i`), " m:", int_to_string(max), " first:", tok`{i`}.sprint() + }, "")) + + /; loop (tok`{i`}.type_is(TOKEN.DEFWORD) && i` < max) [i`++] + ;art.append(tok`{i`}.data) + ;wk = scope`.find_var(art, current) + + /; if (!string_equate(wk.name, "")) + ;i`++ + ;break ;/ - ;/ - /; loop (cur`++; cur` < max && !m) [cur`++] - /; if (tok`{cur`}.type_is(TOKEN.DEFWORD)) - ;root.name = tok`{cur`}.data - ;; if (tok`{cur`}.type_is(TOKEN.KEYWORD)) - /; if (tok`{cur`}.cmp("raw")) - ;root.r = true - ;; else if (tok`{cur`}.cmp("method")) - ;m = true - ;current = current`.find_sub(tok`{cur` + 1}.data) - ;; else - ;log_err(string_join( { - "Keyword ", tok`{cur`}.data, " not impl on mod level blocks" - }, "")) - ;/ - ;; if (tok`{cur`}.cmp("(")) - ;root.vars = parse_param_list(tok, cur, current) - ;; if (tok`{cur`}.cmp("[")) - ;cur`++ - ;ret = get_type(tok, cur, current) - ;; if (tok`{cur`}.cmp("\n")) + /; if (tok`{i` + 1}.cmp(".")) + ;i`++ + ;; else + ;i`++ ;break ;/ ;/ - /; if (!m) - ;{}uint8 l = "" - /; if (!string_equate(current`.name, "")) - ;l = string_add(l, current`.full_path()) - ;l.append('.') - ;/ - ;l = string_add(l, root.name) - ;root.name = l + /; if (string_equate(wk.name, "")) + ;log_err(string_add("Unable to find variable within artifact ", string_join(art, "."))) + ;/ + ;log_info(string_add("Found ", wk.sprint())) + ;return wk +;/ - /; if (current`.exp) - ;out`.hsec = string_add(out`.hsec, "global ") - ;out`.hsec = string_add(out`.hsec, l) - ;out`.hsec.append('\n') - ;/ - ;out`.csec = string_add(out`.csec, l) - ;out`.csec = string_add(out`.csec, ":\n") - ;root.begin_scope(out) +/; _eval_dot (~{}Token tok, int start, max, ~CompData out, ~Module current, ~Scope scope, Type t, bool alt) [Variable] + ;Variable wk = first_match(tok, ~start, max, current, scope) + + /; if (start !< max) + ;return wk ;/ - /; loop (cur` = next_non_nl(tok, cur` + 1); cur` < max && !returned) [cur` = next_non_nl(tok, cur` + 1)] - /; if (tok`{cur`}.cmp("/;") || tok`{cur`}.cmp(";;")) - ;log_debug("Block in block") - /; if (m) - ;compile_block(tok, cur, current, out) - ;; else - ;CompData mov = {"", "", ""}, tmp = {"", "", ""} - ;log_debug("PRE COMPUTATION OF BLOCK\n") - ;int tcr = cur` - ;_compile_block(tok, ~tcr, current, ~tmp, ~mov, ~root, ret) - ;out`.add(mov) - ;log_debug("POST COMPUTATION OF BLOCK") - ;_compile_block(tok, cur, current, out, ~tmp, ~root, ret) - ;/ + ;log_debug(string_add("Eval dot initial val: ", wk.sprint())) - /; if (tok`{cur`}.cmp(";;")) - ;cur` = cur` - 1 - ;/ - ;; else if (tok`{cur`}.type_is(TOKEN.KEYWORD)) - /; if (tok`{cur`}.cmp("return")) - ;cur`++ - ;eval_value(tok, cur, out, out, current, ~root, ret, true) - ;root.end_scope(out) - ;out`.csec = string_add(out`.csec, "\tret\n") - ;returned = true - ;; else if (tok`{cur`}.cmp("raw") && tok`{cur` + 1}.cmp("return")) - /; if (!(root.r)) - ;log_err("Unable to perform a raw return from a non-raw block.") - ;/ - ;cur` = cur` + 2 - ;eval_value(tok, cur, out, out, current, ~root, ret, true) - ;out`.csec = string_add(out`.csec, "\tret\n") - ;returned = true - ;; else if (tok`{cur`}.cmp("asm")) - ;cur`++ - ;out`.csec.append('\t') - ;out`.csec = string_add(out`.csec, unquote_str(tok`{cur`}.data)) - ;out`.csec.append('\n') - ;; else - ;log_err(string_add("Keyword not impl: ", tok`{cur`}.data)) - ;/ - ;; else if (is_definition(tok, cur, current)) - ;log_debug("Block def") - ;eval_def(tok, cur, out, out, current, ~root) - ;; else - ;log_debug("Block val") - ;eval_value(tok, cur, out, out, current, ~root, NO_TYPE, false) - ;/ + /; if (tok`{start}.cmp(".")) + ;log_debug("Pre loop member") + ;wk = wk.member(tok`{start + 1}.data, out) + ;; else + ;log_debug("Pre loop deref") + ;wk = wk.deref(out) ;/ + + ;start = start + 2 - ;cur` = max + /; loop (start < max) [start++] + /; if (tok`{start}.cmp("`")) + ;log_debug("Loop deref") + ;wk = wk.deref(out) + ;; else if (tok`{start}.cmp(".") && tok`{start + 1}.type_is(TOKEN.DEFWORD)) + ;log_debug("Loop member") + ;wk = wk.member(tok`{start + 1}.data, out) + ;start++ + ;/ + ;/ - /; if (!returned && !string_equate(ret.name, "")) - ;log_err("Block must return a value.") + /; if (alt) + ;wk.move_register(2, out) + ;; else + ;wk.move_register(1, out) ;/ - /; if (!m && !returned) - ;root.end_scope(out) - ;out`.csec = string_add(out`.csec, "\tret\n") + ;return wk +;/ + +# FIXME: Important step before the language can be considered remotely usable +/; _eval_call (~{}Token tok, int start, max, ~CompData out, ~Module current, ~Scope scope, Type t) [Variable] + ;return {"#null", NO_TYPE, 0, LOCATION.LITERAL} +;/ + +/; literal_variable ({}uint8 data, l, ~CompData out) [Variable] + ;Variable v = {"#literal", NO_TYPE, 0, LOCATION.LITERAL} + /; if (data{0} == '"') + ;out`.dsec = string_join({ + out`.dsec, + l, ":\n", + declare_size(8), int_to_string(len unquote_str(data)), "\n", + declare_size(1), data, "\n"} + , "") + ;v.data_type = {1, "uint8", "", {POINTER.ARRAY}, {}} + ;v.loc_type = LOCATION.LABEL + ;v.name = l + ;; else if (data{0} == '\'') + ;v.data_type = {1, "uint8", "", {}, {}} + ;v.location = unqote_char(tok`{start}.data) + ;; else if (string_equate(data, "true")) + ;v.data_type = {1, "bool", "", {}, {}} + ;v.location = 1 + ;; else if (string_equate(data, "false")) + ;v.data_type = {1, "bool", "", {}, {}} + ;v.location = 0 + ;; else + ;v.data_type = {8, "int", "", {}, {}} + ;v.location = string_to_int(data) ;/ + ;return v ;/ -# First pass on a module -# Generates structs, enums, and submodules -/; module_pass_one (~{}Token tok, ~int cur, ~Module current, Path f) - ;int max = find_closing(tok, cur) - ;Module new = {current, false, "", {}, {}, {}, {}} - /; loop (cur`++; cur` < len tok`) [cur`++] - /; if (tok`{cur`}.type_is(TOKEN.DEFWORD)) - ;new.name = tok`{cur`}.data - ;; else if (tok`{cur`}.cmp("export")) - ;new.exp = true - ;; else if (!(tok`{cur`}.cmp("module"))) - ;break +/; num_elements(~{}Token tok, int start, max) [int] + ;int out = 1 + /; loop (start < max) [start++] + /; if (tok`{start}.type_is(TOKEN.DELIMITER)) + ;start = find_closing(tok, ~start) + ;; else if (tok`{start}.cmp(",")) + ;out++ ;/ ;/ +;/ - /; loop (cur` < max) [cur`++] - ;log_vis(".") - /; if (tok`{cur`}.cmp(":")) - ;log_debug("INCLUDE") - /; if (tok`{cur` + 2}.type_is(TOKEN.LITERAL)) - ;compile_file_pass_one(f.relative(unquote_str(tok`{cur` + 2}.data)), ~new) - ;cur` = cur` + 2 +/; element_end(~{}Token tok, int start, max) [int] + /; loop (out < max + 1 && !(tok`{start}.cmp(","))) [start++] ;/ + ;return start +;/ + +/; _eval_composite (~{}Token tok, int start, max, ~CompData out, mov, ~Module current, ~Scope scope, Type t, bool alt) [Variable] + ;{}uint8 l = scope`.next_const() + /; if (start == max - 1) + ;out`.dsec = string_join( { + out`.dsec, + l, + decompose_empty(t) + }, "") + ;return {l, t, 0, LOCATION.LABEL} + ;; else if (len(t.ptr_chain) > 0) + ;Variable vout = {l, t, 0, LOCATION.LABEL} + ;t.ptr_chain = strip_int(t.ptr_chain) + + ;int count = num_elements(tok, start, max) + ;{}uint8 out_text = string_join( { + l, + "\tdq ", int_to_string(count), "\n" + }, "") + + ;{}uint8 one_el = "\tdb 0" + /; loop (int i = 1; i < t.size()) [i++] + ;one_el = string_add(one_el, ", 0") + ;/ + ;one_el.append('\n') + + ;int ind = 0 + /; loop (start < max) [start = next_non_nl(tok, start + 1)] + ;Variable v = _eval_value(tok, start, element_end(tok, start, max), out, mov, current, scope, t, alt) + /; if (v.loc_type == LOCATION.LITERAL) + ;out_text = string_join( { + out_text, + declare_size(t.size()), int_to_string(v.location), "\n" + }, "") + ;; else + ;out_text = string_add(out_text, one_el) + ;Variable tos = vout.index({"#literal", get_primitive(is_primitive("uint")), ind, LOCATION.LITERAL}, out) + ;tos.set(v, out) ;/ - ;continue - ;; else if (tok`{cur`}.cmp("/;") || tok`{cur`}.cmp(";;")) - /; if (tok`{cur` + 1}.cmp("export") || tok`{cur` + 1}.cmp("module")) - ;module_pass_one(tok, cur, ~new, f) + ;ind++ + ;/ + ;out`.dsec = string_add(out`.dsec, out_text) + ;return out + ;/ +;/ + +/; _eval_value(~{}Token tok, int start, max, ~CompData out, mov, ~Module current, ~Scope scope, Type t, bool alt) [Variable] + /; if (start == max - 1) + /; if (tok`{start}.type_is(TOKEN.LITERAL)) + ;{}uint8 l = current`.full_path() + + /; if (len l > 0) + ;l.append('.') ;/ - ;; else if (tok`{cur`}.cmp("struct")) - ;new_type(tok, cur, ~new) + + ;l = string_add(l, scope`.next_const()) + ;return literal_variable(tok`{start}.data, l, out) ;/ ;/ - ;current`.sub.append(new) -;/ -# Second pass on a module -# Generates code and calls compile_file_second_pass if an include happens -/; module_pass_two (~{}Token tok, ~int cur, ~Module current, ~CompData out, Path f) - ;int max = find_closing(tok, cur) - /; loop (cur`++; cur` < len tok`) [cur`++] - /; if (tok`{cur`}.type_is(TOKEN.DEFWORD)) - ;current = current`.find_sub(tok`{cur`}.data) - ;; else if (!(tok`{cur`}.cmp("module")) && !(tok`{cur`}.cmp("export"))) - ;break + ;int first = -1, pr = -1, pa = -1 + /; loop (int i = start; i < max) [i++] + /; if (tok`{i}.type_is(TOKEN.AUGMENT) && priority(tok`{i}) !< pr) + ;first = i + ;pr = priority(tok`{i}) + ;; else if (tok`{i}.type_is(TOKEN.DELIMITER)) + ;pa = i + ;i = find_closing(tok, ~i) ;/ ;/ - /; loop (cur` = next_non_nl(tok, cur`); cur` < max) [cur` = next_non_nl(tok, cur` + 1)] - ;log_vis(".") - /; if (tok`{cur`}.cmp(":")) - ;log_debug("INCLUDE") - /; if (tok`{cur` + 2}.type_is(TOKEN.LITERAL)) - ;CompData tmp = compile_file_pass_two(f.relative(unquote_str(tok`{cur` + 2}.data)), current) - ;out`.hsec = string_add(out`.hsec, tmp.hsec) - ;out`.dsec = string_add(out`.dsec, tmp.dsec) - ;out`.csec = string_add(out`.csec, tmp.csec) - ;cur` = cur` + 2 - ;/ - ;continue - ;; else if (tok`{cur`}.cmp("/;") || tok`{cur`}.cmp(";;")) - ;log_debug("Mod block") - /; if (tok`{cur` + 1}.cmp("export") || tok`{cur` + 1}.cmp("module")) - ;module_pass_two(tok, cur, current, out, f) + ;Variable wk = {"#wk", t, 1, LOCATION.REGISTER} + /; if (alt) + ;wk.location = 2 + ;/ + + /; if (pa !< 0 && pr < 2) + /; if (tok`{pa}.cmp("(") && first == pa) + ;return _eval_value(tok, pa + 1, find_closing(tok, ~pa), out, mov, current, scope, t, alt) + ;; else if (tok`{pa}.cmp("{")) + /; if (pa !== first) + ;log_debug("Index") + ;Variable i = _eval_value(tok, pa + 1, find_closing(tok, ~pa), out, mov, current, scope, t, alt) + ;Variable vout = _eval_dot(tok, start, pa, out, current, scope, t, !alt) + ;vout = vout.index(i, out) + ;wk.data_type = vout.data_type + ;out`.csec = string_join( { + out`.csec, + "\tmov ", get_reg(wk.location, 8), ", rsi\n" + }, "") + ;return wk ;; else - ;compile_block(tok, cur, current, out) + ;log_debug("Composite") + ;return _eval_composite(tok, pa + 1, find_closing(tok, ~pa), out, current, scope, t, alt) ;/ - ;; else if (tok`{cur`}.cmp("struct")) - ;log_debug("Mod struct") - ;skip_struct(tok, cur) - ;; else if (tok`{cur`}.cmp("enum")) - ;log_debug("Mod enum") - ;compile_enum(tok, cur, current, out) - ;; else if (is_definition(tok, cur, current)) - ;log_debug("Mod def") - ;compile_file_def(tok, cur, current, out) - ;; else if (!(tok`{cur`}.cmp("\n"))) - ;log_err(string_add("Failed to recognize file-level statement ", tok`{cur`}.sprint())) + ;; else if (tok`{pa}.cmp("[")) + # code for converting value to another type here ;/ ;/ -;/ -# First compiler pass on a file -# Only creates structs, enums, and moduless -/; compile_file_pass_one (Path f, ~Module current) - ;{}Token tok = tokenize(f) - ;log_info(string_add("Number of tokens generated: ", int_to_string(len tok))) + # This is all kinda garbage, to fix. + /; if (is_call(tok, start)) + ;log_debug("Attempt to invoke a call") + ;return _eval_call(tok, start, max, out, current, scope, t, alt) + ;; else if (pr < 2) + ;return _eval_dot(tok, start, max, out, current, scope, t, alt) + ;/ + - /; loop (int i = 0; i < len tok) [i++] - ;log_vis(".") - /; if (tok{i}.cmp(":")) - ;log_debug("INCLUDE") - /; if (tok{i + 2}.type_is(TOKEN.LITERAL)) - ;CompData tmp = compile_file_pass_one(f.relative(unquote_str(tok{i + 2}.data)), current) - ;i = i + 2 - ;/ - ;continue - ;; else if (tok{i}.cmp("/;") || tok{i}.cmp(";;")) - /; if (tok{i + 1}.cmp("export") || tok{i + 1}.cmp("module")) - ;module_pass_one(~tok, ~i, current, f) - ;/ - ;; else if (tok{i}.cmp("struct")) - ;new_type(~tok, ~i, current) + ;Variable s1, s2 + /; if (first == start) + ;s1 = _eval_value(tok, first + 1, max, out, mov, current, scope, t, alt) + ;; else if (first == max - 1) + ;s1 = _eval_value(tok, start, first, out, mov, current, scope, t, alt) + ;; else + ;s1 = _eval_value(tok, start, first, out, mov, current, scope, t, alt) + /; if (tok`{first}.cmp("=")) + ;t = s1.data_type ;/ + ;s2 = _eval_value(tok, first + 1, max, out, mov, current, scope, t, !alt) + ;log_debug(string_add("Calculated s2 as ", s2.name)) ;/ -;/ -/; size_struct (~Type t, ~Module m) - ;int s = 0 + ;log_debug(string_add("Calculated s2 as ", s1.name)) - /; loop (int i = 0; i < len (t`.members)) [i++] - ;int p = is_primitive(t`.members{i}.data_type.name) - /; if (len (t`.members{i}.data_type.ptr_chain) > 0) - ;s = s + 8 - ;; else if (p >== 0) - ;s = s + p + /; if (tok`{first}.cmp("=")) + ;s1.set(s2, out) + ;return s1 + ;/ + + ;log_debug(string_join( { + "_eval_value called with following type info:", t.sprint() + }, " ")) + + # Inc and dec + /; else if (tok`{first}.cmp("++") || tok`{first}.cmp("--")) + ;wk.data_type = s1.data_type + ;wk.set(s1, out) + + /; if (tok`{first}.cmp("++")) + ;s1.inc(out) ;; else - ;log_debug("STRUCT!!!!!!") - ;{}{}uint8 artifact = { t`.members{i}.data_type.name } - ;~Type tp = m`.find_type(artifact) - /; if (tp`.s == 0) - ;size_struct(tp, m) - ;/ - ;t`.members{i}.data_type = tp` - ;s = s + tp`.s + ;s1.dec(out) ;/ - ;/ - ;log_debug(string_add("Sized type ", t`.name)) - ;t`.s = s -;/ -# Regenerates struct sizes (with support for cyclical struct definitions) -/; flush_structs (~Module m) - - /; loop (int i = 0; i < len (m`.types)) [i++] - ;size_struct(~(m`.types{i}), m) + /; if (first == max - 1) + ;return wk + ;/ + ;return s1 ;/ - /; loop (int i = 0; i < len (m`.sub)) [i++] - ;flush_structs(~(m`.sub{i})) + # TODO: Boolean logic + /; if (pr == 7) + ;wk.set(s1, out) + ;wk.cmp(s2, out) + ;wk.data_type = {1, "bool", "_bool", {}, {}} + + ;wk.set(literal_variable("true", "", out), out) + ;{}uint8 l = scope`.next_const() + # ;log_debug(l) + ;out`.csec = string_join( { + out`.csec, + to_jmp(tok`{first}.data), l, "\n" + }, "") + ;wk.set(literal_variable("false", "", out), out) + ;out`.csec = string_join( { + out`.csec, + l, ":\n" + }, "") + + ;return wk ;/ -;/ -# Second pass of compiler -# Does code generation, ignores structs and enums -/; compile_file_pass_two (Path f, ~Module current) [CompData] - ;CompData out = {"", "", ""} - ;{}Token tok = tokenize(f) + /; if (tok`{first}.cmp("+")) + ;wk.set(s1, out) + ;wk.add(s2, out) + ;; else if (tok`{first}.cmp("-")) + /; if (first == start) + ;wk.negative(s1, out) + ;return wk + ;/ + ;wk.set(s1, out) + ;wk.sub(s2, out) + ;; else if (tok`{first}.cmp("|")) + ;wk.set(s1, out) + ;wk.mul(s2, out) + ;; else if (tok`{first}.cmp("&")) + ;wk.set(s1, out) + ;wk.mul(s2, out) + ;; else if (tok`{first}.cmp("^")) + ;wk.set(s1, out) + ;wk.mul(s2, out) + ;; else if (tok`{first}.cmp("*")) + ;wk.set(s1, out) + ;wk.mul(s2, out) + ;; else if (tok`{first}.cmp("*")) + ;wk.set(s1, out) + ;wk.mul(s2, out) + ;; else if (tok`{first}.cmp("/")) + ;wk.set(s1, out) + ;wk.div(s2, out) + ;; else if (tok`{first}.cmp("%")) + ;wk.set(s1, out) + ;wk.mod(s2, out) + ;; else if (tok`{first}.cmp("~")) + /; if (!(s1.is_ref()) && s1.loc_type == LOCATION.REGISTER) + ;s1 = scope`.move_to_stack(s1.location, mov) + ;/ + ;wk.ref(s1, out) + ;; else if (tok`{first}.cmp("!")) + ;wk.not(s1, out) + ;/ - /; loop (int i = next_non_nl(~tok, 0); i < len tok) [i = next_non_nl(~tok, i+1)] - ;log_vis(".") - /; if (tok{i}.cmp(":")) - ;log_debug("INCLUDE") - /; if (tok{i + 2}.type_is(TOKEN.LITERAL)) - ;CompData tmp = compile_file_pass_two(f.relative(unquote_str(tok{i + 2}.data)), current) - ;out.hsec = string_add(out.hsec, tmp.hsec) - ;out.dsec = string_add(out.dsec, tmp.dsec) - ;out.csec = string_add(out.csec, tmp.csec) - ;i = i + 2 - ;/ - ;continue - ;; else if (tok{i}.cmp("/;") || tok{i}.cmp(";;")) - ;log_debug("Root block") - /; if (tok{i + 1}.cmp("export") || tok{i + 1}.cmp("module")) - ;module_pass_two(~tok, ~i, current, ~out, f) - ;; else - ;compile_block(~tok, ~i, current, ~out) - ;/ - ;; else if (tok{i}.cmp("struct")) - ;log_debug("File struct") - ;skip_struct(~tok, ~i) - ;; else if (tok{i}.cmp("enum")) - ;log_debug("File enum") - ;compile_enum(~tok, ~i, current, ~out) - ;; else if (is_definition(~tok, ~i, current)) - ;log_debug("File def") - ;compile_file_def(~tok, ~i, current, ~out) - ;; else if (tok{i}.cmp("asm")) - ;log_debug("File asm") - /; if (len (out.csec) == 0 && len (out.dsec) == 0) - ;out.hsec = string_add(out.hsec, unquote_str(tok{i + 1}.data)) - ;out.hsec.append('\n') - ;; else - ;out.dsec = string_add(out.dsec, unquote_str(tok{i + 1}.data)) - ;out.dsec.append('\n') - ;/ - ;i++ - ;; else if (!(tok{i}.cmp("\n"))) - ;log_err(string_add("Failed to recognize file-level statement", tok{i}.sprint())) + ;return wk +;/ + +# ALWAYS put the value in rax +/; eval_value (~{}Token tok, ~int cur, ~CompData out, mov, ~Module current, ~Scope scope, Type t, bool save) [Variable] + ;int end = cur` + /; loop (end < len tok`) [end++] + /; if (tok`{end}.type_is(TOKEN.SEPARATOR) || tok`{end}.cmp(";/") || tok`{end}.cmp("]") || tok`{end}.cmp(")")) + ;break + ;; else if (tok`{end}.type_is(TOKEN.DELIMITER)) + ;end = find_closing(tok, ~end) ;/ ;/ + ;Variable val = _eval_value(tok, cur`, end, out, mov, current, scope, t, false) + ;cur` = end + /; if (save) + ;Variable set = {"#tmp", t, 0, LOCATION.REGISTER} + ;set.set(val, out) + ;return val + ;/ + ;return { "", NO_TYPE, 0, 0 } +;/ - ;log_info(string_add("File compiled! Generated code length: ", int_to_string(len (out.hsec) + len (out.dsec) + len (out.csec)))) +/; eval_def (~{}Token tok, ~int cur, ~CompData out, mov, ~Module current, ~Scope scope) + ;Type t = get_type(tok, cur, current) + /; loop (tok`{cur`}.type_is(TOKEN.DEFWORD)) + ;scope`.new_var(t, tok`{cur`}.data, out) + ;eval_value(tok, cur, out, mov, current, scope, t, false) - ;return out + /; if (tok`{cur`}.cmp(",")) + ;cur` = next_non_nl(tok, cur` + 1) + ;; else + ;break + ;/ + ;/ ;/ -# Starts the compiler on a given path -/; compile_start (Path f) [{}uint8] - ;{}uint8 out = "" +/; is_bool_statement (~{}Token tok, int start, max, ~Module current, ~Scope parent) [bool] + ;int i = start + /; loop (i < max) [i++] + /; if (tok`{i}.type_is(TOKEN.AUGMENT)) + /; if (priority(tok`{i}) == 7 || priority(tok`{i}) == 8) + ;return true + ;/ + ;; else if (tok`{i}.type_is(TOKEN.LITERAL)) + /; if (string_equate(tok`{i}.data, "false") || string_equate(tok`{i}.data, "true")) + ;return true + ;/ + ;; else if (tok`{i}.type_is(TOKEN.DEFWORD)) + ;int j = i + ;Variable v = first_match(tok, ~j, max, current, parent) + /; if (string_equate(v.data_type.name, "bool")) + ;int j = len(v.data_type.ptr_chain) + /; if (j == 0 || (j == 1 && v.is_ref())) + ;return true + ;/ + ;/ + ;; else if (tok`{i}.type_is(TOKEN.DELIMITER)) + ;i = find_closing(tok, ~i) + ;; else if (tok`{i}.cmp(";") || tok`{i}.cmp("\n")) + ;break + ;/ + ;/ - ;Module root = {0, true, {}, {}, {}, {}, {}} - ;compile_file_pass_one(f, ~root) - ;flush_structs(~root) - ;log_info("First pass DONE") + ;return false +;/ - ;CompData data = compile_file_pass_two(f, ~root) - ;log_info("Second pass DONE") - ;out = string_join({ - data.hsec, - "section .data\n", - data.dsec, - "section .text\n", - data.csec}, "") +/; statement_list(~{}Token tok, int start, end, ~Module current, ~CompData out, mov, ~Scope parent) [{}uint8] + ;log_debug("Statement list!") + ;int b = -1 + ;CompData carry = {"", "", ""} + ;int s = next_non_nl(tok, start + 1) + /; loop (s < end) [s = next_non_nl(tok, s + 1)] + ;out`.add(carry) + ;carry = {"", "", ""} + ;b = -1 + /; if (is_definition(tok, ~s, current)) - ;return out -;/ + ;log_debug("Block def") + ;eval_def(tok, ~s, out, mov, current, parent) + ;; else + ;log_debug("Block val") + /; if (is_bool_statement(tok, s, end, current, parent)) + ;b = s + ;/ + ;Type t = NO_TYPE + /; if (b !< 0) + ;t = {1, "bool", "_bool", {}, {}} + ;log_debug("Boolish") + ;/ + ;eval_value(tok, ~s, out, mov, current, parent, t, b > 0) + ;/ + ;/ -## -## Tokenizer funcs -## + ;{}uint str = "" + /; if (b > 0) + ;str = int_to_string(b) + ;/ -/; is_whitespace (uint8 c) [bool] - ;return (c == '\n' || c == '\t' || c == ' ') + ;return str ;/ -;{}uint8 MULTI_PARENS = "/;:#" -;{}uint8 PARENS = "()[]{}" -;{}uint8 SEPS = "\n;:," -;{}uint8 RESERVED = "`~!%^&*()-+=[]{}|;:/?<>.,\"" -;{}uint8 AUGMENTS = "=~!<>&|^+-*/%`." - -;{}{}uint8 MULTI_AUGMENTS = { - "~=", "`=", "%=", "^=", "&=", "*=", - "!=", "|=", "/=", - - "==", "!==", "&&", "||", "^^", "<==", ">==", "!>", "!<", +# FIXME: +# Need to impl: +# cf block scoping and contextual keywords such as +# continue, break, and return +/; _compile_block (~{}Token tok, ~int cur, ~Module current, ~CompData out, mov, ~Scope parent, Type ret) + ;int max = find_closing(tok, cur) + ;Scope cf = parent`.new_sub_cf("wrap") + + ;CompData outro = {"", "", ""} + ;{}uint8 condition = "" - "<<", ">>", "!&", "!|", "!^" -} + /; loop (cur`++; cur` < max) [cur`++] + /; if (tok`{cur`}.type_is(TOKEN.KEYWORD)) + /; if (tok`{cur` + 1}.cmp("if")) + ;cf = parent`.new_sub_cf("elif") + ;cur`++ + ;; else + ;cf = cf.new_sub_cf(tok`{cur`}.data) + ;/ + ;; else if (tok`{cur`}.cmp("(") || tok`{cur`}.cmp("[")) + ;int psl = find_closing(tok, cur) + /; if (tok`{cur`}.cmp("[")) + ;outro.csec = string_add(cf.scope_rep_label(), ":\n") + ;{}uint8 tmp = statement_list(tok, cur`, psl, current, ~outro, mov, ~cf) + /; if (cf.cf_type("loop")) + /; if (len (tmp) == 0 && len (condition) > 0) + /; if (len (condition) > 0) + ;int tmps = string_to_int(condition) + ;eval_value(tok, ~tmps, ~outro, mov, current, ~cf, {1, "bool", "", {}, {}}, true) + ;; else + ;outro.csec = string_join( { + outro.csec, + "\tjmp ", cf.scope_start_label(), "\n" + }, "") + ;/ + ;/ -;{}{}uint8 KEYWORDS = { - "len", - "is", + /; if (len (tmp) > 0 || len(condition) > 0) + ;outro.csec = string_join( { + outro.csec, + "\ttest al, al\n", + "\tjnz ", cf.scope_start_label(), "\n", + "\tjmp ", cf.scope_end_label(), "\n" + }, "") + ;/ + ;/ + ;; else + ;condition = statement_list(tok, cur`, psl, current, out, mov, ~cf) + /; if (len (condition) == 0) + ;out`.csec = string_join( { + out`.csec, + "\tjmp ", cf.scope_start_label(), "\n" + }, "") + ;; else + ;out`.csec = string_join( { + out`.csec, + "\ttest al, al\n", + "\tjnz ", cf.scope_start_label(), "\n", + "\tjmp ", cf.scope_end_label(), "\n" + }, "") + ;/ + ;/ + ;cur` = psl + ;; else + ;break + ;/ + ;/ - "if", - "else", - "loop", + ;out`.csec = string_join( { + out`.csec, + cf.scope_start_label(), ":\n" + }, "") + + /; if (tok`{cur`}.cmp("\n")) + ;cur` = next_non_nl(tok, cur` + 1) + ;/ - "continue", - "break", - "return", + ;bool returned = false + /; loop (cur` < max && !returned) [cur` = next_non_nl(tok, cur` + 1)] + /; if (tok`{cur`}.cmp("/;") || tok`{cur`}.cmp(";;")) + ;log_debug("Block in block") + ;_compile_block(tok, cur, current, out, mov, ~cf, ret) - "method", - "struct", - "enum", - "interface", + /; if (tok`{cur`}.cmp(";;")) + ;cur` = cur` - 1 + ;/ + ;; else if (tok`{cur`}.type_is(TOKEN.KEYWORD)) + /; if (tok`{cur`}.cmp("return")) + ;cur`++ + ;eval_value(tok, cur, out, mov, current, ~cf, ret, true) + ;cf.end_scope(out) + ;out`.csec = string_add(out`.csec, "\tret\n") + ;returned = true + ;; else if (tok`{cur`}.cmp("raw") && tok`{cur` + 1}.cmp("return")) + /; if (!(cf.r)) + ;log_err("Unable to perform a raw return from a non-raw block.") + ;/ + ;cur` = cur` + 2 + ;eval_value(tok, cur, out, mov, current, ~cf, ret, true) + ;out`.csec = string_add(out`.csec, "\tret\n") + ;returned = true + ;; else if (tok`{cur`}.cmp("asm")) + ;cur`++ + ;out`.csec.append('\t') + ;out`.csec = string_add(out`.csec, unquote_str(tok`{cur`}.data)) + ;out`.csec.append('\n') + ;; else + ;log_err(string_add("Keyword not impl: ", tok`{cur`}.data)) + ;/ + ;; else if (is_definition(tok, cur, current)) + ;log_debug("Block def") + ;eval_def(tok, cur, out, mov, current, ~cf) + ;; else + ;log_debug("Block val") + ;eval_value(tok, cur, out, mov, current, ~cf, NO_TYPE, false) + ;/ + ;/ + ;log_debug("Passing gauntlet 2") - "export", - "module", + /; if (len (outro.csec) > 0) + ;out`.add(outro) + ;; else + ;out`.csec = string_join( { + out`.csec, + cf.scope_rep_label(), ":\n" + }, "") - "const", - "static", - "volatile", - "raw", + /; if (cf.cf_type("loop")) + /; if (len (condition) > 0) + ;int tmps = string_to_int(condition) + ;eval_value(tok, ~tmps, out, mov, current, ~cf, {1, "bool", "", {}, {}}, true) + ;out`.csec = string_join( { + out`.csec, + "\ttest al, al\n", + "\tjnz ", cf.scope_start_label(), "\n", + "\tjmp ", cf.scope_end_label(), "\n" + }, "") + ;; else + ;out`.csec = string_join( { + out`.csec, + "\tjmp ", cf.scope_start_label(), "\n" + }, "") + ;/ + ;/ + ;/ - "extends", - "override", + ;out`.csec = string_join( { + out`.csec, + cf.scope_end_label(), ":\n" + }, "") - "asm" -} + /; if (cf.is_cf()) + ;out`.csec = string_join( { + out`.csec, + "\t", cf.parent`.scope_end_label(), ":\n" + }, "") + ;/ +;/ -;{}{}uint8 KEYTYPES = { - "uint8", - "uint16", - "uint32", - "uint64", - "uint", +/; compile_block (~{}Token tok, ~int cur, ~Module current, ~CompData out) + ;Scope root = {0, 0, 0, "", {}, false} + ;int max = find_closing(tok, cur) + ;bool m = false, returned = false + ;Type ret = NO_TYPE - "int8", - "int16", - "int32", - "int64", - "int", + /; loop (cur`++; cur` < max && !m) [cur`++] + /; if (tok`{cur`}.type_is(TOKEN.DEFWORD)) + ;root.name = tok`{cur`}.data + ;; if (tok`{cur`}.type_is(TOKEN.KEYWORD)) + /; if (tok`{cur`}.cmp("raw")) + ;root.r = true + ;; else if (tok`{cur`}.cmp("method")) + ;m = true + ;current = current`.find_sub(tok`{cur` + 1}.data) + ;; else + ;log_err(string_join( { + "Keyword ", tok`{cur`}.data, " not impl on mod level blocks" + }, "")) + ;/ + ;; if (tok`{cur`}.cmp("(")) + ;root.vars = parse_param_list(tok, cur, current) + ;; if (tok`{cur`}.cmp("[")) + ;cur`++ + ;ret = get_type(tok, cur, current) + ;; if (tok`{cur`}.cmp("\n")) + ;break + ;/ + ;/ - "float32", - "float64", - "float", + /; if (len (current`.name) > 2) + /; if (current`.name{0} == '_' && current`.name{1} == '#') + ;{}{}uint8 split = string_split(current`.name, '#') + ;Type st = current`.find_type( {split{1}} )` + ;st.ptr_chain = {PTYPE.REFERENCE} + ;root.vars.append({"self", st, 0, 0}) + ;/ + ;/ - "comp32", - "comp64", - "comp", + /; if (!m) + ;{}uint8 l = "" + /; if (!string_equate(current`.name, "")) + ;l = string_add(l, current`.full_path()) + ;l.append('.') + ;/ + ;l = string_add(l, root.name) + ;root.name = l - "vect", - "bool", + /; if (current`.exp) + ;out`.hsec = string_add(out`.hsec, "global ") + ;out`.hsec = string_add(out`.hsec, l) + ;out`.hsec.append('\n') + ;/ + ;out`.csec = string_add(out`.csec, l) + ;out`.csec = string_add(out`.csec, ":\n") + ;root.begin_scope(out) + ;/ - "type", - "void" -} + /; loop (cur` = next_non_nl(tok, cur` + 1); cur` < max && !returned) [cur` = next_non_nl(tok, cur` + 1)] + /; if (tok`{cur`}.cmp("/;") || tok`{cur`}.cmp(";;")) + ;log_debug("Block in block") + /; if (m) + ;compile_block(tok, cur, current, out) + ;; else + ;CompData mov = {"", "", ""}, tmp = {"", "", ""} + ;log_debug("PRE COMPUTATION OF BLOCK\n") + ;int tcr = cur` + ;_compile_block(tok, ~tcr, current, ~tmp, ~mov, ~root, ret) + ;out`.add(mov) + ;log_debug("POST COMPUTATION OF BLOCK") + ;_compile_block(tok, cur, current, out, ~tmp, ~root, ret) + ;/ -/; is_delimiter ({}uint8 str) [bool] - /; if (len str > 2 || len str < 1) - ;return false + /; if (tok`{cur`}.cmp(";;")) + ;cur` = cur` - 1 + ;/ + ;; else if (tok`{cur`}.type_is(TOKEN.KEYWORD)) + /; if (tok`{cur`}.cmp("return")) + ;cur`++ + ;eval_value(tok, cur, out, out, current, ~root, ret, true) + ;root.end_scope(out) + ;out`.csec = string_add(out`.csec, "\tret\n") + ;returned = true + ;; else if (tok`{cur`}.cmp("raw") && tok`{cur` + 1}.cmp("return")) + /; if (!(root.r)) + ;log_err("Unable to perform a raw return from a non-raw block.") + ;/ + ;cur` = cur` + 2 + ;eval_value(tok, cur, out, out, current, ~root, ret, true) + ;out`.csec = string_add(out`.csec, "\tret\n") + ;returned = true + ;; else if (tok`{cur`}.cmp("asm")) + ;cur`++ + ;out`.csec.append('\t') + ;out`.csec = string_add(out`.csec, unquote_str(tok`{cur`}.data)) + ;out`.csec.append('\n') + ;; else + ;log_err(string_add("Keyword not impl: ", tok`{cur`}.data)) + ;/ + ;; else if (is_definition(tok, cur, current)) + ;log_debug("Block def") + ;eval_def(tok, cur, out, out, current, ~root) + ;; else + ;log_debug("Block val") + ;eval_value(tok, cur, out, out, current, ~root, NO_TYPE, false) + ;/ ;/ + + ;cur` = max - /; if (len str == 2) - ;return string_contains(MULTI_PARENS, str{0}) && string_contains(MULTI_PARENS, str{1}) + /; if (!returned && !string_equate(ret.name, "")) + ;log_err("Block must return a value.") ;/ - ;return string_contains(PARENS, str{0}) -;/ - -/; is_separator ({}uint8 str) [bool] - /; if (len str < 1) - ;return false + /; if (!m && !returned) + ;root.end_scope(out) + ;out`.csec = string_add(out`.csec, "\tret\n") ;/ - ;return string_contains(SEPS, str{0}) ;/ -/; is_reserved ({}uint8 str) [bool] - /; if (len str < 1) - ;return false +# First pass on a module +# Generates structs, enums, and submodules +/; module_pass_one (~{}Token tok, ~int cur, ~Module current, Path f) + ;int max = find_closing(tok, cur) + ;Module new = {current, false, "", {}, {}, {}, {}} + /; loop (cur`++; cur` < len tok`) [cur`++] + /; if (tok`{cur`}.type_is(TOKEN.DEFWORD)) + ;new.name = tok`{cur`}.data + ;; else if (tok`{cur`}.cmp("export")) + ;new.exp = true + ;; else if (!(tok`{cur`}.cmp("module"))) + ;break + ;/ ;/ - ;return string_contains(RESERVED, str{0}) -;/ -/; is_augment ({}uint8 str) [bool] - /; if (len str == 1) - ;return string_contains(AUGMENTS, str{0}) + /; loop (cur` < max) [cur`++] + ;log_vis(".") + /; if (tok`{cur`}.cmp(":")) + ;log_debug("INCLUDE") + /; if (tok`{cur` + 2}.type_is(TOKEN.LITERAL)) + ;compile_file_pass_one(f.relative(unquote_str(tok`{cur` + 2}.data)), ~new) + ;cur` = cur` + 2 + ;/ + ;continue + ;; else if (tok`{cur`}.cmp("/;") || tok`{cur`}.cmp(";;")) + /; if (tok`{cur` + 1}.cmp("export") || tok`{cur` + 1}.cmp("module")) + ;module_pass_one(tok, cur, ~new, f) + ;/ + ;; else if (tok`{cur`}.cmp("struct")) + ;new_type(tok, cur, ~new) + ;/ ;/ - - ;return list_contains(MULTI_AUGMENTS, str) + ;current`.sub.append(new) ;/ -/; is_str_literal ({}uint8 str) [bool] - /; if (string_equate(str, "\"") || string_equate(str, "'")) - ;return true - ;/ - - /; if (len str < 2) - ;return false - ;; else if (str{0} !== '\'' && str{0} !== '"') - ;return false +# Second pass on a module +# Generates code and calls compile_file_second_pass if an include happens +/; module_pass_two (~{}Token tok, ~int cur, ~Module current, ~CompData out, Path f) + ;int max = find_closing(tok, cur) + /; loop (cur`++; cur` < len tok`) [cur`++] + /; if (tok`{cur`}.type_is(TOKEN.DEFWORD)) + ;current = current`.find_sub(tok`{cur`}.data) + ;; else if (!(tok`{cur`}.cmp("module")) && !(tok`{cur`}.cmp("export"))) + ;break + ;/ ;/ - /; loop (int i = 1; i < len str) [i++] - /; if (str{i} == '\\') - ;i++ - ;; else if (str{i} == str{0}) - ;return i == len str - 1 + /; loop (cur` = next_non_nl(tok, cur`); cur` < max) [cur` = next_non_nl(tok, cur` + 1)] + ;log_vis(".") + /; if (tok`{cur`}.cmp(":")) + ;log_debug("INCLUDE") + /; if (tok`{cur` + 2}.type_is(TOKEN.LITERAL)) + ;CompData tmp = compile_file_pass_two(f.relative(unquote_str(tok`{cur` + 2}.data)), current) + ;out`.hsec = string_add(out`.hsec, tmp.hsec) + ;out`.dsec = string_add(out`.dsec, tmp.dsec) + ;out`.csec = string_add(out`.csec, tmp.csec) + ;cur` = cur` + 2 + ;/ + ;continue + ;; else if (tok`{cur`}.cmp("/;") || tok`{cur`}.cmp(";;")) + ;log_debug("Mod block") + /; if (tok`{cur` + 1}.cmp("export") || tok`{cur` + 1}.cmp("module")) + ;module_pass_two(tok, cur, current, out, f) + ;; else + ;compile_block(tok, cur, current, out) + ;/ + ;; else if (tok`{cur`}.cmp("struct")) + ;log_debug("Mod struct") + ;skip_struct(tok, cur) + ;; else if (tok`{cur`}.cmp("enum")) + ;log_debug("Mod enum") + ;compile_enum(tok, cur, current, out) + ;; else if (is_definition(tok, cur, current)) + ;log_debug("Mod def") + ;compile_file_def(tok, cur, current, out) + ;; else if (!(tok`{cur`}.cmp("\n"))) + ;log_err(string_add("Failed to recognize file-level statement ", tok`{cur`}.sprint())) ;/ ;/ - ;return true ;/ -/; is_num_literal ({}uint8 str) [bool] - /; if (len str < 1) - ;return false - ;; if (len str == 1 && str{0} == '.') - ;return false - ;/ +# First compiler pass on a file +# Only creates structs, enums, and moduless +/; compile_file_pass_one (Path f, ~Module current) + ;{}Token tok = tokenize(f) + ;log_info(string_add("Number of tokens generated: ", int_to_string(len tok))) - ;bool dec = false - /; loop (int i = 0; i < len str) [i++] - /; if (str{i} == '.') - /; if (!dec) - ;dec = true - ;; else - ;return false + /; loop (int i = 0; i < len tok) [i++] + ;log_vis(".") + /; if (tok{i}.cmp(":")) + ;log_debug("INCLUDE") + /; if (tok{i + 2}.type_is(TOKEN.LITERAL)) + ;CompData tmp = compile_file_pass_one(f.relative(unquote_str(tok{i + 2}.data)), current) + ;i = i + 2 ;/ - ;; else if (str{i} < '0' || str{i} > '9') - ;return false + ;continue + ;; else if (tok{i}.cmp("/;") || tok{i}.cmp(";;")) + /; if (tok{i + 1}.cmp("export") || tok{i + 1}.cmp("module")) + ;module_pass_one(~tok, ~i, current, f) + ;/ + ;; else if (tok{i}.cmp("struct")) + ;new_type(~tok, ~i, current) ;/ ;/ - ;return true -;/ - -/; is_literal({}uint8 str) [bool] - ;return is_str_literal(str) || is_num_literal(str) || string_equate(str, "true") || string_equate(str, "false") ;/ -/; gen_type (Token t) [int] - /; if (is_separator(t.data)) - ;return TOKEN.SEPARATOR - ;/ - - /; if (is_literal(t.data)) - ;return TOKEN.LITERAL - ;/ +/; size_struct (~Type t, ~Module m) + ;int s = 0 - /; if (is_reserved(t.data)) - /; if (is_delimiter(t.data)) - ;return TOKEN.DELIMITER - ;; else if (is_augment(t.data)) - ;return TOKEN.AUGMENT + /; loop (int i = 0; i < len (t`.members)) [i++] + ;int p = is_primitive(t`.members{i}.data_type.name) + /; if (len (t`.members{i}.data_type.ptr_chain) > 0) + ;s = s + 8 + ;; else if (p >== 0) + ;s = s + p + ;; else + ;log_debug("STRUCT!!!!!!") + ;{}{}uint8 artifact = { t`.members{i}.data_type.name } + ;~Type tp = m`.find_type(artifact) + /; if (tp`.s == 0) + ;size_struct(tp, m) + ;/ + ;t`.members{i}.data_type = tp` + ;s = s + tp`.s ;/ - ;; else if (list_contains(KEYWORDS, t.data)) - ;return TOKEN.KEYWORD - ;; else if (list_contains(KEYTYPES, t.data)) - ;return TOKEN.KEYTYPE ;/ - - ;return TOKEN.DEFWORD + ;log_debug(string_add("Sized type ", t`.name)) + ;t`.s = s ;/ -/; break_token (Token current, uint8 to_append) [bool] - /; if (is_literal(current.data)) - ;current.data.append(to_append) - ;return !(is_literal(current.data)) - ;/ - - /; if (is_whitespace(to_append) || current.cmp("\n")) - ;return true +# Regenerates struct sizes (with support for cyclical struct definitions) +/; flush_structs (~Module m) + + /; loop (int i = 0; i < len (m`.types)) [i++] + ;size_struct(~(m`.types{i}), m) ;/ - /; if (is_reserved(current.data)) - /; if (is_reserved({to_append})) - ;current.data.append(to_append) - ;return gen_type(current) == TOKEN.DEFWORD - ;/ - ;return true - ;; else if (is_reserved({to_append})) - ;return true + /; loop (int i = 0; i < len (m`.sub)) [i++] + ;flush_structs(~(m`.sub{i})) ;/ - - ;return false ;/ -/; handle_comment (tnsl.io.File fd, ~Token current, ~int line) [bool] - ;bool block = false - /; if (current`.cmp("/")) - ;block = true - ;/ +# Second pass of compiler +# Does code generation, ignores structs and enums +/; compile_file_pass_two (Path f, ~Module current) [CompData] + ;CompData out = {"", "", ""} + ;{}Token tok = tokenize(f) - /; loop (int i = fd.read(); i !== -1) [i = fd.read()] - /; if (i == '\n') - ;line`++ - /; if (!block) - ;return true + /; loop (int i = next_non_nl(~tok, 0); i < len tok) [i = next_non_nl(~tok, i+1)] + ;log_vis(".") + /; if (tok{i}.cmp(":")) + ;log_debug("INCLUDE") + /; if (tok{i + 2}.type_is(TOKEN.LITERAL)) + ;CompData tmp = compile_file_pass_two(f.relative(unquote_str(tok{i + 2}.data)), current) + ;out.hsec = string_add(out.hsec, tmp.hsec) + ;out.dsec = string_add(out.dsec, tmp.dsec) + ;out.csec = string_add(out.csec, tmp.csec) + ;i = i + 2 ;/ - ;; else if (block && i == '#') - ;i = fd.read() - /; if (i == '/') - ;current` = {0, line, ""} - ;return false - ;; else if (i == ';' || i == ':') - ;current`.data.append(i) - ;return false + ;continue + ;; else if (tok{i}.cmp("/;") || tok{i}.cmp(";;")) + ;log_debug("Root block") + /; if (tok{i + 1}.cmp("export") || tok{i + 1}.cmp("module")) + ;module_pass_two(~tok, ~i, current, ~out, f) + ;; else + ;compile_block(~tok, ~i, current, ~out) ;/ - - /; loop (i !== '\n' && i !== -1) [i = fd.read()] ;/ - - ;line`++ + ;; else if (tok{i}.cmp("struct")) + ;log_debug("File struct") + ;skip_struct(~tok, ~i) + ;; else if (tok{i}.cmp("enum")) + ;log_debug("File enum") + ;compile_enum(~tok, ~i, current, ~out) + ;; else if (is_definition(~tok, ~i, current)) + ;log_debug("File def") + ;compile_file_def(~tok, ~i, current, ~out) + ;; else if (tok{i}.cmp("asm")) + ;log_debug("File asm") + /; if (len (out.csec) == 0 && len (out.dsec) == 0) + ;out.hsec = string_add(out.hsec, unquote_str(tok{i + 1}.data)) + ;out.hsec.append('\n') + ;; else + ;out.dsec = string_add(out.dsec, unquote_str(tok{i + 1}.data)) + ;out.dsec.append('\n') + ;/ + ;i++ + ;; else if (!(tok{i}.cmp("\n"))) + ;log_err(string_add("Failed to recognize file-level statement", tok{i}.sprint())) ;/ ;/ -;/ -/; tokenize (Path f) [{}Token] - ;{}Token out = {} + ;log_info(string_add("File compiled! Generated code length: ", int_to_string(len (out.hsec) + len (out.dsec) + len (out.csec)))) - ;tnsl.io.File fd = f.open_read() - - ;Token current = {0, 0, ""} - ;int line = 1 - /; loop (int i = fd.read(); i > -1) [i = fd.read()] - /; if (i == '\r') - ;continue - ;/ + ;return out +;/ - /; if (i == '#' && (break_token(current, i) || gen_type(current) !== TOKEN.LITERAL)) - ;bool ln = handle_comment(fd, ~current, ~line) - /; if (ln) - ;current.tokenType = gen_type(current) - /; if (!(current.cmp(""))) - ;out.append(current) - ;/ - ;out.append({TOKEN.SEPARATOR, line - 1, "\n"}) - ;/ - ;continue - ;/ +# Starts the compiler on a given path +/; compile_start (Path f) [{}uint8] + ;{}uint8 out = "" - /; if (i == '\n' && (break_token(current, i) || gen_type(current) !== TOKEN.LITERAL)) - ;log_vis(".") - /; if (!(current.cmp("\n"))) - ;current.tokenType = gen_type(current) - /; if (!(current.cmp(""))) - ;out.append(current) - ;/ - ;current = {TOKEN.SEPARATOR, line, ""} - ;current.data.append(i) - ;/ - ;line++ - ;; else if (break_token(current, i)) - ;current.tokenType = gen_type(current) - /; if (!(current.cmp(""))) - ;out.append(current) - ;/ - ;current = {0, line, ""} - /; if (!(is_whitespace(i))) - ;current.data.append(i) - ;/ - ;; else - ;current.data.append(i) - ;/ - ;/ - ;log_vis("OK\n") + ;Module root = {0, true, {}, {}, {}, {}, {}} + ;compile_file_pass_one(f, ~root) + ;flush_structs(~root) + ;log_info("First pass DONE") - /; if (!(current.cmp("")) && !(current.cmp("\n"))) - ;current.tokenType = gen_type(current) - ;out.append(current) - ;/ + ;CompData data = compile_file_pass_two(f, ~root) + ;log_info("Second pass DONE") - ;fd.close() + ;out = string_join({ + data.hsec, + "section .data\n", + data.dsec, + "section .text\n", + data.csec}, "") ;return out ;/ -- cgit v1.2.3