Rewrite the REPL in Lisp using FFI
authorDavid Vázquez <davazp@gmail.com>
Wed, 19 Feb 2014 01:48:57 +0000 (02:48 +0100)
committerDavid Vázquez <davazp@gmail.com>
Wed, 19 Feb 2014 02:05:56 +0000 (03:05 +0100)
jscl.html
src/compiler/compiler.lisp
src/stream.lisp
src/toplevel.lisp
tests-report.lisp
tests.html
tests.lisp

index ade16ec..4e29546 100644 (file)
--- a/jscl.html
+++ b/jscl.html
 <!doctype html>
 <html>
   <head>
-    <style>
-     /* The console container element */
-    body { background-color: black; font-size: 16px; font-family: Courier; overflow: hidden; padding: 0 0 0 0;}
-    #console {
-      position: absolute;
-      top: 0px;
-      bottom: 0px;
-      left: 0px;
-      right: 0px;
-      background-color:black;
-    }
-
-    .parents {
-        font-weight: bold;
-    }
-
-    /* The inner console element. */
-    .jqconsole {
-        padding: 10px;
-    }
-    /* The cursor. */
-    .jqconsole-cursor {
-        background-color: gray;
-    }
-    /* The cursor color when the console looses focus. */
-    .jqconsole-blurred .jqconsole-cursor {
-        background-color: #666;
-    }
-    /* The current prompt text color */
-    .jqconsole-prompt {
-        color: White;
-    }
-    /* The command history */
-    .jqconsole-old-prompt {
-        color: White;
-        font-weight: normal;
-    }
-    /* The text color when in input mode. */
-    .jqconsole-input {
-        color: White;
-    }
-    /* Previously entered input. */
-    .jqconsole-old-input {
-        color: White;
-        font-weight: normal;
-    }
-    /* The text color of the output. */
-    .jqconsole-output {
-        color: green;
-    }
-    .jqconsole-return, .jqconsole-header {
-        color: gray;
-    }
-    .jqconsole-error {
-        color: red;
-    }
-</style>
+    <link rel="stylesheet" href="style.css">
   </head>
-
   <body>
     <div id="console"></div>
-    <script src="jscl.js" type="text/javascript"></script>
     <script src="jquery.js" type="text/javascript" charset="utf-8"></script>
     <script src="jqconsole.min.js" type="text/javascript" charset="utf-8"></script>
-    <script>
-      var jqconsole;
-      $(function () {
-        jqconsole = $('#console').jqconsole('Welcome to JSCL!\n\n', '');
-        jqconsole.RegisterMatching('(', ')', 'parents');
-        if (localStorage.getItem("jqhist"))
-           jqconsole.SetHistory(JSON.parse(localStorage.getItem("jqhist")));
-      
-        lisp.write = function(str){
-           jqconsole.Write(xstring(str), 'jqconsole-output', false);
-           return str;
-        }
-
-        var startPrompt = function () {
-          // Start the prompt with history enabled.
-          jqconsole.Write(lisp.evalString('(CL:PACKAGE-NAME CL:*PACKAGE*)') + '> ', 'jqconsole-prompt');
-          jqconsole.Prompt(true, function (input) {
-            // Output input with the class jqconsole-return.
-            if (input[0] != ','){
-                try {
-                    var vs = lisp.evalInput(input);
-                    // for (var i=0; i<vs.length; i++){
-                       jqconsole.Write(lisp.print(vs) + '\n', 'jqconsole-return');
-                       localStorage.setItem("jqhist", JSON.stringify(jqconsole.GetHistory()));
-                    // }
-                } catch(error) {
-                    var msg = error.message || error || 'Unknown error';
-                    if (typeof(msg) != 'string') msg = xstring(msg);
-                    jqconsole.Write('ERROR: ' + msg + '\n', 'jqconsole-error');
-                }
-            } else
-                jqconsole.Write(lisp.compileString(input.slice(1)) + '\n', 'jqconsole-return');
-
-            // Restart the prompt.
-            startPrompt();
-          }, function(input){
-            try {
-                lisp.read(input[0]==','? input.slice(1): input);
-            } catch(error) {
-                return 0;
-            }
-            return false;
-          });
-        };
-        startPrompt();
-      });
-    </script>
+    <script>var jqconsole = $('#console').jqconsole(';; Welcome to JSCL!\n\n', '');</script>
+    <script src="jscl.js" type="text/javascript"></script>
   </body>
 </html>
