added op-case and some conditions for it (error checking)

This commit is contained in:
2024-07-23 16:17:16 +03:00
parent 1732b9a1a1
commit 7fa561a9d9

View File

@@ -1,9 +1,10 @@
(in-package :cl-forth) (in-package :cl-forth)
(defparameter *identifiers* '(+ - |.| =)) (eval-always
(defparameter *identifiers*
(defun is-identifier (sym) '(+ - |.| = ise yoksa yap push değiş üst rot düş))
(find sym *identifiers*)) (defun is-identifier (sym)
(find sym *identifiers*)))
(defun make-token (sym? line col) (defun make-token (sym? line col)
(if (or (is-identifier sym?) (numberp sym?)) (if (or (is-identifier sym?) (numberp sym?))
@@ -13,8 +14,9 @@
(defun token-op (token) (defun token-op (token)
(car token)) (car token))
(defun lex-line (line-stream line-num) (defun lex-line (line &optional (line-num 0))
(iter (with col = 0) (iter (with line-stream = (make-string-input-stream line))
(with col = 0)
(with has-err = nil) (with has-err = nil)
(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))
@@ -49,7 +51,7 @@
(until (null line)) (until (null line))
(for line-num from 1) (for line-num from 1)
(multiple-value-bind (tokens has-err) (multiple-value-bind (tokens has-err)
(lex-line (make-string-input-stream line) line-num) (lex-line line line-num)
(when has-err (when has-err
(setf has-error t) (setf has-error t)
(when report-errors (when report-errors
@@ -77,6 +79,11 @@
(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)
(vector-push-extend
`(ise ,(position 'yap tokens :start i :key #'token-op))
ops))
;; currently does not handle nesting
(t (vector-push-extend (list op) ops)))) (t (vector-push-extend (list op) ops))))
(finally (return ops)))) (finally (return ops))))
@@ -88,23 +95,79 @@
(parse-tokens tokens))) (parse-tokens tokens)))
;; (defun *ops* '(push pop minus dump)) ;; (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)
(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)
(iter (for (op-id) in body)
(when (not (is-identifier op-id))
(error "op-case: ~a is not an identifier" op-id))
(collect op-id into defined-ops)
(finally (identifier-coverage defined-ops)))
(let ((case-sym (gensym)))
`(let ((,case-sym ,case-form))
(case ,case-sym
,@body
(otherwise (if (is-identifier (first ,case-sym))
(error "op: ~a -- Not implemented yet"
(first ,case-sym))
(error "op: ~a -- Does not exist"
(first ,case-sym))))))))
(defun interpret-program (program) (defun interpret-program (program)
(iter (with stack = (make-array 100 :fill-pointer 0 :adjustable t)) (iter (with stack = (make-array 100 :fill-pointer 0 :adjustable t))
(for op in-sequence program) ;; (for op in-sequence program)
(case (first op) (for i from 0 below (length program))
(push (vector-push-extend (second op) stack)) (let ((op (aref program i)))
(+ (vector-push-extend (+ (vector-pop stack) (op-case (first op)
(vector-pop stack)) (push (vector-push-extend (second op) stack))
stack)) (+ (vector-push-extend (+ (vector-pop stack)
(- (vector-push-extend (let ((top (vector-pop stack))) (vector-pop stack))
(- (vector-pop stack) top)) stack))
stack)) (- (vector-push-extend (let ((top (vector-pop stack)))
(|.| (print (vector-pop stack))) (- (vector-pop stack) top))
(= (vector-push-extend (= (vector-pop stack) stack))
(vector-pop stack)) (|.| (print (vector-pop stack)))
stack)) (= (vector-push-extend (if (= (vector-pop stack)
(otherwise (error "op: ~a -- Not implemented yet" (first op)))))) (vector-pop stack))
1 0)
stack))
(yap (next-iteration))
(ise (if (= (vector-pop stack) 1)
nil
(setf i (second op))))
( (let ((top (vector-pop stack)))
(vector-push-extend top stack)
(vector-push-extend top stack)))
(değiş (let* ((fst (vector-pop stack))
(snd (vector-pop stack)))
(vector-push-extend fst stack)
(vector-push-extend snd stack)))
(düş (vector-pop stack))
(üst (let* ((fst (vector-pop stack))
(snd (vector-pop stack)))
(vector-push-extend snd stack)
(vector-push-extend fst stack)
(vector-push-extend snd stack)))
(rot (let* ((fst (vector-pop stack))
(snd (vector-pop stack))
(trd (vector-pop stack)))
(vector-push-extend snd stack)
(vector-push-extend fst stack)
(vector-push-extend trd stack)))))))
;; swap, değiş
;; dup, eş
;; over, üst
;; rot, rot
;; drop, düşür
(defun gen-header (op str) (defun gen-header (op str)
(format str " ;; -- ~s --~%" op)) (format str " ;; -- ~s --~%" op))