~technomancy/fennel#177: 
attempt to index a nil value (local 'source')

While trying to workaround the #176 I've stumped on a kinda weird bug. I've defined the following macro:

(macro defrecord [name ...]
  "Create a constructor and accessor functions for a new record type."
  {:fnl/arglist [name field1 field2 & fields]}
  (let [name (tostring name)
        fields (faccumulate [fields {}
                             i 1 (select :# ...)]
                 (doto fields
                   (tset (tostring (select i ...)) i)))
        metatable {:__newindex
                   (list 'fn [(sym :record#) (sym :f#) (sym :v#)]
                         (list 'rawset (sym :record#) (list '. fields (sym :f#)) (sym :v#)))}
        constructor `(fn [...]
                       `(setmetatable [(,'unquote ...)] ,metatable))
        accessors (collect [f (pairs fields)
                            :into {name constructor}]
                    (.. name :- f)
                    `(fn [,(sym :record#)]
                       `(. (,'unquote ,(sym :record#)) ,(. fields f))))]
    `(macros ,accessors)))

It expands to a bunch of other macros that act as inlined functions:

>> (macrodebug (defrecord foo a b c))
(macros {:foo (fn [...]
                (quote (setmetatable
                        [(unquote ...)]
                        {:__newindex (fn [record# f# v#]
                                       (rawset record# (. {:a 1 :b 2 :c 3} f#) v#))})))
         :foo-a (fn [record#] (quote (. (unquote record#) 1)))
         :foo-b (fn [record#] (quote (. (unquote record#) 2)))
         :foo-c (fn [record#] (quote (. (unquote record#) 3)))})

The weird part is that if I copy the output - it works. But if I just execute the macro above as (defrecord foo a b c) it fails with the error:

Compile error: /data/data/com.termux/files/usr/bin/fennel:3562: attempt to index a nil value (local 'source')

The even weirder part is that removing the setmetatable call from the code that is generated by the defrecord macro makes the error go away.

Status
REPORTED
Submitter
~andreyorst
Assigned to
No-one
Submitted
11 months ago
Updated
a month ago
Labels
bug

~andreyorst 11 months ago*

redacted

~technomancy 11 months ago

It seems like this macro uses nested quoting; do you mean to say it's a duplicate of #176?

~andreyorst 11 months ago*

While it does it's not a duplicate, probably, because the problem with its evaluation resulting with an odd error. As I've described, it can be manually macroexpanded first, then the result can be evaluated without errors, but not fully automatically as it supposed to, unless the newindex metamethod is present.

Register here or Log in to comment, or comment via email.