diff options
Diffstat (limited to 'Tools/LuaMacro/macro/lib')
-rw-r--r-- | Tools/LuaMacro/macro/lib/class.lua | 35 | ||||
-rw-r--r-- | Tools/LuaMacro/macro/lib/test.lua | 144 |
2 files changed, 179 insertions, 0 deletions
diff --git a/Tools/LuaMacro/macro/lib/class.lua b/Tools/LuaMacro/macro/lib/class.lua new file mode 100644 index 0000000..f762f36 --- /dev/null +++ b/Tools/LuaMacro/macro/lib/class.lua @@ -0,0 +1,35 @@ +---- +-- a basic class mechanism. +-- Used for some of the demonstrations; the `class` macro in the `module` +-- package uses it. It provides a single function which returns a new 'class'. +-- The resulting object can be called to generate an instance of the class. +-- You may provide a base class for single inheritance; in this case, the functions +-- of the base class will be copied into the new class' metatable (so-called 'fat metatable') +-- +-- Example: +-- +-- local class = require 'macro.lib.class' +-- A = class() +-- function A._init(name) self.name = name end +-- a = A("hello") +-- assert(a.name == "hello") +-- +-- @module macro.lib.class + +return function (base) + -- OOP with single inheritance + local klass,cmt = {},{} + if base then -- 'fat metatable' inheritance + for k,v in pairs(base) do klass[k] = v end + end + klass.__index = klass + -- provide a callable constructor that invokes user-supplied ctor + function cmt:__call(...) + local obj = setmetatable({},klass) + if klass._init then klass._init(obj,...) + elseif base and base._init then base._init(base,...) end + return obj + end + setmetatable(klass,cmt) + return klass +end diff --git a/Tools/LuaMacro/macro/lib/test.lua b/Tools/LuaMacro/macro/lib/test.lua new file mode 100644 index 0000000..5fff39e --- /dev/null +++ b/Tools/LuaMacro/macro/lib/test.lua @@ -0,0 +1,144 @@ +--- `assert_` macro library support. +-- This module may of course be used on its own; `assert_` merely provides +-- some syntactical sugar for its functionality. It is based on Penlight's +-- `pl.test` module. +-- @module macro.libs.test + +local test = {} + +local _eq,_tostring + +-- very much like tablex.deepcompare from Penlight +function _eq (v1,v2) + if type(v1) ~= type(v2) then return false end + -- if the value isn't a table, or it has defined the equality operator.. + local mt = getmetatable(v1) + if (mt and mt.__eq) or type(v1) ~= 'table' then + return v1 == v2 + end + -- both values are plain tables + if v1 == v2 then return true end -- they were the same table... + for k1,x1 in pairs(v1) do + local x2 = v2[k1] + if x2 == nil or not _eq(x1,x2) then return false end + end + for k2,x2 in pairs(v2) do + local x1 = v1[k2] + if x1 == nil or not _eq(x1,x2) then return false end + end + return true +end + +local function keyv (k) + if type(k) ~= 'string' then + k = '['..k..']' + end + return k +end + +function _tostring (val) + local mt = getmetatable(val) + if (mt and mt.__tostring) or type(val) ~= 'table' then + if type(val) == 'string' then + return '"'..tostring(val)..'"' + else + return tostring(val) + end + end + -- dump the table; doesn't need to be pretty! + local res = {} + local function put(s) res[#res+1] = s end + put '{' + for k,v in pairs(val) do + put(keyv(k)..'=') + put(_tostring(v)) + put ',' + end + table.remove(res) -- remove last ',' + put '}' + return table.concat(res) +end + +local function _lt (v1,v2) return v1 < v2 end +local function _gt (v1,v2) return v1 > v2 end +local function _match (v1,v2) return v1:match(v2) end + +local function _assert (v1,v2,cmp,msg) + if not cmp(v1,v2) then + print('first:',_tostring(v1)) + print(msg) + print('second:',_tostring(v2)) + error('assertion failed',3) + end +end + +--- assert if parameters are not equal. If the values are tables, +-- they will be compared by value. +-- @param v1 given value +-- @param v2 test value +function test.assert_eq (v1,v2) + _assert(v1,v2,_eq,"is not equal to"); +end + +--- assert if first parameter is not less than second. +-- @param v1 given value +-- @param v2 test value +function test.assert_lt (v1,v2) + _assert(v1,v2,_lt,"is not less than") +end + +--- assert if first parameter is not greater than second. +-- @param v1 given value +-- @param v2 test value +function test.assert_gt (v1,v2) + _assert(v1,v2,_gt,"is not greater than") +end + +--- assert if first parameter string does not match the second. +-- The condition is `v1:match(v2)`. +-- @param v1 given value +-- @param v2 test value +function test.assert_match (v1,v2) + _assert(v1,v2,_match,"does not match") +end + +-- return the error message from a function that raises an error. +-- Will raise an error if the function did not raise an error. +-- @param fun the function +-- @param ... any arguments to the function +-- @return the error message +function test.pcall_no(fun,...) + local ok,err = pcall(fun,...) + if ok then error('expression did not throw error',3) end + return err +end + +local tuple = {} + +function tuple.__eq (a,b) + if a.n ~= b.n then return false end + for i=1, a.n do + if not _eq(a[i],b[i]) then return false end + end + return true +end + +function tuple.__tostring (self) + local ts = {} + for i = 1,self.n do + ts[i] = _tostring(self[i]) + end + return '('..table.concat(ts,',')..')' +end + +--- create a tuple capturing multiple return values. +-- Equality between tuples means that all of their values are equal; +-- values may be `nil` +-- @param ... any values +-- @return a tuple object +function test.tuple(...) + return setmetatable({n=select('#',...),...},tuple) +end + +return test + |