Add CL implementations of certain programs

master
yw05 2021-04-16 08:36:33 +02:00
parent b7725e22ab
commit f18025f359
6 changed files with 181 additions and 3 deletions

View File

@ -1,2 +1,3 @@
((nil . ((indent-tabs-mode . t)
(tab-width . 8))))
((nil . ((c-basic-offset . 8)
(indent-tabs-mode . t)
(tab-width . 8))))

2
.gitignore vendored
View File

@ -1,2 +1,4 @@
bin/*
*/*.o
*/*.fasl
*/*~

18
Ackermann/Ackermann.lisp Normal file
View File

@ -0,0 +1,18 @@
;;;; This is a Common Lisp implementation of the Ackermann function
(declaim (ftype (function (fixnum integer) integer) Ackermann))
(defun Ackermann (m n)
(declare (type fixnum m) (type integer n))
(case m
((0) (1+ n))
((1) (+ 2 n))
((2) (+ n n 3))
((3) (+ (expt 2 (+ 3 n)) -3))
(t (let ((ir 1) (m-1 (- m 1)))
(dotimes (i (1+ n) ir)
(setf ir (Ackermann m-1 ir)))))))
(defmacro Ackermann-test (m n)
(let ((i (gensym)) (j (gensym)))
`(dotimes (,i ,m nil) (dotimes (,j ,n) (format t "A(~d,~d)=~d~%" ,i ,j (Ackermann ,i ,j))))))

157
bf/bf2cl.lisp Normal file
View File

@ -0,0 +1,157 @@
;;;; This is a simple BF-Common Lisp transpiler
(defpackage :bf (:use :cl) (:export :tocl :tocl-string :tocl-file
:tofile :tofile-string :tofile-file))
(in-package :bf)
(defgeneric token-tocl (token &key list pointer input output &allow-other-keys))
(defstruct (operation)
(optype nil :type (or null symbol)))
(defstruct (address)
(absolute nil :type boolean)
(offset 0 :type number))
(defmethod token-tocl ((token address) &key list pointer &allow-other-keys)
(copy-list (if (address-absolute token)
`(aref ,list ,(mod (address-offset token) 65536))
(if (eql 0 (address-offset token))
`(aref ,list ,pointer)
`(aref ,list (mod (+ ,pointer ,(address-offset token)) 65536))))))
(defstruct (op-inc
(:include operation (optype 'inc :type symbol :read-only t)))
(position (make-address :absolute nil :offset 0) :type address)
(delta 0 :type fixnum))
(defmethod token-tocl ((token op-inc) &key list pointer &allow-other-keys)
(copy-list `(setf ,(token-tocl (op-inc-position token) :list list :pointer pointer)
(mod (+ ,(token-tocl (op-inc-position token) :list list :pointer pointer)
,(op-inc-delta token))
256))))
(defstruct (op-offset
(:include operation (optype 'offset :type symbol :read-only t)))
(delta 0 :type fixnum))
(defmethod token-tocl ((token op-offset) &key pointer &allow-other-keys)
(copy-list `(setf ,pointer (mod (+ ,pointer ,(op-offset-delta token)) 65536))))
(defstruct (op-read
(:include operation (optype 'read :type symbol :read-only t)))
(position (make-address :absolute nil :offset 0) :type address))
(defmethod token-tocl ((token op-read) &key list pointer input &allow-other-keys)
(copy-list `(setf ,(token-tocl (op-read-position token) :list list :pointer pointer)
(char-code (read-byte ,input nil #\Null)))))
(defstruct (op-write
(:include operation (optype 'write :type symbol :read-only t)))
(position (make-address :absolute nil :offset 0) :type address))
(defmethod token-tocl ((token op-write) &key list pointer output &allow-other-keys)
(copy-list `(write-char
(code-char ,(token-tocl (op-write-position token) :list list :pointer pointer))
,output)))
(defstruct (op-loop
(:include operation (optype 'loop :type symbol :read-only t)))
(position (make-address :absolute nil :offset 0) :type address)
(body nil :type list))
(defmethod token-tocl ((token op-loop) &key list pointer input output &allow-other-keys)
(copy-list `(do () ((eql 0 ,(token-tocl (op-loop-position token)
:list list
:pointer pointer
:input input
:output output)))
(progn . ,(transpile (op-loop-body token) list pointer input output t)))))
(defun tokenize-char (char &optional (stream *standard-input*) (recursive-p nil))
(case char
(#\+ (make-op-inc :delta 1))
(#\- (make-op-inc :delta -1))
(#\< (make-op-offset :delta -1))
(#\> (make-op-offset :delta 1))
(#\, (make-op-read))
(#\. (make-op-write))
(#\[ (make-op-loop :body (tokenize stream t)))
(#\] (if recursive-p t (error "unbalanced ]")))
(t nil)))
(defun tokenize (stream &optional (recursive-p nil))
(do* ((c t (read-char stream nil))
(v nil (tokenize-char c stream recursive-p))
(l nil (if (typep v 'operation) (cons v l) l)))
((or (null c) (eql t v)) l)))
(defmacro deref-pos (absolute-p offset)
(let ((a (gensym)) (o (gensym)))
`(copy (let ((,a ,absolute-p) (,o ,offset))
(cond
(,a (mod ,o 65536))
((eql 0 ,o) 'pos)
(t `(mod (+ pos ,,o) 65536)))))))
(defun let-wrapper (body list pointer input output)
(declare (ignore input output))
(copy-list `(let ((,list (make-array 65536 :element-type 'fixnum :initial-element 0
:adjustable nil))
(,pointer 0))
(declare (type fixnum ,pointer))
,@body)))
(defun transpile (elist list pointer input output &optional (recursive-p nil))
(let ((l (nreverse (cons nil (loop for i in elist collect (token-tocl i
:list list
:pointer pointer
:input input
:output output))))))
(if recursive-p l (let-wrapper l list pointer input output))))
(defun combine-tokens (elist)
(do* ((r elist (cdr r)) (i (car r) (car r))) ((null i) elist)
(typecase i
(op-inc (loop for j on (cdr r) for e = (car j)
while (and (typep e 'op-inc)
(equalp (op-inc-position e) (op-inc-position i)))
do (incf (op-inc-delta i) (op-inc-delta e))
finally (setf (cdr r) j)))
(op-offset (loop for j on (cdr r) for e = (car j)
while (typep e 'op-offset)
do (incf (op-offset-delta i) (op-offset-delta e))
finally (setf (cdr r) j)))
(op-loop (setf (op-loop-body i) (combine-tokens (op-loop-body i))))
(t i))))
(defmacro optimize-token-list (elist)
`(combine-tokens ,elist))
(defmacro toformlist (stream input output)
`(transpile (optimize-token-list (tokenize ,stream)) (gensym) (gensym) ,input ,output))
(defmacro tocl (stream)
`(compile nil `(lambda (&optional (is *standard-input*) (os *standard-output*))
(declare (ignorable is os) (optimize speed))
,(toformlist ,stream 'is 'os))))
(defmacro tocl-string (string)
(let ((str (gensym)))
`(with-input-from-string (,str ,string) (tocl ,str))))
(defmacro tocl-file (file)
(let ((str (gensym)))
`(with-open-file (,str ,file) (tocl ,str))))
(defmacro tofile (istream ostream)
(let ((is (gensym)))
`(let ((,is ,istream))
(prin1 (toformlist ,is '*standard-input* '*standard-output*) ,ostream))))
(defmacro tofile-string (string ostream)
(let ((str (gensym)))
`(with-input-from-string (,str ,string) (tofile ,str ,ostream))))
(defmacro tofile-file (file ostream)
(let ((str (gensym)))
`(with-open-file (,str ,file) (tofile ,str ,ostream))))

View File

@ -65,4 +65,4 @@ if (! @ARGV) {
foreach my $i (keys %defs) {
compile $i;
}
}
}