emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] master f454133: * externals-list: Convert lmc to :external


From: Stefan Monnier
Subject: [elpa] master f454133: * externals-list: Convert lmc to :external
Date: Sat, 28 Nov 2020 23:22:21 -0500 (EST)

branch: master
commit f454133aa5407104467062077384c33cfbb8999d
Author: Stefan Monnier <monnier@iro.umontreal.ca>
Commit: Stefan Monnier <monnier@iro.umontreal.ca>

    * externals-list: Convert lmc to :external
---
 externals-list      |   3 +-
 packages/lmc/lmc.el | 805 ----------------------------------------------------
 2 files changed, 2 insertions(+), 806 deletions(-)

diff --git a/externals-list b/externals-list
index 38b047e..cc3d3e0 100644
--- a/externals-list
+++ b/externals-list
@@ -109,10 +109,11 @@
  ("jsonrpc"            :core "lisp/jsonrpc.el")
  ("leaf"               :external "https://github.com/conao3/leaf.el";)
  ("let-alist"          :core "lisp/emacs-lisp/let-alist.el")
+ ("lmc" :external nil)
  ("map"                 :core "lisp/emacs-lisp/map.el")
  ("markchars"          :external nil)
  ("math-symbol-lists"  :external 
"https://github.com/vspinu/math-symbol-lists.git";)
- ("metar" :external nil)
+ ("metar"              :external nil)
  ("mmm-mode"            :external "https://github.com/purcell/mmm-mode.git";)
  ("modus-operandi-theme":external 
"https://gitlab.com/protesilaos/modus-themes";)
  ("modus-vivendi-theme"        :external 
"https://gitlab.com/protesilaos/modus-themes";)
diff --git a/packages/lmc/lmc.el b/packages/lmc/lmc.el
deleted file mode 100644
index 42029f6..0000000
--- a/packages/lmc/lmc.el
+++ /dev/null
@@ -1,805 +0,0 @@
-;;; lmc.el --- Little Man Computer in Elisp  -*- lexical-binding:t -*-
-
-;; Copyright (C) 2011-2017  Free Software Foundation, Inc.
-
-;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
-;; Version: 1.4
-;; Package-Requires: ((emacs "24") (cl-lib "0.5"))
-
-;; This program 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 of the License, or
-;; (at your option) any later version.
-
-;; This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; A simulator for the Little Man Computer.
-;; http://en.wikipedia.org/wiki/Little_man_computer
-
-;; The simulator uses a plain editable buffer, so you can edit the machine
-;; words just like any other text, and every word can be given a name (label)
-;; which can also be edited in the normal way.  Additionally to the labels it
-;; shows the disassembled meaning of instruction words.  Of course, it can't
-;; always know which words are meant to be code rather than data, so it relies
-;; on information from the assembler to do that, and otherwise just marks every
-;; word it executes as being "code".
-
-;; The assembly uses a slightly different (Lispish) syntax where comments start
-;; with ";", and each instruction needs to be wrapped in parentheses.
-;; Other than that it's the same assembly as documented elsewhere
-;; (accepts a few mnemonic variants, such as IN/INP, STA/STO, BR/BRA).
-;; Another difference is that the DAT mnemonic accepts any number of words
-;; rather than just one.
-;;
-;; So the assembly (stored in files with extension ".elmc") looks like:
-;;
-;;   label1
-;;          (BR label2) ;Useless extra jump.
-;;   label2
-;;          (LDA data1) ;Cleverest part of the algorithm.
-;;          (ADD data2)
-;;          (STO data1)
-;;          (BR label1)
-;;          
-;;   data1  (DAT 0)
-;;   data2  (DAT 050 060 070)
-;;
-;; And actually, since the assembler re-uses the Emacs Lisp reader to parse the
-;; code, you can use binary, octal, and hexadecimal constants as well, using
-;; the notations #b101010, #o277, and #x5F respectively.
-;; 
-;; The lmc-asm-mode supports the usual editing features such as label
-;; completion, mnemonic completion, jumping to a label, automatic indentation,
-;; and code folding.
-
-;;; Code:
-
-(eval-when-compile (require 'cl-lib))
-(require 'hexl)
-
-(defgroup lmc ()
-  "Customization group for the Little Man Computer simulator."
-  :group 'languages)
-
-;;; The LMC-Simulator
-
-(defvar lmc--pc 0 "Program counter for LMC.")
-(make-variable-buffer-local 'lmc--pc)
-
-(defvar lmc-acc 0 "Accumulator for LMC.")
-(make-variable-buffer-local 'lmc--acc)
-
-(defvar lmc-turbo nil
-  "When non-nil, evaluate the code without extra delays.
-When nil, evaluation flashes the cursor at to help you see what's going on,
-which slows it down significantly.
-Also, when nil, evaluation is interrupted when the user hits a key.")
-
-;; Emacs-22 backward compatibility.
-(defmacro lmc--with-silent-modifications (&rest body)
-  (declare (debug t) (indent 0))
-  (if (fboundp 'with-silent-modifications)
-      `(with-silent-modifications ,@body)
-    (let ((modified (make-symbol "modified")))
-      `(let* ((,modified (buffer-modified-p))
-             (buffer-undo-list t)
-             (inhibit-read-only t)
-             (inhibit-modification-hooks t)
-             deactivate-mark
-             ;; Avoid setting and removing file locks and checking
-             ;; buffer's uptodate-ness w.r.t the underlying file.
-             buffer-file-name
-             buffer-file-truename)
-        (unwind-protect
-            (progn
-              ,@body)
-          (unless ,modified
-            (restore-buffer-modified-p nil)))))))
-
-;; (defun lmc-check (cmds)
-;;   (dolist (cmd cmds)
-;;     (pcase cmd
-;;       ((pred symbolp))                                ;A label.
-;;       (`(,(or `IN `OUT `HLT `COB)))                   ;Arity-0 opcode.
-;;       (`(,(or `LDA `STO `ADD `SUB `BR `BRZ `BRP `DAT) ;Arity-1 opcode.
-;;          ,(or (pred lmc--numberp) (pred symbolp))))
-;;       (_ (error "Unknown instruction %S" cmd)))))
-
-(defun lmc--numberp (n max)
-  (when (numberp n)
-    (or (and (or (natnump n) (error "%S is not a positive integer" n))
-             (or (< n max) (error "%S is too large" n))))))
-
-(defun lmc--resolve (arg labels max)
-  (if (lmc--numberp arg max) arg
-    (or (cdr (assq arg labels))
-        (error (if (symbolp arg)
-                   "Unknown label %S"
-                 "Arg %S is neither a label nor a number")
-               arg))))
-
-(defconst lmc-mnemonic-1-table '((LDA . 5)
-                                 (STO . 3) (STA . 3)
-                                 (ADD . 1)
-                                 (SUB . 2)
-                                 (BR . 6) (BRA . 6)
-                                 (BRZ . 7)
-                                 (BRP . 8))
-  "Mnemonic table for arity-1 instructions.")
-
-(defconst lmc-mnemonic-0-table '((HLT . 000) (COB . 000)
-                                 (IN . 901) (INP . 901)
-                                 (OUT . 902))
-  "Mnemonic table for arity-0 instructions.")
-
-(defun lmc--assemble (cmds)
-  ;; FIXME: Move to error position upon error.
-  (let ((pos 0)
-        (labels ()))
-    ;; First pass, resolve labels to their positions.
-    (dolist (cmd cmds)
-      (setq cmd (cdr cmd))              ;Ignore position info at this stage.
-      (cond
-       ((or (consp cmd)
-            (assq cmd lmc-mnemonic-0-table))
-        (setq pos (+ pos (if (eq (car cmd) 'DAT)
-                             (1- (length cmd)) 1))))
-       ((numberp cmd)
-        (cond
-         ((not (and (natnump cmd) (< cmd 100)))
-          (error "%S is not a valid address" cmd))
-         ((< cmd pos)
-          (error "Address %S already used" cmd))
-         ((rassq pos labels)
-          (error "Label %S needs to come after address %S"
-                 (car (rassq pos labels)) cmd))
-         (t (setq pos cmd))))
-       ((and cmd (symbolp cmd))
-        ;; (cl-assert (symbolp cmd))
-        (if (assq cmd labels)
-            (error "Duplicate label %S" cmd)
-          (push (cons cmd pos) labels)))))
-    ;; Second pass, do the actual assembly.
-    (let* ((words ())
-           (ll nil)
-           (newword
-            (lambda (w &optional code)
-              (push (list w ll code) words) (setq ll nil))))
-      (dolist (cmd cmds)
-        (goto-char (pop cmd))          ;Move to start of CMD, in case of error.
-        (cond
-         ((assq cmd lmc-mnemonic-0-table)
-          (funcall newword (cdr (assq cmd lmc-mnemonic-0-table)) 'code))
-         ((and (null (cdr-safe cmd))
-               (assq (car-safe cmd) lmc-mnemonic-0-table))
-          (funcall newword (cdr (assq (car cmd) lmc-mnemonic-0-table)) 'code))
-         ((eq (car-safe cmd) 'DAT)
-          (dolist (arg (cdr cmd))
-            (funcall newword (lmc--resolve arg labels 1000))))
-         ((assq (car-safe cmd) lmc-mnemonic-1-table)
-          (funcall newword
-                   (+ (* 100 (cdr (assq (car cmd) lmc-mnemonic-1-table)))
-                      (lmc--resolve (nth 1 cmd) labels 100))
-                   'code))
-         ((numberp cmd)
-          (dotimes (_ (- cmd (length words)))
-            (funcall newword 0)))
-         ((and cmd (symbolp cmd))
-          (cl-assert (eq (cdr (assq cmd labels)) (length words)))
-          (setq ll cmd))
-         (t (error "Invalid instruction %S" cmd))))
-      (nreverse words))))
-
-;; (defvar lmc-label-width 8)
-
-(defun lmc--load-word (word addr)
-  (cl-assert (bolp))
-  (insert (propertize (format " %02d:\t" addr)
-                      'read-only t
-                      'front-sticky t
-                      'rear-nonsticky t))
-  (let ((word (car word))
-        (label (nth 1 word))
-        (code (nth 2 word)))
-    (let () ;; ((basepos (point)) (base (current-column)))
-      (if (and label (symbolp label))
-          (insert (symbol-name label)))
-      ;; (when (>= (current-column) (+ base tab-width))
-      ;;   (while (>= (current-column) (+ base tab-width -1))
-      ;;     (delete-char -1))
-      ;;   (insert "…")
-      ;;   (put-text-property basepos (point)
-      ;;                      'help-echo (symbol-name label)))
-      ;; (insert (propertize
-      ;;      (make-string (1+ (- lmc-label-width (current-column))) ?\s)
-      ;;      'display '(space :align-to (1+ lmc-label-width))))
-      (insert (eval-when-compile (propertize "\t"
-                                             'read-only t
-                                             'rear-nonsticky t))))
-    (insert (format "  %03d" word))
-    (insert (if code
-                (eval-when-compile (propertize "\n"
-                                               'lmc-code t
-                                               'read-only t
-                                               'rear-nonsticky t))
-              (eval-when-compile (propertize "\n"
-                                             'read-only t
-                                             'rear-nonsticky t))))))
-
-(defun lmc-disassemble-word (word)
-  (let ((code (car (rassq (/ word 100) lmc-mnemonic-1-table))))
-    (cond
-     (code (list code (mod word 100)))
-     ((rassq word lmc-mnemonic-0-table)
-      (list (car (rassq word lmc-mnemonic-0-table)))))))
-
-(defun lmc-addr->point (addr)
-  (goto-char (point-min))
-  (forward-line addr))
-
-(defun lmc-point->addr ()
-  (- (count-lines (point-min) (point)) (if (bolp) 0 1)))
-
-(defun lmc-get-word (&optional addr fix)
-  (save-excursion
-    (if (null addr)
-        (forward-line 0)
-      (lmc-addr->point addr))
-    (cond
-     ((re-search-forward "\t.*\t  \\([0-9][0-9][0-9]\\)$"
-                         (line-end-position) t)
-      (string-to-number (match-string 1)))
-     ((re-search-forward "\t.*\t\\(.*\\)$" (line-end-position) t)
-      (let ((n (string-to-number (match-string 1))))
-        (unless (integerp n) (setq n (truncate n)))
-        (setq n (mod n 1000))
-        (when fix
-          (replace-match (format "  %03d" n) t t nil 1))
-        n))
-     (t 0))))
-
-(defconst lmc-label-re "^\\([^\t\n]*\\)\t\\(.*\\)\t *[0-9]")
-
-(defvar lmc-label-table nil)
-
-(defun lmc-record-label (addr label)
-  (let ((old (aref lmc-label-table addr)))
-    (unless (and old (equal (car old) label))
-      ;; (message "recordlabel %S = %S" addr label)
-      (aset lmc-label-table addr (list label))
-      (when (cdr old)
-        (run-with-timer
-         0 nil
-         (lambda (buf refaddrs)
-           (with-current-buffer buf
-             (save-excursion
-               ;; (message "refreshlabel in %S" refaddrs)
-               (dolist (refaddr refaddrs)
-                 (lmc-addr->point (1+ refaddr))
-                 (unless (bobp)
-                   (let ((inhibit-read-only t))
-                     (put-text-property (1- (point)) (point)
-                                        'fontified nil)))))))
-         (current-buffer) (cdr old))))))
-
-(defun lmc-get-label (addr)
-  (save-excursion
-    ;; (if (null addr)
-    ;;     (forward-line 0)
-    (lmc-addr->point addr) ;; )
-    (let ((label (when (re-search-forward lmc-label-re nil t)
-                   (if (> (match-end 2) (match-beginning 2))
-                       (match-string 2)))))
-      (lmc-record-label addr label)
-      label)))
-
-
-(defun lmc-font-lock-opcode ()
-  (save-match-data
-    (when (get-text-property (line-end-position) 'lmc-code)
-      (let* ((word (lmc-get-word))
-             (code (lmc-disassemble-word word)))
-        ;; Resolve labels.
-        (when (integerp (nth 1 code))
-          (let* ((addr (nth 1 code))
-                 (label (lmc-get-label addr)))
-            (cl-pushnew (lmc-point->addr)
-                        (cdr (aref lmc-label-table addr)))
-            (when label
-              (setf (nth 1 code) label))))
-        (put-text-property
-         (line-end-position) (1+ (line-end-position))
-         'display
-         (format (eval-when-compile
-                   (concat (propertize "\t" 'cursor t)
-                           (propertize "%s" 'face font-lock-comment-face)
-                           "\n"))
-                 (or code '(Invalid opcode)))))
-      nil)))
-
-(defun lmc-font-lock-label ()
-  (lmc-record-label (lmc-point->addr)
-                    (if (> (match-end 2) (match-beginning 2))
-                       (match-string 2)))
-  (save-excursion
-    ;; ;; Replace any TAB found in label.
-    ;; (goto-char (match-beginning 2))
-    ;; (while (progn (skip-chars-forward "^\t" (match-end 2))
-    ;;               (< (point) (match-end 2)))
-    ;;   (insert " ") (delete-char 1))
-    ;; Truncate label's display if needed.
-    (move-to-column (1- (* 2 tab-width)))
-    (when (> (match-end 2) (point))
-      (forward-char -1)
-      (put-text-property (match-beginning 2) (match-end 2)
-                         'help-echo (match-string 2))
-      (put-text-property (point) (match-end 2) 'display "…")))
-  font-lock-constant-face)
-
-(defconst lmc-font-lock-keywords
-  `((,lmc-label-re
-     (1 'hexl-address-region)
-     (2 (lmc-font-lock-label)))
-    (".$" (0 (lmc-font-lock-opcode)))))
-
-(defun lmc-after-change (beg end _len)
-  (unless inhibit-read-only
-    (save-excursion
-      ;; Replace any TAB or NL inserted, which could interfere with parsing.
-      (goto-char beg)
-      (while (progn (skip-chars-forward "^\t\n" end)
-                    (< (point) end))
-        (insert " ") (delete-char 1)))))
-
-(defvar lmc-pc 0 "LMC program counter.")
-(make-variable-buffer-local 'lmc-pc)
-(defvar lmc-acc nil "LMC accumulator.")
-(make-variable-buffer-local 'lmc-acc)
-(defvar lmc-output nil "Past LMC output.")
-(make-variable-buffer-local 'lmc-output)
-
-(defvar lmc--stopped nil "State where we stopped.")
-(make-variable-buffer-local 'lmc--stopped)
-
-(defun lmc-update-pc ()
-  (setq lmc-pc (mod lmc-pc 100))
-  (lmc-addr->point lmc-pc)
-  (move-marker overlay-arrow-position (point))
-  (re-search-forward "\t.*\t *" nil t)
-  (unless (get-text-property (line-end-position) 'lmc-code)
-    (let ((inhibit-read-only t))
-      (put-text-property (line-end-position)
-                         (min (1+ (line-end-position)) (point-max))
-                         'lmc-code t))))
-
-(defun lmc--state ()
-  (list (buffer-chars-modified-tick) lmc-acc lmc-pc))
-(defun lmc-stopped-p ()
-  (equal (lmc--state) lmc--stopped))
-
-;; FIXME: Add tool-bar to LMC-Sim.
-
-(defvar lmc-mode-map
-  (let ((map (make-sparse-keymap)))
-    (define-key map "\C-c\C-s" 'lmc-step)
-    (define-key map "\C-c\C-r" 'lmc-run)
-    (define-key map "\C-c\C-l" 'lmc-load-file)
-    (define-key map "\C-c\C-a" 'lmc-set-acc)
-    (define-key map "\C-c\C-p" 'lmc-set-pc)
-    map))
-
-(easy-menu-define lmc-menu lmc-mode-map "Menu for LMC-Sim."
-  '("LMC-Sim"
-    ["Step" lmc-step (not (lmc-stopped-p))]
-    ["Run" lmc-run (not (lmc-stopped-p))]
-    ["Load file" lmc-load-file]
-    "--"
-    ["Set Program Counter" lmc-set-pc]
-    ["Set Accumulator" lmc-set-acc]))
-
-(defvar lmc-tool-bar-map
-  (let ((map (make-sparse-keymap)))
-    (tool-bar-local-item "gud/next" 'lmc-step 'step map
-                         :label "Step" ;; :vert-only t
-                         :enable '(not (lmc-stopped-p))
-                         )
-    (tool-bar-local-item "gud/run" 'lmc-run 'run map
-                         :label "Run" ;; :vert-only t
-                         :enable '(not (lmc-stopped-p))
-                         )
-    map))
-
-(defun lmc-tool-bar-to-string (&optional map)
-  (let ((res ""))
-    (map-keymap
-     (lambda (_k v)
-       (when (eq (car v) 'menu-item)
-         (let* ((label (nth 1 v))
-                (cmd (nth 2 v))
-                (plist (nthcdr (if (consp (nth 3 v)) 4 3) v))
-                (help-echo (plist-get plist :help))
-                (image     (plist-get plist :image))
-                (enable-exp (if (plist-member plist :enable)
-                                (plist-get plist :enable)
-                              t))
-                (enable (eval enable-exp))
-                (map (let ((map (make-sparse-keymap)))
-                       (define-key map [header-line mouse-1] cmd)
-                       (define-key map [header-line mouse-2] cmd)
-                       map))
-                (button
-                 (propertize " " 'help-echo (or help-echo label)
-                             'keymap map
-                             'face 'header-line
-                             'mouse-face (if enable 'mode-line-highlight)
-                             'rear-nonsticky '(display keymap help-echo)
-                             'display (if (and (eq 'image (car image))
-                                               (not enable))
-                                          `(image :conversion disabled
-                                                  ,@(cdr image))
-                                        image))))
-           (setq res (concat res (propertize " " 'display '(space :width 0.5)
-                                             'face 'header-line
-                                             )
-                             button)))))
-     (or (let ((tool-bar-map map)) (tool-bar-make-keymap))
-         (key-binding [tool-bar])))
-    res))
-
-(define-derived-mode lmc-mode fundamental-mode "LMC-Sim"
-  "The simulator of the Little Man Computer."
-  (set (make-local-variable 'truncate-lines) t)
-  (set (make-local-variable 'truncate-partial-width-windows) t)
-  (set (make-local-variable 'tab-width) 10)
-  (set (make-local-variable 'font-lock-defaults)
-       '(lmc-font-lock-keywords t))
-  (set (make-local-variable 'font-lock-extra-managed-props)
-       '(display help-echo))
-  ;; (set (make-local-variable 'tool-bar-map) lmc-tool-bar-map)
-  (add-hook 'after-change-functions #'lmc-after-change nil t)
-  (set (make-local-variable 'lmc-label-table) (make-vector 100 nil))
-  (set (make-local-variable 'overlay-arrow-position) (point-min-marker))
-  (lmc-update-pc)
-  ;; (overwrite-mode 1)
-  (set (make-local-variable 'header-line-format)
-       `(""
-         (:eval (lmc-tool-bar-to-string lmc-tool-bar-map))
-         "  " ,(propertize "LMC-Sim" 'face '(bold italic)) "  "
-         ,(propertize "PC=" 'face 'font-lock-function-name-face)
-         (:eval (format ,(propertize "%02d"
-                                     'mouse-face 'mode-line-highlight
-                                     'help-echo
-                                     "mouse-2: set the Program Counter"
-                                     'follow-link t
-                                     ;; I'm having problems with mouse-2 to
-                                     ;; mouse-1 remapping in the mode-line and
-                                     ;; header-line, so I over-do it a bit.
-                                     'keymap
-                                     '(keymap
-                                       (header-line keymap
-                                                    (down-mouse-1 . ignore)
-                                                    (mouse-2 . lmc-set-pc)
-                                                    (mouse-1 . lmc-set-pc))))
-                        lmc-pc))
-         "  " ,(propertize "ACC=" 'face 'font-lock-function-name-face)
-         (:eval (format ,(propertize "%03d"
-                                     'mouse-face 'mode-line-highlight
-                                     'help-echo "mouse-2: set the Accumulator"
-                                     'follow-link t
-                                     'keymap
-                                     ;; I'm having problems with mouse-2 to
-                                     ;; mouse-1 remapping in the mode-line and
-                                     ;; header-line, so I over-do it a bit.
-                                     '(keymap
-                                       (header-line keymap
-                                                    (down-mouse-1 . ignore)
-                                                    (mouse-2 . lmc-set-acc)
-                                                    (mouse-1 . lmc-set-acc))))
-                        lmc-acc))
-         "      " ,(propertize "Recent output="
-                               'face 'font-lock-function-name-face)
-         (:eval (if lmc-output (format "%s" lmc-output) "()"))))
-  )
-
-(defun lmc-set-pc (pc)
-  "Set the Program Counter."
-  (interactive (list (read-number "New PC: " lmc-pc)))
-  (setq lmc-pc pc)
-  (lmc-update-pc))
-
-(defun lmc-set-acc (acc)
-  "Set the Accumulator."
-  (interactive (list (read-number "New Accumulator: " lmc-acc)))
-  (setq lmc-acc (mod acc 1000)))
-
-(defun lmc-load (words)
-  (pop-to-buffer "*LMC-Sim*")
-  (lmc-mode)
-  (let ((inhibit-read-only t)
-        (addr 0))
-    (setq lmc-pc 0)
-    (setq lmc-acc 0)
-    (setq lmc-output nil)
-    (erase-buffer)
-    (dolist (word words)
-      (lmc--load-word word addr)
-      (setq addr (1+ addr)))
-    (while (< addr 100)
-      (lmc--load-word '(0) addr)
-      (setq addr (1+ addr))))
-  (lmc-update-pc))
-
-(defcustom lmc-store-flash t
-  "If non-nil, memory words blink when modified."
-  :type 'boolean)
-
-(defun lmc--sit-for (secs)
-  (unless lmc-turbo (sit-for secs)))
-
-(defun lmc-store-word (addr word)
-  (save-excursion
-    (lmc-addr->point addr)
-    (if (not (re-search-forward "\t.*\t\\(.*\\)$" (line-end-position) t))
-        (error "Missing memory cell %S" addr)
-      (let ((mb1 (match-beginning 1)))
-        (when lmc-store-flash
-          (lmc--with-silent-modifications
-           (put-text-property mb1 (point) 'face 'region))
-          (lmc--sit-for 0.2))
-        (let ((me1 (point)))
-          (insert (format "  %03d" word)) (delete-region mb1 me1))
-        (when lmc-store-flash
-          (lmc--sit-for 0.1)
-          (lmc--with-silent-modifications
-           (put-text-property mb1 (point) 'face 'region))
-          (lmc--sit-for 0.1)
-          (lmc--with-silent-modifications
-           (put-text-property mb1 (point) 'face nil))
-          (lmc--sit-for 0.1))))))
-
-(defun lmc-step ()
-  "Execute one LMC instruction."
-  (interactive)
-  (let* ((inst (lmc-get-word lmc-pc 'fix))
-         (code (lmc-disassemble-word inst)))
-    (pcase (car code)
-      (`HLT (if (lmc-stopped-p)
-               (error "Already halted")
-             (setq lmc--stopped (lmc--state))
-             (force-mode-line-update)
-             (message "Done.")))
-      (`IN (setq lmc-acc (mod (read-number "Enter a number: ") 1000))
-          (cl-incf lmc-pc))
-      (`OUT (message "Output: %03d" lmc-acc)
-           (push (format "%03d" lmc-acc) lmc-output)
-           (cl-incf lmc-pc))
-      (`LDA (setq lmc-acc (lmc-get-word (nth 1 code)))
-           (cl-incf lmc-pc))
-      (`STO (lmc-store-word (nth 1 code) lmc-acc)
-           (cl-incf lmc-pc))
-      (`ADD (setq lmc-acc (mod (+ lmc-acc (lmc-get-word (nth 1 code)))
-                              1000))
-           (cl-incf lmc-pc))
-      (`SUB (setq lmc-acc (mod (- lmc-acc (lmc-get-word (nth 1 code)))
-                              1000))
-           (cl-incf lmc-pc))
-      (`BR (setq lmc-pc (nth 1 code)))
-      (`BRZ (setq lmc-pc (if (zerop lmc-acc)
-                            (nth 1 code)
-                          (1+ lmc-pc))))
-      (`BRP (setq lmc-pc (if (< lmc-acc 500)
-                            (nth 1 code)
-                          (1+ lmc-pc))))
-      (`nil (error "Invalid instruction %S" inst))
-      (_ (error "%S not implemented" code))))
-  (lmc-update-pc))
-
-(defun lmc-run ()
-  "Run the code until hitting a HLT.
-The machine will also stop if the user presses a key."
-  (interactive)
-  (while (not (or (unless lmc-turbo (input-pending-p)) (lmc-stopped-p)))
-    (lmc-step)
-    (lmc--sit-for 0.05)))
-
-;;; The LMC assembly language editor.
-
-(defvar lmc-asm-mode-map
-  (let ((map (make-sparse-keymap)))
-    ;; FIXME: Add "load" and "assemble" buttons.
-    (define-key map "\C-c\C-l" 'lmc-asm-load)
-    (define-key map "\C-c\C-a" 'lmc-asm-assemble)
-    map))
-
-(easy-menu-define lmc-asm-menu lmc-asm-mode-map
-  "Menu for the LMC-Asm mode."
-  '("LMC-Asm"
-    ["Assemble" lmc-asm-assemble]
-    ["Load into Simulator" lmc-asm-load]))
-
-
-(defconst lmc-asm-mnemonic-names
-  (mapcar #'symbol-name
-          (append (mapcar #'car lmc-mnemonic-1-table)
-                  (mapcar #'car lmc-mnemonic-0-table)
-                  '(DAT))))
-
-(defconst lmc-asm-mnemonic-names-re (regexp-opt lmc-asm-mnemonic-names))
-
-(defvar lmc-asm-font-lock-keywords
-  `(("^[ \t]*\\(?:\\sw\\|\\s_\\)+"
-     (0 (if (zerop (nth 0 (syntax-ppss))) font-lock-constant-face)))
-    (,(concat "(\\(" lmc-asm-mnemonic-names-re "\\_>\\)")
-     (1 font-lock-keyword-face))))
-
-(defvar lmc-asm-imenu-generic-expression
-  '((nil "^\\(\\(?:\\sw\\|\\s_\\)+\\)" 1)))
-
-(defvar lmc-asm-outline-regexp "^\\(?:\\sw\\|\\s_\\)")
-
-;; We use the ".elmc" extension since the syntax is not identical to
-;; the usual ".lmc" syntax.
-;;;###autoload
-(add-to-list 'auto-mode-alist '("\\.elmc\\'" . lmc-asm-mode))
-
-;;;###autoload
-(define-derived-mode lmc-asm-mode fundamental-mode "LMC-Asm"
-  "Major mode to edit LMC assembly code."
-  :syntax-table emacs-lisp-mode-syntax-table
-  (set (make-local-variable 'font-lock-defaults)
-       '(lmc-asm-font-lock-keywords))
-  (set (make-local-variable 'indent-line-function)
-       #'lmc-asm-indent-line)
-  (set (make-local-variable 'indent-tabs-mode) t)
-  (set (make-local-variable 'imenu-generic-expression)
-       lmc-asm-imenu-generic-expression)
-  (set (make-local-variable 'outline-regexp) lmc-asm-outline-regexp)
-  (add-hook 'completion-at-point-functions #'lmc-asm-completion nil t)
-  (set (make-local-variable 'comment-start) ";")
-  (set (make-local-variable 'comment-start-skip)
-       "\\(\\(^\\|[^\\\\\n]\\)\\(\\\\\\\\\\)*\\);+ *")
-  )
-
-(defun lmc-asm-labels (string)
-  (save-excursion
-    ;; We don't want to count the label being completed as a completion
-    ;; candidate, so let's keep track of the original position of point and
-    ;; skip any label nearby.
-    (let ((point (point)))
-      (goto-char (point-min))
-      (let ((ls ())
-            (re (concat "\\(^\\|(" lmc-asm-mnemonic-names-re "[ \t]+" "\\)"
-                        (regexp-quote string) "\\(?:\\sw\\|\\s_\\)"
-                        (if (> (length string) 0) "*" "+"))))
-        (while (re-search-forward re nil t)
-          (when (or (< point (match-end 1))
-                    (> (match-beginning 1) point))
-            (push (buffer-substring-no-properties
-                   (match-end 1) (match-end 0)) ls)))
-        ls))))
-
-(defun lmc-asm-completion ()
-  (save-excursion
-    (let ((ppss (syntax-ppss)))
-      (cond
-       ((nth 8 ppss) nil)               ;Inside string or comment.
-       ((zerop (nth 0 ppss))
-        (skip-syntax-backward "w_")
-        (when (save-excursion (skip-chars-backward " \t") (bolp))
-          (list (point)
-                (save-excursion (skip-syntax-forward "w_") (point))
-                (completion-table-dynamic #'lmc-asm-labels))))
-       ((= 1 (nth 0 ppss))              ;Inside paren.
-        (skip-syntax-backward "w_")
-        (list (point)
-              (save-excursion (skip-syntax-forward "w_") (point))
-              (if (eq (char-before) ?\()
-                  lmc-asm-mnemonic-names
-                (completion-table-dynamic #'lmc-asm-labels))))))))
-
-(defun lmc-asm-indentation ()
-  (save-excursion
-    (back-to-indentation)
-    (cond
-     ((> (nth 0 (syntax-ppss)) 0) nil)
-     ((looking-at "(") tab-width)
-     ((not (looking-at comment-start-skip))
-      (if (looking-at "[ \t]*$") tab-width 0))
-     ((not (looking-at "\\s<\\s<")) nil)
-     ((save-excursion (forward-comment (- (point))) (bobp)) 0)
-     (t (forward-comment (point-max)) (lmc-asm-indentation)))))
-
-(defun lmc-asm-indent-line (&optional arg)
-  (save-excursion
-    (back-to-indentation)
-    (when (and (zerop (nth 0 (syntax-ppss)))
-               (looking-at (concat lmc-asm-mnemonic-names-re "\\_>")))
-      ;; Apparently the user forgot to parenthesize the instruction.
-      (insert "(")
-      (if (assq (read (current-buffer)) lmc-mnemonic-0-table)
-          (insert ")")
-        (let ((eol (line-end-position)))
-          (ignore-errors
-            (read (current-buffer))
-            (when (<= (point) eol)
-              (insert ")")))))))
-  (let ((indent (lmc-asm-indentation)))
-    (cond
-     ((null indent) (lisp-indent-line arg))
-     (t
-      (let ((left-margin indent)) (indent-to-left-margin))
-      (when (zerop indent)
-        ;; Indent code (if any) after a label.
-        (save-excursion
-          (beginning-of-line)
-          (when (looking-at "\\(?:\\sw\\|\\s_\\)+\\([ \t]*\\)(")
-            (goto-char (match-beginning 1))
-            (if (< (current-column) tab-width)
-                (unless (save-excursion
-                          (goto-char (match-end 1))
-                          (= (current-column) tab-width))
-                  (delete-region (match-beginning 1) (match-end 1))
-                  (indent-to tab-width))
-              (unless (equal (match-string 1) " ")
-                (delete-region (match-beginning 1) (match-end 1))
-                (insert " "))))))))))
-
-(defun lmc-asm-read ()
-  (let ((prog ())
-        (initialpos (point)))
-    (goto-char (point-min))
-    (while (progn (forward-comment (point-max))
-                  (not (eobp)))
-      (let ((start (point)))
-        (condition-case nil
-            (push (cons (point) (read (current-buffer))) prog)
-          (end-of-file (goto-char start) (signal 'end-of-file nil)))))
-    (goto-char initialpos)
-    (nreverse prog)))
-
-(defun lmc-asm-load ()
-  "Load current buffer into the LMC simulator."
-  (interactive)
-  (let ((initialpos (point))
-        (window (if (eq (current-buffer) (window-buffer)) (selected-window))))
-    (save-current-buffer
-      (lmc-load (lmc--assemble (lmc-asm-read))))
-    (goto-char initialpos)
-    (if (and window (eq (current-buffer) (window-buffer window)))
-        (set-window-point window (point)))))
-
-(defun lmc-asm-assemble ()
-  "Assemble current buffer to check syntax."
-  (interactive)
-  (let ((initialpos (point)))
-    (lmc--assemble (lmc-asm-read))
-    (goto-char initialpos)
-    (message "No errors found")))
-
-(defun lmc-load-file (file)
-  "Load FILE into the LMC simulator."
-  (interactive
-   (list (read-file-name "Load LMC file: " nil nil t nil
-                         (lambda (file)
-                           (or (file-directory-p file)
-                               (string-match-p "\\.elmc\\'" file))))))
-  (let ((exists (find-buffer-visiting file))
-        (buf (find-file-noselect file)))
-    (unwind-protect
-        (with-current-buffer buf
-          (condition-case err
-              (lmc-asm-load)
-            (error (error "Error at line %d: %s" (line-number-at-pos)
-                          (error-message-string err)))))
-      (unless exists (kill-buffer buf)))))
-
-(provide 'lmc)
-;;; lmc.el ends here



reply via email to

[Prev in Thread] Current Thread [Next in Thread]