Browse Source

Initial commit.

Paul Onions 11 years ago
commit
e6d4ee45ce
4 changed files with 365 additions and 0 deletions
  1. 113 0
      rpl-base.el
  2. 155 0
      rpl-edb.el
  3. 27 0
      rpl-tools.el
  4. 70 0
      sysrpl-mode.el

+ 113 - 0
rpl-base.el

@@ -0,0 +1,113 @@
+;;; rpl-base.el -- basic setup for the RPL tools
+
+;; Copyright (C) 2014 Paul Onions
+
+;; Author: Paul Onions <paul.onions@acm.org>
+;; Keywords: RPL, SysRPL, HP48, HP49, HP50
+
+;; This file is free software, see the LICENCE file in this directory
+;; for copying terms.
+
+;;; Commentary:
+
+;; Basic setup for the RPL tools.
+
+;;; Code:
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Customizations
+;;
+(defgroup rpl nil
+  "Tools for working with the RPL calculator programming language.")
+
+(defcustom rpl-sysrpl-data-file "sysrpl-data.el"
+  "File from which to `read' SysRPL data."
+  :type 'string
+  :group 'rpl)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Utility functions for generating/loading pre-computed data
+;;
+(defvar rpl-tools-data-dir
+  (and load-file-name (concat (file-name-directory load-file-name) "data/"))
+  "RPL tools data directory.")
+
+(defun rpl-write-data-file (obj filename)
+  "Write OBJ to FILENAME using function `print'.
+
+The directory in which to write the file defaults to the value of
+the variable `rpl-tools-data-dir'. This can be overridden by
+specifying a different path in the FILENAME string (either
+relative or absolute)."
+  (let ((default-directory rpl-tools-data-dir))
+    (with-temp-buffer
+      (print obj (current-buffer))
+      (write-region (point-min) (point-max) filename))))
+
+(defun rpl-read-data-file (filename)
+  "Read a Lisp object from FILENAME using function `read'.
+
+The directory in which FILENAME resides is assumed to be the
+value of the variable `rpl-tools-data-dir'. This can be
+overridden by specifying a different path in the FILENAME
+string (either relative or absolute)."
+  (let ((default-directory rpl-tools-data-dir))
+    (with-temp-buffer
+      (insert-file-contents filename)
+      (goto-char (point-min))
+      (read (current-buffer)))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Load SysRPL names files
+;;
+(message "Loading SysRPL information")
+
+(defvar rpl-sysrpl-data
+  nil  ;;(rpl-read-data-file rpl-sysrpl-data-file)
+  "!!!TODO!!!")
+
+(defvar rpl-sysrpl-names
+  nil  ; extract from rpl-sysrpl-data
+  "!!!TODO!!!")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Common keymap (including the ``RPL'' menu)
+;;
+(defvar rpl-menu-compile-file-enable nil)
+
+(make-variable-buffer-local 'rpl-menu-compile-file-enable)
+
+(defvar rpl-common-keymap
+  (let ((map (make-sparse-keymap "RPL"))
+        (menu-map (make-sparse-keymap "RPL")))
+    (set-keymap-parent map prog-mode-map)
+    ;; Key assignments
+    (define-key map (kbd "C-c C-k") 'rpl-compile-file)
+    ;; Menu items
+    (define-key map [menu-bar rpl-menu] (cons "RPL" menu-map))
+    (define-key menu-map [rpl-menu-compile-file]
+      '(menu-item "Compile File..." rpl-compile-file
+                  :enable rpl-menu-compile-file-enable))
+    (define-key menu-map [axiom-menu-separator-1]
+      '(menu-item "--"))
+    (define-key menu-map [rpl-menu-apropos]
+      '(menu-item "Apropos (at point)..." rpl-apropos-thing-at-point))
+    map)
+  "The RPL tools common keymap.")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Developer utils
+;;
+(defvar rpl-debug nil)
+
+(defmacro rpl-debug-message (msg)
+  (if rpl-debug
+      `(message ,msg)
+    nil))
+
+(defun rpl-force-reload ()
+  (interactive)
+  (load "rpl-base")
+  (load "rpl-sysrpl-mode"))
+
+(provide 'rpl-base)

+ 155 - 0
rpl-edb.el

@@ -0,0 +1,155 @@
+;;; rpl-edb.el -- utilities to parse the entries database
+
+;; Copyright (C) 2014 Paul Onions
+
+;; Author: Paul Onions <paul.onions@acm.org>
+;; Keywords: RPL, UserRPL, SysRPL, HP48, HP49, HP50
+
+;; This file is free software, see the LICENCE file in this directory
+;; for copying terms.
+
+;;; Commentary:
+
+;; Functions to parse the entries.db file.
+
+;;; Code:
+(require 'cl-lib)
+
+(defun rpl-edb-get-line ()
+  "Get line that point is on from the current buffer.
+Return a string containing the line, or nil if at end of buffer.
+As a side-effect set point to the start of the next line."
+  (cond ((eobp)
+         nil)
+        (t
+         (beginning-of-line)
+         (let ((start (point)))
+           (end-of-line)
+           (let ((line (buffer-substring-no-properties start (point))))
+             (forward-char)
+             line)))))
+
+;;; Parsing identifier lines
+;;;
+(defun rpl-edb-consume-ident-line ()
+  "Consume an EDB identifier line.
+Return a list of two strings: the identifier and its stack effect
+description.  Move point to the start of the next line."
+  (let ((line (rpl-edb-get-line)))
+    (cond ((string-match "^[[:graph:]]+" line)
+           (let* ((name (match-string 0 line))
+                  (desc (substring line (match-end 0))))
+             ;; Automatically consume continuation lines
+             ;; (line ends with a backslash)
+             (while (and (> (length desc) 0)
+                         (string-match ".*\\\\[[:blank:]]*$" desc))
+               (setq desc (concat (substring desc 0 (1- (length desc)))
+                                  "\n"
+                                  (rpl-edb-get-line))))
+             (list name desc)))
+          (t
+           (list "" "")))))
+
+;;; Parsing keyword lines
+;;;
+(defun rpl-edb-parse-keyword-line (line)
+  "Parse the given EDB keyword line.
+Return a list consisting of the EDB keyword as a keyword symbol
+and a parameter string (to be further parsed later)."
+  (cond ((string-match "\\.[[:blank:]]+\\([[:alnum:]]+\\):" line)
+         (let ((keyword (intern (concat ":" (match-string 1 line))))
+               (param-str (substring line (match-end 0))))
+           (list keyword param-str)))
+        (t
+         (list nil ""))))
+
+(defun rpl-edb-parse-calc-param-str (str)
+  (cond ((string-match "[[:blank:]]*\\([[:alnum:]]+\\)[[:blank:]]*\\(\\\\[[:graph:]]+\\\\\\)?" str)
+         (let ((addr  (match-string 1 str))
+               (fmt   (match-string 2 str))
+               (flags nil))
+           (setq str (substring str (match-end 0)))
+           (while (string-match "[[:blank:]]*\\[\\([[:graph:]]+\\)\\]" str)
+             (setq flags (cons (intern (concat ":" (match-string 1 str))) flags))
+             (setq str (substring str (match-end 1))))
+           (list addr fmt (reverse flags))))
+        (t
+         (list "" "" nil))))
+
+(defun rpl-edb-parse-aka-param-str (str)
+  (let ((names nil))
+    (while (string-match "[[:blank:]]*\\([[:graph:]]+\\)" str)
+      (setq names (cons (match-string 1 str) names))
+      (setq str (substring str (match-end 1))))
+    (reverse names)))
+
+(defun rpl-edb-consume-keyword-line ()
+  (let ((line (rpl-edb-get-line)))
+    (cl-destructuring-bind (keyword param-str)
+        (rpl-edb-parse-keyword-line line)
+      (cond ((member keyword '(:38G :39G :48G :49G))
+             (cl-destructuring-bind (addr fmt flags)
+                 (rpl-edb-parse-calc-param-str param-str)
+               (append (list keyword addr fmt) flags)))
+            ((eql keyword :AKA)
+             (let ((names (rpl-edb-parse-aka-param-str param-str)))
+               (cons keyword names)))
+            (t
+             (error "Illegal EDB keyword, %s" keyword))))))
+
+;;; Parsing extended description lines
+;;;
+(defun rpl-edb-consume-description-line ()
+  "Consume an EDB extended description line.
+Return a string.  Move point to the start of the next line."
+  (let ((line (rpl-edb-get-line)))
+    (substring line 80)))
+
+;;; Parsing the entries.db buffer
+;;;
+(defun rpl-edb-parse-buffer ()
+  "Parse the current buffer, assumed to be the entries.db file.
+Return a list of EDB entries of the format:
+???
+"
+  (interactive)
+  (let ((entry-names nil)
+        (entry-stack-effect nil)
+        (entry-calc-infos nil)
+        (entry-description "")
+        (entries nil))
+    (beginning-of-buffer)
+    (while (not (eobp))
+      (cond ((eql (char-after) ?*)
+             ;; A comment line -- ignore it
+             (forward-line))
+            ((eql (char-after) ?@)
+             ;; A directive -- ignore it
+             (forward-line))
+            ((eql (char-after) ?\;)
+             ;; An extended description line
+             (setq entry-description (concat entry-description " "
+                                             (rpl-edb-consume-description-line))))
+            ((eql (char-after) ?.)
+             ;; A keyword line
+             (cl-destructuring-bind (keyword &rest params)
+                 (rpl-edb-consume-keyword-line)
+               (cond ((eql keyword :AKA)
+                      (dolist (name params)
+                        (push name entry-names)))
+                     (t
+                      (push (cons keyword params) entry-calc-infos)))))
+            (t
+             ;; An identifier/stack-effect line
+             (when entry-names
+               (push (list entry-names entry-stack-effect entry-calc-infos entry-description) entries))
+             (cl-destructuring-bind (name stack-effect)
+                 (rpl-edb-consume-ident-line)
+               (setq entry-names (list name))
+               (setq entry-stack-effect stack-effect)
+               (setq entry-calc-infos nil)
+               (setq entry-description "")))))
+    (when entry-names
+      (push (list entry-names entry-stack-effect entry-calc-infos entry-description) entries))
+    (reverse entries)))
+

+ 27 - 0
rpl-tools.el

@@ -0,0 +1,27 @@
+;;; rpl-tools.el -- tools for RPL calculator programming
+
+;; Copyright (C) 2014 Paul Onions
+
+;; Author: Paul Onions <paul.onions@acm.org>
+;; Keywords: RPL, SysRPL, HP48, HP49, HP50, calculator
+
+;; This file is free software, see the LICENCE file in this directory
+;; for copying terms.
+
+;;; Commentary:
+
+;; To use this system, ensure this directory is in your `load-path',
+;; and put
+;;
+;;   (require 'rpl-tools)
+;;
+;; into your .emacs file.
+
+;;; Code:
+
+;; Load everything
+(require 'rpl-base)
+(require 'sysrpl-mode)
+
+;; Acknowledge we're loaded
+(provide 'rpl-tools)

+ 70 - 0
sysrpl-mode.el

@@ -0,0 +1,70 @@
+;;; sysrpl-mode.el -- Major mode for the SysRPL programming language
+
+;; Copyright (C) 2013 Paul Onions
+
+;; Author: Paul Onions <paul.onions@acm.org>
+;; Keywords: RPL, SysRPL, HP48, HP49, HP50, calculator
+
+;; This file is free software, see the LICENCE file in this directory
+;; for copying terms.
+
+;;; Commentary:
+
+;; A major mode for the SysRPL language, the system programming
+;; language of HP48/49/50-series calculators.
+
+;;; Code:
+
+(require 'rpl-base)
+
+(defface sysrpl-name '((t (:foreground "blue")))
+  "Face used for displaying SysRPL names."
+  :group 'rpl)
+
+(defvar sysrpl-syntax-table
+  (let ((table (make-syntax-table)))
+    (modify-syntax-entry ?:  "w" table)
+    (modify-syntax-entry ?!  "w" table)
+    (modify-syntax-entry ?@  "w" table)
+    (modify-syntax-entry ?#  "w" table)
+    (modify-syntax-entry ?$  "w" table)
+    (modify-syntax-entry ?%  "w" table)
+    (modify-syntax-entry ?^  "w" table)
+    (modify-syntax-entry ?&  "w" table)
+    (modify-syntax-entry ?\? "w" table)
+    (modify-syntax-entry ?-  "w" table)
+    (modify-syntax-entry ?_  "w" table)
+    (modify-syntax-entry ?=  "w" table)
+    (modify-syntax-entry ?+  "w" table)
+    (modify-syntax-entry ?/  "w" table)
+    (modify-syntax-entry ?<  "w" table)
+    (modify-syntax-entry ?>  "w" table)
+    (modify-syntax-entry ?|  "w" table)
+    table)
+  "The SysRPL syntax table.")
+
+(defvar sysrpl-keywords-regexp
+  (concat "\\<" (regexp-opt rpl-sysrpl-names) "\\>")
+  "Regular expression for SysRPL keywords.")
+
+(defvar sysrpl-keyword-face 'sysrpl-name)
+
+(defvar sysrpl-font-lock-keywords
+  (list (cons sysrpl-keywords-regexp 'sysrpl-keyword-face)))
+
+(defvar sysrpl-mode-map
+  (let ((map (make-sparse-keymap)))
+    (set-keymap-parent map rpl-common-keymap)
+    map)
+  "The SysRPL mode local keymap.")
+
+(defvar sysrpl-mode-hook nil
+  "Hook for customizing SysRPL mode.")
+
+(define-derived-mode sysrpl-mode prog-mode "SysRPL"
+  "Major mode for the SysRPL language."
+  :group 'rpl
+  (setq font-lock-defaults (list sysrpl-font-lock-keywords))
+  (setq rpl-menu-compile-file-enable t))
+
+(provide 'sysrpl-mode)