Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Some cleanup #192

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
169 changes: 57 additions & 112 deletions src/pyswip/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -531,8 +531,8 @@ def check_and_call(*args):
PL_version.restype = c_uint

PL_VERSION = PL_version(PL_VERSION_SYSTEM)
if PL_VERSION < 80200:
raise Exception("swi-prolog >= 8.2.0 is required")
if PL_VERSION < 80400:
raise Exception("swi-prolog >= 8.4.0 is required")
except AttributeError:
raise Exception("swi-prolog version number could not be determined")

Expand All @@ -548,103 +548,60 @@ def check_and_call(*args):
# /* PL_unify_term( arguments */


if PL_VERSION < 80200:
# constants (from SWI-Prolog.h)
# PL_unify_term() arguments
PL_VARIABLE = 1 # nothing
PL_ATOM = 2 # const char
PL_INTEGER = 3 # int
PL_FLOAT = 4 # double
PL_STRING = 5 # const char *
PL_TERM = 6 #
# PL_unify_term()
PL_FUNCTOR = 10 # functor_t, arg ...
PL_LIST = 11 # length, arg ...
PL_CHARS = 12 # const char *
PL_POINTER = 13 # void *
# /* PlArg::PlArg(text, type) */
# define PL_CODE_LIST (14) /* [ascii...] */
# define PL_CHAR_LIST (15) /* [h,e,l,l,o] */
# define PL_BOOL (16) /* PL_set_feature() */
# define PL_FUNCTOR_CHARS (17) /* PL_unify_term() */
# define _PL_PREDICATE_INDICATOR (18) /* predicate_t (Procedure) */
# define PL_SHORT (19) /* short */
# define PL_INT (20) /* int */
# define PL_LONG (21) /* long */
# define PL_DOUBLE (22) /* double */
# define PL_NCHARS (23) /* unsigned, const char * */
# define PL_UTF8_CHARS (24) /* const char * */
# define PL_UTF8_STRING (25) /* const char * */
# define PL_INT64 (26) /* int64_t */
# define PL_NUTF8_CHARS (27) /* unsigned, const char * */
# define PL_NUTF8_CODES (29) /* unsigned, const char * */
# define PL_NUTF8_STRING (30) /* unsigned, const char * */
# define PL_NWCHARS (31) /* unsigned, const wchar_t * */
# define PL_NWCODES (32) /* unsigned, const wchar_t * */
# define PL_NWSTRING (33) /* unsigned, const wchar_t * */
# define PL_MBCHARS (34) /* const char * */
# define PL_MBCODES (35) /* const char * */
# define PL_MBSTRING (36) /* const char * */

REP_ISO_LATIN_1 = 0x0000 # output representation
REP_UTF8 = 0x1000
REP_MB = 0x2000

else:
PL_VARIABLE = 1 # nothing
PL_ATOM = 2 # const char *
PL_INTEGER = 3 # int
PL_RATIONAL = 4 # rational number
PL_FLOAT = 5 # double
PL_STRING = 6 # const char *
PL_TERM = 7

PL_NIL = 8 # The constant []
PL_BLOB = 9 # non-atom blob
PL_LIST_PAIR = 10 # [_|_] term

# # PL_unify_term(
PL_FUNCTOR = 11 # functor_t, arg ...
PL_LIST = 12 # length, arg ...
PL_CHARS = 13 # const char *
PL_POINTER = 14 # void *
# PlArg::PlArg(text, type
PL_CODE_LIST = 15 # [ascii...]
PL_CHAR_LIST = 16 # [h,e,l,l,o]
PL_BOOL = 17 # PL_set_prolog_flag(
PL_FUNCTOR_CHARS = 18 # PL_unify_term(
_PL_PREDICATE_INDICATOR = 19 # predicate_t= Procedure
PL_SHORT = 20 # short
PL_INT = 21 # int
PL_LONG = 22 # long
PL_DOUBLE = 23 # double
PL_NCHARS = 24 # size_t, const char *
PL_UTF8_CHARS = 25 # const char *
PL_UTF8_STRING = 26 # const char *
PL_INT64 = 27 # int64_t
PL_NUTF8_CHARS = 28 # size_t, const char *
PL_NUTF8_CODES = 29 # size_t, const char *
PL_NUTF8_STRING = 30 # size_t, const char *
PL_NWCHARS = 31 # size_t, const wchar_t *
PL_NWCODES = 32 # size_t, const wchar_t *
PL_NWSTRING = 33 # size_t, const wchar_t *
PL_MBCHARS = 34 # const char *
PL_MBCODES = 35 # const char *
PL_MBSTRING = 36 # const char *
PL_INTPTR = 37 # intptr_t
PL_CHAR = 38 # int
PL_CODE = 39 # int
PL_BYTE = 40 # int
# PL_skip_list(
PL_PARTIAL_LIST = 41 # a partial list
PL_CYCLIC_TERM = 42 # a cyclic list/term
PL_NOT_A_LIST = 43 # Object is not a list
# dicts
PL_DICT = 44

