diff options
-rw-r--r-- | .gitignore | 3 | ||||
-rw-r--r-- | tnslc/README.md | 8 | ||||
-rw-r--r-- | tnslc/basic.tnsl | 8 | ||||
-rw-r--r-- | tnslc/compiler.tnsl | 272 | ||||
-rw-r--r-- | tnslc/compiler_structs.tnsl | 480 | ||||
-rw-r--r-- | tnslc/copy.tnsl | 39 | ||||
-rw-r--r-- | tnslc/else.tnsl | 19 | ||||
-rw-r--r-- | tnslc/enum.tnsl | 13 | ||||
-rw-r--r-- | tnslc/hello.tnsl | 33 | ||||
-rw-r--r-- | tnslc/logging.tnsl | 75 | ||||
-rw-r--r-- | tnslc/read_file_test.tnsl | 44 | ||||
-rw-r--r-- | tnslc/run.ps1 | 11 | ||||
-rwxr-xr-x | tnslc/run.sh | 25 | ||||
-rw-r--r-- | tnslc/simple.tnsl | 29 | ||||
-rw-r--r-- | tnslc/str_test.tnsl | 9 | ||||
-rw-r--r-- | tnslc/tnslc.tnsl | 4113 | ||||
-rw-r--r-- | tnslc/tnslc_wrapped.tnsl | 30 | ||||
-rw-r--r-- | tnslc/tokenizer.tnsl | 364 | ||||
-rw-r--r-- | tnslc/tokenizer_wrapped.tnsl | 35 | ||||
-rw-r--r-- | tnslc/utils.tnsl | 122 | ||||
-rw-r--r-- | tnslc/vector.tnsl | 100 | ||||
-rw-r--r-- | tnslc/vector_test.tnsl | 36 |
22 files changed, 17 insertions, 5851 deletions
@@ -1,4 +1,3 @@ -tint *.S *.asm *.o @@ -7,4 +6,4 @@ tint *.exe **/build/ - +ctc diff --git a/tnslc/README.md b/tnslc/README.md index e30130b..422214b 100644 --- a/tnslc/README.md +++ b/tnslc/README.md @@ -4,14 +4,12 @@ The reference compiler for the TNSL programming language. The compiler is writt ## Usage: -Place the interpreter `tint` in the parent folder and execute `run.sh` with the argument being the flags for the compiler. +Place the bootstrap compiler `ctc` in the folder and execute `run.sh` The compiler outputs x86 NASM compatible assembly. Examples: -- `./run.sh dummy.tnsl` - Run the compiler on the dummy file -- `./run.sh "dummy.tnsl ../libtnsl/libtnsl.tnsl"` - Run the compiler on the dummy file but also link libtnsl - -- `.\run.ps1 hello.tnsl`: Run the compiler on the sample "Hello World" program +- `./ctc dummy.tnsl dummy.asm` - Run the bootstrap compiler on the dummy file, output to dummy.asm +- `./run.sh` - Build the compiler ## License diff --git a/tnslc/basic.tnsl b/tnslc/basic.tnsl deleted file mode 100644 index a0cf385..0000000 --- a/tnslc/basic.tnsl +++ /dev/null @@ -1,8 +0,0 @@ -:include "c_wrap.tnsl" - -{}uint8 str = "ASDF\0" - -/; main [int] - _printf(~str{0}) - return 0 -;/
\ No newline at end of file diff --git a/tnslc/compiler.tnsl b/tnslc/compiler.tnsl deleted file mode 100644 index fd5cc15..0000000 --- a/tnslc/compiler.tnsl +++ /dev/null @@ -1,272 +0,0 @@ -############## -# TEXT UTILS # -############## - -{}uint8 e_tc_nl = "\n\0" -{}uint8 e_noquit = "[TNSLC] [UB] PRE-ALPHA VERSION OF COMPILER UNABLE TO EXIT! UNDEFINED BEHAVIOUR AHEAD\n\0" - -{}uint8 e_unknown_meta = "[TNSLC] [WARNING] Unknown meta character '%c'!\n\0" -/; parse_meta (~uint8 str, int idx) [uint8] - uint8 c = str{idx} - - /; if (c == 'n') - return '\n' - ;; else if (c == 'r') - return '\r' - ;; else if (c == '\\') - return '\\' - ;; else if (c == '"') - return '"' - ;; else if (c == '\'') - return '\'' - ;; else if (c == '0') - return 0 - ;/ - - _print_num(~e_unknown_meta{0}, c) - _printf(~e_noquit{0}) - return c -;/ - -/; unquote_char (~uint8 str) [uint8] - int l = cstr_len(str) - - /; if (l < 3) - return 0 - ;; else if (str{1} == '\\') - return parse_meta(str, 2) - ;/ - - return str{1} -;/ - -/; unquote_string (~uint8 str) [~uint8] - ~uint8 out = _alloc(1) - out{0} = 0 - - int ln = 0 - int l = cstr_len(str) - - /; loop (int i = 1; i < l - 1) [i++] - /; if (str{i} == '\\') - out{ln} = parse_meta(str, i + 1) - i++ - ;; else - out{ln} = str{i} - ;/ - - out = _realloc(out, ln + 2) - out{ln + 1} = 0 - ln++ - ;/ - - return out -;/ - -{}uint8 e_str_parse = "[TNSLC] [ERROR] Error when parsing int from string. %d\n\0" -/; str_to_int (~uint8 str) [int] - int out = 0 - int l = cstr_len(str) - - /; loop (int i = 0; i < l) [i++] - uint8 c = str{i} - /; if (c < '0' || c > '9') - _print_num(~e_str_parse{0}, c) - _printf(~e_noquit{0}) - break - ;; else - out = out * 10 - out = out + c - '0' - ;/ - ;/ - - return out -;/ - -{}uint8 w_method_guard = "_#\0" -{}uint8 w_enum_guard = "__#\0" - -#################### -# FIND/PARSE UTILS # -#################### - -# finds the closing delim in a vector of tokens -{}uint8 e_dmiss = "[TNSLC] [ERROR] Delimiter missmatch\n\0" -/; matching_delim (Vector v, int c) [int] - ~Token cur - cur = v.get(c) - uint8 op, first - first = cur`.data{0} - - /; if (first == '(') - op = ')' - ;; else if (first == '[') - op = ']' - ;; else if (first == '{') - op = '}' - ;; else - op = ';' - ;/ - - int p, b, s, f - p = 0 # Parens - b = 0 # Braces - s = 0 # Squiggly Braces - f = 0 # Funcs - - /; loop (c++; cur < v.num_el) [c++] - cur = v.get(c) - /; if (cur`._type !== TOKEN_TYPE.DELIMITER) - continue - ;/ - - first = cur`.data{0} - # Increments - /; if (first == '(') - p++ - continue - ;; else if (first == '[') - b++ - continue - ;; else if (first == '{') - s++ - continue - ;; else if (first == '/') - f++ - continue - ;/ - - # Check end - /; if (first == op) - /; if (p == 0 && b == 0 && s == 0 && f == 0) - return c - ;/ - ;/ - - # Decrement - /; if (first == ')') - p-- - ;; else if (first == ']') - b-- - ;; else if (first == '}') - s-- - ;; else if (first == ';') - first = cur`.data{1} - /; if (first == '/') - f-- - ;/ - ;/ - - # Mismatch - /; if (p < 0 || b < 0 || s < 0 || f < 0) - _printf(~e_dmiss{0}) - _printf(~e_noquit{0}) - ;/ - ;/ - - return 0 - 1 -;/ - -# Entrypoint for round two -/; round_two (Path in, ~Module m) [CompData] - CompData out - out.start() - return out -;/ - - -{}uint8 e_circular = "[TNSLC] [ERROR] Circular struct definition detected in structs:\n\0" -# Structure sizing for the first round -/; size_struct (~Type t, ~Module m) - /; if (t`.s !== 0) - return - ;/ - - t`.s = 0 - 1 - int s = 0 - - ~Variable mb - ~Module mbm - ~Type mbt - /; loop (int i = 0; i < t`.members.num_el) [i++] - mb = t`.members.get(i) - mbt = ~mb`.data_type - /; if (mbt`.ptr_chain.num_el > 0) - s = s + 8 - ;; else if (mbt`.s > 0) - s = s + mbt`.s - ;; else if (mbt`.s == 0) - Vector v - v.start(8) - v.push(~mbt`.name) - - mbm = mbt`.mod - ~Type tmp - tmp = mbm`._find_type(v, 0) - size_struct(tmp, mbm) - - mbt`.s = tmp`.s - s = s + tmp`.s - - v._del() - ;; else if (mbt`.s < 0) - _printf(~e_circular{0}) - - _printf(t`.name) - _printf(~e_tc_nl{0}) - - _printf(mbt`.name) - _printf(~e_tc_nl{0}) - - _printf(~e_noquit{0}) - ;/ - ;/ - - t`.s = s -;/ - -/; flush_structs (~Module m) - ~Type t - /; loop(int i = 0; i < m`.typ.num_el) [i++] - t = m`.typ.get(i) - size_struct(t, m) - ;/ - - ~Module s - /; loop(int i = 0; i < m`.sub.num_el) [i++] - s = m`.sub.get(i) - flush_structs(s) - ;/ -;/ - - -/; round_one_file (Path in, ~Module root) - ~uint8 pth = in.full_path() - Vector v = tokenize_file(pth) - _delete(pth) - - # round_one_tokens(in, v, root, 0, v.num_el) - - # Clean up tokens - ~Token t - /; loop (int i = 0; i < v.num_el) [i++] - t = v.get(i) - _delete(t`.data) - ;/ -;/ - - -/; compile (Path in, out) - Module root - root.start() - root.exp = true - -# round_one_file(in, ~root) -# flush_structs(root) -# CompData dat = round_two(in, ~root) - - ~void fd = out.open_write() - dat.write_file(fd) - _close_file(fd) -;/ - diff --git a/tnslc/compiler_structs.tnsl b/tnslc/compiler_structs.tnsl deleted file mode 100644 index 03ee9ce..0000000 --- a/tnslc/compiler_structs.tnsl +++ /dev/null @@ -1,480 +0,0 @@ -# Actual compilation of the vector of tokens, ported from the "dirty tnsl" -# that was originally written for the interpreter - -# CompData represents three vectors: -# hsec - the heading of the output assembly -# dsec - the data tied to the assembly -# csec - the .text section that is the code of the assembly - -struct CompData { - Vector - hsec, - dsec, - csec -} - -{}uint8 w_data_sec = "\n\nsection .data\n\n\0" -{}uint8 w_text_sec = "\n\nsection .text\n\n\0" - -/; method CompData - /; start - self.hsec.start(1) - self.dsec.start(1) - self.csec.start(1) - ;/ - - /; add (CompData c) - self.hsec.add(c.hsec) - self.dsec.add(c.dsec) - self.csec.add(c.csec) - ;/ - - /; _del - self.hsec._del() - self.dsec._del() - self.csec._del() - ;/ - - /; write_file(~void fd) - /; loop (int i = 0; i < self.hsec.num_el) [i++] - _write_byte(fd, self.hsec.get(i)) - ;/ - - write_to_file(fd, ~w_data_sec{0}) - - /; loop (int i = 0; i < self.dsec.num_el) [i++] - _write_byte(fd, self.dsec.get(i)) - ;/ - - write_to_file(fd, ~w_text_sec{0}) - - /; loop (int i = 0; i < self.csec.num_el) [i++] - _write_byte(fd, self.csec.get(i)) - ;/ - ;/ -;/ - -# Path represents the actual path of a file -# that we are trying to tokenize -# Assumes that the last item in the path array is a file name -struct Path { - int - path_count, - ~~uint8 - split_path -} - -/; method Path - /; start (~uint8 path) - self.split_path = _alloc(8) - self.path_count = 0 - self.relative_file(path) - ;/ - - /; copy [Path] - Path out - ~uint8 f_pth = self.full_path() - out.start(f_pth) - _delete(f_pth) - return out - ;/ - - /; relative_file(~uint8 rel_path) - # Assume the last string is the file name - /; if (self.path_count > 0) - int idx = self.path_count - 1 - _delete(self.split_path{idx}) - self.path_count-- - ;/ - - ~uint8 n_ptr = _alloc(1) - n_ptr{0} = 0 - int idx = self.path_count - - /; loop (int i = 0; i < cstr_len(rel_path)) [i++] - /; if (rel_path{i} == '\\' || rel_path{i} == '/') - /; if (cstr_len(n_ptr) > 0) - self.path_count++ - idx = self.path_count - self.split_path = _realloc(self.split_path, idx * 8) - self.split_path{idx - 1} = n_ptr - - n_ptr = _alloc(1) - n_ptr{0} = 0 - ;/ - ;; else - idx = cstr_len(n_ptr) - n_ptr = _realloc(n_ptr, idx + 2) - n_ptr{idx} = rel_path{i} - n_ptr{idx + 1} = 0 - ;/ - ;/ - - /; if (cstr_len(n_ptr) > 0) - self.path_count++ - idx = self.path_count - self.split_path = _realloc(self.split_path, idx * 8) - self.split_path{idx - 1} = n_ptr - ;/ - ;/ - - /; full_path [~uint8] - ~uint8 pth = _alloc(1) - pth{0} = 0 - - ~uint8 w_ptr = self.split_path{0} - - /; loop (int i = 0; i < self.path_count) [i++] - w_ptr = self.split_path{i} - int old_len = cstr_len(pth) - int new_len = old_len + cstr_len(w_ptr) - - pth = _realloc(pth, new_len + 1) - pth{new_len} = 0 - - - /; loop (int j = 0; j < cstr_len(w_ptr)) [j++] - pth{old_len + j} = w_ptr{j} - ;/ - - /; if (i < self.path_count - 1) - pth = _realloc(pth, new_len + 2) - pth{new_len} = '/' - pth{new_len + 1} = 0 - ;/ - ;/ - - return pth - ;/ - - /; open_read [~void] - ~uint8 path = self.full_path() - ~void out = _open_file(path) - _delete(path) - return out - ;/ - - /; open_write [~void] - ~uint8 path = self.full_path() - ~void out = _create_file(path) - _delete(path) - return out - ;/ - - /; print_all - /; loop (int i = 0; i < self.path_count) [i++] - _printf(self.split_path{i}) - ;/ - ;/ - - /; _del - /; loop (int i = 0; i < self.path_count) [i++] - _delete(self.split_path{i}) - ;/ - - _delete(self.split_path) - ;/ -;/ - -######################################## -# Compiler functions - here be dragons # -######################################## - -enum POINTER_TYPE [uint8] { - POINTER = 0, - REFERENCE = 1, - ARRAY = 2 -} - -# 88 bytes long -struct Type { - int s, - ~uint8 name, - Vector ptr_chain, - Vector members, - ~Module mod -} - -/; method Type - /; start - self.ptr_chain.start(1) - # 112 is the size of one Variable struct - self.members.start(112) - self.s = -1 - ;/ - - /; copy [Type] - Type out - out.name = cstr_make_copy(self.name) - out.mod = self.mod - out.s = self.s - - out.ptr_chain.copy(self.ptr_chain) - - # Deep copy members - out.members.start(112) - ~Variable v - Variable cpy - /; loop (int i = 0; i < self.members) [i++] - v = self.members.get(i) - cpy = v`.copy() - out.members.push(~cpy) - ;/ - - return out - ;/ - - /; push_ptr (uint8 ptype) - self.ptr_chain.push(~ptype) - ;/ - - /; pop_ptr [uint8] - int l = self.ptr_chain.num_el - uint8 out - out = self.ptr_chain.get(l) - self.ptr_chain.pop() - return out - ;/ - - /; push_member(Variable member) - Variable to_push = member.copy() - self.members.push(~to_push) - ;/ - - /; _del - self.ptr_chain._del() - - ~Variable v - /; loop (int i = 0; i < self.members.num_el) [i++] - v = self.members.get(i) - v`._del() - ;/ - self.members._del() - - _delete(self.name) - ;/ -;/ - -{}uint8 CSV_PRIMITIVES = "uint8,uint16,uint32,uint64,uint,int8,int16,int32,int64,int,float32,float64,float,comp32,comp64,comp,vect,bool,type,void" -{}uint8 sizes = {1, 2, 4, 8, 8, 1, 2, 4, 8, 8, 4, 8, 8, 4, 8, 8, 0, 1, 0, 0} -{}uint8 NONE = "NONE\0" - -/; get_primitive (Vector artifact) [Type] - ~~uint8 str_ptr = artifact.get(0) - int idx = in_csv(~CSV_PRIMITIVES, str_ptr`) - - Type out - out.start() - - /; if (idx !< 0) - out.s = sizes{idx} - out.name = str_ptr - out.mod = 0 - return out - ;/ - - out.s = 0 - 1 - out.name = ~NONE{0} - out.mod = 0 - - return out -;/ - -/; is_primitive (~uint8 name) [bool] - int idx = in_csv(~CSV_PRIMITIVES, name) - return idx !< 0 -;/ - -############# -# Variables # -############# - -# 112 bytes long -struct Variable { - ~uint name, - - Type data_type, - - int location, - loc_type -} - -/; method Variable - /; start (Type t) - self.data_type = t - ;/ - - /; copy [Variable] - Variable out - out.name = cstr_make_copy(self.name) - out.data_type = self.data_type.copy() - out.location = self.location - out.loc_type = self.loc_type - return out - ;/ - - /; _del - self.data_type._del() - ;/ -;/ - - - -############# -# Functions # -############# - -# 72 bytes long -struct Function { - ~uint8 - name, - Vector - inputs, - outputs -} - -/; method Function - /; start - self.inputs.start(88) - self.outputs.start(88) - ;/ - - /; _del - ~Type t - - /; loop (int i = 0; i < self.inputs.num_el) [i++] - t = self.inputs.get(i) - t`._del() - ;/ - self.inputs._del() - - /; loop (int i = 0; i < self.outputs.num_el) [i++] - t = self.outputs.get(i) - t`._del() - ;/ - self.outputs._del() - ;/ -;/ - -########### -# Modules # -########### - -# 145 bytes long -struct Module { - ~Module - parent, - ~uint8 - name, - bool - exp, # Export or not - Vector - typ, # Types - fnc, # Functions - def, # Variable definitions (lables) - sub # Sub modules -} - -/; method Module - /; start - self.typ.start(88) - self.fnc.start(72) # not impl yet - self.def.start(112) - self.sub.start(145) - self.parent = 0 - self.exp = false - ;/ - - /; push_struct(Type t) - self.typ.push(~t) - ;/ - - /; push_sub(Module s) - self.sub.push(~s) - ;/ - - /; _find_type(Vector a, int depth) [~Type] - ~Type none = 0 - ~Module p = self.parent - ~~uint8 cmp_ptr = a.get(depth) - - # If we've reached the num_el of the artifact, we are looking for - # the type name in this module's type vector - /; if (depth + 1 !< a.num_el) - ~Type t - /; loop (int i = 0; i < self.typ.num_el) [i++] - t = self.typ.get(i) - /; if (cstr_eq(t`.name, cmp_ptr`) == true) - return t - ;/ - ;/ - # Else we are looking to see if we can find the next sub module - # in the artifact - ;; else - ~Module m - ~Type t = 0 - /; loop (int j = 0; j < self.sub.num_el) [j++] - m = self.typ.get(j) - /; if (cstr_eq(m`.name, cmp_ptr`) == true) - t = m`._find_type(a, depth + 1) - break - ;/ - ;/ - - /; if (t !== 0) - return t - ;/ - ;/ - - # If the parent is zero, we are the root module, and should return 0 - # likewise, if we are above depth 0, we have been called from _find_type - # and do not need to search our parent (the caller) - /; if (p == 0 || depth > 0) - return none - ;/ - - # Recursive search upwards - return p`._find_type(a, 0) - ;/ - - /; find_type (Vector artifact) [Type] - ~Type t = self._find_type(artifact, 0) - - /; if (t == 0) - return get_primitive(artifact) - ;/ - - return t`.copy() - ;/ - - /; _del - /; loop (int i = 0; i < self.typ.num_el) [i++] - ~Type t = self.typ.get(i) - t`._del() - ;/ - self.typ._del() - - /; loop (int i = 0; i < self.fnc.num_el) [i++] - ~Function f = self.fnc.get(i) - f`._del() - ;/ - self.fnc._del() - - /; loop (int i = 0; i < self.def.num_el) [i++] - ~Variable v = self.def.get(i) - v`._del() - ;/ - self.def._del() - - /; loop (int i = 0; i < self.sub.num_el) [i++] - ~Module m = self.sub.get(i) - m`._del() - ;/ - self.sub._del() - - _delete(self.name) - ;/ -;/ - - - diff --git a/tnslc/copy.tnsl b/tnslc/copy.tnsl deleted file mode 100644 index 0050d1a..0000000 --- a/tnslc/copy.tnsl +++ /dev/null @@ -1,39 +0,0 @@ -:include "c_wrap_linux.tnsl" -# :include "utils.tnsl" - - -{}uint8 wrong_args = "Usage: copy [from] [to]" -{}uint8 write_one = "\0\n\0" - -# Proof of concept copy program -/; main (int argc, ~~uint8 argv) [int] - asm "mov r8, rdi" - asm "mov r9, rsi" - - /; if (argc < 3) - _printf(~wrong_args{0}) - return 1 - ;/ - - ~void read_handle = _open_file(argv{1}) - ~void write_handle = _create_file(argv{2}) - - _print_num(~_dec{0}, read_handle) - _print_num(~_dec{0}, write_handle) - - uint8 buf = 0 - int read_count = 0 - /; loop - read_count = _read_byte(read_handle, ~buf) - /; if (read_count == 0) - break - ;/ - _write_byte(write_handle, ~buf) - read_count = 0 - ;/ - - _close_file(read_handle) - _close_file(write_handle) - - return 0 -;/ diff --git a/tnslc/else.tnsl b/tnslc/else.tnsl deleted file mode 100644 index d2a7c94..0000000 --- a/tnslc/else.tnsl +++ /dev/null @@ -1,19 +0,0 @@ -{}uint8 a = "asdf", b = "asdf\0" - -{}uint8 csv_pr = ",\0" - -/; cstr_len (~void cstr, int add) [int] - int i = 0 - /; loop (cstr{i} !== 0) [i++] ;/ - return i + add -;/ - - - -/; main (int argc, ~~uint8 argv) [int] - - uint8 bub = 0 - cstr_len(~b{0}, bub) - - return 0 -;/
\ No newline at end of file diff --git a/tnslc/enum.tnsl b/tnslc/enum.tnsl deleted file mode 100644 index 5dd241b..0000000 --- a/tnslc/enum.tnsl +++ /dev/null @@ -1,13 +0,0 @@ -# to get working - -enum TEST_ENUM [int] { - i = 1 -} - -/; module m - int i = 1 -;/ - -/; main [int] - return TEST_ENUM.i + m.i -;/
\ No newline at end of file diff --git a/tnslc/hello.tnsl b/tnslc/hello.tnsl deleted file mode 100644 index 6a6313a..0000000 --- a/tnslc/hello.tnsl +++ /dev/null @@ -1,33 +0,0 @@ -:include "c_wrap_linux.tnsl" - -{}uint8 star = "*\0" -{}uint8 space = " \0" -{}uint8 new_line = "\n\0" - -/; print_triangle (int argc) - /; loop (int i = 0; i < argc) [i++] - /; loop (int j = 0; j < argc - i) [j++] - _printf(~space{0}) - ;/ - /; loop (int j = 0; j < 1 + 2*i) [j++] - _printf(~star{0}) - ;/ - _printf(~new_line{0}) - ;/ -;/ - -/; main (int argc, ~~uint8 argv) [int] - # On windows, the first two arguments are passed in RCX and RDX, so we need to - # update their positions here or else tnsl will have garbage values in r8 and r9 - # asm "mov r8, rcx" - # asm "mov r9, rdx" - - # If on linux, you would use rdi and rsi instead of rcx and rdx, respectively - # simply comment out the bove asm, and uncomment the below lines - asm "mov r8, rdi" - asm "mov r9, rsi" - - print_triangle(argc) - - return 0 -;/ diff --git a/tnslc/logging.tnsl b/tnslc/logging.tnsl deleted file mode 100644 index 2de326a..0000000 --- a/tnslc/logging.tnsl +++ /dev/null @@ -1,75 +0,0 @@ -## -## LOG UTILITIES -## - -# Log levels: -# 0 - Visual queues and errors only -# 1 - Info (default) -# 2 - Debugging information (useful for me, probably less for you) -# 3 - Also logs the state changes of the log itself -int log_level = 2 -int log_mode = 1 - -{}uint8 _log_print_one = "\0\0" -{}uint8 _log_nl = "\n\0" -{}uint8 _log_prefix = "[TNSLC] [%d] \0" - -/; log_state(int new_state) - /; if (new_state !== log_mode) - _printf(~_log_nl{0}) - ;/ - - log_mode = new_state -;/ - -/; log_err (~uint8 msg) - log_state(0) - _print_num(~_log_prefix{0}, log_mode) - _printf(msg) - _printf(~_log_nl{0}) -;/ - -/; log_info (~uint8 msg) - /; if (log_level > 0) - log_state(1) - _print_num(~_log_prefix{0}, log_mode) - _printf(msg) - _printf(~_log_nl{0}) - ;/ -;/ - -/; log_vis (~uint8 msg) - log_state(0) - _printf(msg) -;/ - -/; log_debug (~uint8 msg) - /; if (log_level > 1) - log_state(2) - _print_num(~_log_prefix{0}, log_mode) - _printf(msg) - _printf(~_log_nl{0}) - ;/ -;/ - -# bypass logging framework (mostly for in-place debugging) - -/; log_one (uint8 c) - _log_print_one{0} = c - _printf(~_log_print_one{0}) -;/ - -/; log_one_nl (uint8 c) - log_one(c) - _printf(~_log_nl{0}) -;/ - -/; log_num (int i) - _print_num(~_dec{0}, i) -;/ - -/; log_num_nl (int i) - _print_num(~_dec{0}, i) - _printf(~_log_nl{0}) -;/ - diff --git a/tnslc/read_file_test.tnsl b/tnslc/read_file_test.tnsl deleted file mode 100644 index cd8299b..0000000 --- a/tnslc/read_file_test.tnsl +++ /dev/null @@ -1,44 +0,0 @@ -:include "c_wrap.tnsl" -:include "utils.tnsl" - -{}uint8 usage_msg = "Usage: read_file.exe [file to read] [file to write]\n\0" -{}uint8 ok_msg = "Ok!\n\0" -{}uint8 print_one = "\0\0" -{}uint8 nl = "\n\0" - -/; main (int argc, ~~uint8 argv) [int] - - # On windows, the first two arguments are passed in RCX and RDX, so we need to - # update their positions here or else tnsl will have garbage values in r8 and r9 - asm "mov r8, rcx" - asm "mov r9, rdx" - - # If on linux, you would use rdi and rsi instead of rcx and rdx, respectively - # simply comment out the bove asm, and uncomment the below lines - # asm "mov r8, rdi" - # asm "mov r9, rsi" - - /; if (argc < 2) - _printf(~usage_msg{0}) - return 1 - ;; else - _printf(~ok_msg{0}) - ;/ - - _printf(argv{1}) - _printf(~nl{0}) - - ~void write_handle = _create_file(argv{1}) - - _print_num(~_dec{0}, write_handle) - - int ln = cstr_len(argv{1}) - - /; loop (int i = 0; i < ln) [i++] - _write_byte(write_handle, ~argv{1}{i}) - ;/ - - _close_file(write_handle) - - return 0 -;/
\ No newline at end of file diff --git a/tnslc/run.ps1 b/tnslc/run.ps1 deleted file mode 100644 index b820fb4..0000000 --- a/tnslc/run.ps1 +++ /dev/null @@ -1,11 +0,0 @@ -if ($args.Length -gt 0) { - ..\tint.exe -flags "$args" -in tnslc.tnsl - mkdir -Force build - mkdir -Force build/artifacts - mv -Force "$($args[0]).asm" "build/artifacts/$($args[0]).asm" - nasm -f win64 -o "build/artifacts/$($args[0]).obj" "build/artifacts/$($args[0]).asm" - gcc -o "build/$($args[0]).exe" "build/artifacts/$($args[0]).obj" -} else { - Write-Host "Usage: run [file to compile]"; - Write-Host ""; -} diff --git a/tnslc/run.sh b/tnslc/run.sh index 9957e15..904e281 100755 --- a/tnslc/run.sh +++ b/tnslc/run.sh @@ -1,18 +1,13 @@ #!/bin/bash -BUILD_DIR="./build" -ARTIFACTS_DIR="$BUILD_DIR/artifacts" - -if [ ! -d $BUILD_DIR ]; then - mkdir $BUILD_DIR -fi - -if [ ! -d $ARTIFACTS_DIR ]; then - mkdir $ARTIFACTS_DIR -fi - -../tint -in tnslc.tnsl -flags "$1" -mv -f "$1.asm" "$ARTIFACTS_DIR/$1.asm" -nasm -f elf64 -o "$ARTIFACTS_DIR/$1.o" "$ARTIFACTS_DIR/$1.asm" -clang -o "./build/${1%.*}" "$ARTIFACTS_DIR/$1.o" +BUILD_DIR=./build +ARTIFACT_DIR=$BUILD_DIR/artifacts + +mkdir -p $BUILD_DIR +mkdir -p $ARTIFACT_DIR +filename=tnslc.tnsl +filename="${filename%.*}" +./ctc $filename.tnsl $ARTIFACT_DIR/$filename.asm +nasm -f elf64 -o $ARTIFACT_DIR/$filename.o $ARTIFACT_DIR/$filename.asm +gcc -o $BUILD_DIR/$filename $ARTIFACT_DIR/$filename.o diff --git a/tnslc/simple.tnsl b/tnslc/simple.tnsl deleted file mode 100644 index 75b91bd..0000000 --- a/tnslc/simple.tnsl +++ /dev/null @@ -1,29 +0,0 @@ -# No longer simple -:include "c_wrap_linux.tnsl" - -{}uint8 str = "Hello copy!\n\0" - -struct Copier { - ~uint8 h8r -} - -/; method Copier - - /; copy [Copier] - Copier out - out.h8r = self.h8r - return out - ;/ - -;/ - -/; main - Copier a - a.h8r = ~str{0} - ~Copier b - b = ~a - Copier c = b`.copy() - _printf(c.h8r) - return 0 -;/ - diff --git a/tnslc/str_test.tnsl b/tnslc/str_test.tnsl deleted file mode 100644 index 7875636..0000000 --- a/tnslc/str_test.tnsl +++ /dev/null @@ -1,9 +0,0 @@ -{}uint8 a = "\n\0\"" - -/; str_call({}uint str) [int] - return len str -;/ - -/; main [int] - return str_call(~a) -;/
\ No newline at end of file diff --git a/tnslc/tnslc.tnsl b/tnslc/tnslc.tnsl index a518cc0..993771b 100644 --- a/tnslc/tnslc.tnsl +++ b/tnslc/tnslc.tnsl @@ -1,4113 +1,6 @@ -## -## LOG UTILITIES -## +:import "c_wrap_linux.tnsl" -# Log levels: -# 0 - Visual queues and errors only -# 1 - Info (default) -# 2 - Debugging information (useful for me, probably less for you) -# 3 - Also logs the state changes of the log itself -;{}uint8 log_level = "1" -;{}uint8 log_mode = "single" - -/; log_state({}uint8 new_state) - ;~{}uint8 l = ~log_mode - /; if (!string_equate(new_state, log_mode)) - ;tnsl.io.println("") - /; if (string_to_int(log_level) > 2) - ;tnsl.io.print("[TNSLC] [LOG] Swapping to state [") - ;tnsl.io.print(new_state) - ;tnsl.io.println("]") - ;/ - ;/ - - ;l` = new_state -;/ - -/; log_err ({}uint8 msg) - ;log_state("err") - ;tnsl.io.print("[TNSLC] [ERR] ") - ;tnsl.io.println(msg) - ;tnsl.exit() -;/ - -/; log_info ({}uint8 msg) - /; if (string_to_int(log_level) > 0) - ;log_state("info") - ;tnsl.io.print("[TNSLC] [INFO] ") - ;tnsl.io.println(msg) - ;/ -;/ - -/; log_vis ({}uint8 msg) - ;log_state("vis") - ;tnsl.io.print(msg) -;/ - -/; log_debug ({}uint8 msg) - /; if (string_to_int(log_level) > 1) - ;log_state("debug") - ;tnsl.io.print("[TNSLC] [DEBUG] ") - ;tnsl.io.println(msg) - ;/ -;/ - -## -## 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 - ;/ - - /; if (str{1} !== '\\') - ;return str{1} - ;/ - - ;uint8 cmp = str{2} - /; if (cmp == '\\') - ;return '\\' - ;; else if (cmp == 'n') - ;return '\n' - ;; else if (cmp == 'r') - ;return '\r' - ;; else if (cmp == 't') - ;return '\t' - ;; else if (cmp == '0') - ;return 0 - ;; else if (cmp == '\'') - ;return '\'' - ;; else if (cmp == '"') - ;return '"' - ;/ -;/ - -/; 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 -;/ - -/; string_reverse ({}uint8 str) [{}uint8] - ;{}uint8 out = "" - /; loop (int i = len str - 1; i !< 0) [i = i - 1] - ;out.append(str{i}) - ;/ - ;return out -;/ - -/; int_to_string (int i) [{}uint8] - /; if (i == 0) - ;return "0" - ;/ - - ;{}uint8 out = "" - ;bool inv = i < 0 - - /; if (inv) - ;i = -i - ;/ - - /; loop [i = i / 10; i > 0] - ;out.append('0' + (i % 10)) - ;/ - - /; if (inv) - ;out.append('-') - ;/ - - ;return string_reverse(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 -;/ - -/; string_to_csb ({}uint8 str) [{}uint8] - ;{}uint8 out = "" - - /; loop (int i = 0; i < len str) [i++] - ;out = string_add(out, int_to_string(str{i})) - /; if (i < len str - 1) - ;out.append(',') - ;out.append(' ') - ;/ - ;/ - - ;return out -;/ - -## -## Structs -## - -# The seperated string sections that make up an asm file -;struct CompData { - {}uint8 - hsec, - dsec, - csec -} - -/; method CompData - /; add (CompData data) - ;self.hsec = string_add(self.hsec, data.hsec) - ;self.dsec = string_add(self.dsec, data.dsec) - ;self.csec = string_add(self.csec, data.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) - ;/ - - /; 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) - ;/ - - /; 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 - ;/ -;/ - -## -## Tokenizer funcs -## - - -/; is_whitespace (uint8 c) [bool] - ;return (c == '\n' || c == '\t' || c == ' ') -;/ - -;{}uint8 MULTI_PARENS = "/;:#" -;{}uint8 PARENS = "()[]{}" -;{}uint8 SEPS = "\n;:," -;{}uint8 RESERVED = "`~!%^&*()-+=[]{}|;:/?<>.,\"" -;{}uint8 AUGMENTS = "=~!<>&|^+-*/%`." - -;{}{}uint8 MULTI_AUGMENTS = { - "++", "--", - - "==", "!==", "&&", "||", "^^", "<==", ">==", "!>", "!<", - - "~=", "`=", "%=", "^=", "&=", "*=", - "!=", "|=", "/=", - - "<<", ">>", "!&", "!|", "!^", - - "len", "is" -} - - -;{}{}uint8 KEYWORDS = { - - "if", - "else", - "loop", - - "continue", - "break", - "return", - - "method", - "struct", - "enum", - "interface", - - "export", - "module", - - "const", - "static", - "volatile", - "raw", - - "extends", - "override", - - "asm" -} - -;{}{}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_separator ({}uint8 str) [bool] - /; if (len str < 1) - ;return false - ;/ - ;return string_contains(SEPS, 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 - ;/ - - ;int i = 0 - /; if ((str{i} == '-' || str{i} == '.') && len str > 1) - ;i++ - ;/ - - ;bool dec = false - /; loop (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) || string_equate(str, "true") || string_equate(str, "false") -;/ - -/; gen_type (Token t) [int] - /; if (is_separator(t.data)) - ;return TOKEN.SEPARATOR - ;; else if (is_literal(t.data)) - ;return TOKEN.LITERAL - ;; else if (is_delimiter(t.data)) - ;return TOKEN.DELIMITER - ;; else if (is_augment(t.data)) - ;return TOKEN.AUGMENT - ;/ - - /; 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] - ;{}uint8 data = current.data - ;data.append(to_append) - - /; if (is_literal(current.data) || is_literal(data)) - ;return !(is_literal(data)) - ;/ - - /; if (is_whitespace(to_append) || current.cmp("\n")) - ;return true - ;/ - - /; if (is_reserved(current.data)) - /; if (is_reserved({to_append})) - ;current.data = data - ;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 == '\r') - ;continue - ;/ - - /; 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' && (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") - - /; if (!(current.cmp("")) && !(current.cmp("\n"))) - ;current.tokenType = gen_type(current) - ;out.append(current) - ;/ - - ;fd.close() - - ;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, - {}int - ptr_chain, - {}Variable - members, - ~Module - mod -} - -/; method Type - /; sprint [{}uint8] - ;{}uint8 out = string_join( {"{ ", int_to_string(self.s), ", ", self.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 - ;/ - - /; has_member ({}uint8 name) [bool] - /; loop (int i = 0; i < len(self.members)) [i++] - /; if (string_equate(self.members{i}.name, name)) - ;return true - ;/ - ;/ - ;return false - ;/ - - /; strip_refs - /; loop (true) - ;int ch = len (self.ptr_chain) - /; if (ch == 0) - ;break - ;; else if (self.ptr_chain{ch - 1} == PTYPE.REFERENCE) - ;self.ptr_chain = strip_int(self.ptr_chain) - ;; else - ;break - ;/ - ;/ - ;/ -;/ - -;{}{}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, "", {}, {}, 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 -;/ - -/; get_primitive (int i) [Type] - ;{}{}uint8 pn = PRIM_NAMES - ;{}int ps = PRIM_SIZES - ;return {ps{i}, pn{i}, {}, {}, 0} -;/ - -# 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) -;/ - -# 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') - ;/ - - ;out = string_add(out, common) - - ;; else - - ;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') - ;/ - ;/ - - ;return out -;/ - -/; get_reg (int r, sz) [{}uint8] - ;return reg_by_name_size(reg_by_num(r), sz) -;/ - -/; 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 "" -;/ - -/; 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, "]" }, "") -;/ - -/; strip_int({}int p) [{}int] - ;{}int out = {} - /; loop (int i = 0; i < len p - 1) [i++] - ;out.append(p{i}) - ;/ - ;return out -;/ - -/; 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 " -;/ - -/; 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 " -;/ - -# 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), " }" - },"") - ;/ - - /; 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( {mov_by_size(sz), "[ rbp - ", int_to_string(self.location), " ]" }, "") - ;; else if (self.loc_type == LOCATION.LITERAL) - ;return int_to_string(self.location) - ;/ - ;/ - - /; 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 (self.data_type.ptr_chain{0} == PTYPE.REFERENCE) - ;return self.data_type.s - ;/ - ;return 8 - ;/ - - /; el_size [int] - ;int index = len(self.data_type.ptr_chain) - 1 - /; loop (index > 0 && self.data_type.ptr_chain{index} == PTYPE.REFERENCE) - ;index-- - ;/ - - ;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 self.data_type.s - ;/ - - # FIXME: Match a type to another type if possible - # this is the type inference engine - # don't really know how well this works - /; match_types (Variable to_match, ~CompData data) [Variable] - ;Variable out = {"#match", self.data_type, 4, LOCATION.REGISTER} - - /; if (self.loc_type == LOCATION.STACK && self.is_ref()) - ;data`.csec = string_join( { - data`.csec, - "\tmov rdi, ", self.norm_loc(0), "\n" - }, "") - ;self.loc_type = LOCATION.REGISTER - ;self.location = 5 - ;; if (to_match.loc_type == LOCATION.STACK && to_match.is_ref()) - ;data`.csec = string_join( { - data`.csec, - "\tmov rsi, ", to_match.norm_loc(0), "\n" - }, "") - ;to_match.loc_type = LOCATION.REGISTER - ;to_match.location = 4 - ;return to_match - ;/ - - /; 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 (out.is_ref()) - ;out.data_type.ptr_chain = strip_int(out.data_type.ptr_chain) - ;/ - - ;{}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 - ;/ - - /; 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.is_ref() || self.loc_type == LOCATION.STACK || self.loc_type == LOCATION.LABEL) && (v.is_ref() || v.loc_type == LOCATION.STACK || v.loc_type == LOCATION.LABEL)) - ;data`.csec = string_join( { - data`.csec, - "\tmov ", get_reg(4, sz), ", ", v.norm_loc(sz), "\n", - "\t", op, " ", self.norm_loc(sz), ", ", get_reg(4, sz), "\n" - }, "") - ;; else - ;data`.csec = string_join( { - data`.csec, - "\t", op, " ", self.norm_loc(sz), ", ", v.norm_loc(sz), "\n" - }, "") - ;/ - ;/ - ;/ - - /; 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 - ;/ - - /; is_arr [bool] - ;int s = len (self.data_type.ptr_chain) - /; if (s > 0) - ;return self.data_type.ptr_chain{s - 1} == PTYPE.ARRAY - ;/ - ;return false - ;/ - - /; is_prim [bool] - /; if (len(self.data_type.ptr_chain) == 0) - ;return is_primitive(self.data_type.name) !< 0 - ;; if (len(self.data_type.ptr_chain) == 1) - ;return !(self.is_ref()) || is_primitive(self.data_type.name) !< 0 - ;/ - ;return true - ;/ - - /; 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) - ;/ - - # Mostly for internal use - /; strip_refs (~CompData data) [Variable] - ;Variable out = {"#ref", self.data_type, 4, LOCATION.REGISTER} - - /; 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) - ;/ - - ;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) - ;/ - ;/ - - /; 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) - ;/ - ;/ - - /; 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) - ;/ - ;/ - - /; 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) - ;/ - ;/ - - /; 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) - ;/ - ;/ - - /; 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" - }, "") - ;/ - ;/ - - /; 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) - ;/ - ;/ - - /; negative (Variable v, ~CompData data) - ;int sz = self.norm_size() - /; if (v.loc_type == LOCATION.LITERAL) - ;data`.csec = string_join( { - data`.csec, - "\tmov ", 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" - }, "") - ;/ - ;/ - - /; 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" - }, "") - ;/ - ;/ - - /; 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" - }, "") - ;/ - ;/ - - /; 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) - - /; if (self.data_type.name{0} == 'i') - ;op = string_add("i", op) - ;/ - - ;data`.csec = string_join( { - data`.csec, - "\tmov ", get_reg(0, sz), ", ", self.norm_loc(sz), "\n", - "\txor rdx, rdx\n", - "\tpush rsi\n", - "\tmov ", get_reg(4, sz), ", ", v.norm_loc(sz), "\n", - "\t", op, " ", get_reg(4, sz), "\n", - "\tpop rsi\n", - "\tmov ", self.norm_loc(sz), ", ", get_reg(keep, sz), "\n" - }, "") - ;/ - ;/ - - /; 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) - ;/ - ;/ - - /; 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) - ;/ - ;/ - - /; 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) - ;/ - ;/ - - # 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()) - ;self.norm_op("mov", self.norm_size(), v, data) - ;; else - ;log_debug("Full struct set") - ;log_debug(self.sprint()) - ;log_debug(v.sprint()) - /; if (self.is_ref() && self.loc_type == LOCATION.STACK) - ;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" - }, "") - ;/ - - /; if (v.is_ref() && v.loc_type == LOCATION.STACK) - ;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" - }, "") - ;/ - - ;data`.csec = string_join( { - data`.csec, - "\tmov rcx, ", int_to_string(sz), "\n", - "\trep movsb\n" - }, "") - ;/ - ;/ - - # To be used to set pointers without dereferencing - /; set_raw(Variable v, ~CompData data) - ;int sz = self.norm_size() - /; if (self.loc_type == LOCATION.LITERAL && v.loc_type == LOCATION.LITERAL) - ;self.location = v.location - ;; else if (self.loc_type == LOCATION.STACK && v.loc_type == LOCATION.STACK) - ;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 - ;{}uint8 p1 = self.norm_loc(sz) - ;{}uint8 p2 = v.norm_loc(sz) - - /; if (self.loc_type == LOCATION.REGISTER) - ;p1 = get_reg(self.location, 8) - ;; if (v.loc_type == LOCATION.REGISTER) - ;p2 = get_reg(v.location, 8) - ;/ - - ;data`.csec = string_join( { - data`.csec, - "\tmov ", p1, ", ", p2, "\n" - }, "") - ;/ - ;/ - - # 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 ", landing_pad, "\n", - "\tmov ", self.norm_loc(1), ", 0\n", - landing_pad, ":\n" - }, "") - ;/ - - /; 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 - ;/ - - # EVERYTHING SOUTH OF HERE NEEDS TO BE RE-DONE - - /; ref (Variable to_ref, ~CompData data) - ;int l = len (to_ref.data_type.ptr_chain) - /; if (to_ref.is_ref()) - ;self.set_raw(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())) - ;/ - ;/ - - /; 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 - ;/ - - /; 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) - - /; if (accum > 0) - ;data`.csec = string_join( { - data`.csec, - "\tadd rsi, ", int_to_string(accum), "\n" - }, "") - ;/ - - ;return out - ;/ - - /; 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())) - ;/ - - ;Variable ind = {"#index", {8, "void", {PTYPE.POINTER}, {}, 0}, 3, LOCATION.REGISTER} - ;ind.set(i, data) - ;ind.mul({"#mul", {8, "uint", {}, {}, 0}, sz, LOCATION.LITERAL}, data) - - /; if (out.is_ref() || out.is_arr()) - ;data`.csec = string_join( { - data`.csec, - "\tadd rsi, 8\n" - }, "") - ;/ - - ;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 - ;/ - - ;log_debug(string_add("Index returning: ", out.sprint())) - ;return out.deref(data) - ;/ - - /; length_of (Variable a, ~CompData data) - ;a = a.strip_refs(data) - ;a.data_type.name = "uint" - ;a.data_type.s = 8 - ;a.data_type.ptr_chain = {PTYPE.REFERENCE} - ;self.set(a, data) - ;/ +/; main [int] + return 0 ;/ -;struct Scope { - int num, c, tmp, - ~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, "}") - ;/ - - /; is_cf [bool] - /;if (len(self.name) < 1) - ;return false - ;/ - ;return self.name{0} == '#' - ;/ - - /; 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)) - ;/ - - /; full_label [{}uint8] - ;{}uint8 out = "" - /; if (self.is_cf()) - ;out = self.parent`.full_label() - ;/ - ;out = string_add(out, self.name) - ;return out - ;/ - - /; get_size [int] - ;int out = 0 - /; loop (int i = 0; i < len (self.vars)) [i++] - ;out = out + self.vars{i}.norm_size() - ;/ - ;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) - ;log_debug("Found register variable") - ;log_debug(self.vars{i}.sprint()) - ;out++ - ;/ - ;/ - - /; if (out > 15) - ;out = -1 - ;/ - - ;return out - ;/ - - /; get_stack [int] - ;int out = 0 - - /; loop (int i = 0; i < len (self.vars)) [i++] - /; if (self.vars{i}.loc_type == LOCATION.STACK) - ;out = out + self.vars{i}.norm_size() - ;/ - ;/ - - ;return out - ;/ - - /; get_full_stack [int] - ;int out = 0 - /; if (self.is_cf()) - ;out = self.parent`.get_full_stack() - ;/ - - /; loop (int i = 0; i < len (self.vars)) [i++] - /; if (self.vars{i}.loc_type == LOCATION.STACK) - ;out = out + self.vars{i}.norm_size() - ;/ - ;/ - - /; if (!(self.is_cf()) && !(self.r)) - ;return out + 72 - ;/ - - ;return out - ;/ - - /; get_full_tmp_stack [int] - ;int out = self.tmp - /; if (self.is_cf()) - ;out = out + self.parent`.get_full_tmp_stack() - ;/ - - /; loop (int i = 0; i < len (self.vars)) [i++] - /; if (self.vars{i}.loc_type == LOCATION.STACK) - ;out = out + self.vars{i}.norm_size() - ;/ - ;/ - - /; if (!(self.is_cf()) && !(self.r)) - ;return out + 72 - ;/ - - ;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) - ;/ - - # pre-stack loop - /; loop (int i = 0; i < len (self.vars)) [i++] - ;int loc = self.next_loc(self.vars{i}.data_type) - /; if (loc !< 0) - ;self.vars{i}.location = loc - ;self.vars{i}.loc_type = LOCATION.REGISTER - ;out`.csec = string_join( { - out`.csec, - "\tmov ", get_reg(loc, 8), ", ", get_reg(loc - 8, 8), "\n\n" - }, "") - ;/ - ;/ - - ;int accum = 0 - /; if (!(self.r)) - ;accum = 72 - ;/ - - ;{}uint8 moves = string_join( { - "\tlea rsi, [rbp + 8]\n\n" - }, "") - - # Move extra variables - /; loop (int i = len (self.vars) - 1; i !< 0) [i = i - 1] - /; if (self.vars{i}.loc_type == LOCATION.LITERAL) - ;self.vars{i}.loc_type = LOCATION.STACK - ;int sz = self.vars{i}.norm_size() - ;accum = accum + sz - ;self.vars{i}.location = accum - /; if (len (self.vars{i}.data_type.ptr_chain) > 0) - ;moves = string_join( { - moves, - "\tsub rsp, 8\n", - "\tlea rdi, qword [rbp - ", int_to_string(accum), "]\n", - "\tmovsq\n\n" - }, "") - ;; else - ;moves = string_join( { - moves, - "\tsub rsp, ", int_to_string(sz), "\n", - "\tlea rdi, [rbp - ", int_to_string(accum), "]\n", - "\tmov rcx, ", int_to_string(sz), "\n", - "\trep movsb\n" - }, "") - ;/ - ;/ - ;/ - - /; if (accum > 72 && !(self.r)) - ;out`.csec = string_add(out`.csec, moves) - ;/ - ;/ - - /; 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" - ;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 - ;/ - ;/ - - /; 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") - ;/ - - /; scope_rep_label [{}uint8] - ;return string_add(self.full_label(), "_rep") - ;/ - - /; scope_end_label [{}uint8] - ;return string_add(self.full_label(), "_end") - ;/ - - /; 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, 0, ~self, cf, {}, self.r} - ;/ - - /; br (uint i, ~CompData out) - ;~Scope top = ~self - ;~Scope sco = ~self - ;int seen = 0 - /; loop (seen !> i && i > 0) - /; if (top`.parent`.is_cf()) - ;top = top`.parent - /; if (top`.cf_type("wrap")) - ;sco = top - ;seen++ - ;/ - ;; else - ;break - ;/ - ;/ - - ;out`.csec = string_join( { - out`.csec, - "\tjmp ", sco`.scope_end_label(), "\n" - }, "") - - ;/ - - /; cont (uint i, ~CompData out) - ;~Scope top = ~self - ;~Scope sco = ~self - ;int seen = 0 - /; loop (seen !> i && i > 0) - /; if (top`.parent`.is_cf()) - ;top = top`.parent - /; if (top`.cf_type("wrap")) - /; if (top`.parent`.is_cf()) - ;sco = top`.parent - ;/ - ;seen++ - ;/ - ;; else - ;break - ;/ - ;/ - - ;out`.csec = string_join( { - out`.csec, - "\tjmp ", sco`.scope_rep_label(), "\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) - ;/ - - /; new_tmp_var (Type t, ~CompData out) [Variable] - ;Variable new = {"##tmp", t, 0, 0} - ;new.loc_type = LOCATION.STACK - ;new.location = self.get_full_tmp_stack() + new.norm_size() - ;self.tmp = self.tmp + new.norm_size() - ;out`.csec = string_join( { - out`.csec, - "\tsub rsp, ", int_to_string(new.norm_size()), "\n" - }, "") - ;log_debug(string_add("Created tmp variable ", new.sprint())) - ;return new - ;/ - - /; clear_tmp (~CompData out) - ;log_debug(string_add("Cleared tmp: ", int_to_string(self.tmp))) - - /; if (self.tmp > 0) - ;out`.csec = string_add(out`.csec, string_add("\tadd rsp, ", int_to_string(self.tmp))) - ;out`.csec.append('\n') - ;self.tmp = 0 - ;/ - ;/ - - /; 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} - ;/ - ;/ - - /; if (!(self.is_cf())) - ;return current`.find_def(artifact) - ;/ - ;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}) - ;/ - ;/ - - /; 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) - ;/ - - /; move_to_stack (int reg, ~CompData out) [Variable] - ;int last_var = self.next_register() - /; if (last_var < 0) - ;last_var = 16 - ;/ - - /; 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))) - ;/ - - ;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`.location = copy.location - ;rv`.loc_type = LOCATION.STACK - ;log_debug(self.sprint()) - - /; if (reg < last_var - 1) - ;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) - ;/ - ;log_debug(self.sprint()) - - - ;return copy - ;/ - - /; next_const [{}uint8] - ;{}uint8 out = string_add(self.full_label(), string_add("#const_", int_to_string(self.c))) - ;self.c++ - ;return out - ;/ -;/ - -;struct Function { - {}uint8 name, - {}Type - inputs, - Type - output, - ~Module mod -} - -/; method Function - /; full_label [{}uint8] - ;{}uint8 out = self.mod`.full_path() - /; if (len out > 0) - ;out.append('.') - ;/ - ;out = string_add(out, self.name) - ;return out - ;/ - - /; is_method [bool] - ;{}uint8 mod_name = self.mod`.name - /; if (len mod_name > 2) - ;return mod_name{0} == '_' && mod_name{1} == '#' - ;/ - ;return false - ;/ - - /; sprint [{}uint8] - ;return string_join( { - "Function ", self.name, " (", int_to_string(len(self.inputs)), ") ", self.output.sprint() - }, "") - ;/ -;/ - -;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.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}) - ;/ - ;/ - ;/ - - /; if (string_equate(self.name, "")) - ;Type nt = {0, artifact{len artifact - 1}, {}, {}, 0} - ;return ~nt - ;/ - - ;~Module m = self.parent - /; loop (r > 0) [r = r - 1] - ;m = m`.parent - ;/ - ;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}, {}, {}, 0} - ;return ~out - ;/ - - ;return self._find_type(artifact, 0) - ;/ - - /; _find_def ({}{}uint8 artifact, int r) [Variable] - ;log_debug(string_add("Finding def: ", artifact{r})) - ;log_debug(string_join(artifact, ".")) - /; if (len artifact !> r) - ;return {"", NO_TYPE, 0, 0} - ;/ - - /; if (len artifact - 1 > r) - ;log_debug("loopin") - ;{}uint8 e_name = string_add("__#", artifact{r}) - ;{}uint8 m_name = string_add("_#", artifact{r}) - /; loop (int i = 0; i < len (self.sub)) [i++] - /; if (string_equate(artifact{r}, self.sub{i}.name) || string_equate(e_name, self.sub{i}.name) || string_equate(m_name, 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} - ;/ - ;/ - ;/ - - /; 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) - ;/ - - /; find_def ({}{}uint8 artifact) [Variable] - ;log_debug("Finding def...") - ;return self._find_def(artifact, 0) - ;/ - - /; _find_function ({}{}uint8 artifact, int r) [Function] - /; if (len artifact !> r) - ;return {"", {}, {}} - ;/ - - /; 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_function(artifact, r + 1) - ;/ - ;/ - ;; else if (len artifact - 1 == r) - /; loop (int i = 0; i < len (self.functions)) [i++] - /; if (string_equate(self.functions{i}.name, artifact{r})) - ;return self.functions{i} - ;/ - ;/ - ;/ - - /; if (string_equate(self.name, "")) - ;return {"", {}, {}} - ;/ - - ;~Module m = self.parent - /; loop (r > 0) [r = r - 1] - ;m = m`.parent - ;/ - ;return m`._find_function(artifact, 0) - ;/ - - /; find_function ({}{}uint8 artifact) [Function] - ;return self._find_function(artifact, 0) - ;/ - - /; _find_mod ({}{}uint8 artifact, int r) [~Module] - /; if (len artifact !> r) - ;return ~self - ;/ - - /; 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}) - ;/ - ;/ - ;/ - - /; 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) - ;/ - - /; find_mod({}{}uint8 artifact) [~Module] - ;return self._find_mod(artifact, 0) - ;/ - - /; 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 ~self - ;/ - - /; 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 -;/ - -/; 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 - ;break - ;/ - ;/ - ;return false -;/ - -/; pre_get_type (~{}Token tok, ~int cur) [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 - ;/ - ;/ - - ;{}uint8 a = string_join(get_artifact(tok, cur), ".") - ;Type out = {0, a, ptr_chain, {}, 0} - - /; if (tok`{cur`}.cmp("`")) - ;out.ptr_chain.append(PTYPE.REFERENCE) - ;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)) - ;/ - ;/ - - /; if (tok`{cur`}.cmp("`")) - ;ptr_chain.append(PTYPE.REFERENCE) - ;cur`++ - ;/ - - ;out.ptr_chain = ptr_chain - ;return out -;/ - -/; 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, "") -;/ - -/; 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('.') - ;/ - - /; 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)) - ;/ - ;/ -;/ - -/; next_non_nl (~{}Token tok, int c) [int] - /; if (len tok` !> c) - ;return c - ;/ - /; loop (tok`{c}.cmp("\n")) [c++] ;/ - ;return c -;/ - -/; pre_parse_params (~{}Token tok, ~int cur) [{}Type] - ;{}Type 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(t) - /; if (tok`{nnl}.cmp(",")) - ;cur`++ - ;/ - ;; else - ;t = pre_get_type(tok, cur) - ;cur` = cur` - 1 - ;/ - ;/ - - ;return out -;/ - -/; 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, LOCATION.LITERAL}) - /; if (tok`{nnl}.cmp(",")) - ;cur`++ - ;/ - ;; else - ;t = get_type(tok, cur, current) - ;cur` = cur` - 1 - ;/ - ;/ - ;return out -;/ - -/; find_or_create ({}uint sub_name, ~Module current, bool exp) [~Module] - /; if (!(string_equate(current`.find_sub(sub_name)`.name, current`.name))) - ;return current`.find_sub(sub_name) - ;/ - ;Module out = {current, exp, "", {}, {}, {}, {}} - - - ;out.name = current`.full_path() - /; if (len (out.name) > 0) - ;out.name.append('.') - ;/ - ;out.name = string_add(out.name, sub_name) - - - ;current`.sub.append(out) - ;return current`.find_sub(sub_name) -;/ - -# Generates new type -/; new_type (~{}Token tok, ~int cur, ~Module current) - ;cur`++ - - /; if (tok`{cur`}.tokenType !== TOKEN.DEFWORD) - ;log_err(string_join( { - "Unexpected token type at ", tok`{cur`}.sprint(), " The struct keyword should be followed by an identifier." - }, "")) - ;/ - - ;Type out = {0, tok`{cur`}.data, {}, {}, 0} - - ;{}uint8 mod_name = string_add("_#", out.name) - ;~Module new = find_or_create(mod_name, current, current`.exp) - ;out.mod = new - - /; 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++] - ;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) -;/ - -/; new_function (~{}Token tok, ~int cur, ~Module current) - ;{}Type inputs = {} - ;Type output = NO_TYPE - - ;int max = find_closing(tok, cur) - ;cur`++ - - /; if (tok`{cur`}.tokenType !== TOKEN.DEFWORD) - ;log_err(string_join( { - "Unexpected token type at ", tok`{cur`}.sprint(), " The struct keyword should be followed by an identifier." - }, "")) - ;/ - - ;{}uint8 name = tok`{cur`}.data - ;cur`++ - - /; loop (cur` < max) [cur`++] - /; if (tok`{cur`}.cmp("(")) - ;inputs = pre_parse_params(tok, cur) - ;; else if (tok`{cur`}.cmp("[")) - ;cur`++ - ;output = pre_get_type(tok, cur) - ;; else - ;break - ;/ - ;/ - - ;cur` = max - ;current`.functions.append( {name, inputs, output, current} ) -;/ - -/; 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) - ;/ - ;/ - ;cur` = max - - ;{}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, 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++ - ;/ - - /; if (m < len (t.members) - 1) - /; loop (m < len (t.members)) [m++] - ;out = string_add(out, decompose_empty(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, 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) - ;/ - ;; 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") - ;/ - - /; if (tok`{cur`}.data{0} == '"') - ;{}uint8 data = unquote_str(tok`{cur`}.data) - ;return string_join({ - declare_size(8), int_to_string(len data), "\n", - declare_size(1), string_to_csb(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) -;/ - -# 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`++ - ;/ - ;/ - - ;log_debug(string_join( { - "Adding enum ", name, " of type ", et.name - }, "")) - - /; if (string_equate(et.name, "")) - ;et = Primitives{3} - ;/ - - /; 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 - ;/ - - /; 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') - ;/ - - ;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) -;/ - -# 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("/;") || 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 - ;/ - ;/ - - /; 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) - /; loop (cur` < len tok`) [cur`++] - /; if (tok`{cur`}.cmp("{")) - ;cur` = find_closing(tok, cur) - ;break - ;/ - ;/ -;/ - -# 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 - - /; loop (start++; start < max) [start++] - /; if (tok`{start}.type_is(TOKEN.DELIMITER)) - ;start = find_closing(tok, ~start) - ;; else if (tok`{start}.cmp(",")) - ;out++ - ;/ - ;/ - - ;return out -;/ - -# Priority -# 0 - deref -# 1 - get -# 2 - ref, len -# 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 (tok.cmp("len")) - ;return 2 - ;; 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 - ;/ - - ;return -1 -;/ - -/; 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() - }, "")) - - /; 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 - ;/ - - /; if (tok`{i` + 1}.cmp(".")) - ;i`++ - ;; else - ;i`++ - ;break - ;/ - ;/ - - /; if (string_equate(wk.name, "")) - ;log_debug(string_add("Unable to find variable within artifact ", string_join(art, "."))) - ;/ - ;log_debug(string_add("Found ", wk.sprint())) - ;return wk -;/ - -/; _param_end (~{}Token tok, int start) [int] - /; loop (start < len tok`) [start++] - /; if (tok`{start}.cmp(")") || tok`{start}.cmp("}") || tok`{start}.cmp(",")) - ;return start - ;; else if (tok`{start}.type_is(TOKEN.DELIMITER)) - ;start = find_closing(tok, ~start) - ;/ - ;/ - ;return start -;/ - -# FIXME: should set up the call by eval of all params -/; _setup_call (~{}Token tok, int start, Variable base, ~CompData out, mov, ~Module current, ~Scope scope) [Function] - ;{}uint8 name = tok`{start}.data - ;start++ - ;int max = find_closing(tok, ~start) - ;start++ - ;Function f - - ;int regs = 1 - /; if (string_equate(base.name, "")) - ;regs = 0 - ;f = current`.find_function( {name} ) - ;; else - ;f = base.data_type.mod`.find_function( {name} ) - ;/ - ;Variable ctmp = {"#ctmp", NO_TYPE, 0-1, LOCATION.REGISTER} - ;int old_start = start - /; loop (int i = 0; i < len (f.inputs)) [i++] - ;Type t = f.mod`.find_type(string_split(f.inputs{i}.name, '.'))` - ;t.ptr_chain = f.inputs{i}.ptr_chain - ;ctmp.data_type = t - - /; if (ctmp.is_ref()) - ;ctmp.data_type.ptr_chain{len (ctmp.data_type.ptr_chain) - 1} = PTYPE.POINTER - ;/ - ;ctmp.data_type.ptr_chain.append(PTYPE.REFERENCE) - - /; if (!(ctmp.is_prim()) || regs !< 6) - ;int layer = 0 - ;Variable val = _eval_value(tok, start, _param_end(tok, start), out, mov, current, scope, t, ~layer) - ;out`.csec = string_join( { - out`.csec, - "\tsub rsp, ", int_to_string(ctmp.norm_size()), "\n" - }, "") - ;scope`.tmp = scope`.tmp + ctmp.norm_size() - ;ctmp.set(val, out) - ;; else - ;regs++ - ;/ - ;start = _param_end(tok, start) + 1 - ;/ - - ;int regs = 1 - /; if (string_equate(base.name, "")) - ;regs = 0 - ;/ - ;start = old_start - /; loop (int i = 0; i < len (f.inputs)) [i++] - ;Type t = f.mod`.find_type(string_split(f.inputs{i}.name, '.'))` - ;t.ptr_chain = f.inputs{i}.ptr_chain - ;ctmp.data_type = t - - /; if (ctmp.is_ref()) - ;ctmp.data_type.ptr_chain{len (ctmp.data_type.ptr_chain)} = PTYPE.POINTER - ;/ - ;ctmp.data_type.ptr_chain.append(PTYPE.REFERENCE) - - /; if (ctmp.is_prim() && regs < 6) - ;int layer = 0 - ;Scope tmp_sc = scope`.new_sub_cf("call") - ;Variable val = _eval_value(tok, start, _param_end(tok, start), out, mov, current, ~tmp_sc, t, ~layer) - ;tmp_sc.clear_tmp(out) - - ;out`.csec = string_join( { - out`.csec, - "\tsub rsp, ", int_to_string(ctmp.norm_size()), "\n" - }, "") - ;scope`.tmp = scope`.tmp + ctmp.norm_size() - - ;ctmp.set(val, out) - ;regs++ - ;; else if (regs == 6) - ;break - ;/ - ;start = _param_end(tok, start) + 1 - ;/ - - /; if (f.is_method()) - /; if (base.is_ref()) - ;base.move_register(0, out) - ;; else - ;out`.csec = string_join( { - out`.csec, - "\tlea rax, ", base.norm_loc(base.norm_size()), "\n" - }, "") - ;/ - ;/ - - ;return f -;/ - -# FIXME: should actually do call based on function given, and return a proper variable. -# assumes the call has been set up -/; _perform_call (Function f, ~Scope scope, ~CompData out) [Variable] - ;int reg = 0, i = 0 - /; if (f.is_method()) - ;reg = 1 - ;/ - ;Variable ctmp = {"#ctmp", NO_TYPE, 4, LOCATION.REGISTER} - /; loop (i < len (f.inputs)) [i++] - ;Type t = f.mod`.find_type(string_split(f.inputs{i}.name, '.'))` - ;t.ptr_chain = f.inputs{i}.ptr_chain - ;ctmp.data_type = t - /; if (ctmp.is_prim() && reg < 6) - ;reg++ - ;; else if (reg == 6) - ;break - ;/ - ;/ - ;reg = reg - 1 - ;i = i - 1 - /; loop (i !< 0) [i = i - 1] - ;Type t = f.mod`.find_type(string_split(f.inputs{i}.name, '.'))` - ;t.ptr_chain = f.inputs{i}.ptr_chain - ;ctmp.data_type = t - /; if (ctmp.is_prim() && reg < 6) - ;out`.csec = string_join( { - out`.csec, - "\tmov ", get_reg(reg, ctmp.norm_size()),", [rsp]\n", - "\tadd rsp, ", int_to_string(ctmp.norm_size()), "\n" - }, "") - ;scope`.tmp = scope`.tmp - ctmp.norm_size() - ;reg = reg - 1 - ;; else if (reg == 6) - ;break - ;/ - ;/ - ;out`.csec = string_join( { - out`.csec, - "\tcall ", f.full_label(), "\n" - }, "") - - /; if (string_equate(f.output.name, "")) - ;return {"", NO_TYPE, 0, 0} - ;/ - - ;Type t = f.mod`.find_type(string_split(f.output.name, '.'))` - ;t.ptr_chain = f.output.ptr_chain - ;ctmp.data_type = t - ;ctmp.location = 0 - /; if (!(ctmp.is_prim()) && !(ctmp.is_ref())) - ;ctmp.data_type.ptr_chain.append(PTYPE.REFERENCE) - ;/ - ;log_debug("perf call ret") - ;return ctmp -;/ - -# Evaluates dot chains, indexing, and calls -/; _eval_dot (~{}Token tok, ~int start, int max, ~CompData out, mov, ~Module current, ~Scope scope, Type t, ~int layer) [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") - /; if (wk.data_type.has_member(tok`{start` + 1}.data)) - ;wk = wk.member(tok`{start` + 1}.data, out) - ;start` = start` + 2 - ;/ - ;; else if (tok`{start`}.cmp("(")) - ;start` = start` - 1 - ;; else if (tok`{start`}.cmp("`")) - ;log_debug("Pre loop deref") - ;wk = wk.deref(out) - ;start` = start` + 1 - ;/ - - ;layer` = layer` + 1 - /; 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") - /; if (wk.data_type.has_member(tok`{start` + 1}.data)) - ;start`++ - ;wk = wk.member(tok`{start`}.data, out) - ;; else if (!(tok`{start` + 2}.cmp("("))) - ;log_err(string_join( { - "Invalid member [", tok`{start` + 1}.data, "] for variable ", wk.sprint() - },"")) - ;/ - ;; else if (tok`{start`}.cmp("{")) - ;log_debug("Index!") - ;Type ut = {8, "uint", {}, {}, 0} - ;Variable i = _eval_value(tok, start` + 1, find_closing(tok, start), out, mov, current, scope, ut, layer) - ;log_debug(i.sprint()) - ;wk = wk.index(i, out) - ;log_debug(wk.sprint()) - ;start` = find_closing(tok, start) - ;; else if (tok`{start` + 1}.cmp("(") && tok`{start`}.type_is(TOKEN.DEFWORD)) - ;log_debug("Call") - - ## Pre-flight check - # ;CompData trash = {"", "", ""} - # ;_setup_call(tok, start`, wk, ~trash, mov, current, scope) - - # Actually do call - - - /; if (layer` > 1) - ;out`.csec = string_join({ - out`.csec, - "\tpush rbx\n" - } , "") - ;scope`.tmp = scope`.tmp + 8 - ;; if (layer` > 2) - ;out`.csec = string_join({ - out`.csec, - "\tpush rcx\n" - } , "") - ;scope`.tmp = scope`.tmp + 8 - ;/ - - ;Scope call_sc = scope`.new_sub_cf("call") - ;Function to_call = _setup_call(tok, start`, wk, out, mov, current, ~call_sc) - ;wk = _perform_call(to_call, ~call_sc, out) - ;log_debug(to_call.sprint()) - ;log_debug(wk.sprint()) - ;call_sc.clear_tmp(out) - - /; if (layer` > 2) - ;out`.csec = string_join({ - out`.csec, - "\tpop rcx\n" - } , "") - ;scope`.tmp = scope`.tmp - 8 - ;; if (layer` > 1) - ;out`.csec = string_join({ - out`.csec, - "\tpop rbx\n" - } , "") - ;scope`.tmp = scope`.tmp - 8 - ;/ - - ;start`++ - ;start` = find_closing(tok, start) - ;/ - ;/ - ;layer` = layer` - 1 - - /; if (layer` > 1) - ;log_debug("Dot tmp variable generated") - ;Variable tt - - /; if (wk.is_ref()) - ;tt = scope`.new_tmp_var({8, "void", {PTYPE.POINTER}, {}, 0}, out) - ;; else - ;tt = scope`.new_tmp_var(wk.data_type, out) - ;/ - - /; if (len (wk.data_type.ptr_chain) > 0) - ;tt.set_raw(wk, out) - ;tt.data_type = wk.data_type - ;; else - ;tt.set(wk, out) - ;/ - - ;wk = tt - ;; else if (layer` == 1) - ;wk.move_register(2, out) - ;; else - ;wk.move_register(1, out) - ;/ - - ;log_debug(string_add("Dot returning ", wk.sprint())) - ;return wk -;/ - -/; 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), string_to_csb(unquote_str(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(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 -;/ - -/; 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++ - ;/ - ;/ -;/ - -/; 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, ~int layer) [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, layer) - /; 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) - ;/ - ;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, ~int layer) [Variable] - ;log_vis(".") - /; if (start == max - 1) - /; if (tok`{start}.type_is(TOKEN.LITERAL)) - ;{}uint8 l = current`.full_path() - - /; if (len l > 0) - ;l.append('.') - ;/ - - ;l = string_add(l, scope`.next_const()) - ;return literal_variable(tok`{start}.data, l, out) - ;/ - ;/ - - ;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) - ;/ - ;/ - - /; if (tok`{start}.cmp("(")) - ;return _eval_value(tok, start + 1, find_closing(tok, ~start), out, mov, current, scope, t, layer) - ;/ - - /; if (pa !< 0 && pr < 2) - /; if (tok`{pa}.cmp("{") && pa == first) - ;log_debug("Composite") - ;return _eval_composite(tok, pa + 1, find_closing(tok, ~pa), out, current, scope, t, layer) - ;/ - ;/ - - /; if (pr < 2) - ;log_debug("Dot _eval_value") - ;return _eval_dot(tok, ~start, max, out, mov, current, scope, t, layer) - ;/ - - ;Variable s1, s2 - ;layer` = layer` + 1 - /; if (first == start) - ;s1 = _eval_value(tok, first + 1, max, out, mov, current, scope, t, layer) - ;; else if (first == max - 1) - ;s1 = _eval_value(tok, start, first, out, mov, current, scope, t, layer) - ;; else - /; if (tok`{first}.cmp("=")) - ;layer` = layer` - 1 - ;/ - ;int l2 = layer` + 1 - - ;s1 = _eval_value(tok, start, first, out, mov, current, scope, t, layer) - ;t = s1.data_type - ;t.strip_refs() - ;s2 = _eval_value(tok, first + 1, max, out, mov, current, scope, t, ~l2) - - /; if (tok`{first}.cmp("=")) - ;layer` = layer` + 1 - ;/ - - ;log_debug(string_add("Calculated s2 as ", s2.sprint())) - ;/ - ;layer` = layer` - 1 - - ;log_debug(string_add("Calculated s1 as ", s1.sprint())) - - /; if (tok`{first}.cmp("=")) - ;s1.set(s2, out) - ;return s1 - ;; if (tok`{first}.cmp("++") || tok`{first}.cmp("--")) - ;t = s1.data_type - ;t.strip_refs() - ;/ - - ;Variable wk = {"#wk", t, 1, LOCATION.REGISTER} - /; if (layer` > 1) - ;wk = scope`.new_tmp_var(t, out) - ;; else if (layer` == 1) - ;wk.location = 2 - ;/ - - ;log_debug(string_join( { - "_eval_value called with following type info:", t.sprint() - }, " ")) - - # Inc and dec - /; if (tok`{first}.cmp("++") || tok`{first}.cmp("--")) - ;wk.set(s1, out) - - /; if (tok`{first}.cmp("++")) - ;s1.inc(out) - ;; else - ;s1.dec(out) - ;/ - - /; if (first == max - 1) - ;return wk - ;/ - - ;return s1 - ;/ - - # TODO: Boolean combinations such as and, or, xor - /; if (pr == 7) - ;wk.set(s1, out) - ;wk.cmp(s2, out) - ;wk.data_type = {1, "bool", {}, {}, 0} - - ;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 - ;; else if (pr == 8) - # TODO: First convert non-boolean values to boolean - /; if (tok`{first}.cmp("&&")) - ;wk.set(s1, out) - ;wk.and(s2, out) - ;; else if (tok`{first}.cmp("||")) - ;wk.set(s1, out) - ;wk.or(s2, out) - ;; else if (tok`{first}.cmp("^^")) - ;wk.set(s1, out) - ;wk.xor(s2, out) - ;/ - ;/ - - /; 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.or(s2, out) - ;; else if (tok`{first}.cmp("&")) - ;wk.set(s1, out) - ;wk.and(s2, out) - ;; else if (tok`{first}.cmp("^")) - ;wk.set(s1, out) - ;wk.xor(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) - ;; else if (tok`{first}.cmp("len")) - ;wk.length_of(s1, out) - ;/ - - ;return wk -;/ - -# ALWAYS put the value in rax on save -/; eval_value (~{}Token tok, ~int cur, ~CompData out, mov, ~Module current, ~Scope scope, Type t, bool save) [Variable] - ;log_debug("Evaling!") - ;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) - ;/ - ;/ - ;CompData tmp = {"", "", ""} - ;int level = 0 - ;_eval_value(tok, cur`, end, ~tmp, mov, current, scope, t, ~level) - ;scope`.clear_tmp(~tmp) - ;Variable val = _eval_value(tok, cur`, end, out, ~tmp, current, scope, t, ~level) - ;log_debug("c") - ;scope`.clear_tmp(out) - ;cur` = end - /; if (save) - /; if (!(val.is_prim())) - ;t.ptr_chain.append(PTYPE.REFERENCE) - ;/ - - ;Variable set = {"#tmp", t, 0, LOCATION.REGISTER} - - /; if (!(val.is_prim()) && set.is_ref()) - ;set.data_type.ptr_chain = { PTYPE.POINTER } - ;set.ref(val, out) - ;set.data_type.ptr_chain = { PTYPE.REFERENCE } - ;; else if (set.is_ref()) - ;set.set_raw(val, out) - ;; else - ;set.set(val, out) - ;/ - - ;return val - ;/ - ;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) - - /; if (tok`{cur`}.cmp(",")) - ;cur` = next_non_nl(tok, cur` + 1) - ;; else - ;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}) == 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 - ;/ - ;/ - - ;return false -;/ - - -/; statement_list(~{}Token tok, int start, end, ~Module current, ~CompData out, mov, ~Scope parent) [int] - ;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") - ;/ - ;eval_value(tok, ~s, out, mov, current, parent, t, b > 0) - ;/ - ;/ - - ;return b -;/ - - -# 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) - ;Scope cf = parent`.new_sub_cf("wrap") - - ;CompData outro = {"", "", ""} - ;int condition = 0 - 1 - - /; loop (cur`++; cur` < len (tok`)) [cur`++] - /; if (tok`{cur`}.type_is(TOKEN.KEYWORD)) - /; if (tok`{cur`}.cmp("else")) - ;log_err("Invalid else!!!") - ;; else - ;cf = cf.new_sub_cf(tok`{cur`}.data) - ;/ - ;; else if (tok`{cur`}.cmp("(")) - ;int psl = find_closing(tok, cur) - ;int tmp = statement_list(tok, cur`, psl, current, out, mov, ~cf) - - /; if (tmp !< 0 && condition < 0 && cf.cf_type("if") == false) - ;condition = tmp - ;Type t = {1, "bool", "_bool", {}, {}} - ;eval_value(tok, ~tmp, ~outro, mov, current, ~cf, t, true) - ;/ - - /; if (tmp !< 0) - /; if (cf.cf_type("if")) - ;out`.csec = string_join( { - out`.csec, - "\ttest al, al\n", - "\tjz ", cf.scope_start_label(), "\n" - }, "") - ;; else - ;out`.csec = string_join( { - out`.csec, - "\ttest al, al\n", - "\tjz ", cf.scope_end_label(), "\n" - }, "") - ;/ - ;/ - - ;cur` = psl - ;; else if (tok`{cur`}.cmp("[")) - ;CompData t_outro = {"", "", ""} - ;int psl = find_closing(tok, cur) - ;int tmp = statement_list(tok, cur`, psl, current, ~t_outro, mov, ~cf) - - /; if (tmp < 0 && condition !< 0) - ;t_outro.add(outro) - ;outro = t_outro - ;; else - ;outro = t_outro - ;/ - - ;cur` = psl - ;; else - ;break - ;/ - ;/ - - /; if (cf.cf_type("loop")) - ;out`.csec = string_join( { - out`.csec, - cf.scope_start_label(), ":\n" - }, "") - ;/ - - ;cur` = next_non_nl(tok, cur`) - - ;bool returned = false - /; loop (cur` < len (tok`) && !returned) [cur` = next_non_nl(tok, cur` + 1)] - /; if (tok`{cur`}.cmp("/;")) - ;log_debug("Block in block") - ;_compile_block(tok, cur, current, out, mov, ~cf, ret) - - /; loop (tok`{cur`}.cmp(";;")) - ;_compile_block(tok, cur, current, out, mov, ~cf, ret) - ;/ - ;; else if (tok`{cur`}.cmp(";;") || (tok`{cur`}.cmp(";/") && tok`{next_non_nl(tok, cur` + 1)}.cmp("/;"))) - /; if (tok`{cur`}.cmp(";/")) - ;cur` = next_non_nl(tok, cur` + 1) - ;/ - - /; if ((cf.cf_type("if") || cf.cf_type("elif")) && tok`{next_non_nl(tok, cur` + 1)}.cmp("else")) - ;cur` = next_non_nl(tok, cur` + 1) - ;out`.csec = string_join( { - out`.csec, - cf.scope_end_label(), ":\n" - }, "") - - /; if (len (outro.csec) > 0) - ;out`.add(outro) - ;/ - - ;out`.csec = string_join( { - out`.csec, - "\tjmp ", cf.parent`.scope_end_label(), "\n", - cf.scope_rep_label(), ":\n" - }, "") - - /; if (len (outro.csec) > 0) - ;out`.add(outro) - ;/ - - ;out`.csec = string_join( { - out`.csec, - cf.scope_start_label(), ":\n" - }, "") - - ;outro = {"", "", ""} - ;condition = 0 - 1 - - /; if (tok`{next_non_nl(tok, cur` + 1)}.cmp("if")) - ;cur` = next_non_nl(tok, cur` + 1) - ;cur` = next_non_nl(tok, cur` + 1) - ;cf = cf.parent`.new_sub_cf("elif") - /; loop (cur` < len (tok`)) [cur`++] - /; if (tok`{cur`}.cmp("(") || tok`{cur`}.cmp("[")) - ;int psl = find_closing(tok, cur) - ;int tmp = statement_list(tok, cur`, psl, current, ~outro, mov, ~cf) - /; if (tmp < 0 && condition !< 0) - ;tmp = condition - ;Type t = {1, "bool", "_bool", {}, {}} - ;eval_value(tok, ~tmp, ~outro, mov, current, ~cf, t, true) - ;; else - ;condition = tmp - ;/ - - /; if (tok`{cur`}.cmp("(") && condition !< 0) - ;out`.add(outro) - ;outro = {"", "", ""} - ;out`.csec = string_join( { - out`.csec, - "\ttest al, al\n", - "\tjz ", cf.scope_start_label(), "\n" - }, "") - ;/ - ;cur` = psl - ;; else - ;break - ;/ - ;/ - - ;cur` = next_non_nl(tok, cur`) - ;cur`-- - ;; else - ;cf = cf.parent`.new_sub_cf("else") - ;/ - ;; else - /; loop (!(tok`{cur`}.cmp(";/") || tok`{cur`}.cmp(";;"))) - ;cur`-- - ;/ - ;cur`-- - ;returned = true - ;/ - ;; else if (tok`{cur`}.cmp(";/")) - ;cur`-- - ;returned = true - ;; else if (tok`{cur`}.type_is(TOKEN.KEYWORD)) - /; if (tok`{cur`}.cmp("return")) - ;cur`++ - /; if (ret.s > 0) - ;eval_value(tok, cur, out, mov, current, ~cf, ret, true) - ;/ - ;cf.end_scope(out) - ;out`.csec = string_add(out`.csec, "\tret\n") - ;; 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 - /; if (ret.s > 0) - ;eval_value(tok, cur, out, mov, current, ~cf, ret, true) - ;/ - ;out`.csec = string_add(out`.csec, "\tret\n") - ;; 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 if (tok`{cur`}.cmp("break")) - /; if (tok`{cur` + 1}.type_is(TOKEN.LITERAL)) - ;cf.br(string_to_int(tok`{cur` + 1}.data), out) - ;cur`++ - ;; else if (cf.cf_type("if") || cf.cf_type("elif") || cf.cf_type("else")) - ;cf.br(1, out) - ;; else - ;cf.br(0, out) - ;/ - ;; else if (tok`{cur`}.cmp("continue")) - /; if (tok`{cur` + 1}.type_is(TOKEN.LITERAL)) - ;cf.cont(string_to_int(tok`{cur` + 1}.data), out) - ;cur`++ - ;; else if (cf.cf_type("if") || cf.cf_type("else")) - ;cf.cont(1, out) - ;; else - ;cf.cont(0, out) - ;/ - ;; 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") - - /; if (cf.cf_type("loop")) - ;out`.csec = string_join( { - out`.csec, - cf.scope_rep_label(), ":\n" - }, "") - - /; if (len (outro.csec) > 0) - ;out`.add(outro) - ;/ - - /; if (condition !< 0) - ;out`.csec = string_join( { - out`.csec, - "\ttest al, al\n", - "\tjnz ", cf.scope_start_label(), "\n", - cf.scope_end_label(), ":\n" - }, "") - ;; else - ;out`.csec = string_join( { - out`.csec, - "\tjmp ", cf.scope_start_label(), "\n", - cf.scope_end_label(), ":\n" - }, "") - ;/ - - ;; else - ;out`.csec = string_join( { - out`.csec, - cf.scope_end_label(), ":\n" - }, "") - - /; if (len (outro.csec) > 0) - ;out`.add(outro) - ;/ - - ;out`.csec = string_join( { - out`.csec, - "\tjmp ", cf.parent`.scope_end_label(), "\n", - cf.scope_rep_label(), ":\n" - }, "") - - /; if (len (outro.csec) > 0) - ;out`.add(outro) - ;/ - - ;out`.csec = string_join( { - out`.csec, - cf.scope_start_label(), ":\n" - }, "") - ;/ - - /; if (cf.is_cf()) - ;out`.csec = string_join( { - out`.csec, - cf.parent`.scope_rep_label(), ":\n", - cf.parent`.scope_end_label(), ":\n" - }, "") - ;/ -;/ - - - - -/; compile_block (~{}Token tok, ~int cur, ~Module current, ~CompData out) - ;Scope root = {0, 0, 0, 0, "", {}, false} - ;int max = find_closing(tok, cur) - ;bool m = false, returned = false - ;Type ret = NO_TYPE - - /; 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, LOCATION.LITERAL}) - ;/ - ;/ - - /; 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("(")) - ;log_debug("Parsing params") - ;{}Variable params = parse_param_list(tok, cur, current) - /;loop (int i = 0; i < len params) [i++] - ;root.vars.append(params{i}) - ;/ - ;; if (tok`{cur`}.cmp("[")) - ;cur`++ - ;ret = get_type(tok, cur, current) - /; if (is_primitive(ret.name) < 0 && len (ret.ptr_chain) == 0) - ;ret.ptr_chain.append(PTYPE.REFERENCE) - ;/ - ;; if (tok`{cur`}.cmp("\n")) - ;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 - - ;log_debug("----------------------------") - ;log_debug(string_add("START OF BLOCK: ", l)) - ;log_debug("----------------------------") - - /; 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) - ;/ - - /; 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) - ;/ - - /; if (tok`{cur`}.cmp(";;")) - ;cur` = cur` - 1 - ;/ - ;; else if (tok`{cur`}.type_is(TOKEN.KEYWORD)) - /; if (tok`{cur`}.cmp("return")) - ;cur`++ - /; if (ret.s > 0) - ;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 - /; if (ret.s > 0) - ;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 (!returned && !string_equate(ret.name, "")) - ;log_err("Block must return a value.") - ;/ - - /; if (!m && !returned) - ;root.end_scope(out) - ;out`.csec = string_add(out`.csec, "\tret\n") - ;/ -;/ - -# 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) - ;{}uint8 name = "" - ;bool exp = false - /; loop (cur`++; cur` < len tok`) [cur`++] - /; if (tok`{cur`}.type_is(TOKEN.DEFWORD)) - ;name = tok`{cur`}.data - ;; else if (tok`{cur`}.cmp("export")) - ;exp = true - ;; else if (tok`{cur`}.cmp("method")) - ;exp = current`.exp - /; if (len name > 0) - ;name = string_add("_#", name) - ;; else if (tok`{cur` + 1}.type_is(TOKEN.DEFWORD)) - ;cur`++ - ;name = string_add("_#", tok`{cur`}.data) - ;; else - ;log_err(string_add("Tried to find name for method block, but there wasn't one nearby. ", tok`{cur`}.sprint())) - ;/ - ;; else if (!(tok`{cur`}.cmp("module"))) - ;break - ;/ - ;/ - - /; if (len name == 0) - ;log_err(string_add("Did not find name for module or pethod block. ", tok`{cur`}.sprint())) - ;/ - ;log_debug(string_add("Generating module ", name)) - - ;~Module new = find_or_create(name, current, exp) - - /; 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") || tok`{cur` + 1}.cmp("method")) - ;module_pass_one(tok, cur, new, f) - ;; else - ;new_function(tok, cur, new) - ;/ - ;; else if (tok`{cur`}.cmp("struct")) - ;new_type(tok, cur, 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) - ;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 (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) - ;; 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())) - ;/ - ;/ -;/ - -/; combine_tok_lists (int cut_a, cut_b, {}Token a, b) [{}Token] - ;{}Token out = {} - /; loop (int i = 0; i < cut_a) [i++] - ;out.append(a{i}) - ;/ - - /; loop (int i = 0; i < len b) [i++] - ;out.append(b{i}) - ;/ - - /; loop (int i = cut_b; i < len a) [i++] - ;out.append(a{i}) - ;/ - - ;return out -;/ - -# First compiler pass on a file -# Only creates structs, enums, and moduless -/; compile_file_pass_one (Path f, ~Module current) [{}Token] - ;{}Token tok = tokenize(f) - ;log_info(string_add("Number of tokens generated: ", int_to_string(len tok))) - - /; 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)) - ;{}Token inc = compile_file_pass_one(f.relative(unquote_str(tok{i + 2}.data)), current) - ;tok = combine_tok_lists(i, i + 3, tok, inc) - ;i = i + len inc - ;/ - ;continue - ;; else if (tok{i}.cmp("/;") || tok{i}.cmp(";;")) - /; if (tok{i + 1}.cmp("export") || tok{i + 1}.cmp("module") || tok{i + 1}.cmp("method")) - ;module_pass_one(~tok, ~i, current, f) - ;; else - ;new_function(~tok, ~i, current) - ;/ - ;; else if (tok{i}.cmp("struct")) - ;new_type(~tok, ~i, current) - ;/ - ;/ - - ;return tok -;/ - -/; 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 - ;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 - ;/ - ;/ - ;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) - ;/ - - /; 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 (~{}Token tok, ~Module current) [CompData] - ;CompData 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) - ;; 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())) - ;/ - ;/ - - ;log_info(string_add("File compiled! Generated code length: ", int_to_string(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, {}, {}, {}, {}, {}} - ;{}Token tok = compile_file_pass_one(f, ~root) - ;flush_structs(~root) - ;log_info("First pass DONE") - - ;CompData data = compile_file_pass_two(~tok, ~root) - ;log_info("Second pass DONE") - - ;out = string_join({ - data.hsec, - "section .data\n", - data.dsec, - "section .text\n", - data.csec}, "") - - ;return out -;/ - -## -## Main -## - -/; main ({}{}uint8 args) [int] - ;log_debug("TNSLC version 0.0.1, built with debugging enabled") - /; if (len args < 1) - ;log_info("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}) - ;/ - - ;log_info("Path: ") - ;log_info(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++] - ;log_vis(".") - ;code = string_add(code, tok{i}.sprint()) - ;/ - ;log_vis("OK\n") - ;/ - - ;p.name = string_add(p.name, ".asm") - - ;p.write(code) - - ;return 0 -;/ diff --git a/tnslc/tnslc_wrapped.tnsl b/tnslc/tnslc_wrapped.tnsl deleted file mode 100644 index 3e73778..0000000 --- a/tnslc/tnslc_wrapped.tnsl +++ /dev/null @@ -1,30 +0,0 @@ -:include "c_wrap_linux.tnsl" -:include "logging.tnsl" -:include "utils.tnsl" -:include "vector.tnsl" -:include "tokenizer.tnsl" -:include "compiler_structs.tnsl" -:include "compiler.tnsl" - -{}uint8 w_usage = "Usage: tnslc [file to compile] [file to write]" - -/; main (int argc, ~~uint8 argv) [int] - asm "mov r8, rdi" - asm "mov r9, rsi" - - /; if (argc < 3) - _printf(~w_usage{0}) - reutrn 1 - ;/ - - Path in, out - in.start(argv{1}) - out.start(argv{2}) - - compile(in, out) - - in._del() - out._del() - - return 0 -;/ diff --git a/tnslc/tokenizer.tnsl b/tnslc/tokenizer.tnsl deleted file mode 100644 index 7a15ade..0000000 --- a/tnslc/tokenizer.tnsl +++ /dev/null @@ -1,364 +0,0 @@ -# All single reserved characters -{}uint8 MULTI_PARENS = "/;:#" -{}uint8 PARENS = "()[]{}" -{}uint8 SEPS = "\n;:," -{}uint8 RESERVED = "`~!%^&*()-+=[]{}|;:/?<>.," -{}uint8 AUGMENTS = "=~!<>&|^+-*/%`." - -{}uint8 WHITESPACE = " \r\n\t" - -# All lists of keywords are comma delim because the compiler does not yet support arrays of strings -{}uint8 CSV_AUGMENTS = "++,--,==,!==,&&,||,^^,<==,>==,!>,!<,~=,`=,%=,^=,&=,*=,!=,|=,/=,<<,>>,!&,!|,!^,len,is" - -{}uint8 CSV_KEYWORDS = "if,else,loop,continue,break,return,method,struct,enum,interface,export,module,const,static,volatile,raw,extends,override,asm" - -{}uint8 CSV_KEYTYPES = "uint8,uint16,uint32,uint64,uint,int8,int16,int32,int64,int,float32,float64,float,comp32,comp64,comp,vect,bool,type,void" - -# Types of tokens -enum TOKEN_TYPE [uint] { - SEPARATOR = 0, - DELIMITER = 1, - AUGMENT = 2, - KEYTYPE = 3, - KEYWORD = 4, - LITERAL = 5, - DEFWORD = 6 -} - -# Token structure represents a single token in the program -struct Token { - uint - _type, - line, - column, - ~uint8 - data -} - -# Shortcut methods on the token struct -/; method Token - - # Initialize the data buffer - /; start - self.data = _alloc(1) - self.data{0} = 0 - ;/ - - # Append a character to the end of the token - /; append (uint8 ch) - int ln = cstr_len(self.data) - self.data = _realloc(self.data, ln + 2) - self.data{ln} = ch - self.data{ln + 1} = 0 - ;/ - - # Remove the last character from this token - /; pop - int ln = cstr_len(self.data) - self.data{ln - 1} = 0 - ;/ - - # Copy another token to this token - /; copy (Token other) - self._type = other._type - self.line = other.line - self.column = other.column - - self.data = _alloc(cstr_len(other.data) + 1) - - cstr_copy(other.data, self.data) - ;/ - - # Delete the memory associated with this token - /; _del - _realloc(self.data, 0) - ;/ - - # length of the string that this token encodes - /; _len [int] - return cstr_len(self.data) - ;/ -;/ - -{}uint8 tkn_st = "{ \0", tkn_nd = " }\n\0", tkn_sp = " \0" - -/; print_token (Token tok, ~void file_out) - write_to_file(file_out, ~tkn_st{0}) - - write_to_file(file_out, print_tok_type(tok)) - write_to_file(file_out, ~tkn_sp{0}) - write_to_file(file_out, tok.data) - - write_to_file(file_out, ~tkn_nd{0}) -;/ - -# Returns true if the character is whitespace -/; is_whitespace(uint8 c) [bool] - return contains_char(~WHITESPACE, c) -;/ - - -# Returns true if the character is reserved -/; is_reserved (uint8 c) [bool] - return contains_char(~RESERVED, c) -;/ - -# Returns true if the token is a valid reserved token -/; tok_reserved (Token tok) [bool] - /; if (tok._len() == 1) - return is_reserved(tok.data{0}) - ;; else if (tok._len() == 2) - /; if (contains_char(~MULTI_PARENS, tok.data{0}) && contains_char(~MULTI_PARENS, tok.data{1})) - return true - ;/ - ;/ - - return in_csv(~CSV_AUGMENTS, tok.data) !< 0 -;/ - -# True if the token is a valid number (integer or float) -/; is_numeric_literal(Token tok) [bool] - /; if (tok._len() < 1) - return false - ;; else if (tok.data{0} < '0' || tok.data{0} > '9') - return false - ;/ - - bool non_dec = false - /; if (tok._len() > 1 && tok.data{0} == '0') - non_dec = tok.data{1} > '9' - # TODO: non_dec not impl - ;/ - - bool dec_seen = false - - /; loop (int i = 0; i < tok._len()) [i++] - /; if (dec_seen == false && tok.data{i} == '.') - dec_seen = true - ;; else if (tok.data{i} < '0' || tok.data{i} > '9') - return false - ;/ - ;/ - - return true -;/ - -/; get_tok_type(Token tok) [uint] - /; if (tok_reserved(tok) == true) - /; if (tok._len() > 1) - /; if (contains_char(~MULTI_PARENS, tok.data{0}) && contains_char(~MULTI_PARENS, tok.data{1})) - return TOKEN_TYPE.DELIMITER - ;/ - return TOKEN_TYPE.AUGMENT - ;; else if (contains_char(~PARENS, tok.data{0}) == true) - return TOKEN_TYPE.DELIMITER - ;; else if (contains_char(~SEPS, tok.data{0}) == true) - return TOKEN_TYPE.SEPARATOR - ;; else if (contains_char(~AUGMENTS, tok.data{0}) == true) - return TOKEN_TYPE.AUGMENT - ;/ - ;; else if (in_csv(~CSV_KEYWORDS, tok.data) !< 0) - return TOKEN_TYPE.KEYWORD - ;; else if (in_csv(~CSV_KEYTYPES, tok.data) !< 0) - return TOKEN_TYPE.KEYTYPE - ;; else if (is_numeric_literal(tok) == true) - return TOKEN_TYPE.LITERAL - ;/ - - return TOKEN_TYPE.DEFWORD -;/ - - -/; break_token(~Token tok, uint8 c) [bool] - uint type_before = get_tok_type(tok`) - tok`.append(c) - uint type_after = get_tok_type(tok`) - tok`.pop() - - bool a = is_whitespace(c) && type_after !== TOKEN_TYPE.LITERAL - - bool b = false - /; if (is_reserved(c) == true) - b = type_after == TOKEN_TYPE.DEFWORD - ;; else if (tok`._len() > 0) - b = is_reserved(tok`.data{0}) - ;/ - - bool c = type_before == TOKEN_TYPE.LITERAL && type_after == TOKEN_TYPE.DEFWORD - - return a || b || c -;/ - -/; handle_comment (~void file_in) - uint8 buf = 0 - int read_count = 0 - /; loop - read_count = _read_byte(file_in, ~buf) - /; if (buf == '\n' || read_count == 0) - break - ;/ - read_count = 0 - ;/ -;/ - -/; handle_str (~void file_in, Token tmp, ~int line, column, uint8 first) [Token] - uint8 buf = first - int read_count = 0 - tmp._type = TOKEN_TYPE.LITERAL - tmp.append(buf) - read_count = 0 - - /; loop - read_count = _read_byte(file_in, ~buf) - - /; if (read_count == 0) - break - ;/ - - /; if (buf == '\\') - tmp.append(buf) - read_count = _read_byte(file_in, ~buf) - column`++ - /; if (read_count !== 0) - tmp.append(buf) - ;/ - ;; else if (buf == first) - tmp.append(buf) - break - ;; else - tmp.append(buf) - ;/ - - /; if (buf == '\n') - line`++ - column` = 1 - ;; else - column`++ - ;/ - - read_count = 0 - ;/ - - return tmp -;/ - -{}uint8 w_tkn_gen = "%d Tokens generated from file.\n\0" - -/; tokenize_file (~void file_in) [Vector] - # This vector is going to store all of our tokens as we generate them - Vector out_vect - # The size of a token struct is 3 uint + pointer = 4*8 = 32 bytes - out_vect.start(32) - - Token tmp - tmp.start() - tmp.line = 1 - tmp.column = 1 - - uint8 buf = 0 - int read_count = 0 - int line = 1 - int column = 1 - - # Read loop. - /; loop [column++] - read_count = _read_byte(file_in, ~buf) - /; if (read_count == 0) - break - ;/ - - /; if (buf == '#') - - # Handle comment - handle_comment(file_in) - line++ - - ;; else if (buf == '\'' || buf == '"') - - # Don't rope the last token into this - /; if (tmp._len() > 0) - tmp._type = get_tok_type(tmp) - out_vect.push(~tmp) - tmp.start() - ;/ - - # Handle char/string literal - tmp = handle_str(file_in, tmp, ~line, ~column, buf) - - out_vect.push(~tmp) - tmp.start() - tmp.line = line - tmp.column = column - - ;; else if (break_token(~tmp, buf) == true) - - # Handle token break - /; if (tmp._len() > 0) - tmp._type = get_tok_type(tmp) - out_vect.push(~tmp) - tmp.start() - ;/ - - tmp.line = line - tmp.column = column - /; if (is_whitespace(buf) == false) - tmp.append(buf) - ;/ - - ;; else if (is_whitespace(buf) == false) - - # Add non-whitespace - tmp.append(buf) - - ;/ - - /; if (buf == '\n') - line++ - column = 0 - ;/ - - read_count = 0 - ;/ - - /; if (tmp._len() > 0) - tmp._type = get_tok_type(tmp) - out_vect.push(~tmp) - ;/ - - _print_num(~w_tkn_gen{0}, out_vect._len()) - - return out_vect -;/ - -{}uint8 w_SEP = "SEPARATOR\0" -{}uint8 w_DEL = "DELIMITER\0" -{}uint8 w_AUG = "AUGMENT\0" -{}uint8 w_KTP = "KEYTYPE\0" -{}uint8 w_KWD = "KEYWORD\0" -{}uint8 w_LIT = "LITERAL\0" -{}uint8 w_DEF = "DEFWORD\0" - -/; print_tok_type(uint tt) [~uint8] - - ~uint8 ptr = ~w_DEF{0} - - /; if (tt == TOKEN_TYPE.SEPARATOR) - ptr = ~w_SEP{0} - ;; else if (tt == TOKEN_TYPE.DELIMITER) - ptr = ~w_DEL{0} - ;; else if (tt == TOKEN_TYPE.AUGMENT) - ptr = ~w_AUG{0} - ;; else if (tt == TOKEN_TYPE.KEYTYPE) - ptr = ~w_KTP{0} - ;; else if (tt == TOKEN_TYPE.KEYWORD) - ptr = ~w_KWD{0} - ;; else if (tt == TOKEN_TYPE.LITERAL) - ptr = ~w_LIT{0} - ;; else if (tt == TOKEN_TYPE.DEFWORD) - ptr = ~w_DEF{0} - ;/ - - return ptr - -;/ - diff --git a/tnslc/tokenizer_wrapped.tnsl b/tnslc/tokenizer_wrapped.tnsl deleted file mode 100644 index 70a074e..0000000 --- a/tnslc/tokenizer_wrapped.tnsl +++ /dev/null @@ -1,35 +0,0 @@ -:include "c_wrap_linux.tnsl" -:include "logging.tnsl" -:include "utils.tnsl" -:include "vector.tnsl" -:include "tokenizer.tnsl" - -{}uint8 w_usage = "Usage: tokenizer [file in] [file out]" - -/; main (int argc, ~~uint8 argv) [int] - asm "mov r8, rdi" - asm "mov r9, rsi" - - /; if (argc < 3) - _printf(~w_usage{0}) - return 1 - ;/ - - ~void fin = _open_file(argv{1}) - ~void fout = _create_file(argv{2}) - - Vector tokens = tokenize_file(fin) - ~Token tok - - /; loop (int i = 0; i < tokens.num_el) [i++] - tok = tokens.get(i) - print_token(tok`, fout) - tok`._del() - ;/ - - _close_file(fin) - _close_file(fout) - - return 0 -;/ - diff --git a/tnslc/utils.tnsl b/tnslc/utils.tnsl deleted file mode 100644 index a1c5884..0000000 --- a/tnslc/utils.tnsl +++ /dev/null @@ -1,122 +0,0 @@ -/; cstr_len (~uint8 cstr) [int] - int i = 0 - /; loop (cstr{i} !== 0) [i++] ;/ - return i -;/ - -/; cstr_eq (~uint8 a, b) [bool] - int ln = cstr_len(a) - /; if (ln !== cstr_len(b)) - return false - ;/ - - /; loop (int i = 0; i < ln) [i++] - /; if (a{i} !== b{i}) - return false - ;/ - ;/ - - return true -;/ - -{}uint8 csv_pr = "\0\0" - -/; in_csv ({}uint8 csv, ~uint8 cstr) [int] - int sl = cstr_len(cstr) - int cl = len csv - int seen = 0 - int idx = 0 - - /; loop (int i = 0; i < cl) [i++] - - /; if (seen < 0) - /; if (csv{i} == ',') - seen = 0 - idx++ - ;/ - continue - ;/ - - /; if (seen !< sl) - /; if (csv{i} == ',') - return idx - ;/ - seen = -1 - ;; else if (cstr{seen} == csv{i}) - csv_pr{0} = cstr{seen} - # _printf(~csv_pr{0}) - seen++ - ;; else if (csv{i} == ',') - idx++ - seen = 0 - ;; else - seen = -1 - ;/ - ;/ - - /; if (seen == sl) - return idx - ;/ - - return 0 - 1 -;/ - -/; cstr_copy (~uint8 from, to) - int ln = cstr_len(from) - - /; loop (int i = 0; i !> ln) [i++] - to{i} = from{i} - ;/ -;/ - -/; cstr_make_copy(~uint8 to_copy) [~uint8] - int l = cstr_len(to_copy) - ~uint8 out = _alloc(l + 1) - out{l} = 0 - cstr_copy(to_copy, out) - return out -;/ - -/; contains_char ({}uint8 arr, uint8 c) [bool] - /; loop (int i = 0; i < len arr) [i++] - /; if (arr{i} == c) - return true - ;/ - ;/ - return false -;/ - -/; cstr_contains (~uint8 cstr, uint8 c) [bool] - int j = cstr_len(cstr) - /; loop (int i = 0; i < j) [i++] - /; if (cstr{i} == c) - return true - ;/ - ;/ - return false -;/ - -/; write_to_file(~void file, ~uint8 string) - int ln = cstr_len(string) - /; loop (int i = 0; i < ln) [i++] - _write_byte(file, string + i) - ;/ -;/ - -/; cstr_add(~uint8 a, b) [~uint8] - int al = cstr_len(a) - int bl = cstr_len(b) - ~uint8 out = _alloc(al + bl + 1) - - /; loop (int i = 0; i < al) [i++] - out{i} = a{i} - ;/ - - /; loop (int i = 0, i < bl) [i++] - out{al + i} = b{i} - ;/ - - out{al + bl} = 0 - return out -;/ - diff --git a/tnslc/vector.tnsl b/tnslc/vector.tnsl deleted file mode 100644 index 9401508..0000000 --- a/tnslc/vector.tnsl +++ /dev/null @@ -1,100 +0,0 @@ -# 32 bytes long -struct Vector { - uint - el_size, - num_el, - dat_size, - ~uint8 dat -} - -/; method Vector - - /; resize (uint num_el) - self.dat_size = num_el - self.dat = _realloc(self.dat, num_el * self.el_size) - ;/ - - /; get (uint i) [~uint8] - /; if (i !< self.num_el) - return self.dat - ;/ - return self.dat + (i * self.el_size) - ;/ - - /; set (uint i, ~uint8 data) - ~uint8 index = self.get(i) - /; loop (i = 0; i < self.el_size) [i++] - index` = data` - index++ - data++ - ;/ - ;/ - - /; push (~uint8 data) - self.num_el++ - self.set(self.num_el - 1, data) - /; if (self.num_el !< self.dat_size) - self.resize(2 * self.dat_size) - ;/ - ;/ - - /; pop - self.num_el-- - /; if (self.num_el > 0 && self.num_el < self.dat_size / 4) - self.resize(self.dat_size / 2) - ;; else if (self.num_el < 0) - self.num_el = 0 - ;/ - ;/ - - /; remove (int index) - index++ - /; loop (index < self.num_el) [index++] - self.set(index - 1, self.get(index)) - ;/ - self.pop() - ;/ - - /; copy (Vector v) - self.dat_size = v.dat_size - self.num_el = v.num_el - self.el_size = v.el_size - self.dat = _alloc(self.dat_size * self.el_size) - - /; loop (int i = 0; i < self.num_el) [i++] - self.set(i, v.dat + i * self.el_size) - ;/ - ;/ - - /; add (Vector v) - /; loop (int i = 0; i < v._len()) [i++] - self.push(v.get(i)) - ;/ - ;/ - - # [UNSAFE] ONLY USE FOR STRING VECTORS - /; add_str (~uint8 dat) - /; loop (int i = 0; dat{i} !== 0) [i++] - self.push(dat + i) - ;/ - ;/ - - /; start (int el_size) - self.num_el = 0 - self.el_size = el_size - self.dat_size = 1 - self.dat = _alloc(self.el_size) - ;/ - - /; _len [uint] - return self.num_el - ;/ - - /; _del - self.num_el = 0 - self.el_size = 0 - self.dat_size = 0 - _delete(self.dat) - self.dat = 0 - ;/ -;/ diff --git a/tnslc/vector_test.tnsl b/tnslc/vector_test.tnsl deleted file mode 100644 index 5606d80..0000000 --- a/tnslc/vector_test.tnsl +++ /dev/null @@ -1,36 +0,0 @@ -:include "c_wrap_linux.tnsl" -:include "vector.tnsl" - -/; main (int argc, ~~uint argv) [int] - # On windows, the first two arguments are passed in RCX and RDX, so we need to - # update their positions here or else tnsl will have garbage values in r8 and r9 - # asm "mov r8, rcx" - # asm "mov r9, rdx" - - # If on linux, you would use rdi and rsi instead of rcx and rdx, respectively - # simply comment out the bove asm, and uncomment the below lines - asm "mov r8, rdi" - asm "mov r9, rsi" - - Vector vec - vec.start(1) - - int mx = 100 - uint8 buf = 0 - /; loop (int i = 0; i < mx) [i++] - buf = 'A' + i - vec.push(~buf) - ;/ - - buf = 0 - vec.push(~buf) - - _printf(vec.dat) - - /; loop (int i = 0; i < mx + 1) [i++] - vec.pop() - ;/ - - vec._del() - return 0 -;/ |