]> gitweb.factorcode.org Git - factor.git/commitdiff
FUEL: Stack inference support.
authorJose A. Ortega Ruiz <jao@gnu.org>
Sat, 20 Dec 2008 15:51:05 +0000 (16:51 +0100)
committerJose A. Ortega Ruiz <jao@gnu.org>
Sat, 20 Dec 2008 15:51:05 +0000 (16:51 +0100)
extra/fuel/fuel.factor
misc/fuel/README
misc/fuel/fuel-autodoc.el [new file with mode: 0644]
misc/fuel/fuel-base.el
misc/fuel/fuel-completion.el
misc/fuel/fuel-eval.el
misc/fuel/fuel-help.el
misc/fuel/fuel-mode.el
misc/fuel/fuel-stack.el [new file with mode: 0644]
misc/fuel/fuel-syntax.el

index 1c8bfd1522c21ac36cbec7d14759b890362370be..0b81696ad4c70f1722a00a7b1e6ee84c7898d2fe 100644 (file)
@@ -43,15 +43,14 @@ t clone fuel-eval-res-flag set-global
 
 : pop-fuel-status ( -- )
     fuel-status-stack get empty? [
-        fuel-status-stack get pop {
-            [ in>> in set ]
-            [ use>> clone use set ]
-            [
-                restarts>> fuel-eval-restartable? [ drop ] [
-                    clone restarts set-global
-                ] if
-            ]
-        } cleave
+        fuel-status-stack get pop
+        [ in>> in set ]
+        [ use>> clone use set ]
+        [
+            restarts>> fuel-eval-restartable? [ drop ] [
+                clone restarts set-global
+            ] if
+        ] tri
     ] unless ;
 
 
index 5073980dbd7b1322050a2fa52db105c8e4ee8a7c..c05761765c9e0237dedced0b57c98a7f0932c8ca 100644 (file)
@@ -68,6 +68,7 @@ C-cC-eC-r is the same as C-cC-er)).
  - C-cC-da : toggle autodoc mode
  - C-cC-dd : help for word at point
  - C-cC-ds : short help word at point
+ - C-cC-de : show stack effect of current sexp (with prefix, region)
 
 * In the listener:
 
