git » jacl.git » commit 24f6524

REPL documentation

author Alan Dipert
2020-04-15 07:09:32 UTC
committer Alan Dipert
2020-04-15 07:09:32 UTC
parent d8124102f82f5eb263d7d5c24d58ec7cbb35c510

REPL documentation

RUN.md +125 -0
jacl-tests.lisp +1 -1
jacl.js +2 -2
repl-client/jacl-client.R +13 -2

diff --git a/RUN.md b/RUN.md
new file mode 100644
index 0000000..45f0039
--- /dev/null
+++ b/RUN.md
@@ -0,0 +1,125 @@
+This document describes:
+
+* The purpose of various files in the distribution.
+* How to run the JACL tests in a Web browser.
+* How to connect to a JACL REPL, hosted in Google Chrome, from a
+  host terminal.
+* How to connect to a JACL REPL from within
+  [Emacs](https://www.gnu.org/software/emacs/).
+
+# Files of Interest
+
+* `index.html` is Web page that includes the JACL runtime, compiler,
+  and test suite. Currently, JACL development is performed mostly by
+  making changes and reloading this file in a Web browser to see if
+  anything breaks.
+* `jacl.js` contains the JACL runtime, compiler, and REPL
+  machinery. `jacl.js` will also fetch, compile, and evaluate any
+  `<script type='application/lisp' src=... />` tags found in `<head>`
+  in their order of appearance. Lisp script loading is why `index.html`
+  must be served from a Web browser and not simply from a `file://`
+  URL. JACL uses Ajax to fetch Lisp scripts.
+* `boot.lisp` is where the `COMMON-LISP` package is populated from. It
+  is evaluated by `jacl.js` when `index.html` loads.
+* `jacl-tests.lisp` contains Lisp unit tests and is evaluated after
+  `boot.lisp`.
+* `repl/jacl-client.R` is a JACL REPL client written in R. It is
+  capable of connecting to the WebSocket interface presented by an
+  instance of Google Chrome with remote debugging enabled. It then
+  communicates with JACL over the debugging channel.
+* `repl/jacl` is a shell wrapper around `jacl-client.R`. It is
+  designed to be symlinked from somewhere on your `$PATH` for use as
+  an Emacs
+  [inferior-lisp](https://www.gnu.org/software/emacs/manual/html_node/emacs/External-Lisp.html)
+  program.
+
+# Running JACL Tests
+
+First, you must start a local Web server on localhost:8000 to serve
+this directory. There are many ways to do this, but on a typical Linux
+system, one or both of the following commands will probably work:
+
+    # If you have Python 2:
+    python -m SimpleHTTPServer
+
+    # If you have Python 3:
+    python3 -m http.server
+
+Next, visit http://localhost:8000 with your Web browser of
+choice. JACL development is performed primarily on Google Chrome, but
+other browsers should work.
+
+You should see a page of test results. [QUnit](https://qunitjs.com/)
+
+The JACL runtime and compiler are contained in the file `jacl.js`.
+
+# Connect to a JACL REPL
+
+This task involves downloading R, several R packages, and starting
+Google Chrome with remote debugging enabled. These instructions are
+for Linux but likely work on macOS and Windows 10 with slight
+modification.
+
+## Install R and required R Packages
+
+First, install the latest version of [R](https://www.r-project.org/)
+for your platform. Then, install openssl for your platform:
+
+* deb: libssl-dev (Debian, Ubuntu, etc)
+* rpm: openssl-devel (Fedora, CentOS, RHEL)
+* csw: libssl_dev (Solaris)
+* brew: openssl (Mac OSX)
+
+Next, start R with the `R` command. At the R prompt, evaluate the
+following to install the `remotes` package package from CRAN, R's
+primary package repository:
+
+    install.packages(c("curl", "remotes"))
+
+Now you must install a development package, `chromote`, that is not
+yet on CRAN. `chromote` may be installed from GitHub using the
+`remotes` package you have just installed. At the R prompt, evaluate
+the following:
+
+    remotes::install_github("rstudio/chromote")
+
+After compilation completes, you will be returned to the `>` R
+prompt. You can exit R with `q()`. You need not "Save workspace image"
+when prompted.
+
+## Run Google Chrome with Remote Debugging
+
+If you haven't yet, start a local Web server using the instructions
+under "Run JACL Tests".
+
+Then, start Google Chrome — or Chromium, an open-source alternative —
+using the procedure documented here:
+https://blog.chromium.org/2011/05/remote-debugging-with-chrome-developer.html
+
+Note that the `--user-data-dir` is required; Chrome will not start
+properly unless this directory is specified, exists, and can be
+created or is otherwise writable.
+
+After the browser opens, use it to navigate to
+http://localhost:8000. You should see the JACL tests page.
+
+## Start `jacl`
+
+At this point, you may start a JACL REPL with the following command:
+
+    ./repl-client/jacl
+
+# Connect to a JACL REPL from Emacs
+
+Follow the steps under "Connect to a JACL REPL".
+
+Then, open Emacs, and type `C-u M-x run-lisp`
+
+At the prompt, enter `jacl`
+
+You should be presented with an inferior-lisp buffer in which you may
+evaluate JACL forms.
+
+You may also send forms from Lisp buffers to the JACL REPL for
+evaluation. See the documentation for `lisp-mode` for details and
+applicable key bindings.
diff --git a/jacl-tests.lisp b/jacl-tests.lisp
index 5c266e3..842f191 100644
--- a/jacl-tests.lisp
+++ b/jacl-tests.lisp
@@ -72,7 +72,7 @@
   (tagbody
    start
    (when (> from 0)
-     (log @"from=" from)
+     ;; (log @"from=" from)
      (setq from (1- from))
      (go start))))
 
diff --git a/jacl.js b/jacl.js
index c64329d..6ad45d6 100644
--- a/jacl.js
+++ b/jacl.js
@@ -2180,11 +2180,11 @@ const startRepl = async () => {
   try {
     for await(const obj of replReader) {
       const node = optimize(analyze(emptyEnv, null, obj));
-      console.log(node)
+      // console.log(node)
       const sb = new StringBuffer();
       emitNode(sb.append.bind(sb), node);
       const code = sb.toString();
-      console.log('code="',code,'"');
+      // console.log('code="',code,'"');
       const result = eval(code);
       console.log(result);
     }
diff --git a/repl-client/jacl-client.R b/repl-client/jacl-client.R
index 683f378..7a4b663 100755
--- a/repl-client/jacl-client.R
+++ b/repl-client/jacl-client.R
@@ -9,10 +9,21 @@ invisibly <- function(expr) {
   invisible()
 }
 
+first_id <- function(r) {
+  ts <- r$Target$getTargets()$targetInfos
+  stopifnot(length(ts) > 0)
+  r$Target$getTargets()$targetInfos[[1]]$targetId
+}
+
 # TODO figure out how to use Log instead of deprecated Console
 invisibly({
-  b <- ChromoteSession$new()
-  b$Page$navigate("http://rstudio.local:8000")
+  rc <- ChromeRemote$new(host = "localhost", port = 9222)
+  r <- Chromote$new(browser = rc)
+  tid <- first_id(r)
+  b <- r$new_session(targetId = tid)
+  # The below is for use with headless chrome:
+  #b <- ChromoteSession$new()
+  #b$Page$navigate("http://localhost:8000")
   b$Console$messageAdded(function (msg) { 
     cat(msg$message$text)
     cat('\n> ')