4 ms·
Debugging layers
- kazinator 11y ago> As the compiler creates an AST from the parse tree, it copies src infos over (sometimes from tokens, sometimes from non-terminals). In the TXR language, the same thing is done by the function rlcp (and a few relatives). I don't remember what "rl" stands for: probably read-time location. You can see rlcp and rl calls throughout this parser: http://www.kylheku.com/cgit/txr/tree/parser.y http://www.kylheku.com/cgit/txr/tree/parser.y In the evaluation module, http://www.kylheku.com/cgit/txr/tree/eval.c http://www.kylheku.com/cgit/txr/tree/eval.c you can see this code: } else if ((macro = lookup_mac(menv, sym))) { val mac_expand = expand_macro(form, macro, menv); if (mac_expand == form) return form; form = rlcp_tree(mac_expand, form); goto tail; User-defined macros aren't expected to do rlcp diligently; so we compensate for their negligence with rlcp_tree(mac_expand, form). This basically liberally sprinkles the source location of the original form over the nodes of the macro-expansion. It works pretty well in practice, helping to relate errors in macro expansions to the original source. rlcp_tree respects nodes that already have source info; it gives it to those which don't have it. Source info is associated with tree nodes using a weak global hash table. When an object with source info attached goes away, the info goes away. Trivial test: macro-error-test.tl: 1: (defmacro mac (expr) 2: expr) 3: (mac (/ 1 0)) $ txr macro-error-test.tl txr: unhandled exception of type numeric-error: txr: possibly triggered at macro-error-test.tl:3 by form (/ 1 0) txr: message: /: division by zero If we change the example to this: 1: (defmacro mac (expr) 2: (copy expr)) 3: (mac (/ 1 0)) the error is exactly the same. This time the expr coming out of the macro is a copy and so it has no source info. The macro expander adds it. This is less accurate: the line number of the macro call isn't necessarily that of the (/ 1 0). Here it happens to be because it's a one-liner expression. Example of an error during macro expansion: 1: (defmacro mac (expr) 2: (/ 1 0)) 3: (mac foo) $ txr macro-error-test-2.tl txr: unhandled exception of type numeric-error: txr: possibly triggered at macro-error-test-2.tl:2 by form (/ 1 0) txr: during expansion at macro-error-test-2.tl:3 of form (mac (/ 1 0)) txr: message: /: division by zero