summaryrefslogtreecommitdiff
path: root/tnslc/tnslc.tnsl
diff options
context:
space:
mode:
authorKyle Gunger <kgunger12@gmail.com>2024-03-25 22:39:06 -0400
committerKyle Gunger <kgunger12@gmail.com>2024-03-25 22:39:06 -0400
commitf3a773c750181f8f3d52fd672587814275a04bd7 (patch)
tree8c37ae892960f0988aa6006661beef4ff8b8e8e5 /tnslc/tnslc.tnsl
parent0bc05b40d541483d16445b98ea0841d1912a8198 (diff)
Remove old parser files
Diffstat (limited to 'tnslc/tnslc.tnsl')
-rw-r--r--tnslc/tnslc.tnsl4113
1 files changed, 3 insertions, 4110 deletions
diff --git a/tnslc/tnslc.tnsl b/tnslc/tnslc.tnsl
index a518cc0..993771b 100644
--- a/tnslc/tnslc.tnsl
+++ b/tnslc/tnslc.tnsl
@@ -1,4113 +1,6 @@
-##
-## LOG UTILITIES
-##
+:import "c_wrap_linux.tnsl"
-# Log levels:
-# 0 - Visual queues and errors only
-# 1 - Info (default)
-# 2 - Debugging information (useful for me, probably less for you)
-# 3 - Also logs the state changes of the log itself
-;{}uint8 log_level = "1"
-;{}uint8 log_mode = "single"
-
-/; log_state({}uint8 new_state)
- ;~{}uint8 l = ~log_mode
- /; if (!string_equate(new_state, log_mode))
- ;tnsl.io.println("")
- /; if (string_to_int(log_level) > 2)
- ;tnsl.io.print("[TNSLC] [LOG] Swapping to state [")
- ;tnsl.io.print(new_state)
- ;tnsl.io.println("]")
- ;/
- ;/
-
- ;l` = new_state
-;/
-
-/; log_err ({}uint8 msg)
- ;log_state("err")
- ;tnsl.io.print("[TNSLC] [ERR] ")
- ;tnsl.io.println(msg)
- ;tnsl.exit()
-;/
-
-/; log_info ({}uint8 msg)
- /; if (string_to_int(log_level) > 0)
- ;log_state("info")
- ;tnsl.io.print("[TNSLC] [INFO] ")
- ;tnsl.io.println(msg)
- ;/
-;/
-
-/; log_vis ({}uint8 msg)
- ;log_state("vis")
- ;tnsl.io.print(msg)
-;/
-
-/; log_debug ({}uint8 msg)
- /; if (string_to_int(log_level) > 1)
- ;log_state("debug")
- ;tnsl.io.print("[TNSLC] [DEBUG] ")
- ;tnsl.io.println(msg)
- ;/
-;/
-
-##
-## UTIL FUNCS
-##
-
-/; string_split ({}uint8 str, uint8 split) [{}{}uint8]
- /; if (len str == 0)
- ;return {}
- ;/
-
- ;{}{}uint8 out = {}
-
- ;{}uint8 run = ""
-
- /; loop (int i = 0; i < len str) [i++]
- /; if (str{i} == split)
- ;out.append(run)
- ;run = ""
- ;; else
- ;run.append(str{i})
- ;/
- ;/
-
- ;out.append(run)
-
- ;return out
-;/
-
-/; string_join ({}{}uint8 strs, {}uint8 join) [{}uint8]
- ;{}uint8 out = ""
- /; loop (int i = 0; i < len strs) [i++]
- ;out = string_add(out, strs{i})
- /; if (i !== len strs - 1)
- ;out = string_add(out, join)
- ;/
- ;/
- ;return out
-;/
-
-/; string_add ({}uint8 base, add) [{}uint8]
- /; loop (int i = 0; i < len add) [i++]
- ;base.append(add{i})
- ;/
- ;return base
-;/
-
-/; string_equate ({}uint8 a, b) [bool]
- /; if (len a !== len b)
- ;return false
- ;/
-
- /; loop (int i = 0; i < len a) [i++]
- /; if (a{i} !== b{i})
- ;return false
- ;/
- ;/
-
- ;return true
-;/
-
-/; string_contains ({}uint8 str, uint8 chk) [bool]
- /; loop (int i = 0; i < len str) [i++]
- /; if (str{i} == chk)
- ;return true
- ;/
- ;/
- ;return false
-;/
-
-/; list_contains ({}{}uint8 list, {}uint8 str) [bool]
- /; loop (int i = 0; i < len list) [i++]
- /; if (string_equate(list{i}, str))
- ;return true
- ;/
- ;/
- ;return false
-;/
-
-/; unqote_char ({}uint8 str) [uint8]
- /; if (len str < 3)
- ;return 0
- ;/
-
- /; if (str{1} !== '\\')
- ;return str{1}
- ;/
-
- ;uint8 cmp = str{2}
- /; if (cmp == '\\')
- ;return '\\'
- ;; else if (cmp == 'n')
- ;return '\n'
- ;; else if (cmp == 'r')
- ;return '\r'
- ;; else if (cmp == 't')
- ;return '\t'
- ;; else if (cmp == '0')
- ;return 0
- ;; else if (cmp == '\'')
- ;return '\''
- ;; else if (cmp == '"')
- ;return '"'
- ;/
-;/
-
-/; unquote_str({}uint8 str) [{}uint8]
- /; if (str{0} !== '\'' && str{0} !== '"')
- ;return str
- ;/
- ;{}uint8 out = ""
-
- /; loop (int i = 1; i < len str - 1) [i++]
- /; if (str{i} == '\\')
- ;{}uint8 unq = "'\\"
- ;unq.append(str{i + 1})
- ;out.append(unqote_char(unq))
- ;i++
- ;; else
- ;out.append(str{i})
- ;/
- ;/
-
- ;return out
-;/
-
-/; string_reverse ({}uint8 str) [{}uint8]
- ;{}uint8 out = ""
- /; loop (int i = len str - 1; i !< 0) [i = i - 1]
- ;out.append(str{i})
- ;/
- ;return out
-;/
-
-/; int_to_string (int i) [{}uint8]
- /; if (i == 0)
- ;return "0"
- ;/
-
- ;{}uint8 out = ""
- ;bool inv = i < 0
-
- /; if (inv)
- ;i = -i
- ;/
-
- /; loop [i = i / 10; i > 0]
- ;out.append('0' + (i % 10))
- ;/
-
- /; if (inv)
- ;out.append('-')
- ;/
-
- ;return string_reverse(out)
-;/
-
-/; digit_from_base (uint8 ch, int base) [int]
- /; if (ch == '-')
- ;return 0
- ;/
-
- /; if (base !> 10)
- ;return ch - '0'
- ;; if (base == 16)
- /; if (ch !< 'A' && ch < 'G')
- ;return 11 + (ch - 'A')
- ;; else if (ch !< 'a' && ch < 'g')
- ;return 11 + (ch - 'a')
- ;/
- ;return ch - '0'
- ;/
- ;return 0
-;/
-
-/; string_to_int ({}uint8 str) [int]
- /; if (len str < 1)
- ;return 0
- ;/
- ;int i = 0
- ;bool inv = str{0} == '-'
- /; if (inv)
- ;i = 1
- ;/
-
- ;int out = 0
- ;int base = 10
-
- /; if (len str !< 3 && str{i} == '0')
- /; if (str{i + 1} == 'x')
- ;base = 16
- ;i = i + 2
- ;; if (str{i + 1} == 'b')
- ;base = 2
- ;i = i + 2
- ;; if (str{i + 1} == 'o')
- ;base = 8
- ;i = i + 2
- ;/
- ;/
-
- /; loop (i < len str) [i++]
- ;out = out * base
- ;out = out + digit_from_base(str{i}, base)
- ;/
-
- /; if (inv)
- ;out = -out
- ;/
- ;return out
-;/
-
-/; string_to_csb ({}uint8 str) [{}uint8]
- ;{}uint8 out = ""
-
- /; loop (int i = 0; i < len str) [i++]
- ;out = string_add(out, int_to_string(str{i}))
- /; if (i < len str - 1)
- ;out.append(',')
- ;out.append(' ')
- ;/
- ;/
-
- ;return out
-;/
-
-##
-## Structs
-##
-
-# The seperated string sections that make up an asm file
-;struct CompData {
- {}uint8
- hsec,
- dsec,
- csec
-}
-
-/; method CompData
- /; add (CompData data)
- ;self.hsec = string_add(self.hsec, data.hsec)
- ;self.dsec = string_add(self.dsec, data.dsec)
- ;self.csec = string_add(self.csec, data.csec)
- ;/
-;/
-
-# Represents a relative file path
-;struct Path {
- {}{}uint8 path,
- {}uint8 name
-}
-
-/; method Path
-
- /; relative ({}uint8 rel_path) [Path]
- ;Path out = self
- ;{}{}uint8 rel_split = string_split(rel_path, '/')
-
- /; loop (int i = 0; i < len rel_split - 1)
- ;out.path.append(rel_split{i})
- ;/
-
- ;out.name = rel_split{len rel_split - 1}
-
- ;return out
- ;/
-
- /; full_path [{}uint8]
- ;{}uint8 out = string_join(self.path, "/")
- /; if (len out > 0)
- ;out.append('/')
- ;/
- ;return string_add(out, self.name)
- ;/
-
- /; open_read [tnsl.io.File]
- ;return tnsl.io.readFile(self.full_path())
- ;/
-
- /; write ({}uint8 bytes)
- ;tnsl.io.File out = tnsl.io.writeFile(self.full_path())
-
- /; loop (int i = 0; i < len bytes) [i++]
- ;out.write(bytes{i})
- ;/
-
- ;out.close()
- ;/
-;/
-
-# Represents the different classes of token
-;enum TOKEN [int] {
- SEPARATOR = 0,
- DELIMITER = 1,
- AUGMENT = 2,
- KEYTYPE = 3,
- KEYWORD = 4,
- LITERAL = 5,
- DEFWORD = 6
-}
-
-# Represents a single token in a TNSL file
-;struct Token {
- int
- tokenType,
- line,
-
- {}uint8 data
-}
-
-/; method Token
-
- /; type_is (int a) [bool]
- ;return self.tokenType == a
- ;/
-
- /; cmp ({}uint8 str) [bool]
- ;return string_equate(self.data, str)
- ;/
-
- /; sprint [{}uint8]
- ;{}uint8 out = "{ "
- ;out = string_add(out, self.data)
- ;out.append(' ')
- ;out = string_add(out, int_to_string(self.tokenType))
- ;out.append(' ')
- ;out.append('}')
- ;return out
- ;/
-;/
-
-##
-## Tokenizer funcs
-##
-
-
-/; is_whitespace (uint8 c) [bool]
- ;return (c == '\n' || c == '\t' || c == ' ')
-;/
-
-;{}uint8 MULTI_PARENS = "/;:#"
-;{}uint8 PARENS = "()[]{}"
-;{}uint8 SEPS = "\n;:,"
-;{}uint8 RESERVED = "`~!%^&*()-+=[]{}|;:/?<>.,\""
-;{}uint8 AUGMENTS = "=~!<>&|^+-*/%`."
-
-;{}{}uint8 MULTI_AUGMENTS = {
- "++", "--",
-
- "==", "!==", "&&", "||", "^^", "<==", ">==", "!>", "!<",
-
- "~=", "`=", "%=", "^=", "&=", "*=",
- "!=", "|=", "/=",
-
- "<<", ">>", "!&", "!|", "!^",
-
- "len", "is"
-}
-
-
-;{}{}uint8 KEYWORDS = {
-
- "if",
- "else",
- "loop",
-
- "continue",
- "break",
- "return",
-
- "method",
- "struct",
- "enum",
- "interface",
-
- "export",
- "module",
-
- "const",
- "static",
- "volatile",
- "raw",
-
- "extends",
- "override",
-
- "asm"
-}
-
-;{}{}uint8 KEYTYPES = {
- "uint8",
- "uint16",
- "uint32",
- "uint64",
- "uint",
-
- "int8",
- "int16",
- "int32",
- "int64",
- "int",
-
- "float32",
- "float64",
- "float",
-
- "comp32",
- "comp64",
- "comp",
-
- "vect",
- "bool",
-
- "type",
- "void"
-}
-
-/; is_delimiter ({}uint8 str) [bool]
- /; if (len str > 2 || len str < 1)
- ;return false
- ;/
-
- /; if (len str == 2)
- ;return string_contains(MULTI_PARENS, str{0}) && string_contains(MULTI_PARENS, str{1})
- ;/
-
- ;return string_contains(PARENS, str{0})
-;/
-
-/; is_separator ({}uint8 str) [bool]
- /; if (len str < 1)
- ;return false
- ;/
- ;return string_contains(SEPS, str{0})
-;/
-
-/; is_reserved ({}uint8 str) [bool]
- /; if (len str < 1)
- ;return false
- ;/
- ;return string_contains(RESERVED, str{0})
-;/
-
-/; is_augment ({}uint8 str) [bool]
- /; if (len str == 1)
- ;return string_contains(AUGMENTS, str{0})
- ;/
-
- ;return list_contains(MULTI_AUGMENTS, str)
-;/
-
-/; is_str_literal ({}uint8 str) [bool]
- /; if (string_equate(str, "\"") || string_equate(str, "'"))
- ;return true
- ;/
-
- /; if (len str < 2)
- ;return false
- ;; else if (str{0} !== '\'' && str{0} !== '"')
- ;return false
- ;/
-
- /; loop (int i = 1; i < len str) [i++]
- /; if (str{i} == '\\')
- ;i++
- ;; else if (str{i} == str{0})
- ;return i == len str - 1
- ;/
- ;/
- ;return true
-;/
-
-/; is_num_literal ({}uint8 str) [bool]
- /; if (len str < 1)
- ;return false
- ;/
-
- ;int i = 0
- /; if ((str{i} == '-' || str{i} == '.') && len str > 1)
- ;i++
- ;/
-
- ;bool dec = false
- /; loop (i < len str) [i++]
- /; if (str{i} == '.')
- /; if (!dec)
- ;dec = true
- ;; else
- ;return false
- ;/
- ;; else if (str{i} < '0' || str{i} > '9')
- ;return false
- ;/
- ;/
- ;return true
-;/
-
-/; is_literal({}uint8 str) [bool]
- ;return is_str_literal(str) || is_num_literal(str) || string_equate(str, "true") || string_equate(str, "false")
-;/
-
-/; gen_type (Token t) [int]
- /; if (is_separator(t.data))
- ;return TOKEN.SEPARATOR
- ;; else if (is_literal(t.data))
- ;return TOKEN.LITERAL
- ;; else if (is_delimiter(t.data))
- ;return TOKEN.DELIMITER
- ;; else if (is_augment(t.data))
- ;return TOKEN.AUGMENT
- ;/
-
- /; if (list_contains(KEYWORDS, t.data))
- ;return TOKEN.KEYWORD
- ;; else if (list_contains(KEYTYPES, t.data))
- ;return TOKEN.KEYTYPE
- ;/
-
- ;return TOKEN.DEFWORD
-;/
-
-/; break_token (Token current, uint8 to_append) [bool]
- ;{}uint8 data = current.data
- ;data.append(to_append)
-
- /; if (is_literal(current.data) || is_literal(data))
- ;return !(is_literal(data))
- ;/
-
- /; if (is_whitespace(to_append) || current.cmp("\n"))
- ;return true
- ;/
-
- /; if (is_reserved(current.data))
- /; if (is_reserved({to_append}))
- ;current.data = data
- ;return gen_type(current) == TOKEN.DEFWORD
- ;/
- ;return true
- ;; else if (is_reserved({to_append}))
- ;return true
- ;/
-
- ;return false
-;/
-
-/; handle_comment (tnsl.io.File fd, ~Token current, ~int line) [bool]
- ;bool block = false
- /; if (current`.cmp("/"))
- ;block = true
- ;/
-
- /; loop (int i = fd.read(); i !== -1) [i = fd.read()]
- /; if (i == '\n')
- ;line`++
- /; if (!block)
- ;return true
- ;/
- ;; else if (block && i == '#')
- ;i = fd.read()
- /; if (i == '/')
- ;current` = {0, line, ""}
- ;return false
- ;; else if (i == ';' || i == ':')
- ;current`.data.append(i)
- ;return false
- ;/
-
- /; loop (i !== '\n' && i !== -1) [i = fd.read()] ;/
-
- ;line`++
- ;/
- ;/
-;/
-
-/; tokenize (Path f) [{}Token]
- ;{}Token out = {}
-
- ;tnsl.io.File fd = f.open_read()
-
- ;Token current = {0, 0, ""}
- ;int line = 1
- /; loop (int i = fd.read(); i > -1) [i = fd.read()]
- /; if (i == '\r')
- ;continue
- ;/
-
- /; if (i == '#' && (break_token(current, i) || gen_type(current) !== TOKEN.LITERAL))
- ;bool ln = handle_comment(fd, ~current, ~line)
- /; if (ln)
- ;current.tokenType = gen_type(current)
- /; if (!(current.cmp("")))
- ;out.append(current)
- ;/
- ;out.append({TOKEN.SEPARATOR, line - 1, "\n"})
- ;/
- ;continue
- ;/
-
- /; if (i == '\n' && (break_token(current, i) || gen_type(current) !== TOKEN.LITERAL))
- ;log_vis(".")
- /; if (!(current.cmp("\n")))
- ;current.tokenType = gen_type(current)
- /; if (!(current.cmp("")))
- ;out.append(current)
- ;/
- ;current = {TOKEN.SEPARATOR, line, ""}
- ;current.data.append(i)
- ;/
- ;line++
- ;; else if (break_token(current, i))
- ;current.tokenType = gen_type(current)
- /; if (!(current.cmp("")))
- ;out.append(current)
- ;/
- ;current = {0, line, ""}
- /; if (!(is_whitespace(i)))
- ;current.data.append(i)
- ;/
- ;; else
- ;current.data.append(i)
- ;/
- ;/
- ;log_vis("OK\n")
-
- /; if (!(current.cmp("")) && !(current.cmp("\n")))
- ;current.tokenType = gen_type(current)
- ;out.append(current)
- ;/
-
- ;fd.close()
-
- ;return out
-;/
-
-# General defs:
-## Type defs
-## Function defs
-## Method defs
-## Module defs
-## Constant and variable defs
-
-# Module
-## General defs
-
-# Block
-## Variable defs
-## Control flow defs
-## Value defs
-
-;enum PTYPE [int] {
- POINTER = 0,
- REFERENCE = 1,
- ARRAY = 2
-}
-
-# Represents a data type
-;struct Type {
- int s,
- {}uint8
- name,
- {}int
- ptr_chain,
- {}Variable
- members,
- ~Module
- mod
-}
-
-/; method Type
- /; sprint [{}uint8]
- ;{}uint8 out = string_join( {"{ ", int_to_string(self.s), ", ", self.name, ", { "}, "")
- ;{}{}uint8 pch = {}
- /; loop (int i = 0; i < len(self.ptr_chain)) [i++]
- ;pch.append(int_to_string(self.ptr_chain{i}))
- ;/
- ;out = string_add(out, string_join(pch, ", "))
- ;out = string_add(out, " } }")
- ;return out
- ;/
-
- /; size [int]
- /; loop (int i = 0; i < len(self.ptr_chain)) [i++]
- /; if (self.ptr_chain{i} !== PTYPE.REFERENCE)
- ;return 8
- ;/
- ;/
- ;return self.s
- ;/
-
- /; has_member ({}uint8 name) [bool]
- /; loop (int i = 0; i < len(self.members)) [i++]
- /; if (string_equate(self.members{i}.name, name))
- ;return true
- ;/
- ;/
- ;return false
- ;/
-
- /; strip_refs
- /; loop (true)
- ;int ch = len (self.ptr_chain)
- /; if (ch == 0)
- ;break
- ;; else if (self.ptr_chain{ch - 1} == PTYPE.REFERENCE)
- ;self.ptr_chain = strip_int(self.ptr_chain)
- ;; else
- ;break
- ;/
- ;/
- ;/
-;/
-
-;{}{}uint8 PRIM_NAMES = {
- "uint8", "uint16", "uint32", "uint64", "uint",
- "int8", "int16", "int32", "int64", "int",
- "float32", "float64", "float",
- "bool", "void"
-}
-
-;{}int PRIM_SIZES = {
- 1, 2, 4, 8, 8,
- 1, 2, 4, 8, 8,
- 4, 8, 8,
- 1,
- 8
-}
-
-;Type NO_TYPE = {0, "", {}, {}, 0}
-
-/; is_primitive ({}uint8 t) [int]
- ;{}{}uint8 pn = PRIM_NAMES
- ;{}int ps = PRIM_SIZES
- /; loop (int i = 0; i < len pn) [i++]
- /; if (string_equate(pn{i}, t))
- ;return ps{i}
- ;/
- ;/
- ;return -1
-;/
-
-/; get_primitive (int i) [Type]
- ;{}{}uint8 pn = PRIM_NAMES
- ;{}int ps = PRIM_SIZES
- ;return {ps{i}, pn{i}, {}, {}, 0}
-;/
-
-# Represents the place in memory where a variable is
-;enum LOCATION [int] {
- REGISTER = 0,
- STACK = 1,
- LABEL = 2,
- LITERAL = 3
-}
-
-# Represents a variable
-;struct Variable {
- {}uint8
- name,
- Type
- data_type,
- int
- location,
- loc_type
-}
-
-# Get common register name by index
-/; reg_by_num(int r) [{}uint8]
- /; if (r == 0)
- ;return "ax"
- ;; if (r == 1)
- ;return "bx"
- ;; if (r == 2)
- ;return "cx"
- ;; if (r == 3)
- ;return "dx"
- ;; if (r == 4)
- ;return "si"
- ;; if (r == 5)
- ;return "di"
- ;; if (r == -1)
- ;return "sp"
- ;; if (r == -2)
- ;return "bp"
- ;/
- ;return int_to_string(r)
-;/
-
-# Get common register by common name and size
-/; reg_by_name_size ({}uint8 common, uint sz) [{}uint8]
- ;{}uint8 out = ""
- /; if (common{0} !< 'a')
-
- /; if (sz == 1)
- /; if(common{1} == 'x')
- ;common{1} = 'l'
- ;; else
- ;common.append('l')
- ;/
- ;; else if (sz == 4)
- ;out.append('e')
- ;; else if (sz == 8)
- ;out.append('r')
- ;/
-
- ;out = string_add(out, common)
-
- ;; else
-
- ;out.append('r')
- ;out = string_add(out, common)
- /; if (sz == 1)
- ;out.append('b')
- ;; else if (sz == 2)
- ;out.append('w')
- ;; else if (sz == 4)
- ;out.append('d')
- ;/
- ;/
-
- ;return out
-;/
-
-/; get_reg (int r, sz) [{}uint8]
- ;return reg_by_name_size(reg_by_num(r), sz)
-;/
-
-/; mov_by_size(int sz)[{}uint8]
- /; if (sz == 1)
- ;return "byte "
- ;; else if (sz == 2)
- ;return "word "
- ;; else if (sz == 4)
- ;return "dword "
- ;; else if (sz == 8)
- ;return "qword "
- ;/
- ;return ""
-;/
-
-/; loc_from_str ({}uint8 str, offset, int sz) [{}uint8]
- ;{}uint8 pre = ""
- /; if (sz > 0)
- ;pre = mov_by_size(sz)
- ;/
- ;return string_join( {pre, "[", str, offset, "]" }, "")
-;/
-
-/; strip_int({}int p) [{}int]
- ;{}int out = {}
- /; loop (int i = 0; i < len p - 1) [i++]
- ;out.append(p{i})
- ;/
- ;return out
-;/
-
-/; to_jmp({}uint8 cmp) [{}uint8]
- /; if (string_equate(cmp, "=="))
- ;return "\tje "
- ;; else if (string_equate(cmp, "!=="))
- ;return "\tjne "
- ;; else if (string_equate(cmp, "!<") || string_equate(cmp, ">=="))
- ;return "\tjge "
- ;; else if (string_equate(cmp, "!>") || string_equate(cmp, "<=="))
- ;return "\tjle "
- ;; else if (string_equate(cmp, ">"))
- ;return "\tjg "
- ;; else if (string_equate(cmp, "<"))
- ;return "\tjl "
- ;/
- ;return "\tjnz "
-;/
-
-/; not_jmp({}uint8 cmp) [{}uint8]
- /; if (string_equate(cmp, "=="))
- ;return "\tjne "
- ;; else if (string_equate(cmp, "!=="))
- ;return "\tje "
- ;; else if (string_equate(cmp, "!<") || string_equate(cmp, ">=="))
- ;return "\tjl "
- ;; else if (string_equate(cmp, "!>") || string_equate(cmp, "<=="))
- ;return "\tjg "
- ;; else if (string_equate(cmp, ">"))
- ;return "\tjle "
- ;; else if (string_equate(cmp, "<"))
- ;return "\tjge "
- ;/
- ;return "\tjz "
-;/
-
-# Methods on variables assume that the rax, rdx, rsi, and rdi registers are fair game.
-# ONLY USES RDI ON SOME ASSIGNMENTS. SAFE FOR BOOLEAN STORAGE
-/; method Variable
-
- /; sprint [{}uint8]
- ;return string_join( {
- "{ ", self.name, ", ", self.data_type.sprint(), ", ", int_to_string(self.location), ", ", int_to_string(self.loc_type), " }"
- },"")
- ;/
-
- /; norm_loc (int sz) [{}uint8]
- /; if (self.loc_type == LOCATION.LABEL)
- ;return loc_from_str(string_add("rel ", self.name), string_add(" + ", int_to_string(self.location)), sz)
- ;; else if (self.loc_type == LOCATION.REGISTER)
- /; if (self.is_ref())
- ;return loc_from_str(get_reg(self.location, 8), "", sz)
- ;/
- ;return get_reg(self.location, sz)
- ;; else if (self.loc_type == LOCATION.STACK)
- ;return string_join( {mov_by_size(sz), "[ rbp - ", int_to_string(self.location), " ]" }, "")
- ;; else if (self.loc_type == LOCATION.LITERAL)
- ;return int_to_string(self.location)
- ;/
- ;/
-
- /; norm_size [int]
- /; if (len (self.data_type.ptr_chain) > 1)
- ;return 8
- ;; else if (len (self.data_type.ptr_chain) == 0)
- ;return self.data_type.s
- ;/
-
- /; if (self.data_type.ptr_chain{0} == PTYPE.REFERENCE)
- ;return self.data_type.s
- ;/
- ;return 8
- ;/
-
- /; el_size [int]
- ;int index = len(self.data_type.ptr_chain) - 1
- /; loop (index > 0 && self.data_type.ptr_chain{index} == PTYPE.REFERENCE)
- ;index--
- ;/
-
- ;bool arr = false
- /; loop (index !< 0)
- /; if (self.data_type.ptr_chain{index} !== PTYPE.REFERENCE)
- /; if (arr)
- ;return 8
- ;/
- ;arr = true
- ;index--
- ;; else
- ;index--
- ;/
- ;/
-
- ;return self.data_type.s
- ;/
-
- # FIXME: Match a type to another type if possible
- # this is the type inference engine
- # don't really know how well this works
- /; match_types (Variable to_match, ~CompData data) [Variable]
- ;Variable out = {"#match", self.data_type, 4, LOCATION.REGISTER}
-
- /; if (self.loc_type == LOCATION.STACK && self.is_ref())
- ;data`.csec = string_join( {
- data`.csec,
- "\tmov rdi, ", self.norm_loc(0), "\n"
- }, "")
- ;self.loc_type = LOCATION.REGISTER
- ;self.location = 5
- ;; if (to_match.loc_type == LOCATION.STACK && to_match.is_ref())
- ;data`.csec = string_join( {
- data`.csec,
- "\tmov rsi, ", to_match.norm_loc(0), "\n"
- }, "")
- ;to_match.loc_type = LOCATION.REGISTER
- ;to_match.location = 4
- ;return to_match
- ;/
-
- /; if (to_match.loc_type == LOCATION.LITERAL)
- ;return to_match
- ;; if (!(to_match.is_prim()) || (len(to_match.data_type.ptr_chain) > 0 && !(to_match.is_ref())))
- ;return to_match
- ;/
-
- /; loop (out.is_ref())
- ;out.data_type.ptr_chain = strip_int(out.data_type.ptr_chain)
- ;/
-
- ;{}uint8 mov = "mov"
-
- /; if (self.data_type.name{0} == 'i' && out.norm_size() > to_match.norm_size())
- ;mov = string_add(mov, "sx")
- /; if (out.norm_size() == 8 && to_match.norm_size() == 4)
- ;mov.append('d')
- ;/
- ;; else if (self.data_type.name{0} == 'u' && out.norm_size() > to_match.norm_size() && out.norm_size() !== 8)
- ;mov = string_add(mov, "zx")
- ;; else
- ;return to_match
- ;/
-
- ;data`.csec = string_join( {
- data`.csec,
- "\t", mov, " ", out.norm_loc(out.norm_size()), ", ", to_match.norm_loc(to_match.norm_size()), "\n"
- }, "")
-
- ;return out
- ;/
-
- /; norm_op ({}uint8 op, int sz, Variable v, ~CompData data)
- /; if (self.loc_type == LOCATION.LITERAL)
- ;v.norm_op(op, sz, self, data)
- ;; else
- ;v = self.match_types(v, data)
-
- /; if ((self.is_ref() || self.loc_type == LOCATION.STACK || self.loc_type == LOCATION.LABEL) && (v.is_ref() || v.loc_type == LOCATION.STACK || v.loc_type == LOCATION.LABEL))
- ;data`.csec = string_join( {
- data`.csec,
- "\tmov ", get_reg(4, sz), ", ", v.norm_loc(sz), "\n",
- "\t", op, " ", self.norm_loc(sz), ", ", get_reg(4, sz), "\n"
- }, "")
- ;; else
- ;data`.csec = string_join( {
- data`.csec,
- "\t", op, " ", self.norm_loc(sz), ", ", v.norm_loc(sz), "\n"
- }, "")
- ;/
- ;/
- ;/
-
- /; is_ref [bool]
- ;int s = len (self.data_type.ptr_chain)
- /; if (s > 0)
- ;return self.data_type.ptr_chain{s - 1} == PTYPE.REFERENCE
- ;/
- ;return false
- ;/
-
- /; is_arr [bool]
- ;int s = len (self.data_type.ptr_chain)
- /; if (s > 0)
- ;return self.data_type.ptr_chain{s - 1} == PTYPE.ARRAY
- ;/
- ;return false
- ;/
-
- /; is_prim [bool]
- /; if (len(self.data_type.ptr_chain) == 0)
- ;return is_primitive(self.data_type.name) !< 0
- ;; if (len(self.data_type.ptr_chain) == 1)
- ;return !(self.is_ref()) || is_primitive(self.data_type.name) !< 0
- ;/
- ;return true
- ;/
-
- /; strip_one (~CompData data)
- ;data`.csec = string_join( {
- data`.csec,
- "\tmov rsi, [rsi]\n"
- }, "")
- ;self.data_type.ptr_chain = strip_int(self.data_type.ptr_chain)
- ;/
-
- # Mostly for internal use
- /; strip_refs (~CompData data) [Variable]
- ;Variable out = {"#ref", self.data_type, 4, LOCATION.REGISTER}
-
- /; if (self.loc_type == LOCATION.REGISTER)
- ;data`.csec = string_join( {
- data`.csec,
- "\tmov rsi, ", get_reg(self.location, 8), "\n"
- }, "")
- ;; else
- ;data`.csec = string_join( {
- data`.csec,
- "\tlea rsi, ", self.norm_loc(8), "\n"
- }, "")
- ;out.data_type.ptr_chain.append(PTYPE.REFERENCE)
- ;/
-
- ;int pc = len (out.data_type.ptr_chain)
- /; loop (pc > 1) [pc = len (out.data_type.ptr_chain)]
- /; if (out.data_type.ptr_chain{pc - 1} == PTYPE.REFERENCE && out.data_type.ptr_chain{pc - 2} !== PTYPE.ARRAY)
- ;out.strip_one(data)
- ;; else
- ;break
- ;/
- ;/
- ;return out
- ;/
-
- # functions that do work on this variable
- /; add (Variable v, ~CompData data)
- /; if (self.loc_type == LOCATION.LITERAL && v.loc_type == LOCATION.LITERAL)
- ;self.location = self.location + v.location
- ;; else
- ;self.norm_op("add", self.norm_size(), v, data)
- ;/
- ;/
-
- /; sub (Variable v, ~CompData data)
- /; if (self.loc_type == LOCATION.LITERAL && v.loc_type == LOCATION.LITERAL)
- ;self.location = self.location - v.location
- ;; else
- ;self.norm_op("sub", self.norm_size(), v, data)
- ;/
- ;/
-
- /; or (Variable v, ~CompData data)
- /; if (self.loc_type == LOCATION.LITERAL && v.loc_type == LOCATION.LITERAL)
- ;self.location = self.location | v.location
- ;; else
- ;self.norm_op("or", self.norm_size(), v, data)
- ;/
- ;/
-
- /; and (Variable v, ~CompData data)
- /; if (self.loc_type == LOCATION.LITERAL && v.loc_type == LOCATION.LITERAL)
- ;self.location = self.location & v.location
- ;; else
- ;self.norm_op("and", self.norm_size(), v, data)
- ;/
- ;/
-
- /; xor (Variable v, ~CompData data)
- /; if (self.loc_type == LOCATION.LITERAL && v.loc_type == LOCATION.LITERAL)
- ;self.location = self.location ^ v.location
- ;; else
- ;self.norm_op("xor", self.norm_size(), v, data)
- ;/
- ;/
-
- /; not (Variable v, ~CompData data)
- /; if (self.loc_type == LOCATION.LITERAL && v.loc_type == LOCATION.LITERAL)
- ;self.location = !v.location
- ;; else if (string_equate(v.data_type.name, "bool") && len (v.data_type.ptr_chain) == 0)
-
- ;self.xor(literal_variable("true", "", data), data)
- ;; else
- ;v = self.match_types(v, data)
- ;self.set(v, data)
- ;data`.csec = string_join( {
- data`.csec,
- "\tnot ", self.norm_loc(self.norm_size()), "\n"
- }, "")
- ;/
- ;/
-
- /; cmp (Variable v, ~CompData data)
- /; if (self.loc_type == LOCATION.LITERAL && v.loc_type == LOCATION.LITERAL)
- /; if (self.location == v.location)
- ;self.location = 1
- ;; else
- ;self.location = 0
- ;/
- ;; else if (v.is_prim() && self.is_prim())
- ;self.norm_op("cmp", self.norm_size(), v, data)
- ;/
- ;/
-
- /; negative (Variable v, ~CompData data)
- ;int sz = self.norm_size()
- /; if (v.loc_type == LOCATION.LITERAL)
- ;data`.csec = string_join( {
- data`.csec,
- "\tmov ", self.norm_loc(sz), ", ", int_to_string(v.location), "\n"
- }, "")
- ;; else
- ;v = self.match_types(v, data)
- ;data`.csec = string_join( {
- data`.csec,
- "\tmov ", get_reg(0, sz), ", ", v.norm_loc(sz), "\n",
- "\tnot ", get_reg(0, sz), "\n",
- "\tmov ", self.norm_loc(sz), ", ", get_reg(0, sz), "\n"
- }, "")
- ;/
- ;/
-
- /; inc (~CompData data)
- /; if (self.loc_type == LOCATION.LITERAL)
- ;self.location++
- ;; else
- ;data`.csec = string_join( {
- data`.csec,
- "\tinc ", self.norm_loc(self.norm_size()), "\n"
- }, "")
- ;/
- ;/
-
- /; dec (~CompData data)
- /; if (self.loc_type == LOCATION.LITERAL)
- ;self.location--
- ;; else
- ;data`.csec = string_join( {
- data`.csec,
- "\tdec ", self.norm_loc(self.norm_size()), "\n"
- }, "")
- ;/
- ;/
-
- /; ax_compute ({}uint8 op, int sz, Variable v, ~CompData data, int keep)
- /; if (self.loc_type == LOCATION.LITERAL)
- ;v.ax_compute(op, sz, self, data)
- ;; else
- ;v = self.match_types(v, data)
-
- /; if (self.data_type.name{0} == 'i')
- ;op = string_add("i", op)
- ;/
-
- ;data`.csec = string_join( {
- data`.csec,
- "\tmov ", get_reg(0, sz), ", ", self.norm_loc(sz), "\n",
- "\txor rdx, rdx\n",
- "\tpush rsi\n",
- "\tmov ", get_reg(4, sz), ", ", v.norm_loc(sz), "\n",
- "\t", op, " ", get_reg(4, sz), "\n",
- "\tpop rsi\n",
- "\tmov ", self.norm_loc(sz), ", ", get_reg(keep, sz), "\n"
- }, "")
- ;/
- ;/
-
- /; div (Variable v, ~CompData data)
- /; if (self.loc_type == LOCATION.LITERAL && v.loc_type == LOCATION.LITERAL)
- ;self.location = self.location / v.location
- ;; else
- ;self.ax_compute("div", self.norm_size(), v, data, 0)
- ;/
- ;/
-
- /; mod (Variable v, ~CompData data)
- /; if (self.loc_type == LOCATION.LITERAL && v.loc_type == LOCATION.LITERAL)
- ;self.location = self.location % v.location
- ;; else
- ;self.ax_compute("div", self.norm_size(), v, data, 3)
- ;/
- ;/
-
- /; mul (Variable v, ~CompData data)
- /; if (self.loc_type == LOCATION.LITERAL && v.loc_type == LOCATION.LITERAL)
- ;self.location = self.location * v.location
- ;; else
- ;self.ax_compute("mul", self.norm_size(), v, data, 0)
- ;/
- ;/
-
- # Todo: Make sure this works well.
- /; set (Variable v, ~CompData data)
- ;int sz = self.norm_size()
- ;v = self.match_types(v, data)
- /; if (self.loc_type == LOCATION.LITERAL && v.loc_type == LOCATION.LITERAL)
- ;self.location = v.location
- ;; else if (self.is_prim())
- ;self.norm_op("mov", self.norm_size(), v, data)
- ;; else
- ;log_debug("Full struct set")
- ;log_debug(self.sprint())
- ;log_debug(v.sprint())
- /; if (self.is_ref() && self.loc_type == LOCATION.STACK)
- ;data`.csec = string_join( {
- data`.csec,
- "\tmov rdi, ", self.norm_loc(8), "\n"
- }, "")
- ;; else
- ;data`.csec = string_join( {
- data`.csec,
- "\tlea rdi, ", self.norm_loc(8), "\n"
- }, "")
- ;/
-
- /; if (v.is_ref() && v.loc_type == LOCATION.STACK)
- ;data`.csec = string_join( {
- data`.csec,
- "\tmov rsi, ", v.norm_loc(8), "\n"
- }, "")
- ;; else
- ;data`.csec = string_join( {
- data`.csec,
- "\tlea rsi, ", v.norm_loc(8), "\n"
- }, "")
- ;/
-
- ;data`.csec = string_join( {
- data`.csec,
- "\tmov rcx, ", int_to_string(sz), "\n",
- "\trep movsb\n"
- }, "")
- ;/
- ;/
-
- # To be used to set pointers without dereferencing
- /; set_raw(Variable v, ~CompData data)
- ;int sz = self.norm_size()
- /; if (self.loc_type == LOCATION.LITERAL && v.loc_type == LOCATION.LITERAL)
- ;self.location = v.location
- ;; else if (self.loc_type == LOCATION.STACK && v.loc_type == LOCATION.STACK)
- ;data`.csec = string_join( {
- data`.csec,
- "\tmov ", get_reg(4, sz), ", ", v.norm_loc(sz), "\n",
- "\tmov ", self.norm_loc(sz), ", ", get_reg(4, sz), "\n"
- }, "")
- ;; else
- ;{}uint8 p1 = self.norm_loc(sz)
- ;{}uint8 p2 = v.norm_loc(sz)
-
- /; if (self.loc_type == LOCATION.REGISTER)
- ;p1 = get_reg(self.location, 8)
- ;; if (v.loc_type == LOCATION.REGISTER)
- ;p2 = get_reg(v.location, 8)
- ;/
-
- ;data`.csec = string_join( {
- data`.csec,
- "\tmov ", p1, ", ", p2, "\n"
- }, "")
- ;/
- ;/
-
- # Only to be called from a boolean variable
- /; bool_from (Variable v, ~CompData data, {}uint8 landing_pad)
- ;int sz = v.norm_size()
- ;data`.csec = string_join( {
- data`.csec,
- "\tmov ", get_reg(4, sz), ", ", v.norm_loc(sz), "\n",
- "\ttest ", get_reg(4, sz), ", ", get_reg(4, sz), "\n",
- "\tmov ", self.norm_loc(1), ", 1\n",
- "\tjnz ", landing_pad, "\n",
- "\tmov ", self.norm_loc(1), ", 0\n",
- landing_pad, ":\n"
- }, "")
- ;/
-
- /; move_register (int new_reg, ~CompData data)
- ;int sz = self.norm_size()
- /; if (self.is_ref())
- ;sz = 8
- ;/
- ;data`.csec = string_join( {
- data`.csec,
- "\tmov ", get_reg(new_reg, sz), ", ", get_reg(self.location, sz), "\n"
- }, "")
- ;self.location = new_reg
- ;/
-
- # EVERYTHING SOUTH OF HERE NEEDS TO BE RE-DONE
-
- /; ref (Variable to_ref, ~CompData data)
- ;int l = len (to_ref.data_type.ptr_chain)
- /; if (to_ref.is_ref())
- ;self.set_raw(to_ref, data)
- ;; else if (to_ref.loc_type !== LOCATION.REGISTER && to_ref.loc_type !== LOCATION.LITERAL)
- ;data`.csec = string_join( {
- data`.csec,
- "\tlea rsi, ", to_ref.norm_loc(0), "\n",
- "\tmov ", self.norm_loc(8), ", rsi\n"
- }, "")
- ;; else
- ;log_err(string_add("Failure to create reference from register or literal value ", to_ref.sprint()))
- ;/
- ;/
-
- /; deref (~CompData data) [Variable]
- ;Variable out = self.strip_refs(data)
- ;int opc = len (out.data_type.ptr_chain)
- /; if (opc == 0)
- ;log_err("Can not deref a variable that is not a pointer (ERR: SNPTRC)")
- ;/
- ;out.data_type.ptr_chain{opc - 1} = PTYPE.REFERENCE
- ;return out
- ;/
-
- /; member ({}uint8 name, ~CompData data) [Variable]
- ;Variable out = self.strip_refs(data)
- ;int accum = 0
- ;int i = 0
- /; loop(i < len (out.data_type.members)) [i++]
- /; if (string_equate(out.data_type.members{i}.name, name))
- ;break
- ;/
- ;accum = accum + out.data_type.members{i}.data_type.s
- ;/
-
- ;out.data_type = out.data_type.members{i}.data_type
- ;out.data_type.ptr_chain.append(PTYPE.REFERENCE)
-
- /; if (accum > 0)
- ;data`.csec = string_join( {
- data`.csec,
- "\tadd rsi, ", int_to_string(accum), "\n"
- }, "")
- ;/
-
- ;return out
- ;/
-
- /; index (Variable i, ~CompData data) [Variable]
- ;int sz = self.el_size()
- ;log_debug(string_add("Index starting: ", self.sprint()))
- ;Variable out = self.strip_refs(data)
-
- ;int opc = len (out.data_type.ptr_chain)
-
- /; if (opc == 0 || (out.is_ref() && opc == 1))
- ;log_err(string_add("Unable to index a type if it is not a pointer or array ", out.sprint()))
- ;/
-
- ;Variable ind = {"#index", {8, "void", {PTYPE.POINTER}, {}, 0}, 3, LOCATION.REGISTER}
- ;ind.set(i, data)
- ;ind.mul({"#mul", {8, "uint", {}, {}, 0}, sz, LOCATION.LITERAL}, data)
-
- /; if (out.is_ref() || out.is_arr())
- ;data`.csec = string_join( {
- data`.csec,
- "\tadd rsi, 8\n"
- }, "")
- ;/
-
- ;data`.csec = string_join( {
- data`.csec,
- "\tlea rsi, [rsi + rdx]\n"
- }, "")
-
- /; if (out.is_ref())
- ;out.data_type.ptr_chain = strip_int(out.data_type.ptr_chain)
- ;out.data_type.ptr_chain{len (out.data_type.ptr_chain) - 1} = PTYPE.REFERENCE
- ;/
-
- ;log_debug(string_add("Index returning: ", out.sprint()))
- ;return out.deref(data)
- ;/
-
- /; length_of (Variable a, ~CompData data)
- ;a = a.strip_refs(data)
- ;a.data_type.name = "uint"
- ;a.data_type.s = 8
- ;a.data_type.ptr_chain = {PTYPE.REFERENCE}
- ;self.set(a, data)
- ;/
+/; main [int]
+ return 0
;/
-;struct Scope {
- int num, c, tmp,
- ~Scope parent,
- {}uint8 name,
- {}Variable vars,
- bool r
-}
-
-/; method Scope
- /; sprint [{}uint8]
- ;{}uint8 out = string_join( {
- "SCOPE PRINT [", self.name, "] num:", int_to_string(self.num),
- " C:", int_to_string(self.c),
- " vars:", int_to_string(len (self.vars)), " { "
- }, "")
- /; loop (int i = 0; i < len (self.vars)) [i++]
- ;out = string_add(out, self.vars{i}.sprint())
- ;out.append(' ')
- ;/
- ;return string_add(out, "}")
- ;/
-
- /; is_cf [bool]
- /;if (len(self.name) < 1)
- ;return false
- ;/
- ;return self.name{0} == '#'
- ;/
-
- /; cf_type ({}uint8 cf) [bool]
- ;{}{}uint8 split = string_split(self.name, '_')
- /; if (len split !> 1)
- ;return false
- ;/
- ;return string_equate(split{0}, string_add("#", cf))
- ;/
-
- /; full_label [{}uint8]
- ;{}uint8 out = ""
- /; if (self.is_cf())
- ;out = self.parent`.full_label()
- ;/
- ;out = string_add(out, self.name)
- ;return out
- ;/
-
- /; get_size [int]
- ;int out = 0
- /; loop (int i = 0; i < len (self.vars)) [i++]
- ;out = out + self.vars{i}.norm_size()
- ;/
- ;return out
- ;/
-
- /; next_register [int]
- ;int out = 8
- /; if (self.is_cf())
- ;out = self.parent`.next_register()
- ;/
-
- /; loop (int i = 0; i < len (self.vars) && out < 16) [i++]
- /; if (self.vars{i}.loc_type == LOCATION.REGISTER)
- ;log_debug("Found register variable")
- ;log_debug(self.vars{i}.sprint())
- ;out++
- ;/
- ;/
-
- /; if (out > 15)
- ;out = -1
- ;/
-
- ;return out
- ;/
-
- /; get_stack [int]
- ;int out = 0
-
- /; loop (int i = 0; i < len (self.vars)) [i++]
- /; if (self.vars{i}.loc_type == LOCATION.STACK)
- ;out = out + self.vars{i}.norm_size()
- ;/
- ;/
-
- ;return out
- ;/
-
- /; get_full_stack [int]
- ;int out = 0
- /; if (self.is_cf())
- ;out = self.parent`.get_full_stack()
- ;/
-
- /; loop (int i = 0; i < len (self.vars)) [i++]
- /; if (self.vars{i}.loc_type == LOCATION.STACK)
- ;out = out + self.vars{i}.norm_size()
- ;/
- ;/
-
- /; if (!(self.is_cf()) && !(self.r))
- ;return out + 72
- ;/
-
- ;return out
- ;/
-
- /; get_full_tmp_stack [int]
- ;int out = self.tmp
- /; if (self.is_cf())
- ;out = out + self.parent`.get_full_tmp_stack()
- ;/
-
- /; loop (int i = 0; i < len (self.vars)) [i++]
- /; if (self.vars{i}.loc_type == LOCATION.STACK)
- ;out = out + self.vars{i}.norm_size()
- ;/
- ;/
-
- /; if (!(self.is_cf()) && !(self.r))
- ;return out + 72
- ;/
-
- ;return out
- ;/
-
- /; next_loc (Type t) [int]
- /; if (is_primitive(t.name) !< 0 || len (t.ptr_chain) > 0)
- ;log_debug("Next reg")
- ;return self.next_register()
- ;/
- ;return -1
- ;/
-
- /; begin_scope (~CompData out)
- /; if (!(self.r))
- ;{}uint8 intro = "\tpush rbp\n\tlea rbp, [rsp + 8]\n\tpush r8\n\tpush r9\n\tpush r10\n\tpush r11\n\tpush r12\n\tpush r13\n\tpush r14\n\tpush r15\n"
- ;out`.csec = string_add(out`.csec, intro)
- ;/
-
- # pre-stack loop
- /; loop (int i = 0; i < len (self.vars)) [i++]
- ;int loc = self.next_loc(self.vars{i}.data_type)
- /; if (loc !< 0)
- ;self.vars{i}.location = loc
- ;self.vars{i}.loc_type = LOCATION.REGISTER
- ;out`.csec = string_join( {
- out`.csec,
- "\tmov ", get_reg(loc, 8), ", ", get_reg(loc - 8, 8), "\n\n"
- }, "")
- ;/
- ;/
-
- ;int accum = 0
- /; if (!(self.r))
- ;accum = 72
- ;/
-
- ;{}uint8 moves = string_join( {
- "\tlea rsi, [rbp + 8]\n\n"
- }, "")
-
- # Move extra variables
- /; loop (int i = len (self.vars) - 1; i !< 0) [i = i - 1]
- /; if (self.vars{i}.loc_type == LOCATION.LITERAL)
- ;self.vars{i}.loc_type = LOCATION.STACK
- ;int sz = self.vars{i}.norm_size()
- ;accum = accum + sz
- ;self.vars{i}.location = accum
- /; if (len (self.vars{i}.data_type.ptr_chain) > 0)
- ;moves = string_join( {
- moves,
- "\tsub rsp, 8\n",
- "\tlea rdi, qword [rbp - ", int_to_string(accum), "]\n",
- "\tmovsq\n\n"
- }, "")
- ;; else
- ;moves = string_join( {
- moves,
- "\tsub rsp, ", int_to_string(sz), "\n",
- "\tlea rdi, [rbp - ", int_to_string(accum), "]\n",
- "\tmov rcx, ", int_to_string(sz), "\n",
- "\trep movsb\n"
- }, "")
- ;/
- ;/
- ;/
-
- /; if (accum > 72 && !(self.r))
- ;out`.csec = string_add(out`.csec, moves)
- ;/
- ;/
-
- /; end_scope (~CompData out)
- /; if (!(self.r))
- ;{}uint8 outro = "\tlea rsp, [rbp - 72]\n\tpop r15\n\tpop r14\n\tpop r13\n\tpop r12\n\tpop r11\n\tpop r10\n\tpop r9\n\tpop r8\n\tpop rbp\n"
- ;out`.csec = string_add(out`.csec, outro)
- ;/
- ;/
-
- /; scope_cleanup (~CompData out)
- ;uint sz_to_clean = 0
-
- /; loop (int i = 0; i < len (self.vars))
- /; if (self.vars{i}.loc_type == LOCATION.STACK)
- ;sz_to_clean = sz_to_clean + self.vars{i}.s
- ;/
- ;/
-
- /; if (sz_to_clean > 0)
- ;out`.csec = string_add(out`.csec, string_add("\tadd rsp, ", int_to_string(sz_to_clean)))
- ;/
- ;/
-
- /; scope_start_label [{}uint8]
- ;return string_add(self.full_label(), "_start")
- ;/
-
- /; scope_rep_label [{}uint8]
- ;return string_add(self.full_label(), "_rep")
- ;/
-
- /; scope_end_label [{}uint8]
- ;return string_add(self.full_label(), "_end")
- ;/
-
- /; new_sub_cf ({}uint8 cf) [Scope]
- ;cf = string_add("#", cf)
- ;cf.append('_')
- ;cf = string_add(cf, int_to_string(self.num))
- ;self.num++
-
- ;return {0, 0, 0, ~self, cf, {}, self.r}
- ;/
-
- /; br (uint i, ~CompData out)
- ;~Scope top = ~self
- ;~Scope sco = ~self
- ;int seen = 0
- /; loop (seen !> i && i > 0)
- /; if (top`.parent`.is_cf())
- ;top = top`.parent
- /; if (top`.cf_type("wrap"))
- ;sco = top
- ;seen++
- ;/
- ;; else
- ;break
- ;/
- ;/
-
- ;out`.csec = string_join( {
- out`.csec,
- "\tjmp ", sco`.scope_end_label(), "\n"
- }, "")
-
- ;/
-
- /; cont (uint i, ~CompData out)
- ;~Scope top = ~self
- ;~Scope sco = ~self
- ;int seen = 0
- /; loop (seen !> i && i > 0)
- /; if (top`.parent`.is_cf())
- ;top = top`.parent
- /; if (top`.cf_type("wrap"))
- /; if (top`.parent`.is_cf())
- ;sco = top`.parent
- ;/
- ;seen++
- ;/
- ;; else
- ;break
- ;/
- ;/
-
- ;out`.csec = string_join( {
- out`.csec,
- "\tjmp ", sco`.scope_rep_label(), "\n"
- }, "")
- ;/
-
- /; new_var (Type t, {}uint8 name, ~CompData out)
- ;Variable new = {name, t, 0, 0}
- /; if (self.next_loc(t) !< 0)
- ;new.loc_type = LOCATION.REGISTER
- ;new.location = self.next_loc(t)
- ;; else
- ;new.loc_type = LOCATION.STACK
- ;new.location = self.get_full_stack() + new.norm_size()
- ;out`.csec = string_join( {
- out`.csec,
- "\tsub rsp, ", int_to_string(new.norm_size()), "\n"
- }, "")
- ;/
- ;log_debug(string_add("Created new variable ", new.sprint()))
- ;self.vars.append(new)
- ;/
-
- /; new_tmp_var (Type t, ~CompData out) [Variable]
- ;Variable new = {"##tmp", t, 0, 0}
- ;new.loc_type = LOCATION.STACK
- ;new.location = self.get_full_tmp_stack() + new.norm_size()
- ;self.tmp = self.tmp + new.norm_size()
- ;out`.csec = string_join( {
- out`.csec,
- "\tsub rsp, ", int_to_string(new.norm_size()), "\n"
- }, "")
- ;log_debug(string_add("Created tmp variable ", new.sprint()))
- ;return new
- ;/
-
- /; clear_tmp (~CompData out)
- ;log_debug(string_add("Cleared tmp: ", int_to_string(self.tmp)))
-
- /; if (self.tmp > 0)
- ;out`.csec = string_add(out`.csec, string_add("\tadd rsp, ", int_to_string(self.tmp)))
- ;out`.csec.append('\n')
- ;self.tmp = 0
- ;/
- ;/
-
- /; find_var ({}{}uint8 artifact, ~Module current) [Variable]
- /; loop (int i = 0; i < len (self.vars)) [i++]
- /; if (string_equate(self.vars{i}.name, artifact{0}))
- ;return self.vars{i}
- ;/
- ;/
-
- /; if (!(self.is_cf()))
- ;return current`.find_def(artifact)
- ;/
- ;return self.parent`.find_var(artifact, current)
- ;/
-
- /; find_reg_variable (int reg) [~Variable]
- /; loop (int i = 0; i < len (self.vars)) [i++]
- /; if (self.vars{i}.loc_type == LOCATION.REGISTER && self.vars{i}.location == reg)
- ;return ~(self.vars{i})
- ;/
- ;/
-
- /; if (!(self.is_cf()))
- ;log_err(string_add("Can't move variable to stack as it does not exist in the current context ", int_to_string(reg)))
- ;/
- ;return self.parent`.find_reg_variable(reg)
- ;/
-
- /; move_to_stack (int reg, ~CompData out) [Variable]
- ;int last_var = self.next_register()
- /; if (last_var < 0)
- ;last_var = 16
- ;/
-
- /; if (reg < 8 || reg > last_var - 1)
- ;log_err(string_add("Can't move a register to stack as it is not in scope. ", int_to_string(reg)))
- ;/
-
- ;log_debug(string_join( {
- "Attempting to move variable at register ",
- int_to_string(reg), " to stack. last_var = ", int_to_string(last_var)
- }, ""))
-
- ;~Variable rv = self.find_reg_variable(reg)
- ;Variable copy = {rv`.name, rv`.data_type, 0, 0}
- ;copy.loc_type = LOCATION.STACK
- ;copy.location = self.get_full_stack() + copy.norm_size()
- ;out`.csec = string_join( {
- out`.csec,
- "\tsub rsp, ", int_to_string(copy.norm_size()), "\n"
- }, "")
- ;copy.set(rv`, out)
- ;rv`.location = copy.location
- ;rv`.loc_type = LOCATION.STACK
- ;log_debug(self.sprint())
-
- /; if (reg < last_var - 1)
- ;rv = self.find_reg_variable(last_var - 1)
- ;log_debug(string_join({
- "Moving variable from ", int_to_string(last_var - 1), " to ", int_to_string(reg), ". ",
- "Variable name: ", rv`.name
- }, ""))
- ;rv`.move_register(reg, out)
- ;/
- ;log_debug(self.sprint())
-
-
- ;return copy
- ;/
-
- /; next_const [{}uint8]
- ;{}uint8 out = string_add(self.full_label(), string_add("#const_", int_to_string(self.c)))
- ;self.c++
- ;return out
- ;/
-;/
-
-;struct Function {
- {}uint8 name,
- {}Type
- inputs,
- Type
- output,
- ~Module mod
-}
-
-/; method Function
- /; full_label [{}uint8]
- ;{}uint8 out = self.mod`.full_path()
- /; if (len out > 0)
- ;out.append('.')
- ;/
- ;out = string_add(out, self.name)
- ;return out
- ;/
-
- /; is_method [bool]
- ;{}uint8 mod_name = self.mod`.name
- /; if (len mod_name > 2)
- ;return mod_name{0} == '_' && mod_name{1} == '#'
- ;/
- ;return false
- ;/
-
- /; sprint [{}uint8]
- ;return string_join( {
- "Function ", self.name, " (", int_to_string(len(self.inputs)), ") ", self.output.sprint()
- }, "")
- ;/
-;/
-
-;struct Module {
- # Parent module
- ~Module parent,
- # Export functions or not
- bool exp,
- # Name of module
- {}uint8 name,
- # Types defined in this module
- {}Type types,
- # Variables defined in this module
- {}Variable defs,
- # Functions defined in this module
- {}Function functions,
- # Sub modules
- {}Module sub
-}
-
-/; method Module
- # Internal recursive function
- /; _find_type ({}{}uint8 artifact, int r) [~Type]
- /; if (len artifact !> r)
- ;return ~NO_TYPE
- ;/
-
- /; if (len artifact - 1 > r)
- /; loop (int i = 0; i < len (self.sub)) [i++]
- /; if (string_equate(artifact{r}, self.sub{i}.name))
- ;return self.sub{i}._find_type(artifact, r + 1)
- ;/
- ;/
- ;; else if (len artifact - 1 == r)
- /; loop (int i = 0; i < len (self.types)) [i++]
- /; if (string_equate(self.types{i}.name, artifact{r}))
- ;return ~(self.types{i})
- ;/
- ;/
- ;/
-
- /; if (string_equate(self.name, ""))
- ;Type nt = {0, artifact{len artifact - 1}, {}, {}, 0}
- ;return ~nt
- ;/
-
- ;~Module m = self.parent
- /; loop (r > 0) [r = r - 1]
- ;m = m`.parent
- ;/
- ;return m`._find_type(artifact, 0)
- ;/
-
- # Consumer facing function
- /; find_type ({}{}uint8 artifact) [~Type]
- ;int p = is_primitive(artifact{0})
- /; if (p !< 0)
- ;Type out = {p, artifact{0}, {}, {}, 0}
- ;return ~out
- ;/
-
- ;return self._find_type(artifact, 0)
- ;/
-
- /; _find_def ({}{}uint8 artifact, int r) [Variable]
- ;log_debug(string_add("Finding def: ", artifact{r}))
- ;log_debug(string_join(artifact, "."))
- /; if (len artifact !> r)
- ;return {"", NO_TYPE, 0, 0}
- ;/
-
- /; if (len artifact - 1 > r)
- ;log_debug("loopin")
- ;{}uint8 e_name = string_add("__#", artifact{r})
- ;{}uint8 m_name = string_add("_#", artifact{r})
- /; loop (int i = 0; i < len (self.sub)) [i++]
- /; if (string_equate(artifact{r}, self.sub{i}.name) || string_equate(e_name, self.sub{i}.name) || string_equate(m_name, self.sub{i}.name))
- ;log_debug(string_add("Artifact: ", artifact{r}))
- ;return self.sub{i}._find_def(artifact, r + 1)
- ;/
- ;/
- ;; else if (len artifact - 1 == r)
- ;{}uint8 true_name = self.full_path()
- /; if (len true_name > 0)
- ;true_name.append('.')
- ;/
- ;true_name = string_add(true_name, artifact{r})
- /; loop (int i = 0; i < len (self.defs)) [i++]
- /; if (string_equate(self.defs{i}.name, true_name))
- ;return self.defs{i}
- ;/
- ;/
- ;/
-
- /; if (string_equate(self.name, ""))
- ;return {"", NO_TYPE, 0, 0}
- ;/
-
- ;~Module m = self.parent
- /; loop (r > 0) [r = r - 1]
- ;m = m`.parent
- ;/
- ;return m`._find_def(artifact, 0)
- ;/
-
- /; find_def ({}{}uint8 artifact) [Variable]
- ;log_debug("Finding def...")
- ;return self._find_def(artifact, 0)
- ;/
-
- /; _find_function ({}{}uint8 artifact, int r) [Function]
- /; if (len artifact !> r)
- ;return {"", {}, {}}
- ;/
-
- /; if (len artifact - 1 > r)
- /; loop (int i = 0; i < len (self.sub)) [i++]
- /; if (string_equate(artifact{r}, self.sub{i}.name))
- ;log_debug(string_add("Artifact: ", artifact{r}))
- ;return self.sub{i}._find_function(artifact, r + 1)
- ;/
- ;/
- ;; else if (len artifact - 1 == r)
- /; loop (int i = 0; i < len (self.functions)) [i++]
- /; if (string_equate(self.functions{i}.name, artifact{r}))
- ;return self.functions{i}
- ;/
- ;/
- ;/
-
- /; if (string_equate(self.name, ""))
- ;return {"", {}, {}}
- ;/
-
- ;~Module m = self.parent
- /; loop (r > 0) [r = r - 1]
- ;m = m`.parent
- ;/
- ;return m`._find_function(artifact, 0)
- ;/
-
- /; find_function ({}{}uint8 artifact) [Function]
- ;return self._find_function(artifact, 0)
- ;/
-
- /; _find_mod ({}{}uint8 artifact, int r) [~Module]
- /; if (len artifact !> r)
- ;return ~self
- ;/
-
- /; if (len artifact - 1 > r)
- /; loop (int i = 0; i < len (self.sub)) [i++]
- /; if (string_equate(artifact{r}, self.sub{i}.name))
- ;return self.sub{i}._find_mod(artifact, r + 1)
- ;/
- ;/
- ;; else if (len artifact - 1 == r)
- ;{}uint8 v1 = string_add("_#", artifact{r}), v2 = string_add("__#", artifact{r})
- /; loop (int i = 0; i < len (self.defs)) [i++]
- /; if (string_equate(self.sub{i}.name, artifact{r}) ||string_equate(self.sub{i}.name, v1) || string_equate(self.sub{i}.name, v2))
- ;return ~(self.sub{i})
- ;/
- ;/
- ;/
-
- /; if (string_equate(self.name, ""))
- ;return ~self
- ;/
-
- ;~Module m = self.parent
- /; loop (r > 0) [r = r - 1]
- ;m = m`.parent
- ;/
- ;return m`._find_mod(artifact, 0)
- ;/
-
- /; find_mod({}{}uint8 artifact) [~Module]
- ;return self._find_mod(artifact, 0)
- ;/
-
- /; find_sub ({}uint8 s_mod) [~Module]
- ;{}uint8 v1 = string_add("_#", s_mod)
- ;{}uint8 v2 = string_add("__#", s_mod)
- /; loop (int i = 0; i < len (self.sub)) [i++]
- /; if (string_equate(self.sub{i}.name, s_mod) || string_equate(self.sub{i}.name, v1) || string_equate(self.sub{i}.name, v2))
- ;return ~(self.sub{i})
- ;/
- ;/
-
- ;return ~self
- ;/
-
- /; full_path [{}uint8]
- /; if (string_equate(self.name, ""))
- ;return ""
- ;/
- ;{}uint8 out = self.parent`.full_path()
- /; if (len out > 0)
- ;out = string_add(out, ".")
- ;/
- ;out = string_add(out, self.name)
- ;return out
- ;/
-;/
-
-##
-## Compiler funcs
-##
-
-/; get_artifact (~{}Token tok, ~int cur) [{}{}uint8]
- ;{}{}uint8 out = {}
-
- ;out.append(tok`{cur`}.data)
- ;cur`++
-
- /; loop (cur` < len tok` && tok`{cur`}.cmp(".")) [cur`++]
- /; if (tok`{cur` + 1}.type_is(TOKEN.DEFWORD))
- ;out.append(tok`{cur` + 1}.data)
- ;cur`++
- ;/
- ;/
- ;return out
-;/
-
-/; is_call(~{}Token tok, int i) [bool]
- /; loop (i < len (tok`)) [i++]
- /; if (tok`{i}.cmp("{"))
- ;i = find_closing(tok, ~i)
- ;; else if (tok`{i}.cmp("("))
- ;return true
- ;; else if (tok`{i}.cmp(".") || tok`{i}.cmp("`") || tok`{i}.type_is(TOKEN.DEFWORD))
- ;continue
- ;; else
- ;break
- ;/
- ;/
- ;return false
-;/
-
-/; pre_get_type (~{}Token tok, ~int cur) [Type]
- ;{}int ptr_chain = {}
-
- /; loop (cur` < len tok`) [cur`++]
- /; if (tok`{cur`}.cmp("{"))
- ;ptr_chain.append(PTYPE.ARRAY)
- ;cur`++
- ;; else if (tok`{cur`}.cmp("~"))
- ;ptr_chain.append(PTYPE.POINTER)
- ;; else
- ;break
- ;/
- ;/
-
- ;{}uint8 a = string_join(get_artifact(tok, cur), ".")
- ;Type out = {0, a, ptr_chain, {}, 0}
-
- /; if (tok`{cur`}.cmp("`"))
- ;out.ptr_chain.append(PTYPE.REFERENCE)
- ;cur`++
- ;/
-
- ;return out
-;/
-
-/; get_type (~{}Token tok, ~int cur, ~Module current) [Type]
- ;{}int ptr_chain = {}
-
- /; loop (cur` < len tok`) [cur`++]
- /; if (tok`{cur`}.cmp("{"))
- ;ptr_chain.append(PTYPE.ARRAY)
- ;cur`++
- ;; else if (tok`{cur`}.cmp("~"))
- ;ptr_chain.append(PTYPE.POINTER)
- ;; else
- ;break
- ;/
- ;/
-
- ;~Type pout = current`.find_type(get_artifact(tok, cur))
- ;Type out = pout`
- /; if (string_equate(out.name, ""))
- ;return out
- ;/
-
- ;{}Type generics = {}
- /; if (tok`{cur`}.cmp("("))
- ;int max = find_closing(tok, cur)
- ;cur`++
- /; loop (cur` < max) [cur`++]
- ;generics.append(get_type(tok, cur, current))
- ;/
- ;/
-
- /; if (tok`{cur`}.cmp("`"))
- ;ptr_chain.append(PTYPE.REFERENCE)
- ;cur`++
- ;/
-
- ;out.ptr_chain = ptr_chain
- ;return out
-;/
-
-/; is_definition (~{}Token tok, ~int cur, ~Module current) [bool]
- ;int i = cur`
- ;Type t = get_type(tok, ~i, current)
- ;return tok`{i}.type_is(TOKEN.DEFWORD) && !string_equate(t.name, "")
-;/
-
-/; compile_file_def (~{}Token tok, ~int cur, ~Module current, ~CompData out)
- ;Type t = get_type(tok, cur, current)
- ;{}uint8 base = current`.full_path()
-
- /; if (len base > 0)
- ;base.append('.')
- ;/
-
- /; loop (!(tok`{cur`}.cmp("\n")))
- /; loop (tok`{cur`}.cmp(","))
- ;cur`++
- ;/
-
- ;{}uint8 l = string_add(base, tok`{cur`}.data)
- ;Variable v = {l, t, 0, LOCATION.LABEL}
- ;current`.defs.append(v)
-
- /; if (current`.exp)
- ;out`.hsec = string_add(out`.hsec, "global ")
- ;out`.hsec = string_add(out`.hsec, l)
- ;out`.hsec.append('\n')
- ;/
-
- ;l.append(':')
- ;l.append('\n')
- ;out`.dsec = string_add(out`.dsec, l)
-
- ;cur`++
- /; if (tok`{cur`}.cmp("="))
- ;cur`++
- ;out`.dsec = string_add(out`.dsec, decompose_data(tok, cur, t))
- ;cur`++
- ;; else
- ;out`.dsec = string_add(out`.dsec, decompose_empty(t))
- ;/
- ;/
-;/
-
-/; next_non_nl (~{}Token tok, int c) [int]
- /; if (len tok` !> c)
- ;return c
- ;/
- /; loop (tok`{c}.cmp("\n")) [c++] ;/
- ;return c
-;/
-
-/; pre_parse_params (~{}Token tok, ~int cur) [{}Type]
- ;{}Type out = {}
-
- ;int max = find_closing(tok, cur)
-
- ;Type t = NO_TYPE
- /; loop (cur` = next_non_nl(tok, cur` + 1); cur` < max) [cur` = next_non_nl(tok, cur` + 1)]
- ;int nnl = next_non_nl(tok, cur` + 1)
- /; if (tok`{nnl}.cmp(",") || nnl == max)
- ;out.append(t)
- /; if (tok`{nnl}.cmp(","))
- ;cur`++
- ;/
- ;; else
- ;t = pre_get_type(tok, cur)
- ;cur` = cur` - 1
- ;/
- ;/
-
- ;return out
-;/
-
-/; parse_param_list (~{}Token tok, ~int cur, ~Module current) [{}Variable]
- ;{}Variable out = {}
-
- ;int max = find_closing(tok, cur)
- ;Type t = NO_TYPE
- /; loop (cur` = next_non_nl(tok, cur` + 1); cur` < max) [cur` = next_non_nl(tok, cur` + 1)]
- ;int nnl = next_non_nl(tok, cur` + 1)
- /; if (tok`{nnl}.cmp(",") || nnl == max)
- ;out.append({tok`{cur`}.data, t, 0, LOCATION.LITERAL})
- /; if (tok`{nnl}.cmp(","))
- ;cur`++
- ;/
- ;; else
- ;t = get_type(tok, cur, current)
- ;cur` = cur` - 1
- ;/
- ;/
- ;return out
-;/
-
-/; find_or_create ({}uint sub_name, ~Module current, bool exp) [~Module]
- /; if (!(string_equate(current`.find_sub(sub_name)`.name, current`.name)))
- ;return current`.find_sub(sub_name)
- ;/
- ;Module out = {current, exp, "", {}, {}, {}, {}}
-
-
- ;out.name = current`.full_path()
- /; if (len (out.name) > 0)
- ;out.name.append('.')
- ;/
- ;out.name = string_add(out.name, sub_name)
-
-
- ;current`.sub.append(out)
- ;return current`.find_sub(sub_name)
-;/
-
-# Generates new type
-/; new_type (~{}Token tok, ~int cur, ~Module current)
- ;cur`++
-
- /; if (tok`{cur`}.tokenType !== TOKEN.DEFWORD)
- ;log_err(string_join( {
- "Unexpected token type at ", tok`{cur`}.sprint(), " The struct keyword should be followed by an identifier."
- }, ""))
- ;/
-
- ;Type out = {0, tok`{cur`}.data, {}, {}, 0}
-
- ;{}uint8 mod_name = string_add("_#", out.name)
- ;~Module new = find_or_create(mod_name, current, current`.exp)
- ;out.mod = new
-
- /; loop (cur` < len tok`) [cur`++]
- /; if (tok`{cur`}.cmp("{"))
- ;break
- ;/
- ;/
-
- ;out.members = parse_param_list(tok, cur, current)
- /; loop (int i = 0; i < len (out.members)) [i++]
- ;log_debug(string_join({"[", out.members{i}.name, ":", out.members{i}.data_type.name, "]"}, ""))
- ;/
-
- ;log_debug(string_add("Generated type ", string_add(out.name, string_add(":", out.mod`.name))))
- ;current`.types.append(out)
-;/
-
-/; new_function (~{}Token tok, ~int cur, ~Module current)
- ;{}Type inputs = {}
- ;Type output = NO_TYPE
-
- ;int max = find_closing(tok, cur)
- ;cur`++
-
- /; if (tok`{cur`}.tokenType !== TOKEN.DEFWORD)
- ;log_err(string_join( {
- "Unexpected token type at ", tok`{cur`}.sprint(), " The struct keyword should be followed by an identifier."
- }, ""))
- ;/
-
- ;{}uint8 name = tok`{cur`}.data
- ;cur`++
-
- /; loop (cur` < max) [cur`++]
- /; if (tok`{cur`}.cmp("("))
- ;inputs = pre_parse_params(tok, cur)
- ;; else if (tok`{cur`}.cmp("["))
- ;cur`++
- ;output = pre_get_type(tok, cur)
- ;; else
- ;break
- ;/
- ;/
-
- ;cur` = max
- ;current`.functions.append( {name, inputs, output, current} )
-;/
-
-/; decompose_empty (Type t) [{}uint8]
- /; if (len (t.ptr_chain) > 0)
- ;return "\tdq 0\n"
- ;/
- ;{}uint8 out = "\tdb 0"
- /; loop (int i = 1; i < t.s) [i++]
- ;out = string_add(out, ", 0")
- ;/
- ;out.append('\n')
- ;return out
-;/
-
-# Used to take an array literal and make it into a label
-/; decompose_array (~{}Token tok, ~int cur, Type t) [{}uint8]
- ;int max = find_closing(tok, cur)
- ;{}uint8 arr = ""
- ;int alen = 0
-
- /; loop (cur` = next_non_nl(tok, cur` + 1); cur` < max) [cur` = next_non_nl(tok, cur` + 1)]
- ;alen++
- /; if (tok`{cur`}.cmp("{"))
- /; if (len(t.ptr_chain) > 0)
- ;t.ptr_chain = strip_int(t.ptr_chain)
- ;arr = string_add(arr, decompose_array(tok, cur, t))
- ;cur` = next_non_nl(tok, cur` + 1)
- ;; else
- ;decompose_struct(tok, cur, t)
- ;cur` = next_non_nl(tok, cur` + 1)
- ;/
- ;; else
- ;arr = string_add(arr, decompose_data(tok, cur, t))
- ;cur` = next_non_nl(tok, cur` + 1)
- ;/
- ;/
- ;cur` = max
-
- ;{}uint out = string_join( { "\tdq ", int_to_string(alen), "\n", arr, "\n" }, "")
-
- ;return out
-;/
-
-# Used to take a struct literal and make it into a label
-/; decompose_struct (~{}Token tok, ~int cur, Type t) [{}uint8]
- ;int max = find_closing(tok, cur)
- ;{}uint8 out = ""
- ;int m = 0
- /; loop (cur` = next_non_nl(tok, cur` + 1); cur` < max) [cur` = next_non_nl(tok, cur` + 1)]
- /; if (tok`{cur`}.cmp("}"))
- ;break
- ;; else if (tok`{cur`}.cmp(","))
- ;cur` = next_non_nl(tok, cur` + 1)
- ;/
- ;out = string_add(out, decompose_data(tok, cur, t.members{m}.data_type))
- ;m++
- ;/
-
- /; if (m < len (t.members) - 1)
- /; loop (m < len (t.members)) [m++]
- ;out = string_add(out, decompose_empty(t.members{m}))
- ;/
- ;/
-
- ;return out
-;/
-
-/; declare_size(int sz) [{}uint8]
- ;{}uint8 out = "\tdb "
-
- /; if (sz == 2)
- ;out{2} = 'w'
- ;; if (sz == 4)
- ;out{2} = 'd'
- ;; if (sz == 8)
- ;out{2} = 'q'
- ;/
-
- ;return out
-;/
-
-# Used to take data from a literal and make it into a label
-/; decompose_data (~{}Token tok, ~int cur, Type t) [{}uint8]
- /; if (tok`{cur`}.cmp("{"))
- /; if (len (t.ptr_chain) > 0)
- ;t.ptr_chain = strip_int(t.ptr_chain)
- ;return decompose_array(tok, cur, t)
- ;; else
- ;return decompose_struct(tok, cur, t)
- ;/
- ;; if (tok`{cur`}.type_is(TOKEN.LITERAL))
- /; if (string_equate(t.name, "bool"))
- ;{}uint data = "0"
- /; if (!(tok`{cur`}.cmp("false")))
- ;data = "1"
- ;/
- ;return string_add(string_add(declare_size(t.s), data), "\n")
- ;/
-
- /; if (tok`{cur`}.data{0} == '"')
- ;{}uint8 data = unquote_str(tok`{cur`}.data)
- ;return string_join({
- declare_size(8), int_to_string(len data), "\n",
- declare_size(1), string_to_csb(data), "\n"}, "")
- ;; else if (tok`{cur`}.data{0} == '\'')
- ;return string_join({
- declare_size(1), tok`{cur`}.data, "\n"}, "")
- ;/
- ;return string_add(string_add(declare_size(t.s), tok`{cur`}.data), "\n")
- ;/
- ;return decompose_empty(t)
-;/
-
-# Compiles new enum for the file
-/; compile_enum (~{}Token tok, ~int cur, ~Module current, ~CompData out)
- ;cur`++
- ;Type et = NO_TYPE
- ;{}uint8 name = ""
-
- /; if (tok`{cur`}.cmp("["))
- ;cur`++
- ;et = get_type(tok, cur, current)
- ;cur`++
- ;; if (!(tok`{cur`}.cmp("{")))
- ;name = tok`{cur`}.data
- ;cur`++
- /; if (tok`{cur`}.cmp("["))
- ;cur`++
- ;et = get_type(tok, cur, current)
- ;cur`++
- ;/
- ;/
-
- ;log_debug(string_join( {
- "Adding enum ", name, " of type ", et.name
- }, ""))
-
- /; if (string_equate(et.name, ""))
- ;et = Primitives{3}
- ;/
-
- /; loop (!(tok`{cur`}.cmp("{"))) [cur`++] ;/
- ;cur`++
-
- ;Module enum_mod = {current, current`.exp, string_add("__#", name), {}, {}, {}, {}}
- /; loop (cur` < len tok`) [cur`++]
- /; if (tok`{cur`}.cmp("}"))
- ;break
- ;/
-
- /; if (tok`{cur`}.type_is(TOKEN.DEFWORD))
- ;{}uint8 l = string_add(enum_mod.full_path(), ".")
- ;l = string_add(l, tok`{cur`}.data)
-
- /; if (current`.exp)
- ;out`.hsec = string_add(out`.hsec, "global ")
- ;out`.hsec = string_add(out`.hsec, l)
- ;out`.hsec.append('\n')
- ;/
-
- ;Variable v = {l, et, 0, LOCATION.LABEL}
- ;enum_mod.defs.append(v)
-
- ;l.append(':')
- ;l.append('\n')
- ;cur` = cur` + 2
- ;l = string_add(l, decompose_data(tok, cur, et))
- ;out`.dsec = string_add(out`.dsec, l)
- ;/
- ;/
-
- ;current`.sub.append(enum_mod)
-;/
-
-# Generates opposite closing bracket
-/; closing_for (Token d) [{}uint8]
- /; if (d.cmp("("))
- ;return ")"
- ;; else if (d.cmp("["))
- ;return "]"
- ;; else if (d.cmp("{"))
- ;return "}"
- ;; else if (d.cmp("/;") || d.cmp(";;"))
- ;return ";/"
- ;/
- ;log_err(string_add("Error, unrecognized delim: ", d.data))
-;/
-
-# Finds closing bracket
-/; find_closing (~{}Token tok, ~int cur) [int]
- ;int bl = 0, p = 0, br = 0, c = 0
- ;{}uint8 cl = closing_for(tok`{cur`})
- /; loop (int i = cur` + 1; i < len tok`) [i++]
- /; if (bl == 0 && p == 0 && br == 0 && c == 0)
- /; if ((tok`{i}.cmp(";;") || tok`{i}.cmp(";:")) && string_equate(cl, ";/"))
- ;return i
- ;; else if (tok`{i}.cmp(cl))
- ;return i
- ;/
- ;/
-
- /; if (tok`{i}.cmp("("))
- ;p++
- ;; else if (tok`{i}.cmp("["))
- ;br++
- ;; else if (tok`{i}.cmp("{"))
- ;c++
- ;; else if (tok`{i}.cmp("/;"))
- ;bl++
- ;/
-
- /; if (tok`{i}.cmp(")"))
- ;p = p - 1
- ;; else if (tok`{i}.cmp("]"))
- ;br = br - 1
- ;; else if (tok`{i}.cmp("}"))
- ;c = c - 1
- ;; else if (tok`{i}.cmp(";/") || tok`{i}.cmp(";:"))
- ;bl = bl - 1
- ;/
- ;/
-
- ;return len tok` - 1
-;/
-
-# Skips cur to the end of a struct
-/; skip_struct (~{}Token tok, ~int cur)
- /; loop (cur` < len tok`) [cur`++]
- /; if (tok`{cur`}.cmp("{"))
- ;cur` = find_closing(tok, cur)
- ;break
- ;/
- ;/
-;/
-
-# Counts number of components in a composite value
-/; count_comp_el (~{}Token tok, int start) [int]
- ;int max = find_closing(tok, ~start)
- ;int out = 0
-
- /; loop (start++; start < max) [start++]
- /; if (tok`{start}.type_is(TOKEN.DELIMITER))
- ;start = find_closing(tok, ~start)
- ;; else if (tok`{start}.cmp(","))
- ;out++
- ;/
- ;/
-
- ;return out
-;/
-
-# Priority
-# 0 - deref
-# 1 - get
-# 2 - ref, len
-# 3 - inc/dec
-# 4 - mul/div/mod
-# 5 - add/sub
-# 6 - bitwise
-# 7 - boolean cmp
-# 8 - boolean logic
-# 9 - assignment
-/; priority (Token tok) [int]
- /; if (!(tok.type_is(TOKEN.AUGMENT)))
- ;return -1
- ;/
-
- /; if (tok.cmp("."))
- ;return 1
- ;; else if (tok.cmp("len"))
- ;return 2
- ;; else if (len (tok.data) == 1)
- /; if (tok.cmp("`"))
- ;return 0
- ;; else if (tok.cmp("~"))
- ;return 2
- ;; else if (tok.cmp("*") || tok.cmp("/") || tok.cmp("%"))
- ;return 4
- ;; else if (tok.cmp("-") || tok.cmp("+"))
- ;return 5
- ;; else if (tok.cmp("&") || tok.cmp("|") || tok.cmp("^") || tok.cmp("!"))
- ;return 6
- ;; else if (tok.cmp("<") || tok.cmp(">"))
- ;return 7
- ;; else if (tok.cmp("="))
- ;return 9
- ;/
- ;; else if (len (tok.data) == 2)
- /; if (tok.data{0} == tok.data{1})
- /; if (tok.data{0} == '<' || tok.data{0} == '>')
- ;return 6
- ;; else if (tok.data{0} == '=')
- ;return 7
- ;; else if (tok.data{0} == '+' || tok.data{0} == '-')
- ;return 3
- ;/
- ;return 8
- ;; else if (tok.data{1} == '=')
- ;return 9
- ;; else if (tok.data{1} == '<' || tok.data{1} == '>')
- ;return 7
- ;/
- ;return 6
- ;; else if (len (tok.data) == 3)
- ;return 7
- ;/
-
- ;return -1
-;/
-
-/; first_match (~{}Token tok, ~int i, int max, ~Module current, ~Scope scope) [Variable]
- ;Variable wk
- ;{}{}uint8 art = {}
-
- ;log_debug(string_join( {
- "Variable match with s:", int_to_string(i`), " m:", int_to_string(max), " first:", tok`{i`}.sprint()
- }, ""))
-
- /; loop (tok`{i`}.type_is(TOKEN.DEFWORD) && i` < max) [i`++]
- ;art.append(tok`{i`}.data)
- ;wk = scope`.find_var(art, current)
-
- /; if (!string_equate(wk.name, ""))
- ;i`++
- ;break
- ;/
-
- /; if (tok`{i` + 1}.cmp("."))
- ;i`++
- ;; else
- ;i`++
- ;break
- ;/
- ;/
-
- /; if (string_equate(wk.name, ""))
- ;log_debug(string_add("Unable to find variable within artifact ", string_join(art, ".")))
- ;/
- ;log_debug(string_add("Found ", wk.sprint()))
- ;return wk
-;/
-
-/; _param_end (~{}Token tok, int start) [int]
- /; loop (start < len tok`) [start++]
- /; if (tok`{start}.cmp(")") || tok`{start}.cmp("}") || tok`{start}.cmp(","))
- ;return start
- ;; else if (tok`{start}.type_is(TOKEN.DELIMITER))
- ;start = find_closing(tok, ~start)
- ;/
- ;/
- ;return start
-;/
-
-# FIXME: should set up the call by eval of all params
-/; _setup_call (~{}Token tok, int start, Variable base, ~CompData out, mov, ~Module current, ~Scope scope) [Function]
- ;{}uint8 name = tok`{start}.data
- ;start++
- ;int max = find_closing(tok, ~start)
- ;start++
- ;Function f
-
- ;int regs = 1
- /; if (string_equate(base.name, ""))
- ;regs = 0
- ;f = current`.find_function( {name} )
- ;; else
- ;f = base.data_type.mod`.find_function( {name} )
- ;/
- ;Variable ctmp = {"#ctmp", NO_TYPE, 0-1, LOCATION.REGISTER}
- ;int old_start = start
- /; loop (int i = 0; i < len (f.inputs)) [i++]
- ;Type t = f.mod`.find_type(string_split(f.inputs{i}.name, '.'))`
- ;t.ptr_chain = f.inputs{i}.ptr_chain
- ;ctmp.data_type = t
-
- /; if (ctmp.is_ref())
- ;ctmp.data_type.ptr_chain{len (ctmp.data_type.ptr_chain) - 1} = PTYPE.POINTER
- ;/
- ;ctmp.data_type.ptr_chain.append(PTYPE.REFERENCE)
-
- /; if (!(ctmp.is_prim()) || regs !< 6)
- ;int layer = 0
- ;Variable val = _eval_value(tok, start, _param_end(tok, start), out, mov, current, scope, t, ~layer)
- ;out`.csec = string_join( {
- out`.csec,
- "\tsub rsp, ", int_to_string(ctmp.norm_size()), "\n"
- }, "")
- ;scope`.tmp = scope`.tmp + ctmp.norm_size()
- ;ctmp.set(val, out)
- ;; else
- ;regs++
- ;/
- ;start = _param_end(tok, start) + 1
- ;/
-
- ;int regs = 1
- /; if (string_equate(base.name, ""))
- ;regs = 0
- ;/
- ;start = old_start
- /; loop (int i = 0; i < len (f.inputs)) [i++]
- ;Type t = f.mod`.find_type(string_split(f.inputs{i}.name, '.'))`
- ;t.ptr_chain = f.inputs{i}.ptr_chain
- ;ctmp.data_type = t
-
- /; if (ctmp.is_ref())
- ;ctmp.data_type.ptr_chain{len (ctmp.data_type.ptr_chain)} = PTYPE.POINTER
- ;/
- ;ctmp.data_type.ptr_chain.append(PTYPE.REFERENCE)
-
- /; if (ctmp.is_prim() && regs < 6)
- ;int layer = 0
- ;Scope tmp_sc = scope`.new_sub_cf("call")
- ;Variable val = _eval_value(tok, start, _param_end(tok, start), out, mov, current, ~tmp_sc, t, ~layer)
- ;tmp_sc.clear_tmp(out)
-
- ;out`.csec = string_join( {
- out`.csec,
- "\tsub rsp, ", int_to_string(ctmp.norm_size()), "\n"
- }, "")
- ;scope`.tmp = scope`.tmp + ctmp.norm_size()
-
- ;ctmp.set(val, out)
- ;regs++
- ;; else if (regs == 6)
- ;break
- ;/
- ;start = _param_end(tok, start) + 1
- ;/
-
- /; if (f.is_method())
- /; if (base.is_ref())
- ;base.move_register(0, out)
- ;; else
- ;out`.csec = string_join( {
- out`.csec,
- "\tlea rax, ", base.norm_loc(base.norm_size()), "\n"
- }, "")
- ;/
- ;/
-
- ;return f
-;/
-
-# FIXME: should actually do call based on function given, and return a proper variable.
-# assumes the call has been set up
-/; _perform_call (Function f, ~Scope scope, ~CompData out) [Variable]
- ;int reg = 0, i = 0
- /; if (f.is_method())
- ;reg = 1
- ;/
- ;Variable ctmp = {"#ctmp", NO_TYPE, 4, LOCATION.REGISTER}
- /; loop (i < len (f.inputs)) [i++]
- ;Type t = f.mod`.find_type(string_split(f.inputs{i}.name, '.'))`
- ;t.ptr_chain = f.inputs{i}.ptr_chain
- ;ctmp.data_type = t
- /; if (ctmp.is_prim() && reg < 6)
- ;reg++
- ;; else if (reg == 6)
- ;break
- ;/
- ;/
- ;reg = reg - 1
- ;i = i - 1
- /; loop (i !< 0) [i = i - 1]
- ;Type t = f.mod`.find_type(string_split(f.inputs{i}.name, '.'))`
- ;t.ptr_chain = f.inputs{i}.ptr_chain
- ;ctmp.data_type = t
- /; if (ctmp.is_prim() && reg < 6)
- ;out`.csec = string_join( {
- out`.csec,
- "\tmov ", get_reg(reg, ctmp.norm_size()),", [rsp]\n",
- "\tadd rsp, ", int_to_string(ctmp.norm_size()), "\n"
- }, "")
- ;scope`.tmp = scope`.tmp - ctmp.norm_size()
- ;reg = reg - 1
- ;; else if (reg == 6)
- ;break
- ;/
- ;/
- ;out`.csec = string_join( {
- out`.csec,
- "\tcall ", f.full_label(), "\n"
- }, "")
-
- /; if (string_equate(f.output.name, ""))
- ;return {"", NO_TYPE, 0, 0}
- ;/
-
- ;Type t = f.mod`.find_type(string_split(f.output.name, '.'))`
- ;t.ptr_chain = f.output.ptr_chain
- ;ctmp.data_type = t
- ;ctmp.location = 0
- /; if (!(ctmp.is_prim()) && !(ctmp.is_ref()))
- ;ctmp.data_type.ptr_chain.append(PTYPE.REFERENCE)
- ;/
- ;log_debug("perf call ret")
- ;return ctmp
-;/
-
-# Evaluates dot chains, indexing, and calls
-/; _eval_dot (~{}Token tok, ~int start, int max, ~CompData out, mov, ~Module current, ~Scope scope, Type t, ~int layer) [Variable]
- ;Variable wk = first_match(tok, start, max, current, scope)
-
- /; if (start` !< max)
- ;return wk
- ;/
-
- ;log_debug(string_add("Eval dot initial val: ", wk.sprint()))
-
- /; if (tok`{start`}.cmp("."))
- ;log_debug("Pre loop member")
- /; if (wk.data_type.has_member(tok`{start` + 1}.data))
- ;wk = wk.member(tok`{start` + 1}.data, out)
- ;start` = start` + 2
- ;/
- ;; else if (tok`{start`}.cmp("("))
- ;start` = start` - 1
- ;; else if (tok`{start`}.cmp("`"))
- ;log_debug("Pre loop deref")
- ;wk = wk.deref(out)
- ;start` = start` + 1
- ;/
-
- ;layer` = layer` + 1
- /; loop (start` < max) [start`++]
- /; if (tok`{start`}.cmp("`"))
- ;log_debug("Loop deref")
- ;wk = wk.deref(out)
- ;; else if (tok`{start`}.cmp(".") && tok`{start` + 1}.type_is(TOKEN.DEFWORD))
- ;log_debug("Loop member")
- /; if (wk.data_type.has_member(tok`{start` + 1}.data))
- ;start`++
- ;wk = wk.member(tok`{start`}.data, out)
- ;; else if (!(tok`{start` + 2}.cmp("(")))
- ;log_err(string_join( {
- "Invalid member [", tok`{start` + 1}.data, "] for variable ", wk.sprint()
- },""))
- ;/
- ;; else if (tok`{start`}.cmp("{"))
- ;log_debug("Index!")
- ;Type ut = {8, "uint", {}, {}, 0}
- ;Variable i = _eval_value(tok, start` + 1, find_closing(tok, start), out, mov, current, scope, ut, layer)
- ;log_debug(i.sprint())
- ;wk = wk.index(i, out)
- ;log_debug(wk.sprint())
- ;start` = find_closing(tok, start)
- ;; else if (tok`{start` + 1}.cmp("(") && tok`{start`}.type_is(TOKEN.DEFWORD))
- ;log_debug("Call")
-
- ## Pre-flight check
- # ;CompData trash = {"", "", ""}
- # ;_setup_call(tok, start`, wk, ~trash, mov, current, scope)
-
- # Actually do call
-
-
- /; if (layer` > 1)
- ;out`.csec = string_join({
- out`.csec,
- "\tpush rbx\n"
- } , "")
- ;scope`.tmp = scope`.tmp + 8
- ;; if (layer` > 2)
- ;out`.csec = string_join({
- out`.csec,
- "\tpush rcx\n"
- } , "")
- ;scope`.tmp = scope`.tmp + 8
- ;/
-
- ;Scope call_sc = scope`.new_sub_cf("call")
- ;Function to_call = _setup_call(tok, start`, wk, out, mov, current, ~call_sc)
- ;wk = _perform_call(to_call, ~call_sc, out)
- ;log_debug(to_call.sprint())
- ;log_debug(wk.sprint())
- ;call_sc.clear_tmp(out)
-
- /; if (layer` > 2)
- ;out`.csec = string_join({
- out`.csec,
- "\tpop rcx\n"
- } , "")
- ;scope`.tmp = scope`.tmp - 8
- ;; if (layer` > 1)
- ;out`.csec = string_join({
- out`.csec,
- "\tpop rbx\n"
- } , "")
- ;scope`.tmp = scope`.tmp - 8
- ;/
-
- ;start`++
- ;start` = find_closing(tok, start)
- ;/
- ;/
- ;layer` = layer` - 1
-
- /; if (layer` > 1)
- ;log_debug("Dot tmp variable generated")
- ;Variable tt
-
- /; if (wk.is_ref())
- ;tt = scope`.new_tmp_var({8, "void", {PTYPE.POINTER}, {}, 0}, out)
- ;; else
- ;tt = scope`.new_tmp_var(wk.data_type, out)
- ;/
-
- /; if (len (wk.data_type.ptr_chain) > 0)
- ;tt.set_raw(wk, out)
- ;tt.data_type = wk.data_type
- ;; else
- ;tt.set(wk, out)
- ;/
-
- ;wk = tt
- ;; else if (layer` == 1)
- ;wk.move_register(2, out)
- ;; else
- ;wk.move_register(1, out)
- ;/
-
- ;log_debug(string_add("Dot returning ", wk.sprint()))
- ;return wk
-;/
-
-/; literal_variable ({}uint8 data, l, ~CompData out) [Variable]
- ;Variable v = {"#literal", NO_TYPE, 0, LOCATION.LITERAL}
- /; if (data{0} == '"')
- ;out`.dsec = string_join({
- out`.dsec,
- l, ":\n",
- declare_size(8), int_to_string(len unquote_str(data)), "\n",
- declare_size(1), string_to_csb(unquote_str(data)), "\n"}
- , "")
- ;v.data_type = {1, "uint8", "", {POINTER.ARRAY}, {}}
- ;v.loc_type = LOCATION.LABEL
- ;v.name = l
- ;; else if (data{0} == '\'')
- ;v.data_type = {1, "uint8", "", {}, {}}
- ;v.location = unqote_char(data)
- ;; else if (string_equate(data, "true"))
- ;v.data_type = {1, "bool", "", {}, {}}
- ;v.location = 1
- ;; else if (string_equate(data, "false"))
- ;v.data_type = {1, "bool", "", {}, {}}
- ;v.location = 0
- ;; else
- ;v.data_type = {8, "int", "", {}, {}}
- ;v.location = string_to_int(data)
- ;/
- ;return v
-;/
-
-/; num_elements(~{}Token tok, int start, max) [int]
- ;int out = 1
- /; loop (start < max) [start++]
- /; if (tok`{start}.type_is(TOKEN.DELIMITER))
- ;start = find_closing(tok, ~start)
- ;; else if (tok`{start}.cmp(","))
- ;out++
- ;/
- ;/
-;/
-
-/; element_end(~{}Token tok, int start, max) [int]
- /; loop (out < max + 1 && !(tok`{start}.cmp(","))) [start++] ;/
- ;return start
-;/
-
-/; _eval_composite (~{}Token tok, int start, max, ~CompData out, mov, ~Module current, ~Scope scope, Type t, ~int layer) [Variable]
- ;{}uint8 l = scope`.next_const()
- /; if (start == max - 1)
- ;out`.dsec = string_join( {
- out`.dsec,
- l,
- decompose_empty(t)
- }, "")
- ;return {l, t, 0, LOCATION.LABEL}
- ;; else if (len(t.ptr_chain) > 0)
- ;Variable vout = {l, t, 0, LOCATION.LABEL}
- ;t.ptr_chain = strip_int(t.ptr_chain)
-
- ;int count = num_elements(tok, start, max)
- ;{}uint8 out_text = string_join( {
- l,
- "\tdq ", int_to_string(count), "\n"
- }, "")
-
- ;{}uint8 one_el = "\tdb 0"
- /; loop (int i = 1; i < t.size()) [i++]
- ;one_el = string_add(one_el, ", 0")
- ;/
- ;one_el.append('\n')
-
- ;int ind = 0
- /; loop (start < max) [start = next_non_nl(tok, start + 1)]
- ;Variable v = _eval_value(tok, start, element_end(tok, start, max), out, mov, current, scope, t, layer)
- /; if (v.loc_type == LOCATION.LITERAL)
- ;out_text = string_join( {
- out_text,
- declare_size(t.size()), int_to_string(v.location), "\n"
- }, "")
- ;; else
- ;out_text = string_add(out_text, one_el)
- ;Variable tos = vout.index({"#literal", get_primitive(is_primitive("uint")), ind, LOCATION.LITERAL}, out)
- ;tos.set(v, out)
- ;/
- ;ind++
- ;/
- ;out`.dsec = string_add(out`.dsec, out_text)
- ;return out
- ;/
-;/
-
-/; _eval_value(~{}Token tok, int start, max, ~CompData out, mov, ~Module current, ~Scope scope, Type t, ~int layer) [Variable]
- ;log_vis(".")
- /; if (start == max - 1)
- /; if (tok`{start}.type_is(TOKEN.LITERAL))
- ;{}uint8 l = current`.full_path()
-
- /; if (len l > 0)
- ;l.append('.')
- ;/
-
- ;l = string_add(l, scope`.next_const())
- ;return literal_variable(tok`{start}.data, l, out)
- ;/
- ;/
-
- ;int first = -1, pr = -1, pa = -1
- /; loop (int i = start; i < max) [i++]
- /; if (tok`{i}.type_is(TOKEN.AUGMENT) && priority(tok`{i}) !< pr)
- ;first = i
- ;pr = priority(tok`{i})
- ;; else if (tok`{i}.type_is(TOKEN.DELIMITER))
- ;pa = i
- ;i = find_closing(tok, ~i)
- ;/
- ;/
-
- /; if (tok`{start}.cmp("("))
- ;return _eval_value(tok, start + 1, find_closing(tok, ~start), out, mov, current, scope, t, layer)
- ;/
-
- /; if (pa !< 0 && pr < 2)
- /; if (tok`{pa}.cmp("{") && pa == first)
- ;log_debug("Composite")
- ;return _eval_composite(tok, pa + 1, find_closing(tok, ~pa), out, current, scope, t, layer)
- ;/
- ;/
-
- /; if (pr < 2)
- ;log_debug("Dot _eval_value")
- ;return _eval_dot(tok, ~start, max, out, mov, current, scope, t, layer)
- ;/
-
- ;Variable s1, s2
- ;layer` = layer` + 1
- /; if (first == start)
- ;s1 = _eval_value(tok, first + 1, max, out, mov, current, scope, t, layer)
- ;; else if (first == max - 1)
- ;s1 = _eval_value(tok, start, first, out, mov, current, scope, t, layer)
- ;; else
- /; if (tok`{first}.cmp("="))
- ;layer` = layer` - 1
- ;/
- ;int l2 = layer` + 1
-
- ;s1 = _eval_value(tok, start, first, out, mov, current, scope, t, layer)
- ;t = s1.data_type
- ;t.strip_refs()
- ;s2 = _eval_value(tok, first + 1, max, out, mov, current, scope, t, ~l2)
-
- /; if (tok`{first}.cmp("="))
- ;layer` = layer` + 1
- ;/
-
- ;log_debug(string_add("Calculated s2 as ", s2.sprint()))
- ;/
- ;layer` = layer` - 1
-
- ;log_debug(string_add("Calculated s1 as ", s1.sprint()))
-
- /; if (tok`{first}.cmp("="))
- ;s1.set(s2, out)
- ;return s1
- ;; if (tok`{first}.cmp("++") || tok`{first}.cmp("--"))
- ;t = s1.data_type
- ;t.strip_refs()
- ;/
-
- ;Variable wk = {"#wk", t, 1, LOCATION.REGISTER}
- /; if (layer` > 1)
- ;wk = scope`.new_tmp_var(t, out)
- ;; else if (layer` == 1)
- ;wk.location = 2
- ;/
-
- ;log_debug(string_join( {
- "_eval_value called with following type info:", t.sprint()
- }, " "))
-
- # Inc and dec
- /; if (tok`{first}.cmp("++") || tok`{first}.cmp("--"))
- ;wk.set(s1, out)
-
- /; if (tok`{first}.cmp("++"))
- ;s1.inc(out)
- ;; else
- ;s1.dec(out)
- ;/
-
- /; if (first == max - 1)
- ;return wk
- ;/
-
- ;return s1
- ;/
-
- # TODO: Boolean combinations such as and, or, xor
- /; if (pr == 7)
- ;wk.set(s1, out)
- ;wk.cmp(s2, out)
- ;wk.data_type = {1, "bool", {}, {}, 0}
-
- ;wk.set(literal_variable("true", "", out), out)
- ;{}uint8 l = scope`.next_const()
- # ;log_debug(l)
- ;out`.csec = string_join( {
- out`.csec,
- to_jmp(tok`{first}.data), l, "\n"
- }, "")
- ;wk.set(literal_variable("false", "", out), out)
- ;out`.csec = string_join( {
- out`.csec,
- l, ":\n"
- }, "")
-
- ;return wk
- ;; else if (pr == 8)
- # TODO: First convert non-boolean values to boolean
- /; if (tok`{first}.cmp("&&"))
- ;wk.set(s1, out)
- ;wk.and(s2, out)
- ;; else if (tok`{first}.cmp("||"))
- ;wk.set(s1, out)
- ;wk.or(s2, out)
- ;; else if (tok`{first}.cmp("^^"))
- ;wk.set(s1, out)
- ;wk.xor(s2, out)
- ;/
- ;/
-
- /; if (tok`{first}.cmp("+"))
- ;wk.set(s1, out)
- ;wk.add(s2, out)
- ;; else if (tok`{first}.cmp("-"))
- /; if (first == start)
- ;wk.negative(s1, out)
- ;return wk
- ;/
- ;wk.set(s1, out)
- ;wk.sub(s2, out)
- ;; else if (tok`{first}.cmp("|"))
- ;wk.set(s1, out)
- ;wk.or(s2, out)
- ;; else if (tok`{first}.cmp("&"))
- ;wk.set(s1, out)
- ;wk.and(s2, out)
- ;; else if (tok`{first}.cmp("^"))
- ;wk.set(s1, out)
- ;wk.xor(s2, out)
- ;; else if (tok`{first}.cmp("*"))
- ;wk.set(s1, out)
- ;wk.mul(s2, out)
- ;; else if (tok`{first}.cmp("/"))
- ;wk.set(s1, out)
- ;wk.div(s2, out)
- ;; else if (tok`{first}.cmp("%"))
- ;wk.set(s1, out)
- ;wk.mod(s2, out)
- ;; else if (tok`{first}.cmp("~"))
- /; if (!(s1.is_ref()) && s1.loc_type == LOCATION.REGISTER)
- ;s1 = scope`.move_to_stack(s1.location, mov)
- ;/
- ;wk.ref(s1, out)
- ;; else if (tok`{first}.cmp("!"))
- ;wk.not(s1, out)
- ;; else if (tok`{first}.cmp("len"))
- ;wk.length_of(s1, out)
- ;/
-
- ;return wk
-;/
-
-# ALWAYS put the value in rax on save
-/; eval_value (~{}Token tok, ~int cur, ~CompData out, mov, ~Module current, ~Scope scope, Type t, bool save) [Variable]
- ;log_debug("Evaling!")
- ;int end = cur`
- /; loop (end < len tok`) [end++]
- /; if (tok`{end}.type_is(TOKEN.SEPARATOR) || tok`{end}.cmp(";/") || tok`{end}.cmp("]") || tok`{end}.cmp(")"))
- ;break
- ;; else if (tok`{end}.type_is(TOKEN.DELIMITER))
- ;end = find_closing(tok, ~end)
- ;/
- ;/
- ;CompData tmp = {"", "", ""}
- ;int level = 0
- ;_eval_value(tok, cur`, end, ~tmp, mov, current, scope, t, ~level)
- ;scope`.clear_tmp(~tmp)
- ;Variable val = _eval_value(tok, cur`, end, out, ~tmp, current, scope, t, ~level)
- ;log_debug("c")
- ;scope`.clear_tmp(out)
- ;cur` = end
- /; if (save)
- /; if (!(val.is_prim()))
- ;t.ptr_chain.append(PTYPE.REFERENCE)
- ;/
-
- ;Variable set = {"#tmp", t, 0, LOCATION.REGISTER}
-
- /; if (!(val.is_prim()) && set.is_ref())
- ;set.data_type.ptr_chain = { PTYPE.POINTER }
- ;set.ref(val, out)
- ;set.data_type.ptr_chain = { PTYPE.REFERENCE }
- ;; else if (set.is_ref())
- ;set.set_raw(val, out)
- ;; else
- ;set.set(val, out)
- ;/
-
- ;return val
- ;/
- ;return { "", NO_TYPE, 0, 0 }
-;/
-
-/; eval_def (~{}Token tok, ~int cur, ~CompData out, mov, ~Module current, ~Scope scope)
- ;Type t = get_type(tok, cur, current)
- /; loop (tok`{cur`}.type_is(TOKEN.DEFWORD))
- ;scope`.new_var(t, tok`{cur`}.data, out)
- ;eval_value(tok, cur, out, mov, current, scope, t, false)
-
- /; if (tok`{cur`}.cmp(","))
- ;cur` = next_non_nl(tok, cur` + 1)
- ;; else
- ;break
- ;/
- ;/
-;/
-
-/; is_bool_statement (~{}Token tok, int start, max, ~Module current, ~Scope parent) [bool]
- ;int i = start
- /; loop (i < max) [i++]
- /; if (tok`{i}.type_is(TOKEN.AUGMENT))
- /; if (priority(tok`{i}) == 7 || priority(tok`{i}) == 8)
- ;return true
- ;/
- ;; else if (tok`{i}.type_is(TOKEN.LITERAL))
- /; if (string_equate(tok`{i}.data, "false") || string_equate(tok`{i}.data, "true"))
- ;return true
- ;/
- ;; else if (tok`{i}.type_is(TOKEN.DEFWORD))
- ;int j = i
- ;Variable v = first_match(tok, ~j, max, current, parent)
- /; if (string_equate(v.data_type.name, "bool"))
- ;int j = len(v.data_type.ptr_chain)
- /; if (j == 0 || (j == 1 && v.is_ref()))
- ;return true
- ;/
- ;/
- ;; else if (tok`{i}.type_is(TOKEN.DELIMITER))
- ;i = find_closing(tok, ~i)
- ;; else if (tok`{i}.cmp(";") || tok`{i}.cmp("\n"))
- ;break
- ;/
- ;/
-
- ;return false
-;/
-
-
-/; statement_list(~{}Token tok, int start, end, ~Module current, ~CompData out, mov, ~Scope parent) [int]
- ;log_debug("Statement list!")
- ;int b = -1
- ;CompData carry = {"", "", ""}
- ;int s = next_non_nl(tok, start + 1)
- /; loop (s < end) [s = next_non_nl(tok, s + 1)]
- ;out`.add(carry)
- ;carry = {"", "", ""}
- ;b = -1
- /; if (is_definition(tok, ~s, current))
-
- ;log_debug("Block def")
- ;eval_def(tok, ~s, out, mov, current, parent)
- ;; else
- ;log_debug("Block val")
- /; if (is_bool_statement(tok, s, end, current, parent))
- ;b = s
- ;/
- ;Type t = NO_TYPE
- /; if (b !< 0)
- ;t = {1, "bool", "_bool", {}, {}}
- ;log_debug("Boolish")
- ;/
- ;eval_value(tok, ~s, out, mov, current, parent, t, b > 0)
- ;/
- ;/
-
- ;return b
-;/
-
-
-# FIXME:
-# Need to impl:
-# cf block scoping and contextual keywords such as
-# continue, break, and return
-/; _compile_block (~{}Token tok, ~int cur, ~Module current, ~CompData out, mov, ~Scope parent, Type ret)
- ;Scope cf = parent`.new_sub_cf("wrap")
-
- ;CompData outro = {"", "", ""}
- ;int condition = 0 - 1
-
- /; loop (cur`++; cur` < len (tok`)) [cur`++]
- /; if (tok`{cur`}.type_is(TOKEN.KEYWORD))
- /; if (tok`{cur`}.cmp("else"))
- ;log_err("Invalid else!!!")
- ;; else
- ;cf = cf.new_sub_cf(tok`{cur`}.data)
- ;/
- ;; else if (tok`{cur`}.cmp("("))
- ;int psl = find_closing(tok, cur)
- ;int tmp = statement_list(tok, cur`, psl, current, out, mov, ~cf)
-
- /; if (tmp !< 0 && condition < 0 && cf.cf_type("if") == false)
- ;condition = tmp
- ;Type t = {1, "bool", "_bool", {}, {}}
- ;eval_value(tok, ~tmp, ~outro, mov, current, ~cf, t, true)
- ;/
-
- /; if (tmp !< 0)
- /; if (cf.cf_type("if"))
- ;out`.csec = string_join( {
- out`.csec,
- "\ttest al, al\n",
- "\tjz ", cf.scope_start_label(), "\n"
- }, "")
- ;; else
- ;out`.csec = string_join( {
- out`.csec,
- "\ttest al, al\n",
- "\tjz ", cf.scope_end_label(), "\n"
- }, "")
- ;/
- ;/
-
- ;cur` = psl
- ;; else if (tok`{cur`}.cmp("["))
- ;CompData t_outro = {"", "", ""}
- ;int psl = find_closing(tok, cur)
- ;int tmp = statement_list(tok, cur`, psl, current, ~t_outro, mov, ~cf)
-
- /; if (tmp < 0 && condition !< 0)
- ;t_outro.add(outro)
- ;outro = t_outro
- ;; else
- ;outro = t_outro
- ;/
-
- ;cur` = psl
- ;; else
- ;break
- ;/
- ;/
-
- /; if (cf.cf_type("loop"))
- ;out`.csec = string_join( {
- out`.csec,
- cf.scope_start_label(), ":\n"
- }, "")
- ;/
-
- ;cur` = next_non_nl(tok, cur`)
-
- ;bool returned = false
- /; loop (cur` < len (tok`) && !returned) [cur` = next_non_nl(tok, cur` + 1)]
- /; if (tok`{cur`}.cmp("/;"))
- ;log_debug("Block in block")
- ;_compile_block(tok, cur, current, out, mov, ~cf, ret)
-
- /; loop (tok`{cur`}.cmp(";;"))
- ;_compile_block(tok, cur, current, out, mov, ~cf, ret)
- ;/
- ;; else if (tok`{cur`}.cmp(";;") || (tok`{cur`}.cmp(";/") && tok`{next_non_nl(tok, cur` + 1)}.cmp("/;")))
- /; if (tok`{cur`}.cmp(";/"))
- ;cur` = next_non_nl(tok, cur` + 1)
- ;/
-
- /; if ((cf.cf_type("if") || cf.cf_type("elif")) && tok`{next_non_nl(tok, cur` + 1)}.cmp("else"))
- ;cur` = next_non_nl(tok, cur` + 1)
- ;out`.csec = string_join( {
- out`.csec,
- cf.scope_end_label(), ":\n"
- }, "")
-
- /; if (len (outro.csec) > 0)
- ;out`.add(outro)
- ;/
-
- ;out`.csec = string_join( {
- out`.csec,
- "\tjmp ", cf.parent`.scope_end_label(), "\n",
- cf.scope_rep_label(), ":\n"
- }, "")
-
- /; if (len (outro.csec) > 0)
- ;out`.add(outro)
- ;/
-
- ;out`.csec = string_join( {
- out`.csec,
- cf.scope_start_label(), ":\n"
- }, "")
-
- ;outro = {"", "", ""}
- ;condition = 0 - 1
-
- /; if (tok`{next_non_nl(tok, cur` + 1)}.cmp("if"))
- ;cur` = next_non_nl(tok, cur` + 1)
- ;cur` = next_non_nl(tok, cur` + 1)
- ;cf = cf.parent`.new_sub_cf("elif")
- /; loop (cur` < len (tok`)) [cur`++]
- /; if (tok`{cur`}.cmp("(") || tok`{cur`}.cmp("["))
- ;int psl = find_closing(tok, cur)
- ;int tmp = statement_list(tok, cur`, psl, current, ~outro, mov, ~cf)
- /; if (tmp < 0 && condition !< 0)
- ;tmp = condition
- ;Type t = {1, "bool", "_bool", {}, {}}
- ;eval_value(tok, ~tmp, ~outro, mov, current, ~cf, t, true)
- ;; else
- ;condition = tmp
- ;/
-
- /; if (tok`{cur`}.cmp("(") && condition !< 0)
- ;out`.add(outro)
- ;outro = {"", "", ""}
- ;out`.csec = string_join( {
- out`.csec,
- "\ttest al, al\n",
- "\tjz ", cf.scope_start_label(), "\n"
- }, "")
- ;/
- ;cur` = psl
- ;; else
- ;break
- ;/
- ;/
-
- ;cur` = next_non_nl(tok, cur`)
- ;cur`--
- ;; else
- ;cf = cf.parent`.new_sub_cf("else")
- ;/
- ;; else
- /; loop (!(tok`{cur`}.cmp(";/") || tok`{cur`}.cmp(";;")))
- ;cur`--
- ;/
- ;cur`--
- ;returned = true
- ;/
- ;; else if (tok`{cur`}.cmp(";/"))
- ;cur`--
- ;returned = true
- ;; else if (tok`{cur`}.type_is(TOKEN.KEYWORD))
- /; if (tok`{cur`}.cmp("return"))
- ;cur`++
- /; if (ret.s > 0)
- ;eval_value(tok, cur, out, mov, current, ~cf, ret, true)
- ;/
- ;cf.end_scope(out)
- ;out`.csec = string_add(out`.csec, "\tret\n")
- ;; else if (tok`{cur`}.cmp("raw") && tok`{cur` + 1}.cmp("return"))
- /; if (!(cf.r))
- ;log_err("Unable to perform a raw return from a non-raw block.")
- ;/
- ;cur` = cur` + 2
- /; if (ret.s > 0)
- ;eval_value(tok, cur, out, mov, current, ~cf, ret, true)
- ;/
- ;out`.csec = string_add(out`.csec, "\tret\n")
- ;; else if (tok`{cur`}.cmp("asm"))
- ;cur`++
- ;out`.csec.append('\t')
- ;out`.csec = string_add(out`.csec, unquote_str(tok`{cur`}.data))
- ;out`.csec.append('\n')
- ;; else if (tok`{cur`}.cmp("break"))
- /; if (tok`{cur` + 1}.type_is(TOKEN.LITERAL))
- ;cf.br(string_to_int(tok`{cur` + 1}.data), out)
- ;cur`++
- ;; else if (cf.cf_type("if") || cf.cf_type("elif") || cf.cf_type("else"))
- ;cf.br(1, out)
- ;; else
- ;cf.br(0, out)
- ;/
- ;; else if (tok`{cur`}.cmp("continue"))
- /; if (tok`{cur` + 1}.type_is(TOKEN.LITERAL))
- ;cf.cont(string_to_int(tok`{cur` + 1}.data), out)
- ;cur`++
- ;; else if (cf.cf_type("if") || cf.cf_type("else"))
- ;cf.cont(1, out)
- ;; else
- ;cf.cont(0, out)
- ;/
- ;; else
- ;log_err(string_add("Keyword not impl: ", tok`{cur`}.data))
- ;/
- ;; else if (is_definition(tok, cur, current))
- ;log_debug("Block def")
- ;eval_def(tok, cur, out, mov, current, ~cf)
- ;; else
- ;log_debug("Block val")
- ;eval_value(tok, cur, out, mov, current, ~cf, NO_TYPE, false)
- ;/
- ;/
-
- ;log_debug("Passing gauntlet 2")
-
- /; if (cf.cf_type("loop"))
- ;out`.csec = string_join( {
- out`.csec,
- cf.scope_rep_label(), ":\n"
- }, "")
-
- /; if (len (outro.csec) > 0)
- ;out`.add(outro)
- ;/
-
- /; if (condition !< 0)
- ;out`.csec = string_join( {
- out`.csec,
- "\ttest al, al\n",
- "\tjnz ", cf.scope_start_label(), "\n",
- cf.scope_end_label(), ":\n"
- }, "")
- ;; else
- ;out`.csec = string_join( {
- out`.csec,
- "\tjmp ", cf.scope_start_label(), "\n",
- cf.scope_end_label(), ":\n"
- }, "")
- ;/
-
- ;; else
- ;out`.csec = string_join( {
- out`.csec,
- cf.scope_end_label(), ":\n"
- }, "")
-
- /; if (len (outro.csec) > 0)
- ;out`.add(outro)
- ;/
-
- ;out`.csec = string_join( {
- out`.csec,
- "\tjmp ", cf.parent`.scope_end_label(), "\n",
- cf.scope_rep_label(), ":\n"
- }, "")
-
- /; if (len (outro.csec) > 0)
- ;out`.add(outro)
- ;/
-
- ;out`.csec = string_join( {
- out`.csec,
- cf.scope_start_label(), ":\n"
- }, "")
- ;/
-
- /; if (cf.is_cf())
- ;out`.csec = string_join( {
- out`.csec,
- cf.parent`.scope_rep_label(), ":\n",
- cf.parent`.scope_end_label(), ":\n"
- }, "")
- ;/
-;/
-
-
-
-
-/; compile_block (~{}Token tok, ~int cur, ~Module current, ~CompData out)
- ;Scope root = {0, 0, 0, 0, "", {}, false}
- ;int max = find_closing(tok, cur)
- ;bool m = false, returned = false
- ;Type ret = NO_TYPE
-
- /; if (len (current`.name) > 2)
- /; if (current`.name{0} == '_' && current`.name{1} == '#')
- ;{}{}uint8 split = string_split(current`.name, '#')
- ;Type st = current`.find_type( {split{1}} )`
- ;st.ptr_chain = {PTYPE.REFERENCE}
- ;root.vars.append({"self", st, 0, LOCATION.LITERAL})
- ;/
- ;/
-
- /; loop (cur`++; cur` < max && !m) [cur`++]
- /; if (tok`{cur`}.type_is(TOKEN.DEFWORD))
- ;root.name = tok`{cur`}.data
- ;; if (tok`{cur`}.type_is(TOKEN.KEYWORD))
- /; if (tok`{cur`}.cmp("raw"))
- ;root.r = true
- ;; else if (tok`{cur`}.cmp("method"))
- ;m = true
- ;current = current`.find_sub(tok`{cur` + 1}.data)
- ;; else
- ;log_err(string_join( {
- "Keyword ", tok`{cur`}.data, " not impl on mod level blocks"
- }, ""))
- ;/
- ;; if (tok`{cur`}.cmp("("))
- ;log_debug("Parsing params")
- ;{}Variable params = parse_param_list(tok, cur, current)
- /;loop (int i = 0; i < len params) [i++]
- ;root.vars.append(params{i})
- ;/
- ;; if (tok`{cur`}.cmp("["))
- ;cur`++
- ;ret = get_type(tok, cur, current)
- /; if (is_primitive(ret.name) < 0 && len (ret.ptr_chain) == 0)
- ;ret.ptr_chain.append(PTYPE.REFERENCE)
- ;/
- ;; if (tok`{cur`}.cmp("\n"))
- ;break
- ;/
- ;/
-
- /; if (!m)
- ;{}uint8 l = ""
- /; if (!string_equate(current`.name, ""))
- ;l = string_add(l, current`.full_path())
- ;l.append('.')
- ;/
- ;l = string_add(l, root.name)
- ;root.name = l
-
- ;log_debug("----------------------------")
- ;log_debug(string_add("START OF BLOCK: ", l))
- ;log_debug("----------------------------")
-
- /; if (current`.exp)
- ;out`.hsec = string_add(out`.hsec, "global ")
- ;out`.hsec = string_add(out`.hsec, l)
- ;out`.hsec.append('\n')
- ;/
- ;out`.csec = string_add(out`.csec, l)
- ;out`.csec = string_add(out`.csec, ":\n")
- ;root.begin_scope(out)
- ;/
-
- /; loop (cur` = next_non_nl(tok, cur` + 1); cur` < max && !returned) [cur` = next_non_nl(tok, cur` + 1)]
- /; if (tok`{cur`}.cmp("/;") || tok`{cur`}.cmp(";;"))
- ;log_debug("Block in block")
- /; if (m)
- ;compile_block(tok, cur, current, out)
- ;; else
- ;CompData mov = {"", "", ""}, tmp = {"", "", ""}
- ;log_debug("PRE COMPUTATION OF BLOCK\n")
- ;int tcr = cur`
- ;_compile_block(tok, ~tcr, current, ~tmp, ~mov, ~root, ret)
- ;out`.add(mov)
- ;log_debug("POST COMPUTATION OF BLOCK")
- ;_compile_block(tok, cur, current, out, ~tmp, ~root, ret)
- ;/
-
- /; if (tok`{cur`}.cmp(";;"))
- ;cur` = cur` - 1
- ;/
- ;; else if (tok`{cur`}.type_is(TOKEN.KEYWORD))
- /; if (tok`{cur`}.cmp("return"))
- ;cur`++
- /; if (ret.s > 0)
- ;eval_value(tok, cur, out, out, current, ~root, ret, true)
- ;/
- ;root.end_scope(out)
- ;out`.csec = string_add(out`.csec, "\tret\n")
- ;returned = true
- ;; else if (tok`{cur`}.cmp("raw") && tok`{cur` + 1}.cmp("return"))
- /; if (!(root.r))
- ;log_err("Unable to perform a raw return from a non-raw block.")
- ;/
- ;cur` = cur` + 2
- /; if (ret.s > 0)
- ;eval_value(tok, cur, out, out, current, ~root, ret, true)
- ;/
- ;out`.csec = string_add(out`.csec, "\tret\n")
- ;returned = true
- ;; else if (tok`{cur`}.cmp("asm"))
- ;cur`++
- ;out`.csec.append('\t')
- ;out`.csec = string_add(out`.csec, unquote_str(tok`{cur`}.data))
- ;out`.csec.append('\n')
- ;; else
- ;log_err(string_add("Keyword not impl: ", tok`{cur`}.data))
- ;/
- ;; else if (is_definition(tok, cur, current))
- ;log_debug("Block def")
- ;eval_def(tok, cur, out, out, current, ~root)
- ;; else
- ;log_debug("Block val")
- ;eval_value(tok, cur, out, out, current, ~root, NO_TYPE, false)
- ;/
- ;/
-
- ;cur` = max
-
- /; if (!returned && !string_equate(ret.name, ""))
- ;log_err("Block must return a value.")
- ;/
-
- /; if (!m && !returned)
- ;root.end_scope(out)
- ;out`.csec = string_add(out`.csec, "\tret\n")
- ;/
-;/
-
-# First pass on a module
-# Generates structs, enums, and submodules
-/; module_pass_one (~{}Token tok, ~int cur, ~Module current, Path f)
- ;int max = find_closing(tok, cur)
- ;{}uint8 name = ""
- ;bool exp = false
- /; loop (cur`++; cur` < len tok`) [cur`++]
- /; if (tok`{cur`}.type_is(TOKEN.DEFWORD))
- ;name = tok`{cur`}.data
- ;; else if (tok`{cur`}.cmp("export"))
- ;exp = true
- ;; else if (tok`{cur`}.cmp("method"))
- ;exp = current`.exp
- /; if (len name > 0)
- ;name = string_add("_#", name)
- ;; else if (tok`{cur` + 1}.type_is(TOKEN.DEFWORD))
- ;cur`++
- ;name = string_add("_#", tok`{cur`}.data)
- ;; else
- ;log_err(string_add("Tried to find name for method block, but there wasn't one nearby. ", tok`{cur`}.sprint()))
- ;/
- ;; else if (!(tok`{cur`}.cmp("module")))
- ;break
- ;/
- ;/
-
- /; if (len name == 0)
- ;log_err(string_add("Did not find name for module or pethod block. ", tok`{cur`}.sprint()))
- ;/
- ;log_debug(string_add("Generating module ", name))
-
- ;~Module new = find_or_create(name, current, exp)
-
- /; loop (cur` < max) [cur`++]
- ;log_vis(".")
- /; if (tok`{cur`}.cmp(":"))
- ;log_debug("INCLUDE")
- /; if (tok`{cur` + 2}.type_is(TOKEN.LITERAL))
- ;compile_file_pass_one(f.relative(unquote_str(tok`{cur` + 2}.data)), new)
- ;cur` = cur` + 2
- ;/
- ;continue
- ;; else if (tok`{cur`}.cmp("/;") || tok`{cur`}.cmp(";;"))
- /; if (tok`{cur` + 1}.cmp("export") || tok`{cur` + 1}.cmp("module") || tok`{cur` + 1}.cmp("method"))
- ;module_pass_one(tok, cur, new, f)
- ;; else
- ;new_function(tok, cur, new)
- ;/
- ;; else if (tok`{cur`}.cmp("struct"))
- ;new_type(tok, cur, new)
- ;/
- ;/
-;/
-
-# Second pass on a module
-# Generates code and calls compile_file_second_pass if an include happens
-/; module_pass_two (~{}Token tok, ~int cur, ~Module current, ~CompData out)
- ;int max = find_closing(tok, cur)
- /; loop (cur`++; cur` < len tok`) [cur`++]
- /; if (tok`{cur`}.type_is(TOKEN.DEFWORD))
- ;current = current`.find_sub(tok`{cur`}.data)
- ;; else if (!(tok`{cur`}.cmp("module")) && !(tok`{cur`}.cmp("export")))
- ;break
- ;/
- ;/
-
- /; loop (cur` = next_non_nl(tok, cur`); cur` < max) [cur` = next_non_nl(tok, cur` + 1)]
- ;log_vis(".")
- /; if (tok`{cur`}.cmp(":"))
- ;log_debug("INCLUDE")
- /; if (tok`{cur` + 2}.type_is(TOKEN.LITERAL))
- ;CompData tmp = compile_file_pass_two(f.relative(unquote_str(tok`{cur` + 2}.data)), current)
- ;out`.hsec = string_add(out`.hsec, tmp.hsec)
- ;out`.dsec = string_add(out`.dsec, tmp.dsec)
- ;out`.csec = string_add(out`.csec, tmp.csec)
- ;cur` = cur` + 2
- ;/
- ;continue
- ;; else if (tok`{cur`}.cmp("/;") || tok`{cur`}.cmp(";;"))
- ;log_debug("Mod block")
- /; if (tok`{cur` + 1}.cmp("export") || tok`{cur` + 1}.cmp("module"))
- ;module_pass_two(tok, cur, current, out)
- ;; else
- ;compile_block(tok, cur, current, out)
- ;/
- ;; else if (tok`{cur`}.cmp("struct"))
- ;log_debug("Mod struct")
- ;skip_struct(tok, cur)
- ;; else if (tok`{cur`}.cmp("enum"))
- ;log_debug("Mod enum")
- ;compile_enum(tok, cur, current, out)
- ;; else if (is_definition(tok, cur, current))
- ;log_debug("Mod def")
- ;compile_file_def(tok, cur, current, out)
- ;; else if (!(tok`{cur`}.cmp("\n")))
- ;log_err(string_add("Failed to recognize file-level statement ", tok`{cur`}.sprint()))
- ;/
- ;/
-;/
-
-/; combine_tok_lists (int cut_a, cut_b, {}Token a, b) [{}Token]
- ;{}Token out = {}
- /; loop (int i = 0; i < cut_a) [i++]
- ;out.append(a{i})
- ;/
-
- /; loop (int i = 0; i < len b) [i++]
- ;out.append(b{i})
- ;/
-
- /; loop (int i = cut_b; i < len a) [i++]
- ;out.append(a{i})
- ;/
-
- ;return out
-;/
-
-# First compiler pass on a file
-# Only creates structs, enums, and moduless
-/; compile_file_pass_one (Path f, ~Module current) [{}Token]
- ;{}Token tok = tokenize(f)
- ;log_info(string_add("Number of tokens generated: ", int_to_string(len tok)))
-
- /; loop (int i = 0; i < len tok) [i++]
- ;log_vis(".")
- /; if (tok{i}.cmp(":"))
- ;log_debug("INCLUDE")
- /; if (tok{i + 2}.type_is(TOKEN.LITERAL))
- ;{}Token inc = compile_file_pass_one(f.relative(unquote_str(tok{i + 2}.data)), current)
- ;tok = combine_tok_lists(i, i + 3, tok, inc)
- ;i = i + len inc
- ;/
- ;continue
- ;; else if (tok{i}.cmp("/;") || tok{i}.cmp(";;"))
- /; if (tok{i + 1}.cmp("export") || tok{i + 1}.cmp("module") || tok{i + 1}.cmp("method"))
- ;module_pass_one(~tok, ~i, current, f)
- ;; else
- ;new_function(~tok, ~i, current)
- ;/
- ;; else if (tok{i}.cmp("struct"))
- ;new_type(~tok, ~i, current)
- ;/
- ;/
-
- ;return tok
-;/
-
-/; size_struct (~Type t, ~Module m)
- ;int s = 0
-
- /; loop (int i = 0; i < len (t`.members)) [i++]
- ;int p = is_primitive(t`.members{i}.data_type.name)
- /; if (len (t`.members{i}.data_type.ptr_chain) > 0)
- ;s = s + 8
- ;; else if (p >== 0)
- ;s = s + p
- ;; else
- ;log_debug("STRUCT!!!!!!")
- ;{}{}uint8 artifact = { t`.members{i}.data_type.name }
- ;~Type tp = m`.find_type(artifact)
- /; if (tp`.s == 0)
- ;size_struct(tp, m)
- ;/
- ;t`.members{i}.data_type = tp`
- ;s = s + tp`.s
- ;/
- ;/
- ;log_debug(string_add("Sized type ", t`.name))
- ;t`.s = s
-;/
-
-# Regenerates struct sizes (with support for cyclical struct definitions)
-/; flush_structs (~Module m)
-
- /; loop (int i = 0; i < len (m`.types)) [i++]
- ;size_struct(~(m`.types{i}), m)
- ;/
-
- /; loop (int i = 0; i < len (m`.sub)) [i++]
- ;flush_structs(~(m`.sub{i}))
- ;/
-;/
-
-# Second pass of compiler
-# Does code generation, ignores structs and enums
-/; compile_file_pass_two (~{}Token tok, ~Module current) [CompData]
- ;CompData out = {"", "", ""}
-
- /; loop (int i = next_non_nl(tok, 0); i < len tok`) [i = next_non_nl(tok, i+1)]
- ;log_vis(".")
- /; if (tok`{i}.cmp(":"))
- ;log_debug("INCLUDE")
- /; if (tok`{i + 2}.type_is(TOKEN.LITERAL))
- ;CompData tmp = compile_file_pass_two(f.relative(unquote_str(tok`{i + 2}.data)), current)
- ;out.hsec = string_add(out.hsec, tmp.hsec)
- ;out.dsec = string_add(out.dsec, tmp.dsec)
- ;out.csec = string_add(out.csec, tmp.csec)
- ;i = i + 2
- ;/
- ;continue
- ;; else if (tok`{i}.cmp("/;") || tok`{i}.cmp(";;"))
- ;log_debug("Root block")
- /; if (tok`{i + 1}.cmp("export") || tok`{i + 1}.cmp("module"))
- ;module_pass_two(tok, ~i, current, ~out)
- ;; else
- ;compile_block(tok, ~i, current, ~out)
- ;/
- ;; else if (tok`{i}.cmp("struct"))
- ;log_debug("File struct")
- ;skip_struct(tok, ~i)
- ;; else if (tok`{i}.cmp("enum"))
- ;log_debug("File enum")
- ;compile_enum(tok, ~i, current, ~out)
- ;; else if (is_definition(tok, ~i, current))
- ;log_debug("File def")
- ;compile_file_def(tok, ~i, current, ~out)
- ;; else if (tok`{i}.cmp("asm"))
- ;log_debug("File asm")
- /; if (len (out.csec) == 0 && len (out.dsec) == 0)
- ;out.hsec = string_add(out.hsec, unquote_str(tok`{i + 1}.data))
- ;out.hsec.append('\n')
- ;; else
- ;out.dsec = string_add(out.dsec, unquote_str(tok`{i + 1}.data))
- ;out.dsec.append('\n')
- ;/
- ;i++
- ;; else if (!(tok`{i}.cmp("\n")))
- ;log_err(string_add("Failed to recognize file-level statement", tok`{i}.sprint()))
- ;/
- ;/
-
- ;log_info(string_add("File compiled! Generated code length: ", int_to_string(len (out.hsec) + len (out.dsec) + len (out.csec))))
-
- ;return out
-;/
-
-# Starts the compiler on a given path
-/; compile_start (Path f) [{}uint8]
- ;{}uint8 out = ""
-
- ;Module root = {0, true, {}, {}, {}, {}, {}}
- ;{}Token tok = compile_file_pass_one(f, ~root)
- ;flush_structs(~root)
- ;log_info("First pass DONE")
-
- ;CompData data = compile_file_pass_two(~tok, ~root)
- ;log_info("Second pass DONE")
-
- ;out = string_join({
- data.hsec,
- "section .data\n",
- data.dsec,
- "section .text\n",
- data.csec}, "")
-
- ;return out
-;/
-
-##
-## Main
-##
-
-/; main ({}{}uint8 args) [int]
- ;log_debug("TNSLC version 0.0.1, built with debugging enabled")
- /; if (len args < 1)
- ;log_info("Give me something to compile!")
- ;return 1
- ;/
-
- ;bool tokenize_only = len args > 1
-
- ;{}{}uint8 fsplit = string_split(args{0}, '/')
- ;Path p = {{}, fsplit{len fsplit - 1}}
-
- /; loop (int i = 0; i < len fsplit - 1) [i++]
- ;p.path.append(fsplit{i})
- ;/
-
- ;log_info("Path: ")
- ;log_info(p.full_path())
-
- ;{}uint8 code = ""
- /; if (!tokenize_only)
- ;code = compile_start(p)
- ;; else
- ;{}Token tok = tokenize(p)
- /; loop(int i = 0; i < len tok) [i++]
- ;log_vis(".")
- ;code = string_add(code, tok{i}.sprint())
- ;/
- ;log_vis("OK\n")
- ;/
-
- ;p.name = string_add(p.name, ".asm")
-
- ;p.write(code)
-
- ;return 0
-;/