Пример #1
0
        /// <summary>
        /// <para>Create a <see cref="ReadOnlyCollection&lt;T&gt;"/> of <see cref="PlQueryVariables"/>.</para>
        /// <para>If calling ToList() all solutions of the query are generated and stored in the Collection.</para>
        /// </summary>
        /// <returns>A ReadOnlyCollection of PlQueryVariables containing all solutions of the query.</returns>
        /// <example>
        ///     <code source="..\..\TestSwiPl\LinqSwiPl.cs" region="Test_multi_goal_ToList_doc" />
        /// </example>
        public ReadOnlyCollection <PlQueryVariables> ToList()
        {
            var list = new List <PlQueryVariables>();

            EraseRecords();
            while (NextSolution())
            {
                for (int i = 0; i < _queryVariables.Count; i++)
                {
                    _records.Add(LibPl.PL_record(_queryVariables[i].Value.TermRef));   // to keep the PlTerms
                }
            }

            var qv    = new PlQueryVariables(); // dummy to make the compiler happy
            int avIdx = _queryVariables.Count;

            foreach (uintptr_t recordTerm in _records)
            {
                var ptrTerm = LibPl.PL_new_term_ref();
                LibPl.PL_recorded(recordTerm, ptrTerm);
                if (avIdx == _queryVariables.Count)
                {
                    qv = new PlQueryVariables();
                    list.Add(qv);
                    avIdx = 0;
                }
                //qv.Add(new PlQueryVar(GetVariableName(avIdx), new PlTerm(term)));   // If this line is deleted -> update comment in PlTern(term_ref)
                qv.Add(new PlQueryVar(_queryVariables[avIdx].Name, new PlTerm(ptrTerm)));   // If this line is deleted -> update comment in PlTern(term_ref)
                avIdx++;
                //av[avIdx++].TermRef = term_t;
            }
            return(new ReadOnlyCollection <PlQueryVariables>(list));
        }
Пример #2
0
        /// <summary>
        /// Provide the next solution to the query. Prolog exceptions are mapped to C# exceptions.
        /// </summary>
        /// <returns>return true if successful and false if there are no (more) solutions.</returns>
        /// <remarks>
        /// <para>If the query is closed it will be opened. If the last solution was generated the query will be closed.</para>
        /// <para>If an exception is thrown while parsing (open) the query the _qid is set to zero.</para>
        /// </remarks>
        /// <exception cref="PlException">Is thrown if <see href="http://gollem.science.uva.nl/SWI-Prolog/Manual/foreigninclude.html#PL_next_solution()">SWI-Prolog Manual PL_next_solution()</see> returns false </exception>
        public bool NextSolution()
        {
            if (0 == _qid)
            {
                Check.Require(!string.IsNullOrEmpty(_name), "PlQuery.NextSolution() _name is required");

                IntPtr p = LibPl.PL_predicate(_name, _av.Size, _module);
                _qid = LibPl.PL_open_query((IntPtr)0, LibPl.PL_Q_CATCH_EXCEPTION, p, _av.A0);
            }
            int rval = LibPl.PL_next_solution(_qid);

            if (0 == rval)
            {                 // error
                uintptr_t ex; // term_t
                if ((ex = LibPl.PL_exception(_qid)) > 0)
                {
                    _qid = 0;   // to avoid an AccessViolationException on Dispose. E.g. if the query is miss spelled.
                    var etmp = new PlException(new PlTerm(ex));
                    etmp.Throw();
                }
            }
            if (rval <= 0)
            {
                Free(false);
            }

            return(rval > 0);
        }
