(in-package "MESYSTEM") ; defuna (defun translate (arg) (cond ((cl:listp arg) (mapcar #'(lambda (z) (translate z)) arg)) ((cl:numberp arg) (cl-fixnum arg)) (t arg))) (defmacro defuna (&rest body) `(defun ,@(translate body))) (defmacro defparametera (&rest body) `(defparameter ,@(translate body))) ; neu zu definierende Kontrollstrukturen im Interpreter ; vergleichsfunktionen allgemein (defuna null (x) (eq x nil)) (defuna atom (x) (not (consp x))) ; logische funktionen (defuna not (x) (cond ((null x) t) (t nil))) ; die conses, lese und schreibfunktionen (defuna cons (x y) (let ((p (%allocate-space 8))) (set-word p 0 x) (set-word p 4 y) (setf p (tag-set p 1)) p)) (defuna car (x) (if (null x) nil (get-word x 0))) (defuna cdr (x) (if (null x) nil (get-word x 4))) (defuna set-car (x v) (set-word x 0 v)) (defuna set-cdr (x v) (set-word x 4 v)) ; die conses, testfunktionen (defparametera *cons-tag* 1) (defuna consp (x) (tag-eq x *cons-tag*)) (defuna listp (x) (or (null x) (consp x))) ; die strings, lesen und schreiben von zeichenpositionen (defparametera *string-head-tag* 2) (defparametera *string-tag* 2) (defuna make-string (n) (let ((len (%div (%align n 2) 4))) (let ((n-align (%align (%+ (%* len 4) 8) 3))) (let ((p (%allocate-space n-align))) (set-word p 0 (tag-set (addr-ior (p-shiftl n-align 2) 1) *string-head-tag*)) (set-word p 4 n) (do ((i 0 (%+ i 1))) ((%>= i n)) (set-char p i (code-char 0))) (setq p (tag-set p *string-tag*)) p)))) (defuna char (str i) (let ((byte-val (get-byte str (%+ i 8)))) (code-char byte-val))) (defuna set-char (str i c) (let ((byte-val (char-code c))) (set-byte str (%+ i 8) byte-val))) ; die strings, testfunktionen (defuna stringp (x) (and (tag-eq x *string-tag*) (let ((h (get-word x 0))) (and (addr-eqi (addr-and h 2) 0) (tag-eq h *string-head-tag*))))) ; die strings, vergleichsfunktionen (defuna length (s) (if (or (stringp s) (arrayp s)) (get-word s 4) -1)) (defuna string< (x y) ) (defuna string> (x y) ) (defuna string= (x y) ) (defuna string-cmp-code (x y) (let ((len-x (length x)) (len-y (length y)) (res-code 0)) (do ((i 0 (%+ i 1))) ((or (%>= i len-x) (%>= i len-y) (%/= res-code 0)) res-code) (let ((cc-1 (char-code (char x i))) (cc-2 (char-code (char y i)))) (if (%< cc-1 cc-2) (setq res-code -1) (if (%> cc-1 cc-2) (setq res-code +1))))) (if (%= res-code 0) (cond ((%< len-x len-y) -1) ((%= len-x len-y) 0) ((%> len-x len-y) +1)) res-code))) (defuna get-hash (str n) (let ((len (length str)) (res 2)) (do ((i 0 (%+ i 2))) ((%>= i (%- len 1)) (%rem res n)) (setq res (%rem (%+ res (%+ (char-code (char str i)) (%* (char-code (char str (%+ i 1))) 256))) n))))) ; die vectoren, lesen und schreiben von elementen (defparametera *array-head-tag* 1) (defparametera *array-tag* 2) (defparametera *array-lead* 12) (defuna make-vector (n) (let ((n-bytes (%align (%+ (%* 4 n) *array-lead*) 3))) (let ((p (%allocate-space n-bytes))) (set-word p 0 (tag-set (addr-ior (p-shiftl n-bytes 2) 1) *array-head-tag*)) (set-word p 4 n) (set-word p 8 0) (do ((i 0 (%+ i 1))) ((%>= i n)) (set-svref p i nil)) (setq p (tag-set p *array-tag*))))) (defuna svref (vect i) (get-word vect (%+ (%* i 4) *array-lead*))) (defuna set-svref (vect i val) (set-word vect (%+ (%* i 4) *array-lead*) val)) ; die vectoren, testfunktionen (defuna arrayp (x) (and (tag-eq x *array-tag*) (let ((h (get-word x 0))) (and (addr-eqi (addr-and h 2) 0) (tag-eq h *array-head-tag*))))) ; die chars (defparametera *char-mark* 0) (defparametera *char-tag* 3) (defuna char-code (c) (p-shiftr c 14)) (defuna code-char (x) (tag-set (p-shiftl x 14) *char-tag*)) (defuna characterp (x) (tag-eq x *char-tag*)) ; die atome (defparametera *symbol-head-addr* 3) (defparametera *symbol-head-tag* 2) (defparametera *symbol-tag* 2) (defuna make-symbol (str) (let ((p (%allocate-space 24))) (set-word p 0 (tag-set *symbol-head-addr* *symbol-head-tag*)) (set-word p 4 str) (set-word p 8 nil) (set-word p 12 nil) (set-word p 16 nil) (set-word p 20 nil) (tag-set p *symbol-tag*))) (defuna intern (str) (let ((hash-val (get-hash str *base-pkg-len*))) (let ((slot (svref *base-pkg* hash-val)) (p-old nil) (p-akt nil) (str-cmp-val -1) (test-str str)) (do ((akt-atom slot (cdr akt-atom))) ((or (null akt-atom) (%>= str-cmp-val 0))) (setq str-cmp-val (string-cmp-code str (symbol-name (car akt-atom)))) (setq p-old p-akt) (setq p-akt akt-atom)) (cond ((%= 0 str-cmp-val) (car p-akt)) ((%>= str-cmp-val 0) (let* ((new-sym (make-symbol str)) (new-holder (cons new-sym p-akt))) (set-symbol-package new-sym *base-pkg*) (if (null p-old) (let () (set-svref *base-pkg* hash-val new-holder)) (set-cdr p-old new-holder)) new-sym)) ((%< str-cmp-val 0) (let* ((new-sym (make-symbol str)) (new-holder (cons new-sym nil))) (set-symbol-package new-sym *base-pkg*) (if (null p-akt) (let () (set-svref *base-pkg* hash-val new-holder)) (set-cdr p-akt new-holder)) new-sym)))))) ; die atom attribute, lesen (defuna symbol-name (sym) (get-word sym 4)) (defuna symbol-value (sym) (get-word sym 8)) (defuna symbol-function (sym) (get-word sym 12)) (defuna symbol-plist (sym) (get-word sym 16)) (defuna symbol-package (sym) (get-word sym 20)) ; die atom attribute, schreiben (defuna set-symbol-value (sym val) (set-word sym 8 val)) (defuna set-symbol-function (sym val) (set-word sym 12 val)) (defuna set-symbol-plist (sym val) (set-word sym 16 val)) (defuna set-symbol-package (sym val) (set-word sym 20 val)) ; die atome, testfunktion ; symbol hat |10 als tag im zeiger und 1|00 im header (defuna symbolp (x) (and (tag-eq x *symbol-tag*) (let ((h (get-word x 0))) (and (addr-eqi (addr-and h 2) 2) (tag-eq h *symbol-head-tag*))))) ; die (fix)nums (defparametera *fixnum-tag* 0) (defuna numberp (x) (tag-eq x *fixnum-tag*)) (defuna %align (x i) (p-shiftl (p-align (p-shiftr x 2) i) 2)) ; die closures (defparametera *closure-head-addr* 3) (defparametera *closure-head-tag* 1) (defparametera *closure-tag* 2) (defparametera *closure-slots* 2) (defuna make-closure (templ vect) (let ((p (%allocate-space (%+ (%* *closure-slots* 4) 8)))) (set-word p 0 (tag-set *closure-head-addr* *closure-head-tag*)) (set-closure-ref p 0 templ) (set-closure-ref p 1 vect) (setq p (tag-set p *closure-tag*)) p)) (defuna closure-ref (cl i) (get-word cl (%+ 4 (%* i 4)))) (defuna set-closure-ref (cl i x) (set-word cl (%+ 4 (%* i 4)) x)) (defuna closurep (x) (and (tag-eq x *closure-tag*) (let ((h (get-word x 0))) (and (addr-eqi (addr-and h 2) 2) (tag-eq h *closure-head-tag*))))) ; die templates (defparametera *template-head-tag* 3) (defparametera *template-tag* 2) (defparametera *template-leader* 4) ; d und c sind anzahl von 32 bit worten (defuna make-template (d c) (let ((n-bytes (%align (%+ (%* (%+ d c) 4) (%* 4 *template-leader*)) 3))) (let ((p (%allocate-space n-bytes))) (set-word p 0 (tag-set (addr-ior (p-shiftl n-bytes 2) 1) *template-head-tag*)) (set-word p 4 (p-add p (%+ (%* *template-leader* 4) (%* d 4)))) (set-word p 8 d) (set-word p 12 c) (do ((i 0 (+ i 1))) ((%>= i d)) (set-templ-ref-d p i nil)) (do ((i 0 (+ i 1))) ((%>= i c)) (set-templ-ref-c p i 0 0)) (setq p (tag-set p *template-tag*)) p))) (defuna length-d (templ) (get-word templ 8)) (defuna templ-ref-d (templ i) (get-word templ (%+ (%* *template-leader* 4) (%* i 4)))) (defuna templ-ref-c (templ i) (let ((pc (get-word templ 4))) (get-word pc (%* i 4)))) (defuna set-templ-ref-d (templ i val) (set-word templ (%+ (%* *template-leader* 4) (%* i 4)) val)) (defuna set-templ-ref-c (templ i v-high v-low) (let ((pc (get-word templ 4))) (set-word pc (%* i 4) (p-constr v-high v-low)))) (defuna templatep (x) (and (tag-eq x *template-tag*) (let ((h (get-word x 0))) (and (addr-eqi (addr-and h 2) 0) (tag-eq h *template-head-tag*))))) ; allgemeiner heap allokator. ruft (später: inkrementellen) garbage collector auf (defuna %allocate-space (n) (let ((ret *alloc-pointer*)) (setf *alloc-pointer* (+ *alloc-pointer* (p-shiftr n 2))) ret)) ; system-erzeugung ; tests (defparametera *base-pkg-len* 53) (setf *base-pkg* (make-vector *base-pkg-len*)) ;(setf str (cl-string "juergen")) ; tests (setf *type-fun-l* '(consp listp symbolp numberp characterp stringp arrayp closurep templatep)) (defun show-types (x) (loop for f in *type-fun-l* do (format t "~S (~S) = ~S~%" f x (funcall (cl:symbol-function f) x)))) (setf *tst-l* (cl:list 1 #\a (cl:cons 2 3) 'utz (cl:make-array 5) "juergen" )) (intern (cl-string "read-error")) (intern (cl-string "next")) (intern (cl-string "same")) (intern (cl-string "peek")) (mapcar #'(lambda (z) (intern (cl-string z))) '("cond" "labels" "let" "setq" "progn" "do" "do-until" "funcall" "funarg" "car" "cdr" "cons" "eq" "defun" "+" "-" "*" "divrem" ">" "<" "=" ">=" "<=" "null" "atom"))