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 }