#include "structures.h" /* the function de_ref, which follows a chain of variables until it reaches a non_variable */ term_pointer de_ref(term_pointer t, var_array *var) { int count=0; while(count<1000&& t->term_type==VARIABLE && var->array[t->functor]!=NULL) { count++; t=var->array[t->functor]; } if (count==1000) { printf("Error: circular term\n"); return NULL; } return t; } /* ============================================================ | shallow_identical() | |----------------------------------------------------------| | Params : 1)a term | | 2)a term | | Desc : compares the terms at the top level (i.e. does not compare arguments). | Returns: SUCCESS if the two terms are identical at top level, Failure otherwise |==========================================================| */ int shallow_identical(struct term *t1, struct term *t2) { if (t1->term_type!=t2->term_type|| t1->functor!=t2->functor || t1->arity != t2->arity|| (t1->term_type==STRING &&t2->term_type==STRING&& strcmp(t1->const_string,t2->const_string)!=0)) return FAILURE; else return SUCCESS; } /* ============================================================ | match() | |----------------------------------------------------------| | Params : 1) | | 2) | | 3) | | Desc : matches a fully instantiated term with a non-instantiated term. Returns SUCCESS if the match is possible, returns FAIL if it is not possible |==========================================================| */ int match(term_pointer inst_term, term_pointer var_term, var_array *vars) { int so_far; int arg_counter=inst_term->arity; term_pointer ref=de_ref(var_term,vars); if (ref->term_type==VARIABLE) { vars->array[ref->functor]=inst_term; so_far = SUCCESS; } else { so_far=shallow_identical(inst_term,ref); while (so_far==SUCCESS && (arg_counter !=0)) { so_far=match(inst_term->argument_array[arg_counter-1], ref->argument_array[arg_counter-1], vars); arg_counter--; } } return so_far; } /* ============================================================ | dereference() | |----------------------------------------------------------| | Params : 1) | | 2) | | 3) | | Desc : makes a de-referenced version of a term |==========================================================| */ term_pointer dereference(term_pointer var_term, var_array *vars) { term_pointer t; term_pointer *arg_array; int i; if (var_term->term_type==VARIABLE && vars->array[var_term->functor]!=NULL) { t=dereference(vars->array[var_term->functor],vars); } else { arg_array=maketermarray(var_term->arity); for(i=0;iarity;i++) arg_array[i]=dereference(var_term->argument_array[i], vars); t=maketerm(var_term->term_type, var_term->functor, var_term->arity, var_term->const_string, arg_array); } return t; } /* ============================================================ | identical() | |----------------------------------------------------------| | Params : 1) | | 2) | | 3) | | Desc :checks to see if two terms are identical | | | Returns: | |==========================================================| */ int identical(struct term *t1, struct term *t2) { int i=0,answer; answer=shallow_identical(t1,t2); while (answer==SUCCESS && iarity) { answer=identical(t1->argument_array[i], t2->argument_array[i]); i++; } return answer; } /* ============================================================ | loose_match() | |----------------------------------------------------------| | Params : 1) a term | | 2) a term | | | | Desc : sees if the two terms match, disregarding | | shared variables | | Returns:SUCCESS or FAILURE | |==========================================================| */ int loose_match(struct term *t1, struct term *t2) { int i=0,answer; if (t1->term_type!=VARIABLE && t2->term_type!=VARIABLE) { answer=shallow_identical(t1,t2); while (answer && iarity) { answer=loose_match(t1->argument_array[i], t2->argument_array[i]); i++; } } else answer=SUCCESS; return answer; } /* the function prototype for de_ref, which follows a chain of variables until it reaches a non_variable */ term_pointer de_ref(term_pointer t, var_array *var); /* ============================================================ | is_ground() | |----------------------------------------------------------| | Params : 1) a term | | 2) a substitution array | | | | Returns: TRUE if the term is fully ground under that substitution, false otherwise | |==========================================================| */ int is_ground(term_ptr t, var_array *vars) { int answer,i; t=de_ref(t,vars); if (t->term_type==VARIABLE) answer=FALSE; else { answer=TRUE; for(i=0;answer&&iarity;i++) answer=is_ground(t->argument_array[i],vars); } return answer; } extern EvalFunctionDescriptor *get_eval_function(int functor); /* ============================================================ | eval_deref() | |----------------------------------------------------------| | Params : 1)a term | | 2)a var array | Desc : dereferences the term with respect to the var array, and evaluates all the evaluable functions | | | Returns: a term | |==========================================================| */ term_pointer eval_deref(term_pointer var_term, var_array *vars) { term_pointer t; term_pointer *arg_array; int i; EvalFunctionDescriptor *eval=NULL; var_term=de_ref(var_term, vars); arg_array=maketermarray(var_term->arity); for(i=0;iarity;i++) arg_array[i]=eval_deref(var_term->argument_array[i], vars); if (var_term->term_type==NONVAR) eval=get_eval_function(var_term->functor); if (eval==NULL) { t=maketerm(var_term->term_type, var_term->functor, var_term->arity, var_term->const_string, arg_array); } else { t=(eval->funct)(var_term->arity,arg_array); if (t!=NULL) { for(i=0;iarity;i++) free_term(arg_array[i]); free(arg_array); } else t=maketerm(var_term->term_type, var_term->functor, var_term->arity, var_term->const_string, arg_array); } return t; } /* ============================================================ | no_bind_match() | |----------------------------------------------------------| | Params : 1)a fully instantiated term | | 2)a (possibly) non_ground term | | 3)a var_array | | Desc : tries to match the first term against the eval_de-referenced version of the second term. Fails if the second term is not fully bound with respect to the var_array, or the two terms do not match.| | | | Returns: SUCCESS or FAILURE | |==========================================================| */ int no_bind_match(term_pointer inst_term, term_pointer var_term, var_array *vars) { if (vars==NULL) return identical(inst_term,var_term); else { struct term *temp=eval_deref(var_term,vars); int result=identical(inst_term,temp); free_term(temp); return result; } } /* ============================================================ | eval_match() | |----------------------------------------------------------| | Params : 1) an instantiated, evaluated term | | 2) a possibly uninstantiated term | | 3) a var array | | Desc : matches the first term against the dereferenced,| | evaluated version of the second term. Binds variables. | Returns: Success if match is possible. | |==========================================================| */ int eval_match(term_pointer inst_term, term_pointer var_term, var_array *vars) { struct term *temp=eval_deref(var_term,vars); int result=match(inst_term,temp,vars); free_term(temp); return result; }