Оставшаяся часть описания машины проста. Так, арифметические операции в основном те же, и создаются они редактированием одного образца. Ниже показана операция add
:
add() /* add top two elems on stack */
{
Datum d1, d2;
d2 = pop();
d1 = pop();
d1.val += d2.val;
push(d1);
}
Другие процедуры также просты:
eval() /* evaluate variable on stack */
{
Datum d;
d = pop();
if (d.sym->type == UNDEF)
execerror("undefined variable", d.sym->name);
d.val = d.sym->u.val;
push(d);
}
assign() /* assign top value to next value */
{
Datum d1, d2;
d1 = pop();
d2 = pop();
if (d1.sym->type != VAR && d1.sym->type != UNDEF)
execerror("assignment to non-variable", d1.sym->name);
d1.sym->u.val = d2.val;
d1.sym->type = VAR;
push(d2);
}
print() /* pop top value from stack, print it */
{
Datum d;
d = pop();
printf("\t%.8g\n", d.val);
}
bltin() /* evaluate built-in on top of stack */
{
Datum d;
d = pop();
d.val = (*(double (*)())(*pc++))(d.val);
push(d);
}
Самый сложный момент здесь операция приведения в функции, которая требует, чтобы *pc
рассматривался как указатель на функцию, возвращающую double
, и эта функция выполняется с d.val
в качестве аргумента.
Диагностические сообщения от функций eval
и assign
никогда не появятся, если программа работает нормально. Мы оставили их на случай возникновения недоразумений из-за какой-нибудь ошибки программы. Потери за счет увеличения времени выполнения и размера кода даже не так важны, как обнаружение ошибки при внесении необдуманных изменений (что мы и наблюдали несколько раз).
Использование языка Си дает возможность работать с указателем на функцию, что позволяет писать компактные и эффективные программы.
Альтернативное решение состоит в том, чтобы сделать операторы константами и сгруппировать семантические функции в большой переключатель в функции execute
. Попытайтесь реализовать его в качестве упражнения.
make
По мере увеличения исходного текста программы hoc
возрастает необходимость механически отслеживать изменения и взаимозависимости. Неоценимую помощь здесь может оказать команда make
: она автоматизирует процесс, который иначе пришлось бы выполнять вручную (и иногда с ошибками) или создавать для этого специальный командный файл.
Мы сделаем еще две модификации в файле makefile
. Первая связана с тем, что хотя несколько файлов и зависят от констант, определенных в yacc программе файла y.tab.h
, нет нужды их перетранслировать, если не изменились сами константы, а изменение в тексте Си программы из файла hoc.y
не влияет на другие файлы. В новой версии makefile
файлы .o
зависят от нового файла x.tab.h
, который изменяется только при замене содержимого файла y.tab.h
. Вторая модификация основана на том, что правило для pr
(печать исходных файлов) зависит лишь от самих исходных файлов, а именно, печатаются только измененные файлы.
Первая модификация позволяет существенно экономить время в случае больших программ, когда грамматика постоянна, а семантические действия меняются (обычная ситуация). Второе изменение обеспечивает экономию бумаги.
Приведем makefile
для hoc4
:
YFLAGS = -d
OBJS = hoc.o code.o init.o math.o symbol.o
hoc4: $(OBJS)
cc $(OBJS) -lm -o hoc4
hoc.o code.o init.o symbol.o: hoc.h
code.o init.o symbol.o: x.tab.h
x.tab.h: y.tab.h
-cmp -s x.tab.h y.tab.h || cp y.tab.h x.tab.h
pr: hoc.y hoc.h code.c init.c math.c symbol.c
@pr $?
@touch pr
clean:
rm -f $(OBJS) [xy].tab.[ch]
Символ '-'
перед командой cmp
дает указание make
продолжать выполнение даже в случае неудачи cmp
; это позволяет не останавливать работу и при несуществующем файле x.tab.h
(флаг -s
предписывает команде cmp
не производить вывод, но установить код завершения). Комбинация $?
раскрывается как список элементов из правила с устаревшей версией. К сожалению, форма записи в makefile
слабо связана с обозначениями в интерпретаторе.
Проиллюстрируем изложенное выше на примере (в предположении, что все файлы последней версии):
$ touch hoc.y
Изменим время для файла hoc.y
$ make
Вильям Л Саймон , Вильям Саймон , Наталья Владимировна Макеева , Нора Робертс , Юрий Викторович Щербатых
Зарубежная компьютерная, околокомпьютерная литература / ОС и Сети, интернет / Короткие любовные романы / Психология / Прочая справочная литература / Образование и наука / Книги по IT / Словари и Энциклопедии