diff options
Diffstat (limited to 'xlisp/xlbfun.c')
-rw-r--r-- | xlisp/xlbfun.c | 674 |
1 files changed, 674 insertions, 0 deletions
diff --git a/xlisp/xlbfun.c b/xlisp/xlbfun.c new file mode 100644 index 0000000..45e5a90 --- /dev/null +++ b/xlisp/xlbfun.c @@ -0,0 +1,674 @@ +/* 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" +#include "string.h" + +/* forward declarations */ +FORWARD LOCAL LVAL makesymbol(int iflag); + +/* xeval - the built-in function 'eval' */ +LVAL xeval(void) +{ + LVAL expr; + + /* get the expression to evaluate */ + expr = xlgetarg(); + xllastarg(); + + /* evaluate the expression */ + return (xleval(expr)); +} + +/* xapply - the built-in function 'apply' */ +LVAL xapply(void) +{ + 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(void) +{ + 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(void) +{ + LVAL form; + form = xlgetarg(); + xllastarg(); + return (xlexpandmacros(form)); +} + +/* x1macroexpand - expand a macro call */ +LVAL x1macroexpand(void) +{ + 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(void) +{ + LVAL arg; + arg = xlgetarg(); + xllastarg(); + return (atomp(arg) ? s_true : NIL); +} + +/* xsymbolp - is this an symbol? */ +LVAL xsymbolp(void) +{ + LVAL arg; + arg = xlgetarg(); + xllastarg(); + return (arg == NIL || symbolp(arg) ? s_true : NIL); +} + +/* xnumberp - is this a number? */ +LVAL xnumberp(void) +{ + LVAL arg; + arg = xlgetarg(); + xllastarg(); + return (fixp(arg) || floatp(arg) ? s_true : NIL); +} + +/* xintegerp - is this an integer? */ +LVAL xintegerp(void) +{ + LVAL arg; + arg = xlgetarg(); + xllastarg(); + return (fixp(arg) ? s_true : NIL); +} + +/* xfloatp - is this a float? */ +LVAL xfloatp(void) +{ + LVAL arg; + arg = xlgetarg(); + xllastarg(); + return (floatp(arg) ? s_true : NIL); +} + +/* xcharp - is this a character? */ +LVAL xcharp(void) +{ + LVAL arg; + arg = xlgetarg(); + xllastarg(); + return (charp(arg) ? s_true : NIL); +} + +/* xstringp - is this a string? */ +LVAL xstringp(void) +{ + LVAL arg; + arg = xlgetarg(); + xllastarg(); + return (stringp(arg) ? s_true : NIL); +} + +/* xarrayp - is this an array? */ +LVAL xarrayp(void) +{ + LVAL arg; + arg = xlgetarg(); + xllastarg(); + return (vectorp(arg) ? s_true : NIL); +} + +/* xstreamp - is this a stream? */ +LVAL xstreamp(void) +{ + LVAL arg; + arg = xlgetarg(); + xllastarg(); + return (streamp(arg) || ustreamp(arg) ? s_true : NIL); +} + +/* xobjectp - is this an object? */ +LVAL xobjectp(void) +{ + LVAL arg; + arg = xlgetarg(); + xllastarg(); + return (objectp(arg) ? s_true : NIL); +} + +/* xboundp - is this a value bound to this symbol? */ +LVAL xboundp(void) +{ + LVAL sym; + sym = xlgasymbol(); + xllastarg(); + return (boundp(sym) ? s_true : NIL); +} + +/* xfboundp - is this a functional value bound to this symbol? */ +LVAL xfboundp(void) +{ + LVAL sym; + sym = xlgasymbol(); + xllastarg(); + return (fboundp(sym) ? s_true : NIL); +} + +/* xnull - is this null? */ +LVAL xnull(void) +{ + LVAL arg; + arg = xlgetarg(); + xllastarg(); + return (null(arg) ? s_true : NIL); +} + +/* xlistp - is this a list? */ +LVAL xlistp(void) +{ + LVAL arg; + arg = xlgetarg(); + xllastarg(); + return (listp(arg) ? s_true : NIL); +} + +/* xendp - is this the end of a list? */ +LVAL xendp(void) +{ + LVAL arg; + arg = xlgalist(); + xllastarg(); + return (null(arg) ? s_true : NIL); +} + +/* xconsp - is this a cons? */ +LVAL xconsp(void) +{ + LVAL arg; + arg = xlgetarg(); + xllastarg(); + return (consp(arg) ? s_true : NIL); +} + +/* xeq - are these equal? */ +LVAL xeq(void) +{ + LVAL arg1,arg2; + + /* get the two arguments */ + arg1 = xlgetarg(); + arg2 = xlgetarg(); + xllastarg(); + + /* compare the arguments */ + return (arg1 == arg2 ? s_true : NIL); +} + +/* xeql - are these equal? */ +LVAL xeql(void) +{ + LVAL arg1,arg2; + + /* get the two arguments */ + arg1 = xlgetarg(); + arg2 = xlgetarg(); + xllastarg(); + + /* compare the arguments */ + return (eql(arg1,arg2) ? s_true : NIL); +} + +/* xequal - are these equal? (recursive) */ +LVAL xequal(void) +{ + LVAL arg1,arg2; + + /* get the two arguments */ + arg1 = xlgetarg(); + arg2 = xlgetarg(); + xllastarg(); + + /* compare the arguments */ + return (lval_equal(arg1,arg2) ? s_true : NIL); +} + +/* xset - built-in function set */ +LVAL xset(void) +{ + 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(void) +{ + 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, (char *) 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(void) +{ + return (makesymbol(FALSE)); +} + +/* xintern - make a new interned symbol */ +LVAL xintern(void) +{ + return (makesymbol(TRUE)); +} + +/* makesymbol - make a new symbol */ +LOCAL LVAL makesymbol(int iflag) +{ + LVAL pname; + + /* get the print name of the symbol to intern */ + pname = xlgastring(); + xllastarg(); + + /* make the symbol */ + return (iflag ? xlenter((char *) getstring(pname)) + : xlmakesym((char *) getstring(pname))); +} + +/* xsymname - get the print name of a symbol */ +LVAL xsymname(void) +{ + LVAL sym; + + /* get the symbol */ + sym = xlgasymbol(); + xllastarg(); + + /* return the print name */ + return (getpname(sym)); +} + +/* xsymvalue - get the value of a symbol */ +LVAL xsymvalue(void) +{ + 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(void) +{ + 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(void) +{ + LVAL sym; + + /* get the symbol */ + sym = xlgasymbol(); + xllastarg(); + + /* return the property list */ + return (getplist(sym)); +} + +/* xget - get the value of a property */ +LVAL xget(void) +{ + 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(void) +{ + 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(void) +{ + 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(void) +{ + 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); + str = NULL; + } + + /* return the hash index */ + return (cvfixnum((FIXTYPE)hash((char *) str, n))); +} + +/* xaref - array reference function */ +LVAL xaref(void) +{ + 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(void) +{ + 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(void) +{ + 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); +} + +/* allow xerror, xcleanup, xtoplevel, and xcontinue to return nothing */ +/* #pragma warning(disable: 4035)*/ + +/* xerror - special form 'error' */ +LVAL xerror(void) +{ + LVAL emsg,arg; + + /* get the error message and the argument */ + emsg = xlgastring(); + arg = (moreargs() ? xlgetarg() : s_unbound); + xllastarg(); + + /* signal the error */ + xlerror((char *) getstring(emsg),arg); + return NIL; /* won't ever happen */ +} + +/* xcerror - special form 'cerror' */ +LVAL xcerror(void) +{ + 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((char *) getstring(cmsg), (char *) getstring(emsg),arg); + + /* return nil */ + return (NIL); +} + +/* xbreak - special form 'break' */ +LVAL xbreak(void) +{ + LVAL emsg,arg; + + /* get the error message */ + emsg = (moreargs() ? xlgastring() : NIL); + arg = (moreargs() ? xlgetarg() : s_unbound); + xllastarg(); + + /* enter the break loop */ + xlbreak((emsg ? (char *) getstring(emsg) : "**BREAK**"),arg); + + /* return nil */ + return (NIL); +} + +/* xcleanup - special form 'clean-up' */ +LVAL xcleanup(void) +{ + xllastarg(); + xlcleanup(); +} + +/* xtoplevel - special form 'top-level' */ +LVAL xtoplevel(void) +{ + xllastarg(); + xltoplevel(); + /* this point will never be reached because xltoplevel() does a + longjmp(). The return is added to avoid false positive + error messages from static analyzers and compilers */ + return (NIL); +} + +/* xcontinue - special form 'continue' */ +LVAL xcontinue(void) +{ + xllastarg(); + xlcontinue(); + return (NIL); +} + +/* xevalhook - eval hook function */ +LVAL xevalhook(void) +{ + 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); +} + |