1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
#..
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 .. "\n" .. ([[
|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, "<source can be found in lib/metaprogramming.nom>")
# 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 (do %) =: %
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 <unknown source code>"))
|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"
|