summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Silverstone <dsilvers@digital-scurf.org>2013-11-26 21:23:42 +0100
committerDaniel Silverstone <dsilvers@digital-scurf.org>2013-11-26 21:23:42 +0100
commitf566f178016ae766d5c20fb7408f2280c8995c51 (patch)
treebfc606c4febcbe0426f42f70e2e2865338171c4b
parentd1b50c8feb02007697e0f946b819dfd2419643a0 (diff)
downloadlace-f566f178016ae766d5c20fb7408f2280c8995c51.tar.gz
Lots of ldoc
-rw-r--r--ldoc/.gitignore1
-rw-r--r--ldoc/config.ld5
-rw-r--r--lib/lace.lua4
-rw-r--r--lib/lace/builtin.lua104
-rw-r--r--lib/lace/compiler.lua40
-rw-r--r--lib/lace/error.lua52
-rw-r--r--lib/lace/lex.lua19
7 files changed, 221 insertions, 4 deletions
diff --git a/ldoc/.gitignore b/ldoc/.gitignore
new file mode 100644
index 0000000..1936cc1
--- /dev/null
+++ b/ldoc/.gitignore
@@ -0,0 +1 @@
+html
diff --git a/ldoc/config.ld b/ldoc/config.ld
new file mode 100644
index 0000000..57c2914
--- /dev/null
+++ b/ldoc/config.ld
@@ -0,0 +1,5 @@
+file = {"../lib"}
+format = "discount"
+project = "Lua Access Control Engine"
+title = "Lace - Lua Access Control Engine"
+dir = "html"
diff --git a/lib/lace.lua b/lib/lace.lua
index 2002cf3..9e039d6 100644
--- a/lib/lace.lua
+++ b/lib/lace.lua
@@ -7,6 +7,10 @@
-- For licence terms, see COPYING
--
+--- Lua Access Control Engine.
+--
+--
+
local lex = require "lace.lex"
local compiler = require "lace.compiler"
local builtin = require "lace.builtin"
diff --git a/lib/lace/builtin.lua b/lib/lace/builtin.lua
index 2f03549..147da6a 100644
--- a/lib/lace/builtin.lua
+++ b/lib/lace/builtin.lua
@@ -7,6 +7,14 @@
-- For Licence terms, see COPYING
--
+--- Lace builtin commands and match types.
+--
+-- The builtin match types and commands provided by Lace. These commands and
+-- match types are supported automatically by all lace compiles. The builtin
+-- command `default` and the builtin commands `allow` and `deny` collude with
+-- the compiler to ensure that all compiled rulesets will always either
+-- explicitly allow or deny access.
+
local builtin = {}
local engine = require "lace.engine"
@@ -53,12 +61,36 @@ end
local unconditional_result, last_result
+--- Internal function to get/set the last result for unconditional access.
+--
+-- The last result (unconditional only) is stored so that defaults can be
+-- processed in the absence of a `default` statement.
+--
+-- This function exists to collude with `lace.compiler.internal_compile` so
+-- that it can synthesise default access statements if needed.
+--
+-- @tparam string|nil newv The new value for the last access result.
+-- It should be one of `allow`, `deny` or a _nil_.
+-- @treturn string|nil The old (current) value for the last access result.
+-- @function get_set_last_unconditional_result
local function get_set_last_unconditional_result(newv)
local ret = unconditional_result
unconditional_result = newv
return ret
end
+--- Internal function to get/set the last result for access.
+--
+-- The last result (conditional perhaps) is stored so that defaults can be
+-- processed in the absence of a `default` statement.
+--
+-- This function exists to collude with `lace.compiler.internal_compile` so
+-- that it can synthesise default access statements if needed.
+--
+-- @tparam string|nil newv The new value for the last access result.
+-- It should be one of `allow`, `deny` or a _nil_.
+-- @treturn string|nil The old (current) value for the last access result.
+-- @function get_set_last_result
local function get_set_last_result(newv)
local ret = last_result
last_result = newv
@@ -78,6 +110,21 @@ local function _do_return(exec_context, result, reason, cond)
return result, reason
end
+--- Compile an `allow` or `deny`.
+--
+-- (_Note: this is also `commands.deny`_)
+--
+-- Allowing and denying access is, after all, what access control lists are all
+-- about. This function compiles in an `allow` or `deny` statement including
+-- noting what kind of access statement it is and what
+--
+-- @tparam table compcontext The compilation context
+-- @tparam string result The result to be compiled (`allow` or `deny`).
+-- @tparam string reason The reason to be returned to the user for this.
+-- @tparam[opt] string ... The conditions placed on this `allow` or `deny`.
+-- @treturn table The compiled `allow`/`deny`.
+-- @function commands.allow
+-- @alias commands.deny
local function _return(compcontext, result, reason, ...)
if result ~= "allow" and result ~= "deny" then
return err.error("Unknown result: " .. result, {1})
@@ -103,6 +150,24 @@ builtin.deny = _return
--[ Default for Allow and Deny ]------------------------------------
+--- Compile a `default` command.
+--
+-- All rulesets must, ultimately, allow or deny access. The `default` command
+-- allows rulesets to define whether they are permissive (defaulting to
+-- `allow`) or proscriptive (defaulting to `deny`).
+--
+-- In addition, setting default causes a record to be made, preventing
+-- additional attempts to set a default access mode. This ensures that once
+-- the default has been selected, additional ruleset included (perhaps from
+-- untrusted sources) cannot change the default behaviour.
+--
+-- @tparam table compcontext The compilation context
+-- @tparam string def The command which triggered this compilation. (`default`)
+-- @tparam string result The default result (`allow` or `deny`)
+-- @tparam string reason The reason to be given.
+-- @tparam[opt] * unwanted If _unwanted_ is anything but nil, an error occurs.
+-- @treturn table A null command
+-- @function commands.default
function builtin.default(compcontext, def, result, reason, unwanted)
assert(def == "default", "Somehow, builtin.default got something odd")
if type(result) ~= "string" then
@@ -164,6 +229,24 @@ local function _controlfn(ctx, name)
return cfn
end
+--- Compile a definition command
+--
+-- Definitions are a core behaviour of Lace. This builtin allows the ruleset
+-- to define additional conditions on which `allow`, `deny` and `include` can
+-- operate.
+--
+-- @tparam table compcontext The compilation context.
+-- @tparam string define The word which triggered this compilation command.
+-- (`define`)
+-- @tparam string name The name being defined.
+-- @tparam string controltype The control type to be used. (Such as `anyof`,
+-- `allof` or any of the match types defined by
+-- the caller of the compiler).
+-- @tparam[opt] string ... The content of the definition (consumed by the
+-- match type compiler).
+-- @treturn table The compiled definition command.
+-- @function commands.define
+-- @alias commands.def
function builtin.define(compcontext, define, name, controltype, ...)
if type(name) ~= "string" then
return err.error("Expected name, got nothing", {1})
@@ -217,6 +300,27 @@ local function _do_include(exec_context, ruleset, conds)
return result, msg
end
+--- Compile an `include` command.
+--
+-- Compile a lace `include` command. This uses the exported internal loader
+-- function `lace.compiler.internal_loader` to find a loader and if it finds
+-- one, it uses the internal compilation function
+-- `lace.compiler.internal_compile` to compile the loaded source before
+-- constructing a runtime "inclusion" which deals with the conditions before
+-- running the sub-ruleset if appropriate.
+--
+-- Regardless of the conditions placed on the include statement, includes are
+-- always processed during compilation.
+--
+-- @tparam table comp_context The compilation context
+-- @tparam string cmd The command which triggered this include command.
+-- (`include` or `include?`)
+-- @tparam string file The file (source name) to include.
+-- @tparam[opt] string ... Zero or more conditions under which the included
+-- content will be run by the engine. If there are no
+-- conditions then the include is unconditional.
+-- @treturn table The compiled inclusion command.
+-- @function commands.include
function builtin.include(comp_context, cmd, file, ...)
local safe_if_not_present = cmd:sub(-1) == "?"
diff --git a/lib/lace/compiler.lua b/lib/lace/compiler.lua
index 1a89897..26a4e23 100644
--- a/lib/lace/compiler.lua
+++ b/lib/lace/compiler.lua
@@ -7,6 +7,12 @@
-- For licence terms, see COPYING
--
+--- The compiler for the Lua Access Control engine.
+--
+-- Lace works hard to give you good error message information when encountering
+-- problems with your rulesets. The compiler gathers a lot of debug
+-- information and stores it alongside the compiled ruleset.
+
local lex = require "lace.lex"
local builtin = require "lace.builtin"
local err = require "lace.error"
@@ -19,6 +25,15 @@ local function _fake_command(ctx)
return err.error("Command is disabled by context")
end
+--- Internal loader abstraction.
+--
+-- Used by `lace.builtin.commands.include`, this function returns a loader
+-- which can be used to acquire more content during compilation of a Lace
+-- ruleset.
+--
+-- @tparam table ctx The Lace compiliation context
+-- @treturn function A loader function
+-- @function internal_loader
local function _loader(ctx)
-- We know the context is a table with a _lace table, so retrieve
-- the loader function. If it's absent, return a loader which
@@ -61,6 +76,18 @@ local function compile_one_line(compcontext, line)
return cmdfn(compcontext, unpack(args))
end
+--- Internal ruleset compilation.
+--
+-- Internal ruleset compilation function. This function should not be used
+-- except from compilation commands such as `lace.builtin.commands.include`.
+-- This function is much less forgiving of issues than `lace.compiler.compile`.
+--
+-- @tparam table compcontext Compilation context
+-- @tparam string sourcename Source name
+-- @tparam string content Source content
+-- @tparam boolean suppress_default Suppress the use of a default rule.
+-- @treturn table Compiled Lace ruleset
+-- @function internal_compile
local function internal_compile_ruleset(compcontext, sourcename, content, suppress_default)
assert(type(compcontext) == "table", "Compilation context must be a table")
assert(type(compcontext._lace) == "table", "Compilation context must contain a _lace table")
@@ -144,6 +171,19 @@ local function internal_compile_ruleset(compcontext, sourcename, content, suppre
return ruleset
end
+--- Compile a lace ruleset.
+--
+-- Compile a lace ruleset so that it can be executed by `lace.engine.run`
+-- later. If you provide content then it is compiled using the source name as
+-- the name used in error messages. If you do not supply any content then Lace
+-- will construct an implicit include of the given source name.
+--
+-- @tparam table ctx Compilation context
+-- @tparam string src Source name
+-- @tparam ?string cnt Source contents (nil to cause an implicit
+-- include of _src_)
+-- @treturn table Compiled Lace ruleset
+-- @function compile
local function compile_ruleset(ctx, src, cnt)
-- Augment the compiler context with a false
-- source so that we can be sure the expect early errors to stand a chance
diff --git a/lib/lace/error.lua b/lib/lace/error.lua
index 29683e4..96998bd 100644
--- a/lib/lace/error.lua
+++ b/lib/lace/error.lua
@@ -7,6 +7,25 @@
-- For licence terms, see COPYING
--
+--- Error routines for Lace ruleset compilers and runtime engines.
+--
+-- Errors are a critical part of anything user-facing. Lace works very
+-- hard to ensure that it can report errors effectively so that the author
+-- of the ruleset (the user of the application which is using Lace) can work
+-- out what went wrong and how to fix it.
+
+--- Report an error.
+--
+-- Report an error, including indicating which words caused the problem.
+-- The words are 1-indexed from the start of whatever routine is trying
+-- to consume words.
+--
+-- @tparam string str The error message.
+-- @tparam {number,...}|nil words A list of the words causing this error.
+-- @tparam boolean rnil Whether to return nil (indicating a programming error).
+-- @treturn boolean|nil,table The compilation result (false or nil) and a
+-- compilation error table
+-- @function error
local function _error(str, words, rnil)
local ret = false
if rnil then
@@ -15,6 +34,16 @@ local function _error(str, words, rnil)
return ret, { msg = str, words = words or {} }
end
+--- Offset an error's recorded wordset.
+--
+-- Since errors carry word indices, if the layers of the compiler or runtime
+-- alter the offsets, this routine can be used to offset the word indices
+-- in an error message.
+--
+-- @tparam table err The error table
+-- @tparam number offs The offset by which to adjust the error words.
+-- @treturn table The error table (mutated by the offset).
+-- @function offset
local function _offset(err, offs)
if not err.words then
err.words = {}
@@ -25,12 +54,35 @@ local function _offset(err, offs)
return err
end
+--- Augment an error with source information
+--
+-- In order for errors to be useful they need to be augmented with the source
+-- document in which they occurred and the line number on which they occurred.
+-- This function allows the compiler (or runtime) to do just that.
+--
+-- @tparam table err The error table to augment
+-- @tparam table source The lexically analysed source document.
+-- @tparam linenr number The line number on which the error occurred.
+-- @treturn table The error table (mutated with the source information).
+-- @function augment
local function _augment(err, source, linenr)
err.source = source
err.linenr = linenr
return err
end
+--- Render an error down to a string.
+--
+-- Error tables carry a message, an optional set of words which caused the
+-- error (if known) and a lexically analysed source and line number.
+--
+-- This function renders that information down to a multiline string which can
+-- usefully be presented to the user of an application using Lace for access
+-- control.
+--
+-- @tparam table err The error table.
+-- @treturn string A multiline string rendering of the error.
+-- @function render
local function _render(err)
-- A rendered error has four lines
-- The first line is the error message
diff --git a/lib/lace/lex.lua b/lib/lace/lex.lua
index d9434b1..1085bed 100644
--- a/lib/lace/lex.lua
+++ b/lib/lace/lex.lua
@@ -7,6 +7,14 @@
-- For Licence terms, see COPYING
--
+--- Lace Internals - Ruleset lexer.
+--
+-- The lexer for Lace is only used internally and is generally not accessed
+-- from outside of Lace. It is exposed only for testing and validation
+-- purposes.
+
+local M = {}
+
local function lex_one_line(line)
local r = {}
local acc = ""
@@ -83,7 +91,12 @@ local function lex_one_line(line)
return r, warnings
end
-local function lex_a_ruleset(ruleset, sourcename)
+--- Lexically analyse a ruleset.
+-- @tparam string ruleset The ruleset to lex.
+-- @tparam string sourcename The name of the source to go into debug info.
+-- @treturn table A list of lexed lines, each line being a table of tokens
+-- with their associated debug information.
+function M.string(ruleset, sourcename)
local lines = {}
local ret = { source = sourcename, lines = lines }
local n = 1
@@ -112,6 +125,4 @@ local function lex_a_ruleset(ruleset, sourcename)
return ret
end
-return {
- string = lex_a_ruleset,
-}
+return M