branching (if else) added, as interpretation and compilation
This commit is contained in:
@@ -9,14 +9,17 @@
|
|||||||
((listp el) `(format nil ,@el))))
|
((listp el) `(format nil ,@el))))
|
||||||
lst))))
|
lst))))
|
||||||
|
|
||||||
(defmacro defop (op-name args &body asm-strings)
|
(defmacro defop (op-name (&key (indent 4) args) &body asm-strings)
|
||||||
`(setf (gethash ',op-name *operations*)
|
`(setf (gethash ',op-name *operations*)
|
||||||
(lambda (out-stream ,@args)
|
(lambda (out-stream ,@args)
|
||||||
(format out-stream "~{ ~a~%~}"
|
(format out-stream
|
||||||
|
,(format nil "~~{~a~~a~~%~~}"
|
||||||
|
(make-string indent :initial-element
|
||||||
|
#\Space))
|
||||||
,(normalize-op-list asm-strings)))))
|
,(normalize-op-list asm-strings)))))
|
||||||
|
|
||||||
|
|
||||||
(defop push (a)
|
(defop push (:args (a))
|
||||||
("push ~d" a))
|
("push ~d" a))
|
||||||
|
|
||||||
(defop + ()
|
(defop + ()
|
||||||
@@ -35,6 +38,38 @@
|
|||||||
"pop rdi"
|
"pop rdi"
|
||||||
"call dump")
|
"call dump")
|
||||||
|
|
||||||
|
(defop = ()
|
||||||
|
"mov rcx, 0"
|
||||||
|
"mov rdx, 1"
|
||||||
|
"pop rax"
|
||||||
|
"pop rbx"
|
||||||
|
"cmp rax, rbx"
|
||||||
|
"cmove rcx, rdx"
|
||||||
|
"push rcx")
|
||||||
|
|
||||||
|
(defop exit (:args (exit-code))
|
||||||
|
"mov rax, 60"
|
||||||
|
("mov rdi, ~a" exit-code)
|
||||||
|
"syscall")
|
||||||
|
|
||||||
|
(defop ise (:args (label-num))
|
||||||
|
"pop rax"
|
||||||
|
"test rax, rax"
|
||||||
|
("jz et_~a" label-num))
|
||||||
|
|
||||||
|
(defop yoksa (:args (yap-num ise-num) :indent 0)
|
||||||
|
(" jmp et_~a" yap-num)
|
||||||
|
("et_~a:" ise-num))
|
||||||
|
|
||||||
|
(defop yap (:args (label-num) :indent 0)
|
||||||
|
("et_~a:" label-num))
|
||||||
|
|
||||||
|
(defun gen-code (op str)
|
||||||
|
(let ((op-fn (gethash (car op) *operations*)))
|
||||||
|
(if (null op-fn)
|
||||||
|
(error "~s is not a valid op" op)
|
||||||
|
(apply op-fn str (cdr op)))))
|
||||||
|
|
||||||
(defun gen-dump (str)
|
(defun gen-dump (str)
|
||||||
(format str "~{~a~%~}"
|
(format str "~{~a~%~}"
|
||||||
'("dump:"
|
'("dump:"
|
||||||
|
|||||||
@@ -74,16 +74,24 @@
|
|||||||
(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 = ())
|
||||||
(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)
|
||||||
(vector-push-extend
|
(push i if-stack)
|
||||||
`(ise ,(position 'yap tokens :start i :key #'token-op))
|
(vector-push-extend (list 'ise nil) ops))
|
||||||
ops))
|
((eq 'yoksa op)
|
||||||
;; currently does not handle nesting
|
(let ((current (pop if-stack)))
|
||||||
|
(setf (second (aref ops current)) i)
|
||||||
|
(push i if-stack)
|
||||||
|
(vector-push-extend (list 'yoksa nil i) ops)))
|
||||||
|
((eq 'yap op)
|
||||||
|
(let ((current (pop if-stack)))
|
||||||
|
(setf (second (aref ops current)) i)
|
||||||
|
(vector-push-extend (list 'yap i) ops)))
|
||||||
(t (vector-push-extend (list op) ops))))
|
(t (vector-push-extend (list op) ops))))
|
||||||
(finally (return ops))))
|
(finally (return ops))))
|
||||||
|
|
||||||
@@ -141,6 +149,7 @@
|
|||||||
1 0)
|
1 0)
|
||||||
stack))
|
stack))
|
||||||
(yap (next-iteration))
|
(yap (next-iteration))
|
||||||
|
(yoksa (setf i (second op)))
|
||||||
(ise (if (= (vector-pop stack) 1)
|
(ise (if (= (vector-pop stack) 1)
|
||||||
nil
|
nil
|
||||||
(setf i (second op))))
|
(setf i (second op))))
|
||||||
@@ -184,13 +193,8 @@
|
|||||||
"_start:"))
|
"_start:"))
|
||||||
(iter (for op in-sequence program)
|
(iter (for op in-sequence program)
|
||||||
(gen-header op out)
|
(gen-header op out)
|
||||||
(let ((op-fn (gethash (car op) *operations*)))
|
(gen-code op out))
|
||||||
(if (null op-fn)
|
(gen-code '(exit 0) out))
|
||||||
(format t "~s is not an op" (car op))
|
|
||||||
(apply op-fn out (cdr op)))))
|
|
||||||
(format out "~{~a~%~}" '(" mov rax, 60"
|
|
||||||
" mov rdi, 0"
|
|
||||||
" syscall")))
|
|
||||||
(when compile
|
(when compile
|
||||||
(run `("nasm" "-felf64" ,path))
|
(run `("nasm" "-felf64" ,path))
|
||||||
(let ((name (first (uiop:split-string path :separator '(#\.)))))
|
(let ((name (first (uiop:split-string path :separator '(#\.)))))
|
||||||
|
|||||||
Reference in New Issue
Block a user