/************************************************************************* * * * YAP Prolog * * * * Yap Prolog was developed at NCCUP - Universidade do Porto * * * * Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 * * * ************************************************************************** * * * File: adtdefs.c * * Last rev: * * mods: * * comments: abstract machine definitions * * * *************************************************************************/ #ifdef SCCS static char SccsId[] = "%W% %G%"; #endif #define ADTDEFS_C #ifdef __SUNPRO_CC #define inline #endif #include "Yap.h" Prop STD_PROTO(PredPropByFunc,(Functor, SMALLUNSGN)); Prop STD_PROTO(PredPropByAtom,(Atom, SMALLUNSGN)); #include "Yatom.h" #include "Heap.h" #include "yapio.h" #include #if HAVE_STRING_H #include #endif /* this routine must be run at least having a read lock on ae */ static Prop GetFunctorProp(AtomEntry *ae, unsigned int arity) { /* look property list of atom a for kind */ FunctorEntry *pp; pp = RepFunctorProp(ae->PropsOfAE); while (!EndOfPAEntr(pp) && (!IsFunctorProperty(pp->KindOfPE) || pp->ArityOfFE != arity)) pp = RepFunctorProp(pp->NextOfPE); return (AbsFunctorProp(pp)); } /* vsc: We must guarantee that IsVarTerm(functor) returns true! */ static inline Functor InlinedUnlockedMkFunctor(AtomEntry *ae, unsigned int arity) { FunctorEntry *p; Prop p0; p0 = GetFunctorProp(ae, arity); if (p0 != NIL) { return ((Functor) RepProp(p0)); } p = (FunctorEntry *) AllocAtomSpace(sizeof(*p)); p->KindOfPE = FunctorProperty; p->NameOfFE = AbsAtom(ae); p->ArityOfFE = arity; p->PropsOfFE = NIL; p->NextOfPE = ae->PropsOfAE; INIT_RWLOCK(p->FRWLock); ae->PropsOfAE = AbsProp((PropEntry *) p); return ((Functor) p); } Functor UnlockedMkFunctor(AtomEntry *ae, unsigned int arity) { return(InlinedUnlockedMkFunctor(ae, arity)); } /* vsc: We must guarantee that IsVarTerm(functor) returns true! */ Functor MkFunctor(Atom ap, unsigned int arity) { AtomEntry *ae = RepAtom(ap); Functor f; WRITE_LOCK(ae->ARWLock); f = InlinedUnlockedMkFunctor(ae, arity); WRITE_UNLOCK(ae->ARWLock); return (f); } /* vsc: We must guarantee that IsVarTerm(functor) returns true! */ void MkFunctorWithAddress(Atom ap, unsigned int arity, FunctorEntry *p) { AtomEntry *ae = RepAtom(ap); WRITE_LOCK(ae->ARWLock); p->KindOfPE = FunctorProperty; p->NameOfFE = ap; p->ArityOfFE = arity; p->NextOfPE = RepAtom(ap)->PropsOfAE; ae->PropsOfAE = AbsProp((PropEntry *) p); WRITE_UNLOCK(ae->ARWLock); } inline static Atom SearchInInvisible(char *atom) { AtomEntry *chain; READ_LOCK(INVISIBLECHAIN.AERWLock); chain = RepAtom(INVISIBLECHAIN.Entry); while (!EndOfPAEntr(chain) && strcmp(chain->StrOfAE, atom) != 0) { chain = RepAtom(chain->NextOfAE); } READ_UNLOCK(INVISIBLECHAIN.AERWLock); if (EndOfPAEntr(chain)) return (NIL); else return(AbsAtom(chain)); } static inline Atom SearchAtom(unsigned char *p, Atom a) { AtomEntry *ae; /* search atom in chain */ while (a != NIL) { ae = RepAtom(a); if (strcmp(ae->StrOfAE, (const char *)p) == 0) { return(a); } a = ae->NextOfAE; } return(NIL); } Atom LookupAtom(char *atom) { /* lookup atom in atom table */ register CELL hash; register unsigned char *p; Atom a; AtomEntry *ae; /* compute hash */ p = (unsigned char *)atom; HashFunction(p, hash); WRITE_LOCK(HashChain[hash].AERWLock); a = HashChain[hash].Entry; /* search atom in chain */ a = SearchAtom((unsigned char *)atom, a); if (a != NIL) { WRITE_UNLOCK(HashChain[hash].AERWLock); return(a); } /* add new atom to start of chain */ ae = (AtomEntry *) AllocAtomSpace((sizeof *ae) + strlen(atom)); a = AbsAtom(ae); ae->NextOfAE = HashChain[hash].Entry; HashChain[hash].Entry = a; ae->PropsOfAE = NIL; if (ae->StrOfAE != atom) strcpy(ae->StrOfAE, atom); INIT_RWLOCK(ae->ARWLock); WRITE_UNLOCK(HashChain[hash].AERWLock); return (a); } Atom FullLookupAtom(char *atom) { /* lookup atom in atom table */ Atom t; if ((t = SearchInInvisible(atom)) != NIL) { return (t); } return(LookupAtom(atom)); } void LookupAtomWithAddress(char *atom, AtomEntry *ae) { /* lookup atom in atom table */ register CELL hash; register unsigned char *p; Atom a; /* compute hash */ p = (unsigned char *)atom; HashFunction(p, hash); /* ask for a WRITE lock because it is highly unlikely we shall find anything */ WRITE_LOCK(HashChain[hash].AERWLock); a = HashChain[hash].Entry; /* search atom in chain */ if (SearchAtom(p, a) != NIL) { Error(FATAL_ERROR,TermNil,"repeated initialisation for atom %s", ae); WRITE_UNLOCK(HashChain[hash].AERWLock); return; } /* add new atom to start of chain */ ae->NextOfAE = a; HashChain[hash].Entry = AbsAtom(ae); ae->PropsOfAE = NIL; strcpy(ae->StrOfAE, atom); INIT_RWLOCK(ae->ARWLock); WRITE_UNLOCK(HashChain[hash].AERWLock); } void ReleaseAtom(Atom atom) { /* Releases an atom from the hash chain */ register Int hash; register unsigned char *p; AtomEntry *inChain; AtomEntry *ap = RepAtom(atom); char *name = ap->StrOfAE; /* compute hash */ p = (unsigned char *)name; HashFunction(p, hash); WRITE_LOCK(HashChain[hash].AERWLock); if (HashChain[hash].Entry == atom) { HashChain[hash].Entry = ap->NextOfAE; WRITE_UNLOCK(HashChain[hash].AERWLock); return; } /* else */ inChain = RepAtom(HashChain[hash].Entry); while (inChain->NextOfAE != atom) inChain = RepAtom(inChain->NextOfAE); WRITE_LOCK(inChain->ARWLock); inChain->NextOfAE = ap->NextOfAE; WRITE_UNLOCK(inChain->ARWLock); WRITE_UNLOCK(HashChain[hash].AERWLock); } static Prop StaticGetAPropHavingLock(AtomEntry *ae, PropFlags kind) { /* look property list of atom a for kind */ PropEntry *pp; pp = RepProp(ae->PropsOfAE); while (!EndOfPAEntr(pp) && pp->KindOfPE != kind) pp = RepProp(pp->NextOfPE); return (AbsProp(pp)); } Prop GetAPropHavingLock(AtomEntry *ae, PropFlags kind) { /* look property list of atom a for kind */ return (StaticGetAPropHavingLock(ae,kind)); } Prop GetAProp(Atom a, PropFlags kind) { /* look property list of atom a for kind */ AtomEntry *ae = RepAtom(a); Prop out; READ_LOCK(ae->ARWLock); out = StaticGetAPropHavingLock(ae, kind); READ_UNLOCK(ae->ARWLock); return (out); } inline static Prop GetPredPropByAtomHavingLock(AtomEntry* ae, SMALLUNSGN cur_mod) /* get predicate entry for ap/arity; create it if neccessary. */ { Prop p0; p0 = ae->PropsOfAE; while (p0) { PredEntry *pe = RepPredProp(p0); if ( pe->KindOfPE == PEProp && (pe->ModuleOfPred == cur_mod || !pe->ModuleOfPred)) { return(p0); } p0 = pe->NextOfPE; } return(NIL); } Prop GetPredPropByAtom(Atom at, SMALLUNSGN cur_mod) /* get predicate entry for ap/arity; create it if neccessary. */ { Prop p0; AtomEntry *ae = RepAtom(at); READ_LOCK(ae->ARWLock); p0 = GetPredPropByAtomHavingLock(ae, cur_mod); READ_UNLOCK(ae->ARWLock); return(p0); } static inline Prop GetPredPropByFuncHavingLock(Functor f, SMALLUNSGN cur_mod) /* get predicate entry for ap/arity; create it if neccessary. */ { Prop p0; FunctorEntry *fe = (FunctorEntry *)f; p0 = fe->PropsOfFE; while (p0) { PredEntry *p = RepPredProp(p0); if (/* p->KindOfPE != 0 || only props */ (p->ModuleOfPred == cur_mod || !(p->ModuleOfPred))) { return (p0); } p0 = p->NextOfPE; } return(NIL); } Prop GetPredPropByFunc(Functor f, SMALLUNSGN cur_mod) /* get predicate entry for ap/arity; */ { Prop p0; READ_LOCK(f->FRWLock); p0 = GetPredPropByFuncHavingLock(f, cur_mod); READ_UNLOCK(f->FRWLock); return (p0); } Prop GetPredPropHavingLock(Atom ap, unsigned int arity, SMALLUNSGN mod) /* get predicate entry for ap/arity; */ { Prop p0; AtomEntry *ae = RepAtom(ap); Functor f; if (arity == 0) { GetPredPropByAtomHavingLock(ae, mod); } f = InlinedUnlockedMkFunctor(ae, arity); READ_LOCK(f->FRWLock); p0 = GetPredPropByFuncHavingLock(f, mod); READ_UNLOCK(f->FRWLock); return (p0); } /* get expression entry for at/arity; */ Prop GetExpProp(Atom at, unsigned int arity) { Prop p0; AtomEntry *ae = RepAtom(at); ExpEntry *p; READ_LOCK(ae->ARWLock); p = RepExpProp(p0 = ae->PropsOfAE); while (p0 && (p->KindOfPE != ExpProperty || p->ArityOfEE != arity)) p = RepExpProp(p0 = p->NextOfPE); READ_UNLOCK(ae->ARWLock); return (p0); } /* get expression entry for at/arity, at is already locked; */ Prop GetExpPropHavingLock(AtomEntry *ae, unsigned int arity) { Prop p0; ExpEntry *p; p = RepExpProp(p0 = ae->PropsOfAE); while (p0 && (p->KindOfPE != ExpProperty || p->ArityOfEE != arity)) p = RepExpProp(p0 = p->NextOfPE); return (p0); } Prop NewPredPropByFunctor(FunctorEntry *fe, SMALLUNSGN cur_mod) { Prop p0; PredEntry *p = (PredEntry *) AllocAtomSpace(sizeof(*p)); /* printf("entering %s:%s/%d\n", RepAtom(AtomOfTerm(ModuleName[cur_mod]))->StrOfAE, RepAtom(fe->NameOfFE)->StrOfAE, fe->ArityOfFE); */ INIT_RWLOCK(p->PRWLock); p->KindOfPE = PEProp; p->ArityOfPE = fe->ArityOfFE; p->FirstClause = p->LastClause = NIL; p->PredFlags = 0L; p->StateOfPred = 0; p->OwnerFile = AtomNil; p->OpcodeOfPred = UNDEF_OPCODE; p->TrueCodeOfPred = p->CodeOfPred = (CODEADDR)(&(p->OpcodeOfPred)); p->ModuleOfPred = cur_mod; p->NextPredOfModule = ModulePred[cur_mod]; ModulePred[cur_mod] = p; INIT_LOCK(p->StatisticsForPred.lock); p->StatisticsForPred.NOfEntries = 0; p->StatisticsForPred.NOfHeadSuccesses = 0; p->StatisticsForPred.NOfRetries = 0; #ifdef TABLING p->TableOfPred = NULL; #endif /* TABLING */ /* careful that they don't cross MkFunctor */ p->NextOfPE = fe->PropsOfFE; fe->PropsOfFE = p0 = AbsPredProp(p); p->FunctorOfPred = (Functor)fe; WRITE_UNLOCK(fe->FRWLock); return (p0); } Prop NewPredPropByAtom(AtomEntry *ae, SMALLUNSGN cur_mod) { Prop p0; PredEntry *p = (PredEntry *) AllocAtomSpace(sizeof(*p)); /* Printf("entering %s:%s/0\n", RepAtom(AtomOfTerm(ModuleName[cur_mod]))->StrOfAE, ae->StrOfAE); */ INIT_RWLOCK(p->PRWLock); p->KindOfPE = PEProp; p->ArityOfPE = 0; p->FirstClause = p->LastClause = NIL; p->PredFlags = 0L; p->StateOfPred = 0; p->OwnerFile = AtomNil; p->OpcodeOfPred = UNDEF_OPCODE; p->TrueCodeOfPred = p->CodeOfPred = (CODEADDR)(&(p->OpcodeOfPred)); p->ModuleOfPred = cur_mod; p->NextPredOfModule = ModulePred[cur_mod]; ModulePred[cur_mod] = p; INIT_LOCK(p->StatisticsForPred.lock); p->StatisticsForPred.NOfEntries = 0; p->StatisticsForPred.NOfHeadSuccesses = 0; p->StatisticsForPred.NOfRetries = 0; #ifdef TABLING p->TableOfPred = NULL; #endif /* TABLING */ /* careful that they don't cross MkFunctor */ p->NextOfPE = ae->PropsOfAE; ae->PropsOfAE = p0 = AbsPredProp(p); p->FunctorOfPred = (Functor)AbsAtom(ae); WRITE_UNLOCK(ae->ARWLock); return (p0); } Term GetValue(Atom a) { Prop p0 = GetAProp(a, ValProperty); Term out; if (p0 == NIL) return (TermNil); READ_LOCK(RepValProp(p0)->VRWLock); out = RepValProp(p0)->ValueOfVE; READ_UNLOCK(RepValProp(p0)->VRWLock); return (out); } void PutValue(Atom a, Term v) { AtomEntry *ae = RepAtom(a); Prop p0; ValEntry *p; WRITE_LOCK(ae->ARWLock); p0 = GetAPropHavingLock(ae, ValProperty); if (p0 != NIL) { p = RepValProp(p0); WRITE_LOCK(p->VRWLock); WRITE_UNLOCK(ae->ARWLock); } else { p = (ValEntry *) AllocAtomSpace(sizeof(ValEntry)); p->NextOfPE = RepAtom(a)->PropsOfAE; RepAtom(a)->PropsOfAE = AbsValProp(p); p->KindOfPE = ValProperty; /* take care that the lock for the property will be inited even if someone else searches for the property */ INIT_RWLOCK(p->VRWLock); WRITE_LOCK(p->VRWLock); WRITE_UNLOCK(ae->ARWLock); } if (IsFloatTerm(v)) { /* store a float in code space, so that we can access the property */ union { Float f; CELL ar[sizeof(Float) / sizeof(CELL)]; } un; CELL *pt, *iptr; unsigned int i; un.f = FloatOfTerm(v); if (p0 != NIL && IsApplTerm(p->ValueOfVE)) pt = RepAppl(p->ValueOfVE); else { pt = (CELL *) AllocAtomSpace(sizeof(CELL)*(1 + 2*sizeof(Float)/sizeof(CELL))); } pt[0] = (CELL)FunctorDouble; iptr = pt+1; for (i = 0; i < sizeof(Float) / sizeof(CELL); i++) { *iptr++ = MkIntTerm(un.ar[i]/65536); *iptr++ = MkIntTerm(un.ar[i]%65536); } p->ValueOfVE = AbsAppl(pt); } else if (IsLongIntTerm(v)) { CELL *pt; Int val = LongIntOfTerm(v); if (p0 != NIL && IsApplTerm(p->ValueOfVE)) { pt = RepAppl(p->ValueOfVE); } else { pt = (CELL *) AllocAtomSpace(3 * sizeof(CELL)); } pt[0] = (CELL)FunctorLongInt; pt[1] = MkIntTerm(val/65536); pt[2] = MkIntTerm(val%65536); p->ValueOfVE = AbsAppl(pt); } else { if (p0 != NIL && IsApplTerm(p->ValueOfVE)) { /* recover space */ FreeCodeSpace((char *) (RepAppl(p->ValueOfVE))); } p->ValueOfVE = v; } WRITE_UNLOCK(p->VRWLock); } Term StringToList(char *s) { register Term t; register unsigned char *cp = (unsigned char *)s + strlen(s); t = MkAtomTerm(AtomNil); while (cp > (unsigned char *)s) { t = MkPairTerm(MkIntTerm(*--cp), t); } return (t); } Term StringToListOfAtoms(char *s) { register Term t; char so[2]; register unsigned char *cp = (unsigned char *)s + strlen(s); so[1] = '\0'; t = MkAtomTerm(AtomNil); while (cp > (unsigned char *)s) { so[0] = *--cp; t = MkPairTerm(MkAtomTerm(LookupAtom(so)), t); } return (t); } Term ArrayToList(register Term *tp, int nof) { register Term *pt = tp + nof; register Term t; t = MkAtomTerm(AtomNil); while (pt > tp) { Term tm = *--pt; #if SBA if (tm == 0) t = MkPairTerm((CELL)pt, t); else #endif t = MkPairTerm(tm, t); } return (t); } int GetName(char *s, UInt max, Term t) { register Term Head; register Int i; if (IsVarTerm(t) || !IsPairTerm(t)) return (FALSE); while (IsPairTerm(t)) { Head = HeadOfTerm(t); if (!IsNumTerm(Head)) return (FALSE); i = IntOfTerm(Head); if (i < 0 || i > 255) return (FALSE); *s++ = i; t = TailOfTerm(t); if (--max == 0) { Error(FATAL_ERROR,t,"not enough space for GetName"); } } *s = '\0'; return (TRUE); } #ifdef SFUNC Term MkSFTerm(Functor f, int n, Term *a, empty_value) { Term t, p = AbsAppl(H); int i; *H++ = f; RESET_VARIABLE(H); ++H; for (i = 1; i <= n; ++i) { t = Derefa(a++); if (t != empty_value) { *H++ = i; *H++ = t; } } *H++ = 0; return (p); } CELL * ArgsOfSFTerm(Term t) { CELL *p = RepAppl(t) + 1; while (*p != (CELL) p) p = CellPtr(*p) + 1; return (p + 1); } #endif