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