pc = (Inst*)fp->retpc; --fp; returning = 1;}Некоторые программы интерпретатора нуждаются в небольших поправках для учета ситуаций, когда происходит возврат во вложенных операторах. Решение не элегантно, но верно и состоит во введении признака с именем
returningreturnifcodewhilecodeexecutereturningcallifcode() { Datum d; Inst *savepc = pc; /* then part */ execute(savepc+3); /* condition */ d = pop(); if (d.val) execute(*((Inst**)(savepc))); else if (*((Inst**)(savepc+1))) /* else part? */ execute(*((Inst**)(savepc+1))); if (!returning) pc = *((Inst**)(savepc+2)); /* next stmt */}whilecode() { Datum d; Inst *savepc = pc; execute(savepc+2); /* condition */ d = pop(); while (d.val) { execute(*((Inst**)(savepc))); /* body */ if (returning) break; execute(savepc+2); /* condition */ d = pop(); } if (!returning) pc = *((Inst**)(savepc+1)); /* next stmt */}execute(p) Inst *p;{ for (pc = p; *pc != STOP && !returning; ) (*((++pc)[-1]))();}Аргументы выбираются для получения значения или присваивания с помощью функции
getargdouble *getarg() /* return pointer to argument */{ int nargs = (int)*pc++; if (nargs > fp->nargs) execerror(fp->sp->name, "not enough arguments"); return &fp->argn[nargs - fp->nargs].val;}arg() /* push argument onto stack */{ Datum d; d.val = *getarg(); push(d);}argassign() /* store top of stack in argument */{ Datum d; d = pop(); push(d); /* leave value on stack */ *getarg() = d.val;}Функции
prstrprexprprstr() /* print string value */{ printf("%s", (char*)*pc++);}prexpr() /* print numeric value */{ Datum d; d = pop(); printf("%.8g d.val);}Функция
varreadvarread() /* read into variable */{ Datum d; extern FILE *fin; Symbol *var = (Symbol*)*pc++;Again: switch (fscanf(fin, "%lf", &var->u.val)) { case EOF: if (moreinput()) goto Again; d.val = var->u.val = 0.0; break; case 0: execerror("non-number read into", var->name); break; default: d.val = 1.0; break; } var->type = VAR; push(d);}Обнаружив конец файла для текущего входного потока, функция
varreadmoreinputmoreinputИтак, мы завершили разработку программы
hoc