00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <plang/term.h>
00021 #include <plang/database.h>
00022 #include "term-priv.h"
00023 #include "context-priv.h"
00024 #include "rbtree-priv.h"
00025 #include "inst-priv.h"
00026 #include <string.h>
00027 #include <stdarg.h>
00028 #include <stdio.h>
00029
00030
00031
00032 P_INLINE p_term *p_term_deref_non_null(const p_term *term)
00033 {
00034 for(;;) {
00035 if (term->header.type & P_TERM_VARIABLE) {
00036 if (!term->var.value)
00037 break;
00038 term = term->var.value;
00039 } else {
00040 break;
00041 }
00042 }
00043 return (p_term *)term;
00044 }
00045
00060
00061
00173 p_term *p_term_create_functor(p_context *context, p_term *name, int arg_count)
00174 {
00175 struct p_term_functor *term;
00176
00177
00178 if (!name || arg_count < 0)
00179 return 0;
00180 if (name->header.type != P_TERM_ATOM) {
00181 name = p_term_deref_non_null(name);
00182 if (name->header.type != P_TERM_ATOM)
00183 return 0;
00184 }
00185
00186
00187 if (!arg_count)
00188 return name;
00189
00190
00191 term = p_term_malloc
00192 (context, struct p_term_functor,
00193 sizeof(struct p_term_functor) +
00194 (sizeof(p_term *) * (unsigned int)(arg_count - 1)));
00195 if (!term)
00196 return 0;
00197 term->header.type = P_TERM_FUNCTOR;
00198 term->header.size = (unsigned int)arg_count;
00199 term->functor_name = name;
00200 return (p_term *)term;
00201 }
00202
00214 int p_term_bind_functor_arg(p_term *term, int index, p_term *value)
00215 {
00216 if (!term || term->header.type != P_TERM_FUNCTOR || !value)
00217 return 0;
00218 if (((unsigned int)index) >= term->header.size)
00219 return 0;
00220 if (term->functor.arg[index])
00221 return 0;
00222 term->functor.arg[index] = value;
00223 return 1;
00224 }
00225
00234 p_term *p_term_create_functor_with_args(p_context *context, p_term *name, p_term **args, int arg_count)
00235 {
00236 int index;
00237 p_term *term = p_term_create_functor(context, name, arg_count);
00238 if (!term)
00239 return 0;
00240 for (index = 0; index < arg_count; ++index)
00241 term->functor.arg[index] = args[index];
00242 return term;
00243 }
00244
00252 p_term *p_term_create_list(p_context *context, p_term *head, p_term *tail)
00253 {
00254 struct p_term_list *term = p_term_new(context, struct p_term_list);
00255 if (!term)
00256 return 0;
00257 term->header.type = P_TERM_LIST;
00258 term->header.size = 2;
00259 term->head = head;
00260 term->tail = tail;
00261 return (p_term *)term;
00262 }
00263
00274 void p_term_set_tail(p_term *list, p_term *tail)
00275 {
00276 if (!list || list->header.type != P_TERM_LIST)
00277 return;
00278 list->list.tail = tail;
00279 }
00280
00300 p_term *p_term_create_atom(p_context *context, const char *name)
00301 {
00302 return p_term_create_atom_n(context, name, name ? strlen(name) : 0);
00303 }
00304
00324 p_term *p_term_create_atom_n(p_context *context, const char *name, size_t len)
00325 {
00326 unsigned int hash;
00327 const char *n;
00328 size_t nlen;
00329 p_term *atom;
00330
00331
00332 hash = 0;
00333 n = name;
00334 nlen = len;
00335 while (nlen > 0) {
00336 hash = hash * 5 + (((unsigned int)(*n++)) & 0xFF);
00337 --nlen;
00338 }
00339 hash %= P_CONTEXT_HASH_SIZE;
00340 atom = context->atom_hash[hash];
00341 while (atom != 0) {
00342 if (atom->header.size == len &&
00343 !memcmp(atom->atom.name, name, len))
00344 return atom;
00345 atom = atom->atom.next;
00346 }
00347
00348
00349 atom = p_term_malloc
00350 (context, p_term, sizeof(struct p_term_atom) + len);
00351 if (!atom)
00352 return 0;
00353 atom->header.type = P_TERM_ATOM;
00354 atom->header.size = (unsigned int)len;
00355 atom->atom.next = context->atom_hash[hash];
00356 if (len > 0)
00357 memcpy(atom->atom.name, name, len);
00358 atom->atom.name[len] = '\0';
00359 context->atom_hash[hash] = atom;
00360 return atom;
00361 }
00362
00382 p_term *p_term_create_string(p_context *context, const char *str)
00383 {
00384 size_t len = str ? strlen(str) : 0;
00385 struct p_term_string *term = p_term_malloc
00386 (context, struct p_term_string, sizeof(struct p_term_string) + len);
00387 if (!term)
00388 return 0;
00389 term->header.type = P_TERM_STRING;
00390 term->header.size = (unsigned int)len;
00391 if (len > 0)
00392 memcpy(term->name, str, len);
00393 term->name[len] = '\0';
00394 return (p_term *)term;
00395 }
00396
00413 p_term *p_term_create_string_n(p_context *context, const char *str, size_t len)
00414 {
00415 struct p_term_string *term = p_term_malloc
00416 (context, struct p_term_string, sizeof(struct p_term_string) + len);
00417 if (!term)
00418 return 0;
00419 term->header.type = P_TERM_STRING;
00420 term->header.size = (unsigned int)len;
00421 if (len > 0)
00422 memcpy(term->name, str, len);
00423 term->name[len] = '\0';
00424 return (p_term *)term;
00425 }
00426
00435 p_term *p_term_create_variable(p_context *context)
00436 {
00437 struct p_term_var *term = p_term_new(context, struct p_term_var);
00438 if (!term)
00439 return 0;
00440 term->header.type = P_TERM_VARIABLE;
00441 return (p_term *)term;
00442 }
00443
00454 p_term *p_term_create_named_variable(p_context *context, const char *name)
00455 {
00456 size_t len = name ? strlen(name) : 0;
00457 struct p_term_var *term;
00458 if (!len)
00459 return p_term_create_variable(context);
00460 term = p_term_malloc(context, struct p_term_var,
00461 sizeof(struct p_term_var) + len + 1);
00462 if (!term)
00463 return 0;
00464 term->header.type = P_TERM_VARIABLE;
00465 term->header.size = (unsigned int)len;
00466 strcpy((char *)(term + 1), name);
00467 return (p_term *)term;
00468 }
00469
00484 p_term *p_term_create_member_variable(p_context *context, p_term *object, p_term *name, int auto_create)
00485 {
00486 struct p_term_member_var *term;
00487 if (!name || !object)
00488 return 0;
00489 name = p_term_deref_non_null(name);
00490 if (name->header.type != P_TERM_ATOM)
00491 return 0;
00492 term = p_term_new(context, struct p_term_member_var);
00493 if (!term)
00494 return 0;
00495 term->header.type = P_TERM_MEMBER_VARIABLE;
00496 term->header.size = (auto_create ? 1 : 0);
00497 term->object = object;
00498 term->name = name;
00499 return (p_term *)term;
00500 }
00501
00511 p_term *p_term_create_integer(p_context *context, int value)
00512 {
00513 struct p_term_integer *term =
00514 p_term_new(context, struct p_term_integer);
00515 if (!term)
00516 return 0;
00517 term->header.type = P_TERM_INTEGER;
00518 #if defined(P_TERM_64BIT)
00519
00520 term->header.size = (unsigned int)value;
00521 #else
00522 term->value = value;
00523 #endif
00524 return (p_term *)term;
00525 }
00526
00536 p_term *p_term_create_real(p_context *context, double value)
00537 {
00538 struct p_term_real *term = p_term_new(context, struct p_term_real);
00539 if (!term)
00540 return 0;
00541 term->header.type = P_TERM_REAL;
00542 term->value = value;
00543 return (p_term *)term;
00544 }
00545
00557 p_term *p_term_nil_atom(p_context *context)
00558 {
00559 return context->nil_atom;
00560 }
00561
00573 p_term *p_term_prototype_atom(p_context *context)
00574 {
00575 return context->prototype_atom;
00576 }
00577
00589 p_term *p_term_class_name_atom(p_context *context)
00590 {
00591 return context->class_name_atom;
00592 }
00593
00609 p_term *p_term_deref(const p_term *term)
00610 {
00611 return term ? p_term_deref_non_null(term) : 0;
00612 }
00613
00629 p_term *p_term_deref_member(p_context *context, p_term *term)
00630 {
00631 p_term *object;
00632 p_term *value;
00633 if (!term)
00634 return 0;
00635 term = p_term_deref_non_null(term);
00636 if (term->header.type != P_TERM_MEMBER_VARIABLE)
00637 return term;
00638 object = p_term_deref_member(context, term->member_var.object);
00639 if (!object || object->header.type != P_TERM_OBJECT)
00640 return term;
00641 value = p_term_property(context, object, term->member_var.name);
00642 if (value) {
00643
00644 p_term_bind_variable(context, term, value, P_BIND_DEFAULT);
00645 } else if (term->header.size) {
00646
00647
00648 value = p_term_create_variable(context);
00649 p_term_add_property
00650 (context, object, term->member_var.name, value);
00651 p_term_bind_variable(context, term, value, P_BIND_DEFAULT);
00652 }
00653 return p_term_deref(value);
00654 }
00655
00673 p_term *p_term_deref_own_member(p_context *context, p_term *term)
00674 {
00675 p_term *object;
00676 p_term *value;
00677 if (!term)
00678 return 0;
00679 term = p_term_deref_non_null(term);
00680 if (term->header.type != P_TERM_MEMBER_VARIABLE)
00681 return term;
00682 object = p_term_deref_member(context, term->member_var.object);
00683 if (!object || object->header.type != P_TERM_OBJECT)
00684 return term;
00685 value = p_term_own_property(context, object, term->member_var.name);
00686 if (value) {
00687
00688 p_term_bind_variable(context, term, value, P_BIND_DEFAULT);
00689 } else if (term->header.size) {
00690
00691
00692 value = p_term_create_variable(context);
00693 p_term_add_property
00694 (context, object, term->member_var.name, value);
00695 p_term_bind_variable(context, term, value, P_BIND_DEFAULT);
00696 }
00697 return term;
00698 }
00699
00709 int p_term_type(const p_term *term)
00710 {
00711 if (term)
00712 return (int)(p_term_deref_non_null(term)->header.type);
00713 else
00714 return P_TERM_INVALID;
00715 }
00716
00727 int p_term_arg_count(const p_term *term)
00728 {
00729 if (!term)
00730 return 0;
00731
00732 if (term->header.type == P_TERM_FUNCTOR ||
00733 term->header.type == P_TERM_PREDICATE)
00734 return (int)(term->header.size);
00735 term = p_term_deref_non_null(term);
00736 if (term->header.type == P_TERM_FUNCTOR ||
00737 term->header.type == P_TERM_PREDICATE)
00738 return (int)(term->header.size);
00739 else
00740 return 0;
00741 }
00742
00753 const char *p_term_name(const p_term *term)
00754 {
00755 if (!term)
00756 return 0;
00757 term = p_term_deref_non_null(term);
00758 switch (term->header.type) {
00759 case P_TERM_FUNCTOR:
00760 return p_term_name(term->functor.functor_name);
00761 case P_TERM_ATOM:
00762 return term->atom.name;
00763 case P_TERM_STRING:
00764 return term->string.name;
00765 case P_TERM_PREDICATE:
00766 return p_term_name(term->predicate.name);
00767 case P_TERM_VARIABLE:
00768 if (term->header.size > 0)
00769 return (const char *)(&(term->var) + 1);
00770 break;
00771 case P_TERM_MEMBER_VARIABLE:
00772 return p_term_name(term->member_var.name);
00773 default: break;
00774 }
00775 return 0;
00776 }
00777
00790 size_t p_term_name_length(const p_term *term)
00791 {
00792 if (!term)
00793 return 0;
00794 term = p_term_deref_non_null(term);
00795 switch (term->header.type) {
00796 case P_TERM_FUNCTOR:
00797 return p_term_name_length(term->functor.functor_name);
00798 case P_TERM_PREDICATE:
00799 return p_term_name_length(term->predicate.name);
00800 case P_TERM_ATOM:
00801 case P_TERM_STRING:
00802 case P_TERM_VARIABLE:
00803 return term->header.size;
00804 case P_TERM_MEMBER_VARIABLE:
00805 return p_term_name_length(term->member_var.name);
00806 default: break;
00807 }
00808 return 0;
00809 }
00810
00811
00812 int _p_term_next_utf8(const char *str, size_t len, size_t *size)
00813 {
00814 int ch, ch2;
00815 size_t req, sz;
00816 if (!len) {
00817 *size = 0;
00818 return -1;
00819 }
00820 ch = ((int)(*str)) & 0xFF;
00821 sz = 1;
00822 if (ch < 0x80) {
00823 req = 0;
00824 } else if ((ch & 0xE0) == 0xC0) {
00825 ch &= 0x1F;
00826 req = 1;
00827 ++str;
00828 --len;
00829 } else if ((ch & 0xF0) == 0xE0) {
00830 ch &= 0x0F;
00831 req = 2;
00832 ++str;
00833 --len;
00834 } else if ((ch & 0xF8) == 0xF0) {
00835 ch &= 0x07;
00836 req = 3;
00837 ++str;
00838 --len;
00839 } else {
00840 ++str;
00841 --len;
00842 invalid:
00843
00844 while (len > 0) {
00845 ch = ((int)(*str)) & 0xFF;
00846 if (ch < 0x80 || (ch & 0xE0) == 0xC0 ||
00847 (ch & 0xF0) == 0xE0 || (ch & 0xF8) == 0xF0)
00848 break;
00849 ++sz;
00850 ++str;
00851 --len;
00852 }
00853 *size = sz;
00854 return -1;
00855 }
00856 while (req > 0) {
00857 if (!len)
00858 goto invalid;
00859 ch2 = ((int)(*str)) & 0xFF;
00860 if ((ch2 & 0xC0) == 0x80)
00861 ch = (ch << 6) | (ch2 & 0x3F);
00862 else
00863 goto invalid;
00864 ++str;
00865 --len;
00866 ++sz;
00867 --req;
00868 }
00869 *size = sz;
00870 return ch;
00871 }
00872
00885 size_t p_term_name_length_utf8(const p_term *term)
00886 {
00887 const char *name;
00888 size_t byte_len;
00889 size_t utf8_len;
00890 size_t ch_size;
00891 if (!term)
00892 return 0;
00893 term = p_term_deref_non_null(term);
00894 switch (term->header.type) {
00895 case P_TERM_FUNCTOR:
00896 return p_term_name_length_utf8(term->functor.functor_name);
00897 case P_TERM_PREDICATE:
00898 return p_term_name_length_utf8(term->predicate.name);
00899 case P_TERM_ATOM:
00900 name = term->atom.name;
00901 byte_len = term->header.size;
00902 break;
00903 case P_TERM_STRING:
00904 name = term->string.name;
00905 byte_len = term->header.size;
00906 break;
00907 case P_TERM_VARIABLE:
00908 byte_len = term->header.size;
00909 if (!byte_len)
00910 return 0;
00911 name = (const char *)(&(term->var) + 1);
00912 break;
00913 case P_TERM_MEMBER_VARIABLE:
00914 return p_term_name_length_utf8(term->member_var.name);
00915 default: return 0;
00916 }
00917 utf8_len = 0;
00918 while (byte_len > 0) {
00919 _p_term_next_utf8(name, byte_len, &ch_size);
00920 name += ch_size;
00921 byte_len -= ch_size;
00922 ++utf8_len;
00923 }
00924 return utf8_len;
00925 }
00926
00936 p_term *p_term_functor(const p_term *term)
00937 {
00938 if (!term)
00939 return 0;
00940
00941 if (term->header.type == P_TERM_FUNCTOR)
00942 return term->functor.functor_name;
00943 else if (term->header.type == P_TERM_PREDICATE)
00944 return term->predicate.name;
00945 term = p_term_deref_non_null(term);
00946 if (term->header.type == P_TERM_FUNCTOR)
00947 return term->functor.functor_name;
00948 else if (term->header.type == P_TERM_PREDICATE)
00949 return term->predicate.name;
00950 return 0;
00951 }
00952
00963 p_term *p_term_arg(const p_term *term, int index)
00964 {
00965 if (!term)
00966 return 0;
00967
00968 if (term->header.type != P_TERM_FUNCTOR) {
00969 term = p_term_deref_non_null(term);
00970 if (term->header.type != P_TERM_FUNCTOR)
00971 return 0;
00972 }
00973 if (((unsigned int)index) < term->header.size)
00974 return term->functor.arg[index];
00975 else
00976 return 0;
00977 }
00978
00988 int p_term_integer_value(const p_term *term)
00989 {
00990 if (!term)
00991 return 0;
00992 #if defined(P_TERM_64BIT)
00993
00994 if (term->header.type == P_TERM_INTEGER)
00995 return (int)(term->header.size);
00996 term = p_term_deref_non_null(term);
00997 if (term->header.type == P_TERM_INTEGER)
00998 return (int)(term->header.size);
00999 else
01000 return 0;
01001 #else
01002 if (term->header.type == P_TERM_INTEGER)
01003 return term->integer.value;
01004 term = p_term_deref_non_null(term);
01005 if (term->header.type == P_TERM_INTEGER)
01006 return term->integer.value;
01007 else
01008 return 0;
01009 #endif
01010 }
01011
01021 double p_term_real_value(const p_term *term)
01022 {
01023 if (!term)
01024 return 0.0;
01025
01026 if (term->header.type == P_TERM_REAL)
01027 return term->real.value;
01028 term = p_term_deref_non_null(term);
01029 if (term->header.type == P_TERM_REAL)
01030 return term->real.value;
01031 else
01032 return 0.0;
01033 }
01034
01044 p_term *p_term_head(const p_term *term)
01045 {
01046 if (!term)
01047 return 0;
01048
01049 if (term->header.type == P_TERM_LIST)
01050 return term->list.head;
01051 term = p_term_deref_non_null(term);
01052 if (term->header.type == P_TERM_LIST)
01053 return term->list.head;
01054 else
01055 return 0;
01056 }
01057
01067 p_term *p_term_tail(const p_term *term)
01068 {
01069 if (!term)
01070 return 0;
01071
01072 if (term->header.type == P_TERM_LIST)
01073 return term->list.tail;
01074 term = p_term_deref_non_null(term);
01075 if (term->header.type == P_TERM_LIST)
01076 return term->list.tail;
01077 else
01078 return 0;
01079 }
01080
01092 p_term *p_term_object(const p_term *term)
01093 {
01094 if (!term)
01095 return 0;
01096
01097 if (term->header.type == P_TERM_MEMBER_VARIABLE)
01098 return term->member_var.object;
01099 term = p_term_deref_non_null(term);
01100 if (term->header.type == P_TERM_MEMBER_VARIABLE)
01101 return term->member_var.object;
01102 else
01103 return 0;
01104 }
01105
01116 p_term *p_term_create_object(p_context *context, p_term *prototype)
01117 {
01118 struct p_term_object *term;
01119 if (!prototype)
01120 return 0;
01121 prototype = p_term_deref_non_null(prototype);
01122 if (prototype->header.type != P_TERM_OBJECT)
01123 return 0;
01124 term = p_term_new(context, struct p_term_object);
01125 if (!term)
01126 return 0;
01127 term->header.type = P_TERM_OBJECT;
01128 term->header.size = 1;
01129 term->properties[0].name = context->prototype_atom;
01130 term->properties[0].value = prototype;
01131 return (p_term *)term;
01132 }
01133
01145 p_term *p_term_create_class_object(p_context *context, p_term *class_name, p_term *prototype)
01146 {
01147 struct p_term_object *term;
01148 if (!class_name)
01149 return 0;
01150 class_name = p_term_deref_non_null(class_name);
01151 if (class_name->header.type != P_TERM_ATOM)
01152 return 0;
01153 if (prototype) {
01154 prototype = p_term_deref_non_null(prototype);
01155 if (prototype->header.type != P_TERM_OBJECT)
01156 return 0;
01157 }
01158 term = p_term_new(context, struct p_term_object);
01159 if (!term)
01160 return 0;
01161 term->header.type = P_TERM_OBJECT;
01162 if (prototype) {
01163
01164 term->properties[0].name = context->prototype_atom;
01165 term->properties[0].value = prototype;
01166 term->properties[1].name = context->class_name_atom;
01167 term->properties[1].value = class_name;
01168 term->header.size = 2;
01169 } else {
01170 term->properties[0].name = context->class_name_atom;
01171 term->properties[0].value = class_name;
01172 term->header.size = 1;
01173 }
01174 return (p_term *)term;
01175 }
01176
01192 int p_term_add_property(p_context *context, p_term *term, p_term *name, p_term *value)
01193 {
01194
01195 if (!term || !name)
01196 return 0;
01197 term = p_term_deref_non_null(term);
01198 if (term->header.type != P_TERM_OBJECT)
01199 return 0;
01200 name = p_term_deref_non_null(name);
01201 if (name->header.type != P_TERM_ATOM)
01202 return 0;
01203 if (name == context->prototype_atom ||
01204 name == context->class_name_atom)
01205 return 0;
01206
01207
01208 while (term->header.size >= P_TERM_MAX_PROPS && term->object.next)
01209 term = term->object.next;
01210 if (term->header.size >= P_TERM_MAX_PROPS) {
01211
01212 p_term *block = p_term_malloc
01213 (context, p_term, sizeof(struct p_term_object));
01214 if (!block)
01215 return 0;
01216 block->header.type = P_TERM_OBJECT;
01217 term->object.next = block;
01218 term = block;
01219 }
01220
01221
01222 term->object.properties[term->header.size].name = name;
01223 term->object.properties[term->header.size].value = value;
01224 ++(term->header.size);
01225 return 1;
01226 }
01227
01239 p_term *p_term_property(p_context *context, const p_term *term, const p_term *name)
01240 {
01241 const p_term *block;
01242 unsigned int index;
01243
01244
01245 if (!term || !name)
01246 return 0;
01247 term = p_term_deref_non_null(term);
01248 if (term->header.type != P_TERM_OBJECT)
01249 return 0;
01250 name = p_term_deref_non_null(name);
01251 if (name->header.type != P_TERM_ATOM)
01252 return 0;
01253
01254 for (;;) {
01255
01256 block = term;
01257 do {
01258 for (index = 0; index < block->header.size; ++index) {
01259 if (block->object.properties[index].name == name)
01260 return block->object.properties[index].value;
01261 }
01262 block = block->object.next;
01263 } while (block != 0);
01264
01265
01266 if (term->object.properties[0].name != context->prototype_atom)
01267 break;
01268 term = term->object.properties[0].value;
01269 }
01270 return 0;
01271 }
01272
01283 p_term *p_term_own_property(p_context *context, const p_term *term, const p_term *name)
01284 {
01285 unsigned int index;
01286
01287
01288 if (!term || !name)
01289 return 0;
01290 term = p_term_deref_non_null(term);
01291 if (term->header.type != P_TERM_OBJECT)
01292 return 0;
01293 name = p_term_deref_non_null(name);
01294 if (name->header.type != P_TERM_ATOM)
01295 return 0;
01296
01297
01298 do {
01299 for (index = 0; index < term->header.size; ++index) {
01300 if (term->object.properties[index].name == name)
01301 return term->object.properties[index].value;
01302 }
01303 term = term->object.next;
01304 } while (term != 0);
01305 return 0;
01306 }
01307
01328 int p_term_set_own_property(p_context *context, p_term *term, p_term *name, p_term *value)
01329 {
01330 unsigned int index;
01331
01332
01333 if (!term || !name)
01334 return 0;
01335 term = p_term_deref_non_null(term);
01336 if (term->header.type != P_TERM_OBJECT)
01337 return 0;
01338 name = p_term_deref_non_null(name);
01339 if (name->header.type != P_TERM_ATOM)
01340 return 0;
01341
01342
01343 do {
01344 for (index = 0; index < term->header.size; ++index) {
01345 if (term->object.properties[index].name == name) {
01346 term->object.properties[index].value = value;
01347 return 1;
01348 }
01349 }
01350 term = term->object.next;
01351 } while (term != 0);
01352
01353
01354 return p_term_add_property(context, term, name, value);
01355 }
01356
01367 int p_term_is_instance_object(p_context *context, const p_term *term)
01368 {
01369 p_term *name;
01370 if (!term)
01371 return 0;
01372 if (term->header.type != P_TERM_OBJECT) {
01373 term = p_term_deref_non_null(term);
01374 if (term->header.type != P_TERM_OBJECT)
01375 return 0;
01376 }
01377 name = context->class_name_atom;
01378 return term->object.properties[0].name != name &&
01379 term->object.properties[1].name != name;
01380 }
01381
01392 int p_term_is_class_object(p_context *context, const p_term *term)
01393 {
01394 p_term *name;
01395 if (!term)
01396 return 0;
01397 if (term->header.type != P_TERM_OBJECT) {
01398 term = p_term_deref_non_null(term);
01399 if (term->header.type != P_TERM_OBJECT)
01400 return 0;
01401 }
01402 name = context->class_name_atom;
01403 return term->object.properties[0].name == name ||
01404 term->object.properties[1].name == name;
01405 }
01406
01416 int p_term_inherits(p_context *context, const p_term *term1, const p_term *term2)
01417 {
01418 p_term *pname = context->prototype_atom;
01419 if (!term1 || !term2)
01420 return 0;
01421 term2 = p_term_deref_non_null(term2);
01422 if (term2->header.type != P_TERM_OBJECT)
01423 return 0;
01424 do {
01425 term1 = p_term_deref_non_null(term1);
01426 if (term1 == term2)
01427 return 1;
01428 if (term1->header.type != P_TERM_OBJECT)
01429 break;
01430 if (term1->object.properties[0].name != pname)
01431 break;
01432 term1 = term1->object.properties[0].value;
01433 } while (term1 != 0);
01434 return 0;
01435 }
01436
01447 int p_term_is_instance_of(p_context *context, const p_term *term1, const p_term *term2)
01448 {
01449 if (!p_term_is_instance_object(context, term1))
01450 return 0;
01451 if (!p_term_is_class_object(context, term2))
01452 return 0;
01453 return p_term_inherits(context, term1, term2);
01454 }
01455
01469 p_term *p_term_create_predicate(p_context *context, p_term *name, int arg_count)
01470 {
01471 struct p_term_predicate *term;
01472
01473
01474 if (!name || arg_count < 0)
01475 return 0;
01476 if (name->header.type != P_TERM_ATOM) {
01477 name = p_term_deref_non_null(name);
01478 if (name->header.type != P_TERM_ATOM)
01479 return 0;
01480 }
01481
01482
01483 term = p_term_new(context, struct p_term_predicate);
01484 if (!term)
01485 return 0;
01486 term->header.type = P_TERM_PREDICATE;
01487 term->header.size = (unsigned int)arg_count;
01488 term->name = name;
01489 return (p_term *)term;
01490 }
01491
01499 p_term *p_term_create_dynamic_clause(p_context *context, p_term *head, p_term *body)
01500 {
01501 struct p_term_clause *term =
01502 p_term_new(context, struct p_term_clause);
01503 p_code *code = _p_code_new();
01504 if (!term || !code)
01505 return 0;
01506 term->header.type = P_TERM_CLAUSE;
01507 _p_code_generate_dynamic_clause(context, head, body, code);
01508 _p_code_finish(code, &(term->clause_code));
01509 return (p_term *)term;
01510 }
01511
01512
01513 P_INLINE void p_term_add_indexed_clause
01514 (p_context *context, struct p_term_clause_list *list,
01515 struct p_term_clause *clause, int first)
01516 {
01517 if (!list->head) {
01518 list->head = clause;
01519 list->tail = clause;
01520 clause->next_index = 0;
01521 } else if (!first) {
01522 list->tail->next_index = clause;
01523 clause->next_index = 0;
01524 list->tail = clause;
01525 } else {
01526 clause->next_index = list->head;
01527 list->head = clause;
01528 }
01529 }
01530
01531
01532 P_INLINE void p_term_add_regular_clause
01533 (p_context *context, struct p_term_clause_list *list,
01534 p_term *clause, int first)
01535 {
01536 if (!list->head) {
01537 list->head = &(clause->clause);
01538 list->tail = &(clause->clause);
01539 clause->clause.next_clause = 0;
01540 } else if (!first) {
01541 list->tail->next_clause = &(clause->clause);
01542 clause->clause.next_clause = 0;
01543 list->tail = &(clause->clause);
01544 } else {
01545 clause->clause.next_clause = list->head;
01546 list->head = &(clause->clause);
01547 }
01548 }
01549
01550
01551 static void p_term_index_clause
01552 (p_context *context, p_term *predicate,
01553 struct p_term_clause *clause, int first)
01554 {
01555 p_rbkey key;
01556 p_rbnode *node;
01557
01558
01559
01560
01561 if (!_p_code_argument_key(&key, &(clause->clause_code),
01562 predicate->predicate.index_arg)) {
01563 p_term_add_indexed_clause
01564 (context, &(predicate->predicate.var_clauses),
01565 clause, first);
01566 return;
01567 }
01568
01569
01570 node = _p_rbtree_insert(&(predicate->predicate.index), &key);
01571 if (!node)
01572 return;
01573 p_term_add_indexed_clause(context, &(node->clauses), clause, first);
01574 }
01575
01576
01577 static void p_term_index_all_clauses
01578 (p_context *context, p_term *predicate)
01579 {
01580 struct p_term_clause *clause;
01581 p_rbkey key;
01582 p_rbkey keys[4];
01583 unsigned int counts[4];
01584 unsigned int arg;
01585 unsigned int max_count;
01586
01587
01588 if (predicate->header.size == 0) {
01589 predicate->predicate.dont_index = 1;
01590 return;
01591 }
01592
01593
01594
01595
01596 clause = predicate->predicate.clauses.head;
01597 for (arg = 0; arg < 4 && arg < predicate->header.size; ++arg) {
01598 if (!_p_code_argument_key
01599 (&(keys[arg]), &(clause->clause_code), arg)) {
01600 keys[arg].type = P_TERM_VARIABLE;
01601 keys[arg].size = 0;
01602 keys[arg].name = 0;
01603 }
01604 counts[arg] = 0;
01605 }
01606 while ((clause = clause->next_clause) != 0) {
01607 for (arg = 0; arg < 4 && arg < predicate->header.size; ++arg) {
01608 if (!_p_code_argument_key
01609 (&key, &(clause->clause_code), arg)) {
01610 key.type = P_TERM_VARIABLE;
01611 key.size = 0;
01612 key.name = 0;
01613 }
01614 if (_p_rbkey_compare_keys(&(keys[arg]), &key) != 0) {
01615 ++(counts[arg]);
01616 keys[arg] = key;
01617 }
01618 }
01619 }
01620 max_count = counts[0];
01621 predicate->predicate.index_arg = 0;
01622 for (arg = 1; arg < 4 && arg < predicate->header.size; ++arg) {
01623 if (counts[arg] > max_count) {
01624 max_count = counts[arg];
01625 predicate->predicate.index_arg = arg;
01626 }
01627 }
01628 if (predicate->predicate.index_arg == 0 &&
01629 keys[0].type == P_TERM_VARIABLE && !(counts[arg]) &&
01630 predicate->header.size >= 2) {
01631
01632
01633
01634 predicate->predicate.index_arg = 1;
01635 }
01636
01637
01638 clause = predicate->predicate.clauses.head;
01639 while (clause != 0) {
01640 p_term_index_clause(context, predicate, clause, 0);
01641 clause = clause->next_clause;
01642 }
01643
01644
01645 predicate->predicate.is_indexed = 1;
01646 }
01647
01648
01649
01650 static void p_term_renumber_clauses(p_term *predicate)
01651 {
01652 unsigned int clause_num = P_TERM_DEFAULT_CLAUSE_NUM -
01653 predicate->predicate.clause_count / 2;
01654 struct p_term_clause *clause = predicate->predicate.clauses.head;
01655 while (clause != 0) {
01656 clause->header.size = clause_num++;
01657 clause = clause->next_clause;
01658 }
01659 }
01660
01675 void p_term_add_clause_first(p_context *context, p_term *predicate, p_term *clause)
01676 {
01677 unsigned int clause_num;
01678 if (predicate->predicate.clauses.head) {
01679 struct p_term_clause *first = predicate->predicate.clauses.head;
01680 clause_num = first->header.size - 1;
01681 } else {
01682 clause_num = P_TERM_DEFAULT_CLAUSE_NUM;
01683 }
01684 clause->header.size = clause_num;
01685 p_term_add_regular_clause
01686 (context, &(predicate->predicate.clauses), clause, 1);
01687 ++(predicate->predicate.clause_count);
01688 if (!clause->header.size)
01689 p_term_renumber_clauses(predicate);
01690 if (predicate->predicate.is_indexed) {
01691 p_term_index_clause(context, predicate, &(clause->clause), 1);
01692 } else if (!(predicate->predicate.dont_index) &&
01693 predicate->predicate.clause_count > P_TERM_INDEX_TRIGGER) {
01694 p_term_index_all_clauses(context, predicate);
01695 }
01696 }
01697
01712 void p_term_add_clause_last(p_context *context, p_term *predicate, p_term *clause)
01713 {
01714 unsigned int clause_num;
01715 if (predicate->predicate.clauses.tail) {
01716 struct p_term_clause *last = predicate->predicate.clauses.tail;
01717 clause_num = last->header.size + 1;
01718 } else {
01719 clause_num = P_TERM_DEFAULT_CLAUSE_NUM;
01720 }
01721 clause->header.size = clause_num;
01722 p_term_add_regular_clause
01723 (context, &(predicate->predicate.clauses), clause, 0);
01724 ++(predicate->predicate.clause_count);
01725 if (!clause->header.size)
01726 p_term_renumber_clauses(predicate);
01727 if (predicate->predicate.is_indexed) {
01728 p_term_index_clause(context, predicate, &(clause->clause), 0);
01729 } else if (!(predicate->predicate.dont_index) &&
01730 predicate->predicate.clause_count > P_TERM_INDEX_TRIGGER) {
01731 p_term_index_all_clauses(context, predicate);
01732 }
01733 }
01734
01735
01736 int _p_term_retract_clause
01737 (p_context *context, p_term *predicate,
01738 struct p_term_clause *clause, p_term *clause2)
01739 {
01740 p_rbkey key;
01741 p_rbnode *node;
01742 p_term *body;
01743 void *marker;
01744 struct p_term_clause_list *list;
01745 struct p_term_clause *current;
01746 struct p_term_clause *prev;
01747
01748
01749 if (!predicate->predicate.is_indexed ||
01750 !_p_code_argument_key
01751 (&key, &(clause->clause_code),
01752 predicate->predicate.index_arg)) {
01753 key.type = P_TERM_VARIABLE;
01754 key.size = 0;
01755 key.name = 0;
01756 }
01757
01758
01759 marker = p_context_mark_trail(context);
01760 body = p_term_unify_clause
01761 (context, p_term_arg(clause2, 0), (p_term *)clause);
01762 if (!body)
01763 return 0;
01764 if (!p_term_unify(context, body,
01765 p_term_arg(clause2, 1), P_BIND_DEFAULT)) {
01766 p_context_backtrack_trail(context, marker);
01767 return 0;
01768 }
01769
01770
01771 if (!predicate->predicate.is_indexed)
01772 return 1;
01773
01774
01775 if (key.type != P_TERM_VARIABLE) {
01776 node = _p_rbtree_lookup(&(predicate->predicate.index), &key);
01777 if (node)
01778 list = &(node->clauses);
01779 else
01780 list = &(predicate->predicate.var_clauses);
01781 } else {
01782 list = &(predicate->predicate.var_clauses);
01783 }
01784 current = list->head;
01785 prev = 0;
01786 while (current != 0 && current != clause) {
01787 prev = current;
01788 current = current->next_index;
01789 }
01790 if (!current)
01791 return 1;
01792 if (prev) {
01793 prev->next_index = current->next_index;
01794 if (!current->next_index)
01795 list->tail = prev;
01796 } else {
01797 list->head = current->next_index;
01798 if (!(list->head)) {
01799 list->tail = 0;
01800 if (key.type != P_TERM_VARIABLE)
01801 _p_rbtree_remove(&(predicate->predicate.index), &key);
01802 }
01803 }
01804 return 1;
01805 }
01806
01821 void p_term_clauses_begin(const p_term *predicate, const p_term *head, p_term_clause_iter *iter)
01822 {
01823 iter->next1 = 0;
01824 iter->next2 = 0;
01825 iter->next3 = 0;
01826 if (!predicate)
01827 return;
01828 if (predicate->header.type != P_TERM_PREDICATE) {
01829 predicate = p_term_deref_non_null(predicate);
01830 if (predicate->header.type != P_TERM_PREDICATE)
01831 return;
01832 }
01833 if (head && predicate->predicate.is_indexed) {
01834 p_rbkey key;
01835 p_rbnode *node;
01836 p_term *arg = p_term_arg(head, predicate->predicate.index_arg);
01837 if (_p_rbkey_init(&key, arg)) {
01838 node = _p_rbtree_lookup
01839 (&(predicate->predicate.index), &key);
01840 if (node) {
01841 iter->next1 = node->clauses.head;
01842 iter->next2 = predicate->predicate.var_clauses.head;
01843 return;
01844 }
01845 }
01846 }
01847 iter->next3 = predicate->predicate.clauses.head;
01848 }
01849
01857 p_term *p_term_clauses_next(p_term_clause_iter *iter)
01858 {
01859 struct p_term_clause *clause;
01860 if (iter->next1) {
01861 clause = iter->next1;
01862 if (iter->next2 && iter->next2->header.size < clause->header.size) {
01863 clause = iter->next2;
01864 iter->next2 = clause->next_index;
01865 } else {
01866 iter->next1 = clause->next_index;
01867 if (!(iter->next1)) {
01868 iter->next1 = iter->next2;
01869 iter->next2 = 0;
01870 }
01871 }
01872 return (p_term *)clause;
01873 } else if (iter->next3) {
01874 clause = iter->next3;
01875 iter->next3 = clause->next_clause;
01876 return (p_term *)clause;
01877 }
01878 return 0;
01879 }
01880
01888 int p_term_clauses_has_more(const p_term_clause_iter *iter)
01889 {
01890 return iter->next1 != 0 || iter->next3 != 0;
01891 }
01892
01899 p_term *p_term_create_database(p_context *context)
01900 {
01901 struct p_term_database *term =
01902 p_term_new(context, struct p_term_database);
01903 if (!term)
01904 return 0;
01905 term->header.type = P_TERM_DATABASE;
01906 return (p_term *)term;
01907 }
01908
01916 void p_term_database_add_predicate(p_term *database, p_term *predicate)
01917 {
01918 p_rbkey key;
01919 p_rbnode *node;
01920 database = p_term_deref(database);
01921 predicate = p_term_deref(predicate);
01922 if (!database || database->header.type != P_TERM_DATABASE)
01923 return;
01924 if (!predicate || predicate->header.type != P_TERM_PREDICATE)
01925 return;
01926 key.type = P_TERM_FUNCTOR;
01927 key.size = predicate->header.size;
01928 key.name = predicate->predicate.name;
01929 node = _p_rbtree_insert(&(database->database.predicates), &key);
01930 if (!node)
01931 return;
01932 node->value = predicate;
01933 }
01934
01944 p_term *p_term_database_lookup_predicate
01945 (p_term *database, p_term *name, int arity)
01946 {
01947 p_rbkey key;
01948 p_rbnode *node;
01949 database = p_term_deref(database);
01950 name = p_term_deref(name);
01951 if (!database || database->header.type != P_TERM_DATABASE)
01952 return 0;
01953 if (!name || name->header.type != P_TERM_ATOM)
01954 return 0;
01955 key.type = P_TERM_FUNCTOR;
01956 key.size = arity;
01957 key.name = name;
01958 node = _p_rbtree_lookup(&(database->database.predicates), &key);
01959 if (node)
01960 return node->value;
01961 else
01962 return 0;
01963 }
01964
01976 p_term *p_term_create_member_name
01977 (p_context *context, p_term *class_name, p_term *name)
01978 {
01979 size_t clen = p_term_name_length(class_name);
01980 size_t nlen = p_term_name_length(name);
01981 char *str = (char *)GC_MALLOC(clen + nlen + 2);
01982 p_term *result;
01983 if (!str)
01984 return name;
01985 memcpy(str, p_term_name(class_name), clen);
01986 str[clen] = ':';
01987 str[clen + 1] = ':';
01988 memcpy(str + clen + 2, p_term_name(name), nlen);
01989 result = p_term_create_atom_n(context, str, clen + nlen + 2);
01990 GC_FREE(str);
01991 return result;
01992 }
01993
01994
01995 int p_term_occurs_in(const p_term *var, const p_term *value)
01996 {
01997 unsigned int index;
01998 if (!value)
01999 return 0;
02000 value = p_term_deref_non_null(value);
02001 if (var == value)
02002 return 1;
02003 switch (value->header.type) {
02004 case P_TERM_FUNCTOR:
02005
02006 for (index = 0; index < value->header.size; ++index) {
02007 if (p_term_occurs_in(var, value->functor.arg[index]))
02008 return 1;
02009 }
02010 break;
02011 case P_TERM_LIST:
02012
02013 do {
02014 if (p_term_occurs_in(var, value->list.head))
02015 return 1;
02016 value = value->list.tail;
02017 if (!value)
02018 return 0;
02019 value = p_term_deref_non_null(value);
02020 } while (value->header.type == P_TERM_LIST);
02021 if (value->header.type != P_TERM_ATOM)
02022 return p_term_occurs_in(var, value);
02023 break;
02024 case P_TERM_OBJECT:
02025
02026 do {
02027 for (index = 0; index < value->header.size; ++index) {
02028 if (p_term_occurs_in
02029 (var, value->object.properties[index].value))
02030 return 1;
02031 }
02032 value = value->object.next;
02033 }
02034 while (value);
02035 break;
02036 case P_TERM_MEMBER_VARIABLE:
02037 return p_term_occurs_in(var, value->member_var.object);
02038 default: break;
02039 }
02040 return 0;
02041 }
02042
02111 int p_term_bind_variable(p_context *context, p_term *var, p_term *value, int flags)
02112 {
02113 if (!var)
02114 return 0;
02115 var = p_term_deref_non_null(var);
02116 if ((var->header.type & P_TERM_VARIABLE) == 0)
02117 return 0;
02118 if ((flags & P_BIND_NO_OCCURS_CHECK) == 0) {
02119 if (p_term_occurs_in(var, value))
02120 return 0;
02121 }
02122 if ((flags & P_BIND_NO_RECORD) == 0) {
02123 if (!_p_context_record_in_trail(context, var))
02124 return 0;
02125 }
02126 var->var.value = value;
02127 return 1;
02128 }
02129
02130
02131 P_INLINE int p_term_bind_var(p_context *context, p_term *var, p_term *value, int flags)
02132 {
02133 if ((flags & P_BIND_NO_OCCURS_CHECK) == 0) {
02134 if (p_term_occurs_in(var, value))
02135 return 0;
02136 }
02137 if ((flags & P_BIND_NO_RECORD) == 0) {
02138 if (!_p_context_record_in_trail(context, var))
02139 return 0;
02140 }
02141 var->var.value = value;
02142 return 1;
02143 }
02144
02145
02146 static int p_term_unify_inner(p_context *context, p_term *term1, p_term *term2, int flags);
02147
02148
02149 static p_term *p_term_resolve_member(p_context *context, p_term *term, int flags)
02150 {
02151 p_term *object = term->member_var.object;
02152 p_term *value;
02153 if (!object)
02154 return 0;
02155 object = p_term_deref_non_null(object);
02156 if (object->header.type == P_TERM_MEMBER_VARIABLE) {
02157
02158 object = p_term_resolve_member(context, object, flags);
02159 if (!object)
02160 return 0;
02161 object = p_term_deref_non_null(object);
02162 }
02163 if (object->header.type != P_TERM_OBJECT)
02164 return 0;
02165 value = p_term_property(context, object, term->member_var.name);
02166 if (!value && term->header.size && (flags & P_BIND_EQUALITY) == 0) {
02167
02168 value = p_term_create_variable(context);
02169 if (!p_term_add_property(context, object,
02170 term->member_var.name, value))
02171 return 0;
02172 }
02173 return value;
02174 }
02175
02176
02177 static int p_term_unify_variable(p_context *context, p_term *term1, p_term *term2, int flags)
02178 {
02179
02180 if (term1->header.type == P_TERM_MEMBER_VARIABLE) {
02181 term1 = p_term_resolve_member(context, term1, flags);
02182 return p_term_unify_inner(context, term1, term2, flags);
02183 }
02184 if (term2->header.type == P_TERM_MEMBER_VARIABLE) {
02185 term2 = p_term_resolve_member(context, term2, flags);
02186 return p_term_unify_inner(context, term1, term2, flags);
02187 }
02188
02189
02190 if (flags & P_BIND_EQUALITY)
02191 return 0;
02192
02193
02194 if (flags & P_BIND_RECORD_ONE_WAY)
02195 flags |= P_BIND_NO_RECORD;
02196 return p_term_bind_var(context, term1, term2, flags);
02197 }
02198
02199
02200 static int p_term_unify_inner(p_context *context, p_term *term1, p_term *term2, int flags)
02201 {
02202 if (!term1 || !term2)
02203 return 0;
02204 term1 = p_term_deref_non_null(term1);
02205 term2 = p_term_deref_non_null(term2);
02206 if (term1 == term2)
02207 return 1;
02208 if (term1->header.type & P_TERM_VARIABLE)
02209 return p_term_unify_variable(context, term1, term2, flags);
02210 if (term2->header.type & P_TERM_VARIABLE) {
02211 if (flags & P_BIND_ONE_WAY)
02212 return 0;
02213 return p_term_unify_variable
02214 (context, term2, term1, flags & ~P_BIND_RECORD_ONE_WAY);
02215 }
02216 switch (term1->header.type) {
02217 case P_TERM_FUNCTOR:
02218
02219 if (term2->header.type == P_TERM_FUNCTOR &&
02220 term1->header.size == term2->header.size &&
02221 term1->functor.functor_name ==
02222 term2->functor.functor_name) {
02223 unsigned int index;
02224 for (index = 0; index < term1->header.size; ++index) {
02225 if (!p_term_unify_inner
02226 (context, term1->functor.arg[index],
02227 term2->functor.arg[index], flags))
02228 return 0;
02229 }
02230 return 1;
02231 }
02232 break;
02233 case P_TERM_LIST:
02234
02235
02236 if (term2->header.type != P_TERM_LIST)
02237 return 0;
02238 for (;;) {
02239 if (!p_term_unify_inner(context, term1->list.head,
02240 term2->list.head, flags))
02241 break;
02242 term1 = term1->list.tail;
02243 term2 = term2->list.tail;
02244 if (!term1 || !term2)
02245 break;
02246 term1 = p_term_deref_non_null(term1);
02247 term2 = p_term_deref_non_null(term2);
02248 if (term1->header.type != P_TERM_LIST ||
02249 term2->header.type != P_TERM_LIST)
02250 return p_term_unify_inner(context, term1, term2, flags);
02251 }
02252 break;
02253 case P_TERM_ATOM:
02254
02255
02256 break;
02257 case P_TERM_STRING:
02258
02259 if (term2->header.type == P_TERM_STRING &&
02260 term1->header.size == term2->header.size &&
02261 !memcmp(term1->string.name, term2->string.name,
02262 term1->header.size))
02263 return 1;
02264 break;
02265 case P_TERM_INTEGER:
02266
02267 if (term2->header.type == P_TERM_INTEGER) {
02268 #if defined(P_TERM_64BIT)
02269
02270 return term1->header.size == term2->header.size;
02271 #else
02272 return term1->integer.value == term2->integer.value;
02273 #endif
02274 }
02275 break;
02276 case P_TERM_REAL:
02277
02278 if (term2->header.type == P_TERM_REAL)
02279 return term1->real.value == term2->real.value;
02280 break;
02281 case P_TERM_OBJECT:
02282 case P_TERM_PREDICATE:
02283 case P_TERM_CLAUSE:
02284 case P_TERM_DATABASE:
02285
02286
02287
02288 break;
02289 default: break;
02290 }
02291 return 0;
02292 }
02293
02303 int p_term_unify(p_context *context, p_term *term1, p_term *term2, int flags)
02304 {
02305 void *marker = p_context_mark_trail(context);
02306 int result = p_term_unify_inner(context, term1, term2, flags);
02307 if (!result && (flags & P_BIND_NO_RECORD) == 0)
02308 p_context_backtrack_trail(context, marker);
02309 return result;
02310 }
02311
02330 void p_term_stdio_print_func(void *data, const char *format, ...)
02331 {
02332 va_list va;
02333 va_start(va, format);
02334 vfprintf((FILE *)data, format, va);
02335 va_end(va);
02336 }
02337
02338
02339 static const p_term *p_term_deref_limited(const p_term *term)
02340 {
02341 int count = 32;
02342 if (!term)
02343 return 0;
02344 while (count-- > 0) {
02345 if (term->header.type & P_TERM_VARIABLE) {
02346 if (!term->var.value)
02347 break;
02348 term = term->var.value;
02349 } else {
02350 break;
02351 }
02352 }
02353 return term;
02354 }
02355
02356
02357 static void p_term_print_quoted(const p_term *term, p_term_print_func print_func, void *print_data, int quote)
02358 {
02359 const char *str = p_term_name(term);
02360 size_t len = p_term_name_length(term);
02361 int ch;
02362 (*print_func)(print_data, "%c", quote);
02363 while (len-- > 0) {
02364 ch = ((int)(*str++)) & 0xFF;
02365 if (ch == quote || ch == '\\')
02366 (*print_func)(print_data, "\\%c", ch);
02367 else if (ch >= 0x20)
02368 (*print_func)(print_data, "%c", ch);
02369 else if (ch == '\t')
02370 (*print_func)(print_data, "\\t");
02371 else if (ch == '\n')
02372 (*print_func)(print_data, "\\n");
02373 else if (ch == '\r')
02374 (*print_func)(print_data, "\\r");
02375 else if (ch == '\f')
02376 (*print_func)(print_data, "\\f");
02377 else if (ch == '\v')
02378 (*print_func)(print_data, "\\v");
02379 else if (ch == '\0')
02380 (*print_func)(print_data, "\\0");
02381 else
02382 (*print_func)(print_data, "\\x%02x", ch);
02383 }
02384 (*print_func)(print_data, "%c", quote);
02385 }
02386
02387
02388 static void p_term_print_atom(const p_term *atom, p_term_print_func print_func, void *print_data)
02389 {
02390 const char *name = p_term_name(atom);
02391 int ok;
02392 if (!name)
02393 return;
02394 if (*name >= 'a' && *name <= 'z') {
02395 ++name;
02396 while (*name != '\0') {
02397 if (*name >= 'a' && *name <= 'z')
02398 ++name;
02399 else if (*name >= 'Z' && *name <= 'Z')
02400 ++name;
02401 else if (*name >= '0' && *name <= '9')
02402 ++name;
02403 else if (*name == '_')
02404 ++name;
02405 else if (*name == ':' && name[1] == ':')
02406 name += 2;
02407 else
02408 break;
02409 }
02410 ok = (name == (atom->atom.name + atom->header.size));
02411 } else if (*name == '[' && name[1] == ']' && name[2] == '\0' &&
02412 atom->header.size == 2) {
02413 ok = 1;
02414 } else {
02415 ok = 0;
02416 }
02417 if (ok)
02418 (*print_func)(print_data, "%s", p_term_name(atom));
02419 else
02420 p_term_print_quoted(atom, print_func, print_data, '\'');
02421 }
02422
02423 static p_term *p_term_var_name(const p_term *vars, const p_term *var)
02424 {
02425 p_term *v;
02426 vars = p_term_deref(vars);
02427 while (vars && vars->header.type == P_TERM_LIST) {
02428 v = p_term_arg(vars->list.head, 1);
02429 while (v && v != var) {
02430 if (v->header.type & P_TERM_VARIABLE)
02431 v = v->var.value;
02432 else
02433 break;
02434 }
02435 if (v == var) {
02436 p_term *name = p_term_deref(p_term_arg(vars->list.head, 0));
02437 if (name && (name->header.type == P_TERM_ATOM ||
02438 name->header.type == P_TERM_STRING))
02439 return name;
02440 else
02441 break;
02442 }
02443 vars = p_term_deref(vars->list.tail);
02444 }
02445 return 0;
02446 }
02447
02448 static void p_term_print_inner(p_context *context, const p_term *term, p_term_print_func print_func, void *print_data, int level, int prec, const p_term *vars)
02449 {
02450
02451 if (level <= 0) {
02452 (*print_func)(print_data, "...");
02453 return;
02454 }
02455
02456
02457 if (!term) {
02458 (*print_func)(print_data, "NULL");
02459 return;
02460 }
02461
02462
02463 switch (term->header.type) {
02464 case P_TERM_FUNCTOR: {
02465 unsigned int index;
02466 p_op_specifier spec;
02467 int priority;
02468 spec = p_db_operator_info
02469 (term->functor.functor_name,
02470 (int)(term->header.size), &priority);
02471 if (spec == P_OP_NONE) {
02472 p_term_print_atom(term->functor.functor_name,
02473 print_func, print_data);
02474 (*print_func)(print_data, "(");
02475 for (index = 0; index < term->header.size; ++index) {
02476 if (index)
02477 (*print_func)(print_data, ", ");
02478 p_term_print_inner
02479 (context, term->functor.arg[index],
02480 print_func, print_data, level - 1, 950, vars);
02481 }
02482 (*print_func)(print_data, ")");
02483 } else {
02484 int bracketed = (priority > prec);
02485 if (bracketed) {
02486 (*print_func)(print_data, "(");
02487 priority = 1300;
02488 }
02489 switch (spec) {
02490 case P_OP_NONE: break;
02491 case P_OP_XF:
02492 p_term_print_inner
02493 (context, term->functor.arg[0],
02494 print_func, print_data, level - 1,
02495 priority - 1, vars);
02496 (*print_func)(print_data, " %s",
02497 p_term_name(term->functor.functor_name));
02498 break;
02499 case P_OP_YF:
02500 p_term_print_inner
02501 (context, term->functor.arg[0],
02502 print_func, print_data, level - 1, priority, vars);
02503 (*print_func)(print_data, " %s",
02504 p_term_name(term->functor.functor_name));
02505 break;
02506 case P_OP_XFX:
02507 p_term_print_inner
02508 (context, term->functor.arg[0],
02509 print_func, print_data, level - 1,
02510 priority - 1, vars);
02511 (*print_func)(print_data, " %s ",
02512 p_term_name(term->functor.functor_name));
02513 p_term_print_inner
02514 (context, term->functor.arg[1],
02515 print_func, print_data, level - 1,
02516 priority - 1, vars);
02517 break;
02518 case P_OP_XFY:
02519 p_term_print_inner
02520 (context, term->functor.arg[0],
02521 print_func, print_data, level - 1,
02522 priority - 1, vars);
02523 (*print_func)(print_data, " %s ",
02524 p_term_name(term->functor.functor_name));
02525 p_term_print_inner
02526 (context, term->functor.arg[1],
02527 print_func, print_data, level - 1,
02528 priority, vars);
02529 break;
02530 case P_OP_YFX:
02531 p_term_print_inner
02532 (context, term->functor.arg[0],
02533 print_func, print_data, level - 1, priority, vars);
02534 (*print_func)(print_data, " %s ",
02535 p_term_name(term->functor.functor_name));
02536 p_term_print_inner
02537 (context, term->functor.arg[1],
02538 print_func, print_data, level - 1,
02539 priority - 1, vars);
02540 break;
02541 case P_OP_FX:
02542 (*print_func)(print_data, "%s ",
02543 p_term_name(term->functor.functor_name));
02544 p_term_print_inner
02545 (context, term->functor.arg[0],
02546 print_func, print_data, level - 1,
02547 priority - 1, vars);
02548 break;
02549 case P_OP_FY:
02550 (*print_func)(print_data, "%s ",
02551 p_term_name(term->functor.functor_name));
02552 p_term_print_inner
02553 (context, term->functor.arg[0],
02554 print_func, print_data, level - 1, priority, vars);
02555 break;
02556 }
02557 if (bracketed)
02558 (*print_func)(print_data, ")");
02559 }
02560 break; }
02561 case P_TERM_LIST:
02562 (*print_func)(print_data, "[");
02563 p_term_print_inner(context, term->list.head,
02564 print_func, print_data,
02565 level - 1, 950, vars);
02566 term = p_term_deref_limited(term->list.tail);
02567 while (term && term->header.type == P_TERM_LIST && level > 0) {
02568 (*print_func)(print_data, ", ");
02569 p_term_print_inner(context, term->list.head,
02570 print_func, print_data,
02571 level - 1, 950, vars);
02572 term = p_term_deref_limited(term->list.tail);
02573 --level;
02574 }
02575 if (level <= 0) {
02576 (*print_func)(print_data, "|...]");
02577 break;
02578 }
02579 if (term != context->nil_atom) {
02580 (*print_func)(print_data, "|");
02581 p_term_print_inner(context, term, print_func,
02582 print_data, level - 1, 950, vars);
02583 }
02584 (*print_func)(print_data, "]");
02585 break;
02586 case P_TERM_ATOM:
02587 p_term_print_atom(term, print_func, print_data);
02588 break;
02589 case P_TERM_STRING:
02590 p_term_print_quoted(term, print_func, print_data, '"');
02591 break;
02592 case P_TERM_INTEGER:
02593 (*print_func)(print_data, "%d", p_term_integer_value(term));
02594 break;
02595 case P_TERM_REAL:
02596 (*print_func)(print_data, "%.10g", p_term_real_value(term));
02597 break;
02598 case P_TERM_OBJECT: {
02599 p_term *name = p_term_property
02600 (context, term, context->class_name_atom);
02601 unsigned int index;
02602 int first = 1;
02603 if (p_term_is_class_object(context, term))
02604 (*print_func)(print_data, "class ");
02605 if (name)
02606 (*print_func)(print_data, "%s {", p_term_name(name));
02607 else
02608 (*print_func)(print_data, "unknown_class {");
02609 do {
02610 for (index = 0; index < term->header.size; ++index) {
02611 name = term->object.properties[index].name;
02612 if (name == context->class_name_atom)
02613 continue;
02614 if (name == context->prototype_atom)
02615 continue;
02616 if (!first)
02617 (*print_func)(print_data, ", ");
02618 p_term_print_atom(name, print_func, print_data);
02619 (*print_func)(print_data, ": ");
02620 p_term_print_inner
02621 (context, term->object.properties[index].value,
02622 print_func, print_data, level - 1, 950, vars);
02623 first = 0;
02624 }
02625 term = term->object.next;
02626 } while (term != 0);
02627 (*print_func)(print_data, "}");
02628 break; }
02629 case P_TERM_PREDICATE:
02630 (*print_func)(print_data, "predicate ");
02631 p_term_print_atom(term->predicate.name, print_func, print_data);
02632 (*print_func)(print_data, "/%d", (int)(term->header.size));
02633 break;
02634 case P_TERM_CLAUSE:
02635 (*print_func)(print_data, "clause %lx", (long)term);
02636 break;
02637 case P_TERM_DATABASE:
02638 (*print_func)(print_data, "database %lx", (long)term);
02639 break;
02640 case P_TERM_VARIABLE: {
02641 if (term->var.value) {
02642 p_term_print_inner(context, term->var.value, print_func,
02643 print_data, level - 1, prec, vars);
02644 } else if (vars) {
02645 p_term *name = p_term_var_name(vars, term);
02646 if (name)
02647 (*print_func)(print_data, "%s", p_term_name(name));
02648 else
02649 (*print_func)(print_data, "_%lx", (long)term);
02650 } else if (term->header.size > 0) {
02651 (*print_func)(print_data, "%s", p_term_name(term));
02652 } else {
02653 (*print_func)(print_data, "_%lx", (long)term);
02654 }
02655 break; }
02656 case P_TERM_MEMBER_VARIABLE:
02657 if (term->var.value) {
02658 p_term_print_inner(context, term->var.value, print_func,
02659 print_data, level - 1, prec, vars);
02660 break;
02661 }
02662 p_term_print_inner(context, term->member_var.object, print_func,
02663 print_data, level - 1, 0, vars);
02664 (*print_func)(print_data, ".");
02665 p_term_print_atom(term->member_var.name, print_func, print_data);
02666 break;
02667 default: break;
02668 }
02669 }
02670
02682 void p_term_print(p_context *context, const p_term *term, p_term_print_func print_func, void *print_data)
02683 {
02684 p_term_print_inner(context, term, print_func, print_data, 1000, 1300, 0);
02685 }
02686
02701 void p_term_print_unquoted(p_context *context, const p_term *term, p_term_print_func print_func, void *print_data)
02702 {
02703 term = p_term_deref(term);
02704 if (term) {
02705 if (term->header.type == P_TERM_ATOM ||
02706 term->header.type == P_TERM_STRING) {
02707 (*print_func)(print_data, "%s", p_term_name(term));
02708 return;
02709 }
02710 }
02711 p_term_print_inner(context, term, print_func, print_data, 1000, 1300, 0);
02712 }
02713
02726 void p_term_print_with_vars(p_context *context, const p_term *term, p_term_print_func print_func, void *print_data, const p_term *vars)
02727 {
02728 if (!vars)
02729 vars = p_term_nil_atom(context);
02730 p_term_print_inner(context, term, print_func, print_data, 1000, 1300, vars);
02731 }
02732
02751 int p_term_precedes(p_context *context, const p_term *term1, const p_term *term2)
02752 {
02753 int group1, group2, cmp;
02754 static unsigned char const precedes_ordering[] = {
02755 0,
02756 6,
02757 6,
02758 5,
02759 4,
02760 3,
02761 2,
02762 7,
02763 8,
02764 9,
02765 10,
02766 0, 0, 0, 0, 0,
02767 1,
02768 1
02769 };
02770
02771
02772 if (!term1)
02773 return term2 ? -1 : 0;
02774 if (!term2)
02775 return 1;
02776 term1 = p_term_deref_non_null(term1);
02777 term2 = p_term_deref_non_null(term2);
02778 if (term1 == term2)
02779 return 0;
02780
02781
02782 group1 = precedes_ordering[term1->header.type];
02783 group2 = precedes_ordering[term2->header.type];
02784 if (group1 < group2)
02785 return -1;
02786 else if (group1 > group2)
02787 return 1;
02788
02789
02790 switch (term1->header.type) {
02791 case P_TERM_FUNCTOR:
02792 case P_TERM_LIST: {
02793 p_term *name1;
02794 p_term *name2;
02795 unsigned int index;
02796 if (term1->header.size < term2->header.size)
02797 return -1;
02798 else if (term1->header.size > term2->header.size)
02799 return 1;
02800 if (term1->header.type == P_TERM_FUNCTOR)
02801 name1 = term1->functor.functor_name;
02802 else
02803 name1 = context->dot_atom;
02804 if (term2->header.type == P_TERM_FUNCTOR)
02805 name2 = term2->functor.functor_name;
02806 else
02807 name2 = context->dot_atom;
02808 cmp = p_term_strcmp(name1, name2);
02809 if (cmp < 0)
02810 return -1;
02811 else if (cmp > 0)
02812 return 1;
02813 if (term1->header.type == P_TERM_FUNCTOR &&
02814 term2->header.type == P_TERM_FUNCTOR) {
02815 for (index = 0; index < term1->header.size; ++index) {
02816 cmp = p_term_precedes(context,
02817 term1->functor.arg[index],
02818 term2->functor.arg[index]);
02819 if (cmp != 0)
02820 return cmp;
02821 }
02822 } else if (term1->header.type == P_TERM_LIST &&
02823 term2->header.type == P_TERM_LIST) {
02824 do {
02825 cmp = p_term_precedes
02826 (context, term1->list.head, term2->list.head);
02827 if (cmp != 0)
02828 return cmp;
02829 term1 = term1->list.tail;
02830 term2 = term2->list.tail;
02831 if (!term1 || !term2)
02832 break;
02833 term1 = p_term_deref_non_null(term1);
02834 term2 = p_term_deref_non_null(term2);
02835 } while (term1->header.type == P_TERM_LIST &&
02836 term2->header.type == P_TERM_LIST);
02837 return p_term_precedes(context, term1, term2);
02838 } else {
02839
02840
02841
02842 return (term1 < term2) ? -1 : 1;
02843 }
02844 break; }
02845 case P_TERM_ATOM:
02846 case P_TERM_STRING:
02847 cmp = p_term_strcmp(term1, term2);
02848 if (cmp < 0)
02849 return -1;
02850 else if (cmp > 0)
02851 return 1;
02852 break;
02853 case P_TERM_INTEGER:
02854 #if defined(P_TERM_64BIT)
02855 if (((int)(term1->header.size)) < ((int)(term2->header.size)))
02856 return -1;
02857 else if (((int)(term1->header.size)) > ((int)(term2->header.size)))
02858 return 1;
02859 #else
02860 if (term1->integer.value < term2->integer.value)
02861 return -1;
02862 else if (term1->integer.value > term2->integer.value)
02863 return 1;
02864 #endif
02865 break;
02866 case P_TERM_REAL:
02867 if (term1->real.value < term2->real.value)
02868 return -1;
02869 else if (term1->real.value > term2->real.value)
02870 return 1;
02871 break;
02872 case P_TERM_OBJECT:
02873 case P_TERM_PREDICATE:
02874 case P_TERM_CLAUSE:
02875 case P_TERM_DATABASE:
02876 case P_TERM_VARIABLE:
02877 case P_TERM_MEMBER_VARIABLE:
02878 return (term1 < term2) ? -1 : 1;
02879 default: break;
02880 }
02881 return 0;
02882 }
02883
02893 int p_term_is_ground(const p_term *term)
02894 {
02895 if (!term)
02896 return 0;
02897 term = p_term_deref_non_null(term);
02898 switch (term->header.type) {
02899 case P_TERM_FUNCTOR: {
02900 unsigned int index;
02901 for (index = 0; index < term->header.size; ++index) {
02902 if (!p_term_is_ground(term->functor.arg[index]))
02903 return 0;
02904 }
02905 return 1; }
02906 case P_TERM_LIST:
02907 do {
02908 if (!p_term_is_ground(term->list.head))
02909 return 0;
02910 term = term->list.tail;
02911 if (!term)
02912 return 0;
02913 term = p_term_deref_non_null(term);
02914 }
02915 while (term->header.type == P_TERM_LIST);
02916 return p_term_is_ground(term);
02917 case P_TERM_ATOM:
02918 case P_TERM_STRING:
02919 case P_TERM_INTEGER:
02920 case P_TERM_REAL:
02921 case P_TERM_OBJECT:
02922 case P_TERM_PREDICATE:
02923 case P_TERM_CLAUSE:
02924 case P_TERM_DATABASE:
02925 return 1;
02926 case P_TERM_VARIABLE:
02927 case P_TERM_MEMBER_VARIABLE:
02928 case P_TERM_RENAME:
02929 return 0;
02930 default: break;
02931 }
02932 return 0;
02933 }
02934
02935 static p_term *p_term_clone_inner(p_context *context, p_term *term)
02936 {
02937 p_term *clone;
02938 p_term *rename;
02939 if (!term)
02940 return 0;
02941 term = p_term_deref_non_null(term);
02942 switch (term->header.type) {
02943 case P_TERM_FUNCTOR: {
02944
02945 unsigned int index;
02946 clone = p_term_create_functor
02947 (context, term->functor.functor_name,
02948 (int)(term->header.size));
02949 if (!clone)
02950 return 0;
02951 for (index = 0; index < term->header.size; ++index) {
02952 p_term *arg = p_term_clone_inner
02953 (context, term->functor.arg[index]);
02954 if (!arg)
02955 return 0;
02956 p_term_bind_functor_arg(clone, (int)index, arg);
02957 }
02958 return clone; }
02959 case P_TERM_LIST: {
02960
02961 p_term *head;
02962 p_term *tail = 0;
02963 clone = 0;
02964 do {
02965 head = p_term_clone_inner(context, term->list.head);
02966 if (!head)
02967 return 0;
02968 head = p_term_create_list(context, head, 0);
02969 if (tail)
02970 tail->list.tail = head;
02971 else
02972 clone = head;
02973 tail = head;
02974 term = term->list.tail;
02975 if (!term)
02976 return 0;
02977 term = p_term_deref_non_null(term);
02978 }
02979 while (term->header.type == P_TERM_LIST);
02980 head = p_term_clone_inner(context, term);
02981 if (!head)
02982 return 0;
02983 tail->list.tail = head;
02984 return clone; }
02985 case P_TERM_ATOM:
02986 case P_TERM_STRING:
02987 case P_TERM_INTEGER:
02988 case P_TERM_REAL:
02989 case P_TERM_OBJECT:
02990 case P_TERM_PREDICATE:
02991 case P_TERM_DATABASE:
02992
02993 break;
02994 case P_TERM_VARIABLE:
02995
02996
02997
02998 if (term->header.size > 0)
02999 clone = p_term_create_named_variable(context, p_term_name(term));
03000 else
03001 clone = p_term_create_variable(context);
03002 if (!clone)
03003 return 0;
03004 _p_context_record_in_trail(context, term);
03005 rename = p_term_malloc
03006 (context, p_term, sizeof(struct p_term_rename));
03007 if (!rename)
03008 return 0;
03009 rename->header.type = P_TERM_RENAME;
03010 rename->rename.var = clone;
03011 term->var.value = rename;
03012 return clone;
03013 case P_TERM_MEMBER_VARIABLE:
03014
03015 clone = p_term_clone_inner(context, term->member_var.object);
03016 if (!clone)
03017 return 0;
03018 clone = p_term_create_member_variable
03019 (context, clone, term->member_var.name,
03020 (int)(term->header.size));
03021 if (!clone)
03022 return 0;
03023 _p_context_record_in_trail(context, term);
03024 rename = p_term_malloc
03025 (context, p_term, sizeof(struct p_term_rename));
03026 if (!rename)
03027 return 0;
03028 rename->header.type = P_TERM_RENAME;
03029 rename->rename.var = clone;
03030 term->var.value = rename;
03031 return clone;
03032 case P_TERM_RENAME:
03033
03034 return term->rename.var;
03035 default: break;
03036 }
03037 return term;
03038 }
03039
03048 p_term *p_term_clone(p_context *context, p_term *term)
03049 {
03050
03051
03052
03053
03054 void *marker = p_context_mark_trail(context);
03055 p_term *clone = p_term_clone_inner(context, term);
03056 p_context_backtrack_trail(context, marker);
03057 return clone;
03058 }
03059
03076 p_term *p_term_unify_clause(p_context *context, p_term *term, p_term *clause)
03077 {
03078 unsigned int index;
03079 p_goal_result result;
03080 p_term *body = 0;
03081
03082
03083 term = p_term_deref(term);
03084 if (!term)
03085 return 0;
03086 if (term->header.type == P_TERM_FUNCTOR) {
03087 for (index = 0; index < term->header.size; ++index) {
03088 _p_code_set_xreg
03089 (context, (int)index, term->functor.arg[index]);
03090 }
03091 }
03092
03093
03094
03095 result = _p_code_run(context, &(clause->clause.clause_code), &body);
03096 if (result == P_RESULT_RETURN_BODY)
03097 return body;
03098 else if (result == P_RESULT_TRUE)
03099 return context->true_atom;
03100 else
03101 return 0;
03102 }
03103
03117 int p_term_strcmp(const p_term *str1, const p_term *str2)
03118 {
03119 const char *s1;
03120 unsigned int s1len;
03121 const char *s2;
03122 unsigned int s2len;
03123 int cmp;
03124 if (!str1 || !str2)
03125 return 0;
03126 str1 = p_term_deref_non_null(str1);
03127 str2 = p_term_deref_non_null(str2);
03128 if (str1->header.type == P_TERM_ATOM) {
03129 s1 = str1->atom.name;
03130 s1len = str1->header.size;
03131 } else if (str1->header.type == P_TERM_STRING) {
03132 s1 = str1->string.name;
03133 s1len = str1->header.size;
03134 } else {
03135 return 0;
03136 }
03137 if (str2->header.type == P_TERM_ATOM) {
03138 s2 = str2->atom.name;
03139 s2len = str2->header.size;
03140 } else if (str2->header.type == P_TERM_STRING) {
03141 s2 = str2->string.name;
03142 s2len = str2->header.size;
03143 } else {
03144 return 0;
03145 }
03146 if (!s1len)
03147 return s2len ? -1 : 0;
03148 if (!s2len)
03149 return s1len ? 1 : 0;
03150 if (s1len == s2len) {
03151 return memcmp(s1, s2, s1len);
03152 } else if (s1len < s2len) {
03153 cmp = memcmp(s1, s2, s1len);
03154 if (cmp != 0)
03155 return cmp;
03156 else
03157 return -1;
03158 } else {
03159 cmp = memcmp(s1, s2, s2len);
03160 if (cmp != 0)
03161 return cmp;
03162 else
03163 return 1;
03164 }
03165 }
03166
03176 p_term *p_term_concat_string(p_context *context, p_term *str1, p_term *str2)
03177 {
03178 size_t len;
03179 struct p_term_string *term;
03180 str1 = p_term_deref(str1);
03181 str2 = p_term_deref(str2);
03182 if (!str1 || str1->header.type != P_TERM_STRING)
03183 return 0;
03184 if (!str2 || str2->header.type != P_TERM_STRING)
03185 return 0;
03186 if (str1->header.size == 0)
03187 return str2;
03188 if (str2->header.size == 0)
03189 return str1;
03190 len = str1->header.size + str2->header.size;
03191 term = p_term_malloc
03192 (context, struct p_term_string, sizeof(struct p_term_string) + len);
03193 if (!term)
03194 return 0;
03195 term->header.type = P_TERM_STRING;
03196 term->header.size = (unsigned int)len;
03197 memcpy(term->name, str1->string.name, str1->header.size);
03198 memcpy(term->name + str1->header.size, str2->string.name, str2->header.size);
03199 return (p_term *)term;
03200 }
03201
03202
03203 static p_term *p_term_witness_inner
03204 (p_context *context, p_term *term, p_term *list)
03205 {
03206 unsigned int index;
03207 if (!term)
03208 return list;
03209 term = p_term_deref_non_null(term);
03210 switch (term->header.type) {
03211 case P_TERM_FUNCTOR:
03212
03213 for (index = 0; index < term->header.size; ++index) {
03214 list = p_term_witness_inner
03215 (context, term->functor.arg[index], list);
03216 }
03217 break;
03218 case P_TERM_LIST:
03219
03220 do {
03221 list = p_term_witness_inner(context, term->list.head, list);
03222 term = term->list.tail;
03223 if (!term)
03224 break;
03225 term = p_term_deref_non_null(term);
03226 } while (term->header.type == P_TERM_LIST);
03227 return p_term_witness_inner(context, term, list);
03228 case P_TERM_VARIABLE:
03229
03230
03231
03232
03233
03234 if (list)
03235 list = p_term_create_list(context, term, list);
03236 if (_p_context_record_in_trail(context, term))
03237 term->var.value = context->true_atom;
03238 break;
03239 case P_TERM_MEMBER_VARIABLE:
03240
03241 return p_term_witness_inner
03242 (context, term->member_var.object, list);
03243 default: break;
03244 }
03245 return list;
03246 }
03247
03260 p_term *p_term_witness(p_context *context, p_term *term, p_term **subgoal)
03261 {
03262 p_term *caret = p_term_create_atom(context, "^");
03263 p_term *list;
03264 void *marker = p_context_mark_trail(context);
03265 while (term) {
03266 term = p_term_deref_non_null(term);
03267 if (term->header.type == P_TERM_FUNCTOR &&
03268 term->header.size == 2 &&
03269 term->functor.functor_name == caret) {
03270 p_term_witness_inner(context, term->functor.arg[0], 0);
03271 term = term->functor.arg[1];
03272 } else {
03273 break;
03274 }
03275 }
03276 *subgoal = term;
03277 list = p_term_witness_inner(context, term, context->nil_atom);
03278 p_context_backtrack_trail(context, marker);
03279 return list;
03280 }
03281
03282