changed . to dump, extended defop syntax, added while loops

This commit is contained in:
2024-07-27 11:58:41 +03:00
parent 025c958e2f
commit 2d94db0990
2 changed files with 120 additions and 51 deletions

View File

@@ -3,23 +3,38 @@
(defparameter *operations* (make-hash-table)) (defparameter *operations* (make-hash-table))
(eval-always (eval-always
(defun normalize-op-list (lst) (defun normalize-op-list (asm-list)
(cons 'list (cons 'list
(mapcar (lambda (el) (cond ((stringp el) el) (mapcar (lambda (el) (cond ((stringp el) el)
((listp el) `(format nil ,@el)))) ((listp el) `(format nil ,@el))))
lst)))) asm-list)))
(defmacro defop (op-name (&key (indent 4) args) &body asm-strings) (defun defop-format (str space-num asm-list)
`(setf (gethash ',op-name *operations*) (format str
(lambda (out-stream ,@args) (format nil "~~{~a~~a~~%~~}"
(format out-stream (make-string space-num :initial-element #\Space))
,(format nil "~~{~a~~a~~%~~}" asm-list))
(make-string indent :initial-element
#\Space))
,(normalize-op-list asm-strings)))))
(defun replace-write (out-stream indent forms)
(if (consp forms)
(if (eq :write (car forms))
`(defop-format ,out-stream ,indent
,(normalize-op-list (cdr forms)))
(cons (replace-write out-stream indent (car forms))
(replace-write out-stream indent (cdr forms))))
forms)))
(defop push (:args (a)) (defmacro defop (op-name+args (&key (indent 4)) &body body)
(with-gensyms (out-stream)
(destructuring-bind (op-name . args) (mklist op-name+args)
`(setf (gethash ',op-name *operations*)
(lambda (,out-stream ,@args)
,(if (or (stringp (car body)) (stringp (caar body)))
`(defop-format ,out-stream ,indent
,(normalize-op-list body))
(replace-write out-stream indent (car body))))))))
(defop (push a) ()
("push ~d" a)) ("push ~d" a))
(defop + () (defop + ()
@@ -34,7 +49,7 @@
"sub rbx, rax" "sub rbx, rax"
"push rbx") "push rbx")
(defop |.| () (defop dump ()
"pop rdi" "pop rdi"
"call dump") "call dump")
@@ -47,23 +62,60 @@
"cmove rcx, rdx" "cmove rcx, rdx"
"push rcx") "push rcx")
(defop exit (:args (exit-code)) (defop (exit code) ()
"mov rax, 60" "mov rax, 60"
("mov rdi, ~a" exit-code) ("mov rdi, ~a" code)
"syscall") "syscall")
(defop ise (:args (label-num)) (defop (ise label-num) ()
"pop rax" "pop rax"
"test rax, rax" "test rax, rax"
("jz et_~a" label-num)) ("jz et_~a" label-num))
(defop yoksa (:args (yap-num ise-num) :indent 0) (defop (yoksa yap-num ise-num) (:indent 0)
(" jmp et_~a" yap-num) (" jmp et_~a" yap-num)
("et_~a:" ise-num)) ("et_~a:" ise-num))
(defop yap (:args (label-num) :indent 0) (defop (yap label-num &optional döngü-num) (:indent 0)
(if (null döngü-num)
(:write ("et_~a:" label-num))
(:write (" jmp et_~a" döngü-num)
("et_~a:" label-num))))
(defop ()
"pop rax"
"push rax"
"push rax")
(defop düş ()
"pop rax")
(defop (iken label-num) ()
"pop rax"
"test rax, rax"
("jz et_~a" label-num))
(defop (döngü label-num) (:indent 0)
("et_~a:" label-num)) ("et_~a:" label-num))
(defop < ()
"mov rcx, 0"
"mov rdx, 1"
"pop rbx"
"pop rax"
"cmp rax, rbx"
"cmovl rcx, rdx"
"push rcx")
(defop > ()
"mov rcx, 0"
"mov rdx, 1"
"pop rbx"
"pop rax"
"cmp rax, rbx"
"cmovg rcx, rdx"
"push rcx")
(defun gen-code (op str) (defun gen-code (op str)
(let ((op-fn (gethash (car op) *operations*))) (let ((op-fn (gethash (car op) *operations*)))
(if (null op-fn) (if (null op-fn)

View File

@@ -2,7 +2,7 @@
(eval-always (eval-always
(defparameter *identifiers* (defparameter *identifiers*
'(+ - |.| = ise yoksa yap push değiş üst rot düş)) '(+ - dump = ise yoksa yap push değiş üst rot düş döngü iken < >))
(defun is-identifier (sym) (defun is-identifier (sym)
(find sym *identifiers*))) (find sym *identifiers*)))
@@ -14,6 +14,7 @@
(defun token-op (token) (defun token-op (token)
(car token)) (car token))
;;; LEXER
(defun lex-line (line &optional (line-num 0)) (defun lex-line (line &optional (line-num 0))
(iter (with line-stream = (make-string-input-stream line)) (iter (with line-stream = (make-string-input-stream line))
(with col = 0) (with col = 0)
@@ -21,13 +22,13 @@
(for next-char = (peek-char nil line-stream nil nil)) (for next-char = (peek-char nil line-stream nil nil))
(until (null next-char)) (until (null next-char))
(let ((flag t)) (let ((flag t))
(cond ((char= #\. next-char) (cond ;; ((char= #\. next-char)
(collect (make-token '|.| line-num col) into tokens) ;; (collect (make-token '|.| line-num col) into tokens)
(read-char line-stream)) ;; (read-char line-stream))
((char= #\Space next-char) (read-char line-stream)) ((char= #\Space next-char) (read-char line-stream))
((char= #\; next-char) ;; and not in string ((char= #\; next-char) ;; and not in string
(finish)) (finish))
(t (setf flag nil))) (t (setf flag nil)))
(when flag (when flag
(incf col) (incf col)
(next-iteration))) (next-iteration)))
@@ -64,34 +65,42 @@
(appending tokens)))) (appending tokens))))
has-error))) has-error)))
;; (defun prog-from-tokens (tokens) ;;; PARSER
;; (iter (for token in tokens)
;; (let ((op (token-op token)))
;; (cond ((numberp op)
;; (collect `(push ,op) result-type 'vector))
;; (t (collect (list op) result-type 'vector))))))
(defun parse-tokens (tokens) (defun parse-tokens (tokens)
(iter (with ops = (make-array (length tokens) :fill-pointer 0 (iter (with ops = (make-array (length tokens) :fill-pointer 0
:adjustable t)) :adjustable t))
(with if-stack = ()) (with stack = ())
(for i from 0) (for i from 0)
(for token in tokens) (for token in tokens)
(let ((op (token-op token))) (let ((op (token-op token)))
(cond ((numberp op) (cond ((numberp op)
(vector-push-extend `(push ,op) ops)) (vector-push-extend `(push ,op) ops))
((eq 'ise op) ((eq 'ise op)
(push i if-stack) (push (list 'ise i) stack)
(vector-push-extend (list 'ise nil) ops)) (vector-push-extend (list 'ise nil) ops))
((eq 'yoksa op) ((eq 'yoksa op)
(let ((current (pop if-stack))) (let ((top (pop stack)))
(setf (second (aref ops current)) i) (assert (eq 'ise (car top)))
(push i if-stack) (setf (second (aref ops (cadr top))) i)
(push (list 'yoksa i) stack)
(vector-push-extend (list 'yoksa nil i) ops))) (vector-push-extend (list 'yoksa nil i) ops)))
((eq 'yap op) ((eq 'yap op)
(let ((current (pop if-stack))) (let ((top (pop stack)))
(setf (second (aref ops current)) i) (cond ((find (car top) (list 'yoksa 'ise))
(vector-push-extend (list 'yap i) ops))) (setf (second (aref ops (cadr top))) i)
(vector-push-extend (list 'yap i) ops))
((eq 'iken (car top))
(setf (second (aref ops (cadr top))) i)
(vector-push-extend (list 'yap i (third top)) ops))
(t (error "yap cannot reference: ~a" (car top))))))
((eq 'döngü op)
(push (list 'döngü i) stack)
(vector-push-extend (list 'döngü i) ops))
((eq 'iken op)
(let ((top (pop stack)))
(assert (eq 'döngü (car top)))
(push (list 'iken i (cadr top)) stack)
(vector-push-extend (list 'iken nil) ops)))
(t (vector-push-extend (list op) ops)))) (t (vector-push-extend (list op) ops))))
(finally (return ops)))) (finally (return ops))))
@@ -102,17 +111,19 @@
(error "Can't generate program due to error during lexing")) (error "Can't generate program due to error during lexing"))
(parse-tokens tokens))) (parse-tokens tokens)))
;; (defun *ops* '(push pop minus dump))
(define-condition op-not-implemented (style-warning)
((undef-ops :initarg :ops :reader undef-ops))
(:report (lambda (condition stream)
(format stream "These ops are not defined in op-case: ~s"
(undef-ops condition)))))
(defun identifier-coverage (defined-ops) ;;; INTERPRETER
(let ((undef-ops (set-difference *identifiers* defined-ops))) (eval-always
(unless (null undef-ops) (define-condition op-not-implemented (style-warning)
(warn (make-condition 'op-not-implemented :ops undef-ops))))) ((undef-ops :initarg :ops :reader undef-ops))
(:report (lambda (condition stream)
(format stream "These ops are not defined in op-case: ~s"
(undef-ops condition)))))
(defun identifier-coverage (defined-ops)
(let ((undef-ops (set-difference *identifiers* defined-ops)))
(unless (null undef-ops)
(warn (make-condition 'op-not-implemented :ops undef-ops))))))
(defmacro op-case (case-form &body body) (defmacro op-case (case-form &body body)
(iter (for (op-id) in body) (iter (for (op-id) in body)
@@ -178,6 +189,9 @@
;; rot, rot ;; rot, rot
;; drop, düşür ;; drop, düşür
;;; COMPILER
(defun gen-header (op str) (defun gen-header (op str)
(format str " ;; -- ~s --~%" op)) (format str " ;; -- ~s --~%" op))
@@ -203,5 +217,8 @@
(defun compile-program (path) (defun compile-program (path)
(generate-program (make-program path) :compile t)) (generate-program (make-program path) :compile t))
(defun assembly-undefined-ops ()
(iter (for (k) in-hashtable *operations*)
(collect k into defops)
(finally (return (set-difference *identifiers* defops)))))