#.. This File contains rules for making rules and macros and some helper functions to make that easier. # Rule to make rules: lua code ".." |nomsu:defmacro("rule %rule_def = %body", function(nomsu, vars) | local aliases = nomsu:typecheck(vars, "rule_def", "Block").value | local canonical = aliases[1] | local body = nomsu:typecheck(vars, "body", "Block") | local thunk = nomsu:tree_to_lua({type="Thunk", value={type="Statements", value=body.value, src=body.src}, src=body.src}) | local lua = ([[ |nomsu:def(%s, %s, %s) |]]):format(nomsu:repr(canonical.src), thunk, nomsu:repr(body.src)) | if #aliases > 1 then | lua = lua .. ([[ |do | local aliased = %s | local src = %s | local function dealiaser(nomsu, vars) | return nomsu:tree_to_lua(nomsu:replaced_vars(aliased, vars)) | end |]]):format(nomsu:repr(canonical), nomsu:repr(canonical.src)) | for i=2,#aliases do | lua = lua .. ([[ | nomsu:defmacro(%s, dealiaser, %s) |]]):format(nomsu:repr(aliases[i].src), nomsu:repr(canonical.src)) | end | lua = lua .. [[ |end |]] | end | return nil, lua |end, "") # Rule to make nomsu macros: rule (escaped parse %shorthand as %longhand) =: lua code ".." |local aliases = nomsu:typecheck(vars, "shorthand", "Block").value |local template = nomsu:typecheck(vars, "longhand", "Block") |local function parsing_as(nomsu, vars) | local replacement = nomsu:replaced_vars(template, vars) | return nomsu:tree_to_lua(replacement) |end |for _,call in ipairs(aliases) do | nomsu:defmacro(call, parsing_as, template.src) |end escaped parse \(parse %shorthand as %longhand) as \: escaped parse \%shorthand as \%longhand # Rule to make lua macros: rule (escaped compile %macro_def to %body) =: lua code ".." |local aliases = nomsu:typecheck(vars, "macro_def", "Block").value |local body = nomsu:typecheck(vars, "body", "Block") |local thunk = nomsu:tree_to_value({type="Thunk", value={type="Statements", value=body.value, src=body.src}, src=body.src}) |for _,alias in ipairs(aliases) do | nomsu:defmacro(alias, thunk, body.src) |end rule (escaped compile %macro_def to code %body) =: lua code ".." |local aliases = nomsu:typecheck(vars, "macro_def", "Block").value |local body = nomsu:typecheck(vars, "body", "Block") |local thunk = nomsu:tree_to_value({type="Thunk", value={type="Statements", value=body.value, src=body.src}, src=body.src}) |local thunk2 = function(nomsu, vars) return nil, thunk(nomsu, vars) end |for _,alias in ipairs(aliases) do | nomsu:defmacro(alias, thunk2) |end parse (compile %macro_def to %body) as: escaped compile \%macro_def to \%body parse (compile %macro_def to code %body) as: escaped compile \%macro_def to code \%body parse (compile %macro_def to block %body) as: escaped compile \%macro_def to code\: ".." |do | \(%body) |end rule (%tree as lua) =: lua expr "nomsu:tree_to_lua(\(%tree))" rule (%tree as value) =: lua expr "nomsu:tree_to_value(\(%tree), vars)" compile (repr %obj) to: "nomsu:repr(\(%obj as lua))" parse (lua block %block) as: lua code ".." |do | \(%block) |end rule (%tree as lua statement) =: lua block ".." |local _,statement = nomsu:tree_to_lua(\(%tree)) |return statement rule (%tree as lua statements) =: lua block ".." |local statements_tree = {type='Statements', value=\(%tree).value, src=\(%tree).src} |local _,statements = nomsu:tree_to_lua(statements_tree) |return statements 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)))" # Get the source code for a function rule (help %rule) =: lua block ".." |local fn_def = nomsu:get_fn_def(vars.rule) |if not fn_def then | nomsu:writeln("Rule not found: "..nomsu:repr(vars.rule)) |else | nomsu:writeln("rule "..nomsu:repr(nomsu.utils.keys(fn_def.invocation)) | .." ="..(fn_def.src or ":\\n ")) |end # Compiler tools parse (eval %code; run %code) as: nomsu "run" [%code] rule (source code from tree %tree) =: lua block ".." |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 code "nomsu.debug = true" parse (disable debugging) as: lua code "nomsu.debug = false"