summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libtnsl/libtnsl.tnsl3
-rw-r--r--tnslc/compile.tnsl1503
-rw-r--r--tnslc/compile/compile.tnsl768
-rw-r--r--tnslc/compile/isa_x86.tnsl182
-rw-r--r--tnslc/compile/value.tnsl362
-rw-r--r--tnslc/copy.tnsl30
-rw-r--r--tnslc/dummy.tnsl33
-rw-r--r--tnslc/inc.tnsl3
-rw-r--r--tnslc/parse/parse.tnsl87
-rw-r--r--tnslc/parse/token.tnsl331
-rw-r--r--tnslc/parse/tokenizer.tnsl114
-rw-r--r--tnslc/paths.tnsl103
-rw-r--r--tnslc/test.tnsl21
-rw-r--r--tnslc/tests/complex/enums.tnsl84
-rw-r--r--tnslc/tests/complex/generics.tnsl35
-rw-r--r--tnslc/tests/complex/if_else.tnsl46
-rw-r--r--tnslc/tests/complex/interfaces.tnsl0
-rw-r--r--tnslc/tests/complex/loops.tnsl0
-rw-r--r--tnslc/tests/complex/switch.tnsl0
-rw-r--r--tnslc/tests/simple/comments.tnsl52
-rw-r--r--tnslc/tests/simple/if_else.tnsl0
-rw-r--r--tnslc/tests/simple/includes_a.tnsl1
-rw-r--r--tnslc/tests/simple/includes_b.tnsl0
-rw-r--r--tnslc/tests/simple/modules_a.tnsl0
-rw-r--r--tnslc/tests/simple/modules_b.tnsl0
-rw-r--r--tnslc/tests/simple/structs.tnsl0
-rw-r--r--tnslc/tnslc.tnsl43
-rw-r--r--tnslc/util.tnsl199
28 files changed, 1744 insertions, 2256 deletions
diff --git a/libtnsl/libtnsl.tnsl b/libtnsl/libtnsl.tnsl
index 56d7e1e..91894e4 100644
--- a/libtnsl/libtnsl.tnsl
+++ b/libtnsl/libtnsl.tnsl
@@ -20,10 +20,11 @@
#/
/;export module tnsl
- ; const ~void _null = 0x0
+ ;const ~void _null = 0xDEADC0DE
/: import
"algo"
+ "asm"
"box"
"io"
"math"
diff --git a/tnslc/compile.tnsl b/tnslc/compile.tnsl
new file mode 100644
index 0000000..8bad758
--- /dev/null
+++ b/tnslc/compile.tnsl
@@ -0,0 +1,1503 @@
+##
+## UTIL FUNCS
+##
+
+/; string_split ({}uint8 str, uint8 split) [{}{}uint8]
+ /; if (len str == 0)
+ ;return {}
+ ;/
+
+ ;{}{}uint8 out = {}
+
+ ;{}uint8 run = ""
+
+ /; loop (int i = 0; i < len str) [i++]
+ /; if (str{i} == split)
+ ;out.append(run)
+ ;run = ""
+ ;; else
+ ;run.append(str{i})
+ ;/
+ ;/
+
+ ;out.append(run)
+
+ ;return out
+;/
+
+/; string_join ({}{}uint8 strs, {}uint8 join) [{}uint8]
+ ;{}uint8 out = ""
+ /; loop (int i = 0; i < len strs) [i++]
+ ;out = string_add(out, strs{i})
+ /; if (i !== len strs - 1)
+ ;out = string_add(out, join)
+ ;/
+ ;/
+ ;return out
+;/
+
+/; string_add ({}uint8 base, add) [{}uint8]
+ /; loop (int i = 0; i < len add) [i++]
+ ;base.append(add{i})
+ ;/
+ ;return base
+;/
+
+/; string_equate ({}uint8 a, b) [bool]
+ /; if (len a !== len b)
+ ;return false
+ ;/
+
+ /; loop (int i = 0; i < len a) [i++]
+ /; if (a{i} !== b{i})
+ ;return false
+ ;/
+ ;/
+
+ ;return true
+;/
+
+/; string_contains ({}uint8 str, uint8 chk) [bool]
+ /; loop (int i = 0; i < len str) [i++]
+ /; if (str{i} == chk)
+ ;return true
+ ;/
+ ;/
+ ;return false
+;/
+
+/; list_contains ({}{}uint8 list, {}uint8 str) [bool]
+ /; loop (int i = 0; i < len list) [i++]
+ /; if (string_equate(list{i}, str))
+ ;return true
+ ;/
+ ;/
+ ;return false
+;/
+
+/; unqote_char ({}uint8 str) [uint8]
+ /; if (len str < 3)
+ ;return 0
+ ;/
+
+ ;uint8 cmp = str{2}
+ /; if (cmp == '\\')
+ ;return '\\'
+ ;; else if (cmp == 'n')
+ ;return '\n'
+ ;; else if (cmp == 'r')
+ ;return '\r'
+ ;/
+
+;/
+
+/; unquote_str({}uint8 str) [{}uint8]
+ /; if (str{0} !== '\'' && str{0} !== '"')
+ ;return str
+ ;/
+ ;{}uint8 out = ""
+
+ /; loop (int i = 1; i < len str - 1) [i++]
+ /; if (str{i} == '\\')
+ ;{}uint8 unq = "'\\"
+ ;unq.append(str{i + 1})
+ ;out.append(unqote_char(unq))
+ ;i++
+ ;; else
+ ;out.append(str{i})
+ ;/
+ ;/
+
+ ;return out
+;/
+
+/; int_to_string (int i) [{}uint8]
+ /; if (i == 0)
+ ;return "0"
+ ;/
+
+ ;{}uint8 out = ""
+
+ /; if (i < 0)
+ ;out.append('-')
+ ;i = -i
+ ;/
+
+ /; loop [i = i / 10; i > 0]
+ ;out.append('0' + (i % 10))
+ ;/
+
+ ;return out
+;/
+
+/; digit_from_base (uint8 ch, int base) [int]
+ /; if (ch == '-')
+ ;return 0
+ ;/
+
+ /; if (base !> 10)
+ ;return ch - '0'
+ ;; if (base == 16)
+ /; if (ch !< 'A' && ch < 'G')
+ ;return 11 + (ch - 'A')
+ ;; else if (ch !< 'a' && ch < 'g')
+ ;return 11 + (ch - 'a')
+ ;/
+ ;return ch - '0'
+ ;/
+ ;return 0
+;/
+
+/; string_to_int ({}uint8 str) [int]
+ /; if (len str < 1)
+ ;return 0
+ ;/
+ ;int i = 0
+ ;bool inv = str{0} == '-'
+ /; if (inv)
+ ;i = 1
+ ;/
+
+ ;int out = 0
+ ;int base = 10
+
+ /; if (len str !< 3 && str{i} == '0')
+ /; if (str{i + 1} == 'x')
+ ;base = 16
+ ;i = i + 2
+ ;; if (str{i + 1} == 'b')
+ ;base = 2
+ ;i = i + 2
+ ;; if (str{i + 1} == 'o')
+ ;base = 8
+ ;i = i + 2
+ ;/
+ ;/
+
+ /; loop (i < len str) [i++]
+ ;out = out * base
+ ;out = out + digit_from_base(str{i}, base)
+ ;/
+
+ /; if (inv)
+ ;out = -out
+ ;/
+ ;return out
+;/
+
+##
+## Structs
+##
+
+# The seperated string sections that make up an asm file
+;struct CompData {
+ {}uint8
+ hsec,
+ dsec,
+ csec
+}
+
+# Represents a relative file path
+;struct Path {
+ {}{}uint8 path,
+ {}uint8 name
+}
+
+/; method Path
+
+ /; relative ({}uint8 rel_path) [Path]
+ ;Path out = self
+ ;{}{}uint8 rel_split = string_split(rel_path, '/')
+
+ /; loop (int i = 0; i < len rel_split - 1)
+ ;out.path.append(rel_split{i})
+ ;/
+
+ ;out.name = rel_split{len rel_split - 1}
+
+ ;return out
+ ;/
+
+ /; full_path [{}uint8]
+ ;{}uint8 out = string_join(self.path, "/")
+ /; if (len out > 0)
+ ;out.append('/')
+ ;/
+ ;return string_add(out, self.name)
+ ;/
+
+ /; extension [{}uint8]
+ ;{}{}uint8 split_name = string_split(self.name, '.')
+
+ /; if (len split_name > 1)
+ ;return split_name{len split_name - 1}
+ ;/
+
+ ;return ""
+ ;/
+
+ /; open_read [tnsl.io.File]
+ ;return tnsl.io.readFile(self.full_path())
+ ;/
+
+ /; write ({}uint8 bytes)
+ ;tnsl.io.File out = tnsl.io.writeFile(self.full_path())
+
+ /; loop (int i = 0; i < len bytes) [i++]
+ ;out.write(bytes{i})
+ ;/
+
+ ;out.close()
+ ;/
+;/
+
+# Represents the different classes of token
+;enum TOKEN [int] {
+ SEPARATOR = 0,
+ DELIMITER = 1,
+ AUGMENT = 2,
+ KEYTYPE = 3,
+ KEYWORD = 4,
+ LITERAL = 5,
+ DEFWORD = 6
+}
+
+# Represents a single token in a TNSL file
+;struct Token {
+ int
+ tokenType,
+ line,
+
+ {}uint8 data
+}
+
+/; method Token
+
+ /; type_is (int a) [bool]
+ ;return self.tokenType == a
+ ;/
+
+ /; cmp ({}uint8 str) [bool]
+ ;return string_equate(self.data, str)
+ ;/
+
+ /; print
+ ;tnsl.io.print(self.data)
+ ;tnsl.io.print(": { type: ")
+ ;tnsl.io.print(self.tokenType)
+ ;tnsl.io.print(" line: ")
+ ;tnsl.io.print(self.line)
+ ;tnsl.io.print(" }")
+ ;/
+
+ /; sprint [{}uint8]
+ ;{}uint8 out = "{ "
+ ;out = string_add(out, self.data)
+ ;out.append(' ')
+ ;out = string_add(out, int_to_string(self.tokenType))
+ ;out.append(' ')
+ ;out.append('}')
+ ;return out
+ ;/
+;/
+
+# General defs:
+## Type defs
+## Function defs
+## Method defs
+## Module defs
+## Constant and variable defs
+
+# Module
+## General defs
+
+# Block
+## Variable defs
+## Control flow defs
+## Value defs
+
+;enum PTYPE [int] {
+ POINTER = 0,
+ REFERENCE = 1,
+ ARRAY = 2
+}
+
+# Represents a data type
+;struct Type {
+ int s,
+ {}uint8
+ name,
+ mod_name,
+ {}int
+ ptr_chain,
+ {}Variable
+ members
+}
+
+;{}{}uint8 PRIM_NAMES = {
+ "uint8", "uint16", "uint32", "uint64", "uint",
+ "int8", "int16", "int32", "int64", "int",
+ "float32", "float64", "float",
+ "bool", "void"
+}
+
+;{}int PRIM_SIZES = {
+ 1, 2, 4, 8, 8,
+ 1, 2, 4, 8, 8,
+ 4, 8, 8,
+ 1,
+ 8
+}
+
+;Type NO_TYPE = {0, "", "", {}, {}}
+
+/; is_primitive ({}uint8 t) [int]
+ ;{}{}uint8 pn = PRIM_NAMES
+ ;{}int ps = PRIM_SIZES
+ /; loop (int i = 0; i < len pn) [i++]
+ /; if (string_equate(pn{i}, t))
+ ;return ps{i}
+ ;/
+ ;/
+ ;return -1
+;/
+
+# Represents the place in memory where a variable is
+;enum LOCATION [int] {
+ REGISTER = 0,
+ STACK = 1,
+ LABEL = 2,
+ LITERAL = 3
+}
+
+# Represents a variable
+;struct Variable {
+ {}uint8
+ name,
+ Type
+ data_type,
+ int
+ location,
+ loc_type
+}
+
+# Get common register name by index
+/; reg_by_num(int r) [{}uint8]
+ /; if (r == 0)
+ ;return "ax"
+ ;; if (r == 1)
+ ;return "bx"
+ ;; if (r == 2)
+ ;return "cx"
+ ;; if (r == 3)
+ ;return "dx"
+ ;; if (r == 4)
+ ;return "si"
+ ;; if (r == 5)
+ ;return "di"
+ ;; if (r == -1)
+ ;return "sp"
+ ;; if (r == -2)
+ ;return "bp"
+ ;/
+ ;return int_to_string(r + 2)
+;/
+
+# Get common register by common name and size
+/; reg_by_name_size ({}uint8 common, uint sz) [{}uint8]
+ ;{}uint8 out = "%"
+
+ /; if (common{0} !< 'a')
+
+ /; if (sz == 1)
+ /; if(common{1} == 'x')
+ ;common{1} = 'l'
+ ;; else
+ ;common.append('l')
+ ;/
+ ;; else if (sz == 4)
+ ;out.append('e')
+ ;; else if (sz == 8)
+ ;out.append('r')
+ ;/
+
+ ;string_add(out, common)
+
+ ;; else
+
+ ;out.append('r')
+ ;string_add(out, common)
+ /; if (sz == 1)
+ ;out.append('b')
+ ;; else if (sz == 2)
+ ;out.append('w')
+ ;; else if (sz == 4)
+ ;out.append('d')
+ ;/
+ ;return out
+ ;/
+
+ ;return out
+;/
+
+/; get_reg (int r, sz) [{}uint8]
+ ;return reg_by_name_size(reg_by_num(r), sz)
+;/
+
+# Most methods make use of one or more temporary variables.
+# These are denoted by tr
+/; method Variable
+
+ /; norm_loc (int sz) [{}uint8]
+ /; if (self.loc_type == LOCATION.LABEL)
+ ;return ""
+ ;; else if (self.loc_type == LOCATION.REGISTER)
+ ;return get_reg(self.location, sz)
+ ;; else if (self.loc_type == LOCATION.STACK)
+ ;return string_join( { "[ rsp + ", int_to_string(self.location), " ]" } , "")
+ ;/
+ ;/
+
+ /; norm_size [int]
+ /; if (len (self.data_type.ptr_chain) > 0)
+ ;return 8
+ ;; else
+ ;return self.data_type.s
+ ;/
+ ;/
+
+ /; norm_op ({}uint8 op, {}{}uint8 args) [{}uint8]
+ ;return string_join(
+ {
+ "\t", op, " ",
+ string_join(args, ", "), "\n"
+ },
+ ""
+ )
+ ;/
+
+ # functions that do work on this variable
+ /; add (Variable v, int tr) [{}uint8]
+ /; if (self.loc_type == LOCATION.LITERAL)
+ /; if (v.loc_type !== LOCATION.LITERAL)
+ ;return v.add(self)
+ ;/
+ ;self.location = self.location + v.location
+ ;return ""
+ ;; if (self.loc_type == LOCATION.STACK && v.loc_type == LOCATION.STACK)
+ ;{}uint8 tmp = get_reg(tr, self.norm_size())
+ ;{}uint8 out = self.norm_op("mov", { tmp, v.norm_loc(self.norm_size()) })
+ ;return string_add(out, self.norm_op("add", { self.norm_loc(self.norm_size()), tmp }))
+ ;/
+ ;return self.norm_op("add", { self.norm_loc(self.norm_size()), get_reg(tr, self.norm_size()) })
+ ;/
+
+ /; sub (Variable v)
+ /; if (self.loc_type == LOCATION.LITERAL)
+ /; if (v.loc_type !== LOCATION.LITERAL)
+ ;return v.add(self)
+ ;/
+ ;self.location = self.location - v.location
+ ;return ""
+ ;; if (self.loc_type == LOCATION.STACK && v.loc_type == LOCATION.STACK)
+ ;{}uint8 tmp = get_reg(tr, self.norm_size())
+ ;{}uint8 out = self.norm_op("mov", { tmp, v.norm_loc(self.norm_size()) })
+ ;return string_add(out, self.norm_op("sub", { self.norm_loc(self.norm_size()), tmp }))
+ ;/
+ ;return self.norm_op("sub", { self.norm_loc(self.norm_size()), get_reg(tr, self.norm_size()) })
+ ;/
+
+ /; div (Variable v)
+ /; if (self.loc_type == LOCATION.LITERAL)
+ /; if (v.loc_type !== LOCATION.LITERAL)
+ ;return v.div(self)
+ ;/
+ ;self.location = self.location + v.location
+ ;return ""
+ ;; if (self.loc_type == LOCATION.STACK && v.loc_type == LOCATION.STACK)
+ ;{}uint8 out = ""
+ # TODO
+ ;return out
+ ;/
+ ;return self.norm_op("div", { self.norm_loc(self.norm_size()), v.norm_loc(self.norm_size) })
+ ;/
+
+ /; mul (Variable v)
+ /; if (self.loc_type == LOCATION.LITERAL)
+ /; if (v.loc_type !== LOCATION.LITERAL)
+ ;return v.mul(self)
+ ;/
+ ;self.location = self.location * v.location
+ ;return ""
+ ;; if (self.loc_type == LOCATION.STACK && v.loc_type == LOCATION.STACK)
+ ;{}uint8 out = ""
+ # TODO
+ ;return out
+ ;/
+ ;return self.norm_op("mul", { self.norm_loc(self.norm_size()), v.norm_loc(self.norm_size) })
+ ;/
+
+ /; set (Variable v)
+ /; if (self.loc_type == LOCATION.LITERAL)
+ /; if (v.loc_type !== LOCATION.LITERAL)
+ ;return v.set(self)
+ ;/
+ ;self.location = v.location
+ ;return ""
+ ;; if (self.loc_type == LOCATION.STACK && v.loc_type == LOCATION.STACK)
+ ;{}uint8 out = ""
+ # TODO
+ ;return out
+ ;/
+ ;return self.norm_op("mov", { self.norm_loc(self.norm_size()), v.norm_loc(self.norm_size) })
+ ;/
+
+ # functions that do work on another variable
+ /; ref (Variable out)
+ ;/
+
+ /; deref (Variable out)
+ ;/
+
+ /; member (Variable out, {}uint8 name)
+ ;/
+
+ /; index (Variable out, Variable i)
+ /;
+
+ ;/
+ ;/
+
+ /; call (Variable out, {}uint8 name)
+ ;/
+;/
+
+;struct Scope {
+ {}Variable vars
+}
+
+;struct Function {
+ {}uint8 name,
+ {}Type
+ inputs,
+ outputs
+}
+
+;struct Module {
+ # Parent module
+ ~Module parent,
+ # Export functions or not
+ bool exp,
+ # Name of module
+ {}uint8 name,
+ # Types defined in this module
+ {}Type types,
+ # Variables defined in this module
+ {}Variable defs,
+ # Functions defined in this module
+ {}Function functions,
+ # Sub modules
+ {}Module sub
+}
+
+/; method Module
+ # Internal recursive function
+ /; _find_type ({}{}uint8 artifact, int r) [~Type]
+ /; if (len artifact !> r)
+ ;return ~NO_TYPE
+ ;/
+
+ /; if (len artifact - 1 > r)
+ /; loop (int i = 0; i < len (self.sub)) [i++]
+ /; if (string_equate(artifact{r}, self.sub{i}.name))
+ ;return self._find_type(artifact, r + 1)
+ ;/
+ ;/
+ ;/
+
+ /; loop (int i = 0; i < len (self.types)) [i++]
+ /; if (string_equate(self.types{i}.name, artifact{r}))
+ ;return ~(self.types{i})
+ ;/
+ ;/
+
+ ;Type nt = {0, artifact{len artifact - 1}, "", {}, {}}
+ ;return ~nt
+ ;/
+
+ # Consumer facing function
+ /; find_type ({}{}uint8 artifact) [~Type]
+ ;int p = is_primitive(artifact{0})
+ /; if (p !< 0)
+ ;Type out = {p, artifact{0}, {}, {}, {}}
+ ;return ~out
+ ;/
+
+ ;return self._find_type(artifact, 0)
+ ;/
+
+ /; _find_def ({}{}uint8 artifact, int r) [Variable]
+ /; if (len artifact !> r)
+ ;retirn {{}, "", 0, 0, 0}
+ ;/
+
+ /; if (len artifact - 1 > r)
+ /; loop (int i = 0; i < len (self.sub)) [i++]
+ /; if (string_equate(artifact{r}, self.sub{i}.name))
+ ;return self._find_type(artifact, r + 1)
+ ;/
+ ;/
+ ;/
+
+ /; loop (int i = 0; i < len (self.defs)) [i++]
+ /; if (string_equate(self.defs{i}.name, artifact{r}))
+ ;return self.defs{i}
+ ;/
+ ;/
+
+ ;return {{}, "", 0, 0, 0}
+ ;/
+
+ /; find_def ({}{}uint8 artifact) [Variable]
+ ;return _find_def(artifact, 0)
+ ;/
+
+ /; _find_function ({}{}uint8 artifact, int r) [Variable]
+ /; if (len artifact !> r)
+ ;retirn {{}, "", 0, 0, 0}
+ ;/
+
+ /; if (len artifact - 1 > r)
+ /; loop (int i = 0; i < len (self.sub)) [i++]
+ /; if (string_equate(artifact{r}, self.sub{i}.name))
+ ;return self._find_type(artifact, r + 1)
+ ;/
+ ;/
+ ;/
+
+ /; loop (int i = 0; i < len (self.funcs)) [i++]
+ /; if (string_equate(self.funcs{i}.name, artifact{r}))
+ ;return self.funcs{i}
+ ;/
+ ;/
+
+ ;return {{}, "", 0, 0, 0}
+ ;/
+
+ /; find_function ({}{}uint8 artifact) [Variable]
+ ;return _find_function(artifact, 0)
+ ;/
+
+ /; full_path [{}uint8]
+ /; if (string_equate(self.name, ""))
+ ;return ""
+ ;/
+ ;{}uint8 out = self.parent`.full_path()
+ /; if (len out > 0)
+ ;out = string_add(out, ".")
+ ;/
+ ;out = string_add(out, self.name)
+ ;return out
+ ;/
+;/
+
+##
+## Compiler funcs
+##
+
+/; get_artifact (~{}Token tok, ~int cur) [{}{}uint8]
+ ;{}{}uint8 out = {}
+
+ ;out.append(tok`{cur`}.data)
+ ;cur`++
+
+ /; loop (cur` < len tok` && tok`{cur`}.cmp(".")) [cur`++]
+ /; if (tok`{cur` + 1}.type_is(TOKEN.DEFWORD))
+ ;out.append(tok`{cur` + 1}.data)
+ ;cur`++
+ ;/
+ ;/
+ ;return out
+;/
+
+/; get_type (~{}Token tok, ~int cur, ~Module current) [Type]
+ ;{}int ptr_chain = {}
+
+ /; loop (cur` < len tok`) [cur`++]
+ /; if (tok`{cur`}.cmp("{"))
+ ;ptr_chain.append(PTYPE.ARRAY)
+ ;cur`++
+ ;; else if (tok`{cur`}.cmp("~"))
+ ;ptr_chain.append(PTYPE.POINTER)
+ ;; else
+ ;break
+ ;/
+ ;/
+
+ ;~Type pout = current`.find_type(get_artifact(tok, cur))
+ ;Type out = pout`
+ /; if (string_equate(out.name, ""))
+ ;return out
+ ;/
+
+ ;{}Type generics = {}
+ /; if (tok`{cur`}.cmp("("))
+ ;int max = find_closing(tok, cur)
+ ;cur`++
+ /; loop (cur` < max) [cur`++]
+ ;generics.append(get_type(tok, cur, current))
+ ;/
+ ;/
+
+ # TODO: References
+
+ ;out.ptr_chain = ptr_chain
+ ;return out
+;/
+
+/; is_definition (~{}Token tok, ~int cur) [bool]
+ ;return false
+;/
+
+/; compile_file_def (~{}Token tok, ~int cur, Type t, ~Module current) [{}Variable]
+ ;return {}
+;/
+
+/; next_non_nl (~{}Token tok, int c) [int]
+ /; loop (tok`{c}.cmp("\n")) [c++] ;/
+ ;return c
+;/
+
+/; parse_param_list (~{}Token tok, ~int cur, ~Module current) [{}Variable]
+ ;{}Variable out = {}
+ ;int max = find_closing(tok, cur)
+ ;Type t = NO_TYPE
+ /; loop (cur` = next_non_nl(tok, cur` + 1); cur` < max) [cur` = next_non_nl(tok, cur` + 1)]
+ ;int nnl = next_non_nl(tok, cur` + 1)
+ /; if (tok`{nnl}.cmp(",") || nnl == max)
+ ;out.append({tok`{cur`}.data, t, 0, 0})
+ /; if (tok`{nnl}.cmp(","))
+ ;cur`++
+ ;/
+ ;; else
+ ;t = get_type(tok, cur, current)
+ ;cur` = cur` - 1
+ ;/
+ ;/
+ ;return out
+;/
+
+# Generates new type
+/; new_type (~{}Token tok, ~int cur, ~Module current)
+ ;cur`++
+ ;Type out = {0, tok`{cur`}.data, "", {}, {}}
+ ;out.mod_name = string_add(current`.full_path(), "_#")
+ ;out.mod_name = string_add(out.mod_name, out.name)
+ ;current`.sub.append({current, current`.exp, out.mod_name, {}, {}, {}, {}})
+
+ /; loop (cur` < len tok`) [cur`++]
+ /; if (tok`{cur`}.cmp("{"))
+ ;break
+ ;/
+ ;/
+
+ ;out.members = parse_param_list(tok, cur, current)
+ /; loop (int i = 0; i < len (out.members)) [i++]
+ ;tnsl.io.print(string_join({"[", out.members{i}.name, ":", out.members{i}.data_type.name, "]"}, ""))
+ ;/
+
+ ;tnsl.io.print(string_add("Generated type ", string_add(out.name, string_add(":", out.mod_name))))
+ ;current`.types.append(out)
+;/
+
+/; decompose_empty (~Module current, Type t) [{}uint8]
+ ;return ""
+;/
+
+# Used to take an array literal and make it into a label
+/; decompose_array (~{}Token tok, ~int cur, ~Module current, Type t) [{}uint8]
+ ;int max = find_closing(tok, cur)
+ ;{}uint8 arr = ""
+ ;int alen = 0
+
+ /; loop (cur`++; cur` < max) [cur`++]
+ ;alen++
+
+ /; if (tok`{cur`}.cmp("{"))
+ /; if (ptr_chain{0} == PTYPE.ARRAY)
+ ;{}int ptr = {}
+ /; loop (int i = 1; i < len (t.ptr_chain)) [i++]
+ ;ptr.append(t.ptr_chain{i})
+ ;/
+ ;t.ptr_chain = ptr
+ ;arr = string_add(arr, decompose_array(tok, cur, current, t))
+ ;cur`++
+ ;; else
+ ;decompose_struct(tok, cur, current, t)
+ ;cur`++
+ ;/
+ ;; else
+ ;arr = string_add(arr, decompose_data(tok, cur, current, t))
+ ;cur`++
+ ;/
+ ;/
+
+ ;{}uint out = string_join( { "\tdq ", int_to_string(alen), "\n", arr, "\n" }, "")
+
+ ;return out
+;/
+
+# Used to take a struct literal and make it into a label
+/; decompose_struct (~{}Token tok, ~int cur, ~Module current, Type t) [{}uint8]
+ ;int max = find_closing(tok, cur)
+ ;{}uint8 out = ""
+ ;int m = 0
+ /; loop (cur`++; cur` < max) [cur`++]
+ /; if (tok`{cur`}.cmp("}"))
+ ;break
+ ;; else if (tok`{cur`}.cmp(","))
+ ;cur`++
+ ;/
+ ;out = string_add(out, decompose_data(tok, cur, current, t.members{m}.data_type))
+ ;m++
+ ;/
+
+ /; if (m < len (t.members) - 1)
+ /; loop (m < len (t.members)) [m++]
+ ;out = string_add(out, decompose_empty(current, t.members{m}))
+ ;/
+ ;/
+
+ ;return out
+;/
+
+/; declare_size(int sz) [{}uint8]
+ ;{}uint8 out = "\tdb "
+
+ /; if (sz == 2)
+ ;out{2} = 'w'
+ ;; if (sz == 4)
+ ;out{2} = 'd'
+ ;; if (sz == 8)
+ ;out{2} = 'q'
+ ;/
+
+ ;return out
+;/
+
+# Used to take data from a literal and make it into a label
+/; decompose_data (~{}Token tok, ~int cur, ~Module current, Type t) [{}uint8]
+ /; if (tok`{cur`}.cmp("{"))
+ /; if (len (t.ptr_chain) > 0)
+ ;{}int ptr = {}
+ /; loop (int i = 1; i < len (t.ptr_chain)) [i++]
+ ;ptr.append(t.ptr_chain{i})
+ ;/
+ ;t.ptr_chain = ptr
+ ;return decompose_array(tok, cur, current, t)
+ ;; else
+ ;return decompose_struct(tok, cur, current, t)
+ ;/
+ ;; if (tok`{cur`}.type_is(TOKEN.LITERAL))
+ /; if (tok`{cur`}.data{0} == '"')
+ ;return string_join({
+ declare_size(8), int_to_string(len unquote_str(tok`{cur`}.data)), "\n",
+ declare_size(1), tok`{cur`}.data, "\n"}, "")
+ ;; else if (tok`{cur`}.data{0} == '\'')
+ ;return string_join({
+ declare_size(1), tok`{cur`}.data, "\n"}, "")
+ ;/
+ ;return string_add(string_add(declare_size(t.s), tok`{cur`}.data), "\n")
+ ;/
+
+ ;return decompose_empty(current, t)
+;/
+
+# Compiles new enum for the file
+/; compile_enum (~{}Token tok, ~int cur, ~Module current) [{}uint8]
+ ;cur`++
+ ;Type et = NO_TYPE
+ ;{}uint8 name = ""
+
+ /; if (tok`{cur`}.cmp("["))
+ ;cur`++
+ ;et = get_type(tok, cur, current)
+ ;cur`++
+ ;; if (!(tok`{cur`}.cmp("{")))
+ ;name = tok`{cur`}.data
+ ;cur`++
+ /; if (tok`{cur`}.cmp("["))
+ ;cur`++
+ ;et = get_type(tok, cur, current)
+ ;cur`++
+ ;/
+ ;/
+
+ /; if (string_equate(et.name, ""))
+ ;et = Primitives{3}
+ ;/
+
+ /; loop (!(tok`{cur`}.cmp("{"))) [cur`++] ;/
+ ;cur`++
+
+ ;Module enum_mod = {current, current`.exp, string_add("__#", name), {}, {}, {}, {}}
+
+ ;{}uint8 out = ""
+
+ /; loop (cur` < len tok`) [cur`++]
+ /; if (tok`{cur`}.cmp("}"))
+ ;break
+ ;/
+
+ /; if (tok`{cur`}.type_is(TOKEN.DEFWORD))
+ ;{}uint8 l = string_add(enum_mod.full_path(), ".")
+ ;l = string_add(l, tok`{cur`}.data)
+ ;l.append(':')
+ ;l.append('\n')
+ ;cur` = cur` + 2
+ ;l = string_add(l, decompose_data(tok, cur, current, et))
+ ;out = string_add(out, l)
+ ;/
+ ;/
+
+ ;current`.sub.append(enum_mod)
+
+ ;return out
+;/
+
+# Generates opposite closing bracket
+/; closing_for (Token d) [{}uint8]
+ /; if (d.cmp("("))
+ ;return ")"
+ ;; else if (d.cmp("["))
+ ;return "]"
+ ;; else if (d.cmp("{"))
+ ;return "}"
+ ;/
+ ;tnsl.io.println(string_add("Error, unrecognized delim: ", d))
+;/
+
+# Finds closing bracket
+/; find_closing (~{}Token tok, ~int cur) [int]
+ ;int bl = 0, p = 0, br = 0, c = 0
+ ;{}uint8 cl = closing_for(tok`{cur`})
+
+ /; loop (int i = cur` + 1; i < len tok`) [i++]
+ /; if (bl == 0 && p == 0 && br == 0 && c == 0)
+ /; if ((tok`{i}.cmp(";;") || tok`{i}.cmp(";:")) && string_equate(cl, "/;"))
+ ;return i
+ ;; else if (tok`{i}.cmp(cl))
+ ;return i
+ ;/
+ ;/
+
+ /; if (tok`{i}.cmp("("))
+ ;p++
+ ;; else if (tok`{i}.cmp("["))
+ ;br++
+ ;; else if (tok`{i}.cmp("{"))
+ ;c++
+ ;; else if (tok`{i}.cmp("/;"))
+ ;bl++
+ ;/
+
+ /; if (tok`{i}.cmp(")"))
+ ;p = p - 1
+ ;; else if (tok`{i}.cmp("]"))
+ ;br = br - 1
+ ;; else if (tok`{i}.cmp("}"))
+ ;c = c - 1
+ ;; else if (tok`{i}.cmp(";/") || tok`{i}.cmp(";:"))
+ ;bl = bl - 1
+ ;/
+ ;/
+
+ ;return len tok` - 1
+;/
+
+# Skips cur to the end of a struct
+/; skip_struct (~{}Token tok, ~int cur)
+ ;{}uint8 name = tok`{cur` + 1}.data
+ /; loop (cur` < len tok`) [cur`++]
+ /; if (tok`{cur`}.cmp("{"))
+ ;cur` = find_closing(tok, cur)
+ ;break
+ ;/
+ ;/
+;/
+
+# TODO:
+/; compile_function (~{}Token tok, ~int cur, ~CompData out, ~Module current, ~Scope scope) [Function]
+
+;/
+
+# TODO:
+/; compile_method (~{}Token tok, ~int cur, ~CompData out, ~Module current, ~Scope scope) [Function]
+
+;/
+
+# First pass on a module
+# Generates structs, enums, and submodules
+/; module_pass_one (~{}Token tok, ~int cur, ~Module current)
+
+;/
+
+# Second pass on a module
+# Generates code and calls compile_file_second_pass if an include happens
+/; module_pass_two (~{}Token tok, ~int cur, ~Module current)
+
+;/
+
+# First compiler pass on a file
+# Only creates structs, enums, and moduless
+/; compile_file_pass_one (Path f, ~Module current)
+ ;{}Token tok = tokenize(f)
+
+ ;tnsl.io.print("Number of tokens generated: ")
+ ;tnsl.io.println(len tok)
+
+ /; loop (int i = 0; i < len tok) [i++]
+ ;tnsl.io.print(".")
+ /; if (tok{i}.cmp(":"))
+ ;tnsl.io.println("INCLUDE")
+ /; if (tok{i + 2}.type_is(TOKEN.LITERAL))
+ ;CompData tmp = compile_file_pass_one(f.relative(unquote_str(tok{i + 2}.data)), current)
+ ;i = i + 2
+ ;/
+ ;continue
+ ;; else if (tok{i}.cmp("/;") || tok{i}.cmp(";;"))
+ /; if (tok{i + 1}.cmp("export") || tok{i + 1}.cmp("module"))
+ ;module_pass_one(~tok, ~i, current)
+ ;/
+ ;; else if (tok{i}.cmp("struct"))
+ ;new_type(~tok, ~i, current)
+ ;/
+ ;/
+;/
+
+/; size_struct (~Type t, ~Module m)
+ ;int s = 0
+ /; loop (int i = 0; i < len (t`.members)) [i++]
+ ;int p = is_primitive(t`.members{i}.data_type.name)
+ /; if (len (t`.members{i}.data_type.ptr_chain) > 0)
+ ;s = s + 8
+ ;; else if (p >== 0)
+ ;s = s + p
+ ;; else
+ ;~Type tp = m`.find_type(t`.members{i}.data_type.name)
+ /; if (tp`.s == 0)
+ ;size_struct(tp, m)
+ ;/
+ ;t`.members{i}.data_type = tp`
+ ;s = s + tp`.s
+ ;/
+ ;/
+ ;tnsl.io.println(string_add("Sized type ", t`.name))
+ ;t`.s = s
+;/
+
+# Regenerates struct sizes (with support for cyclical struct definitions)
+/; flush_structs (~Module m)
+
+ /; loop (int i = 0; i < len (m`.types)) [i++]
+ ;size_struct(~(m`.types{i}), m)
+ ;/
+
+ /; loop (int i = 0; i < len (m`.sub)) [i++]
+ ;flush_structs(~(m`.sub{i}))
+ ;/
+;/
+
+# Second pass of compiler
+# Does code generation, ignores structs and enums
+/; compile_file_pass_two (Path f, ~Module current) [CompData]
+ ;CompData out = {"", "", ""}
+ ;{}Token tok = tokenize(f)
+
+ /; loop (int i = 0; i < len tok) [i++]
+ ;tnsl.io.print(".")
+ /; if (tok{i}.cmp(":"))
+ ;tnsl.io.println("INCLUDE")
+ /; if (tok{i + 2}.type_is(TOKEN.LITERAL))
+ ;CompData tmp = compile_file_pass_two(f.relative(unquote_str(tok{i + 2}.data)), current)
+ ;out.hsec = string_add(out.hsec, tmp.hsec)
+ ;out.dsec = string_add(out.dsec, tmp.dsec)
+ ;out.csec = string_add(out.csec, tmp.csec)
+ ;i = i + 2
+ ;/
+ ;continue
+ ;; else if (tok{i}.cmp("/;") || tok{i}.cmp(";;"))
+ ;tnsl.io.print("block")
+ /; if (tok{i + 1}.cmp("export") || tok{i + 1}.cmp("module"))
+ ;module_pass_two(~tok, ~i, current)
+ ;/
+ ;; else if (tok{i}.cmp("struct"))
+ ;tnsl.io.print("struct")
+ ;skip_struct(~tok, ~i)
+ ;; else if (tok{i}.cmp("enum"))
+ ;tnsl.io.print("enum")
+ ;out.dsec = string_add(out.dsec, compile_enum(~tok, ~i, current))
+ ;; else if (is_definition(~tok, ~i))
+ ;tnsl.io.print("def")
+ ;Type t = get_type(~tok, ~i, current)
+ ;out.dsec = string_add(out.dsec, compile_file_def(~tok, ~i, t, current))
+ ;; else if (!(tok{i}.cmp("\n")))
+ ;tnsl.io.println("Failed to recognize file-level statement")
+ ;tok{i}.print()
+ ;break
+ ;/
+ ;/
+
+ ;tnsl.io.print("Generated code length: ")
+ ;tnsl.io.println(len (out.hsec) + len (out.dsec) + len (out.csec))
+
+ ;return out
+;/
+
+# Starts the compiler on a given path
+/; compile_start (Path f) [{}uint8]
+ ;{}uint8 out = ""
+
+ ;Module root = {0, true, {}, {}, {}, {}, {}}
+ ;compile_file_pass_one(f, ~root)
+ ;flush_structs(~root)
+ ;tnsl.io.println("First pass DONE")
+
+ ;CompData data = compile_file_pass_two(f, ~root)
+ ;tnsl.io.println("Second pass DONE")
+
+ ;out = string_join({
+ data.hsec,
+ "section .data\n",
+ data.dsec,
+ "section .text\n",
+ data.csec}, "")
+
+ ;return out
+;/
+
+##
+## Tokenizer funcs
+##
+
+
+/; is_whitespace (uint8 c) [bool]
+ ;return (c == '\n' || c == '\t' || c == ' ')
+;/
+
+;{}uint8 MULTI_PARENS = "/;:#"
+;{}uint8 PARENS = "()[]{}"
+;{}uint8 RESERVED = "`~!%^&*()-+=[]{}|;:/?<>.,"
+;{}uint8 AUGMENTS = "=~!<>&|^+-*/`."
+
+;{}{}uint8 MULTI_AUGMENTS = {
+ "~=", "`=", "%=", "^=", "&=", "*=",
+ "!=", "|=", "/=",
+
+ "==", "!==", "&&", "||", "^^", "<==", ">==", "!>", "!<",
+
+ "<<", ">>", "!&", "!|", "!^"
+}
+
+
+;{}{}uint8 KEYWORDS = {
+ "len",
+ "is",
+
+ "if",
+ "else",
+ "loop",
+ "continue",
+ "break",
+
+ "return",
+
+ "method",
+ "struct",
+ "enum",
+ "interface",
+
+ "export",
+ "module",
+
+ "const",
+ "static",
+ "volatile",
+
+ "extends",
+ "override"
+}
+
+;{}{}uint8 KEYTYPES = {
+ "uint8",
+ "uint16",
+ "uint32",
+ "uint64",
+ "uint",
+
+ "int8",
+ "int16",
+ "int32",
+ "int64",
+ "int",
+
+ "float32",
+ "float64",
+ "float",
+
+ "comp32",
+ "comp64",
+ "comp",
+
+ "vect",
+ "bool",
+
+ "type",
+ "void"
+}
+
+/; is_delimiter ({}uint8 str) [bool]
+ /; if (len str > 2 || len str < 1)
+ ;return false
+ ;/
+
+ /; if (len str == 2)
+ ;return string_contains(MULTI_PARENS, str{0}) && string_contains(MULTI_PARENS, str{1})
+ ;/
+
+ ;return string_contains(PARENS, str{0})
+;/
+
+/; is_reserved ({}uint8 str) [bool]
+ /; if (len str < 1)
+ ;return false
+ ;/
+ ;return string_contains(RESERVED, str{0})
+;/
+
+/; is_augment ({}uint8 str) [bool]
+ /; if (len str == 1)
+ ;return string_contains(AUGMENTS, str{0})
+ ;/
+
+ ;return list_contains(MULTI_AUGMENTS, str)
+;/
+
+/; is_str_literal ({}uint8 str) [bool]
+ /; if (string_equate(str, "\"") || string_equate(str, "'"))
+ ;return true
+ ;/
+
+ /; if (len str < 2)
+ ;return false
+ ;; else if (str{0} !== '\'' && str{0} !== '"')
+ ;return false
+ ;/
+
+ /; loop (int i = 1; i < len str) [i++]
+ /; if (str{i} == '\\')
+ ;i++
+ ;; else if (str{i} == str{0})
+ ;return i == len str - 1
+ ;/
+ ;/
+ ;return true
+;/
+
+/; is_num_literal ({}uint8 str) [bool]
+ /; if (len str < 1)
+ ;return false
+ ;/
+
+ ;bool dec = false
+ /; loop (int i = 0; i < len str) [i++]
+ /; if (str{i} == '.')
+ /; if (!dec)
+ ;dec = true
+ ;; else
+ ;return false
+ ;/
+ ;; else if (str{i} < '0' || str{i} > '9')
+ ;return false
+ ;/
+ ;/
+ ;return true
+;/
+
+/; is_literal({}uint8 str) [bool]
+ ;return is_str_literal(str) || is_num_literal(str)
+;/
+
+/; gen_type (Token t) [int]
+ /; if (t.cmp("\n") || t.cmp(","))
+ ;return TOKEN.SEPARATOR
+ ;/
+
+ /; if (is_literal(t.data))
+ ;return TOKEN.LITERAL
+ ;/
+
+ /; if (is_reserved(t.data))
+ /; if (is_delimiter(t.data))
+ ;return TOKEN.DELIMITER
+ ;; else if (is_augment(t.data))
+ ;return TOKEN.AUGMENT
+ ;/
+ ;; else if (list_contains(KEYWORDS, t.data))
+ ;return TOKEN.KEYWORD
+ ;; else if (list_contains(KEYTYPES, t.data))
+ ;return TOKEN.KEYTYPE
+ ;/
+
+ ;return TOKEN.DEFWORD
+;/
+
+/; break_token (Token current, uint8 to_append) [bool]
+ /; if (is_literal(current.data))
+ ;current.data.append(to_append)
+ ;return !(is_literal(current.data))
+ ;/
+
+ /; if (is_whitespace(to_append) || current.cmp("\n"))
+ ;return true
+ ;/
+
+ /; if (is_reserved(current.data))
+ /; if (is_reserved({to_append}))
+ ;current.data.append(to_append)
+ ;return gen_type(current) == TOKEN.DEFWORD
+ ;/
+ ;return true
+ ;; else if (is_reserved({to_append}))
+ ;return true
+ ;/
+
+ ;return false
+;/
+
+/; handle_comment (tnsl.io.File fd, ~Token current, ~int line) [bool]
+ ;bool block = false
+ /; if (current`.cmp("/"))
+ ;block = true
+ ;/
+
+ /; loop (int i = fd.read(); i !== -1) [i = fd.read()]
+ /; if (i == '\n')
+ ;line`++
+ /; if (!block)
+ ;return true
+ ;/
+ ;; else if (block && i == '#')
+ ;i = fd.read()
+ /; if (i == '/')
+ ;current` = {0, line, ""}
+ ;return false
+ ;; else if (i == ';' || i == ':')
+ ;current`.data.append(i)
+ ;return false
+ ;/
+
+ /; loop (i !== '\n' && i !== -1) [i = fd.read()] ;/
+
+ ;line`++
+ ;/
+ ;/
+;/
+
+/; tokenize (Path f) [{}Token]
+ ;{}Token out = {}
+
+ ;tnsl.io.File fd = f.open_read()
+
+ ;Token current = {0, 0, ""}
+ ;int line = 1
+ /; loop (int i = fd.read(); i > -1) [i = fd.read()]
+
+ /; if (i == '#' && (break_token(current, i) || gen_type(current) !== TOKEN.LITERAL))
+ ;bool ln = handle_comment(fd, ~current, ~line)
+ /; if (ln)
+ ;current.tokenType = gen_type(current)
+ /; if (!(current.cmp("")))
+ ;out.append(current)
+ ;/
+ ;out.append({TOKEN.SEPARATOR, line - 1, "\n"})
+ ;/
+ ;continue
+ ;/
+
+ /; if (i == '\n')
+ ;tnsl.io.print(".")
+ /; if (!(current.cmp("\n")))
+ ;current.tokenType = gen_type(current)
+ /; if (!(current.cmp("")))
+ ;out.append(current)
+ ;/
+ ;current = {TOKEN.SEPARATOR, line, ""}
+ ;current.data.append(i)
+ ;/
+ ;line++
+ ;; else if (break_token(current, i))
+ ;current.tokenType = gen_type(current)
+ /; if (!(current.cmp("")))
+ ;out.append(current)
+ ;/
+ ;current = {0, line, ""}
+ /; if (!(is_whitespace(i)))
+ ;current.data.append(i)
+ ;/
+ ;; else
+ ;current.data.append(i)
+ ;/
+ ;/
+ ;tnsl.io.println("OK")
+
+ /; if (!(current.cmp("")) && !(current.cmp("\n")))
+ ;current.tokenType = gen_type(current)
+ ;out.append(current)
+ ;/
+
+ ;fd.close()
+
+ ;return out
+;/
+
+##
+## Main
+##
+
+/; main ({}{}uint8 args) [int]
+ /; if (len args < 1)
+ ;tnsl.io.println("Give me something to compile!")
+ ;return 1
+ ;/
+
+ ;bool tokenize_only = len args > 1
+
+ ;{}{}uint8 fsplit = string_split(args{0}, '/')
+ ;Path p = {{}, fsplit{len fsplit - 1}}
+
+ /; loop (int i = 0; i < len fsplit - 1) [i++]
+ ;p.path.append(fsplit{i})
+ ;/
+
+ ;tnsl.io.print("Path: ")
+ ;tnsl.io.println(p.full_path())
+
+ ;{}uint8 code = ""
+ /; if (!tokenize_only)
+ ;code = compile_start(p)
+ ;; else
+ ;{}Token tok = tokenize(p)
+ /; loop(int i = 0; i < len tok) [i++]
+ ;tnsl.io.print(".")
+ ;code = string_add(code, tok{i}.sprint())
+ ;/
+ ;tnsl.io.println("OK")
+ ;/
+
+ ;p.name = string_add(p.name, ".asm")
+
+ ;p.write(code)
+
+ ;return 0
+;/
diff --git a/tnslc/compile/compile.tnsl b/tnslc/compile/compile.tnsl
deleted file mode 100644
index 034304c..0000000
--- a/tnslc/compile/compile.tnsl
+++ /dev/null
@@ -1,768 +0,0 @@
-/##
- Copyright 2021-2022 Kyle Gunger
-
- This file is licensed under the CDDL 1.0 (the License)
- and may only be used in accordance with the License.
- You should have received a copy of the License with this
- software/source code. If you did not, a copy can be found
- at the following URL:
-
- https://opensource.org/licenses/CDDL-1.0
-
- THIS SOFTWARE/SOURCE CODE IS PROVIDED "AS IS" WITH NO
- WARRANTY, GUARANTEE, OR CLAIM OF FITNESS FOR ANY PURPOSE
- EXPRESS OR IMPLIED
-#/
-
-
-;{}{}uint8 COMMON_ASM = {
- "\tret\n"
-}
-
-# Represents a type
-;struct VType {
- uint
- _size,
- int
- ptr,
-
- {}uint8 name,
-
- {}VType sub_types,
- {}{}uint8 sub_names
-}
-
-/; method VType
- /; get_sub_type({}uint8 name) [VType]
- /; loop (int i = 0; i < len (self.sub_types)) [i++]
- /; if (string_equate(~name, ~(self.sub_names{i})))
- ;return self.sub_types{i}
- ;/
- ;/
- ;return NT
- ;/
-
- /; get_offset({}uint8 name) [int]
- ;int out = 0
- /; loop (int i = 0; i < len (self.on_stack)) [i++]
- /; if (string_equate(~name, ~(self.sub_types{i*2 + 1})))
- ;return out
- ;; else if (self.on_stack{i})
- ;VType tmp = vtype_by_name(self.sub_types{i*2})
- ;out = out + tmp.size
- ;/
- ;/
- ;return -1
- ;/
-
- /; print
- ;tnsl.io.print("Size: ")
- ;tnsl.io.print(self._size)
- ;tnsl.io.print(" | Ptr: ")
- ;tnsl.io.print(self.ptr)
- ;tnsl.io.print(" | Name: ")
- ;tnsl.io.println(self.name)
- ;/
-;/
-
-# Tracks defined variables in a block
-;struct VTrack {
- {}{}uint8
- sym_names,
-
- {}Value
- sym_vals
-}
-
-/; method VTrack
-
- /; next_loc(VType vt) [int]
- /; if (is_struct(vt) && vt.ptr == 0)
- ;return -1
- ;/
-
- ;int count = 0
- /; loop (int i = 0; i < len (self.sym_vals)) [i++]
- /; if (!(self.sym_vals{i}.on_stack))
- ;count++
- ;/
-
- /; if (count > 7)
- ;return -1
- ;/
- ;/
-
- ;return count + 6
- ;/
-
- # returns with init commands
- /; add_track({}uint8 name, VType _type) [{}uint8]
- ;Value v = track_val(_type, to_stack, self.next_loc(_type))
-
- /; if (v.loc < 0)
- ;v.loc = 0
- ;/
-
- ;self.sym_names.append(name)
- ;self.sym_vals.append(v)
- ;return v.init_val()
- ;/
-
- # Returns true if the variable is being tracked
- /; in_vtrack({}uint8 name) [bool]
- /; loop (int i = 0; i < len (self.sym_names)) [i++]
- /; if (string_equate(name, self.sym_names{i}))
- ;return true
- ;/
- ;/
- ;return false
- ;/
-
- # Returns the total allocated memory on the stack for this tracker
- /; stack_total [int]
- ;int out = 0
- /; loop (int i = 0; i < len (self.on_stack)) [i++]
- /; if (self.on_stack{i})
- ;out = out + (self.sym_vals{i}._type._size)
- ;/
- ;/
- ;return out
- ;/
-
- # returns the type of the named variable
- /; get_val ({}uint8 name) [Value]
- /; loop (int i = 0; i < len (self.sym_names)) [i++]
- /; if (string_equate(name, self.sym_names{i}))
- ;return (self.sym_vals{i})
- ;/
- ;/
- ;/
-
- # push stack updates loc for every value on the stack
- /; push_stack (VType vt) [{}uint8]
- ;int tsz = vt._size
- /; if (vt.ptr !== 0)
- ;tsz = 8
- ;/
-
- /; loop (int i = 0; i < len (self.sym_vals)) [i++]
- /; if (self.sym_vals{i}.on_stack)
- ;self.sym_vals{i}.loc = self.sym_vals{i}.loc + tsz
- ;/
- ;/
-
- ;{}uint8 out = "\tsub $"
- ;{}uint8 tmp = string_from_int(tsz)
- ;add_strings(~out, ~tmp)
- ;out.append(',')
- ;out.append(' ')
- ;tmp = "%rsp"
- ;add_strings(~out, ~tmp)
- ;return out
- ;/
-;/
-
-# Sizes of items
-;{}VType type_table = {
- {1, 0, "int8", {}, {}},
- {2, 0, "int16", {}, {}},
- {4, 0, "int32", {}, {}},
- {8, 0, "int64", {}, {}},
- {8, 0, "int", {}, {}},
- {1, 0, "uint8", {}, {}},
- {2, 0, "uint16", {}, {}},
- {4, 0, "uint32", {}, {}},
- {8, 0, "uint64", {}, {}},
- {8, 0, "uint", {}, {}},
- {4, 0, "float32", {}, {}},
- {8, 0, "float64", {}, {}},
- {8, 0, "float", {}, {}},
- {1, 0, "bool", {}, {}},
- {8, 0, "void", {}, {}}
-}
-
-# Null type
-;VType NT = {0, 0, "null", {}, {}}
-
-# Returns an index in the vtrack for a given variable name
-/; name_to_index ({}uint8 name, ~VTrack tab) [int]
- /; loop (int i = 0; i < len (tab`.sym_names)) [i++]
- /; if (string_equate(tab`.sym_names{i}, name))
- ;return i
- ;/
- ;/
-
- ;tnsl.io.print("Failed to find vairable ")
- ;tnsl.io.println(name)
-
- ;return -1
-;/
-
-# Bool to j
-/; cmp_to_jxt ({}uint8 c) [{}uint8]
- /; if (string_equate(c, "<"))
- ;return "l"
- ;; else if (string_equate(c, ">"))
- ;return "g"
- ;; else if (string_equate(c, "!<") || string_equate(c, ">=="))
- ;return "nl"
- ;; else if (string_equate(c, "!>") || string_equate(c, "<=="))
- ;return "ng"
- ;; else if (string_equate(c, "=="))
- ;return "e"
- ;; else if (string_equate(c, "!=="))
- ;return "ne"
- ;/
- ;return "nz"
-;/
-
-# Is struct returns true if the type name given is a struct
-/; is_struct (VType t) [bool]
- ;VType tmp = NT
- /; loop (int i = 0; i < 15) [i++]
- ;tmp = tnslc.type_table{i}
- /; if (string_equate(tmp.name, t.name))
- ;return false
- ;/
- ;/
-
- ;return true
-;/
-
-# Using the given offset (in bytes), return an asm value of form ".quad <offset>"
-/; construct_value (int size, int offset) [{}uint8]
- ;{}uint8 out = ".byte "
- /; if (size == 2)
- ;out = ".word "
- ;; if (size == 4)
- ;out = ".long"
- ;; if (size == 8)
- ;out = ".quad "
- ;/
- ;{}uint8 tmp = string_from_int(offset)
- ;add_strings(~out, ~tmp)
- ;return out
-;/
-
-/; construct_text_value ({}uint8 t) [{}uint8]
- ;{}uint8 tmp = "\n\t.ascii "
- ;add_strings(~tmp, ~t)
- ;return tmp
-;/
-
-/; construct_mov_literal({}uint8 value, reg) [{}uint8]
- ;{}uint8 tmp = "$"
- ;add_strings(~tmp, ~value)
- ;return mov_asm(tmp, reg)
-;/
-
-# Parse a struct and add it to the table
-/; def_struct (~int cur, ~{}Token data, ~{}uint8 dsec) [VType]
- ;VType out = {0, 0, "", {}, {}}
- ;cur`++
-
- ;out.name = data`{cur`}.data`
-
- ;cur`++
- ;cur`++
- # Should be indexed at first type in the type list
-
- /; if (token_is(cur, data, "}"))
- ;return NT
- ;/
-
- ;VType ctype = get_vtype(cur, data)
- ;cur`++
-
- /; loop (cur` < len data`) [cur`++]
- /; if (token_is(cur, data, "}"))
- ;break
- ;; else if (token_is(cur, data, ","))
- ;cur`++
- ;/
-
- ;cur`++
- /; if (token_is(cur, data, ",") || token_is(cur, data, "}"))
- # Use ctype
- ;cur`--
-
- /; if (ctype.ptr > 0)
- ;out._size = out._size + 8
- ;; else
- ;out._size = out._size + ctype._size
- ;/
- ;out.sub_types.append(ctype)
- ;out.sub_names.append(data`{cur`}.data`)
-
- ;; else
- # Get type
- ;cur`--
- ;ctype = get_vtype(cur, data)
- ;/
- ;/
- ;out.print()
- ;type_table.append(out)
-
- ;return out
-;/
-
-# Checks if the current token's data member is equal to a given string
-/; token_is(~int cur, ~{}Token data, {}uint8 str) [bool]
- ;return string_equate(data`{cur`}.data`, str)
-;/
-
-# Skips in a definition or list until it finds a name
-/; skip_to_name (~int cur, ~{}Token data)
- ;int tmp = 0
- /; loop (cur` < len data`) [cur`++]
- ;tmp = cur` + 1
- /; if (data`{cur`}.token_type == TOKEN_TYPE.DEFWORD &&
- ( token_is(~tmp, data, ",") || token_is(~tmp, data, ")") || token_is(~tmp, data, "}") || token_is(~tmp, data, ";") ))
- ;break
- ;/
- ;/
-;/
-
-# Searches the type table for a type
-/; vtype_by_name ({}uint8 name) [VType]
- /; loop (int i = 0; i < len type_table) [i++]
- ;VType tmp = tnslc.type_table{i}
- /; if (string_equate(name, tmp.name))
- ;return tmp
- ;/
- ;/
- ;return NT
-;/
-
-# Parses a type in a definition or list
-/; get_vtype (~int cur, ~{}Token data) [VType]
- ;uint ptr = 0
- ;VType out = NT
-
- /; loop (cur` < len data`) [cur`++]
- ;int i = data`{cur`}.token_type
- /; if (token_is(cur, data, "~") || token_is(cur, data, "{"))
- ;ptr++
- ;; else if (i == TOKEN_TYPE.DEFWORD || i == TOKEN_TYPE.KEYTYPE)
- ;out = vtype_by_name(data`{cur`}.data`)
- ;break
- ;; else if (!token_is(cur, data, "}"))
- ;break
- ;/
- ;/
-
- ;out.ptr = ptr
-
- ;return out
-;/
-
-# Assumes cur points to the beginning of the arguments list
-# Sets up the VTrack struct that is pointed to.
-/; setup_vtrack (~int cur, ~{}Token data, ~VTrack tab, ~{}uint8 csec)
- ;cur`++
-
- ;VType last = NT
- ;Value tmp = {false, false, 0, 0, last}
-
- /; loop (cur` < len data`) [cur`++]
- ;int pre_skip = cur`
- /; if (token_is(cur, data, ")"))
-
- ;break
- ;; else if (!token_is(cur, data, ","))
-
- ;skip_to_name(cur, data)
-
- /; if (pre_skip !== cur`)
- ;last = get_vtype(~pre_skip, data)
- ;tmp._type = last
- ;/
-
- ;tab`.sym_names.append(data`{cur`}.data`)
- ;int nloc = tab`.next_loc(last)
-
- ;Value store = {false, false, nloc, 0, last}
- /; if (store.loc !< 0 && tmp.loc !> 5)
- ;{}uint8 tstr = store.set_value(tmp)
- ;add_strings(csec, ~tstr)
- ;tmp.loc = tmp.loc + 1
- ;; else
- ;store.loc = 0
- ;store.on_stack = true
- ;tab`.push_stack(last)
- ;/
-
- ;tab`.sym_vals.append(store)
- ;/
- ;/
-;/
-
-# Mostly deals with structs and enums
-/; compile_global (~int cur, ~{}Token data, ~{}uint8 hsec, csec, dsec)
- ;cur`++
- /; if (token_is(cur, data, "struct"))
- ;def_struct(cur, data, dsec)
- ;/
-;/
-
-# Evaluate a value
-/; eval_value (~int cur, ~{}Token data, ~VTrack tab, ~{}uint8 hsec, csec, dsec, int val_layer) [Value]
- /; if (token_is(cur, data, ";/"))
- ;return NV
- ;/
-
- ;Value tmp = {false, false, val_layer % 5, 0, NT}
-
- /; if (val_layer > 5)
- ;tmp.on_stack = true
- ;/
-
- /; loop (cur` < len data`)
- ;tnsl.io.println("looping")
- /; if (data`{cur`}.token_type == TOKEN_TYPE.LITERAL)
- /; if (data`{cur`}.data`{0} == '"')
- # String literal
- ;tmp._type = type_table{5}
- ;tmp._type.ptr = 1
- ;; else if (data`{cur`}.data`{0} == '\'')
- # Char literal
- ;int val = unquote_char(data`{cur`}.data`)
- ;Value lit = {false, true, 0, val, type_table{5}}
- ;{}uint8 tmp = out.set_value(lit)
- ;add_strings(csec, ~tmp)
- ;; else
- # int literal
- ;tnsl.io.print("int literal ")
- ;tnsl.io.println(data`{cur`}.data`)
- ;tmp.val = int_from_string(data`{cur`}.data`)
- ;tmp.literal = true
- ;tmp._type = tnslc.type_table{4}
- ;cur`++
- ;tnsl.io.print("next tok ")
- ;tnsl.io.println(data`{cur`}.data`)
- ;/
- ;; else if (data`{cur`}.token_type == TOKEN_TYPE.DEFWORD)
-
- /; if (is_call(cur, data))
- ;; else if (tab`.in_vtrack(data`{cur`}.data`))
- ;tmp = tab`.get_val(data`{cur`}.data`)
- ;cur`++
- /; loop (token_is(cur, data, "."))
- ;cur`++
- ;tmp = tmp.get_member_value(data`{cur`}.data`)
- ;cur`++
- ;/
- ;/
-
- ;; else if (token_is(cur, data, "~"))
- ;; else if (data`{cur`}.token_type == TOKEN_TYPE.AUGMENT)
-
- ;int acr = cur`
- ;cur`++
- ;Value nxt = eval_value(cur, data, tab, hsec, csec, dsec, val_layer + 1)
- ;{}uint8 code = ""
- /; if (token_is(~acr, data, "="))
- ;code = tmp.set_value(nxt)
- ;; if (token_is(~acr, data, "+"))
- ;code = tmp.add_value(nxt)
- ;; if (token_is(~acr, data, "-"))
- ;tnsl.io.println("here")
- ;code = tmp.sub_value(nxt)
- ;; if (token_is(~acr, data, "*"))
- ;code = tmp.mul_value(nxt)
- ;; if (token_is(~acr, data, "/"))
- ;code = tmp.div_value(nxt)
- ;/
- ;add_strings(csec, ~code)
- ;break
- ;; else
- ;break
- ;/
- ;/
- ;return tmp
-;/
-
-/; get_function_label(~int cur, ~{}Token data) [{}uint8]
- /; if (string_equate(data`{cur` + 1}.data`, "("))
- ;return data`{cur`}.data`
- ;/
-
- ;{}{}uint8 func_path = {}
-
- /; loop (cur` < len data`) [cur`++]
- /; if (token_is(cur, data, "("))
- ;break
- ;; else if (!token_is(cur, data, "."))
- ;func_path.append(data`{cur`}.data`)
- ;/
- ;/
- ;{}uint8 out = "_."
- ;{}uint8 jn_tmp = join(func_path, '.')
- ;add_strings(~out, ~jn_tmp)
- ;return out
-;/
-
-# Sets up a call and reports back where the return value is stored
-/; eval_call (~int cur, ~{}Token data, ~VTrack tab, ~{}uint8 hsec, csec, dsec) [{}uint8]
-
- # Store the name of the function we are calling
- ;{}uint8 to_call = get_function_label(cur, data)
- ;tnsl.io.println(to_call)
- # Set read head to first parameter
- ;cur`++
- /; loop (!token_is(cur, data, ")"))
- /; if (token_is(cur, data, ","))
- ;cur`++
- ;; else
- /; if (reg < 7)
- ;eval_value(cur, data, tab, hsec, csec, dsec)
- ;reg++
- ;; else
- ;eval_value(cur, data, tab, hsec, csec, dsec)
- ;push_asm(get_reg(8, "bp"))
- ;/
- ;/
- ;/
- ;cur`++
-
- ;{}uint8 call_ist = call_asm(to_call)
-
- ;add_strings(csec, ~call_ist)
- ;return "ax"
-;/
-
-/; is_call (~int cur, ~{}Token data) [bool]
- ;bool look_def = true
- /; loop (int i = cur`; i < len data`) [i++]
- /; if (look_def && data`{i}.token_type == TOKEN_TYPE.DEFWORD)
- ;look_def = false
- ;; else if (!look_def && token_is(~i, data, "."))
- ;look_def = true
- ;; else if (!look_def && token_is(~i, data, "("))
- ;return true
- ;; else
- ;break
- ;/
- ;/
- ;return false
-;/
-
-# Compile a statement in a function
-/; compile_statement (~int cur, ~{}Token data, ~VTrack tab, ~{}uint8 hsec, csec, dsec) [bool]
- ;cur`++
- ;bool r = false
- /; if (cur` !< len data`)
- ;return false
- ;/
-
- /; if (token_is(cur, data, "asm"))
- ;cur`++
- ;{}uint8 raw_asm = unquote_string(data`{cur`}.data`)
- ;raw_asm.append('\n')
- ;csec`.append('\t')
- ;add_strings(csec, ~raw_asm)
- ;cur`++
- ;; else if (token_is(cur, data, "raw"))
- ;cur`++
- ;r = true
- ;; else if (token_is(cur, data, "return"))
- ;cur`++
- ;Value out = eval_value(cur, data, tab, hsec, csec, dsec, 0)
- ;{}uint8 mv = out.mov_to_reg(0)
- ;add_strings(csec, ~mv)
- ;tail_guard(csec)
- ;add_strings(csec, ~(tnslc.COMMON_ASM{0}))
- ;return true
- ;; else if (is_call(cur, data))
- # Function call
- ;eval_call(cur, data, tab, hsec, csec, dsec)
- ;; else if (tab.in_vtrack(data`{cur`}.data`))
- # set value
- ;int i = name_to_index(data`{cur`}.data`, tab)
- ;{}uint8 tmp = index_to_loc(i)
- ;eval_value(cur, data, tab, hsec, csec, dsec)
- ;tmp = mov_asm(get_reg(tab`.sym_types{i}._size, "ax"), tmp)
- ;add_strings(csec, ~tmp)
- ;; else
- #Definition
- ;VType def_t = get_vtype(cur, data)
- ;cur`++
-
- /; loop (data`{cur`}.token_type == TOKEN_TYPE.DEFWORD)
- ;{}uint8 init = tab`.add_track(data`{cur`}.data`, def_t)
- ;add_strings(~out, ~init)
- ;cur`++
- /; if (token_is(cur, data, ","))
- ;cur`++
- ;; else if (token_is(cur, data, "="))
- ;{}uint8 set = index_to_loc(len tab`.sym_names - 1, tab)
- ;eval_value(cur, data, tab, hsec, csec, dsec, loc)
- /; if (token_is(cur, data, ","))
- ;cur`++
- ;/
- ;; else
- ;break
- ;/
- ;/
- /; if (string_equate(data`{cur`+1}.data`, "="))
- ;/
- ;; if (token_is(cur, data, "return"))
- ;add_strings(csec, ~(tnslc.COMMON_ASM{0}))
- ;return true
- ;/
-
- ;return false
-;/
-
-
-
-/; compile_block (~int cur, ~{}Token data, ~{}uint8 hsec, csec, dsec, {}{}uint8 mod_path, Path rel)
- ;VTrack tab = { {}, {} }
- ;VType out_type = tnslc.type_table{14}
- ;{}uint8 name = ""
- ;bool r = false
-
- /; loop (cur`++; cur` < len data`) [cur`++]
- /; if (token_is(cur, data, "module"))
- ;mod_path.append(data`{cur` + 1}.data`)
- ;cur` = cur` + 2
- ;break
- ;/
- /; if (data`{cur`}.token_type == TOKEN_TYPE.DEFWORD && len name == 0)
- ;name = data`{cur`}.data`
- /; if (len mod_path > 0)
- ;{}uint8 frs = "_."
- ;{}uint8 jn = join(mod_path, '.')
- ;add_strings(~frs, ~jn)
- ;add_strings(csec, ~frs)
- ;csec`.append('.')
- ;/
- ;add_strings(csec, ~name)
- ;csec`.append(':')
- ;csec`.append('\n')
- /; if (!r)
- ;header_guard(csec)
- ;/
- ;; else if (token_is(cur, data, "("))
- ;setup_vtrack(cur, data, ~tab, csec)
- ;; else if (token_is(cur, data, "["))
- ;cur`++
- ;out_type = get_vtype(cur, data)
- ;cur`++
- ;; else if (token_is(cur, data, "raw"))
- ;r = true
- ;; else
- ;break
- ;/
- ;/
-
- ;tnsl.io.println(out_type.name)
-
- ;bool ret = false
- /; loop (cur` < len data` && !ret)
- /; if (token_is(cur, data, ";/"))
- /; if (!r)
- ;tail_guard(csec)
- ;/
- ;add_strings(csec, ~(tnslc.COMMON_ASM{0}))
- ;break
- ;; else if (token_is(cur, data, "/;"))
- ;bool ch = true
- /; loop (ch)
- ;compile_block(cur, data, hsec, csec, dsec, mod_path)
- /; if (cur` !< len data`)
- ;break
- ;/
- ;ch = token_is(cur, data, ";;")
- ;/
- ;; else if (string_equate(data`{cur`}.data`, ":"))
- ;cur` = cur` + 2
- ;Path inc = rel.rel_file(unquote_string(data`{cur`}.data`))
- ;compile_include(inc, hsec, csec, dsec, mod_path)
- ;cur`++
- ;; else if (string_equate(data`{cur`}.data`, ";"))
- ;ret = compile_statement(cur, data, ~tab, hsec, csec, dsec)
- ;; else
- ;tnsl.io.print("Failed to compile token [compile_block]: ")
- ;data`{cur`}.print()
- ;tnsl.io.println("")
- ;break
- ;/
- ;/
-
- ;csec`.append('\n')
-;/
-
-/; compile_include (Path file_path, ~{}uint8 hsec, csec, dsec, {}{}uint8 mod_path)
- # Autocomplete in the case of module syntax
- ;bool d = file_path.extension_is("tnsl")
- /; if (!d)
- ;file_path.dirs.append(file_path.file)
- ;{}uint8 ftmp = file_path.file
- ;{}uint8 tmp = ".tnsl"
- ;add_strings(~ftmp, ~tmp)
- ;file_path.file = ftmp
- ;/
-
- ;tnsl.io.print("[TNSLC:INCLUDE] ")
- ;tnsl.io.println(file_path.full_path())
-
- ;tnsl.io.File inc = file_path.open_r()
- ;~{}Token data = parse.tokenize(inc)
- ;inc.close()
-
- ;tnsl.io.print(len data`)
- ;tnsl.io.println(" tokens parsed.")
-
- ;compile_file(file_path, data, hsec, csec, dsec, mod_path)
-;/
-
-/; compile_file (Path rel, ~{}Token data, ~{}uint8 hsec, csec, dsec, {}{}uint8 mod_path)
-
- ;int j = len data`
-
- /; loop (int i = 0; i < j) [i++]
- /; if (string_equate(data`{i}.data`, "/;"))
- ;compile_block(~i, data, hsec, csec, dsec, mod_path, rel)
- ;; else if (string_equate(data`{i}.data`, ";"))
- ;compile_global(~i, data, hsec, csec, dsec)
- ;; else if (string_equate(data`{i}.data`, ":"))
- ;i = i + 2
- ;Path inc = rel.rel_file(unquote_string(data`{i}.data`))
- ;compile_include(inc, hsec, csec, dsec, mod_path)
- ;; else
- ;break
- ;/
- ;/
-
-;/
-
-/; do_compile ({}uint8 file_out, Path rel)
- ;{}uint8 hsec = ".global main\n"
- ;{}uint8 csec = ".text\n"
- ;{}uint8 dsec = ".data\n"
-
- ;tnslc.compile_include(rel, ~hsec, ~csec, ~dsec, {})
-
- ;tnsl.io.File out = tnsl.io.writeFile(file_out)
-
- /; loop (int i = 0; i < len hsec) [i++]
- ;out.write(hsec{i})
- ;/
-
- ;out.write('\n')
-
- /; loop (int i = 0; i < len dsec) [i++]
- ;out.write(dsec{i})
- ;/
-
- ;out.write('\n')
-
- /; loop (int i = 0; i < len csec) [i++]
- ;out.write(csec{i})
- ;/
-
- ;out.write('\n')
- ;out.close()
-;/
-
diff --git a/tnslc/compile/isa_x86.tnsl b/tnslc/compile/isa_x86.tnsl
deleted file mode 100644
index 1cb09ab..0000000
--- a/tnslc/compile/isa_x86.tnsl
+++ /dev/null
@@ -1,182 +0,0 @@
-/##
- Copyright 2021-2022 Kyle Gunger
-
- This file is licensed under the CDDL 1.0 (the License)
- and may only be used in accordance with the License.
- You should have received a copy of the License with this
- software/source code. If you did not, a copy can be found
- at the following URL:
-
- https://opensource.org/licenses/CDDL-1.0
-
- THIS SOFTWARE/SOURCE CODE IS PROVIDED "AS IS" WITH NO
- WARRANTY, GUARANTEE, OR CLAIM OF FITNESS FOR ANY PURPOSE
- EXPRESS OR IMPLIED
-#/
-
-/; construct_statement({}uint8 base, {}{}uint8 args) [{}uint8]
- /; loop (int i = 0; i < len args) [i++]
- ;add_strings(~base, ~(args{i}))
- /; if (i < len args - 1)
- ;base.append(',')
- ;base.append(' ')
- ;/
- ;/
- ;base.append('\n')
- ;return base
-;/
-
-/; literal_num ({}uint8 num) [{}uint8]
- ;{}uint8 out = "$"
- ;add_strings(~out, ~num)
- ;return out
-;/
-
-/; add_asm ({}uint8 from, to) [{}uint8]
- ;return construct_statement("\tadd ", {from, to})
-;/
-
-/; sub_asm({}uint8 from, to) [{}uint8]
- ;return construct_statement("\tsub ", {from, to})
-;/
-
-/; push_asm ({}uint8 reg) [{}uint8]
- ;return construct_statement("\tpush ", {reg})
-;/
-
-/; pop_asm ({}uint8 reg) [{}uint8]
- ;return construct_statement("\tpop ", {reg})
-;/
-
-/; cmp_asm ({}uint8 a, b) [{}uint8]
- ;return construct_statement("\tcmp ", {a, b})
-;/
-
-/; mov_asm ({}uint8 a, b) [{}uint8]
- ;return construct_statement("\tmov ", {a, b})
-;/
-
-/; jmp_asm ({}uint8 pos) [{}uint8]
- ;return construct_statement("\tjmp ", {pos})
-;/
-
-/; call_asm ({}uint8 pos) [{}uint8]
- ;return construct_statement("\tcall ", {pos})
-;/
-
-/; cjmp_asm ({}uint8 suffix, pos) [{}uint8]
- ;{}uint8 p = "\tj"
- ;add_strings(~p, ~suffix)
- ;p.append(' ')
- ;return construct_statement(p, {pos})
-;/
-
-/; mem_offset ({}uint8 pos, offset, scale) [{}uint8]
- ;{}uint8 tmp = construct_statement("(", {pos, offset, scale})
- ;tmp{len tmp - 1} = ')'
- ;return tmp
-;/
-
-/; header_guard (~{}uint8 csec) [{}uint8]
- ;{}uint8 out = "", tmp = ""
- ;tmp = push_asm("%r8")
- ;add_strings(~out, ~tmp)
- ;tmp = push_asm("%r9")
- ;add_strings(~out, ~tmp)
- ;tmp = push_asm("%r10")
- ;add_strings(~out, ~tmp)
- ;tmp = push_asm("%r11")
- ;add_strings(~out, ~tmp)
- ;tmp = push_asm("%r12")
- ;add_strings(~out, ~tmp)
- ;tmp = push_asm("%r13")
- ;add_strings(~out, ~tmp)
- ;tmp = push_asm("%r14")
- ;add_strings(~out, ~tmp)
- ;tmp = push_asm("%r15")
- ;add_strings(~out, ~tmp)
- ;add_strings(csec, ~out)
-;/
-
-/; tail_guard (~{}uint8 csec) [{}uint8]
- ;{}uint8 out = "", tmp = ""
- ;tmp = pop_asm("%r15")
- ;add_strings(~out, ~tmp)
- ;tmp = pop_asm("%r14")
- ;add_strings(~out, ~tmp)
- ;tmp = pop_asm("%r13")
- ;add_strings(~out, ~tmp)
- ;tmp = pop_asm("%r12")
- ;add_strings(~out, ~tmp)
- ;tmp = pop_asm("%r11")
- ;add_strings(~out, ~tmp)
- ;tmp = pop_asm("%r10")
- ;add_strings(~out, ~tmp)
- ;tmp = pop_asm("%r9")
- ;add_strings(~out, ~tmp)
- ;tmp = pop_asm("%r8")
- ;add_strings(~out, ~tmp)
- ;add_strings(csec, ~out)
-;/
-
-/; is_common_reg ({}uint8 n) [bool]
- ;return string_equate(n, "ax") || string_equate(n, "bx") || string_equate(n, "cx") || string_equate(n, "dx")
- || string_equate(n, "sp") || string_equate(n, "bp") || string_equate(n, "si") || string_equate(n, "di")
- || string_equate(n, "8") || string_equate(n, "9") || string_equate(n, "10") || string_equate(n, "11")
- || string_equate(n, "12") || string_equate(n, "13") || string_equate(n, "14") || string_equate(n, "15")
-;/
-
-/# Accepted common names:
-# - ax
-# - bx
-# - cx
-# - dx
-# - si
-# - di
-# - bp
-# - sp
-# - 8-15
-#/
-/; get_reg (uint size, {}uint8 common) [{}uint8]
- ;{}uint8 out = "%"
-
- /; if (common{0} !< 'a')
-
- /; if (size == 1)
- /; if(common{1} == 'x')
- ;common{1} = 'l'
- ;; else
- ;common.append('l')
- ;/
- ;; else if (size == 4)
- ;out.append('e')
- ;; else if (size == 8)
- ;out.append('r')
- ;/
-
- ;add_strings(~out, ~common)
-
- ;; else
-
- ;out.append('r')
- ;add_strings(~out, ~common)
- /; if (size == 1)
- ;out.append('b')
- ;; else if (size == 2)
- ;out.append('w')
- ;; else if (size == 4)
- ;out.append('d')
- ;/
- ;return out
- ;/
-
- ;return out
-;/
-
-/; make_label ({}uint8 func_name, func_place, ~{}uint8 csec)
- ;func_name.append("_")
- ;add_strings(~func_name, ~func_place)
- ;func_name.append(':')
- ;func_name.append('\n')
- ;add_strings(csec, ~func_name)
-;/
diff --git a/tnslc/compile/value.tnsl b/tnslc/compile/value.tnsl
deleted file mode 100644
index da76ac8..0000000
--- a/tnslc/compile/value.tnsl
+++ /dev/null
@@ -1,362 +0,0 @@
-;struct Value {
- bool
- on_stack,
- literal,
-
- int
- loc,
- val,
-
- VType
- _type
-}
-
-;Value NV = {false, false, 0, 0, 0, {0, 0, "null", {}, {}}}
-
-/; val_from_address (int offset, {}uint8 reg) [{}uint8]
- ;{}uint8 out = string_from_int(offset)
- ;out.append('(')
- ;add_strings(~out, ~reg)
- ;out.append(')')
- ;return out
-;/
-
-
-# The temp registers in order
-/; 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"
- ;/
- ;return string_from_int(r + 2)
-;/
-
-/; ext_by_size(int s) [uint8]
- /; if (r == 1)
- ;return 'b'
- ;; if (r == 2)
- ;return 'w'
- ;; if (r == 4)
- ;return 'l'
- ;/
- ;return 'q'
-;/
-
-
-/; method Value
-
- /; get_norm_sz [int]
- /; if (self._type.ptr !== 0)
- ;return 8
- ;/
- ;returnself._type._size
- ;/
-
- /; get_norm_loc [{}uint8]
- /; if (self.on_stack)
- ;return val_from_address(self.loc, "%rsp")
- ;; if (!(self.on_stack) && self._type.ptr == 0 && is_struct(self._type))
- ;{}uint8 out = "("
- ;{}uint8 tmp = get_reg(8, reg_by_num(self.loc))
- ;add_strings(~out, ~tmp)
- ;out.append(')')
- ;return out
- ;/
-
- /; if (self.literal)
- ;{}uint8 out = "$"
- ;{}uint8 num = string_from_int(self.val)
- ;add_strings(~out, ~num)
- ;return out
- ;/
-
- ;int sz = self._type._size
- /; if (self._type.ptr !== 0)
- ;sz = 8
- ;/
-
- ;return get_reg(sz, reg_by_num(self.loc))
- ;/
-
- /; init_val [{}uint8]
- /; if (self.literal || !self.on_stack)
- ;return ""
- ;/
-
- ;{}uint8 out = "\tsub $"
- ;{}uint8 tmp = string_from_int(self._type._size)
- ;add_strings(~out, ~tmp)
- ;tmp = ", %rsp\n"
- ;add_strings(~out, ~tmp)
- ;return out
- ;/
-
- /; standard_op(Value other, {}uint8 op) [{}uint8]
- ;tnsl.io.print("Std op ")
- ;tnsl.io.println(op)
- ;int tsz = other._type._size
- ;other._type._size = self._type._size
- ;{}uint8 tmp = other.get_norm_loc()
- ;other._type._size = tsz
- ;{}uint8 out = "\t"
- ;add_strings(~out, ~op)
- ;out.append(' ')
- ;add_strings(~out, ~tmp)
- ;out.append(',')
- ;out.append(' ')
- ;tmp = self.get_norm_loc()
- ;add_strings(~out, ~tmp)
- ;out.append('\n')
- ;return out
- ;/
-
- /; add_value (Value v) [{}uint8]
- /; if (self.literal)
- ;self.val = self.val + v.val
- ;return ""
- ;; else if (!(self.on_stack))
- ;return self.standard_op(v, "add")
- ;/
- ;/
-
- /; sub_value (Value v) [{}uint8]
- /; if (self.literal)
- ;self.val = self.val - v.val
- ;return ""
- ;; else if (!(self.on_stack))
- ;return self.standard_op(v, "sub")
- ;/
- ;/
-
- /; ax_compute(Value v, {}uint8 op, bool save_dx)
- ;{}uint8 out = "\tpush %rax\n\tpush %rdx\n"
-
- /; if (v.on_stack)
- ;v.loc = v.loc + 16
- ;; if (self.on_stack)
- ;self.loc = self.loc + 16
- ;/
-
- ;{}uint8 tmp = "\tmov "
- ;{}uint8 t2 = v.get_norm_loc()
- ;add_strings(~tmp, ~t2)
- ;t2 = ", %rax\n"
- ;add_strings(~tmp, ~t2)
- ;add_strings(~out, ~tmp)
-
- ;tmp = "\txor %rdx, %rdx\n"
- ;add_strings(~out, ~tmp)
-
- ;tmp = "\t"
- ;add_strings(~tmp, ~op)
- ;tmp.append(' ')
- ;{}uint8 t2 = self.get_norm_loc()
- ;add_strings(~tmp, ~t2)
- ;tmp.append('\n')
- ;add_strings(~out, ~tmp)
-
- /; if (save_dx)
- ;tmp = "\tmov %rdx, "
- ;; else
- ;tmp = "\tmov %rax, "
- ;/
- ;add_strings(~tmp, ~t2)
- ;tmp.append('\n')
- ;add_strings(~out, ~tmp)
-
- /; if (v.on_stack)
- ;v.loc = v.loc - 16
- ;; if (self.on_stack)
- ;self.loc = self.loc - 16
- ;/
-
- ;tmp = "\tpop %rdx\n\tpop %rax"
- ;add_strings(~out, ~tmp)
- ;return out
- ;/
-
- /; mul_value (Value v) [{}uint8]
- /; if (self.literal)
- ;self.val = self.val * v.val
- ;return ""
- ;; else if (!(self.on_stack))
- /; if (self._type.name{0} !== 'u')
- ;return self.standard_op(v, "imul")
- ;/
-
- ;return self.ax_compute(v, "mul", false)
- ;/
- ;/
-
- /; div_value (Value v) [{}uint8]
- /; if (self.literal)
- ;self.val = self.val + v.val
- ;return ""
- ;; else if (!(self.on_stack))
- /; if (self._type.name{0} !== 'u')
- ;return self.ax_compute(v, "idiv", false)
- ;/
-
- ;return self.ax_compute(v, "div", false)
- ;/
- ;/
-
- /; mod_value (Value v) [{}uint8]
- /; if (self.literal)
- ;self.val = self.val / v.val
- ;return ""
- ;; else if (!self.on_stack)
- /; if (self._type.name{0} !== 'u')
- ;return self.ax_compute(v, "idiv", true)
- ;/
-
- ;return self.ax_compute(v, "div", true)
- ;/
- ;/
-
- /; ref_value (Value to_ref) [{}uint8]
- /; if (!to_ref.on_stack)
- ;return ""
- ;/
-
- ;return self.standard_op(to_ref, "lea")
- ;/
-
- /; deref_value [{}uint8]
- /; if (self._type.ptr == 0)
- ;return ""
- ;/
-
- ;Value new = self
- ;new._type.ptr = new._type.ptr - 1
- ;{}uint8 out = "\tmov ("
- ;{}uint8 tmp = self.get_norm_loc()
- ;add_strings(~out, ~tmp)
- ;out.append(')')
- ;out.append(',')
- ;out.append(' ')
- ;tmp = new.get_norm_loc()
- ;add_strings(~out, ~tmp)
-
- ;self = new
- ;return out
- ;/
-
- /; get_index (Value index) [Value]
- /; if (self._type.ptr == 0)
- ;return NV
- ;/
- ;/
-
- /; set_value (Value v) [{}uint8]
- /; if (self.literal)
- ;self.val = v.val
- ;return ""
- ;; else if (!(self.on_stack))
- /; if (!is_struct(self._type))
- ;return self.standard_op(v, "mov")
- ;/
- # This is the case where we are storing an address to
- # a struct in a register.
- ;{}charp out = "\tpush %rcx\n\tmov "
- ;{}charp tmp = self.get_norm_loc()
- ;add_strings(~out, ~tmp)
- ;tmp = ", %rcx\n"
- ;add_strings(~out, ~tmp)
- ;tmp = self.standard_op(v, "movsb")
- ;add_strings(~out, ~tmp)
- ;tmp = "\tpop %rcx"
- ;add_strings(~out, ~tmp)
- ;return out
- ;/
-
- /; if (self._type._size !> 8)
- /; if (!v.on_stack)
- ;return self.standard_op(v, "mov")
- ;/
- ;{}charp out = "\tpush %rax\n\tmov "
- ;{}charp tmp = v.get_norm_loc()
- ;add_strings(~out, ~tmp)
- ;tmp = ", %rax\n"
- ;add_strings(~out, ~tmp)
- ;tmp = self.standard_op(v, "mov")
- ;add_strings(~out, ~tmp)
- ;return out
- ;/
-
- ;/
-
- /; load_label_address ({}uint8 lab) [{}uint8]
- ;{}uint8 out = "\tlea "
- ;{}uint8 tmp = "(%rip), "
- ;add_strings(~out, ~lab)
- ;add_strings(~out, ~tmp)
- ;tmp = self.get_norm_loc()
- ;add_strings(~out, tmp)
- ;out.append('\n')
- ;return out
- ;/
-
- /; get_member_value ({}uint8 name) [Value]
- ;Value out = self
- /; if (self.on_stack)
- ;out.loc = out.loc + self._type.get_offset(name)
- ;; else
- ;out.val = out.val + self._type.get_offset(name)
- ;/
- ;out._type = self._type.get_sub_type(name)
- ;out._type.ptr = -1
- ;return out
- ;/
-
- /; mov_to_reg (int reg) [{}uint8]
- /; if (!(self.on_stack))
- ;return self.update_loc(0)
- ;/
- ;/
-
- /; update_loc(int loc) [{}uint8]
- /; if (self.on_stack)
- ;self.loc = self.loc + loc
- ;; else if (!(self.literal))
- ;{}uint8 out = "\tmov "
- ;int tsz = self._type._size
- ;self._type._size = 8
-
- ;{}uint8 tmp = self.get_norm_loc()
- ;add_strings(~out, ~tmp)
- ;out.append(',')
- ;out.append(' ')
-
- ;self.loc = loc
-
- ;tmp = self.get_norm_loc()
- ;add_strings(~out, ~tmp)
- ;out.append('\n')
-
- ;self._type._size = tsz
- ;return out
- ;/
- ;return ""
- ;/
-
-;/
-
-/; literal_val (int l, VType t) [Value]
- ;return {false, true, 0, l, t}
-;/
-
-/; track_val(VType ty, bool on_stack, int loc) [Value]
- ;return {on_stack, false, loc, 0, ty}
-;/
diff --git a/tnslc/copy.tnsl b/tnslc/copy.tnsl
deleted file mode 100644
index 0cc594e..0000000
--- a/tnslc/copy.tnsl
+++ /dev/null
@@ -1,30 +0,0 @@
-/#
- Proof of concept that the language can copy any file.
-
- For testing with executibles to make sure that the language's current state
- would be able to produce one from data alone.
-
- Seems to work.
-#/
-
-/; main ({}{}uint8 args) [int]
- /; if (len args < 2)
- ;tnsl.io.println("Usage: copy [file to copy] [path to copy to]")
- ;return 1
- ;/
-
- ;tnsl.io.File in = tnsl.io.readFile(args{0})
- ;tnsl.io.File out = tnsl.io.writeFile(args{1})
-
- /; loop (int chk = in.read(); chk !< 0) [chk = in.read()]
- ;uint8 write = chk
- ;out.write(write)
- ;/
-
- ;tnsl.io.println("Copy complete.")
-
- ;in.close()
- ;out.close()
-
- ;return 0
-;/
diff --git a/tnslc/dummy.tnsl b/tnslc/dummy.tnsl
deleted file mode 100644
index 741a0e0..0000000
--- a/tnslc/dummy.tnsl
+++ /dev/null
@@ -1,33 +0,0 @@
-;struct test {
- int8 i, j, k, l
-}
-
-;struct test2 {
- test a, b
-}
-
-/; add (int a, b) [int]
- ;return a + b - 9 - 30
-;/
-
-/; main (uint argc, ~~uint8 argv) [int]
- # Fix for main func
- ;asm "mov %rdi, %r8"
- ;asm "mov %rsi, %r9"
- # ;~void ptr = _alloc(10)
- # ;_delete(ptr)
- # ;return add(argc, 2)
-;/
-
-
-/; _alloc (uint bytes) [~void]
- ;asm "mov %rax, %rdi"
- ;asm "mov $0, %r10"
- ;asm "call malloc"
-;/
-
-/; _delete (~void ptr)
- ;asm "mov %rax, %rdi"
- ;asm "mov $0, %r10"
- ;asm "call free"
-;/
diff --git a/tnslc/inc.tnsl b/tnslc/inc.tnsl
deleted file mode 100644
index 6e17855..0000000
--- a/tnslc/inc.tnsl
+++ /dev/null
@@ -1,3 +0,0 @@
-/; module main
- :include "dummy.tnsl"
-;/ \ No newline at end of file
diff --git a/tnslc/parse/parse.tnsl b/tnslc/parse/parse.tnsl
deleted file mode 100644
index 8919c3a..0000000
--- a/tnslc/parse/parse.tnsl
+++ /dev/null
@@ -1,87 +0,0 @@
-/##
- Copyright 2021-2022 Kyle Gunger
-
- This file is licensed under the CDDL 1.0 (the License)
- and may only be used in accordance with the License.
- You should have received a copy of the License with this
- software/source code. If you did not, a copy can be found
- at the following URL:
-
- https://opensource.org/licenses/CDDL-1.0
-
- THIS SOFTWARE/SOURCE CODE IS PROVIDED "AS IS" WITH NO
- WARRANTY, GUARANTEE, OR CLAIM OF FITNESS FOR ANY PURPOSE
- EXPRESS OR IMPLIED
-#/
-
-/; export module parse
- :include "parse/token.tnsl"
- :include "parse/tokenizer.tnsl"
-;/
-
-/; create_panic ({}uint8 err)
- ;tnsl.io.println("ABOUT TO INDUCE PANIC... STAND BY")
- ;tnsl.io.print("Error code given: ")
- ;tnsl.io.println(err)
- ;{}int i = {0}
- ;i{2}
-;/
-
-/# The various types of tokens #/
-; enum TOKEN_TYPE [int] {
- LINESEP = 0,
- INLNSEP = 1,
- DELIMIT = 2,
- AUGMENT = 3,
- LITERAL = 4,
- KEYTYPE = 5,
- PREWORD = 6,
- KEYWORD = 7,
- DEFWORD = 8
-}
-
-/# Token struct definition #/
-; struct Token {
- int
- token_type,
- line,
- col,
-
- ~{}uint8
- data
-}
-
-/; method Token
-
- /; print
- ;tnsl.io.print("{ ")
- ;tnsl.io.print(self.token_type)
- ;tnsl.io.print(" ")
- ;tnsl.io.print(self.data`)
- ;tnsl.io.print(" ")
- ;tnsl.io.print(self.line)
- ;tnsl.io.print(" ")
- ;tnsl.io.print(self.col)
- ;tnsl.io.print(" } ")
- ;/
-
- /; operator delete
- ;delete self.data
- ;/
-
- /; add_char (~{}uint8 part)
- # ;uint l = len self.data`
- # ;realloc self.data, l + len part
- /; loop (int i = 0; i < len part`) [i++]
- # ;self.data`{l + i} = part{i}
- ;self.data`.append(part`{i})
- ;/
- ;/
-;/
-
-/; print_tokens(~{}Token dat)
- /; loop (int i = 0; i < len dat`) [i++]
- ;dat`{i}.print()
- ;/
- ;tnsl.io.print("\n")
-;/
diff --git a/tnslc/parse/token.tnsl b/tnslc/parse/token.tnsl
deleted file mode 100644
index fecc7f7..0000000
--- a/tnslc/parse/token.tnsl
+++ /dev/null
@@ -1,331 +0,0 @@
-/#
- Copyright 2021-2022 Kyle Gunger
-
- This file is licensed under the CDDL 1.0 (the License)
- and may only be used in accordance with the License.
- You should have received a copy of the License with this
- software/source code. If you did not, a copy can be found
- at the following URL:
-
- https://opensource.org/licenses/CDDL-1.0
-
- THIS SOFTWARE/SOURCE CODE IS PROVIDED "AS IS" WITH NO
- WARRANTY, GUARANTEE, OR CLAIM OF FITNESS FOR ANY PURPOSE
- EXPRESS OR IMPLIED
-#/
-
-/#
- Reserved words and characters, as well as
- helper funcs for checking their token types.
-#/
-
-;{}{}uint8 PREWORDS = {
- "include",
- "define",
- "extern",
- "size",
- "align",
- "address",
- "rootfile",
- "if",
- "else",
- "abi"
-}
-
-;{}{}uint8 KEYTYPES = {
- "int8",
- "int16",
- "int32",
- "int64",
- "int",
-
- "uint8",
- "uint16",
- "uint32",
- "uint64",
- "uint",
-
- "float32",
- "float64",
- "float",
-
- "bool",
- "void",
- "type"
-}
-
-;{}{}uint8 KEYWORDS = {
- "struct",
- "interface",
- "enum",
- "extends",
-
- "loop",
- "continue",
- "break",
-
- "match",
- "case",
- "default",
-
- "label",
- "goto",
-
- "if",
- "else",
-
- "const",
- "static",
- "volatile",
-
- "method",
- "override",
- "operator",
-
- "raw",
- "asm",
- "inline",
- "virtual",
-
- "delete",
- "alloc",
- "salloc",
- "realloc",
-
- "module",
- "export"
-}
-
-;{}{}uint8 LITERALS = {
- "true",
- "false",
-
- "null",
-
- "self",
- "super"
-}
-
-;{}uint8 RESERVED = "`~!#%^&*()-=+[]{}|;:,.<>/"
-
-;{}uint8 DELIMITS = "()[]{}"
-;{}uint8 LINESEPS = ";:#"
-;{}uint8 INLNSEPS = ","
-;{}uint8 AUGMENTS = "~`.&|^><!+-*/%"
-
-;{}{}uint8 MDELIMITS = {
- # Code block
- "/;",
- ";/",
-
- # Comment block
- "/#",
- "#/",
-
- # Preproc block
- "/:",
- ":/",
-
- # Redef blocks
- ";;",
- "::",
- ";#",
- ":#",
- "#;",
- "#:"
-}
-
-;{}{}uint8 MAUGMENTS = {
- # Boolean
- "==",
- "&&",
- "||",
-
- # Bitwise shifts
- "<<",
- ">>",
-
- # PREaugmented augmentors
- "&=",
- "|=",
- "^=",
- "+=",
- "-=",
- "*=",
- "/=",
- "%=",
- "~=",
- "`=",
-
- # POSTaugmented augmentors
- "!&",
- "!|",
- "!^",
- "!==",
- "!&&",
- "!||",
- "!>",
- "!<",
- ">==",
- "<==",
-
- # Increment and De-increment
- "++",
- "--",
-
- "is",
- "len",
- "size"
-}
-
-;int MAX_MRESERVED = 3
-
-/##
- Checks if the character point p is in the string cmp
-
-#; is_in_string (~{}uint8 cmp, uint8 p) [bool]
-
- /; loop (int i = 0; i < len cmp`) [i++]
- /; if (p == cmp`{i})
- ;return true
- ;/
- ;/
-
- ;return false
-;/
-
-/##
- Checks if the string s is in the list cmp
-
-#; is_in_string_list (~{}{}uint8 cmp, ~{}uint8 s) [bool]
-
- /; loop (int i = 0; i < len cmp`) [i++]
-
- /; if (len s` == len cmp`{i})
-
- /; loop (int j = 0; j < len s`) [j++]
-
- /; if (s`{j} !== cmp`{i}{j})
- ;break 1
- ;/
- ;/
-
- ;return true
- ;/
-
- ;/
-
- ;return false
-;/
-
-/; is_numeric_literal(~{}uint8 dat) [bool]
- /; if (len dat` == 0)
- ;return false
- ;/
-
- ;bool dec = true, flt = false
-
- ;int i = 0
-
- /; if (len dat` > 1)
- /; if (dat`{0} == '0' && !is_digit(dat`{1}) && dat`{1} !== '.')
- ;dec = false
- ;i = 2
- ;/
- ;/
-
- /; loop (i < len dat`) [i++]
- /; if (!is_digit(dat`{i}) && dec)
- /; if (dat`{i} == '.')
- /; if (flt)
- ;return false
- ;/
- ;flt = true
- ;; else if (dec)
- ;return false
- ;/
- ;/
- ;/
-
- ;return true
-;/
-
-/; is_text_literal(~{}uint8 dat) [bool]
- /; if (len dat` < 1)
- ;return false
- ;/
- ;return dat`{0} == '"' || dat`{0} == '\''
-;/
-
-/; string_closed ({}uint8 dat, uint8 c) [bool]
- /; if (len dat < 2)
- ;return false
- ;/
-
- ;uint8 closing = dat{0}
- ;bool escaping = false
-
- /; loop (int i = 1; i < len dat) [i++]
- /; if (dat{i} == closing && !escaping)
- ;return true
- ;; else if (dat{i} == '\\' && !escaping)
- ;escaping = true
- ;; else
- ;escaping = false
- ;/
- ;/
-
- ;return false
-;/
-
-/#
- Get the token_type value for a given string of character points
-
-#; get_token_type (~{}uint8 s) [int]
-
- /; if (len s` > 1)
-
- /; if (is_numeric_literal(s) || s`{0} == '"' || s`{0} == '\'')
- ;return TOKEN_TYPE.LITERAL
- ;/
-
- /; if (is_in_string_list(~PREWORDS, s))
- ;return TOKEN_TYPE.PREWORD
- ;; else if (is_in_string_list(~KEYTYPES, s))
- ;return TOKEN_TYPE.KEYTYPE
- ;; else if (is_in_string_list(~KEYWORDS, s))
- ;return TOKEN_TYPE.KEYWORD
- ;; else if (is_in_string_list(~LITERALS, s))
- ;return TOKEN_TYPE.LITERAL
- ;; else if (is_in_string_list(~MDELIMITS, s))
- ;return TOKEN_TYPE.DELIMIT
- ;; else if (is_in_string_list(~MAUGMENTS, s))
- ;return TOKEN_TYPE.AUGMENT
- ;/
-
- ;return TOKEN_TYPE.DEFWORD
-
- ;;else if (len s` == 1)
-
- /; if (is_digit(s`{0}))
- ;return TOKEN_TYPE.LITERAL
- ;/
-
- /; if (is_in_string(~DELIMITS, s`{0}))
- ;return TOKEN_TYPE.DELIMIT
- ;; else if (is_in_string(~LINESEPS, s`{0}))
- ;return TOKEN_TYPE.LINESEP
- ;; else if (is_in_string(~INLNSEPS, s`{0}))
- ;return TOKEN_TYPE.INLNSEP
- ;; else if (is_in_string(~AUGMENTS, s`{0}))
- ;return TOKEN_TYPE.AUGMENT
- ;/
-
- ;return TOKEN_TYPE.DEFWORD
- ;/
-
- # What, we just produce vacant tokens now?
- # Something has gone wrong.
-
- ;return -1
-;/ \ No newline at end of file
diff --git a/tnslc/parse/tokenizer.tnsl b/tnslc/parse/tokenizer.tnsl
deleted file mode 100644
index 30ccd4b..0000000
--- a/tnslc/parse/tokenizer.tnsl
+++ /dev/null
@@ -1,114 +0,0 @@
-/#
- Copyright 2021-2022 Kyle Gunger
-
- This file is licensed under the CDDL 1.0 (the License)
- and may only be used in accordance with the License.
- You should have received a copy of the License with this
- software/source code. If you did not, a copy can be found
- at the following URL:
-
- https://opensource.org/licenses/CDDL-1.0
-
- THIS SOFTWARE/SOURCE CODE IS PROVIDED "AS IS" WITH NO
- WARRANTY, GUARANTEE, OR CLAIM OF FITNESS FOR ANY PURPOSE
- EXPRESS OR IMPLIED
-#/
-
-/; is_float (~{}uint8 dat) [bool]
- ;return is_numeric_literal(dat) && is_in_string(dat, '.')
-;/
-
-/; break_token ({}uint8 dat, uint8 c) [bool]
- /; if (len dat == 0)
- ;return false
-
- ;; else if (dat{0} == '"' || dat{0} == '\'')
- ;return string_closed(dat, c)
-
- ;; else if (is_in_string(~RESERVED, dat{len dat - 1}))
-
- /; if (is_in_string(~RESERVED, c))
- ;dat.append(c)
- ;return get_token_type(~dat) == TOKEN_TYPE.DEFWORD
-
- ;; else if (len dat == 1 && dat{0} == '.')
- ;return !is_digit(c)
-
- ;/
-
- ;return true
-
- ;; else if (is_in_string(~RESERVED, c))
-
- /; if (is_numeric_literal(~dat) && !is_float(~dat) && c == '.')
- ;return false
-
- ;/
-
- ;return true
- ;/
-
- ;return is_whitespace(c)
-;/
-
-/; strip_and_expand (~{}Token dat) [{}Token]
- ;{}Token out = {}
-
- ;bool cblk = false
-
- /; loop (int i = 0; i < len dat`) [i++]
- /; if (!cblk)
- /; if (string_equate(dat`{i}.data`, "/#"))
- ;cblk = true
- ;; else
- ;out.append(dat`{i})
- ;/
-
- ;; else if (string_equate(dat`{i}.data`, "#/"))
- ;cblk = false
- ;/
- ;/
-
- ;return out
-;/
-
-/; tokenize (tnsl.io.File fstr) [~{}Token]
- ;{}Token out = {}
- ;{}uint8 tdat = {}
- ;bool comment = false
- ;int line = 1, col = 1
-
- /; loop (int i = fstr.read(); i !== -1) [i = fstr.read()]
- /; if (break_token(tdat, i) && !comment)
- /; if (len tdat == 1 && tdat{0} == '#')
- ;tdat = {}
- ;comment = true
- ;; else if (len tdat > 0)
- ;{}uint8 tmp = tdat
- ;Token ttk = {get_token_type(~tmp), line, col, ~tmp}
- ;out.append(ttk)
- ;tdat = {}
- ;/
- ;/
-
- /; if ( (!is_whitespace(i) || is_text_literal(~tdat)) && !comment )
- ;tdat.append(i)
- ;; else if (i == '\n')
- ;line++
- ;col = 0
- /; if (comment)
- ;comment = false
- ;/
- ;/
-
- ;col++
- ;/
-
- /; if (len tdat > 0)
- ;Token ttk = {get_token_type(~tdat), line, col, ~tdat}
- ;out.append(ttk)
- ;/
-
- ;out = strip_and_expand(~out)
- ;return ~out
-;/
diff --git a/tnslc/paths.tnsl b/tnslc/paths.tnsl
deleted file mode 100644
index 17719a0..0000000
--- a/tnslc/paths.tnsl
+++ /dev/null
@@ -1,103 +0,0 @@
-# Requires util.tnsl
-;struct Path {
- {}{}uint8 dirs,
- {}uint8 file
-}
-
-/; method Path
- /; rel_file ({}uint8 rpath) [Path]
- ;{}{}uint8 spl = split(rpath, '/')
- ;Path out = {{}, ""}
-
- /; loop (int i = 0; i < len (self.dirs)) [i++]
- ;out.dirs.append(self.dirs{i})
- ;/
-
- /; loop (int i = 0; i < len spl - 1) [i++]
- ;out.dirs.append(spl{i})
- ;/
-
- ;out.file = spl{len spl - 1}
- ;return out
- ;/
-
- /; full_path [{}uint8]
- ;{}uint8 out = join((self.dirs), '/')
- /; if (len (self.dirs) > 0)
- ;out.append('/')
- ;/
- ;add_strings(~out, ~(self.file))
- ;return out
- ;/
-
- /; open_w [tnsl.io.File]
- ;return tnsl.io.writeFile(self.full_path())
- ;/
-
- /; open_r [tnsl.io.File]
- ;return tnsl.io.readFile(self.full_path())
- ;/
-
- /; extension_is ({}uint8 chk) [bool]
- ;{}uint8 ext = ""
- ;int dot = -1
- /; loop (int i = len (self.file) - 1; i > 0) [i = i - 1]
- /; if (self.file{i} == '.')
- ;dot = i
- ;break
- ;/
- ;/
-
- /; if (dot > 0)
- ;dot++
- /; loop (dot < len (self.file)) [dot++]
- ;ext.append(self.file{dot})
- ;/
- ;/
-
- ;return string_equate(chk, ext)
- ;/
-
-;/
-
-/; split({}uint8 str, uint8 c) [{}{}uint8]
- ;{}{}uint8 out = {}
- ;{}uint8 tmp = ""
-
- /; loop (int i = 0; i < len str) [i++]
- /; if (str{i} == c)
- ;out.append(tmp)
- ;{}uint8 tmp = ""
- ;true # work around for interpreter bug
- ;; else
- ;tmp.append(str{i})
- ;/
- ;/
- ;out.append(tmp)
-
- ;return out
-;/
-
-/; join ({}{}uint8 s, uint8 jc) [{}uint8]
- ;{}uint8 out = ""
- /; loop (int i = 0; i < len s) [i++]
- /; loop (int j = 0; j < len s{i}) [j++]
- ;out.append(s{i}{j})
- ;/
- /; if (i < len s - 1)
- ;out.append(jc)
- ;/
- ;/
-
- ;return out
-;/
-
-/; path_from_str ({}uint8 f) [Path]
- ;{}{}uint8 spl = split(f, '/')
- ;Path out = {{}, ""}
- /; loop (int i = 0; i < len spl - 1) [i++]
- ;out.dirs.append(spl{i})
- ;/
- ;out.file = spl{len spl - 1}
- ;return out
-;/
diff --git a/tnslc/test.tnsl b/tnslc/test.tnsl
new file mode 100644
index 0000000..b274dfd
--- /dev/null
+++ b/tnslc/test.tnsl
@@ -0,0 +1,21 @@
+struct PTR_TEST {
+ int dat, in
+}
+
+struct ARRAY_TEST {
+ {}PTR_TEST dat
+}
+
+enum ENUM_TEST [{}int] {
+ A = {2, 3, 4, 5, 623459},
+ B = {1, 2}
+}
+
+enum EN_ARR [PTR_TEST] {
+ A = {1, 2},
+ B = {3, 4}
+}
+
+/; main [int]
+ return EN_ARR.A.dat
+;/ \ No newline at end of file
diff --git a/tnslc/tests/complex/enums.tnsl b/tnslc/tests/complex/enums.tnsl
new file mode 100644
index 0000000..80776f0
--- /dev/null
+++ b/tnslc/tests/complex/enums.tnsl
@@ -0,0 +1,84 @@
+# Enums should be able to store structs as well
+struct EnumTester {
+ int i, j
+ ~EnumTester ptr
+}
+
+# Simple integer enum
+enum IntEnum [int] {
+ A = 0,
+ B = 1,
+ C = -2
+}
+
+# Simple float enum
+enum FloatEnum[float] {
+ A = 0.1,
+ B = 0.2,
+ C = 3.1415
+}
+
+# More complex struct enum
+enum TestEnum [EnumTester] {
+ A = {1, 2, null},
+ B = {2, 3, ~TestEnum.A},
+ C = {3, 3, null}
+}
+
+# Type enum
+enum TypeEnum [type] {
+ A = int,
+ B = float,
+ C = EnumTester
+}
+
+enum SurfaceType [int] {
+ LAND = 0,
+ WATER = 1,
+ AIR = 2,
+
+ SPACE = -1
+}
+
+/; interface Vehicle
+ /; fuel [float] ;/
+ /; max_speed [float] ;/
+ /; min_speed [float] ;/
+ /; can_travel (SurfaceType surface) [bool] ;/
+;/
+
+struct Car extends Vehicle {
+ int wheels
+}
+
+struct Boat extends Vehicle {
+ int propellers
+}
+
+struct Plane extends Vehicle {
+ bool biplane, passenger
+ int engines,
+}
+
+struct Rocket extends Vehicle {
+ int
+ engines,
+ stages
+}
+
+struct HoverCraft extends Vehicle {
+ {3}float
+ max_antigrav,
+ bool
+ space_ready
+}
+
+# Enums can also handle interfaces (and extended types)
+# but only if the given standard library has support for those things
+enum CommonVehicles [Vehicle] {
+ A = {4}[Car],
+ B = {1}[Boat],
+ C = {false, true, 2}[Plane],
+ D = {4, 5}[Rocket],
+ E = {{5, 14.8, 5}, false}[HoverCraft]
+}
diff --git a/tnslc/tests/complex/generics.tnsl b/tnslc/tests/complex/generics.tnsl
new file mode 100644
index 0000000..3f62474
--- /dev/null
+++ b/tnslc/tests/complex/generics.tnsl
@@ -0,0 +1,35 @@
+struct ListNode (type T) {
+ T element,
+ ~ListNode(T) next
+}
+
+/; method ListNode
+ /; get_el [T]
+ return self.element
+ ;/
+
+ /; get_next [ListNode(T)]
+ return self.next`
+ ;/
+;/
+
+struct ReferenceNode (type T) extends ListNode(T`) {
+ super
+}
+
+/; method ReferenceNode
+ /; change_ref (~T new_ref)
+ ~self.element = new_ref
+ ;/
+;/
+
+struct List(type T) {
+
+}
+
+# Generic (type T)
+# Unknown generic (?)
+# Ref to a type (type T) -> T`
+# Ref types can be used interchangably with their referenced type while pointer types can not
+# Variables typed by reference have the additional trait that you can
+# set the address of that variable \ No newline at end of file
diff --git a/tnslc/tests/complex/if_else.tnsl b/tnslc/tests/complex/if_else.tnsl
new file mode 100644
index 0000000..d965e6b
--- /dev/null
+++ b/tnslc/tests/complex/if_else.tnsl
@@ -0,0 +1,46 @@
+/; main [int]
+ /; if ()
+
+ ;/
+
+ /; if ()
+
+ ;; else
+
+ ;/
+
+ /; if ()
+
+ ;//; else
+
+ ;/
+
+ /; if ()
+
+ ;; else if ()
+
+ ;/
+
+ /; if () []
+ ;; else if () []
+ ;; else []
+ ;/
+
+ /; if () []
+ ;; if () []
+ ;; else []
+ ;/
+
+ /; if () []
+ ;; if () []
+ ;; else if () []
+ ;; else []
+ ;/
+
+ int i = 0
+
+ # Short if syntax for variable declaration
+ i = if (i < 1) [7] else [9]
+
+ ;return 0
+;/ \ No newline at end of file
diff --git a/tnslc/tests/complex/interfaces.tnsl b/tnslc/tests/complex/interfaces.tnsl
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tnslc/tests/complex/interfaces.tnsl
diff --git a/tnslc/tests/complex/loops.tnsl b/tnslc/tests/complex/loops.tnsl
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tnslc/tests/complex/loops.tnsl
diff --git a/tnslc/tests/complex/switch.tnsl b/tnslc/tests/complex/switch.tnsl
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tnslc/tests/complex/switch.tnsl
diff --git a/tnslc/tests/simple/comments.tnsl b/tnslc/tests/simple/comments.tnsl
new file mode 100644
index 0000000..dbece20
--- /dev/null
+++ b/tnslc/tests/simple/comments.tnsl
@@ -0,0 +1,52 @@
+# These are tests for where comments may be located
+# as well as the type of comments that may be parsed.
+# A '#' denotes a single line comment, and will
+# ignore everything on the line.
+# '/#' denotes the start of a multi line comment
+# if you want to use '#/' (the end of a multiline comment)
+# inside of a multiline comment, use '#' at the start of the line
+# to escape the whole line.
+
+/#
+ This is an example
+ of a multiline comment.
+#/
+
+/#
+# This is also a multiline comment
+# however, you can use #/
+# inside of it because we have '#' at
+# the start of each line
+#/
+
+/##
+# This is an example of a doc comment.
+# It is a doc comment of a code block because it starts with '/##' instead of '/#'
+# and ends with '# ;' which ends the comment and opens a block.
+# This doc comment is on the main function
+#; main /# Comment inside function declaration #/ [int /# Comment inside this list of outputs #/ ]
+ return 0 # line comment inside a function
+ /# Block comment inside function #/
+;/
+
+/# Comment before block opens #/ /; interface /# Comment in interface block definition #/ ITest
+ # Comment in interface block
+ /; test_method [int] ;/
+/# Comment before block closes #/ ;/
+
+struct Test {
+ # comment inside a list of member variables
+ int /# Comment btwn type and variable name #/ i
+}
+
+/; method /# Comment in method block definition #/ Test
+ # Comment in method block
+ /; /# Comment before method name#/ test_method (/# Comment inside function params #/) [/# comment inside return type again#/ int]
+/# Comment at start of line before statement#/ return /# Comment btwn return and value #/ i
+ ;/
+
+ /; cf_comment [int]
+
+ ;/
+;/
+
diff --git a/tnslc/tests/simple/if_else.tnsl b/tnslc/tests/simple/if_else.tnsl
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tnslc/tests/simple/if_else.tnsl
diff --git a/tnslc/tests/simple/includes_a.tnsl b/tnslc/tests/simple/includes_a.tnsl
new file mode 100644
index 0000000..930098a
--- /dev/null
+++ b/tnslc/tests/simple/includes_a.tnsl
@@ -0,0 +1 @@
+:include "includes_b.tnsl" \ No newline at end of file
diff --git a/tnslc/tests/simple/includes_b.tnsl b/tnslc/tests/simple/includes_b.tnsl
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tnslc/tests/simple/includes_b.tnsl
diff --git a/tnslc/tests/simple/modules_a.tnsl b/tnslc/tests/simple/modules_a.tnsl
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tnslc/tests/simple/modules_a.tnsl
diff --git a/tnslc/tests/simple/modules_b.tnsl b/tnslc/tests/simple/modules_b.tnsl
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tnslc/tests/simple/modules_b.tnsl
diff --git a/tnslc/tests/simple/structs.tnsl b/tnslc/tests/simple/structs.tnsl
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tnslc/tests/simple/structs.tnsl
diff --git a/tnslc/tnslc.tnsl b/tnslc/tnslc.tnsl
deleted file mode 100644
index 7ca1dfb..0000000
--- a/tnslc/tnslc.tnsl
+++ /dev/null
@@ -1,43 +0,0 @@
-/##
- Copyright 2021-2022 Kyle Gunger
-
- This file is licensed under the CDDL 1.0 (the License)
- and may only be used in accordance with the License.
- You should have received a copy of the License with this
- software/source code. If you did not, a copy can be found
- at the following URL:
-
- https://opensource.org/licenses/CDDL-1.0
-
- THIS SOFTWARE/SOURCE CODE IS PROVIDED "AS IS" WITH NO
- WARRANTY, GUARANTEE, OR CLAIM OF FITNESS FOR ANY PURPOSE
- EXPRESS OR IMPLIED
-#/
-
-:include "util.tnsl"
-:include "paths.tnsl"
-
-/; export module tnslc
- :include "parse/parse.tnsl"
- :include "compile/compile.tnsl"
- :include "compile/isa_x86.tnsl"
- :include "compile/value.tnsl"
-;/
-
-/; main ({}{}uint8 args) [int]
- /; if (len args < 1)
- ;tnsl.io.println("Usage: tnslc [file in]")
- ;return 1
- ;/
-
- ;{}uint8 file = args{0}
-
- # ;tnslc.Node tree_node = tnslc.ast.make_tree(psrc, args{0})
-
- ;Path rel = path_from_str(file)
- ;file.append('.')
- ;file.append('S')
- ;tnslc.do_compile(file, rel)
-
- ;return 0
-;/
diff --git a/tnslc/util.tnsl b/tnslc/util.tnsl
deleted file mode 100644
index d4a7b4b..0000000
--- a/tnslc/util.tnsl
+++ /dev/null
@@ -1,199 +0,0 @@
-/##
- Copyright 2021-2022 Kyle Gunger
-
- This file is licensed under the CDDL 1.0 (the License)
- and may only be used in accordance with the License.
- You should have received a copy of the License with this
- software/source code. If you did not, a copy can be found
- at the following URL:
-
- https://opensource.org/licenses/CDDL-1.0
-
- THIS SOFTWARE/SOURCE CODE IS PROVIDED "AS IS" WITH NO
- WARRANTY, GUARANTEE, OR CLAIM OF FITNESS FOR ANY PURPOSE
- EXPRESS OR IMPLIED
-#/
-
-/# util.tnsl
- Utility functions that may be useful in many places.
-#/
-
-/; string_equate({}uint8 s1, s2) [bool]
- /; if (len s1 !== len s2)
- ;return false
- ;/
-
- /; loop (int i = 0; i < len s1) [i++]
- /; if (s1{i} !== s2{i})
- ;return false
- ;/
- ;/
-
- ;return true
-;/
-
-/; add_strings (~{}uint8 a, b)
- /; loop (int i = 0; i < len b`) [i++]
- ;a`.append(b`{i})
- ;/
-;/
-
-/; reverse_string({}uint8 str) [{}uint8]
- ;{}uint8 out = ""
-
- /; loop (int i = len str; i > 0) [i = i - 1]
- ;out.append(str{i - 1})
- ;/
-
- ;return out
-;/
-
-/; is_whitespace (uint8 c) [bool]
- ;return c == '\t' || c == '\n' || c == ' '
-;/
-
-/; is_digit (uint8 c) [bool]
- ;return c !< '0' && c !> '9'
-;/
-
-/; is_alpha (uint8 c) [bool]
- ;bool low = c !< 'A' && c !> 'Z', high = c !< 'a' && c >! 'z'
- ;return low || high
-;/
-
-/; digit_to_char(int i) [uint8]
- ;uint8 out = '0'
- ;out = out + (i % 10)
- ;return out
-;/
-
-/; string_from_int(int i) [{}uint8]
- ;{}uint8 c = ""
- ;bool n = false
-
- /; if (i < 0)
- ;n = true
- ;i = -i
- ;/
-
- ;c.append(digit_to_char(i))
- ;i = i / 10
-
- /; loop (i !== 0) [i = i / 10]
- ;c.append(digit_to_char(i))
- ;/
-
- /;if (n)
- ;c.append('-')
- ;/
-
- ;return reverse_string(c)
-;/
-
-/; int_from_string ({}uint8 str) [int]
- ;bool inv = str{0} == '-'
- ;int out = 0
- ;int fac = 10
- ;int i = 0
-
- /; if (inv)
- ;i++
- ;/
-
- /; loop (i < len str) [i++]
- ;out = out * fac
- ;out = out + str{i} - '0'
- ;/
-
- /; if (inv)
- ;out = -out
- ;/
-
- ;return out
-;/
-
-/; get_escape_code (uint8 c) [uint8]
- /; if (c == '\'')
- ;return '\''
- ;; else if (c == '"')
- ;return '"'
- ;; else if (c == 'a')
- ;return '\a'
- ;; else if (c == 'b')
- ;return '\b'
- ;; else if (c == 'e')
- ;return '\e'
- ;; else if (c == 'f')
- ;return '\f'
- ;; else if (c == 'n')
- ;return '\n'
- ;; else if (c == 'r')
- ;return '\r'
- ;; else if (c == 't')
- ;return '\t'
- ;; else if (c == 'v')
- ;return '\v'
- ;/
-
- ;return 0
-;/
-
-/; parse_hex_code ({}uint8 c) [uint8]
- ;uint8 out = 0
-
- /; loop (int i = 0; i < len c) [i++]
- ;out = out * 16
- ;uint8 tmp = c{i}
- /; if (tmp !< 'a')
- ;tmp = tmp - 'a' + 'A'
- ;/
-
- /; if (tmp !< '0' && tmp !> '9')
- ;out = out + tmp - '0'
- ;; else if (tmp !< 'A' && tmp !> 'F')
- ;out = out + 10 + (tmp - 'A')
- ;; else
- ;break
- ;/
- ;/
-
- ;return out
-;/
-
-/; unquote_char ({}uint8 c) [uint8]
- /; if (c{1} == '\\')
- /; if (c{2} == 'x')
- ;{}uint8 d = {c{3}, c{4}}
- ;return parse_hex_code(d)
- ;/
- ;return get_escape_code(c{2})
- ;/
-
- ;return c{1}
-;/
-
-/; unquote_string ({}uint8 str) [{}uint8]
- ;{}uint8 out = ""
- ;{}uint8 unc = "'"
-
- /; loop (int i = 1; i < len str - 1) [i++]
- /; if (str{i} == '\\')
- ;unc.append('\\')
- ;unc.append(str{i + 1})
- ;i++
-
- /; if (str{i} == 'x')
- ;unc.append(str{i + 1})
- ;unc.append(str{i + 2})
- ;i = i + 2
- ;/
-
- ;out.append(unquote_char(unc))
- ;unc = "'"
- ;; else
- ;out.append(str{i})
- ;/
- ;/
-
- ;return out
-;/