From c6a0bb10528a05db9153f6987f3d73f791e782bd Mon Sep 17 00:00:00 2001 From: Daniel Silverstone Date: Tue, 15 May 2012 16:22:23 +0100 Subject: Add anyof/allof combinators and tests for the builtin. --- lib/lace/builtin.lua | 39 +++++++++++++-- test/test-lace.builtin.lua | 120 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 156 insertions(+), 3 deletions(-) diff --git a/lib/lace/builtin.lua b/lib/lace/builtin.lua index 5978bd0..71d5010 100644 --- a/lib/lace/builtin.lua +++ b/lib/lace/builtin.lua @@ -15,7 +15,8 @@ local function compiler() return require "lace.compiler" end -local function run_conditions(exec_context, cond) +local function run_conditions(exec_context, cond, anyof) + local anymet = false for i = 1, #cond do local name = cond[i] local invert = false @@ -32,10 +33,17 @@ local function run_conditions(exec_context, cond) end if not res then -- condition failed - return false + if not anyof then + return false + end + else + anymet = true end end -- conditions passed + if anyof then + return anymet + end return true end @@ -121,11 +129,36 @@ function builtin.default(compcontext, def, result, reason, unwanted) } end +--[ Control types ]-------------------------------------------------- + +local function _compile_any_all_of(compcontext, mtype, first, second, ...) + if type(first) ~= "string" then + return compiler().error("Expected at least two names, got none") + end + if type(second) ~= "string" then + return compiler().error("Expected at least two names, only got one") + end + + return { + fn = run_conditions, + args = { { first, second, ...}, mtype == "anyof" } + } +end + +local builtin_control_fn = { + anyof = _compile_any_all_of, + allof = _compile_any_all_of +} + --[ Definitions ]---------------------------------------------------- local function _controlfn(ctx, name) local ctt = ctx[".lace"].controltype or {} - return ctt[name] + local cfn = ctt[name] + if cfn == nil then + cfn = builtin_control_fn[name] + end + return cfn end function builtin.define(compcontext, define, name, controltype, ...) diff --git a/test/test-lace.builtin.lua b/test/test-lace.builtin.lua index 8df9af8..4ee79c2 100644 --- a/test/test-lace.builtin.lua +++ b/test/test-lace.builtin.lua @@ -12,6 +12,7 @@ local luacov = require 'luacov' local builtin = require 'lace.builtin' +local engine = require 'lace.engine' local testnames = {} @@ -487,6 +488,125 @@ function suite.run_cond_include_present_passing() assert(msg == "because", "Should propagate reason") end +function suite.compile_anyof_no_args() + local compctx = {[".lace"] = {}} + local cmdtab, msg = builtin.commands.define(compctx, "define", "foo", "anyof") + assert(cmdtab == false, "Internal errors should return false") + assert(type(msg) == "table", "Internal errors should be tables") + assert(msg.msg:match(", got none"), "Error should mention that there were no args") +end + +function suite.compile_allof_no_args() + local compctx = {[".lace"] = {}} + local cmdtab, msg = builtin.commands.define(compctx, "define", "foo", "allof") + assert(cmdtab == false, "Internal errors should return false") + assert(type(msg) == "table", "Internal errors should be tables") + assert(msg.msg:match(", got none"), "Error should mention that there were no args") +end + +function suite.compile_anyof_one_args() + local compctx = {[".lace"] = {}} + local cmdtab, msg = builtin.commands.define(compctx, "define", "foo", "anyof", "foo") + assert(cmdtab == false, "Internal errors should return false") + assert(type(msg) == "table", "Internal errors should be tables") + assert(msg.msg:match(", only got one"), "Error should mention that there was only one arg") +end + +function suite.compile_allof_one_args() + local compctx = {[".lace"] = {}} + local cmdtab, msg = builtin.commands.define(compctx, "define", "foo", "allof", "foo") + assert(cmdtab == false, "Internal errors should return false") + assert(type(msg) == "table", "Internal errors should be tables") + assert(msg.msg:match(", only got one"), "Error should mention that there was only one arg") +end + + +function suite.compile_anyof_two_args() + local compctx = {[".lace"] = {}} + local cmdtab, msg = builtin.commands.define(compctx, "define", "foo", "anyof", "foo", "bar") + assert(type(cmdtab) == "table", "Successful compilations should return tables") + assert(type(cmdtab.fn) == "function", "With functions") + assert(type(cmdtab.args) == "table", "And arguments") + assert(#cmdtab.args == 2, "There should be two args") + assert(type(cmdtab.args[1]) == "string", "The first should be a table") + assert(type(cmdtab.args[2]) == "table", "The second should be a bool") + local ctrltab = cmdtab.args[2] + assert(type(ctrltab) == "table", "Successfully compiled control functions should return tables") + assert(type(ctrltab.fn) == "function", "With functions") + assert(type(ctrltab.args) == "table", "And arguments") + assert(#ctrltab.args == 2, "There should be two args") + assert(type(ctrltab.args[1]) == "table", "The first should be a table") + assert(type(ctrltab.args[2]) == "boolean", "The second should be a bool") + assert(ctrltab.args[2] == true, "The anyof indicator should be true") +end + +function suite.compile_allof_two_args() + local compctx = {[".lace"] = {}} + local cmdtab, msg = builtin.commands.define(compctx, "define", "foo", "allof", "foo", "bar") + assert(type(cmdtab) == "table", "Successful compilations should return tables") + assert(type(cmdtab.fn) == "function", "With functions") + assert(type(cmdtab.args) == "table", "And arguments") + assert(#cmdtab.args == 2, "There should be two args") + assert(type(cmdtab.args[1]) == "string", "The first should be a table") + assert(type(cmdtab.args[2]) == "table", "The second should be a bool") + local ctrltab = cmdtab.args[2] + assert(type(ctrltab) == "table", "Successfully compiled control functions should return tables") + assert(type(ctrltab.fn) == "function", "With functions") + assert(type(ctrltab.args) == "table", "And arguments") + assert(#ctrltab.args == 2, "There should be two args") + assert(type(ctrltab.args[1]) == "table", "The first should be a table") + assert(type(ctrltab.args[2]) == "boolean", "The second should be a bool") + assert(ctrltab.args[2] == false, "The anyof indicator should be false") +end + +function suite.run_anyof_two_args() + local compctx = {[".lace"] = {}} + local cmdtab, msg = builtin.commands.define(compctx, "define", "jeff", "anyof", "foo", "bar") + assert(type(cmdtab) == "table", "Successful compilations should return tables") + local ectx = { + [".lace"] = { + defs = { + foo = { + fn = function() return true end, + args = {} + }, + bar = { + fn = function() return false end, + args = {} + } + } + } + } + local ok, msg = cmdtab.fn(ectx, unpack(cmdtab.args)) + assert(ok, "Running a define should work") + assert(ectx[".lace"].defs.foo.fn, "definition should have passed through") + assert(engine.test(ectx, "jeff"), "Any of true,false should be true") +end + +function suite.run_anyof_two_args() + local compctx = {[".lace"] = {}} + local cmdtab, msg = builtin.commands.define(compctx, "define", "jeff", "allof", "foo", "bar") + assert(type(cmdtab) == "table", "Successful compilations should return tables") + local ectx = { + [".lace"] = { + defs = { + foo = { + fn = function() return true end, + args = {} + }, + bar = { + fn = function() return false end, + args = {} + } + } + } + } + local ok, msg = cmdtab.fn(ectx, unpack(cmdtab.args)) + assert(ok, "Running a define should work") + assert(ectx[".lace"].defs.foo.fn, "definition should have passed through") + assert(engine.test(ectx, "jeff") == false, "All of true,false should be false") +end + local count_ok = 0 for _, testname in ipairs(testnames) do -- print("Run: " .. testname) -- cgit v1.2.1