Add code to populate asm function table using listing declarations
This commit is contained in:
parent
3862092ce2
commit
09dc731444
3 changed files with 132 additions and 5 deletions
|
@ -2,17 +2,31 @@
|
|||
|
||||
(defvar *asm-functions* (make-hash-table :test #'equalp))
|
||||
|
||||
(defun asm-function-exists-p (name)
|
||||
(not (null (gethash name *asm-functions*))))
|
||||
|
||||
(defun get-asm-function (name)
|
||||
(gethash name *asm-functions*))
|
||||
|
||||
(defclass asm-function ()
|
||||
((%name :accessor name :initarg :name)
|
||||
(%address :accessor address :initarg :address
|
||||
:initform #xFEC0)))
|
||||
(%address :accessor address :initarg :address)))
|
||||
|
||||
(defun add-asm-function (name address &key &allow-other-keys)
|
||||
(when (or (not (asm-function-exists-p name))
|
||||
(/= address (address (get-asm-function name))))
|
||||
(setf (gethash name *asm-functions*)
|
||||
(make-instance 'asm-function :name name :address address))))
|
||||
|
||||
(tlk:define-simple-print-object (asm-function %name))
|
||||
|
||||
(define-transformation (token (token-name asm-function))
|
||||
(multiple-value-bind (asm-function existsp)
|
||||
(gethash (name token) *asm-functions*)
|
||||
(get-asm-function (name token))
|
||||
(if existsp
|
||||
asm-function
|
||||
(setf (gethash (name token) *asm-functions*)
|
||||
(make-instance 'asm-function :name (name token))))))
|
||||
(progn
|
||||
(cerror "Create dummy function with placeholder address."
|
||||
"Tried to transform token into non-existent function ~A."
|
||||
(name token))
|
||||
(add-asm-function (name token) #xC0FE)))))
|
||||
|
|
112
wip-duuqnd/user-side-compiler/populate-asm-functions.lisp
Normal file
112
wip-duuqnd/user-side-compiler/populate-asm-functions.lisp
Normal file
|
@ -0,0 +1,112 @@
|
|||
(in-package #:user-side-compiler)
|
||||
|
||||
(defun get-line-comment (line)
|
||||
(unless (zerop (length line))
|
||||
(let ((index
|
||||
(loop :with got-it-p := nil
|
||||
:for index :from 0
|
||||
:for char := (char line index)
|
||||
:when (char= char #\;)
|
||||
:do (setf got-it-p t)
|
||||
:until (or (and got-it-p (char/= char #\;))
|
||||
(= (1+ index) (length line)))
|
||||
:finally (return
|
||||
(if (= (1+ index) (length line))
|
||||
nil
|
||||
index)))))
|
||||
(unless (null index)
|
||||
(subseq line index)))))
|
||||
|
||||
(defun parse-asm-label (string)
|
||||
(flet
|
||||
((name-char-p (char)
|
||||
(or (alphanumericp char) (char= char #\_))))
|
||||
(cond
|
||||
((zerop (length string))
|
||||
nil)
|
||||
;; if it's an assembler macro, check that it's .proc
|
||||
((and (char= (char string 0) #\.)
|
||||
(string-equal (subseq string 0 5) ".proc")
|
||||
(whitespacep (char string 5)))
|
||||
(let* ((start (position-if-not #'whitespacep string :start 5))
|
||||
(end (position-if-not #'name-char-p string :start start)))
|
||||
(subseq string start end)))
|
||||
;; Regular colon label (ROUTINE_NAME:)
|
||||
((loop :for char :across string
|
||||
:until (char= char #\:)
|
||||
:always (name-char-p char))
|
||||
(subseq string 0 (position #\: string))))))
|
||||
|
||||
(defun asm-declaration-p (string)
|
||||
(let ((comment (get-line-comment string))
|
||||
(label (parse-asm-label string)))
|
||||
(and (search "user-procedure" comment :test #'char-equal) label)))
|
||||
|
||||
(defun parse-asm-declaration (string)
|
||||
(assert (asm-declaration-p string))
|
||||
(let ((routine-name (parse-asm-label string))
|
||||
(declaration (get-line-comment string)))
|
||||
(with-input-from-string (input declaration)
|
||||
(list routine-name
|
||||
(let ((*read-eval* nil)
|
||||
(eof '#.(gensym)))
|
||||
(loop :for obj := (read input nil eof)
|
||||
:until (eql obj eof)
|
||||
:collect obj))))))
|
||||
|
||||
(defun find-declarations-in-listing (filepath)
|
||||
(with-open-file (stream filepath)
|
||||
(loop :for line := (read-line stream)
|
||||
:until (and (not (zerop (length line)))
|
||||
(digit-char-p (char line 0))))
|
||||
(loop :for line := (read-line stream nil :eof)
|
||||
:until (eql line :eof)
|
||||
:for address := (parse-integer line :start 0 :end 6 :radix 16)
|
||||
:for main-text := (subseq line 24)
|
||||
:when (asm-declaration-p main-text)
|
||||
:collect (destructuring-bind (name declaration)
|
||||
(parse-asm-declaration main-text)
|
||||
(list name address declaration)))))
|
||||
|
||||
(defparameter *program-listing-filepath* #P"../../wip-hugo/program.lst")
|
||||
(defparameter *program-build-filepath* #P"../../wip-hugo/build.sh")
|
||||
|
||||
(defun check-for-asm-build-script ()
|
||||
(do ((path *program-build-filepath*))
|
||||
((probe-file path) path)
|
||||
(restart-case
|
||||
(error "Couldn't find assembly build script ~S." path)
|
||||
(use-value (filepath)
|
||||
:report "Specify a different path to the build script."
|
||||
:interactive (lambda ()
|
||||
(format t "Enter new pathname (evaled): ")
|
||||
(eval (read)))
|
||||
(setf path filepath)))))
|
||||
|
||||
(defun build-assembly-program ()
|
||||
(let ((script-path (check-for-asm-build-script))
|
||||
(current-dir (uiop:getcwd)))
|
||||
(unwind-protect
|
||||
(progn
|
||||
(uiop:chdir (make-pathname :defaults script-path
|
||||
:name nil :type nil))
|
||||
(uiop:run-program (namestring
|
||||
(make-pathname :defaults script-path
|
||||
:directory '(:relative ".")))))
|
||||
(uiop:chdir current-dir))))
|
||||
|
||||
(defun check-for-assembly-listing ()
|
||||
(do ((listing *program-listing-filepath*))
|
||||
((probe-file listing) listing)
|
||||
(restart-case
|
||||
(error "Couldn't find assembly listing ~S." listing)
|
||||
(build-program ()
|
||||
:report "Build the assembly program to generate listing."
|
||||
(build-assembly-program)))))
|
||||
|
||||
(defun populate-asm-functions ()
|
||||
(let* ((listing (check-for-assembly-listing))
|
||||
(routine-info (find-declarations-in-listing listing)))
|
||||
(loop :for (name address declaration) :in routine-info
|
||||
;; TODO: Use declaration info
|
||||
:do (add-asm-function name address))))
|
|
@ -12,6 +12,7 @@
|
|||
(:file "symbol-table")
|
||||
(:file "tokenizer")
|
||||
(:file "asm-function")
|
||||
(:file "populate-asm-functions")
|
||||
(:file "high-level")
|
||||
(:file "parser")
|
||||
(:file "label")
|
||||
|
|
Loading…
Add table
Reference in a new issue