/************************************************************************/
/* contents: evaluator and namestack maintenance routines */
/************************************************************************/
/* eval *****************************************************************/
/* returns the value of the pointer passed as the argument. */
register lispval a
= actarg
;
register struct nament
*namptr
;
register struct argent
*workp
;
register struct argent
*lbot
;
register struct argent
*np
;
struct nament
*oldbnp
= bnp
;
lispval
Ifcall(), Iarray();
handy
= errorh(Vermisc
,"Unbound Variable:",nil
,TRUE
,0,a
);
(np
++)->val
= a
; /* push form on namestack */
lbot
= np
; /* define beginning of argstack */
oldbnp
= bnp
; /* remember start of bind stack */
a
= a
->car
; /* function name or lambda-expr */
/* get function binding */
if(a
->fnbnd
==nil
&& a
->clb
!=nil
) {
a
= a
->l
; /* get value */
vtemp
= (CNIL
-1); /* sentinel value for error test */
/* decide whether lambda, nlambda or
macro and push args onto argstack
if(a
->discipline
==nlambda
) {
}else if(a
->discipline
==macro
) {
} else for(;argptr
!=nil
; argptr
= argptr
->cdr
) {
(np
++)->val
= eval(argptr
->car
);
if(TYPE(a
->discipline
)==INT
)
vtemp
= (*(lispval (*)())(a
->entry
))();
vtemp
= Iarray(a
,actarg
->cdr
);
/* push args on argstack according to
for(argptr
= actarg
->cdr
;
argptr
!=nil
; argptr
=argptr
->cdr
) {
(np
++)->val
= eval(argptr
->car
);
} else if (argptr
==nlambda
) {
(np
++)->val
= actarg
->cdr
;
} else if(argptr
==macro
) {
} else if(argptr
==lexpr
) {
for(argptr
= actarg
->cdr
;
argptr
!=nil
; argptr
=argptr
->cdr
) {
(np
++)->val
= eval(argptr
->car
);
handy
->car
= (lispval
)lbot
;
handy
->cdr
= (lispval
)np
;
PUSHDOWN(lexpr_atom
,handy
);
(np
++)->val
= inewint(((lispval
*)handy
->cdr
) - (lispval
*)handy
->car
);
} else break; /* something is wrong - this isn't a proper function */
if(bnp
+ (np
- lbot
)> bnplim
)
for(;argptr
!= (lispval
)nil
;
workp
++,argptr
= argptr
->cdr
) /* rebind formal names (shallow) */
/*if(((namptr)->atm = argptr->car)==nil)
error("Attempt to lambda bind nil",FALSE);*/
namptr
->atm
= argptr
->car
;
namptr
->val
= namptr
->atm
->clb
;
namptr
->atm
->clb
= workp
->val
;
error("Too few actual parameters",FALSE
);
error("Too many actual parameters",FALSE
);
/* execute body, implied prog allowed */
for (handy
= a
->cdr
->cdr
;
vtemp
= eval(handy
->car
);
/* if we get here with a believable value, */
/* we must have executed a function. */
/* in case some clown trashed t */
tatom
->clb
= (lispval
) tatom
;
if(a
->car
==macro
) return(eval(vtemp
));
/* It is of the most wonderful
coincidence that the offset
for car is the same as for
discipline so we get bcd macros
a
= (lispval
) errorh(Vermisc
,"BAD FUNCTION",nil
,TRUE
,0,actarg
);
return(a
); /* other data types are considered constants */
/* popnames *************************************************************/
/* removes from the name stack all entries above the first argument. */
/* routine should usually be used to clean up the name stack as it */
/* knows about the special cases. np is returned pointing to the */
/* same place as the argument passed. */
register struct nament
*llimit
;
register struct nament
*rnp
;
for(rnp
= bnp
- 1; rnp
>= llimit
; rnp
--)
rnp
->atm
->clb
= rnp
->val
;
/************************************************************************/
/* Caveat -- Work in Progress -- not guaranteed! not tested!
/* apply ***************************************************************/
register struct argent
*workp
;
register struct nament
*namptr
;
register struct argent
*lbot
;
register struct argent
*np
;
struct nament
*oldbnp
= bnp
;
struct argent
*oldlbot
= lbot
; /* Bottom of my frame! */
errorh(Vermisc
,"Apply: Wrong number of args.",nil
,FALSE
,
if(TYPE(argptr
)!=DTPR
&& argptr
!=nil
)
argptr
= errorh(Vermisc
,"Apply: non-list of args",nil
,TRUE
,
(np
++)->val
= a
; /* push form on namestack */
lbot
= np
; /* bottom of current frame */
if (TYPE(a
) == ATOM
) a
= a
->fnbnd
;
/* get function defn (unless calling form */
/* is itself a lambda-expr) */
vtemp
= CNIL
; /* sentinel value for error test */
case BCD
: /* printf("BCD\n");*/
/* push arguments - value of a */
if(a
->discipline
==nlambda
|| a
->discipline
==macro
) {
} else for (; argptr
!=nil
; argptr
= argptr
->cdr
) {
vtemp
= (*(lispval (*)())(a
->entry
))(); /* go for it */
vtemp
= Iarray(a
,argptr
);
if (a
->car
==nlambda
|| a
->car
==macro
) {
} else if (a
->car
==lambda
)
for (; argptr
!=nil
; argptr
= argptr
->cdr
) {
(np
++)->val
= argptr
->car
;
for (; argptr
!=nil
; argptr
= argptr
->cdr
) {
(np
++)->val
= argptr
->car
;
handy
->car
= (lispval
)lbot
;
handy
->cdr
= (lispval
)np
;
PUSHDOWN(lexpr_atom
,handy
);
(np
++)->val
= inewint(((lispval
*)handy
->cdr
) - (lispval
*)handy
->car
);
} else break; /* something is wrong - this isn't a proper function */
rebind(a
->cdr
->car
,lbot
);
for (handy
= a
->cdr
->cdr
;
vtemp
= eval(handy
->car
); /* go for it */
/* if we get here with a believable value, */
/* we must have executed a function. */
/* in case some clown trashed t */
tatom
->clb
= (lispval
) tatom
;
printr(oldlbot
->val
,stdout
);
a
= (lispval
) error("BAD FUNCTION",TRUE
);
* Rebind -- rebind formal names
register lispval argptr
; /* argptr points to list of atoms */
register struct argent
* workp
; /* workp points to position on stack
where evaluated args begin */
register struct nament
*namptr
= bnp
;
register struct argent
*lbot
;
register struct argent
*np
;
for(;argptr
!= (lispval
)nil
;
workp
++,argptr
= argptr
->cdr
) /* rebind formal names (shallow) */
namptr
->atm
= argptr
->car
;
namptr
->val
= namptr
->atm
->clb
;
namptr
->atm
->clb
= workp
->val
;
error("Too few actual parameters",FALSE
);
error("Too many actual parameters",FALSE
);
register struct argent
*oldlbot
;
register struct nament
**namptr
;
register struct argent
*lbot
;
register struct argent
*np
;
lispval
Ifcall(),Llist(),Iarray();
struct nament
*oldbnp
= bnp
;
printr(lbot->val,stdout);
oldlbot
= lbot
; /* bottom of my namestack frame */
a
= lbot
->val
; /* function I am evaling. */
if (typ
== ATOM
) a
= a
->fnbnd
, typ
= TYPE(a
);
/* get function defn (unless calling form */
/* is itself a lambda-expr) */
vtemp
= CNIL
; /* sentinel value for error test */
vtemp
= Iarray(a
,Llist());
if(a
->discipline
==nlambda
)
{ if(np
==lbot
) protect(nil
); /* default is nil */
while(np
-lbot
!=1 || (lbot
->val
!= nil
&&
TYPE(lbot
->val
)!=DTPR
)) {
lbot
->val
= error("Bad funcall arg(s) to fexpr.",TRUE
);
if(TYPE(a
->discipline
)==INT
)
vtemp
= (*(lispval (*)())(a
->entry
))();
} else if (a
->car
== nlambda
|| a
->car
==macro
) {
if( np
==lbot
) protect(nil
); /* default */
while(np
-lbot
!=1 || (lbot
->val
!= nil
&&
TYPE(lbot
->val
)!=DTPR
)) {
lbot
->val
= error("Bad funcall arg(s) to fexpr.",TRUE
);
} else if (a
->car
== lexpr
) {
handy
->car
= (lispval
) lbot
;
handy
->cdr
= (lispval
) np
;
PUSHDOWN(lexpr_atom
,handy
);
(np
++)->val
= inewint(((lispval
*)handy
->cdr
) - (lispval
*)handy
->car
);
} else break; /* something is wrong - this isn't a proper function */
rebind(a
->cdr
->car
,lbot
);
for (handy
= a
->cdr
->cdr
;
vtemp
= eval(handy
->car
); /* go for it */
/* if we get here with a believable value, */
/* we must have executed a function. */
/* in case some clown trashed t */
tatom
->clb
= (lispval
) tatom
;
if(a>(lispval) end){printf(" leaving:");
printr(oldlbot
->val
,stdout
);
a
= (lispval
) error("BAD FUNCTION",TRUE
);
/* protect **************************************************************/
/* pushes the first argument onto namestack, thereby protecting from gc */
asm(" movl 4(ap),(r6)+");
asm(" calls $0,_namerr");
/* unprot ****************************************************************/
/* returns the top thing on the name stack. Underflow had better not */
error("BYTE INTERPRETER CALLED ERRONEOUSLY",FALSE
);
/* Undeff - called from qfuncl when it detects a call to a undefined
function from compiled code, we print out a message and
printf("\n%s - ",atmn
->pname
);
error("Undefined function called from compiled code",FALSE
);
register lispval
*argp
= &firstarg
;
register struct nament
*mybnp
= bnp
;
mybnp
->val
= mybnp
->atm
->clb
;
mybnp
->atm
->clb
= *argp
++;