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
/
XLLIST.C
< prev
next >
Wrap
Text File
|
1985-02-19
|
19KB
|
809 lines
/* xllist - xlisp list builtin functions */
#ifdef AZTEC
#include "stdio.h"
#else
#include <stdio.h>
#endif
#include "xlisp.h"
/* external variables */
extern struct node *xlstack;
extern struct node *s_unbound;
extern struct node *true;
/* forward declarations */
FORWARD struct node *nth(),*member(),*assoc(),*afind();
FORWARD struct node *delete(),*subst(),*sublis(),*map();
FORWARD int eq(),equal();
/* xcar - return the car of a list */
struct node *xcar(args)
struct node *args;
{
struct node *list;
/* get the list and return its car */
list = xlmatch(LIST,&args);
xllastarg(args);
return (list ? list->n_listvalue : NULL);
}
/* xcaar - return the caar of a list */
struct node *xcaar(args)
struct node *args;
{
struct node *list;
/* get the list and return its caar */
list = xlmatch(LIST,&args);
xllastarg(args);
if (list) list = list->n_listvalue;
return (list ? list->n_listvalue : NULL);
}
/* xcadr - return the cadr of a list */
struct node *xcadr(args)
struct node *args;
{
struct node *list;
/* get the list and return its cadr */
list = xlmatch(LIST,&args);
xllastarg(args);
if (list) list = list->n_listnext;
return (list ? list->n_listvalue : NULL);
}
/* xcdr - return the cdr of a list */
struct node *xcdr(args)
struct node *args;
{
struct node *list;
/* get the list and return its cdr */
list = xlmatch(LIST,&args);
xllastarg(args);
return (list ? list->n_listnext : NULL);
}
/* xcdar - return the cdar of a list */
struct node *xcdar(args)
struct node *args;
{
struct node *list;
/* get the list and return its cdar */
list = xlmatch(LIST,&args);
xllastarg(args);
if (list) list = list->n_listvalue;
return (list ? list->n_listnext : NULL);
}
/* xcddr - return the cddr of a list */
struct node *xcddr(args)
struct node *args;
{
struct node *list;
/* get the list and return its cddr */
list = xlmatch(LIST,&args);
xllastarg(args);
if (list) list = list->n_listnext;
return (list ? list->n_listnext : NULL);
}
/* xcons - construct a new list cell */
struct node *xcons(args)
struct node *args;
{
struct node *arg1,*arg2,*val;
/* get the two arguments */
arg1 = xlarg(&args);
arg2 = xlarg(&args);
xllastarg(args);
/* construct a new list element */
val = newnode(LIST);
val->n_listvalue = arg1;
val->n_listnext = arg2;
/* return the list */
return (val);
}
/* xlist - built a list of the arguments */
struct node *xlist(args)
struct node *args;
{
struct node *oldstk,arg,list,val,*last,*lptr;
/* create a new stack frame */
oldstk = xlsave(&arg,&list,&val,NULL);
/* initialize */
arg.n_ptr = args;
/* evaluate and append each argument */
for (last = NULL; arg.n_ptr != NULL; last = lptr) {
/* evaluate the next argument */
val.n_ptr = xlarg(&arg.n_ptr);
/* append this argument to the end of the list */
lptr = newnode(LIST);
if (last == NULL)
list.n_ptr = lptr;
else
last->n_listnext = lptr;
lptr->n_listvalue = val.n_ptr;
}
/* restore the previous stack frame */
xlstack = oldstk;
/* return the list */
return (list.n_ptr);
}
/* xappend - builtin function append */
struct node *xappend(args)
struct node *args;
{
struct node *oldstk,arg,list,last,val,*lptr;
/* create a new stack frame */
oldstk = xlsave(&arg,&list,&last,&val,NULL);
/* initialize */
arg.n_ptr = args;
/* evaluate and append each argument */
while (arg.n_ptr != NULL) {
/* evaluate the next argument */
list.n_ptr = xlmatch(LIST,&arg.n_ptr);
/* append each element of this list to the result list */
while (list.n_ptr != NULL && list.n_ptr->n_type == LIST) {
/* append this element */
lptr = newnode(LIST);
if (last.n_ptr == NULL)
val.n_ptr = lptr;
else
last.n_ptr->n_listnext = lptr;
lptr->n_listvalue = list.n_ptr->n_listvalue;
/* save the new last element */
last.n_ptr = lptr;
/* move to the next element */
list.n_ptr = list.n_ptr->n_listnext;
}
/* make sure the list ended in a nil */
if (list.n_ptr != NULL)
xlfail("bad list");
}
/* restore previous stack frame */
xlstack = oldstk;
/* return the list */
return (val.n_ptr);
}
/* xreverse - builtin function reverse */
struct node *xreverse(args)
struct node *args;
{
struct node *oldstk,list,val,*lptr;
/* create a new stack frame */
oldstk = xlsave(&list,&val,NULL);
/* get the list to reverse */
list.n_ptr = xlmatch(LIST,&args);
xllastarg(args);
/* append each element of this list to the result list */
while (list.n_ptr != NULL && list.n_ptr->n_type == LIST) {
/* append this element */
lptr = newnode(LIST);
lptr->n_listvalue = list.n_ptr->n_listvalue;
lptr->n_listnext = val.n_ptr;
val.n_ptr = lptr;
/* move to the next element */
list.n_ptr = list.n_ptr->n_listnext;
}
/* make sure the list ended in a nil */
if (list.n_ptr != NULL)
xlfail("bad list");
/* restore previous stack frame */
xlstack = oldstk;
/* return the list */
return (val.n_ptr);
}
/* xlast - return the last cons of a list */
struct node *xlast(args)
struct node *args;
{
struct node *list;
/* get the list */
list = xlmatch(LIST,&args);
xllastarg(args);
/* find the last cons */
while (list && list->n_type == LIST && list->n_listnext)
list = list->n_listnext;
/* make sure the list ended correctly */
if (list == NULL && list->n_type != LIST)
xlfail("bad list");
/* return the last element */
return (list);
}
/* xmember - builtin function 'member' */
struct node *xmember(args)
struct node *args;
{
return (member(args,equal));
}
/* xmemq - builtin function 'memq' */
struct node *xmemq(args)
struct node *args;
{
return (member(args,eq));
}
/* member - internal member function */
LOCAL struct node *member(args,fcn)
struct node *args; int (*fcn)();
{
struct node *x,*list;
/* get the expression to look for and the list */
x = xlarg(&args);
list = xlmatch(LIST,&args);
xllastarg(args);
/* look for the expression */
for (; list && list->n_type == LIST; list = list->n_listnext)
if ((*fcn)(x,list->n_listvalue))
return (list);
/* return failure indication */
return (NULL);
}
/* xassoc - builtin function 'assoc' */
struct node *xassoc(args)
struct node *args;
{
return (assoc(args,equal));
}
/* xassq - builtin function 'assq' */
struct node *xassq(args)
struct node *args;
{
return (assoc(args,eq));
}
/* assoc - internal assoc function */
LOCAL struct node *assoc(args,fcn)
struct node *args; int (*fcn)();
{
struct node *expr,*alist,*pair;
/* get the expression to look for and the association list */
expr = xlarg(&args);
alist = xlmatch(LIST,&args);
xllastarg(args);
/* look for the expression */
return (afind(expr,alist,fcn));
}
/* afind - find a pair in an association list */
LOCAL struct node *afind(expr,alist,fcn)
struct node *expr,*alist; int (*fcn)();
{
struct node *pair;
for (; alist && alist->n_type == LIST; alist = alist->n_listnext)
if ((pair = alist->n_listvalue) && pair->n_type == LIST)
if ((*fcn)(expr,pair->n_listvalue))
return (pair);
return (NULL);
}
/* xsubst - substitute one expression for another */
struct node *xsubst(args)
struct node *args;
{
struct node *oldstk,to,from,expr,*val;
/* create a new stack frame */
oldstk = xlsave(&to,&from,&expr,NULL);
/* get the to value, the from value and the expression */
to.n_ptr = xlarg(&args);
from.n_ptr = xlarg(&args);
expr.n_ptr = xlarg(&args);
xllastarg(args);
/* do the substitution */
val = subst(to.n_ptr,from.n_ptr,expr.n_ptr);
/* restore the previous stack frame */
xlstack = oldstk;
/* return the result */
return (val);
}
/* subst - substitute one expression for another */
LOCAL struct node *subst(to,from,expr)
struct node *to,*from,*expr;
{
struct node *oldstk,car,cdr,*val;
if (eq(expr,from))
val = to;
else if (expr == NULL || expr->n_type != LIST)
val = expr;
else {
oldstk = xlsave(&car,&cdr,NULL);
car.n_ptr = subst(to,from,expr->n_listvalue);
cdr.n_ptr = subst(to,from,expr->n_listnext);
val = newnode(LIST);
val->n_listvalue = car.n_ptr;
val->n_listnext = cdr.n_ptr;
xlstack = oldstk;
}
return (val);
}
/* xsublis - substitute using an association list */
struct node *xsublis(args)
struct node *args;
{
struct node *oldstk,alist,expr,*val;
/* create a new stack frame */
oldstk = xlsave(&alist,&expr,NULL);
/* get the assocation list and the expression */
alist.n_ptr = xlmatch(LIST,&args);
expr.n_ptr = xlarg(&args);
xllastarg(args);
/* do the substitution */
val = sublis(alist.n_ptr,expr.n_ptr);
/* restore the previous stack frame */
xlstack = oldstk;
/* return the result */
return (val);
}
/* sublis - substitute using an association list */
LOCAL struct node *sublis(alist,expr)
struct node *alist,*expr;
{
struct node *oldstk,car,cdr,*val;
if (val = afind(expr,alist,eq))
val = val->n_listnext;
else if (expr == NULL || expr->n_type != LIST)
val = expr;
else {
oldstk = xlsave(&car,&cdr,NULL);
car.n_ptr = sublis(alist,expr->n_listvalue);
cdr.n_ptr = sublis(alist,expr->n_listnext);
val = newnode(LIST);
val->n_listvalue = car.n_ptr;
val->n_listnext = cdr.n_ptr;
xlstack = oldstk;
}
return (val);
}
/* xnth - return the nth element of a list */
struct node *xnth(args)
struct node *args;
{
return (nth(args,FALSE));
}
/* xnthcdr - return the nth cdr of a list */
struct node *xnthcdr(args)
struct node *args;
{
return (nth(args,TRUE));
}
/* nth - internal nth function */
LOCAL struct node *nth(args,cdrflag)
struct node *args; int cdrflag;
{
struct node *list;
int n;
/* get n and the list */
if ((n = xlmatch(INT,&args)->n_int) < 0)
xlfail("invalid argument");
if ((list = xlmatch(LIST,&args)) == NULL)
xlfail("invalid argument");
xllastarg(args);
/* find the nth element */
for (; n > 0; n--) {
list = list->n_listnext;
if (list == NULL || list->n_type != LIST)
xlfail("invalid argument");
}
/* return the list beginning at the nth element */
return (cdrflag ? list : list->n_listvalue);
}
/* xlength - return the length of a list */
struct node *xlength(args)
struct node *args;
{
struct node *list,*val;
int n;
/* get the list */
list = xlmatch(LIST,&args);
xllastarg(args);
/* find the length */
for (n = 0; list != NULL; n++)
list = list->n_listnext;
/* create the value node */
val = newnode(INT);
val->n_int = n;
/* return the length */
return (val);
}
/* xmapcar - builtin function 'mapcar' */
struct node *xmapcar(args)
struct node *args;
{
return (map(args,TRUE));
}
/* xmaplist - builtin function 'maplist' */
struct node *xmaplist(args)
struct node *args;
{
return (map(args,FALSE));
}
/* map - internal mapping function */
LOCAL struct node *map(args,carflag)
struct node *args; int carflag;
{
struct node *oldstk,fcn,lists,arglist,val,*last,*p,*x,*y;
/* create a new stack frame */
oldstk = xlsave(&fcn,&lists,&arglist,&val,NULL);
/* get the function to apply */
fcn.n_ptr = xlarg(&args);
/* make sure there is at least one argument list */
if (args == NULL)
xlfail("too few arguments");
/* get the argument lists */
while (args) {
p = newnode(LIST);
p->n_listnext = lists.n_ptr;
lists.n_ptr = p;
p->n_listvalue = xlmatch(LIST,&args);
}
/* if the function is a symbol, get its value */
if (fcn.n_ptr && fcn.n_ptr->n_type == SYM)
fcn.n_ptr = xleval(fcn.n_ptr);
/* loop through each of the argument lists */
for (;;) {
/* build an argument list from the sublists */
arglist.n_ptr = NULL;
for (x = lists.n_ptr; x && (y = x->n_listvalue); x = x->n_listnext) {
p = newnode(LIST);
p->n_listnext = arglist.n_ptr;
arglist.n_ptr = p;
p->n_listvalue = (carflag ? y->n_listvalue : y);
x->n_listvalue = y->n_listnext;
}
/* quit if any of the lists were empty */
if (x) break;
/* apply the function to the arguments */
p = newnode(LIST);
if (val.n_ptr)
last->n_listnext = p;
else
val.n_ptr = p;
last = p;
p->n_listvalue = xlapply(fcn.n_ptr,arglist.n_ptr);
}
/* restore the previous stack frame */
xlstack = oldstk;
/* return the last test expression value */
return (val.n_ptr);
}
/* xrplca - replace the car of a list node */
struct node *xrplca(args)
struct node *args;
{
struct node *list,*newcar;
/* get the list and the new car */
if ((list = xlmatch(LIST,&args)) == NULL)
xlfail("null list");
newcar = xlarg(&args);
xllastarg(args);
/* replace the car */
list->n_listvalue = newcar;
/* return the list node that was modified */
return (list);
}
/* xrplcd - replace the cdr of a list node */
struct node *xrplcd(args)
struct node *args;
{
struct node *list,*newcdr;
/* get the list and the new cdr */
if ((list = xlmatch(LIST,&args)) == NULL)
xlfail("null list");
newcdr = xlarg(&args);
xllastarg(args);
/* replace the cdr */
list->n_listnext = newcdr;
/* return the list node that was modified */
return (list);
}
/* xnconc - destructively append lists */
struct node *xnconc(args)
struct node *args;
{
struct node *list,*last,*val;
/* concatenate each argument */
for (val = NULL; args; ) {
/* concatenate this list */
if (list = xlmatch(LIST,&args)) {
/* check for this being the first non-empty list */
if (val)
last->n_listnext = list;
else
val = list;
/* find the end of the list */
while (list && list->n_type == LIST && list->n_listnext)
list = list->n_listnext;
/* make sure the list ended correctly */
if (list == NULL || list->n_type != LIST)
xlfail("bad list");
/* save the new last element */
last = list;
}
}
/* return the list */
return (val);
}
/* xdelete - builtin function 'delete' */
struct node *xdelete(args)
struct node *args;
{
return (delete(args,equal));
}
/* xdelq - builtin function 'delq' */
struct node *xdelq(args)
struct node *args;
{
return (delete(args,eq));
}
/* delete - internal delete function */
LOCAL struct node *delete(args,fcn)
struct node *args; int (*fcn)();
{
struct node *x,*list,*last,*val;
/* get the expression to delete and the list */
x = xlarg(&args);
list = xlmatch(LIST,&args);
xllastarg(args);
/* delete leading matches */
while (list && list->n_type == LIST) {
if (!(*fcn)(x,list->n_listvalue))
break;
list = list->n_listnext;
}
val = last = list;
/* delete embedded matches */
if (list && list->n_type == LIST) {
/* skip the first non-matching element */
list = list->n_listnext;
/* look for embedded matches */
while (list && list->n_type == LIST) {
/* check to see if this element should be deleted */
if ((*fcn)(x,list->n_listvalue))
last->n_listnext = list->n_listnext;
else
last = list;
/* move to the next element */
list = list->n_listnext;
}
}
/* make sure the list ended in a nil */
if (list != NULL)
xlfail("bad list");
/* return the updated list */
return (val);
}
/* xatom - is this an atom? */
struct node *xatom(args)
struct node *args;
{
struct node *arg;
return ((arg = xlarg(&args)) == NULL || arg->n_type != LIST ? true : NULL);
}
/* xsymbolp - is this an symbol? */
struct node *xsymbolp(args)
struct node *args;
{
struct node *arg;
return ((arg = xlarg(&args)) && arg->n_type == SYM ? true : NULL);
}
/* xnumberp - is this an number? */
struct node *xnumberp(args)
struct node *args;
{
struct node *arg;
return ((arg = xlarg(&args)) && arg->n_type == INT ? true : NULL);
}
/* xboundp - is this a value bound to this symbol? */
struct node *xboundp(args)
struct node *args;
{
struct node *sym;
sym = xlmatch(SYM,&args);
return (sym->n_symvalue == s_unbound ? NULL : true);
}
/* xnull - is this null? */
struct node *xnull(args)
struct node *args;
{
return (xlarg(&args) == NULL ? true : NULL);
}
/* xlistp - is this a list? */
struct node *xlistp(args)
struct node *args;
{
struct node *arg;
return ((arg = xlarg(&args)) == NULL || arg->n_type == LIST ? true : NULL);
}
/* xconsp - is this a cons? */
struct node *xconsp(args)
struct node *args;
{
struct node *arg;
return ((arg = xlarg(&args)) != NULL && arg->n_type == LIST ? true : NULL);
}
/* xeq - are these equal? */
struct node *xeq(args)
struct node *args;
{
struct node *arg1,*arg2;
/* get the two arguments */
arg1 = xlarg(&args);
arg2 = xlarg(&args);
xllastarg(args);
/* compare the arguments */
return (eq(arg1,arg2) ? true : NULL);
}
/* eq - internal eq function */
LOCAL int eq(arg1,arg2)
struct node *arg1,*arg2;
{
/* compare the arguments */
if (arg1 != NULL && arg1->n_type == INT &&
arg2 != NULL && arg2->n_type == INT)
return (arg1->n_int == arg2->n_int);
else
return (arg1 == arg2);
}
/* xequal - are these equal? */
struct node *xequal(args)
struct node *args;
{
struct node *arg1,*arg2;
/* get the two arguments */
arg1 = xlarg(&args);
arg2 = xlarg(&args);
xllastarg(args);
/* compare the arguments */
return (equal(arg1,arg2) ? true : NULL);
}
/* equal - internal equal function */
LOCAL int equal(arg1,arg2)
struct node *arg1,*arg2;
{
/* compare the arguments */
if (eq(arg1,arg2))
return (TRUE);
else if (arg1 && arg1->n_type == LIST &&
arg2 && arg2->n_type == LIST)
return (equal(arg1->n_listvalue,arg2->n_listvalue) &&
equal(arg1->n_listnext, arg2->n_listnext));
else
return (FALSE);
}