author | Alan Dipert
<alan@dipert.org> 2020-02-13 08:13:38 UTC |
committer | Alan Dipert
<alan@dipert.org> 2020-02-13 08:13:38 UTC |
parent | cb6e331c2bd714d1afcd6c35b8fd91273b72d1a2 |
paper/jacl-els-2020.bib | +201 | -5 |
paper/jacl-els-2020.tex | +87 | -75 |
diff --git a/paper/jacl-els-2020.bib b/paper/jacl-els-2020.bib index 8775d57..a966254 100644 --- a/paper/jacl-els-2020.bib +++ b/paper/jacl-els-2020.bib @@ -1,7 +1,203 @@ @online{Somasegar12, -author ={Soma Somasegar}, -year = 2012, -title ="TypeScript: JavaScript Development at Application Scale", -url ="https://web.archive.org/web/20121003001910/http://blogs.msdn.com/b/somasegar/archive/2012/10/01/typescript-javascript-development-at-application-scale.aspx", -lastaccessed ="February 4, 2020", + author ={Soma Somasegar}, + year = 2012, + title ="TypeScript: JavaScript Development at Application Scale", + url ="https://web.archive.org/web/20121003001910/http://blogs.msdn.com/b/somasegar/archive/2012/10/01/typescript-javascript-development-at-application-scale.aspx", + lastaccessed ="February 4, 2020", +} + +@online{Czaplicki12, + author={Evan Czaplicki}, + year=2012, + title="Elm: Concurrent FRP for Functional GUIs", + url="https://elm-lang.org/assets/papers/concurrent-frp.pdf", + lastaccessed="February 12, 2020", +} + +@misc{wiki:ReasonML, + author = "{Wikipedia contributors}", + title = "Reason (syntax extension for OCaml) --- {W}ikipedia{,} The Free Encyclopedia", + year = "2020", + url = "https://en.wikipedia.org/w/index.php?title=Reason_(syntax_extension_for_OCaml)&oldid=940051580", + note = "[Online; accessed February 12, 2020]" +} + +@online{Cannon07, + author={Howard I. Cannon}, + year=2007, + title="Flavors: A non-hierarchical approach to object-oriented programming", + url="http://www.softwarepreservation.org/projects/LISP/MIT/nnnfla1-20040122.pdf", + lastaccessed="February 12, 2020", +} + +@article{Garnet90, + author = {B. A. Myers et al.}, + title = {Comprehensive Support for Graphical, Highly-Interactive User Interfaces: The Garnet User Interface Development Environment}, + journal = {IEEE Computer}, + issue_date = {November 1990}, + volume = {23}, + number = {11}, + pages = {71-85}, + month = nov, + year = {1990}, + issn = {0018-9162}, + url = {https://doi.org/10.1109/2.60882}, + doi = {10.1109/2.60882}, + publisher = {IEEE}, +} + +@online{Baringer05, + author={Marco Baringer}, + year=2005, + title="Parenscript", + url="https://web.archive.org/web/20051122141019/http://blogs.bl0rg.net/netzstaub/archives/000525.html", + lastaccessed="February 12, 2020", +} + +@online{ParenScriptManual, + author={Marco Baringer, Henrik Hjelte, Vladimir Sedach}, + year={2005-2019}, + title="Parenscript Reference Manual", + url="https://common-lisp.net/project/parenscript/reference.html", + lastaccessed="February 12, 2020", +} + +@online{SLipHome, + author={Mihai Bazon}, + year={2012-2018}, + title="SLip — a Lisp system in JavaScript", + url="http://lisperator.net/slip/", + lastaccessed="February 12, 2020", +} + +@online{SLipImpl, + author={Mihai Bazon}, + year={2012-2018}, + title="Implementation notes", + url="http://lisperator.net/slip/impl", + lastaccessed="February 12, 2020", +} + +@online{SLipVsCl, + author={Mihai Bazon}, + year={2012-2018}, + title="Versus Common Lisp", + url="http://lisperator.net/slip/vscl", + lastaccessed="February 12, 2020", +} + +@book{Norvig92, + author = {Peter Norvig}, + title = {Paradigms of Artificial Intelligence Programming: Case studies in Common Lisp}, + year = {1992}, + isbn = {1-55860-191-0}, + publisher = {Morgan Kaufmann Publishers}, + address = {San Francisco, CA, USA}, +} + +@online{JSCLGitHub, + author={David Vázquez Púa and contributors}, + title="jscl-project/jscl", + url="https://github.com/jscl-project/jscl/", + lastaccessed="February 12, 2020", +} + +@misc{JSCLTalk, + author= {David Vázquez Púa}, + year= {2018}, + title = {Growing a Lisp compiler}, + url= {https://www.youtube.com/watch?v=XT7JYPtWMd8}, + month = {feb}, + lastaccessed = {February 12, 2020}, +} + +@online{CljsUsers, + author={{Cognitect, Inc.}}, + year={2020}, + title="Companies", + url="https://clojurescript.org/community/companies", + lastaccessed="https://clojure.org/community/companies", +} + +@online{Cljs, + author={{Cognitect, Inc.}}, + year={2020}, + title="ClojureScript", + url="https://clojurescript.org/", + lastaccessed="February 12, 2020", +} + +@online{Clojure, + author={{Cognitect, Inc.}}, + year={2020}, + title="Clojure", + url="https://clojure.org/", + lastaccessed="February 12, 2020", +} + +@misc{CljsRelease, + author= {Rich Hickey}, + year= {2012}, + title = {ClojureScript Release}, + url= {https://www.youtube.com/watch?v=tVooR-dF_Ag}, + month = {dec}, + lastaccessed = {February 12, 2020}, +} + +@online{CljsQuickStart, + author={David Nolen}, + year={2020}, + title="ClojureScript Quick Start", + url="https://clojurescript.org/guides/quick-start", + lastaccessed="February 12, 2020", +} + +@online{V8async, + author={Maya Lekova, Benedikt Meurer}, + year={2018}, + month = {nov}, + title="Faster async functions and promises", + url="https://v8.dev/blog/fast-async", + lastaccessed="February 12, 2020", +} + +@online{GDevTools, + author={{Google, Inc.}}, + year={2020}, + title="Chrome DevTools", + url="https://developers.google.com/web/tools/chrome-devtools", + lastaccessed="February 12, 2020", +} + +@software{Rstats, + author = {{R Core Team}}, + title = {R: A Language and Environment for Statistical Computing}, + url = {http://www.R-project.org/}, + version = {3.6.2}, + date = {2019-12-12}, +} + +@software{Rwebsocket, + author = {Alan Dipert and Barbara Borges and Winston Chang and Joe Cheng}, + title = {websocket: 'WebSocket' Client Library}, + url = {https://cran.r-project.org/web/packages/websocket/index.html}, + version = {1.1.0}, + date = {2019-08-08}, +} + +@software{Rchromote, + author = {Winston Chang}, + title = {chromote: Headless Chrome Web Browser Interface}, + url = {https://github.com/rstudio/chromote}, + version = {a28092d8ea08eb6625583ca223f31ed6d0a08980}, + date = {2019-02-07}, +} + +@online{Rees84, + author={Jonathan A. Rees}, + year={1984}, + title="Using EQ instead of EQL to compare catch tags", + url="https://cl-su-ai.cddddr.org/msg00552.html", + lastaccessed="February 12, 2020", + note = "Discussion on CL design mailing list regarding TAGBODY implementation" } \ No newline at end of file diff --git a/paper/jacl-els-2020.tex b/paper/jacl-els-2020.tex index 795283d..71dbba7 100644 --- a/paper/jacl-els-2020.tex +++ b/paper/jacl-els-2020.tex @@ -114,16 +114,17 @@ easily overcome. Developers have responded to these challenges by creating a widening variety of special-purpose programming languages that compile to -JavaScript. [refs] Each new language promotes one or more -paradigms, application architectures, or development workflows, and -claim some advantage relative to the status quo. +JavaScript.\cite{Somasegar12,Czaplicki12,wiki:ReasonML} Each new +language promotes one or more paradigms, application architectures, or +development workflows, and claim some advantage relative to the status +quo. This paper presents one new such language, JavaScript-Assisted Common Lisp (JACL), an implementation of an extended subset of Common Lisp. Unlike contemporary languages, Lisp is closely associated with a history of innovation in the field of large-scale UI development that -predates the existence of the Web. [refs Flavors, Garnet] The design +predates the existence of the Web.\cite{Cannon07,Garnet90} The design of Common Lisp is informed by the lessons learned in pursuit of those and other innovations. @@ -156,10 +157,9 @@ that implement a significant subset of Common Lisp. \subsection{Parenscript} -% https://web.archive.org/web/20051122141019/http://blogs.bl0rg.net/netzstaub/archives/000525.html - -Released in 2005 [ref], Parenscript was the first Common Lisp compiler -to target JavaScript. +Released in 2005\cite{Baringer05}, Parenscript\footnote{Also known as + ParenScript.}\cite{ParenScriptManual} was the first Common Lisp +compiler to target JavaScript. Parenscript is not bootstrapped and its compiler is not written in JavaScript, and so it relies on a hosting Common Lisp system for @@ -175,16 +175,17 @@ JavaScript-behaviors to static Web sites. \subsection{SLip} -% http://lisperator.net/slip/impl - -SLip [ref] is perhaps the most ambitious Common Lisp-on-JavaScript -system created to date. It offers a stunning array of powerful -features including a self-hosting compiler, a full set of control -operators, JavaScript FFI, tail-call optimization, green threads, and -perhaps most impressively, a resident Emacs clone. +SLip\cite{SLipHome,SLipImpl} is arguably the most ambitious Common +Lisp-on-JavaScript system created to date, even though it +intentionally diverges\cite{SLipVsCl} from Common Lisp in certain +ways. It offers a stunning array of powerful features including a +self-hosting compiler, a full set of control operators, JavaScript +FFI, tail-call optimization, green threads, and perhaps most +impressively, a resident Emacs clone. SLip is based originally on the compiler and bytecode interpreter -presented in PAIP [ref]. +presented in Chapter 23 of \emph{Paradigms of Artificial Intelligence + Programming: Case studies in Common Lisp}\cite{Norvig92}. Lisp files may be batch-compiled to FASLs. FASLs represent code as JavaScript code instead of as Lisp data. The browser is able to load @@ -198,11 +199,12 @@ project goal of facilitating large-scale industrial SPA development. \subsection{JSCL} -Of existing Common Lisps, JSCL is the one aligned most closely with -the JACL project goal. Unlike Parenscript, JSCL is a genuine Lisp -system. And unlike SLip, JSCL compiles directly to JavaScript instead -of to an interpreted bytecode. It is self-hosting, includes the major -control operators, and integrates tightly with JavaScript. +Of existing Common Lisps, JSCL\cite{JSCLGitHub,JSCLTalk} is the one +aligned most closely with the JACL project goal. Unlike Parenscript, +JSCL is a genuine Lisp system. And unlike SLip, JSCL compiles directly +to JavaScript instead of to an interpreted bytecode. It is +self-hosting, includes the major control operators, and integrates +tightly with JavaScript. JSCL includes a reader, compiler, and printer, and evaluation is performed by JavaScript's \texttt{eval} function. Between these, a @@ -214,8 +216,9 @@ includes a reference implementation of one. JSCL supports reading from string-backed pseudo-streams. Input streams from which characters may be synchronously consumed are not an abstraction supported by JavaScript in Web browsers. With a few -obscure exceptions [foot], JavaScript programs may only receive input -asynchronously. +obscure exceptions\footnote{\texttt{window.prompt()} and + \texttt{window.confirm()}}, JavaScript programs may only receive +input asynchronously. An error is signaled if the end of a string-backed input stream is encountered before the reader has finished reading a datum. @@ -260,28 +263,28 @@ lexical analysis, and JavaScript AST generation all occur. The lexical environment is maintained in a special variable as the compiler descends into Lisp code and produces JavaScript AST. -Code for \texttt{TAGBODY}/\texttt{GO} is generated in the first -stage, and the generated code is much slower than comparable -JavaScript code for looping. +Code for \texttt{TAGBODY} is generated in the first stage, and the +generated code is much slower than comparable JavaScript code for +looping. -Only the general, dynamic case of \texttt{TAGBODY}/\texttt{GO} is +Only the general, dynamic case of \texttt{TAGBODY} is implemented. Every control transfer initiated by \texttt{GO} results in a JavaScript exception being thrown, which is an expensive operation. Since many Common Lisp operators have \emph{implicit tagbodies}, and since most other iteration operators are expressed in terms of -\texttt{TAGBODY}/\texttt{GO}, this performance problem pervades the -JSCL system. +\texttt{TAGBODY}, this performance problem pervades the JSCL system. -Unfortunately, the first stage of the JSCL compiler does not define -its own AST, and so there is no framework for implementing -sophisticated, staged optimizations, such as those that could mitigate -performance problems like this one. +More efficient ways of implementing \texttt{TAGBODY} are +known\cite{Rees84}, but the implementation of optimizations is not +facilitated by JSCL. Its first stage descends recursively into code in +a single pass. Support for subsequent optimization passes of a +high-level intermediate representation (IR) is not implemented. -Optimizations such as this are particularly important for a Lisp to -JavaScript compiler to perform, because they are exactly the kind that -a JavaScript optimizer could not perform, provided only JavaScript +High-level optimizations are important for a Lisp to JavaScript +compiler to perform, because they are exactly the kind that a +JavaScript optimizer could not later perform, provided only JavaScript code. On the other hand, the arithmetic expression code-size optimizations @@ -291,20 +294,21 @@ performed by a JavaScript optimizer. \subsection{ClojureScript} A discussion of industrial Lisp technology in the SPA setting would be -incomplete without mention of ClojureScript. ClojureScript is probably -the most successful Lisp dialect for building SPAs, at least with -respect to public lists of known users [ref]. +incomplete without mention of ClojureScript.\cite{Cljs} ClojureScript +is probably the most successful Lisp dialect for building SPAs by +number of commercial users.\cite{CljsUsers}. ClojureScript targets JavaScript, and is a dialect of an earlier -language, Clojure, which targets Java Virtual Machine (JVM) -bytecode. Both were designed and initially developed by the same +language, Clojure\cite{Clojure}, which targets Java Virtual Machine +(JVM) bytecode. Both were designed and initially developed by the same person, Rich Hickey. ClojureScript's reader and macro systems were both originally hosted in Clojure, in a manner similar to Parenscript. -Since its introduction, ClojureScript has heavily promoted and -prioritized the ability to produce high-performance deliverables. It -has always been capable of generating JavaScript deliverables amenable -to aggressive optimization by the Google Closure Compiler. +Since its introduction\cite{CljsRelease}, ClojureScript has heavily +promoted and prioritized the ability to produce high-performance +deliverables. It has always been capable of generating JavaScript +deliverables amenable to aggressive optimization by the Google Closure +Compiler. In this respect, ClojureScript aligns closely with the JACL project goal of competitive application performance. In fact, the author's @@ -314,9 +318,10 @@ crucial capability of JACL. Other than the fact that JACL is a Common Lisp and ClojureScript is not, the biggest difference between the two is JACL's promotion of a -dynamic, interactive environment for SPA development. In contrast, the -the typical ClojureScript SPA development workflow is characterized by -alternating batch compilation and whole-program reloading. +browser-based development environment with minimal host-side +tooling. ClojureScript, in contrast, promotes\cite{CljsQuickStart} a +development experience oriented around compilation performed on the +host. \section{Design and Implementation} @@ -352,9 +357,9 @@ Promises, iterators, async functions, async iterators, and the \texttt{await} keyword. These features simplify the JACL implementation and aid its -performance [ref V8 async/await]. It is hoped that JACL will -eventually be written in itself, and that these features will be -accessible from Lisp. +performance\cite{V8async}. It is hoped that JACL will eventually be +written in itself, and that these features will be accessible from +Lisp. The following example demonstrates, in JavaScript, the mechanism by which the JACL reader consumes characters and produces Lisp objects. A @@ -363,22 +368,25 @@ characters asynchronously, and then the resulting Lisp object is printed to the JavaScript console. \begin{verbatim} -let bs = new BufferedStream(), - rdr = new Reader(bs); - -window.setTimeout(() => { - bs.writeEach("123 "); -}, 1000); - -console.log(await rdr.read()); +(async () => { + let bs = new BufferedStream(), + rdr = new Reader(bs); + + window.setTimeout(() => bs.write("1"), 1000); + window.setTimeout(() => bs.write("2"), 2000); + window.setTimeout(() => bs.write("3"), 3000); + window.setTimeout(() => bs.write(" "), 4000); + + console.log(await rdr.read()); +})() \end{verbatim} In the preceding example, \texttt{window.setTimeout()} is used to -enqueue a JavaScript function for execution after 1000 -milliseconds. The enqueued function writes input to the -\texttt{BufferedStream} \texttt{bs}. +enqueue several JavaScript functions for execution after 1000, 2000, +3000, and 4000 milliseconds. Each enqueued function writes a character +of input to the \texttt{BufferedStream} \texttt{bs} when invoked. -Before the enqueued function is invoked, execution proceeds to the +Before any enqueued function is invoked, execution proceeds to the \texttt{console.log} call, but is suspended by the \texttt{await} keyword. @@ -388,8 +396,10 @@ and JavaScript execution remains suspended until the Promise has it represents has completed. \texttt{rdr.read()} is an \texttt{async} function that returns such a Promise. -Once \texttt{rdr} has completed a form, execution continues, and the -number \texttt{123} is printed to the JavaScript console. +Once \texttt{rdr} has completed a form --- in this case, the number +123, after about 4000 milliseconds have elapsed --- execution +continues, and the number \texttt{123} is printed to the JavaScript +console. The ``read'' portion of JACL's REPL is satisfied by first establishing \texttt{BufferedStream} and \texttt{Reader} objects. Then, in an @@ -434,9 +444,9 @@ Instead, JACL offers an alternative development REPL approach that requires minimal host tooling: the DevTools-based REPL. For each tab, Google Chrome is capable of hosting a WebSocket-based -debug endpoint that implements the DevTools Protocol. The Chrome -DevTools Protocol is a standard for JSON object interchange over -WebSocket that makes all of the browser's debugging facilities +debug endpoint that implements the DevTools Protocol.\cite{GDevTools} +The Chrome DevTools Protocol is a standard for JSON object interchange +over WebSocket that makes all of the browser's debugging facilities available remotely, over the network. JACL takes advantage of this feature of Chrome in order to deliver a @@ -468,15 +478,17 @@ Lisp system, and displays characters output from Lisp. While \texttt{jacl-client} presents a synchronous input/output interface, it is actually the frontend for bidirectional asynchronous data transfer. -\texttt{jacl-repl} is currently an R script requiring an R -installation and the installation of two supporting R packages, -\texttt{websocket} and \texttt{chromote}. A standalone binary -executable is imagined in the future. +\texttt{jacl-repl} is currently an R\cite{Rstats} script requiring an +R installation and the installation of two supporting R packages, +\texttt{websocket}\cite{Rwebsocket} and +\texttt{chromote}\cite{Rchromote}. A standalone binary executable is +imagined in the future. JACL has yet to define a printer for its native types, or an extensible print protocol. Currently, object string representations are obtained by calling the generic JavaScript \texttt{toString()} -method, which produces a representation that can't be read back in. +method, which doesn't always produce a representation that can be read +back in. \subsection{High-level analyzing compiler} @@ -1020,8 +1032,8 @@ TODO %% %% The next two lines define the bibliography style to be used, and %% the bibliography file. -%% \bibliographystyle{ACM-Reference-Format} -%% \bibliography{jacl-els-2020} +\bibliographystyle{ACM-Reference-Format} +\bibliography{jacl-els-2020} %% %% If your work has an appendix, this is the place to put it.