changed . to dump, extended defop syntax, added while loops
This commit is contained in:
@@ -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 eş ()
|
||||||
|
"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)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
(eval-always
|
(eval-always
|
||||||
(defparameter *identifiers*
|
(defparameter *identifiers*
|
||||||
'(+ - |.| = ise yoksa yap eş push değiş üst rot düş))
|
'(+ - dump = ise yoksa yap eş 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)))))
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user