YAP 7.1.0
modules.c
1/*************************************************************************
2* *
3* YAP Prolog *
4* *
5* Yap Prolog was developed at NCCUP - Universidade do Porto *
6* *
7* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
8* *
9**************************************************************************
10* *
11 File: modules.c *
12* Last rev: *
13* mods: *
14* comments: module support *
15* *
16*************************************************************************/
17
18
19#ifdef SCCSLookupSystemModule
20static char SccsId[] = "%W% %G%";
21#endif
22
23#include "Yap.h"
24#include "YapHeap.h"
25#include "Yatom.h"
26
27static Int current_module(USES_REGS1);
28static Int current_module1(USES_REGS1);
29static ModEntry *LookupModule(Term a);
30static ModEntry *LookupSystemModule(Term a);
31static ModEntry *GetModuleEntry(Atom at USES_REGS);
32static ModEntry *FetchModuleEntry(Atom at);
33
42static ModEntry *initMod(AtomEntry *toname, AtomEntry *ae) {
43 CACHE_REGS
44 ModEntry *n, *parent;
45
46 if (toname == NULL)
47 parent = NULL;
48 else {
49 parent = FetchModuleEntry(toname);
50 }
51 n = (ModEntry *)Yap_AllocAtomSpace(sizeof(*n));
52 INIT_RWLOCK(n->ModRWLock);
53 n->KindOfPE = ModProperty;
54 n->PredForME = NULL;
55 n->OpForME = NULL;
56 n->NextME = CurrentModules;
57 CurrentModules = n;
58 n->AtomOfME = ae;
59 n->NextOfPE = NULL;
60 if (ae == AtomProlog || GLOBAL_Stream == NULL)
61 n->OwnerFile = AtomUserIn;
62 else
63 n->OwnerFile = Yap_ConsultingFile(PASS_REGS1);
64 AddPropToAtom(ae, (PropEntry *)n);
65 Yap_setModuleFlags(n, parent);
66 return n;
67}
68
76static ModEntry *GetModuleEntry(Atom at USES_REGS) {
77 Prop p0;
78 AtomEntry *ae = RepAtom(at);
79
80 READ_LOCK(ae->ARWLock);
81 p0 = ae->PropsOfAE;
82 while (p0) {
83 ModEntry *me = RepModProp(p0);
84 if (me->KindOfPE == ModProperty) {
85 READ_UNLOCK(ae->ARWLock);
86 return me;
87 }
88 p0 = me->NextOfPE;
89 }
90 READ_UNLOCK(ae->ARWLock);
91
92 return initMod(
93 (CurrentModule == PROLOG_MODULE ? NULL : AtomOfTerm(CurrentModule)), at);
94}
95
97static ModEntry *FetchModuleEntry(Atom at) {
98 Prop p0;
99 AtomEntry *ae = RepAtom(at);
100
101 READ_LOCK(ae->ARWLock);
102 p0 = ae->PropsOfAE;
103 while (p0) {
104 ModEntry *me = RepModProp(p0);
105 if (me->KindOfPE == ModProperty) {
106 READ_UNLOCK(ae->ARWLock);
107 return me;
108 }
109 p0 = me->NextOfPE;
110 }
111 READ_UNLOCK(ae->ARWLock);
112 return NULL;
113}
114
115Term Yap_getUnknownModule(ModEntry *m) {
116 if (m && m->flags & UNKNOWN_ERROR) {
117 return TermError;
118 } else if (m && m->flags & UNKNOWN_WARNING) {
119 return TermWarning;
120 } else if (m && m->flags & UNKNOWN_FAST_FAIL) {
121 return TermFastFail;
122 } else {
123 return TermFail;
124 }
125}
126
127bool Yap_getUnknown(Term mod) {
128 ModEntry *m = LookupModule(mod);
129 return Yap_getUnknownModule(m);
130}
131
132bool Yap_CharacterEscapes(Term mt) {
133 CACHE_REGS
134 if (mt == PROLOG_MODULE)
135 mt = TermProlog;
136 return GetModuleEntry(AtomOfTerm(mt) PASS_REGS)->flags & M_CHARESCAPE;
137}
138
139#define ByteAdr(X) ((char *)&(X))
140Term Yap_Module_Name(PredEntry *ap) {
141 CACHE_REGS
142
143 if (!ap)
144 return TermUser;
145 if (!ap->ModuleOfPred)
146 /* If the system predicate is a meta-call I should return the
147 module for the metacall, which I will suppose has to be
148 reachable from the current module anyway.
149
150 So I will return the current module in case the system
151 predicate is a meta-call. Otherwise it will still work.
152 */
153 return TermProlog;
154 else {
155 return ap->ModuleOfPred;
156 }
157}
158
159static ModEntry *LookupSystemModule(Term a) {
160 CACHE_REGS
161 Atom at;
162 ModEntry *me;
163
164 /* prolog module */
165 if (a == 0) {
166 a = TermProlog;
167 }
168 at = AtomOfTerm(a);
169 me = GetModuleEntry(at PASS_REGS);
170 if (!me)
171 return NULL;
172 me->flags |= M_SYSTEM;
173 me->OwnerFile = NULL; //Yap_ConsultingFile(PASS_REGS1);
174 return me;
175}
176
177static ModEntry *LookupModule(Term a) {
178 CACHE_REGS
179 Atom at;
180 ModEntry *me;
181
182 /* prolog module */
183 if (a == 0) {
184 return GetModuleEntry(AtomProlog PASS_REGS);
185 }
186 at = AtomOfTerm(a);
187 me = GetModuleEntry(at PASS_REGS);
188 return me;
189}
190
191bool Yap_isSystemModule(Term a) {
192 ModEntry *me = LookupModule(a);
193 return me != NULL && me->flags & M_SYSTEM;
194}
195
196Term Yap_Module(Term tmod) {
197 LookupModule(tmod);
198 return tmod;
199}
200
201ModEntry *Yap_GetModuleEntry(Term mod) {
202 ModEntry *me;
203
204 if (!(me = LookupModule(mod)))
205 return NULL;
206 return me;
207}
208
209Term Yap_GetModuleFromEntry(ModEntry *me) {
210 return MkAtomTerm(me->AtomOfME);
211 ;
212}
213
214struct pred_entry *Yap_ModulePred(Term mod) {
215 ModEntry *me;
216 if (!(me = LookupModule(mod)))
217 return NULL;
218 return me->PredForME;
219}
220
221void Yap_NewModulePred(Term mod, struct pred_entry *ap) {
222 ModEntry *me;
223
224 if (mod == 0)
225 mod = TermProlog;
226 if (!(me = LookupModule(mod)))
227 return;
228 WRITE_LOCK(me->ModRWLock);
229 ap->NextPredOfModule = me->PredForME;
230 me->PredForME = ap;
231 WRITE_UNLOCK(me->ModRWLock);
232}
233
234static Int
235 current_module(USES_REGS1) { /* $current_module(Old,N) */
236 Term t;
237
238 if (CurrentModule) {
239 if (!Yap_unify_constant(ARG1, CurrentModule))
240 return FALSE;
241 } else {
242 if (!Yap_unify_constant(ARG1, TermProlog))
243 return FALSE;
244 }
245 t = Deref(ARG2);
246 if (IsVarTerm(t) || !IsAtomTerm(t))
247 return FALSE;
248 if (t == TermProlog) {
249 CurrentModule = PROLOG_MODULE;
250 } else {
251 // make it very clear that t inherits from cm.
252 LookupModule(t);
253 CurrentModule = t;
254 }
255 LOCAL_SourceModule = CurrentModule;
256 return TRUE;
257}
258
259static Int change_module(USES_REGS1) { /* $change_module(N) */
260 Term mod = Deref(ARG1);
261 LookupModule(mod);
262 CurrentModule = mod;
263 LOCAL_SourceModule = mod;
264 return TRUE;
265}
266static Int set_source_module(USES_REGS1) { /* $change_module(N) */
267 Term mod;
268 if (!Yap_unify(ARG1,(LOCAL_SourceModule? LOCAL_SourceModule:TermProlog)))
269 return false;
270 mod =Deref(ARG2);
271 CurrentModule = mod;
272 LOCAL_SourceModule = mod;
273 return true;
274}
275
276static Int current_module1(USES_REGS1) { /* $current_module(Old)
277 */
278 if (CurrentModule)
279 return Yap_unify_constant(ARG1, CurrentModule);
280 return Yap_unify_constant(ARG1, TermProlog);
281}
282
283static Int cont_current_module(USES_REGS1) {
284 ModEntry *imod = AddressOfTerm(EXTRA_CBACK_ARG(1, 1)), *next;
285 Term t = MkAtomTerm(imod->AtomOfME);
286 next = imod->NextME;
287
288 /* ARG1 is unbound */
289 Yap_unify(ARG1, t);
290 if (!next)
291 cut_succeed();
292 EXTRA_CBACK_ARG(1, 1) = MkAddressTerm(next);
293 return TRUE;
294}
295
296static Int init_current_module(
297 USES_REGS1) { /* current_module(?ModuleName) */
298 Term t = Deref(ARG1);
299 if (!IsVarTerm(t)) {
300 if (!IsAtomTerm(t)) {
301 Yap_Error(TYPE_ERROR_ATOM, t, "module name must be an atom");
302 return FALSE;
303 }
304 if (FetchModuleEntry(AtomOfTerm(t)) != NULL)
305 cut_succeed();
306 cut_fail();
307 }
308 EXTRA_CBACK_ARG(1, 1) = MkIntegerTerm((Int)CurrentModules);
309 return cont_current_module(PASS_REGS1);
310}
311
312static Int cont_ground_module(USES_REGS1) {
313 ModEntry *imod = AddressOfTerm(EXTRA_CBACK_ARG(3, 1)), *next;
314 Term t2 = MkAtomTerm(imod->AtomOfME);
315 next = imod->NextME;
316
317 /* ARG2 is unbound */
318 if (!next)
319 cut_succeed();
320 EXTRA_CBACK_ARG(3, 1) = MkAddressTerm(next);
321 return Yap_unify(ARG2, t2);
322}
323
324static Int init_ground_module(USES_REGS1) {
325 /* current_module(?ModuleName) */
326 Term t1 = Deref(ARG1), tmod = CurrentModule, t3;
327 if (tmod == PROLOG_MODULE) {
328 tmod = TermProlog;
329 }
330 t3 = Yap_YapStripModule(t1, &tmod);
331 if (!t3) {
332 Yap_Error(TYPE_ERROR_CALLABLE, t3, "trying to obtain module");
333 return FALSE;
334 }
335 if (!IsVarTerm(tmod)) {
336 if (!IsAtomTerm(tmod)) {
337 Yap_Error(TYPE_ERROR_ATOM, tmod, "module name must be an atom");
338 cut_fail();
339 }
340 if (FetchModuleEntry(AtomOfTerm(tmod)) != NULL && Yap_unify(tmod, ARG2) &&
341 Yap_unify(t3, ARG3)) {
342 cut_succeed();
343 }
344 cut_fail();
345 }
346 if (!Yap_unify(ARG2, tmod) || !Yap_unify(ARG3, t3)) {
347 cut_fail();
348 }
349 // make sure we keep the binding
350 B->cp_tr = TR;
351 B->cp_h = HR;
352 EXTRA_CBACK_ARG(3, 1) = MkAddressTerm(CurrentModules);
353 return cont_ground_module(PASS_REGS1);
354}
355
363static Int is_system_module(USES_REGS1) {
364 Term t;
365 if (IsVarTerm(t = Deref(ARG1))) {
366 return false;
367 }
368 if (!IsAtomTerm(t)) {
369 Yap_Error(TYPE_ERROR_ATOM, t, "load_files/2");
370 return false;
371 }
372 return Yap_isSystemModule(t);
373}
374
375static Int new_system_module(USES_REGS1) {
376 ModEntry *me;
377 Term t;
378 if (IsVarTerm(t = Deref(ARG1))) {
379 Yap_Error(INSTANTIATION_ERROR, t, NULL);
380 return false;
381 }
382 if (!IsAtomTerm(t)) {
383 Yap_Error(TYPE_ERROR_ATOM, t, NULL);
384 return false;
385 }
386 if ((me = LookupSystemModule(t)))
387 me->OwnerFile = Yap_ConsultingFile(PASS_REGS1);
388 return me != NULL;
389}
390
391static Int strip_module(USES_REGS1) {
392 Term t1 = Deref(ARG1), tmod = CurrentModule;
393 if (tmod == PROLOG_MODULE) {
394 tmod = TermProlog;
395 }
396 t1 = Yap_StripModule(t1, &tmod);
397 if (!t1) {
398 Yap_Error(TYPE_ERROR_CALLABLE, t1, "trying to obtain module");
399 return FALSE;
400 }
401 return Yap_unify(ARG3, t1) && Yap_unify(ARG2, tmod);
402}
403
404static Int yap_strip_clause(USES_REGS1) {
405 Term t1 = Deref(ARG1), th, tbody, tmod = LOCAL_SourceModule, thmod;
406 if (tmod == PROLOG_MODULE) {
407 tmod = TermProlog;
408 }
409 t1 = Yap_StripModule(t1, &tmod);
410 thmod=tmod;
411 if (IsVarTerm(t1) || IsVarTerm(tmod)) {
412 Yap_Error(INSTANTIATION_ERROR, t1, "trying to obtain module");
413 return false;
414 } else if (IsApplTerm(t1)) {
415 Functor f = FunctorOfTerm(t1);
416 if (IsExtensionFunctor(f)) {
417 Yap_Error(TYPE_ERROR_CALLABLE, t1, "trying to obtain module");
418 return false;
419 }
420 if (f == FunctorAssert ) {
421 thmod = tmod;
422 th = ArgOfTerm(1, t1);
423 tbody = ArgOfTerm(2, t1);
424 th = Yap_StripModule(th, &thmod);
425 if (IsVarTerm(th)) {
426 Yap_Error(INSTANTIATION_ERROR, t1, "trying to obtain module");
427 return false;
428 } else if (IsVarTerm(thmod)) {
429 Yap_Error(INSTANTIATION_ERROR, thmod, "trying to obtain module");
430 return false;
431 } else if (IsIntTerm(th) ||
432 (IsApplTerm(th) && IsExtensionFunctor(FunctorOfTerm(t1)))) {
433 Yap_Error(TYPE_ERROR_CALLABLE, t1, "trying to obtain module");
434 return false;
435 } else if (!IsAtomTerm(thmod)) {
436 Yap_Error(TYPE_ERROR_ATOM, thmod, "trying to obtain module");
437 return false;
438 }
439 } else {
440 th = t1;
441 thmod = tmod;
442 tbody = TermTrue;
443 }
444 } else if (IsIntTerm(t1) || IsIntTerm(tmod)) {
445 Yap_Error(TYPE_ERROR_CALLABLE, t1, "trying to obtain module");
446 return false;
447 } else {
448 th = t1;
449 thmod = tmod;
450 tbody = TermTrue;
451 }
452 return Yap_unify(ARG4, th) && Yap_unify(ARG2, tmod)
453 && Yap_unify(ARG3,thmod)
454 && Yap_unify(ARG5,tbody);
455}
456
457Term Yap_YapStripModule(Term t, Term *modp) {
458 CACHE_REGS
459 Term tmod;
460
461 if (modp) {
462 tmod = *modp;
463 if (tmod == PROLOG_MODULE) {
464 *modp = tmod = TermProlog;
465 }
466 } else {
467 tmod = CurrentModule;
468 if (tmod == PROLOG_MODULE) {
469 tmod = CurrentModule = TermProlog;
470 }
471 }
472restart:
473 if (IsVarTerm(t) || !IsApplTerm(t)) {
474 if (modp)
475 *modp = tmod;
476 return t;
477 } else {
478 Functor fun = FunctorOfTerm(t);
479 if (fun == FunctorModule) {
480 Term t1 = ArgOfTerm(1, t);
481 tmod = t1;
482 if (!IsVarTerm(tmod) && !IsAtomTerm(tmod)) {
483 if (modp)
484 *modp = tmod;
485 return t;
486 }
487 t = ArgOfTerm(2, t);
488 goto restart;
489 }
490 if (modp)
491 *modp = tmod;
492 return t;
493 }
494 return 0L;
495}
496
497static Int yap_strip_module(USES_REGS1) {
498 Term t1 = Deref(ARG1), tmod = CurrentModule;
499 if (tmod == PROLOG_MODULE) {
500 tmod = TermProlog;
501 }
502 t1 = Yap_YapStripModule(t1, &tmod);
503 if (!t1 || (!IsVarTerm(tmod) && !IsAtomTerm(tmod))) {
504 Yap_Error(TYPE_ERROR_CALLABLE, t1, "trying to obtain module");
505 return FALSE;
506 }
507 return Yap_unify(ARG3, t1) && Yap_unify(ARG2, tmod);
508}
509
510static Int context_module(USES_REGS1) {
511 yamop *parentcp = P;
512 CELL *yenv;
513 PredEntry *ap = EnvPreg(parentcp);
514 if (ap->ModuleOfPred && !(ap->PredFlags & MetaPredFlag))
515 return Yap_unify(ARG1, ap->ModuleOfPred);
516 parentcp = CP;
517 yenv = ENV;
518 do {
519 ap = EnvPreg(parentcp);
520 if (ap->ModuleOfPred && !(ap->PredFlags & MetaPredFlag))
521 return Yap_unify(ARG1, ap->ModuleOfPred);
522 parentcp = (yamop *)yenv[E_CP];
523 yenv = (CELL *)yenv[E_E];
524 } while (yenv);
525 if (CurrentModule)
526 return Yap_unify(ARG1, CurrentModule);
527 else
528 return Yap_unify(ARG1, TermProlog);
529}
530
538static Int source_module(USES_REGS1) {
539 if (LOCAL_SourceModule == PROLOG_MODULE) {
540 return Yap_unify(ARG1, TermProlog);
541 }
542 return Yap_unify(ARG1, LOCAL_SourceModule);
543}
544
552static Int current_source_module(USES_REGS1) {
553 Term t;
554 if (LOCAL_SourceModule == PROLOG_MODULE) {
555 LOCAL_SourceModule = TermProlog;
556 }
557 if (!Yap_unify(ARG1, LOCAL_SourceModule)) {
558 return false;
559 };
560 if (IsVarTerm(t = Deref(ARG2))) {
561 Yap_Error(INSTANTIATION_ERROR, t, NULL);
562 return false;
563 }
564 if (!IsAtomTerm(t)) {
565 Yap_Error(TYPE_ERROR_ATOM, t, NULL);
566 return false;
567 }
568 LOCAL_SourceModule = CurrentModule = t;
569 return true;
570}
571
579static Int copy_operators(USES_REGS1) {
580 ModEntry *me = LookupModule(Deref(ARG1));
581 if (!me)
582 return true;
583 ModEntry *she = LookupModule(Deref(ARG2));
584 if (!she)
585 return true;
586 OpEntry *op = me->OpForME;
587 while (op) {
588 if (!Yap_dup_op(op, she)) {
589 return false;
590 }
591 op = op->NextForME;
592 }
593 return true;
594}
595
596Term Yap_StripModule(Term t, Term *modp) {
597 CACHE_REGS
598 Term tmod;
599
600 if (modp)
601 tmod = *modp;
602 else {
603 tmod = CurrentModule;
604 if (tmod == PROLOG_MODULE) {
605 tmod = TermProlog;
606 }
607 }
608restart:
609 if (IsVarTerm(t) || !IsApplTerm(t)) {
610 if (modp)
611 *modp = tmod;
612 return t;
613 } else {
614 Functor fun = FunctorOfTerm(t);
615 if (fun == FunctorModule) {
616 Term t1 = ArgOfTerm(1, t);
617 if (IsVarTerm(t1)) {
618 *modp = tmod;
619 return t;
620 }
621 tmod = t1;
622 if (!IsVarTerm(tmod) && !IsAtomTerm(tmod)) {
623 return 0L;
624 }
625 t = ArgOfTerm(2, t);
626 goto restart;
627 }
628 if (modp)
629 *modp = tmod;
630 return t;
631 }
632 return 0L;
633}
634
635void Yap_InitModulesC(void) {
636 Yap_InitCPred("$current_module", 2, current_module,
637 SafePredFlag | SyncPredFlag);
638 Yap_InitCPred("$current_module", 1, current_module1,
639 SafePredFlag | SyncPredFlag);
640 Yap_InitCPred("set_source_module", 2, set_source_module,
641 SafePredFlag | SyncPredFlag);
642 Yap_InitCPred("$change_module", 1, change_module,
643 SafePredFlag | SyncPredFlag);
644 Yap_InitCPred("strip_module", 3, strip_module, SafePredFlag | SyncPredFlag);
645 Yap_InitCPred("$yap_strip_module", 3, yap_strip_module,
646 SafePredFlag | SyncPredFlag);
647 Yap_InitCPred("source_module", 1, source_module, SafePredFlag | SyncPredFlag);
648 Yap_InitCPred("current_source_module", 2, current_source_module,
649 SafePredFlag | SyncPredFlag);
650 Yap_InitCPred("$yap_strip_clause", 5, yap_strip_clause,
651 SafePredFlag);
652 Yap_InitCPred("context_module", 1, context_module, 0);
653 Yap_InitCPred("$is_system_module", 1, is_system_module, SafePredFlag);
654 Yap_InitCPred("$copy_operators", 2, copy_operators, 0);
655 Yap_InitCPred("new_system_module", 1, new_system_module, SafePredFlag);
656 Yap_InitCPredBack("$all_current_modules", 1, 1, init_current_module,
657 cont_current_module, SafePredFlag | SyncPredFlag);
658 Yap_InitCPredBack("$ground_module", 3, 1, init_ground_module,
659 cont_ground_module, SafePredFlag | SyncPredFlag);
660}
661
662void Yap_InitModules(void) {
663 CACHE_REGS
664 CurrentModules = NULL;
665 LookupSystemModule(MkAtomTerm(AtomProlog));
666 LOCAL_SourceModule = MkAtomTerm(AtomProlog);
667 LookupModule(USER_MODULE);
668 LookupModule(IDB_MODULE);
669 LookupModule(ATTRIBUTES_MODULE);
670 LookupSystemModule(CHARSIO_MODULE);
671 LookupSystemModule(TERMS_MODULE);
672 LookupSystemModule(SYSTEM_MODULE);
673 LookupSystemModule(READUTIL_MODULE);
674 LookupSystemModule(HACKS_MODULE);
675 LookupModule(ARG_MODULE);
676 LookupSystemModule(GLOBALS_MODULE);
677 LookupSystemModule(DBLOAD_MODULE);
678 LookupSystemModule(RANGE_MODULE);
679 CurrentModule = PROLOG_MODULE;
680}
Main definitions.
A matrix.
Definition: matrix.c:68
Module property: low-level data used to manage modes.
Definition: Yatom.h:209
struct mod_entry * NextME
Module local flags (from SWI compat)
Definition: Yatom.h:220
Atom AtomOfME
index in operator table
Definition: Yatom.h:214
struct operator_entry * OpForME
index in module table
Definition: Yatom.h:213
Atom OwnerFile
module's name
Definition: Yatom.h:215
struct pred_entry * PredForME
kind of property
Definition: Yatom.h:212
PropFlags KindOfPE
chain of atom properties
Definition: Yatom.h:211
unsigned int flags
module's owner file
Definition: Yatom.h:219
Definition: Yatom.h:295
Definition: Yatom.h:544
Definition: amidefs.h:264