aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile5
-rw-r--r--README.md2
-rw-r--r--bitops.lua123
-rw-r--r--bitops.moon44
-rw-r--r--compatibility/3.7.nom30
-rw-r--r--containers.lua240
-rw-r--r--containers.moon99
-rw-r--r--core/collections.nom78
-rw-r--r--core/metaprogramming.nom2
-rw-r--r--core/operators.nom6
-rw-r--r--core/text.nom4
-rw-r--r--lib/file_hash.nom37
-rw-r--r--nomsu_compiler.lua105
-rw-r--r--nomsu_compiler.moon52
14 files changed, 638 insertions, 189 deletions
diff --git a/Makefile b/Makefile
index 29b3737..a28a030 100644
--- a/Makefile
+++ b/Makefile
@@ -10,9 +10,10 @@ PREFIX=
UNINSTALL_VERSION=
# ========= You shouldn't need to mess with any of these variables below ================
-MOON_FILES= code_obj.moon error_handling.moon files.moon nomsu.moon nomsu_compiler.moon syntax_tree.moon parser.moon
+MOON_FILES= code_obj.moon error_handling.moon files.moon nomsu.moon nomsu_compiler.moon \
+ syntax_tree.moon parser.moon containers.moon
LUA_FILES= code_obj.lua consolecolors.lua error_handling.lua files.lua nomsu.lua nomsu_compiler.lua \
- syntax_tree.lua parser.lua utils.lua uuid.lua
+ syntax_tree.lua parser.lua containers.lua utils.lua uuid.lua
CORE_NOM_FILES= $(wildcard core/*.nom)
CORE_LUA_FILES= $(patsubst %.nom,%.lua,$(CORE_NOM_FILES))
LIB_NOM_FILES= $(wildcard lib/*.nom)
diff --git a/README.md b/README.md
index 877877b..1f561eb 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@ revolving around natural language rule-making and self modification.
## Dependencies
-Nomsu's only dependencies are [Lua 5.2+](https://www.lua.org/) or [Luajit 2.0+](http://luajit.org/) and [LPEG](http://www.inf.puc-rio.br/~roberto/lpeg/) (`luarocks install lpeg`). Nomsu's compiler was written in [Moonscript](http://moonscript.org/), but all of the .moon files have been compiled into lua for convenience, so Moonscript is not a dependency. Optionally, if luafilesystem ([Lua version](https://github.com/keplerproject/luafilesystem) or [LuaJIT version](https://github.com/spacewander/luafilesystem)) is installed, it will be used. Otherwise Nomsu will fall back to using system commands (`find` and `ls`), which is slower and a bit less safe. Nomsu has been tested on Mac and Linux, but not Windows.
+Nomsu's only dependencies are [Lua 5.2+](https://www.lua.org/) (or [Luajit 2.0+](http://luajit.org/), compiled with `XCFLAGS=-DLUAJIT_ENABLE_LUA52COMPAT` for Lua 5.2 compatibility) and [LPEG](http://www.inf.puc-rio.br/~roberto/lpeg/) (`luarocks install lpeg`). Nomsu's compiler was written in [Moonscript](http://moonscript.org/), but all of the .moon files have been compiled into lua for convenience, so Moonscript is not a dependency. Optionally, if luafilesystem ([Lua version](https://github.com/keplerproject/luafilesystem) or [LuaJIT version](https://github.com/spacewander/luafilesystem)) is installed, it will be used. Otherwise Nomsu will fall back to using system commands (`find` and `ls`), which is slower and a bit less safe. Nomsu has been tested on Mac and Linux, but not Windows.
## Usage
diff --git a/bitops.lua b/bitops.lua
new file mode 100644
index 0000000..f87be64
--- /dev/null
+++ b/bitops.lua
@@ -0,0 +1,123 @@
+local bitlib
+if jit then
+ bitlib = require('bit')
+elseif _VERSION == "Lua 5.2" then
+ bitlib = bit32
+else
+ bitlib = error("no bit library for Lua 5.3+")
+end
+local ret
+do
+ local _tbl_0 = { }
+ for k, v in pairs(bitlib) do
+ _tbl_0[k] = v
+ end
+ ret = _tbl_0
+end
+ret.bnot = function(x)
+ do
+ local mt = getmetatable(x)
+ if mt then
+ if mt.__bnot then
+ return mt.__bnot(x)
+ end
+ end
+ end
+ return bitlib.bnot(x)
+end
+ret.band = function(x, y)
+ do
+ local mt_x = getmetatable(x)
+ if mt_x then
+ if mt_x.__band then
+ return mt_x.__band(x, y)
+ end
+ end
+ end
+ do
+ local mt_y = getmetatable(x)
+ if mt_y then
+ if mt_y.__band then
+ return mt_y.__band(x, y)
+ end
+ end
+ end
+ return bitlib.band(x, y)
+end
+ret.bor = function(x, y)
+ do
+ local mt_x = getmetatable(x)
+ if mt_x then
+ if mt_x.__bor then
+ return mt_x.__bor(x, y)
+ end
+ end
+ end
+ do
+ local mt_y = getmetatable(x)
+ if mt_y then
+ if mt_y.__bor then
+ return mt_y.__bor(x, y)
+ end
+ end
+ end
+ return bitlib.bor(x, y)
+end
+ret.bxor = function(x, y)
+ do
+ local mt_x = getmetatable(x)
+ if mt_x then
+ if mt_x.__bxor then
+ return mt_x.__bxor(x, y)
+ end
+ end
+ end
+ do
+ local mt_y = getmetatable(x)
+ if mt_y then
+ if mt_y.__bxor then
+ return mt_y.__bxor(x, y)
+ end
+ end
+ end
+ return bitlib.bxor(x, y)
+end
+ret.lshift = function(x, y)
+ do
+ local mt_x = getmetatable(x)
+ if mt_x then
+ if mt_x.__shl then
+ return mt_x.__shl(x, y)
+ end
+ end
+ end
+ do
+ local mt_y = getmetatable(x)
+ if mt_y then
+ if mt_y.__shl then
+ return mt_y.__shl(x, y)
+ end
+ end
+ end
+ return bitlib.lshift(x, y)
+end
+ret.rshift = function(x, y)
+ do
+ local mt_x = getmetatable(x)
+ if mt_x then
+ if mt_x.__shr then
+ return mt_x.__shr(x, y)
+ end
+ end
+ end
+ do
+ local mt_y = getmetatable(x)
+ if mt_y then
+ if mt_y.__shr then
+ return mt_y.__shr(x, y)
+ end
+ end
+ end
+ return bitlib.rshift(x, y)
+end
+return ret
diff --git a/bitops.moon b/bitops.moon
new file mode 100644
index 0000000..27752eb
--- /dev/null
+++ b/bitops.moon
@@ -0,0 +1,44 @@
+-- This file defines wrapper functions around the Lua 5.2/LuaJIT bitwise operators
+-- The wrapper functions check for the appropriate metatable functions like
+-- "__bxor" for bit.bxor(), etc.
+bitlib = if jit then require('bit')
+elseif _VERSION == "Lua 5.2" bit32
+else error("no bit library for Lua 5.3+")
+
+ret = {k,v for k,v in pairs(bitlib)}
+ret.bnot = (x)->
+ if mt = getmetatable(x)
+ if mt.__bnot then return mt.__bnot(x)
+ return bitlib.bnot(x)
+ret.band = (x,y)->
+ if mt_x = getmetatable(x)
+ if mt_x.__band then return mt_x.__band(x, y)
+ if mt_y = getmetatable(x)
+ if mt_y.__band then return mt_y.__band(x, y)
+ return bitlib.band(x, y)
+ret.bor = (x,y)->
+ if mt_x = getmetatable(x)
+ if mt_x.__bor then return mt_x.__bor(x, y)
+ if mt_y = getmetatable(x)
+ if mt_y.__bor then return mt_y.__bor(x, y)
+ return bitlib.bor(x, y)
+ret.bxor = (x,y)->
+ if mt_x = getmetatable(x)
+ if mt_x.__bxor then return mt_x.__bxor(x, y)
+ if mt_y = getmetatable(x)
+ if mt_y.__bxor then return mt_y.__bxor(x, y)
+ return bitlib.bxor(x, y)
+ret.lshift = (x,y)->
+ if mt_x = getmetatable(x)
+ if mt_x.__shl then return mt_x.__shl(x, y)
+ if mt_y = getmetatable(x)
+ if mt_y.__shl then return mt_y.__shl(x, y)
+ return bitlib.lshift(x, y)
+ret.rshift = (x,y)->
+ if mt_x = getmetatable(x)
+ if mt_x.__shr then return mt_x.__shr(x, y)
+ if mt_y = getmetatable(x)
+ if mt_y.__shr then return mt_y.__shr(x, y)
+ return bitlib.rshift(x, y)
+
+return ret
diff --git a/compatibility/3.7.nom b/compatibility/3.7.nom
new file mode 100644
index 0000000..1980f92
--- /dev/null
+++ b/compatibility/3.7.nom
@@ -0,0 +1,30 @@
+#!/usr/bin/env nomsu -V3.6.5.6
+#
+ This file defines upgrades from Nomsu <3.7 to 3.7
+
+use "compatibility/compatibility.nom"
+
+# Indexing
+upgrade action [%index st to last in %list] to "3.7" as (%list::%index st to last)
+upgrade action [%index nd to last in %list] to "3.7" as (%list::%index nd to last)
+upgrade action [%index rd to last in %list] to "3.7" as (%list::%index rd to last)
+upgrade action [%index th to last in %list] to "3.7" as (%list::%index rd th last)
+upgrade action [last in %list] to "3.7" (%list::last)
+upgrade action [first in %list] to "3.7" (%list::first)
+upgrade action [%item is in %list, %list contains %item, %list has %item] to "3.7" as (..)
+ %list::has %item
+
+upgrade action [..]
+ %item isn't in %list, %item is not in %list, %list doesn't contain %item
+ %list does not contain %item, %list doesn't have %item, %list does not have %item
+..to "3.7" as (not (%list::has %item))
+
+upgrade action [%list has key %index, %list has index %index] to "3.7" as (%list.%index != (nil))
+upgrade action [..]
+ %list doesn't have key %index, %list does not have key %index
+ %list doesn't have index %index, %list does not have index %index
+..to "3.7" as (%list.%index == (nil))
+
+upgrade action [..]
+ number of keys in %list, len %list, || %list ||, length %list, length of %list
+..to "3.7" as (size of %list)
diff --git a/containers.lua b/containers.lua
new file mode 100644
index 0000000..09de4e5
--- /dev/null
+++ b/containers.lua
@@ -0,0 +1,240 @@
+local insert, remove, concat
+do
+ local _obj_0 = table
+ insert, remove, concat = _obj_0.insert, _obj_0.remove, _obj_0.concat
+end
+local repr, stringify, equivalent, nth_to_last, size
+do
+ local _obj_0 = require('utils')
+ repr, stringify, equivalent, nth_to_last, size = _obj_0.repr, _obj_0.stringify, _obj_0.equivalent, _obj_0.nth_to_last, _obj_0.size
+end
+local list, dict
+local _list_mt = {
+ __eq = equivalent,
+ __tostring = function(self)
+ return "[" .. concat((function()
+ local _accum_0 = { }
+ local _len_0 = 1
+ for _index_0 = 1, #self do
+ local b = self[_index_0]
+ _accum_0[_len_0] = repr(b)
+ _len_0 = _len_0 + 1
+ end
+ return _accum_0
+ end)(), ", ") .. "]"
+ end,
+ __lt = function(self, other)
+ assert(type(self) == 'table' and type(other) == 'table', "Incompatible types for comparison")
+ for i = 1, math.max(#self, #other) do
+ if not self[i] and other[i] then
+ return true
+ elseif self[i] and not other[i] then
+ return false
+ elseif self[i] < other[i] then
+ return true
+ elseif self[i] > other[i] then
+ return false
+ end
+ end
+ return false
+ end,
+ __le = function(self, other)
+ assert(type(self) == 'table' and type(other) == 'table', "Incompatible types for comparison")
+ for i = 1, math.max(#self, #other) do
+ if not self[i] and other[i] then
+ return true
+ elseif self[i] and not other[i] then
+ return false
+ elseif self[i] < other[i] then
+ return true
+ elseif self[i] > other[i] then
+ return false
+ end
+ end
+ return true
+ end,
+ __add = function(self, other)
+ local ret = list((function()
+ local _accum_0 = { }
+ local _len_0 = 1
+ for _index_0 = 1, #self do
+ local x = self[_index_0]
+ _accum_0[_len_0] = x
+ _len_0 = _len_0 + 1
+ end
+ return _accum_0
+ end)())
+ for _index_0 = 1, #other do
+ local x = other[_index_0]
+ insert(ret, x)
+ end
+ return ret
+ end,
+ __index = {
+ add_1 = insert,
+ append_1 = insert,
+ add_1_at_index_2 = function(t, x, i)
+ return insert(t, i, x)
+ end,
+ at_index_1_add_2 = insert,
+ pop = remove,
+ remove_last = remove,
+ remove_index_1 = remove,
+ last = (function(self)
+ return self[#self]
+ end),
+ first = (function(self)
+ return self[1]
+ end),
+ _1_st_to_last = nth_to_last,
+ _1_nd_to_last = nth_to_last,
+ _1_rd_to_last = nth_to_last,
+ _1_th_to_last = nth_to_last,
+ has_1 = function(self, item)
+ for _index_0 = 1, #self do
+ local x = self[_index_0]
+ if x == item then
+ return true
+ end
+ end
+ return false
+ end,
+ index_of_1 = function(self, item)
+ for i, x in ipairs(self) do
+ if x == item then
+ return i
+ end
+ end
+ return nil
+ end
+ }
+}
+list = function(t)
+ return setmetatable(t, _list_mt)
+end
+local walk_items
+walk_items = function(self, i)
+ i = i + 1
+ local k, v = next(self.table, self.key)
+ if k ~= nil then
+ self.key = k
+ return i, dict({
+ key = k,
+ value = v
+ })
+ end
+end
+local _dict_mt = {
+ __eq = equivalent,
+ __len = size,
+ __tostring = function(self)
+ return "{" .. concat((function()
+ local _accum_0 = { }
+ local _len_0 = 1
+ for k, v in pairs(self) do
+ _accum_0[_len_0] = tostring(repr(k)) .. ": " .. tostring(repr(v))
+ _len_0 = _len_0 + 1
+ end
+ return _accum_0
+ end)(), ", ") .. "}"
+ end,
+ __ipairs = function(self)
+ return walk_items, {
+ table = self,
+ key = nil
+ }, 0
+ end,
+ __band = function(self, other)
+ return dict((function()
+ local _tbl_0 = { }
+ for k, v in pairs(self) do
+ if other[k] ~= nil then
+ _tbl_0[k] = v
+ end
+ end
+ return _tbl_0
+ end)())
+ end,
+ __bor = function(self, other)
+ local ret
+ do
+ local _tbl_0 = { }
+ for k, v in pairs(self) do
+ _tbl_0[k] = v
+ end
+ ret = _tbl_0
+ end
+ for k, v in pairs(other) do
+ if ret[k] == nil then
+ ret[k] = v
+ end
+ end
+ return dict(ret)
+ end,
+ __bxor = function(self, other)
+ local ret
+ do
+ local _tbl_0 = { }
+ for k, v in pairs(self) do
+ _tbl_0[k] = v
+ end
+ ret = _tbl_0
+ end
+ for k, v in pairs(other) do
+ if ret[k] == nil then
+ ret[k] = v
+ else
+ ret[k] = nil
+ end
+ end
+ return dict(ret)
+ end,
+ __add = function(self, other)
+ local ret
+ do
+ local _tbl_0 = { }
+ for k, v in pairs(self) do
+ _tbl_0[k] = v
+ end
+ ret = _tbl_0
+ end
+ for k, v in pairs(other) do
+ if ret[k] == nil then
+ ret[k] = v
+ else
+ ret[k] = ret[k] + v
+ end
+ end
+ return dict(ret)
+ end,
+ __sub = function(self, other)
+ local ret
+ do
+ local _tbl_0 = { }
+ for k, v in pairs(self) do
+ _tbl_0[k] = v
+ end
+ ret = _tbl_0
+ end
+ for k, v in pairs(other) do
+ if ret[k] == nil then
+ ret[k] = -v
+ else
+ ret[k] = ret[k] - v
+ end
+ end
+ return dict(ret)
+ end
+}
+dict = function(t)
+ return setmetatable(t, _dict_mt)
+end
+for i, entry in ipairs(dict({
+ x = 99
+})) do
+ assert(i == 1 and entry.key == "x" and entry.value == 99, "ipairs compatibility issue")
+end
+return {
+ list = list,
+ dict = dict
+}
diff --git a/containers.moon b/containers.moon
new file mode 100644
index 0000000..deb5684
--- /dev/null
+++ b/containers.moon
@@ -0,0 +1,99 @@
+-- This file contains container classes, i.e. Lists, Dicts, and Sets
+{:insert,:remove,:concat} = table
+{:repr, :stringify, :equivalent, :nth_to_last, :size} = require 'utils'
+
+local list, dict
+
+-- List and Dict classes to provide basic equality/tostring functionality for the tables
+-- used in Nomsu. This way, they retain a notion of whether they were originally lists or dicts.
+_list_mt =
+ __eq:equivalent
+ -- Could consider adding a __newindex to enforce list-ness, but would hurt performance
+ __tostring: =>
+ "["..concat([repr(b) for b in *@], ", ").."]"
+ __lt: (other)=>
+ assert type(@) == 'table' and type(other) == 'table', "Incompatible types for comparison"
+ for i=1,math.max(#@, #other)
+ if not @[i] and other[i] then return true
+ elseif @[i] and not other[i] then return false
+ elseif @[i] < other[i] then return true
+ elseif @[i] > other[i] then return false
+ return false
+ __le: (other)=>
+ assert type(@) == 'table' and type(other) == 'table', "Incompatible types for comparison"
+ for i=1,math.max(#@, #other)
+ if not @[i] and other[i] then return true
+ elseif @[i] and not other[i] then return false
+ elseif @[i] < other[i] then return true
+ elseif @[i] > other[i] then return false
+ return true
+ __add: (other)=>
+ ret = list[x for x in *@]
+ for x in *other
+ insert(ret, x)
+ return ret
+ __index:
+ add_1: insert, append_1: insert
+ add_1_at_index_2: (t,x,i)-> insert(t,i,x)
+ at_index_1_add_2: insert
+ pop: remove, remove_last: remove, remove_index_1: remove
+ last: (=> @[#@]), first: (=> @[1])
+ _1_st_to_last:nth_to_last, _1_nd_to_last:nth_to_last
+ _1_rd_to_last:nth_to_last, _1_th_to_last:nth_to_last
+ has_1: (item)=>
+ for x in *@
+ if x == item
+ return true
+ return false
+ index_of_1: (item)=>
+ for i,x in ipairs @
+ if x == item
+ return i
+ return nil
+
+list = (t)-> setmetatable(t, _list_mt)
+
+walk_items = (i)=>
+ i = i + 1
+ k, v = next(@table, @key)
+ if k != nil
+ @key = k
+ return i, dict{key:k, value:v}
+
+_dict_mt =
+ __eq:equivalent
+ __len:size
+ __tostring: =>
+ "{"..concat(["#{repr(k)}: #{repr(v)}" for k,v in pairs @], ", ").."}"
+ __ipairs: => walk_items, {table:@, key:nil}, 0
+ __band: (other)=>
+ dict{k,v for k,v in pairs(@) when other[k] != nil}
+ __bor: (other)=>
+ ret = {k,v for k,v in pairs(@)}
+ for k,v in pairs(other)
+ if ret[k] == nil then ret[k] = v
+ return dict(ret)
+ __bxor: (other)=>
+ ret = {k,v for k,v in pairs(@)}
+ for k,v in pairs(other)
+ if ret[k] == nil then ret[k] = v
+ else ret[k] = nil
+ return dict(ret)
+ __add: (other)=>
+ ret = {k,v for k,v in pairs(@)}
+ for k,v in pairs(other)
+ if ret[k] == nil then ret[k] = v
+ else ret[k] += v
+ return dict(ret)
+ __sub: (other)=>
+ ret = {k,v for k,v in pairs(@)}
+ for k,v in pairs(other)
+ if ret[k] == nil then ret[k] = -v
+ else ret[k] -= v
+ return dict(ret)
+dict = (t)-> setmetatable(t, _dict_mt)
+
+for i,entry in ipairs(dict({x:99}))
+ assert(i == 1 and entry.key == "x" and entry.value == 99, "ipairs compatibility issue")
+
+return {:list, :dict}
diff --git a/core/collections.nom b/core/collections.nom
index 00bb5d8..938466d 100644
--- a/core/collections.nom
+++ b/core/collections.nom
@@ -7,63 +7,37 @@ use "core/metaprogramming.nom"
use "core/control_flow.nom"
use "core/operators.nom"
-# List/dict functions:
-# Indexing
-test:
- assume ((2 nd to last in [1, 2, 3, 4, 5]) is 4)
-compile [..]
- %index st to last in %list, %index nd to last in %list
- %index rd to last in %list, %index th to last in %list
-..to (Lua value "utils.nth_to_last(\(%list as lua expr), \(%index as lua expr))")
-
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-parse [last in %list] as (1 st to last in %list)
-parse [first in %list] as %list.1
-
-# Membership testing
-test:
- assume (3 is in [1, 2, 3, 4, 5])
-action [%item is in %list, %list contains %item, %list has %item]:
- for %key = %value in %list:
- if (%key is %item): return (yes)
- return (no)
-
-test:
- assume (99 isn't in [1, 2, 3])
-action [..]
- %item isn't in %list, %item is not in %list, %list doesn't contain %item
- %list does not contain %item, %list doesn't have %item, %list does not have %item
-..:
- for %key = %value in %list:
- if (%key is %item): return (no)
- return (yes)
-
-test:
- assume ({x:no} has key "x")
-parse [%list has key %index, %list has index %index] as (%list.%index != (nil))
-
-test:
- assume ({x:no} doesn't have key "y")
- assume (not ({x:no} doesn't have key "x"))
-parse [..]
- %list doesn't have key %index, %list does not have key %index
- %list doesn't have index %index, %list does not have index %index
-..as (%list.%index == (nil))
-
-compile [number of keys in %list] to (..)
- Lua value "utils.size(\(%list as lua expr))"
-
+# List functionality:
test:
%list = [1, 2, 3, 4, 5]
+ %visited = {}
+ for %i = %x in %list: %visited.%i = (yes)
+ assume (%visited == {1:yes, 2:yes, 3:yes, 4:yes, 5:yes})
+ %visited = {}
+ for %x in %list: %visited.%x = (yes)
+ assume (%visited == {1:yes, 2:yes, 3:yes, 4:yes, 5:yes})
+ assume ((%list::2 nd to last) == 4)
+ assume ((%list::first) == 1)
+ assume (%list::has 3)
+ assume ((%list::index of 3) == 3)
+ assume ((size of %list) == 5)
%list::add 6
- assume ((last in %list) is 6)
+ assume ((%list::last) == 6)
%list::pop
- assume ((last in %list) is 5)
+ assume ((%list::last) == 5)
%list::remove index 1
- assume ((first in %list) is 2)
-
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ assume ((%list::first) == 2)
+
+# Dict functionality
+test:
+ %dict = {x:1, y:2, z:3}
+ assume ((size of %dict) == 3)
+ assume ((% for % in {x:1}) == [{key:"x", value:1}])
+ assume (({key:%k, value:%v} for %k = %v in {x:1}) == [{key:"x", value:1}])
+ assume (({x:1, y:1} + {y:10, z:10}) == {x:1, y:11, z:10})
+ assume (({x:1, y:1} | {y:10, z:10}) == {x:1, y:1, z:10})
+ assume (({x:1, y:1} & {y:10, z:10}) == {y:1})
+ assume (({x:1, y:1} ~ {y:10, z:10}) == {x:1, z:10})
# List Comprehension
test:
diff --git a/core/metaprogramming.nom b/core/metaprogramming.nom
index bd65a7e..3657e02 100644
--- a/core/metaprogramming.nom
+++ b/core/metaprogramming.nom
@@ -3,7 +3,7 @@
This File contains actions for making actions and compile-time actions and some helper
functions to make that easier.
-lua> "NOMSU_CORE_VERSION = 6"
+lua> "NOMSU_CORE_VERSION = 7"
lua> ".."
COMPILE_ACTIONS["1 -> 2"] = function(nomsu, tree, \%args, \%body)
local lua = LuaCode.Value(tree.source, "(function(")
diff --git a/core/operators.nom b/core/operators.nom
index fbf88bb..863ebc8 100644
--- a/core/operators.nom
+++ b/core/operators.nom
@@ -238,7 +238,7 @@ compile [%x or %y] to (Lua value "(\(%x as lua expr) or \(%y as lua expr))")
# Bitwise Operators
# TODO: implement OR, XOR, AND for multiple operands?
test:
- assume ((~ 5) == -6)
+ assume ((~ (~ 5)) == 5)
assume ((1 | 4) == 5)
assume ((1 ~ 3) == 2)
assume ((1 & 3) == 1)
@@ -285,8 +285,8 @@ compile [- %] to (Lua value "(- \(% as lua expr))")
compile [not %] to (Lua value "(not \(% as lua expr))")
test:
- assume ((length of [1, 2, 3]) == 3)
-compile [length of %list, len %list, || %list ||] to (..)
+ assume ((size of [1, 2, 3]) == 3)
+compile [size of %list, length of %list, len %list, || %list ||] to (..)
Lua value "(#\(%list as lua expr))"
compile [%list is empty] to (Lua value "(#\(%list as lua expr) == 0)")
diff --git a/core/text.nom b/core/text.nom
index 25d4066..3cc979c 100644
--- a/core/text.nom
+++ b/core/text.nom
@@ -49,6 +49,10 @@ compile [bytes %start to %stop of %text] to (..)
Lua value ".."
list{(\(%text as lua expr)):byte(\(%start as lua expr), \(%stop as lua expr))}
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+action [bytes of %text] (bytes 1 to (=lua "#\%text") of %text)
+
test:
assume (("asdf" capitalized) == "Asdf")
compile [capitalized %text, %text capitalized] to (..)
diff --git a/lib/file_hash.nom b/lib/file_hash.nom
index 188df78..bce8c08 100644
--- a/lib/file_hash.nom
+++ b/lib/file_hash.nom
@@ -5,13 +5,38 @@
use "lib/os.nom"
use "lib/base64.nom"
-%hashlib = (=lua "require('openssl.digest')")
+lua> ".."
+ local \%use_sha1, \%hashlib = pcall(require, 'openssl.digest')
test:
- assume ((hash "hello world") == "Kq5sNclPz7QV2+lfQIuc6R7oRu0=")
-action [hash %, sha1 %]:
- %hash = (=lua "\%hashlib.new('sha1'):final(\%)")
- return (base64 %hash)
+ assume ((hash "hello world") == (hash "hello world"))
+ assume ((hash "hello world") != (hash "goodbye")) or barf ".."
+ Hash collision:
+ (hash "hello world") = \(hash "hello world")
+ (hash "goodbye") = \(hash "goodbye")
+ assume (..)
+ (..)
+ hash ".."
+ This is a really long string meant to stress test the hashing function and
+ ensure that it's not overflowing with long inputs.
+ ..!= "inf"
+ assume ((hash "\0") != (hash "\0\0\0\0\0")) or barf "Incorrect hashing of null strings"
+ if %use_sha1:
+ assume ((hash "hello world") == "Kq5sNclPz7QV2+lfQIuc6R7oRu0=")
+if %use_sha1:
+ action [hash %]:
+ %hash = (=lua "\%hashlib.new('sha1'):final(\%)")
+ return (base64 %hash)
+..else:
+ # TODO: remove warning?
+ say "\027[31;1mWARNING: OpenSSL module not found. Defaulting to a non-cryptographically secure hash function.\027[0m"
+ action [hash %]:
+ %bytes = (bytes of %)
+ %hash = (%bytes.1 << 7)
+ for %i in 2 to (size of %bytes):
+ %hash = ((1000003 * %hash) ~ %bytes.%i)
+ %hash = (%hash ~ (size of %bytes))
+ return "\%hash"
action [file with hash %hash]:
for file %filename in ".":
@@ -19,4 +44,4 @@ action [file with hash %hash]:
%file_hash = (hash %contents)
if (%file_hash == %hash): return %filename
-parse [hash of file %filename] as (sha1 (read file %filename))
+parse [hash of file %filename] as (hash (read file %filename))
diff --git a/nomsu_compiler.lua b/nomsu_compiler.lua
index 4855476..11bdc9d 100644
--- a/nomsu_compiler.lua
+++ b/nomsu_compiler.lua
@@ -4,6 +4,11 @@ local utils = require('utils')
local Files = require('files')
local repr, stringify, equivalent
repr, stringify, equivalent = utils.repr, utils.stringify, utils.equivalent
+local list, dict
+do
+ local _obj_0 = require('containers')
+ list, dict = _obj_0.list, _obj_0.dict
+end
colors = require('consolecolors')
colored = setmetatable({ }, {
__index = function(_, color)
@@ -82,84 +87,6 @@ do
end
end
end
-local _list_mt = {
- __eq = equivalent,
- __tostring = function(self)
- return "[" .. concat((function()
- local _accum_0 = { }
- local _len_0 = 1
- for _index_0 = 1, #self do
- local b = self[_index_0]
- _accum_0[_len_0] = repr(b)
- _len_0 = _len_0 + 1
- end
- return _accum_0
- end)(), ", ") .. "]"
- end,
- __lt = function(self, other)
- assert(type(self) == 'table' and type(other) == 'table', "Incompatible types for comparison")
- for i = 1, math.max(#self, #other) do
- if not self[i] and other[i] then
- return true
- elseif self[i] and not other[i] then
- return false
- elseif self[i] < other[i] then
- return true
- elseif self[i] > other[i] then
- return false
- end
- end
- return false
- end,
- __le = function(self, other)
- assert(type(self) == 'table' and type(other) == 'table', "Incompatible types for comparison")
- for i = 1, math.max(#self, #other) do
- if not self[i] and other[i] then
- return true
- elseif self[i] and not other[i] then
- return false
- elseif self[i] < other[i] then
- return true
- elseif self[i] > other[i] then
- return false
- end
- end
- return true
- end,
- __index = {
- add_1 = insert,
- append_1 = insert,
- add_1_at_index_2 = function(t, x, i)
- return insert(t, i, x)
- end,
- at_index_1_add_2 = insert,
- pop = table.remove,
- remove_last = table.remove,
- remove_index_1 = table.remove
- }
-}
-local list
-list = function(t)
- return setmetatable(t, _list_mt)
-end
-local _dict_mt = {
- __eq = equivalent,
- __tostring = function(self)
- return "{" .. concat((function()
- local _accum_0 = { }
- local _len_0 = 1
- for k, v in pairs(self) do
- _accum_0[_len_0] = tostring(repr(k)) .. ": " .. tostring(repr(v))
- _len_0 = _len_0 + 1
- end
- return _accum_0
- end)(), ", ") .. "}"
- end
-}
-local dict
-dict = function(t)
- return setmetatable(t, _dict_mt)
-end
local MAX_LINE = 80
local NomsuCompiler = setmetatable({
name = "Nomsu"
@@ -232,10 +159,21 @@ do
list = list,
dict = dict
}
- if jit then
- to_add.bit = require('bit')
- elseif _VERSION == "Lua 5.2" then
- to_add.bit = bit32
+ if _VERSION == "Lua 5.4" then
+ to_add.ipairs = function(x)
+ do
+ local mt = getmetatable(x)
+ if mt then
+ if mt.__ipairs then
+ return mt.__ipairs(x)
+ end
+ end
+ end
+ return ipairs(x)
+ end
+ end
+ if jit or _VERSION == "Lua 5.2" then
+ to_add.bit = require("bitops")
end
for k, v in pairs(to_add) do
NomsuCompiler[k] = v
@@ -591,6 +529,9 @@ do
local lua = LuaCode.Value(tree.source)
if tree.target then
lua:append(self:compile(tree.target), ":")
+ if string.as_lua_id(stub):match("^[0-9]") then
+ lua:append("_")
+ end
else
lua:append("A_")
end
diff --git a/nomsu_compiler.moon b/nomsu_compiler.moon
index 5ac6a87..70e3f40 100644
--- a/nomsu_compiler.moon
+++ b/nomsu_compiler.moon
@@ -14,6 +14,7 @@ re = require 're'
utils = require 'utils'
Files = require 'files'
{:repr, :stringify, :equivalent} = utils
+{:list, :dict} = require 'containers'
export colors, colored
colors = require 'consolecolors'
colored = setmetatable({}, {__index:(_,color)-> ((msg)-> colors[color]..tostring(msg or '')..colors.reset)})
@@ -57,46 +58,6 @@ do
if type(i) == 'number' then return sub(@, i, i)
elseif type(i) == 'table' then return sub(@, i[1], i[2])
--- List and Dict classes to provide basic equality/tostring functionality for the tables
--- used in Nomsu. This way, they retain a notion of whether they were originally lists or dicts.
-_list_mt =
- __eq:equivalent
- -- Could consider adding a __newindex to enforce list-ness, but would hurt performance
- __tostring: =>
- "["..concat([repr(b) for b in *@], ", ").."]"
- __lt: (other)=>
- assert type(@) == 'table' and type(other) == 'table', "Incompatible types for comparison"
- for i=1,math.max(#@, #other)
- if not @[i] and other[i] then return true
- elseif @[i] and not other[i] then return false
- elseif @[i] < other[i] then return true
- elseif @[i] > other[i] then return false
- return false
- __le: (other)=>
- assert type(@) == 'table' and type(other) == 'table', "Incompatible types for comparison"
- for i=1,math.max(#@, #other)
- if not @[i] and other[i] then return true
- elseif @[i] and not other[i] then return false
- elseif @[i] < other[i] then return true
- elseif @[i] > other[i] then return false
- return true
- __index:
- add_1: insert
- append_1: insert
- add_1_at_index_2: (t,x,i)-> insert(t,i,x)
- at_index_1_add_2: insert
- pop: table.remove
- remove_last: table.remove
- remove_index_1: table.remove
-
-list = (t)-> setmetatable(t, _list_mt)
-
-_dict_mt =
- __eq:equivalent
- __tostring: =>
- "{"..concat(["#{repr(k)}: #{repr(v)}" for k,v in pairs @], ", ").."}"
-dict = (t)-> setmetatable(t, _dict_mt)
-
MAX_LINE = 80 -- For beautification purposes, try not to make lines much longer than this value
NomsuCompiler = setmetatable {name:"Nomsu"},
__index: (k)=> if _self = rawget(@, "self") then _self[k] else nil
@@ -120,8 +81,13 @@ with NomsuCompiler
-- Nomsu types:
:list, :dict,
}
- if jit then to_add.bit = require('bit')
- elseif _VERSION == "Lua 5.2" then to_add.bit = bit32
+ if _VERSION == "Lua 5.4"
+ to_add.ipairs = (x)->
+ if mt = getmetatable(x)
+ if mt.__ipairs then return mt.__ipairs(x)
+ return ipairs(x)
+ if jit or _VERSION == "Lua 5.2"
+ to_add.bit = require("bitops")
for k,v in pairs(to_add) do NomsuCompiler[k] = v
for k,v in pairs(AST) do NomsuCompiler[k] = v
.LuaCode = LuaCode
@@ -365,6 +331,8 @@ with NomsuCompiler
lua = LuaCode.Value(tree.source)
if tree.target
lua\append @compile(tree.target), ":"
+ if string.as_lua_id(stub)\match("^[0-9]")
+ lua\append "_"
else
lua\append "A_"
lua\append(string.as_lua_id(stub),"(")