diff options
| author | Alasdair Armstrong | 2019-01-21 19:05:39 +0000 |
|---|---|---|
| committer | Alasdair Armstrong | 2019-01-21 19:07:39 +0000 |
| commit | 864fb194128fa36990a53b80d000092e4b76b5fc (patch) | |
| tree | 7306853b63fc0cf7fae074b0df2a12b7e0733d6a /editors | |
| parent | 2c81fff611c458fe04b2de2045247bdc77f8f80a (diff) | |
Remove old emacs mode to avoid confusion
Diffstat (limited to 'editors')
| -rw-r--r-- | editors/sail-mode.el | 2150 | ||||
| -rw-r--r-- | editors/sail2-mode.el | 67 |
2 files changed, 59 insertions, 2158 deletions
diff --git a/editors/sail-mode.el b/editors/sail-mode.el index 28a109b0..38404f14 100644 --- a/editors/sail-mode.el +++ b/editors/sail-mode.el @@ -1,2099 +1,67 @@ -;;; sail.el --- Sail mode for Emacs. -;;; based on tuareg.el which was - ;; Copyright (C) 1997-2006 Albert Cohen, all rights reserved. - ;; Copyright (C) 2009-2010 Jane Street Holding, LLC. - ;; Licensed under the GNU General Public License. - ;; Author: Albert Cohen <Albert.Cohen@inria.fr> - ;; Sam Steingold <sds@gnu.org> - ;; Christophe Troestler <Christophe.Troestler@umons.ac.be> - ;; Till Varoquaux <till@pps.jussieu.fr> - ;; Sean McLaughlin <seanmcl@gmail.com> - ;; Created: 8 Jan 1997 - ;; Version: 2.0.5 - ;; URL: http://forge.ocamlcore.org/projects/tuareg/ - ;; EmacsWiki: TuaregMode - -(eval-when-compile (require 'cl)) -(require 'easymenu) - -(defalias 'sail-match-string - (if (fboundp 'match-string-no-properties) - 'match-string-no-properties - 'match-string)) - - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; User customizable variables - -;; Use the standard `customize' interface or `sail-mode-hook' to -;; Configure these variables - -(require 'custom) - -(defgroup sail nil - "Support for the Sail language." - :group 'languages) - -;; Comments - -(defcustom sail-indent-leading-comments t - "*If true, indent leading comment lines (starting with `(*') like others." - :group 'sail :type 'boolean) - -(defcustom sail-indent-comments t - "*If true, automatically align multi-line comments." - :group 'sail :type 'boolean) - -(defcustom sail-comment-end-extra-indent 0 - "*How many spaces to indent a leading comment end `*)'. -If you expect comments to be indented like - (* - ... - *) -even without leading `*', use `sail-comment-end-extra-indent' = 1." - :group 'sail - :type '(radio :extra-offset 8 - :format "%{Comment End Extra Indent%}: - Comment alignment:\n%v" - (const :tag "align with `(' in comment opening" 0) - (const :tag "align with `*' in comment opening" 1) - (integer :tag "custom alignment" 0))) - -(defcustom sail-support-leading-star-comments t - "*Enable automatic intentation of comments of the form - (* - * ... - *) -Documentation comments (** *) are not concerned by this variable -unless `sail-leading-star-in-doc' is also set. - -If you do not set this variable and still expect comments to be -indented like - (* - ... - *) -\(without leading `*'), set `sail-comment-end-extra-indent' to 1." - :group 'sail :type 'boolean) - -(defcustom sail-leading-star-in-doc nil - "*Enable automatic intentation of documentation comments of the form - (** - * ... - *)" - :group 'sail :type 'boolean) - -;; Indentation defaults - -(defcustom sail-default-indent 2 - "*Default indentation. - -Global indentation variable (large values may lead to indentation overflows). -When no governing keyword is found, this value is used to indent the line -if it has to." - :group 'sail :type 'integer) - -(defcustom sail-let-always-indent t - "*If true, enforce indentation is at least `sail-let-indent' after a `let'. - -As an example, set it to false when you have `sail-with-indent' set to 0, -and you want `let x = match ... with' and `match ... with' indent the -same way." - :group 'sail :type 'boolean) - -(defcustom sail-case-extra-unindent sail-default-indent - "*Extra backward indent for Sail lines starting with the `case' operator. - -It is NOT the variable controlling the indentation of the `case' itself: -this value is automatically added to `switch' to leave enough space for `case' backward -indentation." - - :group 'sail :type 'integer) - -(defcustom sail-enum-indent sail-default-indent - "*How many spaces to indent from an `enumerate' keyword." - :group 'sail :type 'integer) - -(defcustom sail-struct-struct-indent sail-default-indent - "*How many spaces to indent from a `struct' keyword." - :group 'sail :type 'integer) - -(defcustom sail-foreach-indent sail-default-indent - "*How many spaces to indent from a `foreach' keyword." - :group 'sail :type 'integer) - -(defcustom sail-function-indent sail-default-indent - "*How many spaces to indent from a `function' keyword." - :group 'sail :type 'integer) - -(defcustom sail-if-then-else-indent sail-default-indent - "*How many spaces to indent from an `if', `then' or `else' keyword." - :group 'sail :type 'integer) - -(defcustom sail-let-indent sail-default-indent - "*How many spaces to indent from a `let' keyword." - :group 'sail :type 'integer) - -(defcustom sail-in-indent sail-default-indent - "*How many spaces to indent from a `in' keyword." - :group 'sail :type 'integer) - -(defcustom sail-switch-indent sail-default-indent - "*How many spaces to indent from a `switch' keyword." - :group 'sail :type 'integer) - -(defcustom sail-with-indent sail-default-indent - "*How many spaces to indent from a `with' keyword." - :group 'sail :type 'integer) - -(defcustom sail-typedef-indent sail-default-indent - "*How many spaces to indent from a `typedef' keyword." - :group 'sail :type 'integer) - -(defcustom sail-val-indent sail-default-indent - "*How many spaces to indent from a `val' keyword." - :group 'sail :type 'integer) - -;; Automatic indentation -;; Using abbrev-mode and electric keys - -(defcustom sail-use-abbrev-mode t - "*Non-nil means electrically indent lines starting with leading keywords. -It makes use of `abbrev-mode'. - -Many people find eletric keywords irritating, so you can disable them by -setting this variable to nil." - :group 'sail :type 'boolean - :set '(lambda (var val) - (setq sail-use-abbrev-mode val) - (abbrev-mode val))) - -(defcustom sail-electric-indent t - "*Non-nil means electrically indent lines starting with `|]', '||]', '>', `)', `]' or `}'. - -Many people find eletric keys irritating, so you can disable them in -setting this variable to nil." - :group 'sail :type 'boolean) - -(defcustom sail-electric-close-range t - "*Non-nil means electrically insert `|' before a list-closing `]'. - -Many people find eletric keys irritating, so you can disable them in -setting this variable to nil. You should probably have this on, -though, if you also have `sail-electric-indent' on." - :group 'sail :type 'boolean) - -(defcustom sail-electric-close-block t -"*Non-nil means electrically insert `}'" - :group 'sail :type 'boolean) - - -(defvar sail-options-list - '(("Automatic indentation of leading keywords" . 'sail-use-abbrev-mode) - ("Automatic indentation of ), ], |], ||], >, and }" . 'sail-electric-indent) - ("Automatic matching of [|" . 'sail-electric-close-range) - "---" - ("Indent body of comments" . 'sail-indent-comments) - ("Indent first line of comments" . 'sail-indent-leading-comments) - ("Leading-`*' comment style" . 'sail-support-leading-star-comments)) - "*List of menu-configurable Sail options.") - -(eval-and-compile - (defconst sail-use-syntax-ppss (fboundp 'syntax-ppss) - "*If nil, use our own parsing and caching.")) - -(defgroup sail-faces nil - "Special faces for the Sail mode." - :group 'sail) - -(defconst sail-faces-inherit-p - (and (boundp 'face-attribute-name-alist) - (assq :inherit face-attribute-name-alist))) - -(defface sail-font-lock-governing-face - '((((background light)) (:foreground "blue" :bold t)) - (t (:foreground "orange" :bold t))) - "Face description for governing/leading keywords." - :group 'sail-faces) -(defvar sail-font-lock-governing-face - 'sail-font-lock-governing-face) - -(defface sail-font-lock-operator-face - '((((background light)) (:foreground "brown")) - (t (:foreground "khaki"))) - "Face description for all operators." - :group 'sail-faces) -(defvar sail-font-lock-operator-face - 'sail-font-lock-operator-face) - -(defface sail-font-lock-error-face - '((t (:foreground "yellow" :background "red" :bold t))) - "Face description for all errors reported to the source." - :group 'sail-faces) -(defvar sail-font-lock-error-face - 'sail-font-lock-error-face) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Support definitions - -(defun sail-leading-star-p () - (and sail-support-leading-star-comments - (save-excursion ; this function does not make sense outside of a comment - (sail-beginning-of-literal-or-comment) - (and (or sail-leading-star-in-doc - (not (looking-at "(\\*[Tt][Ee][Xx]\\|(\\*\\*"))) - (progn - (forward-line 1) - (back-to-indentation) - (looking-at "\\*[^)]")))))) - -(defun sail-auto-fill-insert-leading-star (&optional leading-star) - (let ((point-leading-comment (looking-at "(\\*")) (return-leading nil)) - (save-excursion - (back-to-indentation) - (when sail-electric-indent - (when (and (sail-in-comment-p) - (or leading-star - (sail-leading-star-p))) - (unless (looking-at "(?\\*") - (insert-before-markers "* ")) - (setq return-leading t)) - (unless point-leading-comment - ;; Use optional argument to break recursion - (sail-indent-command t)))) - return-leading)) - -(defun sail-auto-fill-function () - (unless (sail-in-literal-p) - (let ((leading-star - (and (not (char-equal ?\n last-command-event)) - (sail-auto-fill-insert-leading-star)))) - (do-auto-fill) - (unless (char-equal ?\n last-command-event) - (sail-auto-fill-insert-leading-star leading-star))))) - -;; these two functions are different from the standard -;; in that they do NOT signal errors beginning-of-buffer and end-of-buffer -(defun sail-forward-char (&optional step) - (if step (goto-char (+ (point) step)) - (goto-char (1+ (point))))) - -(defun sail-backward-char (&optional step) - (if step (goto-char (- (point) step)) - (goto-char (1- (point))))) - -(defun sail-in-indentation-p () - "Return non-nil if all chars between beginning of line and point are blanks." - (save-excursion - (skip-chars-backward " \t") - (bolp))) - -(defvar sail-cache-stop (point-min)) -(make-variable-buffer-local 'sail-cache-stop) -(defvar sail-cache nil) -(make-variable-buffer-local 'sail-cache) -(defvar sail-cache-local nil) -(make-variable-buffer-local 'sail-cache-local) -(defvar sail-cache-last-local nil) -(make-variable-buffer-local 'sail-cache-last-local) -(defvar sail-last-loc (cons nil nil)) - -;; PPSS definitions -(defun sail-ppss-in-literal-or-comment () (error "sail uses PPSS")) -(defun sail-ppss-fontify (beg end) (error "sail uses PPSS")) -(defun sail-ppss-in-literal-p () - "Returns non-nil if point is inside a Sail literal." - (nth 3 (syntax-ppss))) -(defun sail-ppss-in-comment-p () - "Returns non-nil if point is inside or right before a Sail comment." - (or (nth 4 (syntax-ppss)) - (looking-at "[ \t]*(\\*"))) -(defun sail-ppss-in-literal-or-comment-p () - "Returns non-nil if point is inside a Sail literal or comment." - (nth 8 (syntax-ppss))) -(defun sail-ppss-beginning-of-literal-or-comment () - "Skips to the beginning of the current literal or comment (or buffer)." - (interactive) - (goto-char (or (nth 8 (syntax-ppss)) (point)))) -(defun sail-ppss-beginning-of-literal-or-comment-fast () - (goto-char (or (nth 8 (syntax-ppss)) (point-min)))) -;; FIXME: not clear if moving out of a string/comment counts as 1 or no. -(defalias 'sail-backward-up-list 'backward-up-list) - -;; non-PPSS definitions -(defun sail-!ppss-in-literal-p () - "Return non-nil if point is inside a Sail literal." - (car (sail-in-literal-or-comment))) -(defun sail-!ppss-in-comment-p () - "Return non-nil if point is inside a Sail comment." - (cdr (sail-in-literal-or-comment))) -(defun sail-!ppss-in-literal-or-comment-p () - "Return non-nil if point is inside a Sail literal or comment." - (sail-in-literal-or-comment) - (or (car sail-last-loc) (cdr sail-last-loc))) -(defun sail-!ppss-in-literal-or-comment () - "Return the pair `((sail-in-literal-p) . (sail-in-comment-p))'." - (if (and (<= (point) sail-cache-stop) sail-cache) - (progn - (if (or (not sail-cache-local) (not sail-cache-last-local) - (and (>= (point) (caar sail-cache-last-local)))) - (setq sail-cache-local sail-cache)) - (while (and sail-cache-local (< (point) (caar sail-cache-local))) - (setq sail-cache-last-local sail-cache-local - sail-cache-local (cdr sail-cache-local))) - (setq sail-last-loc - (if sail-cache-local - (cons (eq (cadar sail-cache-local) 'b) - (> (cddar sail-cache-local) 0)) - (cons nil nil)))) - (let ((flag t) (op (point)) (mp (min (point) (1- (point-max)))) - (balance 0) (end-of-comment nil)) - (while (and sail-cache (<= sail-cache-stop (caar sail-cache))) - (setq sail-cache (cdr sail-cache))) - (if sail-cache - (if (eq (cadar sail-cache) 'b) - (progn - (setq sail-cache-stop (1- (caar sail-cache))) - (goto-char sail-cache-stop) - (setq balance (cddar sail-cache)) - (setq sail-cache (cdr sail-cache))) - (setq balance (cddar sail-cache)) - (setq sail-cache-stop (caar sail-cache)) - (goto-char sail-cache-stop) - (skip-chars-forward "(")) - (goto-char (point-min))) - (skip-chars-backward "\\\\*") - (while flag - (if end-of-comment (setq balance 0 end-of-comment nil)) - (skip-chars-forward "^\\\\'`\"(\\*") - (cond - ((looking-at "\\\\") - (sail-forward-char 2)) - ((looking-at "'\\([^\n\\']\\|\\\\[^ \t\n][^ \t\n]?[^ \t\n]?\\)'") - (setq sail-cache (cons (cons (1+ (point)) (cons 'b balance)) - sail-cache)) - (goto-char (match-end 0)) - (setq sail-cache (cons (cons (point) (cons 'e balance)) - sail-cache))) - ((looking-at "\"") - (sail-forward-char) - (setq sail-cache (cons (cons (point) (cons 'b balance)) - sail-cache)) - (skip-chars-forward "^\\\\\"") - (while (looking-at "\\\\") - (sail-forward-char 2) (skip-chars-forward "^\\\\\"")) - (sail-forward-char) - (setq sail-cache (cons (cons (point) (cons 'e balance)) - sail-cache))) - ((looking-at "(\\*") - (setq balance (1+ balance)) - (setq sail-cache (cons (cons (point) (cons nil balance)) - sail-cache)) - (sail-forward-char 2)) - ((looking-at "\\*)") - (sail-forward-char 2) - (if (> balance 1) - (progn - (setq balance (1- balance)) - (setq sail-cache (cons (cons (point) (cons nil balance)) - sail-cache))) - (setq end-of-comment t) - (setq sail-cache (cons (cons (point) (cons nil 0)) - sail-cache)))) - (t (sail-forward-char))) - (setq flag (<= (point) mp))) - (setq sail-cache-local sail-cache - sail-cache-stop (point)) - (goto-char op) - (if sail-cache (sail-in-literal-or-comment) - (setq sail-last-loc (cons nil nil)) - sail-last-loc)))) -(defun sail-!ppss-beginning-of-literal-or-comment () - "Skips to the beginning of the current literal or comment (or buffer)." - (interactive) - (when (sail-in-literal-or-comment-p) - (sail-beginning-of-literal-or-comment-fast))) - -(defun sail-!ppss-beginning-of-literal-or-comment-fast () - (while (and sail-cache-local - (or (eq 'b (cadar sail-cache-local)) - (> (cddar sail-cache-local) 0))) - (setq sail-cache-last-local sail-cache-local - sail-cache-local (cdr sail-cache-local))) - (if sail-cache-last-local - (goto-char (caar sail-cache-last-local)) - (goto-char (point-min))) - (when (eq 'b (cadar sail-cache-last-local)) (sail-backward-char))) - -(defun sail-!ppss-backward-up-list () - "Safe up-list regarding comments, literals and errors." - (let ((balance 1) (op (point)) (oc nil)) - (sail-in-literal-or-comment) - (while (and (> (point) (point-min)) (> balance 0)) - (setq oc (if sail-cache-local (caar sail-cache-local) (point-min))) - (condition-case nil (up-list -1) (error (goto-char (point-min)))) - (if (>= (point) oc) (setq balance (1- balance)) - (goto-char op) - (skip-chars-backward "^[]{}()<>") (sail-backward-char) - (cond ((sail-in-literal-or-comment-p) - (sail-beginning-of-literal-or-comment-fast)) - ((looking-at "[[{(<]") - (setq balance (1- balance))) - ((looking-at "[]})>]") - (setq balance (1+ balance))))) - (setq op (point))))) - -(defalias 'sail-in-literal-or-comment - (eval-and-compile (if sail-use-syntax-ppss - 'sail-ppss-in-literal-or-comment - 'sail-!ppss-in-literal-or-comment))) -(defalias 'sail-fontify - (eval-and-compile (if sail-use-syntax-ppss - 'sail-ppss-fontify - 'sail-!ppss-fontify))) -(defalias 'sail-in-literal-p - (eval-and-compile (if sail-use-syntax-ppss - 'sail-ppss-in-literal-p - 'sail-!ppss-in-literal-p))) -(defalias 'sail-in-comment-p - (eval-and-compile (if sail-use-syntax-ppss - 'sail-ppss-in-comment-p - 'sail-!ppss-in-comment-p))) -(defalias 'sail-in-literal-or-comment-p - (eval-and-compile (if sail-use-syntax-ppss - 'sail-ppss-in-literal-or-comment-p - 'sail-!ppss-in-literal-or-comment-p))) -(defalias 'sail-beginning-of-literal-or-comment - (eval-and-compile (if sail-use-syntax-ppss - 'sail-ppss-beginning-of-literal-or-comment - 'sail-!ppss-beginning-of-literal-or-comment))) -(defalias 'sail-beginning-of-literal-or-comment-fast - (eval-and-compile (if sail-use-syntax-ppss - 'sail-ppss-beginning-of-literal-or-comment-fast - 'sail-!ppss-beginning-of-literal-or-comment-fast))) -(defalias 'sail-backward-up-list - ;; FIXME: not clear if moving out of a string/comment counts as 1 or no. - (eval-and-compile (if sail-use-syntax-ppss - 'backward-up-list - 'sail-!ppss-backward-up-list))) - -(defun sail-false-=-p () - "Is the underlying `=' the first/second letter of an operator?" - (or (memq (preceding-char) '(?: ?> ?< ?=)) - (char-equal ?= (char-after (1+ (point)))))) - -(defun sail-at-phrase-break-p () - "Is the underlying `;' a phrase break?" - (and (char-equal ?\; (following-char)) - (or (and (not (eobp)) - (char-equal ?\; (char-after (1+ (point))))) - (char-equal ?\; (preceding-char))))) - -(defvar sail-mode-syntax-table +(defvar sail2-mode-hook nil) + +(add-to-list 'auto-mode-alist '("\\.sail\\'" . sail2-mode)) + +(defconst sail2-keywords + '("val" "function" "type" "struct" "union" "enum" "let" "var" "if" "then" "by" + "else" "match" "in" "return" "register" "ref" "forall" "operator" "effect" + "overload" "cast" "sizeof" "constant" "constraint" "default" "assert" "newtype" "from" + "pure" "infixl" "infixr" "infix" "scattered" "end" "try" "catch" "and" "to" + "throw" "clause" "as" "repeat" "until" "while" "do" "foreach" "bitfield" + "mapping" "where" "with")) + +(defconst sail2-kinds + '("Int" "Type" "Order" "Bool" "inc" "dec" + "barr" "depend" "rreg" "wreg" "rmem" "rmemt" "wmv" "wmvt" "eamem" "wmem" + "exmem" "undef" "unspec" "nondet" "escape" "configuration")) + +(defconst sail2-types + '("vector" "int" "nat" "atom" "range" "unit" "bit" "real" "list" "bool" "string" "bits" "option" + "uint64_t" "int64_t" "bv_t" "mpz_t")) + +(defconst sail2-special + '("_prove" "_not_prove" "create" "kill" "convert" "undefined" + "$define" "$include" "$ifdef" "$ifndef" "$else" "$endif" "$option" "$latex")) + +(defconst sail2-font-lock-keywords + `((,(regexp-opt sail2-keywords 'symbols) . font-lock-keyword-face) + (,(regexp-opt sail2-kinds 'symbols) . font-lock-builtin-face) + (,(regexp-opt sail2-types 'symbols) . font-lock-type-face) + (,(regexp-opt sail2-special 'symbols) . font-lock-preprocessor-face) + ("~" . font-lock-negation-char-face) + ("\\(::\\)<" 1 font-lock-keyword-face) + ("@" . font-lock-preprocessor-face) + ("<->" . font-lock-negation-char-face) + ("\'[a-zA-Z0-9_]+" . font-lock-variable-name-face) + ("\\([a-zA-Z0-9_]+\\)(" 1 font-lock-function-name-face) + ("function \\([a-zA-Z0-9_]+\\)" 1 font-lock-function-name-face) + ("val \\([a-zA-Z0-9_]+\\)" 1 font-lock-function-name-face) + ("\\_<\\([0-9]+\\|0b[0-9_]+\\|0x[0-9a-fA-F_]+\\|true\\|false\\|bitone\\|bitzero\\)\\_>\\|()" . font-lock-constant-face))) + +(defconst sail2-mode-syntax-table (let ((st (make-syntax-table))) - (modify-syntax-entry ?_ "_" st) - (modify-syntax-entry ?? ". p" st) - (modify-syntax-entry ?~ ". p" st) - (modify-syntax-entry ?: "." st) - (modify-syntax-entry ?' "w" st) ; ' is part of words (for primes). - (modify-syntax-entry ?\" "\"" st) ; " is a string delimiter - (modify-syntax-entry ?\\ "\\" st) - (modify-syntax-entry ?* ". 23" st) - (condition-case nil - (progn - (modify-syntax-entry ?\( "()1n" st) - (modify-syntax-entry ?\) ")(4n" st)) - (error ;XEmacs signals an error instead of ignoring `n'. - (modify-syntax-entry ?\( "()1" st) - (modify-syntax-entry ?\) ")(4" st))) + (modify-syntax-entry ?> "." st) + (modify-syntax-entry ?_ "w" st) + (modify-syntax-entry ?' "w" st) + (modify-syntax-entry ?* ". 23" st) + (modify-syntax-entry ?/ ". 124b" st) + (modify-syntax-entry ?\n "> b" st) st) - "Syntax table in use in Sail mode buffers.") - -(defmacro sail-with-internal-syntax (&rest body) - `(progn - ;; Switch to a modified internal syntax. - (modify-syntax-entry ?. "w" sail-mode-syntax-table) - (modify-syntax-entry ?_ "w" sail-mode-syntax-table) - (unwind-protect (progn ,@body) - ;; Switch back to the interactive syntax. - (modify-syntax-entry ?. "." sail-mode-syntax-table) - (modify-syntax-entry ?_ "_" sail-mode-syntax-table)))) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Font-Lock - -(defvar sail-doc-face 'font-lock-doc-face) - -(unless sail-use-syntax-ppss - - (defun sail-fontify-buffer () - (font-lock-default-fontify-buffer) - (sail-fontify (point-min) (point-max))) - - (defun sail-fontify-region (begin end &optional verbose) - (font-lock-default-fontify-region begin end verbose) - (sail-fontify begin end)) - - (defun sail-fontify (begin end) - (when (eq major-mode 'sail-mode) - (save-excursion - (sail-with-internal-syntax - - (let ((case-fold-search nil) - (modified (buffer-modified-p))) ; Emacs hack (see below) - (goto-char begin) - (setq begin (line-beginning-position)) - (goto-char (1- end)) - (end-of-line) - ;; Dirty hack to trick `font-lock-default-unfontify-region' - (forward-line 2) - (setq end (point)) - - (while (> end begin) - (goto-char (1- end)) - (sail-in-literal-or-comment) - (cond - ((cdr sail-last-loc) - (sail-beginning-of-literal-or-comment) - (put-text-property (max begin (point)) end 'face - (if (looking-at - "(\\*[Tt][Ee][Xx]\\|(\\*\\*[^*]") - sail-doc-face - 'font-lock-comment-face)) - (setq end (1- (point)))) - ((car sail-last-loc) - (sail-beginning-of-literal-or-comment) - (put-text-property (max begin (point)) end 'face - 'font-lock-string-face) - (setq end (point))) - (t (while (and sail-cache-local - (or (> (caar sail-cache-local) end) - (eq 'b (cadar sail-cache-local)))) - (setq sail-cache-local (cdr sail-cache-local))) - (setq end (if sail-cache-local - (caar sail-cache-local) begin))))) - (unless modified (set-buffer-modified-p nil))) - )))) - ) ;; end sail-use-syntax-ppss - -(defconst sail-font-lock-syntactic-keywords - ;; Char constants start with ' but ' can also appear in identifiers. - ;; Beware not to match things like '*)hel' or '"hel' since the first ' - ;; might be inside a string or comment. - '(("\\<\\('\\)\\([^'\\\n]\\|\\\\.[^\\'\n \")]*\\)\\('\\)" - (1 '(7)) (3 '(7))))) - -(defun sail-font-lock-syntactic-face-function (state) - (if (nth 3 state) font-lock-string-face - (let ((start (nth 8 state))) - (if (and (> (point-max) (+ start 2)) - (eq (char-after (+ start 2)) ?*) - (not (eq (char-after (+ start 3)) ?*))) - ;; This is a documentation comment - sail-doc-face - font-lock-comment-face)))) - -;; Initially empty, set in `sail-install-font-lock' -(defvar sail-font-lock-keywords () - "Font-Lock patterns for Sail mode.") - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Keymap - -(defvar sail-mode-map - (let ((map (make-sparse-keymap))) - ;(define-key map "|]" 'sail-electric-piperb) - (define-key map ")" 'sail-electric-rp) - (define-key map "}" 'sail-electric-rc) - ;(define-key map "]" 'sail-electric-rb) - (define-key map ">" 'sail-electric-lt) - (define-key map "\M-q" 'sail-indent-phrase) - (define-key map "\C-c\C-q" 'sail-indent-phrase) - (define-key map "\M-\C-\\" 'indent-region) - (define-key map "\C-c\C-a" 'sail-find-alternate-file) - (define-key map "\C-c\C-c" 'compile) - (define-key map "\C-xnd" 'sail-narrow-to-phrase) - (define-key map "\C-c\C-n" 'sail-next-phrase) - (define-key map "\C-c\C-p" 'sail-previous-phrase) - (define-key map [(backspace)] 'backward-delete-char-untabify) - (define-key map [(control c) (control down)] 'sail-next-phrase) - (define-key map [(control c) (control up)] 'sail-previous-phrase) - (define-key map [(meta control down)] 'sail-next-phrase) - (define-key map [(meta control up)] 'sail-previous-phrase) - (define-key map [(meta control n)] 'sail-next-phrase) - (define-key map [(meta control p)] 'sail-previous-phrase) - (define-key map [(meta control h)] 'sail-mark-phrase) - map) - "Keymap used in Sail mode.") - -(defconst sail-font-lock-syntax - `((?_ . "w") (?` . ".") - ,@(unless sail-use-syntax-ppss - '((?\" . ".") (?\( . ".") (?\) . ".") (?* . ".")))) - "Syntax changes for Font-Lock.") - -(defvar sail-mode-abbrev-table () - "Abbrev table used for Sail mode buffers.") -(defun sail-define-abbrev (keyword) - (define-abbrev sail-mode-abbrev-table keyword keyword 'sail-abbrev-hook)) -(if sail-mode-abbrev-table () - (setq sail-mode-abbrev-table (make-abbrev-table)) - (mapc 'sail-define-abbrev - '("scattered" "function" "typedef" "let" "default" "val" "register" - "alias" "union" "member" "clause" "extern" "cast" "effect" - "rec" "and" "switch" "case" "when" "exit" "foreach" "from" "else" - "to" "end" "downto" "in" "then" "with" "if" "nondet" "as" - "undefined" "const" "struct" "IN" "deinfix" "return" "constraint" "sizeof")) - (setq abbrevs-changed nil)) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; The major mode + "Syntax table for Sail2 mode") -;;;###autoload (add-to-list 'auto-mode-alist '("\\.sail?" . sail-mode)) - -;;;###autoload -(defun sail-mode () - "Major mode for editing Sail code. - -Based on Tuareg mode. See Tuareg mode for usage" +(defun sail2-mode () + "Major mode for editing Sail Language files" (interactive) (kill-all-local-variables) - (setq major-mode 'sail-mode) - (setq mode-name "Sail") - (use-local-map sail-mode-map) - (set-syntax-table sail-mode-syntax-table) - (setq local-abbrev-sail sail-mode-abbrev-table) - - ;; Initialize the Sail menu - (sail-build-menu) - - ;; Initialize indentation regexps - (sail-make-indentation-regexps) - - (make-local-variable 'paragraph-start) - (setq paragraph-start (concat "^[ \t]*$\\|\\*)$\\|" page-delimiter)) - (make-local-variable 'paragraph-separate) - (setq paragraph-separate paragraph-start) - (make-local-variable 'require-final-newline) - (setq require-final-newline t) - (make-local-variable 'comment-start) - (setq comment-start "(* ") - (make-local-variable 'comment-end) - (setq comment-end " *)") - (make-local-variable 'comment-column) - (setq comment-column 40) - (make-local-variable 'comment-start-skip) - (setq comment-start-skip "(\\*+[ \t]*") - (make-local-variable 'comment-multi-line) - (setq comment-multi-line t) - (make-local-variable 'parse-sexp-ignore-comments) - (setq parse-sexp-ignore-comments nil) - ;; (make-local-variable 'indent-line-function) - ;; setq indent-line-function 'sail-indent-command) - (unless sail-use-syntax-ppss - (add-hook 'before-change-functions 'sail-before-change-function nil t)) - (make-local-variable 'normal-auto-fill-function) - (setq normal-auto-fill-function 'sail-auto-fill-function) - - (when (featurep 'imenu) - (setq imenu-prev-index-position-function 'sail-imenu-prev-index-position - imenu-extract-index-name-function 'sail-imenu-extract-index-name)) - - ;; Hooks for sail-mode, use them for sail-mode configuration - (sail-install-font-lock) - (run-hooks 'sail-mode-hook) - (when sail-use-abbrev-mode (abbrev-mode 1)) - (message nil)) - -(defun sail-install-font-lock () - (setq - sail-font-lock-keywords - `(("\\<\\(extern\\|cast\\|overload\\|deinfix\\|function\\|scattered\\|clause\\|effect\\|default\\|struct\\|const\\|union\\|val\\|typedef\\|let\\|rec\\|and\\|end\\|register\\|alias\\|member\\|enumerate\\)\\>" - 0 sail-font-lock-governing-face nil nil) - ("\\<\\(_prove\\)\\>" - 0 font-lock-preprocessor-face nil nil) - ("\\<\\(false\\|true\\|bitzero\\|bitone\\|0x[:xdigit:]\\|[:digit:]\\)\\>" 0 font-lock-constant-face nil nil) - ("\\<\\(as\\|downto\\|else\\|foreach\\|while\\|do\\|repeat\\|until\\|try\\|catch\\|throw\\|if\\|t\\(hen\\|o\\)\\|when\\|in\\|switch\\|with\\|case\\|when\\|exit\\|constraint\\|sizeof\\|nondet\\|from\\|by\\|return\\)\\>" - 0 font-lock-keyword-face nil nil) - ("\\<\\(clause\\)\\>[ \t\n]*\\(\\(\\w\\|[_ \t()*,]\\)+\\)" - 2 font-lock-variable-name-face keep nil) - ("\\<\\(typedef\\|union\\)\\>[ \t\n]*\\(\\(\\w\\|[_ \t()*,]\\)+\\)" - 2 font-lock-type-face keep nil) - ("\\<\\(Type\\|Nat\\|Num\\|Order\\|Effect\\|inc\\|dec\\|implicit\\|vector\\|rreg\\|wreg\\|rmem\\|wmem\\|wmv\\|eamem\\|barr\\|undef\\|escape\\|unspec\\|nondet\\|pure\\|effect\\|IN\\|forall\\|exist\\|bit\\|unit\\|bool\\|nat\\|real\\|int\\)\\>" - 0 font-lock-type-face keep nil) - ("\\<\\(val\\|extern\\|clause\\|and\\||let\\|rec\\>[ \t\n]*\\(\\(\\w\\|[_,?~.]\\)*\\)" - 2 font-lock-variable-name-face keep nil) - ("\\<\\(val\\|and\\|let\\>[ \t\n]*\\(\\(\\w\\|[_,?~.]\\)*\\)\\>\\(\\(\\w\\|[->_ \t,?~.]\\|(\\(\\w\\|[--->_ \t,?~.=]\\)*)\\)*\\)" - 6 font-lock-variable-name-face keep nil) - ("\\<\\([?~]?[_[:alpha:]]\\w*\\)[ \t\n]*:[^:>=]" - 0 font-lock-variable-name-face keep nil) - ("^#\\w+\\>" 0 font-lock-preprocessor-face t nil) - )) - (setq font-lock-defaults - (list* - 'sail-font-lock-keywords (not sail-use-syntax-ppss) nil - sail-font-lock-syntax nil - '(font-lock-syntactic-keywords - . sail-font-lock-syntactic-keywords) - '(parse-sexp-lookup-properties - . t) - '(font-lock-syntactic-face-function - . sail-font-lock-syntactic-face-function) - (unless sail-use-syntax-ppss - '((font-lock-fontify-region-function - . sail-fontify-region))))) - (when (and (boundp 'font-lock-fontify-region-function) - (not sail-use-syntax-ppss)) - (make-local-variable 'font-lock-fontify-region-function) - (setq font-lock-fontify-region-function 'sail-fontify-region))) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Indentation stuff - -(eval-and-compile - (defconst sail-no-more-code-this-line-regexp "[ \t]*" - "Regexp matching lines which have no more code: - blanks + (maybe) comment start.")) - -(defmacro sail-no-code-after (rex) - `(eval-when-compile (concat ,rex sail-no-more-code-this-line-regexp))) - -(defconst sail-no-code-this-line-regexp - (concat "^" sail-no-more-code-this-line-regexp)) - -(defun sail-ro (&rest words) (concat "\\<" (regexp-opt words t) "\\>")) - -(defconst sail-extra-unindent-regexp - (concat "\\(" (sail-ro "function") - "\\[" sail-no-more-code-this-line-regexp "\\)") - "Regexp for keywords needing extra indentation to compensate for case matches.") - -(defun sail-give-extra-unindent-regexp () - sail-extra-unindent-regexp) - -(defconst sail-keyword-regexp - (concat (sail-ro "scattered" "function" "typedef" "let" "overload" "default" "val" "register" - "alias" "union" "member" "clause" "cast" "extern" "effect" - "rec" "and" "switch" "case" "exit" "return" "foreach" "from" "else" - "to" "end" "downto" "in" "then" "with" "if" "nondet" "as" - "undefined" "const" "struct" "IN" "deinfix" "sizeof") - "\\|->\\|[;,|]") - "Regexp for all recognized keywords.") - -(defun sail-give-keyword-regexp () sail-keyword-regexp) - -(defconst sail-operator-regexp "[---+*/=<>@^&|]\\|:>\\|::\\|\\<\\(or\\|l\\(and\\|x?or\\|s[lr]\\)\\|as[lr]\\|mod\\)\\>" - "Regexp for all operators.") - -(defconst sail-matching-keyword-regexp - (sail-ro "and" "then" "else" "in") - "Regexp matching Sail keywords which act as end block delimiters.") - -(defun sail-give-matching-keyword-regexp () sail-matching-keyword-regexp) - -(defconst sail-matching-kwop-regexp - (concat sail-matching-keyword-regexp - "\\|\\<with\\>\\|[|>]?\\]\\|>?}\\|[|)]\\|;;") - "Regexp matching Sail keywords or operators which act as end block -delimiters.") - -(defun sail-give-matching-kwop-regexp () sail-matching-kwop-regexp) - -(defconst sail-block-regexp - (concat (sail-ro "foreach" "nondet" "if" "clause" "switch" "case") - "\\|[][(){}]\\|\\*)")) - -(defconst sail-find-kwop-regexp - (concat sail-matching-keyword-regexp "" sail-block-regexp)) - -(defun sail-give-find-kwop-regexp () sail-find-kwop-regexp) - -(defconst sail-governing-phrase-regexp - (sail-ro "val" "typedef" "function" "scattered" "default" "union" "member" - "end" "extern" "let") - "Regexp matching Sail phrase delimitors.") - -(defconst sail-keyword-alist - '(("end" . sail-default-indent) - ("foreach" . sail-foreach-indent) - ("val" . sail-val-indent) - ("function" . sail-fun-indent) - ("if" . sail-if-then-else-indent) - ("then" . sail-if-then-else-indent) - ("else" . sail-if-then-else-indent) - ("let" . sail-let-indent) - ("switch" . sail-match-indent) - - ;; Case match keywords - ("case" . sail-case-indent) - - ;; Assume default indentation for other keywords and operators - ) - "Association list of indentation values based on governing keywords.") - -(defconst sail-leading-kwop-alist - '(("}" . sail-find-match) - (">" . sail-find-match) - (")" . sail-find-match) - ("]" . sail-find-match) - ("|]" . sail-find-match) - ("||]" . sail-find-match) - ("in" . sail-find-in-match) - ("else" . sail-find-else-match) - ("then" . sail-find-then-match) - ("to" . sail-find-match) - ("downto" . sail-find-match) - ("by" . sail-find-match) - ("and" . sail-find-and-match)) - "Association list used in Sail mode for skipping back over nested blocks.") - -(defun sail-find-leading-kwop-match (kwop) - (funcall (cdr (assoc kwop sail-leading-kwop-alist)))) - -(defconst sail-binding-regexp "\\(\\<and\\>\\|(*\\<let\\>\\)") - -(defun sail-assoc-indent (kwop &optional look-for-let-or-and) - "Return relative indentation of the keyword given in argument." - (let ((ind (or (symbol-value (cdr (assoc kwop sail-keyword-alist))) - sail-default-indent)) - (looking-let-or-and (and look-for-let-or-and - (looking-at sail-binding-regexp)))) - (if (string-match (sail-give-extra-unindent-regexp) kwop) - (if (and sail-let-always-indent - looking-let-or-and (< ind sail-let-indent)) - sail-let-indent ind) - ind))) - -(defconst sail-meaningful-word-regexp - "[^ \t\n_[:alnum:]]\\|\\<\\(\\w\\|_\\)+\\>\\|\\*)") -(defun sail-find-meaningful-word () - "Look back for a word, skipping comments and blanks. -Returns the actual text of the word, if found." - (let ((found nil) (kwop nil) (pt (point))) - (while (and (not found) - (re-search-backward sail-meaningful-word-regexp - (point-min) t)) - (setq kwop (sail-match-string 0)) - (cond ((or (string= kwop "=") (string= kwop ">")) - (backward-char 2) - (setq kwop (concat ">>" kwop))) - ((and (string= kwop ">") (char-equal ?- (char-before))) - (backward-char) - (setq kwop "->"))) - (when (= pt (point)) - (error "sail-find-meaningful-word: inf loop at %d, kwop=%s" pt kwop)) - (setq pt (point)) - (if kwop - (if (sail-in-comment-p) - (sail-beginning-of-literal-or-comment-fast) - (setq found t)) - (setq found t))) - (if found kwop (goto-char (point-min)) nil))) - -(defun sail-make-find-kwop-regexp (kwop-regexp) - "Make a custom indentation regexp." - (concat (sail-give-find-kwop-regexp) "\\|" kwop-regexp)) - -;; Static regexps -(defconst sail-find-and-match-regexp - (concat (sail-ro "else" "in" "then" "downto" "by" "from" - "foreach" "if" "function" - "let" "in" "typedef" "val" "end") - "\\|[][(){}]\\|\\*)")) -(defconst sail-find-phrase-beginning-regexp - (concat (sail-ro "end" "typedef" "let") - "\\|^#[ \t]*[a-z][_a-z]*\\>\\|;;")) -(defconst sail-find-phrase-beginning-and-regexp - (concat "\\<\\(and\\)\\>\\|" sail-find-phrase-beginning-regexp)) -(defconst sail-back-to-paren-or-indentation-regexp - "[][(){}]\\|\\.<\\|>\\.\\|\\*)\\|^[ \t]*\\(.\\|\n\\)") - -(defun sail-make-indentation-regexps () - "Initialisation of specific indentation regexp. -Gathered here for memoization and dynamic reconfiguration purposes." - (setq - sail-find-comma-match-regexp - (sail-make-find-kwop-regexp - (concat (sail-ro "and" "switch" "else" "then" "function" "let" "foreach") - "\\|->\\|[[{(]")) - sail-find-with-match-regexp - (sail-make-find-kwop-regexp - (concat (sail-ro "switch" "case" "typedef") - "\\|[[{(]")) - sail-find-in-match-regexp - (sail-make-find-kwop-regexp (sail-ro "let" "function")) - sail-find-else-match-regexp - (sail-make-find-kwop-regexp ";") - sail-find-do-match-regexp - (sail-make-find-kwop-regexp "->") - sail-find-=-match-regexp - (sail-make-find-kwop-regexp - (concat (sail-ro "val" "let" "function" "typedef" "if" "in") - "\\|=")) - sail-find-arrow-match-regexp - (sail-make-find-kwop-regexp - (concat (sail-ro "extern" "typedef" "val" "function" "let") - "\\|[|;]")) - sail-find-semicolon-match-regexp - (sail-make-find-kwop-regexp - (concat ";" sail-no-more-code-this-line-regexp "\\|->\\|" - (sail-ro "let"))) - sail-find-phrase-indentation-regexp - (sail-make-find-kwop-regexp - (concat sail-governing-phrase-regexp "\\|" (sail-ro "and"))) - sail-find-phrase-indentation-break-regexp - (concat sail-find-phrase-indentation-regexp "\\|;") - sail-compute-argument-indent-regexp - (sail-make-find-kwop-regexp - (concat (sail-give-keyword-regexp) "\\|=")) - sail-compute-normal-indent-regexp - (concat sail-compute-argument-indent-regexp "\\|^.[ \t]*") - sail-find-monadic-match-regexp - (concat sail-block-regexp "\\|\\([;=]\\)\\|\\(->\\)\\|" - (sail-ro "val" "let" "function" "typedef" "if" "in" "end")))) - -(defun sail-strip-trailing-whitespace (string) - (if (string-match "[ \t]*\\'" string) - (substring string 0 (match-beginning 0)) - string)) - -(defun sail-find-kwop-pos (kr do-not-skip-regexp may-terminate-early) - "Look back for a keyword or operator matching KR (short for kwop regexp). -Skips blocks etc... - -Ignore occurences inside literals and comments. -If found, return the actual text of the keyword or operator." - (let ((found nil) - (kwop nil) pos - (kwop-regexp kr)) - (while (and (not found) - (setq pos (re-search-backward kwop-regexp (point-min) t)) - (setq kwop (sail-strip-trailing-whitespace - ;; for trailing blanks after a semicolon - (sail-match-string 0)))) - (cond - ((sail-in-literal-or-comment-p) - (sail-beginning-of-literal-or-comment-fast)) - ((looking-at "[>]})]") - (sail-backward-up-list)) - ((sail-at-phrase-break-p) - (setq found t)) - ((and do-not-skip-regexp (looking-at do-not-skip-regexp)) - (if (and (string= kwop "|") (char-equal ?| (preceding-char))) - (backward-char) - (setq found t))) - ((looking-at (sail-give-matching-keyword-regexp)) - (let ((mkwop (sail-find-leading-kwop-match (sail-match-string 0)))) - (when (and may-terminate-early (string-match kwop-regexp mkwop)) - (setq found t)))) - (t - (setq found t)))) - (if found (list kwop pos) (goto-char (point-min)) nil))) - -(defun sail-find-kwop (kr &optional do-not-skip-regexp) - (car (sail-find-kwop-pos kr do-not-skip-regexp nil))) - -(defun sail-find-match () - (let ((kwop (sail-find-kwop (sail-give-find-kwop-regexp)))) - (when (string= kwop "then") - (sail-find-then-match) - (sail-find-match)) - kwop)) - -(defun sail-find-comma-match () - (car (sail-find-kwop-pos sail-find-comma-match-regexp nil t))) - -(defun sail-find-in-match () - (let ((kwop (sail-find-kwop sail-find-in-match-regexp "\\<and\\>"))) - (cond - ((string= kwop "and") - (sail-find-in-match)) - (t - kwop)))) - -(defconst sail-find-then-match-regexp - (sail-make-find-kwop-regexp "\\(->\\)")) -(defun sail-find-then-kwop () - (sail-find-kwop sail-find-then-match-regexp "\\(->\\)")) -(defun sail-find-then-match () - (let ((kwop (sail-find-then-kwop))) - (cond ((string= kwop "if") - (let ((back (point))) - (sail-back-to-paren-or-indentation) - (if (looking-at "else[ \t]*\\((\\*.*\\*)\\)*[ \t]*if") - "else if" - (goto-char back) - kwop))) - (t kwop)))) - -(defun sail-find-then-else-match () - (let ((kwop (sail-find-then-kwop))) - (cond - ((string= kwop "if") - (let ((pos (point))) - (if (and (not (sail-in-indentation-p)) - (string= "else" (sail-find-meaningful-word))) - "else" - (goto-char pos) - kwop))) - (t - kwop)))) - -(defun sail-find-else-match () - (let ((kwop (sail-find-kwop sail-find-else-match-regexp - "\\<then\\>"))) - (cond - ((string= kwop "then") - (sail-find-then-else-match)) - ((string= kwop ";") - (sail-find-semicolon-match) - (sail-find-else-match))))) - - -(defconst sail-done-match-stop-regexp (sail-ro "and")) -(defun sail-find-done-match () - (let ((kwop (sail-find-kwop (sail-give-find-kwop-regexp) - sail-done-match-stop-regexp))) - (cond - ((string= kwop "and") - (sail-find-and-match)) - (t - kwop)))) - -(defun sail-find-and-match () - (let* ((kwop (sail-find-kwop - sail-find-and-match-regexp - (sail-give-and-stop-regexp))) - (old-point (point))) - (cond - ((string= kwop "typedef") - (let ((kwop2 (sail-find-meaningful-word))) - (cond ((string= kwop2 "and") - (sail-find-and-match)) - ((and (string= kwop "function") - (string= kwop2 "let")) - kwop2) - (t (goto-char old-point) kwop)))) - (t kwop)))) - -(defconst sail-=-stop-regexp (concat (sail-ro "and" "in" "function") "\\|=")) -(defun sail-give-=-stop-regexp () sail-=-stop-regexp) - -(defun sail-find-=-match () - (let ((kwop (sail-find-kwop - sail-find-=-match-regexp - (sail-give-=-stop-regexp)))) - (cond - ((string= kwop "and") - (sail-find-and-match)) - ((and (string= kwop "=") - (not (sail-false-=-p))) - (while (and (string= kwop "=") - (not (sail-false-=-p))) - (setq kwop (sail-find-=-match))) - kwop) - (t kwop)))) - -(defconst sail-captive-regexp - (sail-ro "let" "if" "typedef")) -(defun sail-captive-= () - (save-excursion - (sail-find-=-match) - (looking-at sail-captive-regexp))) - - -(defun sail-find-arrow-match () - (let ((kwop (sail-find-kwop (sail-give-find-arrow-match-regexp) - "\\<with\\>"))) - (cond - ((string= kwop "function") - (let ((pos (point))) - (progn (goto-char pos) kwop))) - ((not (string= kwop ":")) - kwop) - ;; If we get this far, we know we're looking at a colon. - ((or (char-equal (char-before) ?:) - (char-equal (char-after (1+ (point))) ?:) - (char-equal (char-after (1+ (point))) ?>)) - (sail-find-arrow-match)) - ;; Patch by T. Freeman - (t - (let ((oldpoint (point)) - (match (sail-find-arrow-match))) - (if (looking-at ":") - match - (progn - ;; Go back to where we were before the recursive call. - (goto-char oldpoint) - kwop))))))) - -(defconst sail-semicolon-match-stop-regexp - (sail-ro "and" "end" "in")) -(defconst sail-no-code-after-paren-regexp - (sail-no-code-after "[[{(][|<]?")) -(defun sail-semicolon-indent-kwop-point (&optional leading-semi-colon) - ;; return (kwop kwop-point indentation) - (let ((kwop (sail-find-kwop sail-find-semicolon-match-regexp - sail-semicolon-match-stop-regexp)) - (point (point))) - ;; We don't need to find the keyword matching `and' since we know it's `let'! - (list - (cond - ((string= kwop ";") - (forward-line 1) - (while (or (sail-in-comment-p) - (looking-at sail-no-code-this-line-regexp)) - (forward-line 1)) - (back-to-indentation) - (current-column)) - ((and leading-semi-colon - (looking-at "\\((\\|\\[[<|]?\\|{<?\\)[ \t]*[^ \t\n]") - (not (looking-at sail-no-code-after-paren-regexp))) - (current-column)) - ;; ((looking-at (tuareg-no-code-after "\\((\\|\\[[<|]?\\|{<?\\)")) - ;; (+ (current-column) tuareg-default-indent)) - ((looking-at "\\(\\.<\\|(\\|\\[[<|]?\\|{<?\\)") ; paren with subsequent text - (sail-search-forward-paren) - (current-column)) - ((string= kwop "->") - (if (save-excursion - (sail-find-arrow-match) - (or (looking-at "\\<function\\>\\||") - (looking-at (sail-give-extra-unindent-regexp)))) - (sail-paren-or-indentation-indent) - (sail-find-semicolon-match))) - ((string= kwop "in") - (sail-find-in-match) - (+ (current-column) sail-in-indent)) - ((string= kwop "let") - (+ (current-column) sail-let-indent)) - (t (sail-paren-or-indentation-indent))) - kwop point))) - -(defun sail-find-semicolon-match (&optional leading-semi-colon) - (car (sail-semicolon-indent-kwop-point leading-semi-colon))) - -(defmacro sail-reset-and-kwop (kwop) - `(when (and ,kwop (string= ,kwop "and")) - (setq ,kwop (sail-find-and-match)))) - -(defconst sail-phrase-regexp-1 (sail-ro "typedef" "end")) -(defconst sail-phrase-regexp-2 (sail-ro "and" "let" "function" "case")) -(defconst sail-phrase-regexp-3 - (sail-ro "and" "in")) -(defun sail-find-phrase-indentation (&optional phrase-break) - (if (and (looking-at sail-phrase-regexp-1) (> (point) (point-min)) - (save-excursion - (sail-find-meaningful-word) - (looking-at sail-phrase-regexp-2))) - (progn - (sail-find-meaningful-word) - (+ (current-column) sail-default-indent)) - (let ((looking-at-and (looking-at "\\<and\\>")) - (kwop (sail-find-kwop - (if phrase-break - sail-find-phrase-indentation-break-regexp - sail-find-phrase-indentation-regexp) - sail-phrase-regexp-3)) - (tmpkwop nil) (curr nil)) - (sail-reset-and-kwop kwop) - (cond ((not kwop) (current-column)) - ((and (string= kwop "in") - (not (save-excursion - (setq tmpkwop (sail-find-in-match)) - (sail-reset-and-kwop tmpkwop) - (setq curr (point)) - (and (string= tmpkwop "let") - (not (sail-looking-at-internal-let)))))) - (goto-char curr) - (sail-find-phrase-indentation phrase-break)) - ((sail-at-phrase-break-p) - (end-of-line) - (sail-skip-blank-and-comments) - (current-column)) - ((string= kwop "let") - (if (sail-looking-at-internal-let) - (sail-find-phrase-indentation phrase-break) - (current-column))) - ((string= kwop "in") - (sail-find-in-match) - (current-column)) - ((looking-at "\\(\\.<\\|(\\|\\[[<|]?\\|{<?\\)[ \t]*[^ \t\n]") - (sail-search-forward-paren) - (current-column)) - (t (current-column)))))) - -(defconst sail-paren-or-indentation-stop-regexp - (sail-ro "and" "in")) -(defun sail-back-to-paren-or-indentation () - "Search backwards for the first open paren in line, or skip to indentation. -Returns t iff skipped to indentation." - (if (or (bolp) (sail-in-indentation-p)) - (progn (back-to-indentation) t) - (let ((kwop (sail-find-kwop - sail-back-to-paren-or-indentation-regexp - sail-paren-or-indentation-stop-regexp)) - (retval)) - (setq retval - (cond - ((string= kwop "in") - (sail-in-indentation-p)) -; ((looking-at "[[{(]") (tuareg-search-forward-paren) nil) -; ((looking-at "\\.<") -; (if tuareg-support-metaocaml -; (progn -; (tuareg-search-forward-paren) nil) -; (tuareg-back-to-paren-or-indentation))) - (t (back-to-indentation) t))) - (cond - ; ((looking-at "|[^|]") - ; (re-search-forward "|[^|][ \t]*") nil) - ((string= kwop "in") - (sail-find-in-match) - (sail-back-to-paren-or-indentation) - (if (looking-at "\\<\\(let\\|and\\)\\>") - (forward-char sail-in-indent)) nil) - (t retval))))) - -(defun sail-paren-or-indentation-column () - (sail-back-to-paren-or-indentation) - (current-column)) - -(defun sail-paren-or-indentation-indent () - (+ (sail-paren-or-indentation-column) sail-default-indent)) - -(defun sail-search-forward-paren () - (re-search-forward "\\(\\.<\\|(\\|\\[[<|]?\\|{|<\\)[ \t]*")) - -(defun sail-add-default-indent (leading-operator) - (if leading-operator 0 sail-default-indent)) - -(defconst sail-internal-let-regexp - (concat "[[({;=]\\|" - (sail-ro "if" "in" "then" "else" "switch"))) -(defun sail-looking-at-internal-let () - (save-excursion - (sail-find-meaningful-word) - (and (not (sail-at-phrase-break-p)) - (or (looking-at sail-internal-let-regexp) - (looking-at sail-operator-regexp))))) - -(defun sail-looking-at-in-let () - (save-excursion - (string= (sail-find-meaningful-word) "in"))) - -(defun sail-indent-from-previous-kwop () - (let* ((start-pos (point)) - (kwop (sail-find-argument-kwop-non-blank t)) - (captive= (and (string= kwop "=") (sail-captive-=))) - (kwop-pos (point))) - (forward-char (length kwop)) - (sail-skip-blank-and-comments) - (cond ((or (not captive=) - (/= (point) start-pos)) ; code between paren and kwop - (goto-char start-pos) - (sail-paren-or-indentation-indent)) - (t - (goto-char kwop-pos) - (when (string= kwop "=") - (setq kwop (sail-find-=-match))) - (+ sail-default-indent - (if (assoc kwop sail-leading-kwop-alist) - (sail-compute-kwop-indent kwop) - (current-column))))))) - -(defun sail-indent-from-paren (leading-operator start-pos) - (cond - ((looking-at (sail-no-code-after "\\(\\(\\.<\\|(\\|\\[[<|]?\\|{\\|<\\)\\)")) - (cond ((sail-in-indentation-p) - (+ sail-default-indent - (current-column))) - (t (sail-indent-from-previous-kwop)))) - ((looking-at "([ \t]*\\(\\w\\)") - (goto-char (match-beginning 1)) - (current-column)) - (t - (+ (sail-add-default-indent leading-operator) - (current-column))))) - -(defun sail-skip-to-next-form (old-point) - (while (and (not (looking-at sail-no-more-code-this-line-regexp)) - (< (point) old-point)) ; do not go beyond old-point - (forward-sexp 1)) - (sail-skip-blank-and-comments) - (sail-back-to-paren-or-indentation)) - -(defun sail-find-argument-kwop (leading-operator) - (sail-find-kwop (if leading-operator - sail-compute-argument-indent-regexp - sail-compute-normal-indent-regexp) - (sail-give-keyword-regexp))) - -(defun sail-find-argument-kwop-clean (leading-operator) - (let (kwop) - (while (or (progn (setq kwop (sail-find-argument-kwop leading-operator)) - (sail-reset-and-kwop kwop) - nil) - (and (string= kwop "=") (sail-false-=-p)) - (and (looking-at sail-no-code-this-line-regexp) - (not (= (point) (point-min)))))) - kwop)) - -(defun sail-find-argument-kwop-non-blank (leading-operator) - (let ((kwop "") (point (1+ (point)))) - (while (and (> point (point)) (string= "" kwop)) - (setq point (point) - kwop (sail-find-argument-kwop-clean leading-operator))) - kwop)) - -(defun sail-compute-argument-indent (leading-operator) - (let* ((old-point (line-beginning-position)) - (kwop (sail-find-argument-kwop-non-blank leading-operator)) - (match-end-point (+ (point) (length kwop)))) ; match-end is invalid! - (cond - ((let (matching-kwop matching-pos) - (save-excursion - (setq matching-kwop (sail-find-arrow-match)) - (setq matching-pos (point))) - (cond - ((or (string= matching-kwop "val") (string= matching-kwop "let") (string= matching-kwop "function")) - (+ (current-column) sail-val-indent)) - (t - (+ (sail-paren-or-indentation-column) - (sail-add-default-indent leading-operator)))))) - ((string= kwop "function") - (+ (sail-paren-or-indentation-column) - (sail-add-default-indent leading-operator) - (sail-assoc-indent kwop))) - ((<= old-point (point)) - (+ (sail-add-default-indent leading-operator) - (current-column))) - (t - (goto-char match-end-point) ; skip kwop == (forward-char (length kwop)) - (sail-skip-to-next-form old-point) - (+ (sail-add-default-indent - (if (save-excursion (goto-char match-end-point) - (looking-at sail-no-more-code-this-line-regexp)) - (or leading-operator (string= kwop "{") - (looking-at (sail-no-code-after "[[:upper:]].*\\."))) - (not (looking-at sail-operator-regexp)))) - (current-column)))))) - -(defun sail-compute-arrow-indent (start-pos) - (let (kwop pos) - (save-excursion (setq kwop (sail-find-arrow-match) pos (point))) - (cond ((or (string= kwop "val") - (string= kwop "let")) - (goto-char pos) - (+ (current-column) sail-val-indent)) - ((string= kwop "typedef") - (goto-char pos) - (+ (current-column) sail-type-indent - sail-default-indent)) - ((string= kwop "(") - (goto-char pos) - (sail-indent-after-next-char)) - ((or (string= kwop "{") - (string= kwop ";")) - (if (and (looking-at "->") - (search-backward ":" pos t)) - (sail-indent-after-next-char) - (sail-back-to-paren-or-indentation) - (current-column))) - (t (sail-paren-or-indentation-indent))))) - -(defun sail-compute-keyword-indent (kwop leading-operator start-pos) - (cond ((string= kwop ";") - (if (looking-at (sail-no-code-after ";")) - (let* ((pos (point)) (indent (sail-find-semicolon-match))) - (if (looking-at sail-phrase-regexp-1) - (progn - (goto-char start-pos) - (if (search-backward ":" pos t) - (sail-indent-after-next-char) - indent)) - indent)) - (sail-paren-or-indentation-indent))) - ((string= kwop ",") - (if (looking-at (sail-no-code-after ",")) - (let ((mkwop (sail-find-comma-match))) - (cond ((or (string= mkwop "[") - (string= mkwop "{") - (string= mkwop "(") - (string= mkwop "<") - (string- mkwop "[|")) - (forward-char 1) (skip-syntax-forward " ") - (current-column)) - ((looking-at "[[{(]\\|\\<") - (sail-indent-from-paren t start-pos)) - ((or (and (looking-at "[<|]") - (char-equal ?\[ (preceding-char))) - (and (looking-at "<") - (char-equal ?\{ (preceding-char)))) - (sail-backward-char) - (sail-indent-from-paren t start-pos)) - ((and (looking-at "\\<let\\>") (string= mkwop "in")) - (+ (current-column) sail-in-indent)) - (t (+ (sail-paren-or-indentation-column) - (sail-assoc-indent mkwop))))) - (sail-paren-or-indentation-indent))) - ((or (string= kwop "function") (string= kwop "and")) - (sail-back-to-paren-or-indentation) - (+ (sail-paren-or-indentation-indent) - (sail-assoc-indent kwop t))) - ((string-match "\\<\\(function\\)\\>" kwop) - (+ (sail-paren-or-indentation-column) - (sail-add-default-indent leading-operator) - (sail-assoc-indent kwop t))) - ((string-match (sail-give-extra-unindent-regexp) kwop) - (+ (sail-paren-or-indentation-column) - (sail-assoc-indent kwop t))) - ((string= kwop "in") - (when (looking-at (sail-no-code-after "\\<in\\>")) - (sail-find-in-match)) - (+ (current-column) - sail-in-indent)) - ((string-match (sail-give-matching-kwop-regexp) kwop) - (sail-find-leading-kwop-match kwop) - (if (sail-in-indentation-p) - (+ (current-column) - (sail-assoc-indent kwop t)) - (sail-back-to-paren-or-indentation) - (+ (sail-paren-or-indentation-indent) - (sail-assoc-indent kwop t)))) - (t (+ (if (sail-in-indentation-p) - (current-column) - (sail-paren-or-indentation-indent)) - (sail-assoc-indent kwop t))))) - -(defconst sail-=-indent-regexp-1 - (sail-ro "val" "let" "function" "scattered" "foreach" "if")) - -(defun sail-compute-=-indent (start-pos) - (let ((current-column-module-type nil) (kwop1 (sail-find-=-match)) - (next-pos (point))) - (+ (save-excursion - (sail-reset-and-kwop kwop1) - (cond ((string= kwop1 "typedef") - (sail-find-meaningful-word) - (cond (t (goto-char start-pos) - (beginning-of-line) - (+ (sail-add-default-indent - (looking-at "[ \t]*[\[|]")) - sail-type-indent)))) - ((looking-at sail-=-indent-regexp-1) - (let ((matched-string (sail-match-string 0))) - (setq current-column-module-type (current-column)) - (sail-assoc-indent matched-string))) - ((looking-at sail-no-code-after-paren-regexp) - (setq current-column-module-type - (sail-indent-from-paren nil next-pos)) - sail-default-indent) - (t (setq current-column-module-type - (sail-paren-or-indentation-indent)) - sail-default-indent))) - (or current-column-module-type - (current-column))))) - -(defun sail-indent-after-next-char () - (forward-char 1) - (sail-skip-blank-and-comments) - (current-column)) - -(defconst sail-definitions-regexp - (sail-ro "and" "val" "typedef" "scattered" "function" "default" "register" "let") - "Regexp matching definition phrases.") - -(defun sail-compute-normal-indent () - (let ((leading-operator (looking-at sail-operator-regexp))) - (beginning-of-line) - (save-excursion - (let ((start-pos (point)) - (kwop (sail-find-argument-kwop-clean leading-operator))) - (cond - ((not kwop) (current-column)) - ((sail-at-phrase-break-p) - (sail-find-phrase-indentation t)) - ((or (looking-at "[[{(<]") - (and (looking-at "[<|]") - (char-equal ?\[ (preceding-char)) - (progn (sail-backward-char) t)) - (and (looking-at "<") - (char-equal ?\{ (preceding-char)) - (progn (sail-backward-char) t))) - (cond ((looking-at "{ *[A-Z]") - (forward-char 1) (skip-syntax-forward " ") - (current-column)) - ((looking-at (sail-no-code-after "[[{(][<|]?")) - (sail-indent-from-paren leading-operator start-pos)) - ((and leading-operator (string= kwop "(")) - (sail-indent-after-next-char)) - (t (+ sail-default-indent - (sail-indent-from-paren leading-operator start-pos))))) - ((looking-at (sail-give-keyword-regexp)) - (sail-compute-keyword-indent kwop leading-operator start-pos)) - ((and (string= kwop "=") (not (sail-false-=-p)) - (or (null leading-operator) - ;; defining "=", not testing for equality - (string-match sail-definitions-regexp - (save-excursion - (sail-find-argument-kwop-clean t))))) - (sail-compute-=-indent start-pos)) - (nil 0) - (t (sail-compute-argument-indent leading-operator))))))) - -(defun sail-compute-paren-indent (paren-match-p old-point) - (unless paren-match-p - (sail-search-forward-paren)) - (let ((looking-at-paren (char-equal ?\( (char-after))) (start-pos (point))) - (when (or looking-at-paren - (looking-at (sail-no-code-after "\\(\{\\(.*with[ \t]*\\([[:upper:]].*\\.\\)?\\)?\\|\\[\\)"))) - (if (sail-in-indentation-p) - (sail-back-to-paren-or-indentation) - (sail-indent-from-previous-kwop)) - (when looking-at-paren - (skip-chars-forward "( \t" start-pos)) - (while (and (looking-at "[([{]") - (> (scan-sexps (point) 1) - (save-excursion (goto-char old-point) - (line-end-position)))) - (forward-char 1) - (skip-syntax-forward " ")))) - (current-column)) - -(defun sail-compute-kwop-indent-general (kwop matching-kwop) - (let* ((looking-at-matching (looking-at matching-kwop)) - (extra-unindent ; non-paren code before matching-kwop - (unless (save-excursion - (skip-chars-backward "( \t" (line-beginning-position)) - (bolp)) - (sail-back-to-paren-or-indentation) - t))) - (+ (current-column) - (sail-add-default-indent - (or (not (string= kwop "then")) - looking-at-matching))))) - -(defun sail-compute-kwop-indent (kwop) - (when (string= kwop "rec") - (setq kwop "and")) - (let* ((old-point (point)) - (paren-match-p (looking-at "[|>]?[]})]\\|>\\.")) - (real-pipe (looking-at "|\\([^|]\\|$\\)")) - (matching-kwop (sail-find-leading-kwop-match kwop))) - (cond ((looking-at "[[{(][<|]?\\|\\.<") - (sail-compute-paren-indent paren-match-p old-point)) - ((string= kwop "and") - (if (sail-in-indentation-p) - (current-column) - (sail-paren-or-indentation-column))) - ((string= kwop "in") - (+ (current-column) - (sail-add-default-indent (string= matching-kwop "let")))) - ((not (string= kwop "and")) ; pretty general case - (sail-compute-kwop-indent-general kwop matching-kwop)) - (t (sail-paren-or-indentation-column))))) - -(defun sail-indent-to-code (beg-pos match) - (unless (and (string= match "(") - (search-forward "->" beg-pos t)) - (forward-char (length match))) - (sail-skip-blank-and-comments) - (current-column)) - -(defun sail-indent-command (&optional from-leading-star) - "Indent the current line in Sail mode. - -Compute new indentation based on Sail syntax." - (interactive "*") - (unless from-leading-star - (sail-auto-fill-insert-leading-star)) - (let ((case-fold-search nil)) - (sail-with-internal-syntax - (save-excursion - (back-to-indentation) - (indent-line-to (max 0 (sail-compute-indent)))) - (when (sail-in-indentation-p) (back-to-indentation))))) - -(defun sail-compute-indent () - (save-excursion - (cond - ((sail-in-comment-p) - (cond - ((looking-at "(\\*") - (if sail-indent-leading-comments - (save-excursion - (sail-skip-blank-and-comments) - (back-to-indentation) - (current-column)) - (current-column))) - ((looking-at "\\*\\**)") - (sail-beginning-of-literal-or-comment-fast) - (if (sail-leading-star-p) - (+ (current-column) - (if (save-excursion - (forward-line 1) - (back-to-indentation) - (looking-at "*")) 1 - sail-comment-end-extra-indent)) - (+ (current-column) sail-comment-end-extra-indent))) - (sail-indent-comments - (let ((star (and (sail-leading-star-p) - (looking-at "\\*")))) - (sail-beginning-of-literal-or-comment-fast) - (if star (re-search-forward "(") (re-search-forward "(\\*+[ \t]*")) - (current-column))) - (t (current-column)))) - ((sail-in-literal-p) - (current-column)) - ((looking-at "\\<let\\>") - (if (sail-looking-at-internal-let) - (if (sail-looking-at-in-let) - (progn - (sail-find-meaningful-word) - (sail-find-in-match) - (current-column)) - (sail-compute-normal-indent)) - (sail-find-phrase-indentation))) - ((or (looking-at sail-governing-phrase-regexp) - (looking-at ";")) - (sail-find-phrase-indentation)) - ((looking-at ";") - (sail-find-semicolon-match t)) - ((or (looking-at (sail-give-matching-kwop-regexp)) - (looking-at "\\<rec\\>")) - (sail-compute-kwop-indent (sail-match-string 0))) - (t (sail-compute-normal-indent))))) - -(defun sail-split-string () - "Called whenever a line is broken inside an Sail string literal." - (insert-before-markers "\\ ") - (sail-backward-char)) - -(defadvice newline-and-indent (around - sail-newline-and-indent - activate) - "Handle multi-line strings in Sail mode." - (let ((hooked (and (eq major-mode 'sail-mode) (sail-in-literal-p))) - (split-mark)) - (when hooked - (setq split-mark (set-marker (make-marker) (point))) - (sail-split-string)) - ad-do-it - (when hooked - (goto-char split-mark) - (set-marker split-mark nil)))) - -(defun sail-electric-rp () - "If inserting a ) operator or a comment-end at beginning of line, -reindent the line." - (interactive "*") - (let ((electric (and sail-electric-indent - (or (sail-in-indentation-p) - (char-equal ?* (preceding-char))) - (not (sail-in-literal-p)) - (or (not (sail-in-comment-p)) - (save-excursion - (back-to-indentation) - (looking-at "\\*")))))) - (self-insert-command 1) - (and electric - (indent-according-to-mode)))) - -(defun sail-electric-lt () - "If inserting a > operator or a comment-end at beginning of line, -reindent the line." - (interactive "*") - (let ((electric (and sail-electric-indent - (or (sail-in-indentation-p) - (char-equal ?* (preceding-char))) - (not (sail-in-literal-p)) - (or (not (sail-in-comment-p)) - (save-excursion - (back-to-indentation) - (looking-at "\\*")))))) - (self-insert-command 1) - (and electric - (indent-according-to-mode)))) - -(defun sail-electric-rc () - "If inserting a } operator at beginning of line, reindent the line." - (interactive "*") - (let* ((prec (preceding-char)) - (look-bra (and sail-electric-close-range - (not (sail-in-literal-or-comment-p)) - (not (char-equal ?> prec)))) - (electric (and sail-electric-indent - (or (sail-in-indentation-p) - (and (char-equal ?> prec) - (save-excursion (sail-backward-char) - (sail-in-indentation-p)))) - (not (sail-in-literal-or-comment-p))))) - (self-insert-command 1) - (when look-bra - (save-excursion - (let ((inserted-char - (save-excursion - (sail-backward-char) - (sail-backward-up-list) - (cond ((looking-at "{<") ">") - (t ""))))) - (sail-backward-char) - (insert inserted-char)))) - (when electric (indent-according-to-mode)))) - -(defun sail-electric-rb () - "If inserting a ] operator at beginning of line, reindent the line. - -Reindent also if ] is inserted after a | operator at beginning of line. -Also, if the matching [ is followed by a | and this ] is not preceded -by |, insert one |." - (interactive "*") - (let* ((prec (preceding-char)) - (look-pipe-or-bra (and sail-electric-close-range - (not (sail-in-literal-or-comment-p)) - (not (and (char-equal ?| prec) - (not (char-equal - (save-excursion - (sail-backward-char) - (preceding-char)) ?\[)))))) - (electric (and sail-electric-indent - (or (sail-in-indentation-p) - (and (char-equal ?| prec) - (save-excursion (sail-backward-char) - (sail-in-indentation-p)))) - (not (sail-in-literal-or-comment-p))))) - (self-insert-command 1) - (when look-pipe-or-bra - (save-excursion - (let ((inserted-char - (save-excursion - (sail-backward-char) - (sail-backward-up-list) - (cond ((looking-at "\\[|") "\\|") - (t ""))))) - (sail-backward-char) - (insert inserted-char)))) - (when electric (indent-according-to-mode)))) - -(defun sail-abbrev-hook () - "If inserting a leading keyword at beginning of line, reindent the line." - (unless (sail-in-literal-or-comment-p) - (let* ((bol (line-beginning-position)) - (kw (save-excursion - (and (re-search-backward "^[ \t]*\\(\\w\\|_\\)+\\=" bol t) - (sail-match-string 1))))) - (when kw - (insert " ") - (indent-according-to-mode) - (backward-delete-char-untabify 1))))) - -(defun sail-skip-to-end-of-phrase () - (let ((old-point (point))) - (when (and (string= (sail-find-meaningful-word) ";") - (char-equal (preceding-char) ?\;)) - (setq old-point (1- (point)))) - (goto-char old-point) - (let ((kwop (sail-find-meaningful-word))) - (goto-char (+ (point) (length kwop)))))) - -(defun sail-skip-blank-and-comments () - (skip-syntax-forward " ") - (while (and (not (eobp)) (sail-in-comment-p) - (search-forward "*)" nil t)) - (skip-syntax-forward " "))) - -(defun sail-skip-back-blank-and-comments () - (skip-syntax-backward " ") - (while (save-excursion (sail-backward-char) - (and (> (point) (point-min)) (sail-in-comment-p))) - (sail-backward-char) - (sail-beginning-of-literal-or-comment) (skip-syntax-backward " "))) - -(defun sail-find-phrase-beginning (&optional stop-at-and) - "Find `real' phrase beginning and return point." - (beginning-of-line) - (sail-skip-blank-and-comments) - (end-of-line) - (sail-skip-to-end-of-phrase) - (let ((old-point (point)) (pt (point))) - (if stop-at-and - (sail-find-kwop sail-find-phrase-beginning-and-regexp "and") - (sail-find-kwop sail-find-phrase-beginning-regexp)) - (while (and (> (point) (point-min)) (< (point) old-point) - (or (not (looking-at sail-find-phrase-beginning-and-regexp)) - (and (looking-at "\\<let\\>") - (sail-looking-at-internal-let)) - (and (looking-at "\\<and\\>") - (save-excursion - (sail-find-and-match) - (sail-looking-at-internal-let))) - ) - (when (= pt (point)) - (error "sail-find-phrase-beginning: inf loop at %d" pt)) - (setq pt (point)) - (if (looking-at "\\<end\\>") - (sail-find-match) - (unless (bolp) (sail-backward-char)) - (setq old-point (point)) - (if stop-at-and - (sail-find-kwop sail-find-phrase-beginning-and-regexp "and") - (sail-find-kwop sail-find-phrase-beginning-regexp)))) - (when (sail-at-phrase-break-p) - (end-of-line) (sail-skip-blank-and-comments)) - (back-to-indentation) - (point)))) - -(defun sail-imenu-prev-index-position () - "The default value for `imenu-prev-index-position-function'." - (let ((pos (point)) ret) - (while (and (<= 0 pos) - (<= pos (setq ret (sail-find-phrase-beginning t)))) - (setq pos (goto-char (1- pos)))) - (and (<= 0 pos) ret))) - -(defun sail-imenu-extract-index-name () - "The default value for `imenu-extract-index-name-function'." - (forward-sexp 1) - (skip-syntax-forward " ") - (buffer-substring-no-properties (point) (scan-sexps (point) 1))) - -(defun sail-mark-phrase () - "Put mark at end of this Sail phrase, point at beginning. -The Sail phrase is the phrase just before the point." - (interactive) - (let ((pair (sail-discover-phrase))) - (goto-char (nth 1 pair)) (push-mark (nth 0 pair) t t))) - -(defun sail-next-phrase (&optional quiet stop-at-and) - "Skip to the beginning of the next phrase." - (interactive "i") - (goto-char (save-excursion - (nth 2 (sail-discover-phrase quiet stop-at-and)))) - (cond - ((looking-at "}") - (forward-char 1) - (sail-skip-blank-and-comments)) - ((looking-at ")") - (forward-char 1) - (sail-skip-blank-and-comments)) - ((looking-at ";") - (forward-char 1) - (sail-skip-blank-and-comments)))) - -(defun sail-previous-phrase () - "Skip to the beginning of the previous phrase." - (interactive) - (beginning-of-line) - (sail-skip-to-end-of-phrase) - (sail-discover-phrase)) - -(defun sail-indent-phrase () - "Depending of the context: justify and indent a comment, -or indent all lines in the current phrase." - (interactive) - (save-excursion - (back-to-indentation) - (if (sail-in-comment-p) - (let* ((cobpoint (save-excursion - (sail-beginning-of-literal-or-comment) - (point))) - (begpoint (save-excursion - (while (and (> (point) cobpoint) - (sail-in-comment-p) - (not (looking-at "^[ \t]*$"))) - (forward-line -1)) - (max cobpoint (point)))) - (coepoint (save-excursion - (while (sail-in-comment-p) - (re-search-forward "\\*)" nil 'end)) - (point))) - (endpoint (save-excursion - (re-search-forward "^[ \t]*$" coepoint 'end) - (line-beginning-position 2))) - (leading-star (sail-leading-star-p))) - (goto-char begpoint) - (while (and leading-star - (< (point) endpoint) - (not (looking-at "^[ \t]*$"))) - (forward-line 1) - (back-to-indentation) - (when (looking-at "\\*\\**\\([^)]$\\)") - (delete-char 1) - (setq endpoint (1- endpoint)))) - (goto-char (min (point) endpoint)) - (fill-region begpoint endpoint) - (re-search-forward "\\*)" nil 'end) - (setq endpoint (point)) - (when leading-star - (goto-char begpoint) - (forward-line 1) - (if (< (point) endpoint) - (sail-auto-fill-insert-leading-star t))) - (indent-region begpoint endpoint nil)) - (let ((pair (sail-discover-phrase))) - (indent-region (nth 0 pair) (nth 1 pair) nil))))) - -(defun sail-complete (arg) - "Completes qualified Sail identifiers." - (interactive "p") - (modify-syntax-entry ?_ "w" sail-mode-syntax-table) - (caml-complete arg) - (modify-syntax-entry ?_ "_" sail-mode-syntax-table)) - -(defun sail-ensure-space () - (let ((prec (preceding-char))) - (when (and prec (not (char-equal ?\ (char-syntax prec)))) - (insert " ")))) - -(defun sail-insert-if-form () - "Insert a nicely formatted if-then-else form, leaving a mark after else." - (interactive "*") - (sail-ensure-space) - (let ((old (point))) - (insert "if\n\nthen\n\nelse\n") - (end-of-line) - (indent-region old (point) nil) - (indent-according-to-mode) - (push-mark) - (forward-line -2) - (indent-according-to-mode) - (forward-line -2) - (indent-according-to-mode))) - -(defun sail-insert-let-form () - "Insert a nicely formatted let-in form, leaving a mark after in." - (interactive "*") - (sail-ensure-space) - (let ((old (point))) - (insert "let in\n") - (end-of-line) - (indent-region old (point) nil) - (indent-according-to-mode) - (push-mark) - (beginning-of-line) - (backward-char 4) - (indent-according-to-mode))) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Menu support - -(defun sail-about () - (interactive) - (describe-variable 'sail-mode-version)) - -(defun sail-short-cuts () - "Short cuts for the sail mode: -\\{sail-mode-map} - -" - (interactive) - (describe-function 'sail-short-cuts)) - -(defun sail-help () - (interactive) - (describe-function 'sail-mode)) - -(defvar sail-definitions-menu (list ["Scan..." sail-list-definitions t]) - "Initial content of the definitions menu.") -(make-variable-buffer-local 'sail-definitions-menu) - -(defvar sail-definitions-menu-last-buffer nil) -(defvar sail-definitions-keymaps nil) - -(defun sail-build-menu () - (easy-menu-define - sail-mode-menu (list sail-mode-map) - "Sail Mode Menu." - '("Sail" - ("Sail Forms" - ["let .. in .." sail-insert-let-form t] - ["if .. then .. else .." sail-insert-if-form t]) - "---" - ["Customize Sail Mode..." (customize-group 'sail) t] - ("Sail Options" ["Dummy" nil t]) - "---" - ["About" sail-about t] - ["Short Cuts" sail-short-cuts] - ["Help" sail-help t])) - (easy-menu-add sail-mode-menu) - (sail-update-options-menu) - ;; Save and update definitions menu - (when (functionp 'easy-menu-create-menu) - ;; Patch for Emacs - (add-hook 'menu-bar-update-hook - 'sail-with-emacs-update-definitions-menu) - (make-local-variable 'sail-definitions-keymaps) - (setq sail-definitions-keymaps - (cdr (easy-menu-create-menu - "Definitions" sail-definitions-menu))) - (setq sail-definitions-menu-last-buffer nil))) - -(defun sail-update-definitions-menu () - (when (eq major-mode 'sail-mode) - (easy-menu-change - '("Sail") "Definitions" - sail-definitions-menu))) - -(defun sail-with-emacs-update-definitions-menu () - (when (current-local-map) - (let ((keymap - (lookup-key (current-local-map) [menu-bar Sail Definitions]))) - (if (and - (keymapp keymap) - (not (eq sail-definitions-menu-last-buffer (current-buffer)))) - (setcdr keymap sail-definitions-keymaps) - (setq sail-definitions-menu-last-buffer (current-buffer)))))) - -(defun sail-toggle-option (symbol) - (interactive) - (set symbol (not (symbol-value symbol))) - (when (eq 'sail-use-abbrev-mode symbol) - (abbrev-mode sail-use-abbrev-mode)) ; toggle abbrev minor mode - (sail-update-options-menu)) - -(defun sail-update-options-menu () - (easy-menu-change - '("Sail") "Sail Options" - (mapcar (lambda (pair) - (if (consp pair) - (vector (car pair) - (list 'sail-toggle-option (cdr pair)) - ':style 'toggle - ':selected (nth 1 (cdr pair)) - ':active t) - pair)) sail-options-list)) - ) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Definitions List - -;; Designed from original code by M. Quercia - -(defconst sail--id-regexp "[[:alpha:]][_'[:alnum:]]*") - -(defconst sail-definitions-bind-skip-regexp - (concat (sail-ro "rec" "typedef" "function") "\\'" - sail--id-regexp "\\|('.*)") - "Regexp matching stuff to ignore after a binding keyword.") - -(defconst sail-identifier-regexp (concat "\\<" sail--id-regexp "\\>")) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; Hooks and Exit - -(eval-when-compile - (autoload 'speedbar-add-supported-extension "speedbar")) -(when (require 'speedbar nil t) - (speedbar-add-supported-extension - '(".sail"))) - -(defvar sail-load-hook nil - "This hook is run when Sail is loaded in. It is a good place to put -key-bindings or hack Font-Lock keywords...") - -(run-hooks 'sail-load-hook) + (set-syntax-table sail2-mode-syntax-table) + (setq font-lock-defaults '(sail2-font-lock-keywords)) + (setq comment-start-skip "\\(//+\\|/\\*+\\)\\s *") + (setq comment-start "/*") + (setq comment-end "*/") + (setq major-mode 'sail2-mode) + (setq mode-name "Sail2") + (run-hooks 'sail2-mode-hook)) -(provide 'sail-mode) +(provide 'sail2-mode) -;;; sail.el ends here diff --git a/editors/sail2-mode.el b/editors/sail2-mode.el deleted file mode 100644 index 38404f14..00000000 --- a/editors/sail2-mode.el +++ /dev/null @@ -1,67 +0,0 @@ - -(defvar sail2-mode-hook nil) - -(add-to-list 'auto-mode-alist '("\\.sail\\'" . sail2-mode)) - -(defconst sail2-keywords - '("val" "function" "type" "struct" "union" "enum" "let" "var" "if" "then" "by" - "else" "match" "in" "return" "register" "ref" "forall" "operator" "effect" - "overload" "cast" "sizeof" "constant" "constraint" "default" "assert" "newtype" "from" - "pure" "infixl" "infixr" "infix" "scattered" "end" "try" "catch" "and" "to" - "throw" "clause" "as" "repeat" "until" "while" "do" "foreach" "bitfield" - "mapping" "where" "with")) - -(defconst sail2-kinds - '("Int" "Type" "Order" "Bool" "inc" "dec" - "barr" "depend" "rreg" "wreg" "rmem" "rmemt" "wmv" "wmvt" "eamem" "wmem" - "exmem" "undef" "unspec" "nondet" "escape" "configuration")) - -(defconst sail2-types - '("vector" "int" "nat" "atom" "range" "unit" "bit" "real" "list" "bool" "string" "bits" "option" - "uint64_t" "int64_t" "bv_t" "mpz_t")) - -(defconst sail2-special - '("_prove" "_not_prove" "create" "kill" "convert" "undefined" - "$define" "$include" "$ifdef" "$ifndef" "$else" "$endif" "$option" "$latex")) - -(defconst sail2-font-lock-keywords - `((,(regexp-opt sail2-keywords 'symbols) . font-lock-keyword-face) - (,(regexp-opt sail2-kinds 'symbols) . font-lock-builtin-face) - (,(regexp-opt sail2-types 'symbols) . font-lock-type-face) - (,(regexp-opt sail2-special 'symbols) . font-lock-preprocessor-face) - ("~" . font-lock-negation-char-face) - ("\\(::\\)<" 1 font-lock-keyword-face) - ("@" . font-lock-preprocessor-face) - ("<->" . font-lock-negation-char-face) - ("\'[a-zA-Z0-9_]+" . font-lock-variable-name-face) - ("\\([a-zA-Z0-9_]+\\)(" 1 font-lock-function-name-face) - ("function \\([a-zA-Z0-9_]+\\)" 1 font-lock-function-name-face) - ("val \\([a-zA-Z0-9_]+\\)" 1 font-lock-function-name-face) - ("\\_<\\([0-9]+\\|0b[0-9_]+\\|0x[0-9a-fA-F_]+\\|true\\|false\\|bitone\\|bitzero\\)\\_>\\|()" . font-lock-constant-face))) - -(defconst sail2-mode-syntax-table - (let ((st (make-syntax-table))) - (modify-syntax-entry ?> "." st) - (modify-syntax-entry ?_ "w" st) - (modify-syntax-entry ?' "w" st) - (modify-syntax-entry ?* ". 23" st) - (modify-syntax-entry ?/ ". 124b" st) - (modify-syntax-entry ?\n "> b" st) - st) - "Syntax table for Sail2 mode") - -(defun sail2-mode () - "Major mode for editing Sail Language files" - (interactive) - (kill-all-local-variables) - (set-syntax-table sail2-mode-syntax-table) - (setq font-lock-defaults '(sail2-font-lock-keywords)) - (setq comment-start-skip "\\(//+\\|/\\*+\\)\\s *") - (setq comment-start "/*") - (setq comment-end "*/") - (setq major-mode 'sail2-mode) - (setq mode-name "Sail2") - (run-hooks 'sail2-mode-hook)) - -(provide 'sail2-mode) - |
