diff options
author | bd <bdunahu@operationnull.com> | 2025-04-10 20:28:34 -0400 |
---|---|---|
committer | bd <bdunahu@operationnull.com> | 2025-04-10 20:28:34 -0400 |
commit | c1507d153161413e4958362d19ae9aa9abedee47 (patch) | |
tree | 23c6f4538c1b385cb1e6f97d197b8afa18a45619 /src | |
parent | df508744ec2975cec0ba05e8a4358c1c41265c4c (diff) |
Add write raw bytes stage
Diffstat (limited to 'src')
-rw-r--r-- | src/emit.lisp | 9 | ||||
-rw-r--r-- | src/main.lisp | 44 | ||||
-rw-r--r-- | src/package.lisp | 27 | ||||
-rw-r--r-- | src/util.lisp | 13 |
4 files changed, 66 insertions, 27 deletions
diff --git a/src/emit.lisp b/src/emit.lisp index acc2772..48ebebe 100644 --- a/src/emit.lisp +++ b/src/emit.lisp @@ -2,7 +2,7 @@ (defun fits-in-X-bits (n) "Returns the number of bits required to represent N" - (ceiling (/ (log (ceiling n (log 2))) (log 2)))) + (ceiling (/ (log n) (log 2)))) (defmacro generate-type-map (ops) "Generates an alist where the key corresponds to an element in @@ -11,8 +11,7 @@ number of bits required to represent all concatenated with TYPE." `(let ((i 0) (opsize (fits-in-X-bits (length ,ops)))) - (mapcar (lambda (x) - (incf i) + (mapcar (lambda (x) (incf i) (cons x (util:format-as-binary i opsize))) ,ops))) @@ -62,5 +61,7 @@ concatenated with TYPE." (+ pos parse:line-number))) (defun emit (p) - (format t "~a~%" p) (eval p)) + +(defun ast->str (p) + (format nil "~a" p)) diff --git a/src/main.lisp b/src/main.lisp index f20b022..517d395 100644 --- a/src/main.lisp +++ b/src/main.lisp @@ -23,27 +23,51 @@ _/_/ _/_/ " :long-name "parse" :short-name #\p :required nil - :key :parse))) + :key :parse) + (clingon:make-option + :flag + :description "run the emitter, but stop before writing" + :long-name "emit" + :short-name #\e + :required nil + :key :emit))) + +(defun postprocess (out file) + "Given OUT, a list of words, writes the raw bytes to FILE." + (let ((file (util:generate-file-name file)) + (bytes (alexandria:flatten + (mapcar (lambda (x) + (util:word-to-bytes (parse-integer x :radix 2))) + out)))) + (with-open-file (stream file + :direction :output + :if-exists :supersede + :if-does-not-exist :create + :element-type '(unsigned-byte 8)) + (loop for byte in bytes do (write-byte byte stream))) + (format t "File written! Check ~a~%" file))) (defun driver (cmd) "Reads in a file and directs lexing, parsing, and binary emission." (print-splash) (let* ((args (clingon:command-arguments cmd)) (file (car args)) - (emit? (not (clingon:getopt cmd :parse)))) + (emit? (not (clingon:getopt cmd :parse))) + (write? (not (clingon:getopt cmd :emit)))) (cond - ;; complain about num arguments ((/= (length args) 1) (error "Wrong number of arguments.~%")) ((not (util:asm-extension? file)) (error "The file is not an asm source code file.~%")) (t (let ((str (uiop:read-file-string file))) (if str - (let ((ast (esrap:parse 'parse::str->ast (string-upcase str)))) - (when emit? - (format t "~a~%" (emit::emit ast)))) - (error "The file does not exist, or it could not be opened.~%")) - (format t "Nitimur in Vetitum~%")))))) - + (let ((ast (esrap:parse 'parse::str->ast (string-upcase str)))) + (if emit? + (let ((words (emit:emit ast))) + (if write? + (postprocess words file) + (format t "Emission successfull, got: ~%~a~%" words))) + (format t "Parse successful, got:~%~a~%" (emit:ast->str ast)))) + (error "The file does not exist, or it could not be opened.~%"))))))) (defun cli/command () "Returns a clingon command." @@ -51,7 +75,7 @@ _/_/ _/_/ " :name "rva" :description "generates a binary compatible with the RISC V[ECTOR] simulator" :usage "[options] file" - :version(asdf:component-version + :version (asdf:component-version (asdf:find-system "rva" nil)) :options (cli/options) :handler #'driver)) diff --git a/src/package.lisp b/src/package.lisp index bbb45a3..d016501 100644 --- a/src/package.lisp +++ b/src/package.lisp @@ -6,22 +6,25 @@ (:use #:cl) (:export #:asm-extension? #:format-as-binary - #:insert-in-middle - #:iota - #:riffle - #:add-variable - #:add-label - #:get-variable - #:get-label - #:r-type - #:i-type - #:j-type)) + #:generate-file-name + #:word-to-bytes + #:insert-in-middle + #:iota + #:riffle + #:add-variable + #:add-label + #:get-variable + #:get-label + #:r-type + #:i-type + #:j-type)) (defpackage #:parse (:use #:cl) (:export #:str->ast - #:line-number)) + #:line-number)) (defpackage #:emit (:use #:cl) - (:export #:emit)) + (:export #:emit + #:ast->str)) diff --git a/src/util.lisp b/src/util.lisp index f3035fe..8d98680 100644 --- a/src/util.lisp +++ b/src/util.lisp @@ -4,6 +4,9 @@ "Returns t if FILE is extended with .asm, nil otherwise." (string= (pathname-type file) "asm")) +(defun generate-file-name (file) + "Given a .asm file, generates an identically named .rv file." + (subseq file 0 (- (length file) 4))) (defun format-as-binary (num len) "Formats NUM as a binary number, and pads to LEN with zeros." @@ -12,7 +15,15 @@ (let ((max-val (1- (expt 2 len)))) (format nil "~V,'0b" len (logand num max-val)))) +(defun word-to-bytes (int) + "Given a 32-bit integer, outputs a list of 4 bytes." + (list (logand #xff (ash int -24)) + (logand #xff (ash int -16)) + (logand #xff (ash int -8)) + (logand #xff int))) + (defun insert-in-middle (list element) + "Inserts ELEMENT in the second slot of LIST." (append (list (car list)) (list element) (cdr list))) (defun iota (n) @@ -48,7 +59,7 @@ of the elements from both lists. Returns nil if the lists are not equal size." (alexandria:if-let ((value (gethash name variable-table))) value (progn (maphash #'(lambda (k v) (format t "~A => ~A~%" k v)) variable-table) - (error "~@<Variable ~S not declared.~@:>" name)))) + (error "~@<Variable ~S not declared.~@:>" name)))) (defun get-label (name) (alexandria:if-let ((value (gethash name label-table))) |