summaryrefslogtreecommitdiff
path: root/tnslc
diff options
context:
space:
mode:
Diffstat (limited to 'tnslc')
-rw-r--r--tnslc/compile/function.tnsl217
-rw-r--r--tnslc/compile/var.tnsl59
-rw-r--r--tnslc/test.tnsl25
3 files changed, 283 insertions, 18 deletions
diff --git a/tnslc/compile/function.tnsl b/tnslc/compile/function.tnsl
index eac1732..9188ca3 100644
--- a/tnslc/compile/function.tnsl
+++ b/tnslc/compile/function.tnsl
@@ -10,6 +10,9 @@ struct Function {
~Module mod
}
+~uint8 BOOL_OPS = "&&,||,^^,!&&,!||,!^^\0"
+~uint8 CMP_OPS = "==,<,>,!==,!<,!>,<==,>==\0"
+
/; method Function
/; init (~parse.Node n)
self.name = utils.strcpy(n`.data)
@@ -579,9 +582,6 @@ struct Function {
/; _compile_loop (~Scope s, ~parse.Node n)
- # TODO
- _printf("Loops not impl, sorry :(\n\0")
-
# Generate scope
Scope ls = s`.gen_sub("loop\0")
@@ -1437,17 +1437,226 @@ struct Function {
return working
;/
- /; _compile_chain(~Scope s, ~parse.Node n) [Var]
+ /; _compile_chain (~Scope s, ~parse.Node n) [Var]
# FIND_VAR!!!!!
utils.Vector chain
chain.init(8)
return self._compile_chain_r(s, n, ~chain)
;/
+ /; _compile_bool_op (~Scope s, ~parse.Node n) [Var]
+ Scope bs = s`.gen_sub("bool\0")
+ ~parse.Node lhn = n`.sub.get(0)
+ ~parse.Node rhn = n`.sub.get(1)
+
+ ~uint8 op = n`.data
+
+ ~Struct t = self._find_literal_type(s, "bool\0")
+ Var dummy
+ dummy._init(t)
+ Var out = s`.mk_tmp(~dummy)
+ dummy.end()
+
+ # Compute left hand side
+ Var lhs = self._compile_value(s, lhn)
+ /; if (s`.is_tmp(~lhs) == true)
+ s`.free_after(~lhs, true)
+ ;/
+
+ /; if (lhs.is_struct() == true)
+ _printf("Can not use struct as boolean value\n\0")
+ lhs.end()
+ bs.end()
+ return out
+ ;/
+
+ ~CompBuf buf = s`.cb
+
+ # Pre-operation (jmp or mov) for this bool operator
+ /; if (op{1} == '&')
+ lhs.test(buf)
+ ~uint8 lab = bs.end_label()
+ buf`.add_c(" je \0")
+ buf`.add_c(lab)
+ buf`.add_c("\n\0")
+ ;; else if (op{1} == '|')
+ lhs.test(buf)
+ ~uint8 lab = bs.end_label()
+ buf`.add_c(" jne \0")
+ buf`.add_c(lab)
+ buf`.add_c("\n\0")
+ ;; else if (op{1} == '^')
+ /; if (lhs.loc > 0 && lhs.loc < 11)
+ /; if (s`.is_tmp(~lhs) == false)
+ bool was_ref = false
+ /; if (lhs.is_ref() == true)
+ was_ref = true
+ int32 ptr = 0
+ ptr = ptr - 1
+ lhs.ptr_pop()
+ lhs.ptr_push(ptr)
+ ;/
+
+ Var tmp = s`.mk_tmp(~lhs)
+
+ tmp.set(s`.cb, ~lhs)
+ lhs.end()
+ lhs = tmp
+
+ /; if (was_ref == true)
+ lhs.ptr_pop()
+ lhs.ptr_push(0)
+ ;/
+ ;/
+ ;/
+ ;/
+
+ # Compute right hand side
+ Var rhs = self._compile_value(s, rhn)
+
+ /; if (rhs.is_struct() == true)
+ _printf("Can not use struct as boolean value\n\0")
+ lhs.end()
+ rhs.end()
+ bs.end()
+ return out
+ ;/
+
+ # Post compare or test for this particular bool op
+ /; if (op{1} == '^')
+ # Mov lhs to a register
+ bool is_ref = lhs.is_ref()
+ /; if (lhs.loc < 1 || is_ref == true)
+ Var tmp = lhs.copy()
+ tmp.strip_refs()
+ tmp.loc = 3
+ tmp.offset = 0
+ tmp.set(s`.cb, ~lhs)
+ lhs.end()
+ lhs = tmp
+ ;/
+
+ /; if (op{0} == '!')
+ out.cmov(s`.cb, ~lhs, ~rhs, "e\0")
+ ;; else
+ out.cmov(s`.cb, ~lhs, ~rhs, "e\0")
+ ;/
+ ;; else
+ rhs.test(buf)
+ bs.place_end_label()
+ /; if (op{0} == '!')
+ out.cset(buf, "e\0")
+ ;; else
+ out.cset(buf, "ne\0")
+ ;/
+ ;/
+
+ lhs.end()
+ rhs.end()
+ s`.free_after(~out, true)
+ bs.end()
+ return out
+ ;/
+
+ /; _compile_cmp_op (~Scope s, ~parse.Node n) [Var]
+ ~parse.Node lhn = n`.sub.get(0)
+ ~parse.Node rhn = n`.sub.get(1)
+
+ # Setup output
+ ~Struct t = self._find_literal_type(s, "bool\0")
+ Var dummy
+ dummy._init(t)
+ Var out = s`.mk_tmp(~dummy)
+ dummy.end()
+
+ # Compute left hand side
+ Var lhs = self._compile_value(s, lhn)
+ /; if (s`.is_tmp(~lhs) == true)
+ s`.free_after(~lhs, true)
+ ;/
+
+ # TODO: move lhs maybe if it is in rdi
+ /; if (lhs.loc > 0 && lhs.loc < 11)
+ /; if (s`.is_tmp(~lhs) == false)
+ bool was_ref = false
+ /; if (lhs.is_ref() == true)
+ was_ref = true
+ int32 ptr = 0
+ ptr = ptr - 1
+ lhs.ptr_pop()
+ lhs.ptr_push(ptr)
+ ;/
+
+ Var tmp = s`.mk_tmp(~lhs)
+
+ tmp.set(s`.cb, ~lhs)
+ lhs.end()
+ lhs = tmp
+
+ /; if (was_ref == true)
+ lhs.ptr_pop()
+ lhs.ptr_push(0)
+ ;/
+ ;/
+ ;/
+
+ # Compute right hand side
+ Var rhs = self._compile_value(s, rhn)
+
+ # Check not structs
+ /; if (lhs.is_struct() == true || rhs.is_struct() == true)
+ _printf("Can not compare structs in this version of tnsl\n\0")
+ lhs.end()
+ rhs.end()
+ s`.free_after(~out, true)
+ return out
+ ;/
+
+ # Mov lhs to a register
+ bool is_ref = lhs.is_ref()
+ /; if (lhs.loc < 1 || is_ref == true)
+ Var tmp = lhs.copy()
+ tmp.strip_refs()
+ tmp.loc = 3
+ tmp.offset = 0
+ tmp.set(s`.cb, ~lhs)
+ lhs.end()
+ lhs = tmp
+ ;/
+
+ # Do comparitive move
+ /; if (utils.strcmp(n`.data, "==\0") == true)
+ out.cmov(s`.cb, ~lhs, ~rhs, "e\0")
+ ;; else if (utils.strcmp(n`.data, "<\0") == true)
+ out.cmov(s`.cb, ~lhs, ~rhs, "l\0")
+ ;; else if (utils.strcmp(n`.data, ">\0") == true)
+ out.cmov(s`.cb, ~lhs, ~rhs, "g\0")
+ ;; else if (utils.strcmp(n`.data, "!==\0") == true)
+ out.cmov(s`.cb, ~lhs, ~rhs, "ne\0")
+ ;; else if (utils.strcmp(n`.data, "!<\0") == true)
+ out.cmov(s`.cb, ~lhs, ~rhs, "nl\0")
+ ;; else if (utils.strcmp(n`.data, "!>\0") == true)
+ out.cmov(s`.cb, ~lhs, ~rhs, "ng\0")
+ ;; else if (utils.strcmp(n`.data, "<==\0") == true)
+ out.cmov(s`.cb, ~lhs, ~rhs, "le\0")
+ ;; else if (utils.strcmp(n`.data, ">==\0") == true)
+ out.cmov(s`.cb, ~lhs, ~rhs, "ge\0")
+ ;/
+
+ lhs.end()
+ rhs.end()
+ s`.free_after(~out, true)
+ return out
+ ;/
+
/; _compile_bin (~Scope s, ~parse.Node n) [Var]
# TODO
/; if (utils.strcmp(n`.data, ".\0") == true)
return self._compile_chain(s, n)
+ ;; else if (parse._in_csv(BOOL_OPS, n`.data) == true)
+ return self._compile_bool_op(s, n)
+ ;; else if (parse._in_csv(CMP_OPS, n`.data) == true)
+ return self._compile_cmp_op(s, n)
;/
~parse.Node lhn = n`.sub.get(0)
diff --git a/tnslc/compile/var.tnsl b/tnslc/compile/var.tnsl
index 122233a..5f87cc7 100644
--- a/tnslc/compile/var.tnsl
+++ b/tnslc/compile/var.tnsl
@@ -1662,6 +1662,8 @@ struct Var {
self._unary(buf, "dec\0")
;/
+ # Boolean related
+
/; test (~CompBuf buf)
~uint8 to_str = self._set_prim_l(buf)
buf`.add_c(" cmp \0")
@@ -1682,6 +1684,63 @@ struct Var {
_delete(to_str)
;/
+ /; cmov (~CompBuf buf, ~Var a, ~Var b, ~uint8 cc)
+
+ buf`.add_c(" cmp \0")
+ ~uint8 a_str = a`._set_prim_l(buf)
+ buf`.add_c(a_str)
+ _delete(a_str)
+ buf`.add_c(", \0")
+ ~uint8 b_str = b`._set_prim_r(buf, a)
+ buf`.add_c(b_str)
+ _delete(b_str)
+ buf`.add_c("\n\0")
+
+ buf`.add_c(" mov ax, 0\n\0")
+ buf`.add_c(" mov cx, 1\n\0")
+ buf`.add_c(" cmov\0")
+ buf`.add_c(cc)
+ buf`.add_c(" ax, cx ; Compare set\n\0")
+
+ ~uint8 to_str = self._set_prim_l(buf)
+
+ Var ax = self.copy()
+ ax.loc = 1
+
+ buf`.add_c(" mov \0")
+ ~uint8 to_str = self._set_prim_l(buf)
+ buf`.add_c(to_str)
+ _delete(to_str)
+ buf`.add_c(", \0")
+ ~uint8 ax_str = ax._set_prim_r(buf, ~self)
+ buf`.add_c(ax_str)
+ _delete(ax_str)
+ buf`.add_c(" ; Mov after compare\n\0")
+ ;/
+
+ /; cset (~CompBuf buf, ~uint8 cc)
+ buf`.add_c(" mov ax, 0\n\0")
+ buf`.add_c(" mov cx, 1\n\0")
+ buf`.add_c(" cmov\0")
+ buf`.add_c(cc)
+ buf`.add_c(" ax, cx ; Compare set\n\0")
+
+ ~uint8 to_str = self._set_prim_l(buf)
+
+ Var ax = self.copy()
+ ax.loc = 1
+
+ buf`.add_c(" mov \0")
+ ~uint8 to_str = self._set_prim_l(buf)
+ buf`.add_c(to_str)scope
+ _delete(to_str)
+ buf`.add_c(", \0")
+ ~uint8 ax_str = ax._set_prim_r(buf, ~self)
+ buf`.add_c(ax_str)
+ _delete(ax_str)
+ buf`.add_c(" ; Mov after compare\n\0")
+ ;/
+
/; member (~CompBuf buf, ~uint8 name) [Var]
/; if (self.is_struct() == false)
_printf("ERROR: Attempted to get a member named \"\0")
diff --git a/tnslc/test.tnsl b/tnslc/test.tnsl
index 715ddf2..896897e 100644
--- a/tnslc/test.tnsl
+++ b/tnslc/test.tnsl
@@ -1,19 +1,16 @@
-struct A {
- int a, b
-}
-
-/; method A
- /; add_one
- int a = self.a + 1
- ;/
+/; five [int]
+ return 5
;/
/; main (int argc, ~~uint8 argv) [int]
- A a
- a.a = 1
- a.b = 2
- a.add_one()
- return a.a + a.b
-;/
+ # Mov input from C
+ asm "mov r10, rdi"
+ asm "mov r11, rsi"
+ /; if (argc < 5 && argc > 1)
+ return argc
+ ;/
+
+ return five()
+;/