diff --git a/C/absmi.c b/C/absmi.c index a028faca1..6d8213f9d 100755 --- a/C/absmi.c +++ b/C/absmi.c @@ -916,6 +916,7 @@ static int interrupt_dexecute(USES_REGS1) { static void undef_goal(USES_REGS1) { PredEntry *pe = PredFromDefCode(P); + CELL *b; BEGD(d0); /* avoid trouble with undefined dynamic procedures */ @@ -926,12 +927,24 @@ static void undef_goal(USES_REGS1) { PP = pe; } #endif - if (pe->PredFlags & (DynamicPredFlag | LogUpdatePredFlag | MultiFileFlag) || - pe == UndefCode) { + if (UndefCode == NULL || UndefCode->OpcodeOfPred == UNDEF_OPCODE) { + fprintf(stderr,"call to undefined Predicates %s ->", IndicatorOfPred(pe)); + Yap_DebugPlWriteln(ARG1); + fprintf(stderr," error handler not available, failing\n"); #if defined(YAPOR) || defined(THREADS) UNLOCKPE(19, PP); PP = NULL; #endif + CalculateStackGap(PASS_REGS1); + P = FAILCODE; + return; + } + if (pe->PredFlags & (DynamicPredFlag | LogUpdatePredFlag | MultiFileFlag) ) { +#if defined(YAPOR) || defined(THREADS) + UNLOCKPE(19, PP); + PP = NULL; +#endif + CalculateStackGap(PASS_REGS1); P = FAILCODE; return; } @@ -940,12 +953,14 @@ static void undef_goal(USES_REGS1) { PP = NULL; #endif d0 = pe->ArityOfPE; + HR[0] = Yap_Module_Name(pe); + b = HR; + HR += 2; if (d0 == 0) { - HR[1] = MkAtomTerm((Atom)(pe->FunctorOfPred)); + b[1] = MkAtomTerm((Atom)(pe->FunctorOfPred)); } else { - HR[d0 + 2] = AbsAppl(HR); - *HR = (CELL)pe->FunctorOfPred; - HR++; + b[1] = AbsAppl(HR); + *HR++ = (CELL)pe->FunctorOfPred; BEGP(pt1); pt1 = XREGS + 1; for (; d0 > 0; --d0) { @@ -976,10 +991,8 @@ static void undef_goal(USES_REGS1) { ENDP(pt1); } ENDD(d0); - HR[0] = Yap_Module_Name(pe); - ARG1 = (Term)AbsPair(HR); - ARG2 = Yap_getUnknownModule(Yap_GetModuleEntry(HR[0])); - HR += 2; + ARG2 = Yap_getUnknownModule(Yap_GetModuleEntry(b[0])); + ARG1 = AbsPair(b); #ifdef LOW_LEVEL_TRACER if (Yap_do_low_level_trace) low_level_trace(enter_pred, UndefCode, XREGS + 1); diff --git a/C/c_interface.c b/C/c_interface.c index 3e554be13..354cd4315 100755 --- a/C/c_interface.c +++ b/C/c_interface.c @@ -88,7 +88,7 @@ struct foreign_context { X_API bool python_in_python; -X_API int YAP_Reset(yap_reset_t mode); +X_API int YAP_Reset(yap_reset_t mode, bool reset_global); #if !HAVE_STRNCPY #define strncpy(X, Y, Z) strcpy(X, Y) @@ -1484,6 +1484,7 @@ X_API Term YAP_ReadBuffer(const char *s, Term *tp) { return 0L; } LOCAL_ErrorMessage = NULL; + RECOVER_H(); return 0; } else { break; @@ -1941,14 +1942,12 @@ X_API Int YAP_RunGoalOnce(Term t) { yhandle_t CSlot; BACKUP_MACHINE_REGS(); - Yap_InitYaamRegs(0); CSlot = Yap_StartSlots(); LOCAL_PrologMode = UserMode; - // Yap_heap_regs->yap_do_low_level_trace=true; - out = Yap_RunTopGoal(t, true); + out = Yap_RunTopGoal(t, true); LOCAL_PrologMode = oldPrologMode; - Yap_CloseSlots(CSlot); + // Yap_CloseSlots(CSlot); if (!(oldPrologMode & UserCCallMode)) { /* called from top-level */ LOCAL_AllowRestart = FALSE; @@ -2110,22 +2109,23 @@ X_API int YAP_InitConsult(int mode, const char *fname, char *full, int *osnop) { int lvl = push_text_stack(); if (mode == YAP_BOOT_MODE) { mode = YAP_CONSULT_MODE; - } - char *bfp = Malloc(YAP_FILENAME_MAX + 1); - bfp[0] = '\0'; - if (fname == NULL || fname[0] == '\0') { - fname = Yap_BOOTFILE; - } - if (fname) { - fl = Yap_AbsoluteFile(fname, bfp, true); - if (!fl || !fl[0]) { - pop_text_stack(lvl); + } + char *bfp = Malloc(YAP_FILENAME_MAX + 1); + bfp[0] = '\0'; + if (fname == NULL || fname[0] == '\0') { + fname = Yap_BOOTFILE; + } + if (fname) { + fl = Yap_AbsoluteFile(fname, bfp, true); + if (!fl || !fl[0]) { + pop_text_stack(lvl); return -1; } } bool consulted = (mode == YAP_CONSULT_MODE); - Yap_init_consult(consulted, bfp); sno = Yap_OpenStream(fl, "r", MkAtomTerm(Yap_LookupAtom(bfp))); + if (!Yap_ChDir(dirname((char *)fl))) return -1; + Yap_init_consult(consulted, bfp); *osnop = Yap_CheckAlias(AtomLoopStream); if (!Yap_AddAlias(AtomLoopStream, sno)) { Yap_CloseStream(sno); @@ -2136,6 +2136,7 @@ X_API int YAP_InitConsult(int mode, const char *fname, char *full, int *osnop) { GLOBAL_Stream[sno].name = Yap_LookupAtom(fl); GLOBAL_Stream[sno].user_name = MkAtomTerm(Yap_LookupAtom(fname)); GLOBAL_Stream[sno].encoding = LOCAL_encoding; + RECOVER_MACHINE_REGS(); UNLOCK(GLOBAL_Stream[sno].streamlock); return sno; @@ -2159,9 +2160,10 @@ X_API FILE *YAP_TermToStream(Term t) { return NULL; } -X_API void YAP_EndConsult(int sno, int *osnop) { +X_API void YAP_EndConsult(int sno, int *osnop, const char *full) { BACKUP_MACHINE_REGS(); Yap_CloseStream(sno); + Yap_ChDir(full); if (osnop >= 0) Yap_AddAlias(AtomLoopStream, *osnop); Yap_end_consult(); @@ -2298,10 +2300,10 @@ X_API int YAP_CompareTerms(Term t1, Term t2) { return Yap_compare_terms(t1, t2); } -X_API int YAP_Reset(yap_reset_t mode) { +X_API int YAP_Reset(yap_reset_t mode, bool reset_global) { int res = TRUE; BACKUP_MACHINE_REGS(); - res = Yap_Reset(mode); + res = Yap_Reset(mode, reset_global); RECOVER_MACHINE_REGS(); return res; } diff --git a/C/cdmgr.c b/C/cdmgr.c index fbdeb8e46..342454d3a 100644 --- a/C/cdmgr.c +++ b/C/cdmgr.c @@ -56,7 +56,7 @@ static Int p_startconsult(USES_REGS1); static Int p_showconslultlev(USES_REGS1); static Int p_endconsult(USES_REGS1); static Int p_undefined(USES_REGS1); -static Int p_new_multifile(USES_REGS1); +static Int new_multifile(USES_REGS1); static Int p_is_multifile(USES_REGS1); static Int p_optimizer_on(USES_REGS1); static Int p_optimizer_off(USES_REGS1); @@ -2405,32 +2405,25 @@ static Int return (Yap_unify_constant(ARG3, MkIntegerTerm(ncl))); } -static Int p_new_multifile(USES_REGS1) { /* '$new_multifile'(+N,+Ar,+Mod) */ - Atom at; - arity_t arity; - PredEntry *pe; - Term t = Deref(ARG1); - Term mod = Deref(ARG3); +/* @pred '$new_multifile'(+N,+Ar,+Mod) + * sets the multi-file flag + * */ +static Int new_multifile(USES_REGS1) { + PredEntry *pe; + Atom at; + arity_t arity; - if (IsVarTerm(t)) - return (FALSE); - if (IsAtomTerm(t)) - at = AtomOfTerm(t); - else - return (FALSE); - t = Deref(ARG2); - if (IsVarTerm(t)) - return (FALSE); - if (IsIntTerm(t)) - arity = IntOfTerm(t); - else - return FALSE; - if (arity == 0) - pe = RepPredProp(PredPropByAtom(at, mod)); - else - pe = RepPredProp(PredPropByFunc(Yap_MkFunctor(at, arity), mod)); - PELOCK(26, pe); - if (pe->PredFlags & MultiFileFlag) { + pe = new_pred(Deref(ARG1), Deref(ARG2), "multifile"); + if (EndOfPAEntr(pe)) + return FALSE; + PELOCK(30, pe); + arity = pe->ArityOfPE; + if (arity == 0) + at = (Atom)pe->FunctorOfPred; + else + at = NameOfFunctor(pe->FunctorOfPred); + + if (pe->PredFlags & MultiFileFlag) { UNLOCKPE(26, pe); return true; } @@ -2656,7 +2649,7 @@ static Int p_set_owner_file(USES_REGS1) { /* '$owner_file'(+P,M,F) */ return TRUE; } -static Int p_mk_d(USES_REGS1) { /* '$make_dynamic'(+P) */ +static Int mk_dynamic(USES_REGS1) { /* '$make_dynamic'(+P) */ PredEntry *pe; Atom at; arity_t arity; @@ -4713,10 +4706,10 @@ void Yap_InitCdMgr(void) { Yap_InitCPred("$is_exo", 2, p_is_exo, TestPredFlag | SafePredFlag); Yap_InitCPred("$owner_file", 3, owner_file, SafePredFlag); Yap_InitCPred("$set_owner_file", 3, p_set_owner_file, SafePredFlag); - Yap_InitCPred("$mk_d", 2, p_mk_d, SafePredFlag); + Yap_InitCPred("$mk_dynamic", 2, mk_dynamic, SafePredFlag); Yap_InitCPred("$sys_export", 2, p_sys_export, TestPredFlag | SafePredFlag); Yap_InitCPred("$pred_exists", 2, p_pred_exists, TestPredFlag | SafePredFlag); - Yap_InitCPred("$number_of_clauses", 3, p_number_of_clauses, + Yap_InitCPred("$numb er_of_clauses", 3, p_number_of_clauses, SafePredFlag | SyncPredFlag); Yap_InitCPred("$undefined", 2, p_undefined, SafePredFlag | TestPredFlag); Yap_InitCPred("$undefp_handler", 2, undefp_handler, @@ -4729,8 +4722,8 @@ void Yap_InitCdMgr(void) { SafePredFlag | SyncPredFlag); Yap_InitCPred("$kill_dynamic", 2, p_kill_dynamic, SafePredFlag | SyncPredFlag); - Yap_InitCPred("$new_multifile", 3, p_new_multifile, - SafePredFlag | SyncPredFlag); + Yap_InitCPred("$new_multifile", 2, new_multifile, + SafePredFlag | SyncPredFlag | HiddenPredFlag); Yap_InitCPred("$is_multifile", 2, p_is_multifile, TestPredFlag | SafePredFlag); Yap_InitCPred("$new_system_predicate", 3, new_system_predicate, diff --git a/C/errors.c b/C/errors.c index a7ad9b6d2..6972c7e61 100755 --- a/C/errors.c +++ b/C/errors.c @@ -385,6 +385,11 @@ yamop *Yap_Error__(const char *file, const char *function, int lineno, fprintf(stderr, "%% ERROR WITHIN ERROR %d: %s\n", LOCAL_Error_TYPE, tmpbuf); Yap_RestartYap(1); } + if (LOCAL_DoingUndefp && type == EVALUATION_ERROR_UNDEFINED) { + P = FAILCODE; + CalculateStackGap(PASS_REGS1); + return P; + } LOCAL_ActiveError->errorNo = type; LOCAL_ActiveError->errorAsText = Yap_errorName(type); LOCAL_ActiveError->errorClass = Yap_errorClass(type); @@ -616,8 +621,12 @@ yamop *Yap_Error__(const char *file, const char *function, int lineno, } else { error_t = Yap_MkApplTerm(fun, 2, nt); } - memset(LOCAL_ActiveError, 0, sizeof(*LOCAL_ActiveError)); - Yap_JumpToEnv(error_t); + if (LOCAL_DoingUndefp) { + Yap_PrintWarning(error_t); + } else { + memset(LOCAL_ActiveError, 0, sizeof(*LOCAL_ActiveError)); + Yap_JumpToEnv(error_t); + } P = (yamop *)FAILCODE; LOCAL_PrologMode &= ~InErrorMode; return P; diff --git a/C/exec.c b/C/exec.c index 0a30836ff..73a528d42 100755 --- a/C/exec.c +++ b/C/exec.c @@ -1637,6 +1637,7 @@ bool Yap_execute_pred(PredEntry *ppe, CELL *pt, bool pass_ex USES_REGS) { /* we have failed, and usually we would backtrack to this B, trouble is, we may also have a delayed cut to do */ if (B != NULL) + HB = B->cp_h; YENV = ENV; // should we catch the exception or pass it through? @@ -1744,7 +1745,13 @@ Term Yap_RunTopGoal(Term t, bool handle_errors) { Yap_Error(INSTANTIATION_ERROR, t, "call/1"); LOCAL_PrologMode &= ~TopGoalMode; return (FALSE); - } else if (IsAtomTerm(t)) { + } if (IsPairTerm(t)) { + Term ts[2]; + ts[0] = t; + ts[1] = (CurrentModule == 0? TermProlog: CurrentModule); + t = Yap_MkApplTerm(FunctorCsult,2,ts); + } + if (IsAtomTerm(t)) { Atom a = AtomOfTerm(t); pt = NULL; pe = Yap_GetPredPropByAtom(a, tmod); @@ -1951,20 +1958,28 @@ static Int cut_up_to_next_disjunction(USES_REGS1) { return TRUE; } -bool Yap_Reset(yap_reset_t mode) { +/** + * Reset the Prolog engine . If _Hard_ resèt the global stack_el. If + * p_no_use_'soft_float keei + * + * @param mode + * @param hard + * + * @return + */ +bool Yap_Reset(yap_reset_t mode, bool hard) { CACHE_REGS int res = TRUE; Yap_ResetException(worker_id); /* first, backtrack to the root */ - while (B->cp_b) { + while (B) { + P = FAILCODE; + Yap_exec_absmi(true, mode); B = B->cp_b; } - // B shoul lead to CP with _ystop0, - P = FAILCODE; - res = Yap_exec_absmi(true, mode); /* reinitialize the engine */ - // Yap_InitYaamRegs( worker_id ); + Yap_InitYaamRegs(worker_id, false); GLOBAL_Initialised = true; ENV = LCL0; ASP = (CELL *)B; @@ -2069,7 +2084,7 @@ static Int jump_env(USES_REGS1) { return TRUE; } - void Yap_InitYaamRegs(int myworker_id) { + void Yap_InitYaamRegs(int myworker_id, bool full_reset) { Term h0var; // getchar(); #if PUSH_REGS @@ -2090,8 +2105,8 @@ static Int jump_env(USES_REGS1) { Yap_ResetException(worker_id); Yap_PutValue(AtomBreak, MkIntTerm(0)); TR = (tr_fr_ptr)REMOTE_TrailBase(myworker_id); - HR = H0 = ((CELL *)REMOTE_GlobalBase(myworker_id)) + - 1; // +1: hack to ensure the gc does not try to mark mistakenly + HR = H0 = ((CELL *) REMOTE_GlobalBase(myworker_id)) + + 1; // +1: hack to ensure the gc does not try to mark mistakenly LCL0 = ASP = (CELL *)REMOTE_LocalBase(myworker_id); CurrentTrailTop = (tr_fr_ptr)(REMOTE_TrailTop(myworker_id) - MinTrailGap); /* notice that an initial choice-point and environment @@ -2103,12 +2118,22 @@ static Int jump_env(USES_REGS1) { DEPTH = RESET_DEPTH(); #endif STATIC_PREDICATES_MARKED = FALSE; - if (REMOTE_GlobalArena(myworker_id) == 0L || - REMOTE_GlobalArena(myworker_id) == TermNil) { + if (full_reset) { + HR = H0+1; + h0var = MkVarTerm(); + REMOTE_GcGeneration(myworker_id) = Yap_NewTimedVar(h0var); + REMOTE_GcCurrentPhase(myworker_id) = 0L; + REMOTE_GcPhase(myworker_id) = + Yap_NewTimedVar(MkIntTerm(REMOTE_GcCurrentPhase(myworker_id))); +#if COROUTINING + REMOTE_WokenGoals(myworker_id) = Yap_NewTimedVar(TermNil); + h0var = MkVarTerm(); + REMOTE_AttsMutableList(myworker_id) = Yap_NewTimedVar(h0var); +#endif + Yap_AllocateDefaultArena(128 * 1024, 2, myworker_id); } else { - HR = RepAppl(REMOTE_GlobalArena(myworker_id)); + HR = Yap_ArenaLimit(REMOTE_GlobalArena(myworker_id)); } - REMOTE_GlobalArena(myworker_id) = TermNil; Yap_InitPreAllocCodeSpace(myworker_id); #ifdef FROZEN_STACKS H_FZ = HR; @@ -2125,22 +2150,11 @@ static Int jump_env(USES_REGS1) { LOCAL = REMOTE(myworker_id); worker_id = myworker_id; #endif /* THREADS */ -#if COROUTINING - REMOTE_WokenGoals(myworker_id) = Yap_NewTimedVar(TermNil); - h0var = MkVarTerm(); - REMOTE_AttsMutableList(myworker_id) = Yap_NewTimedVar(h0var); -#endif Yap_RebootSlots(myworker_id); - h0var = MkVarTerm(); - REMOTE_GcGeneration(myworker_id) = Yap_NewTimedVar(h0var); - REMOTE_GcCurrentPhase(myworker_id) = 0L; - REMOTE_GcPhase(myworker_id) = - Yap_NewTimedVar(MkIntTerm(REMOTE_GcCurrentPhase(myworker_id))); #if defined(YAPOR) || defined(THREADS) PP = NULL; PREG_ADDR = NULL; #endif - Yap_AllocateDefaultArena(128 * 1024, 2, myworker_id); cut_c_initialize(myworker_id); Yap_PrepGoal(0, NULL, NULL PASS_REGS); #ifdef FROZEN_STACKS diff --git a/C/fli_absmi_insts.h b/C/fli_absmi_insts.h index 4b95f9a85..371f5248c 100644 --- a/C/fli_absmi_insts.h +++ b/C/fli_absmi_insts.h @@ -623,10 +623,12 @@ BOp(undef_p, e); /* save S for module name */ - saveregs(); + LOCAL_DoingUndefp = true; + saveregs(); undef_goal(PASS_REGS1); setregs(); /* for profiler */ + LOCAL_DoingUndefp = false; CACHE_A1(); JMPNext(); ENDBOp(); diff --git a/C/globals.c b/C/globals.c index 2826fa41c..ba9b3a3d6 100644 --- a/C/globals.c +++ b/C/globals.c @@ -163,6 +163,11 @@ static inline CELL *ArenaLimit(Term arena) { return arena_base + sz; } +/* pointer to top of an arena */ +CELL *Yap_ArenaLimit(Term arena) { + return ArenaLimit(arena); +} + /* pointer to top of an arena */ static inline CELL *ArenaPt(Term arena) { return (CELL *)RepAppl(arena); } diff --git a/C/init.c b/C/init.c index 283e6a7a5..a5291fb94 100755 --- a/C/init.c +++ b/C/init.c @@ -1432,7 +1432,7 @@ void Yap_InitWorkspace(struct yap_boot_params *yapi, GLOBAL_AllowLocalExpansion = true; GLOBAL_AllowTrailExpansion = true; Yap_InitExStacks(0, Trail, Stack); - Yap_InitYaamRegs(0); + Yap_InitYaamRegs(0, true); InitStdPreds(yapi); /* make sure tmp area is available */ { Yap_ReleasePreAllocCodeSpace(Yap_PreAllocCodeSpace()); } diff --git a/C/qlyr.c b/C/qlyr.c index a67f3109f..7d268b4a5 100755 --- a/C/qlyr.c +++ b/C/qlyr.c @@ -1087,7 +1087,7 @@ static Int qload_program(USES_REGS1) { if ((stream = Yap_GetInputStream(t1, "from read_program"))) { return FALSE; } - Yap_Reset(YAP_RESET_FROM_RESTORE); + Yap_Reset(YAP_RESET_FROM_RESTORE, true); if (do_header(stream) == NIL) return FALSE; read_module(stream); diff --git a/C/save.c b/C/save.c index fe53275d9..ce4c44958 100755 --- a/C/save.c +++ b/C/save.c @@ -1582,7 +1582,7 @@ static int Restore(char *s_dir USES_REGS) { break; case DO_ONLY_CODE: UnmarkTrEntries(PASS_REGS1); - Yap_InitYaamRegs(0); + Yap_InitYaamRegs(0, true); break; } diff --git a/C/scanner.c b/C/scanner.c index 9eea1e6cb..96316fb4b 100755 --- a/C/scanner.c +++ b/C/scanner.c @@ -530,15 +530,26 @@ typedef struct scanner_internals { size_t CommentsBuffLim; } scanner_internals; +static struct stream_desc *inp0; + // standard get char, uses conversion table // and converts to wide -#define getchr(inp) inp->stream_wgetc_for_read(inp - GLOBAL_Stream) +static inline int getchr(struct stream_desc *inp) +{ + if (inp != inp0) { fprintf(stderr,"\n %s **********************************\n", AtomName(inp->name)); + inp0 = inp; + } + int ch = inp->stream_wgetc_for_read(inp - GLOBAL_Stream); + // fprintf(stderr,"%c", ch); + return ch; +} // get char for quoted data, eg, quoted atoms and so on // converts to wide -#define getchrq(inp) inp->stream_wgetc(inp - GLOBAL_Stream) -// get char for UTF-8 quoted data, eg, quoted strings -// reads bytes -#define getchru(inp) inp->stream_getc_utf8(inp - GLOBAL_Stream) +static inline int getchrq(struct stream_desc *inp) +{ + int ch = inp->stream_wgetc(inp - GLOBAL_Stream); + return ch; +} /* in case there is an overflow */ typedef struct scanner_extra_alloc { diff --git a/C/threads.c b/C/threads.c index 96f51175e..2101f2642 100644 --- a/C/threads.c +++ b/C/threads.c @@ -384,7 +384,7 @@ setup_engine(int myworker_id, int init_thread) // create a mbox mboxCreate( MkIntTerm(myworker_id), &REMOTE_ThreadHandle(myworker_id).mbox_handle PASS_REGS ); Yap_InitTime( myworker_id ); - Yap_InitYaamRegs( myworker_id ); + Yap_InitYaamRegs( myworker_id, true] ); REFRESH_CACHE_REGS Yap_ReleasePreAllocCodeSpace(Yap_PreAllocCodeSpace()); /* I exist */ diff --git a/C/write.c b/C/write.c index bcf6613a5..af447d555 100644 --- a/C/write.c +++ b/C/write.c @@ -1216,6 +1216,8 @@ static void wrputref(CODEADDR ref, int Quote_illegal, struct rewind_term rwt; yhandle_t sls = Yap_CurrentSlot(); + if (t==0) + return; if (!mywrite) { CACHE_REGS wglb.stream = GLOBAL_Stream + LOCAL_c_error_stream; diff --git a/C/yap-args.c b/C/yap-args.c index 573964e8a..0b91d2afe 100755 --- a/C/yap-args.c +++ b/C/yap-args.c @@ -63,6 +63,98 @@ #endif +X_API bool YAP_initialized = false; +static int n_mdelays = 0; +static YAP_delaymodule_t *m_delays; + +static void init_globals(YAP_init_args *yap_init) { + GLOBAL_FAST_BOOT_FLAG = yap_init->FastBoot; +#if defined(YAPOR) || defined(TABLING) + + Yap_init_root_frames(); + +#endif /* YAPOR || TABLING */ +#ifdef YAPOR + Yap_init_yapor_workers(); +#if YAPOR_THREADS + if (Yap_thread_self() != 0) { +#else + if (worker_id != 0) { +#endif +#if defined(YAPOR_COPY) || defined(YAPOR_SBA) + /* + In the SBA we cannot just happily inherit registers + from the other workers + */ + Yap_InitYaamRegs(worker_id, true); +#endif /* YAPOR_COPY || YAPOR_SBA */ +#ifndef YAPOR_THREADS + Yap_InitPreAllocCodeSpace(0); +#endif /* YAPOR_THREADS */ + /* slaves, waiting for work */ + CurrentModule = USER_MODULE; + P = GETWORK_FIRST_TIME; + Yap_exec_absmi(FALSE, YAP_EXEC_ABSMI); + Yap_Error(SYSTEM_ERROR_INTERNAL, TermNil, + "abstract machine unexpected exit (YAP_Init)"); + } +#endif /* YAPOR */ + RECOVER_MACHINE_REGS(); + /* make sure we do this after restore */ + if (yap_init->MaxStackSize) { + GLOBAL_AllowLocalExpansion = FALSE; + } else { + GLOBAL_AllowLocalExpansion = TRUE; + } + if (yap_init->MaxGlobalSize) { + GLOBAL_AllowGlobalExpansion = FALSE; + } else { + GLOBAL_AllowGlobalExpansion = TRUE; + } + if (yap_init->MaxTrailSize) { + GLOBAL_AllowTrailExpansion = FALSE; + } else { + GLOBAL_AllowTrailExpansion = TRUE; + } + if (yap_init->PrologRCFile) { + Yap_PutValue(AtomConsultOnBoot, + MkAtomTerm(Yap_LookupAtom(yap_init->PrologRCFile))); + /* + This must be done again after restore, as yap_flags + has been overwritten .... + */ + setBooleanGlobalPrologFlag(HALT_AFTER_CONSULT_FLAG, + yap_init->HaltAfterConsult); + } + if (yap_init->PrologTopLevelGoal) { + Yap_PutValue(AtomTopLevelGoal, + MkAtomTerm(Yap_LookupAtom(yap_init->PrologTopLevelGoal))); + } + if (yap_init->PrologGoal) { + Yap_PutValue(AtomInitGoal, + MkAtomTerm(Yap_LookupAtom(yap_init->PrologGoal))); + } + if (yap_init->PrologAddPath) { + Yap_PutValue(AtomExtendFileSearchPath, + MkAtomTerm(Yap_LookupAtom(yap_init->PrologAddPath))); + } + + if (yap_init->QuietMode) { + setVerbosity(TermSilent); + } +} + +static void start_modules(void) { + Term cm = CurrentModule; + size_t i; + for (i = 0; i < n_mdelays; i++) { + CurrentModule = MkAtomTerm(YAP_LookupAtom(m_delays[i].s)); + m_delays[i].f(); + } + CurrentModule = cm; +} + + const char *Yap_BINDIR, *Yap_ROOTDIR, *Yap_SHAREDIR, *Yap_LIBDIR, *Yap_DLLDIR, *Yap_PLDIR, *Yap_BOOTPLDIR, *Yap_BOOTSTRAPPLDIR, *Yap_COMMONSDIR, *Yap_STARTUP, *Yap_BOOTFILE; @@ -70,11 +162,12 @@ const char *Yap_BINDIR, *Yap_ROOTDIR, *Yap_SHAREDIR, *Yap_LIBDIR, *Yap_DLLDIR, static int yap_lineno = 0; /* do initial boot by consulting the file boot.yap */ -static void do_bootfile(const char *b_file USES_REGS) { +static void consult(const char *b_file USES_REGS) { Term t; int boot_stream, osno; Functor functor_query = Yap_MkFunctor(Yap_LookupAtom("?-"), 1); Functor functor_command1 = Yap_MkFunctor(Yap_LookupAtom(":-"), 1); + Functor functor_compile2 = Yap_MkFunctor(Yap_LookupAtom("c_compile"), 2); /* consult boot.pl */ char *full = malloc(YAP_FILENAME_MAX + 1); @@ -85,29 +178,27 @@ static void do_bootfile(const char *b_file USES_REGS) { fprintf(stderr, "[ FATAL ERROR: could not open boot_stream %s ]\n", b_file); exit(1); } - free(full); - setAtomicGlobalPrologFlag(RESOURCE_DATABASE_FLAG, - MkAtomTerm(GLOBAL_Stream[boot_stream].name)); - do { + +do { CACHE_REGS - YAP_Reset(YAP_FULL_RESET); + YAP_Reset(YAP_FULL_RESET, false); Yap_StartSlots(); t = YAP_ReadClauseFromStream(boot_stream); - - // Yap_DebugPlWriteln(t); + //Yap_GetNèwSlot(t); if (t == 0) { fprintf(stderr, "[ SYNTAX ERROR: while parsing boot_stream %s at line %d ]\n", b_file, yap_lineno); - } else if (YAP_IsVarTerm(t) || t == TermNil) { + } else if (IsVarTerm(t) || t == TermNil) { fprintf(stderr, "[ line %d: term cannot be compiled ]", yap_lineno); - } else if (YAP_IsPairTerm(t)) { - fprintf(stderr, "[ SYSTEM ERROR: consult not allowed in boot file ]\n"); - fprintf(stderr, "error found at line %d and pos %d", yap_lineno, - fseek(GLOBAL_Stream[boot_stream].file, 0L, SEEK_CUR)); } else if (IsApplTerm(t) && (FunctorOfTerm(t) == functor_query || FunctorOfTerm(t) == functor_command1)) { - YAP_RunGoalOnce(ArgOfTerm(1, t)); + t = ArgOfTerm(1, t); + if (IsApplTerm(t) && FunctorOfTerm(t) == functor_compile2) { + consult( RepAtom(AtomOfTerm(ArgOfTerm(1,t)))->StrOfAE); + } else { + YAP_RunGoalOnce(t); + } } else { Term ts[2]; char *ErrorMessage; @@ -128,7 +219,8 @@ static void do_bootfile(const char *b_file USES_REGS) { } while (t != TermEof); BACKUP_MACHINE_REGS(); - YAP_EndConsult(boot_stream, &osno); + YAP_EndConsult(boot_stream, &osno, full); + free(full); #if DEBUG if (Yap_output_msg) fprintf(stderr, "Boot loaded\n"); @@ -140,46 +232,77 @@ static void do_bootfile(const char *b_file USES_REGS) { * @long The options are * `[V]` use a configuration variable YAP_XXXDIR, prefixed by "DESTDIR" * `(V)PATH` compute V and add /PATH, - * `$V` search the envurinment + * `$V` search the environment * `?V` search the WINDOWS registry * ~` search HOME * `@` query user option. * */ -const char *rootdirs[] = {"[root]", "(execdir)..", "/usr/local", "/", "/usr", - "/opt", "$HOME", "$PWD", NULL}; +typedef struct config { + char *name; + const char * *root; +const char * *lib; +const char * *share; +const char * *include; +const char * *pl; +const char * *commons; +const char * *dll; + const char * *ss; + const char * *bootpl; +} config_t; -const char *bindirs[] = {"[bin]", "(root)bin", NULL}; +const char *gd_root[] = {"@RootDir","[root]", "(execdir).."}; +const char *gd_lib[] = {"@LibDir","[lib]", "(root)lib"}; +const char *gd_share[] = {"@ShareDir","[share]", "(root)share"}; +const char *gd_include[] = {"@IncludeDir","[include]", "(root)include"}; +const char *gd_dll[] = {"@DLLDir","(lib)Yap"}; +const char *gd_pl[] = {"@PlDir","(share)Yap"}; +const char *gd_commons[] = {"@CommonsDir","(share)PrologCommons"}; +const char *gd_ss[] = {"@SavedState","(dll)startup.yss"}; +const char *gd_bootpl[] = {"@PrologBootFile","(pl)pl/boot.yap"}; -const char *libdirs[] = { -#if __ANDROID__ - "/assets/lib", -#endif - "[lib]", "(root)lib", NULL}; +static config_t *gnu(config_t *i) +{ + i->root = gd_root; + i->lib = gd_lib; + i->share = gd_share; + i->include = gd_include; + i->dll = gd_dll; + i->pl = gd_pl; + i->commons = gd_commons; + i->ss = gd_ss; + i->bootpl = gd_bootpl; -const char *sharedirs[] = { -#if __ANDROID__ - "/assets/share", -#endif - "[share]", "(root)share", NULL}; + return i; +} -const char *dlldirs[] = {"$YAPLIBDIR", "(lib)Yap", "$PWD", NULL}; +const char *build_root[] = {"."}; +const char *build_lib[] = {"."}; +const char *build_share[] = {"(src)"}; +const char *build_include[] = {"(src/include]"}; +const char *build_dll[] = {"."}; +const char *build_pl[] = {"pl"}; +const char *build_commons[] = {"PrologCommons"}; +const char *build_ss[] = {NULL}; +const char *build_bootpl[] = {"(pl)boot.yap"}; -const char *ssdirs[] = {"$PWD", "$YAPLIBDIR", "(lib)Yap", NULL}; -const char *pldirs[] = {"$YAPSHAREDIR", "?library", "(share)Yap", "$PWD", NULL}; - -const char *bootpldirs[] = {"(pl)pl", "$PWD", NULL}; - -const char *bootstrappldirs[] = {YAP_PL_SRCDIR, NULL}; - -const char *commonsdirs[] = {"(share)PrologCommons", "$PWD", NULL}; - -const char *ssnames[] = {"@SavedState", YAP_STARTUP, "startup.yss", NULL}; - -const char *plnames[] = {"@YapPrologBootFile", YAP_BOOTFILE, "boot.yap", NULL}; - -/** +static config_t *build(config_t *i) +{ +i->root = build_root; +i->lib = build_lib; +i->share = build_share; +i->include = build_include; +i->dll = build_dll; +i->pl = build_pl; +i->commons = build_commons; +i->ss = build_ss; +i->bootpl = build_bootpl; + return i; +} + + + /** * Search */ char *location(YAP_init_args *iap, const char *inp, char *out) { @@ -215,7 +338,7 @@ char *location(YAP_init_args *iap, const char *inp, char *out) { strcat(out, inp + strlen("(pl)")); } else if (strstr(inp + 1, "execdir") == inp + 1) { char *buf = Malloc(YAP_FILENAME_MAX + 1); - const char *ex = Yap_AbsoluteFile(Yap_FindExecutable(), buf, false); + const char *ex = Yap_AbsoluteFile(Yap_FindExecutable(), buf, false); if (ex != NULL) { strcpy(out, dirname((char *)ex)); strcat(out, "/"); @@ -224,9 +347,32 @@ char *location(YAP_init_args *iap, const char *inp, char *out) { } } else if (inp[0] == '@') { - if (strstr(inp + 1, "YapPrologBootFile") == inp + 1) { - const char *tmp; - tmp = iap->YapPrologBootFile; + if (strstr(inp + 1, "RootDir") == inp + 1) { + const char *tmp = iap->RootDir; + if (tmp && tmp[0]) + strcpy(out, tmp); + } else if (strstr(inp + 1, "LibDir") == inp + 1) { + const char *tmp = iap->LibDir; + if (tmp && tmp[0]) + strcpy(out, tmp); + } else if (strstr(inp + 1, "IncludeDir") == inp + 1) { + const char *tmp = iap->IncludeDir; + if (tmp && tmp[0]) + strcpy(out, tmp); + } else if (strstr(inp + 1, "SharedDir") == inp + 1) { + const char *tmp = iap->SharedDir; + if (tmp && tmp[0]) + strcpy(out, tmp); + } else if (strstr(inp + 1, "DLLDir") == inp + 1) { + const char *tmp = iap->DLLDir; + if (tmp && tmp[0]) + strcpy(out, tmp); + } else if (strstr(inp + 1, "PlDir") == inp + 1) { + const char *tmp = iap->SavedState; + if (tmp && tmp[0]) + strcpy(out, tmp); + } else if (strstr(inp + 1, "PrologBootFile") == inp + 1) { + const char *tmp = iap->PrologBootFile; if (tmp && tmp[0]) strcpy(out, tmp); } else if (strstr(inp + 1, "SavedState") == inp + 1) { @@ -322,7 +468,7 @@ static const char *find_directory(YAP_init_args *iap, const char *paths[], while ((inp = paths[i++]) != NULL) { out[0] = '\0'; char *o = location(iap, inp, out), *no; - if (o && o[0] && Yap_isDirectory(o)) { + if (o && o[0] && Yap_Exists(o)) { if (names) { size_t s = strlen(o); o[s++] = '/'; @@ -330,9 +476,13 @@ static const char *find_directory(YAP_init_args *iap, const char *paths[], int j = 0; while ((p = names[j++])) { char *io = o + s; - if ((no = location(iap, p, io)) && io[0] != '\0' && Yap_Exists(o)) - return pop_output_text_stack(lvl, realpath(o, full)); + if ((no = location(iap, p, io)) && io[0] != '\0' && Yap_Exists(o)) { + o = pop_output_text_stack(lvl, o); + o = realpath(o, full); + return o; + } + } } else { return pop_output_text_stack(lvl, o); } @@ -343,40 +493,19 @@ static const char *find_directory(YAP_init_args *iap, const char *paths[], } static void Yap_set_locations(YAP_init_args *iap) { -#if CONDA_BUILD - if (!getenv("DESTDIR")) { - int lvl = push_text_stack(); - const char *path = getenv("PATH"); - char *o = &path[0L], *no, *p; - char *buf = Malloc(YAP_FILENAME_MAX + 1); - o = Malloc(strlen(path) + 1); - strcpy(o, path); - if ((p = strstr(o, "anaconda"))) { - char *q = p + strlen("anaconda"), *r = strstr(q, "/bin"); - if (r - q > 0 && r - q < 10 && (r[4] == ':' || r[4] == '\0')) { - r[0] = '\0'; - q = strrchr(o, ':'); - if (q) - o = q + 1; - } else - o = NULL; - } - Yap_ROOTDIR = pop_output_text_stack(lvl, o); - } - if (!Yap_ROOTDIR) -#endif - Yap_ROOTDIR = find_directory(iap, rootdirs, NULL); - Yap_LIBDIR = find_directory(iap, libdirs, NULL); - Yap_BINDIR = find_directory(iap, bindirs, NULL); - Yap_SHAREDIR = find_directory(iap, sharedirs, NULL); - Yap_DLLDIR = find_directory(iap, dlldirs, NULL); - Yap_PLDIR = find_directory(iap, pldirs, NULL); - Yap_COMMONSDIR = find_directory(iap, commonsdirs, NULL); - Yap_STARTUP = find_directory(iap, ssdirs, ssnames); - if (iap->bootstrapping) - Yap_BOOTFILE = find_directory(iap, bootstrappldirs, plnames); - else - Yap_BOOTFILE = find_directory(iap, bootpldirs, plnames); + config_t t, *template; + + + template= gnu(&t); + Yap_ROOTDIR = find_directory(iap, template->root, NULL); + Yap_LIBDIR = find_directory(iap, template->lib, NULL); + //Yap_BINDIR = find_directory(iap, template->bin, NULL); + Yap_SHAREDIR = find_directory(iap, template->share, NULL); + Yap_DLLDIR = find_directory(iap, template->dll, NULL); + Yap_PLDIR = find_directory(iap, template->pl, NULL); + Yap_COMMONSDIR = find_directory(iap, template->commons, NULL); + Yap_STARTUP = find_directory(iap, template->ss, NULL); + Yap_BOOTFILE = find_directory(iap, template->bootpl, NULL); if (Yap_ROOTDIR) setAtomicGlobalPrologFlag(HOME_FLAG, MkAtomTerm(Yap_LookupAtom(Yap_ROOTDIR))); @@ -519,25 +648,25 @@ X_API YAP_file_type_t YAP_parse_yap_arguments(int argc, char *argv[], case 'b': iap->boot_file_type = YAP_PL; if (p[1]) - iap->YapPrologBootFile = p + 1; + iap->PrologBootFile = p + 1; else if (argv[1] && *argv[1] != '-') { - iap->YapPrologBootFile = *++argv; + iap->PrologBootFile = *++argv; argc--; } else { - iap->YapPrologBootFile = "boot.yap"; + iap->PrologBootFile = "boot.yap"; } break; case 'B': iap->boot_file_type = YAP_BOOT_PL; if (p[1]) - iap->YapPrologBootFile = p + 1; + iap->PrologBootFile = p + 1; else if (argv[1] && *argv[1] != '-') { - iap->YapPrologBootFile = *++argv; + iap->PrologBootFile = *++argv; argc--; } else { - iap->YapPrologBootFile = NULL; + iap->PrologBootFile = NULL; } - iap->bootstrapping = true; + iap->install = true; break; case '?': print_usage(); @@ -571,7 +700,7 @@ X_API YAP_file_type_t YAP_parse_yap_arguments(int argc, char *argv[], argc--; argv++; if (strcmp(*argv, "none")) { - iap->YapPrologRCFile = *argv; + iap->PrologRCFile = *argv; } break; } @@ -663,7 +792,7 @@ X_API YAP_file_type_t YAP_parse_yap_arguments(int argc, char *argv[], break; } if (ch) { - iap->YapPrologTopLevelGoal = add_end_dot(*argv); + iap->PrologTopLevelGoal = add_end_dot(*argv); } else { *ssize = i; } @@ -747,11 +876,11 @@ X_API YAP_file_type_t YAP_parse_yap_arguments(int argc, char *argv[], exit(1); } else if (!strcmp("--", *argv)) { /* shell script, the next entry should be the file itself */ - iap->YapPrologRCFile = argv[1]; + iap->PrologRCFile = argv[1]; argc = 1; break; } else { - iap->YapPrologRCFile = *argv; + iap->PrologRCFile = *argv; argc--; } if (*p) { @@ -772,7 +901,7 @@ X_API YAP_file_type_t YAP_parse_yap_arguments(int argc, char *argv[], /* run goal before top-level */ case 'g': if ((*argv)[0] == '\0') - iap->YapPrologGoal = *argv; + iap->PrologGoal = *argv; else { argc--; if (argc == 0) { @@ -781,13 +910,13 @@ X_API YAP_file_type_t YAP_parse_yap_arguments(int argc, char *argv[], exit(EXIT_FAILURE); } argv++; - iap->YapPrologGoal = *argv; + iap->PrologGoal = *argv; } break; /* run goal as top-level */ case 'z': if ((*argv)[0] == '\0') - iap->YapPrologTopLevelGoal = *argv; + iap->PrologTopLevelGoal = *argv; else { argc--; if (argc == 0) { @@ -796,7 +925,7 @@ X_API YAP_file_type_t YAP_parse_yap_arguments(int argc, char *argv[], exit(EXIT_FAILURE); } argv++; - iap->YapPrologTopLevelGoal = add_end_dot(*argv); + iap->PrologTopLevelGoal = add_end_dot(*argv); } break; case 'n': @@ -809,8 +938,24 @@ X_API YAP_file_type_t YAP_parse_yap_arguments(int argc, char *argv[], if (!strcmp("-nosignals", p)) { iap->PrologCannotHandleInterrupts = true; break; + } else if (!strncmp("-output-saved-state=", p, strlen("-output-saved-state="))) { + iap->OutputSavedState = p + strlen("-output-saved-state="); } else if (!strncmp("-home=", p, strlen("-home="))) { - GLOBAL_Home = p + strlen("-home="); + iap->RootDir = p + strlen("-home="); + } else if (!strncmp("-system-library-directory=", p, strlen("-system-library-directory="))) { + iap->LibDir = p + strlen("-system-library-directory="); + } else if (!strncmp("-system-shared-directory=", p, strlen("-system-shared-directory="))) { + iap->SharedDir = p + strlen("-system-shared-directory="); + } else if (!strncmp("-prolog-library-directory=", p, strlen("-prolog-library-directory="))) { + iap->PlDir = p + strlen("-prolog-library-directory="); + } else if (!strncmp("-dll-library-directory=", p, strlen("-dll-library-directory="))) { + iap->DLLDir = p + strlen("-dll-library-directory="); + } else if (!strncmp("-home=", p, strlen("-home="))) { + iap->RootDir = p + strlen("-home="); + } else if (!strncmp("-home=", p, strlen("-home="))) { + iap->RootDir = p + strlen("-home="); + } else if (!strncmp("-home=", p, strlen("-home="))) { + iap->RootDir = p + strlen("-home="); } else if (!strncmp("-cwd=", p, strlen("-cwd="))) { if (!Yap_ChDir(p + strlen("-cwd="))) { fprintf(stderr, " [ YAP unrecoverable error in setting cwd: %s ]\n", @@ -828,10 +973,22 @@ X_API YAP_file_type_t YAP_parse_yap_arguments(int argc, char *argv[], ssize = &(iap->HeapSize); p += strlen("-heap="); goto GetSize; + } else if (!strncmp("-max-stack=", p, strlen("-max-stack="))) { + ssize = &(iap->MaxStackSize); + p += strlen("-max-stack="); + goto GetSize; + } else if (!strncmp("-max-trail=", p, strlen("-max-trail="))) { + ssize = &(iap->MaxTrailSize); + p += strlen("-max-trail="); + goto GetSize; + } else if (!strncmp("-max-heap=", p, strlen("-max-heap="))) { + ssize = &(iap->MaxHeapSize); + p += strlen("-max-heap="); + goto GetSize; } else if (!strncmp("-goal=", p, strlen("-goal="))) { - iap->YapPrologGoal = p + strlen("-goal="); + iap->PrologGoal = p + strlen("-goal="); } else if (!strncmp("-top-level=", p, strlen("-top-level="))) { - iap->YapPrologTopLevelGoal = p + strlen("-top-level="); + iap->PrologTopLevelGoal = p + strlen("-top-level="); } else if (!strncmp("-table=", p, strlen("-table="))) { ssize = &(iap->MaxTableSpaceSize); p += strlen("-table="); @@ -845,7 +1002,7 @@ X_API YAP_file_type_t YAP_parse_yap_arguments(int argc, char *argv[], break; case 'p': if ((*argv)[0] == '\0') - iap->YapPrologAddPath = *argv; + iap->PrologAddPath = *argv; else { argc--; if (argc == 0) { @@ -854,7 +1011,7 @@ X_API YAP_file_type_t YAP_parse_yap_arguments(int argc, char *argv[], exit(EXIT_FAILURE); } argv++; - iap->YapPrologAddPath = *argv; + iap->PrologAddPath = *argv; } break; /* nf: Begin preprocessor code */ @@ -903,10 +1060,6 @@ X_API YAP_file_type_t YAP_parse_yap_arguments(int argc, char *argv[], the module. */ -X_API bool YAP_initialized = false; -static int n_mdelays = 0; -static YAP_delaymodule_t *m_delays; - X_API bool YAP_DelayInit(YAP_ModInit_t f, const char s[]) { if (m_delays) { m_delays = realloc(m_delays, (n_mdelays + 1) * sizeof(YAP_delaymodule_t)); @@ -930,16 +1083,6 @@ bool Yap_LateInit(const char s[]) { return false; } -static void start_modules(void) { - Term cm = CurrentModule; - size_t i; - for (i = 0; i < n_mdelays; i++) { - CurrentModule = MkAtomTerm(YAP_LookupAtom(m_delays[i].s)); - m_delays[i].f(); - } - CurrentModule = cm; -} - /// whether Yap is under control of some other system bool Yap_embedded = true; @@ -991,90 +1134,9 @@ static void init_hw(YAP_init_args *yap_init, struct ssz_t *spt) { #endif } -static void init_globals(YAP_init_args *yap_init) { - GLOBAL_FAST_BOOT_FLAG = yap_init->FastBoot; -#if defined(YAPOR) || defined(TABLING) - - Yap_init_root_frames(); - -#endif /* YAPOR || TABLING */ -#ifdef YAPOR - Yap_init_yapor_workers(); -#if YAPOR_THREADS - if (Yap_thread_self() != 0) { -#else - if (worker_id != 0) { -#endif -#if defined(YAPOR_COPY) || defined(YAPOR_SBA) - /* - In the SBA we cannot just happily inherit registers - from the other workers - */ - Yap_InitYaamRegs(worker_id); -#endif /* YAPOR_COPY || YAPOR_SBA */ -#ifndef YAPOR_THREADS - Yap_InitPreAllocCodeSpace(0); -#endif /* YAPOR_THREADS */ - /* slaves, waiting for work */ - CurrentModule = USER_MODULE; - P = GETWORK_FIRST_TIME; - Yap_exec_absmi(FALSE, YAP_EXEC_ABSMI); - Yap_Error(SYSTEM_ERROR_INTERNAL, TermNil, - "abstract machine unexpected exit (YAP_Init)"); - } -#endif /* YAPOR */ - RECOVER_MACHINE_REGS(); - /* make sure we do this after restore */ - if (yap_init->MaxStackSize) { - GLOBAL_AllowLocalExpansion = FALSE; - } else { - GLOBAL_AllowLocalExpansion = TRUE; - } - if (yap_init->MaxGlobalSize) { - GLOBAL_AllowGlobalExpansion = FALSE; - } else { - GLOBAL_AllowGlobalExpansion = TRUE; - } - if (yap_init->MaxTrailSize) { - GLOBAL_AllowTrailExpansion = FALSE; - } else { - GLOBAL_AllowTrailExpansion = TRUE; - } - if (yap_init->YapPrologRCFile) { - Yap_PutValue(AtomConsultOnBoot, - MkAtomTerm(Yap_LookupAtom(yap_init->YapPrologRCFile))); - /* - This must be done again after restore, as yap_flags - has been overwritten .... - */ - setBooleanGlobalPrologFlag(HALT_AFTER_CONSULT_FLAG, - yap_init->HaltAfterConsult); - } - if (yap_init->YapPrologTopLevelGoal) { - Yap_PutValue(AtomTopLevelGoal, - MkAtomTerm(Yap_LookupAtom(yap_init->YapPrologTopLevelGoal))); - } - if (yap_init->YapPrologGoal) { - Yap_PutValue(AtomInitGoal, - MkAtomTerm(Yap_LookupAtom(yap_init->YapPrologGoal))); - } - if (yap_init->YapPrologAddPath) { - Yap_PutValue(AtomExtendFileSearchPath, - MkAtomTerm(Yap_LookupAtom(yap_init->YapPrologAddPath))); - } - - if (yap_init->QuietMode) { - setVerbosity(TermSilent); - } -} - static YAP_file_type_t end_init(YAP_init_args *yap_init, YAP_file_type_t rc) { - init_globals(yap_init); - LOCAL_PrologMode &= ~BootMode; - - start_modules(); - YAP_initialized = true; + LOCAL_PrologMode &= ~BootMode; return rc; } @@ -1106,7 +1168,7 @@ X_API YAP_file_type_t YAP_Init(YAP_init_args *yap_init) { if (yap_init->QuietMode) { setVerbosity(TermSilent); } - if (yap_init->YapPrologRCFile != NULL) { + if (yap_init->PrologRCFile != NULL) { /* This must be done before restore, otherwise restore will print out messages .... @@ -1122,10 +1184,18 @@ X_API YAP_file_type_t YAP_Init(YAP_init_args *yap_init) { Yap_Restore(Yap_STARTUP)) { setBooleanGlobalPrologFlag(SAVED_PROGRAM_FLAG, true); CurrentModule = LOCAL_SourceModule = USER_MODULE; - return end_init(yap_init, YAP_QLY); + init_globals(yap_init); + + start_modules(); +return end_init(yap_init, YAP_QLY); } else { - do_bootfile(Yap_BOOTFILE PASS_REGS); - setBooleanGlobalPrologFlag(SAVED_PROGRAM_FLAG, false); + init_globals(yap_init); + + start_modules(); + consult(Yap_BOOTFILE PASS_REGS); + setAtomicGlobalPrologFlag(RESOURCE_DATABASE_FLAG, + MkAtomTerm(Yap_BOOTFILE)); + setBooleanGlobalPrologFlag(SAVED_PROGRAM_FLAG, false); return end_init(yap_init, YAP_BOOT_PL); } } @@ -1153,6 +1223,7 @@ X_API YAP_file_type_t YAP_FastInit(char *saved_state, int argc, char *argv[]) { YAP_init_args init_args; YAP_file_type_t out; + if ((out = Yap_InitDefaults(&init_args, saved_state, argc, argv)) != YAP_FOUND_BOOT_ERROR) out = YAP_Init(&init_args); diff --git a/CMakeLists.txt b/CMakeLists.txt index cbabf24b8..578f17e9d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -528,7 +528,7 @@ List(APPEND YLIBS $) List(APPEND YLIBS $) List(APPEND YLIBS $) List(APPEND YLIBS $) -if (WIN32) +if (WIN32 OR ANDROID) List(APPEND YLIBS $) List(APPEND YLIBS $) if (WITH_PYTHON) diff --git a/CXX/yapdb.hh b/CXX/yapdb.hh index f7d132c19..d4838b5f3 100644 --- a/CXX/yapdb.hh +++ b/CXX/yapdb.hh @@ -119,6 +119,7 @@ protected: YAPTerm tt = YAPTerm(tout); ap = getPred(tt, modp); } + YAPPredicate(Term &t, Term &tmod, CELL * &ts, const char *pname); /// Term constructor for predicates /// diff --git a/CXX/yapi.cpp b/CXX/yapi.cpp index 7acb291b8..6b0531a7a 100644 --- a/CXX/yapi.cpp +++ b/CXX/yapi.cpp @@ -3,6 +3,7 @@ #define _EXPORT_KERNEL 1 #include "yapi.hh" + extern "C" { #if __ANDROID__ @@ -25,6 +26,45 @@ X_API bool do_init_python(void); #endif } + +YAPPredicate::YAPPredicate(Term &t, Term &tmod, CELL * &ts, const char *pname) { + Term t0 = t; + ap = nullptr; + restart: + if (IsVarTerm(t)) { + Yap_Error(INSTANTIATION_ERROR, t0, pname); + } else if (IsAtomTerm(t)) { + ap = RepPredProp(Yap_GetPredPropByAtom(AtomOfTerm(t), tmod)); + ts = nullptr; + } else if (IsIntegerTerm(t) && tmod == IDB_MODULE) { + ts = nullptr; + ap = Yap_FindLUIntKey(IntegerOfTerm(t)); + } else if (IsPairTerm(t)) { + t = Yap_MkApplTerm(FunctorCsult, 1, &t); + goto restart; + } else if (IsApplTerm(t)) { + Functor fun = FunctorOfTerm(t); + if (IsExtensionFunctor(fun)) { + Yap_Error(TYPE_ERROR_CALLABLE, Yap_PredicateIndicator(t, tmod), pname); + } + if (fun == FunctorModule) { + tmod = ArgOfTerm(1, t); + if (IsVarTerm(tmod)) { + Yap_Error(INSTANTIATION_ERROR, t0, pname); + } + if (!IsAtomTerm(tmod)) { + Yap_Error(TYPE_ERROR_ATOM, t0, pname); + } + t = ArgOfTerm(2, t); + goto restart; + } + ap = RepPredProp(Yap_GetPredPropByFunc(fun, tmod)); + ts = RepAppl(t)+1; + } else { + Yap_Error(TYPE_ERROR_CALLABLE, t0, pname); + } +} + YAPAtomTerm::YAPAtomTerm(char *s) { // build string BACKUP_H(); @@ -384,11 +424,6 @@ bool YAPEngine::call(YAPPredicate ap, YAPTerm ts[]) { for (arity_t i = 0; i < arity; i++) XREGS[i + 1] = ts[i].term(); - if (ap.ap == nullptr || ap.ap->OpcodeOfPred == UNDEF_OPCODE) { - Term g = YAP_MkApplTerm(ap.ap->FunctorOfPred, arity, XREGS + 1); - ap = YAPPredicate(rewriteUndefEngineQuery(ap.ap, g, ap.ap->ModuleOfPred)); - } - q.CurSlot = Yap_StartSlots(); q.p = P; @@ -422,38 +457,30 @@ bool YAPEngine::mgoal(Term t, Term tmod) { CACHE_REGS BACKUP_MACHINE_REGS(); Term *ts = nullptr; - PredEntry *ap = Yap_get_pred(t, tmod, "C++"); - + Yap_DebugPlWriteln(tmod); + if (IsStringTerm(tmod)) + tmod = MkAtomTerm(Yap_LookupAtom(StringOfTerm(tmod))); + PredEntry *ap = (new YAPPredicate(t, tmod, ts, "C++"))->ap; + Yap_DebugPlWriteln(t); if (ap == nullptr || ap->OpcodeOfPred == UNDEF_OPCODE) { ap = rewriteUndefEngineQuery(ap, t, tmod); - if (ap == nullptr || ap->OpcodeOfPred == UNDEF_OPCODE) - return false; - } else { - /* legal ap */ - arity_t arity = ap->ArityOfPE; - - if (arity) { - if (IsApplTerm(t)) { - ts = RepAppl(t) + 1; - } else { - ts = RepPair(t); - } - for (arity_t i = 0; i < arity; i++) - XREGS[i + 1] = ts[i]; - } else if (IsAtomTerm(t)) { - ts = nullptr; - } } + /* legal ap */ + arity_t arity = ap->ArityOfPE; + + for (arity_t i = 0; i < arity; i++) { + XREGS[i + 1] = ts[i]; + } + ts = nullptr; bool result; q.CurSlot = Yap_StartSlots(); q.p = P; q.cp = CP; - // allow Prolog style exceotion handling + // allow Prolog style exception handling LOCAL_RestartEnv = &buf; if (sigsetjmp(*LOCAL_RestartEnv, false)) { return false; - return 0; - throw YAPError(); + //throw YAPError(); } // don't forget, on success these guys may create slots __android_log_print(ANDROID_LOG_INFO, "YAPDroid", "exec "); @@ -470,7 +497,7 @@ bool YAPEngine::mgoal(Term t, Term tmod) { Yap_CloseHandles(q.CurSlot); LOCAL_RestartEnv = oldp; return 0; - throw e; + //throw e; } } @@ -529,8 +556,10 @@ Term YAPEngine::fun(Term t) { sigjmp_buf buf, *oldp = LOCAL_RestartEnv; LOCAL_RestartEnv = &buf; if (sigsetjmp(*LOCAL_RestartEnv, false)) { - return false; - throw YAPError(); + // throw YAPError(); + LOCAL_RestartEnv = oldp; + RECOVER_MACHINE_REGS(); + return 0; } // don't forget, on success these guys may create slots __android_log_print(ANDROID_LOG_INFO, "YAPDroid", "exec "); @@ -578,7 +607,7 @@ YAPQuery::YAPQuery(YAPFunctor f, YAPTerm mod, YAPTerm ts[]) goal = MkVarTerm(); } openQuery(); - names = YAPPairTerm(TermNil); + names = YAPPairTerm(TermNil); RECOVER_MACHINE_REGS(); } @@ -603,16 +632,16 @@ YAPQuery::YAPQuery(YAPTerm t) : YAPPredicate(t) { BACKUP_MACHINE_REGS(); CELL *nts; Term tt = t.term(); - goal = *new YAPTerm(tt); if (IsPairTerm(tt)) { nts = RepPair(tt); tt = Yap_MkApplTerm(FunctorCsult, 1, nts); } + goal = *new YAPTerm(tt); if (IsApplTerm(tt)) { Functor f = FunctorOfTerm(tt); if (!IsExtensionFunctor(f)) { nts = nullptr; - arity_t arity = ap->ArityOfPE; + arity_t arity = ArityOfFunctor(f); if (arity) { nts = RepAppl(tt) + 1; for (arity_t i = 0; i < arity; i++) @@ -704,21 +733,21 @@ bool YAPQuery::next() { } PredEntry *YAPQuery::rewriteUndefQuery() { - Term ts[3]; - ARG1 = ts[0] = goal.term(); - ARG2 = ts[1] = ap->ModuleOfPred; - ARG3 = ts[2] = Yap_cp_as_integer(B PASS_REGS); - goal = YAPApplTerm(FunctorUndefinedQuery, ts); - return ap = PredUndefinedQuery; + ARG1 = goal.term(); + goal = YAPApplTerm(FunctorMetaCall, &ARG1); + return ap = PredCall; } -PredEntry *YAPEngine::rewriteUndefEngineQuery(PredEntry *a, Term goal, +PredEntry *YAPEngine::rewriteUndefEngineQuery(PredEntry *a, Term tgoal, Term mod) { - Term ts[3]; - ARG1 = ts[0] = goal; - ARG2 = ts[1] = mod; - ARG3 = ts[2] = Yap_cp_as_integer(B PASS_REGS); - return PredUndefinedQuery; + Term ts[2]; + ts[0] = mod; + ts[1] = tgoal; + ARG1 = Yap_MkApplTerm(FunctorModule, 2, ts); + //goal = YAPTerm(Yap_MkApplTerm(FunctorMetaCall, 1, &ARG1)); + return PredCall; + + // return YAPApplTerm(FunctorUndefinedQuery, ts); } diff --git a/CXX/yapi.hh b/CXX/yapi.hh index 44bcf5d1c..70c1b9faa 100644 --- a/CXX/yapi.hh +++ b/CXX/yapi.hh @@ -29,6 +29,9 @@ * interface. * */ + +extern "C" { + #include #include @@ -37,8 +40,6 @@ #include -extern "C" { - #include #include "Yap.h" diff --git a/CXX/yapq.hh b/CXX/yapq.hh index 2f7be4810..cc83e634d 100644 --- a/CXX/yapq.hh +++ b/CXX/yapq.hh @@ -109,14 +109,12 @@ public: if (IsApplTerm(tgoal)) { Functor f = FunctorOfTerm(tgoal); if (!IsExtensionFunctor(f)) { - if (!IsExtensionFunctor(f)) { arity_t arity = ap->ArityOfPE; if (arity) { qt = RepAppl(tgoal) + 1; for (arity_t i = 0; i < arity; i++) XREGS[i + 1] = qt[i]; } - } } } names = YAPPairTerm(tnames); @@ -125,7 +123,6 @@ public: // inline YAPQuery() : YAPPredicate(s, tgoal, tnames) // { // __android_log_print(ANDROID_LOG_INFO, "YAPDroid", "got game %ld", - // LOCAL_CurSlot); // if (!ap) // return; // __android_log_print(ANDROID_LOG_INFO, "YAPDroid", "%s", vnames.text()); @@ -219,19 +216,19 @@ public: inline bool getMaxTrailSize() { return MaxTrailSize; }; - inline void setYapLibDir(const char *fl) { - YapLibDir = (const char *)malloc(strlen(fl) + 1); - strcpy((char *)YapLibDir, fl); + inline void setLibDir(const char *fl) { + LibDir = (const char *)malloc(strlen(fl) + 1); + strcpy((char *)LibDir, fl); }; - inline const char *getYapLibDir() { return YapLibDir; }; + inline const char *getLibDir() { return LibDir; }; - inline void setYapShareDir(const char *fl) { - YapShareDir = (const char *)malloc(strlen(fl) + 1); - strcpy((char *)YapShareDir, fl); + inline void setSharedDir(const char *fl) { + SharedDir = (const char *)malloc(strlen(fl) + 1); + strcpy((char *)SharedDir, fl); }; - inline const char *getYapShareDir() { return YapShareDir; }; + inline const char *getSharedDir() { return SharedDir; }; inline void setSavedState(const char *fl) { SavedState = (const char *)malloc(strlen(fl) + 1); @@ -240,23 +237,23 @@ public: inline const char *getSavedState() { return SavedState; }; - inline void setYapPrologBootFile(const char *fl) { - YapPrologBootFile = (const char *)malloc(strlen(fl) + 1); - strcpy((char *)YapPrologBootFile, fl); + inline void setPrologBootFile(const char *fl) { + PrologBootFile = (const char *)malloc(strlen(fl) + 1); + strcpy((char *)PrologBootFile, fl); }; - inline const char *getYapPrologBootFile() { return YapPrologBootFile; }; + inline const char *getPrologBootFile() { return PrologBootFile; }; - inline void setYapPrologGoal(const char *fl) { YapPrologGoal = fl; }; + inline void setPrologGoal(const char *fl) { PrologGoal = fl; }; - inline const char *getYapPrologGoal() { return YapPrologGoal; }; + inline const char *getPrologGoal() { return PrologGoal; }; - inline void setYapPrologTopLevelGoal(const char *fl) { - YapPrologTopLevelGoal = fl; + inline void setPrologTopLevelGoal(const char *fl) { + PrologTopLevelGoal = fl; }; - inline const char *getYapPrologTopLevelGoal() { - return YapPrologTopLevelGoal; + inline const char *getPrologTopLevelGoal() { + return PrologTopLevelGoal; }; inline void setHaltAfterConsult(bool fl) { HaltAfterConsult = fl; }; diff --git a/H/HEAPFIELDS b/H/HEAPFIELDS index 5495d5a00..795f8e255 100644 --- a/H/HEAPFIELDS +++ b/H/HEAPFIELDS @@ -140,7 +140,7 @@ rwlock_t PredHashRWLock void /* Well-Known Predicates */ struct pred_entry *CreepCode MkPred AtomCreep 1 PROLOG_MODULE -struct pred_entry *UndefCode MkPred AtomUndefp0 2 PROLOG_MODULE +struct pred_entry *UndefCode MkPred AtomUndefp 2 PROLOG_MODULE struct pred_entry *SpyCode MkPred AtomSpy 1 PROLOG_MODULE struct pred_entry *PredFail MkPred AtomFail 0 PROLOG_MODULE struct pred_entry *PredTrue MkPred AtomTrue 0 PROLOG_MODULE @@ -157,6 +157,7 @@ struct pred_entry *PredIs MkPred FunctorIs PROLOG_MODULE struct pred_entry *PredLogUpdClause MkPred FunctorDoLogUpdClause PROLOG_MODULE struct pred_entry *PredLogUpdClauseErase MkPred FunctorDoLogUpdClauseErase PROLOG_MODULE struct pred_entry *PredLogUpdClause0 MkPred FunctorDoLogUpdClause PROLOG_MODULE +struct pred_entry *PredCall MkPred FunctorCall PROLOG_MODULE struct pred_entry *PredMetaCall MkPred FunctorMetaCall PROLOG_MODULE struct pred_entry *PredProtectStack MkPred FunctorProtectStack PROLOG_MODULE struct pred_entry *PredRecordedWithKey MkPred FunctorRecordedWithKey PROLOG_MODULE diff --git a/H/Yapproto.h b/H/Yapproto.h index 22dddeebe..efecad63b 100755 --- a/H/Yapproto.h +++ b/H/Yapproto.h @@ -210,7 +210,7 @@ extern bool Yap_Execute(Term t USES_REGS); /* exo.c */ extern void Yap_InitExoPreds(void); extern void Yap_udi_Interval_init(void); -extern bool Yap_Reset(yap_reset_t mode); +extern bool Yap_Reset(yap_reset_t mode, bool hard); /* foreign.c */ extern char *Yap_FindExecutable(void); @@ -237,8 +237,9 @@ extern void Yap_InitGlobals(void); extern Term Yap_SaveTerm(Term); extern Term Yap_SetGlobalVal(Atom, Term); extern Term Yap_GetGlobal(Atom); -extern Int Yap_DeleteGlobal(Atom); +extern Int Yap_DeleteGlobal(Atom); extern void Yap_AllocateDefaultArena(Int, Int, int); +extern CELL *Yap_ArenaLimit(Term arena); /* grow.c */ extern Int Yap_total_stack_shift_time(void); @@ -282,7 +283,7 @@ extern void Yap_KillStacks(int); #else extern void Yap_KillStacks(int); #endif -extern void Yap_InitYaamRegs(int); +extern void Yap_InitYaamRegs(int, bool full_reset); extern void Yap_ReInitWTime(void); extern int Yap_OpDec(int, char *, Atom, Term); extern void Yap_CloseScratchPad(void); diff --git a/H/generated/dhstruct.h b/H/generated/dhstruct.h index f71adc5c7..510ebd9a1 100644 --- a/H/generated/dhstruct.h +++ b/H/generated/dhstruct.h @@ -141,6 +141,7 @@ #define PredLogUpdClause Yap_heap_regs->PredLogUpdClause_ #define PredLogUpdClauseErase Yap_heap_regs->PredLogUpdClauseErase_ #define PredLogUpdClause0 Yap_heap_regs->PredLogUpdClause0_ +#define PredCall Yap_heap_regs->PredCall_ #define PredMetaCall Yap_heap_regs->PredMetaCall_ #define PredProtectStack Yap_heap_regs->PredProtectStack_ #define PredRecordedWithKey Yap_heap_regs->PredRecordedWithKey_ diff --git a/H/generated/h0struct.h b/H/generated/h0struct.h index a95b3105d..b405ecc25 100644 --- a/H/generated/h0struct.h +++ b/H/generated/h0struct.h @@ -145,6 +145,7 @@ EXTERNAL struct pred_entry *PredIs; EXTERNAL struct pred_entry *PredLogUpdClause; EXTERNAL struct pred_entry *PredLogUpdClauseErase; EXTERNAL struct pred_entry *PredLogUpdClause0; +EXTERNAL struct pred_entry *PredCall; EXTERNAL struct pred_entry *PredMetaCall; EXTERNAL struct pred_entry *PredProtectStack; EXTERNAL struct pred_entry *PredRecordedWithKey; diff --git a/H/generated/hstruct.h b/H/generated/hstruct.h index 9d73e4c5d..e62f90698 100755 --- a/H/generated/hstruct.h +++ b/H/generated/hstruct.h @@ -145,6 +145,7 @@ struct pred_entry *PredLogUpdClause_; struct pred_entry *PredLogUpdClauseErase_; struct pred_entry *PredLogUpdClause0_; + struct pred_entry *PredCall_; struct pred_entry *PredMetaCall_; struct pred_entry *PredProtectStack_; struct pred_entry *PredRecordedWithKey_; diff --git a/H/generated/iatoms.h b/H/generated/iatoms.h index 098f04e86..5ff0b2095 100644 --- a/H/generated/iatoms.h +++ b/H/generated/iatoms.h @@ -226,7 +226,8 @@ AtomMaximum = Yap_LookupAtom("maximum"); TermMaximum = MkAtomTerm(AtomMaximum); AtomMaxArity = Yap_LookupAtom("max_arity"); TermMaxArity = MkAtomTerm(AtomMaxArity); AtomMaxFiles = Yap_LookupAtom("max_files"); TermMaxFiles = MkAtomTerm(AtomMaxFiles); - AtomMegaClause = Yap_FullLookupAtom("$mega_clause"); TermMegaClause = MkAtomTerm(AtomMegaClause); + +AtomMegaClause = Yap_FullLookupAtom("$mega_clause"); TermMegaClause = MkAtomTerm(AtomMegaClause); AtomMetaCall = Yap_FullLookupAtom("$call"); TermMetaCall = MkAtomTerm(AtomMetaCall); AtomMfClause = Yap_FullLookupAtom("$mf_clause"); TermMfClause = MkAtomTerm(AtomMfClause); AtomMin = Yap_LookupAtom("min"); TermMin = MkAtomTerm(AtomMin); diff --git a/H/generated/ihstruct.h b/H/generated/ihstruct.h index 752cc2049..7ce75d9fa 100644 --- a/H/generated/ihstruct.h +++ b/H/generated/ihstruct.h @@ -124,7 +124,7 @@ #endif CreepCode = RepPredProp(PredPropByFunc(Yap_MkFunctor(AtomCreep,1),PROLOG_MODULE)); - UndefCode = RepPredProp(PredPropByFunc(Yap_MkFunctor(AtomUndefp0,2),PROLOG_MODULE)); + UndefCode = RepPredProp(PredPropByFunc(Yap_MkFunctor(AtomUndefp,2),PROLOG_MODULE)); SpyCode = RepPredProp(PredPropByFunc(Yap_MkFunctor(AtomSpy,1),PROLOG_MODULE)); PredFail = RepPredProp(PredPropByAtom(AtomFail,PROLOG_MODULE)); PredTrue = RepPredProp(PredPropByAtom(AtomTrue,PROLOG_MODULE)); @@ -141,6 +141,7 @@ PredLogUpdClause = RepPredProp(PredPropByFunc(FunctorDoLogUpdClause,PROLOG_MODULE)); PredLogUpdClauseErase = RepPredProp(PredPropByFunc(FunctorDoLogUpdClauseErase,PROLOG_MODULE)); PredLogUpdClause0 = RepPredProp(PredPropByFunc(FunctorDoLogUpdClause,PROLOG_MODULE)); + PredCall = RepPredProp(PredPropByFunc(FunctorCall,PROLOG_MODULE)); PredMetaCall = RepPredProp(PredPropByFunc(FunctorMetaCall,PROLOG_MODULE)); PredProtectStack = RepPredProp(PredPropByFunc(FunctorProtectStack,PROLOG_MODULE)); PredRecordedWithKey = RepPredProp(PredPropByFunc(FunctorRecordedWithKey,PROLOG_MODULE)); diff --git a/H/generated/rhstruct.h b/H/generated/rhstruct.h index 2677d387b..a846b195d 100644 --- a/H/generated/rhstruct.h +++ b/H/generated/rhstruct.h @@ -141,6 +141,7 @@ PredLogUpdClause = PtoPredAdjust(PredLogUpdClause); PredLogUpdClauseErase = PtoPredAdjust(PredLogUpdClauseErase); PredLogUpdClause0 = PtoPredAdjust(PredLogUpdClause0); + PredCall = PtoPredAdjust(PredCall); PredMetaCall = PtoPredAdjust(PredMetaCall); PredProtectStack = PtoPredAdjust(PredProtectStack); PredRecordedWithKey = PtoPredAdjust(PredRecordedWithKey); diff --git a/cmake/FindR.cmake b/cmake/FindR.cmake old mode 100755 new mode 100644 diff --git a/console/yap.c b/console/yap.c index f73011f29..f77deba53 100755 --- a/console/yap.c +++ b/console/yap.c @@ -102,7 +102,7 @@ static void exec_top_level(int BootMode, YAP_init_args *iap) { */ atomfalse = YAP_MkAtomTerm(YAP_FullLookupAtom("$false")); while (YAP_GetValue(livegoal) != atomfalse) { - YAP_Reset(YAP_FULL_RESET); + YAP_Reset(YAP_FULL_RESET, false); do_top_goal(YAP_MkAtomTerm(livegoal)); livegoal = YAP_FullLookupAtom("$live"); } @@ -141,7 +141,7 @@ int main(int argc, char **argv) } } - YAP_Reset(YAP_FULL_RESET); + YAP_Reset(YAP_FULL_RESET, false); /* End preprocessor code */ exec_top_level(BootMode, &init_args); diff --git a/include/VFS.h b/include/VFS.h index a11bfb199..a6d83427c 100644 --- a/include/VFS.h +++ b/include/VFS.h @@ -83,7 +83,8 @@ typedef struct vfs { /// in this space, usual w,r,a,b flags plus B (store in a buffer) bool (*close)(int sno); /// close the object int (*get_char)(int sno); /// get an octet from the stream - int (*peek_char)(int sno); /// unget an octet from the stream + int (*peek_char)(int sno); /// unget an octet from the stream + int (*peek_wchar)(int sno); /// unget an octet from the stream int (*put_char)(int sno, int ch); /// output an octet to the stream void (*flush)(int sno); /// flush a stream int64_t (*seek)(int sno, int64_t offset, diff --git a/include/YapDefs.h b/include/YapDefs.h index 67944d129..e42ab8951 100755 --- a/include/YapDefs.h +++ b/include/YapDefs.h @@ -182,10 +182,28 @@ X_API YAP_file_type_t Yap_InitDefaults(void *init_args, char saved_state[], typedef struct yap_boot_params { //> boot type as suggested by the user YAP_file_type_t boot_file_type; - //> bootstrapping mode: YAP is not properly installed - bool bootstrapping; + //> how files are organised: NULL is GNU/Linux way + // const char *directory_structure; + //> if NON-NULL, set value for Yap_ROOTDIR + const char *RootDir; + //> if NON-NULL, location of libYap, sets Yap_LIBDIR + const char *LibDir; + //> if NON-NULL, architecture independent files, sets Yap_SHAREDIR + const char *SharedDir; + //> if NON-NULL, include files, sets Yap_INCLUDEDIR + const char *IncludeDir; + //> if NON-NULL, Prolog DLL location, sets Yap_DLLDIR + const char *DLLDir; + //> if NON-NULL, Prolog library, sets Yap_DLLDIR + const char *PlDir; + //> if NON-NULL, name for a Prolog file to use when booting + const char *PrologBootFile; //> if NON-NULL, path where we can find the saved state const char *SavedState; + //> bootstrapping mode: YAP is not properly installed + bool install; + //> generats a saved space at this path + char *OutputSavedState; //> if NON-0, minimal size for Heap or Code Area size_t HeapSize; //> if NON-0, maximal size for Heap or Code Area @@ -204,28 +222,16 @@ typedef struct yap_boot_params { size_t AttsSize; //> if NON-0, maximal size for AttributeVarStack size_t MaxAttsSize; - //> if NON-NULL, value for YAPROOTDIR - const char *YapRootDir; - //> if NON-NULL, value for YAPLIBDIR - const char *YapLibDir; - //> if NON-NULL, value for YAPSHAREDIR, that is, default value for libraries - const char *YapShareDir; - //> if NON-NULL, value for YAPDLLDIR, that is, default value for libraries - const char *YapDLLDir; - //> if NON-NULL, value for YAPPLDIR, that is, default value for libraries - const char *YapPlDir; - //> if NON-NULL, name for a Prolog file to use when booting - const char *YapPrologBootFile; //> if NON-NULL, name for a Prolog file to use when initializing const char *YapPrologInitGoal; //> if NON-NULL, name for a Prolog file to consult before entering top-level - const char *YapPrologRCFile; + const char *PrologRCFile; //> if NON-NULL, a goal to run before top-level - const char *YapPrologGoal; + const char *PrologGoal; //> if NON-NULL, a goal to run as top-level - const char *YapPrologTopLevelGoal; + const char *PrologTopLevelGoal; //> if NON-NULL, a path to extend file-search-path - const char *YapPrologAddPath; + const char *PrologAddPath; //> if previous NON-NULL and TRUE, halt after consulting that file bool HaltAfterConsult; //> ignore .yaprc, .prolog.ini, etc. files. @@ -409,4 +415,4 @@ typedef struct { const char *s; } YAP_delaymodule_t; -#endif /* _YAPDEFS_H */ \ No newline at end of file +#endif /* _YAPDEFS_H */ diff --git a/include/YapInterface.h b/include/YapInterface.h index e67e595bd..96f68416b 100755 --- a/include/YapInterface.h +++ b/include/YapInterface.h @@ -356,7 +356,7 @@ extern X_API YAP_Bool YAP_GoalHasException(YAP_Term *); /* void YAP_ClearExceptions(void) */ extern X_API void YAP_ClearExceptions(void); -extern X_API int YAP_Reset(yap_reset_t reset); +extern X_API int YAP_Reset(yap_reset_t reset, bool reset_global); extern X_API void YAP_Error(int myerrno, YAP_Term t, const char *buf, ...); @@ -409,7 +409,7 @@ extern X_API FILE *YAP_TermToStream(YAP_Term t); extern X_API int YAP_InitConsult(int mode, const char *filename, char *buf, int *previous_sno); -extern X_API void YAP_EndConsult(int s, int *previous_sno); +extern X_API void YAP_EndConsult(int s, int *previous_sno, const char *previous_cwd); extern X_API void YAP_Exit(int); diff --git a/include/YapStreams.h b/include/YapStreams.h index b3c3a8cdd..2ff0c9910 100644 --- a/include/YapStreams.h +++ b/include/YapStreams.h @@ -230,11 +230,16 @@ typedef struct stream_desc { int fd; } socket; #endif - struct { + struct { const unsigned char *buf, *ptr; } irl; void *private_data; } u; + struct { + bool on; + int ch; + intptr_t pos, line, lpos; + } buf; YAP_Int charcount, linecount, linepos; stream_flags_t status; @@ -250,11 +255,11 @@ typedef struct stream_desc { int); /** function the stream uses for reading a character. */ struct vfs *vfs; /** stream belongs to a space */ void *vfs_handle; /** direct handle to stream in that space. */ - int (*stream_wgetc_for_read)( - int); /* function the stream uses for parser. It may be different + int (*stream_wgetc_for_read)(int); /** function the stream uses for parser. It may be different from above if the ISO character conversion is on */ + int (*stream_peek)(int); /** check if the next character is available. */ + int (*stream_wpeek)(int); /** check if the next wide character is available. */ encoding_t encoding; /** current encoding for stream */ -struct yapchlookahead *recbs; /// support arbitrary depth peek } StreamDesc; #endif diff --git a/library/dialect/swi/fli/swi.c b/library/dialect/swi/fli/swi.c index 16b4f31f1..8bc0b6119 100755 --- a/library/dialect/swi/fli/swi.c +++ b/library/dialect/swi/fli/swi.c @@ -2198,8 +2198,8 @@ X_API int PL_initialise(int myargc, char **myargv) { #else init_args.SavedState = NULL; #endif - init_args.YapLibDir = NULL; - init_args.YapPrologBootFile = NULL; + init_args.LibDir = NULL; + init_args.PrologBootFile = NULL; init_args.HaltAfterConsult = FALSE; init_args.FastBoot = FALSE; init_args.MaxTableSpaceSize = 0; diff --git a/os/CMakeLists.txt b/os/CMakeLists.txt index ccc16e8ed..dac6284cc 100644 --- a/os/CMakeLists.txt +++ b/os/CMakeLists.txt @@ -1,3 +1,8 @@ +set (YAPOS_HEADERS + getw.h + iopreds.h + yapio.h + ) set (YAPOS_SOURCES alias.c diff --git a/os/charsio.c b/os/charsio.c index 0284d51f3..13d0fbdf8 100644 --- a/os/charsio.c +++ b/os/charsio.c @@ -93,67 +93,133 @@ INLINE_ONLY inline EXTERN Int CharOfAtom(Atom at) { return val; } -int PopCode(int sno) { +int peekWideWithGetwc(int sno){ StreamDesc *s; - Int ch; - struct yapchlookahead *p; s = GLOBAL_Stream + sno; - if (!s->recbs) { - return EOF; - } - p = s->recbs; - ch = p->ch; - s->recbs = s->recbs->next; - free(p); - if (!s->recbs) - Yap_DefaultStreamOps(s); + int ch = getwc(s->file); + ungetwc(ch, s->file); return ch; } -static int peekCode(int sno, bool wide) { - Int ocharcount, olinecount, olinepos; + +int Yap_peekWithGetw(int sno) { StreamDesc *s; - Int ch; - struct yapchlookahead *recb = malloc(sizeof(struct yapchlookahead)), *r; - recb->next = NULL; s = GLOBAL_Stream + sno; - ocharcount = s->charcount; - olinecount = s->linecount; - olinepos = s->linepos; - if (wide) - recb->ch = ch = GLOBAL_Stream[sno].stream_wgetc(sno); - else - recb->ch = ch = GLOBAL_Stream[sno].stream_getc(sno); - if (ch == EOFCHAR) { - s->stream_getc = EOFPeek; - s->stream_wgetc = EOFWPeek; - s->status |= Push_Eof_Stream_f; - return ch; - } - recb->charcount = s->charcount; - recb->linecount = s->linecount; - recb->linepos = s->linepos; - s->charcount = ocharcount; - s->linecount = olinecount; - s->linepos = olinepos; - if (s->recbs) { - r = s->recbs; - while (r->next) { - r = r->next; - } - r->next = recb; + int ch = getc(s->file); + ungetc(ch, s->file); + return ch; +} + + +int Yap_peekWideWithSeek(int sno) { + StreamDesc *s; + s = GLOBAL_Stream + sno; + Int pos = s->charcount; + Int line = s->linecount; + Int lpos = s->linepos; + int ch = s->stream_wgetc(sno); + if (ch == EOF) { + if (s->file) clearerr(s->file); + s->status &= ~Eof_Error_Stream_f; + // do not try doing error processing } else { - s->recbs = recb; - } - /* buffer the character */ - GLOBAL_Stream[sno].stream_getc = PopCode; - GLOBAL_Stream[sno].stream_wgetc = PopCode; + Yap_SetCurInpPos(sno, pos); + s->charcount = pos; + s->linecount = line; + s->linepos = lpos; +} return ch; } -Int Yap_peek(int sno) { return peekCode(sno, true); } -static Int dopeek_byte(int sno) { return peekCode(sno, false); } +int Yap_peekWithSeek(int sno) { + StreamDesc *s; + s = GLOBAL_Stream + sno; + Int pos = s->charcount; + Int line = s->linecount; + Int lpos = s->linepos; + int ch = s->stream_getc(sno); + if (ch == EOF) { + if (s->file) clearerr(s->file); + s->status &= ~Eof_Error_Stream_f; + // do not try doing error processing + } else { + Yap_SetCurInpPos(sno, pos); + s->charcount = pos; + s->linecount = line; + s->linepos = lpos; + } + return ch; +} + + +int Yap_popChar(int sno) { + StreamDesc *s = GLOBAL_Stream + sno; + s->buf.on = false; + s->charcount = s->buf.pos; + s->linecount = s->buf.line; + s->linepos = s->buf.lpos; + Yap_DefaultStreamOps(s); + return s->buf.ch; +} + +int Yap_peekWide(int sno) { + StreamDesc *s = GLOBAL_Stream + sno; + Int pos = s->charcount; + Int line = s->linecount; + Int lpos = s->linepos; + int ch = s->stream_wgetc(sno); + if (ch == EOF) { + if (s->file) clearerr(s->file); + s->status &= ~Eof_Error_Stream_f; + // do not try doing error processing + } else { + s->buf.on = true; + s->buf.ch = ch; + s->buf.pos = s->charcount; + s->buf.line = s->linecount; + s->buf.lpos = s->linepos; + s->charcount = pos; + s->linecount = line; + s->linepos = lpos; + s->stream_getc = Yap_popChar; + s->stream_wgetc = Yap_popChar; + Yap_SetCurInpPos(sno, pos); + } + return ch; +} + + +int Yap_peekChar(int sno) { + StreamDesc *s = GLOBAL_Stream + sno; + Int pos = s->charcount; + Int line = s->linecount; + Int lpos = s->linepos; + int ch = s->stream_getc(sno); + if (ch == EOF) { + if (s->file) clearerr(s->file); + s->status &= ~Eof_Error_Stream_f; + // do not try doing error processing + } else { + s->buf.on = true; + s->buf.ch = ch; + s->buf.pos = s->charcount; + s->buf.line = s->linecount; + s->buf.lpos = s->linepos; + s->charcount = pos; + s->linecount = line; + s->linepos = lpos; + s->stream_getc = Yap_popChar; + s->stream_wgetc = Yap_popChar; + Yap_SetCurInpPos(sno, pos); + } + return ch; +} + + +int Yap_peek(int sno) { return GLOBAL_Stream[sno].stream_wpeek(sno); } + +static int dopeek_byte(int sno) { return GLOBAL_Stream[sno].stream_wpeek(sno); } bool store_code(int ch, Term t USES_REGS) { Term t2 = Deref(t); diff --git a/os/fmem.c b/os/fmem.c index 6265f18c7..1d1b46f61 100644 --- a/os/fmem.c +++ b/os/fmem.c @@ -108,7 +108,7 @@ bool fill_pads(int sno, int sno0, int total, format_info *fg USES_REGS) GLOBAL_Stream[sno].linecount = 1; GLOBAL_Stream[sno].linepos += nchars; GLOBAL_Stream[sno].charcount = 0; - GLOBAL_Stream[sno].recbs = NULL; + GLOBAL_Stream[sno].buf.on = false; fg->phys_start = 0; fg->lstart = GLOBAL_Stream[sno].linepos; fg->gapi = 0; @@ -123,7 +123,7 @@ bool Yap_set_stream_to_buf(StreamDesc *st, const char *buf, st->file = f = fmemopen((char *)buf, nchars, "r"); st->status = Input_Stream_f | Seekable_Stream_f | InMemory_Stream_f; st->vfs = NULL; - st->recbs = NULL; + st->buf.on = false; st->encoding = LOCAL_encoding; Yap_DefaultStreamOps(st); st->linecount = 0; @@ -196,7 +196,7 @@ int Yap_open_buf_write_stream(encoding_t enc, memBufSource src) { st->linecount = 1; st->encoding = enc; st->vfs = NULL; - st->recbs = NULL; + st->buf.on = false; #if HAVE_OPEN_MEMSTREAM st->file = open_memstream(&st->nbuf, &st->nsize); // setbuf(st->file, NULL); diff --git a/os/iopreds.c b/os/iopreds.c index 9de0dae5d..0c4aec210 100644 --- a/os/iopreds.c +++ b/os/iopreds.c @@ -199,6 +199,64 @@ static Term is_file_errors(Term t) { return TermZERO; } + + +int ResetEOF(StreamDesc *s) { + if (s->status & Eof_Error_Stream_f) { + Atom name = s->name; + // Yap_CloseStream(s - GLOBAL_Stream); + Yap_Error(PERMISSION_ERROR_INPUT_PAST_END_OF_STREAM, MkAtomTerm(name), + "GetC"); + return FALSE; + } else if (s->status & Reset_Eof_Stream_f) { + s->status &= ~Push_Eof_Stream_f; + /* reset the eof indicator on file */ + if (feof(s->file)) + clearerr(s->file); + /* reset our function for reading input */ + Yap_DefaultStreamOps(s); + /* next, reset our own error indicator */ + s->status &= ~Eof_Stream_f; + /* try reading again */ + return TRUE; + } else { + s->status |= Past_Eof_Stream_f; + return FALSE; + } +} + +/* handle reading from a stream after having found an EOF */ +static int EOFWGetc(int sno) { + register StreamDesc *s = &GLOBAL_Stream[sno]; + + if (s->status & Push_Eof_Stream_f) { + /* ok, we have pushed an EOF, send it away */ + s->status &= ~Push_Eof_Stream_f; + return EOF; + } + if (ResetEOF(s)) { + Yap_DefaultStreamOps(s); + return (s->stream_wgetc(sno)); + } + return EOF; +} + +static int EOFGetc(int sno) { + register StreamDesc *s = &GLOBAL_Stream[sno]; + + if (s->status & Push_Eof_Stream_f) { + /* ok, we have pushed an EOF, send it away */ + s->status &= ~Push_Eof_Stream_f; + ResetEOF(s); + return EOF; + } + if (ResetEOF(s)) { + Yap_DefaultStreamOps(s); + return s->stream_getc(sno); + } + return EOF; +} + static void unix_upd_stream_info(StreamDesc *s) { if (s->status & InMemory_Stream_f) { s->status |= Seekable_Stream_f; @@ -290,9 +348,22 @@ void Yap_DefaultStreamOps(StreamDesc *st) { st->stream_wgetc = get_wchar_from_file; } #endif - if (st->recbs) { - st->stream_getc = PopCode; - st->stream_wgetc = PopCode; + if (st->buf.on) { + st->stream_getc = Yap_popChar; + st->stream_wgetc = Yap_popChar; + } + if (st->status & Seekable_Stream_f ) { + st->stream_peek = Yap_peekWithSeek; + st->stream_wpeek = Yap_peekWideWithSeek; + } else { + st->stream_peek = Yap_peekChar; + st->stream_wpeek = Yap_peekWide; + } + if (st->status & Eof_Stream_f ) { + st->stream_peek = EOFPeek; + st->stream_wpeek = EOFPeek; + st->stream_getc = EOFGetc; + st->stream_wgetc = EOFWGetc; } if (GLOBAL_CharConversionTable != NULL) st->stream_wgetc_for_read = ISOWGetc; @@ -313,7 +384,7 @@ static void InitStdStream(int sno, SMALLUNSGN flags, FILE *file, VFS_t *vfsp) { s->linecount = 1; s->charcount = 0; s->vfs = vfsp; - s->recbs = NULL; + s->buf.on = false; s->encoding = ENC_ISO_UTF8; INIT_LOCK(s->streamlock); if (vfsp != NULL) { @@ -346,7 +417,7 @@ static void InitStdStream(int sno, SMALLUNSGN flags, FILE *file, VFS_t *vfsp) { #if LIGHT s->status |= Tty_Stream_f | Promptable_Stream_f; #endif - s->recbs = NULL; + s->buf.on = false; Yap_DefaultStreamOps(s); #if HAVE_SETBUF if (s->status & Tty_Stream_f && sno == 0) { @@ -590,61 +661,6 @@ static int NullPutc(int sno, int ch) { return ((int)ch); } -int ResetEOF(StreamDesc *s) { - if (s->status & Eof_Error_Stream_f) { - Atom name = s->name; - // Yap_CloseStream(s - GLOBAL_Stream); - Yap_Error(PERMISSION_ERROR_INPUT_PAST_END_OF_STREAM, MkAtomTerm(name), - "GetC"); - return FALSE; - } else if (s->status & Reset_Eof_Stream_f) { - s->status &= ~Push_Eof_Stream_f; - /* reset the eof indicator on file */ - if (feof(s->file)) - clearerr(s->file); - /* reset our function for reading input */ - Yap_DefaultStreamOps(s); - /* next, reset our own error indicator */ - s->status &= ~Eof_Stream_f; - /* try reading again */ - return TRUE; - } else { - s->status |= Past_Eof_Stream_f; - return FALSE; - } -} - -/* handle reading from a stream after having found an EOF */ -static int EOFWGetc(int sno) { - register StreamDesc *s = &GLOBAL_Stream[sno]; - - if (s->status & Push_Eof_Stream_f) { - /* ok, we have pushed an EOF, send it away */ - s->status &= ~Push_Eof_Stream_f; - return EOF; - } - if (ResetEOF(s)) { - Yap_DefaultStreamOps(s); - return (s->stream_wgetc(sno)); - } - return EOF; -} - -static int EOFGetc(int sno) { - register StreamDesc *s = &GLOBAL_Stream[sno]; - - if (s->status & Push_Eof_Stream_f) { - /* ok, we have pushed an EOF, send it away */ - s->status &= ~Push_Eof_Stream_f; - ResetEOF(s); - return EOF; - } - if (ResetEOF(s)) { - Yap_DefaultStreamOps(s); - return s->stream_getc(sno); - } - return EOF; -} /* check if we read a LOCAL_newline or an EOF */ int console_post_process_eof(StreamDesc *s) { @@ -1106,7 +1122,7 @@ bool Yap_initStream(int sno, FILE *fd, const char *name, Term file_name, st->status = flags; st->vfs = vfs; - st->recbs = NULL; + st->buf.on = false; st->charcount = 0; st->linecount = 1; if (flags & Binary_Stream_f) { @@ -1973,6 +1989,7 @@ void Yap_InitIOPreds(void) { Yap_InitCPred("$open_null_stream", 1, p_open_null_stream, SafePredFlag | SyncPredFlag | HiddenPredFlag); Yap_InitIOStreams(); + Yap_InitAliases(); Yap_InitCharsio(); Yap_InitChtypes(); Yap_InitConsole(); diff --git a/os/iopreds.h b/os/iopreds.h index 2cf7367ce..c524d2e1f 100644 --- a/os/iopreds.h +++ b/os/iopreds.h @@ -98,6 +98,8 @@ static inline Int GetCurInpLine(StreamDesc *inp_stream) { static inline Int GetCurInpPos(StreamDesc *inp_stream) { return (inp_stream->charcount); } +extern bool Yap_SetCurInpPos(int sno, Int pos USES_REGS); + #define PlIOError(type, culprit, ...) \ @@ -151,12 +153,21 @@ extern void Yap_InitWriteTPreds(void); extern void Yap_InitReadTPreds(void); extern void Yap_socketStream(StreamDesc *s); extern void Yap_ReadlineFlush(int sno); -Int Yap_ReadlinePeekChar(int sno); +int Yap_ReadlinePeekChar(int sno); int Yap_ReadlineForSIGINT(void); bool Yap_DoPrompt(StreamDesc *s); -Int Yap_peek(int sno); -int Yap_MemPeekc(int sno); +extern int Yap_peek(int sno); +extern int Yap_MemPeekc(int sno); + +extern int Yap_popChar(int sno); +extern int Yap_peekWithGetc(int sno); +extern int Yap_peekWideWithGetwc(int sno); +extern int Yap_peekWideWithSeek(int sno); + extern int Yap_peekWithSeek(int sno); +extern int Yap_peekWide(int sno); +extern int Yap_peekChar(int sno); + Term Yap_syntax_error(TokEntry *tokptr, int sno); diff --git a/os/readline.c b/os/readline.c index 5d8727dc0..b164eb719 100644 --- a/os/readline.c +++ b/os/readline.c @@ -390,7 +390,7 @@ static int ReadlineGetc(int sno) { with EOF, though. */ -Int Yap_ReadlinePeekChar(int sno) { +int Yap_ReadlinePeekChar(int sno) { StreamDesc *s = &GLOBAL_Stream[sno]; int ch; diff --git a/os/sockets.c b/os/sockets.c index 3c5aa3e8b..d0fc6eb25 100644 --- a/os/sockets.c +++ b/os/sockets.c @@ -257,7 +257,7 @@ Yap_InitSocketStream(int fd, socket_info flags, socket_domain domain) { st->linecount = 1; st->linepos = 0; st->vfs = NULL; - st->recbs = NULL; + st->buf.on = false; st->stream_putc = SocketPutc; st->stream_getc = SocketGetc; Yap_DefaultStreamOps( st ); diff --git a/os/streams.c b/os/streams.c index 384854c2e..c72fc9e94 100644 --- a/os/streams.c +++ b/os/streams.c @@ -157,7 +157,7 @@ int Yap_GetFreeStreamD(void) { return GetFreeStreamD(); } */ bool Yap_clearInput(int sno) { - if (!(GLOBAL_Stream[sno].status & Tty_Stream_f)) + if (!(GLOBAL_Stream[sno].status & Tty_Stream_f) || sno < 3) return true; if (GLOBAL_Stream[sno].vfs) { GLOBAL_Stream[sno].vfs->flush(sno); @@ -300,6 +300,29 @@ has_reposition(int sno, } } + + + +bool Yap_SetCurInpPos(int sno, Int pos + USES_REGS) { /* '$set_output'(+Stream,-ErrorMessage) */ + + + if (GLOBAL_Stream[sno].vfs) { + if (GLOBAL_Stream[sno].vfs->seek && GLOBAL_Stream[sno].vfs->seek(sno, 0L, SEEK_END) == -1) { + UNLOCK(GLOBAL_Stream[sno].streamlock); + PlIOError(SYSTEM_ERROR_INTERNAL, pos, + "fseek failed for set_stream_position/2: %s", strerror(errno)); + return (FALSE); + } + } else if (fseek(GLOBAL_Stream[sno].file, pos, SEEK_SET) == -1) { + UNLOCK(GLOBAL_Stream[sno].streamlock); + PlIOError(SYSTEM_ERROR_INTERNAL, MkIntegerTerm(0), + "fseek failed for set_stream_position/2: %s", strerror(errno)); + return (FALSE); + } + return true; +} + char *Yap_guessFileName(FILE *file, int sno, char *nameb, size_t max) { size_t maxs = Yap_Max(1024, max); if (!nameb) { @@ -1319,7 +1342,14 @@ static Int "set_stream_position/2"); return (FALSE); } - if (fseek(GLOBAL_Stream[sno].file, 0L, SEEK_END) == -1) { + if(GLOBAL_Stream[sno].vfs) { + if (GLOBAL_Stream[sno].vfs->seek && GLOBAL_Stream[sno].vfs->seek(sno, 0L, SEEK_END) == -1) { + UNLOCK(GLOBAL_Stream[sno].streamlock); + PlIOError(SYSTEM_ERROR_INTERNAL, tp, + "fseek failed for set_stream_position/2: %s", strerror(errno)); + return (FALSE); + } + } else if (fseek(GLOBAL_Stream[sno].file, 0L, SEEK_END) == -1) { UNLOCK(GLOBAL_Stream[sno].streamlock); PlIOError(SYSTEM_ERROR_INTERNAL, tp, "fseek failed for set_stream_position/2: %s", strerror(errno)); diff --git a/packages/bdd/simplecudd_lfi/simplecudd.h b/packages/bdd/simplecudd_lfi/simplecudd.h index bdca14271..89bcd7fb8 100644 --- a/packages/bdd/simplecudd_lfi/simplecudd.h +++ b/packages/bdd/simplecudd_lfi/simplecudd.h @@ -185,6 +185,7 @@ \******************************************************************************/ +#include #include #include #include @@ -209,6 +210,9 @@ #elif HAVE_CUDDINT_H #include "cuddInt.h" #endif +#ifdef VERSION +#undef VERSION +#endif #include "general.h" diff --git a/packages/cplint/approx/simplecuddLPADs/simplecudd.c b/packages/cplint/approx/simplecuddLPADs/simplecudd.c index 234ef9c4f..89e6ec89d 100644 --- a/packages/cplint/approx/simplecuddLPADs/simplecudd.c +++ b/packages/cplint/approx/simplecuddLPADs/simplecudd.c @@ -388,7 +388,7 @@ int simpleNamedBDDtoDot(DdManager *manager, namedvars varmap, DdNode *bdd, perror(filename); return -1; } - const char **vs = varmap.vars; + char * const*vs = varmap.vars; ret = Cudd_DumpDot(manager, 1, f, vs, NULL, fd); fclose(fd); return ret; diff --git a/packages/python/pl2py.c b/packages/python/pl2py.c index 8d25fe38a..87462fb2a 100644 --- a/packages/python/pl2py.c +++ b/packages/python/pl2py.c @@ -133,6 +133,7 @@ PyObject *term_to_python(term_t t, bool eval, PyObject *o, bool cvt) { o = PyUnicode_FromString(s); } if (o) { + //PyDict_SetItemString(py_Atoms, s, Py_None); Py_INCREF(o); return o; } diff --git a/packages/python/py2pl.c b/packages/python/py2pl.c index 32f94fb21..7e7ccfad1 100644 --- a/packages/python/py2pl.c +++ b/packages/python/py2pl.c @@ -57,7 +57,7 @@ foreign_t python_to_term(PyObject *pVal, term_t t) { if (pVal == Py_None) { // fputs("<<*** ",stderr);Yap_DebugPlWrite(YAP_GetFromSlot(t)); fputs(" // >>***\n",stderr); - rc = PL_unify_atom(t, ATOM_none); + rc = true; // fputs("<<*** ",stderr);Yap_DebugPlWrite(YAP_GetFromSlot(t)); fputs(" // >>***\n",stderr); } else if (PyBool_Check(pVal)) { @@ -80,26 +80,23 @@ foreign_t python_to_term(PyObject *pVal, term_t t) { rc = rc && PL_unify(t, to); } } else if (PyUnicode_Check(pVal)) { - atom_t tmp_atom; - #if PY_MAJOR_VERSION < 3 size_t sz = PyUnicode_GetSize(pVal) + 1; - wchar_t *ptr = malloc(sizeof(wchar_t) * sz); - sz = PyUnicode_AsWideChar((PyUnicodeObject *)pVal, ptr, sz - 1); - tmp_atom = PL_new_atom_wchars(sz, ptr); + wchar_t *s = malloc(sizeof(wchar_t) * sz); + sz = PyUnicode_AsWideChar((PyUnicodeObject *)pVal, a, sz - 1); free(ptr); #else const char *s = PyUnicode_AsUTF8(pVal); - tmp_atom = PL_new_atom(s); #endif - rc = rc && PL_unify_atom(t, tmp_atom); - } else if (PyByteArray_Check(pVal)) { - atom_t tmp_atom = PL_new_atom(PyByteArray_AsString(pVal)); - rc = rc && PL_unify_atom(t, tmp_atom); -#if PY_MAJOR_VERSION < 3 - } else if (PyString_Check(pVal)) { - atom_t tmp_atom = PL_new_atom(PyString_AsString(pVal)); - rc = rc && PL_unify_atom(t, tmp_atom); +// if (PyDict_GetItemString(py_Atoms, s)) +// rc = rc && PL_unify_atom_chars(t, s); +// else + rc = rc && PL_unify_atom_chars(t, s); + } else if (PyByteArray_Check(pVal)) { + rc = rc && PL_unify_string_chars(t, PyByteArray_AsString(pVal)); + #if PY_MAJOR_VERSION < 3 + } else if (PyString_Check(pVal)) { + rc = rc && PL_unify_string_chars(t, PyString_AsString(pVal)); #endif } else if (PyTuple_Check(pVal)) { Py_ssize_t i, sz = PyTuple_Size(pVal); diff --git a/packages/python/py4yap.h b/packages/python/py4yap.h index ac0545a11..1cd70f1ad 100644 --- a/packages/python/py4yap.h +++ b/packages/python/py4yap.h @@ -60,7 +60,6 @@ typedef YAP_Arity arity_t; extern atom_t ATOM_true, ATOM_false, ATOM_colon, ATOM_dot, ATOM_none, ATOM_t, ATOM_comma, ATOM_builtin, ATOM_V, ATOM_A, ATOM_self, ATOM_nil, ATOM_brackets, ATOM_curly_brackets; -; extern functor_t FUNCTOR_dollar1, FUNCTOR_abs1, FUNCTOR_all1, FUNCTOR_any1, FUNCTOR_bin1, FUNCTOR_brackets1, FUNCTOR_comma2, FUNCTOR_dir1, @@ -75,6 +74,7 @@ extern X_API PyObject *py_Main; extern X_API PyObject *py_Builtin; extern X_API PyObject *py_Yapex; extern X_API PyObject *py_Local; +extern X_API PyObject *py_Atoms; extern X_API PyObject *py_Global; extern X_API PyObject *py_Context; extern PyObject *Py_f2p; diff --git a/packages/python/python.c b/packages/python/python.c index d99657cfc..75aac7599 100644 --- a/packages/python/python.c +++ b/packages/python/python.c @@ -18,6 +18,7 @@ functor_t FUNCTOR_dollar1, FUNCTOR_abs1, FUNCTOR_all1, FUNCTOR_any1, FUNCTOR_colon2, FUNCTOR_comma2, FUNCTOR_equal2, FUNCTOR_sqbrackets2, FUNCTOR_dot2, FUNCTOR_brackets1; +X_API PyObject *py_Atoms; X_API PyObject *py_Builtin; X_API PyObject *py_Yapex; X_API PyObject *py_Sys; @@ -77,24 +78,21 @@ static int py_put(int sno, int ch) { return ch; } -static int py_get(int sno) -{ +static int py_get(int sno) { StreamDesc *s = YAP_GetStreamFromId(sno); PyObject *fget = PyObject_GetAttrString(s->u.private_data, "read"); PyObject *pyr = PyObject_CallFunctionObjArgs(fget, PyLong_FromLong(1), NULL); return PyUnicode_READ_CHAR(pyr, 0); } -static int py_peek(int sno) -{ +static int py_peek(int sno) { StreamDesc *s = YAP_GetStreamFromId(sno); PyObject *fget = PyObject_GetAttrString(s->u.private_data, "peek"); PyObject *pyr = PyObject_CallFunctionObjArgs(fget, PyLong_FromLong(1), NULL); return PyUnicode_READ_CHAR(pyr, 0); } -static int64_t py_seek(int sno, int64_t where, int how) -{ +static int64_t py_seek(int sno, int64_t where, int how) { StreamDesc *s = YAP_GetStreamFromId(sno); PyObject *fseek = PyObject_GetAttrString(s->u.private_data, "seek"); PyObject *pyr = PyObject_CallFunctionObjArgs(fseek, PyLong_FromLong(where), @@ -152,6 +150,7 @@ static void add_modules(void) { py_Main = PyImport_AddModule("__main__"); Py_INCREF(py_Main); py_Sys = PyImport_AddModule("sys"); + py_Atoms = PyDict_New(); Py_INCREF(py_Sys); py_Builtin = PyImport_AddModule("__builtin__"); Py_INCREF(py_Builtin); diff --git a/packages/python/swig/prolog/yapi.yap b/packages/python/swig/prolog/yapi.yap index 2a0d4b94a..93365df3f 100644 --- a/packages/python/swig/prolog/yapi.yap +++ b/packages/python/swig/prolog/yapi.yap @@ -2,7 +2,7 @@ %% @brief support yap shell %% -% :- yap_flag(verbose, verbose). +:- yap_flag(verbose, verbose). :- use_module( library(python) ). diff --git a/packages/python/swig/yap4py/__init__.py.in b/packages/python/swig/yap4py/__init__.py.in index ed4c12f41..9222b6f41 100644 --- a/packages/python/swig/yap4py/__init__.py.in +++ b/packages/python/swig/yap4py/__init__.py.in @@ -13,7 +13,7 @@ if platform.system() == 'Windows': def load( dll ): dll = glob.glob(os.path.join(yap_lib_path,dll))[0] dll = os.path.abspath(dll) - ctypes.WinDLL(dll)s + ctypes.WinDLL(dll) elif platform.system() == 'Darwin': def load( dll ): dll = glob.glob(os.path.join(os.path.realpath(__file__),dll))[0] @@ -21,11 +21,10 @@ elif platform.system() == 'Darwin': ctypes.CDLL(dll) # load('libYap.dylib') # load('libPy4YAP.dylib') - load( '_yap.dylib' ) -#else: -# def load( dll ): -# dll = glob.glob(os.path.join(yap_lib_path,dll))[0] -# dll = os.path.abspath(dll) -# ctypes.CDLL(dll) -# load('libYap.so') -# load('libPy4YAP.so') \ No newline at end of file + #load( '_yap*.dylib' ) +else: + def load( dll ): + dll = glob.glob(os.path.join(os.path.realpath(__file__),dll))[0] + dll = os.path.abspath(dll) + ctypes.CDLL(dll) + # \`load('_yap*.so') diff --git a/packages/python/yap_kernel/CMakeLists.txt b/packages/python/yap_kernel/CMakeLists.txt index edb122911..541c4a54b 100644 --- a/packages/python/yap_kernel/CMakeLists.txt +++ b/packages/python/yap_kernel/CMakeLists.txt @@ -1,17 +1,9 @@ - set (EXTRAS - MANIFEST.in - YAP_KERNEL.md - ) - - set (PL_SOURCES - yap_ipython/prolog/jupyter.yap - ) set (PYTHON_SOURCES yap_ipython/core/getipython.py yap_ipython/core/__init__.py yap_ipython/core/interactiveshell.py - yap_ipython/core/modulefind.py + # yap_ipython/core/modulefind.py yap_ipython/core/oinspect.py yap_ipython/core/release.py yap_ipython/core/shellapp.py @@ -59,19 +51,62 @@ yap_kernel/pylab/config.py ) - configure_file(setup.py.in ${CMAKE_CURRENT_BINARY_DIR}/setup.py) - configure_file(${CMAKE_SOURCE_DIR}/misc/editors/prolog.js.in ${CMAKE_CURRENT_BINARY_DIR}/prolog.js ) + set (EXTRAS + MANIFEST.in + YAP_KERNEL.md + setup.py + setup.cfg + README.md + ) + set (RESOURCES + resources/custom.js + resources/prolog.js + #resources/logo-32x32.png + #resources/logo-64x64.png + ) + set (RENAMED_RESOURCES + resources/logo-32x32.png + resources/logo-64x64.png + # resources/codemirror/mode/prolog/prolog.js + ) + + set (PL_SOURCES + yap_ipython/prolog/jupyter.yap + ) + +set(FILES ${PYTHON_SOURCES} ${PL_SOURCES} ${EXTRAS} ${RESOURCES}) set(SETUP_PY ${CMAKE_CURRENT_BINARY_DIR}/setup.py) - add_custom_target( YAPKernel ALL + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${i} + COMMAND ${CMAKE_COMMAND} -E tar cvf ${CMAKE_CURRENT_BINARY_DIR}/yap.tgz ${FILESi} + + + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +) + + +add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/resources/logo-32x32.png + COMMAND ${CMAKE_COMMAND} -E tar xvf yap.tgz + COMMAND ${CMAKE_COMMAND} -E copy_if_changed ${CMAKE_SOURCE_DIR}/docs/icons/yap_32z32x32.png ${CMAKE_CURRENT_BINARY_DIR}/resources/logo-32x32.png + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/docs/icons/yap_32x32x32.png + ) + + + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/resources/logo-64x64.png + COMMAND ${CMAKE_COMMAND} -E copy_if_changed ${CMAKE_SOURCE_DIR}/docs/icons/yap_64x64x32.png ${CMAKE_CURRENT_BINARY_DIR}/resources/logo-64x64.png + ) + + add_custom_target(YAP_KERNEL + COMMAND ${CMAKE_COMMAND} -E tar xvf yap.tgz COMMAND ${PYTHON_EXECUTABLE} ${SETUP_PY} build sdist bdist WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - DEPENDS YAP4PY - ) + ) + install(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} -m pip install --ignore-installed --no-deps . + COMMAND ${PYTHON_EXECUTABLE} -m yap_kernel.kernelspec WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})") install(FILES ${PL_SOURCES} DESTINATION ${libpl} ) diff --git a/packages/python/yap_kernel/kernel.js b/packages/python/yap_kernel/kernel.js index b5fd0586e..71cc6cb74 100644 --- a/packages/python/yap_kernel/kernel.js +++ b/packages/python/yap_kernel/kernel.js @@ -1,9 +1,42 @@ -/*define(['./prolog.js'], function(){ - var onload = function(){ - console.log("I am being loaded"); +;(function(window_CodeMirror){ + "use strict"; - - }; - return {onload:onload} -});*/ \ No newline at end of file + // the `require` namespace for codemirror + CM_PATH = "components/codemirror/"; + + define( + [ + "underscore", + "jquery", + CM_PATH + "lib/codemirror", + "base/js/namespace", + // silent upgrades + "./jshint.js", + CM_PATH + "addon/lint/javascript-lint", + CM_PATH + "addon/hint/javascript-hint", + CM_PATH + "addon/lint/lint", + CM_PATH + "addon/hint/show-hint", + "./prolog.js" + ], + function(_, $, CodeMirror, Jupyter){ + + // the main function + cm_tweak_js = function(cell){ + var editor = cell.code_mirror, + opts = {}, + meta = ensure_ns(cell), + keys = editor.getOption("extraKeys") || {}, + mode = editor.getMode(); + + // only update editors we care about, reset ones we might have messed + if(!editor){ + return; + } else { + editor.setOption("mode", "x-text/prolog"); + } + } + } + } // the `define` callback + ); // the `define` + ).call(this, window.CodeMirror); diff --git a/packages/python/yap_kernel/setup.py.in b/packages/python/yap_kernel/setup.py similarity index 74% rename from packages/python/yap_kernel/setup.py.in rename to packages/python/yap_kernel/setup.py index 3a86917ef..cc73098b7 100644 --- a/packages/python/yap_kernel/setup.py.in +++ b/packages/python/yap_kernel/setup.py @@ -39,20 +39,19 @@ pjoin = os.path.join here = os.path.abspath(os.path.dirname(__file__)) # pkg_root = pjoin(here, name) -packages = setuptools.find_packages('${CMAKE_CURRENT_SOURCE_DIR}') +packages = setuptools.find_packages(here) # for d, _, _ in os.walk(pjoin(here, name)): # if os.path.exists(pjoin(d, '__init__.py')): # packages.append(d[len(here)+1:].replace(os.path.sep, '.')) -sys.path.insert(0, "${CMAKE_CURRENT_SOURCE_DIR}") +sys.path.insert(0, here) package_data = { 'yap_ipython': ['prolog/*.*'], 'yap_kernel': ['resources/*.*'] } -version_ns = {} -with open(pjoin('${CMAKE_CURRENT_SOURCE_DIR}', name, '_version.py')) as f: +version_ns = {here, name, '_version.py')) as f: exec(f.read(), {}, version_ns) @@ -65,7 +64,7 @@ setup_args = dict( packages = packages, py_modules = ['yap_kernel_launcher'], package_data = package_data, - package_dir = {'':"${CMAKE_CURRENT_SOURCE_DIR}"}, + package_dir = {'':here}, description = "YAP Kernel for Jupyter", author = 'YAP Development Team', author_email = 'YAP-dev@scipy.org', @@ -95,29 +94,24 @@ if any(a.startswith(('bdist', 'build', 'install')) for a in sys.argv): from yap_kernel.kernelspec import write_kernel_spec, make_yap_kernel_cmd, KERNEL_NAME - argv = make_yap_kernel_cmd(executable='python') + argv = make_yap_kernel_cmd(executable=sys.executable) dest = os.path.join(here, 'resources') try: - shutil.rmtree(dest) - os.makedirs( dest ) - shutil.copy2('${CMAKE_SOURCE_DIR}/docs/icons/yap_32x32x32.png',pjoin(dest,"logo_32x32.png")) - shutil.copy2('${CMAKE_SOURCE_DIR}/docs/icons/yap_64x64x32.png',pjoin(dest,"logo_64x64.png")) write_kernel_spec(dest, overrides={'argv': argv}) except: pass - # shutil.copy('${CMAKE_CURRENT_SOURCE_DIR}/kernel.js',dest) # shutil.copy('${CMAKE_SOURCE_DIR}/misc/editors/prolog.js',dest) - setup_args['data_files'] = [(pjoin('share', 'jupyter', 'kernels', KERNEL_NAME), glob(pjoin(dest, '*')))] + #setup_args['data_files'] = [(pjoin('share', 'jupyter', 'kernels', KERNEL_NAME), glob(pjoin(dest, '*')))] mode_loc = pjoin( sysconfig.get_path('platlib'), 'notebook', 'static', 'components', 'codemirror', 'mode', 'prolog') custom_loc = pjoin( sysconfig.get_path('platlib'), 'notebook', 'static', 'custom') - # try: - # shutil.copy( pjoin( custom_loc, "custom.js") , pjoin( custom_loc, "custom.js.orig")) - # shutil.copy( "${CMAKE_CURRENT_SOURCE_DIR}/custom.js" , pjoin( custom_loc, "custom.js")) - # if not os.path.exists(mode_loc): - # os.makedirs(mode_loc) - # shutil.copy( "${CMAKE_SOURCE_DIR}/misc/editors/prolog.js" , mode_loc) - # except: - # pass + try: + shutil.copy( pjoin( custom_loc, "custom.js") , pjoin( custom_loc, "custom.js.orig")) + shutil.copy( pjoin( "resources", "custom.js") , pjoin( custom_loc, "custom.js")) + if not os.path.exists(mode_loc): + os.makedirs(mode_loc) + shutil.copy( pjoin( "resources","prolog.js") , mode_loc) + except: + pass extras_require = setuptools_args['extras_require'] = { 'test:python_version=="2.7"': ['mock'], diff --git a/packages/python/yap_kernel/yap_ipython/core/completer.py b/packages/python/yap_kernel/yap_ipython/core/completer.py index 79666376d..1ad3c8f0d 100644 --- a/packages/python/yap_kernel/yap_ipython/core/completer.py +++ b/packages/python/yap_kernel/yap_ipython/core/completer.py @@ -74,7 +74,7 @@ manager. You will find that the following are experimental: - :any:`provisionalcompleter` - - :any:`IPCompleter.completions` + - :any:PyCompleter.completions` - :any:`Completion` - :any:`rectify_completions` @@ -154,7 +154,7 @@ except ImportError: #----------------------------------------------------------------------------- # Public API -__all__ = ['Completer','IPCompleter'] +__all__ = ['Completer','YAPCompleter'] if sys.platform == 'win32': PROTECTABLES = ' ' @@ -349,7 +349,7 @@ class Completion: Completion object used and return by yap_ipython completers. .. warning:: Unstable - + This function is unstable, API may change without warning. It will also raise unless use in proper context manager. @@ -590,7 +590,7 @@ class Completer(Configurable): 'information for experimental jedi integration.')\ .tag(config=True) - backslash_combining_completions = Bool(True, + backslash_combining_completions = Bool(True, help="Enable unicode completions, e.g. \\alpha . " "Includes completion of latex commands, unicode names, and expanding " "unicode characters back to latex commands.").tag(config=True) @@ -692,7 +692,7 @@ class Completer(Configurable): # Another option, seems to work great. Catches things like ''. m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text) - + if m: expr, attr = m.group(1, 3) elif self.greedy: @@ -702,7 +702,7 @@ class Completer(Configurable): expr, attr = m2.group(1,2) else: return [] - + try: obj = eval(expr, self.namespace) except: @@ -737,7 +737,7 @@ def get__all__entries(obj): words = getattr(obj, '__all__') except: return [] - + return [w for w in words if isinstance(w, str)] @@ -886,14 +886,14 @@ def _safe_isinstance(obj, module, class_name): def back_unicode_name_matches(text): u"""Match unicode characters back to unicode name - + This does ``☃`` -> ``\\snowman`` Note that snowman is not a valid python3 combining character but will be expanded. Though it will not recombine back to the snowman character by the completion machinery. This will not either back-complete standard sequences like \\n, \\b ... - + Used on Python 3 only. """ if len(text)<2: @@ -916,7 +916,7 @@ def back_unicode_name_matches(text): def back_latex_name_matches(text:str): """Match latex characters back to unicode name - + This does ``\\ℵ`` -> ``\\aleph`` Used on Python 3 only. @@ -990,7 +990,7 @@ def _make_signature(completion)-> str: class IPCompleter(Completer): """Extension of the completer class with yap_ipython-specific features""" - + @observe('greedy') def _greedy_changed(self, change): """update the splitter and readline delims when greedy is changed""" @@ -998,36 +998,36 @@ class IPCompleter(Completer): self.splitter.delims = GREEDY_DELIMS else: self.splitter.delims = DELIMS - + merge_completions = Bool(True, help="""Whether to merge completion results into a single list - + If False, only the completion results from the first non-empty completer will be returned. """ ).tag(config=True) omit__names = Enum((0,1,2), default_value=2, help="""Instruct the completer to omit private method names - + Specifically, when completing on ``object.``. - + When 2 [default]: all names that start with '_' will be excluded. - + When 1: all 'magic' names (``__foo__``) will be excluded. - + When 0: nothing will be excluded. """ ).tag(config=True) limit_to__all__ = Bool(False, help=""" DEPRECATED as of version 5.0. - + Instruct the completer to use __all__ for the completion - + Specifically, when completing on ``object.``. - + When True: only those names in obj.__all__ will be included. - + When False [default]: the __all__ attribute is ignored """, ).tag(config=True) @@ -1060,7 +1060,7 @@ class IPCompleter(Completer): secondary optional dict for completions, to handle cases (such as yap_ipython embedded inside functions) where both Python scopes are visible. - + use_readline : bool, optional DEPRECATED, ignored since yap_ipython 6.0, will have no effects """ @@ -1611,7 +1611,7 @@ class IPCompleter(Completer): closing_quote, token_offset, matches = match_dict_keys(keys, prefix, self.splitter.delims) if not matches: return matches - + # get the cursor position of # - the text being completed # - the start of the key text @@ -1622,13 +1622,13 @@ class IPCompleter(Completer): completion_start = key_start + token_offset else: key_start = completion_start = match.end() - + # grab the leading prefix, to make sure all completions start with `text` if text_start > key_start: leading = '' else: leading = text[text_start:completion_start] - + # the index of the `[` character bracket_idx = match.end(1) @@ -1647,18 +1647,18 @@ class IPCompleter(Completer): # brackets were opened inside text, maybe close them if not continuation.startswith(']'): suf += ']' - + return [leading + k + suf for k in matches] def unicode_name_matches(self, text): u"""Match Latex-like syntax for unicode characters base on the name of the character. - + This does ``\\GREEK SMALL LETTER ETA`` -> ``η`` Works only on valid python 3 identifier, or on combining characters that will combine to form a valid identifier. - + Used on Python 3 only. """ slashpos = text.rfind('\\') @@ -1676,7 +1676,7 @@ class IPCompleter(Completer): def latex_matches(self, text): u"""Match Latex syntax for unicode characters. - + This does both ``\\alp`` -> ``\\alpha`` and ``\\alpha`` -> ``α`` Used on Python 3 only. @@ -1748,13 +1748,13 @@ class IPCompleter(Completer): Returns an iterator over the possible completions .. warning:: Unstable - + This function is unstable, API may change without warning. It will also raise unless use in proper context manager. Parameters ---------- - + text:str Full text of the current input, multi line string. offset:int @@ -1783,7 +1783,7 @@ class IPCompleter(Completer): and usual yap_ipython completion. .. note:: - + Completions are not completely deduplicated yet. If identical completions are coming from different sources this function does not ensure that each completion object will only be present once. @@ -1973,7 +1973,7 @@ class IPCompleter(Completer): if name_text: return name_text, name_matches[:MATCHES_LIMIT], \ [meth.__qualname__]*min(len(name_matches), MATCHES_LIMIT), () - + # If no line buffer is given, assume the input text is all there was if line_buffer is None: diff --git a/packages/python/yap_kernel/yap_ipython/core/inputsplitter.py b/packages/python/yap_kernel/yap_ipython/core/inputsplitter.py index b3c9407d1..377fff9db 100644 --- a/packages/python/yap_kernel/yap_ipython/core/inputsplitter.py +++ b/packages/python/yap_kernel/yap_ipython/core/inputsplitter.py @@ -292,7 +292,7 @@ class InputSplitter(object): """ # A cache for storing the current indentation # The first value stores the most recently processed source input - # The second value is the number of spaces for the current indentation + # The second value is the number of spaces for the current indentation # If self.source matches the first value, the second value is a valid # current indentation. Otherwise, the cache is invalid and the indentation # must be recalculated. @@ -345,14 +345,14 @@ class InputSplitter(object): def check_complete(self, source): """Return whether a block of code is ready to execute, or should be continued - + This is a non-stateful API, and will reset the state of this InputSplitter. - + Parameters ---------- source : string Python input code, which can be multiline. - + Returns ------- status : str @@ -441,7 +441,7 @@ class InputSplitter(object): guess whether a block is complete or not based solely on prior and current input lines. The InputSplitter considers it has a complete interactive block and will not accept more input when either: - + * A SyntaxError is raised * The code is complete and consists of a single line or a single @@ -461,20 +461,20 @@ class InputSplitter(object): if not self._is_complete: #print("Not complete") # debug return True - + # The user can make any (complete) input execute by leaving a blank line last_line = self.source.splitlines()[-1] if (not last_line) or last_line.isspace(): #print("Blank line") # debug return False - + # If there's just a single line or AST node, and we're flush left, as is # the case after a simple statement such as 'a=1', we want to execute it # straight away. if self.get_indent_spaces() == 0: if len(self.source.splitlines()) <= 1: return False - + try: code_ast = ast.parse(u''.join(self._buffer)) except Exception: @@ -528,11 +528,11 @@ class IPythonInputSplitter(InputSplitter): # String with raw, untransformed input. source_raw = '' - + # Flag to track when a transformer has stored input that it hasn't given # back yet. transformer_accumulating = False - + # Flag to track when assemble_python_lines has stored input that it hasn't # given back yet. within_python_line = False @@ -547,7 +547,7 @@ class IPythonInputSplitter(InputSplitter): super(IPythonInputSplitter, self).__init__() self._buffer_raw = [] self._validate = True - + if physical_line_transforms is not None: self.physical_line_transforms = physical_line_transforms else: @@ -557,7 +557,7 @@ class IPythonInputSplitter(InputSplitter): ipy_prompt(), cellmagic(end_on_blank_line=line_input_checker), ] - + self.assemble_logical_lines = assemble_logical_lines() if logical_line_transforms is not None: self.logical_line_transforms = logical_line_transforms @@ -568,21 +568,21 @@ class IPythonInputSplitter(InputSplitter): assign_from_magic(), assign_from_system(), ] - + self.assemble_python_lines = assemble_python_lines() if python_line_transforms is not None: self.python_line_transforms = python_line_transforms else: # We don't use any of these at present self.python_line_transforms = [] - + @property def transforms(self): "Quick access to all transformers." return self.physical_line_transforms + \ [self.assemble_logical_lines] + self.logical_line_transforms + \ [self.assemble_python_lines] + self.python_line_transforms - + @property def transforms_in_use(self): """Transformers, excluding logical line transformers if we're in a @@ -607,13 +607,13 @@ class IPythonInputSplitter(InputSplitter): # Nothing that calls reset() expects to handle transformer # errors pass - + def flush_transformers(self): def _flush(transform, outs): """yield transformed lines - + always strings, never None - + transform: the current transform outs: an iterable of previously transformed inputs. Each may be multiline, which will be passed @@ -625,16 +625,16 @@ class IPythonInputSplitter(InputSplitter): tmp = transform.push(line) if tmp is not None: yield tmp - + # reset the transform tmp = transform.reset() if tmp is not None: yield tmp - + out = [] for t in self.transforms_in_use: out = _flush(t, out) - + out = list(out) if out: self._store('\n'.join(out)) @@ -645,7 +645,7 @@ class IPythonInputSplitter(InputSplitter): out = self.source_raw self.reset() return out - + def source_reset(self): try: self.flush_transformers() @@ -714,18 +714,14 @@ class IPythonInputSplitter(InputSplitter): if transformed_lines_list: transformed_lines = '\n'.join(transformed_lines_list) - return super(IPythonInputSplitter, self).push(transformed_lines) - else: - # Got nothing back from transformers - they must be waiting for - # more input. - return False + return hasSyntaxError(self, lines) def _transform_line(self, line): """Push a line of input code through the various transformers. - + Returns any output from the transformers, or None if a transformer is accumulating lines. - + Sets self.transformer_accumulating as a side effect. """ def _accumulating(dbg): @@ -738,24 +734,8 @@ class IPythonInputSplitter(InputSplitter): if line is None: return _accumulating(transformer) - if not self.within_python_line: - line = self.assemble_logical_lines.push(line) - if line is None: - return _accumulating('acc logical line') - for transformer in self.logical_line_transforms: - line = transformer.push(line) - if line is None: - return _accumulating(transformer) - - line = self.assemble_python_lines.push(line) - if line is None: - self.within_python_line = True - return _accumulating('acc python line') - else: - self.within_python_line = False - - for transformer in self.python_line_transforms: + for transformer in self.logical_line_transforms: line = transformer.push(line) if line is None: return _accumulating(transformer) @@ -763,4 +743,3 @@ class IPythonInputSplitter(InputSplitter): #print("transformers clear") #debug self.transformer_accumulating = False return line - diff --git a/packages/python/yap_kernel/yap_ipython/core/interactiveshell.py b/packages/python/yap_kernel/yap_ipython/core/interactiveshell.py index 120e39d1e..1f741361d 100644 --- a/packages/python/yap_kernel/yap_ipython/core/interactiveshell.py +++ b/packages/python/yap_kernel/yap_ipython/core/interactiveshell.py @@ -29,6 +29,7 @@ from io import open as io_open from pickleshare import PickleShareDB +import yap_ipython.yapi from traitlets.config.configurable import SingletonConfigurable from yap_ipython.core import oinspect from yap_ipython.core import magic @@ -78,7 +79,7 @@ from traitlets import ( from warnings import warn from logging import error import yap_ipython.core.hooks -from yap_ipython.yapi import YAPRun, YAPCompleter +from yap_ipython.yapi import YAPRun, YAPCompleter, YAPInputSplitter from typing import List as ListType from ast import AST @@ -337,15 +338,17 @@ class InteractiveShell(SingletonConfigurable): # Input splitter, to transform input line by line and detect when a block # is ready to be executed. - input_splitter = Instance('yap_ipython.core.inputsplitter.IPythonInputSplitter', - (), {'line_input_checker': True}) + #input_splitter = Instance('yap_ipython.core.inputsplitter.IPythonInputSplitter', + # (), {'line_input_checker': True}) + input_splitter = Instance('yap_ipython.yapi.YAPInputSplitter', + (), {'line_input_checker': False}) # This InputSplitter instance is used to transform completed cells before # running them. It allows cell magics to contain blank lines. # input_transformer_manager = Instance('yap_ipython.core.inputsplitter.IPythonInputSplitter', # (), {'line_input_checker': False}) - input_transformer_manager = Instance('yap_ipython.yapi.YAPLineProcessor', - (), {'line_input_checker': False}) + input_transformer_manager = Instance('yap_ipython.yapi.YAPInputSplitter', + (), {'line_input_checker': True}) logstart = Bool(False, help= """ @@ -476,8 +479,8 @@ class InteractiveShell(SingletonConfigurable): warn('As of yap_ipython 5.0 `PromptManager` config will have no effect' ' and has been replaced by TerminalInteractiveShell.prompts_class') self.configurables = [self] - self._yrun_cell = YAPRun._yrun_cell - YAPRun.init(self) + yrun = YAPRun( self) + self._yrun_cell = yrun._yrun_cell # These are relatively independent and stateless self.init_ipython_dir(ipython_dir) @@ -519,6 +522,8 @@ class InteractiveShell(SingletonConfigurable): # The following was in post_config_initialization self.init_inspector() self.raw_input_original = input + self.input_splitter.engine(self.yapeng) + self.input_transformer_manager.engine(self.yapeng) self.init_completer() # TODO: init_io() needs to happen before init_traceback handlers # because the traceback handlers hardcode the stdout/stderr streams. @@ -541,6 +546,8 @@ class InteractiveShell(SingletonConfigurable): self.events.trigger('shell_initialized', self) atexit.register(self.atexit_operations) + + def get_ipython(self): """Return the currently running yap_ipython instance.""" return self @@ -1966,23 +1973,20 @@ class InteractiveShell(SingletonConfigurable): magic_run_completer, cd_completer, reset_completer) self.Completer = YAPCompleter(shell=self, - namespace=self.user_ns, - global_namespace=self.user_global_ns, - parent=self ) self.configurables.append(self.Completer) # Add custom completers to the basic ones built into IPCompleter - sdisp = self.strdispatchers.get('complete_command', StrDispatch()) - self.strdispatchers['complete_command'] = sdisp - self.Completer.custom_completers = sdisp - - self.set_hook('complete_command', module_completer, str_key = 'import') - self.set_hook('complete_command', module_completer, str_key = 'from') - self.set_hook('complete_command', module_completer, str_key = '%aimport') - self.set_hook('complete_command', magic_run_completer, str_key = '%run') - self.set_hook('complete_command', cd_completer, str_key = '%cd') - self.set_hook('complete_command', reset_completer, str_key = '%reset') + # sdisp = self.strdispatchers.get('complete_command', StrDispatch()) + # self.strdispatchers['complete_command'] = sdisp + # self.Completer.custom_completers = sdisp + # + # #self.set_hook('complete_command', module_completer, str_key = 'import') + # #self.set_hook('complete_command', module_completer, str_key = 'from') + # self.set_hook('complete_command', module_completer, str_key = '%aimport') + # self.set_hook('complete_command', magic_run_completer, str_key = '%run') + # self.set_hook('complete_command', cd_completer, str_key = '%cd') + # self.set_hook('complete_command', reset_completer, str_key = '%reset') def complete(self, text, line=None, cursor_pos=None): @@ -2376,6 +2380,7 @@ class InteractiveShell(SingletonConfigurable): # code out there that may rely on this). self.prefilter = self.prefilter_manager.prefilter_lines + def auto_rewrite_input(self, cmd): """Print to the screen the rewritten form of the user's command. @@ -2658,7 +2663,7 @@ class InteractiveShell(SingletonConfigurable): """ try: result = self._yrun_cell( - self, raw_cell, store_history, silent, shell_futures) + raw_cell, store_history, silent, shell_futures) finally: self.events.trigger('post_execute') if not silent: diff --git a/packages/python/yap_kernel/yap_ipython/prolog/jupyter.yap b/packages/python/yap_kernel/yap_ipython/prolog/jupyter.yap index 59dc19edc..d97b89b9e 100644 --- a/packages/python/yap_kernel/yap_ipython/prolog/jupyter.yap +++ b/packages/python/yap_kernel/yap_ipython/prolog/jupyter.yap @@ -10,214 +10,37 @@ * - */ -:- module(jupyter, [jupyter_query/3, - ready/3, - valid/3, - errors/2]). + :- module( jupyter, + [jupyter_query/3, + errors/2, + ready/2, + completion/2 + ] + ). - :- use_module(library(yapi)). - :- use_module(library(lists)). - :- use_module(library(maplist)). - :- use_module(library(python)). - :- python_import(sys). +:- use_module(library(yapi)). +:- use_module(library(lists)). +:- use_module(library(maplist)). +:- use_module(library(python)). - :- dynamic user:portray_message/2. - :- multifile user:portray_message/2. +:- python_import(sys). -jupyter_query(Self, Cell, Line ) :- - setup_call_cleanup( +user:jupyter_query(Self, Cell, Line ) :- + setup_call_cleanup( enter_cell(Self), jupyter_cell(Self, Cell, Line), exit_cell(Self) ). -ready(_Self, Line ) :- - blank( Line ), - !. -ready(Self, Line ) :- - errors( Self, Line ), - \+ syntax_error(_,_). - -errors( Self, Text ) :- - setup_call_cleanup( - open_events( Self, Text, Stream), - clauses(Self, Stream), - close_events( Self ) - ). - -clauses(Self, Stream) :- - repeat, - read_clause(Stream, Cl, [term_position(_Pos), syntax_errors(fail)] ), - command( Self, Cl ), - Cl == end_of_file, - !. - -command( _Self, ( :- op(Prio,Assoc,Name) ) ) :- - addop(Prio,Assoc,Name). - -command( _Self, ( :- module(Name, Exports) )) :- - retract( active_module( M0 ) ), - atom_concat( '__m0_', Name, M ), - assert( active_module(M) ), - assert( undo( active_module(M0) ) ), - maplist( addop2(M), Exports). - - -addop(Prio,Assoc,Name) :- - ( - current_op(OPrio, SimilarAssoc, Name), - op(Prio, Assoc, Name), - matched_op(Assoc, SimilarAssoc) - -> - assertz( undo(op( OPrio, Assoc, Name ) ) ) - ; - assertz( undo(op( 0, Assoc, Name ) ) ) - ). - -addop2(M, op(Prio, Assoc, Name)) :- - addop( Prio, Assoc, M:Name ). - -matched_op(A, B) :- - optype( A, T), - optype( B, T). - -optype(fx,pre). -optype(fy,pre). -optype(xfx,in). -optype(xfy,in). -optype(yfx,in). -optype(yfy,in). -optype(xf,pos). -optype(yf,pos). - -:- dynamic user:portray_message/2. -:- multifile user:portray_message/2. - -:- dynamic syntax_error/2, undo/1. - -open_events(Self, Text, Stream) :- - Self.errors := [], - open_mem_read_stream( Text, Stream ), - assert((user:portray_message(_Severity, error(error(syntax_error(_),info(between(_,LN,_), _FileName, CharPos, _Details)))) :- - assert( syntax_error(LN,CharPos) ) - )). - -close_events( Self ) :- - retract( undo(G) ), - call(G), - fail. -close_events( Self ) :- - retract( syntax_error( L, N )), - Self.errors := [t(L,N)] + Self.errors, - fail. -close_events( _ ). - -cell2pq( Cell, ``, ``) :- - sub_string(Cell, 0, 2, _, `%%`), - string_code(3, Cell, Code), - code_type(Code, alpha), - !. -cell2pq( Cell, P, Q, N) :- - sub_string(Cell, 0, 1, _, `%`), - string_codes(Cell, [Code|Codes]), - code_type(Code, alpha), - skip(10, Codes, Rest, LineF,Line1), - skip_blanks(Rest, Body, Line1,Line0), - reverse(Body, RBody), - cell2pq2(RBody, Ps, Qs, N), - extend(Ps, Qs, LineF, Line0, NPs, NQs), - string_codes(P, NPs), - string_codes(Q, NQs). -cell2pq( Cell, P, Q, N) :- - string_codes(Cell, Codes), - reverse(Codes, RCodes), - cell2pq2(RCodes, NPs, NQs, N), - string_codes(P, NPs), - string_codes(Q, NQs). - -% -% terminates with dot -% -cell2pq2(RCodes, NP, NQ, N) :- - skip_allblanks( RCodes, [C|Rest], L1, L0), - ( C =:= "." - -> - N = 1, - RP = RCodes, - RQ = "" - ; - skip_to_blank_line( [C|Rest], RP, L0, []), - RQ = L1, - ( - C =:= "*" - -> - N = -1 - ; - N=1 - ) - ), - reverse(RP,NP), - reverse(RQ,NQ). - -/** - * @pred skip( Char, Input, Remainder, Begin, End) - * - * split the list according to character _Char_: - * - * - _Remainder_ is what is after chars - * - _Begin_-_End_ represents what is before char. - * - */ -skip(_, "", "") --> - !, - []. -skip(C, [C|Cs], Cs) --> - !, - [C]. -skip(C, [OC|Cs], Line) --> - [OC], - skip(C,Cs, Line). - -skip_to_blank_line("", "") --> - !. -skip_to_blank_line(Cs, Left) --> - blank_line(Cs, Left), - !, - []. -skip_to_blank_line(Cs, Line) --> - line(Cs, Line), - !. - -blank_line("", []) --> []. -blank_line([10|Cs], Cs) --> - [10], - !. -blank_line([C|Cs], Rest) --> - { code_type(C, white)}, - !, - [C], - blank_line(Cs, Rest). - -line("", []) --> - []. -line([10|Cs], Cs) --> - [10], - !. -line([C|Cs], Rest) --> - [C], - line(Cs,Rest). - - jupyter_cell(_Self, Cell, _) :- - % stop_low_level_trace, jupyter_consult(Cell), fail. jupyter_cell( _Self, _, Line ) :- blank( Line ), !. +jupyter_cell( Self, _, [] ) :- !. jupyter_cell( Self, _, Line ) :- - % start_low_level_trace, python_query( Self, Line ). jupyter_consult(Text) :- @@ -250,14 +73,14 @@ exit_cell(_Self) :- close( user_error). -completions(S, Self) :- +user:completions(S, Self) :- open_mem_read_stream(S, St), scan_to_list(St, Tokens), close(St), reverse(Tokens, RTokens), strip_final_tokens(RTokens, MyTokens), setof( Completion, complete(MyTokens, Completion), Cs), - Self.completions := Cs. + Self.matches := Cs. strip_final_tokens(['EOT'|Ts], Ts) :- !. @@ -347,3 +170,88 @@ cont(0, F, P, P0) :- atom_concat( F, P, P0 ). cont( _, F, P, PB ):- atom_concat( [F, P, '('], PB ). + + +ready(_Self, Line ) :- + blank( Line ), + !. +ready(Self, Line ) :- + errors( Self, Line ), + \+ syntax_error(_,_). + +user:errors( Self, Text ) :- + setup_call_cleanup( + open_events( Self, Text, Stream), + clauses(Self, Stream), + close_events( Self ) + ). + +clauses(Self, Stream) :- + repeat, + read_clause(Stream, Cl, [term_position(_Pos), syntax_errors(fail)] ), + command( Self, Cl ), + Cl == end_of_file, + !. + +command(_, end_of_file) :- !. + +command( _Self, ( :- op(Prio,Assoc,Name) ) ) :- + addop(Prio,Assoc,Name). + +command( _Self, ( :- module(Name, Exports) )) :- + retract( active_module( M0 ) ), + atom_concat( '__m0_', Name, M ), + assert( active_module(M) ), + assert( undo( active_module(M0) ) ), + maplist( addop2(M), Exports). + + +addop(Prio,Assoc,Name) :- + ( + current_op(OPrio, SimilarAssoc, Name), + op(Prio, Assoc, Name), + matched_op(Assoc, SimilarAssoc) + -> + assertz( undo(op( OPrio, Assoc, Name ) ) ) + ; + assertz( undo(op( 0, Assoc, Name ) ) ) + ). + +addop2(M, op(Prio, Assoc, Name)) :- + addop( Prio, Assoc, M:Name ). + +matched_op(A, B) :- + optype( A, T), + optype( B, T). + +optype(fx,pre). +optype(fy,pre). +optype(xfx,in). +optype(xfy,in). +optype(yfx,in). +optype(yfy,in). +optype(xf,pos). +optype(yf,pos). + +:- dynamic user:portray_message/2. +:- multifile user:portray_message/2. + +:- dynamic syntax_error/4, undo/1. + +open_events(Self, Text, Stream) :- + Self.errors := [], + open_mem_read_stream( Text, Stream ), + assert((user:portray_message(_Severity, error(syntax_error(Cause),info(between(_,LN,_), _FileName, CharPos, Details))) :- + assert( syntax_error(Cause,LN,CharPos,Details) ) + )). + +close_events( Self ) :- + retract( undo(G) ), + call(G), + fail. +close_events( Self ) :- + retract( syntax_error( C, L, N, A )), + Self.errors := [t(C,L,N,A)] + Self.errors, + fail. +close_events( _ ). + diff --git a/packages/python/yap_kernel/yap_ipython/terminal/debugger.py b/packages/python/yap_kernel/yap_ipython/terminal/debugger.py index ce76d3c4d..f09dea94a 100644 --- a/packages/python/yap_kernel/yap_ipython/terminal/debugger.py +++ b/packages/python/yap_kernel/yap_ipython/terminal/debugger.py @@ -3,8 +3,8 @@ import sys from yap_ipython.core.debugger import Pdb -from yap_ipython.core.completer import IPCompleter -from .ptutils import IPythonPTCompleter +from yap_ipython.yapi import YAPCompleter +#from .ptutils import IPythonPTCompleter from .shortcuts import suspend_to_bg, cursor_in_leading_ws from prompt_toolkit.enums import DEFAULT_BUFFER diff --git a/packages/python/yap_kernel/yap_ipython/terminal/interactiveshell.py b/packages/python/yap_kernel/yap_ipython/terminal/interactiveshell.py index 9b6eddb86..5a4b0221c 100644 --- a/packages/python/yap_kernel/yap_ipython/terminal/interactiveshell.py +++ b/packages/python/yap_kernel/yap_ipython/terminal/interactiveshell.py @@ -33,7 +33,7 @@ from .debugger import TerminalPdb, Pdb from .magics import TerminalMagics from .pt_inputhooks import get_inputhook_name_and_func from .prompts import Prompts, ClassicPrompts, RichPromptDisplayHook -from .ptutils import IPythonPTCompleter, IPythonPTLexer +#from .ptutils import IPythonPTCompleter, IPythonPTLexer from .shortcuts import register_ipython_shortcuts DISPLAY_BANNER_DEPRECATED = object() @@ -269,8 +269,8 @@ class TerminalInteractiveShell(InteractiveShell): editing_mode=editing_mode, key_bindings_registry=kbmanager.registry, history=history, - completer=IPythonPTCompleter(shell=self, - patch_stdout=patch_stdout), + # completer=IPythonPTCompleter(shell=self, + # patch_stdout=patch_stdout), enable_history_search=True, style=self.style, mouse_support=self.mouse_support, diff --git a/packages/python/yap_kernel/yap_ipython/terminal/ipapp.py b/packages/python/yap_kernel/yap_ipython/terminal/ipapp.py index d292792f7..89db35052 100644 --- a/packages/python/yap_kernel/yap_ipython/terminal/ipapp.py +++ b/packages/python/yap_kernel/yap_ipython/terminal/ipapp.py @@ -18,7 +18,7 @@ from traitlets.config.loader import Config from traitlets.config.application import boolean_flag, catch_config_error from yap_ipython.core import release from yap_ipython.core import usage -from yap_ipython.core.completer import IPCompleter +from yap_ipython.yapi import YAPCompleter from yap_ipython.core.crashhandler import CrashHandler from yap_ipython.core.formatters import PlainTextFormatter from yap_ipython.core.history import HistoryManager @@ -177,7 +177,7 @@ class LocateIPythonApp(BaseYAPApplication): class TerminalIPythonApp(BaseYAPApplication, InteractiveShellApp): - name = u'ipython' + name = u'yap' description = usage.cl_usage crash_handler_class = IPAppCrashHandler examples = _examples @@ -202,7 +202,7 @@ class TerminalIPythonApp(BaseYAPApplication, InteractiveShellApp): HistoryManager, ProfileDir, PlainTextFormatter, - IPCompleter, + YAPCompleter, ScriptMagics, LoggingMagics, StoreMagics, @@ -301,7 +301,7 @@ class TerminalIPythonApp(BaseYAPApplication, InteractiveShellApp): argv[idx] = '--pylab' return super(TerminalIPythonApp, self).parse_command_line(argv) - + @catch_config_error def initialize(self, argv=None): """Do actions after construct, but before starting the app.""" diff --git a/packages/python/yap_kernel/yap_ipython/yapi.py b/packages/python/yap_kernel/yap_ipython/yapi.py index 33aabb07c..55df85d2e 100644 --- a/packages/python/yap_kernel/yap_ipython/yapi.py +++ b/packages/python/yap_kernel/yap_ipython/yapi.py @@ -2,17 +2,23 @@ import os import sys import abc import math +import itertools + + +from typing import Iterator, List, Tuple, Iterable, Union +from traitlets import Bool, Enum, observe, Int try: - import yap4py.yapi + from yap4py.yapi import Engine except: print("Could not load _yap dll.") from yap_ipython.core import interactiveshell -from yap_ipython.core.completer import IPCompleter +from yap_ipython.core.completer import Completer, Completion from yap_ipython.utils.strdispatch import StrDispatch # import yap_ipython.core from traitlets import Instance - +from yap_ipython.core.inputsplitter import * +from yap_ipython.core.inputtransformer import * from pygments import highlight from pygments.lexers.prolog import PrologLexer from pygments.formatters import HtmlFormatter @@ -26,18 +32,278 @@ library = namedtuple('library', 'list') v = namedtuple('_', 'slot') load_files = namedtuple('load_files', 'file ofile args') python_query= namedtuple('python_query', 'query_mgr string') -JupyterQuery = namedtuple('jupyter_query', 'self text query') +jupyter_query = namedtuple('jupyter_query', 'self text query') enter_cell = namedtuple('enter_cell', 'self' ) exit_cell = namedtuple('exit_cell', 'self' ) completions = namedtuple('completions', 'txt self' ) +errors = namedtuple('errors', 'self text' ) -class YAPCompleter: - def __init__(self, - shell=None, namespace=None, global_namespace=None, - parent=None, - ): - self.completions = None +class YAPInputSplitter(InputSplitter): + """An input splitter that recognizes all of iyap's special syntax.""" + + # String with raw, untransformed input. + source_raw = '' + + # Flag to track when a transformer has stored input that it hasn't given + # back yet. + transformer_accumulating = False + + # Flag to track when assemble_yap_lines has stored input that it hasn't + # given back yet. + within_yap_line = False + + # Private attributes + + # List with lines of raw input accumulated so far. + _buffer_raw = None + + def __init__(self, line_input_checker=True, physical_line_transforms=None, + logical_line_transforms=None): + self._buffer_raw = [] + self._validate = True + self.yapeng = None + + if physical_line_transforms is not None: + self.physical_line_transforms = physical_line_transforms + else: + self.physical_line_transforms = [ + leading_indent(), + classic_prompt(), + ipy_prompt(), + cellmagic(end_on_blank_line=line_input_checker), + ] + + self.assemble_logical_lines = assemble_logical_lines() + if logical_line_transforms is not None: + self.logical_line_transforms = logical_line_transforms + else: + self.logical_line_transforms = [ + help_end(), + escaped_commands(), + assign_from_magic(), + assign_from_system(), + ] + + + @property + def transforms(self): + "Quick access to all transformers." + return self.physical_line_transforms + \ + [self.assemble_logical_lines] + self.logical_line_transforms + + + @property + def transforms_in_use(self): + """Transformers, excluding logical line transformers if we're in a + Python line.""" + t = self.physical_line_transforms + \ + [self.assemble_logical_lines] + self.logical_line_transforms + + def engine(self, engine): + self.yapeng = engine + + def validQuery(self, text, line=None): + """Return whether a legal query + """ + if not line: + (_,line,_) = self.shell.prolog_cell(text) + line = line.strip().rstrip() + if not line: + return False + self.errors = [] + self.yapeng.mgoal(errors(self, line),"user") + return self.errors != [] + + + def reset(self): + """Reset the input buffer and associated state.""" + #super(YAPInputSplitter, self).reset() + self._buffer_raw[:] = [] + self.source_raw = '' + self.transformer_accumulating = False + + for t in self.transforms: + try: + t.reset() + except SyntaxError: + # Nothing that calls reset() expects to handle transformer + # errors + pass + + def flush_transformers(self): + def _flush(transform, outs): + """yield transformed lines + + always strings, never None + + transform: the current transform + outs: an iterable of previously transformed inputs. + Each may be multiline, which will be passed + one line at a time to transform. + """ + for out in outs: + for line in out.splitlines(): + # push one line at a time + tmp = transform.push(line) + if tmp is not None: + yield tmp + + # reset the transform + tmp = transform.reset() + if tmp is not None: + yield tmp + + out = [] + + for t in self.transforms: + out = _flush(t, out) + + out = list(out) + if out: + self._store('\n'.join(out)) + + def raw_reset(self): + """Return raw input only and perform a full reset. + """ + out = self.source_raw + self.reset() + return out + + def source_reset(self): + try: + self.flush_transformers() + return self.source + finally: + self.reset() + + def push_accepts_more(self): + if self.transformer_accumulating: + return True + else: + return self,validQuery(self.source) + + def transform_cell(self, cell): + """Process and translate a cell of input. + """ + self.reset() + try: + self.push(cell) + self.flush_transformers() + return self.source + finally: + self.reset() + + def push(self, lines): + """Push one or more lines of yap_ipython input. + + This stores the given lines and returns a status code indicating + whether the code forms a complete Python block or not, after processing + all input lines for special yap_ipython syntax. + + Any exceptions generated in compilation are swallowed, but if an + exception was produced, the method returns True. + + Parameters + ---------- + lines : string + One or more lines of Python input. + + Returns + ------- + is_complete : boolean + True if the current input source (the result of the current input + plus prior inputs) forms a complete Python execution block. Note that + this value is also stored as a private attribute (_is_complete), so it + can be queried at any time. + """ + + # We must ensure all input is pure unicode + lines = cast_unicode(lines, self.encoding) + # ''.splitlines() --> [], but we need to push the empty line to transformers + lines_list = lines.splitlines() + if not lines_list: + lines_list = [''] + + # Store raw source before applying any transformations to it. Note + # that this must be done *after* the reset() call that would otherwise + # flush the buffer. + self._store(lines, self._buffer_raw, 'source_raw') + + transformed_lines_list = [] + for line in lines_list: + transformed = self._transform_line(line) + if transformed is not None: + transformed_lines_list.append(transformed) + if transformed_lines_list: + transformed_lines = '\n'.join(transformed_lines_list) + else: + # Got nothing back from transformers - they must be waiting for + # more input. + return False + + def _transform_line(self, line): + """Push a line of input code through the various transformers. + + Returns any output from the transformers, or None if a transformer + is accumulating lines. + + Sets self.transformer_accumulating as a side effect. + """ + def _accumulating(dbg): + #print(dbg) + self.transformer_accumulating = True + return None + + for transformer in self.physical_line_transforms: + line = transformer.push(line) + if line is None: + return _accumulating(transformer) + + for transformer in self.logical_line_transforms: + line = transformer.push(line) + if line is None: + return _accumulating(transformer) + + + #print("transformers clear") #debug + self.transformer_accumulating = False + return line + + +class YAPCompleter(Completer): + + greedy = Bool(False, + help="""Activate greedy completion + PENDING DEPRECTION. this is now mostly taken care of with Jedi. + + This will enable completion on elements of lists, results of function calls, etc., + but can be unsafe because the code is actually evaluated on TAB. + """ + ).tag(config=True) + + debug = Bool(default_value=False, + help='Enable debug for the Completer. Mostly print extra ' + 'information for experimental jedi integration.') \ + .tag(config=True) + + backslash_combining_completions = Bool(True, + help="Enable unicode completions, e.g. \\alpha . " + "Includes completion of latex commands, unicode names, and expanding " + "unicode characters back to latex commands.").tag(config=True) + + + + def __init__(self, namespace=None, global_namespace=None, shell=None, **kwargs): + """Create a new completer for the command line. + + Completer(namespace=ns, global_namespace=ns2) -> completer instance. + + """ + + self.shell = shell + self.magic_escape = ESC_MAGIC + super(Completer, self).__init__(**kwargs) def complete(self, text, line=None, cursor_pos=None): """Return the completed text and a list of completions. @@ -50,6 +316,9 @@ class YAPCompleter: instead a line/position pair are given. In this case, the completer itself will split the line like readline does. + This is called successively with state == 0, 1, 2, ... until it + returns None. The completion should begin with 'text'. + line : string, optional The complete line that text is part of. @@ -79,65 +348,197 @@ class YAPCompleter: In [2]: _ip.complete('x.l') Out[2]: ('x.l', ['x.ljust', 'x.lower', 'x.lstrip']) """ - if not text: text = line[:cursor_pos] - self.yapeng.goal(completions(text, self)) - return text, self.completions + return self.completions(text, cursor_pos) - # def _init__(self, **kwargs) -> None: - # PyCompleter.__init__(**kwargs__) + + def magic_matches(self, text): + """Match magics""" + # Get all shell magics now rather than statically, so magics loaded at + # runtime show up too. + lsm = self.shell.magics_manager.lsmagic() + line_magics = lsm['line'] + cell_magics = lsm['cell'] + pre = self.magic_escape + pre2 = pre+pre + + explicit_magic = text.startswith(pre) + + # Completion logic: + # - user gives %%: only do cell magics + # - user gives %: do both line and cell magics + # - no prefix: do both + # In other words, line magics are skipped if the user gives %% explicitly + # + # We also exclude magics that match any currently visible names: + # https://github.com/ipython/ipython/issues/4877, unless the user has + # typed a %: + # https://github.com/ipython/ipython/issues/10754 + bare_text = text.lstrip(pre) + global_matches = [] + if not explicit_magic: + def matches(magic): + """ + Filter magics, in particular remove magics that match + a name present in global namespace. + """ + return ( magic.startswith(bare_text) and + magic not in global_matches ) + else: + def matches(magic): + return magic.startswith(bare_text) + + comp = [ pre2+m for m in cell_magics if matches(m)] + if not text.startswith(pre2): + comp += [ pre+m for m in line_magics if matches(m)] + + return comp + + def magic_config_matches(self, text:str) -> List[str]: + """ Match class names and attributes for %config magic """ + texts = text.strip().split() + + if len(texts) > 0 and (texts[0] == 'config' or texts[0] == '%config'): + # get all configuration classes + classes = sorted(set([ c for c in self.shell.configurables + if c.__class__.class_traits(config=True) + ]), key=lambda x: x.__class__.__name__) + classnames = [ c.__class__.__name__ for c in classes ] + + # return all classnames if config or %config is given + if len(texts) == 1: + return classnames + + # match classname + classname_texts = texts[1].split('.') + classname = classname_texts[0] + classname_matches = [ c for c in classnames + if c.startswith(classname) ] + + # return matched classes or the matched class with attributes + if texts[1].find('.') < 0: + return classname_matches + elif len(classname_matches) == 1 and \ + classname_matches[0] == classname: + cls = classes[classnames.index(classname)].__class__ + help = cls.class_get_help() + # strip leading '--' from cl-args: + help = re.sub(re.compile(r'^--', re.MULTILINE), '', help) + return [ attr.split('=')[0] + for attr in help.strip().splitlines() + if attr.startswith(texts[1]) ] + return [] + + + def magic_color_matches(self, text:str) -> List[str] : + """ Match color schemes for %colors magic""" + texts = text.split() + if text.endswith(' '): + # .split() strips off the trailing whitespace. Add '' back + # so that: '%colors ' -> ['%colors', ''] + texts.append('') + + if len(texts) == 2 and (texts[0] == 'colors' or texts[0] == '%colors'): + prefix = texts[1] + return [ color for color in InspectColors.keys() + if color.startswith(prefix) ] + return [] -class YAPLineProcessor: - def __init__(self, - shell - ): - self.engine = shell.engine - - def validQuery(self, text, line=None, cursor_pos=None): - """Return whether a legal query + def completions(self, text, offset): """ - if not line: - (_,line,_) = self.prolog_cell(text) - line = line.strip().rstrip() - if not line: - return False - self.yapeng.goal(errors(text, line)) - return not self.errors + Returns an iterator over the possible completions - # def _init__(self, **kwargs) -> None: - # PyCompleter.__init__(**kwargs__) + .. warning:: Unstable + + This function is unstable, API may change without warning. + It will also raise unless use in proper context manager. + + Parameters + ---------- + + text:str + Full text of the current input, multi line string. + offset:int + Integer representing the position of the cursor in ``text``. Offset + is 0-based indexed. + + Yields + ------ + :any:`Completion` object + + + The cursor on a text can either be seen as being "in between" + characters or "On" a character depending on the interface visible to + the user. For consistency the cursor being on "in between" characters X + and Y is equivalent to the cursor being "on" character Y, that is to say + the character the cursor is on is considered as being after the cursor. + + Combining characters may span more that one position in the + text. + + + .. note:: + + If ``IPCompleter.debug`` is :any:`True` will yield a ``--jedi/ipython--`` + fake Completion token to distinguish completion returned by Jedi + and usual yap_ipython completion. + + .. note:: + + Completions are not completely deduplicated yet. If identical + completions are coming from different sources this function does not + ensure that each completion object will only be present once. + """ + self.matches = [] + prolog_res = self.shell.yapeng.mgoal(completions(text, self), "user") + magic_res = self.magic_matches(text) + + return text, self.matches+magic_res -class YAPRun(): +class YAPRun: """An enhanced, interactive shell for YAP.""" - def init(self): - self.yapeng = yap4py.yapi.Engine() + def __init__(self, shell): + self.shell = shell + self.yapeng = Engine() self.yapeng.goal(use_module(library("jupyter"))) self.q = None self.run = False - self.port = None + self.shell.port = None + self.shell.yapeng = self.yapeng + self._get_exc_info = shell._get_exc_info + + def syntaxErrors(self, text): + """Return whether a legal query + """ + if not text: + return [] + self.errors=[] + self.yapeng.mgoal(errors(self,text),"user") + return self.errors def jupyter_query(self, s): # import pdb; pdb.set_trace() # # construct a self.query from a one-line string # self.q is opaque to Python - self.bindings = {} + iterations = 0 + self.shell.bindings = {} if self.q and s != self.os: self.q.close() self.q = None if not self.q: #import pdb; pdb.set_trace() - self.port = "call" - program,query,iterations = YAPRun.prolog_cell(self,s) - self.q = self.yapeng.query(JupyterQuery(self, program, query)) - self.Solutions = [] + self.shell.port = "call" + program,query,_ = self.prolog_cell(s) + self.q = self.yapeng.query(jupyter_query(self, program, query)) + self.shell.Solutions = [] if not self.q: return True, [] self.os = s @@ -162,27 +563,26 @@ class YAPRun(): # deterministic = one solution #Dict = {} #engine.goal(show_answer( q.namedVars(), Dict)) - self.Solutions += [self.bindings] - if self.port == "exit": + self.shell.Solutions += [self.shell.bindings] + if self.shell.port == "exit": # done self.q.close() self.q = None self.os = "" - return True, self.Solutions + return True, self.shell.Solutions if iterations == 0: - return True, self.Solutions + return True, self.shell.Solutions else: print("No (more) answers") self.q.close() self.q = None self.os = '' - return True, self.Solutions + return True, self.shell.Solutions def answer(self, q): try: return q.next() except Exception as e: - print(e.args[1]) self.yapeng.goal(exit_cell(self)) return False, None @@ -236,69 +636,75 @@ class YAPRun(): result = interactiveshell.ExecutionResult(info) if (raw_cell == "") or raw_cell.isspace(): - self.last_execution_succeeded = True + self.shell.last_execution_succeeded = True return result if silent: store_history = False if store_history: - result.execution_count = self.execution_count+1 + result.execution_count = self.shell.execution_count+1 def error_before_exec(value): result.error_before_exec = value - self.last_execution_succeeded = False + self.shell.last_execution_succeeded = False return result - self.events.trigger('pre_execute') + self.shell.events.trigger('pre_execute') if not silent: - self.events.trigger('pre_run_cell') - + self.shell.events.trigger('pre_run_cell') # If any of our input transformation (input_transformer_manager or # prefilter_manager) raises an exception, we store it in this variable # so that we can display the error after logging the input and storing # it in the history. preprocessing_exc_tuple = None - try: - # Static input transformations - cell = self.input_transformer_manager.transform_cell(raw_cell) - except SyntaxError: - preprocessing_exc_tuple = self.syntax_error() # sys.exc_info() + # try: + # # Static input transformations + # cell = self.shell.input_transformer_manager.transform_cell(raw_cell) + # except SyntaxError: + # preprocessing_exc_tuple = self.shell.syntax_error() # sys.exc_info() cell = raw_cell # cell has to exist so it can be stored/logged # else: - # # import pdb; pdb.set_trace() # if False and len(cell.splitlines()) == 1: # # Dynamic transformations - only applied for single line commands - # with self.builtin_trap: + # with self.shell.builtin_trap: # try: # # use prefilter_lines to handle trailing newlines # # restore trailing newline for ast.parse - # cell = self.prefilter_manager.prefilter_lines(cell) + '\n' + # cell = self.shell.prefilter_manager.prefilter_lines(cell) + '\n' # except Exception: # # don't allow prefilter errors to crash IPython # preprocessing_exc_tuple = sys.exc_info() + e for i in self.syntaxErrors(raw_cell): + try: + (what,lin,_,text) = i + e = SyntaxError(what, ("", lin, 1, text)) + raise e + except SyntaxError: + self.shell.showsyntaxerror( ) + preprocessing_exc_tuple = sys.exc_info() + # Store raw and processed history if store_history: - self.history_manager.store_inputs(self.execution_count, + self.shell.history_manager.store_inputs(self.shell.execution_count, cell, raw_cell) if not silent: - self.logger.log(cell, raw_cell) + self.shell.logger.log(cell, raw_cell) # # Display the exception if input processing failed. # if preprocessing_exc_tuple is not None: # self.showtraceback(preprocessing_exc_tuple) # if store_history: - # self.execution_count += 1 + # self.shell.execution_count += 1 # return error_before_exec(preprocessing_exc_tuple[2]) # Our own compiler remembers the __future__ environment. If we want to # run code with a separate __future__ environment, use the default # compiler - # compiler = self.compile if shell_futures else CachingCompiler() - - cell_name = str( self.execution_count) + # compiler = self.shell.compile if shell_futures else CachingCompiler() + cell_name = str( self.shell.execution_count) if cell[0] == '%': if cell[1] == '%': @@ -309,53 +715,53 @@ class YAPRun(): mcell = cell.lstrip('%') txt0 = mcell.split(maxsplit = 2, sep = '\n') txt = txt0[0].split(maxsplit = 2) - magic = txt[0] + magic = txt[0] if len(txt) == 2: line = txt[1] else: line = "" if linec: - self.run_line_magic(magic, line) + self.shell.run_line_magic(magic, line) if len(txt0) == 2: cell = txt0[1] else: cellArea = "" else: - self.run_cell_magic(magic, line, cell) + self.shell.run_cell_magic(magic, line, cell) return # Give the displayhook a reference to our ExecutionResult so it # can fill in the output value. - self.displayhook.exec_result = result + self.shell.displayhook.exec_result = result has_raised = False try: - self.bindings = dict = {} - state = YAPRun.jupyter_query(self, cell) + self.shell.bindings = dict = {} + state = self.jupyter_query( cell) if state: - self.last_execution_succeeded = True + self.shell.last_execution_succeeded = True result.result = (True, dict) else: - self.last_execution_succeeded = True + self.shell.last_execution_succeeded = True result.result = (True, {}) except Exception as e: print(e) has_raised = True result.result = False - self.last_execution_succeeded = not has_raised + self.shell.last_execution_succeeded = not has_raised # Reset this so later displayed values do not modify the # ExecutionResult - self.displayhook.exec_result = None - self.events.trigger('post_execute') + self.shell.displayhook.exec_result = None + self.shell.events.trigger('post_execute') if not silent: - self.events.trigger('post_run_cell') + self.shell.events.trigger('post_run_cell') if store_history: # Write output to the database. Does nothing unless # history output logging is enabled. - self.history_manager.store_output(self.execution_count) + self.shell.history_manager.store_output(self.shell.execution_count) # Each cell is a *single* input, regardless of how many lines it has - self.execution_count += 1 + self.shell.execution_count += 1 return result @@ -377,12 +783,14 @@ class YAPRun(): its = 0 s0 = '' for c in s: - if c == '\n' or c.isblank(): - s0 += [c] + if c == '\n' or c.isspace(): + s0 += c + break sf = '' for c in reversed(s): - if c == '\n' or c.isblank(): - sf += [c]+sf + if c == '\n' or c.isspace(): + sf += c + break [program,x,query] = s.rpartition('\n') if query == '': query = program diff --git a/packages/python/yap_kernel/yap_kernel/ipkernel.py b/packages/python/yap_kernel/yap_kernel/ipkernel.py index e82cae219..b9107962a 100644 --- a/packages/python/yap_kernel/yap_kernel/ipkernel.py +++ b/packages/python/yap_kernel/yap_kernel/ipkernel.py @@ -15,7 +15,7 @@ from .zmqshell import ZMQInteractiveShell try: from yap_ipython.core.completer import rectify_completions as _rectify_completions, provisionalcompleter as _provisionalcompleter - _use_experimental_60_completion = True + _use_experimental_60_completion = False except ImportError: _use_experimental_60_completion = False @@ -203,6 +203,7 @@ class YAPKernel(KernelBase): self._forward_input(allow_stdin) reply_content = {} + import trace; try: res = shell.run_cell(code, store_history=store_history, silent=silent) finally: diff --git a/packages/python/yap_kernel/yap_kernel/kernelapp.py b/packages/python/yap_kernel/yap_kernel/kernelapp.py index 8f7f980a6..a906201cc 100644 --- a/packages/python/yap_kernel/yap_kernel/kernelapp.py +++ b/packages/python/yap_kernel/yap_kernel/kernelapp.py @@ -35,14 +35,14 @@ from jupyter_client import write_connection_file from jupyter_client.connect import ConnectionFileMixin # local imports -from .iostream import IOPubThread -from .heartbeat import Heartbeat -from .ipkernel import YAPKernel -from .parentpoller import ParentPollerUnix, ParentPollerWindows +from yap_kernel.iostream import IOPubThread +from yap_kernel.heartbeat import Heartbeat +from yap_kernel.ipkernel import YAPKernel +from yap_kernel.parentpoller import ParentPollerUnix, ParentPollerWindows from jupyter_client.session import ( Session, session_flags, session_aliases, ) -from .zmqshell import ZMQInteractiveShell +from yap_kernel.zmqshell import ZMQInteractiveShell #----------------------------------------------------------------------------- # Flags and Aliases diff --git a/packages/python/yap_kernel/yap_kernel/resources/logo-32x32.png b/packages/python/yap_kernel/yap_kernel/resources/logo-32x32.png deleted file mode 100755 index be8133076..000000000 Binary files a/packages/python/yap_kernel/yap_kernel/resources/logo-32x32.png and /dev/null differ diff --git a/packages/python/yap_kernel/yap_kernel/resources/logo-64x64.png b/packages/python/yap_kernel/yap_kernel/resources/logo-64x64.png deleted file mode 100755 index eebbff638..000000000 Binary files a/packages/python/yap_kernel/yap_kernel/resources/logo-64x64.png and /dev/null differ diff --git a/packages/python/yap_kernel/yap_kernel/zmqshell.py b/packages/python/yap_kernel/yap_kernel/zmqshell.py index dd14c4761..ff1627713 100644 --- a/packages/python/yap_kernel/yap_kernel/zmqshell.py +++ b/packages/python/yap_kernel/yap_kernel/zmqshell.py @@ -235,7 +235,7 @@ class KernelMagics(Magics): -n Open the editor at a specified line number. By default, the yap_ipython - editor hook uses the unix syntax 'editor +N filename', but you can + editor hook uses the unix syntax//i 'editor +N filename', but you can configure this by providing your own modified hook if your favorite editor supports line-number specifications with a different syntax. diff --git a/pl/CMakeLists.txt b/pl/CMakeLists.txt index b578e7a7e..2942a0e78 100644 --- a/pl/CMakeLists.txt +++ b/pl/CMakeLists.txt @@ -8,6 +8,7 @@ set(PL_BOOT_SOURCES boot.yap bootlists.yap bootutils.yap + builtins.yap callcount.yap checker.yap consult.yap @@ -26,7 +27,7 @@ set(PL_BOOT_SOURCES grammar.yap ground.yap hacks.yap - init.yap + imports.yap listing.yap load_foreign.yap messages.yap @@ -59,11 +60,16 @@ set(PL_BOOT_SOURCES add_to_group(PL_BOOT_SOURCES pl_boot_library) +install(FILES ${PL_BOOT_SOURCES} + DESTINATION ${libpl}/pl + ) +install(FILES ../library/ypp.yap + DESTINATION ${libpl}/library + ) if (ANDROID) add_custom_target(STARTUP DEPENDS ${PL_BOOT_SOURCES} ) - file (INSTALL ${PL_BOOT_SOURCES} DESTINATION ${libpl}/pl) else(CMAKE_CROSSCOMPILING) add_custom_target(STARTUP ALL SOURCES DEPENDS ${PL_BOOT_SOURCES} @@ -72,27 +78,17 @@ else(CMAKE_CROSSCOMPILING) #add_custom_target(STARTUP ALL # DEPENDS ${CMAKE_TOP_BINARY_DIR}/${YAP_STARTUP} # ) - add_custom_command(OUTPUT ${CMAKE_TOP_BINARY_DIR}/${YAP_STARTUP} - COMMAND ./yap -B + install(CODE + "execute_process(COMMAND ${bindir}/yap -B VERBATIM - WORKING_DIRECTORY ${CMAKE_TOP_BINARY_DIR} - DEPENDS ${PL_BOOT_SOURCES} yap-bin - ) + WORKING_DIRECTORY ${dlls} + )") # install(CODE "execute_process(COMMAND ./yap -B # WORKING_DIRECTORY ${CMAKE_TOP_BINARY_DIR})" # DEPENDS Py4YAP ${PL_BOOT_SOURCES} yap-bin ) - install(FILES ${CMAKE_TOP_BINARY_DIR}/${YAP_STARTUP} - DESTINATION ${YAP_INSTALL_DLLDIR} - ) endif() -install(FILES ${PL_BOOT_SOURCES} - DESTINATION ${libpl}/pl - ) -install(FILES ../library/ypp.yap - DESTINATION ${libpl}/library - ) diff --git a/pl/boot.yap b/pl/boot.yap index 5c683e0c0..edd29fb68 100644 --- a/pl/boot.yap +++ b/pl/boot.yap @@ -28,154 +28,6 @@ */ -/** @pred :_P_ ; :_Q_ is iso -Disjunction of goals (or). - -Example: - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - p(X) :- q(X); r(X). -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -should be read as "p( _X_) if q( _X_) or r( _X_)". - - -*/ - -/** @pred \+ 0:P is iso -Negation by failure. - -Goal _P_ is not provable. The execution of this predicate fails if -and only if the goal _P_ finitely succeeds. It is not a true logical -negation, which is impossible in standard Prolog, but -"negation-by-failure". - -This predicate might be defined as: - -~~~~~~~~~~~~ - \+(P) :- P, !, fail. - \+(_). -~~~~~~~~~~~~ -if _P_ did not include "cuts". - -If _P_ includes cuts, the cuts are defined to be scoped by _P_: they cannot cut over the calling prredicate. - - ~~~~~~~~~~~~ - go(P). - -:- \+ P, !, fail. - \+(_). - ~~~~~~~~~~~~ - -*/ - -/** @pred 0:Condition -> 0:Action is iso - - -@short If _Condition__ has a solution, call _Action_; - -@long -Read as "if-then-else" or "commit". This operator is similar to the -conditional operator of imperative languages and can be used alone or -with an else part as follows: - - -~~~~~ - +P -> +Q -~~~~~ - -"if P then Q". - - -~~~~~ - +P -> +Q; +R -~~~~~ - -"if P then Q else R". - -These two predicates could be defined respectively in Prolog as: - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - (P -> Q) :- P, !, Q. -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -and - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - (P -> Q; R) :- P, !, Q. - (P -> Q; R) :- R. -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -if there were no "cuts" in _P_, _Q_ and _R_. - -Note that the commit operator works by "cutting" any alternative -solutions of _P_. - -Note also that you can use chains of commit operators like: - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - P -> Q ; R -> S ; T. -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Note that `(->)/2` does not affect the scope of cuts in its -arguments. - - -*/ - -/** @pred 0:Condition *-> 0:Action is iso - -This construct implements the so-called soft-cut. The control is -defined as follows: - + If _Condition_ succeeds at least once, the -semantics is the same as ( _Condition_, _Action_). - - + If - _Condition_ does not succeed, the semantics is that of (\\+ - _Condition_, _Else_). - - In other words, if _Condition_ -succeeds at least once, simply behave as the conjunction of - _Condition_ and _Action_, otherwise execute _Else_. - -The construct _A *-> B_, i.e. without an _Else_ branch, is -translated as the normal conjunction _A_, _B_. - - -*/ - -/** @pred ! is iso - - -Read as "cut". Cuts any choices taken in the current procedure. -When first found "cut" succeeds as a goal, but if backtracking should -later return to it, the parent goal (the one which matches the head of -the clause containing the "cut", causing the clause activation) will -fail. This is an extra-logical predicate and cannot be explained in -terms of the declarative semantics of Prolog. - -example: - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - member(X,[X|_]). - member(X,[_|L]) :- member(X,L). -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -With the above definition - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - ?- member(X,[1,2,3]). -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -will return each element of the list by backtracking. With the following -definition: - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - member(X,[X|_]) :- !. - member(X,[_|L]) :- member(X,L). -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -the same query would return only the first element of the -list, since backtracking could not "pass through" the cut. - -*/ - system_module(_Mod, _SysExps, _Decls). % new_system_module(Mod). @@ -256,100 +108,29 @@ private(_). :- use_system_module( '$_strict_iso', ['$check_iso_strict_clause'/1, '$iso_check_goal'/2]). +% be careful here not to generate an undefined exception. -'$early_print_message'(Level, Msg) :- - '$pred_exists'(print_message(_,_), prolog), !, - print_message( Level, Msg). -'$early_print_message'(informational, _) :- - yap_flag( verbose, S), - S == silent, - !. -'$early_print_message'(_, absolute_file_path(X, Y)) :- !, - format(user_error, X, Y), nl(user_error). -'$early_print_message'(_, loading( C, F)) :- !, - (yap_flag( verbose_load , silent ) -> true; - format(user_error, '~*|% ~a ~w...~n', [2,C,F]) ). -'$early_print_message'(_, loaded(F,C,M,T,H)) :- !, - (yap_flag( verbose_load , silent ) -> true; - format(user_error, '~*|% ~a:~w ~a ~d bytes in ~d seconds...~n', [2, M, F ,C, H, T]) ). -'$early_print_message'(_, loaded(F,C,M,T,H)) :- !, - (yap_flag( verbose_load , silent ) -> true; - format(user_error, '~*|% ~a:~w ~a ~d bytes in ~d seconds...~n', [2, M, F ,C, H, T]) ). -'$early_print_message'(_, loaded(F,C,M,T,H)) :- !, - (yap_flag( verbose_load , silent ) -> true; - format(user_error, '~*|% ~a:~w ~a ~d bytes in ~d seconds...~n', [2, M, F ,C, H, T]) ). -'$early_print_message'(Level, Msg) :- - source_location(F0, L), - !, - format(user_error, '~a:~d:0: unprocessed ~a ~w ~n', [F0, L,Level,Msg]). -'$early_print_message'(Level, Msg) :- - format(user_error, 'unprocessed ~a ~w ~n', [Level,Msg]). -'$bootstrap_predicate'('$expand_a_clause'(_,_,_,_), _M, _) :- !, - fail. -'$bootstrap_predicate'('$imported_predicate'(_,_,_,_), _M, _) :- !, - fail. -'$bootstrap_predicate'('$process_directive'(Gs, _Mode, M, _VL, _Pos) , _M, _) :- !, - '$execute'( M:Gs ). - '$bootstrap_predicate'('$LoopError'( Error, _), _M, _) :- !, - source_location(F0, L), - format('~a:~d:0: error in bootstrap:~n ~w~n', [F0,L,Error]), - fail. -'$bootstrap_predicate'(delayed_goals(_, _, _ , _), _M, _) :- !, - fail. -'$bootstrap_predicate'(sort(L, S), _M, _) :- !, - '$sort'(L, S). -'$bootstrap_predicate'(print_message(Context, Msg), _M, _) :- !, - '$early_print_message'(Context, Msg). -'$bootstrap_predicate'(print_message(Context, Msg), _M, _) :- !, - '$early_print_message'(Context, Msg). -'$bootstrap_predicate'(prolog_file_type(A,prolog), _, _) :- !, - ( A = yap ; A = pl ; A = prolog ). -'$bootstrap_predicate'(file_search_path(_A,_B), _, _ ) :- !, fail. -'$bootstrap_predicate'(meta_predicate(G), M, _) :- !, - strip_module(M:G, M1, G1), - '$meta_predicate'(M1:G1). -'$bootstrap_predicate'(G, ImportingMod, _) :- - recorded('$import','$import'(ExportingModI,ImportingMod,G,G0I,_,_),_), !, - % writeln('$execute0'(G0I, ExportingModI)), - '$execute0'(G0I, ExportingModI). - % undef handler -'$bootstrap_predicate'(G0, M0, Action) :- - % make sure we do not loop on undefined predicates - yap_flag( unknown, Action, fail), - clause_location(Call, Caller), - format(user_error,'undefined directive ~w', [M0:G0]), - strip_module(M0:G0,M1,NGoal), - throw(error(evaluation(undefined,M0:G0), - [[g|g(M1:NGoal)],[p|Call],[e|Caller],[h|g(M0:G0)]])). -% -% -% -'$undefp0'([M|G], Action) :- - '$bootstrap_predicate'(G, M, Action). -/** @pred true is iso -Succeed. +'$undefp0'([_M|'$imported_predicate'(G, _ImportingMod, G, prolog)], _Action) :- + nonvar(G), '$is_system_predicate'(G, prolog), !. +'$undefp0'([_M|print_message(A,B)], _Action) :- + !. +'$undefp0'([_M|sort(A,B)], _Action) :- + !, + '$sort'(A,B). +'$undefp0'([M|G], _Action) :- + stream_property( loop_stream, file_name(F)), + stream_property( loop_stream, line_number(L)), + %'$bootstrap_predicate'(G, M, Action). + writeln(F:L:M:G), + fail. + +:- '$undefp_handler'('$undefp0'(_,_),prolog). -Succeeds once. -*/ -true :- true. live :- - '$live'. - -initialize_prolog :- - '$init_system'. - -'$live' :- - '$init_system', - '$do_live'. - -'$init_prolog' :- - '$init_system'. - -'$do_live' :- - repeat, + repeat, '$current_module'(Module), ( Module==user -> true % '$compile_mode'(_,0) @@ -358,71 +139,10 @@ initialize_prolog :- ), '$system_catch'('$enter_top_level',Module,Error,'$Error'(Error)). +initialize_prolog :- + '$init_system'. -'$init_system' :- - get_value('$yap_inited', true), !. -'$init_system' :- - % start_low_level_trace, - % do catch as early as possible - ( - % \+ '$uncaught_throw' - current_prolog_flag(halt_after_consult, false), - current_prolog_flag(verbose, normal) - -> - '$version' - ; - true - ), - current_prolog_flag(file_name_variables, OldF), - set_prolog_flag(file_name_variables, true), - '$init_consult', - set_prolog_flag(file_name_variables, OldF), - '$init_globals', - set_prolog_flag(fileerrors, true), - set_value('$gc',on), - ('$exit_undefp' -> true ; true), - prompt1(' ?- '), - set_prolog_flag(debug, false), - % simple trick to find out if this is we are booting from Prolog. - % boot from a saved state - ( - current_prolog_flag(saved_program, false) - -> - prolog_flag(verbose_load, OldVL, silent), - prolog_flag(verbose, OldV, silent), - prolog_flag(resource_database, RootPath), - file_directory_name( RootPath, Dir ), - atom_concat( Dir, '/init.yap' , Init), - bootstrap(Init), - prolog_flag(verbose, OldV, silent), - set_prolog_flag(verbose_load, OldVL), - module( user ), - '$make_saved_state' - ; - % use saved state - '$init_state' - ), - '$db_clean_queues'(0), - % this must be executed from C-code. - % '$startup_saved_state', - set_input(user_input), - set_output(user_output), - '$init_or_threads', - '$run_at_thread_start', - set_value('$yap_inited', true). - -'$make_saved_state' :- - current_prolog_flag(os_argv, Args), - ( - lists:member( Arg, Args ), - atom_concat( '-B', _, Arg ) - -> - qsave_program( 'startup.yss'), - halt(0) - ; - true - ). '$init_globals' :- @@ -461,6 +181,55 @@ initialize_prolog :- W1 is W-1, '$start_orp_threads'(W1). +'$version' :- + current_prolog_flag(halt_after_consult, false), + current_prolog_flag(verbose, normal), !, + current_prolog_flag(version_git,VersionGit), + current_prolog_flag(compiled_at,AT), + current_prolog_flag(version_data, yap(Mj, Mi, Patch, _) ), + sub_atom( VersionGit, 0, 8, _, VERSIONGIT ), + current_prolog_flag(version_data, yap(Mj, Mi, Patch, _) ), + current_prolog_flag(resource_database, Saved ), + format(user_error, '% YAP ~d.~d.~d-~a (compiled ~a)~n', [Mj,Mi, Patch, VERSIONGIT, AT]), + format(user_error, '% database loaded from ~a~n', [Saved]), + fail. +'$version'. + +'$init_system' :- + get_value('$yap_inited', true), !. +'$init_system' :- + set_value('$yap_inited', true), % start_low_level_trace, + % do catch as early as possible + '$version', + current_prolog_flag(file_name_variables, OldF), + set_prolog_flag(file_name_variables, true), + '$init_consult', + set_prolog_flag(file_name_variables, OldF), + '$init_globals', + set_prolog_flag(fileerrors, true), + set_value('$gc',on), + ('$exit_undefp' -> true ; true), + prompt1(' ?- '), + set_prolog_flag(debug, false), + % simple trick to find out if this is we are booting from Prolog. + % boot from a saved state + ( + current_prolog_flag(saved_program, true) + % use saved state + -> + '$init_state' + ; + qsave_program( 'startup.yss') + ), + '$db_clean_queues'(0), + % this must be executed from C-code. + % '$startup_saved_state', + set_input(user_input), + set_output(user_output), + '$init_or_threads', + '$run_at_thread_start'. + + % Start file for yap /* I/O predicates */ @@ -546,55 +315,6 @@ initialize_prolog :- '$erase_sets' :- \+ recorded('$path',_,_), recorda('$path',"",_). '$erase_sets'. -'$version' :- - current_prolog_flag(version_git,VersionGit), - current_prolog_flag(compiled_at,AT), - current_prolog_flag(version_data, yap(Mj, Mi, Patch, _) ), - sub_atom( VersionGit, 0, 8, _, VERSIONGIT ), - current_prolog_flag(version_data, yap(Mj, Mi, Patch, _) ), - current_prolog_flag(resource_database, Saved ), - format(user_error, '% YAP ~d.~d.~d-~a (compiled ~a)~n', [Mj,Mi, Patch, VERSIONGIT, AT]), - format(user_error, '% database loaded from ~a~n', [Saved]), - fail. -'$version'. - -/** @pred repeat is iso -Succeeds repeatedly. - -In the next example, `repeat` is used as an efficient way to implement -a loop. The next example reads all terms in a file: -~~~~~~~~~~~~~{.prolog} - a :- repeat, read(X), write(X), nl, X=end_of_file, !. -~~~~~~~~~~~~~ -the loop is effectively terminated by the cut-goal, when the test-goal -`X=end` succeeds. While the test fails, the goals `read(X)`, -`write(X)`, and `nl` are executed repeatedly, because -backtracking is caught by the `repeat` goal. - -The built-in `repeat/0` could be defined in Prolog by: - -~~~~~{.prolog} - repeat. - repeat :- repeat. -~~~~~ - -The predicate between/3 can be used to iterate for a pre-defined -number of steps. - -*/ - repeat :- '$repeat'. - - '$repeat'. - '$repeat'. - '$repeat'. - '$repeat'. - '$repeat'. - '$repeat'. - '$repeat'. - '$repeat'. - '$repeat'. - '$repeat' :- '$repeat'. - '$start_corouts' :- eraseall('$corout'), eraseall('$result'), @@ -652,7 +372,7 @@ number of steps. '$do_error'(type_error(callable,R),meta_call(Source)). '$execute_command'(end_of_file,_,_,_,_) :- !. '$execute_command'(Command,_,_,_,_) :- - '$nb_getval'('$if_skip_mode', skip, fail), + '__NB_getval__'('$if_skip_mode', skip, fail), \+ '$if_directive'(Command), !. '$execute_command'((:-G),VL,Pos,Option,_) :- @@ -739,9 +459,9 @@ number of steps. '$init_as_dynamic'( asserta ). '$init_as_dynamic'( assertz ). '$init_as_dynamic'( consult ) :- - '$nb_getval'('$assert_all',on,fail). + '__NB_getval__'('$assert_all',on,fail). '$init_as_dynamic'( reconsult ) :- - '$nb_getval'('$assert_all',on,fail). + '__NB_getval__'('$assert_all',on,fail). '$check_if_reconsulted'(N,A) :- once(recorded('$reconsulted',N/A,_)), @@ -1052,46 +772,6 @@ write_query_answer( Bindings ) :- '$write_output_vars'(VL). -/** @pred + _P_ is nondet - -The same as `call( _P_)`. This feature has been kept to provide -compatibility with C-Prolog. When compiling a goal, YAP -generates a `call( _X_)` whenever a variable _X_ is found as -a goal. - -~~~~~{.prolog} - a(X) :- X. -~~~~~ -is converted to: - -~~~~~{.prolog} - a(X) :- call(X). -~~~~~ - - -*/ - -/** @pred call(+ _P_) is iso -Meta-call predicate. - -If _P_ is instantiated to an atom or a compound term, the goal `call( -_P_)` is executed as if the clause was originally written as _P_ -instead as call( _P_ ), except that any "cut" occurring in _P_ only -cuts alternatives in the execution of _P_. - - -*/ -call(G) :- '$execute'(G). - -/** @pred incore(+ _P_) - - -The same as call/1. - - -*/ -incore(G) :- '$execute'(G). - % % standard meta-call, called if $execute could not do everything. % @@ -1125,68 +805,10 @@ incore(G) :- '$execute'(G). '$enable_debugging'. '$trace_on' :- - '$nb_getval'('$trace', on, fail). + '__NB_getval__'('$trace', on, fail). '$trace_off' :- - '$nb_getval'('$trace', off, fail). - - -/** @pred :_P_ , :_Q_ is iso, meta -Conjunction of goals (and). - -The conjunction is a fundamental construct of Prolog. Example: - -~~~~~~~ - p(X) :- q(X), r(X). -~~~~~~~ - -should be read as `p( _X_) if q( _X_) and r( _X_). - - -*/ -','(X,Y) :- - yap_hacks:env_choice_point(CP), - '$current_module'(M), - '$call'(X,CP,(X,Y),M), - '$call'(Y,CP,(X,Y),M). -';'((X->A),Y) :- !, - yap_hacks:env_choice_point(CP), - '$current_module'(M), - ( '$execute'(X) - -> - '$call'(A,CP,(X->A;Y),M) - ; - '$call'(Y,CP,(X->A;Y),M) - ). -';'((X*->A),Y) :- !, - yap_hacks:env_choice_point(CP), - '$current_module'(M), - ( - '$current_choice_point'(DCP), - '$execute'(X), - yap_hacks:cut_at(DCP), - '$call'(A,CP,((X*->A),Y),M) - ; - '$call'(Y,CP,((X*->A),Y),M) - ). -';'(X,Y) :- - yap_hacks:env_choice_point(CP), - '$current_module'(M), - ( '$call'(X,CP,(X;Y),M) ; '$call'(Y,CP,(X;Y),M) ). -'|'(X,Y) :- - yap_hacks:env_choice_point(CP), - '$current_module'(M), - ( '$call'(X,CP,(X|Y),M) ; '$call'(Y,CP,(X|Y),M) ). -'->'(X,Y) :- - yap_hacks:env_choice_point(CP), - '$current_module'(M), - ( '$call'(X,CP,(X->Y),M) -> '$call'(Y,CP,(X->Y),M) ). -'*->'(X,Y) :- - yap_hacks:env_choice_point(CP), - '$current_module'(M), - ( '$call'(X,CP,(X*->Y),M), '$call'(Y,CP,(X*->Y),M) ). -\+(G) :- \+ '$execute'(G). -not(G) :- \+ '$execute'(G). + '__NB_getval__'('$trace', off, fail). '$cut_by'(CP) :- '$$cut_by'(CP). @@ -1305,38 +927,6 @@ not(G) :- \+ '$execute'(G). '$check_callable'(_,_). -bootstrap(F) :- - yap_flag(verbose_load, Old, silent), - open(F, read, Stream), - stream_property(Stream, [file_name(File)]), - '$start_consult'(consult, File, LC), - file_directory_name(File, Dir), - working_directory(OldD, Dir), - ( - current_prolog_flag(verbose_load, silent) - -> - true - ; - H0 is heapused, '$cputime'(T0,_), - format(user_error, '~*|% consulting ~w...~n', [LC,F]) - ), - '$boot_loop'(Stream,consult), - working_directory(_, OldD), - '$current_module'(_, prolog), - '$end_consult', - ( - current_prolog_flag(verbose_load, silent) - -> - true - ; - H is heapused-H0, '$cputime'(TF,_), T is TF-T0, - format(user_error, '~*|% ~w consulted ~w bytes in ~d msecs~n', [LC,F,H,T]) - ), - !, - yap_flag(verbose_load, _, Old), - close(Stream). - - '$loop'(Stream,exo) :- prolog_flag(agc_margin,Old,0), prompt1(': '), prompt(_,' '), @@ -1682,6 +1272,677 @@ log_event( String, Args ) :- prompt(_,' | '), '$ensure_prompting'. + /** @} @} */ + + +/** + +@{ + @defgroup library The Prolog library + + + + @addtogroup YAPControl +@ingroup builtins + @{ +*/ +:- system_module( '$_init', [!/0, + ':-'/1, + '?-'/1, + []/0, + extensions_to_present_answer/1, + fail/0, + false/0, + goal_expansion/2, + goal_expansion/3, + otherwise/0, + term_expansion/2, + version/2, + '$do_log_upd_clause'/6, + '$do_log_upd_clause0'/6, + '$do_log_upd_clause_erase'/6, + '$do_static_clause'/5], [ + '$system_module'/1]). + +:- use_system_module( '$_boot', ['$cut_by'/1]). + +%:- start_low_level_trace. + +% This is the YAP init file +% should be consulted first step after booting + +% These are pseudo declarations +% so that the user will get a redefining system predicate + + +% just create a choice-point +% the 6th argument marks the time-stamp. +'$do_log_upd_clause'(_,_,_,_,_,_). +'$do_log_upd_clause'(A,B,C,D,E,_) :- + '$continue_log_update_clause'(A,B,C,D,E). +'$do_log_upd_clause'(_,_,_,_,_,_). + + +'$do_log_upd_clause_erase'(_,_,_,_,_,_). +'$do_log_upd_clause_erase'(A,B,C,D,E,_) :- + '$continue_log_update_clause_erase'(A,B,C,D,E). +'$do_log_upd_clause_erase'(_,_,_,_,_,_). + +'$do_log_upd_clause0'(_,_,_,_,_,_). +'$do_log_upd_clause0'(A,B,C,D,_,_) :- + '$continue_log_update_clause'(A,B,C,D). +'$do_log_upd_clause0'(_,_,_,_,_,_). + + +'$do_static_clause'(_,_,_,_,_). +'$do_static_clause'(A,B,C,D,E) :- + '$continue_static_clause'(A,B,C,D,E). +'$do_static_clause'(_,_,_,_,_). + +%:- start_low_level_trace. +:- c_compile('arith.yap'). +:- c_compile('builtins.yap'). +%:- stop_low_level_trace. + +:- '$all_current_modules'(M), yap_flag(M:unknown, error) ; true. + + +:- compile_expressions. + + +:- c_compile('imports.yap'). +:- c_compile('bootutils.yap'). +:- c_compile('bootlists.yap'). +:- c_compile('consult.yap'). +:- c_compile('preddecls.yap'). +:- c_compile('preddyns.yap'). +:- c_compile('meta.yap'). +:- c_compile('newmod.yap'). + +:- c_compile('atoms.yap'). +:- c_compile('os.yap'). +:- c_compile('grammar.yap'). +:- c_compile('errors.yap'). +:- c_compile('absf.yap'). + +%:- set_prolog_flag(verbose_file_search, true ). +%:- yap_flag(write_strings,on). +%:- start_low_level_trace. +:- [ + 'preds.yap', + 'modules.yap' + ]. + + + :- use_module('error.yap'). + + +:- [ + 'utils.yap', + 'control.yap', + 'flags.yap' +]. + + +:- [ + % lists is often used. + '../os/yio.yap', + '../pl/debug.yap', + 'checker.yap', + 'depth_bound.yap', + 'ground.yap', + 'listing.yap', + 'arithpreds.yap', + % modules must be after preds, otherwise we will have trouble + % with meta-predicate expansion being invoked + % must follow grammar + 'eval.yap', + 'signals.yap', + 'profile.yap', + 'callcount.yap', + 'load_foreign.yap', +% 'save.yap', + 'setof.yap', + 'sort.yap', + 'statistics.yap', + 'strict_iso.yap', + 'tabling.yap', + 'threads.yap', + 'eam.yap', + 'yapor.yap', + 'qly.yap', + 'spy.yap', + 'udi.yap']. + + +:- meta_predicate(log_event(+,:)). + +:- dynamic prolog:'$user_defined_flag'/4. + +:- multifile prolog:debug_action_hook/1. + +:- multifile prolog:'$system_predicate'/2. + +:- ['protect.yap']. + +version(yap,[6,3]). + +:- op(1150,fx,(mode)). + +:- dynamic 'extensions_to_present_answer'/1. + +:- ['arrays.yap']. +%:- start_low_level_trace. + +:- multifile user:portray_message/2. + +:- dynamic user:portray_message/2. + +/** @pred _CurrentModule_:goal_expansion(+ _G_,+ _M_,- _NG_), user:goal_expansion(+ _G_,+ _M_,- _NG_) + + +YAP now supports goal_expansion/3. This is an user-defined +procedure that is called after term expansion when compiling or +asserting goals for each sub-goal in a clause. The first argument is +bound to the goal and the second to the module under which the goal + _G_ will execute. If goal_expansion/3 succeeds the new +sub-goal _NG_ will replace _G_ and will be processed in the same + way. If goal_expansion/3 fails the system will use the defaultyap+flrules. + + +*/ +:- multifile user:goal_expansion/3. + +:- dynamic user:goal_expansion/3. + +:- multifile user:goal_expansion/2. + +:- dynamic user:goal_expansion/2. + +:- multifile system:goal_expansion/2. + +:- dynamic system:goal_expansion/2. + +:- multifile goal_expansion/2. + +:- dynamic goal_expansion/2. + +:- use_module('messages.yap'). + +:- ['undefined.yap']. + +:- use_module('hacks.yap'). + + +:- use_module('attributes.yap'). +:- use_module('corout.yap'). +:- use_module('dialect.yap'). +:- use_module('dbload.yap'). +:- use_module('../library/ypp.yap'). +:- use_module('../os/chartypes.yap'). +:- ensure_loaded('../os/edio.yap'). + +yap_hacks:cut_by(CP) :- '$$cut_by'(CP). + +:- '$change_type_of_char'(36,7). % Make $ a symbol character + +:- set_prolog_flag(generate_debug_info,true). + +% +% cleanup ensure loaded and recover some data-base space. +% +%:- ( recorded('$lf_loaded',_,R), erase(R), fail ; true ). +%:- ( recorded('$module',_,R), erase(R), fail ; true ). + +:- set_value('$user_module',user), '$protect'. + +:- style_check([+discontiguous,+multiple,+single_var]). + +% +% moved this to init_gc in gc.c to separate the alpha +% +% :- yap_flag(gc,on). + +% :- yap_flag(gc_trace,verbose). + +:- multifile + prolog:comment_hook/3. + +:- source. + +:- module(user). + + +/** @pred _CurrentModule_:term_expansion( _T_,- _X_), user:term_expansion( _T_,- _X_) + + +This user-defined predicate is called by `expand_term/3` to +preprocess all terms read when consulting a file. If it succeeds: + ++ +If _X_ is of the form `:- G` or `?- G`, it is processed as +a directive. ++ +If _X_ is of the form `$source_location`( _File_, _Line_): _Clause_` it is processed as if from `File` and line `Line`. + ++ +If _X_ is a list, all terms of the list are asserted or processed +as directives. ++ The term _X_ is asserted instead of _T_. + + + +*/ +:- multifile term_expansion/2. + +:- dynamic term_expansion/2. + +:- multifile system:term_expansion/2. + +:- dynamic system:term_expansion/2. + +:- multifile swi:swi_predicate_table/4. + +/** @pred user:message_hook(+ _Term_, + _Kind_, + _Lines_) + + +Hook predicate that may be define in the module `user` to intercept +messages from print_message/2. _Term_ and _Kind_ are the +same as passed to print_message/2. _Lines_ is a list of +format statements as described with print_message_lines/3. + +This predicate should be defined dynamic and multifile to allow other +modules defining clauses for it too. + + +*/ +:- multifile user:message_hook/3. + +:- dynamic user:message_hook/3. + +/** @pred exception(+ _Exception_, + _Context_, - _Action_) + + +Dynamic predicate, normally not defined. Called by the Prolog system on run-time exceptions that can be repaired `just-in-time`. The values for _Exception_ are described below. See also catch/3 and throw/1. +If this hook predicate succeeds it must instantiate the _Action_ argument to the atom `fail` to make the operation fail silently, `retry` to tell Prolog to retry the operation or `error` to make the system generate an exception. The action `retry` only makes sense if this hook modified the environment such that the operation can now succeed without error. + ++ `undefined_predicate` + _Context_ is instantiated to a predicate-indicator ( _Module:Name/Arity_). If the predicate fails Prolog will generate an existence_error exception. The hook is intended to implement alternatives to the SWI built-in autoloader, such as autoloading code from a database. Do not use this hook to suppress existence errors on predicates. See also `unknown`. ++ `undefined_global_variable` + _Context_ is instantiated to the name of the missing global variable. The hook must call nb_setval/2 or b_setval/2 before returning with the action retry. + +*/ + +:- multifile user:exception/3. + +:- dynamic user:exception/3. + +:- ensure_loaded('../pl/pathconf.yap'). +/* + Add some tests +*/ + + +:- yap_flag(user:unknown,error). + +/* +:- if(predicate_property(run_tests, static)). + +aa b. + +p(X,Y) :- Y is X*X. + +prefix(information, '% ', S, user_error) --> []. + +:- format('~d~n', [a]). + +:- format('~d~n', []). + +:- p(X,Y). + +a(1). + +a. + +a(2). +a(2). + +lists:member(1,[1]). + +clause_to_indicator(T, M:Name/Arity) :- , + strip_module(T, M, T1), + pred_arity( T1, Name, Arity ). +:- endif. +*/ +/** + +@{ + @defgroup library The Prolog library + + + + @addtogroup YAPControl +@ingroup builtins + @{ +*/ +:- '$system_predicate'( + [!/0, + ':-'/1, + '?-'/1, + []/0, + extensions_to_present_answer/1, + fail/0, + false/0, + goal_expansion/2, + goal_expansion/3, + otherwise/0, + term_expansion/2, + version/2]). + +%:- start_low_level_trace. + +% This is the YAP init file +% should be consulted first step after booting + +% These are pseudo declarations +% so that the user will get a redefining system predicate + +:- '$init_pred_flag_vals'('$flag_info'(a,0), prolog). + +/** @pred fail is iso + +Always fails. +*/ +fail :- fail. + +/** @pred false is iso + + +The same as fail. + + +*/ +false :- fail. + +otherwise. + +!. + +(:- G) :- '$execute'(G), !. + +(?- G) :- '$execute'(G). + +'$$!'(CP) :- '$cut_by'(CP). + +[] :- true. + +% just create a choice-point +% the 6th argument marks the time-stamp. +'$do_log_upd_clause'(_,_,_,_,_,_). +'$do_log_upd_clause'(A,B,C,D,E,_) :- + '$continue_log_update_clause'(A,B,C,D,E). +'$do_log_upd_clause'(_,_,_,_,_,_). + + +'$do_log_upd_clause_erase'(_,_,_,_,_,_). +'$do_log_upd_clause_erase'(A,B,C,D,E,_) :- + '$continue_log_update_clause_erase'(A,B,C,D,E). +'$do_log_upd_clause_erase'(_,_,_,_,_,_). + +'$do_log_upd_clause0'(_,_,_,_,_,_). +'$do_log_upd_clause0'(A,B,C,D,_,_) :- + '$continue_log_update_clause'(A,B,C,D). +'$do_log_upd_clause0'(_,_,_,_,_,_). + + +'$do_static_clause'(_,_,_,_,_). +'$do_static_clause'(A,B,C,D,E) :- + '$continue_static_clause'(A,B,C,D,E). +'$do_static_clause'(_,_,_,_,_). + +:- c_compile('arith.yap', prolog). + +:- '$all_current_modules'(M), yap_flag(M:unknown, error) ; true. + +:- compile_expressions. + + +:- c_compile('bootutils.yap', prolog). +:- c_compile('bootlists.yap', prolog). +:- c_compile('consult.yap', prolog). +:- c_compile('preddecls.yap', prolog). +:- c_compile('preddyns.yap', prolog). +:- c_compile('meta.yap', prolog). +:- c_compile('newmod.yap', prolog). + +:- c_compile('atoms.yap', prolog). +:- c_compile('os.yap', prolog). +:- c_compile('grammar.yap', prolog). +:- c_compile('directives.yap', prolog). +:- c_compile('absf.yap', prolog). + +:- dynamic prolog:'$parent_module'/2. +%:- set_prolog_flag(verbose_file_search, true ). +%:- yap_flag(write_strings,on). +%:- start_low_level_trace. + +:- ensure_loaded([ + 'preds.yap', + 'modules.yap' + ]). +%:-stop_low_level_trace. + +:- use_module('error.yap'). + + +:- ensure_loaded([ + 'errors.yap', + 'utils.yap', + 'control.yap', + 'flags.yap' +]). + + +:- ensure_loaded([ + % lists is often used. + '../os/yio.yap', + 'debug.yap', + 'checker.yap', + 'depth_bound.yap', + 'ground.yap', + 'listing.yap', + 'arithpreds.yap', + % modules must be after preds, otherwise we will have trouble + % with meta-predicate expansion being invoked + % must follow grammar + 'eval.yap', + 'signals.yap', + 'profile.yap', + 'callcount.yap', + 'load_foreign.yap', +% 'save.yap', + 'setof.yap', + 'sort.yap', + 'statistics.yap', + 'strict_iso.yap', + 'tabling.yap', + 'threads.yap', + 'eam.yap', + 'yapor.yap', + 'qly.yap', + 'spy.yap', + 'udi.yap']). + + +:- meta_predicate(log_event(+,:)). + +:- dynamic prolog:'$user_defined_flag'/4. + +:- multifile prolog:debug_action_hook/1. + +:- multifile prolog:'$system_predicate'/2. + +:- ensure_loaded(['protect.yap']). + +version(yap,[6,3]). + +:- op(1150,fx,(mode)). + +:- dynamic 'extensions_to_present_answer'/1. + +:- ensure_loaded(['arrays.yap']). +%:- start_low_level_trace. + +:- multifile user:portray_message/2. + +:- dynamic user:portray_message/2. + +/** @pred _CurrentModule_:goal_expansion(+ _G_,+ _M_,- _NG_), user:goal_expansion(+ _G_,+ _M_,- _NG_) + + +YAP now supports goal_expansion/3. This is an user-defined +procedure that is called after term expansion when compiling or +asserting goals for each sub-goal in a clause. The first argument is +bound to the goal and the second to the module under which the goal + _G_ will execute. If goal_expansion/3 succeeds the new +sub-goal _NG_ will replace _G_ and will be processed in the same + way. If goal_expansion/3 fails the system will use the defaultyap+flrules. + + +*/ +:- multifile user:goal_expansion/3. + +:- dynamic user:goal_expansion/3. + +:- multifile user:goal_expansion/2. + +:- dynamic user:goal_expansion/2. + +:- multifile system:goal_expansion/2. + +:- dynamic system:goal_expansion/2. + +:- multifile goal_expansion/2. + +:- dynamic goal_expansion/2. + +:- use_module('messages.yap'). + +:- ensure_loaded(['undefined.yap']). + +:- use_module('hacks.yap'). + + +:- use_module('attributes.yap'). +:- use_module('corout.yap'). +:- use_module('dialect.yap'). +:- use_module('dbload.yap'). +:- use_module('../library/ypp.yap'). +:- use_module('../os/chartypes.yap'). +:- ensure_loaded('../os/edio.yap'). + +yap_hacks:cut_by(CP) :- '$$cut_by'(CP). + +:- '$change_type_of_char'(36,7). % Make $ a symbol character + +:- set_prolog_flag(generate_debug_info,true). + +% +% cleanup ensure loaded and recover some data-base space. +% +:- ( recorded('$lf_loaded',_,R), erase(R), fail ; true ). +:- ( recorded('$lf_loaded',_,R), erase(R), fail ; true ). +:- ( recorded('$module',_,R), erase(R), fail ; true ). + +:- set_value('$user_module',user), '$protect'. + +:- style_check([+discontiguous,+multiple,+single_var]). + +% +% moved this to init_gc in gc.c to separate the alpha +% +% :- yap_flag(gc,on). + +% :- yap_flag(gc_trace,verbose). + +:- multifile + prolog:comment_hook/3. + +:- source. + +:- module(user). + + +/** @pred _CurrentModule_:term_expansion( _T_,- _X_), user:term_expansion( _T_,- _X_) + + +This user-defined predicate is called by `expand_term/3` to +preprocess all terms read when consulting a file. If it succeeds: + ++ +If _X_ is of the form `:- G` or `?- G`, it is processed as +a directive. ++ +If _X_ is of the form `$source_location`( _File_, _Line_): _Clause_` it is processed as if from `File` and line `Line`. + ++ +If _X_ is a list, all terms of the list are asserted or processed +as directives. ++ The term _X_ is asserted instead of _T_. + + + +*/ +:- multifile term_expansion/2. + +:- dynamic term_expansion/2. + +:- multifile system:term_expansion/2. + +:- dynamic system:term_expansion/2. + +:- multifile swi:swi_predicate_table/4. + +/** @pred user:message_hook(+ _Term_, + _Kind_, + _Lines_) + + +Hook predicate that may be define in the module `user` to intercept +messages from print_message/2. _Term_ and _Kind_ are the +same as passed to print_message/2. _Lines_ is a list of +format statements as described with print_message_lines/3. + +This predicate should be defined dynamic and multifile to allow other +modules defining clauses for it too. + + +*/ +:- multifile user:message_hook/3. + +:- dynamic user:message_hook/3. + +/** @pred exception(+ _Exception_, + _Context_, - _Action_) + + +Dynamic predicate, normally not defined. Called by the Prolog system on run-time exceptions that can be repaired `just-in-time`. The values for _Exception_ are described below. See also catch/3 and throw/1. +If this hook predicate succeeds it must instantiate the _Action_ argument to the atom `fail` to make the operation fail silently, `retry` to tell Prolog to retry the operation or `error` to make the system generate an exception. The action `retry` only makes sense if this hook modified the environment such that the operation can now succeed without error. + ++ `undefined_predicate` + _Context_ is instantiated to a predicate-indicator ( _Module:Name/Arity_). If the predicate fails Prolog will generate an existence_error exception. The hook is intended to implement alternatives to the SWI built-in autoloader, such as autoloading code from a database. Do not use this hook to suppress existence errors on predicates. See also `unknown`. ++ `undefined_global_variable` + _Context_ is instantiated to the name of the missing global variable. The hook must call nb_setval/2 or b_setval/2 before returning with the action retry. + +*/ + +:- multifile user:exception/3. + +:- dynamic user:exception/3. + +:- ensure_loaded('pathconf.yap'). + +:- yap_flag(user:unknown,error). + + +:- halt(0). diff --git a/pl/builtins.yap b/pl/builtins.yap new file mode 100644 index 000000000..c4ce3d257 --- /dev/null +++ b/pl/builtins.yap @@ -0,0 +1,351 @@ +/************************************************************************* +* * +* YAP Prolog * +* * +* Yap Prolog was developed at NCCUP - Universidade do Porto * +* * +* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-2014 * +* * +************************************************************************** +* * +* File: boot.yap * +* Last rev: 8/2/88 * +* mods: * +* commen ts: boot file for Prolog * +* * +*************************************************************************/ + +/** + @file boot.yap + @brief YAP bootstrap + + @defgroup YAPControl Control Predicates + @ingroup builtins + +@{ + +*/ + +/** @pred 0:P,0:Q is iso, meta +Conjunction of goals (and). + +The conjunction is a fundamental construct of Prolog. Example: + +~~~~~~~ + p(X) :- q(X), r(X). +~~~~~~~ + +should be read as `p( _X_) if q( _X_) and r( _X_). + + +*/ +','(X,Y) :- + yap_hacks:env_choice_point(CP), + '$current_module'(M), + '$call'(X,CP,(X,Y),M), + '$call'(Y,CP,(X,Y),M). + +/** @pred 0:P ; 0:Q is iso +Disjunction of goals (or). + +Example: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + p(X) :- q(X); r(X). +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +should be read as "p( _X_) if q( _X_) or r( _X_)". + + +*/ +';'((X->A),Y) :- !, + yap_hacks:env_choice_point(CP), + '$current_module'(M), + ( '$execute'(X) + -> + '$call'(A,CP,(X->A;Y),M) + ; + '$call'(Y,CP,(X->A;Y),M) + ). +';'((X*->A),Y) :- !, + yap_hacks:env_choice_point(CP), + '$current_module'(M), + ( + '$current_choice_point'(DCP), + '$execute'(X), + yap_hacks:cut_at(DCP), + '$call'(A,CP,((X*->A),Y),M) + ; + '$call'(Y,CP,((X*->A),Y),M) + ). +';'(X,Y) :- + yap_hacks:env_choice_point(CP), + '$current_module'(M), + ( '$call'(X,CP,(X;Y),M) ; '$call'(Y,CP,(X;Y),M) ). + + +'|'(X,Y) :- + yap_hacks:env_choice_point(CP), + '$current_module'(M), + ( '$call'(X,CP,(X|Y),M) ; '$call'(Y,CP,(X|Y),M) ). + +/** @pred 0:Condition -> 0:Action is iso + +@short If _Condition__ has a solution, call _Action_; + +@long +Read as "if-then-else" or "commit". This operator is similar to the +conditional operator of imperative languages and can be used alone or +with an else part as follows: + + +~~~~~ + +P -> +Q +~~~~~ + +"if P then Q". + + +~~~~~ + +P -> +Q; +R +~~~~~ + +"if P then Q else R". + +These two predicates could be defined respectively in Prolog as: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + (P -> Q) :- P, !, Q. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +and + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + (P -> Q; R) :- P, !, Q. + (P -> Q; R) :- R. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +if there were no "cuts" in _P_, _Q_ and _R_. + +vNote that the commit operator works by "cutting" any alternative +solutions of _P_. + +Note also that you can use chains of commit operators like: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + P -> Q ; R -> S ; T. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Note that `(->)/2` does not affect the scope of cuts in its +arguments. + + +*/ +'->'(X,Y) :- + yap_hacks:env_choice_point(CP), + '$current_module'(M), + ( '$call'(X,CP,(X->Y),M) -> '$call'(Y,CP,(X->Y),M) ). + + +/** @pred 0:Condition *-> 0:Action is iso + +This construct implements the so-called soft-cut. The control is +defined as follows: + + If _Condition_ succeeds at least once, the +semantics is the same as ( _Condition_, _Action_). + + + If + _Condition_ does not succeed, the semantics is that of (\\+ + _Condition_, _Else_). + + In other words, if _Condition_ +succeeds at least once, simply behave as the conjunction of + _Condition_ and _Action_, otherwise execute _Else_. + +The construct _A *-> B_, i.e. without an _Else_ branch, is +translated as the normal conjunction _A_, _B_. + + +*/ +'*->'(X,Y) :- + yap_hacks:env_choice_point(CP), + '$current_module'(M), + ( '$call'(X,CP,(X*->Y),M), '$call'(Y,CP,(X*->Y),M) ). + + +/** @pred ! is iso + + +Read as "cut". Cuts any choices taken in the current procedure. +When first found "cut" succeeds as a goal, but if backtracking should +later return to it, the parent goal (the one which matches the head of +the clause containing the "cut", causing the clause activation) will +fail. This is an extra-logical predicate and cannot be explained in +terms of the declarative semantics of Prolog. + +example: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + member(X,[X|_]). + member(X,[_|L]) :- member(X,L). +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +With the above definition + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ?- member(X,[1,2,3]). +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +will return each element of the list by backtracking. With the following +definition: + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + member(X,[X|_]) :- !. + member(X,[_|L]) :- member(X,L). +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +the same query would return only the first element of the +list, since backtracking could not "pass through" the cut. + +*/ +! :- + yap_hacks:parent_choice_point(CP), + yap_hacks:cut_at(CP). + +/** @pred \+ 0:P is iso, meta +Negation by failure. + +Goal _P_ is not provable. The execution of this predicate fails if +and only if the goal _P_ finitely succeeds. It is not a true logical +negation, which is impossible in standard Prolog, but +"negation-by-failure". + +This predicate might be defined as: + +~~~~~~~~~~~~ + \+(P) :- P, !, fail. + \+(_). +~~~~~~~~~~~~ +if _P_ did not include "cuts". + +If _P_ includes cuts, the cuts are defined to be scoped by _P_: they cannot cut over the calling prredicate. + + ~~~~~~~~~~~~ + go(P). + +:- \+ P, !, fail. + \+(_). + ~~~~~~~~~~~~ + +*/ +\+(G) :- \+ '$execute'(G). + +not(G) :- \+ '$execute'(G). + + + +/** @pred fail is iso + +Always fails. +*/ +fail :- fail. + +/** @pred false is iso + +The same as fail. +*/ +false :- fail. + +/** @pred true is iso +Succeed. + +Succeeds once. +*/ +true :- true. + +/** @pred otherwise is iso +Succeed. + +Succeeds once. +*/ +otherwise. + +/** @pred repeat is iso +Succeeds repeatedly. + +In the next example, `repeat` is used as an efficient way to implement +a loop. The next example reads all terms in a file: +~~~~~~~~~~~~~{.prolog} + a :- repeat, read(X), write(X), nl, X=end_of_file, !. +~~~~~~~~~~~~~ +the loop is effectively terminated by the cut-goal, when the test-goal +`X=end` succeeds. While the test fails, the goals `read(X)`, +`write(X)`, and `nl` are executed repeatedly, because +backtracking is caught by the `repeat` goal. + +The built-in `repeat/0` could be defined in Prolog by: + +~~~~~{.prolog} + +repeat. +repeat :- repeat. +~~~~~ + +The predicate between/3 can be used to iterate for a pre-defined +number of steps. + +*/ + repeat :- '$repeat'. + + '$repeat'. + '$repeat'. + '$repeat'. + '$repeat'. + '$repeat'. + '$repeat'. + '$repeat'. + '$repeat'. + '$repeat'. + '$repeat' :- '$repeat'. + +/** @pred + _P_ is nondet + +The same as `call( _P_)`. This feature has been kept to provide +compatibility with C-Prolog. When compiling a goal, YAP +generates a `call( _X_)` whenever a variable _X_ is found as +a goal. + +~~~~~{.prolog} + a(X) :- X. +~~~~~ +is converted to: + +~~~~~{.prolog} + a(X) :- call(X). +~~~~~ + + +*/ + +/** @pred call( 0:P ) is iso +Meta-call predicate. + +If _P_ is instantiated to an atom or a compound term, the goal `call( +_P_)` is executed as if the clause was originally written as _P_ +instead as call( _P_ ), except that any "cut" occurring in _P_ only +cuts alternatives in the execution of _P_. + + +*/ +call(G) :- '$execute'(G). + +/** @pred incore( 0:P ) + +The same as call/1. +*/ +incore(G) :- '$execute'(G). + + +(:- G) :- '$execute'(G), !. + +(?- G) :- '$execute'(G). + +'$$!'(CP) :- '$cut_by'(CP). + +[] :- true. diff --git a/pl/consult.yap b/pl/consult.yap index 5ef025794..af114056a 100644 --- a/pl/consult.yap +++ b/pl/consult.yap @@ -216,7 +216,7 @@ load_files(Files,Opts) :- '$lf_option'(if, 5, true). '$lf_option'(imports, 6, all). '$lf_option'(qcompile, 7, Current) :- - nb:nb:'$nb_getval'('$qcompile', Current, Current = never). + '__NB_getval__'('$qcompile', Current, Current = never). '$lf_option'(silent, 8, _). '$lf_option'(skip_unix_header, 9, true). '$lf_option'(compilation_mode, 10, Flag) :- @@ -258,7 +258,7 @@ load_files(Files,Opts) :- setarg( Id, TOpts, Val ). '$load_files'(Files, Opts, Call) :- - ( nb:'$nb_getval'('$lf_status', OldTOpts, fail), nonvar(OldTOpts) -> + ( '__NB_getval__'('$lf_status', OldTOpts, fail), nonvar(OldTOpts) -> '$lf_opt'(autoload, OldTOpts, OldAutoload) ; '$lf_option'(last_opt, LastOpt), @@ -661,7 +661,7 @@ db_files(Fs) :- '$do_lf'(_ContextModule, Stream, _UserFile, _File, _TOpts) :- stream_property(Stream, file_name(Y)), - nb:'$nb_getval'('$loop_streams',Sts0, Sts0 = []), + '__NB_getval__'('$loop_streams',Sts0, Sts0 = []), lists:member(Stream0, Sts0), stream_property(Stream0, file_name(Y)), !. @@ -670,12 +670,12 @@ db_files(Fs) :- stream_property(OldStream, alias(loop_stream) ), '$lf_opt'(encoding, TOpts, Encoding), set_stream( Stream, [alias(loop_stream), encoding(Encoding)] ), - nb:'$nb_getval'('$loop_streams',Sts0, Sts0=[]), + '__NB_getval__'('$loop_streams',Sts0, Sts0=[]), nb_setval('$loop_streams',[Stream|Sts0]), '$lf_opt'('$context_module', TOpts, ContextModule), '$lf_opt'(reexport, TOpts, Reexport), '$lf_opt'(qcompile, TOpts, QCompiling), - nb:'$nb_getval'('$qcompile', ContextQCompiling, ContextQCompiling = never), + '__NB_getval__'('$qcompile', ContextQCompiling, ContextQCompiling = never), nb_setval('$qcompile', QCompiling), % format( 'I=~w~n', [Verbosity=UserFile] ), % export to process @@ -757,13 +757,13 @@ db_files(Fs) :- '$q_do_save_file'(_File, _, _TOpts ). '$reset_if'(OldIfLevel) :- - nb:'$nb_getval'('$if_level', OldIfLevel, fail), !, + '__NB_getval__'('$if_level', OldIfLevel, fail), !, nb_setval('$if_level',0). '$reset_if'(0) :- nb_setval('$if_le1vel',0). '$get_if'(Level0) :- - nb:'$nb_getval'('$if_level', Level, fail), !, + '__NB_getval__'('$if_level', Level, fail), !, Level0 = Level. '$get_if'(0). @@ -807,7 +807,7 @@ nb_setval('$if_le1vel',0). fail. '$exec_initialization_goals' :- '$current_module'(M), - nb:'$nb_getval'('$lf_status', TOpts, fail), + '__NB_getval__'('$lf_status', TOpts, fail), '$lf_opt'( initialization, TOpts, Ref), nb:nb_queue_close(Ref, Answers, []), lists:member(G, Answers), @@ -855,7 +855,7 @@ nb_setval('$if_le1vel',0). '$lf_opt'(encoding, TOpts, Encoding), set_stream(Stream, [encoding(Encoding),alias(loop_stream)] ), '$loaded'(Y, X, Mod, _OldY, _L, include, _, Dir, TOpts,[]), - ( nb:'$nb_getval'('$included_file', OY, fail ) -> true ; OY = [] ), + ( '__NB_getval__'('$included_file', OY, fail ) -> true ; OY = [] ), nb_setval('$included_file', Y), print_message(informational, loading(including, Y)), '$loop'(Stream,Status), @@ -965,7 +965,7 @@ prolog_load_context(file, FileName) :- FileName = user_input ). prolog_load_context(module, X) :- - nb:'$nb_getval'('$consulting_file', _, fail), + '__NB_getval__'('$consulting_file', _, fail), '$current_module'(X). prolog_load_context(source, F0) :- ( source_location(F0, _) /*, @@ -1480,20 +1480,20 @@ If an error occurs, the error is printed and processing proceeds as if '$get_if'(Level0), Level is Level0 + 1, nb_setval('$if_level',Level), - ( nb:'$nb_getval'('$endif', OldEndif, fail) -> true ; OldEndif=top), - ( nb:'$nb_getval'('$if_skip_mode', Mode, fail) -> true ; Mode = run ), + ( '__NB_getval__'('$endif', OldEndif, fail) -> true ; OldEndif=top), + ( '__NB_getval__'('$if_skip_mode', Mode, fail) -> true ; Mode = run ), nb_setval('$endif',elif(Level,OldEndif,Mode)), fail. % we are in skip mode, ignore.... '$if'(_Goal,_) :- - nb:'$nb_getval'('$endif',elif(Level, OldEndif, skip), fail), !, + '__NB_getval__'('$endif',elif(Level, OldEndif, skip), fail), !, nb_setval('$endif',endif(Level, OldEndif, skip)). % we are in non skip mode, check.... '$if'(Goal,_) :- ('$if_call'(Goal) -> % we will execute this branch, and later enter skip - nb:'$nb_getval'('$endif', elif(Level,OldEndif,Mode), fail), + '__NB_getval__'('$endif', elif(Level,OldEndif,Mode), fail), nb_setval('$endif',endif(Level,OldEndif,Mode)) ; @@ -1539,7 +1539,7 @@ no test succeeds the else branch is processed. % we can try the elif '$elif'(Goal,_) :- '$get_if'(Level), - nb:'$nb_getval'('$endif',elif(Level,OldEndif,Mode),fail), + '__NB_getval__'('$endif',elif(Level,OldEndif,Mode),fail), ('$if_call'(Goal) -> % we will not skip, and we will not run any more branches. @@ -1599,7 +1599,7 @@ End of conditional compilation. set_prolog_flag(source, false). '$fetch_comp_status'(assert_all) :- - nb:'$nb_getval'('$assert_all',on, fail), !. + '__NB_getval__'('$assert_all',on, fail), !. '$fetch_comp_status'(source) :- current_prolog_flag(source, true), !. '$fetch_comp_status'(compact). diff --git a/pl/control.yap b/pl/control.yap index b5546cf9a..b6321ae4f 100644 --- a/pl/control.yap +++ b/pl/control.yap @@ -485,7 +485,7 @@ variable is used non-backtrackable. */ nb_getval(GlobalVariable, Val) :- - '$nb_getval'(GlobalVariable, Val, Error), + '__NB_getval__'(GlobalVariable, Val, Error), (var(Error) -> true @@ -524,7 +524,7 @@ the requested variable does not exist. */ b_getval(GlobalVariable, Val) :- - '$nb_getval'(GlobalVariable, Val, Error), + '__NB_getval__'(GlobalVariable, Val, Error), (var(Error) -> true diff --git a/pl/errors.yap b/pl/errors.yap index 9b0156be4..edd29fb68 100644 --- a/pl/errors.yap +++ b/pl/errors.yap @@ -4,146 +4,1945 @@ * * * Yap Prolog was developed at NCCUP - Universidade do Porto * * * -* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 * +* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-2014 * * * ************************************************************************** -* * -* File: errors.yap * - * comments: error messages for YAP * -* * -* * +* * +* File: boot.yap * +* Last rev: 8/2/88 * +* mods: * +* commen ts: boot file for Prolog * * * *************************************************************************/ +/** + @file boot.yap + @brief YAP bootstrap -/** @defgroup YAPErrorHandler Error Handling - -@ingroup YAPErrors - -The error handler is called when there is an execution error or a -warning needs to be displayed. The handlers include a number of hooks -to allow user-control. - -Errors are terms of the form: - - - error( domain_error( Domain, Culprit )` - - error( evaluation_error( Expression, Culprit )` - - error( existence_error( Object, Culprit )` - - error( instantiation_error )` - - error( permission_error( Error, Permission, Culprit)` - - error( representation_error( Domain, Culprit )` - - error( resource_error( Resource, Culprit )` - - error( syntax_error( Error )` - - error( system_error( Domain, Culprit )` - - error( type_error( Type, Culprit )` - - error( uninstantiation_error( Culprit )` + @defgroup YAPControl Control Predicates + @ingroup builtins @{ + */ -:- system_module( '$_errors', [system_error/2], ['$Error'/1, - '$do_error'/2, - system_error/3, - system_error/2]). -:- use_system_module( '$messages', [file_location/2, - generate_message/3, - translate_message/4]). +system_module(_Mod, _SysExps, _Decls). +% new_system_module(Mod). + +use_system_module(_Module, _SysExps). + +private(_). + +% +% boootstrap predicates. +% +:- system_module( '$_boot', [ + bootstrap/1, + call/1, + catch/3, + catch_ball/2, + expand_term/2, + import_system_module/2, + incore/1, + (not)/1, + repeat/0, + throw/1, + true/0], ['$$compile'/4, + '$call'/4, + '$catch'/3, + '$check_callable'/2, + '$check_head_and_body'/4, + '$check_if_reconsulted'/2, + '$clear_reconsulting'/0, + '$command'/4, + '$cut_by'/1, + '$disable_debugging'/0, + '$do_live'/0, + '$'/0, + '$find_goal_definition'/4, + '$head_and_body'/3, + '$inform_as_reconsulted'/2, + '$init_system'/0, + '$init_win_graphics'/0, + '$live'/0, + '$loop'/2, + '$meta_call'/2, + '$prompt_alternatives_on'/1, + '$run_at_thread_start'/0, + '$system_catch'/4, + '$undefp'/1, + '$version'/0]). + +:- use_system_module( '$_absf', ['$system_library_directories'/2]). + +:- use_system_module( '$_checker', ['$check_term'/5, + '$sv_warning'/2]). + +:- use_system_module( '$_consult', ['$csult'/2]). + +:- use_system_module( '$_control', ['$run_atom_goal'/1]). + +:- use_system_module( '$_directives', ['$all_directives'/1, + '$exec_directives'/5]). + +:- use_system_module( '$_errors', ['$do_error'/2]). + +:- use_system_module( '$_grammar', ['$translate_rule'/2]). + +:- use_system_module( '$_modules', ['$get_undefined_pred'/4, + '$meta_expansion'/6, + '$module_expansion'/6]). + +:- use_system_module( '$_preddecls', ['$dynamic'/2]). + +:- use_system_module( '$_preds', ['$assert_static'/5, + '$assertz_dynamic'/4, + '$init_preds'/0, + '$unknown_error'/1, + '$unknown_warning'/1]). + +:- use_system_module( '$_qly', ['$init_state'/0]). + +:- use_system_module( '$_strict_iso', ['$check_iso_strict_clause'/1, + '$iso_check_goal'/2]). + +% be careful here not to generate an undefined exception. -/** - * @pred system_error( +Error, +Cause) - * - * Generate a system error _Error_, informing the possible cause _Cause_. - * - */ -system_error(Type,Goal) :- - '$do_error'(Type,Goal). - -'$do_error'(Type,Goal) :- -% format('~w~n', [Type]), - ancestor_location(Call, Caller), - throw(error(Type, [ - [g|g(Goal)], - [p|Call], - [e|Caller]])). - -/** - * @pred system_error( +Error, +Cause, +Culprit) - * - * Generate a system error _Error_, informing the source goal _Cause_ and a possible _Culprit_. - * - * - * ~~~~~~~~~~ - * ~~~~~~~~~~ - * - * - */ -system_error(Type,Goal,Culprit) :- - % format('~w~n', [Type]), - ancestor_location(Call, Caller), - throw(error(Type, [ - [i|Culprit], - [g|g(Goal)], - [p|Call], - [e|Caller]])). - -'$do_pi_error'(type_error(callable,Name/0),Message) :- !, - '$do_error'(type_error(callable,Name),Message). -'$do_pi_error'(Error,Message) :- !, - '$do_error'(Error,Message). - -'$Error'(E) :- - '$LoopError'(E,top). - -'$LoopError'(_, _) :- - flush_output(user_output), - flush_output(user_error), - fail. -'$LoopError'(Error, Level) :- !, - '$process_error'(Error, Level), - fail. -'$LoopError'(_, _) :- - flush_output, - '$close_error', +'$undefp0'([_M|'$imported_predicate'(G, _ImportingMod, G, prolog)], _Action) :- + nonvar(G), '$is_system_predicate'(G, prolog), !. +'$undefp0'([_M|print_message(A,B)], _Action) :- + !. +'$undefp0'([_M|sort(A,B)], _Action) :- + !, + '$sort'(A,B). +'$undefp0'([M|G], _Action) :- + stream_property( loop_stream, file_name(F)), + stream_property( loop_stream, line_number(L)), + %'$bootstrap_predicate'(G, M, Action). + writeln(F:L:M:G), fail. -'$process_error'('$forward'(Msg), _) :- - !, - throw( '$forward'(Msg) ). -'$process_error'(abort, Level) :- - !, - ( - Level \== top - -> - throw( abort ) +:- '$undefp_handler'('$undefp0'(_,_),prolog). + + +live :- + repeat, + '$current_module'(Module), + ( Module==user -> + true % '$compile_mode'(_,0) ; - current_prolog_flag(break_level, 0) - -> - print_message(informational,abort(user)), - fail - ; - current_prolog_flag(break_level, I0), - I is I0-1, - current_prolog_flag(break_level, I), - throw(abort) - ). -'$process_error'(error(thread_cancel(_Id), _G),top) :- + format(user_error,'[~w]~n', [Module]) + ), + '$system_catch'('$enter_top_level',Module,Error,'$Error'(Error)). + +initialize_prolog :- + '$init_system'. + + + + +'$init_globals' :- + % set_prolog_flag(break_level, 0), + % '$set_read_error_handler'(error), let the user do that + nb_setval('$chr_toplevel_show_store',false). + +'$init_consult' :- + set_value('$open_expands_filename',true), + nb_setval('$assert_all',off), + nb_setval('$if_level',0), + nb_setval('$endif',off), + nb_setval('$initialization_goals',off), + nb_setval('$included_file',[]), + nb_setval('$loop_streams',[]), + \+ '$undefined'('$init_preds',prolog), + '$init_preds', + fail. +'$init_consult'. + +'$init_win_graphics' :- + '$undefined'(window_title(_,_), system), !. +'$init_win_graphics' :- + load_files([library(win_menu)], [silent(true),if(not_loaded)]), + fail. +'$init_win_graphics'. + +'$init_or_threads' :- + '$c_yapor_workers'(W), !, + '$start_orp_threads'(W). +'$init_or_threads'. + +'$start_orp_threads'(1) :- !. +'$start_orp_threads'(W) :- + thread_create('$c_worker',_,[detached(true)]), + W1 is W-1, + '$start_orp_threads'(W1). + +'$version' :- + current_prolog_flag(halt_after_consult, false), + current_prolog_flag(verbose, normal), !, + current_prolog_flag(version_git,VersionGit), + current_prolog_flag(compiled_at,AT), + current_prolog_flag(version_data, yap(Mj, Mi, Patch, _) ), + sub_atom( VersionGit, 0, 8, _, VERSIONGIT ), + current_prolog_flag(version_data, yap(Mj, Mi, Patch, _) ), + current_prolog_flag(resource_database, Saved ), + format(user_error, '% YAP ~d.~d.~d-~a (compiled ~a)~n', [Mj,Mi, Patch, VERSIONGIT, AT]), + format(user_error, '% database loaded from ~a~n', [Saved]), + fail. +'$version'. + +'$init_system' :- + get_value('$yap_inited', true), !. +'$init_system' :- + set_value('$yap_inited', true), % start_low_level_trace, + % do catch as early as possible + '$version', + current_prolog_flag(file_name_variables, OldF), + set_prolog_flag(file_name_variables, true), + '$init_consult', + set_prolog_flag(file_name_variables, OldF), + '$init_globals', + set_prolog_flag(fileerrors, true), + set_value('$gc',on), + ('$exit_undefp' -> true ; true), + prompt1(' ?- '), + set_prolog_flag(debug, false), + % simple trick to find out if this is we are booting from Prolog. + % boot from a saved state + ( + current_prolog_flag(saved_program, true) + % use saved state + -> + '$init_state' + ; + qsave_program( 'startup.yss') + ), + '$db_clean_queues'(0), + % this must be executed from C-code. + % '$startup_saved_state', + set_input(user_input), + set_output(user_output), + '$init_or_threads', + '$run_at_thread_start'. + + +% Start file for yap + +/* I/O predicates */ + +/* meaning of flags for '$write' is + 1 quote illegal atoms + 2 ignore operator declarations + 4 output '$VAR'(N) terms as A, B, C, ... + 8 use portray(_) +*/ + +/* main execution loop */ +'$read_toplevel'(Goal, Bindings) :- + '$prompt', + catch(read_term(user_input, + Goal, + [variable_names(Bindings), syntax_errors(dec10)]), + E, '$handle_toplevel_error'( E) ). + +'$handle_toplevel_error'( syntax_error(_)) :- + !, + fail. +'$handle_toplevel_error'( error(io_error(read,user_input),_)) :- !. -'$process_error'(error(thread_cancel(Id), G), _) :- - !, - throw(error(thread_cancel(Id), G)). -'$process_error'(error(permission_error(module,redefined,A),B), Level) :- - Level \= top, !, - throw(error(permission_error(module,redefined,A),B)). -'$process_error'(Error, _Level) :- - functor(Error, Severity, _), - print_message(Severity, Error), !. -%'$process_error'(error(Msg, Where), _) :- -% Print_message(error,error(Msg, [g|Where])), !. -'$process_error'(Throw, _) :- - print_message(error,error(unhandled_exception,Throw)). +'$handle_toplevel_error'(_, E) :- + throw(E). -%% @} + +/** @pred stream_property( _Stream_, _Prop_) + +*/ + +% reset alarms when entering top-level. +'$enter_top_level' :- + '$alarm'(0, 0, _, _), + fail. +'$enter_top_level' :- + '$clean_up_dead_clauses', + fail. +'$enter_top_level' :- + get_value('$top_level_goal',GA), GA \= [], !, + set_value('$top_level_goal',[]), + '$run_atom_goal'(GA), + current_prolog_flag(break_level, BreakLevel), + ( + BreakLevel \= 0 + -> + true + ; + '$pred_exists'(halt(_), user) + -> + halt(0) + ; + '$halt'(0) + ). +'$enter_top_level' :- + flush_output, + '$run_toplevel_hooks', + prompt1(' ?- '), + '$read_toplevel'(Command,Varnames), + nb_setval('$spy_gn',1), + % stop at spy-points if debugging is on. + nb_setval('$debug_state', state(creep,0,stop)), + '$command'(Command,Varnames,_Pos,top), + current_prolog_flag(break_level, BreakLevel), + ( + BreakLevel \= 0 + -> + true + ; + '$pred_exists'(halt(_), user) + -> halt(0) + ; + '$halt'(0) + ). + + +'$erase_sets' :- + eraseall('$'), + eraseall('$$set'), + eraseall('$$one'), + eraseall('$reconsulted'), fail. +'$erase_sets' :- \+ recorded('$path',_,_), recorda('$path',"",_). +'$erase_sets'. + +'$start_corouts' :- + eraseall('$corout'), + eraseall('$result'), + eraseall('$actual'), + fail. +'$start_corouts' :- recorda('$actual',main,_), + recordz('$corout','$corout'(main,main,'$corout'([],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[])),_Ref), + recorda('$result',going,_). + +'$command'(C,VL,Pos,Con) :- + current_prolog_flag(strict_iso, true), !, /* strict_iso on */ + '$execute_command'(C,VL,Pos,Con,_Source). +'$command'(C,VL,Pos,Con) :- + ( (Con = top ; var(C) ; C = [_|_]) -> + '$execute_command'(C,VL,Pos,Con,C), ! ; + % do term expansion + expand_term(C, EC), + % execute a list of commands + '$execute_commands'(EC,VL,Pos,Con,_Source), + % succeed only if the *original* was at end of file. + C == end_of_file + ). + + % + % Hack in case expand_term has created a list of commands. + % + '$execute_commands'(V,_,_,_,Source) :- var(V), !, + '$do_error'(instantiation_error,meta_call(Source)). + '$execute_commands'([],_,_,_,_) :- !. + '$execute_commands'([C|Cs],VL,Pos,Con,Source) :- !, + ( + '$system_catch'('$execute_command'(C,VL,Pos,Con,Source),prolog,Error,'$LoopError'(Error, Con)), + fail + ; + '$execute_commands'(Cs,VL,Pos,Con,Source) + ). + '$execute_commands'(C,VL,Pos,Con,Source) :- + '$execute_command'(C,VL,Pos,Con,Source). + + % + % + % + +'$execute_command'(C,_,_,top,Source) :- + var(C), + !, + '$do_error'(instantiation_error,meta_call(Source)). +'$execute_command'(C,_,_,top,Source) :- + number(C), + !, + '$do_error'(type_error(callable,C),meta_call(Source)). + '$execute_command'(R,_,_,top,Source) :- + db_reference(R), + !, + '$do_error'(type_error(callable,R),meta_call(Source)). + '$execute_command'(end_of_file,_,_,_,_) :- !. + '$execute_command'(Command,_,_,_,_) :- + '__NB_getval__'('$if_skip_mode', skip, fail), + \+ '$if_directive'(Command), + !. + '$execute_command'((:-G),VL,Pos,Option,_) :- +% !, + Option \= top, !, + % allow user expansion + expand_term((:- G), O), + ( + O = (:- G1) + -> + '$yap_strip_module'(G1, M, G2), + + '$process_directive'(G2, Option, M, VL, Pos) + ; + '$execute_commands'(G1,VL,Pos,Option,O) + ). + '$execute_command'((?-G), VL, Pos, Option, Source) :- + Option \= top, + !, + '$execute_command'(G, VL, Pos, top, Source). + '$execute_command'(G, VL, Pos, Option, Source) :- + '$continue_with_command'(Option, VL, Pos, G, Source). + + +'$continue_with_command'(Where,V,'$stream_position'(C,_P,A1,A2,A3),'$source_location'(_F,L):G,Source) :- + !, + '$continue_with_command'(Where,V,'$stream_position'(C,L,A1,A2,A3),G,Source). +'$continue_with_command'(reconsult,V,Pos,G,Source) :- +% writeln(G), + '$go_compile_clause'(G,V,Pos,reconsult,Source), + fail. +'$continue_with_command'(consult,V,Pos,G,Source) :- + '$go_compile_clause'(G,V,Pos,consult,Source), + fail. +'$continue_with_command'(top,V,_,G,_) :- + '$query'(G,V). + + %% + % @pred '$go_compile_clause'(G,Vs,Pos, Where, Source) is det + % + % interfaces the loader and the compiler + % not 100% compatible with SICStus Prolog, as SICStus Prolog would put + % module prefixes all over the place, although unnecessarily so. + % + % @param [in] _G_ is the clause to compile + % @param [in] _Vs_ a list of variables and their name + % @param [in] _Pos_ the source-code position + % @param [in] _N_ a flag telling whether to add first or last + % @param [out] _Source_ the user-tranasformed clause +'$go_compile_clause'(G, _Vs, _Pos, Where, Source) :- + '$precompile_term'(G, Source, G1), + !, + '$$compile'(G1, Where, Source, _). + '$go_compile_clause'(G,_Vs,_Pos, _Where, _Source) :- + throw(error(system, compilation_failed(G))). + +'$$compile'(C, Where, C0, R) :- + '$head_and_body'( C, MH, B ), + strip_module( MH, Mod, H), + ( + '$undefined'(H, Mod) + -> + '$init_pred'(H, Mod, Where) + ; + true + ), +% writeln(Mod:((H:-B))), + '$compile'((H:-B), Where, C0, Mod, R). + +'$init_pred'(H, Mod, _Where ) :- + recorded('$import','$import'(NM,Mod,NH,H,_,_),RI), +% NM \= Mod, + functor(NH,N,Ar), + print_message(warning,redefine_imported(Mod,NM,Mod:N/Ar)), + erase(RI), + fail. +'$init_pred'(H, Mod, Where ) :- + '$init_as_dynamic'(Where), + !, + functor(H, Na, Ar), + '$dynamic'(Na/Ar, Mod). +'$init_pred'(_H, _Mod, _Where ). + +'$init_as_dynamic'( asserta ). +'$init_as_dynamic'( assertz ). +'$init_as_dynamic'( consult ) :- + '__NB_getval__'('$assert_all',on,fail). +'$init_as_dynamic'( reconsult ) :- + '__NB_getval__'('$assert_all',on,fail). + +'$check_if_reconsulted'(N,A) :- + once(recorded('$reconsulted',N/A,_)), + recorded('$reconsulted',X,_), + ( X = N/A , !; + X = '$', !, fail; + fail + ). + +'$inform_as_reconsulted'(N,A) :- + recorda('$reconsulted',N/A,_). + +'$clear_reconsulting' :- + recorded('$reconsulted',X,Ref), + erase(Ref), + X == '$', + !, + ( recorded('$reconsulting',_,R) -> erase(R) ). + +'$prompt_alternatives_on'(determinism). + +/* Executing a query */ + +'$query'(end_of_file,_). +'$query'(G,[]) :- + '$prompt_alternatives_on'(OPT), + ( OPT = groundness ; OPT = determinism), + !, + '$yes_no'(G,(?-)). +'$query'(G,V) :- + ( + '$current_module'(M), + '$current_choice_point'(CP), + '$user_call'(G, M), + '$current_choice_point'(NCP), + '$delayed_goals'(G, V, Vs, LGs, DCP), + '$write_answer'(Vs, LGs, Written), + '$write_query_answer_true'(Written), + ( + '$prompt_alternatives_on'(determinism), CP == NCP, DCP = 0 + -> + format(user_error, '.~n', []), + ! + ; + '$another', + ! + ), + fail + ; + '$out_neg_answer' + ). + + '$yes_no'(G,C) :- + '$current_module'(M), + '$do_yes_no'(G,M), + '$delayed_goals'(G, [], NV, LGs, _), + '$write_answer'(NV, LGs, Written), + ( Written = [] -> + !,'$present_answer'(C, true) + ; + '$another', ! + ), + fail. + '$yes_no'(_,_) :- + '$out_neg_answer'. + +'$add_env_and_fail' :- fail. + + +'$process_answer'(Vs, LGs, Bindings) :- +'$purge_dontcares'(Vs,IVs), +'$sort'(IVs, NVs), +'$prep_answer_var_by_var'(NVs, LAnsw, LGs), +'$name_vars_in_goals'(LAnsw, Vs, Bindings). + +% +% *-> at this point would require compiler support, which does not exist. +% +'$delayed_goals'(G, V, NV, LGs, NCP) :- + ( + CP is '$last_choice_pt', + '$current_choice_point'(NCP1), + attributes:delayed_goals(G, V, NV, LGs), + '$current_choice_point'(NCP2), + '$clean_ifcp'(CP), + NCP is NCP2-NCP1 + ; + copy_term_nat(V, NV), + LGs = [], +% term_factorized(V, NV, LGs), + NCP = 0 + ). + +'$out_neg_answer' :- + print_message( help, false), + fail. + + +'$do_yes_no'([X|L], M) :- + !, + '$csult'([X|L], M). +'$do_yes_no'(G, M) :- + '$user_call'(G, M). + +'$write_query_answer_true'([]) :- !, + format(user_error,true,[]). +'$write_query_answer_true'(_). + + +% +% present_answer has three components. First it flushes the streams, +% then it presents the goals, and last it shows any goals frozen on +% the arguments. +% +'$present_answer'(_,_):- + flush_output, + fail. +'$present_answer'((?-), Answ) :- + current_prolog_flag(break_level, BL ), + ( BL \= 0 -> format(user_error, '[~p] ',[BL]) ; + true ), + ( current_prolog_flag(toplevel_print_options, Opts) -> + write_term(user_error,Answ,Opts) ; + format(user_error,'~w',[Answ]) + ), + format(user_error,'.~n', []). + +'$another' :- + format(user_error,' ? ',[]), + '$clear_input'(user_input), + get_code(user_input,C), + '$do_another'(C). + +'$do_another'(C) :- + ( C=:= ";" -> + skip(user_input,10), % + % '$add_nl_outside_console', + fail + ; + C== 10 + -> + '$add_nl_outside_console', + ( + '$undefined'(print_message(_,_),prolog) + -> + format(user_error,'yes~n', []) + ; + print_message(help,yes) + ) + ; + C== 13 + -> + get0(user_input,NC), + '$do_another'(NC) + ; + C== -1 + -> + halt + ; + skip(user_input,10), '$ask_again_for_another' + ). + +%'$add_nl_outside_console' :- +% '$is_same_tty'(user_input, user_error), !. +'$add_nl_outside_console' :- + format(user_error,'~n',[]). + +'$ask_again_for_another' :- + format(user_error,'Action (\";\" for more choices, for exit)', []), + '$another'. + +'$write_answer'(_,_,_) :- + flush_output, + fail. +'$write_answer'(Vs, LBlk, FLAnsw) :- + '$process_answer'(Vs, LBlk, NLAnsw), + '$write_vars_and_goals'(NLAnsw, first, FLAnsw). + +write_query_answer( Bindings ) :- + '$write_vars_and_goals'(Bindings, first, _FLAnsw). + +'$purge_dontcares'([],[]). +'$purge_dontcares'([Name=_|Vs],NVs) :- + atom_codes(Name, [C|_]), C is "_", !, + '$purge_dontcares'(Vs,NVs). +'$purge_dontcares'([V|Vs],[V|NVs]) :- + '$purge_dontcares'(Vs,NVs). + + +'$prep_answer_var_by_var'([], L, L). +'$prep_answer_var_by_var'([Name=Value|L], LF, L0) :- + '$delete_identical_answers'(L, Value, NL, Names), + '$prep_answer_var'([Name|Names], Value, LF, LI), + '$prep_answer_var_by_var'(NL, LI, L0). + +% fetch all cases that have the same solution. +'$delete_identical_answers'([], _, [], []). +'$delete_identical_answers'([(Name=Value)|L], Value0, FL, [Name|Names]) :- + Value == Value0, !, + '$delete_identical_answers'(L, Value0, FL, Names). +'$delete_identical_answers'([VV|L], Value0, [VV|FL], Names) :- + '$delete_identical_answers'(L, Value0, FL, Names). + +% now create a list of pairs that will look like goals. +'$prep_answer_var'(Names, Value, LF, L0) :- var(Value), !, + '$prep_answer_unbound_var'(Names, LF, L0). +'$prep_answer_var'(Names, Value, [nonvar(Names,Value)|L0], L0). + +% ignore unbound variables +'$prep_answer_unbound_var'([_], L, L) :- !. +'$prep_answer_unbound_var'(Names, [var(Names)|L0], L0). + +'$gen_name_string'(I,L,[C|L]) :- I < 26, !, C is I+65. +'$gen_name_string'(I,L0,LF) :- + I1 is I mod 26, + I2 is I // 26, + C is I1+65, + '$gen_name_string'(I2,[C|L0],LF). + +'$write_vars_and_goals'([], _, []). +'$write_vars_and_goals'([nl,G1|LG], First, NG) :- !, + nl(user_error), + '$write_goal_output'(G1, First, NG, Next, IG), + '$write_vars_and_goals'(LG, Next, IG). +'$write_vars_and_goals'([G1|LG], First, NG) :- + '$write_goal_output'(G1, First, NG, Next, IG), + '$write_vars_and_goals'(LG, Next, IG). + +'$goal_to_string'(Format, G, String) :- + format(codes(String),Format,G). + +'$write_goal_output'(var([V|VL]), First, [var([V|VL])|L], next, L) :- !, + ( First = first -> true ; format(user_error,',~n',[]) ), + format(user_error,'~a',[V]), + '$write_output_vars'(VL). +'$write_goal_output'(nonvar([V|VL],B), First, [nonvar([V|VL],B)|L], next, L) :- !, + ( First = first -> true ; format(user_error,',~n',[]) ), + format(user_error,'~a',[V]), + '$write_output_vars'(VL), + format(user_error,' = ', []), + ( yap_flag(toplevel_print_options, Opts) -> + write_term(user_error,B,[priority(699)|Opts]) ; + write_term(user_error,B,[priority(699)]) + ). +'$write_goal_output'(nl, First, NG, First, NG) :- !, + format(user_error,'~n',[]). +'$write_goal_output'(Format-G, First, NG, Next, IG) :- !, + G = [_|_], !, + % dump on string first so that we can check whether we actually + % had any output from the solver. + '$goal_to_string'(Format, G, String), + ( String == [] -> + % we didn't + IG = NG, First = Next + ; + % we did + ( First = first -> true ; format(user_error,',~n',[]) ), + format(user_error, '~s', [String]), + NG = [G|IG] + ). +'$write_goal_output'(_-G, First, [G|NG], next, NG) :- !, + ( First = first -> true ; format(user_error,',~n',[]) ), + ( yap_flag(toplevel_print_options, Opts) -> + write_term(user_error,G,Opts) ; + format(user_error,'~w',[G]) + ). +'$write_goal_output'(_M:G, First, [G|NG], next, NG) :- !, + ( First = first -> true ; format(user_error,',~n',[]) ), + ( yap_flag(toplevel_print_options, Opts) -> + write_term(user_error,G,Opts) ; + format(user_error,'~w',[G]) + ). +'$write_goal_output'(G, First, [M:G|NG], next, NG) :- + '$current_module'(M), + ( First = first -> true ; format(user_error,',~n',[]) ), + ( yap_flag(toplevel_print_options, Opts) -> + write_term(user_error,G,Opts) ; + format(user_error,'~w',[G]) + ). + +'$name_vars_in_goals'(G, VL0, G) :- + '$name_well_known_vars'(VL0), + '$variables_in_term'(G, [], GVL), + '$name_vars_in_goals1'(GVL, 0, _). + +'$name_well_known_vars'([]). +'$name_well_known_vars'([Name=V|NVL0]) :- + var(V), !, + V = '$VAR'(Name), + '$name_well_known_vars'(NVL0). +'$name_well_known_vars'([_|NVL0]) :- + '$name_well_known_vars'(NVL0). + +'$name_vars_in_goals1'([], I, I). +'$name_vars_in_goals1'([V|NGVL], I0, IF) :- + I is I0+1, + '$gen_name_string'(I0,[],SName), !, + atom_codes(Name, [95|SName]), + V = '$VAR'(Name), + '$name_vars_in_goals1'(NGVL, I, IF). +'$name_vars_in_goals1'([NV|NGVL], I0, IF) :- + nonvar(NV), + '$name_vars_in_goals1'(NGVL, I0, IF). + +'$write_output_vars'([]). +'$write_output_vars'([V|VL]) :- + format(user_error,' = ~a',[V]), + '$write_output_vars'(VL). + + +% +% standard meta-call, called if $execute could not do everything. +% +'$meta_call'(G, M) :- + '$current_choice_point'(CP), + '$call'(G, CP, G, M). + +'$user_call'(G, M) :- + gated_call( + '$enable_debugging', + M:G, + Port, + '$disable_debugging_on_port'(Port) + ). + +'$disable_debugging_on_port'(retry) :- + !, + '$enable_debugging'. +'$disable_debugging_on_port'(_Port) :- + '$disable_debugging'. + + + +% enable creeping +'$enable_debugging':- + current_prolog_flag(debug, false), !. +'$enable_debugging' :- + '__NB_setval__'('$debug_status', state(creep, 0, stop)), + '$trace_on', !, + '$creep'. +'$enable_debugging'. + +'$trace_on' :- + '__NB_getval__'('$trace', on, fail). + +'$trace_off' :- + '__NB_getval__'('$trace', off, fail). + +'$cut_by'(CP) :- '$$cut_by'(CP). + +% +% do it in ISO mode. +% +'$meta_call'(G,_ISO,M) :- + '$iso_check_goal'(G,G), + '$current_choice_point'(CP), + '$call'(G, CP, G, M). + +'$meta_call'(G, CP, G0, M) :- + '$call'(G, CP, G0, M). + +'$call'(G, CP, G0, _, M) :- /* iso version */ + '$iso_check_goal'(G,G0), + '$call'(G, CP, G0, M). + + +'$call'(M:_,_,G0,_) :- var(M), !, + '$do_error'(instantiation_error,call(G0)). +'$call'(M:G,CP,G0,_) :- !, + '$call'(G,CP,G0,M). +'$call'((X,Y),CP,G0,M) :- !, + '$call'(X,CP,G0,M), + '$call'(Y,CP,G0,M). +'$call'((X->Y),CP,G0,M) :- !, + ( + '$call'(X,CP,G0,M) + -> + '$call'(Y,CP,G0,M) + ). +'$call'((X*->Y),CP,G0,M) :- !, + '$call'(X,CP,G0,M), + '$call'(Y,CP,G0,M). +'$call'((X->Y; Z),CP,G0,M) :- !, + ( + '$call'(X,CP,G0,M) + -> + '$call'(Y,CP,G0,M) + ; + '$call'(Z,CP,G0,M) + ). +'$call'((X*->Y; Z),CP,G0,M) :- !, + ( + '$current_choice_point'(DCP), + '$call'(X,CP,G0,M), + yap_hacks:cut_at(DCP), + '$call'(Y,CP,G0,M) + ; + '$call'(Z,CP,G0,M) + ). +'$call'((A;B),CP,G0,M) :- !, + ( + '$call'(A,CP,G0,M) + ; + '$call'(B,CP,G0,M) + ). +'$call'((X->Y| Z),CP,G0,M) :- !, + ( + '$call'(X,CP,G0,M) + -> + '$call'(Y,CP,G0,M) + ; + '$call'(Z,CP,G0,M) + ). +'$call'((X*->Y| Z),CP,G0,M) :- !, + ( + '$current_choice_point'(DCP), + '$call'(X,CP,G0,M), + yap_hacks:cut_at(DCP), + '$call'(Y,CP,G0,M) + ; + '$call'(Z,CP,G0,M) + ). +'$call'((A|B),CP, G0,M) :- !, + ( + '$call'(A,CP,G0,M) + ; + '$call'(B,CP,G0,M) + ). +'$call'(\+ X, _CP, G0, M) :- !, + \+ ('$current_choice_point'(CP), + '$call'(X,CP,G0,M) ). +'$call'(not(X), _CP, G0, M) :- !, + \+ ('$current_choice_point'(CP), + '$call'(X,CP,G0,M) ). +'$call'(!, CP, _,_) :- !, + '$$cut_by'(CP). +'$call'([A|B], _, _, M) :- !, + '$csult'([A|B], M). +'$call'(G, _CP, _G0, CurMod) :- +/* + ( + '$is_metapredicate'(G,CurMod) + -> + '$disable_debugging', + ( '$expand_meta_call'(CurMod:G, [], NG) -> true ; true ), + '$enable_debugging' + ; + NG = G + ), + */ + '$execute0'(G, CurMod). + +'$check_callable'(V,G) :- var(V), !, + '$do_error'(instantiation_error,G). +'$check_callable'(M:_G1,G) :- var(M), !, + '$do_error'(instantiation_error,G). +'$check_callable'(_:G1,G) :- !, + '$check_callable'(G1,G). +'$check_callable'(A,G) :- number(A), !, + '$do_error'(type_error(callable,A),G). +'$check_callable'(R,G) :- db_reference(R), !, + '$do_error'(type_error(callable,R),G). +'$check_callable'(_,_). + + +'$loop'(Stream,exo) :- + prolog_flag(agc_margin,Old,0), + prompt1(': '), prompt(_,' '), + '$current_module'(OldModule), + repeat, + '$system_catch'(dbload_from_stream(Stream, OldModule, exo), '$db_load', Error, + user:'$LoopError'(Error, top)), + prolog_flag(agc_margin,_,Old), + !. +'$loop'(Stream,db) :- + prolog_flag(agc_margin,Old,0), + prompt1(': '), prompt(_,' '), + '$current_module'(OldModule), + repeat, + '$system_catch'(dbload_from_stream(Stream, OldModule, db), '$db_load', Error, + user:'$LoopError'(Error, top)), + prolog_flag(agc_margin,_,Old), + !. +'$loop'(Stream,Status) :- + repeat, + '$current_module'( OldModule, OldModule ), + '$system_catch'( '$enter_command'(Stream,OldModule,Status), + OldModule, Error, + user:'$LoopError'(Error, Status) + ), + !. + +'$boot_loop'(Stream,Where) :- + repeat, + '$current_module'( OldModule, OldModule ), + read_clause(Stream, Command, [module(OldModule), syntax_errors(dec10),variable_names(_Vars), term_position(_Pos)]), + (Command == end_of_file + -> + ! + ; + Command = (:- Goal) -> + '$system_catch'('$boot_execute'(Goal), prolog, Error, + user:'$LoopError'(Error, consult) ), + fail + ; +Command = (H --> B) -> + '$system_catch'('$boot_dcg'(H,B, Where), prolog, Error, + user:'$LoopError'(Error, consult) ), + + fail + ; + '$system_catch'('$boot_clause'( Command, Where ), prolog, Error, + user:'$LoopError'(Error, consult) ), + fail + ). + + '$boot_execute'( Goal ) :- + '$execute'( Goal ), + !. + '$boot_execute'( Goal ) :- + format(user_error, ':- ~w failed.~n', [Goal]). + +'$boot_dcg'( H, B, Where ) :- + '$translate_rule'((H --> B), (NH :- NB) ), + '$$compile'((NH :- NB), Where, ( H --> B), _R), + !. +'$boot_dcg'( H, B, _ ) :- + format(user_error, ' ~w --> ~w failed.~n', [H,B]). + +'$boot_clause'( Command, Where ) :- + '$$compile'(Command, Where, Command, _R), + !. +'$boot_clause'( Command, _ ) :- + format(user_error, ' ~w failed.~n', [Command]). + + + +'$enter_command'(Stream, Mod, Status) :- + prompt1(': '), prompt(_,' '), + Options = [module(Mod), syntax_errors(dec10),variable_names(Vars), term_position(Pos)], + ( + Status == top + -> + read_term(Stream, Command, Options) + ; + read_clause(Stream, Command, Options) + ), + '$command'(Command,Vars,Pos, Status). + +/** @pred user:expand_term( _T_,- _X_) is dynamic,multifile. + + This user-defined predicate is called by YAP after + reading goals and clauses. + + - _Module_:`expand_term(` _T_ , _X_) is called first on the + current source module _Module_ ; if i + - `user:expand_term(` _T_ , _X_ `)` is available on every module. + + */ + +/* General purpose predicates */ + +'$head_and_body'((H:-B),H,B) :- !. +'$head_and_body'(H,H,true). + + +gated_call(Setup, Goal, Catcher, Cleanup) :- + '$setup_call_catcher_cleanup'(Setup), + '$gated_call'( true , Goal, Catcher, Cleanup) . + +'$gated_call'( All , Goal, Catcher, Cleanup) :- + Task0 = cleanup( All, Catcher, Cleanup, Tag, true, CP0), + TaskF = cleanup( All, Catcher, Cleanup, Tag, false, CP0), + '$tag_cleanup'(CP0, Task0), + '$execute'( Goal ), + '$cleanup_on_exit'(CP0, TaskF). + + +% +% split head and body, generate an error if body is unbound. +% +'$check_head_and_body'(C,M,H,B,P) :- + '$yap_strip_module'(C,M1,(MH:-B0)), + !, + '$yap_strip_module'(M1:MH,M,H), + ( M == M1 -> B = B0 ; B = M1:B0), + is_callable(M:H,P). + +'$check_head_and_body'(MH, M, H, true, P) :- + '$yap_strip_module'(MH,M,H), + is_callable(M:H,P). + % term expansion +% +% return two arguments: Expanded0 is the term after "USER" expansion. +% Expanded is the final expanded term. +% +'$precompile_term'(Term, ExpandedUser, Expanded) :- +%format('[ ~w~n',[Term]), + '$expand_clause'(Term, ExpandedUser, ExpandedI), + !, +%format(' -> ~w~n',[Expanded0]), + ( + current_prolog_flag(strict_iso, true) /* strict_iso on */ + -> + Expanded = ExpandedI, + '$check_iso_strict_clause'(ExpandedUser) + ; + '$expand_array_accesses_in_term'(ExpandedI,Expanded) + -> true + ; + Expanded = ExpandedI + ). +'$precompile_term'(Term, Term, Term). + +'$expand_clause'(InputCl, C1, CO) :- + source_module(SM), + '$yap_strip_clause'(SM:InputCl, M, ICl), + '$expand_a_clause'( M:ICl, SM, C1, CO), + !. +'$expand_clause'(Cl, Cl, Cl). + +/** @pred expand_term( _T_,- _X_) + +This predicate is used by YAP for preprocessing each top level +term read when consulting a file and before asserting or executing it. +It rewrites a term _T_ to a term _X_ according to the following +rules: first try term_expansion/2 in the current module, and then try to use the user defined predicate user:term_expansion/2`. If this call fails then the translating process +for DCG rules is applied, together with the arithmetic optimizer +whenever the compilation of arithmetic expressions is in progress. + + +*/ +expand_term(Term,Expanded) :- + ( + '$do_term_expansion'(Term,Expanded) + -> + true + ; + '$expand_term_grammar'(Term,Expanded) + ). + +% +% Grammar Rules expansion +% +'$expand_term_grammar'((A-->B), C) :- + prolog:'$translate_rule'((A-->B),C), !. +'$expand_term_grammar'(A, A). + +% +% Arithmetic expansion +% +'$expand_array_accesses_in_term'(Expanded0,ExpandedF) :- + '$array_refs_compiled', + '$arrays':'$c_arrays'(Expanded0,ExpandedF), !. +'$expand_array_accesses_in_term'(Expanded,Expanded). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% catch/throw implementation + +% at each catch point I need to know: +% what is ball; +% where was the previous catch +/** @pred catch( : _Goal_,+ _Exception_,+ _Action_) is iso + + +The goal `catch( _Goal_, _Exception_, _Action_)` tries to +execute goal _Goal_. If during its execution, _Goal_ throws an +exception _E'_ and this exception unifies with _Exception_, the +exception is considered to be caught and _Action_ is executed. If +the exception _E'_ does not unify with _Exception_, control +again throws the exception. + +The top-level of YAP maintains a default exception handler that +is responsible to capture uncaught exceptions. + + +*/ +catch(G, C, A) :- + '$catch'(G,C,A). + +% makes sure we have an environment. +'$true'. + + +% system_catch is like catch, but it avoids the overhead of a full +% meta-call by calling '$execute0' instead of $execute. +% This way it +% also avoids module preprocessing and goal_expansion +% +'$system_catch'(G, M, C, A) :- + % check current trail + '$catch'(M:G,C,A). + +'$catch'(MG,_,_) :- + '$$save_by'(CP0), + '$execute'(MG), + '$$save_by'(CP1), + % remove catch + ( + CP0 == CP1 + -> + ! + ; + true + ). +'$catch'(_,C,A) :- + '$get_exception'(C), + '$run_catch'(A, C). + +% variable throws are user-handled. +'$run_catch'(G,E) :- + E = '$VAR'(_), + !, + call(G ). +'$run_catch'(abort,_) :- + abort. +'$run_catch'('$Error'(E),E) :- + !, + '$LoopError'(E, top ). +'$run_catch'('$LoopError'(E, Where),E) :- + !, + '$LoopError'(E, Where). +'$run_catch'('$TraceError'(E, GoalNumber, G, Module, CalledFromDebugger),E) :- + !, + '$TraceError'(E, GoalNumber, G, Module, CalledFromDebugger). +'$run_catch'(_Signal,E) :- + functor( E, N, _), + '$hidden_atom'(N), !, + throw(E). +'$run_catch'( Signal, _E) :- + call( Signal ). + +% +% throw has to be *exactly* after system catch! +% +/** @pred throw(+ _Ball_) is iso + + +The goal `throw( _Ball_)` throws an exception. Execution is +stopped, and the exception is sent to the ancestor goals until reaching +a matching catch/3, or until reaching top-level. + +*/ +throw(Ball) :- + % get current jump point + '$jump_env_and_store_ball'(Ball). + +'$run_toplevel_hooks' :- + current_prolog_flag(break_level, 0 ), + recorded('$toplevel_hooks',H,_), + H \= fail, !, + ( call(user:H) -> true ; true). +'$run_toplevel_hooks'. + +'$run_at_thread_start' :- + recorded('$thread_initialization',M:D,_), + '$meta_call'(D, M), + fail. +'$run_at_thread_start'. + +log_event( String, Args ) :- + format( atom( M ), String, Args), + log_event( M ). + +'$prompt' :- + current_prolog_flag(break_level, BreakLevel), + ( + BreakLevel == 0 + -> + LF = LD + ; + LF = ['Break (level ', BreakLevel, ')'|LD] + ), + current_prolog_flag(debug, DBON), + ( + '$trace_on' + -> + ( + var(LF) + -> + LD = ['trace'|LP] + ; + LD = [', trace '|LP] + ) + ; + DBON == true + -> + (var(LF) + -> + LD = ['debug'|LP] + ; + LD = [', debug'|LP] + ) + ; + LD = LP + ), + ( + var(LF) + -> + LP = [P] + ; + LP = [' ',P] + ), + yap_flag(toplevel_prompt, P), + atomic_concat(LF, PF), + prompt1(PF), + prompt(_,' | '), + '$ensure_prompting'. + + +/** +@} @} +*/ + + +/** + +@{ + @defgroup library The Prolog library + + + + @addtogroup YAPControl +@ingroup builtins + @{ +*/ +:- system_module( '$_init', [!/0, + ':-'/1, + '?-'/1, + []/0, + extensions_to_present_answer/1, + fail/0, + false/0, + goal_expansion/2, + goal_expansion/3, + otherwise/0, + term_expansion/2, + version/2, + '$do_log_upd_clause'/6, + '$do_log_upd_clause0'/6, + '$do_log_upd_clause_erase'/6, + '$do_static_clause'/5], [ + '$system_module'/1]). + +:- use_system_module( '$_boot', ['$cut_by'/1]). + +%:- start_low_level_trace. + +% This is the YAP init file +% should be consulted first step after booting + +% These are pseudo declarations +% so that the user will get a redefining system predicate + + +% just create a choice-point +% the 6th argument marks the time-stamp. +'$do_log_upd_clause'(_,_,_,_,_,_). +'$do_log_upd_clause'(A,B,C,D,E,_) :- + '$continue_log_update_clause'(A,B,C,D,E). +'$do_log_upd_clause'(_,_,_,_,_,_). + + +'$do_log_upd_clause_erase'(_,_,_,_,_,_). +'$do_log_upd_clause_erase'(A,B,C,D,E,_) :- + '$continue_log_update_clause_erase'(A,B,C,D,E). +'$do_log_upd_clause_erase'(_,_,_,_,_,_). + +'$do_log_upd_clause0'(_,_,_,_,_,_). +'$do_log_upd_clause0'(A,B,C,D,_,_) :- + '$continue_log_update_clause'(A,B,C,D). +'$do_log_upd_clause0'(_,_,_,_,_,_). + + +'$do_static_clause'(_,_,_,_,_). +'$do_static_clause'(A,B,C,D,E) :- + '$continue_static_clause'(A,B,C,D,E). +'$do_static_clause'(_,_,_,_,_). + +%:- start_low_level_trace. +:- c_compile('arith.yap'). +:- c_compile('builtins.yap'). +%:- stop_low_level_trace. + +:- '$all_current_modules'(M), yap_flag(M:unknown, error) ; true. + + +:- compile_expressions. + + +:- c_compile('imports.yap'). +:- c_compile('bootutils.yap'). +:- c_compile('bootlists.yap'). +:- c_compile('consult.yap'). +:- c_compile('preddecls.yap'). +:- c_compile('preddyns.yap'). +:- c_compile('meta.yap'). +:- c_compile('newmod.yap'). + +:- c_compile('atoms.yap'). +:- c_compile('os.yap'). +:- c_compile('grammar.yap'). +:- c_compile('errors.yap'). +:- c_compile('absf.yap'). + +%:- set_prolog_flag(verbose_file_search, true ). +%:- yap_flag(write_strings,on). +%:- start_low_level_trace. +:- [ + 'preds.yap', + 'modules.yap' + ]. + + + :- use_module('error.yap'). + + +:- [ + 'utils.yap', + 'control.yap', + 'flags.yap' +]. + + +:- [ + % lists is often used. + '../os/yio.yap', + '../pl/debug.yap', + 'checker.yap', + 'depth_bound.yap', + 'ground.yap', + 'listing.yap', + 'arithpreds.yap', + % modules must be after preds, otherwise we will have trouble + % with meta-predicate expansion being invoked + % must follow grammar + 'eval.yap', + 'signals.yap', + 'profile.yap', + 'callcount.yap', + 'load_foreign.yap', +% 'save.yap', + 'setof.yap', + 'sort.yap', + 'statistics.yap', + 'strict_iso.yap', + 'tabling.yap', + 'threads.yap', + 'eam.yap', + 'yapor.yap', + 'qly.yap', + 'spy.yap', + 'udi.yap']. + + +:- meta_predicate(log_event(+,:)). + +:- dynamic prolog:'$user_defined_flag'/4. + +:- multifile prolog:debug_action_hook/1. + +:- multifile prolog:'$system_predicate'/2. + +:- ['protect.yap']. + +version(yap,[6,3]). + +:- op(1150,fx,(mode)). + +:- dynamic 'extensions_to_present_answer'/1. + +:- ['arrays.yap']. +%:- start_low_level_trace. + +:- multifile user:portray_message/2. + +:- dynamic user:portray_message/2. + +/** @pred _CurrentModule_:goal_expansion(+ _G_,+ _M_,- _NG_), user:goal_expansion(+ _G_,+ _M_,- _NG_) + + +YAP now supports goal_expansion/3. This is an user-defined +procedure that is called after term expansion when compiling or +asserting goals for each sub-goal in a clause. The first argument is +bound to the goal and the second to the module under which the goal + _G_ will execute. If goal_expansion/3 succeeds the new +sub-goal _NG_ will replace _G_ and will be processed in the same + way. If goal_expansion/3 fails the system will use the defaultyap+flrules. + + +*/ +:- multifile user:goal_expansion/3. + +:- dynamic user:goal_expansion/3. + +:- multifile user:goal_expansion/2. + +:- dynamic user:goal_expansion/2. + +:- multifile system:goal_expansion/2. + +:- dynamic system:goal_expansion/2. + +:- multifile goal_expansion/2. + +:- dynamic goal_expansion/2. + +:- use_module('messages.yap'). + +:- ['undefined.yap']. + +:- use_module('hacks.yap'). + + +:- use_module('attributes.yap'). +:- use_module('corout.yap'). +:- use_module('dialect.yap'). +:- use_module('dbload.yap'). +:- use_module('../library/ypp.yap'). +:- use_module('../os/chartypes.yap'). +:- ensure_loaded('../os/edio.yap'). + +yap_hacks:cut_by(CP) :- '$$cut_by'(CP). + +:- '$change_type_of_char'(36,7). % Make $ a symbol character + +:- set_prolog_flag(generate_debug_info,true). + +% +% cleanup ensure loaded and recover some data-base space. +% +%:- ( recorded('$lf_loaded',_,R), erase(R), fail ; true ). +%:- ( recorded('$module',_,R), erase(R), fail ; true ). + +:- set_value('$user_module',user), '$protect'. + +:- style_check([+discontiguous,+multiple,+single_var]). + +% +% moved this to init_gc in gc.c to separate the alpha +% +% :- yap_flag(gc,on). + +% :- yap_flag(gc_trace,verbose). + +:- multifile + prolog:comment_hook/3. + +:- source. + +:- module(user). + + +/** @pred _CurrentModule_:term_expansion( _T_,- _X_), user:term_expansion( _T_,- _X_) + + +This user-defined predicate is called by `expand_term/3` to +preprocess all terms read when consulting a file. If it succeeds: + ++ +If _X_ is of the form `:- G` or `?- G`, it is processed as +a directive. ++ +If _X_ is of the form `$source_location`( _File_, _Line_): _Clause_` it is processed as if from `File` and line `Line`. + ++ +If _X_ is a list, all terms of the list are asserted or processed +as directives. ++ The term _X_ is asserted instead of _T_. + + + +*/ +:- multifile term_expansion/2. + +:- dynamic term_expansion/2. + +:- multifile system:term_expansion/2. + +:- dynamic system:term_expansion/2. + +:- multifile swi:swi_predicate_table/4. + +/** @pred user:message_hook(+ _Term_, + _Kind_, + _Lines_) + + +Hook predicate that may be define in the module `user` to intercept +messages from print_message/2. _Term_ and _Kind_ are the +same as passed to print_message/2. _Lines_ is a list of +format statements as described with print_message_lines/3. + +This predicate should be defined dynamic and multifile to allow other +modules defining clauses for it too. + + +*/ +:- multifile user:message_hook/3. + +:- dynamic user:message_hook/3. + +/** @pred exception(+ _Exception_, + _Context_, - _Action_) + + +Dynamic predicate, normally not defined. Called by the Prolog system on run-time exceptions that can be repaired `just-in-time`. The values for _Exception_ are described below. See also catch/3 and throw/1. +If this hook predicate succeeds it must instantiate the _Action_ argument to the atom `fail` to make the operation fail silently, `retry` to tell Prolog to retry the operation or `error` to make the system generate an exception. The action `retry` only makes sense if this hook modified the environment such that the operation can now succeed without error. + ++ `undefined_predicate` + _Context_ is instantiated to a predicate-indicator ( _Module:Name/Arity_). If the predicate fails Prolog will generate an existence_error exception. The hook is intended to implement alternatives to the SWI built-in autoloader, such as autoloading code from a database. Do not use this hook to suppress existence errors on predicates. See also `unknown`. ++ `undefined_global_variable` + _Context_ is instantiated to the name of the missing global variable. The hook must call nb_setval/2 or b_setval/2 before returning with the action retry. + +*/ + +:- multifile user:exception/3. + +:- dynamic user:exception/3. + +:- ensure_loaded('../pl/pathconf.yap'). +/* + Add some tests +*/ + + +:- yap_flag(user:unknown,error). + +/* +:- if(predicate_property(run_tests, static)). + +aa b. + +p(X,Y) :- Y is X*X. + +prefix(information, '% ', S, user_error) --> []. + +:- format('~d~n', [a]). + +:- format('~d~n', []). + +:- p(X,Y). + +a(1). + +a. + +a(2). +a(2). + +lists:member(1,[1]). + +clause_to_indicator(T, M:Name/Arity) :- , + strip_module(T, M, T1), + pred_arity( T1, Name, Arity ). +:- endif. +*/ +/** + +@{ + @defgroup library The Prolog library + + + + @addtogroup YAPControl +@ingroup builtins + @{ +*/ +:- '$system_predicate'( + [!/0, + ':-'/1, + '?-'/1, + []/0, + extensions_to_present_answer/1, + fail/0, + false/0, + goal_expansion/2, + goal_expansion/3, + otherwise/0, + term_expansion/2, + version/2]). + +%:- start_low_level_trace. + +% This is the YAP init file +% should be consulted first step after booting + +% These are pseudo declarations +% so that the user will get a redefining system predicate + +:- '$init_pred_flag_vals'('$flag_info'(a,0), prolog). + +/** @pred fail is iso + +Always fails. +*/ +fail :- fail. + +/** @pred false is iso + + +The same as fail. + + +*/ +false :- fail. + +otherwise. + +!. + +(:- G) :- '$execute'(G), !. + +(?- G) :- '$execute'(G). + +'$$!'(CP) :- '$cut_by'(CP). + +[] :- true. + +% just create a choice-point +% the 6th argument marks the time-stamp. +'$do_log_upd_clause'(_,_,_,_,_,_). +'$do_log_upd_clause'(A,B,C,D,E,_) :- + '$continue_log_update_clause'(A,B,C,D,E). +'$do_log_upd_clause'(_,_,_,_,_,_). + + +'$do_log_upd_clause_erase'(_,_,_,_,_,_). +'$do_log_upd_clause_erase'(A,B,C,D,E,_) :- + '$continue_log_update_clause_erase'(A,B,C,D,E). +'$do_log_upd_clause_erase'(_,_,_,_,_,_). + +'$do_log_upd_clause0'(_,_,_,_,_,_). +'$do_log_upd_clause0'(A,B,C,D,_,_) :- + '$continue_log_update_clause'(A,B,C,D). +'$do_log_upd_clause0'(_,_,_,_,_,_). + + +'$do_static_clause'(_,_,_,_,_). +'$do_static_clause'(A,B,C,D,E) :- + '$continue_static_clause'(A,B,C,D,E). +'$do_static_clause'(_,_,_,_,_). + +:- c_compile('arith.yap', prolog). + +:- '$all_current_modules'(M), yap_flag(M:unknown, error) ; true. + +:- compile_expressions. + + +:- c_compile('bootutils.yap', prolog). +:- c_compile('bootlists.yap', prolog). +:- c_compile('consult.yap', prolog). +:- c_compile('preddecls.yap', prolog). +:- c_compile('preddyns.yap', prolog). +:- c_compile('meta.yap', prolog). +:- c_compile('newmod.yap', prolog). + +:- c_compile('atoms.yap', prolog). +:- c_compile('os.yap', prolog). +:- c_compile('grammar.yap', prolog). +:- c_compile('directives.yap', prolog). +:- c_compile('absf.yap', prolog). + +:- dynamic prolog:'$parent_module'/2. +%:- set_prolog_flag(verbose_file_search, true ). +%:- yap_flag(write_strings,on). +%:- start_low_level_trace. + +:- ensure_loaded([ + 'preds.yap', + 'modules.yap' + ]). +%:-stop_low_level_trace. + +:- use_module('error.yap'). + + +:- ensure_loaded([ + 'errors.yap', + 'utils.yap', + 'control.yap', + 'flags.yap' +]). + + +:- ensure_loaded([ + % lists is often used. + '../os/yio.yap', + 'debug.yap', + 'checker.yap', + 'depth_bound.yap', + 'ground.yap', + 'listing.yap', + 'arithpreds.yap', + % modules must be after preds, otherwise we will have trouble + % with meta-predicate expansion being invoked + % must follow grammar + 'eval.yap', + 'signals.yap', + 'profile.yap', + 'callcount.yap', + 'load_foreign.yap', +% 'save.yap', + 'setof.yap', + 'sort.yap', + 'statistics.yap', + 'strict_iso.yap', + 'tabling.yap', + 'threads.yap', + 'eam.yap', + 'yapor.yap', + 'qly.yap', + 'spy.yap', + 'udi.yap']). + + +:- meta_predicate(log_event(+,:)). + +:- dynamic prolog:'$user_defined_flag'/4. + +:- multifile prolog:debug_action_hook/1. + +:- multifile prolog:'$system_predicate'/2. + +:- ensure_loaded(['protect.yap']). + +version(yap,[6,3]). + +:- op(1150,fx,(mode)). + +:- dynamic 'extensions_to_present_answer'/1. + +:- ensure_loaded(['arrays.yap']). +%:- start_low_level_trace. + +:- multifile user:portray_message/2. + +:- dynamic user:portray_message/2. + +/** @pred _CurrentModule_:goal_expansion(+ _G_,+ _M_,- _NG_), user:goal_expansion(+ _G_,+ _M_,- _NG_) + + +YAP now supports goal_expansion/3. This is an user-defined +procedure that is called after term expansion when compiling or +asserting goals for each sub-goal in a clause. The first argument is +bound to the goal and the second to the module under which the goal + _G_ will execute. If goal_expansion/3 succeeds the new +sub-goal _NG_ will replace _G_ and will be processed in the same + way. If goal_expansion/3 fails the system will use the defaultyap+flrules. + + +*/ +:- multifile user:goal_expansion/3. + +:- dynamic user:goal_expansion/3. + +:- multifile user:goal_expansion/2. + +:- dynamic user:goal_expansion/2. + +:- multifile system:goal_expansion/2. + +:- dynamic system:goal_expansion/2. + +:- multifile goal_expansion/2. + +:- dynamic goal_expansion/2. + +:- use_module('messages.yap'). + +:- ensure_loaded(['undefined.yap']). + +:- use_module('hacks.yap'). + + +:- use_module('attributes.yap'). +:- use_module('corout.yap'). +:- use_module('dialect.yap'). +:- use_module('dbload.yap'). +:- use_module('../library/ypp.yap'). +:- use_module('../os/chartypes.yap'). +:- ensure_loaded('../os/edio.yap'). + +yap_hacks:cut_by(CP) :- '$$cut_by'(CP). + +:- '$change_type_of_char'(36,7). % Make $ a symbol character + +:- set_prolog_flag(generate_debug_info,true). + +% +% cleanup ensure loaded and recover some data-base space. +% +:- ( recorded('$lf_loaded',_,R), erase(R), fail ; true ). +:- ( recorded('$lf_loaded',_,R), erase(R), fail ; true ). +:- ( recorded('$module',_,R), erase(R), fail ; true ). + +:- set_value('$user_module',user), '$protect'. + +:- style_check([+discontiguous,+multiple,+single_var]). + +% +% moved this to init_gc in gc.c to separate the alpha +% +% :- yap_flag(gc,on). + +% :- yap_flag(gc_trace,verbose). + +:- multifile + prolog:comment_hook/3. + +:- source. + +:- module(user). + + +/** @pred _CurrentModule_:term_expansion( _T_,- _X_), user:term_expansion( _T_,- _X_) + + +This user-defined predicate is called by `expand_term/3` to +preprocess all terms read when consulting a file. If it succeeds: + ++ +If _X_ is of the form `:- G` or `?- G`, it is processed as +a directive. ++ +If _X_ is of the form `$source_location`( _File_, _Line_): _Clause_` it is processed as if from `File` and line `Line`. + ++ +If _X_ is a list, all terms of the list are asserted or processed +as directives. ++ The term _X_ is asserted instead of _T_. + + + +*/ +:- multifile term_expansion/2. + +:- dynamic term_expansion/2. + +:- multifile system:term_expansion/2. + +:- dynamic system:term_expansion/2. + +:- multifile swi:swi_predicate_table/4. + +/** @pred user:message_hook(+ _Term_, + _Kind_, + _Lines_) + + +Hook predicate that may be define in the module `user` to intercept +messages from print_message/2. _Term_ and _Kind_ are the +same as passed to print_message/2. _Lines_ is a list of +format statements as described with print_message_lines/3. + +This predicate should be defined dynamic and multifile to allow other +modules defining clauses for it too. + + +*/ +:- multifile user:message_hook/3. + +:- dynamic user:message_hook/3. + +/** @pred exception(+ _Exception_, + _Context_, - _Action_) + + +Dynamic predicate, normally not defined. Called by the Prolog system on run-time exceptions that can be repaired `just-in-time`. The values for _Exception_ are described below. See also catch/3 and throw/1. +If this hook predicate succeeds it must instantiate the _Action_ argument to the atom `fail` to make the operation fail silently, `retry` to tell Prolog to retry the operation or `error` to make the system generate an exception. The action `retry` only makes sense if this hook modified the environment such that the operation can now succeed without error. + ++ `undefined_predicate` + _Context_ is instantiated to a predicate-indicator ( _Module:Name/Arity_). If the predicate fails Prolog will generate an existence_error exception. The hook is intended to implement alternatives to the SWI built-in autoloader, such as autoloading code from a database. Do not use this hook to suppress existence errors on predicates. See also `unknown`. ++ `undefined_global_variable` + _Context_ is instantiated to the name of the missing global variable. The hook must call nb_setval/2 or b_setval/2 before returning with the action retry. + +*/ + +:- multifile user:exception/3. + +:- dynamic user:exception/3. + +:- ensure_loaded('pathconf.yap'). + +:- yap_flag(user:unknown,error). + + +:- halt(0). diff --git a/pl/imports.yap b/pl/imports.yap new file mode 100644 index 000000000..77158a199 --- /dev/null +++ b/pl/imports.yap @@ -0,0 +1,43 @@ +:- '$mk_dynamic'('$parent_module'(_,_),prolog). + +'$get_undefined_predicates'(G, ImportingMod, G0, ExportingMod) :- + recorded('$import','$import'(ExportingModI,ImportingMod,G0I,G,_,_),_), + '$continue_imported'(ExportingMod, ExportingModI, G0, G0I). +% SWI builtin +'$get_undefined_predicates'(G, _ImportingMod, G, user) :- + nonvar(G), + '$pred_exists'(G, user). +% autoload +'$get_undefined_predicates'(G, ImportingMod, G0, ExportingMod) :- + recorded('$dialect',swi,_), + prolog_flag(autoload, true), + prolog_flag(unknown, OldUnk, fail), + ( + '$autoload'(G, ImportingMod, ExportingModI, swi) + -> + prolog_flag(unknown, _, OldUnk) + ; + prolog_flag(unknown, _, OldUnk), + fail + ), + '$continue_imported'(ExportingMod, ExportingModI, G0, G). +% parent module mechanism +'$get_undefined_predicates'(G, ImportingMod, G0, ExportingMod) :- + '$parent_module'(ImportingMod,ExportingModI), + '$continue_imported'(ExportingMod, ExportingModI, G0, G). + +'$get_undefined_pred'(G, ImportingMod, G0, ExportingMod) :- + '$get_undefined_predicates'(G, ImportingMod, G0, ExportingMod), + !. + + +% be careful here not to generate an undefined exception. +'$imported_predicate'(G, _ImportingMod, G, prolog) :- + nonvar(G), '$is_system_predicate'(G, prolog), !. +'$imported_predicate'(G, ImportingMod, G0, ExportingMod) :- + ( var(G) -> true ; + var(ImportingMod) -> true ; + '$undefined'(G, ImportingMod) + ), + '$get_undefined_predicates'(G, ImportingMod, G0, ExportingMod), + ExportingMod \= ImportingMod. \ No newline at end of file diff --git a/pl/init.yap b/pl/init.yap index b96c5a55f..82dd79167 100644 --- a/pl/init.yap +++ b/pl/init.yap @@ -15,373 +15,3 @@ * * *************************************************************************/ -/** - - @file init.yap - -@{ - @defgroup library The Prolog library - -@} - - @addtogroup YAPControl -@ingroup builtins - @{ -*/ -:- system_module( '$_init', [!/0, - ':-'/1, - '?-'/1, - []/0, - extensions_to_present_answer/1, - fail/0, - false/0, - goal_expansion/2, - goal_expansion/3, - otherwise/0, - term_expansion/2, - version/2, - '$do_log_upd_clause'/6, - '$do_log_upd_clause0'/6, - '$do_log_upd_clause_erase'/6, - '$do_static_clause'/5], [ - '$system_module'/1]). - -:- use_system_module( '$_boot', ['$cut_by'/1]). - -%:- start_low_level_trace. - -% This is the YAP init file -% should be consulted first step after booting - -% These are pseudo declarations -% so that the user will get a redefining system predicate - - -:- '$init_pred_flag_vals'('$flag_info'(a,0), prolog). - -/** @pred fail is iso - -Always fails. -*/ -fail :- fail. - -/** @pred false is iso - - -The same as fail. - - -*/ -false :- fail. - -otherwise. - -!. - -(:- G) :- '$execute'(G), !. - -(?- G) :- '$execute'(G). - -'$$!'(CP) :- '$cut_by'(CP). - -[] :- true. - -:- set_value('$doindex',true). - -% just create a choice-point -% the 6th argument marks the time-stamp. -'$do_log_upd_clause'(_,_,_,_,_,_). -'$do_log_upd_clause'(A,B,C,D,E,_) :- - '$continue_log_update_clause'(A,B,C,D,E). -'$do_log_upd_clause'(_,_,_,_,_,_). - - -'$do_log_upd_clause_erase'(_,_,_,_,_,_). -'$do_log_upd_clause_erase'(A,B,C,D,E,_) :- - '$continue_log_update_clause_erase'(A,B,C,D,E). -'$do_log_upd_clause_erase'(_,_,_,_,_,_). - -'$do_log_upd_clause0'(_,_,_,_,_,_). -'$do_log_upd_clause0'(A,B,C,D,_,_) :- - '$continue_log_update_clause'(A,B,C,D). -'$do_log_upd_clause0'(_,_,_,_,_,_). - - -'$do_static_clause'(_,_,_,_,_). -'$do_static_clause'(A,B,C,D,E) :- - '$continue_static_clause'(A,B,C,D,E). -'$do_static_clause'(_,_,_,_,_). - -:- bootstrap('arith.yap'). - -:- '$all_current_modules'(M), yap_flag(M:unknown, error) ; true. - -:- compile_expressions. - - -:- bootstrap('bootutils.yap'). -:- bootstrap('bootlists.yap'). -:- bootstrap('consult.yap'). -:- bootstrap('preddecls.yap'). -:- bootstrap('preddyns.yap'). -:- bootstrap('meta.yap'). -:- bootstrap('newmod.yap'). - -:- bootstrap('atoms.yap'). -:- bootstrap('os.yap'). -:- bootstrap('grammar.yap'). -:- bootstrap('directives.yap'). -:- bootstrap('absf.yap'). - -:- dynamic prolog:'$parent_module'/2. -%:- set_prolog_flag(verbose_file_search, true ). -%:- yap_flag(write_strings,on). -%:- start_low_level_trace. -:- [ - 'preds.yap', - 'modules.yap' - ]. - - -:- use_module('error.yap'). - - -:- [ - 'errors.yap', - 'utils.yap', - 'control.yap', - 'flags.yap' -]. - - -:- [ - % lists is often used. - '../os/yio.yap', - 'debug.yap', - 'checker.yap', - 'depth_bound.yap', - 'ground.yap', - 'listing.yap', - 'arithpreds.yap', - % modules must be after preds, otherwise we will have trouble - % with meta-predicate expansion being invoked - % must follow grammar - 'eval.yap', - 'signals.yap', - 'profile.yap', - 'callcount.yap', - 'load_foreign.yap', -% 'save.yap', - 'setof.yap', - 'sort.yap', - 'statistics.yap', - 'strict_iso.yap', - 'tabling.yap', - 'threads.yap', - 'eam.yap', - 'yapor.yap', - 'qly.yap', - 'spy.yap', - 'udi.yap']. - - -:- meta_predicate(log_event(+,:)). - -:- dynamic prolog:'$user_defined_flag'/4. - -:- multifile prolog:debug_action_hook/1. - -:- multifile prolog:'$system_predicate'/2. - -:- ['protect.yap']. - -version(yap,[6,3]). - -:- op(1150,fx,(mode)). - -:- dynamic 'extensions_to_present_answer'/1. - -:- ['arrays.yap']. -%:- start_low_level_trace. - -:- multifile user:portray_message/2. - -:- dynamic user:portray_message/2. - -/** @pred _CurrentModule_:goal_expansion(+ _G_,+ _M_,- _NG_), user:goal_expansion(+ _G_,+ _M_,- _NG_) - - -YAP now supports goal_expansion/3. This is an user-defined -procedure that is called after term expansion when compiling or -asserting goals for each sub-goal in a clause. The first argument is -bound to the goal and the second to the module under which the goal - _G_ will execute. If goal_expansion/3 succeeds the new -sub-goal _NG_ will replace _G_ and will be processed in the same - way. If goal_expansion/3 fails the system will use the defaultyap+flrules. - - -*/ -:- multifile user:goal_expansion/3. - -:- dynamic user:goal_expansion/3. - -:- multifile user:goal_expansion/2. - -:- dynamic user:goal_expansion/2. - -:- multifile system:goal_expansion/2. - -:- dynamic system:goal_expansion/2. - -:- multifile goal_expansion/2. - -:- dynamic goal_expansion/2. - -:- use_module('messages.yap'). - -:- ['undefined.yap']. - -:- use_module('hacks.yap'). - - -:- use_module('attributes.yap'). -:- use_module('corout.yap'). -:- use_module('dialect.yap'). -:- use_module('dbload.yap'). -:- use_module('../library/ypp.yap'). -:- use_module('../os/chartypes.yap'). -:- ensure_loaded('../os/edio.yap'). - -yap_hacks:cut_by(CP) :- '$$cut_by'(CP). - -:- '$change_type_of_char'(36,7). % Make $ a symbol character - -:- set_prolog_flag(generate_debug_info,true). - -% -% cleanup ensure loaded and recover some data-base space. -% -:- ( recorded('$lf_loaded',_,R), erase(R), fail ; true ). -:- ( recorded('$lf_loaded',_,R), erase(R), fail ; true ). -:- ( recorded('$module',_,R), erase(R), fail ; true ). - -:- set_value('$user_module',user), '$protect'. - -:- style_check([+discontiguous,+multiple,+single_var]). - -% -% moved this to init_gc in gc.c to separate the alpha -% -% :- yap_flag(gc,on). - -% :- yap_flag(gc_trace,verbose). - -:- multifile - prolog:comment_hook/3. - -:- source. - -:- module(user). - - -/** @pred _CurrentModule_:term_expansion( _T_,- _X_), user:term_expansion( _T_,- _X_) - - -This user-defined predicate is called by `expand_term/3` to -preprocess all terms read when consulting a file. If it succeeds: - -+ -If _X_ is of the form `:- G` or `?- G`, it is processed as -a directive. -+ -If _X_ is of the form `$source_location`( _File_, _Line_): _Clause_` it is processed as if from `File` and line `Line`. - -+ -If _X_ is a list, all terms of the list are asserted or processed -as directives. -+ The term _X_ is asserted instead of _T_. - - - -*/ -:- multifile term_expansion/2. - -:- dynamic term_expansion/2. - -:- multifile system:term_expansion/2. - -:- dynamic system:term_expansion/2. - -:- multifile swi:swi_predicate_table/4. - -/** @pred user:message_hook(+ _Term_, + _Kind_, + _Lines_) - - -Hook predicate that may be define in the module `user` to intercept -messages from print_message/2. _Term_ and _Kind_ are the -same as passed to print_message/2. _Lines_ is a list of -format statements as described with print_message_lines/3. - -This predicate should be defined dynamic and multifile to allow other -modules defining clauses for it too. - - -*/ -:- multifile user:message_hook/3. - -:- dynamic user:message_hook/3. - -/** @pred exception(+ _Exception_, + _Context_, - _Action_) - - -Dynamic predicate, normally not defined. Called by the Prolog system on run-time exceptions that can be repaired `just-in-time`. The values for _Exception_ are described below. See also catch/3 and throw/1. -If this hook predicate succeeds it must instantiate the _Action_ argument to the atom `fail` to make the operation fail silently, `retry` to tell Prolog to retry the operation or `error` to make the system generate an exception. The action `retry` only makes sense if this hook modified the environment such that the operation can now succeed without error. - -+ `undefined_predicate` - _Context_ is instantiated to a predicate-indicator ( _Module:Name/Arity_). If the predicate fails Prolog will generate an existence_error exception. The hook is intended to implement alternatives to the SWI built-in autoloader, such as autoloading code from a database. Do not use this hook to suppress existence errors on predicates. See also `unknown`. -+ `undefined_global_variable` - _Context_ is instantiated to the name of the missing global variable. The hook must call nb_setval/2 or b_setval/2 before returning with the action retry. - -*/ - -:- multifile user:exception/3. - -:- dynamic user:exception/3. - -:- reconsult('pathconf.yap'). -/* - Add some tests -*/ - - -:- yap_flag(user:unknown,error). - -/* -:- if(predicate_property(run_tests, static)). - -aa b. - -p(X,Y) :- Y is X*X. - -prefix(information, '% ', S, user_error) --> []. - -:- format('~d~n', [a]). - -:- format('~d~n', []). - -:- p(X,Y). - -a(1). - -a. - -a(2). -a(2). - -lists:member(1,[1]). - -clause_to_indicator(T, M:Name/Arity) :- , - strip_module(T, M, T1), - pred_arity( T1, Name, Arity ). -:- endif. -*/ diff --git a/pl/messages.yap b/pl/messages.yap index b6fd52bd2..549319040 100644 --- a/pl/messages.yap +++ b/pl/messages.yap @@ -956,7 +956,7 @@ prolog:print_message(Level, _Msg) :- !. prolog:print_message(_, _Msg) :- % first step at hook processing - '$nb_getval'('$if_skip_mode',skip,fail), + '__NB_getval__'('$if_skip_mode',skip,fail), !. prolog:print_message(force(_Severity), Msg) :- !, print(user_error,Msg). diff --git a/pl/meta.yap b/pl/meta.yap index 5c3691422..f867bdac0 100644 --- a/pl/meta.yap +++ b/pl/meta.yap @@ -57,10 +57,7 @@ meta_predicate declaration functor(P,F,N), ( M1 = prolog -> M = _ ; M1 = M), ( retractall(prolog:'$meta_predicate'(F,M,N,_)), fail ; true), - asserta(prolog:'$meta_predicate'(F,M,N,P)), - '$predicate_flags'(P, M1, Fl, Fl), - NFlags is Fl \/ 0x200000, - '$predicate_flags'(P, M1, Fl, NFlags). + '$compile'(('$meta_predicate'(F,M,N,P) :- true),assertz,'$meta_predicate'(F,M,N,P),prolog,_). % comma has its own problems. diff --git a/pl/modules.yap b/pl/modules.yap index f8e8a7bc7..75b4eabc6 100644 --- a/pl/modules.yap +++ b/pl/modules.yap @@ -355,47 +355,6 @@ system_module(Mod) :- '$continue_imported'(FM, IM, FPred, Pred). -% be careful here not to generate an undefined exception. -'$imported_predicate'(G, _ImportingMod, G, prolog) :- - nonvar(G), '$is_system_predicate'(G, prolog), !. -'$imported_predicate'(G, ImportingMod, G0, ExportingMod) :- - ( var(G) -> true ; - var(ImportingMod) -> true ; - '$undefined'(G, ImportingMod) - ), - '$get_undefined_predicates'(G, ImportingMod, G0, ExportingMod), - ExportingMod \= ImportingMod. - -'$get_undefined_pred'(G, ImportingMod, G0, ExportingMod) :- - '$get_undefined_predicates'(G, ImportingMod, G0, ExportingMod), - !. - -'$get_undefined_predicates'(G, ImportingMod, G0, ExportingMod) :- - recorded('$import','$import'(ExportingModI,ImportingMod,G0I,G,_,_),_), - '$continue_imported'(ExportingMod, ExportingModI, G0, G0I). -% SWI builtin -'$get_undefined_predicates'(G, _ImportingMod, G, user) :- - nonvar(G), - '$pred_exists'(G, user). -% autoload -'$get_undefined_predicates'(G, ImportingMod, G0, ExportingMod) :- - recorded('$dialect',swi,_), - prolog_flag(autoload, true), - prolog_flag(unknown, OldUnk, fail), - ( - '$autoload'(G, ImportingMod, ExportingModI, swi) - -> - prolog_flag(unknown, _, OldUnk) - ; - prolog_flag(unknown, _, OldUnk), - fail - ), - '$continue_imported'(ExportingMod, ExportingModI, G0, G). -% parent module mechanism -'$get_undefined_predicates'(G, ImportingMod, G0, ExportingMod) :- - '$parent_module'(ImportingMod,ExportingModI), - '$continue_imported'(ExportingMod, ExportingModI, G0, G). - '$autoload'(G, _ImportingMod, ExportingMod, Dialect) :- functor(G, Name, Arity), '$pred_exists'(index(Name,Arity,ExportingMod,_),Dialect), @@ -410,7 +369,7 @@ system_module(Mod) :- '$autoloader_find_predicate'(G,ExportingModI) :- - '$nb_getval'('$autoloader_set', true, false), !, + '__NB_getval__'('$autoloader_set', true, false), !, autoloader:find_predicate(G,ExportingModI). '$autoloader_find_predicate'(G,ExportingModI) :- yap_flag(autoload, true, false), @@ -555,7 +514,7 @@ export_list(Module, List) :- '$check_import'(_,_,_,_). '$redefine_import'( M1, M2, Mod, ContextM, N/K) :- - '$nb_getval'('$lf_status', TOpts, fail), + '__NB_getval__'('$lf_status', TOpts, fail), '$lf_opt'(redefine_module, TOpts, Action), !, '$redefine_action'(Action, M1, M2, Mod, ContextM, N/K). '$redefine_import'( M1, M2, Mod, ContextM, N/K) :- diff --git a/pl/newmod.yap b/pl/newmod.yap index 9ad9bbb52..c17c883c4 100644 --- a/pl/newmod.yap +++ b/pl/newmod.yap @@ -57,7 +57,7 @@ name with the `:/2` operator. '$module_dec'(N, Ps). '$module_dec'(N, Ps) :- source_location(F,Line), - '$nb_getval'( '$user_source_file', F0 , fail), + '__NB_getval__'( '$user_source_file', F0 , fail), '$add_module_on_file'(N, F, Line,F0, Ps), '$current_module'(_M0,N). diff --git a/pl/preddecls.yap b/pl/preddecls.yap index 646fe7ba3..49e58500e 100644 --- a/pl/preddecls.yap +++ b/pl/preddecls.yap @@ -93,7 +93,7 @@ dynamic(X) :- '$dynamic'(A/N1,Mod). '$dynamic'(A/N,Mod) :- functor(G, A, N), - '$mk_d'(G,Mod). + '$mk_dynamic'(G,Mod). /** @pred public( _P_ ) is iso @@ -176,9 +176,7 @@ multifile(P) :- fail. '$multifile'(N/A, M) :- functor(S,N,A), - '$is_multifile'(S, M), !. -'$multifile'(N/A, M) :- !, - '$new_multifile'(N,A,M). + '$new_multifile'(S, M), !. '$multifile'([H|T], M) :- !, '$multifile'(H,M), '$multifile'(T,M). diff --git a/pl/preds.yap b/pl/preds.yap index bfb819e57..895d13f77 100644 --- a/pl/preds.yap +++ b/pl/preds.yap @@ -97,6 +97,8 @@ and therefore he should try to avoid them whenever possible. :- use_system_module( '$_strict_iso', ['$check_iso_strict_clause'/1]). + + /** @pred assert_static(: _C_) diff --git a/pl/signals.yap b/pl/signals.yap index f103adea1..ed63a9aed 100644 --- a/pl/signals.yap +++ b/pl/signals.yap @@ -304,7 +304,7 @@ read_sig. :- '$set_no_trace'('$execute_nonstop'(_,_), prolog). :- '$set_no_trace'('$execute_clause'(_,_,_,_), prolog). :- '$set_no_trace'('$restore_regs'(_,_), prolog). -:- '$set_no_trace'('$undefp0'(_,_), prolog). +:- '$set_no_trace'('$undefp'(_,_), prolog). :- '$set_no_trace'('$Error'(_), prolog). :- '$set_no_trace'('$LoopError'(_,_), prolog). :- '$set_no_trace'('$TraceError'(_,_,_,_,_), prolog). diff --git a/pl/undefined.yap b/pl/undefined.yap index a4ef740f8..583889636 100644 --- a/pl/undefined.yap +++ b/pl/undefined.yap @@ -109,6 +109,9 @@ undefined_query(G0, M0, Cut) :- expand_goal(MG, FMG). +:- abolish('$undefp'/2). + + % undef handler '$undefp'([M0|G0], Action) :- % make sure we do not loop on undefined predicates @@ -135,7 +138,7 @@ undefined_query(G0, M0, Cut) :- '$handle_error'(Action,G0,M0) ). -:- '$undefp_handler'('$undefp'(_,_), prolog). +%:- '$undefp_handler'('$undefp'(_,_), prolog). /** @pred unknown(- _O_,+ _N_) diff --git a/pl/utils.yap b/pl/utils.yap index 919910b16..80e7808da 100644 --- a/pl/utils.yap +++ b/pl/utils.yap @@ -344,7 +344,7 @@ enumeration is undefined. */ nb_current(GlobalVariable, Val) :- '$nb_current'(GlobalVariable), - '$nb_getval'(GlobalVariable, Val, _). + '__NB_getval__'(GlobalVariable, Val, _). '$getval_exception'(GlobalVariable, _Val, Caller) :- user:exception(undefined_global_variable, GlobalVariable, Action),