bakpakin / Fennel

Lua Lisp Language
https://fennel-lang.org
MIT License
2.42k stars 124 forks source link

Expose the 'varg' function to the compiler environment #461

Closed homedirectory closed 1 year ago

homedirectory commented 1 year ago

Function varg from fennel.utils returns a symbol representing var args (...). Since this symbol's name starts with a dot, it cannot be constructed using (sym "..."), which would signal an error.

This prevents us from writing macros that need access to the var args symbol.

Example:

(macro define [name ...]
  (let [varg (sym "...")]
    `(fn ,name [,varg]
     ...)))

;; expect (define f [...] (+ 1 2))
(define f (+ 1 2))

Output:

varg.fnl:9:? Compile error: invalid character: .

(define f (+ 1 2))
* Try deleting or replacing ..
* Try avoiding reserved characters like ", \, ', ~, ;, @, `, and comma.
stack traceback:
  [C]: in function 'error'
  /usr/bin/fennel:3702: in function 'assert-compile'
  /usr/bin/fennel:2478: in function 'assert_compile'
  /usr/bin/fennel:2623: in function 'check_binding_valid'
  /usr/bin/fennel:2628: in function ?
  /usr/bin/fennel:1256: in function 'special'
  /usr/bin/fennel:2975: in function ?
  /usr/bin/fennel:3390: in function ?
  /usr/bin/fennel:5374: in function ?
  [C]: in function 'xpcall'
  /usr/bin/fennel:6267: in function ?
  [C]: in ?

I've also tried using (require :fennel.utils) inside a macro to access the varg function. The module is found only when compiled with --no-compiler-sandbox.

technomancy commented 1 year ago

This doesn't work with normal symbols, but it should be possible to get this thru quoting; have you tried:

`(fn ,name [...]
homedirectory commented 1 year ago

@technomancy The example I provided was too simple. I'm actually trying to form an argument list by adding ... to the end. Here is a more realistic example:

(fn defun [name arglist ...]
  (let [args (mandatory-args arglist)]
    (table.insert args varg-sym) ;; need varg-sym
    `(fn ,name ,args
       ;; ommited
       )))
andreyorst commented 1 year ago

(table.insert args '...) should work

homedirectory commented 1 year ago

@andreyorst, it works, thank you. This was almost too simple.