 
 (defconst futhark-keywords
   '("if" "then" "else" "let" "loop" "in" "with" "type"
-    "fun" "entry" "fn" "for" "while" "do" "do" "op" "not"
-    "empty" "unsafe" "default" "include")
+    "fun" "entry" "fn" "for" "while" "do" "op" "not"
+    "empty" "unsafe" "default" "include" "struct")
   "All Futhark keywords.")
 
 (defconst futhark-builtin-functions


;;; Code:

;;;; Basics.

(require 'cl) ; incf, some

;;;###autoload

  "All Futhark booleans.")

(defconst futhark-var
  (concat "\\(?:" "[_'[:alnum:]]+" "\\)")
  "A regex describing a Futhark variable.")

(defconst futhark-non-tuple-type
  (concat "\\(?:"
          "\\*" "?"
           "\\(?:"
             "\\["
               "\\(?:"
                 ""
               "\\|"
                 futhark-var
               "\\)"
             "\\]"
           "\\)" "*"
           futhark-var
           "\\)"
           )
  "A regex describing a Futhark type which is not a tuple")

(defconst futhark-tuple-type
  (concat "\\(?:"
          "("
          "[^)]" "+"
          ")"
          "\\)"
          )
  "A regex describing a Futhark type which is a tuple")

(defconst futhark-type
  (concat "\\(?:"
          futhark-non-tuple-type
          "\\|"
          futhark-tuple-type
          "\\)"
          )
  "A regex describing a Futhark type")


;;; Highlighting

(let (
      (ws "[[:space:]\n]*")
      (ws1 "[[:space:]\n]+")
      )
  (defvar futhark-font-lock
    `(

      ;; Function declarations.
      (,(concat "\\(?:" "fun" "\\|" "entry" "\\)"
                ws1 "\\(" futhark-var "\\)")
       . '(1 font-lock-function-name-face))

      ;; Variable and tuple declarations.
      ;;; Lets.
      ;;;; Primitive values.
      (,(concat "let" ws1
                "\\(" futhark-var "\\)")
       . '(1 font-lock-variable-name-face))
      ;;;; Tuples.  TODO: It would be nice to highlight only the variable names
      ;;;; inside the parantheses, and not also the commas.
      (,(concat "let" ws1 "("
                "\\(" "[^)]+" "\\)")
       . '(1 font-lock-variable-name-face))
      ;;; Function parameters.
      (,(concat "\\(" futhark-var "\\)" ws ":")
       . '(1 font-lock-variable-name-face))

      ;; Keywords.
      (,(regexp-opt futhark-keywords 'words)
       . font-lock-keyword-face)

      ;; Types.
      ;;; Type aliases.  TODO: It would be nice to highlight only the variable
      ;;; names, and not also the commas and parantheses.
      (,(concat "type" ws1
                "\\("
                "\\(?:" futhark-type ws ",?" ws "\\)" "+"
                "\\)")
       . '(1 font-lock-type-face))
      (,(concat "type" "[[:space:]]+"
                "\\(?:" futhark-type ws ",?" ws "\\)" "+"
                ws "=" ws
                "\\(" ".+" "\\)"
                )
       . '(1 font-lock-type-face))
      ;;; Function parameters types and return type.  This does not work with
      ;;; nested tuple types.
      (,(concat ":" ws "\\(" futhark-type "\\)")
       . '(1 font-lock-type-face))
      ;;; Builtin types.
      (,(regexp-opt futhark-builtin-types 'words)
       . font-lock-type-face)

      ;; Builtins.
      ;;; Functions.
      (,(regexp-opt futhark-builtin-functions 'words)
       . font-lock-builtin-face)
      ;;; Operators.
      (,(regexp-opt futhark-builtin-operators)
       . font-lock-builtin-face)

      ;; Constants.
      ;;; Booleans.
      (,(regexp-opt futhark-booleans 'words)
       . font-lock-constant-face)

      )
    "Highlighting expressions for Futhark.")
  )

(defvar futhark-mode-syntax-table
  (let ((st (make-syntax-table)))
