Вход/Регистрация
UNIX — универсальная среда программирования
вернуться

Керниган Брайан Уилсон

Шрифт:

Inst *progbase = prog; /* start of current subprogram */

int returning; /* 1 if return stmt seen */

typedef struct Frame { /* proc/func call stack frame */

 Symbol *sp; /* symbol table entry */

 Inst *retpc; /* where to resume after return */

 Datum *argn; /* n-th argument on stack */

 int nargs; /* number of arguments */

} Frame;

#define NFRAME 100 Frame frame[NFRAME];

Frame *fp; /* frame pointer */

initcode {

 progp = progbase;

 stackp = stack;

 fp = frame;

 returning = 0;

}

...

$

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

hoc.h
:

$ cat hoc.h

typedef struct Symbol { /* symbol table entry */

 char *name;

 short type;

 union {

double val; /* VAR */

double (*ptr); /* BLTIN */

int (*defn); /* FUNCTION, PROCEDURE */

char *str; /* STRING */

 } u;

 struct Symbol *next; /* to link to another */

} Symbol;

$

В процессе трансляции функция

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

define(sp) /* put func/proc in symbol table */

 Symbol *sp;

{

 sp->u.defn = (Inst)progbase; /* start of code */

 progbase = progp; /* next code starts here */

}

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

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

call /* call a function */

{

 Symbol *sp = (Symbol*)pc[0]; /* symbol table entry */

 /* for function */

 if (fp++ >= &frame[NFRAME-1])

execerror(sp->name, "call nested too deeply");

 fp->sp = sp;

 fp->nargs = (int)pc[1];

 fp->retpc = pc + 2;

 fp->argn = stackp - 1; /* last argument */

 execute(sp->u.defn);

 returning = 0;

}

Создаваемая структура показана на рис. 8.2.

Рис. 8.2: Структуры данных для вызова процедуры

В конце концов произойдет возврат из вызываемой программы при выполнении

procret
или
funcret
:

funcret /* return from a function */

{

 Datum d;

 if (fp->sp->type == PROCEDURE)

execerror(fp->sp->name, "(proc) returns value");

 d = pop; /* preserve function return value */

 ret;

 push(d);

}

procret /* return from a procedure */

{

 if (fp->sp->type == FUNCTION)

execerror(fp->sp->name(func) returns no value");

  • Читать дальше
  • 1
  • ...
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: