git » jacl.git » commit 3cbc877

paper

author Alan Dipert
2020-02-21 07:03:56 UTC
committer Alan Dipert
2020-02-21 07:03:56 UTC
parent 497b7f881537dc973c809b90f17b5bc187c1d9ed

paper

paper/jacl-els-2020.tex +54 -60

diff --git a/paper/jacl-els-2020.tex b/paper/jacl-els-2020.tex
index d77c3a4..92c81b7 100644
--- a/paper/jacl-els-2020.tex
+++ b/paper/jacl-els-2020.tex
@@ -178,15 +178,9 @@ standard Lisp atoms and list syntax, but has the potential to be
 stymied by extended syntax, such as that added by reader macros. As
 such, the pre-reader is a separate, degenerate reader that limits
 what's capable of being read by the underlying, full-featured
-synchronous reader.
-
-SLip's reader is also synchronous, and its Emacs clone, Ymacs, also
-includes a pre-reader as part of its Lisp interaction mode. JSCL and
-SLip both demonstrate that when the underlying reader facility is
-synchronous, a REPL cannot effectively be made available at run-time
-because of the asynchrony of input events in JavaScript. In the best
-case, the reader is only partially available through a pre-reader that
-accumulates characters asynchronously.
+synchronous reader. SLip's reader is also synchronous, and its Emacs
+clone, Ymacs, also includes a pre-reader as part of its Lisp
+interaction mode.
 
 \subsubsection{Compiler organization}
 
@@ -195,7 +189,9 @@ JSCL compilation is performed in two stages:
 \begin{itemize}
   \item Conversion from Lisp to a JavaScript Abstract Syntax Tree
     (AST) represented as S-expressions.
-  \item Conversion from JavaScript AST to JavaScript strings.
+  \item Conversion from JavaScript AST to JavaScript strings. Some
+    code-size optimization of arithmetic expressions is also performed
+    in this stage.
 \end{itemize}
 
 The first stage, the conversion from Lisp to JavaScript Abstract
@@ -221,10 +217,10 @@ More efficient ways of implementing \texttt{TAGBODY} are not hard to
 imagine, but the JSCL compiler does not amene itself to the
 implementation of this or other high-level optimizations, as JSCL
 lacks a sufficiently expressive intermediate representation
-(IR). High-level, semantic optimizations and transformations 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.
+(IR). High-level optimizations and transformations 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
 performed by the second, code-generation stage of the JSCL compiler
@@ -246,13 +242,11 @@ 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, experience with,
-and admiration for, ClojureScript is the reason the ability to produce
-high-performance deliverables is considered a crucial capability of
-JACL.
+Compiler. In this respect, ClojureScript aligns closely with the JACL
+project goal of competitive application performance. In fact,
+experience with, and admiration for, ClojureScript is the reason the
+ability to produce high-performance deliverables is considered a
+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
@@ -296,7 +290,7 @@ features will be accessible from Lisp, perhaps as a set of
 implementation-dependent \emph{declaration specifiers} available in
 \texttt{DECLARE} expressions.
 
-The following example demonstrates, in JavaScript, the mechanism by
+The following example demonstrates, in JavaScript, the process by
 which the JACL reader consumes characters and produces Lisp objects. A
 \texttt{BufferedStream} and \texttt{Reader} are instantiated, sent
 characters asynchronously, and then the resulting Lisp object is
@@ -342,11 +336,9 @@ analyzed, compiled, and evaluated.
 
 Concurrently, characters may be sent to the \texttt{BufferedStream}
 instantiated by the REPL by calling its \texttt{write()} or
-\texttt{writeEach()} methods.
-
-Neither character input nor read object consumption impede other
-JavaScript operations, so the JACL REPL model supports embedding in
-applications.
+\texttt{writeEach()} methods. Neither character input nor read object
+consumption impede other JavaScript operations, so the JACL REPL is
+suitable for embedding in applications.
 
 Because of the platform and implementation-dependent nature of JACL's
 reader, JACL does not support Common Lisp input streams, nor its
