(defstruct forth-word
name
definition)
(defun list-to-word (list)
(make-forth-word :name (first list)
:definition (rest list)))
(defun make-forth-dictionary (&rest lists)
(loop for lst in lists
collect (make-forth-word :name (first lst)
:definition (second lst))))
(defun add-word-to-dictionary (the-word dictionary)
(cons the-word dictionary))
(defvar *data-stack* nil)
(defparameter *dictionary*
(make-forth-dictionary
(list '+ #'(lambda (stack)
(let ((a (pop stack))
(b (pop stack)))
(cons (+ a b)
stack))))
(list '- #'(lambda (stack)
(let ((a (pop stack))
(b (pop stack)))
(cons (- b a)
stack))))
(list '* #'(lambda (stack)
(let ((a (pop stack))
(b (pop stack)))
(cons (* a b)
stack))))
(list '/ #'(lambda (stack)
(let ((a (pop stack))
(b (pop stack)))
(cons (/ a b)
stack))))
(list '\. #'(lambda (stack)
(print (car stack))
(cdr stack)))
(list 'dup #'(lambda (stack)
(cons (car stack)
stack)))
(list 'swap #'(lambda (stack)
(let ((a (pop stack))
(b (pop stack)))
(push a stack)
(push b stack))))
(list 'inc '(1 +))
))
(defmacro aif (test then &optional else)
`(let ((it ,test))
(if it
,then
,else)))
(defun find-word-in-dictionary (word-symbol dictionary)
(loop for w in dictionary
do (when (equal word-symbol
(forth-word-name w))
(return w))))
(defun find-word-definition-in-dictionary (word-symbol dictionary)
(aif (find-word-in-dictionary word-symbol dictionary)
(forth-word-definition it)))
(defun eval-forth-word (word-symbol stack dictionary)
(block nil
(aif (find-word-definition-in-dictionary word-symbol dictionary)
(cond
((functionp it)
(return (funcall it stack)))
((listp it)
(eval-forth-program it
stack
*dictionary*
'eval)))
(error "Ошибка. Неизвестное слово: ~A" word-symbol))))
(defun define-word (program stack dictionary state definition)
(let ((current-word (first program)))
(if (eql current-word 'end-define)
(eval-forth-program (rest program)
stack
(cons dictionary (list-to-word (nreverse definition)))
state)
(define-word
(rest program)
stack
dictionary
state
(cons current-word definition)))))
(defun eval-forth-program (program &optional (stack nil) (dictionary *dictionary*) (state 'eval))
; (print stack)
(let ((current-word (first program)))
(case state
((eval)
(cond
((null program)
(return-from eval-forth-program stack))
((eql current-word 'define)
(define-word
(rest program)
stack
dictionary
state
nil))
((eql current-word 'if)
(if (not (zerop (first stack)))
(eval-forth-program (rest program)
(rest stack)
dictionary
'then-eval)
(eval-forth-program (rest program)
(rest stack)
dictionary
'then-skip)
))
((numberp current-word)
(eval-forth-program (rest program)
(cons current-word stack)
dictionary
'eval))
((symbolp current-word)
(eval-forth-program (rest program)
(eval-forth-word current-word stack dictionary)
dictionary
'eval))))
((then-eval) ; АХТУНГ Функция слишком большая. Оператор ветвления не поддерживает вложенности. И вообще я ничего ещё не дописал.
(cond
((null program)
(return-from eval-forth-program stack))
((eql current-word 'define)
(eval-forth-program (rest program)
stack
dictionary
'defining))
((eql current-word 'if)
(if (not (zerop (first stack)))
(eval-forth-program (rest program)
(rest stack)
dictionary
'then-eval)
(eval-forth-program (rest program)
(rest stack)
dictionary
'then-skip)
))
((numberp current-word)
(eval-forth-program (rest program)
(cons current-word stack)
dictionary
'eval))
((symbolp current-word)
(eval-forth-program (rest program)
(eval-forth-word current-word stack dictionary)
dictionary
'eval))))
)))
Как мне реализовать оператор ветвления так, чтобы он поддерживал вложенность.
И ещё, не подскажите ли, как разбить код на функции? А то функция eval-forth-program слишком большая и сложная.