Ambrose Bonnaire-Sergeant: 1 Support rshift, lshift, band, bxor, fix bnot 7 files changed, 107 insertions(+), 34 deletions(-)
Copy & paste the following snippet into your terminal to import this patchset into git:
curl -s https://lists.sr.ht/~technomancy/fennel/patches/39700/mbox | git am -3Learn more about email & git
I can't seem to use fnlfmt correctly, or run `make test` successfully, so the work is not entirely done.
Thanks for adding this! The original parser we just lifted straight from a different project which only had LuaJIT support and I always wanted to come back and update it for newer features but hadn't gotten around to it. It looks like the test issue is my bad; some of the fnlfmt changes are one-lining things they shouldn't, and it somehow got overlooked when the original change happened, so it's not your fault. I'll go ahead and apply the patch and come back to the weird tests later since the failures are unrelated to your change. thanks again! -Phil
--- README.md | 3 ++ anticompiler.fnl | 8 +++-- lang/lexer.lua | 23 +++++++++++++-- lang/operator.lua | 8 +++-- lang/parser.lua | 2 +- test.lua | 22 ++++++++++++++ test_expected.fnl | 75 ++++++++++++++++++++++++++++++++--------------- 7 files changed, 107 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 081d390..0e1ca87 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,9 @@ The Antifennel compiler assumes its input file is valid Lua 5.1; it does not attempt to give good error messages when provided with files that won't parse or support newer features of Lua. +Antifennel supports all [bitwise operators](https://www.lua.org/manual/5.3/manual.html#3.4.2) +introduced in Lua 5.3. + Antifennel will never emit variadic operators, hashfns, or pattern matches, even in cases that would result in much better code. diff --git a/anticompiler.fnl b/anticompiler.fnl index 49ef239..66cdf4f 100644 --- a/anticompiler.fnl +++ b/anticompiler.fnl @@ -115,14 +115,16 @@ (.. "return " (table.concat (map args view) ", ")))))) (fn binary [compile scope {: left : right : operator} ast] - (let [operators {:== := "~=" :not= "#" :length "~" :bnot}] + (let [operators {:== := "~=" :not= "#" :length "~" :bxor + :<< :lshift :>> :rshift :& :band :| :bor}] (list (sym (or (. operators operator) operator)) (compile scope left) (compile scope right)))) (fn unary [compile scope {: argument : operator} ast] - (list (sym operator) - (compile scope argument))) + (let [operators {"~" :bnot}] + (list (sym (or (. operators operator) operator)) + (compile scope argument)))) (fn call [compile scope {: arguments : callee}] (list (compile scope callee) (unpack (map arguments (partial compile scope))))) diff --git a/lang/lexer.lua b/lang/lexer.lua index 444b364..aef60dd 100644 --- a/lang/lexer.lua +++ b/lang/lexer.lua @@ -14,7 +14,8 @@ local ReservedKeyword = {['and'] = 1, ['break'] = 2, ['do'] = 3, ['else'] = 4, [ local uint64, int64 = ffi.typeof('uint64_t'), ffi.typeof('int64_t') local complex = ffi.typeof('complex') -local TokenSymbol = { TK_ge = '>=', TK_le = '<=' , TK_concat = '..', TK_eq = '==', TK_ne = '~=', TK_eof = '<eof>' } +local TokenSymbol = { TK_ge = '>=', TK_le = '<=' , TK_concat = '..', TK_eq = '==', TK_ne = '~=', TK_eof = '<eof>', + TK_shl = '<<', TK_shr = '>>' } local function token2str(tok) if string.match(tok, "^TK_") then @@ -422,10 +423,26 @@ local function llex(ls) if ls.current ~= '=' then return '=' else nextchar(ls); return 'TK_eq' end elseif current == '<' then nextchar(ls) - if ls.current ~= '=' then return '<' else nextchar(ls); return 'TK_le' end + if ls.current == '=' then + nextchar(ls); + return 'TK_le' + elseif ls.current == '<' then + nextchar(ls); + return 'TK_shl' + else + return '<' + end elseif current == '>' then nextchar(ls) - if ls.current ~= '=' then return '>' else nextchar(ls); return 'TK_ge' end + if ls.current == '=' then + nextchar(ls); + return 'TK_ge' + elseif ls.current == '>' then + nextchar(ls); + return 'TK_shr' + else + return '>' + end elseif current == '~' then nextchar(ls) if ls.current ~= '=' then return '~' else nextchar(ls); return 'TK_ne' end diff --git a/lang/operator.lua b/lang/operator.lua index b80717a..616935e 100644 --- a/lang/operator.lua +++ b/lang/operator.lua @@ -2,14 +2,16 @@ -- (left priority) * 256 + (right priority) -- modulus is your friend local binop = { - ['+'] = 6 * 256 + 6, ['-'] = 6 * 256 + 6, ['*'] = 7 * 256 + 7, ['/'] = 7 * 256 + 7, ['%'] = 7 * 256 + 7, - ['^'] = 10* 256 + 9, ['..'] = 5 * 256 + 4, -- POW CONCAT (right associative) + ['+'] = 9 * 256 + 9, ['-'] = 9 * 256 + 9, ['*'] = 10 * 256 + 10, ['/'] = 10 * 256 + 10, ['%'] = 10 * 256 + 10, + ['^'] = 13* 256 +12, ['..'] = 8 * 256 + 7, -- POW CONCAT (right associative) + ['<<'] = 7 * 256 + 7, ['>>'] = 7 * 256 + 7, + ['&'] = 6 * 256 + 6, ['~'] = 5 * 256 + 5, ['|'] = 4 * 256 + 4, ['=='] = 3 * 256 + 3, ['~='] = 3 * 256 + 3, ['<'] = 3 * 256 + 3, ['>='] = 3 * 256 + 3, ['>'] = 3 * 256 + 3, ['<='] = 3 * 256 + 3, ['and']= 2 * 256 + 2, ['or'] = 1 * 256 + 1, } -local unary_priority = 8 +local unary_priority = 12 -- Pseudo priority of a simple identifier. Should be higher than any -- others operator's priority. diff --git a/lang/parser.lua b/lang/parser.lua index 6a468e8..0afb481 100644 --- a/lang/parser.lua +++ b/lang/parser.lua @@ -139,7 +139,7 @@ end function expr_unop(ast, ls) local tk = ls.token - if tk == 'TK_not' or tk == '-' or tk == '#' then + if tk == 'TK_not' or tk == '-' or tk == '#' or tk == '~' then local line = ls.linenumber ls:next() local v = expr_binop(ast, ls, operator.unary_priority) diff --git a/test.lua b/test.lua index fc56fd1..718c456 100644 --- a/test.lua +++ b/test.lua @@ -101,4 +101,26 @@ do local isolated = 9 end +assert ((50 >> 1) == 25) +assert ((1 << 2) == 4) +assert ((50 & 25) == 16) +assert ((1 ~ 2) == 3) +assert ((1 | 6) == 7) +assert ((#{1} | 6) == 7) +assert ((100 | 99 >> 2 << 1) == 116) +assert ((100 | (99 >> 2) << 1) == 116) +assert ((((100 | 99) >> 2) << 1) == 50) +assert (((100 | (99 >> 2)) << 1) == 248) +assert ((100 | (99 >> (2 << 1))) == 102) +assert (59 >> 2 << 127 == 0) +assert ((59 >> 2) << 127 == 0) +assert (59 >> (2 << 127) == 59) +assert (50 >> 2 >> 1 == 6) +assert ((50 >> 2) >> 1 == 6) +assert (50 >> (2 >> 1) == 25) +assert ((59 >> 2) << 127 == 0) +assert (59 >> (2 << 127) == 59) +assert ((~ 1) == -2) +assert ((1 + (~ 1)) == -1) + return (f123("path") or {"a", "b", "c"}).mode diff --git a/test_expected.fnl b/test_expected.fnl index f40e46c..b707e53 100644 --- a/test_expected.fnl +++ b/test_expected.fnl @@ -11,8 +11,7 @@ (: :abcdef :match :abc) -(local t {:t2 {:f (fn [x] - x)}}) +(local t {:t2 {:f (fn [x] x)}}) (: (. t :t2) :f) @@ -23,10 +22,7 @@ (noprint (.. (or base "") "_" append "_")) -(fn f [x y] - (var (z zz) (values 9 8)) - (local b 99) - (set-forcibly! x 5) +(fn f [x y] (var (z zz) (values 9 8)) (local b 99) (set-forcibly! x 5) (set z 0) (global a 1) (set y.y false)) @@ -42,14 +38,10 @@ y 20] (+ x y))) -(noprint ((fn [] - (let [x 1] - x)))) +(noprint ((fn [] (let [x 1] x)))) (fn f123 [/_1] - (let [/_0 :zero] - (noprint (.. /_0 /_1)) - (values {} 2 3))) + (let [/_0 :zero] (noprint (.. /_0 /_1)) (values {} 2 3))) (fn bcd [...] (let [t {1 :bcd 2 ... :a :value}] @@ -71,24 +63,19 @@ (fn early-returns [some-var] (when true - (let [___antifnl_rtn_1___ some-var] - (lua "return ___antifnl_rtn_1___"))) + (let [___antifnl_rtn_1___ some-var] (lua "return ___antifnl_rtn_1___"))) nil) (local early-result (early-returns :success)) (assert (= early-result :success) early-result) -(for [outer 1 10] - (for [inner 1 10 2] - (noprint outer inner))) +(for [outer 1 10] (for [inner 1 10 2] (noprint outer inner))) -(fn dynamic-step [] - 3) +(fn dynamic-step [] 3) (for [dynamic 1 2 (dynamic-step)] - (for [unnecessary-step 1 10] - (noprint dynamic unnecessary-step))) + (for [unnecessary-step 1 10] (noprint dynamic unnecessary-step))) (print {1 1 2 2 :a 3}) @@ -96,8 +83,48 @@ (set (chr src.line src.from-macro?) (values filename line true)) -(let [isolated 9] - nil) +(let [isolated 9] nil) -(. (or (f123 :path) [:a :b :c]) :mode) +(assert (= (rshift 50 1) 25)) + +(assert (= (lshift 1 2) 4)) + +(assert (= (band 50 25) 16)) + +(assert (= (bxor 1 2) 3)) + +(assert (= (bor 1 6) 7)) + +(assert (= (bor (length [1]) 6) 7)) + +(assert (= (bor 100 (lshift (rshift 99 2) 1)) 116)) + +(assert (= (bor 100 (lshift (rshift 99 2) 1)) 116)) + +(assert (= (lshift (rshift (bor 100 99) 2) 1) 50)) + +(assert (= (lshift (bor 100 (rshift 99 2)) 1) 248)) + +(assert (= (bor 100 (rshift 99 (lshift 2 1))) 102)) +(assert (= (lshift (rshift 59 2) 127) 0)) + +(assert (= (lshift (rshift 59 2) 127) 0)) + +(assert (= (rshift 59 (lshift 2 127)) 59)) + +(assert (= (rshift (rshift 50 2) 1) 6)) + +(assert (= (rshift (rshift 50 2) 1) 6)) + +(assert (= (rshift 50 (rshift 2 1)) 25)) + +(assert (= (lshift (rshift 59 2) 127) 0)) + +(assert (= (rshift 59 (lshift 2 127)) 59)) + +(assert (= (bnot 1) (- 2))) + +(assert (= (+ 1 (bnot 1)) (- 1))) + +(. (or (f123 :path) [:a :b :c]) :mode) -- 2.37.1 (Apple Git-137.1)
Ambrose Bonnaire-Sergeant <abonnairesergeant@gmail.com> writes: