From 70061308ff2fb6e993492d3a73e42d3f8ccf88d1 Mon Sep 17 00:00:00 2001 From: Vitor Santos Costa Date: Thu, 28 Apr 2016 15:01:16 +0100 Subject: [PATCH] make modules remember which operators they ever defined. Make modules import operators from other modules --- C/cdmgr.c | 12 +++++++----- C/init.c | 38 +++++++++++++++++++++++++++++++++----- C/modules.c | 27 ++++++++++++++++++++++++++- C/scanner.c | 18 +++++++++++++----- C/stdpreds.c | 19 +++++++++++++++++++ CMakeLists.txt | 5 ++--- H/YapGFlagInfo.h | 7 +++++++ H/Yatom.h | 32 +++++++++++++++++++------------- 8 files changed, 126 insertions(+), 32 deletions(-) diff --git a/C/cdmgr.c b/C/cdmgr.c index 0ded1d96f..6e1451550 100644 --- a/C/cdmgr.c +++ b/C/cdmgr.c @@ -1638,6 +1638,8 @@ bool Yap_addclause(Term t, yamop *cp, Term tmode, Term mod, Term *t4ref) tf = ArgOfTerm(1, t); else tf = t; + tf = Yap_YapStripModule(tf, &mod); + if (IsAtomTerm(tf)) { at = AtomOfTerm(tf); p = RepPredProp(PredPropByAtom(at, mod)); @@ -1796,11 +1798,6 @@ bool Yap_addclause(Term t, yamop *cp, Term tmode, Term mod, Term *t4ref) } else { tf = Yap_MkStaticRefTerm(ClauseCodeToStaticClause(cp), p); } - if (t4ref && *t4ref != TermNil) { - if (!Yap_unify(*t4ref, tf)) { - return false; - } - } if (mod == PROLOG_MODULE) mod = TermProlog; if (pflags & MultiFileFlag) { @@ -1814,6 +1811,11 @@ bool Yap_addclause(Term t, yamop *cp, Term tmode, Term mod, Term *t4ref) tn = Yap_MkApplTerm(FunctorMultiFileClause, 5, t); Yap_Recordz(AtomMultiFile, tn); } + if (t4ref && *t4ref != TermNil) { + if (!Yap_unify(*t4ref, tf)) { + return false; + } + } return true; } diff --git a/C/init.c b/C/init.c index b6e0f0215..40eac7037 100755 --- a/C/init.c +++ b/C/init.c @@ -202,10 +202,17 @@ static int OpDec(int p, const char *type, Atom a, Term m) { AtomEntry *ae = RepAtom(a); OpEntry *info; +#if defined(MODULE_INDEPENDENT_OPERATORS_FLAG) + if (booleanFlag(MODULE_INDEPENDENT_OPERATORS_FLAG)) { + m = PROLOG_MODULE; +} else +#endif + { if (m == TermProlog) m = PROLOG_MODULE; else if (m == USER_MODULE) - m = PROLOG_MODULE; + m = PROLOG_MODULE; + } for (i = 1; i <= 7; ++i) if (strcmp(type, optypes[i]) == 0) break; @@ -223,9 +230,14 @@ static int OpDec(int p, const char *type, Atom a, Term m) { WRITE_LOCK(ae->ARWLock); info = Yap_GetOpPropForAModuleHavingALock(ae, m); if (EndOfPAEntr(info)) { + ModEntry *me; info = (OpEntry *)Yap_AllocAtomSpace(sizeof(OpEntry)); + if (!info) + return false; info->KindOfPE = Ord(OpProperty); - info->OpModule = m; + info->NextForME = (me = Yap_GetModuleEntry(m))->OpForME; + me->OpForME = info; + info->OpModule = m; info->OpName = a; // LOCK(OpListLock); info->OpNext = OpList; @@ -246,7 +258,7 @@ static int OpDec(int p, const char *type, Atom a, Term m) { /* ISO dictates */ WRITE_UNLOCK(info->OpRWLock); Yap_Error(PERMISSION_ERROR_CREATE_OPERATOR, MkAtomTerm(a), "op/3"); - return FALSE; + return false; } info->Infix = p; } else if (i <= 5) { @@ -256,14 +268,14 @@ static int OpDec(int p, const char *type, Atom a, Term m) { /* ISO dictates */ WRITE_UNLOCK(info->OpRWLock); Yap_Error(PERMISSION_ERROR_CREATE_OPERATOR, MkAtomTerm(a), "op/3"); - return FALSE; + return false; } info->Posfix = p; } else { info->Prefix = p; } WRITE_UNLOCK(info->OpRWLock); - return (TRUE); + return true; } int Yap_OpDec(int p, char *type, Atom a, Term m) { @@ -278,6 +290,22 @@ static void SetOp(int p, int type, char *at, Term m) { OpDec(p, optypes[type], Yap_LookupAtom(at), m); } +bool Yap_dup_op(OpEntry *op, ModEntry *she) +{ + AtomEntry *ae = RepAtom(op->OpName); + OpEntry *info = (OpEntry *)Yap_AllocAtomSpace(sizeof(OpEntry)); + if (!info) + return false; + memcpy(info, op, sizeof(OpEntry)); + info->NextForME =she->OpForME; + she->OpForME = info; + info->OpModule = MkAtomTerm(she->AtomOfME); + AddPropToAtom(ae, AbsOpProp(info)); + INIT_RWLOCK(info->OpRWLock); + return true; +} + + /* Gets the info about an operator in a prop */ Atom Yap_GetOp(OpEntry *pp, int *prio, int fix) { int n; diff --git a/C/modules.c b/C/modules.c index 9835ed74f..6f989eb21 100644 --- a/C/modules.c +++ b/C/modules.c @@ -462,6 +462,30 @@ static Int source_module(USES_REGS1) { return Yap_unify(ARG1, LOCAL_SourceModule); } +/** + * @pred $copy_operators(+ModSource, +ModTarget) + * + * Copy all operators in ModSource to ModTarget + * + * : _Mod_ is the current read-in or source module. + */ +static Int copy_operators(USES_REGS1) { + ModEntry * me = LookupModule( Deref(ARG1) ); + if (!me) + return true; + ModEntry *she = LookupModule( Deref(ARG2) ); + if (!she) + return true; + OpEntry *op = me->OpForME; + while (op) { + if (!Yap_dup_op(op, she)) { + return false; + } + op = op->NextForME; + } + return true; +} + Term Yap_StripModule(Term t, Term *modp) { CACHE_REGS Term tmod; @@ -513,7 +537,8 @@ void Yap_InitModulesC(void) { Yap_InitCPred("$yap_strip_module", 3, yap_strip_module, SafePredFlag | SyncPredFlag); Yap_InitCPred("context_module", 1, context_module, 0); - Yap_InitCPred("$is_system_module", 1, is_system_module, SafePredFlag); + Yap_InitCPred("$is_system_module", 1, is_system_module, SafePredFlag); + Yap_InitCPred("$copy_operators", 2, copy_operators, 0); Yap_InitCPred("new_system_module", 1, new_system_module, SafePredFlag); Yap_InitCPredBack("$all_current_modules", 1, 1, init_current_module, cont_current_module, SafePredFlag | SyncPredFlag); diff --git a/C/scanner.c b/C/scanner.c index 4aab7521f..d0a48cf9b 100755 --- a/C/scanner.c +++ b/C/scanner.c @@ -1730,8 +1730,10 @@ TokEntry *Yap_tokenizer(struct stream_desc *inp_stream, bool store_comments, (chtype(pch) == BS || chtype(pch) == EF || pch == '%')) { t->Tok = Ord(kind = eot_tok); // consume... - if (ch == '%') + if (pch == '%') { + t->TokInfo = TermNewLine; return l; + } ch = getchr(inp_stream); if (chtype(ch) == EF) { mark_eof(inp_stream); @@ -1748,12 +1750,14 @@ TokEntry *Yap_tokenizer(struct stream_desc *inp_stream, bool store_comments, if (och == '.') { if (chtype(ch) == BS || chtype(ch) == EF || ch == '%') { t->Tok = Ord(kind = eot_tok); - if (ch == '%') + if (ch == '%') { + t->TokInfo = TermNewLine; return l; + } if (chtype(ch) == EF) { mark_eof(inp_stream); - t->TokInfo = TermEof; - } else { + t->TokInfo = TermEof; + } else { t->TokInfo = TermNewLine; } return l; @@ -1802,7 +1806,11 @@ TokEntry *Yap_tokenizer(struct stream_desc *inp_stream, bool store_comments, enter_symbol: if (och == '.' && (chtype(ch) == BS || chtype(ch) == EF || ch == '%')) { t->Tok = Ord(kind = eot_tok); - if (chtype(ch) == EF) { + if (ch == '%') { + t->TokInfo = TermNewLine; + return l; + } + if (chtype(ch) == EF) { mark_eof(inp_stream); t->TokInfo = TermEof; } else { diff --git a/C/stdpreds.c b/C/stdpreds.c index f79470f91..b7ab85295 100755 --- a/C/stdpreds.c +++ b/C/stdpreds.c @@ -1060,6 +1060,25 @@ static Int init_current_atom_op( return cont_current_atom_op(PASS_REGS1); } +static Int copy_local_ops (USES_REGS1) { /* current_op(-Precedence,-Type,-Atom) */ + Term tmodin = Deref(ARG1); + Term t = Deref(ARG1); + AtomEntry *ae; + OpEntry *ope; + + if (IsVarTerm(t) || !IsAtomTerm(t)) { + Yap_Error(TYPE_ERROR_ATOM, t, "current_op/3"); + cut_fail(); + } + ae = RepAtom(AtomOfTerm(t)); + if (EndOfPAEntr((ope = NextOp(RepOpProp(ae->PropsOfAE) PASS_REGS)))) { + cut_fail(); + } + EXTRA_CBACK_ARG(5, 1) = (CELL)MkIntegerTerm((Int)ope); + B->cp_h = HR; + return cont_current_atom_op(PASS_REGS1); +} + void Yap_show_statistics(void) { CACHE_REGS unsigned long int heap_space_taken; diff --git a/CMakeLists.txt b/CMakeLists.txt index e89d4bbfc..78b8580dc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -128,7 +128,6 @@ else() set(YAP_STARTUP startup.yss) endif() -set(WITH_CUDD YES CACHE FILEPATH "Try to use Cudd (currently Cudd 3)") if (WITH_CUDD) #detect cudd setup, as it is shared between different installations. @@ -148,13 +147,13 @@ check_include_files( "stdio.h;cudd/cudd.h;cudd/cuddInt.h" HAVE_CUDD_CUDDINT_H ) endif(WITH_CUDD) -set(WITH_JAVA YES CACHE FILEPATH "Try to use Java (currently Java 6,7,8)") +option(WITH_JAVA "Try to use Java (currently Java 6,7,8)" ON) if (WITH_JAVA) include(java) endif(WITH_JAVA) -set(WITH_PYTHON YES CACHE FILEPATH "Try to use Python (currently Python 3)") +option(WITH_PYTHON "Try to use Python (currently Python 3)" ON) if (WITH_PYTHON) include(python) diff --git a/H/YapGFlagInfo.h b/H/YapGFlagInfo.h index bed5cba37..c27820781 100644 --- a/H/YapGFlagInfo.h +++ b/H/YapGFlagInfo.h @@ -304,6 +304,13 @@ If true, `open_shared_object/2` and friends are implemented, providing access to shared libraries (`.so` files) or to dynamic link libraries (`.DLL` files). */ +//YAP_FLAG(MODULE_INDEPENDENT_OPERATORS_FLAG, "module_independent_operators", true, booleanFlag, +// "false", NULL), +/**< `module_independent_operators ` + +If `true` an operator declaration will be valid for every module in the program. This is for compatibility with old software that +might expect module-independent operators. + */ YAP_FLAG(OPTIMISE_FLAG, "optimise", true, booleanFlag, "false", NULL), YAP_FLAG(OS_ARGV_FLAG, "os_argv", false, os_argv, "?-", NULL), YAP_FLAG(PID_FLAG, "pid", false, ro, "0", NULL), diff --git a/H/Yatom.h b/H/Yatom.h index 41e2245d3..9cada262b 100755 --- a/H/Yatom.h +++ b/H/Yatom.h @@ -250,18 +250,22 @@ INLINE_ONLY inline EXTERN bool IsWideAtom(Atom at) { IsWideAtomProperty(RepWideAtomProp(RepAtom(at)->PropsOfAE)->KindOfPE); } -/* Module property */ +/** Module property: low-level data used to manage modes. + + Includes lists of pedicates, operators and other well-defIned properties. + */ typedef struct mod_entry { Prop NextOfPE; /** chain of atom properties */ - PropFlags KindOfPE; /* kind of property */ - struct pred_entry *PredForME; /* index in module table */ - Atom AtomOfME; /* module's name */ - Atom OwnerFile; /* module's owner file */ + PropFlags KindOfPE; /** kind of property */ + struct pred_entry *PredForME; /** index in module table */ + struct operator_entry *OpForME; /** index in operator table */ + Atom AtomOfME; /** module's name */ + Atom OwnerFile; /** module's owner file */ #if defined(YAPOR) || defined(THREADS) - rwlock_t ModRWLock; /* a read-write lock to protect the entry */ + rwlock_t ModRWLock; /** a read-write lock to protect the entry */ #endif - unsigned int flags; /* Module local flags (from SWI compat) */ - struct mod_entry *NextME; /* next module */ + unsigned int flags; /** Module local flags (from SWI compat) */ + struct mod_entry *NextME; /** next module */ } ModEntry; #if USE_OFFSETS_IN_PROPS @@ -327,7 +331,7 @@ INLINE_ONLY inline EXTERN bool IsModProperty(int flags) { (UNKNOWN_ERROR | UNKNOWN_WARNING | UNKNOWN_FAIL | UNKNOWN_FAST_FAIL | \ UNKNOWN_ABORT | UNKNOWN_HALT) -Term Yap_getUnknownModule(ModEntry *m); + Term Yap_getUnknownModule(ModEntry *m); void Yap_setModuleFlags(ModEntry *n, ModEntry *o); /* operator property entry structure */ @@ -340,7 +344,8 @@ typedef struct operator_entry { Atom OpName; /* atom name */ Term OpModule; /* module of predicate */ struct operator_entry *OpNext; /* next in list of operators */ - BITS16 Prefix, Infix, Posfix; /* precedences */ + struct operator_entry *NextForME; /* next in list of module operators */ + BITS16 Prefix, Infix, Posfix; /**o precedences */ } OpEntry; #if USE_OFFSETS_IN_PROPS @@ -382,9 +387,10 @@ OpEntry *Yap_GetOpProp(Atom, op_type, Term CACHE_TYPE); int Yap_IsPrefixOp(Atom, int *, int *); int Yap_IsOp(Atom); int Yap_IsInfixOp(Atom, int *, int *, int *); -int Yap_IsPosfixOp(Atom, int *, int *); - -/* defines related to operator specifications */ + int Yap_IsPosfixOp(Atom, int *, int *); + bool Yap_dup_op(OpEntry *op, ModEntry *she); + + /* defines related to operator specifications */ #define MaskPrio 0x0fff #define DcrlpFlag 0x1000 #define DcrrpFlag 0x2000