summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--tnslc/README.md8
-rw-r--r--tnslc/basic.tnsl8
-rw-r--r--tnslc/compiler.tnsl272
-rw-r--r--tnslc/compiler_structs.tnsl480
-rw-r--r--tnslc/copy.tnsl39
-rw-r--r--tnslc/else.tnsl19
-rw-r--r--tnslc/enum.tnsl13
-rw-r--r--tnslc/hello.tnsl33
-rw-r--r--tnslc/logging.tnsl75
-rw-r--r--tnslc/read_file_test.tnsl44
-rw-r--r--tnslc/run.ps111
-rwxr-xr-xtnslc/run.sh25
-rw-r--r--tnslc/simple.tnsl29
-rw-r--r--tnslc/str_test.tnsl9
-rw-r--r--tnslc/tnslc.tnsl4113
-rw-r--r--tnslc/tnslc_wrapped.tnsl30
-rw-r--r--tnslc/tokenizer.tnsl364
-rw-r--r--tnslc/tokenizer_wrapped.tnsl35
-rw-r--r--tnslc/utils.tnsl122
-rw-r--r--tnslc/vector.tnsl100
-rw-r--r--tnslc/vector_test.tnsl36
22 files changed, 17 insertions, 5851 deletions
diff --git a/.gitignore b/.gitignore
index 217d483..a5ec8be 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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
-;/