Литмир - Электронная Библиотека
Содержание  
A
A

hoc1
59

hoc2
94

hoc3
248 (для версии с
lex
229)

hoc4
396

hoc5
574

hoc6
809

Конечно, эти значения были вычислены программным способом: $

sed '/$/d' `pick *.[chyl]` | wc -l

Безусловно, развитие языка может быть продолжено, и вам предоставляется такая возможность в приведенных ниже упражнениях.

Упражнение 8.18

Измените

hoc6
так, чтобы можно было использовать поименованные формальные параметры в подпрограммах вместо
$1
и т.д.

Упражнение 8.19

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

auto
, которое резервирует место в стеке для перечисленных переменных; не перечисленные переменные считаются глобальными. Кроме того, придется расширить таблицу имен так, чтобы поиск в ней осуществлялся вначале для локальных, а затем для глобальных переменных. Как это связано с поименованными аргументами?

Упражнение 8.20

Как бы вы ввели массивы в язык

hoc
? Как следует передавать их функциям и процедурам? Как возвращать их?

Упражнение 8.21

Обобщите работу со строками так, чтобы переменные могли хранить строки, а не только числа. Какие операции потребуются для этого? Самая трудная часть управление памятью добейтесь динамичного хранения строк: память должна освобождаться, когда строки перестают быть нужными. В качестве промежуточного шага добавьте более развитые форматы печати, например, обеспечьте возможность использования некоторых форм стандартной Си функции

printf
.

8.7 Оценка времени выполнения

Мы сравнивали

hoc
с другими программами-калькуляторами UNIX, чтобы приблизительно оценить, насколько хорошо он работает. К таблице, представленной ниже (табл. 8.1), можно, конечно, отнестись скептически, но она показывает "разумность" нашей реализации. Все приведенные в ней величины даны в секундах. Работа велась на PDP-11/70. Было выполнено два теста. Первый, вычисление функции Аккерманна
ack(3,3)
, — хороший тест для отработки механизма вызова функций. Здесь происходят 2432 вызова, причем некоторые из них достаточно глубоко вложены.

func ack() {

 if ($1 == 0) return ($2+1)

 if($2 == 0) return (ack($1 - 1, 1))

 return (ack($1 - 1, ack($1, $2 - 1)))

}

ack(3,3)

Второй тест — стократное вычисление чисел Фибоначчи со значениями, меньшими 1000. В этом случае выполнялись в основном арифметические операции с периодическим вызовом функций:

proc fib() {

 a = 0

 b = 1

 while (b < $1) {

  с = b

  b = a+b

  a = c

 }

}

i = 1

while (i < 100) {

 fib(1000)

 i = i + 1

}

Тест выполнялся на четырех языках:

hoc
,
bc(1)
,
bas
(древний диалект Бейсика, который существует только на PDP-11) и Си (использовался тип PDP-11 для всех переменных) .

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

time
.

Программа (3,3) 100*fib(1000)
hoc
5.5 5.0
bas
1.3 0.7
bc
39.7 14.9
c
<0.1 0.1

Таблица 8.1: Время работы на PDP-11/70 (в секундах)

Можно также приспособить Си программу для определения количества времени, используемого каждой функцией. Программу нужно перетранслировать в режиме профилирования, введя флаг

-p
в каждой единице трансляции Си и при режиме загрузки. Если изменить файл
makefile
для чтения:

hoc6: $(OBJS)

      сс $(CFLAGS) $(OBJS) -lm -о hoc6

чтобы команда

сс
задействовала переменную
CFLAGS
, а затем задать

$ make clean; make CFLAGS=-p

то результирующая программа будет выполняться с профилированием. После выполнения программы остается файл

mon.out
, который интерпретируется программой профилировщиком
prof
.

Для иллюстрации изложенного мы протестировали

hoc6
на приведенной выше программе Фибоначчи:

$ hoc6 &lt;fibtest      
Запуск теста

$ prof hoc6 | sed 15q
Анализ

name   %time cumsec #call ms/call

_pop    15.6 0.85   32182  0.03

_push   14.3 1.63   32182  0.02

mcount  11.3 2.25

csv     10.1 2.80

cret     8.8 3.28

_assign  8.2 3.73    5050  0.09

_eval    8.2 4.18    8218  0.05

_execute 6.0 4.51    3567  0.09

_varpush 5.9 4.83   13268  0.02

_lt      2.7 4.98    1783  0.08

122
{"b":"248117","o":1}