]> gitweb.factorcode.org Git - factor.git/blob - misc/fuel/fuel-stack.el
Merge commit 'origin/master'
[factor.git] / misc / fuel / fuel-stack.el
1 ;;; fuel-stack.el -- stack inference help
2
3 ;; Copyright (C) 2008 Jose Antonio Ortega Ruiz
4 ;; See http://factorcode.org/license.txt for BSD license.
5
6 ;; Author: Jose Antonio Ortega Ruiz <jao@gnu.org>
7 ;; Keywords: languages, fuel, factor
8 ;; Start date: Sat Dec 20, 2008 01:08
9
10 ;;; Comentary:
11
12 ;; Utilities and a minor mode to show inferred stack effects in the
13 ;; echo area.
14
15 ;;; Code:
16
17 (require 'fuel-autodoc)
18 (require 'fuel-syntax)
19 (require 'fuel-eval)
20 (require 'fuel-base)
21
22 \f
23 ;;; Customization
24
25 (defgroup fuel-stack nil
26   "Customization for FUEL's stack inference engine"
27   :group 'fuel)
28
29 (defface fuel-font-lock-stack-region (face-user-default-spec 'highlight)
30   "Face used to highlight the region whose stack effect is shown"
31   :group 'fuel-stack
32   :group 'faces)
33
34 (defcustom fuel-stack-highlight-period 2
35   "Time, in seconds, the region is highlighted when showing its
36 stack effect.
37
38 Set it to 0 to disable highlighting."
39   :group 'fuel-stack
40   :type 'float)
41
42 (defcustom fuel-stack-mode-show-sexp-p t
43   "Whether to show in the echo area the sexp together with its stack effect."
44   :group 'fuel-stack
45   :type 'boolean)
46
47 \f
48 ;;; Querying for stack effects
49
50 (defun fuel-stack--infer-effect (str)
51   (let ((cmd `(:fuel*
52                ((:using stack-checker effects)
53                 ([ (:factor ,str) ] infer effect>string :get)))))
54     (fuel-eval--retort-result (fuel-eval--send/wait cmd 500))))
55
56 (defsubst fuel-stack--infer-effect/prop (str)
57   (let ((e (fuel-stack--infer-effect str)))
58     (when e
59       (put-text-property 0 (length e) 'face 'factor-font-lock-stack-effect e))
60     e))
61
62 (defvar fuel-stack--overlay
63   (let ((overlay (make-overlay 0 0)))
64     (overlay-put overlay 'face 'fuel-font-lock-stack-region)
65     (delete-overlay overlay)
66     overlay))
67
68 (defun fuel-stack-effect-region (begin end)
69   "Displays the inferred stack effect of the code in current region."
70   (interactive "r")
71   (when (> fuel-stack-highlight-period 0)
72     (move-overlay fuel-stack--overlay begin end))
73   (condition-case nil
74       (let* ((str (fuel--region-to-string begin end))
75              (effect (fuel-stack--infer-effect/prop str)))
76         (if effect (message "%s" effect)
77           (message "Couldn't infer effect for '%s'"
78                    (fuel--shorten-region begin end 60)))
79         (sit-for fuel-stack-highlight-period))
80     (error))
81   (delete-overlay fuel-stack--overlay))
82
83 (defun fuel-stack-effect-sexp (&optional arg)
84   "Displays the inferred stack effect for the current sexp.
85 With prefix argument, use current region instead"
86   (interactive "P")
87   (if arg
88       (call-interactively 'fuel-stack-effect-region)
89     (fuel-stack-effect-region (1+ (fuel-syntax--beginning-of-sexp-pos))
90                               (if (looking-at-p ";") (point)
91                                 (fuel-syntax--end-of-symbol-pos)))))
92
93 \f
94 ;;; Stack mode:
95
96 (make-variable-buffer-local
97  (defvar fuel-stack-mode-string " S"
98    "Modeline indicator for fuel-stack-mode"))
99
100 (defun fuel-stack--eldoc ()
101   (when (looking-at-p " \\|$")
102     (let* ((r (fuel--region-to-string (1+ (fuel-syntax--beginning-of-sexp-pos))))
103            (e (fuel-stack--infer-effect/prop r)))
104       (when e
105         (if fuel-stack-mode-show-sexp-p
106             (concat (fuel--shorten-str r 30) ": " e)
107           e)))))
108
109 (define-minor-mode fuel-stack-mode
110   "Toggle Fuel's Stack mode.
111 With no argument, this command toggles the mode.
112 Non-null prefix argument turns on the mode.
113 Null prefix argument turns off the mode.
114
115 When Stack mode is enabled, inferred stack effects for current
116 sexp are automatically displayed in the echo area."
117   :init-value nil
118   :lighter fuel-stack-mode-string
119   :group 'fuel-stack
120
121   (setq fuel-autodoc--fallback-function
122         (when fuel-stack-mode 'fuel-stack--eldoc))
123   (set (make-local-variable 'eldoc-minor-mode-string) nil)
124   (unless fuel-autodoc-mode
125     (set (make-local-variable 'eldoc-documentation-function)
126          (when fuel-stack-mode 'fuel-stack--eldoc))
127     (eldoc-mode fuel-stack-mode)
128     (message "Fuel Stack Autodoc %s" (if fuel-stack-mode "enabled" "disabled"))))
129
130 \f
131 (provide 'fuel-stack)
132 ;;; fuel-stack.el ends here