summaryrefslogtreecommitdiffstats
path: root/emacs/caml-types.el
diff options
context:
space:
mode:
Diffstat (limited to 'emacs/caml-types.el')
-rw-r--r--emacs/caml-types.el258
1 files changed, 217 insertions, 41 deletions
diff --git a/emacs/caml-types.el b/emacs/caml-types.el
index 74ec5be9e..4c42574d2 100644
--- a/emacs/caml-types.el
+++ b/emacs/caml-types.el
@@ -12,7 +12,7 @@
;(* $Id$ *)
-; An emacs-lisp complement to the "-dtypes" option of ocamlc and ocamlopt.
+; An emacs-lisp complement to the "-annot" option of ocamlc and ocamlopt.
;; XEmacs compatibility
@@ -25,15 +25,15 @@
(defvar caml-types-location-re nil "Regexp to parse *.annot files.
-Annotation files *.annot may be generated with the \"-dtypes\" option
-of ocamlc and ocamlopt.
+Annotation files *.annot may be generated with the \"-annot\" option
+of ocamlc and ocamlopt.
Their format is:
file ::= block *
block ::= position <SP> position <LF> annotation *
position ::= filename <SP> num <SP> num <SP> num
- annotation ::= keyword open-paren <LF> <SP> <SP> data <LF> close-paren
+ annotation ::= keyword open-paren <LF> <SP> <SP> data <LF> close-paren <LF>
<SP> is a space character (ASCII 0x20)
<LF> is a line-feed character (ASCII 0x0A)
@@ -52,38 +52,60 @@ Their format is:
- the char number within the line is the difference between the third
and second nums.
-For the moment, the only possible keyword is \"type\"."
+The current list of keywords is:
+type call ident"
)
(let* ((caml-types-filename-re "\"\\(\\([^\\\"]\\|\\\\.\\)*\\)\"")
- (caml-types-number-re "\\([0-9]*\\)")
- (caml-types-position-re
+ (caml-types-number-re "\\([0-9]*\\)"))
+ (setq caml-types-position-re
(concat caml-types-filename-re " "
caml-types-number-re " "
caml-types-number-re " "
- caml-types-number-re)))
+ caml-types-number-re))
(setq caml-types-location-re
(concat "^" caml-types-position-re " " caml-types-position-re)))
(defvar caml-types-expr-ovl (make-overlay 1 1))
-
-(make-face 'caml-types-face)
-(set-face-doc-string 'caml-types-face
+(make-face 'caml-types-expr-face)
+(set-face-doc-string 'caml-types-expr-face
"face for hilighting expressions and types")
-(if (not (face-differs-from-default-p 'caml-types-face))
- (set-face-background 'caml-types-face "#88FF44"))
+(if (not (face-differs-from-default-p 'caml-types-expr-face))
+ (set-face-background 'caml-types-expr-face "#88FF44"))
+(overlay-put caml-types-expr-ovl 'face 'caml-types-expr-face)
(defvar caml-types-typed-ovl (make-overlay 1 1))
-
(make-face 'caml-types-typed-face)
(set-face-doc-string 'caml-types-typed-face
"face for hilighting typed expressions")
(if (not (face-differs-from-default-p 'caml-types-typed-face))
(set-face-background 'caml-types-typed-face "#FF8844"))
-
-(overlay-put caml-types-expr-ovl 'face 'caml-types-face)
(overlay-put caml-types-typed-ovl 'face 'caml-types-typed-face)
+(defvar caml-types-scope-ovl (make-overlay 1 1))
+(make-face 'caml-types-scope-face)
+(set-face-doc-string 'caml-types-scope-face
+ "face for hilighting variable scopes")
+(if (not (face-differs-from-default-p 'caml-types-scope-face))
+ (set-face-background 'caml-types-scope-face "#BBFFFF"))
+(overlay-put caml-types-scope-ovl 'face 'caml-types-scope-face)
+
+(defvar caml-types-def-ovl (make-overlay 1 1))
+(make-face 'caml-types-def-face)
+(set-face-doc-string 'caml-types-def-face
+ "face for hilighting binding occurrences")
+(if (not (face-differs-from-default-p 'caml-types-def-face))
+ (set-face-background 'caml-types-def-face "#FF4444"))
+(overlay-put caml-types-def-ovl 'face 'caml-types-def-face)
+
+(defvar caml-types-occ-ovl (make-overlay 1 1))
+(make-face 'caml-types-occ-face)
+(set-face-doc-string 'caml-types-occ-face
+ "face for hilighting variable occurrences")
+(if (not (face-differs-from-default-p 'caml-types-occ-face))
+ (set-face-background 'caml-types-occ-face "#44FF44"))
+(overlay-put caml-types-occ-ovl 'face 'caml-types-occ-face)
+
(defvar caml-types-annotation-tree nil)
(defvar caml-types-annotation-date nil)
@@ -130,7 +152,7 @@ See `caml-types-location-re' for annotation file format.
(caml-types-preprocess type-file)
(setq caml-types-buffer (get-buffer-create caml-types-buffer-name))
(let* ((targ-loc (vector target-file target-line target-bol target-cnum))
- (node (caml-types-find-location targ-loc ()
+ (node (caml-types-find-location targ-loc "type" ()
caml-types-annotation-tree)))
(cond
((null node)
@@ -139,7 +161,7 @@ See `caml-types-location-re' for annotation file format.
(t
(let ((left (caml-types-get-pos target-buf (elt node 0)))
(right (caml-types-get-pos target-buf (elt node 1)))
- (type (elt node 2)))
+ (type (cdr (assoc "type" (elt node 2)))))
(move-overlay caml-types-expr-ovl left right target-buf)
(with-current-buffer caml-types-buffer
(erase-buffer)
@@ -154,6 +176,153 @@ See `caml-types-location-re' for annotation file format.
(delete-overlay caml-types-expr-ovl)
)))
+(defun caml-types-show-call (arg)
+ "Show the kind of call at point.
+ The smallest function call that contains point is
+ temporarily highlighted. Its kind is highlighted in the .annot
+ file and the mark is set to the beginning of the kind.
+ The kind is also displayed in the mini-buffer.
+
+The kind is also displayed in the buffer *caml-types*, which is
+displayed when the command is called with Prefix argument 4.
+
+See `caml-types-location-re' for annotation file format.
+"
+ (interactive "p")
+ (let* ((target-buf (current-buffer))
+ (target-file (file-name-nondirectory (buffer-file-name)))
+ (target-line (1+ (count-lines (point-min)
+ (caml-line-beginning-position))))
+ (target-bol (caml-line-beginning-position))
+ (target-cnum (point))
+ (type-file (concat (file-name-sans-extension (buffer-file-name))
+ ".annot")))
+ (caml-types-preprocess type-file)
+ (setq caml-types-buffer (get-buffer-create caml-types-buffer-name))
+ (let* ((targ-loc (vector target-file target-line target-bol target-cnum))
+ (node (caml-types-find-location targ-loc "call" ()
+ caml-types-annotation-tree)))
+ (cond
+ ((null node)
+ (delete-overlay caml-types-expr-ovl)
+ (message "Point is not within a function call."))
+ (t
+ (let ((left (caml-types-get-pos target-buf (elt node 0)))
+ (right (caml-types-get-pos target-buf (elt node 1)))
+ (kind (cdr (assoc "call" (elt node 2)))))
+ (move-overlay caml-types-expr-ovl left right target-buf)
+ (with-current-buffer caml-types-buffer
+ (erase-buffer)
+ (insert kind)
+ (message (format "%s call" kind)))
+ ))))
+ (if (and (= arg 4)
+ (not (window-live-p (get-buffer-window caml-types-buffer))))
+ (display-buffer caml-types-buffer))
+ (unwind-protect
+ (caml-sit-for 60)
+ (delete-overlay caml-types-expr-ovl)
+ )))
+
+(defun caml-types-show-ident (arg)
+ "Show the kind of call at point.
+ The smallest function call that contains point is
+ temporarily highlighted. Its kind is highlighted in the .annot
+ file and the mark is set to the beginning of the kind.
+ The kind is also displayed in the mini-buffer.
+
+The kind is also displayed in the buffer *caml-types*, which is
+displayed when the command is called with Prefix argument 4.
+
+See `caml-types-location-re' for annotation file format.
+"
+ (interactive "p")
+ (let* ((target-buf (current-buffer))
+ (target-file (file-name-nondirectory (buffer-file-name)))
+ (target-line (1+ (count-lines (point-min)
+ (caml-line-beginning-position))))
+ (target-bol (caml-line-beginning-position))
+ (target-cnum (point))
+ (type-file (concat (file-name-sans-extension (buffer-file-name))
+ ".annot")))
+ (caml-types-preprocess type-file)
+ (setq caml-types-buffer (get-buffer-create caml-types-buffer-name))
+ (let* ((targ-loc (vector target-file target-line target-bol target-cnum))
+ (node (caml-types-find-location targ-loc "ident" ()
+ caml-types-annotation-tree)))
+ (cond
+ ((null node)
+ (delete-overlay caml-types-expr-ovl)
+ (message "Point is not within an identifier."))
+ (t
+ (let ((left (caml-types-get-pos target-buf (elt node 0)))
+ (right (caml-types-get-pos target-buf (elt node 1)))
+ (kind (cdr (assoc "ident" (elt node 2)))))
+ (move-overlay caml-types-expr-ovl left right target-buf)
+ (let* ((loc-re (concat caml-types-position-re " "
+ caml-types-position-re))
+ (end-re (concat caml-types-position-re " --"))
+ (def-re (concat "def " loc-re))
+ (def-end-re (concat "def " end-re))
+ (internal-re (concat "internal_ref " loc-re))
+ (external-re "external_ref \\(.*\\)"))
+ (cond
+ ((string-match def-re kind)
+ (let ((l-file (file-name-nondirectory (match-string 1 kind)))
+ (l-line (string-to-int (match-string 3 kind)))
+ (l-bol (string-to-int (match-string 4 kind)))
+ (l-cnum (string-to-int (match-string 5 kind)))
+ (r-file (file-name-nondirectory (match-string 6 kind)))
+ (r-line (string-to-int (match-string 8 kind)))
+ (r-bol (string-to-int (match-string 9 kind)))
+ (r-cnum (string-to-int (match-string 10 kind))))
+ (let* ((lpos (vector l-file l-line l-bol l-cnum))
+ (rpos (vector r-file r-line r-bol r-cnum))
+ (left (caml-types-get-pos target-buf lpos))
+ (right (caml-types-get-pos target-buf rpos)))
+ (move-overlay caml-types-scope-ovl left right target-buf))))
+ ((string-match def-end-re kind)
+ (let ((l-file (file-name-nondirectory (match-string 1 kind)))
+ (l-line (string-to-int (match-string 3 kind)))
+ (l-bol (string-to-int (match-string 4 kind)))
+ (l-cnum (string-to-int (match-string 5 kind))))
+ (let* ((lpos (vector l-file l-line l-bol l-cnum))
+ (left (caml-types-get-pos target-buf lpos))
+ (right (buffer-size target-buf)))
+ (move-overlay caml-types-scope-ovl left right target-buf))))
+ ((string-match internal-re kind)
+ (let ((l-file (file-name-nondirectory (match-string 1 kind)))
+ (l-line (string-to-int (match-string 3 kind)))
+ (l-bol (string-to-int (match-string 4 kind)))
+ (l-cnum (string-to-int (match-string 5 kind)))
+ (r-file (file-name-nondirectory (match-string 6 kind)))
+ (r-line (string-to-int (match-string 8 kind)))
+ (r-bol (string-to-int (match-string 9 kind)))
+ (r-cnum (string-to-int (match-string 10 kind))))
+ (let* ((lpos (vector l-file l-line l-bol l-cnum))
+ (rpos (vector r-file r-line r-bol r-cnum))
+ (left (caml-types-get-pos target-buf lpos))
+ (right (caml-types-get-pos target-buf rpos)))
+ (move-overlay caml-types-def-ovl left right target-buf)
+ (message (format "this variable is bound at line %d char %d"
+ l-line (- l-cnum l-bol))))))
+ ((string-match external-re kind)
+ (let ((fullname (match-string 1 kind)))
+ (with-current-buffer caml-types-buffer
+ (erase-buffer)
+ (insert fullname)
+ (message (format "external ident: %s" fullname)))))))
+ ))))
+ (if (and (= arg 4)
+ (not (window-live-p (get-buffer-window caml-types-buffer))))
+ (display-buffer caml-types-buffer))
+ (unwind-protect
+ (caml-sit-for 60)
+ (delete-overlay caml-types-expr-ovl)
+ (delete-overlay caml-types-def-ovl)
+ (delete-overlay caml-types-scope-ovl)
+ )))
+
(defun caml-types-preprocess (type-file)
(let* ((type-date (nth 5 (file-attributes type-file)))
(target-file (file-name-nondirectory (buffer-file-name)))
@@ -173,7 +342,7 @@ See `caml-types-location-re' for annotation file format.
(setq caml-types-annotation-tree tree
caml-types-annotation-date type-date)
(kill-buffer type-buf)
- (message ""))
+ (message "done"))
)))
(defun caml-types-date< (date1 date2)
@@ -191,18 +360,26 @@ See `caml-types-location-re' for annotation file format.
(symbol-name (intern elem table)))
+(defun next-annotation ()
+ (forward-char 1)
+ (if (re-search-forward "^[a-z\"]" () t)
+ (forward-char -1)
+ (goto-char (point-max)))
+ (looking-at "[a-z]")
+)
+
; tree of intervals
; each node is a vector
-; [ pos-left pos-right type-info child child child... ]
-; type-info =
-; () if this node does not correspond to an annotated interval
-; (type-start . type-end) address of the annotation in the .annot file
+; [ pos-left pos-right annotation child child child... ]
+; annotation is a list of:
+; (kind . info) where kind = "type" "call" etc.
+; and info = the contents of the annotation
(defun caml-types-build-tree (target-file)
(let ((stack ())
(accu ())
(table (caml-types-make-hash-table))
- (type-info ()))
+ (annotation ()))
(while (re-search-forward caml-types-location-re () t)
(let ((l-file (file-name-nondirectory (match-string 1)))
(l-line (string-to-int (match-string 3)))
@@ -213,14 +390,13 @@ See `caml-types-location-re' for annotation file format.
(r-bol (string-to-int (match-string 9)))
(r-cnum (string-to-int (match-string 10))))
(unless (caml-types-not-in-file l-file r-file target-file)
- (while (and (re-search-forward "^" () t)
- (not (looking-at "type"))
- (not (looking-at "\\\"")))
- (forward-char 1))
- (setq type-info
- (if (looking-at
- "^type(\n\\( \\([^\n)]\\|.)\\|\n[^)]\\)*\\)\n)")
- (caml-types-hcons (match-string 1) table)))
+ (setq annotation ())
+ (while (next-annotation)
+ (cond ((looking-at
+ "^\\([a-z]+\\)(\n \\(\\([^\n)]\\|.)\\|\n[^)]\\)*\\)\n)")
+ (let ((kind (caml-types-hcons (match-string 1) table))
+ (info (caml-types-hcons (match-string 2) table)))
+ (setq annotation (cons (cons kind info) annotation))))))
(setq accu ())
(while (and stack
(caml-types-pos-contains l-cnum r-cnum (car stack)))
@@ -228,7 +404,7 @@ See `caml-types-location-re' for annotation file format.
(setq stack (cdr stack)))
(let* ((left-pos (vector l-file l-line l-bol l-cnum))
(right-pos (vector r-file r-line r-bol r-cnum))
- (node (caml-types-make-node left-pos right-pos type-info
+ (node (caml-types-make-node left-pos right-pos annotation
accu)))
(setq stack (cons node stack))))))
(if (null stack)
@@ -245,12 +421,12 @@ See `caml-types-location-re' for annotation file format.
(and (not (string= r-file target-file))
(not (string= r-file "")))))
-(defun caml-types-make-node (left-pos right-pos type-info children)
+(defun caml-types-make-node (left-pos right-pos annotation children)
(let ((result (make-vector (+ 3 (length children)) ()))
(i 3))
(aset result 0 left-pos)
(aset result 1 right-pos)
- (aset result 2 type-info)
+ (aset result 2 annotation)
(while children
(aset result i (car children))
(setq children (cdr children))
@@ -261,15 +437,15 @@ See `caml-types-location-re' for annotation file format.
(and (<= l-cnum (elt (elt node 0) 3))
(>= r-cnum (elt (elt node 1) 3))))
-(defun caml-types-find-location (targ-pos curr node)
+(defun caml-types-find-location (targ-pos kind curr node)
(if (not (caml-types-pos-inside targ-pos node))
curr
- (if (elt node 2)
+ (if (and (elt node 2) (assoc kind (elt node 2)))
(setq curr node))
(let ((i (caml-types-search node targ-pos)))
(if (and (> i 3)
(caml-types-pos-inside targ-pos (elt node (1- i))))
- (caml-types-find-location targ-pos curr (elt node (1- i)))
+ (caml-types-find-location targ-pos kind curr (elt node (1- i)))
curr))))
; trouve le premier fils qui commence apres la position
@@ -377,7 +553,7 @@ See `caml-types-location-re' for annotation file format.
(with-current-buffer buf (toggle-read-only 1))
)
(t
- (error "No annotation file. You should compile with option \"-dtypes\"."))
+ (error "No annotation file. You should compile with option \"-annot\"."))
)
buf))
@@ -494,7 +670,7 @@ The function uses two overlays.
target-pos
(vector target-file target-line target-bol cnum))
(save-excursion
- (setq node (caml-types-find-location
+ (setq node (caml-types-find-location "type"
target-pos () target-tree))
(set-buffer caml-types-buffer)
(erase-buffer)
@@ -567,7 +743,7 @@ The function uses two overlays.
(defun caml-types-version ()
"internal version number of caml-types.el"
(interactive)
- (message "2")
+ (message "3")
)
(provide 'caml-types)