1818# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1919# SOFTWARE.
2020
21- from pyswip .core import *
21+ import inspect
22+ from typing import Union , Callable , Optional
23+
24+ from pyswip .core import (
25+ PL_new_atom ,
26+ PL_register_atom ,
27+ PL_atom_wchars ,
28+ PL_get_atom ,
29+ PL_unregister_atom ,
30+ PL_new_term_ref ,
31+ PL_compare ,
32+ PL_get_chars ,
33+ PL_copy_term_ref ,
34+ PL_unify_atom ,
35+ PL_unify_string_chars ,
36+ PL_unify_integer ,
37+ PL_unify_bool ,
38+ PL_unify_float ,
39+ PL_unify_list ,
40+ PL_unify_nil ,
41+ PL_term_type ,
42+ PL_put_term ,
43+ PL_new_functor ,
44+ PL_functor_name ,
45+ PL_functor_arity ,
46+ PL_get_functor ,
47+ PL_new_term_refs ,
48+ PL_get_arg ,
49+ PL_cons_functor_v ,
50+ PL_put_atom_chars ,
51+ PL_put_integer ,
52+ PL_put_functor ,
53+ PL_put_nil ,
54+ PL_cons_list ,
55+ PL_get_long ,
56+ PL_get_float ,
57+ PL_is_list ,
58+ PL_get_list ,
59+ PL_register_foreign_in_module ,
60+ PL_call ,
61+ PL_new_module ,
62+ PL_pred ,
63+ PL_open_query ,
64+ PL_next_solution ,
65+ PL_cut_query ,
66+ PL_close_query ,
67+ PL_VARIABLE ,
68+ PL_STRINGS_MARK ,
69+ PL_TERM ,
70+ PL_DICT ,
71+ PL_ATOM ,
72+ PL_STRING ,
73+ PL_INTEGER ,
74+ PL_FLOAT ,
75+ PL_Q_NODEBUG ,
76+ PL_Q_CATCH_EXCEPTION ,
77+ PL_FA_NONDETERMINISTIC ,
78+ CVT_VARIABLE ,
79+ BUF_RING ,
80+ REP_UTF8 ,
81+ CVT_ATOM ,
82+ CVT_STRING ,
83+ CFUNCTYPE ,
84+ cleaned ,
85+ cast ,
86+ c_size_t ,
87+ byref ,
88+ c_void_p ,
89+ atom_t ,
90+ create_string_buffer ,
91+ c_char_p ,
92+ functor_t ,
93+ c_int ,
94+ c_long ,
95+ c_double ,
96+ foreign_t ,
97+ term_t ,
98+ control_t ,
99+ module_t ,
100+ )
22101
23102
24103integer_types = (int ,)
@@ -134,11 +213,7 @@ def __hash__(self):
134213 return self .handle
135214
136215
137- def isstr (s ):
138- return isinstance (s , str )
139-
140-
141- class Variable (object ):
216+ class Variable :
142217 __slots__ = "handle" , "chars"
143218
144219 def __init__ (self , handle = None , name = None ):
@@ -170,7 +245,7 @@ def _fun(self, value, t):
170245 if type (value ) == Atom :
171246 fun = PL_unify_atom
172247 value = value .handle
173- elif isstr (value ):
248+ elif isinstance (value , str ):
174249 fun = PL_unify_string_chars
175250 value = value .encode ()
176251 elif type (value ) == int :
@@ -284,7 +359,9 @@ def fromTerm(cls, term):
284359
285360 fromTerm = classmethod (fromTerm )
286361
287- value = property (lambda s : s .__value )
362+ @property
363+ def value (self ):
364+ return self .__value
288365
289366 def __call__ (self , * args ):
290367 assert self .arity == len (args ) # FIXME: Put a decent error message
@@ -346,12 +423,10 @@ def putTerm(term, value):
346423 value .put (term )
347424 elif isinstance (value , list ):
348425 putList (term , value )
349- elif isinstance (value , Atom ):
350- print ("ATOM" )
351426 elif isinstance (value , Functor ):
352427 PL_put_functor (term , value .handle )
353428 else :
354- raise Exception ("Not implemented" )
429+ raise Exception (f "Not implemented for type: { type ( value ) } " )
355430
356431
357432def putList (l , ls ): # noqa: E741
@@ -498,8 +573,6 @@ def getVariable(t):
498573
499574
500575def _callbackWrapper (arity = 1 , nondeterministic = False ):
501- global arities
502-
503576 res = arities .get ((arity , nondeterministic ))
504577 if res is None :
505578 if nondeterministic :
@@ -514,8 +587,6 @@ def _callbackWrapper(arity=1, nondeterministic=False):
514587
515588
516589def _foreignWrapper (fun , nondeterministic = False ):
517- global funwraps
518-
519590 res = funwraps .get (fun )
520591 if res is None :
521592
@@ -535,32 +606,42 @@ def wrapper(*args):
535606cwraps = []
536607
537608
538- def registerForeign (func , name = None , arity = None , flags = 0 ):
539- """Register a Python predicate
540- ``func``: Function to be registered. The function should return a value in
541- ``foreign_t``, ``True`` or ``False``.
542- ``name`` : Name of the function. If this value is not used, ``func.func_name``
543- should exist.
544- ``arity``: Arity (number of arguments) of the function. If this value is not
545- used, ``func.arity`` should exist.
609+ def registerForeign (
610+ func : Callable , name : str = "" , arity : Optional [int ] = None , flags : int = 0
611+ ):
546612 """
547- global cwraps
613+ Registers a Python callable as a Prolog predicate
548614
549- if arity is None :
550- arity = func .arity
615+ :param func: Callable to be registered. The callable should return a value in ``foreign_t``, ``True`` or ``False``.
616+ :param name: Name of the callable. If the name is not specified, it is derived from ``func.__name__``.
617+ :param arity: Number of parameters of the callable. If not specified, it is derived from the callable signature.
618+ :param flags: Only supported flag is ``PL_FA_NONDETERMINISTIC``.
551619
552- if name is None :
553- name = func .__name__
620+ See: `PL_register_foreign <https://www.swi-prolog.org/pldoc/man?CAPI=PL_register_foreign>`_.
554621
622+ .. Note::
623+ This function is deprecated.
624+ Use :py:meth:`Prolog.register_foreign` instead.
625+ """
626+ if not callable (func ):
627+ raise ValueError ("func is not callable" )
555628 nondeterministic = bool (flags & PL_FA_NONDETERMINISTIC )
629+ if arity is None :
630+ # backward compatibility
631+ if hasattr (func , "arity" ):
632+ arity = func .arity
633+ else :
634+ arity = len (inspect .signature (func ).parameters )
635+ if nondeterministic :
636+ arity -= 1
637+ if not name :
638+ name = func .__name__
556639
557640 cwrap = _callbackWrapper (arity , nondeterministic )
558641 fwrap = _foreignWrapper (func , nondeterministic )
559642 fwrap2 = cwrap (fwrap )
560643 cwraps .append (fwrap2 )
561- return PL_register_foreign (name , arity , fwrap2 , flags )
562- # return PL_register_foreign(name, arity,
563- # _callbackWrapper(arity)(_foreignWrapper(func)), flags)
644+ return PL_register_foreign_in_module (None , name , arity , fwrap2 , flags )
564645
565646
566647newTermRef = PL_new_term_ref
@@ -588,13 +669,30 @@ def call(*terms, **kwargs):
588669 return PL_call (t .handle , module )
589670
590671
591- def newModule (name ):
592- """Create a new module.
593- ``name``: An Atom or a string
672+ def newModule (name : Union [str , Atom ]) -> module_t :
673+ """
674+ Returns a module with the given name.
675+
676+ The module is created if it does not exist.
677+
678+ .. NOTE::
679+ This function is deprecated. Use ``module`` instead.
680+
681+ :param name: Name of the module
682+ """
683+ return module (name )
684+
685+
686+ def module (name : Union [str , Atom ]) -> module_t :
687+ """
688+ Returns a module with the given name.
689+
690+ The module is created if it does not exist.
691+
692+ :param name: Name of the module
594693 """
595694 if isinstance (name , str ):
596695 name = Atom (name )
597-
598696 return PL_new_module (name .handle )
599697
600698
0 commit comments