REP_ISO_LATIN_1 = 0x0000 # output representation
REP_UTF8 = 0x00100000
REP_MB = 0x00200000
PL_VARIABLE = 1 # nothing
PL_ATOM = 2 # const char *
PL_INTEGER = 3 # int
PL_RATIONAL = 4 # rational number
PL_FLOAT = 5 # double
PL_STRING = 6 # const char *
PL_TERM = 7

PL_NIL = 8 # The constant []
PL_BLOB = 9 # non-atom blob
PL_LIST_PAIR = 10 # [_|_] term

# # PL_unify_term(
PL_FUNCTOR = 11 # functor_t, arg ...
PL_LIST = 12 # length, arg ...
PL_CHARS = 13 # const char *
PL_POINTER = 14 # void *
# PlArg::PlArg(text, type
PL_CODE_LIST = 15 # [ascii...]
PL_CHAR_LIST = 16 # [h,e,l,l,o]
PL_BOOL = 17 # PL_set_prolog_flag(
PL_FUNCTOR_CHARS = 18 # PL_unify_term(
_PL_PREDICATE_INDICATOR = 19 # predicate_t= Procedure
PL_SHORT = 20 # short
PL_INT = 21 # int
PL_LONG = 22 # long
PL_DOUBLE = 23 # double
PL_NCHARS = 24 # size_t, const char *
PL_UTF8_CHARS = 25 # const char *
PL_UTF8_STRING = 26 # const char *
PL_INT64 = 27 # int64_t
PL_NUTF8_CHARS = 28 # size_t, const char *
PL_NUTF8_CODES = 29 # size_t, const char *
PL_NUTF8_STRING = 30 # size_t, const char *
PL_NWCHARS = 31 # size_t, const wchar_t *
PL_NWCODES = 32 # size_t, const wchar_t *
PL_NWSTRING = 33 # size_t, const wchar_t *
PL_MBCHARS = 34 # const char *
PL_MBCODES = 35 # const char *
PL_MBSTRING = 36 # const char *
PL_INTPTR = 37 # intptr_t
PL_CHAR = 38 # int
PL_CODE = 39 # int
PL_BYTE = 40 # int
# PL_skip_list(
PL_PARTIAL_LIST = 41 # a partial list
PL_CYCLIC_TERM = 42 # a cyclic list/term
PL_NOT_A_LIST = 43 # Object is not a list
# dicts
PL_DICT = 44

REP_ISO_LATIN_1 = 0x0000 # output representation
REP_UTF8 = 0x00100000
REP_MB = 0x00200000

# /********************************
# * NON-DETERMINISTIC CALL/RETURN *
Expand Down Expand Up @@ -890,12 +847,6 @@ def PL_STRINGS_MARK():
PL_get_string_chars = _lib.PL_get_string
PL_get_string_chars.argtypes = [term_t, POINTER(c_char_p), c_int_p]

PL_get_chars = _lib.PL_get_chars # FIXME:
PL_get_chars.argtypes = [term_t, POINTER(c_char_p), c_uint]
PL_get_chars.restype = c_int

PL_get_chars = check_strings(None, 1)(PL_get_chars)

PL_get_integer = _lib.PL_get_integer
PL_get_integer.argtypes = [term_t, POINTER(c_int)]
PL_get_integer.restype = c_int
Expand Down Expand Up @@ -943,7 +894,6 @@ def PL_STRINGS_MARK():
PL_atom_chars.restype = c_char_p

PL_atom_wchars = _lib.PL_atom_wchars
PL_atom_wchars.argtypes = [atom_t, POINTER(c_size_t)]
PL_atom_wchars.restype = c_wchar_p

PL_predicate = _lib.PL_predicate
Expand Down Expand Up @@ -973,6 +923,7 @@ def PL_STRINGS_MARK():
PL_get_list.restype = c_int

PL_get_chars = _lib.PL_get_chars # FIXME
PL_get_wchars = _lib.PL_get_wchars

PL_close_query = _lib.PL_close_query
PL_close_query.argtypes = [qid_t]
Expand Down Expand Up @@ -1012,10 +963,6 @@ def PL_STRINGS_MARK():
PL_unify_atom.argtypes = [term_t, atom_t]
PL_unify_atom.restype = c_int

PL_unify_atom_chars = _lib.PL_unify_atom_chars
PL_unify_atom_chars.argtypes = [term_t, c_char_p]
PL_unify_atom_chars.restype = c_int

PL_unify_string_chars = _lib.PL_unify_string_chars
PL_unify_string_chars.argtypes = [term_t, c_char_p]
PL_unify_string_chars.restype = c_void_p
Expand Down Expand Up @@ -1174,8 +1121,6 @@ def PL_STRINGS_MARK():
PL_is_initialised = _lib.PL_is_initialised

