extensions
This commit is contained in:
parent
3a36285bb2
commit
31fd3eb344
4
C/text.c
4
C/text.c
@ -738,9 +738,9 @@ static Term write_number(unsigned char *s, seq_tv_t *out,
|
|||||||
yap_error_descriptor_t new_error;
|
yap_error_descriptor_t new_error;
|
||||||
int i = push_text_stack();
|
int i = push_text_stack();
|
||||||
Yap_pushErrorContext(&new_error);
|
Yap_pushErrorContext(&new_error);
|
||||||
t = Yap_StringToNumberTerm((char *)s, &out->enc, error_on);
|
t = Yap_StringToNumberTerm((char *)s, &out->enc,true);
|
||||||
pop_text_stack(i);
|
pop_text_stack(i);
|
||||||
Yap_popErrorContext(true);
|
Yap_popErrorContext(error_on);
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
133
C/yap-args.c
133
C/yap-args.c
@ -145,10 +145,9 @@ static void init_globals(YAP_init_args *yap_init) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const char *Yap_BINDIR, *Yap_ROOTDIR, *Yap_SHAREDIR, *Yap_LIBDIR, *Yap_DLLDIR,
|
const char *Yap_BINDIR, *Yap_ROOTDIR, *Yap_SHAREDIR, *Yap_LIBDIR, *Yap_DLLDIR,
|
||||||
*Yap_PLDIR, *Yap_BOOTSTRAP, *Yap_COMMONSDIR,
|
*Yap_PLDIR, *Yap_BOOTSTRAP, *Yap_COMMONSDIR, *Yap_STARTUP,
|
||||||
*Yap_STARTUP, *Yap_INPUT_STARTUP, *Yap_OUTPUT_STARTUP, *Yap_BOOTFILE, *Yap_INCLUDEDIR;
|
*Yap_INPUT_STARTUP, *Yap_OUTPUT_STARTUP, *Yap_BOOTFILE, *Yap_INCLUDEDIR;
|
||||||
|
|
||||||
/* do initial boot by consulting the file boot.yap */
|
/* do initial boot by consulting the file boot.yap */
|
||||||
static void consult(const char *b_file USES_REGS) {
|
static void consult(const char *b_file USES_REGS) {
|
||||||
@ -180,7 +179,8 @@ static void consult(const char *b_file USES_REGS) {
|
|||||||
CACHE_REGS
|
CACHE_REGS
|
||||||
YAP_Reset(YAP_FULL_RESET, false);
|
YAP_Reset(YAP_FULL_RESET, false);
|
||||||
Yap_StartSlots();
|
Yap_StartSlots();
|
||||||
__android_log_print(ANDROID_LOG_INFO, "YAPDroid", "read %s <%d>", b_file, GLOBAL_Stream[c_stream].linecount);
|
__android_log_print(ANDROID_LOG_INFO, "YAPDroid", "read %s <%d>", b_file,
|
||||||
|
GLOBAL_Stream[c_stream].linecount);
|
||||||
Term vs = YAP_MkVarTerm(), pos = MkVarTerm();
|
Term vs = YAP_MkVarTerm(), pos = MkVarTerm();
|
||||||
t = YAP_ReadClauseFromStream(c_stream, vs, pos);
|
t = YAP_ReadClauseFromStream(c_stream, vs, pos);
|
||||||
// Yap_GetNèwSlot(t);
|
// Yap_GetNèwSlot(t);
|
||||||
@ -213,40 +213,28 @@ static void consult(const char *b_file USES_REGS) {
|
|||||||
|
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
static const char * sel(bool dir, ...) {
|
static const char *sel(bool dir, bool ok1, const char *s1, bool ok2, const char *s2,
|
||||||
CACHE_REGS
|
...) {
|
||||||
va_list args;
|
if (ok1 && s1)
|
||||||
va_start(args ,dir);
|
return s1;
|
||||||
while (true) {
|
if (ok2)
|
||||||
bool init = va_arg(args, int);
|
return s2;
|
||||||
const char *fmt = va_arg(args, char *);
|
|
||||||
if (init) {
|
|
||||||
va_end(args);
|
|
||||||
return fmt;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char * join(const char *s, ...) {
|
static const char *join(const char *s0, const char *s1) {
|
||||||
CACHE_REGS
|
CACHE_REGS
|
||||||
va_list args;
|
|
||||||
va_start(args , s);
|
if (!s0 || s0[0] == '\0')
|
||||||
|
return s1;
|
||||||
|
if (!s1 || s1[0] == '\0')
|
||||||
|
return s0;
|
||||||
// int lvl = push_text_stack();
|
// int lvl = push_text_stack();
|
||||||
char *buf = malloc(FILENAME_MAX + 1);
|
char *buf = malloc(FILENAME_MAX + 1);
|
||||||
if (s && s[0])
|
strcpy(buf, s0);
|
||||||
strcpy(buf, s);
|
strcat(buf, s1);
|
||||||
while (true) {
|
|
||||||
const char *fmt = va_arg(args, char *);
|
|
||||||
if (fmt == NULL) {
|
|
||||||
va_end(args);
|
|
||||||
// return pop_output_text_stack(lvl,buf);
|
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
strcat(buf, fmt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Yap_set_locations(YAP_init_args *iap) {
|
static void Yap_set_locations(YAP_init_args *iap) {
|
||||||
|
|
||||||
@ -257,123 +245,101 @@ static const char * join(const char *s, ...) {
|
|||||||
/// It is:
|
/// It is:
|
||||||
// --_not useful in Android, WIN32;
|
// --_not useful in Android, WIN32;
|
||||||
/// -- DESTDIR/ in Anaconda
|
/// -- DESTDIR/ in Anaconda
|
||||||
/// -- /usr/local in most Unix style systems
|
/// -- /usr/locall in most Unix style systems
|
||||||
Yap_ROOTDIR = sel(true, iap->ROOTDIR != NULL, iap->ROOTDIR,
|
Yap_ROOTDIR = sel(true, iap->ROOTDIR != NULL, iap->ROOTDIR, true,
|
||||||
true,
|
|
||||||
#if __ANDROID__
|
#if __ANDROID__
|
||||||
NULL,
|
NULL,
|
||||||
#else
|
#else
|
||||||
join(getenv("DESTDIR"),YAP_ROOTDIR, NULL),
|
join(getenv("DESTDIR"), YAP_ROOTDIR),
|
||||||
#endif
|
#endif
|
||||||
false
|
false);
|
||||||
);
|
|
||||||
/// BINDIR: where the OS stores header files, namely libYap...
|
/// BINDIR: where the OS stores header files, namely libYap...
|
||||||
Yap_BINDIR = sel(true,
|
Yap_BINDIR = sel(true, iap->BINDIR != NULL, iap->BINDIR, true,
|
||||||
iap->BINDIR != NULL, iap->BINDIR,
|
|
||||||
true,
|
|
||||||
#if __ANDROID__
|
#if __ANDROID__
|
||||||
NULL,
|
NULL,
|
||||||
#else
|
#else
|
||||||
join(getenv("DESTDIR"),YAP_BINDIR, NULL),
|
join(getenv("DESTDIR"), YAP_BINDIR),
|
||||||
#endif
|
#endif
|
||||||
false);
|
false);
|
||||||
/// LIBDIR: where the OS stores dynamic libraries, namely libYap...
|
/// LIBDIR: where the OS stores dynamic libraries, namely libYap...
|
||||||
Yap_LIBDIR = sel(true,
|
Yap_LIBDIR = sel(true, iap->LIBDIR != NULL, iap->LIBDIR, true,
|
||||||
iap->LIBDIR != NULL, iap->LIBDIR,
|
|
||||||
true,
|
|
||||||
#if __ANDROID__
|
#if __ANDROID__
|
||||||
NULL,
|
NULL,
|
||||||
#else
|
#else
|
||||||
join(getenv("DESTDIR"),YAP_LIBDIR,NULL),
|
join(getenv("DESTDIR"), YAP_LIBDIR),
|
||||||
#endif
|
#endif
|
||||||
false);
|
false);
|
||||||
/// DLLDIR: where libraries can find expicitely loaded DLLs
|
/// DLLDIR: where libraries can find expicitely loaded DLLs
|
||||||
Yap_DLLDIR = sel(true,
|
Yap_DLLDIR = sel(true, iap->DLLDIR != NULL, iap->DLLDIR, true,
|
||||||
iap->DLLDIR != NULL, iap->DLLDIR,
|
|
||||||
true,
|
|
||||||
#if __ANDROID__
|
#if __ANDROID__
|
||||||
NULL
|
NULL
|
||||||
#else
|
#else
|
||||||
join(getenv("DESTDIR"),YAP_DLLDIR, NULL),
|
join(getenv("DESTDIR"), YAP_DLLDIR),
|
||||||
#endif
|
#endif
|
||||||
false);
|
false);
|
||||||
/// INCLUDEDIR: where the OS stores header files, namely libYap...
|
/// INCLUDEDIR: where the OS stores header files, namely libYap...
|
||||||
Yap_INCLUDEDIR = sel(true,
|
Yap_INCLUDEDIR = sel(true, iap->INCLUDEDIR != NULL, iap->INCLUDEDIR, true,
|
||||||
iap->INCLUDEDIR != NULL, iap->INCLUDEDIR,
|
|
||||||
true,
|
|
||||||
#if __ANDROID__
|
#if __ANDROID__
|
||||||
NULL,
|
NULL,
|
||||||
#else
|
#else
|
||||||
join(getenv("DESTDIR"),YAP_INCLUDEDIR, NULL),
|
join(getenv("DESTDIR"), YAP_INCLUDEDIR),
|
||||||
#endif
|
#endif
|
||||||
false);
|
false);
|
||||||
/// SHAREDIR: where OS & ARCH independent files live
|
/// SHAREDIR: where OS & ARCH independent files live
|
||||||
Yap_SHAREDIR = sel(true,
|
Yap_SHAREDIR = sel(true, iap->SHAREDIR != NULL, iap->SHAREDIR, true,
|
||||||
iap->SHAREDIR != NULL, iap->SHAREDIR,
|
|
||||||
true,
|
|
||||||
#if __ANDROID__
|
#if __ANDROID__
|
||||||
"/assets",
|
"/assets",
|
||||||
#else
|
#else
|
||||||
join(getenv("DESTDIR"),YAP_SHAREDIR, NULL),
|
join(getenv("DESTDIR"), YAP_SHAREDIR),
|
||||||
#endif
|
#endif
|
||||||
false);
|
false);
|
||||||
/// PLDIR: where we can find Prolog files
|
/// PLDIR: where we can find Prolog files
|
||||||
Yap_PLDIR = sel(true,
|
Yap_PLDIR = sel(true, iap->PLDIR != NULL, iap->PLDIR, true,
|
||||||
iap->PLDIR != NULL, iap->PLDIR,
|
|
||||||
true,
|
|
||||||
#if __ANDROID__
|
#if __ANDROID__
|
||||||
"/assets/Yap",
|
"/assets/Yap",
|
||||||
#else
|
#else
|
||||||
join(getenv("DESTDIR"),YAP_PLDIR, NULL),
|
join(getenv("DESTDIR"), YAP_PLDIR),
|
||||||
#endif
|
#endif
|
||||||
false);
|
false);
|
||||||
/// ``COMMONSDIR: Prolog Commons
|
/// ``COMMONSDIR: Prolog Commons
|
||||||
Yap_COMMONSDIR = sel(true,
|
Yap_COMMONSDIR = sel(true, iap->COMMONSDIR != NULL, iap->COMMONSDIR, true,
|
||||||
iap->COMMONSDIR != NULL, iap->COMMONSDIR,
|
|
||||||
true,
|
|
||||||
#if __ANDROID__
|
#if __ANDROID__
|
||||||
"/assets/PrologCommons",
|
"/assets/PrologCommons",
|
||||||
#else
|
#else
|
||||||
join(getenv("DESTDIR"),YAP_SHAREDIR "/PrologCommons", NULL),
|
join(getenv("DESTDIR"), YAP_SHAREDIR "/PrologCommons"),
|
||||||
#endif
|
#endif
|
||||||
false);
|
false);
|
||||||
/// BOOTPLDIR: where we can find Prolog bootstrap files
|
/// BOOTPLDIR: where we can find Prolog bootstrap files
|
||||||
Yap_BOOTSTRAP = sel(true,
|
Yap_BOOTSTRAP = sel(true, iap->BOOTSTRAP != NULL, iap->BOOTSTRAP, true,
|
||||||
iap->BOOTSTRAP != NULL, iap->BOOTSTRAP,
|
|
||||||
true,
|
|
||||||
#if __ANDROID__
|
#if __ANDROID__
|
||||||
"/assets/Yap/pl",
|
"/assets/Yap/pl",
|
||||||
#else
|
#else
|
||||||
join(getenv("DESTDIR"),YAP_BOOTSTRAP, NULL),
|
join(getenv("DESTDIR"), YAP_BOOTSTRAP),
|
||||||
#endif
|
#endif
|
||||||
false);
|
false);
|
||||||
/// BOOTFILE: where we can find the core Prolog bootstrap file
|
/// BOOTFILE: where we can find the core Prolog bootstrap file
|
||||||
Yap_BOOTFILE = sel(false,
|
Yap_BOOTFILE = sel(false, iap->BOOTFILE != NULL, iap->BOOTFILE, true,
|
||||||
iap->BOOTFILE != NULL, iap->BOOTFILE,
|
|
||||||
true,
|
|
||||||
#if __ANDROID__
|
#if __ANDROID__
|
||||||
"/assets/Yap/pl/boot.yap",
|
"/assets/Yap/pl/boot.yap",
|
||||||
#else
|
#else
|
||||||
join(getenv("DESTDIR"),YAP_BOOTFILE, NULL),
|
join(getenv("DESTDIR"), YAP_BOOTFILE),
|
||||||
#endif
|
#endif
|
||||||
false);
|
false);
|
||||||
/// STARTUP: where we can find the core Prolog bootstrap file
|
/// STARTUP: where we can find the core Prolog bootstrap file
|
||||||
Yap_OUTPUT_STARTUP = sel(false,
|
Yap_OUTPUT_STARTUP =
|
||||||
iap->OUTPUT_STARTUP != NULL, iap->OUTPUT_STARTUP,
|
sel(false, iap->OUTPUT_STARTUP != NULL, iap->OUTPUT_STARTUP, true,
|
||||||
true,
|
|
||||||
#if __ANDROID__
|
#if __ANDROID__
|
||||||
NULL,
|
NULL,
|
||||||
#else
|
#else
|
||||||
join(getenv("DESTDIR"),YAP_OUTPUT_STARTUP,NULL),
|
join(getenv("DESTDIR"), YAP_OUTPUT_STARTUP),
|
||||||
#endif
|
#endif
|
||||||
false);
|
false);
|
||||||
Yap_INPUT_STARTUP = sel(false,
|
Yap_INPUT_STARTUP =
|
||||||
iap->INPUT_STARTUP != NULL, iap->INPUT_STARTUP,
|
sel(false, iap->INPUT_STARTUP != NULL, iap->INPUT_STARTUP, true,
|
||||||
true,
|
|
||||||
#if __ANDROID__
|
#if __ANDROID__
|
||||||
NULL,
|
NULL,
|
||||||
#else
|
#else
|
||||||
join(getenv("DESTDIR"),YAP_INPUT_STARTUP,NULL),
|
join(getenv("DESTDIR"), YAP_INPUT_STARTUP),
|
||||||
#endif
|
#endif
|
||||||
false);
|
false);
|
||||||
if (Yap_ROOTDIR)
|
if (Yap_ROOTDIR)
|
||||||
@ -1017,7 +983,6 @@ static YAP_file_type_t end_init(YAP_init_args *yap_init, YAP_file_type_t rc) {
|
|||||||
CurrentModule = cm;
|
CurrentModule = cm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* this routine is supposed to be called from an external program
|
/* this routine is supposed to be called from an external program
|
||||||
that wants to control Yap */
|
that wants to control Yap */
|
||||||
|
|
||||||
@ -1058,8 +1023,10 @@ X_API YAP_file_type_t YAP_Init(YAP_init_args *yap_init) {
|
|||||||
Yap_ExecutionMode = yap_init->ExecutionMode;
|
Yap_ExecutionMode = yap_init->ExecutionMode;
|
||||||
Yap_set_locations(yap_init);
|
Yap_set_locations(yap_init);
|
||||||
|
|
||||||
if (!do_bootstrap && Yap_INPUT_STARTUP && yap_init->boot_file_type != YAP_BOOT_PL &&
|
if (!do_bootstrap && Yap_INPUT_STARTUP &&
|
||||||
Yap_SavedInfo(Yap_INPUT_STARTUP, &minfo.Trail, &minfo.Stack, &minfo.Heap) &&
|
yap_init->boot_file_type != YAP_BOOT_PL &&
|
||||||
|
Yap_SavedInfo(Yap_INPUT_STARTUP, &minfo.Trail, &minfo.Stack,
|
||||||
|
&minfo.Heap) &&
|
||||||
Yap_Restore(Yap_INPUT_STARTUP)) {
|
Yap_Restore(Yap_INPUT_STARTUP)) {
|
||||||
setBooleanGlobalPrologFlag(SAVED_PROGRAM_FLAG, true);
|
setBooleanGlobalPrologFlag(SAVED_PROGRAM_FLAG, true);
|
||||||
CurrentModule = LOCAL_SourceModule = USER_MODULE;
|
CurrentModule = LOCAL_SourceModule = USER_MODULE;
|
||||||
|
@ -294,7 +294,7 @@ set(datadir ${CMAKE_INSTALL_PREFIX}/share) #DATADIR})
|
|||||||
set(mandir ${CMAKE_INSTALL_PREFIX}/share/man) #MANDIR})
|
set(mandir ${CMAKE_INSTALL_PREFIX}/share/man) #MANDIR})
|
||||||
set(docdir ${CMAKE_INSTALL_PREFIX}/share/docs) #MANDIR})
|
set(docdir ${CMAKE_INSTALL_PREFIX}/share/docs) #MANDIR})
|
||||||
|
|
||||||
set(libpl ${datarootdir}/Yap)
|
set(libpl ${datadir}/Yap)
|
||||||
|
|
||||||
set(dlls ${libdir}/Yap)
|
set(dlls ${libdir}/Yap)
|
||||||
|
|
||||||
|
@ -458,14 +458,14 @@ bool YAPEngine::mgoal(Term t, Term tmod) {
|
|||||||
CACHE_REGS
|
CACHE_REGS
|
||||||
BACKUP_MACHINE_REGS();
|
BACKUP_MACHINE_REGS();
|
||||||
Term *ts = nullptr;
|
Term *ts = nullptr;
|
||||||
Yap_DebugPlWriteln(tmod);
|
|
||||||
if (IsStringTerm(tmod))
|
if (IsStringTerm(tmod))
|
||||||
tmod = MkAtomTerm(Yap_LookupAtom(StringOfTerm(tmod)));
|
tmod = MkAtomTerm(Yap_LookupAtom(StringOfTerm(tmod)));
|
||||||
PredEntry *ap = (new YAPPredicate(t, tmod, ts, "C++"))->ap;
|
PredEntry *ap = (new YAPPredicate(t, tmod, ts, "C++"))->ap;
|
||||||
Yap_DebugPlWriteln(t);
|
|
||||||
if (ap == nullptr || ap->OpcodeOfPred == UNDEF_OPCODE) {
|
if (ap == nullptr || ap->OpcodeOfPred == UNDEF_OPCODE) {
|
||||||
ap = rewriteUndefEngineQuery(ap, t, tmod);
|
ap = rewriteUndefEngineQuery(ap, t, tmod);
|
||||||
}
|
}
|
||||||
|
if (IsApplTerm(t)) ts = RepAppl(t)+1;
|
||||||
|
else if (IsPairTerm(t)) ts = RepPair(t);
|
||||||
/* legal ap */
|
/* legal ap */
|
||||||
arity_t arity = ap->ArityOfPE;
|
arity_t arity = ap->ArityOfPE;
|
||||||
|
|
||||||
@ -739,12 +739,12 @@ PredEntry *YAPQuery::rewriteUndefQuery() {
|
|||||||
return ap = PredCall;
|
return ap = PredCall;
|
||||||
}
|
}
|
||||||
|
|
||||||
PredEntry *YAPEngine::rewriteUndefEngineQuery(PredEntry *a, Term tgoal,
|
PredEntry *YAPEngine::rewriteUndefEngineQuery(PredEntry *a, Term &tgoal,
|
||||||
Term mod) {
|
Term mod) {
|
||||||
Term ts[2];
|
Term ts[2];
|
||||||
ts[0] = mod;
|
ts[0] = mod;
|
||||||
ts[1] = tgoal;
|
ts[1] = tgoal;
|
||||||
ARG1 = Yap_MkApplTerm(FunctorModule, 2, ts);
|
ARG1 = tgoal = Yap_MkApplTerm(FunctorModule, 2, ts);
|
||||||
//goal = YAPTerm(Yap_MkApplTerm(FunctorMetaCall, 1, &ARG1));
|
//goal = YAPTerm(Yap_MkApplTerm(FunctorMetaCall, 1, &ARG1));
|
||||||
return PredCall;
|
return PredCall;
|
||||||
|
|
||||||
|
@ -217,12 +217,14 @@ public:
|
|||||||
|
|
||||||
inline bool getMaxTrailSize() { return MaxTrailSize; };
|
inline bool getMaxTrailSize() { return MaxTrailSize; };
|
||||||
|
|
||||||
inline void setLibDir(const char *fl) {
|
inline void setPLDIR(const char *fl) {
|
||||||
LIBDIR = (const char *)malloc(strlen(fl) + 1);
|
LIBDIR = (const char *)malloc(strlen(fl) + 1);
|
||||||
strcpy((char *)LIBDIR, fl);
|
strcpy((char *)LIBDIR, fl);
|
||||||
};
|
};
|
||||||
|
|
||||||
inline const char *setINPUT_STARTUP(const char *fl) {
|
inline const char *getPLDIR() { return PLDIR; };
|
||||||
|
|
||||||
|
inline void setINPUT_STARTUP(const char *fl) {
|
||||||
INPUT_STARTUP = (const char *)malloc(strlen(fl) + 1);
|
INPUT_STARTUP = (const char *)malloc(strlen(fl) + 1);
|
||||||
strcpy((char *)INPUT_STARTUP, fl);
|
strcpy((char *)INPUT_STARTUP, fl);
|
||||||
};
|
};
|
||||||
@ -290,7 +292,7 @@ private:
|
|||||||
YAPError yerror;
|
YAPError yerror;
|
||||||
void doInit(YAP_file_type_t BootMode, YAPEngineArgs *cargs);
|
void doInit(YAP_file_type_t BootMode, YAPEngineArgs *cargs);
|
||||||
YAP_dogoalinfo q;
|
YAP_dogoalinfo q;
|
||||||
PredEntry *rewriteUndefEngineQuery(PredEntry *ap, Term t, Term tmod);
|
PredEntry *rewriteUndefEngineQuery(PredEntry *ap, Term &t, Term tmod);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// construct a new engine; may use a variable number of arguments
|
/// construct a new engine; may use a variable number of arguments
|
||||||
|
@ -2002,6 +2002,15 @@ significant byte first (like Motorola and SPARC, unlike Intel). */
|
|||||||
#define YAP_DLLDIR "${YAP_LIBDIR}/Yap"
|
#define YAP_DLLDIR "${YAP_LIBDIR}/Yap"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* run-time boot */
|
||||||
|
#ifndef YAP_INPUT_STARTUP
|
||||||
|
#define YAP_INPUT_STARTUP "${YAP_DLLDIR}/${YAP_STARTUP}"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* init-time boot */
|
||||||
|
#ifndef YAP_OUTPUT_STARTUP
|
||||||
|
#define YAP_OUTPUT_STARTUP "${CMAKE_BINARY_DIR}/${YAP_STARTUP}"
|
||||||
|
#endif
|
||||||
|
|
||||||
/* name of YAP JIT library */
|
/* name of YAP JIT library */
|
||||||
#ifndef YAP_YAPJITLIB
|
#ifndef YAP_YAPJITLIB
|
||||||
@ -2009,17 +2018,17 @@ significant byte first (like Motorola and SPARC, unlike Intel). */
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef YAP_SHAREDIR
|
#ifndef YAP_SHAREDIR
|
||||||
#define YAP_SHAREDIR "${YAP_ROOTDIR}/share"
|
#define YAP_SHAREDIR "${YAP_DATADIR}"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* name of YAP PL library */
|
/* name of YAP PL library */
|
||||||
#ifndef YAP_PLDIR
|
#ifndef YAP_PLDIR
|
||||||
#define YAP_PLDIR "${YAP_SHAREDIR}/Yap"
|
#define YAP_PLDIR "${YAP_PLDIR}"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* name of Commons library */
|
/* name of Commons library */
|
||||||
#ifndef YAP_COMMONSDIR
|
#ifndef YAP_COMMONSDIR
|
||||||
#define YAP COMMONSDIR "${YAP_SHAREDIR}/PrologCommmons"
|
#define YAP COMMONSDIR "${YAP_DATADIR}/PrologCommmons"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -2035,16 +2044,6 @@ significant byte first (like Motorola and SPARC, unlike Intel). */
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* run-time boot */
|
|
||||||
#ifndef YAP_INPUT_STARTUP
|
|
||||||
#define YAP_INPUT_STARTUP "${YAP_DLLDIR}/${YAP_STARTUP}"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* init-time boot */
|
|
||||||
#ifndef YAP_OUTPUT_STARTUP
|
|
||||||
#define YAP_OUTPUT_STARTUP "${CMAKE_BINARY_DIR}/${YAP_STARTUP}"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* HP-UX old socket stuff */
|
/* HP-UX old socket stuff */
|
||||||
#ifndef _XOPEN_SOURCE
|
#ifndef _XOPEN_SOURCE
|
||||||
#cmakedefine _XOPEN_SOURCE "${_XOPEN_SOURCE}"
|
#cmakedefine _XOPEN_SOURCE "${_XOPEN_SOURCE}"
|
||||||
|
@ -37,10 +37,13 @@
|
|||||||
|
|
||||||
#define MAX_ERROR_MSG_SIZE 1024
|
#define MAX_ERROR_MSG_SIZE 1024
|
||||||
|
|
||||||
extern void Yap_InitError__(const char *file, const char *function, int lineno, yap_error_number e, YAP_Term g, ...);
|
extern void
|
||||||
|
Yap_InitError__(const char *file, const char *function, int lineno,
|
||||||
|
yap_error_number e, YAP_Term g, ...);
|
||||||
|
|
||||||
extern struct yami *Yap_Error__(const char *file, const char *function, int lineno,
|
extern struct yami *Yap_Error__(const char *file, const char *function,
|
||||||
yap_error_number err, YAP_Term wheret, ...);
|
int lineno, yap_error_number err,
|
||||||
|
YAP_Term wheret, ...);
|
||||||
|
|
||||||
extern void Yap_ThrowError__(const char *file, const char *function, int lineno,
|
extern void Yap_ThrowError__(const char *file, const char *function, int lineno,
|
||||||
yap_error_number err, YAP_Term wheret, ...)
|
yap_error_number err, YAP_Term wheret, ...)
|
||||||
|
@ -55,7 +55,6 @@ set (LIBRARY_PL
|
|||||||
wgraphs.yap
|
wgraphs.yap
|
||||||
wundgraphs.yap
|
wundgraphs.yap
|
||||||
lam_mpi.yap
|
lam_mpi.yap
|
||||||
ypp.yap
|
|
||||||
ytest.yap
|
ytest.yap
|
||||||
c_alarms.yap
|
c_alarms.yap
|
||||||
flags.yap
|
flags.yap
|
||||||
|
18
os/alias.c
18
os/alias.c
@ -225,6 +225,12 @@ Yap_SetAlias (Atom arg, int sno)
|
|||||||
// replace alias
|
// replace alias
|
||||||
if (aliasp->name == arg) {
|
if (aliasp->name == arg) {
|
||||||
aliasp->alias_stream = sno;
|
aliasp->alias_stream = sno;
|
||||||
|
if (arg == AtomUserIn)
|
||||||
|
LOCAL_c_input_stream = sno;
|
||||||
|
if (arg == AtomUserOut)
|
||||||
|
LOCAL_c_output_stream = sno;
|
||||||
|
if (arg == AtomUserErr)
|
||||||
|
LOCAL_c_error_stream = sno;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
aliasp++;
|
aliasp++;
|
||||||
@ -310,6 +316,18 @@ ExistsAliasForStream (int sno, Atom al)
|
|||||||
|
|
||||||
while (aliasp < aliasp_max) {
|
while (aliasp < aliasp_max) {
|
||||||
if (aliasp->alias_stream == sno && aliasp->name == al) {
|
if (aliasp->alias_stream == sno && aliasp->name == al) {
|
||||||
|
if (al == AtomUserIn) {
|
||||||
|
LOCAL_c_input_stream = StdInStream;
|
||||||
|
aliasp->alias_stream = StdInStream;
|
||||||
|
}
|
||||||
|
if (al == AtomUserOut) {
|
||||||
|
LOCAL_c_output_stream = StdOutStream;
|
||||||
|
aliasp->alias_stream = StdOutStream;
|
||||||
|
}
|
||||||
|
if (al == AtomUserErr) {
|
||||||
|
LOCAL_c_error_stream = StdErrStream;
|
||||||
|
aliasp->alias_stream = StdErrStream;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
aliasp++;
|
aliasp++;
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef enum {
|
typedef enum YAP_encoding {
|
||||||
ENC_OCTET = 0, /// binary files
|
ENC_OCTET = 0, /// binary files
|
||||||
ENC_ISO_LATIN1 = 1, /// US+West Europe
|
ENC_ISO_LATIN1 = 1, /// US+West Europe
|
||||||
ENC_ISO_ASCII = 2, /// US only
|
ENC_ISO_ASCII = 2, /// US only
|
||||||
|
49
os/iopreds.c
49
os/iopreds.c
@ -315,20 +315,40 @@ static void unix_upd_stream_info(StreamDesc *s) {
|
|||||||
s->status |= Seekable_Stream_f;
|
s->status |= Seekable_Stream_f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void default_peek(StreamDesc *st) {
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
else
|
||||||
|
st->stream_wgetc_for_read = st->stream_wgetc;
|
||||||
|
}
|
||||||
|
|
||||||
void Yap_DefaultStreamOps(StreamDesc *st) {
|
void Yap_DefaultStreamOps(StreamDesc *st) {
|
||||||
CACHE_REGS
|
CACHE_REGS
|
||||||
|
|
||||||
st->stream_wputc = put_wchar;
|
st->stream_wputc = put_wchar;
|
||||||
if (st->encoding == ENC_ISO_UTF8)
|
|
||||||
st->stream_wgetc = get_wchar_UTF8;
|
|
||||||
else
|
|
||||||
st->stream_wgetc = get_wchar;
|
st->stream_wgetc = get_wchar;
|
||||||
if (st->vfs) {
|
if (st->vfs) {
|
||||||
st->stream_putc = st->vfs->put_char;
|
st->stream_putc = st->vfs->put_char;
|
||||||
|
st->stream_wputc = st->vfs->put_char;
|
||||||
|
st->stream_getc = st->vfs->get_char;
|
||||||
st->stream_wgetc = st->vfs->get_char;
|
st->stream_wgetc = st->vfs->get_char;
|
||||||
|
default_peek(st);
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
|
if (st->encoding == ENC_ISO_UTF8)
|
||||||
|
st->stream_wgetc = get_wchar_UTF8;
|
||||||
st->stream_putc = FilePutc;
|
st->stream_putc = FilePutc;
|
||||||
st->stream_getc = PlGetc;
|
st->stream_getc = PlGetc;
|
||||||
}
|
|
||||||
if (st->status & Pipe_Stream_f) {
|
if (st->status & Pipe_Stream_f) {
|
||||||
Yap_PipeOps(st);
|
Yap_PipeOps(st);
|
||||||
} else if (st->status & InMemory_Stream_f) {
|
} else if (st->status & InMemory_Stream_f) {
|
||||||
@ -350,11 +370,13 @@ void Yap_DefaultStreamOps(StreamDesc *st) {
|
|||||||
st->stream_getc = Yap_popChar;
|
st->stream_getc = Yap_popChar;
|
||||||
st->stream_wgetc = Yap_popChar;
|
st->stream_wgetc = Yap_popChar;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#if USE_READLINE
|
#if USE_READLINE
|
||||||
if (st->status & Readline_Stream_f) {
|
if (st->status & Readline_Stream_f) {
|
||||||
st->stream_peek = Yap_ReadlinePeekChar;
|
st->stream_peek = Yap_ReadlinePeekChar;
|
||||||
st->stream_wpeek = Yap_ReadlinePeekChar;
|
st->stream_wpeek = Yap_ReadlinePeekChar;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* else {
|
/* else {
|
||||||
st->stream_peek = Yap_peekWithGetc;
|
st->stream_peek = Yap_peekWithGetc;
|
||||||
st->stream_wpeek = Yap_peekWideWithGetwc;
|
st->stream_wpeek = Yap_peekWideWithGetwc;
|
||||||
@ -365,20 +387,7 @@ void Yap_DefaultStreamOps(StreamDesc *st) {
|
|||||||
} */
|
} */
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
default_peek(st);
|
||||||
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;
|
|
||||||
else
|
|
||||||
st->stream_wgetc_for_read = st->stream_wgetc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void InitFileIO(StreamDesc *s) {
|
static void InitFileIO(StreamDesc *s) {
|
||||||
@ -1343,6 +1352,7 @@ do_open(Term file_name, Term t2,
|
|||||||
pop_text_stack(lvl);
|
pop_text_stack(lvl);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
st = &GLOBAL_Stream[sno];
|
st = &GLOBAL_Stream[sno];
|
||||||
st->user_name = file_name;
|
st->user_name = file_name;
|
||||||
// user requested encoding?
|
// user requested encoding?
|
||||||
@ -1503,7 +1513,8 @@ static Int p_file_expansion(USES_REGS1) { /* '$file_expansion'(+File,-Name) */
|
|||||||
}
|
}
|
||||||
int lvl = push_text_stack();
|
int lvl = push_text_stack();
|
||||||
const char *tmp;
|
const char *tmp;
|
||||||
if ((tmp=Yap_AbsoluteFile(RepAtom(AtomOfTerm(file_name))->StrOfAE, false)) == NULL) {
|
if ((tmp = Yap_AbsoluteFile(RepAtom(AtomOfTerm(file_name))->StrOfAE,
|
||||||
|
false)) == NULL) {
|
||||||
pop_text_stack(lvl);
|
pop_text_stack(lvl);
|
||||||
return (PlIOError(EXISTENCE_ERROR_SOURCE_SINK, file_name,
|
return (PlIOError(EXISTENCE_ERROR_SOURCE_SINK, file_name,
|
||||||
"absolute_file_name/3"));
|
"absolute_file_name/3"));
|
||||||
|
@ -1109,7 +1109,6 @@ bool Yap_SetOutputStream( Term sd )
|
|||||||
Yap_CheckStream(sd, Output_Stream_f | Append_Stream_f, "set_output/2");
|
Yap_CheckStream(sd, Output_Stream_f | Append_Stream_f, "set_output/2");
|
||||||
if (sno < 0)
|
if (sno < 0)
|
||||||
return false;
|
return false;
|
||||||
LOCAL_c_output_stream = sno;
|
|
||||||
UNLOCK(GLOBAL_Stream[sno].streamlock);
|
UNLOCK(GLOBAL_Stream[sno].streamlock);
|
||||||
Yap_SetAlias(AtomUserOut, sno);
|
Yap_SetAlias(AtomUserOut, sno);
|
||||||
return true;
|
return true;
|
||||||
|
@ -600,6 +600,7 @@ static Int writeln(USES_REGS1) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int output_stream = Yap_CheckTextStream(ARG1, Output_Stream_f, "writeln/2");
|
int output_stream = Yap_CheckTextStream(ARG1, Output_Stream_f, "writeln/2");
|
||||||
|
fprintf(stderr,"writeln %d\n", output_stream);
|
||||||
if (output_stream < 0) {
|
if (output_stream < 0) {
|
||||||
free(args);
|
free(args);
|
||||||
return false;
|
return false;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
#CHECK: PythonLibs, changed to work in WIN32
|
#CHECK: PythonLibs, changed to work in WIN32
|
||||||
|
|
||||||
set (PYTHON_SOURCES python.c pl2py.c pybips.c py2pl.c pl2pl.c pypreds.c)
|
set (PYTHON_SOURCES python.c pl2py.c pybips.c py2pl.c pl2pl.c pypreds.c pyio.c)
|
||||||
set (PYTHON_HEADERS py4yap.h)
|
set (PYTHON_HEADERS py4yap.h)
|
||||||
set (CMAKE_POSITION_INDEPENDENT_CODE TRUE)
|
set (CMAKE_POSITION_INDEPENDENT_CODE TRUE)
|
||||||
|
|
||||||
|
@ -56,6 +56,8 @@ extern X_API PyObject *yap_to_python(YAP_Term t, bool eval, PyObject *o,
|
|||||||
bool cvt);
|
bool cvt);
|
||||||
extern X_API PyObject *string_to_python(const char *s, bool eval, PyObject *p0);
|
extern X_API PyObject *string_to_python(const char *s, bool eval, PyObject *p0);
|
||||||
typedef YAP_Arity arity_t;
|
typedef YAP_Arity arity_t;
|
||||||
|
extern bool init_python_vfs(void);
|
||||||
|
|
||||||
|
|
||||||
extern atom_t ATOM_true, ATOM_false, ATOM_colon, ATOM_dot, ATOM_none, ATOM_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_comma, ATOM_builtin, ATOM_V, ATOM_A, ATOM_self, ATOM_nil,
|
||||||
|
122
packages/python/pyio.c
Normal file
122
packages/python/pyio.c
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
|
||||||
|
|
||||||
|
#include "py4yap.h"
|
||||||
|
#include <VFS.h>
|
||||||
|
|
||||||
|
#include "YapStreams.h"
|
||||||
|
|
||||||
|
VFS_t pystream;
|
||||||
|
|
||||||
|
static void *py_open(VFS_t *me, int sno, const char *name,
|
||||||
|
const char *io_mode) {
|
||||||
|
#if HAVE_STRCASESTR
|
||||||
|
if (strcasestr(name, "/python/") == name)
|
||||||
|
name += strlen("/python/");
|
||||||
|
#else
|
||||||
|
if (strstr(name, "/python/") == name)
|
||||||
|
name += strlen("/python/");
|
||||||
|
#endif
|
||||||
|
StreamDesc *st = YAP_RepStreamFromId(sno);
|
||||||
|
// we assume object is already open, so there is no need to open it.
|
||||||
|
PyObject *stream = string_to_python(name, true, NULL);
|
||||||
|
if (stream == Py_None)
|
||||||
|
return NULL;
|
||||||
|
Py_INCREF(stream);
|
||||||
|
st->u.private_data = stream;
|
||||||
|
st->vfs = me;
|
||||||
|
st->name = YAP_LookupAtom(name);
|
||||||
|
st->user_name = YAP_MkAtomTerm(st->name);
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool py_close(int sno) { return true; }
|
||||||
|
|
||||||
|
static int py_put(int sno, int ch) {
|
||||||
|
// PyObject *pyw; // buffer
|
||||||
|
// int pyw_kind;
|
||||||
|
// PyObject *pyw_data;
|
||||||
|
// PySys_WriteStdout("%C", ch);
|
||||||
|
// return ch;
|
||||||
|
char s[2];
|
||||||
|
StreamDesc *st = YAP_GetStreamFromId(sno);
|
||||||
|
// PyUnicode_WRITE(pyw_kind, pyw_data, 0, ch);
|
||||||
|
PyObject *err, *fput = PyObject_GetAttrString(st->u.private_data, "write");
|
||||||
|
s[0] = ch;
|
||||||
|
s[1] = '\0';
|
||||||
|
PyObject_CallMethodObjArgs(st->u.private_data, PyUnicode_FromString("write"),
|
||||||
|
PyUnicode_FromString(s), NULL);
|
||||||
|
if ((err = PyErr_Occurred())) {
|
||||||
|
PyErr_SetString(
|
||||||
|
err,
|
||||||
|
"Error in put\n"); // %s:%s:%d!\n", __FILE__, __FUNCTION__, __LINE__);
|
||||||
|
}
|
||||||
|
return ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
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) {
|
||||||
|
StreamDesc *s = YAP_GetStreamFromId(sno);
|
||||||
|
PyObject *fseek = PyObject_GetAttrString(s->u.private_data, "seek");
|
||||||
|
PyObject *pyr = PyObject_CallFunctionObjArgs(fseek, PyLong_FromLong(where),
|
||||||
|
PyLong_FromLong(how), NULL);
|
||||||
|
return PyLong_AsLong(pyr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void py_flush(int sno) {
|
||||||
|
StreamDesc *s = YAP_GetStreamFromId(sno);
|
||||||
|
PyObject *flush = PyObject_GetAttrString(s->u.private_data, "flush");
|
||||||
|
PyObject_CallFunction(flush, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
static void python_output(void) {
|
||||||
|
PyObject *stream = string_to_python("sys.stdout", true, NULL);
|
||||||
|
StreamDesc *st = YAP_GetStreamFromId(1);
|
||||||
|
st->u.private_data = stream;
|
||||||
|
st->vfs = &pystream;
|
||||||
|
stream = string_to_python("sys.stderr", true, NULL);
|
||||||
|
st = YAP_GetStreamFromIds(2);
|
||||||
|
st->u.private_data = stream;
|
||||||
|
st->vfs = &pystream;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static bool initialized = false;
|
||||||
|
|
||||||
|
bool init_python_vfs(void) {
|
||||||
|
// pyw = PyUnicode_FromString("x");
|
||||||
|
// pyw_kind = PyUnicode_KIND(pyw);
|
||||||
|
// pyw_data = PyUnicode_DATA(pyw);
|
||||||
|
if (initialized)
|
||||||
|
return false;
|
||||||
|
initialized = true;
|
||||||
|
pystream.name = "python stream";
|
||||||
|
pystream.vflags =
|
||||||
|
VFS_CAN_WRITE | VFS_CAN_EXEC | VFS_CAN_READ | VFS_HAS_PREFIX;
|
||||||
|
pystream.prefix = "/python/";
|
||||||
|
pystream.suffix = NULL;
|
||||||
|
pystream.open = py_open;
|
||||||
|
pystream.close = py_close;
|
||||||
|
pystream.get_char = py_get;
|
||||||
|
pystream.peek_char = py_peek;
|
||||||
|
pystream.put_char = py_put;
|
||||||
|
pystream.flush = py_flush;
|
||||||
|
pystream.seek = py_seek;
|
||||||
|
pystream.next = GLOBAL_VFS;
|
||||||
|
GLOBAL_VFS = &pystream;
|
||||||
|
// NULL;
|
||||||
|
return true;
|
||||||
|
}
|
@ -680,4 +680,6 @@ install_t install_pypreds(void) {
|
|||||||
PL_register_foreign("python_import", 2, python_import, 0);
|
PL_register_foreign("python_import", 2, python_import, 0);
|
||||||
PL_register_foreign("python_access", 3, python_access, 0);
|
PL_register_foreign("python_access", 3, python_access, 0);
|
||||||
PL_register_foreign("python_threaded", 0, p_python_threaded, 0);
|
PL_register_foreign("python_threaded", 0, p_python_threaded, 0);
|
||||||
|
|
||||||
|
init_python_vfs();
|
||||||
}
|
}
|
||||||
|
@ -25,130 +25,6 @@ X_API PyObject *py_Sys;
|
|||||||
PyObject *py_Context;
|
PyObject *py_Context;
|
||||||
PyObject *py_ModDict;
|
PyObject *py_ModDict;
|
||||||
|
|
||||||
VFS_t pystream;
|
|
||||||
|
|
||||||
static void *
|
|
||||||
py_open(VFS_t *me, int sno, const char *name,
|
|
||||||
const char *io_mode) {
|
|
||||||
#if HAVE_STRCASESTR
|
|
||||||
if (strcasestr(name, "/python/") == name)
|
|
||||||
name += strlen("/python/");
|
|
||||||
#else
|
|
||||||
if (strstr(name, "/python/") == name)
|
|
||||||
name += strlen("/python/");
|
|
||||||
#endif
|
|
||||||
StreamDesc *st = YAP_RepStreamFromId(sno);
|
|
||||||
fprintf(stderr,"opened %d\n", sno);
|
|
||||||
// we assume object is already open, so there is no need to open it.
|
|
||||||
PyObject *stream = string_to_python(name, true, NULL);
|
|
||||||
if (stream == Py_None)
|
|
||||||
return NULL;
|
|
||||||
Py_INCREF(stream);
|
|
||||||
st->u.private_data = stream;
|
|
||||||
st->vfs = me;
|
|
||||||
if (strchr(io_mode,'r'))
|
|
||||||
st->status = Input_Stream_f;
|
|
||||||
else
|
|
||||||
st->status = Append_Stream_f | Output_Stream_f;
|
|
||||||
Yap_DefaultStreamOps(st);
|
|
||||||
return stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
|
||||||
py_close(int sno) {
|
|
||||||
return true;
|
|
||||||
StreamDesc *s = YAP_GetStreamFromId(sno);
|
|
||||||
PyObject *fclose = PyObject_GetAttrString(s->u.private_data, "close");
|
|
||||||
PyObject *rc = PyObject_CallObject(fclose, NULL);
|
|
||||||
bool v = (rc == Py_True);
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
py_put(int sno, int ch) {
|
|
||||||
// PyObject *pyw; // buffer
|
|
||||||
// int pyw_kind;
|
|
||||||
// PyObject *pyw_data;
|
|
||||||
|
|
||||||
char s[2];
|
|
||||||
StreamDesc *st = YAP_GetStreamFromId(sno);
|
|
||||||
// PyUnicode_WRITE(pyw_kind, pyw_data, 0, ch);
|
|
||||||
PyObject *err, *fput = PyObject_GetAttrString(st->u.private_data, "write");
|
|
||||||
s[0] = ch;
|
|
||||||
s[1] = '\0';
|
|
||||||
PyObject_CallFunctionObjArgs(fput, PyBytes_FromString(s), NULL);
|
|
||||||
if ((err = PyErr_Occurred())) {
|
|
||||||
PyErr_SetString(
|
|
||||||
err,
|
|
||||||
"Error in put\n"); // %s:%s:%d!\n", __FILE__, __FUNCTION__, __LINE__);
|
|
||||||
}
|
|
||||||
return ch;
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
|
||||||
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) {
|
|
||||||
StreamDesc *s = YAP_GetStreamFromId(sno);
|
|
||||||
PyObject *fseek = PyObject_GetAttrString(s->u.private_data, "seek");
|
|
||||||
PyObject *pyr = PyObject_CallFunctionObjArgs(fseek, PyLong_FromLong(where),
|
|
||||||
PyLong_FromLong(how), NULL);
|
|
||||||
return PyLong_AsLong(pyr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void py_flush(int sno) {
|
|
||||||
StreamDesc *s = YAP_GetStreamFromId(sno);
|
|
||||||
PyObject *flush = PyObject_GetAttrString(s->u.private_data, "flush");
|
|
||||||
PyObject_CallFunction(flush, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
static void python_output(void) {
|
|
||||||
PyObject *stream = string_to_python("sys.stdout", true, NULL);
|
|
||||||
StreamDesc *st = YAP_GetStreamFromId(1);
|
|
||||||
st->u.private_data = stream;
|
|
||||||
st->vfs = &pystream;
|
|
||||||
stream = string_to_python("sys.stderr", true, NULL);
|
|
||||||
st = YAP_GetStreamFromIds(2);
|
|
||||||
st->u.private_data = stream;
|
|
||||||
st->vfs = &pystream;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static bool init_python_stream(void) {
|
|
||||||
// pyw = PyUnicode_FromString("x");
|
|
||||||
// pyw_kind = PyUnicode_KIND(pyw);
|
|
||||||
// pyw_data = PyUnicode_DATA(pyw);
|
|
||||||
|
|
||||||
pystream.name = "python stream";
|
|
||||||
pystream.vflags =
|
|
||||||
VFS_CAN_WRITE | VFS_CAN_EXEC | VFS_CAN_READ | VFS_HAS_PREFIX;
|
|
||||||
pystream.prefix = "/python/";
|
|
||||||
pystream.suffix = NULL;
|
|
||||||
pystream.open = py_open;
|
|
||||||
pystream.close = py_close;
|
|
||||||
pystream.get_char = py_get;
|
|
||||||
pystream.peek_char = py_peek;
|
|
||||||
pystream.put_char = py_put;
|
|
||||||
pystream.flush = py_flush;
|
|
||||||
pystream.seek = py_seek;
|
|
||||||
pystream.next = GLOBAL_VFS;
|
|
||||||
GLOBAL_VFS = &pystream;
|
|
||||||
// NULL;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
X_API PyObject *Py_f2p;
|
X_API PyObject *Py_f2p;
|
||||||
|
|
||||||
extern X_API bool python_in_python;
|
extern X_API bool python_in_python;
|
||||||
@ -170,7 +46,7 @@ static void add_modules(void) {
|
|||||||
Py_f2p = PythonLookup("f2p", NULL);
|
Py_f2p = PythonLookup("f2p", NULL);
|
||||||
if (Py_f2p)
|
if (Py_f2p)
|
||||||
Py_INCREF(Py_f2p);
|
Py_INCREF(Py_f2p);
|
||||||
init_python_stream();
|
init_python_vfs();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void install_py_constants(void) {
|
static void install_py_constants(void) {
|
||||||
|
@ -31,10 +31,6 @@
|
|||||||
release_GIL/0,
|
release_GIL/0,
|
||||||
python_threaded/0,
|
python_threaded/0,
|
||||||
prolog_list_to_python_list/3,
|
prolog_list_to_python_list/3,
|
||||||
(:=)/2,
|
|
||||||
(:=)/1,
|
|
||||||
% (<-)/2,
|
|
||||||
% (<-)/1,
|
|
||||||
op(100,fy,$),
|
op(100,fy,$),
|
||||||
op(950,fy,:=),
|
op(950,fy,:=),
|
||||||
op(950,yfx,:=),
|
op(950,yfx,:=),
|
||||||
@ -114,41 +110,60 @@ Data types are
|
|||||||
:- use_module(library(charsio)).
|
:- use_module(library(charsio)).
|
||||||
:- dynamic python_mref_cache/2, python_obj_cache/2.
|
:- dynamic python_mref_cache/2, python_obj_cache/2.
|
||||||
|
|
||||||
|
:- multifile user:(:=)/2,
|
||||||
|
user:(:=)/1,
|
||||||
|
user:(<-)/1,
|
||||||
|
user:(<-)/2, user:'()'/1, user:'{}'/1, user:dot_qualified_goal/2, user:import_arg/1.
|
||||||
|
|
||||||
|
|
||||||
|
import( F ) :- catch( python:python_import(F), _, fail ).
|
||||||
|
|
||||||
|
user:dot_qualified_goal(Fs) :- catch( python:python_proc(Fs), _, fail ).
|
||||||
|
|
||||||
|
user:F() :-
|
||||||
|
catch( python:python_proc(F() ), _, fail ).
|
||||||
|
|
||||||
|
|
||||||
|
user(P1,P2) :- !,
|
||||||
|
:= P1,
|
||||||
|
:= P2.
|
||||||
|
|
||||||
|
:= F :- catch( python:python_proc(F), _, fail ).
|
||||||
|
|
||||||
:= (P1,P2) :- !,
|
:= (P1,P2) :- !,
|
||||||
:= P1,
|
:= P1,
|
||||||
:= P2.
|
:= P2.
|
||||||
:= import( F ) :- !, python_import(F).
|
|
||||||
:= F :- python_proc(F).
|
|
||||||
|
|
||||||
V <- F :-
|
user:(:= ) :- catch( python:python_proc(F), _, fail ).
|
||||||
|
|
||||||
|
user:( V := F ) :-
|
||||||
|
python:python_assign(F, V).
|
||||||
|
|
||||||
|
user:(<- F) :-
|
||||||
|
catch( python:python_proc(F), _, fail ).
|
||||||
|
|
||||||
|
user:(V <- F) :-
|
||||||
V := F.
|
V := F.
|
||||||
|
|
||||||
( V := F ) :-
|
python:python_import(Module) :-
|
||||||
python_assign(F, V).
|
python:python_import(Module, _).
|
||||||
|
|
||||||
((<- F)) :-
|
|
||||||
:= F.
|
|
||||||
|
|
||||||
python_import(Module) :-
|
|
||||||
python_import(Module, _).
|
|
||||||
|
|
||||||
|
|
||||||
python(Exp, Out) :-
|
python(Exp, Out) :-
|
||||||
Out := Exp.
|
Out := Exp.
|
||||||
|
|
||||||
python_command(Cmd) :-
|
python_command(Cmd) :-
|
||||||
python_run_command(Cmd).
|
python:python_run_command(Cmd).
|
||||||
|
|
||||||
|
|
||||||
start_python :-
|
start_python :-
|
||||||
python_import('inspect', _),
|
python:python_import('inspect', _),
|
||||||
at_halt(end_python).
|
at_halt(end_python).
|
||||||
|
|
||||||
add_cwd_to_python :-
|
add_cwd_to_python :-
|
||||||
unix(getcwd(Dir)),
|
unix(getcwd(Dir)),
|
||||||
atom_concat(['sys.path.append(\"',Dir,'\")'], Command),
|
atom_concat(['sys.path.append(\"',Dir,'\")'], Command),
|
||||||
python_command(Command),
|
python:python_command(Command),
|
||||||
python_command("sys.argv = [\"yap\"]").
|
python:python_command("sys.argv = [\"yap\"]").
|
||||||
% done
|
% done
|
||||||
|
|
||||||
:- initialization( load_foreign_files(['YAPPython'], [], init_python_dll), now ).
|
:- initialization( load_foreign_files(['YAPPython'], [], init_python_dll), now ).
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
%% @file yapi.yap
|
%% @file yapi.yap
|
||||||
%% @brief support yap shell
|
%% @brief support yap shell
|
||||||
%%
|
%%
|
||||||
:- start_low_level_trace.
|
%:- start_low_level_trace.
|
||||||
:- module(yapi, [
|
:- module(yapi, [
|
||||||
python_ouput/0,
|
python_ouput/0,
|
||||||
show_answer/2,
|
show_answer/2,
|
||||||
@ -60,7 +60,8 @@ argi(N,I,I1) :-
|
|||||||
atomic_concat(`A`,I,N),
|
atomic_concat(`A`,I,N),
|
||||||
I1 is I+1.
|
I1 is I+1.
|
||||||
|
|
||||||
python_query( Self, String ) :-
|
python_query( Caller, String ) :-
|
||||||
|
Self := Caller.it,
|
||||||
atomic_to_term( String, Goal, VarNames ),
|
atomic_to_term( String, Goal, VarNames ),
|
||||||
query_to_answer( Goal, VarNames, Status, Bindings),
|
query_to_answer( Goal, VarNames, Status, Bindings),
|
||||||
Self.port := Status,
|
Self.port := Status,
|
||||||
|
@ -18,11 +18,11 @@ class Engine( YAPEngine ):
|
|||||||
if self_contained:
|
if self_contained:
|
||||||
yap_lib_path = os.path.dirname(__file__)
|
yap_lib_path = os.path.dirname(__file__)
|
||||||
args.setYapShareDir(os.path.join(yap_lib_path, "prolog"))
|
args.setYapShareDir(os.path.join(yap_lib_path, "prolog"))
|
||||||
args.setYapLibDir(yap_lib_path)
|
args.setYapPLDIR(yap_lib_path)
|
||||||
args.setSavedState(os.path.join(yap_lib_path, "startup.yss"))
|
args.setSavedState(os.path.join(yap_lib_path, "startup.yss"))
|
||||||
YAPEngine.__init__(self, args)
|
YAPEngine.__init__(self, args)
|
||||||
self.goal(set_prolog_flag('verbose', 'silent'))
|
self.goal(set_prolog_flag('verbose', 'silent'))
|
||||||
self.goal(use_module(library('yapi')))
|
self.goal(compile(library('yapi')))
|
||||||
self.goal(set_prolog_flag('verbose', 'normal'))
|
self.goal(set_prolog_flag('verbose', 'normal'))
|
||||||
|
|
||||||
def run(self, g, m=None):
|
def run(self, g, m=None):
|
||||||
@ -49,19 +49,22 @@ class Predicate( YAPPredicate ):
|
|||||||
|
|
||||||
class Goal(object):
|
class Goal(object):
|
||||||
"""Goal is a predicate instantiated under a specific environment """
|
"""Goal is a predicate instantiated under a specific environment """
|
||||||
def __init__(self, g, engine, module="user",program=None, max_answers=None ):
|
def __init__(self, engine, g):
|
||||||
self.g = g
|
self.q = engine.query(g)
|
||||||
self.e = engine
|
self.e = engine
|
||||||
|
self.port = "call"
|
||||||
|
self.bindings = None
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
return PrologTableIter( self.e, self.g )
|
return PrologTableIter( self.e, self )
|
||||||
|
|
||||||
class PrologTableIter:
|
class PrologTableIter:
|
||||||
|
|
||||||
def __init__(self, e, query):
|
def __init__(self, e, g):
|
||||||
try:
|
try:
|
||||||
self.e = e
|
self.e = e
|
||||||
self.q = e.query(python_query(self, query))
|
self.g = g
|
||||||
|
self.q = g.q
|
||||||
except:
|
except:
|
||||||
print('Error')
|
print('Error')
|
||||||
|
|
||||||
@ -74,8 +77,8 @@ class PrologTableIter:
|
|||||||
if not self.q:
|
if not self.q:
|
||||||
raise StopIteration()
|
raise StopIteration()
|
||||||
if self.q.next():
|
if self.q.next():
|
||||||
rc = self.q.bindings
|
rc = self.g.bindings
|
||||||
if self.q.port == "exit":
|
if self.g.port == "exit":
|
||||||
self.close()
|
self.close()
|
||||||
return rc
|
return rc
|
||||||
else:
|
else:
|
||||||
@ -98,7 +101,7 @@ global engine, handler
|
|||||||
|
|
||||||
yap_lib_path = os.path.dirname(__file__)
|
yap_lib_path = os.path.dirname(__file__)
|
||||||
|
|
||||||
use_module = namedtuple('use_module', 'file')
|
compile = namedtuple('compile', 'file')
|
||||||
bindvars = namedtuple('bindvars', 'list')
|
bindvars = namedtuple('bindvars', 'list')
|
||||||
library = namedtuple('library', 'list')
|
library = namedtuple('library', 'list')
|
||||||
v = namedtuple( 'v', 'slot')
|
v = namedtuple( 'v', 'slot')
|
||||||
@ -153,7 +156,7 @@ class YAPShell:
|
|||||||
|
|
||||||
|
|
||||||
def query_prolog(self, engine, query):
|
def query_prolog(self, engine, query):
|
||||||
import pdb; pdb.set_trace()
|
#import pdb; pdb.set_trace()
|
||||||
#
|
#
|
||||||
# construct a query from a one-line string
|
# construct a query from a one-line string
|
||||||
# q is opaque to Python
|
# q is opaque to Python
|
||||||
@ -174,8 +177,9 @@ class YAPShell:
|
|||||||
do_ask = True
|
do_ask = True
|
||||||
self.e = engine
|
self.e = engine
|
||||||
bindings = []
|
bindings = []
|
||||||
|
g = python_query(self, query)
|
||||||
if not self.q:
|
if not self.q:
|
||||||
self.it = PrologTableIter( self.e, query )
|
self.it = Goal( engine, g )
|
||||||
for bind in self.it:
|
for bind in self.it:
|
||||||
bindings += [bind]
|
bindings += [bind]
|
||||||
if do_ask:
|
if do_ask:
|
||||||
|
@ -37,15 +37,15 @@ from distutils.core import setup
|
|||||||
|
|
||||||
pjoin = os.path.join
|
pjoin = os.path.join
|
||||||
here = os.path.abspath(os.path.dirname(__file__))
|
here = os.path.abspath(os.path.dirname(__file__))
|
||||||
packages = []
|
packages = ['yap_kernel','yap_ipython']
|
||||||
# pkg_root = pjoin(here, name)
|
# pkg_root = pjoin(here, name)
|
||||||
|
|
||||||
for d, _, _ in os.walk(pjoin(here, 'yap_kernel')):
|
# for d, _, _ in os.walk(pjoin(here, 'yap_kernel')):
|
||||||
if os.path.exists(pjoin(d, '__init__.py')):
|
# if os.path.exists(pjoin(d, '__init__.py')):
|
||||||
packages.append(d[len(here)+1:].replace(os.path.sep, '.'))
|
# packages.append(d[len(here)+1:].replace(os.path.sep, '.'))
|
||||||
for d, _, _ in os.walk(pjoin(here, 'yap_ipython')):
|
# for d, _, _ in os.walk(pjoin(here, 'yap_ipython')):
|
||||||
if os.path.exists(pjoin(d, '__init__.py')):
|
# if os.path.exists(pjoin(d, '__init__.py')):
|
||||||
packages.append(d[len(here)+1:].replace(os.path.sep, '.'))
|
# packages.append(d[len(here)+1:].replace(os.path.sep, '.'))
|
||||||
|
|
||||||
sys.path.insert(0, here)
|
sys.path.insert(0, here)
|
||||||
package_data = {
|
package_data = {
|
||||||
|
@ -2324,8 +2324,8 @@ class InteractiveShell(SingletonConfigurable):
|
|||||||
Command to execute (can not end in '&', as background processes are
|
Command to execute (can not end in '&', as background processes are
|
||||||
not supported.
|
not supported.
|
||||||
split : bool, optional
|
split : bool, optional
|
||||||
If True, split the output into an yap_ipython SList. Otherwise, an
|
If True, split the output into an IPython SList. Otherwise, an
|
||||||
yap_ipython LSString is returned. These are objects similar to normal
|
ipython LSString is returned. These are objects similar to normal
|
||||||
lists and strings, with a few convenience attributes for easier
|
lists and strings, with a few convenience attributes for easier
|
||||||
manipulation of line-based output. You can use '?' on them for
|
manipulation of line-based output. You can use '?' on them for
|
||||||
details.
|
details.
|
||||||
@ -2598,7 +2598,7 @@ class InteractiveShell(SingletonConfigurable):
|
|||||||
with prepended_to_syspath(dname):
|
with prepended_to_syspath(dname):
|
||||||
try:
|
try:
|
||||||
for cell in get_cells():
|
for cell in get_cells():
|
||||||
result = self.run_cell(cell, silent=True, shell_futures=shell_futures)
|
result = self.run_cell(cell, silent=False , shell_futures=shell_futures)
|
||||||
if raise_exceptions:
|
if raise_exceptions:
|
||||||
result.raise_error()
|
result.raise_error()
|
||||||
elif not result.success:
|
elif not result.success:
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @file jupyter.yap
|
* @file jupyter.yap
|
||||||
*
|
*
|
||||||
@ -20,30 +21,30 @@
|
|||||||
%% ).
|
%% ).
|
||||||
|
|
||||||
|
|
||||||
%:- reexport(library(yapi)).
|
:- reexport(library(yapi)).
|
||||||
:- use_module(library(lists)).
|
:- use_module(library(lists)).
|
||||||
:- use_module(library(maplist)).
|
:- use_module(library(maplist)).
|
||||||
:- use_module(library(python)).
|
:- use_module(library(python)).
|
||||||
|
|
||||||
:- python_import(sys).
|
:- python_import(sys).
|
||||||
|
|
||||||
jupyter_query(Self, Cell, Line ) :-
|
jupyter_query(Caller, Cell, Line ) :-
|
||||||
start_low_level_trace,
|
jupyter_cell(Caller, Cell, Line).
|
||||||
setup_call_cleanup(
|
|
||||||
enter_cell(Self),
|
|
||||||
jupyter_cell(Self, Cell, Line),
|
|
||||||
exit_cell(Self)
|
|
||||||
).
|
|
||||||
|
|
||||||
jupyter_cell(_Self, Cell, _) :-
|
jupyter_cell(_Caller, Cell, _) :-
|
||||||
jupyter_consult(Cell),
|
jupyter_consult(Cell),
|
||||||
fail.
|
fail.
|
||||||
jupyter_cell( _Self, _, Line ) :-
|
jupyter_cell( _Caller, _, Line ) :-
|
||||||
blank( Line ),
|
blank( Line ),
|
||||||
!.
|
!.
|
||||||
jupyter_cell( _Self, _, [] ) :- !.
|
jupyter_cell( _Caller, _, [] ) :- !.
|
||||||
jupyter_cell( Self, _, Line ) :-
|
jupyter_cell( Caller, _, Line ) :-
|
||||||
python_query( Self, Line ).
|
gated_call(
|
||||||
|
enter_cell(call),
|
||||||
|
python_query( Caller, Line ),
|
||||||
|
Port,
|
||||||
|
enter_cell(Port)
|
||||||
|
).
|
||||||
|
|
||||||
jupyter_consult(Text) :-
|
jupyter_consult(Text) :-
|
||||||
blank( Text ),
|
blank( Text ),
|
||||||
@ -61,18 +62,31 @@ blankc(' ').
|
|||||||
blankc('\n').
|
blankc('\n').
|
||||||
blankc('\t').
|
blankc('\t').
|
||||||
|
|
||||||
enter_cell(_Self) :-
|
enter_cell(retry) :-
|
||||||
open('/python/input', read, Input, []),
|
enter_cell(call).
|
||||||
open('/python/sys.stdout', append, Output, []),
|
enter_cell(call) :-
|
||||||
open('/python/sys.stdout', append, Error, []),
|
into_cell.
|
||||||
set_prolog_flag(user_input, Input),
|
enter_cell(fail) :-
|
||||||
set_prolog_flag(user_output, Output),
|
enter_cell(exit).
|
||||||
set_prolog_flag(user_error, Error).
|
enter_cell(answer) :-
|
||||||
|
enter_cell(exit).
|
||||||
|
enter_cell(exception(_)) :-
|
||||||
|
enter_cell(exit).
|
||||||
|
enter_cell(external_exception(_)).
|
||||||
|
enter_cell(!).
|
||||||
|
enter_cell(exit) :-
|
||||||
|
nb_setval(jupyter_cell, off),
|
||||||
|
close( user_output).
|
||||||
|
|
||||||
exit_cell(_Self) :-
|
|
||||||
close( user_input),
|
into_cell :-
|
||||||
close( user_output),
|
nb_setval(jupyter_cell, on),
|
||||||
close( user_error).
|
open('/python/sys.input', read, _Input, [bom(false)]),
|
||||||
|
open('/python/sys.stdout', append, _Output, []),
|
||||||
|
open('/python/sys.stderr', append, _Error, []),
|
||||||
|
set_prolog_flag(user_input,_Output),
|
||||||
|
set_prolog_flag(user_output,_Output),
|
||||||
|
set_prolog_flag(user_error,_Error).
|
||||||
|
|
||||||
|
|
||||||
completions(S, Self) :-
|
completions(S, Self) :-
|
||||||
@ -188,14 +202,14 @@ errors( Self, Text ) :-
|
|||||||
close_events( Self )
|
close_events( Self )
|
||||||
).
|
).
|
||||||
|
|
||||||
clauses(Self, Stream) :-
|
clauses(_Self, Stream) :-
|
||||||
repeat,
|
repeat,
|
||||||
read_clause(Stream, Cl, [term_position(_Pos), syntax_errors(fail)] ),
|
read_clause(Stream, Cl, [term_position(_Pos), syntax_errors(fail)] ),
|
||||||
% command( Self, Cl ),
|
% command( Self, Cl ),
|
||||||
Cl == end_of_file,
|
Cl == end_of_file,
|
||||||
!.
|
!.
|
||||||
|
|
||||||
goals(Self, Stream) :-
|
goals(_Self, Stream) :-
|
||||||
repeat,
|
repeat,
|
||||||
read_term(Stream, Cl, [term_position(_Pos), syntax_errors(fail)] ),
|
read_term(Stream, Cl, [term_position(_Pos), syntax_errors(fail)] ),
|
||||||
% command( Self, Cl ),
|
% command( Self, Cl ),
|
||||||
@ -271,4 +285,4 @@ close_events( Self ) :-
|
|||||||
fail.
|
fail.
|
||||||
close_events( _ ).
|
close_events( _ ).
|
||||||
|
|
||||||
:- ( start_low_level_trace ).
|
%:- ( start_low_level_trace ).
|
||||||
|
@ -9,20 +9,21 @@ from typing import Iterator, List, Tuple, Iterable, Union
|
|||||||
from traitlets import Bool, Enum, observe, Int
|
from traitlets import Bool, Enum, observe, Int
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from yap4py.yapi import Engine
|
from yap4py.yapi import Engine, Goal, EngineArgs, PrologTableIter
|
||||||
except:
|
except:
|
||||||
print("Could not load _yap dll.")
|
print("Could not load _yap dll.")
|
||||||
from yap_ipython.core import interactiveshell
|
|
||||||
from yap_ipython.core.completer import Completer, Completion
|
from yap_ipython.core.completer import Completer, Completion
|
||||||
from yap_ipython.utils.strdispatch import StrDispatch
|
from yap_ipython.utils.strdispatch import StrDispatch
|
||||||
# import yap_ipython.core
|
# import yap_ipython.core
|
||||||
from traitlets import Instance
|
from traitlets import Instance
|
||||||
from yap_ipython.core.inputsplitter import *
|
from yap_ipython.core.inputsplitter import *
|
||||||
from yap_ipython.core.inputtransformer import *
|
from yap_ipython.core.inputtransformer import *
|
||||||
|
from yap_ipython.core.interactiveshell import *
|
||||||
from pygments import highlight
|
from pygments import highlight
|
||||||
from pygments.lexers.prolog import PrologLexer
|
from pygments.lexers.prolog import PrologLexer
|
||||||
from pygments.formatters import HtmlFormatter
|
from pygments.formatters import HtmlFormatter
|
||||||
|
|
||||||
|
from yap_ipython.core import interactiveshell
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
@ -106,7 +107,6 @@ class YAPInputSplitter(InputSplitter):
|
|||||||
def validQuery(self, text, line=None):
|
def validQuery(self, text, line=None):
|
||||||
"""Return whether a legal query
|
"""Return whether a legal query
|
||||||
"""
|
"""
|
||||||
print("valid")
|
|
||||||
if not line:
|
if not line:
|
||||||
(_,line,_) = self.shell.prolog_cell(text)
|
(_,line,_) = self.shell.prolog_cell(text)
|
||||||
line = line.strip().rstrip()
|
line = line.strip().rstrip()
|
||||||
@ -114,7 +114,6 @@ class YAPInputSplitter(InputSplitter):
|
|||||||
return False
|
return False
|
||||||
self.errors = []
|
self.errors = []
|
||||||
self.yapeng.mgoal(errors(self, line),"user")
|
self.yapeng.mgoal(errors(self, line),"user")
|
||||||
print(self.errors)
|
|
||||||
return self.errors != []
|
return self.errors != []
|
||||||
|
|
||||||
|
|
||||||
@ -279,7 +278,7 @@ class YAPCompleter(Completer):
|
|||||||
help="""Activate greedy completion
|
help="""Activate greedy completion
|
||||||
PENDING DEPRECTION. this is now mostly taken care of with Jedi.
|
PENDING DEPRECTION. this is now mostly taken care of with Jedi.
|
||||||
|
|
||||||
This will enable completion on elements of lists, results of function calls, etc.,
|
This will enable completion on elements of lists, self.results of function calls, etc.,
|
||||||
but can be unsafe because the code is actually evaluated on TAB.
|
but can be unsafe because the code is actually evaluated on TAB.
|
||||||
"""
|
"""
|
||||||
).tag(config=True)
|
).tag(config=True)
|
||||||
@ -511,8 +510,9 @@ class YAPRun:
|
|||||||
self.yapeng = Engine()
|
self.yapeng = Engine()
|
||||||
self.yapeng.goal(use_module(library("jupyter")))
|
self.yapeng.goal(use_module(library("jupyter")))
|
||||||
self.q = None
|
self.q = None
|
||||||
self.run = False
|
self.port = "call"
|
||||||
self.shell.port = None
|
self.os = None
|
||||||
|
self.it = None
|
||||||
self.shell.yapeng = self.yapeng
|
self.shell.yapeng = self.yapeng
|
||||||
self._get_exc_info = shell._get_exc_info
|
self._get_exc_info = shell._get_exc_info
|
||||||
|
|
||||||
@ -525,27 +525,37 @@ class YAPRun:
|
|||||||
self.yapeng.mgoal(errors(self,text),"user")
|
self.yapeng.mgoal(errors(self,text),"user")
|
||||||
return self.errors
|
return self.errors
|
||||||
|
|
||||||
def jupyter_query(self, s, mx):
|
def jupyter_query(self, s):
|
||||||
#
|
#
|
||||||
# construct a self.query from a one-line string
|
# construct a self.query from a one-line string
|
||||||
# self.q is opaque to Python
|
# self.q is opaque to Python
|
||||||
iterations = 0
|
program,query,mx = self.prolog_cell(s)
|
||||||
bindings = []
|
Found = False
|
||||||
program,query,_ = self.prolog_cell(s)
|
|
||||||
if query == self.shell.os:
|
if query != self.os:
|
||||||
q = self.shell.q
|
self.os = None
|
||||||
self.shell.os = None
|
self.iterations = 0
|
||||||
|
pg = jupyter_query( self, program, query)
|
||||||
|
self.it = Goal( self.yapeng, pg)
|
||||||
else:
|
else:
|
||||||
q = Goal(jupyter_query(self, query), self.yapeng, module="user",program=program)
|
mx += self.iterations
|
||||||
for q in q:
|
self.os = s
|
||||||
bindings += [q.bindings()]
|
for answ in self.it:
|
||||||
iterations += 1
|
found = True
|
||||||
if mx == iterations:
|
self.bindings += [answ]
|
||||||
break
|
self.iterations += 1
|
||||||
if q:
|
if mx == self.iterations:
|
||||||
self.shell.os = query
|
return True, self.bindings
|
||||||
self.shell.q = q
|
port = self.it.port
|
||||||
return bindings
|
if port == "exit":
|
||||||
|
self.q = None
|
||||||
|
self.os = None
|
||||||
|
return True,self.bindings
|
||||||
|
if port == "fail":
|
||||||
|
self.q = none
|
||||||
|
self.os = None
|
||||||
|
if self.bindings_message:
|
||||||
|
return True,self.bindings
|
||||||
|
|
||||||
|
|
||||||
def _yrun_cell(self, raw_cell, store_history=True, silent=False,
|
def _yrun_cell(self, raw_cell, store_history=True, silent=False,
|
||||||
@ -563,7 +573,7 @@ class YAPRun:
|
|||||||
IPython's machinery, this
|
IPython's machinery, this
|
||||||
should be set to False.
|
should be set to False.
|
||||||
silent : bool
|
silent : bool
|
||||||
If True, avoid side-effects, such as implicit displayhooks and
|
v If True, avoid side-effects, such as implicit displayhooks and
|
||||||
and logging. silent=True forces store_history=False.
|
and logging. silent=True forces store_history=False.
|
||||||
shell_futures : bool
|
shell_futures : bool
|
||||||
If True, the code will share future statements with the interactive
|
If True, the code will share future statements with the interactive
|
||||||
@ -576,7 +586,7 @@ class YAPRun:
|
|||||||
|
|
||||||
-------
|
-------
|
||||||
|
|
||||||
`result : :class:`ExecutionResult`
|
`self.result : :class:`Executionself.result`
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# construct a query from a one-line string
|
# construct a query from a one-line string
|
||||||
@ -594,22 +604,22 @@ class YAPRun:
|
|||||||
info = interactiveshell.ExecutionInfo(
|
info = interactiveshell.ExecutionInfo(
|
||||||
raw_cell, store_history, silent, shell_futures)
|
raw_cell, store_history, silent, shell_futures)
|
||||||
|
|
||||||
result = interactiveshell.ExecutionResult(info)
|
self.result = interactiveshell.ExecutionResult(info)
|
||||||
|
|
||||||
if (raw_cell == "") or raw_cell.isspace():
|
if (raw_cell == "") or raw_cell.isspace():
|
||||||
self.shell.last_execution_succeeded = True
|
self.shell.last_execution_succeeded = True
|
||||||
return result
|
return self.result
|
||||||
|
|
||||||
if silent:
|
if silent:
|
||||||
store_history = False
|
store_history = False
|
||||||
|
|
||||||
if store_history:
|
if store_history:
|
||||||
result.execution_count = self.shell.execution_count+1
|
self.result .execution_count = self.shell.execution_count+1
|
||||||
|
|
||||||
def error_before_exec(value):
|
def error_before_exec(value):
|
||||||
result.error_before_exec = value
|
self.result .error_before_exec = value
|
||||||
self.shell.last_execution_succeeded = False
|
self.shell.last_execution_succeeded = False
|
||||||
return result
|
return self.result
|
||||||
|
|
||||||
self.shell.events.trigger('pre_execute')
|
self.shell.events.trigger('pre_execute')
|
||||||
if not silent:
|
if not silent:
|
||||||
@ -646,12 +656,10 @@ class YAPRun:
|
|||||||
except SyntaxError:
|
except SyntaxError:
|
||||||
self.shell.showsyntaxerror( )
|
self.shell.showsyntaxerror( )
|
||||||
preprocessing_exc_tuple = sys.exc_info()
|
preprocessing_exc_tuple = sys.exc_info()
|
||||||
|
|
||||||
# Store raw and processed history
|
# Store raw and processed history
|
||||||
if store_history:
|
if store_history:
|
||||||
self.shell.history_manager.store_inputs(self.shell.execution_count,
|
self.shell.history_manager.store_inputs(self.shell.execution_count,
|
||||||
cell, raw_cell)
|
cell, raw_cell)
|
||||||
silent = False
|
|
||||||
if not silent:
|
if not silent:
|
||||||
self.shell.logger.log(cell, raw_cell)
|
self.shell.logger.log(cell, raw_cell)
|
||||||
# # Display the exception if input processing failed.
|
# # Display the exception if input processing failed.
|
||||||
@ -681,32 +689,33 @@ class YAPRun:
|
|||||||
line = txt[1]
|
line = txt[1]
|
||||||
else:
|
else:
|
||||||
line = ""
|
line = ""
|
||||||
if linec:
|
|
||||||
self.shell.run_line_magic(magic, line)
|
|
||||||
if len(txt0) == 2:
|
if len(txt0) == 2:
|
||||||
cell = txt0[1]
|
cell = txt0[1]
|
||||||
else:
|
else:
|
||||||
cellArea = ""
|
cell = ""
|
||||||
|
if linec:
|
||||||
|
self.shell.run_line_magic(magic, line)
|
||||||
else:
|
else:
|
||||||
self.shell.run_cell_magic(magic, line, cell)
|
self.shell.run_cell_magic(magic, line, cell)
|
||||||
return
|
cell = ""
|
||||||
# Give the displayhook a reference to our ExecutionResult so it
|
# Give the displayhook a reference to our ExecutionResult so it
|
||||||
# can fill in the output value.
|
# can fill in the output value.
|
||||||
self.shell.displayhook.exec_result = result
|
self.shell.displayhook.exec_result = self.result
|
||||||
has_raised = False
|
has_raised = False
|
||||||
try:
|
try:
|
||||||
|
state = None
|
||||||
self.shell.bindings = dict = {}
|
self.shell.bindings = dict = {}
|
||||||
|
if cell.strip():
|
||||||
state = self.jupyter_query( cell )
|
state = self.jupyter_query( cell )
|
||||||
if state:
|
if state:
|
||||||
self.shell.last_execution_succeeded = True
|
self.shell.last_execution_succeeded = True
|
||||||
result.result = (True, dict)
|
self.result.result = (True, dict)
|
||||||
else:
|
else:
|
||||||
self.shell.last_execution_succeeded = True
|
self.shell.last_execution_succeeded = True
|
||||||
result.result = (True, {})
|
self.result.result = (True, {})
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
|
||||||
has_raised = True
|
has_raised = True
|
||||||
result.result = False
|
self.result.result = False
|
||||||
|
|
||||||
self.shell.last_execution_succeeded = not has_raised
|
self.shell.last_execution_succeeded = not has_raised
|
||||||
|
|
||||||
@ -724,10 +733,10 @@ class YAPRun:
|
|||||||
# Each cell is a *single* input, regardless of how many lines it has
|
# Each cell is a *single* input, regardless of how many lines it has
|
||||||
self.shell.execution_count += 1
|
self.shell.execution_count += 1
|
||||||
|
|
||||||
return result
|
return self.result
|
||||||
|
|
||||||
def prolog_cell(self,s):
|
def prolog_cell(self,s):
|
||||||
""""
|
"""
|
||||||
Trasform a text into program+query. A query is the
|
Trasform a text into program+query. A query is the
|
||||||
last line if the last line is non-empty and does not terminate
|
last line if the last line is non-empty and does not terminate
|
||||||
on a dot. You can also finish with
|
on a dot. You can also finish with
|
||||||
|
@ -56,6 +56,7 @@ set(PL_BOOT_SOURCES
|
|||||||
undefined.yap
|
undefined.yap
|
||||||
utils.yap
|
utils.yap
|
||||||
yapor.yap
|
yapor.yap
|
||||||
|
ypp.yap
|
||||||
)
|
)
|
||||||
|
|
||||||
add_to_group(PL_BOOT_SOURCES pl_boot_library)
|
add_to_group(PL_BOOT_SOURCES pl_boot_library)
|
||||||
@ -91,8 +92,5 @@ endif()
|
|||||||
|
|
||||||
|
|
||||||
install(FILES ${PL_BOOT_SOURCES}
|
install(FILES ${PL_BOOT_SOURCES}
|
||||||
DESTINATION ${libpl}/pl
|
DESTINATION ${libpl}/pll
|
||||||
)
|
|
||||||
install(FILES ../library/ypp.yap
|
|
||||||
DESTINATION ${libpl}/library
|
|
||||||
)
|
)
|
||||||
|
63
pl/boot.yap
63
pl/boot.yap
@ -109,65 +109,6 @@ private(_).
|
|||||||
|
|
||||||
% be careful here not to generate an undefined exception..
|
% be careful here not to generate an undefined exception..
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
print_message(L,E) :-
|
print_message(L,E) :-
|
||||||
'$number_of_clauses'(print_message(L,E), prolog_complete, 1),
|
'$number_of_clauses'(print_message(L,E), prolog_complete, 1),
|
||||||
!,
|
!,
|
||||||
@ -326,7 +267,7 @@ initialize_prolog :-
|
|||||||
:- [
|
:- [
|
||||||
% lists is often used.
|
% lists is often used.
|
||||||
'../os/yio.yap',
|
'../os/yio.yap',
|
||||||
'../pl/debug.yap',
|
'debug.yap',
|
||||||
'checker.yap',
|
'checker.yap',
|
||||||
'depth_bound.yap',
|
'depth_bound.yap',
|
||||||
'ground.yap',
|
'ground.yap',
|
||||||
@ -418,7 +359,7 @@ sub-goal _NG_ will replace _G_ and will be processed in the same
|
|||||||
:- use_module('corout.yap').
|
:- use_module('corout.yap').
|
||||||
:- use_module('dialect.yap').
|
:- use_module('dialect.yap').
|
||||||
:- use_module('dbload.yap').
|
:- use_module('dbload.yap').
|
||||||
:- use_module('../library/ypp.yap').
|
:- use_module('ypp.yap').
|
||||||
:- use_module('../os/chartypes.yap').
|
:- use_module('../os/chartypes.yap').
|
||||||
:- ensure_loaded('../os/edio.yap').
|
:- ensure_loaded('../os/edio.yap').
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/*************************************************************************
|
s444444444444444444444444444444444444444444444444444444444444444444444444/*************************************************************************
|
||||||
* *
|
* *
|
||||||
* YAP Prolog *
|
* YAP Prolog *
|
||||||
* *
|
* *
|
||||||
@ -650,6 +650,11 @@ db_files(Fs) :-
|
|||||||
'$load_files'(Fs, [consult(db), if(not_loaded)], exo_files(Fs)).
|
'$load_files'(Fs, [consult(db), if(not_loaded)], exo_files(Fs)).
|
||||||
|
|
||||||
|
|
||||||
|
'$csult'(Fs, M) :-
|
||||||
|
'$skip_list'(_, Fs ,L),
|
||||||
|
L \== [],
|
||||||
|
user:dot_qualified_goal(Fs),
|
||||||
|
!.
|
||||||
'$csult'(Fs, M) :-
|
'$csult'(Fs, M) :-
|
||||||
'$extract_minus'(Fs, MFs), !,
|
'$extract_minus'(Fs, MFs), !,
|
||||||
'$load_files'(M:MFs,[],[M:Fs]).
|
'$load_files'(M:MFs,[],[M:Fs]).
|
||||||
@ -1627,6 +1632,8 @@ End of conditional compilation.
|
|||||||
|
|
||||||
consult_depth(LV) :- '$show_consult_level'(LV).
|
consult_depth(LV) :- '$show_consult_level'(LV).
|
||||||
|
|
||||||
|
:- '$add_multifile'(Name,Arity,Module).
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@}
|
@}
|
||||||
|
|
||||||
|
@ -429,7 +429,7 @@ query_to_answer(G, V, Status, Bindings) :-
|
|||||||
'$answer'( answer, LGs, Vs, Bindings) :-
|
'$answer'( answer, LGs, Vs, Bindings) :-
|
||||||
!,
|
!,
|
||||||
'$process_answer'(Vs, LGs, Bindings).
|
'$process_answer'(Vs, LGs, Bindings).
|
||||||
'$answer'(cut, _, _, _).
|
'$answer'(!, _, _, _).
|
||||||
'$answer'(fail,_,_,_).
|
'$answer'(fail,_,_,_).
|
||||||
'$answer'(exception(E),_,_,_) :-
|
'$answer'(exception(E),_,_,_) :-
|
||||||
'$LoopError'(E,error).
|
'$LoopError'(E,error).
|
||||||
|
@ -469,7 +469,7 @@ be lost.
|
|||||||
Border < GoalNumber,
|
Border < GoalNumber,
|
||||||
( Spy == ignore ; '$pred_being_spied'(G, M) )
|
( Spy == ignore ; '$pred_being_spied'(G, M) )
|
||||||
),
|
),
|
||||||
writeln(go:G:M),
|
%writeln(go:G:M),
|
||||||
!,
|
!,
|
||||||
'$execute_nonstop'(G,M).
|
'$execute_nonstop'(G,M).
|
||||||
'$trace_goal'(G, M, GoalNumber, H) :-
|
'$trace_goal'(G, M, GoalNumber, H) :-
|
||||||
|
@ -238,7 +238,7 @@ user_defined_directive(Dir,Action) :-
|
|||||||
|
|
||||||
'$thread_initialization'(M:D) :-
|
'$thread_initialization'(M:D) :-
|
||||||
eraseall('$thread_initialization'),
|
eraseall('$thread_initialization'),
|
||||||
writeln(M:D),
|
%writeln(M:D),
|
||||||
recorda('$thread_initialization',M:D,_),
|
recorda('$thread_initialization',M:D,_),
|
||||||
fail.
|
fail.
|
||||||
'$thread_initialization'(M:D) :-
|
'$thread_initialization'(M:D) :-
|
||||||
|
@ -365,7 +365,6 @@ system_module(Mod) :-
|
|||||||
functor(G0, N, K),
|
functor(G0, N, K),
|
||||||
'$autoloader_find_predicate'(G0,ExportingMod),
|
'$autoloader_find_predicate'(G0,ExportingMod),
|
||||||
ExportingMod \= ImportingMod,
|
ExportingMod \= ImportingMod,
|
||||||
writeln((ExportingMod,ImportingMod,G0,G0, N ,K)),
|
|
||||||
(recordzifnot('$import','$import'(ExportingMod,ImportingMod,G0,G0, N ,K),_) -> true ; true ).
|
(recordzifnot('$import','$import'(ExportingMod,ImportingMod,G0,G0, N ,K),_) -> true ; true ).
|
||||||
|
|
||||||
|
|
||||||
@ -399,7 +398,7 @@ be associated to a new file.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
'$declare_module'(Name, _Super, Context, _File, _Line) :-
|
'$declare_module'(Name, _Super, Context, _File, _Line) :-
|
||||||
add_import_module(Name, Context, start).
|
addi_mport_module(Name, Context, start).
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@pred abolish_module( + Mod) is det
|
@pred abolish_module( + Mod) is det
|
||||||
@ -492,11 +491,9 @@ export_list(Module, List) :-
|
|||||||
G1=..[N1|Args],
|
G1=..[N1|Args],
|
||||||
( '$check_import'(M0,ContextMod,N1,K) ->
|
( '$check_import'(M0,ContextMod,N1,K) ->
|
||||||
( ContextMod == prolog ->
|
( ContextMod == prolog ->
|
||||||
writeln((M0,ContextMod,G0,G1,N1,K)),
|
|
||||||
recordzifnot('$import','$import'(M0,user,G0,G1,N1,K),_),
|
recordzifnot('$import','$import'(M0,user,G0,G1,N1,K),_),
|
||||||
fail
|
fail
|
||||||
;
|
;
|
||||||
writeln((M0,ContextMod,G0,G1,N1,K)),
|
|
||||||
recordaifnot('$import','$import'(M0,ContextMod,G0,G1,N1,K),_),
|
recordaifnot('$import','$import'(M0,ContextMod,G0,G1,N1,K),_),
|
||||||
fail
|
fail
|
||||||
;
|
;
|
||||||
|
Reference in New Issue
Block a user