1
0
Fork 0
mirror of https://github.com/Reuh/candran.git synced 2025-10-27 17:59:30 +00:00
Updated tests, added a few usefull options to #import()
This commit is contained in:
Étienne Fildadut 2017-08-19 19:05:05 +02:00
parent 83156361cd
commit 97454746b8
6 changed files with 197 additions and 53 deletions

View file

@ -53,7 +53,7 @@ Will output ````print("Bonjour")```` or ````print("Hello")```` depending of the
The preprocessor has access to the following variables : The preprocessor has access to the following variables :
* ````candran```` : the Candran library table. * ````candran```` : the Candran library table.
* ````output```` : the current preprocessor output string. * ````output```` : the current preprocessor output string.
* ````import(module[, [args, autoRequire]])```` : a function which import a module. This is equivalent to use _require(module)_ in the Candran code, except the module will be embedded in the current file. _args_ is an optional preprocessor arguments table for the imported module (current preprocessor arguments will be inherited). _autoRequire_ (boolean, default true) indicate if the module should be automaticaly loaded in a local variable or not. If true, the local variable will have the name of the module. * ````import(module[, [options])```` : a function which import a module. This should be equivalent to using _require(module)_ in the Candran code, except the module will be embedded in the current file. _options_ is an optional preprocessor arguments table for the imported module (current preprocessor arguments will be inherited). Options specific to this function: ```loadLocal``` (default ```true```): ```true``` to automatically load the module into a local variable (i.e. ```local thing = require("module.thing")```); ```loadPackage``` (default ```true```): ```true``` to automatically load the module into the loaded packages table (so it will be available for following ```require("module")``` calls).
* ````include(filename)```` : a function which copy the contents of the file _filename_ to the output. * ````include(filename)```` : a function which copy the contents of the file _filename_ to the output.
* ````write(...)```` : write to the preprocessor output. For example, ````#print("hello()")```` will output ````hello()```` in the final file. * ````write(...)```` : write to the preprocessor output. For example, ````#print("hello()")```` will output ````hello()```` in the final file.
* ```placeholder(name)``` : if the variable _name_ is defined in the preprocessor environement, its content will be inserted here. * ```placeholder(name)``` : if the variable _name_ is defined in the preprocessor environement, its content will be inserted here.
@ -255,6 +255,8 @@ chunkname = "nil" -- The chunkname used when running code using the helper funct
rewriteErrors = true -- True to enable error rewriting when loading code using the helper functions. Will wrap the whole code in a xpcall(). rewriteErrors = true -- True to enable error rewriting when loading code using the helper functions. Will wrap the whole code in a xpcall().
``` ```
There are also a few function-specific options available, see the associated functions documentation for more information.
### Compiling the library ### Compiling the library
The Candran library itself is written is Candran, so you have to compile it with an already compiled Candran library. The Candran library itself is written is Candran, so you have to compile it with an already compiled Candran library.

View file

@ -10,7 +10,7 @@
#import("lib.lua-parser.parser") #import("lib.lua-parser.parser")
local candran = { local candran = {
VERSION = "0.3.0" VERSION = "0.3.1"
} }
--- Default options. --- Default options.
@ -53,17 +53,19 @@ function candran.preprocess(input, options={})
--- Current preprocessor output --- Current preprocessor output
env.output = "" env.output = ""
--- Import an external Candran/Lua module into the generated file --- Import an external Candran/Lua module into the generated file
-- Notable options:
-- * loadLocal (true): true to automatically load the module into a local variable
-- * loadPackage (true): true to automatically load the module into the loaded packages table
-- @tparam modpath string module path -- @tparam modpath string module path
-- @tparam margs table preprocessor arguments to use when preprocessessing the module -- @tparam margs table preprocessor options to use when preprocessessing the module
-- @tparam autoRequire[opt=true] boolean true to automatically load the module into a local variable env.import = function(modpath, margs={})
env.import = function(modpath, margs={}, autoRequire=true)
local filepath = assert(util.search(modpath), "No module named \""..modpath.."\"") local filepath = assert(util.search(modpath), "No module named \""..modpath.."\"")
-- open module file -- open module file
local f = io.open(filepath) local f = io.open(filepath)
if not f then error("Can't open the module file to import") end if not f then error("Can't open the module file to import") end
margs = util.merge(options, { chunkname = filepath }, margs) margs = util.merge(options, { chunkname = filepath, loadLocal = true, loadPackage = true }, margs)
local modcontent = candran.preprocess(f:read("*a"), margs) local modcontent = candran.preprocess(f:read("*a"), margs)
f:close() f:close()
@ -71,13 +73,13 @@ function candran.preprocess(input, options={})
local modname = modpath:match("[^%.]+$") local modname = modpath:match("[^%.]+$")
env.write( env.write(
"-- MODULE \""..modpath.."\" --\n".. "-- MODULE "..modpath.." --\n"..
"local function _()\n".. "local function _()\n"..
modcontent.."\n".. modcontent.."\n"..
"end\n".. "end\n"..
(autoRequire and "local "..modname.." = _() or "..modname.."\n" or "").. -- auto require (margs.loadLocal and ("local %s = _() or %s\n"):format(modname, modname) or "").. -- auto require
"package.loaded[\""..modpath.."\"] = "..(autoRequire and modname or "_()").." or true\n".. -- add to package.loaded (margs.loadPackage and ("package.loaded[%q] = %s or true\n"):format(modpath, margs.loadLocal and modname or "_()") or "").. -- add to package.loaded
"-- END OF MODULE \""..modpath.."\" --" "-- END OF MODULE "..modpath.." --"
) )
end end
--- Include another file content in the preprocessor output. --- Include another file content in the preprocessor output.

View file

@ -651,7 +651,6 @@ return requireStr .. lua(ast) .. newline()
end end
end end
local lua53 = _() or lua53 local lua53 = _() or lua53
package["loaded"]["compiler.lua53"] = lua53 or true
return lua53 return lua53
end end
local luajit = _() or luajit local luajit = _() or luajit
@ -1808,7 +1807,7 @@ return parser
end end
local parser = _() or parser local parser = _() or parser
package["loaded"]["lib.lua-parser.parser"] = parser or true package["loaded"]["lib.lua-parser.parser"] = parser or true
local candran = { ["VERSION"] = "0.3.0" } local candran = { ["VERSION"] = "0.3.1" }
local default = { local default = {
["target"] = "lua53", ["indentation"] = "", ["newline"] = "\ ["target"] = "lua53", ["indentation"] = "", ["newline"] = "\
", ["requirePrefix"] = "CANDRAN_", ["mapLines"] = true, ["chunkname"] = "nil", ["rewriteErrors"] = true ", ["requirePrefix"] = "CANDRAN_", ["mapLines"] = true, ["chunkname"] = "nil", ["rewriteErrors"] = true
@ -1836,25 +1835,26 @@ preprocessor = preprocessor .. "return output"
local env = util["merge"](_G, options) local env = util["merge"](_G, options)
env["candran"] = candran env["candran"] = candran
env["output"] = "" env["output"] = ""
env["import"] = function(modpath, margs, autoRequire) env["import"] = function(modpath, margs)
if margs == nil then margs = {} end if margs == nil then margs = {} end
if autoRequire == nil then autoRequire = true end
local filepath = assert(util["search"](modpath), "No module named \"" .. modpath .. "\"") local filepath = assert(util["search"](modpath), "No module named \"" .. modpath .. "\"")
local f = io["open"](filepath) local f = io["open"](filepath)
if not f then if not f then
error("Can't open the module file to import") error("Can't open the module file to import")
end end
margs = util["merge"](options, { ["chunkname"] = filepath }, margs) margs = util["merge"](options, {
["chunkname"] = filepath, ["loadLocal"] = true, ["loadPackage"] = true
}, margs)
local modcontent = candran["preprocess"](f:read("*a"), margs) local modcontent = candran["preprocess"](f:read("*a"), margs)
f:close() f:close()
local modname = modpath:match("[^%.]+$") local modname = modpath:match("[^%.]+$")
env["write"]("-- MODULE \"" .. modpath .. "\" --\ env["write"]("-- MODULE " .. modpath .. " --\
" .. "local function _()\ " .. "local function _()\
" .. modcontent .. "\ " .. modcontent .. "\
" .. "end\ " .. "end\
" .. (autoRequire and "local " .. modname .. " = _() or " .. modname .. "\ " .. (margs["loadLocal"] and ("local %s = _() or %s\
" or "") .. "package.loaded[\"" .. modpath .. "\"] = " .. (autoRequire and modname or "_()") .. " or true\ "):format(modname, modname) or "") .. (margs["loadPackage"] and ("package.loaded[%q] = %s or true\
" .. "-- END OF MODULE \"" .. modpath .. "\" --") "):format(modpath, margs["loadLocal"] and modname or "_()") or "") .. "-- END OF MODULE " .. modpath .. " --")
end end
env["include"] = function(file) env["include"] = function(file)
local f = io["open"](file) local f = io["open"](file)

View file

@ -28,6 +28,6 @@ end
#local patch = output #local patch = output
#output = "" #output = ""
#import("compiler.lua53", { patch = patch }) #import("compiler.lua53", { patch = patch, loadPackage = false })
return lua53 return lua53

View file

@ -1,6 +1,6 @@
package = "Candran" package = "Candran"
version = "0.3.0-1" version = "0.3.1-1"
description = { description = {
summary = "A simple Lua dialect and preprocessor.", summary = "A simple Lua dialect and preprocessor.",
@ -17,7 +17,7 @@ description = {
source = { source = {
url = "git://github.com/Reuh/Candran", url = "git://github.com/Reuh/Candran",
tag = "v0.3.0" tag = "v0.3.1"
} }
dependencies = { dependencies = {

View file

@ -1,17 +1,13 @@
print("========================")
print("|| CANDRAN TESTS ||")
print("========================")
local candran = dofile(arg[1] or "../candran.lua") local candran = dofile(arg[1] or "../candran.lua")
-- test helper -- test helper
local results = {} -- tests result local results = {} -- tests result
local function test(name, candranCode, result, args) local function test(name, candranCode, expectedResult, options)
results[name] = { result = "not finished", message = "no info" } results[name] = { result = "not finished", message = "no info" }
local self = results[name] local self = results[name]
-- make code -- make code
local success, code = pcall(candran.make, candranCode, args) local success, code = pcall(candran.make, candranCode, options)
if not success then if not success then
self.result = "error" self.result = "error"
self.message = "error while making code:\n"..code self.message = "error while making code:\n"..code
@ -35,9 +31,9 @@ local function test(name, candranCode, result, args)
end end
-- check result -- check result
if output ~= result then if output ~= expectedResult then
self.result = "fail" self.result = "fail"
self.message = "invalid result from the code; it returned "..tostring(output).." instead of "..tostring(result) self.message = "invalid result from the code; it returned "..tostring(output).." instead of "..tostring(expectedResult)
return return
else else
self.result = "success" self.result = "success"
@ -48,10 +44,15 @@ end
-- tests -- tests
print("Running tests...") print("Running tests...")
------------------
-- PREPROCESSOR --
------------------
test("preprocessor", [[ test("preprocessor", [[
#local foo = true #local foo = true
return true return true
]], true) ]], true)
test("preprocessor condition", [[ test("preprocessor condition", [[
#local foo = true #local foo = true
#if not foo then #if not foo then
@ -60,23 +61,45 @@ test("preprocessor condition", [[
return true return true
#end #end
]], true) ]], true)
test("preprocessor args table", [[
test("preprocessor candran table", [[
#write(("return %q"):format(candran.VERSION))
]], candran.VERSION)
test("preprocessor output variable", [[
#output = "return 5"
]], 5)
test("preprocessor import function", [[
#import("toInclude")
return toInclude
]], 5)
test("preprocessor include function", [[
#include('toInclude.lua')
]], 5)
test("preprocessor write function", [[
#write("local a = true")
return a
]], true)
test("preprocessor placeholder function", [[
#placeholder('foo')
]], 5, { foo = "return 5" })
test("preprocessor options", [[
#if not foo == "sky" then #if not foo == "sky" then
# error("Invalid foo argument") # error("Invalid foo argument")
#end #end
return true return true
]], true, { foo = "sky" }) ]], true, { foo = "sky" })
test("preprocessor write function", [[
#write("local a = true")
return a
]], true)
test("preprocessor import function", [[
#import("toInclude")
return toInclude
]], 5)
test("preprocessor include function", "a = [[\n#include('toInclude.lua')\n]]\nreturn a",
"local a = 5\nreturn a\n\n")
----------------------
-- SYNTAX ADDITIONS --
----------------------
-- Assignement operators
test("+=", [[ test("+=", [[
local a = 5 local a = 5
a += 2 a += 2
@ -97,6 +120,11 @@ local a = 5
a /= 2 a /= 2
return a return a
]], 5/2) ]], 5/2)
test("//=", [[
local a = 5
a //= 2
return a
]], 2)
test("^=", [[ test("^=", [[
local a = 5 local a = 5
a ^= 2 a ^= 2
@ -112,6 +140,72 @@ local a = "hello"
a ..= " world" a ..= " world"
return a return a
]], "hello world") ]], "hello world")
test("and=", [[
local a = true
a and= "world"
return a
]], "world")
test("or=", [[
local a = false
a or= "world"
return a
]], "world")
test("&=", [[
local a = 5
a &= 3
return a
]], 1)
test("|=", [[
local a = 5
a |= 3
return a
]], 7)
test("<<=", [[
local a = 23
a <<= 2
return a
]], 92)
test(">>=", [[
local a = 23
a >>= 2
return a
]], 5)
test("right assigments operators", [[
local a = 5
a =+ 2 assert(a == 7, "=+")
a =- 2 assert(a == -5, "=-")
a =* -2 assert(a == 10, "=*")
a =/ 2 assert(a == 0.2, "=/")
a =// 2 assert(a == 10, "=//")
a =^ 2 assert(a == 1024, "=^")
a =% 2000 assert(a == 976, "=%")
a = "world"
a =.. "hello " assert(a == "hello world", "=..")
a =and true assert(a == "hello world", "=and")
a = false
a =or nil assert(a == false, "=or")
a = 3
a =& 5 assert(a == 1, '=&')
a =| 20 assert(a == 21, "=|")
a =<< 1 assert(a == 2097152, "=<<")
a = 2
a =>> 23 assert(a == 5, "=>>")
]], nil)
test("some left+right assigments operators", [[
local a = 5
a -=+ 2 assert(a == 8, "-=+")
a = "hello"
a ..=.. " world " assert(a == "hello world hello", "..=..")
]], nil)
-- Default function parameters
test("default parameters", [[ test("default parameters", [[
local function test(hey, def="re", no, foo=("bar"):gsub("bar", "batru")) local function test(hey, def="re", no, foo=("bar"):gsub("bar", "batru"))
return def..foo return def..foo
@ -119,22 +213,68 @@ end
return test(78, "SANDWICH", true) return test(78, "SANDWICH", true)
]], "SANDWICHbatru") ]], "SANDWICHbatru")
-- results -- @ self alias
print("=====================") test("@ as self alias", [[
print("|| RESULTS ||") local a = {}
print("=====================") function a:hey()
return @ == self
end
return a:hey()
]], true)
test("@ as self alias and indexation", [[
local a = {
foo = "Hoi"
}
function a:hey()
return @.foo
end
return a:hey()
]], "Hoi")
test("@name indexation", [[
local a = {
foo = "Hoi"
}
function a:hey()
return @foo
end
return a:hey()
]], "Hoi")
test("@[expt] indexation", [[
local a = {
foo = "Hoi"
}
function a:hey()
return @["foo"]
end
return a:hey()
]], "Hoi")
-- Short anonymous functions declaration
test("short anonymous function declaration", [[
local a = (arg1)
return arg1
end
return a(5)
]], 5)
test("short anonymous method declaration", [[
local a = :(arg1)
return self + arg1
end
return a(2, 3)
]], 5)
-- results
local resultCounter = {} local resultCounter = {}
local testCounter = 0 local testCounter = 0
for name, test in pairs(results) do for name, t in pairs(results) do
-- print errors & fails -- print errors & fails
if test.result ~= "success" then if t.result ~= "success" then
print("Test \""..name.."\" : "..test.result) print(name.." test: "..t.result)
if test.message then print(test.message) end if t.message then print(t.message) end
print("----------") print("----------")
end end
-- count tests results -- count tests results
resultCounter[test.result] = (resultCounter[test.result] or 0) + 1 resultCounter[t.result] = (resultCounter[t.result] or 0) + 1
testCounter = testCounter + 1 testCounter = testCounter + 1
end end