/* xllist - xlisp list builtin functions */ #ifdef AZTEC #include "a:stdio.h" #else #include #endif #include "xlisp.h" /* external variables */ extern struct node *xlstack; /* local variables */ static struct node *t; static struct node *a_subr; static struct node *a_list; static struct node *a_sym; static struct node *a_int; static struct node *a_str; static struct node *a_obj; static struct node *a_fptr; static struct node *a_kmap; /* xlist - builtin function list */ static 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 = xlevarg(&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); } /* cond - builtin function cond */ static struct node *cond(args) struct node *args; { struct node *oldstk,arg,list,*val; /* create a new stack frame */ oldstk = xlsave(&arg,&list,NULL); /* initialize */ arg.n_ptr = args; /* initialize the return value */ val = NULL; /* find a predicate that is true */ while (arg.n_ptr != NULL) { /* get the next conditional */ list.n_ptr = xlmatch(LIST,&arg.n_ptr); /* evaluate the predicate part */ if (xlevarg(&list.n_ptr) != NULL) { /* evaluate each expression */ while (list.n_ptr != NULL) val = xlevarg(&list.n_ptr); /* exit the loop */ break; } } /* restore the previous stack frame */ xlstack = oldstk; /* return the value */ return (val); } /* atom - is this an atom? */ static struct node *atom(args) struct node *args; { struct node *arg; /* get the argument */ if ((arg = xlevarg(&args)) == NULL || arg->n_type != LIST) return (t); else return (NULL); } /* null - is this null? */ static struct node *null(args) struct node *args; { /* get the argument */ if (xlevarg(&args) == NULL) return (t); else return (NULL); } /* type - return type of a thing */ static struct node *type(args) struct node *args; { struct node *arg; if (!(arg = xlevarg(&args))) return (NULL); switch (arg->n_type) { case SUBR: return (a_subr); case LIST: return (a_list); case SYM: return (a_sym); case INT: return (a_int); case STR: return (a_str); case OBJ: return (a_obj); case FPTR: return (a_fptr); case KMAP: return (a_kmap); default: xlfail("Bad node."); } } /* listp - is this a list? */ static struct node *listp(args) struct node *args; { /* get the argument */ if (xlistp(xlevarg(&args))) return (t); else return (NULL); } /* xlistp - internal listp function */ static int xlistp(arg) struct node *arg; { return (arg == NULL || arg->n_type == LIST); } /* eq - are these equal? */ static struct node *eq(args) struct node *args; { struct node *oldstk,arg,arg1,arg2,*val; /* create a new stack frame */ oldstk = xlsave(&arg,&arg1,&arg2,NULL); /* initialize */ arg.n_ptr = args; /* first argument */ arg1.n_ptr = xlevarg(&arg.n_ptr); /* second argument */ arg2.n_ptr = xlevarg(&arg.n_ptr); /* make sure there aren't any more arguments */ xllastarg(arg.n_ptr); /* compare the arguments */ if (xeq(arg1.n_ptr,arg2.n_ptr)) val = t; else val = NULL; /* restore the previous stack frame */ xlstack = oldstk; /* return the result */ return (val); } /* xeq - internal eq function */ static int xeq(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); } /* equal - are these equal? */ static struct node *equal(args) struct node *args; { struct node *oldstk,arg,arg1,arg2,*val; /* create a new stack frame */ oldstk = xlsave(&arg,&arg1,&arg2,NULL); /* initialize */ arg.n_ptr = args; /* first argument */ arg1.n_ptr = xlevarg(&arg.n_ptr); /* second argument */ arg2.n_ptr = xlevarg(&arg.n_ptr); /* make sure there aren't any more arguments */ xllastarg(arg.n_ptr); /* compare the arguments */ if (xequal(arg1.n_ptr,arg2.n_ptr)) val = t; else val = NULL; /* restore the previous stack frame */ xlstack = oldstk; /* return the result */ return (val); } /* xequal - internal equal function */ static int xequal(arg1,arg2) struct node *arg1,*arg2; { /* compare the arguments */ if (xeq(arg1,arg2)) return (TRUE); else if (xlistp(arg1) && xlistp(arg2)) return (xequal(arg1->n_listvalue,arg2->n_listvalue) && xequal(arg1->n_listnext, arg2->n_listnext)); else return (FALSE); } /* head - return the head of a list */ static struct node *head(args) struct node *args; { struct node *list; /* get the list */ if ((list = xlevmatch(LIST,&args)) == NULL) xlfail("null list"); /* make sure this is the only argument */ xllastarg(args); /* return the head of the list */ return (list->n_listvalue); } /* tail - return the tail of a list */ static struct node *tail(args) struct node *args; { struct node *list; /* get the list */ if ((list = xlevmatch(LIST,&args)) == NULL) xlfail("null list"); /* make sure this is the only argument */ xllastarg(args); /* return the tail of the list */ return (list->n_listnext); } /* nth - return the nth element of a list */ static struct node *nth(args) struct node *args; { struct node *oldstk,arg,list; int n; /* create a new stack frame */ oldstk = xlsave(&arg,&list,NULL); /* initialize */ arg.n_ptr = args; /* get n */ if ((n = xlevmatch(INT,&arg.n_ptr)->n_int) < 1) xlfail("invalid argument"); /* get the list */ if ((list.n_ptr = xlevmatch(LIST,&arg.n_ptr)) == NULL) xlfail("invalid argument"); /* make sure this is the only argument */ xllastarg(arg.n_ptr); /* find the nth element */ for (; n > 1; n--) { list.n_ptr = list.n_ptr->n_listnext; if (list.n_ptr == NULL || list.n_ptr->n_type != LIST) xlfail("invalid argument"); } /* restore the previous stack frame */ xlstack = oldstk; /* return the list nth list element */ return (list.n_ptr->n_listvalue); } /* length - return the length of a list */ static struct node *length(args) struct node *args; { struct node *oldstk,list,*val; int n; /* create a new stack frame */ oldstk = xlsave(&list,NULL); /* get the list */ list.n_ptr = xlevmatch(LIST,&args); /* make sure this is the only argument */ xllastarg(args); /* find the length */ for (n = 0; list.n_ptr != NULL; n++) list.n_ptr = list.n_ptr->n_listnext; /* restore the previous stack frame */ xlstack = oldstk; /* create the value node */ val = newnode(INT); val->n_int = n; /* return the length */ return (val); } /* append - builtin function append */ static struct node *append(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 = xlevmatch(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); } /* reverse - builtin function reverse */ static struct node *reverse(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 = xlevmatch(LIST,&args); /* make sure there aren't any more arguments */ 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); } /* cons - construct a new list cell */ static struct node *cons(args) struct node *args; { struct node *oldstk,arg,arg1,arg2,*lptr; /* create a new stack frame */ oldstk = xlsave(&arg,&arg1,&arg2,NULL); /* initialize */ arg.n_ptr = args; /* first argument */ arg1.n_ptr = xlevarg(&arg.n_ptr); /* second argument */ arg2.n_ptr = xlevarg(&arg.n_ptr); /* make sure there aren't any more arguments */ xllastarg(arg.n_ptr); /* construct a new list element */ lptr = newnode(LIST); lptr->n_listvalue = arg1.n_ptr; lptr->n_listnext = arg2.n_ptr; /* restore the previous stack frame */ xlstack = oldstk; /* return the list */ return (lptr); } /* xllinit - xlisp list initialization routine */ xllinit() { /* define some symbols */ t = xlenter("t"); a_subr = xlenter("SUBR"); a_list = xlenter("LIST"); a_sym = xlenter("SYM"); a_int = xlenter("INT"); a_str = xlenter("STR"); a_obj = xlenter("OBJ"); a_fptr = xlenter("FPTR"); a_kmap = xlenter("KMAP"); /* functions with reasonable names */ xlsubr("head",head); xlsubr("tail",tail); xlsubr("nth",nth); /* real lisp functions */ xlsubr("atom",atom); xlsubr("eq",eq); xlsubr("equal",equal); xlsubr("null",null); xlsubr("type",type); xlsubr("listp",listp); xlsubr("cond",cond); xlsubr("list",xlist); xlsubr("cons",cons); xlsubr("car",head); xlsubr("cdr",tail); xlsubr("append",append); xlsubr("reverse",reverse); xlsubr("length",length); }