00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 #include <plang/database.h>
00021 #include <plang/errors.h>
00022 #include <errno.h>
00023 #include "term-priv.h"
00024 #include "database-priv.h"
00025 #include "context-priv.h"
00026 
00185 
00186 
00187 
00188 
00189 
00190 P_INLINE void p_builtin_set_variable(p_term *var, p_term *value)
00191 {
00192     if (!var || (var->header.type & P_TERM_VARIABLE) == 0)
00193         return;
00194     var->var.value = value;
00195 }
00196 
00197 
00198 static p_goal_result p_builtin_unbind
00199     (p_context *context, p_term **args, p_term **error)
00200 {
00201     p_term *list = p_term_deref(args[0]);
00202     while (list && list->header.type == P_TERM_LIST) {
00203         p_builtin_set_variable(list->list.head, 0);
00204         list = p_term_deref(list->list.tail);
00205     }
00206     return P_RESULT_TRUE;
00207 }
00208 
00212 
00213 
00214 
00215 
00227 
00228 
00229 static void p_builtin_add_member_predicate
00230     (p_context *context, p_term *class_object,
00231      p_term *member_name, p_term *predicate)
00232 {
00233     p_term *list;
00234     p_term *property = p_term_own_property
00235         (context, class_object, member_name);
00236     if (property && property != predicate) {
00237         
00238 
00239 
00240         if (property->header.type == P_TERM_LIST) {
00241             list = property;
00242             while (list && list->header.type == P_TERM_LIST) {
00243                 if (list->list.head == predicate)
00244                     return;     
00245                 list = list->list.tail;
00246             }
00247         } else {
00248             
00249             property = p_term_create_list
00250                 (context, property, context->nil_atom);
00251         }
00252         property = p_term_create_list(context, predicate, property);
00253         p_term_set_own_property
00254             (context, class_object, member_name, property);
00255     } else if (!property) {
00256         
00257         p_term_add_property
00258             (context, class_object, member_name, predicate);
00259     }
00260 }
00261 
00434 static p_goal_result p_builtin_new_class
00435     (p_context *context, p_term **args, p_term **error)
00436 {
00437     p_term *name = p_term_deref_member(context, args[0]);
00438     p_term *parent = p_term_deref_member(context, args[1]);
00439     p_term *vars = p_term_deref_member(context, args[2]);
00440     p_term *clauses = p_term_deref_member(context, args[3]);
00441     p_database_info *info;
00442     p_database_info *info2;
00443     p_class_info *class_info;
00444     p_class_info *parent_info;
00445     p_term *class_object;
00446     p_term *prototype;
00447     p_term *list;
00448     p_term *var_name;
00449     p_term *member_name;
00450     p_term *kind;
00451     p_term *clause_term;
00452     p_term *clause_body;
00453     p_term *clause_atom;
00454     p_term *member_atom;
00455     p_term *predicate;
00456 
00457     
00458     if (!name || (name->header.type & P_TERM_VARIABLE) != 0) {
00459         *error = p_create_instantiation_error(context);
00460         return P_RESULT_ERROR;
00461     }
00462     if (name->header.type != P_TERM_ATOM) {
00463         *error = p_create_type_error(context, "atom", name);
00464         return P_RESULT_ERROR;
00465     }
00466     info = _p_db_create_arity(name, 0);
00467     if (!info)
00468         return P_RESULT_FAIL;
00469     if (info->class_info) {
00470         
00471         *error = p_create_permission_error
00472             (context, "create", "class", name);
00473         return P_RESULT_ERROR;
00474     }
00475 
00476     
00477     if (!parent || (parent->header.type & P_TERM_VARIABLE) != 0) {
00478         *error = p_create_instantiation_error(context);
00479         return P_RESULT_ERROR;
00480     }
00481     if (parent && parent != context->nil_atom) {
00482         if (parent->header.type != P_TERM_ATOM) {
00483             *error = p_create_type_error(context, "atom", parent);
00484             return P_RESULT_ERROR;
00485         }
00486         info2 = _p_db_find_arity(parent, 0);
00487         if (!info2 || !info2->class_info) {
00488             
00489             *error = p_create_existence_error(context, "class", parent);
00490             return P_RESULT_ERROR;
00491         }
00492         parent_info = info2->class_info;
00493         prototype = parent_info->class_object;
00494     } else {
00495         parent_info = 0;
00496         prototype = 0;
00497     }
00498 
00499     
00500     list = vars;
00501     if (!list || (list->header.type & P_TERM_VARIABLE) != 0) {
00502         *error = p_create_instantiation_error(context);
00503         return P_RESULT_ERROR;
00504     }
00505     for (;;) {
00506         if (list == context->nil_atom)
00507             break;
00508         if (!list || list->header.type != P_TERM_LIST) {
00509             *error = p_create_type_error(context, "atom_list", vars);
00510             return P_RESULT_ERROR;
00511         }
00512         var_name = p_term_deref_member(context, list->list.head);
00513         if (!var_name ||
00514                 (var_name->header.type & P_TERM_VARIABLE) != 0) {
00515             *error = p_create_instantiation_error(context);
00516             return P_RESULT_ERROR;
00517         }
00518         if (var_name->header.type != P_TERM_ATOM) {
00519             *error = p_create_type_error(context, "atom_list", vars);
00520             return P_RESULT_ERROR;
00521         }
00522         if(var_name == context->class_name_atom ||
00523                 var_name == context->prototype_atom) {
00524             *error = p_create_type_error
00525                 (context, "member_name", var_name);
00526             return P_RESULT_ERROR;
00527         }
00528         list = p_term_deref_member(context, list->list.tail);
00529     }
00530 
00531     
00532     class_info = GC_NEW(p_class_info);
00533     if (!class_info)
00534         return P_RESULT_FAIL;
00535     class_object = p_term_create_class_object(context, name, prototype);
00536     if (!class_object)
00537         return P_RESULT_FAIL;
00538     class_info->class_object = class_object;
00539     class_info->parent = parent_info;
00540     class_info->var_list = vars;
00541 
00542     
00543 
00544     list = clauses;
00545     clause_atom = p_term_create_atom(context, "clause");
00546     member_atom = p_term_create_atom(context, "member");
00547     while (list && list->header.type == P_TERM_LIST) {
00548         
00549         clause_term = p_term_deref_member(context, list->list.head);
00550         if (!clause_term ||
00551                 (clause_term->header.type & P_TERM_VARIABLE) != 0) {
00552             *error = p_create_instantiation_error(context);
00553             return P_RESULT_ERROR;
00554         }
00555         if (clause_term->header.type == P_TERM_FUNCTOR &&
00556                 clause_term->header.size == 3 &&
00557                 clause_term->functor.functor_name == context->line_atom)
00558             clause_term = p_term_deref_member
00559                 (context, clause_term->functor.arg[2]);
00560         if (clause_term->header.type != P_TERM_FUNCTOR ||
00561                 clause_term->header.size != 3 ||
00562                 clause_term->functor.functor_name != clause_atom) {
00563             break;
00564         }
00565         member_name = p_term_deref_member
00566             (context, clause_term->functor.arg[0]);
00567         kind = p_term_deref_member
00568             (context, clause_term->functor.arg[1]);
00569         clause_body = p_term_deref_member
00570             (context, clause_term->functor.arg[2]);
00571         if (!member_name || member_name->header.type != P_TERM_ATOM)
00572             break;
00573         if (!kind || kind->header.type != P_TERM_ATOM)
00574             break;
00575         if (!clause_body ||
00576                 clause_body->header.type != P_TERM_FUNCTOR ||
00577                 clause_body->header.size != 2 ||
00578                 clause_body->functor.functor_name
00579                         != context->clause_atom)
00580             break;
00581 
00582         
00583         if(member_name == context->class_name_atom ||
00584                 member_name == context->prototype_atom) {
00585             *error = p_create_type_error
00586                 (context, "member_name", member_name);
00587             return P_RESULT_ERROR;
00588         }
00589 
00590         
00591         predicate = _p_db_clause_assert_last(context, clause_body);
00592         if (!predicate) {
00593             
00594             p_term *pred, *head;
00595             pred = p_term_create_functor
00596                 (context, context->slash_atom, 2);
00597             head = p_term_deref_member
00598                 (context, clause_body->functor.arg[0]);
00599             if (head->header.type == P_TERM_FUNCTOR) {
00600                 p_term_bind_functor_arg
00601                     (pred, 0, head->functor.functor_name);
00602                 p_term_bind_functor_arg
00603                     (pred, 1,
00604                      p_term_create_integer(context, head->header.size));
00605             } else {
00606                 p_term_bind_functor_arg(pred, 0, head);
00607                 p_term_bind_functor_arg(pred, 1, 0);
00608             }
00609             *error = p_create_permission_error
00610                 (context, "modify", "static_procedure", pred);
00611             return P_RESULT_ERROR;
00612         }
00613         if (kind == member_atom) {
00614             
00615             p_builtin_add_member_predicate
00616                 (context, class_object, member_name, predicate);
00617         }
00618 
00619         
00620         list = p_term_deref_member
00621             (context, list->list.tail);
00622     }
00623     if (!list || (list->header.type & P_TERM_VARIABLE) != 0) {
00624         *error = p_create_instantiation_error(context);
00625         return P_RESULT_ERROR;
00626     }
00627     if (list != context->nil_atom) {
00628         *error = p_create_type_error(context, "clause_list", clauses);
00629         return P_RESULT_ERROR;
00630     }
00631 
00632     
00633     info->class_info = class_info;
00634     return P_RESULT_TRUE;
00635 }
00636 
00637 static p_goal_result p_builtin_univ
00638     (p_context *context, p_term **args, p_term **error);
00639 
00696 static p_goal_result p_builtin_new
00697     (p_context *context, p_term **args, p_term **error)
00698 {
00699     p_term *name = p_term_deref_member(context, args[0]);
00700     p_term *var = p_term_deref_member(context, args[1]);
00701     p_term *obj;
00702     p_database_info *info;
00703     p_class_info *class_info;
00704     p_term *vars;
00705     p_term *var_name;
00706 
00707     
00708     if (!name || !var || (name->header.type & P_TERM_VARIABLE) != 0) {
00709         *error = p_create_instantiation_error(context);
00710         return P_RESULT_ERROR;
00711     }
00712     if (name->header.type != P_TERM_ATOM) {
00713         *error = p_create_type_error(context, "atom", name);
00714         return P_RESULT_ERROR;
00715     }
00716     if ((var->header.type & P_TERM_VARIABLE) == 0) {
00717         *error = p_create_type_error(context, "variable", var);
00718         return P_RESULT_ERROR;
00719     }
00720 
00721     
00722     info = _p_db_find_arity(name, 0);
00723     if (!info || !(info->class_info)) {
00724         *error = p_create_existence_error(context, "class", name);
00725         return P_RESULT_ERROR;
00726     }
00727 
00728     
00729     class_info = info->class_info;
00730     obj = p_term_create_object(context, class_info->class_object);
00731     if (!obj)
00732         return P_RESULT_FAIL;
00733 
00734     
00735     do {
00736         vars = p_term_deref_member(context, class_info->var_list);
00737         while (vars && vars->header.type == P_TERM_LIST) {
00738             var_name = p_term_deref_member(context, vars->list.head);
00739             if (!p_term_own_property(context, obj, var_name)) {
00740                 p_term_add_property
00741                     (context, obj, var_name,
00742                      p_term_create_variable(context));
00743             }
00744             vars = p_term_deref_member(context, vars->list.tail);
00745         }
00746         class_info = class_info->parent;
00747     } while (class_info);
00748 
00749     
00750     if (p_term_unify(context, var, obj, P_BIND_DEFAULT))
00751         return P_RESULT_TRUE;
00752     else
00753         return P_RESULT_FAIL;
00754 }
00755 static p_goal_result p_builtin_new_object
00756     (p_context *context, p_term **args, p_term **error)
00757 {
00758     p_goal_result result;
00759     p_term *name;
00760     p_term *list;
00761     p_term *univ_args[2];
00762 
00763     
00764     result = p_builtin_new(context, args, error);
00765     if (result != P_RESULT_TRUE)
00766         return result;
00767 
00768     
00769     name = p_term_create_member_name
00770         (context, args[0], p_term_create_atom(context, "new"));
00771     list = p_term_create_list(context, args[1], args[2]);
00772     list = p_term_create_list(context, name, list);
00773     univ_args[0] = p_term_create_variable(context);
00774     univ_args[1] = list;
00775     result = p_builtin_univ(context, args, error);
00776     if (result != P_RESULT_TRUE)
00777         return result;
00778 
00779     
00780     context->current_node->goal = univ_args[0];
00781     return P_RESULT_TREE_CHANGE;
00782 }
00783 
00784 static p_term *p_create_member_existence_error
00785     (p_context *context, p_term *object, p_term *name, p_term *arg_head)
00786 {
00787     p_term *class_name = p_term_property
00788         (context, object, context->class_name_atom);
00789     p_term *full_name = p_term_create_member_name
00790         (context, class_name, name);
00791     p_term *pred = p_term_create_functor
00792         (context, context->slash_atom, 2);
00793     p_term_bind_functor_arg(pred, 0, full_name);
00794     p_term_bind_functor_arg
00795         (pred, 1, p_term_create_integer
00796             (context, (int)(arg_head->header.size)));
00797     return p_create_existence_error(context, "member_predicate", pred);
00798 }
00799 
00800 
00801 static p_goal_result p_builtin_call_member
00802     (p_context *context, p_term **args, p_term **error)
00803 {
00804     p_term *member = p_term_deref(args[0]);
00805     p_term *arg_head = p_term_deref(args[1]);
00806     p_term *object;
00807     p_term *predicate;
00808     p_term *list;
00809     p_term_clause_iter clause_iter;
00810     p_term *clause;
00811     p_term *body;
00812     p_exec_node *current;
00813     p_exec_node *new_current;
00814     p_exec_clause_node *next;
00815     int arity;
00816 
00817     
00818     if (!member || member->header.type != P_TERM_MEMBER_VARIABLE)
00819         return P_RESULT_FAIL;
00820     if (!arg_head || arg_head->header.type != P_TERM_FUNCTOR)
00821         return P_RESULT_FAIL;
00822     object = p_term_deref_member(context, member->member_var.object);
00823     if (!object || object->header.type != P_TERM_OBJECT) {
00824         *error = p_create_type_error(context, "object", object);
00825         return P_RESULT_ERROR;
00826     }
00827 
00828     
00829     predicate = p_term_property
00830         (context, object, member->member_var.name);
00831     if (!predicate) {
00832         *error = p_create_member_existence_error
00833             (context, object, member->member_var.name, arg_head);
00834         return P_RESULT_ERROR;
00835     }
00836     if (predicate->header.type == P_TERM_LIST) {
00837         
00838         list = predicate;
00839         arity = -1;
00840         do {
00841             predicate = p_term_deref(list->list.head);
00842             if (predicate &&
00843                     predicate->header.type == P_TERM_PREDICATE &&
00844                     predicate->header.size == arg_head->header.size) {
00845                 arity = (int)(arg_head->header.size);
00846                 break;
00847             }
00848             list = p_term_deref(list->list.tail);
00849         } while (list && list->header.type == P_TERM_LIST);
00850     } else if (predicate->header.type == P_TERM_PREDICATE) {
00851         
00852         arity = (int)(predicate->header.size);
00853     } else {
00854         *error = p_create_type_error(context, "predicate", predicate);
00855         return P_RESULT_ERROR;
00856     }
00857     if (arity != (int)(arg_head->header.size)) {
00858         *error = p_create_member_existence_error
00859             (context, object, member->member_var.name, arg_head);
00860         return P_RESULT_ERROR;
00861     }
00862 
00863     
00864     p_term_clauses_begin(predicate, arg_head, &clause_iter);
00865     while ((clause = p_term_clauses_next(&clause_iter)) != 0) {
00866         body = p_term_unify_clause(context, arg_head, clause);
00867         if (body) {
00868             current = context->current_node;
00869             if (p_term_clauses_has_more(&clause_iter)) {
00870                 next = GC_NEW(p_exec_clause_node);
00871                 new_current = GC_NEW(p_exec_node);
00872                 if (!next || !new_current)
00873                     return P_RESULT_FAIL;
00874                 next->parent.parent.goal = arg_head;
00875                 next->parent.parent.success_node = current->success_node;
00876                 next->parent.parent.cut_node = context->fail_node;
00877                 _p_context_init_fail_node
00878                     (context, &(next->parent), _p_context_clause_fail_func);
00879                 next->clause_iter = clause_iter;
00880                 new_current->goal = body;
00881                 new_current->success_node = current->success_node;
00882                 new_current->cut_node = context->fail_node;
00883                 context->current_node = new_current;
00884                 context->fail_node = &(next->parent);
00885             } else {
00886                 new_current = GC_NEW(p_exec_node);
00887                 if (!new_current)
00888                     return P_RESULT_FAIL;
00889                 new_current->goal = body;
00890                 new_current->success_node = current->success_node;
00891                 new_current->cut_node = context->fail_node;
00892                 context->current_node = new_current;
00893             }
00894             return P_RESULT_TREE_CHANGE;
00895         }
00896     }
00897     return P_RESULT_FAIL;
00898 }
00899 
00900 
00901 
01013 
01014 
01015 static p_term *p_builtin_parse_indicator
01016     (p_context *context, p_term *pred, int *arity, p_term **error)
01017 {
01018     p_term *name_term;
01019     p_term *arity_term;
01020     pred = p_term_deref_member(context, pred);
01021     if (!pred || (pred->header.type & P_TERM_VARIABLE) != 0) {
01022         *error = p_create_instantiation_error(context);
01023         return 0;
01024     } else if (pred->header.type != P_TERM_FUNCTOR ||
01025                pred->header.size != 2 ||
01026                pred->functor.functor_name != context->slash_atom) {
01027         *error = p_create_type_error
01028             (context, "predicate_indicator", pred);
01029         return 0;
01030     }
01031     name_term = p_term_deref_member(context, pred->functor.arg[0]);
01032     arity_term = p_term_deref_member(context, pred->functor.arg[1]);
01033     if (!name_term || (name_term->header.type & P_TERM_VARIABLE) != 0) {
01034         *error = p_create_instantiation_error(context);
01035         return 0;
01036     }
01037     if (!arity_term || (arity_term->header.type & P_TERM_VARIABLE) != 0) {
01038         *error = p_create_instantiation_error(context);
01039         return 0;
01040     }
01041     if (arity_term->header.type != P_TERM_INTEGER) {
01042         *error = p_create_type_error(context, "integer", arity_term);
01043         return 0;
01044     }
01045     if (name_term->header.type != P_TERM_ATOM) {
01046         *error = p_create_type_error(context, "atom", name_term);
01047         return 0;
01048     }
01049     *arity = p_term_integer_value(arity_term);
01050     if (*arity < 0) {
01051         *error = p_create_domain_error
01052             (context, "not_less_than_zero", arity_term);
01053         return 0;
01054     }
01055     return name_term;
01056 }
01057 
01113 static p_goal_result p_builtin_abolish
01114     (p_context *context, p_term **args, p_term **error)
01115 {
01116     p_term *name;
01117     int arity;
01118     name = p_builtin_parse_indicator(context, args[0], &arity, error);
01119     if (!name)
01120         return P_RESULT_ERROR;
01121     if (!p_db_clause_abolish(context, name, arity)) {
01122         *error = p_create_permission_error
01123             (context, "modify", "static_procedure", args[0]);
01124         return P_RESULT_ERROR;
01125     }
01126     return P_RESULT_TRUE;
01127 }
01128 
01129 static p_term *p_builtin_verify_database
01130     (p_context *context, p_term *arg, p_term **error)
01131 {
01132     p_term *database = p_term_deref_member(context, arg);
01133     if (!database || (database->header.type & P_TERM_VARIABLE) != 0) {
01134         *error = p_create_instantiation_error(context);
01135         return 0;
01136     }
01137     if (database->header.type != P_TERM_DATABASE) {
01138         *error = p_create_type_error(context, "database", database);
01139         return 0;
01140     }
01141     return database;
01142 }
01143 
01192 static p_goal_result p_builtin_abolish_2
01193     (p_context *context, p_term **args, p_term **error)
01194 {
01195     p_term *database;
01196     p_term *name;
01197     int arity;
01198     database = p_builtin_verify_database(context, args[1], error);
01199     if (!database)
01200         return P_RESULT_ERROR;
01201     name = p_builtin_parse_indicator(context, args[0], &arity, error);
01202     if (!name)
01203         return P_RESULT_ERROR;
01204     p_db_local_clause_abolish(context, database, name, arity);
01205     return P_RESULT_TRUE;
01206 }
01207 
01245 static p_goal_result p_builtin_abolish_database
01246     (p_context *context, p_term **args, p_term **error)
01247 {
01248     
01249     p_term *database = p_builtin_verify_database(context, args[0], error);
01250     if (!database)
01251         return P_RESULT_ERROR;
01252 
01253     
01254 
01255     database->database.predicates.root = 0;
01256     return P_RESULT_TRUE;
01257 }
01258 
01325 static p_goal_result p_builtin_assert
01326     (p_context *context, p_term **args, p_term **error,
01327      int at_start, p_term *database)
01328 {
01329     p_term *clause = p_term_deref_member(context, args[0]);
01330     p_term *head;
01331     p_term *pred;
01332     if (!clause || (clause->header.type & P_TERM_VARIABLE) != 0) {
01333         *error = p_create_instantiation_error(context);
01334         return P_RESULT_ERROR;
01335     }
01336     if (clause->header.type == P_TERM_FUNCTOR &&
01337             clause->header.size == 2 &&
01338             clause->functor.functor_name == context->dcg_atom) {
01339         
01340         clause = p_term_expand_dcg(context, clause);
01341     }
01342     if (clause->header.type == P_TERM_FUNCTOR &&
01343             clause->header.size == 2 &&
01344             clause->functor.functor_name == context->clause_atom) {
01345         head = p_term_deref_member(context, clause->functor.arg[0]);
01346     } else {
01347         head = clause;
01348         clause = p_term_create_functor
01349             (context, context->clause_atom, 2);
01350         p_term_bind_functor_arg(clause, 0, head);
01351         p_term_bind_functor_arg(clause, 1, context->true_atom);
01352     }
01353     if (!head || (head->header.type & P_TERM_VARIABLE) != 0) {
01354         *error = p_create_instantiation_error(context);
01355         return P_RESULT_ERROR;
01356     }
01357     if (head->header.type != P_TERM_ATOM &&
01358             head->header.type != P_TERM_FUNCTOR) {
01359         *error = p_create_type_error(context, "callable", head);
01360         return P_RESULT_ERROR;
01361     }
01362     clause = p_term_clone(context, clause);
01363     if (database) {
01364         if (at_start) {
01365             if (p_db_local_clause_assert_first(context, database, clause))
01366                 return P_RESULT_TRUE;
01367         } else {
01368             if (p_db_local_clause_assert_last(context, database, clause))
01369                 return P_RESULT_TRUE;
01370         }
01371     } else {
01372         if (at_start) {
01373             if (p_db_clause_assert_first(context, clause))
01374                 return P_RESULT_TRUE;
01375         } else {
01376             if (p_db_clause_assert_last(context, clause))
01377                 return P_RESULT_TRUE;
01378         }
01379     }
01380     pred = p_term_create_functor(context, context->slash_atom, 2);
01381     if (head->header.type == P_TERM_ATOM) {
01382         p_term_bind_functor_arg(pred, 0, head);
01383         p_term_bind_functor_arg
01384             (pred, 1, p_term_create_integer(context, 0));
01385     } else {
01386         p_term_bind_functor_arg(pred, 0, head->functor.functor_name);
01387         p_term_bind_functor_arg
01388             (pred, 1, p_term_create_integer
01389                             (context, (int)(head->header.size)));
01390     }
01391     *error = p_create_permission_error
01392         (context, "modify", "static_procedure", pred);
01393     return P_RESULT_ERROR;
01394 }
01395 static p_goal_result p_builtin_asserta
01396     (p_context *context, p_term **args, p_term **error)
01397 {
01398     return p_builtin_assert(context, args, error, 1, 0);
01399 }
01400 static p_goal_result p_builtin_assertz
01401     (p_context *context, p_term **args, p_term **error)
01402 {
01403     return p_builtin_assert(context, args, error, 0, 0);
01404 }
01405 
01465 static p_goal_result p_builtin_asserta_2
01466     (p_context *context, p_term **args, p_term **error)
01467 {
01468     p_term *database = p_builtin_verify_database(context, args[1], error);
01469     if (!database)
01470         return P_RESULT_ERROR;
01471     return p_builtin_assert(context, args, error, 1, database);
01472 }
01473 static p_goal_result p_builtin_assertz_2
01474     (p_context *context, p_term **args, p_term **error)
01475 {
01476     p_term *database = p_builtin_verify_database(context, args[1], error);
01477     if (!database)
01478         return P_RESULT_ERROR;
01479     return p_builtin_assert(context, args, error, 0, database);
01480 }
01481 
01483 typedef struct p_exec_clause_fetch_node p_exec_clause_fetch_node;
01484 struct p_exec_clause_fetch_node
01485 {
01486     p_exec_fail_node parent;
01487     p_term *head;
01488     p_term *body;
01489     p_term_clause_iter clause_iter;
01490 };
01493 
01494 static void _p_context_fetch_clause_fail_func
01495     (p_context *context, p_exec_fail_node *node)
01496 {
01497     p_exec_clause_fetch_node *current = (p_exec_clause_fetch_node *)node;
01498     p_term_clause_iter clause_iter = current->clause_iter;
01499     p_term *clause;
01500     p_term *body;
01501     p_exec_node *next;
01502     p_exec_clause_fetch_node *retry;
01503     void *marker;
01504     _p_context_basic_fail_func(context, node);
01505     while ((clause = p_term_clauses_next(&clause_iter)) != 0) {
01506         marker = p_context_mark_trail(context);
01507         body = p_term_unify_clause(context, current->head, clause);
01508         if (body && p_term_unify(context, current->body, body, P_BIND_DEFAULT)) {
01509             if (p_term_clauses_has_more(&clause_iter)) {
01510                 next = GC_NEW(p_exec_node);
01511                 retry = GC_NEW(p_exec_clause_fetch_node);
01512                 if (!next || !retry) {
01513                     current->parent.parent.goal = context->fail_atom;
01514                     return;
01515                 }
01516                 next->goal = context->true_atom;
01517                 next->success_node = current->parent.parent.success_node;
01518                 next->cut_node = current->parent.parent.cut_node;
01519                 retry->parent.parent.goal = current->parent.parent.goal;
01520                 retry->parent.parent.success_node =
01521                         current->parent.parent.success_node;
01522                 retry->parent.parent.cut_node =
01523                         current->parent.parent.cut_node;
01524                 retry->head = current->head;
01525                 retry->body = current->body;
01526                 retry->clause_iter = clause_iter;
01527                 _p_context_init_fail_node
01528                     (context, &(retry->parent),
01529                      _p_context_fetch_clause_fail_func);
01530                 retry->parent.fail_marker = marker;
01531                 context->current_node = next;
01532                 context->fail_node = &(retry->parent);
01533             } else {
01534                 next = GC_NEW(p_exec_node);
01535                 if (next) {
01536                     next->goal = context->true_atom;
01537                     next->success_node = current->parent.parent.success_node;
01538                     next->cut_node = current->parent.parent.cut_node;
01539                     context->current_node = next;
01540                 } else {
01541                     current->parent.parent.goal = context->true_atom;
01542                 }
01543             }
01544             return;
01545         }
01546         p_context_backtrack_trail(context, marker);
01547     }
01548     next = GC_NEW(p_exec_node);
01549     if (next) {
01550         next->goal = context->fail_atom;
01551         next->success_node = current->parent.parent.success_node;
01552         next->cut_node = current->parent.parent.cut_node;
01553                 context->current_node = next;
01554         context->current_node = next;
01555     } else {
01556         current->parent.parent.goal = context->fail_atom;
01557     }
01558 }
01559 
01591 static p_goal_result p_builtin_clause
01592     (p_context *context, p_term **args, p_term **error)
01593 {
01594     p_term *head = p_term_deref_member(context, args[0]);
01595     p_term *name;
01596     unsigned int arity;
01597     p_database_info *info;
01598     p_term *pred;
01599     p_term_clause_iter clause_iter;
01600     p_term *clause;
01601     p_term *body;
01602     void *marker;
01603     p_exec_node *current;
01604     p_exec_node *next;
01605     p_exec_clause_fetch_node *retry;
01606 
01607     
01608     if (!head || (head->header.type & P_TERM_VARIABLE) != 0) {
01609         *error = p_create_instantiation_error(context);
01610         return P_RESULT_ERROR;
01611     }
01612     if (head->header.type == P_TERM_ATOM) {
01613         name = head;
01614         arity = 0;
01615     } else if (head->header.type == P_TERM_FUNCTOR) {
01616         name = head->functor.functor_name;
01617         arity = head->header.size;
01618     } else {
01619         *error = p_create_type_error(context, "callable", head);
01620         return P_RESULT_ERROR;
01621     }
01622 
01623     
01624     info = _p_db_find_arity(name, arity);
01625     if (!info || !info->predicate)
01626         return P_RESULT_FAIL;
01627 
01628     
01629     if (info->flags & (P_PREDICATE_BUILTIN | P_PREDICATE_COMPILED)) {
01630         pred = p_term_create_functor(context, context->slash_atom, 2);
01631         p_term_bind_functor_arg(pred, 0, name);
01632         p_term_bind_functor_arg
01633             (pred, 1, p_term_create_integer(context, (int)arity));
01634         *error = p_create_permission_error
01635             (context, "access", "private_procedure", pred);
01636         return P_RESULT_ERROR;
01637     }
01638 
01639     
01640     p_term_clauses_begin(info->predicate, head, &clause_iter);
01641     while ((clause = p_term_clauses_next(&clause_iter)) != 0) {
01642         marker = p_context_mark_trail(context);
01643         body = p_term_unify_clause(context, head, clause);
01644         if (body && p_term_unify(context, args[1], body, P_BIND_DEFAULT)) {
01645             if (p_term_clauses_has_more(&clause_iter)) {
01646                 current = context->current_node;
01647                 next = GC_NEW(p_exec_node);
01648                 retry = GC_NEW(p_exec_clause_fetch_node);
01649                 if (!next || !retry)
01650                     return P_RESULT_FAIL;
01651                 next->goal = context->true_atom;
01652                 next->success_node = current->success_node;
01653                 next->cut_node = context->fail_node;
01654                 retry->parent.parent.goal = current->goal;
01655                 retry->parent.parent.success_node =
01656                         current->success_node;
01657                 retry->parent.parent.cut_node = context->fail_node;
01658                 retry->head = head;
01659                 retry->body = args[1];
01660                 retry->clause_iter = clause_iter;
01661                 _p_context_init_fail_node
01662                     (context, &(retry->parent),
01663                      _p_context_fetch_clause_fail_func);
01664                 context->current_node = next;
01665                 context->fail_node = &(retry->parent);
01666                 return P_RESULT_TREE_CHANGE;
01667             }
01668             return P_RESULT_TRUE;
01669         }
01670         p_context_backtrack_trail(context, marker);
01671     }
01672     return P_RESULT_FAIL;
01673 }
01674 
01704 static p_goal_result p_builtin_clause_3
01705     (p_context *context, p_term **args, p_term **error)
01706 {
01707     p_term *database;
01708     p_term *head = p_term_deref_member(context, args[0]);
01709     p_term *name;
01710     unsigned int arity;
01711     p_term_clause_iter clause_iter;
01712     p_term *clause;
01713     p_term *body;
01714     p_term *predicate;
01715     void *marker;
01716     p_exec_node *current;
01717     p_exec_node *next;
01718     p_exec_clause_fetch_node *retry;
01719 
01720     
01721     database = p_builtin_verify_database(context, args[2], error);
01722     if (!database)
01723         return P_RESULT_ERROR;
01724 
01725     
01726     if (!head || (head->header.type & P_TERM_VARIABLE) != 0) {
01727         *error = p_create_instantiation_error(context);
01728         return P_RESULT_ERROR;
01729     }
01730     if (head->header.type == P_TERM_ATOM) {
01731         name = head;
01732         arity = 0;
01733     } else if (head->header.type == P_TERM_FUNCTOR) {
01734         name = head->functor.functor_name;
01735         arity = head->header.size;
01736     } else {
01737         *error = p_create_type_error(context, "callable", head);
01738         return P_RESULT_ERROR;
01739     }
01740 
01741     
01742     predicate = p_term_database_lookup_predicate
01743         (database, name, arity);
01744     if (!predicate)
01745         return P_RESULT_FAIL;
01746 
01747     
01748     p_term_clauses_begin(predicate, head, &clause_iter);
01749     while ((clause = p_term_clauses_next(&clause_iter)) != 0) {
01750         marker = p_context_mark_trail(context);
01751         body = p_term_unify_clause(context, head, clause);
01752         if (body && p_term_unify(context, args[1], body, P_BIND_DEFAULT)) {
01753             if (p_term_clauses_has_more(&clause_iter)) {
01754                 current = context->current_node;
01755                 next = GC_NEW(p_exec_node);
01756                 retry = GC_NEW(p_exec_clause_fetch_node);
01757                 if (!next || !retry)
01758                     return P_RESULT_FAIL;
01759                 next->goal = context->true_atom;
01760                 next->success_node = current->success_node;
01761                 next->cut_node = context->fail_node;
01762                 retry->parent.parent.goal = current->goal;
01763                 retry->parent.parent.success_node =
01764                         current->success_node;
01765                 retry->parent.parent.cut_node = context->fail_node;
01766                 retry->head = head;
01767                 retry->body = args[1];
01768                 retry->clause_iter = clause_iter;
01769                 _p_context_init_fail_node
01770                     (context, &(retry->parent),
01771                      _p_context_fetch_clause_fail_func);
01772                 context->current_node = next;
01773                 context->fail_node = &(retry->parent);
01774                 return P_RESULT_TREE_CHANGE;
01775             }
01776             return P_RESULT_TRUE;
01777         }
01778         p_context_backtrack_trail(context, marker);
01779     }
01780     return P_RESULT_FAIL;
01781 }
01782 
01813 static p_goal_result p_builtin_new_database
01814     (p_context *context, p_term **args, p_term **error)
01815 {
01816     p_term *var = p_term_deref_member(context, args[0]);
01817     p_term *database;
01818     if (!var || (var->header.type & P_TERM_VARIABLE) == 0) {
01819         *error = p_create_type_error(context, "variable", var);
01820         return P_RESULT_ERROR;
01821     }
01822     database = p_term_create_database(context);
01823     if (p_term_unify(context, var, database, P_BIND_DEFAULT))
01824         return P_RESULT_TRUE;
01825     else
01826         return P_RESULT_FAIL;
01827 }
01828 
01894 static p_goal_result p_builtin_retract
01895     (p_context *context, p_term **args, p_term **error,
01896      p_term *database)
01897 {
01898     p_term *clause = p_term_deref_member(context, args[0]);
01899     p_term *head;
01900     p_term *pred;
01901     int result;
01902     if (!clause || (clause->header.type & P_TERM_VARIABLE) != 0) {
01903         *error = p_create_instantiation_error(context);
01904         return P_RESULT_ERROR;
01905     }
01906     if (clause->header.type == P_TERM_FUNCTOR &&
01907             clause->header.size == 2 &&
01908             clause->functor.functor_name == context->dcg_atom) {
01909         
01910         clause = p_term_expand_dcg(context, clause);
01911     }
01912     if (clause->header.type == P_TERM_FUNCTOR &&
01913             clause->header.size == 2 &&
01914             clause->functor.functor_name == context->clause_atom) {
01915         head = p_term_deref_member(context, clause->functor.arg[0]);
01916     } else {
01917         head = clause;
01918         clause = p_term_create_functor
01919             (context, context->clause_atom, 2);
01920         p_term_bind_functor_arg(clause, 0, head);
01921         p_term_bind_functor_arg(clause, 1, context->true_atom);
01922     }
01923     if (!head || (head->header.type & P_TERM_VARIABLE) != 0) {
01924         *error = p_create_instantiation_error(context);
01925         return P_RESULT_ERROR;
01926     }
01927     if (head->header.type != P_TERM_ATOM &&
01928             head->header.type != P_TERM_FUNCTOR) {
01929         *error = p_create_type_error(context, "callable", head);
01930         return P_RESULT_ERROR;
01931     }
01932     if (database)
01933         result = p_db_local_clause_retract(context, database, clause);
01934     else
01935         result = p_db_clause_retract(context, clause);
01936     if (result > 0)
01937         return P_RESULT_TRUE;
01938     else if (result < 0)
01939         return P_RESULT_FAIL;
01940     pred = p_term_create_functor(context, context->slash_atom, 2);
01941     if (head->header.type == P_TERM_ATOM) {
01942         p_term_bind_functor_arg(pred, 0, head);
01943         p_term_bind_functor_arg
01944             (pred, 1, p_term_create_integer(context, 0));
01945     } else {
01946         p_term_bind_functor_arg(pred, 0, head->functor.functor_name);
01947         p_term_bind_functor_arg
01948             (pred, 1, p_term_create_integer
01949                             (context, (int)(head->header.size)));
01950     }
01951     *error = p_create_permission_error
01952         (context, "modify", "static_procedure", pred);
01953     return P_RESULT_ERROR;
01954 }
01955 static p_goal_result p_builtin_retract_1
01956     (p_context *context, p_term **args, p_term **error)
01957 {
01958     return p_builtin_retract(context, args, error, 0);
01959 }
01960 
02015 static p_goal_result p_builtin_retract_2
02016     (p_context *context, p_term **args, p_term **error)
02017 {
02018     p_term *database = p_builtin_verify_database(context, args[1], error);
02019     if (!database)
02020         return P_RESULT_ERROR;
02021     return p_builtin_retract(context, args, error, database);
02022 }
02023 
02024 
02025 
02076 
02077 
02165 static p_goal_result p_builtin_consult
02166     (p_context *context, p_term **args, p_term **error)
02167 {
02168     p_term *name = p_term_deref_member(context, args[0]);
02169     int result;
02170     if (!name || (name->header.type & P_TERM_VARIABLE) != 0) {
02171         *error = p_create_instantiation_error(context);
02172         return P_RESULT_ERROR;
02173     } else if (name->header.type != P_TERM_ATOM &&
02174                name->header.type != P_TERM_STRING) {
02175         *error = p_create_type_error(context, "atom_or_string", name);
02176         return P_RESULT_ERROR;
02177     }
02178     result = p_context_consult_file
02179         (context, p_term_name(name), P_CONSULT_DEFAULT);
02180     if (!result) {
02181         return P_RESULT_TRUE;
02182     } else if (result != EINVAL) {
02183         *error = p_create_existence_error(context, "file", name);
02184         return P_RESULT_ERROR;
02185     } else {
02186         return P_RESULT_TRUE;
02187     }
02188 }
02189 
02243 static p_goal_result p_builtin_dynamic
02244     (p_context *context, p_term **args, p_term **error)
02245 {
02246     p_term *name;
02247     int arity;
02248     p_predicate_flags flags;
02249     name = p_builtin_parse_indicator(context, args[0], &arity, error);
02250     if (!name)
02251         return P_RESULT_ERROR;
02252     flags = p_db_predicate_flags(context, name, arity);
02253     if (flags & (P_PREDICATE_COMPILED | P_PREDICATE_BUILTIN)) {
02254         *error = p_create_permission_error
02255             (context, "modify", "static_procedure", args[0]);
02256         return P_RESULT_ERROR;
02257     }
02258     p_db_set_predicate_flag
02259         (context, name, arity, P_PREDICATE_DYNAMIC, 1);
02260     return P_RESULT_TRUE;
02261 }
02262 
02263 
02264 int p_context_builtin_import(p_context *context, const char *name);
02265 
02335 static p_goal_result p_builtin_import
02336     (p_context *context, p_term **args, p_term **error)
02337 {
02338     p_term *name = p_term_deref_member(context, args[0]);
02339     int result;
02340     if (!name || (name->header.type & P_TERM_VARIABLE) != 0) {
02341         *error = p_create_instantiation_error(context);
02342         return P_RESULT_ERROR;
02343     } else if (name->header.type != P_TERM_ATOM &&
02344                name->header.type != P_TERM_STRING) {
02345         *error = p_create_type_error(context, "atom_or_string", name);
02346         return P_RESULT_ERROR;
02347     }
02348     result = p_context_builtin_import(context, p_term_name(name));
02349     if (!result) {
02350         return P_RESULT_FAIL;
02351     } else if (result < 0) {
02352         *error = p_create_existence_error(context, "import", name);
02353         return P_RESULT_ERROR;
02354     } else {
02355         return P_RESULT_TRUE;
02356     }
02357 }
02358 
02443 static p_goal_result p_builtin_load_library
02444     (p_context *context, p_term **args, p_term **error)
02445 {
02446     p_term *name = p_term_deref_member(context, args[0]);
02447     if (!name || (name->header.type & P_TERM_VARIABLE) != 0) {
02448         *error = p_create_instantiation_error(context);
02449         return P_RESULT_ERROR;
02450     }
02451     if (name->header.type != P_TERM_ATOM &&
02452             name->header.type != P_TERM_STRING) {
02453         *error = p_create_type_error(context, "atom_or_string", name);
02454         return P_RESULT_ERROR;
02455     }
02456     return _p_context_load_library(context, name, error);
02457 }
02458 
02459 
02460 
02496 
02497 
02541 static p_goal_result p_builtin_logical_and
02542     (p_context *context, p_term **args, p_term **error)
02543 {
02544     p_exec_node *current = context->current_node;
02545     p_exec_node *next = GC_NEW(p_exec_node);
02546     p_exec_node *new_current = GC_NEW(p_exec_node);
02547     if (!next || !new_current)
02548         return P_RESULT_FAIL;
02549     new_current->goal = args[0];
02550     new_current->success_node = next;
02551     new_current->cut_node = current->cut_node;
02552     next->goal = args[1];
02553     next->success_node = current->success_node;
02554     next->cut_node = current->cut_node;
02555     context->current_node = new_current;
02556     return P_RESULT_TREE_CHANGE;
02557 }
02558 
02600 static p_goal_result p_builtin_logical_or
02601     (p_context *context, p_term **args, p_term **error)
02602 {
02603     p_term *term = p_term_deref_member(context, args[0]);
02604     p_exec_node *current;
02605     p_exec_fail_node *retry;
02606     p_exec_node *commit;
02607     p_exec_node *then;
02608     p_exec_node *if_node;
02609     if (term->header.type == P_TERM_FUNCTOR &&
02610             term->header.size == 2 &&
02611             term->functor.functor_name == context->if_atom) {
02612         
02613         current = context->current_node;
02614         if_node = GC_NEW(p_exec_node);
02615         retry = GC_NEW(p_exec_fail_node);
02616         commit = GC_NEW(p_exec_node);
02617         then = GC_NEW(p_exec_node);
02618         if (!if_node || !retry || !commit || !then)
02619             return P_RESULT_FAIL;
02620         retry->parent.goal = args[1];
02621         retry->parent.success_node = current->success_node;
02622         retry->parent.cut_node = context->fail_node;
02623         _p_context_init_fail_node
02624             (context, retry, _p_context_basic_fail_func);
02625         commit->goal = context->commit_atom;
02626         commit->success_node = then;
02627         commit->cut_node = context->fail_node;
02628         then->goal = p_term_arg(term, 1);
02629         then->success_node = current->success_node;
02630         then->cut_node = context->fail_node;
02631         if_node->goal = p_term_arg(term, 0);
02632         if_node->success_node = commit;
02633         if_node->cut_node = context->fail_node;
02634         context->current_node = if_node;
02635         context->fail_node = retry;
02636         return P_RESULT_TREE_CHANGE;
02637     } else {
02638         
02639         current = context->current_node;
02640         if_node = GC_NEW(p_exec_node);
02641         retry = GC_NEW(p_exec_fail_node);
02642         if (!if_node || !retry)
02643             return P_RESULT_FAIL;
02644         retry->parent.goal = args[1];
02645         retry->parent.success_node = current->success_node;
02646         retry->parent.cut_node = context->fail_node;
02647         _p_context_init_fail_node
02648             (context, retry, _p_context_basic_fail_func);
02649         if_node->goal = term;
02650         if_node->success_node = current->success_node;
02651         if_node->cut_node = context->fail_node;
02652         context->current_node = if_node;
02653         context->fail_node = retry;
02654         return P_RESULT_TREE_CHANGE;
02655     }
02656 }
02657 
02695 static char const p_builtin_logical_implies[] =
02696     "'=>'(A, B)\n"
02697     "{\n"
02698     "    if (call(A))\n"
02699     "        call(B);\n"
02700     "}\n";
02701 
02734 static char const p_builtin_logical_equiv[] =
02735     "'<=>'(A, B)\n"
02736     "{\n"
02737     "    if (call(A))\n"
02738     "        call((B, commit));\n" 
02739     "    else if (call(B))\n"
02740     "        fail;\n"
02741     "}\n";
02742 
02793 static p_goal_result p_builtin_call
02794     (p_context *context, p_term **args, p_term **error)
02795 {
02796     p_exec_node *current = context->current_node;
02797     p_exec_node *new_current = GC_NEW(p_exec_node);
02798     if (!new_current)
02799         return P_RESULT_FAIL;
02800     new_current->goal = args[0];
02801     new_current->success_node = current->success_node;
02802     new_current->cut_node = context->fail_node;
02803     context->current_node = new_current;
02804     return P_RESULT_TREE_CHANGE;
02805 }
02806 
02855 static p_goal_result p_builtin_call_2
02856     (p_context *context, p_term **args, p_term **error)
02857 {
02858     p_exec_node *current = context->current_node;
02859     p_exec_node *new_current;
02860     p_exec_pop_database_node *pop_database;
02861     p_term *database = p_builtin_verify_database(context, args[1], error);
02862     if (!database)
02863         return P_RESULT_ERROR;
02864     new_current = GC_NEW(p_exec_node);
02865     pop_database = GC_NEW(p_exec_pop_database_node);
02866     if (!new_current || !pop_database)
02867         return P_RESULT_FAIL;
02868     new_current->goal = args[0];
02869     new_current->success_node = &(pop_database->parent);
02870     new_current->cut_node = context->fail_node;
02871     pop_database->parent.goal = context->pop_database_atom;
02872     pop_database->parent.success_node = current->success_node;
02873     pop_database->parent.cut_node = context->fail_node;
02874     pop_database->database = context->database;
02875     context->current_node = new_current;
02876     context->database = database;
02877     return P_RESULT_TREE_CHANGE;
02878 }
02879 
02880 
02881 
02882 static p_goal_result p_builtin_pop_database
02883     (p_context *context, p_term **args, p_term **error)
02884 {
02885     p_exec_pop_database_node *pop_database;
02886     pop_database = (p_exec_pop_database_node *)(context->current_node);
02887     context->database = pop_database->database;
02888     return P_RESULT_TRUE;
02889 }
02890 
02929 int p_builtin_handle_catch(p_context *context, p_term *error)
02930 {
02931     p_exec_catch_node *catcher = context->catch_node;
02932     p_term *catch_atom = p_term_create_atom(context, "catch");
02933     p_term *catch_clause_atom = p_term_create_atom(context, "$$catch");
02934     p_term *goal;
02935     while (catcher != 0) {
02936         _p_context_basic_fail_func(context, &(catcher->parent));
02937         goal = p_term_deref_member(context, catcher->parent.parent.goal);
02938         if (goal->functor.functor_name == catch_atom) {
02939             
02940             if (p_term_unify(context, error,
02941                              goal->functor.arg[1], P_BIND_DEFAULT)) {
02942                 catcher->parent.parent.goal = goal->functor.arg[2];
02943                 context->current_node = &(catcher->parent.parent);
02944                 context->fail_node = catcher->parent.parent.cut_node;
02945                 context->catch_node = catcher->catch_parent;
02946                 return 1;
02947             }
02948         } else {
02949             
02950             p_term *list = p_term_deref_member(context, goal->functor.arg[1]);
02951             while (list && list->header.type == P_TERM_LIST) {
02952                 p_term *head = p_term_deref_member
02953                     (context, p_term_head(list));
02954                 if (head->header.type == P_TERM_FUNCTOR &&
02955                         head->header.size == 2 &&
02956                         head->functor.functor_name
02957                                 == catch_clause_atom) {
02958                     if (p_term_unify(context, p_term_arg(head, 0),
02959                                      error, P_BIND_DEFAULT)) {
02960                         catcher->parent.parent.goal = p_term_arg(head, 1);
02961                         context->current_node = &(catcher->parent.parent);
02962                         context->fail_node = catcher->parent.parent.cut_node;
02963                         context->catch_node = catcher->catch_parent;
02964                         return 1;
02965                     }
02966                 }
02967                 list = p_term_deref_member(context, p_term_tail(list));
02968             }
02969         }
02970         catcher = catcher->catch_parent;
02971     }
02972     context->current_node = 0;
02973     context->fail_node = 0;
02974     return 0;
02975 }
02976 static p_goal_result p_builtin_catch
02977     (p_context *context, p_term **args, p_term **error)
02978 {
02979     p_exec_node *current = context->current_node;
02980     p_exec_catch_node *catcher = GC_NEW(p_exec_catch_node);
02981     p_exec_node *new_current = GC_NEW(p_exec_node);
02982     p_exec_pop_catch_node *pop_catch = GC_NEW(p_exec_pop_catch_node);
02983     if (!catcher || !new_current || !pop_catch)
02984         return P_RESULT_FAIL;
02985     catcher->parent.parent.goal = current->goal;
02986     catcher->parent.parent.success_node = current->success_node;
02987     catcher->parent.parent.cut_node = context->fail_node;
02988     catcher->catch_parent = context->catch_node;
02989     _p_context_init_fail_node
02990         (context, &(catcher->parent), _p_context_basic_fail_func);
02991     new_current->goal = args[0];
02992     new_current->success_node = &(pop_catch->parent);
02993     new_current->cut_node = context->fail_node;
02994     pop_catch->parent.goal = context->pop_catch_atom;
02995     pop_catch->parent.success_node = current->success_node;
02996     pop_catch->parent.cut_node = context->fail_node;
02997     pop_catch->catch_node = context->catch_node;
02998     context->current_node = new_current;
02999     context->catch_node = catcher;
03000     return P_RESULT_TREE_CHANGE;
03001 }
03002 
03003 
03004 
03005 static p_goal_result p_builtin_pop_catch
03006     (p_context *context, p_term **args, p_term **error)
03007 {
03008     p_exec_pop_catch_node *pop_catch;
03009     pop_catch = (p_exec_pop_catch_node *)(context->current_node);
03010     context->catch_node = pop_catch->catch_node;
03011     return P_RESULT_TRUE;
03012 }
03013 
03071 static p_goal_result p_builtin_commit
03072     (p_context *context, p_term **args, p_term **error)
03073 {
03074     context->fail_node = context->current_node->cut_node;
03075     return P_RESULT_TRUE;
03076 }
03077 
03110 static char const p_builtin_do[] =
03111     "'$$do'(Vars, Body, Cond)\n"
03112     "{\n"
03113     "    '$$unbind'(Vars);\n"
03114     "    call(Body);\n"
03115     "    commit;\n"
03116     "    if (call(Cond))\n"
03117     "        '$$do'(Vars, Body, Cond);\n"
03118     "}\n"
03119     "'$$do'(Body, Cond)\n"
03120     "{\n"
03121     "    call(Body);\n"
03122     "    commit;\n"
03123     "    if (call(Cond))\n"
03124     "        '$$do'(Body, Cond);\n"
03125     "}\n";
03126 
03166 static char const p_builtin_not_provable[] =
03167     "'!'(Goal)\n"
03168     "{\n"
03169     "    if (call(Goal))\n"
03170     "        fail;\n"
03171     "}\n"
03172     "'\\\\+'(Goal)\n"
03173     "{\n"
03174     "    if (call(Goal))\n"
03175     "        fail;\n"
03176     "}\n";
03177 
03209 static p_goal_result p_builtin_fail
03210     (p_context *context, p_term **args, p_term **error)
03211 {
03212     return P_RESULT_FAIL;
03213 }
03214 
03261 static p_goal_result p_builtin_set_loop_var
03262     (p_context *context, p_term **args, p_term **error)
03263 {
03264     
03265     p_builtin_set_variable(p_term_arg(args[0], 0), args[1]);
03266     return P_RESULT_TRUE;
03267 }
03268 static char const p_builtin_for[] =
03269     "'$$for'(Vars, LoopVar, List, Body)\n"
03270     "{\n"
03271     "    var(List);\n"
03272     "    commit;\n"
03273     "    throw(error(instantiation_error, 'for'/2));\n"
03274     "}\n"
03275     "'$$for'(Vars, LoopVar, [], Body)\n"
03276     "{\n"
03277     "    commit;\n"
03278     "}\n"
03279     "'$$for'(Vars, LoopVar, [H|T], Body)\n"
03280     "{\n"
03281     "    commit;\n"
03282     "    '$$unbind'(Vars);\n"
03283     "    '$$set_loop_var'(LoopVar, H);\n"
03284     "    call(Body);\n"
03285     "    commit;\n"
03286     "    '$$for'(Vars, LoopVar, T, Body);\n"
03287     "}\n"
03288     "'$$for'(Vars, LoopVar, List, Body)\n"
03289     "{\n"
03290     "    throw(error(type_error(list, List), 'for'/2));\n"
03291     "}\n";
03292 
03321 static p_goal_result p_builtin_halt_0
03322     (p_context *context, p_term **args, p_term **error)
03323 {
03324     *error = p_term_create_integer(context, 0);
03325     return P_RESULT_HALT;
03326 }
03327 
03367 static p_goal_result p_builtin_halt_1
03368     (p_context *context, p_term **args, p_term **error)
03369 {
03370     p_term *exitval = p_term_deref_member(context, args[0]);
03371     if (!exitval || (exitval->header.type & P_TERM_VARIABLE) != 0) {
03372         *error = p_create_instantiation_error(context);
03373         return P_RESULT_ERROR;
03374     }
03375     if (exitval->header.type != P_TERM_INTEGER) {
03376         *error = p_create_type_error(context, "integer", exitval);
03377         return P_RESULT_ERROR;
03378     }
03379     *error = exitval;
03380     return P_RESULT_HALT;
03381 }
03382 
03431 static p_goal_result p_builtin_if
03432     (p_context *context, p_term **args, p_term **error)
03433 {
03434     p_exec_node *current = context->current_node;
03435     p_exec_node *commit = GC_NEW(p_exec_node);
03436     p_exec_node *then = GC_NEW(p_exec_node);
03437     p_exec_node *if_node = GC_NEW(p_exec_node);
03438     if (!commit || !then || !if_node)
03439         return P_RESULT_FAIL;
03440     commit->goal = context->commit_atom;
03441     commit->success_node = then;
03442     commit->cut_node = context->fail_node;
03443     then->goal = args[1];
03444     then->success_node = current->success_node;
03445     then->cut_node = context->fail_node;
03446     if_node->goal = args[0];
03447     if_node->success_node = commit;
03448     if_node->cut_node = context->fail_node;
03449     context->current_node = if_node;
03450     return P_RESULT_TREE_CHANGE;
03451 }
03452 
03503 static char const p_builtin_in[] =
03504     "'in'(Term, List)\n"
03505     "{\n"
03506     "    var(List);\n"
03507     "    commit;\n"
03508     "    throw(error(instantiation_error, 'in'/2));\n"
03509     "}\n"
03510     "'in'(Term, [Term|Tail]).\n"
03511     "'in'(Term, [Head|Tail])\n"
03512     "{\n"
03513     "    'in'(Term, Tail);\n"
03514     "}\n";
03515 
03544 static char const p_builtin_once[] =
03545     "once(Goal) { call((Goal, commit)); }";
03546 
03577 static char const p_builtin_repeat[] =
03578     "repeat() {}"
03579     "repeat() { repeat(); }";
03580 
03655 static char const p_builtin_switch[] =
03656     "'$$switch'(Value, [], Default)\n"
03657     "{\n"
03658     "    commit;\n"
03659     "    call(Default);\n"
03660     "}\n"
03661     "'$$switch'(Value, ['$$case'(Cases, Body)|Tail], Default)\n"
03662     "{\n"
03663     "    '$$switch_case_match'(Value, Cases);\n"
03664     "    commit;\n"
03665     "    call(Body);\n"
03666     "}\n"
03667     "'$$switch'(Value, [Head|Tail], Default)\n"
03668     "{\n"
03669     "    '$$switch'(Value, Tail, Default);\n"
03670     "}\n"
03671     "'$$switch_case_match'(Value, [])\n"
03672     "{\n"
03673     "    commit;\n"
03674     "    fail;\n"
03675     "}\n"
03676     "'$$switch_case_match'(Value, [Value|Tail])\n"
03677     "{\n"
03678     "    commit;\n"
03679     "}\n"
03680     "'$$switch_case_match'(Value, [Head|Tail])\n"
03681     "{\n"
03682     "    '$$switch_case_match'(Value, Tail);\n"
03683     "}\n";
03684 
03706 static p_goal_result p_builtin_throw
03707     (p_context *context, p_term **args, p_term **error)
03708 {
03709     *error = p_term_clone(context, args[0]);
03710     return P_RESULT_ERROR;
03711 }
03712 
03736 static p_goal_result p_builtin_true
03737     (p_context *context, p_term **args, p_term **error)
03738 {
03739     return P_RESULT_TRUE;
03740 }
03741 
03775 static char const p_builtin_while[] =
03776     "'$$while'(Vars, Cond, Body)\n"
03777     "{\n"
03778     "    '$$unbind'(Vars);\n"
03779     "    if (call(Cond)) {\n"
03780     "        call(Body);\n"
03781     "        commit;\n"
03782     "        '$$while'(Vars, Cond, Body);\n"
03783     "    }\n"
03784     "}\n"
03785     "'$$while'(Cond, Body)\n"
03786     "{\n"
03787     "    if (call(Cond)) {\n"
03788     "        call(Body);\n"
03789     "        commit;\n"
03790     "        '$$while'(Cond, Body);\n"
03791     "    }\n"
03792     "}\n";
03793 
03794 
03795 
03799 
03800 
03801 
03802 
03834 
03835 
03868 static p_goal_result p_builtin_term_eq
03869     (p_context *context, p_term **args, p_term **error)
03870 {
03871     if (p_term_unify(context, args[0], args[1], P_BIND_EQUALITY))
03872         return P_RESULT_TRUE;
03873     else
03874         return P_RESULT_FAIL;
03875 }
03876 
03912 static p_goal_result p_builtin_term_ne
03913     (p_context *context, p_term **args, p_term **error)
03914 {
03915     if (p_term_unify(context, args[0], args[1], P_BIND_EQUALITY))
03916         return P_RESULT_FAIL;
03917     else
03918         return P_RESULT_TRUE;
03919 }
03920 
03955 static p_goal_result p_builtin_term_lt
03956     (p_context *context, p_term **args, p_term **error)
03957 {
03958     if (p_term_precedes(context, args[0], args[1]) < 0)
03959         return P_RESULT_TRUE;
03960     else
03961         return P_RESULT_FAIL;
03962 }
03963 
04001 static p_goal_result p_builtin_term_le
04002     (p_context *context, p_term **args, p_term **error)
04003 {
04004     if (p_term_precedes(context, args[0], args[1]) <= 0)
04005         return P_RESULT_TRUE;
04006     else
04007         return P_RESULT_FAIL;
04008 }
04009 
04044 static p_goal_result p_builtin_term_gt
04045     (p_context *context, p_term **args, p_term **error)
04046 {
04047     if (p_term_precedes(context, args[0], args[1]) > 0)
04048         return P_RESULT_TRUE;
04049     else
04050         return P_RESULT_FAIL;
04051 }
04052 
04087 static p_goal_result p_builtin_term_ge
04088     (p_context *context, p_term **args, p_term **error)
04089 {
04090     if (p_term_precedes(context, args[0], args[1]) >= 0)
04091         return P_RESULT_TRUE;
04092     else
04093         return P_RESULT_FAIL;
04094 }
04095 
04096 
04097 
04109 
04110 
04223 static p_goal_result p_builtin_univ
04224     (p_context *context, p_term **args, p_term **error)
04225 {
04226     p_term *term = p_term_deref_member(context, args[0]);
04227     p_term *list = p_term_deref_member(context, args[1]);
04228     p_term *new_term;
04229     p_term *functor;
04230     p_term *member;
04231     p_term *list_args;
04232     int index, length;
04233     if ((term->header.type & P_TERM_VARIABLE) == 0) {
04234         if (list->header.type != P_TERM_VARIABLE &&
04235                 list->header.type != P_TERM_LIST) {
04236             *error = p_create_type_error(context, "list", list);
04237             return P_RESULT_ERROR;
04238         }
04239         switch (term->header.type) {
04240         case P_TERM_ATOM:
04241         case P_TERM_INTEGER:
04242         case P_TERM_REAL:
04243         case P_TERM_STRING:
04244         case P_TERM_OBJECT:
04245         case P_TERM_PREDICATE:
04246         case P_TERM_CLAUSE:
04247         case P_TERM_DATABASE:
04248             new_term = p_term_create_list
04249                 (context, term, context->nil_atom);
04250             break;
04251         case P_TERM_FUNCTOR:
04252             new_term = context->nil_atom;
04253             for (index = (int)(term->header.size - 1); index >= 0; --index) {
04254                 new_term = p_term_create_list
04255                     (context, term->functor.arg[index], new_term);
04256             }
04257             new_term = p_term_create_list
04258                 (context, term->functor.functor_name, new_term);
04259             break;
04260         case P_TERM_LIST:
04261             new_term = p_term_create_list
04262                 (context, context->dot_atom,
04263                     p_term_create_list
04264                         (context, term->list.head,
04265                          p_term_create_list
04266                             (context, term->list.tail,
04267                              context->nil_atom)));
04268             break;
04269         default: return P_RESULT_FAIL;
04270         }
04271         if (p_term_unify(context, list, new_term, P_BIND_DEFAULT))
04272             return P_RESULT_TRUE;
04273         else
04274             return P_RESULT_FAIL;
04275     } else {
04276         if (list == context->nil_atom) {
04277             *error = p_create_domain_error
04278                 (context, "non_empty_list", list);
04279             return P_RESULT_ERROR;
04280         }
04281         if (list->header.type != P_TERM_LIST) {
04282             *error = p_create_instantiation_error(context);
04283             return P_RESULT_ERROR;
04284         }
04285         length = 1;
04286         member = p_term_deref_member(context, list->list.tail);
04287         while (member != context->nil_atom) {
04288             if (!member || member->header.type != P_TERM_LIST) {
04289                 *error = p_create_instantiation_error(context);
04290                 return P_RESULT_ERROR;
04291             }
04292             ++length;
04293             member = p_term_deref_member(context, member->list.tail);
04294         }
04295         functor = p_term_deref_member(context, list->list.head);
04296         if ((functor->header.type & P_TERM_VARIABLE) != 0) {
04297             *error = p_create_instantiation_error(context);
04298             return P_RESULT_ERROR;
04299         }
04300         list_args = p_term_deref_member(context, list->list.tail);
04301         if (length == 1) {
04302             switch (functor->header.type) {
04303             case P_TERM_ATOM:
04304             case P_TERM_INTEGER:
04305             case P_TERM_REAL:
04306             case P_TERM_STRING:
04307             case P_TERM_OBJECT:
04308             case P_TERM_PREDICATE:
04309             case P_TERM_CLAUSE:
04310             case P_TERM_DATABASE:
04311                 new_term = functor;
04312                 break;
04313             default:
04314                 *error = p_create_type_error
04315                     (context, "atomic", functor);
04316                 return P_RESULT_ERROR;
04317             }
04318         } else if (functor == context->dot_atom && length == 3) {
04319             new_term = p_term_create_list
04320                 (context, list_args->list.head,
04321                  p_term_deref_member
04322                     (context, list_args->list.tail)->list.head);
04323         } else if (functor->header.type != P_TERM_ATOM) {
04324             *error = p_create_type_error(context, "atom", functor);
04325             return P_RESULT_ERROR;
04326         } else {
04327             new_term = p_term_create_functor
04328                 (context, functor, length - 1);
04329             for (index = 0; index < (length - 1); ++index) {
04330                 p_term_bind_functor_arg
04331                     (new_term, index, list_args->list.head);
04332                 list_args = p_term_deref_member
04333                     (context, list_args->list.tail);
04334             }
04335         }
04336         if (p_term_unify(context, term, new_term, P_BIND_DEFAULT))
04337             return P_RESULT_TRUE;
04338         else
04339             return P_RESULT_FAIL;
04340     }
04341 }
04342 
04393 static p_goal_result p_builtin_arg
04394     (p_context *context, p_term **args, p_term **error)
04395 {
04396     p_term *number = p_term_deref_member(context, args[0]);
04397     p_term *term = p_term_deref_member(context, args[1]);
04398     p_term *arg;
04399     int num;
04400     if (!number || (number->header.type & P_TERM_VARIABLE) != 0) {
04401         *error = p_create_instantiation_error(context);
04402         return P_RESULT_ERROR;
04403     }
04404     if (!term || (term->header.type & P_TERM_VARIABLE) != 0) {
04405         *error = p_create_instantiation_error(context);
04406         return P_RESULT_ERROR;
04407     }
04408     if (number->header.type != P_TERM_INTEGER) {
04409         *error = p_create_type_error(context, "integer", number);
04410         return P_RESULT_ERROR;
04411     }
04412     num = p_term_integer_value(number);
04413     if (num < 0) {
04414         *error = p_create_domain_error
04415             (context, "not_less_than_zero", number);
04416         return P_RESULT_ERROR;
04417     }
04418     if (term->header.type == P_TERM_FUNCTOR) {
04419         if (num > 0 && num <= (int)(term->header.size))
04420             arg = term->functor.arg[num - 1];
04421         else
04422             return P_RESULT_FAIL;
04423     } else if (term->header.type == P_TERM_LIST) {
04424         if (num == 1)
04425             arg = term->list.head;
04426         else if (num == 2)
04427             arg = term->list.tail;
04428         else
04429             return P_RESULT_FAIL;
04430     } else {
04431         *error = p_create_type_error(context, "compound", term);
04432         return P_RESULT_ERROR;
04433     }
04434     if (p_term_unify(context, args[2], arg, P_BIND_DEFAULT))
04435         return P_RESULT_TRUE;
04436     else
04437         return P_RESULT_FAIL;
04438 }
04439 
04469 static p_goal_result p_builtin_copy_term
04470     (p_context *context, p_term **args, p_term **error)
04471 {
04472     p_term *renamed = p_term_clone(context, args[0]);
04473     if (p_term_unify(context, renamed, args[1], P_BIND_DEFAULT))
04474         return P_RESULT_TRUE;
04475     else
04476         return P_RESULT_FAIL;
04477 }
04478 
04547 static p_goal_result p_builtin_functor
04548     (p_context *context, p_term **args, p_term **error)
04549 {
04550     p_term *term = p_term_deref_member(context, args[0]);
04551     p_term *name = p_term_deref_member(context, args[1]);
04552     p_term *arity = p_term_deref_member(context, args[2]);
04553     p_term *new_term;
04554     int arity_value, index;
04555     if (!term || !name || !arity) {
04556         *error = p_create_instantiation_error(context);
04557         return P_RESULT_ERROR;
04558     }
04559     if ((term->header.type & P_TERM_VARIABLE) == 0) {
04560         
04561         switch (term->header.type) {
04562         case P_TERM_ATOM:
04563         case P_TERM_INTEGER:
04564         case P_TERM_REAL:
04565         case P_TERM_STRING:
04566         case P_TERM_OBJECT:
04567         case P_TERM_PREDICATE:
04568         case P_TERM_CLAUSE:
04569         case P_TERM_DATABASE:
04570             if (!p_term_unify(context, name, term, P_BIND_DEFAULT))
04571                 return P_RESULT_FAIL;
04572             if (!p_term_unify(context, arity,
04573                               p_term_create_integer(context, 0),
04574                               P_BIND_DEFAULT))
04575                 return P_RESULT_FAIL;
04576             return P_RESULT_TRUE;
04577         case P_TERM_FUNCTOR:
04578             if (!p_term_unify(context, name,
04579                               term->functor.functor_name,
04580                               P_BIND_DEFAULT))
04581                 return P_RESULT_FAIL;
04582             if (!p_term_unify(context, arity,
04583                               p_term_create_integer
04584                                 (context, (int)(term->header.size)),
04585                               P_BIND_DEFAULT))
04586                 return P_RESULT_FAIL;
04587             return P_RESULT_TRUE;
04588         case P_TERM_LIST:
04589             if (!p_term_unify(context, name, context->dot_atom,
04590                               P_BIND_DEFAULT))
04591                 return P_RESULT_FAIL;
04592             if (!p_term_unify(context, arity,
04593                               p_term_create_integer(context, 2),
04594                               P_BIND_DEFAULT))
04595                 return P_RESULT_FAIL;
04596             return P_RESULT_TRUE;
04597         default: break;
04598         }
04599         return P_RESULT_FAIL;
04600     } else {
04601         
04602         if ((name->header.type & P_TERM_VARIABLE) != 0 ||
04603                 (arity->header.type & P_TERM_VARIABLE) != 0) {
04604             *error = p_create_instantiation_error(context);
04605             return P_RESULT_ERROR;
04606         }
04607         switch (name->header.type) {
04608         case P_TERM_ATOM:
04609         case P_TERM_INTEGER:
04610         case P_TERM_REAL:
04611         case P_TERM_STRING:
04612         case P_TERM_OBJECT:
04613         case P_TERM_PREDICATE:
04614         case P_TERM_CLAUSE:
04615         case P_TERM_DATABASE:
04616             break;
04617         default:
04618             *error = p_create_type_error(context, "atomic", name);
04619             return P_RESULT_ERROR;
04620         }
04621         if (arity->header.type != P_TERM_INTEGER) {
04622             *error = p_create_type_error(context, "integer", arity);
04623             return P_RESULT_ERROR;
04624         }
04625         arity_value = p_term_integer_value(arity);
04626         if (arity_value < 0) {
04627             *error = p_create_domain_error
04628                 (context, "not_less_than_zero", arity);
04629             return P_RESULT_ERROR;
04630         }
04631         if (arity_value == 0) {
04632             new_term = name;
04633         } else if (name->header.type != P_TERM_ATOM) {
04634             *error = p_create_type_error(context, "atom", name);
04635             return P_RESULT_ERROR;
04636         } else if (name == context->dot_atom && arity_value == 2) {
04637             new_term = p_term_create_list
04638                 (context, p_term_create_variable(context),
04639                  p_term_create_variable(context));
04640         } else {
04641             new_term = p_term_create_functor
04642                 (context, name, arity_value);
04643             for (index = 0; index < arity_value; ++index) {
04644                 p_term_bind_functor_arg
04645                     (new_term, index, p_term_create_variable(context));
04646             }
04647         }
04648         if (!p_term_unify(context, term, new_term, P_BIND_DEFAULT))
04649             return P_RESULT_FAIL;
04650         return P_RESULT_TRUE;
04651     }
04652 }
04653 
04654 
04655 
04669 
04670 
04707 static p_goal_result p_builtin_unify
04708     (p_context *context, p_term **args, p_term **error)
04709 {
04710     if (p_term_unify(context, args[0], args[1], P_BIND_DEFAULT))
04711         return P_RESULT_TRUE;
04712     else
04713         return P_RESULT_FAIL;
04714 }
04715 
04747 static p_goal_result p_builtin_not_unifiable
04748     (p_context *context, p_term **args, p_term **error)
04749 {
04750     void *marker = p_context_mark_trail(context);
04751     if (p_term_unify(context, args[0], args[1], P_BIND_DEFAULT)) {
04752         p_context_backtrack_trail(context, marker);
04753         return P_RESULT_FAIL;
04754     } else {
04755         return P_RESULT_TRUE;
04756     }
04757 }
04758 
04784 static p_goal_result p_builtin_unifiable
04785     (p_context *context, p_term **args, p_term **error)
04786 {
04787     void *marker = p_context_mark_trail(context);
04788     if (p_term_unify(context, args[0], args[1], P_BIND_DEFAULT)) {
04789         p_context_backtrack_trail(context, marker);
04790         return P_RESULT_TRUE;
04791     } else {
04792         return P_RESULT_FAIL;
04793     }
04794 }
04795 
04825 static p_goal_result p_builtin_unifiable_one_way
04826     (p_context *context, p_term **args, p_term **error)
04827 {
04828     void *marker = p_context_mark_trail(context);
04829     if (p_term_unify(context, args[0], args[1], P_BIND_ONE_WAY)) {
04830         p_context_backtrack_trail(context, marker);
04831         return P_RESULT_TRUE;
04832     } else {
04833         return P_RESULT_FAIL;
04834     }
04835 }
04836 
04864 static p_goal_result p_builtin_unify_one_way
04865     (p_context *context, p_term **args, p_term **error)
04866 {
04867     if (p_term_unify(context, args[0], args[1], P_BIND_ONE_WAY))
04868         return P_RESULT_TRUE;
04869     else
04870         return P_RESULT_FAIL;
04871 }
04872 
04873 
04874 
04899 
04900 
04935 static p_goal_result p_builtin_atom
04936     (p_context *context, p_term **args, p_term **error)
04937 {
04938     p_term *term = p_term_deref_member(context, args[0]);
04939     if (p_term_type(term) == P_TERM_ATOM)
04940         return P_RESULT_TRUE;
04941     else
04942         return P_RESULT_FAIL;
04943 }
04944 
04979 static p_goal_result p_builtin_atomic
04980     (p_context *context, p_term **args, p_term **error)
04981 {
04982     p_term *term = p_term_deref_member(context, args[0]);
04983     int type = p_term_type(term);
04984     if (type == P_TERM_ATOM || type == P_TERM_INTEGER ||
04985             type == P_TERM_REAL || type == P_TERM_STRING)
04986         return P_RESULT_TRUE;
04987     else
04988         return P_RESULT_FAIL;
04989 }
04990 
05023 static p_goal_result p_builtin_class_1
05024     (p_context *context, p_term **args, p_term **error)
05025 {
05026     p_term *term = p_term_deref_member(context, args[0]);
05027     if (p_term_is_class_object(context, term)) {
05028         return P_RESULT_TRUE;
05029     } else if (p_term_type(term) == P_TERM_ATOM) {
05030         p_database_info *db_info = term->atom.db_info;
05031         if (!db_info || !(db_info->class_info))
05032             return P_RESULT_FAIL;
05033         return P_RESULT_TRUE;
05034     } else {
05035         return P_RESULT_FAIL;
05036     }
05037 }
05038 
05078 static p_goal_result p_builtin_class_2
05079     (p_context *context, p_term **args, p_term **error)
05080 {
05081     p_term *name = p_term_deref_member(context, args[0]);
05082     p_term *class_object = p_term_deref_member(context, args[1]);
05083     int type = p_term_type(name);
05084     if (type == P_TERM_ATOM) {
05085         p_database_info *db_info = name->atom.db_info;
05086         if (!db_info || !(db_info->class_info))
05087             return P_RESULT_FAIL;
05088         if (p_term_unify(context, class_object,
05089                          db_info->class_info->class_object,
05090                          P_BIND_DEFAULT))
05091             return P_RESULT_TRUE;
05092     } else if ((type & P_TERM_VARIABLE) &&
05093                p_term_is_class_object(context, class_object)) {
05094         p_term *class_name = p_term_property
05095             (context, args[1], p_term_class_name_atom(context));
05096         if (p_term_unify(context, name, class_name, P_BIND_DEFAULT))
05097             return P_RESULT_TRUE;
05098     }
05099     return P_RESULT_FAIL;
05100 }
05101 
05132 static p_goal_result p_builtin_compound
05133     (p_context *context, p_term **args, p_term **error)
05134 {
05135     p_term *term = p_term_deref_member(context, args[0]);
05136     int type = p_term_type(term);
05137     if (type == P_TERM_FUNCTOR || type == P_TERM_LIST)
05138         return P_RESULT_TRUE;
05139     else
05140         return P_RESULT_FAIL;
05141 }
05142 
05164 static p_goal_result p_builtin_database
05165     (p_context *context, p_term **args, p_term **error)
05166 {
05167     p_term *term = p_term_deref_member(context, args[0]);
05168     if (p_term_type(term) == P_TERM_DATABASE)
05169         return P_RESULT_TRUE;
05170     else
05171         return P_RESULT_FAIL;
05172 }
05173 
05205 static p_goal_result p_builtin_float
05206     (p_context *context, p_term **args, p_term **error)
05207 {
05208     p_term *term = p_term_deref_member(context, args[0]);
05209     if (p_term_type(term) == P_TERM_REAL)
05210         return P_RESULT_TRUE;
05211     else
05212         return P_RESULT_FAIL;
05213 }
05214 
05246 static p_goal_result p_builtin_integer
05247     (p_context *context, p_term **args, p_term **error)
05248 {
05249     p_term *term = p_term_deref_member(context, args[0]);
05250     if (p_term_type(term) == P_TERM_INTEGER)
05251         return P_RESULT_TRUE;
05252     else
05253         return P_RESULT_FAIL;
05254 }
05255 
05287 static p_goal_result p_builtin_nonvar
05288     (p_context *context, p_term **args, p_term **error)
05289 {
05290     p_term *term = p_term_deref_member(context, args[0]);
05291     if (p_term_type(term) & P_TERM_VARIABLE)
05292         return P_RESULT_FAIL;
05293     else
05294         return P_RESULT_TRUE;
05295 }
05296 
05329 static p_goal_result p_builtin_number
05330     (p_context *context, p_term **args, p_term **error)
05331 {
05332     p_term *term = p_term_deref_member(context, args[0]);
05333     int type = p_term_type(term);
05334     if (type == P_TERM_INTEGER || type == P_TERM_REAL)
05335         return P_RESULT_TRUE;
05336     else
05337         return P_RESULT_FAIL;
05338 }
05339 
05371 static p_goal_result p_builtin_object_1
05372     (p_context *context, p_term **args, p_term **error)
05373 {
05374     p_term *term = p_term_deref_member(context, args[0]);
05375     if (p_term_is_instance_object(context, term))
05376         return P_RESULT_TRUE;
05377     else
05378         return P_RESULT_FAIL;
05379 }
05380 
05417 static p_goal_result p_builtin_object_2
05418     (p_context *context, p_term **args, p_term **error)
05419 {
05420     p_term *term = p_term_deref_member(context, args[0]);
05421     p_term *class_object = p_term_deref_member(context, args[1]);
05422     if (p_term_type(class_object) == P_TERM_ATOM) {
05423         p_database_info *db_info = class_object->atom.db_info;
05424         if (!db_info || !(db_info->class_info))
05425             return P_RESULT_FAIL;
05426         class_object = db_info->class_info->class_object;
05427     }
05428     if (p_term_is_instance_of(context, term, class_object))
05429         return P_RESULT_TRUE;
05430     else
05431         return P_RESULT_FAIL;
05432 }
05433 
05464 static p_goal_result p_builtin_predicate_1
05465     (p_context *context, p_term **args, p_term **error)
05466 {
05467     p_term *term = p_term_deref_member(context, args[0]);
05468     if (p_term_type(term) == P_TERM_PREDICATE)
05469         return P_RESULT_TRUE;
05470     else
05471         return P_RESULT_FAIL;
05472 }
05473 
05526 static p_goal_result p_builtin_predicate_2
05527     (p_context *context, p_term **args, p_term **error)
05528 {
05529     p_term *term = p_term_deref_member(context, args[0]);
05530     if (!term) {
05531         *error = p_create_instantiation_error(context);
05532         return P_RESULT_ERROR;
05533     }
05534     if ((term->header.type & P_TERM_VARIABLE) != 0) {
05535         p_term *name;
05536         int arity;
05537         p_database_info *info;
05538         name = p_builtin_parse_indicator
05539             (context, args[1], &arity, error);
05540         if (!name)
05541             return P_RESULT_ERROR;
05542         info = _p_db_find_arity(name, arity);
05543         if (info && info->predicate) {
05544             if (p_term_unify(context, term, info->predicate,
05545                              P_BIND_DEFAULT))
05546                 return P_RESULT_TRUE;
05547         } else if (info && info->builtin_func) {
05548             
05549             p_term *pred = p_term_create_predicate
05550                 (context, name, arity);
05551             info->predicate = pred;
05552             if (p_term_unify(context, term, pred, P_BIND_DEFAULT))
05553                 return P_RESULT_TRUE;
05554         }
05555         return P_RESULT_FAIL;
05556     } else {
05557         p_term *pred = p_term_create_functor
05558             (context, context->slash_atom, 2);
05559         p_term_bind_functor_arg(pred, 0, term->predicate.name);
05560         p_term_bind_functor_arg
05561             (pred, 1, p_term_create_integer
05562                 (context, (int)(term->header.size)));
05563         if (p_term_unify(context, args[1], pred, P_BIND_DEFAULT))
05564             return P_RESULT_TRUE;
05565         else
05566             return P_RESULT_FAIL;
05567     }
05568 }
05569 
05597 static p_goal_result p_builtin_string
05598     (p_context *context, p_term **args, p_term **error)
05599 {
05600     p_term *term = p_term_deref_member(context, args[0]);
05601     if (p_term_type(term) == P_TERM_STRING)
05602         return P_RESULT_TRUE;
05603     else
05604         return P_RESULT_FAIL;
05605 }
05606 
05637 static p_goal_result p_builtin_var
05638     (p_context *context, p_term **args, p_term **error)
05639 {
05640     p_term *term = p_term_deref_member(context, args[0]);
05641     if (p_term_type(term) & P_TERM_VARIABLE)
05642         return P_RESULT_TRUE;
05643     else
05644         return P_RESULT_FAIL;
05645 }
05646 
05647 
05648 
05668 
05669 
05670 int p_term_occurs_in(const p_term *var, const p_term *value);
05671 p_goal_result p_arith_eval
05672     (p_context *context, p_arith_value *result,
05673      p_term *expr, p_term **error);
05674 
05675 
05676 
05677 P_INLINE p_term *p_term_resolve_variable(p_context *context, p_term *var)
05678 {
05679     p_term *value;
05680     if (!var || var->header.type == P_TERM_VARIABLE)
05681         return var;
05682     if (var->header.type != P_TERM_MEMBER_VARIABLE)
05683         return 0;
05684     p_term_deref_own_member(context, var);
05685     value = var->var.value;
05686     if (value && value->header.type == P_TERM_VARIABLE)
05687         return value;
05688     return 0;
05689 }
05690 
05732 static p_goal_result p_builtin_assign
05733     (p_context *context, p_term **args, p_term **error)
05734 {
05735     p_term *var;
05736     var = p_term_resolve_variable(context, args[0]);
05737     if (!var) {
05738         *error = p_create_type_error(context, "variable", args[0]);
05739         return P_RESULT_ERROR;
05740     }
05741     var->var.value = p_term_clone(context, args[1]);
05742     return P_RESULT_TRUE;
05743 }
05744 
05787 static p_goal_result p_builtin_num_assign
05788     (p_context *context, p_term **args, p_term **error)
05789 {
05790     p_term *var;
05791     p_arith_value value;
05792     p_goal_result result;
05793     var = p_term_resolve_variable(context, args[0]);
05794     if (!var) {
05795         *error = p_create_type_error(context, "variable", args[0]);
05796         return P_RESULT_ERROR;
05797     }
05798     result = p_arith_eval(context, &value, args[1], error);
05799     if (result != P_RESULT_TRUE)
05800         return result;
05801     switch (value.type) {
05802     case P_TERM_INTEGER:
05803         var->var.value =
05804             p_term_create_integer(context, value.integer_value);
05805         break;
05806     case P_TERM_REAL:
05807         var->var.value =
05808             p_term_create_real(context, value.real_value);
05809         break;
05810     case P_TERM_STRING:
05811         var->var.value = value.string_value;
05812         break;
05813     default: return P_RESULT_FAIL;
05814     }
05815     return P_RESULT_TRUE;
05816 }
05817 
05859 static p_goal_result p_builtin_bt_assign
05860     (p_context *context, p_term **args, p_term **error)
05861 {
05862     p_term *var;
05863     p_term *prev;
05864     var = p_term_resolve_variable(context, args[0]);
05865     if (!var) {
05866         *error = p_create_type_error(context, "variable", args[0]);
05867         return P_RESULT_ERROR;
05868     }
05869     prev = var->var.value;
05870     var->var.value = 0;
05871     if (!p_term_occurs_in(var, args[1])) {
05872         _p_context_record_contents_in_trail
05873             (context, (void **)&(var->var.value), prev);
05874         var->var.value = args[1];
05875         return P_RESULT_TRUE;
05876     }
05877     var->var.value = prev;
05878     return P_RESULT_FAIL;
05879 }
05880 
05922 static p_goal_result p_builtin_bt_num_assign
05923     (p_context *context, p_term **args, p_term **error)
05924 {
05925     p_term *var;
05926     p_arith_value value;
05927     p_goal_result result;
05928     var = p_term_resolve_variable(context, args[0]);
05929     if (!var) {
05930         *error = p_create_type_error(context, "variable", args[0]);
05931         return P_RESULT_ERROR;
05932     }
05933     result = p_arith_eval(context, &value, args[1], error);
05934     if (result != P_RESULT_TRUE)
05935         return result;
05936     _p_context_record_contents_in_trail
05937         (context, (void **)&(var->var.value), var->var.value);
05938     switch (value.type) {
05939     case P_TERM_INTEGER:
05940         var->var.value =
05941             p_term_create_integer(context, value.integer_value);
05942         break;
05943     case P_TERM_REAL:
05944         var->var.value =
05945             p_term_create_real(context, value.real_value);
05946         break;
05947     case P_TERM_STRING:
05948         var->var.value = value.string_value;
05949         break;
05950     default: return P_RESULT_FAIL;
05951     }
05952     return P_RESULT_TRUE;
05953 }
05954 
05955 
05956 
05957 
05958 static p_goal_result p_builtin_line
05959     (p_context *context, p_term **args, p_term **error)
05960 {
05961     
05962     context->current_node->goal = args[2];
05963     return P_RESULT_TREE_CHANGE;
05964 }
05965 
05966 
05967 static p_goal_result p_builtin_unique
05968     (p_context *context, p_term **args, p_term **error)
05969 {
05970     p_term *value = p_term_create_integer
05971         (context, (context->unique_num)++);
05972     if (p_term_unify(context, args[0], value, P_BIND_DEFAULT))
05973         return P_RESULT_TRUE;
05974     else
05975         return P_RESULT_FAIL;
05976 }
05977 
05978 
05979 static p_goal_result p_builtin_witness
05980     (p_context *context, p_term **args, p_term **error)
05981 {
05982     p_term *term = p_term_deref_member(context, args[0]);
05983     p_term *subgoal = 0;
05984     p_term *list = p_term_witness(context, term, &subgoal);
05985     if (!p_term_unify(context, args[1], list, P_BIND_DEFAULT))
05986         return P_RESULT_FAIL;
05987     if (!p_term_unify(context, args[2], subgoal, P_BIND_DEFAULT))
05988         return P_RESULT_FAIL;
05989     return P_RESULT_TRUE;
05990 }
05991 
05992 void _p_db_init_builtins(p_context *context)
05993 {
05994     static struct p_builtin const builtins[] = {
05995         {"=", 2, p_builtin_unify},
05996         {"!=", 2, p_builtin_not_unifiable},
05997         {"\\=", 2, p_builtin_not_unifiable},
05998         {"==", 2, p_builtin_term_eq},
05999         {"!==", 2, p_builtin_term_ne},
06000         {"\\==", 2, p_builtin_term_ne},
06001         {"@<", 2, p_builtin_term_lt},
06002         {"@<=", 2, p_builtin_term_le},
06003         {"@=<", 2, p_builtin_term_le},
06004         {"@>", 2, p_builtin_term_gt},
06005         {"@>=", 2, p_builtin_term_ge},
06006         {"!", 0, p_builtin_commit},
06007         {",", 2, p_builtin_logical_and},
06008         {"&&", 2, p_builtin_logical_and},
06009         {"||", 2, p_builtin_logical_or},
06010         {"->", 2, p_builtin_if},
06011         {"?-", 1, p_builtin_call},
06012         {":-", 1, p_builtin_call},
06013         {"=..", 2, p_builtin_univ},
06014         {":=", 2, p_builtin_assign},
06015         {"::=", 2, p_builtin_num_assign},
06016         {":==", 2, p_builtin_bt_assign},
06017         {"::==", 2, p_builtin_bt_num_assign},
06018         {"abolish", 1, p_builtin_abolish},
06019         {"abolish", 2, p_builtin_abolish_2},
06020         {"abolish_database", 1, p_builtin_abolish_database},
06021         {"arg", 3, p_builtin_arg},
06022         {"asserta", 1, p_builtin_asserta},
06023         {"asserta", 2, p_builtin_asserta_2},
06024         {"assertz", 1, p_builtin_assertz},
06025         {"assertz", 2, p_builtin_assertz_2},
06026         {"atom", 1, p_builtin_atom},
06027         {"atomic", 1, p_builtin_atomic},
06028         {"call", 1, p_builtin_call},
06029         {"call", 2, p_builtin_call_2},
06030         {"$$call_member", 2, p_builtin_call_member},
06031         {"catch", 3, p_builtin_catch},
06032         {"class", 1, p_builtin_class_1},
06033         {"class", 2, p_builtin_class_2},
06034         {"clause", 2, p_builtin_clause},
06035         {"clause", 3, p_builtin_clause_3},
06036         {"commit", 0, p_builtin_commit},
06037         {"compound", 1, p_builtin_compound},
06038         {"consult", 1, p_builtin_consult},
06039         {"copy_term", 2, p_builtin_copy_term},
06040         {"database", 1, p_builtin_database},
06041         {"dynamic", 1, p_builtin_dynamic},
06042         {"fail", 0, p_builtin_fail},
06043         {"false", 0, p_builtin_fail},
06044         {"float", 1, p_builtin_float},
06045         {"functor", 3, p_builtin_functor},
06046         {"halt", 0, p_builtin_halt_0},
06047         {"halt", 1, p_builtin_halt_1},
06048         {"import", 1, p_builtin_import},
06049         {"initialization", 1, p_builtin_call},
06050         {"integer", 1, p_builtin_integer},
06051         {"$$line", 3, p_builtin_line},
06052         {"load_library", 1, p_builtin_load_library},
06053         {"$$new", 2, p_builtin_new},
06054         {"new_class", 4, p_builtin_new_class},
06055         {"new_database", 1, p_builtin_new_database},
06056         {"new_object", 3, p_builtin_new_object},
06057         {"nonvar", 1, p_builtin_nonvar},
06058         {"number", 1, p_builtin_number},
06059         {"object", 1, p_builtin_object_1},
06060         {"object", 2, p_builtin_object_2},
06061         {"$$pop_catch", 0, p_builtin_pop_catch},
06062         {"$$pop_database", 0, p_builtin_pop_database},
06063         {"predicate", 1, p_builtin_predicate_1},
06064         {"predicate", 2, p_builtin_predicate_2},
06065         {"retract", 1, p_builtin_retract_1},
06066         {"retract", 2, p_builtin_retract_2},
06067         {"$$set_loop_var", 2, p_builtin_set_loop_var},
06068         {"string", 1, p_builtin_string},
06069         {"throw", 1, p_builtin_throw},
06070         {"true", 0, p_builtin_true},
06071         {"$$try", 2, p_builtin_catch},
06072         {"$$unbind", 1, p_builtin_unbind},
06073         {"unifiable", 2, p_builtin_unifiable},
06074         {"unifiable_one_way", 2, p_builtin_unifiable_one_way},
06075         {"unify_one_way", 2, p_builtin_unify_one_way},
06076         {"unify_with_occurs_check", 2, p_builtin_unify},
06077         {"$$unique", 1, p_builtin_unique},
06078         {"var", 1, p_builtin_var},
06079         {"$$witness", 3, p_builtin_witness},
06080         {0, 0, 0}
06081     };
06082     static const char * const builtin_sources[] = {
06083         p_builtin_logical_equiv,
06084         p_builtin_logical_implies,
06085         p_builtin_do,
06086         p_builtin_for,
06087         p_builtin_in,
06088         p_builtin_not_provable,
06089         p_builtin_once,
06090         p_builtin_repeat,
06091         p_builtin_switch,
06092         p_builtin_while,
06093         0
06094     };
06095     _p_db_register_builtins(context, builtins);
06096     _p_db_register_sources(context, builtin_sources);
06097 }