From bdc4f8a13ad04975ae60ecd00edf5269a1ff0328 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Reuh=20Fildadut?= Date: Tue, 28 May 2024 18:14:10 +0200 Subject: [PATCH] [doc] update gendocs for Anselme standard library and add title and defer tags --- anselme/stdlib/assignment.lua | 23 ++++++- doc/api.md | 5 +- doc/gendocs.lua | 114 +++++++++++++++++++++---------- doc/standard_library.md | 51 ++++++++++++-- doc/standard_library.md.template | 17 +++++ 5 files changed, 162 insertions(+), 48 deletions(-) create mode 100644 doc/standard_library.md.template diff --git a/anselme/stdlib/assignment.lua b/anselme/stdlib/assignment.lua index 7b63a34..9f49c58 100644 --- a/anselme/stdlib/assignment.lua +++ b/anselme/stdlib/assignment.lua @@ -3,6 +3,12 @@ local Nil, Boolean, LuaCall, ParameterTuple, FunctionParameter, Identifier, Over return { { + --- Always return false. + -- Can be used as variable value checking function to prevent any reassignment and thus make the variable constant. + -- ``` + -- :var::constant = 42 + -- ``` + -- @defer value checking "constant", "(exp)", function(state, exp) return Boolean:new(false) @@ -10,6 +16,8 @@ return { }, { + --- Returns true if the expression is a tuple, false otherwise. + -- @defer value checking "is tuple", "(exp)", function(state, exp) return Boolean:new(exp.type == "tuple") @@ -37,13 +45,19 @@ return { }, { - "_=_", "(quote::is quoted(\"identifier\"), value)", function(state, quote, value) + --- Assign `value` to the variable `identifier`. + -- @title identifier = value + "_=_", "(quote::is quoted(\"identifier\"), value)", + function(state, quote, value) state.scope:set(quote.expression, value) return Nil:new() end }, { - "_=_", "(quote::is quoted(\"symbol\"), value)", function(state, quote, value) + --- Define the variable using the symbol `symbol` with the initial value `value`. + -- @title symbol::is symbol = value + "_=_", "(quote::is quoted(\"symbol\"), value)", + function(state, quote, value) local symbol = quote.expression:eval(state) if Overloadable:issub(value) or Overload:is(value) then state.scope:define_overloadable(symbol, value) @@ -54,7 +68,10 @@ return { end }, { - "_=_", "(quote::is quoted(\"tuple\"), value::is tuple)", function(state, quote, tuple) + --- For each `variable` element of the variable tuple and associated `value` element of the value tuple, call `variable = value`. + -- @title variable tuple::is tuple = value tuple::is tuple + "_=_", "(quote::is quoted(\"tuple\"), value::is tuple)", + function(state, quote, tuple) assert(quote.expression:len() == tuple:len(), "left and right tuple do no have the same number of elements") for i, left in quote.expression:iter() do Call:from_operator("_=_", Quote:new(left), tuple:get(i)):eval(state) diff --git a/doc/api.md b/doc/api.md index 055dc1e..0d22c37 100644 --- a/doc/api.md +++ b/doc/api.md @@ -110,9 +110,6 @@ Return a new [State](#state). _defined at line 90 of [anselme/init.lua](../anselme/init.lua):_ `new = function()` ---- -_file generated at 2024-05-25T12:52:49Z_ - # State Contains all state relative to an Anselme interpreter. Each State is fully independant from each other. @@ -299,4 +296,4 @@ Otherwise, each Node has its own module file defined in the [ast/](../ast) direc --- -_file generated at 2024-05-25T12:52:49Z_ +_file generated at 2024-05-28T16:12:56Z_ \ No newline at end of file diff --git a/doc/gendocs.lua b/doc/gendocs.lua index 3b8d732..52e6fe8 100644 --- a/doc/gendocs.lua +++ b/doc/gendocs.lua @@ -5,12 +5,22 @@ local utf8 = utf8 or require("lua-utf8") local files = { - "doc/api.md" + "doc/api.md", + "doc/standard_library.md" } local source_link_prefix = "../" local base_header_level = 2 +local function unescape(str) + return str:gsub("\\(.)", "%1") +end + local title_extractors = { + -- anselme luafunction definition + { "\"(.-)\",%s*\"(.-)\",", function(name, params) + return ("%s %s"):format(unescape(name), unescape(params)) + end }, + -- methods { "(.-)%s*=%s*function%s*%(%s*self%s*%)", ":%1 ()" }, { "(.-)%s*=%s*function%s*%(%s*self%s*%,%s*(.-)%)", ":%1 (%2)" }, @@ -32,44 +42,78 @@ local function extract_block_title(line) return title end +local valid_tags = { title = true, defer = true } local function process(content) + local deferred = {} + return content:gsub("{{(.-)}}", function(lua_file) - local f = io.open(lua_file, "r") - local c = f:read("a") - f:close() - - local output = {} - - local comment_block - local line_no = 1 - for line in c:gmatch("[^\n]*") do - if line:match("^%s*%-%-%-") then - comment_block = {} - table.insert(comment_block, (line:match("^%s*%-%-%-%s?(.-)$"))) - elseif comment_block then - if line:match("^%s*%-%-") then - table.insert(comment_block, (line:match("^%s*%-%-%s?(.-)$"))) - else - if line:match("[^%s]") then - local ident, code = line:match("^(%s*)(.-)$") - table.insert(comment_block, 1, ("%s %s\n"):format( - ("#"):rep(base_header_level+utf8.len(ident)), - extract_block_title(code) - )) - table.insert(comment_block, ("\n_defined at line %s of [%s](%s):_ `%s`"):format(line_no, lua_file, source_link_prefix..lua_file, code)) - end - table.insert(comment_block, "") - table.insert(output, table.concat(comment_block, "\n")) - comment_block = nil - end + -- deferred doc comments + if lua_file:match("^:") then + local defer = lua_file:match("^:(.-)$") + if deferred[defer] then + local output = table.concat(deferred[defer], "\n") + deferred[defer] = nil + return output + else + return "" end - line_no = line_no + 1 + -- lua file + else + local f = io.open(lua_file, "r") + local c = f:read("a") + f:close() + + local output = {} + + local comment_block + local line_no = 1 + for line in c:gmatch("[^\n]*") do + -- doc comment start + if line:match("^%s*%-%-%-") then + comment_block = {} + table.insert(comment_block, (line:match("^%s*%-%-%-%s?(.-)$"))) + elseif comment_block then + -- continue doc comment + if line:match("^%s*%-%-") then + local comment = line:match("^%s*%-%-%s?(.-)$") + if comment:match("^%s*@") then + local tag, data = comment:match("^%s*@%s*([^%s]*)%s*(.-)$") + if valid_tags[tag] then comment_block[tag] = data + else print(("unknown documentation tag @%s, at %s:%s"):format(tag, lua_file, line_no)) end + else + table.insert(comment_block, comment) + end + -- end doc comment + else + if line:match("[^%s]") then + local indent, code = line:match("^(%s*)(.-)$") + if not comment_block.indent then comment_block.indent = utf8.len(indent) end + if not comment_block.title then comment_block.title = extract_block_title(code) end + table.insert(comment_block, ("\n_defined at line %s of [%s](%s):_ `%s`"):format(line_no, lua_file, source_link_prefix..lua_file, code)) + end + if comment_block.title then + table.insert(comment_block, 1, ("%s %s\n"):format( + ("#"):rep(base_header_level+(comment_block.indent or 0)), + comment_block.title + )) + end + table.insert(comment_block, "") + local doc_block = table.concat(comment_block, "\n") + if comment_block.defer then + if not deferred[comment_block.defer] then deferred[comment_block.defer] = {} end + table.insert(deferred[comment_block.defer], doc_block) + else + table.insert(output, doc_block) + end + comment_block = nil + end + end + line_no = line_no + 1 + end + + return table.concat(output, "\n") end - - table.insert(output, ("\n---\n_file generated at %s_"):format(os.date("!%Y-%m-%dT%H:%M:%SZ"))) - - return table.concat(output, "\n") - end) + end) .. ("\n---\n_file generated at %s_"):format(os.date("!%Y-%m-%dT%H:%M:%SZ")) end local function generate_file(input, output) diff --git a/doc/standard_library.md b/doc/standard_library.md index 65718a2..3fd3372 100644 --- a/doc/standard_library.md +++ b/doc/standard_library.md @@ -1,13 +1,52 @@ -TODO generate from source +TODO -# Standard library +# Variable assignment + +TODO intro + +#### identifier = value + +Assign `value` to the variable `identifier`. + +_defined at line 50 of [anselme/stdlib/assignment.lua](../anselme/stdlib/assignment.lua):_ `"_=_", "(quote::is quoted(\"identifier\"), value)",` + +#### symbol::is symbol = value + +Define the variable using the symbol `symbol` with the initial value `value`. + +_defined at line 59 of [anselme/stdlib/assignment.lua](../anselme/stdlib/assignment.lua):_ `"_=_", "(quote::is quoted(\"symbol\"), value)",` + +#### variable tuple::is tuple = value tuple::is tuple + +For each `variable` element of the variable tuple and associated `value` element of the value tuple, call `variable = value`. + +_defined at line 73 of [anselme/stdlib/assignment.lua](../anselme/stdlib/assignment.lua):_ `"_=_", "(quote::is quoted(\"tuple\"), value::is tuple)",` + + +# Value checking TODO -## Variable assignment +#### constant (exp) + +Always return false. +Can be used as variable value checking function to prevent any reassignment and thus make the variable constant. +``` +:var::constant = 42 +``` + +_defined at line 12 of [anselme/stdlib/assignment.lua](../anselme/stdlib/assignment.lua):_ `"constant", "(exp)",` + +#### is tuple (exp) + +Returns true if the expression is a tuple, false otherwise. + +_defined at line 21 of [anselme/stdlib/assignment.lua](../anselme/stdlib/assignment.lua):_ `"is tuple", "(exp)",` + + +# Control flow TODO -## Control flow - -TODO +--- +_file generated at 2024-05-28T16:12:56Z_ \ No newline at end of file diff --git a/doc/standard_library.md.template b/doc/standard_library.md.template new file mode 100644 index 0000000..5bfcb18 --- /dev/null +++ b/doc/standard_library.md.template @@ -0,0 +1,17 @@ +TODO + +# Variable assignment + +TODO intro + +{{anselme/stdlib/assignment.lua}} + +# Value checking + +TODO + +{{:value checking}} + +# Control flow + +TODO