@@ -356,10 +348,6 @@ functions. Standard interfaces for extending the reader, such as the
 supported. However, the JACL reader does provide an
 implementation-specific way to define reader macros.
 
-JACL's reader is far from supporting all of Common Lisp syntax, but
-its fundamental design is complete and unlikely to substantially
-change.
-
 \subsection{Chrome DevTools REPL}
 
 A browser-based REPL facilitates experimentation with the language by
@@ -401,11 +389,10 @@ anticipated that additional host-side tools that depend on
 \texttt{jacl-client} will be necessary in the future to support
 loading source files in dependency order.
 
-An advantage of the reader approach taken by JACL with respect to the
-implementation of \texttt{jacl-client} is that the REPL client is
-completely ignorant of Lisp syntax and semantics. \texttt{jacl-client}
-merely transfers characters between the host machine and the Lisp
-system and so is \emph{not} a pre-reader.
+Unlike the pre-readers of SLip and JSCL, \texttt{jacl-client} is
+completely ignorant of Lisp syntax. \texttt{jacl-client} merely
+transports characters between the host machine and the Lisp system and
+so is \emph{not} a pre-reader.
 
 There are a few obvious ways the JACL REPL experience could be
 improved. For example, \texttt{jacl-repl} is currently an
@@ -475,8 +462,8 @@ syntax. There must be as many placeholders as there are arguments to
 
 In addition to \texttt{JACL:\%JS}, the JACL compiler currently
 supports three more special operators for interacting with the host
-platform, \texttt{JACL:\%NEW}, \texttt{JACL:\%DOT} and
-\texttt{JACL:\%CALL}. They perform JavaScript object instantiation,
+platform: \texttt{JACL:\%NEW}, \texttt{JACL:\%DOT} and
+\texttt{JACL:\%CALL}. These perform JavaScript object instantiation,
 field access, and function calls, respectively. Since JACL functions
 compile into JavaScript functions, \texttt{JACL:\%CALL} is the basis
 for JACL's \texttt{FUNCALL}, and for function calls generally.
@@ -485,12 +472,13 @@ JACL also supplies a convenience macro, \texttt{JACL:\textbackslash.}
 or ``the dot macro'' for performing a series of field accesses and
 method calls\footnote{Strictly speaking, JavaScript ``method calls''
   are normal function calls but with a particular value of
-  \texttt{this}.} concisely. Dot takes direct inspiration from
-Clojure's \texttt{..} macro. \texttt{JACL:\textbackslash.} expands to
-zero or more nested \texttt{JACL:\%DOT} or \texttt{JACL:\%CALL}
-forms. Here is an example of a \texttt{JACL:\textbackslash.} form ---
-equivalent to the JavaScript expression
-\texttt{(123).toString().length} --- and its corresponding expansion:
+  \texttt{this}.} concisely. The dot macro takes direct inspiration
+from Clojure's \texttt{..} macro. \texttt{JACL:\textbackslash.}
+expands to zero or more nested \texttt{JACL:\%DOT} or
+\texttt{JACL:\%CALL} forms. Here is an example of a
+\texttt{JACL:\textbackslash.} form --- equivalent to the JavaScript
+expression \texttt{(123).toString().length} --- and its corresponding
+expansion:
 
 \begin{verbatim}
 (\. 123 (|toString|) |length|)
@@ -499,7 +487,8 @@ equivalent to the JavaScript expression
 
 Note that JavaScript identifiers are case sensitive, and so
 case-preserving, pipe-delimited Lisp symbols must be used to refer to
-JavaScript object field and method names. The dot macro also
+JavaScript object field and method names. The JACL reader's
+\emph{readtable case} cannot currently be modified. The dot macro also
 recognizes Lisp or JavaScript strings as JavaScript identifiers.
 
 \subsubsection{\texttt{TAGBODY} compilation strategy}
