home *** CD-ROM | disk | FTP | other *** search
- /* xlbfun.c - xlisp basic built-in functions */
- /* Copyright (c) 1985, by David Michael Betz
- All Rights Reserved
- Permission is granted for unrestricted non-commercial use */
-
- #include "xlisp.h"
-
- /* external variables */
- extern LVAL xlenv,xlfenv,xldenv,true;
- extern LVAL s_evalhook,s_applyhook;
- extern LVAL s_car,s_cdr,s_nth,s_get,s_svalue,s_splist,s_aref;
- extern LVAL s_lambda,s_macro;
- extern LVAL s_comma,s_comat;
- extern LVAL s_unbound;
- extern char gsprefix[];
- extern int gsnumber;
-
- /* external routines */
- extern LVAL xlxeval();
-
- /* forward declarations */
- FORWARD LVAL bquote1();
- FORWARD LVAL defun();
- FORWARD LVAL makesymbol();
-
- /* xeval - the built-in function 'eval' */
- LVAL xeval()
- {
- LVAL expr;
-
- /* get the expression to evaluate */
- expr = xlgetarg();
- xllastarg();
-
- /* evaluate the expression */
- return (xleval(expr));
- }
-
- /* xapply - the built-in function 'apply' */
- LVAL xapply()
- {
- LVAL fun,arglist;
-
- /* get the function and argument list */
- fun = xlgetarg();
- arglist = xlgalist();
- xllastarg();
-
- /* apply the function to the arguments */
- return (xlapply(pushargs(fun,arglist)));
- }
-
- /* xfuncall - the built-in function 'funcall' */
- LVAL xfuncall()
- {
- LVAL *newfp;
- int argc;
-
- /* build a new argument stack frame */
- newfp = xlsp;
- pusharg(cvfixnum((FIXTYPE)(newfp - xlfp)));
- pusharg(xlgetarg());
- pusharg(NIL); /* will be argc */
-
- /* push each argument */
- for (argc = 0; moreargs(); ++argc)
- pusharg(nextarg());
-
- /* establish the new stack frame */
- newfp[2] = cvfixnum((FIXTYPE)argc);
- xlfp = newfp;
-
- /* apply the function to the arguments */
- return (xlapply(argc));
- }
-
- /* xmacroexpand - expand a macro call repeatedly */
- LVAL xmacroexpand()
- {
- LVAL form;
- form = xlgetarg();
- xllastarg();
- return (xlexpandmacros(form));
- }
-
- /* x1macroexpand - expand a macro call */
- LVAL x1macroexpand()
- {
- LVAL form,fun,args;
-
- /* protect some pointers */
- xlstkcheck(2);
- xlsave(fun);
- xlsave(args);
-
- /* get the form */
- form = xlgetarg();
- xllastarg();
-
- /* expand until the form isn't a macro call */
- if (consp(form)) {
- fun = car(form); /* get the macro name */
- args = cdr(form); /* get the arguments */
- if (symbolp(fun) && fboundp(fun)) {
- fun = xlgetfunction(fun); /* get the expansion function */
- macroexpand(fun,args,&form);
- }
- }
-
- /* restore the stack and return the expansion */
- xlpopn(2);
- return (form);
- }
-
- /* xatom - is this an atom? */
- LVAL xatom()
- {
- LVAL arg;
- arg = xlgetarg();
- xllastarg();
- return (atom(arg) ? true : NIL);
- }
-
- /* xsymbolp - is this an symbol? */
- LVAL xsymbolp()
- {
- LVAL arg;
- arg = xlgetarg();
- xllastarg();
- return (arg == NIL || symbolp(arg) ? true : NIL);
- }
-
- /* xnumberp - is this a number? */
- LVAL xnumberp()
- {
- LVAL arg;
- arg = xlgetarg();
- xllastarg();
- return (fixp(arg) || floatp(arg) ? true : NIL);
- }
-
- /* xintegerp - is this an integer? */
- LVAL xintegerp()
- {
- LVAL arg;
- arg = xlgetarg();
- xllastarg();
- return (fixp(arg) ? true : NIL);
- }
-
- /* xfloatp - is this a float? */
- LVAL xfloatp()
- {
- LVAL arg;
- arg = xlgetarg();
- xllastarg();
- return (floatp(arg) ? true : NIL);
- }
-
- /* xcharp - is this a character? */
- LVAL xcharp()
- {
- LVAL arg;
- arg = xlgetarg();
- xllastarg();
- return (charp(arg) ? true : NIL);
- }
-
- /* xstringp - is this a string? */
- LVAL xstringp()
- {
- LVAL arg;
- arg = xlgetarg();
- xllastarg();
- return (stringp(arg) ? true : NIL);
- }
-
- /* xarrayp - is this an array? */
- LVAL xarrayp()
- {
- LVAL arg;
- arg = xlgetarg();
- xllastarg();
- return (vectorp(arg) ? true : NIL);
- }
-
- /* xstreamp - is this a stream? */
- LVAL xstreamp()
- {
- LVAL arg;
- arg = xlgetarg();
- xllastarg();
- return (streamp(arg) || ustreamp(arg) ? true : NIL);
- }
-
- /* xobjectp - is this an object? */
- LVAL xobjectp()
- {
- LVAL arg;
- arg = xlgetarg();
- xllastarg();
- return (objectp(arg) ? true : NIL);
- }
-
- /* xboundp - is this a value bound to this symbol? */
- LVAL xboundp()
- {
- LVAL sym;
- sym = xlgasymbol();
- xllastarg();
- return (boundp(sym) ? true : NIL);
- }
-
- /* xfboundp - is this a functional value bound to this symbol? */
- LVAL xfboundp()
- {
- LVAL sym;
- sym = xlgasymbol();
- xllastarg();
- return (fboundp(sym) ? true : NIL);
- }
-
- /* xnull - is this null? */
- LVAL xnull()
- {
- LVAL arg;
- arg = xlgetarg();
- xllastarg();
- return (null(arg) ? true : NIL);
- }
-
- /* xlistp - is this a list? */
- LVAL xlistp()
- {
- LVAL arg;
- arg = xlgetarg();
- xllastarg();
- return (listp(arg) ? true : NIL);
- }
-
- /* xendp - is this the end of a list? */
- LVAL xendp()
- {
- LVAL arg;
- arg = xlgalist();
- xllastarg();
- return (null(arg) ? true : NIL);
- }
-
- /* xconsp - is this a cons? */
- LVAL xconsp()
- {
- LVAL arg;
- arg = xlgetarg();
- xllastarg();
- return (consp(arg) ? true : NIL);
- }
-
- /* xeq - are these equal? */
- LVAL xeq()
- {
- LVAL arg1,arg2;
-
- /* get the two arguments */
- arg1 = xlgetarg();
- arg2 = xlgetarg();
- xllastarg();
-
- /* compare the arguments */
- return (arg1 == arg2 ? true : NIL);
- }
-
- /* xeql - are these equal? */
- LVAL xeql()
- {
- LVAL arg1,arg2;
-
- /* get the two arguments */
- arg1 = xlgetarg();
- arg2 = xlgetarg();
- xllastarg();
-
- /* compare the arguments */
- return (eql(arg1,arg2) ? true : NIL);
- }
-
- /* xequal - are these equal? (recursive) */
- LVAL xequal()
- {
- LVAL arg1,arg2;
-
- /* get the two arguments */
- arg1 = xlgetarg();
- arg2 = xlgetarg();
- xllastarg();
-
- /* compare the arguments */
- return (equal(arg1,arg2) ? true : NIL);
- }
-
- /* xset - built-in function set */
- LVAL xset()
- {
- LVAL sym,val;
-
- /* get the symbol and new value */
- sym = xlgasymbol();
- val = xlgetarg();
- xllastarg();
-
- /* assign the symbol the value of argument 2 and the return value */
- setvalue(sym,val);
-
- /* return the result value */
- return (val);
- }
-
- /* xgensym - generate a symbol */
- LVAL xgensym()
- {
- char sym[STRMAX+11]; /* enough space for prefix and number */
- LVAL x;
-
- /* get the prefix or number */
- if (moreargs()) {
- x = xlgetarg();
- switch (ntype(x)) {
- case SYMBOL:
- x = getpname(x);
- case STRING:
- strncpy(gsprefix,getstring(x),STRMAX);
- gsprefix[STRMAX] = '\0';
- break;
- case FIXNUM:
- gsnumber = getfixnum(x);
- break;
- default:
- xlerror("bad argument type",x);
- }
- }
- xllastarg();
-
- /* create the pname of the new symbol */
- sprintf(sym,"%s%d",gsprefix,gsnumber++);
-
- /* make a symbol with this print name */
- return (xlmakesym(sym));
- }
-
- /* xmakesymbol - make a new uninterned symbol */
- LVAL xmakesymbol()
- {
- return (makesymbol(FALSE));
- }
-
- /* xintern - make a new interned symbol */
- LVAL xintern()
- {
- return (makesymbol(TRUE));
- }
-
- /* makesymbol - make a new symbol */
- LOCAL LVAL makesymbol(iflag)
- int iflag;
- {
- LVAL pname;
-
- /* get the print name of the symbol to intern */
- pname = xlgastring();
- xllastarg();
-
- /* make the symbol */
- return (iflag ? xlenter(getstring(pname))
- : xlmakesym(getstring(pname)));
- }
-
- /* xsymname - get the print name of a symbol */
- LVAL xsymname()
- {
- LVAL sym;
-
- /* get the symbol */
- sym = xlgasymbol();
- xllastarg();
-
- /* return the print name */
- return (getpname(sym));
- }
-
- /* xsymvalue - get the value of a symbol */
- LVAL xsymvalue()
- {
- LVAL sym,val;
-
- /* get the symbol */
- sym = xlgasymbol();
- xllastarg();
-
- /* get the global value */
- while ((val = getvalue(sym)) == s_unbound)
- xlunbound(sym);
-
- /* return its value */
- return (val);
- }
-
- /* xsymfunction - get the functional value of a symbol */
- LVAL xsymfunction()
- {
- LVAL sym,val;
-
- /* get the symbol */
- sym = xlgasymbol();
- xllastarg();
-
- /* get the global value */
- while ((val = getfunction(sym)) == s_unbound)
- xlfunbound(sym);
-
- /* return its value */
- return (val);
- }
-
- /* xsymplist - get the property list of a symbol */
- LVAL xsymplist()
- {
- LVAL sym;
-
- /* get the symbol */
- sym = xlgasymbol();
- xllastarg();
-
- /* return the property list */
- return (getplist(sym));
- }
-
- /* xget - get the value of a property */
- LVAL xget()
- {
- LVAL sym,prp;
-
- /* get the symbol and property */
- sym = xlgasymbol();
- prp = xlgasymbol();
- xllastarg();
-
- /* retrieve the property value */
- return (xlgetprop(sym,prp));
- }
-
- /* xputprop - set the value of a property */
- LVAL xputprop()
- {
- LVAL sym,val,prp;
-
- /* get the symbol and property */
- sym = xlgasymbol();
- val = xlgetarg();
- prp = xlgasymbol();
- xllastarg();
-
- /* set the property value */
- xlputprop(sym,val,prp);
-
- /* return the value */
- return (val);
- }
-
- /* xremprop - remove a property value from a property list */
- LVAL xremprop()
- {
- LVAL sym,prp;
-
- /* get the symbol and property */
- sym = xlgasymbol();
- prp = xlgasymbol();
- xllastarg();
-
- /* remove the property */
- xlremprop(sym,prp);
-
- /* return nil */
- return (NIL);
- }
-
- /* xhash - compute the hash value of a string or symbol */
- LVAL xhash()
- {
- unsigned char *str;
- LVAL len,val;
- int n;
-
- /* get the string and the table length */
- val = xlgetarg();
- len = xlgafixnum(); n = (int)getfixnum(len);
- xllastarg();
-
- /* get the string */
- if (symbolp(val))
- str = getstring(getpname(val));
- else if (stringp(val))
- str = getstring(val);
- else
- xlerror("bad argument type",val);
-
- /* return the hash index */
- return (cvfixnum((FIXTYPE)hash(str,n)));
- }
-
- /* xaref - array reference function */
- LVAL xaref()
- {
- LVAL array,index;
- int i;
-
- /* get the array and the index */
- array = xlgavector();
- index = xlgafixnum(); i = (int)getfixnum(index);
- xllastarg();
-
- /* range check the index */
- if (i < 0 || i >= getsize(array))
- xlerror("array index out of bounds",index);
-
- /* return the array element */
- return (getelement(array,i));
- }
-
- /* xmkarray - make a new array */
- LVAL xmkarray()
- {
- LVAL size;
- int n;
-
- /* get the size of the array */
- size = xlgafixnum() ; n = (int)getfixnum(size);
- xllastarg();
-
- /* create the array */
- return (newvector(n));
- }
-
- /* xvector - make a vector */
- LVAL xvector()
- {
- LVAL val;
- int i;
-
- /* make the vector */
- val = newvector(xlargc);
-
- /* store each argument */
- for (i = 0; moreargs(); ++i)
- setelement(val,i,nextarg());
- xllastarg();
-
- /* return the vector */
- return (val);
- }
-
- /* xerror - special form 'error' */
- LVAL xerror()
- {
- LVAL emsg,arg;
-
- /* get the error message and the argument */
- emsg = xlgastring();
- arg = (moreargs() ? xlgetarg() : s_unbound);
- xllastarg();
-
- /* signal the error */
- xlerror(getstring(emsg),arg);
- }
-
- /* xcerror - special form 'cerror' */
- LVAL xcerror()
- {
- LVAL cmsg,emsg,arg;
-
- /* get the correction message, the error message, and the argument */
- cmsg = xlgastring();
- emsg = xlgastring();
- arg = (moreargs() ? xlgetarg() : s_unbound);
- xllastarg();
-
- /* signal the error */
- xlcerror(getstring(cmsg),getstring(emsg),arg);
-
- /* return nil */
- return (NIL);
- }
-
- /* xbreak - special form 'break' */
- LVAL xbreak()
- {
- LVAL emsg,arg;
-
- /* get the error message */
- emsg = (moreargs() ? xlgastring() : NIL);
- arg = (moreargs() ? xlgetarg() : s_unbound);
- xllastarg();
-
- /* enter the break loop */
- xlbreak((emsg ? getstring(emsg) : (unsigned char *)"**BREAK**"),arg);
-
- /* return nil */
- return (NIL);
- }
-
- /* xcleanup - special form 'clean-up' */
- LVAL xcleanup()
- {
- xllastarg();
- xlcleanup();
- }
-
- /* xtoplevel - special form 'top-level' */
- LVAL xtoplevel()
- {
- xllastarg();
- xltoplevel();
- }
-
- /* xcontinue - special form 'continue' */
- LVAL xcontinue()
- {
- xllastarg();
- xlcontinue();
- }
-
- /* xevalhook - eval hook function */
- LVAL xevalhook()
- {
- LVAL expr,newehook,newahook,newenv,oldenv,oldfenv,olddenv,val;
-
- /* protect some pointers */
- xlstkcheck(3);
- xlsave(oldenv);
- xlsave(oldfenv);
- xlsave(newenv);
-
- /* get the expression, the new hook functions and the environment */
- expr = xlgetarg();
- newehook = xlgetarg();
- newahook = xlgetarg();
- newenv = (moreargs() ? xlgalist() : NIL);
- xllastarg();
-
- /* bind *evalhook* and *applyhook* to the hook functions */
- olddenv = xldenv;
- xldbind(s_evalhook,newehook);
- xldbind(s_applyhook,newahook);
-
- /* establish the environment for the hook function */
- if (newenv) {
- oldenv = xlenv;
- oldfenv = xlfenv;
- xlenv = car(newenv);
- xlfenv = cdr(newenv);
- }
-
- /* evaluate the expression (bypassing *evalhook*) */
- val = xlxeval(expr);
-
- /* restore the old environment */
- xlunbind(olddenv);
- if (newenv) {
- xlenv = oldenv;
- xlfenv = oldfenv;
- }
-
- /* restore the stack */
- xlpopn(3);
-
- /* return the result */
- return (val);
- }
-
-