~technomancy/fennel#121: 
allow fennel.view inside of macro sandbox

fennel.view is inaccessible when used through the fennel module from inside a macro module. The code fails when instantiating the macro.

(local fennel (require :fennel))
(fn PP [obj]
  `(print ,(fennel.view obj)))
{: PP}

; (import-macros {: PP} :macros)
; (PP [1 2 3]) ===> attempt to call a nil value (field 'view')

Currently, the workaround is to just use the global view, which is accessible inside of module macros, but it shouldn't hurt to add fennel.view to the sandbox.

Status
RESOLVED IMPLEMENTED
Submitter
~xerool
Assigned to
No-one
Submitted
a month ago
Updated
a month ago
Labels
No labels applied.

~technomancy a month ago

So I guess the question here is how much of the main fennel module do we want to expose inside the sandbox. Of course, nearly everything here which doesn't violate the sandbox is redundant because most of it is already available as a global. But wanting to put it on the module is reasonable IMO because that's the first place you'd look for view. But maybe not for the other functions like list, sym, etc?

{:metadata compiler.metadata :view view :sym-char? utils.sym-char?
       :list utils.list :list? utils.list? :sym utils.sym :sym? utils.sym?
       :sequence utils.sequence :sequence? utils.sequence? :varg utils.varg
       :varg? utils.varg? :comment utils.comment :comment? utils.comment?}

Here's what I'm thinking, but maybe it's overkill? We could just add view too; that would also be reasonable. Not sure what inclusion criteria is best here.

~technomancy a month ago

Looking back at this, the root cause of the problem is a misunderstanding of the macro scope. The whole pattern of requiring fennel in order to get fennel.view is unnecessary because the same function is provided as view in macro scope. The problem is that this is not obvious; everyone is used to getting the function thru the fennel module.

But the fact that (require :fennel) even works at all from inside a macro is ... well, it's a leaky implementation detail. We use it because of the way docstrings work; the compiled output assumes that it can set metadata with require("fennel").metadata. So we include just the minimum shim to allow that; it's not really the fennel module.

The problem is that it's not at all obvious that this is the case. (require :fennel) looks like it works, and it's the expected way that people normally access the view function outside macro scope.

I can't think of a good way to make this clear to people, unless they read the reference very thoroughly. Because of this I'm inclined to let just view thru, and omit the rest, because it's obvious there are better ways to construct symbols and lists in compiler scope.

~technomancy REPORTED IMPLEMENTED a month ago

Just added this.

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