home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
CPM
/
LANGUAGS
/
XLISP
/
XLISP12.ARK
/
XLEVAL.C
< prev
next >
Wrap
Text File
|
1985-02-19
|
8KB
|
368 lines
/* xleval - xlisp evaluator */
#ifdef AZTEC
#include "stdio.h"
#include "setjmp.h"
#else
#include <stdio.h>
#include <setjmp.h>
#endif
#include "xlisp.h"
/* global variables */
struct node *xlstack;
/* trace stack */
static struct node *trace_stack[TDEPTH];
static int trace_pointer;
/* external variables */
extern jmp_buf *xljmpbuf;
extern struct node *xlenv;
extern struct node *s_lambda,*s_nlambda;
extern struct node *s_unbound;
extern struct node *s_stdout;
extern struct node *s_tracenable;
extern struct node *k_rest;
extern struct node *k_aux;
/* forward declarations */
FORWARD struct node *evform();
FORWARD struct node *evsym();
FORWARD struct node *evfun();
/* xleval - evaluate an xlisp expression */
struct node *xleval(expr)
struct node *expr;
{
/* evaluate null to itself */
if (expr == NULL)
return (NULL);
/* add trace entry */
tpush(expr);
/* check type of value */
switch (expr->n_type) {
case LIST:
expr = evform(expr);
break;
case SYM:
expr = evsym(expr);
break;
case INT:
case STR:
case SUBR:
case FSUBR:
break;
default:
xlfail("can't evaluate expression");
}
/* remove trace entry */
tpop();
/* return the value */
return (expr);
}
/* xlapply - apply a function to a list of arguments */
struct node *xlapply(fun,args)
struct node *fun,*args;
{
struct node *val;
/* check for a null function */
if (fun == NULL)
xlfail("null function");
/* evaluate the function */
switch (fun->n_type) {
case SUBR:
val = (*fun->n_subr)(args);
break;
case LIST:
if (fun->n_listvalue != s_lambda)
xlfail("bad function type");
val = evfun(fun,args);
break;
default:
xlfail("bad function");
}
/* return the result value */
return (val);
}
/* evform - evaluate a form */
LOCAL struct node *evform(nptr)
struct node *nptr;
{
struct node *oldstk,fun,args,*val,*type;
/* create a stack frame */
oldstk = xlsave(&fun,&args,NULL);
/* get the function and the argument list */
fun.n_ptr = nptr->n_listvalue;
args.n_ptr = nptr->n_listnext;
/* evaluate the first expression */
if ((fun.n_ptr = xleval(fun.n_ptr)) == NULL)
xlfail("null function");
/* evaluate the function */
switch (fun.n_ptr->n_type) {
case SUBR:
args.n_ptr = xlevlist(args.n_ptr);
case FSUBR:
val = (*fun.n_ptr->n_subr)(args.n_ptr);
break;
case LIST:
if ((type = fun.n_ptr->n_listvalue) == s_lambda)
args.n_ptr = xlevlist(args.n_ptr);
else if (type != s_nlambda)
xlfail("bad function type");
val = evfun(fun.n_ptr,args.n_ptr);
break;
case OBJ:
val = xlsend(fun.n_ptr,args.n_ptr);
break;
default:
xlfail("bad function");
}
/* restore the previous stack frame */
xlstack = oldstk;
/* return the result value */
return (val);
}
/* xlevlist - evaluate a list of arguments */
struct node *xlevlist(args)
struct node *args;
{
struct node *oldstk,src,dst,*new,*last,*val;
/* create a stack frame */
oldstk = xlsave(&src,&dst,NULL);
/* initialize */
src.n_ptr = args;
/* evaluate each argument */
for (val = NULL; src.n_ptr; src.n_ptr = src.n_ptr->n_listnext) {
/* check this entry */
if (src.n_ptr->n_type != LIST)
xlfail("bad argument list");
/* allocate a new list entry */
new = newnode(LIST);
if (val)
last->n_listnext = new;
else
val = dst.n_ptr = new;
new->n_listvalue = xleval(src.n_ptr->n_listvalue);
last = new;
}
/* restore the previous stack frame */
xlstack = oldstk;
/* return the new list */
return (val);
}
/* evsym - evaluate a symbol */
LOCAL struct node *evsym(sym)
struct node *sym;
{
struct node *p;
/* check for a current object */
if ((p = xlobsym(sym)) != NULL)
return (p->n_listvalue);
else if ((p = sym->n_symvalue) == s_unbound)
xlfail("unbound variable");
else
return (p);
}
/* evfun - evaluate a function */
LOCAL struct node *evfun(fun,args)
struct node *fun,*args;
{
struct node *oldenv,*oldstk,cptr,*fargs,*val;
/* create a stack frame */
oldstk = xlsave(&cptr,NULL);
/* skip the function type */
if ((fun = fun->n_listnext) == NULL)
xlfail("bad function definition");
/* get the formal argument list */
if ((fargs = fun->n_listvalue) != NULL && fargs->n_type != LIST)
xlfail("bad formal argument list");
/* bind the formal parameters */
oldenv = xlenv;
xlabind(fargs,args);
xlfixbindings(oldenv);
/* execute the code */
for (cptr.n_ptr = fun->n_listnext; cptr.n_ptr != NULL; )
val = xlevarg(&cptr.n_ptr);
/* restore the environment */
xlunbind(oldenv);
/* restore the previous stack frame */
xlstack = oldstk;
/* return the result value */
return (val);
}
/* xlabind - bind the arguments for a function */
xlabind(fargs,aargs)
struct node *fargs,*aargs;
{
struct node *oldstk,farg,aarg,*arg;
/* create a stack frame */
oldstk = xlsave(&farg,&aarg,NULL);
/* initialize the pointers */
farg.n_ptr = fargs;
aarg.n_ptr = aargs;
/* evaluate and bind each argument */
while (farg.n_ptr != NULL && aarg.n_ptr != NULL) {
/* check for a keyword */
if (iskeyword(arg = farg.n_ptr->n_listvalue))
break;
/* bind the formal variable to the argument value */
xlbind(arg,aarg.n_ptr->n_listvalue);
/* move the argument list pointers ahead */
farg.n_ptr = farg.n_ptr->n_listnext;
aarg.n_ptr = aarg.n_ptr->n_listnext;
}
/* check for the '&rest' keyword */
if (farg.n_ptr && farg.n_ptr->n_listvalue == k_rest) {
farg.n_ptr = farg.n_ptr->n_listnext;
if (farg.n_ptr && (arg = farg.n_ptr->n_listvalue) && !iskeyword(arg))
xlbind(arg,aarg.n_ptr);
else
xlfail("symbol missing after &rest");
farg.n_ptr = farg.n_ptr->n_listnext;
aarg.n_ptr = NULL;
}
/* check for the '&aux' keyword */
if (farg.n_ptr && farg.n_ptr->n_listvalue == k_aux)
while ((farg.n_ptr = farg.n_ptr->n_listnext) != NULL)
xlbind(farg.n_ptr->n_listvalue,NULL);
/* make sure the correct number of arguments were supplied */
if (farg.n_ptr != aarg.n_ptr)
xlfail("incorrect number of arguments to a function");
/* restore the previous stack frame */
xlstack = oldstk;
}
/* iskeyword - check to see if a symbol is a keyword */
LOCAL int iskeyword(sym)
struct node *sym;
{
return (sym == k_rest || sym == k_aux);
}
/* xlsave - save nodes on the stack */
struct node *xlsave(n)
struct node *n;
{
struct node **nptr,*oldstk;
/* save the old stack pointer */
oldstk = xlstack;
/* save each node */
for (nptr = &n; *nptr != NULL; nptr++) {
(*nptr)->n_type = LIST;
(*nptr)->n_listvalue = NULL;
(*nptr)->n_listnext = xlstack;
xlstack = *nptr;
}
/* return the old stack pointer */
return (oldstk);
}
/* xlfail - error handling routine */
xlfail(err)
char *err;
{
/* print the error message */
printf("error: %s\n",err);
/* flush the terminal input buffer */
xlflush();
/* unbind bound symbols */
xlunbind(NULL);
/* do the back trace */
if (s_tracenable->n_symvalue)
baktrace();
trace_pointer = -1;
/* restart */
longjmp(xljmpbuf,1);
}
/* tpush - add an entry to the trace stack */
LOCAL tpush(nptr)
struct node *nptr;
{
if (++trace_pointer < TDEPTH)
trace_stack[trace_pointer] = nptr;
}
/* tpop - pop an entry from the trace stack */
LOCAL tpop()
{
trace_pointer--;
}
/* baktrace - do a back trace */
LOCAL baktrace()
{
for (; trace_pointer >= 0; trace_pointer--)
if (trace_pointer < TDEPTH)
stdprint(trace_stack[trace_pointer]);
}
/* stdprint - print to standard output */
stdprint(expr)
struct node *expr;
{
xlprint(s_stdout->n_symvalue,expr,TRUE);
xlterpri(s_stdout->n_symvalue);
}
/* xleinit - initialize the evaluator */
xleinit()
{
/* initialize debugging stuff */
trace_pointer = -1;
}