#.. This File contains rules for making rules and macros and some helper functions to make that easier. # Nil lua code ".." |nomsu:defmacro("nil", function(nomsu, vars) return "nil", nil end) # Macros: lua code ".." |local function parse_as(nomsu, vars) | if vars.shorthand.type ~= "Block" then | nomsu:error("Expected shorthand to be Block, but got "..vars.shorthand.type) | end | if vars.longhand.type ~= "Block" then | nomsu:error("Expected longhand to be Block, but got "..vars.longhand.type) | end | local template = vars.longhand | local function parsing_as(nomsu, vars) | local expanded = nomsu:replaced_vars(template, vars) | local expr,statement = nomsu:tree_to_lua(expanded) | return expr, statement | end | for _,call in ipairs(vars.shorthand.value) do | nomsu:defmacro(call, parsing_as) | end |end |nomsu:def("parse nomsu %shorthand as nomsu %longhand", parse_as) parse nomsu \(parse %shorthand as %longhand) as nomsu \(parse nomsu \%shorthand as nomsu \%longhand) lua code ".." |nomsu:defmacro("lua expr %code", function(nomsu, vars) | return nomsu:tree_to_value(vars.code, vars), nil |end) # Rule that lets you make new rules lua code ".." |nomsu:defmacro("rule %rule_def = %body", function(nomsu, vars) | if vars.rule_def.type ~= "Block" then | nomsu:error("Wrong type for rule definition, expected Block, but got "..vars.rule_def.type) | end | local thunk = nomsu:tree_to_lua({type="Thunk", value=vars.body, src=vars.body.src}) | local fn_name = "fn_"..nomsu:var_to_lua_identifier(nomsu:get_stub(vars.rule_def.value[1])) | local lua = ([[ |do | local %s = %s | for _,alias in ipairs(%s) do | nomsu:def(alias, %s) | end |end]]):format(fn_name, thunk, nomsu:repr(vars.rule_def.value), fn_name) | return nil, lua |end) parse (rule %rule_name) as: lua expr "nomsu.defs[(nomsu:get_stub(\(%rule_name).value[1]))]" # Macro helper functions rule (%tree as value) =: lua expr "nomsu:tree_to_value(vars.tree, vars)" rule (%tree as lua) =: lua expr "nomsu:tree_to_lua(vars.tree)" parse (lua block %block) as: lua code ".." |do | \(%block) |end parse (nomsu) as: lua expr "nomsu" parse (nomsu's %key) as: lua expr "nomsu['\(%key)']" parse (nomsu %method %args) as: lua expr "nomsu['\(%method)'](nomsu, unpack(\(%args)))" parse (repr %) as: nomsu "repr" [%] repr 5 # 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 rule (eval %code; run %code) =: 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: repr (nomsu "tree_to_str" [\%code]) parse (parse %code as lua code %lua) as: parse nomsu \%code as nomsu: nomsu "replaced_vars" [\(lua code %lua), lua expr "vars"] parse (parse %code as lua expr %lua) as: parse nomsu \%code as nomsu: nomsu "replaced_vars" [\(lua expr %lua), lua expr "vars"] parse (parse %code as lua block %lua) as: parse nomsu \%code as nomsu: nomsu "replaced_vars" [\(lua block %lua), lua expr "vars"] parse (pass) as lua code: "" pass