intptr_t = c_long
ssize_t = intptr_t
wint_t = c_uint

PL_thread_self = _lib.PL_thread_self
PL_thread_self.restype = c_int
Expand Down
14 changes: 10 additions & 4 deletions src/pyswip/easy.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
PL_register_atom,
PL_atom_wchars,
PL_get_atom,
PL_get_wchars,
PL_unregister_atom,
PL_new_term_ref,
PL_compare,
Expand Down Expand Up @@ -72,6 +73,7 @@
PL_STRING,
PL_INTEGER,
PL_FLOAT,
PL_NIL,
PL_Q_NODEBUG,
PL_Q_CATCH_EXCEPTION,
PL_FA_NONDETERMINISTIC,
Expand All @@ -89,6 +91,7 @@
atom_t,
create_string_buffer,
c_char_p,
c_wchar_p,
functor_t,
c_int,
c_long,
Expand Down Expand Up @@ -120,7 +123,7 @@ def __init__(self, expected, got):
Exception.__init__(self, msg)


class Atom(object):
class Atom:
__slots__ = "handle", "chars"

def __init__(self, handleOrChars, chars=None):
Expand Down Expand Up @@ -306,7 +309,7 @@ def __hash__(self):
return self.handle


class Functor(object):
class Functor:
__slots__ = "handle", "name", "arity", "args", "__value", "a0"
func = {}

Expand Down Expand Up @@ -439,8 +442,9 @@ def putList(l, ls): # noqa: E741

def getAtomChars(t):
"""If t is an atom, return it as a string, otherwise raise InvalidTypeError."""
s = c_char_p()
if PL_get_chars(t, byref(s), CVT_ATOM | REP_UTF8):
s = c_wchar_p()
ln = c_size_t()
if PL_get_wchars(t, byref(ln), byref(s), CVT_ATOM | REP_UTF8):
return s.value
else:
raise InvalidTypeError("atom")
Expand Down Expand Up @@ -497,6 +501,8 @@ def getTerm(t):
p = PL_term_type(t)
if p < PL_TERM:
res = _getterm_router[p](t)
elif p == PL_NIL:
return []
elif PL_is_list(t):
res = getList(t)
elif p == PL_DICT:
Expand Down
14 changes: 14 additions & 0 deletions src/pyswip/errors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@

__all__ = "PrologError", "NestedQueryError"

class PrologError(Exception):
pass


class NestedQueryError(PrologError):
"""
SWI-Prolog does not accept nested queries, that is, opening a query while the previous one was not closed.
As this error may be somewhat difficult to debug in foreign code, it is automatically treated inside PySwip
"""

pass
14 changes: 1 addition & 13 deletions src/pyswip/prolog.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
term_t,
control_t,
)
from pyswip.errors import PrologError, NestedQueryError


__all__ = "PrologError", "NestedQueryError", "Prolog"
Expand All @@ -67,19 +68,6 @@
RE_PLACEHOLDER = re.compile(r"%p")


class PrologError(Exception):
pass


class NestedQueryError(PrologError):
"""
SWI-Prolog does not accept nested queries, that is, opening a query while the previous one was not closed.
As this error may be somewhat difficult to debug in foreign code, it is automatically treated inside PySwip
"""

pass


def __initialize():
args = []
args.append("./")
Expand Down
1 change: 1 addition & 0 deletions tests/105.pl
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Prolog file with error
4 changes: 4 additions & 0 deletions tests/139.pl
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
:-op(800, fx, ¬).
:-op(802, xfy, ∨).

m_Proposition_Binary_x_y(X ∨ Y, X, Y).
24 changes: 24 additions & 0 deletions tests/test_issues.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
import sys
import unittest

import pytest


class TestIssues(unittest.TestCase):
"""Each test method is named after the issue it is testing. The docstring
Expand Down Expand Up @@ -290,3 +292,25 @@ def test_functor_return(self):

soln = [s["Y"] for s in p.query("friend(john,Y), father(Y,kur)", maxresult=1)]
self.assertEqual(soln[0], "son(miki)")

@pytest.mark.skip("Skip until v0.3.3")
def test_issue_141(self):
from pyswip import Prolog
fixture = [
{"X": 1, "C": "x"},
{"X": 2, "C": "y"},
]
ls = list(Prolog.query("X = point{x:1,y:2}.C."))
self.assertEqual(fixture, ls)

@pytest.mark.skip("Skip until v0.3.3")
def test_issue_139(self):
from pyswip import Prolog
Prolog.consult("139.pl", relative_to=__file__)
list(Prolog.query(f"m_Proposition_Binary_x_y(∨(¬(p), q), A, B)."))

@pytest.mark.skip("Skip until v0.3.3")
def test_issue_105(self):
from pyswip import Prolog
self.assertRaises(Exception, lambda: Prolog.consult("105.pl", catcherrors=False))

Loading