From 5455c53eafa016b92f054d29ddbfb56e8d1061cf Mon Sep 17 00:00:00 2001 From: Eshel Yaron Date: Sun, 28 Aug 2022 22:55:45 +0300 Subject: [PATCH] ENHANCED: Add optional "reverse" argument flag to sweep-open-query --- Makefile | 2 +- README.org | 17 ++++++++++------- sweep-tests.el | 8 ++++++++ sweep.c | 15 ++++++++++----- 4 files changed, 29 insertions(+), 13 deletions(-) diff --git a/Makefile b/Makefile index f5758a2..6544f4e 100644 --- a/Makefile +++ b/Makefile @@ -33,7 +33,7 @@ CMAKE_OPTIONS += -DSWIPL_INSTALL_IN_LIB=ON .PHONY: clean all swipl check -all: $(TARGET) +all: $(TARGET) $(BASENAME).info $(OBJECT): $(SOURCE) lib/libswipl.$(SOEXT) $(CC) $(CFLAGS) -o $@ -c $(SOURCE) diff --git a/README.org b/README.org index 96d090c..021160b 100644 --- a/README.org +++ b/README.org @@ -95,13 +95,13 @@ The different parts of =sweep= are structured as follows: #+FINDEX: sweep-open-query =sweep= provides the Elisp function =sweep-open-query= for invoking Prolog predicates. The invoked predicate must be of arity two and will be -called in mode =p(+In, -Out)=, i.e. the predicate should treat the first -argument as input and expect a variable for the second argument which -should be unified with the some output. This restriction is placed in -order to facilitate a natural calling convention between Elisp, a -functional language, and Prolog, a logical one. +called in mode =p(+In, -Out)= i.e. the predicate should treat the +first argument as input and expect a variable for the second argument +which should be unified with the some output. This restriction is +placed in order to facilitate a natural calling convention between +Elisp, a functional language, and Prolog, a logical one. -The =sweep-open-query= function takes four arguments, the first three +The =sweep-open-query= function takes five arguments, the first three are strings which denote: - The name of the Prolog context module from which to execute the query, @@ -111,7 +111,10 @@ are strings which denote: The fourth argument to =sweep-open-query= is converted into a Prolog term and used as the first argument of the predicate (see [[Conversion -of Elisp objects to Prolog terms]]). +of Elisp objects to Prolog terms]]). The fifth argument is an +optional "reverse" flag, when this flag is set to non-nil, the order +of the arguments is reversed such the predicate is called in mode +=p(-Out, +In)= rather than =p(+In, -Out)=. #+FINDEX: sweep-next-solution The function =sweep-next-solution= can be used to examine the results of diff --git a/sweep-tests.el b/sweep-tests.el index 072aaf0..84a0610 100644 --- a/sweep-tests.el +++ b/sweep-tests.el @@ -1,3 +1,11 @@ +(ert-deftest lists:member/2 () + "Tests calling the Prolog predicate permutation/2 from Elisp." + (should (equal (sweep-open-query "user" "lists" "member" (list 1 2 3) t) t)) + (should (equal (sweep-next-solution) (cons t 1))) + (should (equal (sweep-next-solution) (cons t 2))) + (should (equal (sweep-next-solution) (cons '! 3))) + (should (equal (sweep-cut-query) t))) + (ert-deftest lists:permutation/2 () "Tests calling the Prolog predicate permutation/2 from Elisp." (should (equal (sweep-open-query "user" "lists" "permutation" (list 1 2 3)) t)) diff --git a/sweep.c b/sweep.c index 02fd5dd..bbb3f99 100644 --- a/sweep.c +++ b/sweep.c @@ -359,10 +359,14 @@ sweep_open_query(emacs_env *env, ptrdiff_t nargs, emacs_value *args, void *data) char * f = NULL; term_t a = PL_new_term_refs(2); emacs_value r = enil(env); + emacs_value s = NULL; (void)data; - (void)nargs; - + if (nargs == 4) { + s = enil(env); + } else { + s = args[4]; + } if (PL_current_query() != 0) { ethrow(env, "Prolog is already executing a query"); @@ -385,12 +389,12 @@ sweep_open_query(emacs_env *env, ptrdiff_t nargs, emacs_value *args, void *data) p = PL_predicate(f, 2, m); - if (value_to_term(env, args[3], a+0) < 0) { + if (value_to_term(env, args[3], a+(env->is_not_nil(env, s) ? 1 : 0)) < 0) { goto cleanup; } PL_open_query(n, PL_Q_NODEBUG | PL_Q_EXT_STATUS | PL_Q_CATCH_EXCEPTION, p, a); - o = a+1; + o = a+(env->is_not_nil(env, s) ? 0 : 1); r = et(env); @@ -484,13 +488,14 @@ REST is passed as the rest of the command line arguments to Prolog.", emacs_value symbol_open_query = env->intern (env, "sweep-open-query"); emacs_value func_open_query = env->make_function(env, - 4, 4, + 4, 5, sweep_open_query, "Query Prolog.\n\ ARG1 is a string denoting the context module for the query.\n\ ARG2 and ARG3 are strings designating the module and predicate name of the Prolog predicate to invoke, which must be of arity 2.\n\ ARG4 is any object that can be converted to a Prolog term, and will be passed as the first argument of the invoked predicate.\n\ The second argument of the predicate is left unbound and is assumed to treated by the invoked predicate as an output variable.\n\ +If ARG5 is non-nil, reverse the order of the predicate arguments such that the first argument is the output variable and the second argument is the input term derived from ARG4. Further instantiations of the output variable can be examined via `sweep-next-solution'.", NULL); emacs_value args_open_query[] = {symbol_open_query, func_open_query}; -- 2.39.2