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

COMPILE-APPLICATION and macro exposure #443

Open
mmontone opened this issue Aug 30, 2022 · 7 comments
Open

COMPILE-APPLICATION and macro exposure #443

mmontone opened this issue Aug 30, 2022 · 7 comments

Comments

@mmontone
Copy link

I'm working on an application that uses JSCL, and I'm using COMPILE-APPLICATION after JSCL:BOOTSTRAP, to compile it.
It compiles and works fine, but there's a problem, macros are not exposed to the runtime, and cannot be accessed from the REPL.
I think the environment needs to be dumped for that, as I understand from this comment here:

;;; BOOTSTRAP MAGIC: We record the macro definitions as lists during

We record the macro definitions as lists during the bootstrap. Once everything is compiled, we want to dump the whole global environment to the output file to reproduce it in the run-time.

I tried calling DUMP-GLOBAL-ENVIRONMENT after COMPILE-APPLICATION, but it fails. Am I right about this? Do you have any idea how I can fix this and continue compiling with this approach?

@mmontone
Copy link
Author

mmontone commented Aug 31, 2022

In the mean time, I've managed to implement a bundle-application function:

(defun bundle-application (files output-pathname &key verbose)
  (let ((*features* (list* :jscl :jscl-xc *features*))
        (*package* (find-package "JSCL"))
        (*default-pathname-defaults* jscl::*base-directory*))
    (setq jscl::*environment* (jscl::make-lexenv))
    (jscl::with-compilation-environment
      (with-open-file (out output-pathname
                           :direction :output
                           :if-exists :supersede)
        (format out "(function(){~%")
        (format out "'use strict';~%")
        (write-string (jscl::read-whole-file (jscl::source-pathname "prelude.js")) out)
        (jscl::do-source input :target
          (jscl::!compile-file input out :print verbose))

	;; NOTE: This file must be compiled after the global
        ;; environment. Because some web worker code may do some
        ;; blocking, like starting a REPL, we need to ensure that
        ;; *environment* and other critical special variables are
        ;; initialized before we do this.
        (jscl::!compile-file "src/toplevel.lisp" out :print verbose)

	;; Compile application files

	(dolist (file files)
	  (jscl::!compile-file file out :print nil))
	
	(write-string (jscl::compile-toplevel '(cl:in-package :cl-user)))
	
        (jscl::dump-global-environment out)        
        
        (format out "})();~%")))

    (jscl::report-undefined-functions)))

Takes the list of application files and outputs a self-contained js file, with jscl and the application.
One of the caveats is that I'm having to wrap in-package defintions with (eval-when (:compile-toplevel :load-toplevel :execute)) in application files.

This bundling method allows me to work with files, packages and expose macros in my JSCL application.

Reference: https://codeberg.org/mmontone/interactive-lang-tools/src/branch/master/backends/jscl

@VitoVan
Copy link
Contributor

VitoVan commented Apr 19, 2023

Hi @mmontone , thanks for your work, I managed to use your work to expose custom my functions.

I want to post a minimum working example here for anyone else who might also need this, since I rummaged around for quite a lot of hours (because of my dumbness).

  1. create a file:

main.lisp

(eval-when (:compile-toplevel :load-toplevel :execute)
  (cl:defpackage :c
    (:use cl)
    (:export
     :hello))
  (in-package :c))

(defun hello (name)
    (#j:console:log "Hello" name))

(in-package :cl-user)
  1. load jscl and bootstrap it
sbcl --load jscl.lisp --eval '(jscl:bootstrap)'
  1. copy and paste the bundle-application code above
...
...
...
BUNDLE-APPLICATION
*
  1. bundle main.lisp
(bundle-application (list "main.lisp") "main.js")
  1. in your index.html, replace jscl.js with main.js
    <script>
      var jqconsole = $("#console").jqconsole("", "");
    </script>
-     <script src="jscl.js" type="text/javascript"></script>
+     <script src="main.js" type="text/javascript"></script>
    <script src="jscl-web.js" type="text/javascript"></script>
  1. open your browser, refresh and type this

imagen

@mmontone
Copy link
Author

It is not because of your dumbness. It is not clear how to do this with JSCL, and you need to understand the compiler internals. I came up with this but still I think some things still didn't work (I don't remember the details now).
I'm glad that this worked for you, if I understand correctly. Adding a demo to the repository would be nice, I do that in my projects too, djula and cl-forms for example. That's valuable.

@mmontone
Copy link
Author

Also I remember there was a problem with packages, like in-package not working some times, or not as I would expect.

@VitoVan
Copy link
Contributor

VitoVan commented Apr 19, 2023

It is not because of your dumbness. It is not clear how to do this with JSCL, and you need to understand the compiler internals. I came up with this but still I think some things still didn't work (I don't remember the details now). I'm glad that this worked for you, if I understand correctly. Adding a demo to the repository would be nice, I do that in my projects too, djula and cl-forms for example. That's valuable.

Thank you Mariano, I'm thinking about adding a Wiki page like "JSCL HOW-TO" to include some newbie questions, like:

  • how to alert?
  • how to access JS object in JSCL?
  • how to access JSCL function in JS?
  • how to add JSCL function to DOM event listener as callback?
  • ......

I haven't figured all of them out yet.

@mmontone
Copy link
Author

Those would be great to have IMO; some docs live in issues at the moment and are difficult to find.
Also include this temporary recipe for compiling application code to the wiki.

@VitoVan
Copy link
Contributor

VitoVan commented Apr 20, 2023

Those would be great to have IMO; some docs live in issues at the moment and are difficult to find. Also include this temporary recipe for compiling application code to the wiki.

WIKI: https://github.com/jscl-project/jscl/wiki/JSCL-HOW-TO

Not finished, will continue to write once I got time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants