Ремонт принтеров, сканнеров, факсов и остальной офисной техники


назад Оглавление вперед




[179]

рованная машина работает намного лучше скомпилированного кода, поскольку настроенный вручную код контроллера должен быть намного лучше, чем результаты работы нашего рудиментарного компилятора общего назначения.

b. Можете ли Вы предложить изменения в компиляторе, помогающие ему порождать код, который приблизится к показателям версии, построенной вручную?

Упражнение 5.46.

Проведите анализ, подобный анализу из упражнения 5.45, и определите эффективность компиляции для процедуры Фибоначчи с древовидной рекурсией

(define (fib n) (if (< n 2) n

(+ (fib (- n 1)) (fib (- n 2)))))

по сравнению с эффективностью работы специализированной машины Фибоначчи с рисунка 5.12. (Измерения интерпретируемой версии см. в упражнении 5.29.) Для процедуры Фибоначчи время растет в нелинейной зависимости от n; следовательно, отношение числа стековых операций не будет приближаться к независимому от n приделу.

Упражнение 5.47.

В этом разделе рассказывалось, как модифицировать вычислитель с явным управлением и позволить интерпретируемому коду вызывать скомпилированные процедуры. Покажите, как можно изменить компилятор и позволить скомпилированным процедурам вызывать не только элементарные и скомпилированные процедуры, но и интерпретируемые. При этом придется изменить compile-procedure-call так, чтобы обрабатывался случай составных (интерпретируемых) процедур. Проследите, чтобы обрабатывались все те же сочетания target и linkage, что и в compile-proc-appl. Для того, чтобы произвести собственно применение процедуры, код должен переходить на точку входа compound-apply вычислителя. На эту метку нельзя напрямую ссылаться из объектного кода (потому что ассемблер требует, чтобы все метки, на которые явно ссылается объектный код, в нем и определялись), так что придется добавить в машину-вычислитель специальный регистр compapp, в котором будет храниться эта точка входа, и команду для его инициализации:

(assign compapp (label compound-apply))

(branch (label external-entry)) ; переход, если установлен flag read-eval-print-loop

Чтобы проверить свой код, для начала определите процедуру f, которая вызывает процедуру g. С помощью compile-and-go скомпилируйте определение f и запустите вычислитель. Теперь, вводя код для интерпретации, определите g и попробуйте вызвать

f.

Упражнение 5.48.

Интерфейс compile-and-go, реализованный в этом разделе, неудобен, поскольку компилятор можно вызвать только один раз (при запуске машины-вычислителя). Дополните интерфейс между компилятором и интерпретатором, введя примитив compile-and-run, который можно будет вызывать из вычислителя с явным управлением так:

;;; Ввод EC-Eval: (compile-and-run (define (factorial n)

(if (= n 1)


1

(* (factorial (- n 1)) n)))) ;;; Значение EC-Eval: ok

;;; Ввод EC-Eval:

(factorial 5)

;;; Значение EC-Eval:

120

Упражнение 5.49.

В качестве альтернативы циклу ввод-выполнение-печать вычислителя с явным управлением, спроектируйте регистровую машину, которая работала бы в цикле ввод-компиляция-выполнение-печать. А именно, машина должна работать в цикле, при каждой итерации которого она считывает выражение, компилирует его, ассемблирует и исполняет получившийся код, и печатает результат. В нашей имитируемой среде это легко устроить, поскольку мы можем заставить compile и assemble работать как «операции регистровой машины».

Упражнение 5.50.

С помощью компилятора оттранслируйте метациклический интерпретатор из раздела 4.1 и запустите эту программу через имитатор регистровых машин. (Чтобы скомпилировать за раз более одного определения, можно упаковать определения в begin.) Получившийся интерпретатор будет работать очень медленно из-за многочисленных уровней интерпретации, однако заставить все детали работать - полезное упражнение.

Упражнение 5.51.

Разработайте рудиментарную реализацию Scheme на C (или на другом низкоуровневом языке по Вашему выбору), переведя на C вычислитель с явными управлением из раздела 5.4. Для того, чтобы запустить этот код, Вам потребуется предоставить также функции для выделения памяти и прочую поддержку времени выполнения.

Упражнение 5.52.

В качестве обратной задачи к упражнению 5.51, измените компилятор так, чтобы он компилировал процедуры Scheme в последовательности команд C. Скомпилируйте метацик-лический интерпретатор из раздела 4.1 и получите интерпретатор Scheme, написанный на C.


Литература

Abelson, Harold, Andrew Berlin, Jacob Katzenelson, William McAllister, Guiller-mo Rozas, Gerald Jay Sussman, and Jack Wisdom. 1992. The Supercomputer Toolkit: A general framework for special-purpose computing. International Journal of High-Speed Electronics 3(3):337-361.

Allen, John. 1978. Anatomy of Lisp. New York: McGraw-Hill.

ANSI X3.226-1994. American National Standard for Information Systems-Programming Language-Common Lisp.

Appel, Andrew W. 1987. Garbage collection can be faster than stack allocation. Information Processing Letters 25(4):275-279.

Backus, John. 1978. Can programming be liberated from the von Neumann style? Communications of the ACM 21(8):613-641.

Baker, Henry G., Jr. 1978. List processing in real time on a serial computer. Communications of the ACM 21(4):280-293.

Batali, John, Neil Mayle, Howard Shrobe, Gerald Jay Sussman, and Daniel Weise. 1982. The Scheme-81 architecture-System and chip. In Proceedings of the MIT Conference on Advanced Research in VLSI, edited by Paul Penfield, Jr. Dedham, MA: Artech House.

Borning, Alan. 1977. ThingLab-An object-oriented system for building simula-ti-ons using constraints. In Proceedings of the 5th International Joint Conference on Artificial Intelligence.

Borodin, Alan, and Ian Munro. 1975. The Computational Complexity of Algebraic and Numeric Problems. New York: American Elsevier.

Chaitin, Gregory J. 1975. Randomness and mathematical proof. Scientific American 232(5):47-52.

Church, Alonzo. 1941. The Calculi of Lambda-Conversion. Princeton, N.J.: Princeton University Press.

Clark, Keith L. 1978. Negation as failure. In Logic and Data Bases. New York:

Plenum Press, pp. 293-322.

Clinger, William. 1982. Nondeterministic call by need is neither lazy nor by name.



[стр.Начало] [стр.1] [стр.2] [стр.3] [стр.4] [стр.5] [стр.6] [стр.7] [стр.8] [стр.9] [стр.10] [стр.11] [стр.12] [стр.13] [стр.14] [стр.15] [стр.16] [стр.17] [стр.18] [стр.19] [стр.20] [стр.21] [стр.22] [стр.23] [стр.24] [стр.25] [стр.26] [стр.27] [стр.28] [стр.29] [стр.30] [стр.31] [стр.32] [стр.33] [стр.34] [стр.35] [стр.36] [стр.37] [стр.38] [стр.39] [стр.40] [стр.41] [стр.42] [стр.43] [стр.44] [стр.45] [стр.46] [стр.47] [стр.48] [стр.49] [стр.50] [стр.51] [стр.52] [стр.53] [стр.54] [стр.55] [стр.56] [стр.57] [стр.58] [стр.59] [стр.60] [стр.61] [стр.62] [стр.63] [стр.64] [стр.65] [стр.66] [стр.67] [стр.68] [стр.69] [стр.70] [стр.71] [стр.72] [стр.73] [стр.74] [стр.75] [стр.76] [стр.77] [стр.78] [стр.79] [стр.80] [стр.81] [стр.82] [стр.83] [стр.84] [стр.85] [стр.86] [стр.87] [стр.88] [стр.89] [стр.90] [стр.91] [стр.92] [стр.93] [стр.94] [стр.95] [стр.96] [стр.97] [стр.98] [стр.99] [стр.100] [стр.101] [стр.102] [стр.103] [стр.104] [стр.105] [стр.106] [стр.107] [стр.108] [стр.109] [стр.110] [стр.111] [стр.112] [стр.113] [стр.114] [стр.115] [стр.116] [стр.117] [стр.118] [стр.119] [стр.120] [стр.121] [стр.122] [стр.123] [стр.124] [стр.125] [стр.126] [стр.127] [стр.128] [стр.129] [стр.130] [стр.131] [стр.132] [стр.133] [стр.134] [стр.135] [стр.136] [стр.137] [стр.138] [стр.139] [стр.140] [стр.141] [стр.142] [стр.143] [стр.144] [стр.145] [стр.146] [стр.147] [стр.148] [стр.149] [стр.150] [стр.151] [стр.152] [стр.153] [стр.154] [стр.155] [стр.156] [стр.157] [стр.158] [стр.159] [стр.160] [стр.161] [стр.162] [стр.163] [стр.164] [стр.165] [стр.166] [стр.167] [стр.168] [стр.169] [стр.170] [стр.171] [стр.172] [стр.173] [стр.174] [стр.175] [стр.176] [стр.177] [стр.178] [стр.179] [стр.180] [стр.181] [стр.182] [стр.183] [стр.184] [стр.185] [стр.186] [стр.187] [стр.188] [стр.189] [стр.190] [стр.191] [стр.192] [стр.193] [стр.194] [стр.195] [стр.196]