private function eval_term(Term $term) { $rel = $term->getName(); $vars = $term->getVariables(); // $vars: [Variable] // all variables have value, no need to generate/iterate candidates if ($term->readyForResolve()) { return $this->isTrue($rel, $term->getInstances()); } /* ---------Have to fill the variables with a candidate value ----------- */ try { if ($this->isRule($rel)) { $candidates = $this->instance_generator_for_rule($term); } else { $candidates = $this->instance_generator_for_fact($term); } } catch (Exception $e) { //echo "no candidates for: \n"; echo " " . $term->toString() . "\n"; return FALSE; } foreach ($candidates as $_instances) { //echo $term->toString() . "\n"; //print_r($_instances); $term->assignValues($_instances); // if $term is fact, isTrue() will not assign value for // variables, it could make wrong variable value for next // term. for example: // hasDesc(A, C) :- hasChild(A, B) o hasDesc(A, C) // assign A = 'x', C = 'z' // hasDesc('x', 'z') :- hasChild('x', ?) o hasDesc(?, 'z') // assign ? = 'y' // hasDesc('x', 'z') :- hasChild('x', 'y') o hasDesc('y', 'z') // if we don't assigin value to ? // hasDesc(?, 'z') will be evaulated // the candicate of ? could be ['x', 'y', 'z'], then // hasDesc('x', 'z') cause infinite loop if ($this->isTrue($rel, $_instances)) { // recursive eval next, if return true, return true // if next term false, continue the iteration if (NULL == $term->next()) { return TRUE; } // no more for eval if ($this->eval_term($term->next())) { return TRUE; } } } return FALSE; // all candidate are false. }