@@ -510,9 +499,9 @@ through the combination of:
 \begin{itemize}
   \item Generating a unique identifier, the \texttt{tbidx}, for each
     \texttt{TAGBODY} encountered during compilation.
-  \item A local JavaScript \texttt{branch} variable containing the tag
-    of the next branch to execute.
-  \item Labeled \texttt{while(true) { ... }} loops each containing a
+  \item A local JavaScript \texttt{branch} variable in the generated
+    code containing the label of the next branch to execute.
+  \item Generated \texttt{while(true) { ... }} loops each containing a
     \texttt{try/catch} statement. The \texttt{catch} arm of the
     \texttt{try/catch} inspects the type of thrown exception, and if
     it is of the marker type \texttt{TagNLX} and corresponds to the
@@ -554,10 +543,10 @@ them, thereby reducing generated code size.
 Code generated for \texttt{TAGBODY} in JACL will still generally
 require a \texttt{switch}, and so a slowdown relative to hand-coded
 JavaScript loops would not be unexpected. However, preliminary
-benchmarking \ref{appendix:hypothetical} of a factorial function on a
+benchmark \ref{appendix:hypothetical} of a factorial function on a
 recent version of Google Chrome revealed only a very small discrepancy
 between JACL's proposed approach and a hand-coded JavaScript
-\texttt{while} loop-based approach.
+\texttt{while} loop-based approach \ref{appendix:baseline}.
 
 \subsection{Delivery}
 
@@ -567,9 +556,10 @@ implemented at all.
 
 Fortunately, since JACL development is image-based, JACL should
 support the traditional approach of specifying a Lisp function
-entrypoint and dumping the Lisp image to native code. SBCL's
-\texttt{SAVE-LISP-AND-DIE} and LispWork's \texttt{DELIVER} function
-are two examples of this in other implementations.
+entrypoint and dumping the Lisp image to native (JavaScript)
+code. SBCL's \texttt{SAVE-LISP-AND-DIE} and LispWork's
+\texttt{DELIVER} function are two examples of this in other
+implementations.
 
 It is imagined that JACL's delivery function will be called in a REPL
 at development time by a developer, or by an automated build
@@ -594,9 +584,6 @@ these definitions can be generated at delivery time. Alternatively,
 statically-linked code could be created automatically in addition to
 dynamically-linked code.
 
-Without experience with the feature, it's hard to know which approach
-to code generation will ultimately be best.
-
 \section{Conclusions and Future Work}
 
 JACL, a new Common Lisp created to ease SPA development, was
@@ -604,10 +591,15 @@ introduced. Four novel aspects of JACL were described with respect to
 other, comparable Lisp implementations:
 
 \begin{enumerate}
-  \item Asynchronous reader.
-  \item Analyzing compiler.
-  \item Chrome DevTools REPL.
-  \item Delivery facility design.
+  \item An asynchronous reader that doesn't necessitate a pre-reader and is suitable for embedded use.
+  \item An analyzing compiler and AST to support high-level
+    optimizations, such as those necessary for a high-performance
+    \texttt{TAGBODY} implementation.
+  \item \texttt{jacl-client}, the Chrome DevTools-based REPL that
+    complements the asynchronous reader to provide a command-line REPL
+    facility on the host.
+  \item The tentative delivery facility design, which will support the
+    creation of competitively small and fast application artifacts.
 \end{enumerate}
 
 Most of Common Lisp that JACL will be capable of supporting remains
@@ -655,6 +647,7 @@ beautiful wife, Sandra Dipert, for her skillful editing.
 \section{Loop Performance Benchmarks}
 
 \subsection{JavaScript Baseline}
+\label{appendix:baseline}
 
 This is a simple JavaScript function for computing the factorial of a
 positive integer as efficiently as possible. Its performance is
@@ -675,6 +668,7 @@ console.log("fact1", performance.now() - start);
 \end{verbatim}
 
 \subsection{Equivalent Lisp}
+\label{appendix:lisp}
 
 The following is an analagous Common Lisp factorial
 function. \texttt{TAGBODY} is the means of iteration. This function