diff --git a/misc/fuel/fuel-autodoc.el b/misc/fuel/fuel-autodoc.el
new file mode 100644 (file)
index 0000000..ddeea35
--- /dev/null
@@ -0,0 +1,95 @@
+;;; fuel-autodoc.el -- doc snippets in the echo area
+
+;; Copyright (C) 2008 Jose Antonio Ortega Ruiz
+;; See http://factorcode.org/license.txt for BSD license.
+
+;; Author: Jose Antonio Ortega Ruiz <jao@gnu.org>
+;; Keywords: languages, fuel, factor
+;; Start date: Sat Dec 20, 2008 00:50
+
+;;; Comentary:
+
+;; Utilities for displaying information automatically in the echo
+;; area.
+
+;;; Code:
+
+(require 'fuel-eval)
+(require 'fuel-syntax)
+(require 'fuel-base)
+
+\f
+;;; Customization:
+
+(defgroup fuel-autodoc nil
+  "Options controlling FUEL's autodoc system"
+  :group 'fuel)
+
+(defcustom fuel-autodoc-minibuffer-font-lock t
+  "Whether to use font lock for info messages in the minibuffer."
+  :group 'fuel-autodoc
+  :type 'boolean)
+
+\f
+;;; Autodoc mode:
+
+(defvar fuel-autodoc--font-lock-buffer
+  (let ((buffer (get-buffer-create " *fuel help minibuffer messages*")))
+    (set-buffer buffer)
+    (fuel-font-lock--font-lock-setup)
+    buffer))
+
+(defun fuel-autodoc--font-lock-str (str)
+  (set-buffer fuel-autodoc--font-lock-buffer)
+  (erase-buffer)
+  (insert str)
+  (let ((font-lock-verbose nil)) (font-lock-fontify-buffer))
+  (buffer-string))
+
+(defun fuel-autodoc--word-synopsis (&optional word)
+  (let ((word (or word (fuel-syntax-symbol-at-point)))
+        (fuel-log--inhibit-p t))
+    (when word
+      (let* ((cmd (if (fuel-syntax--in-using)
+                      `(:fuel* (,word fuel-vocab-summary) t t)
+                    `(:fuel* (((:quote ,word) synopsis :get)) t)))
+             (ret (fuel-eval--send/wait cmd 20))
+             (res (fuel-eval--retort-result ret)))
+        (when (and ret (not (fuel-eval--retort-error ret)) (stringp res))
+          (if fuel-autodoc-minibuffer-font-lock
+              (fuel-autodoc--font-lock-str res)
+            res))))))
+
+(make-variable-buffer-local
+ (defvar fuel-autodoc--fallback-function nil))
+
+(defun fuel-autodoc--eldoc-function ()
+  (or (and fuel-autodoc--fallback-function
+           (funcall fuel-autodoc--fallback-function))
+      (fuel-autodoc--word-synopsis)))
+
+(make-variable-buffer-local
+ (defvar fuel-autodoc-mode-string " A"
+   "Modeline indicator for fuel-autodoc-mode"))
+
+(define-minor-mode fuel-autodoc-mode
+  "Toggle Fuel's Autodoc mode.
+With no argument, this command toggles the mode.
+Non-null prefix argument turns on the mode.
+Null prefix argument turns off the mode.
+
+When Autodoc mode is enabled, a synopsis of the word at point is
+displayed in the minibuffer."
+  :init-value nil
+  :lighter fuel-autodoc-mode-string
+  :group 'fuel-autodoc
+
+  (set (make-local-variable 'eldoc-documentation-function)
+       (when fuel-autodoc-mode 'fuel-autodoc--eldoc-function))
+  (set (make-local-variable 'eldoc-minor-mode-string) nil)
+  (eldoc-mode fuel-autodoc-mode)
+  (message "Fuel Autodoc %s" (if fuel-autodoc-mode "enabled" "disabled")))
+
+\f
+(provide 'fuel-autodoc)
+;;; fuel-autodoc.el ends here
index 1a7cf4fbe6b7b157733e6648234b5eedd0025aa0..17633a22ce16d7dc04977da7a71c37832c243a7d 100644 (file)
                                  (current-buffer)))
           (complete-with-action action (funcall fun string) string pred))))))
 
+(when (not (fboundp 'looking-at-p))
+  (defsubst looking-at-p (regexp)
+    (let ((inhibit-changing-match-data t))
+      (looking-at regexp))))
+
 \f
 ;;; Utilities
 
                                 " ")
                      len))
 
+(defsubst fuel--region-to-string (begin &optional end)
+  (mapconcat 'identity
+             (split-string (buffer-substring-no-properties begin
+                                                           (or end (point)))
+                           nil
+                           t)
+             " "))
+
 (defsubst empty-string-p (str) (equal str ""))
 
 (defun fuel--string-prefix-p (prefix str)
index 953a349d2fcbe4a2597122704588ee4db7408307..6f08e0c4cdffc881c0a47c0a4e901c06394def84 100644 (file)
@@ -178,7 +178,7 @@ terminates a current completion."
 Perform completion similar to Emacs' complete-symbol."
   (interactive)
   (let* ((end (point))
-         (beg (fuel-syntax--symbol-start))
+         (beg (fuel-syntax--beginning-of-symbol-pos))
          (prefix (buffer-substring-no-properties beg end))
          (result (fuel-completion--complete prefix (fuel-syntax--in-using)))
          (completions (car result))
index 871d8c0ae6ce2ea4137597211c20cb2830c9ff09..32073f90531a82ca20d4c58b0698c79c35cecae8 100644 (file)
   (cond ((null sexp) "f")
         ((eq sexp t) "t")
         ((or (stringp sexp) (numberp sexp)) (format "%S" sexp))
-        ((vectorp sexp) (cons :quotation (append sexp nil)))
+        ((vectorp sexp) (factor (cons :quotation (append sexp nil))))
         ((listp sexp)
          (case (car sexp)
            (:array (factor--seq 'V{ '} (cdr sexp)))
            (:quote (format "\\ %s" (factor `(:factor ,(cadr sexp)))))
            (:quotation (factor--seq '\[ '\] (cdr sexp)))
+           (:using (factor `(USING: ,@(cdr sexp) :end)))
            (:factor (format "%s" (mapconcat 'identity (cdr sexp) " ")))
            (:fuel (factor--fuel-factor (cons :rs (cdr sexp))))
            (:fuel* (factor--fuel-factor (cons :nrs (cdr sexp))))
@@ -43,6 +44,7 @@
                    (:in (fuel-syntax--current-vocab))
                    (:usings `(:array ,@(fuel-syntax--usings)))
                    (:get 'fuel-eval-set-result)
+                   (:end '\;)
                    (t `(:factor ,(symbol-name sexp))))))
         ((symbolp sexp) (symbol-name sexp))))
 
index 2154cbebd63a2e18eb0c10ca9c50d02e62b17d97..cc9ac6a1361ffeeae9bca18034342936b52ccaa5 100644 (file)
@@ -15,6 +15,7 @@
 ;;; Code:
 
 (require 'fuel-eval)
+(require 'fuel-autodoc)
 (require 'fuel-completion)
 (require 'fuel-font-lock)
 (require 'fuel-base)
   "Options controlling FUEL's help system"
   :group 'fuel)
 
-(defcustom fuel-help-minibuffer-font-lock t
-  "Whether to use font lock for info messages in the minibuffer."
-  :group 'fuel-help
-  :type 'boolean)
-
 (defcustom fuel-help-always-ask t
   "When enabled, always ask for confirmation in help prompts."
   :type 'boolean
   :group 'fuel-help
   :group 'faces)
 
-\f
-;;; Autodoc mode:
-
-(defvar fuel-help--font-lock-buffer
-  (let ((buffer (get-buffer-create " *fuel help minibuffer messages*")))
-    (set-buffer buffer)
-    (fuel-font-lock--font-lock-setup)
-    buffer))
-
-(defun fuel-help--font-lock-str (str)
-  (set-buffer fuel-help--font-lock-buffer)
-  (erase-buffer)
-  (insert str)
-  (let ((font-lock-verbose nil)) (font-lock-fontify-buffer))
-  (buffer-string))
-
-(defun fuel-help--word-synopsis (&optional word)
-  (let ((word (or word (fuel-syntax-symbol-at-point)))
-        (fuel-log--inhibit-p t))
-    (when word
-      (let* ((cmd (if (fuel-syntax--in-using)
-                      `(:fuel* (,word fuel-vocab-summary) t t)
-                    `(:fuel* (((:quote ,word) synopsis :get)) t)))
-             (ret (fuel-eval--send/wait cmd 20))
-             (res (fuel-eval--retort-result ret)))
-        (when (and ret (not (fuel-eval--retort-error ret)) (stringp res))
-          (if fuel-help-minibuffer-font-lock
-              (fuel-help--font-lock-str res)
-            res))))))
-
-(make-variable-buffer-local
- (defvar fuel-autodoc-mode-string " A"
-   "Modeline indicator for fuel-autodoc-mode"))
-
-(define-minor-mode fuel-autodoc-mode
-  "Toggle Fuel's Autodoc mode.
-With no argument, this command toggles the mode.
-Non-null prefix argument turns on the mode.
-Null prefix argument turns off the mode.
-
-When Autodoc mode is enabled, a synopsis of the word at point is
-displayed in the minibuffer."
-  :init-value nil
-  :lighter fuel-autodoc-mode-string
-  :group 'fuel
-
-  (set (make-local-variable 'eldoc-documentation-function)
-       (when fuel-autodoc-mode 'fuel-help--word-synopsis))
-  (set (make-local-variable 'eldoc-minor-mode-string) nil)
-  (eldoc-mode fuel-autodoc-mode)
-  (message "Fuel Autodoc %s" (if fuel-autodoc-mode "enabled" "disabled")))
-
 \f
 ;;; Help browser history:
 
@@ -116,8 +60,6 @@ displayed in the minibuffer."
         (make-ring fuel-help-history-cache-size)   ; previous
         (make-ring fuel-help-history-cache-size))) ; next
 
-(defvar fuel-help--history-idx 0)
-
 (defun fuel-help--history-push (term)
   (when (and (car fuel-help--history)
              (not (string= (caar fuel-help--history) (car term))))
index 714b9f01042c944a4700cd2a9262b3aedfb16940..e1e361f366ab30d698d5f4f8465a53742e370e67 100644 (file)
 
 (require 'fuel-listener)
 (require 'fuel-completion)
+(require 'fuel-debug)
 (require 'fuel-eval)
 (require 'fuel-help)
-(require 'fuel-debug)
+(require 'fuel-stack)
+(require 'fuel-autodoc)
 (require 'fuel-font-lock)
 (require 'fuel-syntax)
 (require 'fuel-base)
   :group 'fuel)
 
 (defcustom fuel-mode-autodoc-p t
-  "Whether `fuel-autodoc-mode' gets enable by default in fuel buffers."
+  "Whether `fuel-autodoc-mode' gets enabled by default in factor buffers."
+  :group 'fuel-mode
+  :type 'boolean)
+
+(defcustom fuel-mode-stack-p nil
+  "Whether `fuel-stack-mode' gets enabled by default in factor buffers."
   :group 'fuel-mode
   :type 'boolean)
 
@@ -73,7 +80,7 @@ With prefix argument, ask for the file to run."
 
 (defun fuel-eval-region (begin end &optional arg)
   "Sends region to Fuel's listener for evaluation.
-Unless called with a prefix, switchs to the compilation results
+Unless called with a prefix, switches to the compilation results
 buffer in case of errors."
   (interactive "r\nP")
   (let* ((lines (split-string (buffer-substring-no-properties begin end)
@@ -89,9 +96,9 @@ buffer in case of errors."
      (buffer-file-name))))
 
 (defun fuel-eval-extended-region (begin end &optional arg)
-  "Sends region extended outwards to nearest definitions,
+  "Sends region, extended outwards to nearest definition,
 to Fuel's listener for evaluation.
-Unless called with a prefix, switchs to the compilation results
+Unless called with a prefix, switches to the compilation results
 buffer in case of errors."
   (interactive "r\nP")
   (fuel-eval-region (save-excursion (goto-char begin) (mark-defun) (point))
@@ -100,7 +107,7 @@ buffer in case of errors."
 
 (defun fuel-eval-definition (&optional arg)
   "Sends definition around point to Fuel's listener for evaluation.
-Unless called with a prefix, switchs to the compilation results
+Unless called with a prefix, switches to the compilation results
 buffer in case of errors."
   (interactive "P")
   (save-excursion
@@ -188,7 +195,10 @@ interacting with a factor listener is at your disposal.
   :keymap fuel-mode-map
 
   (setq fuel-autodoc-mode-string "/A")
-  (when fuel-mode-autodoc-p (fuel-autodoc-mode fuel-mode)))
+  (when fuel-mode-autodoc-p (fuel-autodoc-mode fuel-mode))
+
+  (setq fuel-stack-mode-string "/S")
+  (when fuel-mode-stack-p (fuel-stack-mode fuel-mode)))
 
 \f
 ;;; Keys:
@@ -220,6 +230,7 @@ interacting with a factor listener is at your disposal.
 
 (fuel-mode--key ?d ?a 'fuel-autodoc-mode)
 (fuel-mode--key ?d ?d 'fuel-help)
+(fuel-mode--key ?d ?e 'fuel-stack-effect-sexp)
 (fuel-mode--key ?d ?s 'fuel-help-short)
 
 \f
diff --git a/misc/fuel/fuel-stack.el b/misc/fuel/fuel-stack.el
new file mode 100644 (file)
index 0000000..3a19a59
--- /dev/null
@@ -0,0 +1,132 @@
+;;; fuel-stack.el -- stack inference help
+
+;; Copyright (C) 2008 Jose Antonio Ortega Ruiz
+;; See http://factorcode.org/license.txt for BSD license.
+
+;; Author: Jose Antonio Ortega Ruiz <jao@gnu.org>
+;; Keywords: languages, fuel, factor
+;; Start date: Sat Dec 20, 2008 01:08
+
+;;; Comentary:
+
+;; Utilities and a minor mode to show inferred stack effects in the
+;; echo area.
+
+;;; Code:
+
+(require 'fuel-autodoc)
+(require 'fuel-syntax)
+(require 'fuel-eval)
+(require 'fuel-base)
+
+\f
+;;; Customization
+
+(defgroup fuel-stack nil
+  "Customization for FUEL's stack inference engine"
+  :group 'fuel)
+
+(defface fuel-font-lock-stack-region (face-user-default-spec 'highlight)
+  "Face used to highlight the region whose stack effect is shown"
+  :group 'fuel-stack
+  :group 'faces)
+
+(defcustom fuel-stack-highlight-period 2
+  "Time, in seconds, the region is highlighted when showing its
+stack effect.
+
+Set it to 0 to disable highlighting."
+  :group 'fuel-stack
+  :type 'float)
+
+(defcustom fuel-stack-mode-show-sexp-p t
+  "Whether to show in the echo area the sexp together with its stack effect."
+  :group 'fuel-stack
+  :type 'boolean)
+
+\f
+;;; Querying for stack effects
+
+(defun fuel-stack--infer-effect (str)
+  (let ((cmd `(:fuel*
+               ((:using stack-checker effects)
+                ([ (:factor ,str) ] infer effect>string :get)))))
+    (fuel-eval--retort-result (fuel-eval--send/wait cmd 500))))
+
+(defsubst fuel-stack--infer-effect/prop (str)
+  (let ((e (fuel-stack--infer-effect str)))
+    (when e
+      (put-text-property 0 (length e) 'face 'factor-font-lock-stack-effect e))
+    e))
+
+(defvar fuel-stack--overlay
+  (let ((overlay (make-overlay 0 0)))
+    (overlay-put overlay 'face 'fuel-font-lock-stack-region)
+    (delete-overlay overlay)
+    overlay))
+
+(defun fuel-stack-effect-region (begin end)
+  "Displays the inferred stack effect of the code in current region."
+  (interactive "r")
+  (when (> fuel-stack-highlight-period 0)
+    (move-overlay fuel-stack--overlay begin end))
+  (condition-case nil
+      (let* ((str (fuel--region-to-string begin end))
+             (effect (fuel-stack--infer-effect/prop str)))
+        (if effect (message "%s" effect)
+          (message "Couldn't infer effect for '%s'"
+                   (fuel--shorten-region begin end 60)))
+        (sit-for fuel-stack-highlight-period))
+    (error))
+  (delete-overlay fuel-stack--overlay))
+
+(defun fuel-stack-effect-sexp (&optional arg)
+  "Displays the inferred stack effect for the current sexp.
+With prefix argument, use current region instead"
+  (interactive "P")
+  (if arg
+      (call-interactively 'fuel-stack-effect-region)
+    (fuel-stack-effect-region (1+ (fuel-syntax--beginning-of-sexp-pos))
+                              (if (looking-at-p ";") (point)
+                                (fuel-syntax--end-of-symbol-pos)))))
+
+\f
+;;; Stack mode:
+
+(make-variable-buffer-local
+ (defvar fuel-stack-mode-string " S"
+   "Modeline indicator for fuel-stack-mode"))
+
+(defun fuel-stack--eldoc ()
+  (when (looking-at-p " \\|$")
+    (let* ((r (fuel--region-to-string (1+ (fuel-syntax--beginning-of-sexp-pos))))
+           (e (fuel-stack--infer-effect/prop r)))
+      (when e
+        (if fuel-stack-mode-show-sexp-p
+            (concat (fuel--shorten-str r 30) ": " e)
+          e)))))
+
+(define-minor-mode fuel-stack-mode
+  "Toggle Fuel's Stack mode.
+With no argument, this command toggles the mode.
+Non-null prefix argument turns on the mode.
+Null prefix argument turns off the mode.
+
+When Stack mode is enabled, inferred stack effects for current
+sexp are automatically displayed in the echo area."
+  :init-value nil
+  :lighter fuel-stack-mode-string
+  :group 'fuel-stack
+
+  (setq fuel-autodoc--fallback-function
+        (when fuel-stack-mode 'fuel-stack--eldoc))
+  (set (make-local-variable 'eldoc-minor-mode-string) nil)
+  (unless fuel-autodoc-mode
+    (set (make-local-variable 'eldoc-documentation-function)
+         (when fuel-stack-mode 'fuel-stack--eldoc))
+    (eldoc-mode fuel-stack-mode)
+    (message "Fuel Stack Autodoc %s" (if fuel-stack-mode "enabled" "disabled"))))
+
+\f
+(provide 'fuel-stack)
+;;; fuel-stack.el ends here
index eb6ec6123e428a93f678fdf51c15210908794378..5f7ab4341cea0deb7c4eb1c93046702de2f9d639 100644 (file)
   "Move point to the beginning of the current symbol."
   (skip-syntax-backward "w_()"))
 
-(defsubst fuel-syntax--symbol-start ()
+(defsubst fuel-syntax--beginning-of-symbol-pos ()
   (save-excursion (fuel-syntax--beginning-of-symbol) (point)))
 
 (defun fuel-syntax--end-of-symbol ()
   "Move point to the end of the current symbol."
   (skip-syntax-forward "w_()"))
 
-(defsubst fuel-syntax--symbol-end ()
+(defsubst fuel-syntax--end-of-symbol-pos ()
   (save-excursion (fuel-syntax--end-of-symbol) (point)))
 
 (put 'factor-symbol 'end-op 'fuel-syntax--end-of-symbol)
   (while (and (not (bobp)) (fuel-syntax--looking-at-emptiness))
     (forward-line -1)))
 
-(defun fuel-syntax--beginning-of-block ()
+(defun fuel-syntax--beginning-of-block-pos ()
   (save-excursion
     (if (> (fuel-syntax--brackets-depth) 0)
         (fuel-syntax--brackets-start)
                              (line-end-position)
                              t)
       (let* ((to (match-beginning 0))
-             (from (fuel-syntax--beginning-of-block)))
+             (from (fuel-syntax--beginning-of-block-pos)))
         (goto-char from)
         (let ((depth (fuel-syntax--brackets-depth)))
           (and (or (re-search-forward fuel-syntax--constructor-regex to t)
 (defsubst fuel-syntax--end-of-defun ()
   (re-search-forward fuel-syntax--end-of-def-regex nil t))
 
+(defconst fuel-syntax--defun-signature-regex
+  (format "\\(%s\\|%s\\)"
+          (format ":[^ ]* [^ ]+\\(%s\\)*" fuel-syntax--stack-effect-regex)
+          "M[^:]*: [^ ]+ [^ ]+"))
+
+(defun fuel-syntax--beginning-of-body ()
+  (let ((p (point)))
+    (and (fuel-syntax--beginning-of-defun)
+         (re-search-forward fuel-syntax--defun-signature-regex p t)
+         (not (re-search-forward fuel-syntax--end-of-def-regex p t)))))
+
+(defun fuel-syntax--beginning-of-sexp ()
+  (if (> (fuel-syntax--brackets-depth) 0)
+      (goto-char (fuel-syntax--brackets-start))
+    (fuel-syntax--beginning-of-body)))
+
+(defsubst fuel-syntax--beginning-of-sexp-pos ()
+  (save-excursion (fuel-syntax--beginning-of-sexp) (point)))
+
 \f
 ;;; USING/IN: