From 4a5b015f914348877b2787316cb5dbc46e1207ff Mon Sep 17 00:00:00 2001 From: Daniel Silverstone Date: Sun, 13 May 2012 21:44:40 +0100 Subject: Add define builtin command --- lib/lace/builtin.lua | 47 ++++++++++++++++++++++++++++ test/test-lace.builtin.lua | 76 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 123 insertions(+) diff --git a/lib/lace/builtin.lua b/lib/lace/builtin.lua index 811047f..fdfcefb 100644 --- a/lib/lace/builtin.lua +++ b/lib/lace/builtin.lua @@ -9,6 +9,8 @@ local builtin = {} +local engine = require "lace.engine" + local function compiler() return require "lace.compiler" end @@ -90,6 +92,51 @@ function builtin.default(compcontext, def, result, reason, unwanted) } end +--[ Definitions ]---------------------------------------------------- + +local function _controlfn(ctx, name) + local ctt = ctx[".lace"].controltype or {} + return ctt[name] +end + +function builtin.define(compcontext, define, name, controltype, ...) + if type(name) ~= "string" then + return compiler().error("Expected name, got nothing") + end + + if name == "" or name:sub(1,1) == "!" then + return compiler().error("Bad name for definition", {2}) + end + + if type(controltype) ~= "string" then + return compiler().error("Expected control type, got nothing") + end + + local controlfn = _controlfn(compcontext, controltype) + if not controlfn then + return compiler().error("Unknown control type", {3}) + end + + local ctrltab, msg = controlfn(compcontext, controltype, ...) + if type(ctrltab) ~= "table" then + -- offset all the words in the error by 2 (for define and name) + if msg.words then + for i = 1, #msg.words do + msg.words[i] = msg.words[i] + 2 + end + end + return false, msg + end + + -- Successfully created a control table, return a rule for it + return { + fn = engine.define, + args = { name, ctrltab } + } +end + +builtin.def = builtin.define + return { commands = builtin, get_set_last_unconditional_result = get_set_last_unconditional_result, diff --git a/test/test-lace.builtin.lua b/test/test-lace.builtin.lua index 558f15a..b80df1c 100644 --- a/test/test-lace.builtin.lua +++ b/test/test-lace.builtin.lua @@ -160,6 +160,82 @@ function suite.compile_builtin_default_noreason() assert(type(compctx[".lace"].default.fn) == "function", "Default table should have a function like a rule") end +function suite.compile_builtin_define_noname() + local compctx = {[".lace"] = {}} + local cmdtab, msg = builtin.commands.define(compctx, "define") + assert(cmdtab == false, "Internal errors should return false") + assert(type(msg) == "table", "Internal errors should return tables") + assert(type(msg.msg) == "string", "Internal errors should have string messages") + assert(msg.msg:match("Expected name"), "Expected error should mention a lack of name") +end + +function suite.compile_builtin_define_badname() + local compctx = {[".lace"] = {}} + local cmdtab, msg = builtin.commands.define(compctx, "define", "!fish") + assert(cmdtab == false, "Internal errors should return false") + assert(type(msg) == "table", "Internal errors should return tables") + assert(type(msg.msg) == "string", "Internal errors should have string messages") + assert(msg.msg:match("Bad name"), "Expected error should mention a bad name") +end + +function suite.compile_builtin_define_noctype() + local compctx = {[".lace"] = {}} + local cmdtab, msg = builtin.commands.define(compctx, "define", "fish") + assert(cmdtab == false, "Internal errors should return false") + assert(type(msg) == "table", "Internal errors should return tables") + assert(type(msg.msg) == "string", "Internal errors should have string messages") + assert(msg.msg:match("Expected control"), "Expected error should mention a lack of control type") +end + +function suite.compile_builtin_define_badctype() + local compctx = {[".lace"] = {}} + local cmdtab, msg = builtin.commands.define(compctx, "define", "fish", "fish") + assert(cmdtab == false, "Internal errors should return false") + assert(type(msg) == "table", "Internal errors should return tables") + assert(type(msg.msg) == "string", "Internal errors should have string messages") + assert(msg.msg:match("Unknown control"), "Expected error should mention unknown control type") +end + +function suite.compile_builtin_define_ctype_errors() + local function _fish() + return false, { msg = "Argh" } + end + local compctx = {[".lace"] = { controltype = { fish = _fish }}} + local cmdtab, msg = builtin.commands.define(compctx, "define", "fish", "fish") + assert(cmdtab == false, "Internal errors should return false") + assert(type(msg) == "table", "Internal errors should return tables") + assert(type(msg.msg) == "string", "Internal errors should have string messages") + assert(msg.msg:match("Argh"), "Expected error should be passed through") +end + +function suite.compile_builtin_define_ctype_errors_offset() + local function _fish() + return false, { msg = "Argh", words = {0} } + end + local compctx = {[".lace"] = { controltype = { fish = _fish }}} + local cmdtab, msg = builtin.commands.define(compctx, "define", "fish", "fish") + assert(cmdtab == false, "Internal errors should return false") + assert(type(msg) == "table", "Internal errors should return tables") + assert(type(msg.msg) == "string", "Internal errors should have string messages") + assert(msg.msg:match("Argh"), "Expected error should be passed through") + assert(msg.words[1] == 2, "Error words should be offset by 2") +end + +function suite.compile_builtin_define_ok() + local function _fish() + return { + JEFF = true + } + end + local compctx = {[".lace"] = { controltype = { fish = _fish }}} + local cmdtab, msg = builtin.commands.define(compctx, "define", "fish", "fish") + assert(type(cmdtab) == "table", "Successful compilation returns tables") + assert(type(cmdtab.fn) == "function", "With functions") + local ectx = {} + local ok, msg = cmdtab.fn(ectx, unpack(cmdtab.args)) + assert(ok, "Running a define should work") + assert(ectx[".lace"].defs.fish.JEFF, "definition should have passed through") +end local count_ok = 0 for _, testname in ipairs(testnames) do -- cgit v1.2.1