Fine-grained debugging facility in implementation.
Chris Pressey
1 year, 9 months ago
131 | 131 | ---- |
132 | 132 | |
133 | 133 | * Interned strings and modules? Hash-consing, even? |
134 | * Debug per component of implementation (scanner, parser, evaluator, modules) | |
135 | 134 | * Tracebacks, or at least line/column, or at least "in function..." |
136 | 135 | |
137 | 136 | ### Modules |
17 | 17 | local registry = Registry.new() |
18 | 18 | while #arg > 0 do |
19 | 19 | if arg[1] == "--debug" then |
20 | do_debug = true | |
20 | table.remove(arg, 1) | |
21 | debug_what = arg[1] | |
21 | 22 | elseif arg[1] == "--eval" then |
22 | 23 | table.remove(arg, 1) |
23 | 24 | registry.eval_module(arg[1]) |
75 | 75 | elseif head.text() == "let*" then |
76 | 76 | local bindings = ast.tail().head() |
77 | 77 | local body = ast.tail().tail().head() |
78 | if do_debug then | |
78 | do_debug("eval", function() | |
79 | 79 | print("ast:", depict(ast)) |
80 | 80 | print("bindings:", depict(bindings)) |
81 | 81 | print("body:", depict(body)) |
82 | end | |
82 | end) | |
83 | 83 | local new_env = bind_all(bindings, env) |
84 | 84 | return eval_expr(body, new_env) |
85 | 85 | elseif head.text() == "cond" then |
109 | 109 | return f |
110 | 110 | else |
111 | 111 | local fn |
112 | if do_debug then | |
113 | print("head Symbol:", depict(head)) | |
114 | end | |
112 | debug("eval", "head Symbol: " .. depict(head)) | |
115 | 113 | fn = eval_expr(ast.head(), env) |
116 | 114 | local args = eval_exprs(ast.tail(), env) |
117 | if do_debug then | |
115 | do_debug("eval", function() | |
118 | 116 | print(depict(ast.tail())) |
119 | 117 | print(render_table(args)) |
120 | end | |
118 | end) | |
121 | 119 | return fn(args) |
122 | 120 | end |
123 | 121 | else |
124 | 122 | local fn |
125 | if do_debug then | |
126 | print("head:", depict(head)) | |
127 | end | |
123 | debug("eval", "head: " .. depict(head)) | |
128 | 124 | fn = eval_expr(ast.head(), env) |
129 | 125 | return fn(eval_exprs(ast.tail(), env)) |
130 | 126 | end |
119 | 119 | local e = Nil |
120 | 120 | local i |
121 | 121 | for i = #es, 1, -1 do |
122 | if do_debug then | |
122 | do_debug("util", function() | |
123 | 123 | print("--> consing", i, depict(es[i])) |
124 | end | |
124 | end) | |
125 | 125 | e = Cons.new(es[i], e) |
126 | 126 | end |
127 | if do_debug then | |
127 | do_debug("util", function() | |
128 | 128 | print("--> consed", depict(e)) |
129 | end | |
129 | end) | |
130 | 130 | return e |
131 | 131 | end |
140 | 140 | end |
141 | 141 | |
142 | 142 | fields.eval_module_file = function(filename) |
143 | debug("eval_module_file: " .. filename) | |
143 | debug("module", "eval_module_file: " .. filename) | |
144 | 144 | return fields.eval_module(load_file(filename)) |
145 | 145 | end |
146 | 146 | |
151 | 151 | local parser = Parser.new(program_text) |
152 | 152 | local exprs = parser.parse_exprs() |
153 | 153 | for j, expr in ipairs(exprs) do |
154 | debug("eval'ing: " .. depict(expr)) | |
154 | debug("module", "eval'ing: " .. depict(expr)) | |
155 | 155 | env = fields.eval_toplevel(expr, env, module) |
156 | 156 | end |
157 | 157 | |
158 | if do_debug then | |
158 | do_debug("module", function() | |
159 | 159 | for name, value in pairs(module) do |
160 | 160 | print(name .. ": " .. tostring(value)) |
161 | 161 | end |
162 | end | |
162 | end) | |
163 | 163 | |
164 | 164 | module_name = module["module"] |
165 | 165 | if module_name ~= nil then |
180 | 180 | elseif expr.head().text() == "import-from" then |
181 | 181 | local name = expr.tail().head() |
182 | 182 | local symbols = expr.tail().tail().head() |
183 | if do_debug then | |
183 | do_debug("module", function() | |
184 | 184 | print("import_from", env, registry, depict(name), depict(symbols)) |
185 | end | |
185 | end) | |
186 | 186 | env = fields.import_from(env, name.text(), symbols) |
187 | 187 | else |
188 | 188 | local result = eval_expr(expr, env) |
201 | 201 | fields.import_from = function(env, module_name, symbols) |
202 | 202 | local imported_module = modules[module_name] |
203 | 203 | if imported_module == nil and module_path ~= nil then |
204 | fields.load_module(module_path .. module_name .. ".scm") | |
204 | fields.eval_module_file(module_path .. module_name .. ".scm") | |
205 | 205 | imported_module = modules[module_name] |
206 | 206 | end |
207 | 207 | if imported_module == nil then |
208 | 208 | error("Could not locate module: " .. module_name) |
209 | 209 | end |
210 | if do_debug then | |
210 | do_debug("module", function() | |
211 | 211 | print("import...:", render_table(imported_module)) |
212 | end | |
212 | end) | |
213 | 213 | local symbol |
214 | 214 | while symbols ~= Nil do |
215 | 215 | symbol = symbols.head() |
216 | 216 | symbol_name = symbol.text() |
217 | 217 | symbol_value = imported_module[symbol_name] |
218 | if do_debug then | |
218 | do_debug("module", function() | |
219 | 219 | print("imported:", symbol_name, depict(symbol_value)) |
220 | end | |
220 | end) | |
221 | 221 | env = bind(symbol, symbol_value, env) |
222 | 222 | symbols = symbols.tail() |
223 | 223 | end |
225 | 225 | end |
226 | 226 | |
227 | 227 | fields.compile_module_file = function(filename) |
228 | debug("compile_module_file: " .. filename) | |
228 | debug("module", "compile_module_file: " .. filename) | |
229 | 229 | return fields.compile_module(load_file(filename)) |
230 | 230 | end |
231 | 231 | |
234 | 234 | local exprs = parser.parse_exprs() |
235 | 235 | local env = {} |
236 | 236 | for j, expr in ipairs(exprs) do |
237 | debug("compiling: " .. depict(expr)) | |
237 | debug("module", "compiling: " .. depict(expr)) | |
238 | 238 | env = fields.compile_toplevel(expr, env) |
239 | 239 | end |
240 | 240 | end |
241 | 241 | |
242 | 242 | fields.compile_toplevel = function(expr, env) |
243 | debug("compiling toplevel: " .. depict(expr)) | |
243 | debug("module", "compiling toplevel: " .. depict(expr)) | |
244 | 244 | --compile_expr(expr, env) |
245 | 245 | return env |
246 | 246 | end |
62 | 62 | fields.set_token = function(text, type) |
63 | 63 | _text = text |
64 | 64 | _type = type |
65 | debug("set_token " .. text .. " (" .. type .. ")") | |
65 | debug("scanner", "set_token " .. text .. " (" .. type .. ")") | |
66 | 66 | end |
67 | 67 | |
68 | 68 | fields.scan = function() |
69 | 69 | fields.scan_impl() |
70 | debug("scanned '" .. _text .. "' (" .. _type .. ")") | |
70 | debug("scanner", "scanned '" .. _text .. "' (" .. _type .. ")") | |
71 | 71 | return _text |
72 | 72 | end |
73 | 73 | |
181 | 181 | end |
182 | 182 | end |
183 | 183 | |
184 | debug("created scanner with string '" .. string .. "'") | |
184 | debug("scanner", "created scanner with string '" .. string .. "'") | |
185 | 185 | |
186 | 186 | return fields |
187 | 187 | end |
2 | 2 | -- |
3 | 3 | |
4 | 4 | table = require "table" |
5 | string = require "string" | |
5 | 6 | |
6 | 7 | |
7 | 8 | --[[ ========== DEBUG ========= ]]-- |
8 | 9 | |
9 | do_debug = false | |
10 | debug_what = "" | |
10 | 11 | |
11 | debug = function(s) | |
12 | if do_debug then | |
13 | print("--> (" .. s .. ")") | |
12 | do_debug = function(what, fn) | |
13 | if string.find(debug_what, what) then | |
14 | fn() | |
14 | 15 | end |
16 | end | |
17 | ||
18 | debug = function(what, s) | |
19 | do_debug(what, function() print("--> (" .. s .. ")") end) | |
15 | 20 | end |
16 | 21 | |
17 | 22 | render_table = function(t) |