Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Part of the code from macro is an array #194

Closed
jcubic opened this issue Nov 4, 2021 · 2 comments
Closed

Part of the code from macro is an array #194

jcubic opened this issue Nov 4, 2021 · 2 comments
Labels
bug Something isn't working
Milestone

Comments

@jcubic
Copy link
Owner

jcubic commented Nov 4, 2021

This is a very specific use case, I've narrowed it down to this reproduction:

(define-macro (define-global first . rest)
  "(define-global var value)
   (define-global (name . args) body)

   Macro that define functions or variables in global context, so they can be used
   inside let and get let variables in closure, Useful for universal macros."
  (if (pair? first)
      (let ((name (car first)))
        `(lips.env.set ,(symbol->string name) (lambda ,(cdr first) ,@rest)))
      `(lips.env.set ,(symbol->string first) ,(car rest))))

(define-macro (globalize expr . rest)
  "(globalize expr)

   Macro will get the value of the expression and add each method as function to global
   scope."
  (let ((obj (eval expr (current-environment)))
        (make-name (if (pair? rest)
                       (let ((prefix (symbol->string (car rest))))
                         (lambda (name) (string->symbol (concat prefix name))))
                       string->symbol)))
    `(begin
       ,@(filter pair?
                 (map (lambda (key)
                        (if (function? (. obj key))
                            (let* ((fname (gensym))
                                   (args (gensym)))
                              `(define-global (,(make-name key) . ,args)
                                 (apply (. ,expr ,key) ,args)))))
                        (array->list (--> Object (keys obj))))))))

(let ((navigator &()))
  (set-global! navigator))

(define LightningFS (require "@isomorphic-git/lightning-fs"))
(define git (require "isomorphic-git"))

(let* ((fs (new LightningFS "fs"))
       (pfs (. fs 'promises)))
  (set-global! fs)
  ;(--> (. git 'plugins) (set "fs" fs))
  (globalize git git.)
  (globalize (let ((x pfs)) x) fs.))

When called from the node it throws an error:

Error: Expecting pair or nil, got array in expression `list->array`
    at typecheck (file:///mnt/ssd/projects/jcubic/lips/repo/src/lips.js:9564:15)
    at recur (file:///mnt/ssd/projects/jcubic/lips/repo/src/lips.js:2326:9)
    at Environment.<anonymous> (file:///mnt/ssd/projects/jcubic/lips/repo/src/lips.js:7447:48)
    at Macro.invoke (file:///mnt/ssd/projects/jcubic/lips/repo/src/lips.js:3240:30)
    at evaluate_macro (file:///mnt/ssd/projects/jcubic/lips/repo/src/lips.js:9758:23)
    at evaluate (file:///mnt/ssd/projects/jcubic/lips/repo/src/lips.js:9889:22)
    at ret (file:///mnt/ssd/projects/jcubic/lips/repo/src/lips.js:9763:30)
    at async exec_lambda (file:///mnt/ssd/projects/jcubic/lips/repo/src/lips.js:9964:53)
    at async run (file:///mnt/ssd/projects/jcubic/lips/repo/bin/lips.js:69:16)
[1]: (begin
       . #(((define-global (fs.init . #:g209)
                           (apply (. (let ((x pfs))
                                       x)
                                     "init")
                                  #:g209))
            (define-global (fs.readFile . #:g211)
                           (apply (. (let ((x pfs))
                                       x)
                                     "readFile")
                                  #:g211))
....
@jcubic jcubic added the bug Something isn't working label Nov 4, 2021
@jcubic
Copy link
Owner Author

jcubic commented Nov 4, 2021

Note that in the standard library there is almost the same macro globalize but it returns (let ...)

jcubic added a commit that referenced this issue Nov 4, 2021
Fix issue with `quasiquote` and `unquote-splicing`
Where it was returning array because unpromise callback
was ignored and this cases some weird errors
@jcubic
Copy link
Owner Author

jcubic commented Nov 4, 2021

Here is shorter reproduction:

(define-macro (make-global first . rest)
  (if (pair? first)
      (let ((name (car first)))
        `(lips.env.set ,(symbol->string name) (lambda ,(cdr first) ,@rest)))
      `(lips.env.set ,(symbol->string first) ,(car rest))))


(define (bar items . rest)
   (let ((input (eval items (current-environment)))
         (make-name (if (pair? rest)
                       (let ((pre (symbol->string (car rest))))
                         (lambda (name) (string->symbol (concat pre name))))
                       string->symbol)))
     `(begin ,@(filter pair?
                       (map (lambda (key)
                              (if (function? (. input key))
                                  (let ((var (make-name key)))
                                    `(make-global (,var) ,key))))
                            (array->list (Object.keys input)))))))

(define LightningFS (require "@isomorphic-git/lightning-fs"))
(let ((navigator &()))
  (set-global! navigator))

(require "fake-indexeddb/auto")

(define fs (new LightningFS "FS"))

(pprint (bar '(let ((pfs fs.promises)) pfs) 'fs-))

The problem was that unquote-splicing was returning an array, because unquote([ ... ] just returned the argument so it was in fact ignored.

@jcubic jcubic closed this as completed Nov 4, 2021
@jcubic jcubic added this to the 1.0 milestone Nov 4, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant