#.. This File contains rules for making rules and macros and some helper functions to make that easier. # Rule to make rules: lua> ".." |nomsu:defmacro("rule %signature = %body", (function(nomsu, vars) | local signature = {}; | for i, alias in ipairs(nomsu:typecheck(vars, "signature", "List").value) do | signature[i] = alias.src; | end | local body = nomsu:typecheck(vars, "body", "Thunk"); | return ([[ |nomsu:def(%s, %s, %s) |]]):format(nomsu:repr(signature), nomsu:tree_to_lua(body), nomsu:repr(nomsu:dedent(nomsu.defs["#macro_tree"].src))), nil; |end), \(__src__)); # Rule to make nomsu macros: rule [parse \%shorthand as \%longhand] =: lua> ".." |local signature = {}; |for i, alias in ipairs(nomsu:typecheck(vars, "shorthand", "List").value) do | signature[i] = alias.src; |end |local template = nomsu:typecheck(vars, "longhand", "Thunk").value; |local function parsing_as(nomsu, vars) # Single expression/statement | if #template == 1 then | local replacement = nomsu:replaced_vars(template[1], vars); | return nomsu:tree_to_lua(replacement); | end # Multiple statements | local lua_bits = {}; | for _,bit in ipairs(template) do | bit = nomsu:replaced_vars(bit, vars); | local expr, statement = nomsu:tree_to_lua(bit); | if statement then table.insert(lua_bits, statement); end | if expr then table.insert(lua_bits, "ret = "..expr..";"); end | end | return nil, table.concat(lua_bits, "\\n"); |end |nomsu:defmacro(signature, parsing_as, \(__src__)); # Rule to make lua macros: rule [compile \%macro_def to \%body] =: lua> ".." |local signature = {}; |for i, alias in ipairs(nomsu:typecheck(vars, "macro_def", "List").value) do | signature[i] = alias.src; |end |local body = nomsu:typecheck(vars, "body", "Thunk"); |local thunk = nomsu:tree_to_value(body); |nomsu:defmacro(signature, thunk, ("compile %s\\n..to %s"):format(vars.macro_def.src, body.src)); rule [compile \%macro_def to code \%body] =: lua> ".." |local signature = {}; |for i, alias in ipairs(nomsu:typecheck(vars, "macro_def", "List").value) do | signature[i] = alias.src; |end |local body = nomsu:typecheck(vars, "body", "Thunk"); |local thunk = nomsu:tree_to_value(body); |local thunk_wrapper = function(nomsu, vars) return nil, thunk(nomsu, vars); end |nomsu:defmacro(signature, thunk_wrapper, ("compile %s\\n..to code %s"):format(vars.macro_def.src, body.src)); rule [remove rule %stub] =: lua> ".." |local def = nomsu.defs[\(%stub)]; |for _, alias in ipairs(def.aliases) do | nomsu.defs[alias] = false; |end rule [%tree as lua] =: =lua "nomsu:tree_to_lua(\(%tree))" rule [%tree as value] =: =lua "nomsu:tree_to_value(\(%tree), vars)" compile [repr %obj] to: "nomsu:repr(\(%obj as lua))" compile [type %obj, type of %obj] to: "type(\(%obj as lua))" parse [lua do> %block] as: lua> "do" lua> %block lua> "end" rule [%tree as lua statement] =: lua do> ".." |local _,statement = nomsu:tree_to_lua(\(%tree)); |return statement; rule [%tree as lua statements] =: lua do> ".." |local lua_bits = {}; |local statements = nomsu:typecheck(vars, "tree", "Thunk").value; |for _,bit in ipairs(statements) do | local expr, statement = nomsu:tree_to_lua(bit); | if statement then table.insert(lua_bits, statement); end | if expr then table.insert(lua_bits, "ret = "..expr..";"); end |end |return table.concat(lua_bits, "\\n"); compile [nomsu] to: "nomsu" compile [nomsu's %key] to: "nomsu[\(%key as lua)]" compile [nomsu %method %args] to: "nomsu[\(%method as lua)](nomsu, unpack(\(%args as lua)))" parse [rule %signature] as: (nomsu's "defs")->(nomsu "get_stub" [\%signature]) # Get the source code for a function rule [help %rule] =: lua do> ".." |local fn_def = nomsu.defs[nomsu:get_stub(vars.rule)] |if not fn_def then | nomsu:writeln("Rule not found: "..nomsu:repr(vars.rule)); |else | nomsu:writeln(fn_def.src or ""); |end # Compiler tools parse [eval %code, run %code] as: nomsu "run" [%code] rule [source code from tree %tree] =: lua do> ".." |local _,_,leading_space = vars.tree.src:find("\\n(%s*)%S"); |if leading_space then | local chunk1, chunk2 = vars.tree.src:match(":%s*([^\\n]*)(\\n.*)"); | chunk2 = chunk2:gsub("\\n"..leading_space, "\\n"); | return chunk1..chunk2.."\\n"; |else | return vars.tree.src:match(":%s*(%S.*)").."\\n"; |end parse [source code %body] as: source code from tree \%body parse [parse tree %code] as: nomsu "tree_to_str" [\%code] parse [enable debugging] as: lua> "nomsu.debug = true" parse [disable debugging] as: lua> "nomsu.debug = false"