Пример #3
0
 /// <summary>
 /// Discards the query, but does not delete any of the data created by the query if discardData is false.
 /// It just invalidate qid, allowing for a new PlQuery object in this context.
 /// </summary>
 /// <remarks>see <see href="http://gollem.science.uva.nl/SWI-Prolog/Manual/foreigninclude.html#PL_cut_query()"/></remarks>
 /// <param name="discardData">if true all bindings of the query are destroyed</param>
 private void Free(bool discardData)
 {
     if (_qid > 0 && PlEngine.IsInitialized)
     {
         try
         {
             if (discardData)
             {
                 // <"leider werden dann die gebundenen variablen der query wieder frei e.g. in PlCall(goal)"/>
                 // unfortunately this statement detaches the bound variables of the query e.g. in PlCall(goal)
                 LibPl.PL_close_query(_qid);
             }
             else
             {
                 LibPl.PL_cut_query(_qid);
             }
         }
         catch (AccessViolationException ex)
         {
             TraceAccessViolationException(ex);
         }
     }
     _qid = 0;
 }
Пример #4
0
 /// <summary>
 /// <para>Obtain status information on the Prolog system. The actual argument type depends on the information required.
 /// The parameter queryType describes what information is wanted.</para>
 /// <para>Returning pointers and integers as a long is bad style. The signature of this function should be changed.</para>
 /// <see>PlQuerySwitch</see>
 /// </summary>
 /// <example>
 ///     <para>This sample shows how to get SWI-Prologs version number</para>
 ///     <code source="..\..\TestSwiPl\PlQuery.cs" region="get_prolog_version_number_doc" />
 /// </example>
 /// <param name="queryType">A <see>PlQuerySwitch</see>.</param>
 /// <returns>A int depending on the given queryType</returns>
 public static long Query(PlQuerySwitch queryType)
 {
     Check.Require(queryType != PlQuerySwitch.None, "PlQuerySwitch (None) is not valid");
     return(LibPl.PL_query((uint)queryType));
 }
Пример #5
0
#pragma warning disable 1573
        /// <inheritdoc cref="PlQuery(string)" />
        /// <summary>locating the predicate in the named module.</summary>
        /// <param name="module">locating the predicate in the named module.</param>
        public PlQuery(string module, string goal)
        {
            if (string.IsNullOrEmpty(goal))
            {
                throw new ArgumentNullException("goal");
            }

            _module = module;
            var queryString = goal;

            try
            {
                // call read_term(Term_of_query_string, [variable_names(VN)]).
                // read_term_from_atom('noun(ş,C)', T, [variable_names(Vars)]).
                // befor 2014 with redirected IO-Streams (PlQuery_Old_Kill_unused)
                var    atom          = new PlTerm("'" + goal.Replace("'", @"\'") + "'");
                PlTerm term          = PlTerm.PlVar();
                PlTerm options       = PlTerm.PlVar();
                PlTerm variablenames = PlTerm.PlVar();
                PlTerm l             = PlTerm.PlTail(options);
                l.Append(PlTerm.PlCompound("variable_names", variablenames));
                l.Close();
                var args = new PlTermV(atom, term, options);
                if (!PlCall("read_term_from_atom", args))
                {
                    throw new PlLibException("PlCall read_term_from_atom/3 fails! goal:" + queryString);
                }

                // set list of variables and variable_names into _queryVariables
                foreach (PlTerm t in variablenames.ToList())
                {
                    // t[0]='=' , t[1]='VN', t[2]=_G123
                    _queryVariables.Add(new PlQueryVar(t[1].ToString(), t[2]));
                }

                // Build the query
                _name = term.Name;

                // is ok e.g. for listing/0.
                // Check.Require(term.Arity > 0, "PlQuery(PlTerm t): t.Arity must be greater than 0.");
                _av = new PlTermV(term.Arity);
                for (int index = 0; index < term.Arity; index++)
                {
                    if (0 == LibPl.PL_get_arg(index + 1, term.TermRef, _av[index].TermRef))
                    {
                        throw new PlException("PL_get_arg in PlQuery " + term.ToString());
                    }
                }
            }
#if _DEBUG
            catch (Exception ex)
            {
                System.Diagnostics.Debug.Print(ex.Message);
                Console.WriteLine(ex.Message);
            }
#endif
            finally
            {
                // NBT
            }
        }