diff options
Diffstat (limited to 'tnslc/compile.tnsl')
-rw-r--r-- | tnslc/compile.tnsl | 1503 |
1 files changed, 0 insertions, 1503 deletions
diff --git a/tnslc/compile.tnsl b/tnslc/compile.tnsl deleted file mode 100644 index 8bad758..0000000 --- a/tnslc/compile.tnsl +++ /dev/null @@ -1,1503 +0,0 @@ -## -## UTIL FUNCS -## - -/; string_split ({}uint8 str, uint8 split) [{}{}uint8] - /; if (len str == 0) - ;return {} - ;/ - - ;{}{}uint8 out = {} - - ;{}uint8 run = "" - - /; loop (int i = 0; i < len str) [i++] - /; if (str{i} == split) - ;out.append(run) - ;run = "" - ;; else - ;run.append(str{i}) - ;/ - ;/ - - ;out.append(run) - - ;return out -;/ - -/; string_join ({}{}uint8 strs, {}uint8 join) [{}uint8] - ;{}uint8 out = "" - /; loop (int i = 0; i < len strs) [i++] - ;out = string_add(out, strs{i}) - /; if (i !== len strs - 1) - ;out = string_add(out, join) - ;/ - ;/ - ;return out -;/ - -/; string_add ({}uint8 base, add) [{}uint8] - /; loop (int i = 0; i < len add) [i++] - ;base.append(add{i}) - ;/ - ;return base -;/ - -/; string_equate ({}uint8 a, b) [bool] - /; if (len a !== len b) - ;return false - ;/ - - /; loop (int i = 0; i < len a) [i++] - /; if (a{i} !== b{i}) - ;return false - ;/ - ;/ - - ;return true -;/ - -/; string_contains ({}uint8 str, uint8 chk) [bool] - /; loop (int i = 0; i < len str) [i++] - /; if (str{i} == chk) - ;return true - ;/ - ;/ - ;return false -;/ - -/; list_contains ({}{}uint8 list, {}uint8 str) [bool] - /; loop (int i = 0; i < len list) [i++] - /; if (string_equate(list{i}, str)) - ;return true - ;/ - ;/ - ;return false -;/ - -/; unqote_char ({}uint8 str) [uint8] - /; if (len str < 3) - ;return 0 - ;/ - - ;uint8 cmp = str{2} - /; if (cmp == '\\') - ;return '\\' - ;; else if (cmp == 'n') - ;return '\n' - ;; else if (cmp == 'r') - ;return '\r' - ;/ - -;/ - -/; unquote_str({}uint8 str) [{}uint8] - /; if (str{0} !== '\'' && str{0} !== '"') - ;return str - ;/ - ;{}uint8 out = "" - - /; loop (int i = 1; i < len str - 1) [i++] - /; if (str{i} == '\\') - ;{}uint8 unq = "'\\" - ;unq.append(str{i + 1}) - ;out.append(unqote_char(unq)) - ;i++ - ;; else - ;out.append(str{i}) - ;/ - ;/ - - ;return out -;/ - -/; int_to_string (int i) [{}uint8] - /; if (i == 0) - ;return "0" - ;/ - - ;{}uint8 out = "" - - /; if (i < 0) - ;out.append('-') - ;i = -i - ;/ - - /; loop [i = i / 10; i > 0] - ;out.append('0' + (i % 10)) - ;/ - - ;return out -;/ - -/; digit_from_base (uint8 ch, int base) [int] - /; if (ch == '-') - ;return 0 - ;/ - - /; if (base !> 10) - ;return ch - '0' - ;; if (base == 16) - /; if (ch !< 'A' && ch < 'G') - ;return 11 + (ch - 'A') - ;; else if (ch !< 'a' && ch < 'g') - ;return 11 + (ch - 'a') - ;/ - ;return ch - '0' - ;/ - ;return 0 -;/ - -/; string_to_int ({}uint8 str) [int] - /; if (len str < 1) - ;return 0 - ;/ - ;int i = 0 - ;bool inv = str{0} == '-' - /; if (inv) - ;i = 1 - ;/ - - ;int out = 0 - ;int base = 10 - - /; if (len str !< 3 && str{i} == '0') - /; if (str{i + 1} == 'x') - ;base = 16 - ;i = i + 2 - ;; if (str{i + 1} == 'b') - ;base = 2 - ;i = i + 2 - ;; if (str{i + 1} == 'o') - ;base = 8 - ;i = i + 2 - ;/ - ;/ - - /; loop (i < len str) [i++] - ;out = out * base - ;out = out + digit_from_base(str{i}, base) - ;/ - - /; if (inv) - ;out = -out - ;/ - ;return out -;/ - -## -## Structs -## - -# The seperated string sections that make up an asm file -;struct CompData { - {}uint8 - hsec, - dsec, - csec -} - -# Represents a relative file path -;struct Path { - {}{}uint8 path, - {}uint8 name -} - -/; method Path - - /; relative ({}uint8 rel_path) [Path] - ;Path out = self - ;{}{}uint8 rel_split = string_split(rel_path, '/') - - /; loop (int i = 0; i < len rel_split - 1) - ;out.path.append(rel_split{i}) - ;/ - - ;out.name = rel_split{len rel_split - 1} - - ;return out - ;/ - - /; full_path [{}uint8] - ;{}uint8 out = string_join(self.path, "/") - /; if (len out > 0) - ;out.append('/') - ;/ - ;return string_add(out, self.name) - ;/ - - /; extension [{}uint8] - ;{}{}uint8 split_name = string_split(self.name, '.') - - /; if (len split_name > 1) - ;return split_name{len split_name - 1} - ;/ - - ;return "" - ;/ - - /; open_read [tnsl.io.File] - ;return tnsl.io.readFile(self.full_path()) - ;/ - - /; write ({}uint8 bytes) - ;tnsl.io.File out = tnsl.io.writeFile(self.full_path()) - - /; loop (int i = 0; i < len bytes) [i++] - ;out.write(bytes{i}) - ;/ - - ;out.close() - ;/ -;/ - -# Represents the different classes of token -;enum TOKEN [int] { - SEPARATOR = 0, - DELIMITER = 1, - AUGMENT = 2, - KEYTYPE = 3, - KEYWORD = 4, - LITERAL = 5, - DEFWORD = 6 -} - -# Represents a single token in a TNSL file -;struct Token { - int - tokenType, - line, - - {}uint8 data -} - -/; method Token - - /; type_is (int a) [bool] - ;return self.tokenType == a - ;/ - - /; cmp ({}uint8 str) [bool] - ;return string_equate(self.data, str) - ;/ - - /; print - ;tnsl.io.print(self.data) - ;tnsl.io.print(": { type: ") - ;tnsl.io.print(self.tokenType) - ;tnsl.io.print(" line: ") - ;tnsl.io.print(self.line) - ;tnsl.io.print(" }") - ;/ - - /; sprint [{}uint8] - ;{}uint8 out = "{ " - ;out = string_add(out, self.data) - ;out.append(' ') - ;out = string_add(out, int_to_string(self.tokenType)) - ;out.append(' ') - ;out.append('}') - ;return out - ;/ -;/ - -# General defs: -## Type defs -## Function defs -## Method defs -## Module defs -## Constant and variable defs - -# Module -## General defs - -# Block -## Variable defs -## Control flow defs -## Value defs - -;enum PTYPE [int] { - POINTER = 0, - REFERENCE = 1, - ARRAY = 2 -} - -# Represents a data type -;struct Type { - int s, - {}uint8 - name, - mod_name, - {}int - ptr_chain, - {}Variable - members -} - -;{}{}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, "", "", {}, {}} - -/; 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 -;/ - -# Represents the place in memory where a variable is -;enum LOCATION [int] { - REGISTER = 0, - STACK = 1, - LABEL = 2, - LITERAL = 3 -} - -# Represents a variable -;struct Variable { - {}uint8 - name, - Type - data_type, - int - location, - loc_type -} - -# 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 + 2) -;/ - -# Get common register by common name and size -/; reg_by_name_size ({}uint8 common, uint sz) [{}uint8] - ;{}uint8 out = "%" - - /; if (common{0} !< 'a') - - /; 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') - ;/ - - ;string_add(out, common) - - ;; else - - ;out.append('r') - ;string_add(out, common) - /; if (sz == 1) - ;out.append('b') - ;; else if (sz == 2) - ;out.append('w') - ;; else if (sz == 4) - ;out.append('d') - ;/ - ;return out - ;/ - - ;return out -;/ - -/; get_reg (int r, sz) [{}uint8] - ;return reg_by_name_size(reg_by_num(r), sz) -;/ - -# Most methods make use of one or more temporary variables. -# These are denoted by tr -/; method Variable - - /; norm_loc (int sz) [{}uint8] - /; if (self.loc_type == LOCATION.LABEL) - ;return "" - ;; else if (self.loc_type == LOCATION.REGISTER) - ;return get_reg(self.location, sz) - ;; else if (self.loc_type == LOCATION.STACK) - ;return string_join( { "[ rsp + ", int_to_string(self.location), " ]" } , "") - ;/ - ;/ - - /; norm_size [int] - /; if (len (self.data_type.ptr_chain) > 0) - ;return 8 - ;; else - ;return self.data_type.s - ;/ - ;/ - - /; norm_op ({}uint8 op, {}{}uint8 args) [{}uint8] - ;return string_join( - { - "\t", op, " ", - string_join(args, ", "), "\n" - }, - "" - ) - ;/ - - # functions that do work on this variable - /; add (Variable v, int tr) [{}uint8] - /; if (self.loc_type == LOCATION.LITERAL) - /; if (v.loc_type !== LOCATION.LITERAL) - ;return v.add(self) - ;/ - ;self.location = self.location + v.location - ;return "" - ;; if (self.loc_type == LOCATION.STACK && v.loc_type == LOCATION.STACK) - ;{}uint8 tmp = get_reg(tr, self.norm_size()) - ;{}uint8 out = self.norm_op("mov", { tmp, v.norm_loc(self.norm_size()) }) - ;return string_add(out, self.norm_op("add", { self.norm_loc(self.norm_size()), tmp })) - ;/ - ;return self.norm_op("add", { self.norm_loc(self.norm_size()), get_reg(tr, self.norm_size()) }) - ;/ - - /; sub (Variable v) - /; if (self.loc_type == LOCATION.LITERAL) - /; if (v.loc_type !== LOCATION.LITERAL) - ;return v.add(self) - ;/ - ;self.location = self.location - v.location - ;return "" - ;; if (self.loc_type == LOCATION.STACK && v.loc_type == LOCATION.STACK) - ;{}uint8 tmp = get_reg(tr, self.norm_size()) - ;{}uint8 out = self.norm_op("mov", { tmp, v.norm_loc(self.norm_size()) }) - ;return string_add(out, self.norm_op("sub", { self.norm_loc(self.norm_size()), tmp })) - ;/ - ;return self.norm_op("sub", { self.norm_loc(self.norm_size()), get_reg(tr, self.norm_size()) }) - ;/ - - /; div (Variable v) - /; if (self.loc_type == LOCATION.LITERAL) - /; if (v.loc_type !== LOCATION.LITERAL) - ;return v.div(self) - ;/ - ;self.location = self.location + v.location - ;return "" - ;; if (self.loc_type == LOCATION.STACK && v.loc_type == LOCATION.STACK) - ;{}uint8 out = "" - # TODO - ;return out - ;/ - ;return self.norm_op("div", { self.norm_loc(self.norm_size()), v.norm_loc(self.norm_size) }) - ;/ - - /; mul (Variable v) - /; if (self.loc_type == LOCATION.LITERAL) - /; if (v.loc_type !== LOCATION.LITERAL) - ;return v.mul(self) - ;/ - ;self.location = self.location * v.location - ;return "" - ;; if (self.loc_type == LOCATION.STACK && v.loc_type == LOCATION.STACK) - ;{}uint8 out = "" - # TODO - ;return out - ;/ - ;return self.norm_op("mul", { self.norm_loc(self.norm_size()), v.norm_loc(self.norm_size) }) - ;/ - - /; set (Variable v) - /; if (self.loc_type == LOCATION.LITERAL) - /; if (v.loc_type !== LOCATION.LITERAL) - ;return v.set(self) - ;/ - ;self.location = v.location - ;return "" - ;; if (self.loc_type == LOCATION.STACK && v.loc_type == LOCATION.STACK) - ;{}uint8 out = "" - # TODO - ;return out - ;/ - ;return self.norm_op("mov", { self.norm_loc(self.norm_size()), v.norm_loc(self.norm_size) }) - ;/ - - # functions that do work on another variable - /; ref (Variable out) - ;/ - - /; deref (Variable out) - ;/ - - /; member (Variable out, {}uint8 name) - ;/ - - /; index (Variable out, Variable i) - /; - - ;/ - ;/ - - /; call (Variable out, {}uint8 name) - ;/ -;/ - -;struct Scope { - {}Variable vars -} - -;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 (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) - ;/ - ;/ - ;/ - - /; loop (int i = 0; i < len (self.types)) [i++] - /; if (string_equate(self.types{i}.name, artifact{r})) - ;return ~(self.types{i}) - ;/ - ;/ - - ;Type nt = {0, artifact{len artifact - 1}, "", {}, {}} - ;return ~nt - ;/ - - # Consumer facing function - /; find_type ({}{}uint8 artifact) [~Type] - ;int p = is_primitive(artifact{0}) - /; if (p !< 0) - ;Type out = {p, artifact{0}, {}, {}, {}} - ;return ~out - ;/ - - ;return self._find_type(artifact, 0) - ;/ - - /; _find_def ({}{}uint8 artifact, int r) [Variable] - /; if (len artifact !> r) - ;retirn {{}, "", 0, 0, 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._find_type(artifact, r + 1) - ;/ - ;/ - ;/ - - /; loop (int i = 0; i < len (self.defs)) [i++] - /; if (string_equate(self.defs{i}.name, artifact{r})) - ;return self.defs{i} - ;/ - ;/ - - ;return {{}, "", 0, 0, 0} - ;/ - - /; find_def ({}{}uint8 artifact) [Variable] - ;return _find_def(artifact, 0) - ;/ - - /; _find_function ({}{}uint8 artifact, int r) [Variable] - /; if (len artifact !> r) - ;retirn {{}, "", 0, 0, 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._find_type(artifact, r + 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} - ;/ - - /; find_function ({}{}uint8 artifact) [Variable] - ;return _find_function(artifact, 0) - ;/ - - /; 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 - ;/ -;/ - -## -## 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`++ - ;/ - ;/ - ;return out -;/ - -/; get_type (~{}Token tok, ~int cur, ~Module current) [Type] - ;{}int ptr_chain = {} - - /; 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 - ;/ - - ;{}Type generics = {} - /; if (tok`{cur`}.cmp("(")) - ;int max = find_closing(tok, cur) - ;cur`++ - /; loop (cur` < max) [cur`++] - ;generics.append(get_type(tok, cur, current)) - ;/ - ;/ - - # TODO: References - - ;out.ptr_chain = ptr_chain - ;return out -;/ - -/; is_definition (~{}Token tok, ~int cur) [bool] - ;return false -;/ - -/; compile_file_def (~{}Token tok, ~int cur, Type t, ~Module current) [{}Variable] - ;return {} -;/ - -/; next_non_nl (~{}Token tok, int c) [int] - /; loop (tok`{c}.cmp("\n")) [c++] ;/ - ;return c -;/ - -/; parse_param_list (~{}Token tok, ~int cur, ~Module current) [{}Variable] - ;{}Variable 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`++ - ;/ - ;; else - ;t = get_type(tok, cur, current) - ;cur` = cur` - 1 - ;/ - ;/ - ;return out -;/ - -# Generates new type -/; new_type (~{}Token tok, ~int cur, ~Module current) - ;cur`++ - ;Type out = {0, tok`{cur`}.data, "", {}, {}} - ;out.mod_name = string_add(current`.full_path(), "_#") - ;out.mod_name = string_add(out.mod_name, out.name) - ;current`.sub.append({current, current`.exp, out.mod_name, {}, {}, {}, {}}) - - /; loop (cur` < len tok`) [cur`++] - /; if (tok`{cur`}.cmp("{")) - ;break - ;/ - ;/ - - ;out.members = parse_param_list(tok, cur, current) - /; loop (int i = 0; i < len (out.members)) [i++] - ;tnsl.io.print(string_join({"[", out.members{i}.name, ":", out.members{i}.data_type.name, "]"}, "")) - ;/ - - ;tnsl.io.print(string_add("Generated type ", string_add(out.name, string_add(":", out.mod_name)))) - ;current`.types.append(out) -;/ - -/; decompose_empty (~Module current, Type t) [{}uint8] - ;return "" -;/ - -# Used to take an array literal and make it into a label -/; decompose_array (~{}Token tok, ~int cur, ~Module current, Type t) [{}uint8] - ;int max = find_closing(tok, cur) - ;{}uint8 arr = "" - ;int alen = 0 - - /; loop (cur`++; cur` < max) [cur`++] - ;alen++ - - /; if (tok`{cur`}.cmp("{")) - /; if (ptr_chain{0} == PTYPE.ARRAY) - ;{}int ptr = {} - /; loop (int i = 1; i < len (t.ptr_chain)) [i++] - ;ptr.append(t.ptr_chain{i}) - ;/ - ;t.ptr_chain = ptr - ;arr = string_add(arr, decompose_array(tok, cur, current, t)) - ;cur`++ - ;; else - ;decompose_struct(tok, cur, current, t) - ;cur`++ - ;/ - ;; else - ;arr = string_add(arr, decompose_data(tok, cur, current, t)) - ;cur`++ - ;/ - ;/ - - ;{}uint out = string_join( { "\tdq ", int_to_string(alen), "\n", arr, "\n" }, "") - - ;return out -;/ - -# Used to take a struct literal and make it into a label -/; decompose_struct (~{}Token tok, ~int cur, ~Module current, Type t) [{}uint8] - ;int max = find_closing(tok, cur) - ;{}uint8 out = "" - ;int m = 0 - /; loop (cur`++; cur` < max) [cur`++] - /; if (tok`{cur`}.cmp("}")) - ;break - ;; else if (tok`{cur`}.cmp(",")) - ;cur`++ - ;/ - ;out = string_add(out, decompose_data(tok, cur, current, t.members{m}.data_type)) - ;m++ - ;/ - - /; if (m < len (t.members) - 1) - /; loop (m < len (t.members)) [m++] - ;out = string_add(out, decompose_empty(current, t.members{m})) - ;/ - ;/ - - ;return out -;/ - -/; declare_size(int sz) [{}uint8] - ;{}uint8 out = "\tdb " - - /; if (sz == 2) - ;out{2} = 'w' - ;; if (sz == 4) - ;out{2} = 'd' - ;; if (sz == 8) - ;out{2} = 'q' - ;/ - - ;return out -;/ - -# Used to take data from a literal and make it into a label -/; decompose_data (~{}Token tok, ~int cur, ~Module current, Type t) [{}uint8] - /; if (tok`{cur`}.cmp("{")) - /; if (len (t.ptr_chain) > 0) - ;{}int ptr = {} - /; loop (int i = 1; i < len (t.ptr_chain)) [i++] - ;ptr.append(t.ptr_chain{i}) - ;/ - ;t.ptr_chain = ptr - ;return decompose_array(tok, cur, current, t) - ;; else - ;return decompose_struct(tok, cur, current, t) - ;/ - ;; if (tok`{cur`}.type_is(TOKEN.LITERAL)) - /; 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(current, t) -;/ - -# Compiles new enum for the file -/; compile_enum (~{}Token tok, ~int cur, ~Module current) [{}uint8] - ;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`++ - ;/ - ;/ - - /; if (string_equate(et.name, "")) - ;et = Primitives{3} - ;/ - - /; loop (!(tok`{cur`}.cmp("{"))) [cur`++] ;/ - ;cur`++ - - ;Module enum_mod = {current, current`.exp, string_add("__#", name), {}, {}, {}, {}} - - ;{}uint8 out = "" - - /; loop (cur` < len tok`) [cur`++] - /; if (tok`{cur`}.cmp("}")) - ;break - ;/ - - /; if (tok`{cur`}.type_is(TOKEN.DEFWORD)) - ;{}uint8 l = string_add(enum_mod.full_path(), ".") - ;l = string_add(l, tok`{cur`}.data) - ;l.append(':') - ;l.append('\n') - ;cur` = cur` + 2 - ;l = string_add(l, decompose_data(tok, cur, current, et)) - ;out = string_add(out, l) - ;/ - ;/ - - ;current`.sub.append(enum_mod) - - ;return out -;/ - -# Generates opposite closing bracket -/; closing_for (Token d) [{}uint8] - /; if (d.cmp("(")) - ;return ")" - ;; else if (d.cmp("[")) - ;return "]" - ;; else if (d.cmp("{")) - ;return "}" - ;/ - ;tnsl.io.println(string_add("Error, unrecognized delim: ", d)) -;/ - -# 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 - ;/ - ;/ - - /; if (tok`{i}.cmp("(")) - ;p++ - ;; else if (tok`{i}.cmp("[")) - ;br++ - ;; else if (tok`{i}.cmp("{")) - ;c++ - ;; else if (tok`{i}.cmp("/;")) - ;bl++ - ;/ - - /; 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 len tok` - 1 -;/ - -# Skips cur to the end of a struct -/; skip_struct (~{}Token tok, ~int cur) - ;{}uint8 name = tok`{cur` + 1}.data - /; loop (cur` < len tok`) [cur`++] - /; if (tok`{cur`}.cmp("{")) - ;cur` = find_closing(tok, cur) - ;break - ;/ - ;/ -;/ - -# TODO: -/; compile_function (~{}Token tok, ~int cur, ~CompData out, ~Module current, ~Scope scope) [Function] - -;/ - -# TODO: -/; compile_method (~{}Token tok, ~int cur, ~CompData out, ~Module current, ~Scope scope) [Function] - -;/ - -# First pass on a module -# Generates structs, enums, and submodules -/; module_pass_one (~{}Token tok, ~int cur, ~Module current) - -;/ - -# 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) - -;/ - -# First compiler pass on a file -# Only creates structs, enums, and moduless -/; compile_file_pass_one (Path f, ~Module current) - ;{}Token tok = tokenize(f) - - ;tnsl.io.print("Number of tokens generated: ") - ;tnsl.io.println(len tok) - - /; loop (int i = 0; i < len tok) [i++] - ;tnsl.io.print(".") - /; if (tok{i}.cmp(":")) - ;tnsl.io.println("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) - ;/ - ;; else if (tok{i}.cmp("struct")) - ;new_type(~tok, ~i, current) - ;/ - ;/ -;/ - -/; size_struct (~Type t, ~Module m) - ;int s = 0 - /; 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 - ;~Type tp = m`.find_type(t`.members{i}.data_type.name) - /; if (tp`.s == 0) - ;size_struct(tp, m) - ;/ - ;t`.members{i}.data_type = tp` - ;s = s + tp`.s - ;/ - ;/ - ;tnsl.io.println(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) - ;/ - - /; loop (int i = 0; i < len (m`.sub)) [i++] - ;flush_structs(~(m`.sub{i})) - ;/ -;/ - -# 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 = 0; i < len tok) [i++] - ;tnsl.io.print(".") - /; if (tok{i}.cmp(":")) - ;tnsl.io.println("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(";;")) - ;tnsl.io.print("block") - /; if (tok{i + 1}.cmp("export") || tok{i + 1}.cmp("module")) - ;module_pass_two(~tok, ~i, current) - ;/ - ;; else if (tok{i}.cmp("struct")) - ;tnsl.io.print("struct") - ;skip_struct(~tok, ~i) - ;; else if (tok{i}.cmp("enum")) - ;tnsl.io.print("enum") - ;out.dsec = string_add(out.dsec, compile_enum(~tok, ~i, current)) - ;; else if (is_definition(~tok, ~i)) - ;tnsl.io.print("def") - ;Type t = get_type(~tok, ~i, current) - ;out.dsec = string_add(out.dsec, compile_file_def(~tok, ~i, t, current)) - ;; else if (!(tok{i}.cmp("\n"))) - ;tnsl.io.println("Failed to recognize file-level statement") - ;tok{i}.print() - ;break - ;/ - ;/ - - ;tnsl.io.print("Generated code length: ") - ;tnsl.io.println(len (out.hsec) + len (out.dsec) + len (out.csec)) - - ;return out -;/ - -# Starts the compiler on a given path -/; compile_start (Path f) [{}uint8] - ;{}uint8 out = "" - - ;Module root = {0, true, {}, {}, {}, {}, {}} - ;compile_file_pass_one(f, ~root) - ;flush_structs(~root) - ;tnsl.io.println("First pass DONE") - - ;CompData data = compile_file_pass_two(f, ~root) - ;tnsl.io.println("Second pass DONE") - - ;out = string_join({ - data.hsec, - "section .data\n", - data.dsec, - "section .text\n", - data.csec}, "") - - ;return out -;/ - -## -## Tokenizer funcs -## - - -/; is_whitespace (uint8 c) [bool] - ;return (c == '\n' || c == '\t' || c == ' ') -;/ - -;{}uint8 MULTI_PARENS = "/;:#" -;{}uint8 PARENS = "()[]{}" -;{}uint8 RESERVED = "`~!%^&*()-+=[]{}|;:/?<>.," -;{}uint8 AUGMENTS = "=~!<>&|^+-*/`." - -;{}{}uint8 MULTI_AUGMENTS = { - "~=", "`=", "%=", "^=", "&=", "*=", - "!=", "|=", "/=", - - "==", "!==", "&&", "||", "^^", "<==", ">==", "!>", "!<", - - "<<", ">>", "!&", "!|", "!^" -} - - -;{}{}uint8 KEYWORDS = { - "len", - "is", - - "if", - "else", - "loop", - "continue", - "break", - - "return", - - "method", - "struct", - "enum", - "interface", - - "export", - "module", - - "const", - "static", - "volatile", - - "extends", - "override" -} - -;{}{}uint8 KEYTYPES = { - "uint8", - "uint16", - "uint32", - "uint64", - "uint", - - "int8", - "int16", - "int32", - "int64", - "int", - - "float32", - "float64", - "float", - - "comp32", - "comp64", - "comp", - - "vect", - "bool", - - "type", - "void" -} - -/; is_delimiter ({}uint8 str) [bool] - /; if (len str > 2 || len str < 1) - ;return false - ;/ - - /; if (len str == 2) - ;return string_contains(MULTI_PARENS, str{0}) && string_contains(MULTI_PARENS, str{1}) - ;/ - - ;return string_contains(PARENS, str{0}) -;/ - -/; is_reserved ({}uint8 str) [bool] - /; if (len str < 1) - ;return false - ;/ - ;return string_contains(RESERVED, str{0}) -;/ - -/; is_augment ({}uint8 str) [bool] - /; if (len str == 1) - ;return string_contains(AUGMENTS, str{0}) - ;/ - - ;return list_contains(MULTI_AUGMENTS, str) -;/ - -/; 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 - ;/ - - /; 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 -;/ - -/; is_num_literal ({}uint8 str) [bool] - /; if (len str < 1) - ;return false - ;/ - - ;bool dec = false - /; loop (int i = 0; i < len str) [i++] - /; if (str{i} == '.') - /; if (!dec) - ;dec = true - ;; else - ;return false - ;/ - ;; else if (str{i} < '0' || str{i} > '9') - ;return false - ;/ - ;/ - ;return true -;/ - -/; is_literal({}uint8 str) [bool] - ;return is_str_literal(str) || is_num_literal(str) -;/ - -/; gen_type (Token t) [int] - /; if (t.cmp("\n") || t.cmp(",")) - ;return TOKEN.SEPARATOR - ;/ - - /; if (is_literal(t.data)) - ;return TOKEN.LITERAL - ;/ - - /; 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 - ;/ - - ;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)) - ;/ - - /; if (is_whitespace(to_append) || current.cmp("\n")) - ;return true - ;/ - - /; 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 - ;/ - - ;return false -;/ - -/; handle_comment (tnsl.io.File fd, ~Token current, ~int line) [bool] - ;bool block = false - /; if (current`.cmp("/")) - ;block = true - ;/ - - /; 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 - ;/ - - /; loop (i !== '\n' && i !== -1) [i = fd.read()] ;/ - - ;line`++ - ;/ - ;/ -;/ - -/; tokenize (Path f) [{}Token] - ;{}Token out = {} - - ;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 == '#' && (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 - ;/ - - /; if (i == '\n') - ;tnsl.io.print(".") - /; 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) - ;/ - ;/ - ;tnsl.io.println("OK") - - /; if (!(current.cmp("")) && !(current.cmp("\n"))) - ;current.tokenType = gen_type(current) - ;out.append(current) - ;/ - - ;fd.close() - - ;return out -;/ - -## -## Main -## - -/; main ({}{}uint8 args) [int] - /; if (len args < 1) - ;tnsl.io.println("Give me something to compile!") - ;return 1 - ;/ - - ;bool tokenize_only = len args > 1 - - ;{}{}uint8 fsplit = string_split(args{0}, '/') - ;Path p = {{}, fsplit{len fsplit - 1}} - - /; loop (int i = 0; i < len fsplit - 1) [i++] - ;p.path.append(fsplit{i}) - ;/ - - ;tnsl.io.print("Path: ") - ;tnsl.io.println(p.full_path()) - - ;{}uint8 code = "" - /; if (!tokenize_only) - ;code = compile_start(p) - ;; else - ;{}Token tok = tokenize(p) - /; loop(int i = 0; i < len tok) [i++] - ;tnsl.io.print(".") - ;code = string_add(code, tok{i}.sprint()) - ;/ - ;tnsl.io.println("OK") - ;/ - - ;p.name = string_add(p.name, ".asm") - - ;p.write(code) - - ;return 0 -;/ |