Peter Siebel - Practical Common Lisp
Здесь есть возможность читать онлайн «Peter Siebel - Practical Common Lisp» весь текст электронной книги совершенно бесплатно (целиком полную версию без сокращений). В некоторых случаях можно слушать аудио, скачать через торрент в формате fb2 и присутствует краткое содержание. Год выпуска: 2005, ISBN: 2005, Издательство: Apress, Жанр: Программирование, на английском языке. Описание произведения, (предисловие) а так же отзывы посетителей доступны на портале библиотеки ЛибКат.
- Название:Practical Common Lisp
- Автор:
- Издательство:Apress
- Жанр:
- Год:2005
- ISBN:1-59059-239-5
- Рейтинг книги:4 / 5. Голосов: 1
-
Избранное:Добавить в избранное
- Отзывы:
-
Ваша оценка:
- 80
- 1
- 2
- 3
- 4
- 5
Practical Common Lisp: краткое содержание, описание и аннотация
Предлагаем к чтению аннотацию, описание, краткое содержание или предисловие (зависит от того, что написал сам автор книги «Practical Common Lisp»). Если вы не нашли необходимую информацию о книге — напишите в комментариях, мы постараемся отыскать её.
Practical Common Lisp — читать онлайн бесплатно полную книгу (весь текст) целиком
Ниже представлен текст книги, разбитый по страницам. Система сохранения места последней прочитанной страницы, позволяет с удобством читать онлайн бесплатно книгу «Practical Common Lisp», без необходимости каждый раз заново искать на чём Вы остановились. Поставьте закладку, и сможете в любой момент перейти на страницу, на которой закончили чтение.
Интервал:
Закладка:
You'll then implement methods on the generic functions in the backend interface that will store the sequence of actions in the vector. Each op is represented by a list consisting of a keyword naming the operation and the arguments passed to the function that generated the op. The function
sexp->opsimplements the first phase of the compiler, compiling a list of FOO forms by calling processon each form with an instance of html-compiler.
This vector of ops stored by the compiler is then passed to a function that optimizes it, merging consecutive
raw-stringops into a single op that emits the combined string in one go. The optimization function can also, optionally, strip out ops that are needed only for pretty printing, which is mostly important because it allows you to merge more raw-stringops.
Finally, the optimized ops vector is passed to a third function,
generate-code, that returns a list of Common Lisp expressions that will actually output the HTML. When *pretty*is true, generate-codegenerates code that uses the methods specialized on html-pretty-printerto output pretty HTML. When *pretty*is NIL , it generates code that writes directly to the stream *html-output*.
The macro
htmlactually generates a body that contains two expansions, one generated with *pretty*bound to T and one with *pretty*bound to NIL . Which expansion is used is determined by the runtime value of *pretty*. Thus, every function that contains a call to htmlwill contain code to generate both pretty and compact output.
The other significant difference between the compiler and the interpreter is that the compiler can embed Lisp forms in the code it generates. To take advantage of that, you need to modify the
processfunction so it calls the embed-codeand embed-valuefunctions when asked to process an expression that's not a FOO form. Since all self-evaluating objects are valid FOO forms, the only forms that won't be passed to process-sexp-htmlare lists that don't match the syntax for FOO cons forms and non-keyword symbols, the only atoms that aren't self-evaluating. You can assume that any non-FOO cons is code to be run inline and all symbols are variables whose value you should embed.
(defun process (processor form)
(cond
((sexp-html-p form) (process-sexp-html processor form))
((consp form) (embed-code processor form))
(t (embed-value processor form))))
Now let's look at the compiler code. First you should define two functions that slightly abstract the vector you'll use to save ops in the first two phases of compilation.
(defun make-op-buffer () (make-array 10 :adjustable t :fill-pointer 0))
(defun push-op (op ops-buffer) (vector-push-extend op ops-buffer))
Next you can define the
html-compilerclass and the methods specialized on it to implement the backend interface.
(defclass html-compiler ()
((ops :accessor ops :initform (make-op-buffer))))
(defmethod raw-string ((compiler html-compiler) string &optional newlines-p)
(push-op `(:raw-string ,string ,newlines-p) (ops compiler)))
(defmethod newline ((compiler html-compiler))
(push-op '(:newline) (ops compiler)))
(defmethod freshline ((compiler html-compiler))
(push-op '(:freshline) (ops compiler)))
(defmethod indent ((compiler html-compiler))
(push-op `(:indent) (ops compiler)))
(defmethod unindent ((compiler html-compiler))
(push-op `(:unindent) (ops compiler)))
(defmethod toggle-indenting ((compiler html-compiler))
(push-op `(:toggle-indenting) (ops compiler)))
(defmethod embed-value ((compiler html-compiler) value)
(push-op `(:embed-value ,value ,*escapes*) (ops compiler)))
(defmethod embed-code ((compiler html-compiler) code)
(push-op `(:embed-code ,code) (ops compiler)))
With those methods defined, you can implement the first phase of the compiler,
sexp->ops.
(defun sexp->ops (body)
(loop with compiler = (make-instance 'html-compiler)
for form in body do (process compiler form)
finally (return (ops compiler))))
During this phase you don't need to worry about the value of
*pretty*: just record all the functions called by process. Here's what sexp->opsmakes of a simple FOO form:
HTML> (sexp->ops '((:p "Foo")))
#((:FRESHLINE) (:RAW-STRING "
" NIL)
(:RAW-STRING "Foo" T) (:RAW-STRING "
" NIL) (:FRESHLINE))
The next phase,
optimize-static-output, takes a vector of ops and returns a new vector containing the optimized version. The algorithm is simple—for each :raw-stringop, it writes the string to a temporary string buffer. Thus, consecutive :raw-stringops will build up a single string containing the concatenation of the strings that need to be emitted. Whenever you encounter an op other than a :raw-stringop, you convert the built-up string into a sequence of alternating :raw-stringand :newlineops with the helper function compile-bufferand then add the next op. This function is also where you strip out the pretty printing ops if *pretty*is NIL .
(defun optimize-static-output (ops)
(let ((new-ops (make-op-buffer)))
(with-output-to-string (buf)
(flet ((add-op (op)
(compile-buffer buf new-ops)
(push-op op new-ops)))
(loop for op across ops do
(ecase (first op)
(:raw-string (write-sequence (second op) buf))
((:newline :embed-value :embed-code) (add-op op))
((:indent :unindent :freshline :toggle-indenting)
(when *pretty* (add-op op)))))
(compile-buffer buf new-ops)))
new-ops))
(defun compile-buffer (buf ops)
Интервал:
Закладка:
Похожие книги на «Practical Common Lisp»
Представляем Вашему вниманию похожие книги на «Practical Common Lisp» списком для выбора. Мы отобрали схожую по названию и смыслу литературу в надежде предоставить читателям больше вариантов отыскать новые, интересные, ещё непрочитанные произведения.
Обсуждение, отзывы о книге «Practical Common Lisp» и просто собственные мнения читателей. Оставьте ваши комментарии, напишите, что Вы думаете о произведении, его смысле или главных героях. Укажите что конкретно понравилось, а что нет, и почему Вы так считаете.