index 1ea5259..222f660 100644 (file)
 (define-builtin functionp (x)
   `(bool (=== (typeof ,x) "function")))
 
-(define-builtin %write-string (x)
-  `(method-call |lisp| "write" ,x))
-
 (define-builtin /debug (x)
   `(method-call |console| "log" (call |xstring| ,x)))
 
index 086b145..d08f52c 100644 (file)
@@ -21,6 +21,9 @@
 
 (/debug "loading stream.lisp!")
 
+(defun %write-string (string)
+  (#j:jqconsole:Write string "jqconsole-output"))
+
 (defvar *standard-output*
   (vector 'stream
           (lambda (ch) (%write-string (string ch)))
index 7dddf6e..3c38003 100644 (file)
 
 (defvar *root* (%js-vref "window"))
 
-;;; Set some external entry point to the Lisp implementation to the
-;;; console. It would not be necessary when FFI is finished.
-(let ((*root* #j:lisp))
-  (setf #j:read #'ls-read-from-string)
-  (setf #j:print #'prin1-to-string)
-  (setf #j:eval #'eval)
-  (setf #j:compile (lambda (s) (compile-toplevel s t)))
-  (setf #j:evalString (lambda (str) (eval (ls-read-from-string str))))
-  (setf #j:evalInput (lambda (str) (eval-interactive (ls-read-from-string str))))
-  (setf #j:compileString (lambda (str) (compile-toplevel (ls-read-from-string str) t))))
 
+(defun load-history ()
+  (#j:jqconsole:SetHistory (#j:JSON:parse (#j:localStorage:getItem "jqhist"))))
+
+(defun save-history ()
+  (#j:localStorage:setItem "jqhist" (#j:JSON:stringify (#j:jqconsole:GetHistory))))
+
+(defun toplevel ()
+  (let ((prompt (format nil "~a> " (package-name *package*))))
+    (#j:jqconsole:Write prompt "jqconsole-prompt"))
+  (flet ((process-input (input)
+           (let* ((form (read-from-string input))
+                  (result (multiple-value-list (eval-interactive form))))
+             (dolist (x result)
+               (#j:jqconsole:Write (format nil "~S~%" x) "jqconsole-return"))
+             (save-history)) 
+           (toplevel)))
+    (#j:jqconsole:Prompt t #'process-input)))
+
+
+(defun init (&rest args)
+  (#j:jqconsole:RegisterMatching "(" ")" "parents")
+  (load-history)
+  (toplevel))
+
+(#j:window:addEventListener "load" #'init)
index 19a95a7..1b44496 100644 (file)
@@ -10,3 +10,5 @@
 
 (unless (zerop *unexpected-passes*)
   (format t "~a test(s) passed unexpectedly.~%" *unexpected-passes*))
+
+(terpri)
index 92a5f13..b814558 100644 (file)
@@ -1,76 +1,14 @@
 <!doctype html>
 <html>
   <head>
-    <style>
-     /* The console container element */
-    body { background-color: black; font-size: 16px; font-family: Courier; overflow: hidden; padding: 0 0 0 0;}
-    #console {
-      position: absolute;
-      top: 0px;
-      bottom: 0px;
-      left: 0px;
-      right: 0px;
-      background-color:black;
-    }
-
-    .parents {
-        font-weight: bold;
-    }
-
-    /* The inner console element. */
-    .jqconsole {
-        padding: 10px;
-    }
-    /* The cursor. */
-    .jqconsole-cursor {
-        background-color: gray;
-    }
-    /* The cursor color when the console looses focus. */
-    .jqconsole-blurred .jqconsole-cursor {
-        background-color: #666;
-    }
-    /* The current prompt text color */
-    .jqconsole-prompt {
-        color: White;
-    }
-    /* The command history */
-    .jqconsole-old-prompt {
-        color: White;
-        font-weight: normal;
-    }
-    /* The text color when in input mode. */
-    .jqconsole-input {
-        color: White;
-    }
-    /* Previously entered input. */
-    .jqconsole-old-input {
-        color: White;
-        font-weight: normal;
-    }
-    /* The text color of the output. */
-    .jqconsole-output {
-        color: green;
-    }
-    .jqconsole-return, .jqconsole-header {
-        color: gray;
-    }
-    .jqconsole-error {
-        color: red;
-    }
-</style>
+    <link rel="stylesheet" href="style.css">
   </head>
   <body>
     <div id="console"></div>
     <script src="jquery.js" type="text/javascript" charset="utf-8"></script>
     <script src="jqconsole.min.js" type="text/javascript" charset="utf-8"></script>
+    <script>var jqconsole = $('#console').jqconsole('Running test suit...', '');</script>
     <script src="jscl.js" type="text/javascript"></script>
-    <script>
-      var jqconsole = $('#console').jqconsole();
-      lisp.write = function(str){
-           jqconsole.Write(xstring(str), 'jqconsole-output', false);
-           return str;
-      };
-    </script>
     <script src="tests.js" type="text/javascript"></script>
   </body>
 </html>
index a09ee75..1eca341 100644 (file)
@@ -41,5 +41,6 @@
 (defmacro test-equal (form value)
   `(test (equal ,form, value)))
 
-(format t "Running tests...~%~%")
 (setq *timestamp* (get-internal-real-time))
+
+(terpri)