almostearthling / pyclips

PyCLIPS - a Python module to integrate CLIPS into Python
Other
35 stars 18 forks source link

Error when setting a clips class instance multislot to [ ] #9

Open gitttt opened 6 years ago

gitttt commented 6 years ago
import clips

C = clips.BuildClass("C", "(is-a USER)(multislot s)")
i = clips.BuildInstance("test1", C)
#i.Slots['s'] = clips.Multifield([])  # error
i.Slots['s'] = []  # error
#i.Slots['s'] = clips.Multifield(["1", "4"])  # no error
#i.Slots['s'] = ["1", "4"]  # no error
print i.Slots["s"]

I am getting this error: _clips.ClipsError: C09: unable to understand argument

Stacktrace:

File "\\VBOXSVR\vagrant\return_empty_list_bug.py", line 6, in <module>
  i.Slots['s'] = [] # error
File "c:\Python27\Lib\site-packages\clips\_clips_wrap.py", line 175, in _WRAPPER
  return f(self, *args)
File "c:\Python27\Lib\site-packages\clips\_clips_wrap.py", line 269, in _WRAPPER
  return f(self, *newargs)
File "c:\Python27\Lib\site-packages\clips\_clips_wrap.py", line 2506, in __setitem__
  _c.directPutSlot(self.__instance, name, _py2cl(v))

_clips.ClipsError: C09: unable to understand argument
gitttt commented 6 years ago

The problem seems to be in file clipsmodule.c line 1788:

case MULTIFIELD:
    if(!PyList_Check(value))
        goto fail;
    n = PyList_Size(value);
    if(n == 0) goto fail;          // <---- This seems to cause the error.
    if(!(do_value = EnvCreateMultifield(env, n)))
        goto fail;
    for(i2 = 0; i2 < n; i2++) {
        item = PyList_GetItem(value, i2);
        if(!item)
            goto fail;
        if(!i_py2do_mfhelp_e(env, item, do_value, (int)(i2 + 1)))
            goto fail;
    }
    break;  /* n is still good for below */
gitttt commented 6 years ago

Why did you add this check? What will happen if I uncomment it?

almostearthling commented 6 years ago

In fact I don't really remember why at the moment: the APG states that multifields can be of zero length - in which case the end index is lower than the begin index! Probably some specific code should be written to handle this case in the clips_to_python and python_to_clips multifield conversion helpers, indeed because of the peculiarity of this indexing method.

gitttt commented 6 years ago

Which helper functions do you mean? _py2cl() and _cl2py() in _clips_wrap.py?

almostearthling commented 6 years ago

No, i mean the lower-level i_do2py...() and i_py2do...() function groups in _clipsmodule.c starting at line 1476.

gitttt commented 6 years ago

Any hint what this "specific code" to handle this case should do? It seems to work if I simply comment out the check.

almostearthling commented 6 years ago

The 0 value was used in that code as an initializer for Py_ssize_t (line 1756), so I used that value to determine that something went wrong. Probably I shouldn't have used 0 and maybe Py_ssize_t in the first place, and initialize the two sizes in some different way - for instance -1. Maybe it would be safe to switch back to plain ints, use -1 for an initializer, check whether n < 0 and in such case goto fail.