/************************************************************************* * * lispFrame.c -- * * This module contains routines that muck around with frames. * * (c) 1996 California Institute of Technology * Department of Computer Science * Pasadena, CA 91125. * * Permission to use, copy, modify, and distribute this software * and its documentation for any purpose and without fee is hereby * granted, provided that the above copyright notice appear in all * copies. The California Institute of Technology makes no representations * about the suitability of this software for any purpose. It is * provided "as is" without express or implied warranty. Export of this * software outside of the United States of America may require an * export license. * * $Header$ * *************************************************************************/ #include #include "lisp/lisp.h" #include "lispInt.h" #include "textio/textio.h" #include "utils/malloc.h" /*------------------------------------------------------------------------ * * A frame is a list of a list of dotted-pairs. * Each dotted-pair is a ( name . binding ). * *------------------------------------------------------------------------ */ Sexp *LispMainFrame = NULL; /* toplevel frame */ LispObj *LispMainFrameObj = NULL; /*----------------------------------------------------------------------------- * * LispFrameInit -- * * Initialize top-level frame. * * Results: * None. * * Side effects: * modifies LispMainFrame * *----------------------------------------------------------------------------- */ void LispFrameInit () { LispMainFrame = LispNewSexp (); CAR(LispMainFrame) = LispNewObj (); CDR(LispMainFrame) = LispNewObj (); LTYPE(CAR(LispMainFrame)) = S_LIST; LTYPE(CDR(LispMainFrame)) = S_LIST; LLIST(CAR(LispMainFrame)) = NULL; LLIST(CDR(LispMainFrame)) = NULL; LispGCAddSexp (LispMainFrame); } /* returns (name val) thing if exists, else null */ static Sexp * findbinding (name,f) char *name; Sexp *f; { Sexp *t, *t1; t = f; while (t) { t1 = LLIST(CAR(t)); while (t1) { if (LSYM(CAR(LLIST(CAR(t1)))) == name) return LLIST(CAR(t1)); t1 = LLIST(CDR(t1)); } t = LLIST(CDR(t)); } return NULL; } /* returns (name val) thing if exists, else null */ static Sexp * revfindbinding (l,f) LispObj *l; Sexp *f; { Sexp *t, *t1; t = f; while (t) { t1 = LLIST(CAR(t)); while (t1) { if (CDR(LLIST(CAR(t1))) == l) return LLIST(CAR(t1)); t1 = LLIST(CDR(t1)); } t = LLIST(CDR(t)); } return NULL; } /*------------------------------------------------------------------------ * * LispFrameLookup -- * * Lookup symbol in frame. The arguments must be canonicalized using * the LispNewString() function, since string comparisons are done * using pointer equality. * * Results: * Returns pointer to symbol if found, NULL otherwise. * * Side effects: * None. * *------------------------------------------------------------------------ */ LispObj * LispFrameLookup (s,f) char *s; Sexp *f; { Sexp *f1; f1 = findbinding (s,f); if (!f1) return NULL; else return CDR(f1); } /*------------------------------------------------------------------------ * * LispFrameRevLookup -- * * Lookup object in frame. This returns the symbol corresponding to * the object. Used for debugging purposes. * * Results: * Returns symbol if found, NULL otherwise. * * Side effects: * None. * *------------------------------------------------------------------------ */ char * LispFrameRevLookup (l,f) LispObj *l; Sexp *f; { Sexp *f1; f1 = revfindbinding (l,f); if (!f1) return NULL; else return LSYM(CAR(f1)); } /*------------------------------------------------------------------------ * * LispAddBinding -- * * Add a ( name . value ) binding to the frame. * * Results: * modifies the frame. * * Side effects: * None. * *------------------------------------------------------------------------ */ void LispAddBinding (name,val,f) LispObj *name; LispObj *val; Sexp *f; { Sexp *t; LispObj *l; if (LTYPE(name) != S_SYM) { TxPrintf ("LispAddBinding: invalid argument!\n"); return; } if (f) { t = LLIST(CAR(f)); while (t) { if (LSYM(name) == LSYM(CAR(LLIST(CAR(t))))) { CDR(LLIST(CAR(t))) = val; return; } t = LLIST(CDR(t)); } } t = LispNewSexp (); CAR(t) = name; CDR(t) = val; l = LispNewObj (); LTYPE(l) = S_LIST; LLIST(l) = t; t = LispNewSexp (); CAR(t) = l; CDR(t) = CAR(f); l = LispNewObj (); LTYPE(l) = S_LIST; LLIST(l) = t; CAR(f) = l; } /*------------------------------------------------------------------------ * * LispModifyBinding -- * * Modify a ( name . value ) binding from the frame. * * Results: * Returns 0 on failure, and non-zero on success. * * Side effects: * None. * *------------------------------------------------------------------------ */ int LispModifyBinding (name,val,f) LispObj *name; LispObj *val; Sexp *f; { Sexp *t; LispObj *l; if (LTYPE(name) != S_SYM) return 0; if (t = findbinding (LSYM(name),f)) { CDR(t) = val; return 1; } return 0; } /*----------------------------------------------------------------------------- * * LispFramePush -- * * Return a new frame which consists of the old frame augmented by * the empty list. * * Results: * None. * * Side effects: * None. * *----------------------------------------------------------------------------- */ Sexp * LispFramePush (f) Sexp *f; { Sexp *nf; nf = LispNewSexp (); CAR(nf) = LispNewObj (); CDR(nf) = LispNewObj (); LTYPE(CAR(nf)) = S_LIST; LLIST(CAR(nf)) = NULL; LTYPE(CDR(nf)) = S_LIST; LLIST(CDR(nf)) = f; return nf; }