~technomancy/fennel

[PATCH 2/2] Special case allowance of ~= as the only allowed symbol with ~

Details
Message ID
<20190901161427.29654-3-phil@hagelb.org>
DKIM signature
missing
Download raw message
Patch: +7 -2
This allows us to retain backwards compatibility but still reserves ~
for future use by the compiler.
---
 changelog.md | 1 -
 fennel.lua   | 7 ++++++-
 test.lua     | 1 +
 3 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/changelog.md b/changelog.md
index e34b03e..0e363c9 100644
--- a/changelog.md
+++ b/changelog.md
@@ -17,7 +17,6 @@
 * Alias `#` special with `length`
 * Replace `@` (unquote) with `,`; comma is **no longer** whitespace
 * **Disallow** `~` in symbols
-* **Remove** `~=` special; use `not=` instead
 * Add `hashfn` and `#` reader macro for shorthand functions like `#(+ $1 $2)`
 * Add `macro` to make defining a single macro easier
 * Add `(comment)` special which emits a Lua comment in the generated source
diff --git a/fennel.lua b/fennel.lua
index 00a970b..969b6e6 100644
--- a/fennel.lua
+++ b/fennel.lua
@@ -361,7 +361,7 @@ local function parser(getbyte, filename)
                     end
                 end
                 ungetb(nextb)
-            elseif issymbolchar(b) then -- Try symbol
+            elseif issymbolchar(b) or b == string.byte("~") then -- Try symbol
                 local chars = {}
                 local bytestart = byteindex
                 repeat
@@ -375,6 +375,10 @@ local function parser(getbyte, filename)
                 elseif rawstr == '...' then dispatch(VARARG)
                 elseif rawstr:match('^:.+$') then -- keyword style strings
                     dispatch(rawstr:sub(2))
+                elseif rawstr:match("^~") and rawstr ~= "~=" then
+                    -- for backwards-compatibility, special-case allowance of ~=
+                    -- but all other uses of ~ are disallowed
+                    parseError("illegal character: ~")
                 else
                     local forceNumber = rawstr:match('^%d')
                     local numberWithStrippedUnderscores = rawstr:gsub("_", "")
@@ -1709,6 +1713,7 @@ defineComparatorSpecial('>=')
 defineComparatorSpecial('<=')
 defineComparatorSpecial('=', '==')
 defineComparatorSpecial('not=', '~=', 'or')
+SPECIALS["~="] = SPECIALS["not="] -- backwards-compatibility alias
 
 local function defineUnarySpecial(op, realop)
     SPECIALS[op] = function(ast, scope, parent)
diff --git a/test.lua b/test.lua
index c148b47..39cd7f0 100644
--- a/test.lua
+++ b/test.lua
@@ -56,6 +56,7 @@ local cases = {
         ["(>= 22 (+ 21 1))"]=true,
         ["(<= 88 32)"]=false,
         ["(not= 33 1)"]=true,
+        ["(~= 33 1)"]=true, -- undocumented alias for backwards-compatibility
         ["(= 1 1 2 2)"]=false,
         ["(not= 6 6 9)"]=true,
         ["(let [f (fn [] (tset tbl :dbl (+ 1 (or (. tbl :dbl) 0))) 1)]\
-- 
2.11.0