Emacs mode for Hack assembler

classic Classic list List threaded Threaded
2 messages Options
exc
Reply | Threaded
Open this post in threaded view
|

Emacs mode for Hack assembler

exc
I could not find an Emacs mode for editing Hack ASM so I whipped up the following. Maybe someone else will find it useful.
;;; hack-asm-mode.el --- mode for editing hack assembler code  -*- lexical-binding: t; -*-

;; Copyright (C) 2022 Excalamus

;; This file is not part of GNU Emacs.

;; This is free software; you can redistribute it and/or modify it under
;; the terms of the GNU General Public License as published by the Free
;; Software Foundation; either version 3, or (at your option) any later
;; version.
;;
;; This is distributed in the hope that it will be useful, but WITHOUT
;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
;; FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
;; for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING.  If not, write to the
;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
;; MA 02110-1301 USA.

;;; Commentary:

;; `hack-asm-mode' handles indentation and rudimentary font highlighting for
;; Hack assembly programs.  Labels are indented to column 0.  All
;; other code indents further to the right.  A-instructions, jumps,
;; and comments each have a different face.

;; To manually enable `hack-asm-mode':

;;   1. Load file:          (load "/path/to/hack-asm-mode.el")
;;   2. Enable mode:        M-x hack-asm-mode

;; To automatically enable `hack-asm-mode':

;; Emacs uses `asm-mode' for files ending in ".asm".  To preserve this
;; while still enabling `hack-asm-mode', save your Hack assembly programs as
;; ".hack.asm" files.  Then have Emacs look for this specific file
;; extension when loading modes:

;;     (add-to-list 'auto-mode-alist '("\\.hack.asm\\'" . hack-asm-mode))

;; FIXME
;; - Font lock for strings may override the comment font lock

;; TODO
;; - Define face for dest keywords
;; - Define faces for (a == 0)-type comp keywords
;; - Define faces for (a == 1)-type comp keywords

;;; Code:

(defconst hack-asm-font-lock-keywords
  (append
   '(;; jumps
     ("JMP\\|JGT\\|JEQ\\|JGE\\|JLT\\|JNE\\|JLE" . font-lock-warning-face)

     ;; labels
     ("(\\(\\sw\\|\\s_\\)+)" . font-lock-function-name-face)

     ;; comments
     ("[ \t]*//.*$" . font-lock-comment-face)

     ;; A-instruction
     ("@\\sw+" . font-lock-reference-face)))

  "Additional expressions to highlight in Hack Assembler mode.")

(defun hack-asm-calculate-indentation ()
  "Calculate indentation for line"
  (or
   ;; Flush labels to the left margin.
   (and (looking-at "(\\(\\sw\\|\\s_\\)+)") 0)
   ;; Same thing for comments.
   (and (looking-at "\\s<\\s<\\s<") 0)
   ;; Inline comments go to the comment-column.
   (and (looking-at "\\s<\\(\\S<\\|\\'\\)") comment-column)
   ;; The rest goes at the first tab stop.
   (indent-next-tab-stop 0)))

(defun hack-asm-indent-line ()
  "Auto-indent the current line."
  (interactive)
  (let* ((savep (point))
         (indent (condition-case nil
                     (save-excursion
                       (forward-line 0)
                       (skip-chars-forward " \t")
                       (if (>= (point) savep) (setq savep nil))
                       (max (hack-asm-calculate-indentation) 0))
                   (error 0))))
    (if savep
        (save-excursion (indent-line-to indent))
      (indent-line-to indent))))

;;;###autoload
(define-derived-mode hack-asm-mode prog-mode "Hack Assembler"
  "Major mode for editing Hack assembler code."
  (setq-local font-lock-defaults '(hack-asm-font-lock-keywords))
  (setq-local indent-line-function #'hack-asm-indent-line)
  (setq-local tab-always-indent t)

  (setq-local comment-start "//")
  (setq-local comment-start-skip "\\(?:\\s<+\\|/[/*]+\\)[ \t]*")
  (setq-local comment-end ""))

(provide 'hack-asm-mode)

;;; hack-asm-mode.el ends here
Using the base16-eighties theme, it looks like:

Reply | Threaded
Open this post in threaded view
|

Re: Emacs mode for Hack assembler

ivant
Good job! It's good to see more Emacs users :)

I managed to find a few more.

First, there are a couple of projects in MELPA: https://melpa.org/#/?q=nand2tetris

Before renaming it to "From NAND to Tetris" the course was called "TECS", short for "The Elements of Computing Systems". There is a rather old emacs package, which supports HACK assembly, VM and Jack languages: https://github.com/thousandwich/tecs-emacs

There's another project here https://github.com/Deng-Li3/emacs-nand2tetris, which supports HDL, test files, VM and Jack.

And here is one just for HDL: https://github.com/CestDiego/nand2tetris.el

I'm sure there are more out there. It would be nice to have some of these in MELPA too to make it easy to install.