Function: verilog-simplify-range-expression

verilog-simplify-range-expression is a byte-compiled function defined in verilog-mode.el.gz.

Signature

(verilog-simplify-range-expression EXPR)

Documentation

Return a simplified range expression with constants eliminated from EXPR.

Source Code

;; Defined in /usr/src/emacs/lisp/progmodes/verilog-mode.el.gz
;;(verilog-make-width-expression "`A:`B")

(defun verilog-simplify-range-expression (expr)
  "Return a simplified range expression with constants eliminated from EXPR."
  ;; Note this is always called with brackets; ie [z] or [z:z]
  (if (or (not verilog-auto-simplify-expressions)
          (not (string-match "[---+*/<>()]" expr)))
      expr  ; disabled or short-circuited
    (let ((out expr)
	  (last-pass ""))
      (while (not (equal last-pass out))
        (while (not (equal last-pass out))
          (setq last-pass out)
          ;; Prefix regexp needs beginning of match, or some symbol of
          ;; lesser or equal precedence.  We assume the [:]'s exist in expr.
          ;; Ditto the end.
          (while (string-match
                  (concat "\\([[({:*/<>+-]\\)"  ; - must be last
                          "(\\<\\([0-9A-Za-z_]+\\))"
                          "\\([])}:*/<>.+-]\\)")
                  out)
            (setq out (replace-match "\\1\\2\\3" nil nil out)))
          (while (string-match
                  (concat "\\([[({:*/<>+-]\\)"  ; - must be last
                          "\\$clog2\\s *(\\<\\([0-9]+\\))"
                          "\\([])}:*/<>+-]\\)")
                  out)
            (setq out (replace-match
                       (concat
                        (match-string 1 out)
                        (int-to-string (verilog-clog2 (string-to-number (match-string 2 out))))
                        (match-string 3 out))
                       nil nil out)))
          ;; For precedence do *,/ before +,-,>>,<<
          (while (and
                  (string-match
                   (concat "\\([[({:*/<>+-]\\)"
                           "\\([0-9]+\\)\\s *\\([*/]\\)\\s *\\([0-9]+\\)"
                           "\\([])}:*/<>+-]\\)")
                   out)
                  (not (and (equal (match-string 3 out) "/")
                            (not (equal 0 (% (string-to-number (match-string 2 out))
                                             (string-to-number (match-string 4 out))))))))
            (setq out (replace-match
                       (concat (match-string 1 out)
                               (if (equal (match-string 3 out) "/")
                                   (int-to-string (/ (string-to-number (match-string 2 out))
                                                     (string-to-number (match-string 4 out)))))
                               (if (equal (match-string 3 out) "*")
                                   (int-to-string (* (string-to-number (match-string 2 out))
                                                     (string-to-number (match-string 4 out)))))
                               (match-string 5 out))
                       nil nil out)))
          ;; Next precedence is +,-
          (while (string-match
                  (concat "\\([[({:<>+-]\\)"  ; No *,/ here as higher prec
                          "\\([0-9]+\\)\\s *\\([---+]\\)\\s *\\([0-9]+\\)"
                          "\\([])}:<>+-]\\)")
                  out)
            (let ((pre (match-string 1 out))
                  (lhs (string-to-number (match-string 2 out)))
                  (rhs (string-to-number (match-string 4 out)))
                  (post (match-string 5 out))
                  val)
              (when (equal pre "-")
                (setq lhs (- lhs)))
              (setq val (if (equal (match-string 3 out) "-")
                            (- lhs rhs)
                          (+ lhs rhs))
                    out (replace-match
                         (concat (if (and (equal pre "-")
                                          (< val 0))
                                     ""  ; Not "--20" but just "-20"
                                   pre)
                                 (int-to-string val)
                                 post)
                         nil nil out)) ))
          ;; Next precedence is >>,<<
          (while (string-match
                  (concat "\\([[({:]\\)"  ;; No << as not transitive
                          "\\([0-9]+\\)\\s *\\([<]\\{2,3\\}\\|[>]\\{2,3\\}\\)\\s *\\([0-9]+\\)"
                          "\\([])}:<>]\\)")
                  out)
            (setq out (replace-match
                       (concat (match-string 1 out)
                               (if (equal (match-string 3 out) ">>")
                                   (int-to-string (ash (string-to-number (match-string 2 out))
                                                       (* -1 (string-to-number (match-string 4 out))))))
                               (if (equal (match-string 3 out) ">>>")
                                   (int-to-string (ash (string-to-number (match-string 2 out))
                                                       (* -1 (string-to-number (match-string 4 out))))))
                               (if (equal (match-string 3 out) "<<")
                                   (int-to-string (ash (string-to-number (match-string 2 out))
                                                       (string-to-number (match-string 4 out)))))
                               (if (equal (match-string 3 out) "<<<")
                                   (int-to-string (ash (string-to-number (match-string 2 out))
                                                       (string-to-number (match-string 4 out)))))
                               (match-string 5 out))
                       nil nil out)))))
      out)))