Читаем UNIX — универсальная среда программирования полностью

 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;

}


push(d)

 Datum d;

{

 if (stackp = stack[NSTACK])

  execerror("stack too deep", (char*)0);

 *stackp++ = d;

}


Datum pop {

 if (stackp == stack)

  execerror("stack underflow", (char*)0);

 return *--stackp;

}


constpush {

 Datum d;

 d.val = ((Symbol*)*pc++)-u.val;

 push(d);

}


varpush {

 Datum d;

 d.sym = (Symbol*)(*pc++);

 push(d);

}


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 */

}


ifcode {

 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 */

}


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 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;

}


ret /* common return from func or proc */

{

 int i;


 for (i = 0; i fp-nargs; i++)

  pop; /* pop arguments */

 pc = (Inst*)fp-retpc;

 --fp;

 returning = 1;

}


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");

 ret;

}


double *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;

}


bltin {

 Datum d;


 d = pop;

 d.val = (*(double(*))*pc++)(d.val);

 push(d);

}


eval /* evaluate variable on stack */

{

 Datum d;


 d = pop;

Перейти на страницу:
Нет соединения с сервером, попробуйте зайти чуть позже