86 #include "binding_map.h"
89 using namespace std::chrono;
90 using namespace r_code;
94 Value::Value(BindingMap *map) :
_Object(), map_(map) {
99 BoundValue::BoundValue(BindingMap *map) : Value(map) {
104 UnboundValue::UnboundValue(BindingMap *map, uint8 index) : Value(map), index_(index) {
106 ++map->unbound_values_;
109 UnboundValue::~UnboundValue() {
111 --map_->unbound_values_;
114 Value *UnboundValue::copy(BindingMap *map)
const {
116 return new UnboundValue(map, index_);
119 void UnboundValue::valuate(
Code *destination, uint16 write_index, uint16& )
const {
121 destination->code(write_index) = Atom::VLPointer(index_);
124 bool UnboundValue::match(
const Code *
object, uint16 index) {
126 Atom o_atom =
object->code(index);
127 switch (o_atom.getDescriptor()) {
129 map_->bind_variable(
new StructureValue(map_,
object, o_atom.asIndex()), index_);
132 map_->bind_variable(
new ObjectValue(map_, object->get_reference(o_atom.asIndex())), index_);
137 map_->bind_variable(
new AtomValue(map_, o_atom), index_);
144 Atom *UnboundValue::get_code() {
149 Code *UnboundValue::get_object() {
154 uint16 UnboundValue::get_code_size() {
161 AtomValue::AtomValue(BindingMap *map,
Atom atom) : BoundValue(map), atom_(atom) {
164 Value *AtomValue::copy(BindingMap *map)
const {
166 return new AtomValue(map, atom_);
169 void AtomValue::valuate(
Code *destination, uint16 write_index, uint16& )
const {
171 destination->code(write_index) = atom_;
174 bool AtomValue::match(
const Code *
object, uint16 index) {
176 return map_->match_atom(object->code(index), atom_);
179 Atom *AtomValue::get_code() {
184 Code *AtomValue::get_object() {
189 uint16 AtomValue::get_code_size() {
194 bool AtomValue::intersect(
const Value *v)
const {
196 return v->_intersect(
this);
199 bool AtomValue::_intersect(
const AtomValue *v)
const {
201 return contains(v->atom_);
204 bool AtomValue::contains(
const Atom a)
const {
209 if (atom_.isFloat() && a.isFloat())
210 return Utils::Equal(atom_.asFloat(), a.asFloat());
217 StructureValue::StructureValue(BindingMap *map,
const Atom *source, uint16 structure_index) : BoundValue(map) {
220 uint16 extent_index = 0;
221 copy_structure(structure_, extent_index, source, structure_index);
224 StructureValue::StructureValue(BindingMap *map, Timestamp time) : BoundValue(map) {
227 structure_->resize_code(3);
228 Utils::SetTimestamp(&structure_->code(0), time);
231 StructureValue::StructureValue(BindingMap *map, microseconds duration) : BoundValue(map) {
233 structure_->resize_code(3);
234 Utils::SetDuration(&structure_->code(0), duration);
237 Value *StructureValue::copy(BindingMap *map)
const {
239 return new StructureValue(map, structure_);
242 void StructureValue::copy_structure(
243 Code *destination, uint16 &extent_index,
const Atom* source, uint16 source_index) {
245 uint16 extent_start = extent_index;
246 uint8 atom_count = source[source_index].getAtomCount();
248 extent_index += (1 + atom_count);
249 for (uint16 i = 0; i <= atom_count; ++i) {
250 Atom a = source[source_index + i];
251 if (a.getDescriptor() == Atom::I_PTR) {
253 destination->code(extent_start + i) = Atom::IPointer(extent_index);
254 copy_structure(destination, extent_index, source, a.asIndex());
257 destination->code(extent_start + i) = a;
261 bool StructureValue::match(
const Code *
object, uint16 index) {
263 if (object->code(index).getDescriptor() != Atom::I_PTR)
265 return map_->match_structure(
object, object->code(index).asIndex(), 0, structure_, 0);
268 Atom *StructureValue::get_code() {
270 return &structure_->code(0);
273 Code *StructureValue::get_object() {
278 uint16 StructureValue::get_code_size() {
280 return structure_->code_size();
283 bool StructureValue::intersect(
const Value *v)
const {
285 return v->_intersect(
this);
288 bool StructureValue::_intersect(
const StructureValue *v)
const {
290 return contains(&v->structure_->code(0));
293 bool StructureValue::contains(
const Atom *s)
const {
295 if (structure_->code(0) != s[0])
297 if (structure_->code(0).getDescriptor() == Atom::TIMESTAMP)
298 return Utils::Synchronous(Utils::GetTimestamp(&structure_->code(0)), Utils::GetTimestamp(s));
299 for (uint16 i = 1; i < structure_->code_size(); ++i) {
301 Atom a = structure_->code(i);
306 if (a.isFloat() && _a.isFloat())
307 if (Utils::Equal(a.asFloat(), _a.asFloat()))
318 ObjectValue::ObjectValue(BindingMap *map,
Code *
object) : BoundValue(map), object_(object) {
321 Value *ObjectValue::copy(BindingMap *map)
const {
323 return new ObjectValue(map, object_);
326 void ObjectValue::valuate(
Code *destination, uint16 write_index, uint16& )
const {
328 destination->code(write_index) = Atom::RPointer(destination->references_size());
329 destination->add_reference(object_);
332 bool ObjectValue::match(
const Code *
object, uint16 index) {
334 return map_->match_object(object->get_reference(object->code(index).asIndex()), object_);
337 Atom *ObjectValue::get_code() {
339 return &object_->code(0);
342 Code *ObjectValue::get_object() {
347 uint16 ObjectValue::get_code_size() {
349 return object_->code_size();
352 bool ObjectValue::intersect(
const Value *v)
const {
354 return v->_intersect(
this);
357 bool ObjectValue::_intersect(
const ObjectValue *v)
const {
359 return contains(v->object_);
362 bool ObjectValue::contains(
const Code *o)
const {
369 _Fact *BindingMap::abstract_f_ihlp(
const _Fact *f_ihlp) {
372 Code *ihlp = f_ihlp->get_reference(0);
373 if (ihlp->code(0).asOpcode() == Opcodes::ICst)
374 opcode = Opcodes::ICst;
376 opcode = Opcodes::IMdl;
378 _Fact *_f_ihlp =
new Fact();
379 for (uint16 i = 0; i < f_ihlp->code_size(); ++i)
380 _f_ihlp->code(i) = f_ihlp->code(i);
382 Code *_ihlp = _Mem::Get()->build_object(Atom::Object(opcode, I_HLP_ARITY));
383 _ihlp->code(I_HLP_OBJ) = Atom::RPointer(0);
385 uint16 extent_index = I_HLP_ARITY + 1;
387 uint32 map_index = 0;
389 uint16 tpl_arg_set_index = ihlp->code(I_HLP_TPL_ARGS).asIndex();
390 uint16 tpl_arg_count = ihlp->code(tpl_arg_set_index).getAtomCount();
392 _ihlp->code(I_HLP_TPL_ARGS) = Atom::IPointer(extent_index);
393 _ihlp->code(extent_index) = Atom::Set(tpl_arg_count);
394 for (uint16 i = 1; i <= tpl_arg_count; ++i)
395 _ihlp->code(extent_index + i) = Atom::VLPointer(map_index++);
396 extent_index += 1 + tpl_arg_count;
398 uint16 arg_set_index = ihlp->code(I_HLP_EXPOSED_ARGS).asIndex();
399 uint16 arg_count = ihlp->code(arg_set_index).getAtomCount();
400 _ihlp->code(I_HLP_EXPOSED_ARGS) = Atom::IPointer(extent_index);
401 _ihlp->code(extent_index) = Atom::Set(arg_count);
402 for (uint16 i = 1; i <= arg_count; ++i)
403 _ihlp->code(extent_index + i) = Atom::VLPointer(map_index++);
405 _ihlp->code(I_HLP_WEAK_REQUIREMENT_ENABLED) = ihlp->code(I_HLP_WEAK_REQUIREMENT_ENABLED);
406 _ihlp->code(I_HLP_ARITY) = ihlp->code(I_HLP_ARITY);
408 _ihlp->add_reference(ihlp->get_reference(ihlp->code(I_HLP_OBJ).asIndex()));
410 _f_ihlp->add_reference(_ihlp);
416 if (fwd_after_index_ == -1)
417 first_index_ = map_.size();
419 uint16 extent_index = FACT_ARITY + 1;
420 abstract_member(original, FACT_OBJ, fact, FACT_OBJ, extent_index, timing_vars_first_search_index);
421 if (fwd_after_index_ != -1 && force_sync) {
423 fact->code(FACT_AFTER) = Atom::VLPointer(fwd_after_index_);
424 fact->code(FACT_BEFORE) = Atom::VLPointer(fwd_before_index_);
427 abstract_member(original, FACT_AFTER, fact, FACT_AFTER, extent_index, timing_vars_first_search_index);
428 abstract_member(original, FACT_BEFORE, fact, FACT_BEFORE, extent_index, timing_vars_first_search_index);
430 fact->code(FACT_CFD) = Atom::Wildcard();
431 fact->code(FACT_ARITY) = Atom::Wildcard();
433 if (fwd_after_index_ == -1) {
436 fwd_after_index_ = fact->code(FACT_AFTER).asIndex();
437 fwd_before_index_ = fact->code(FACT_BEFORE).asIndex();
443 Code *BindingMap::abstract_object(
Code *
object,
bool force_sync,
int timing_vars_first_search_index) {
445 Code *abstracted_object = NULL;
447 uint16 opcode =
object->code(0).asOpcode();
448 if (opcode == Opcodes::Fact)
450 else if (opcode == Opcodes::AntiFact)
452 else if (opcode == Opcodes::Cmd) {
454 uint16 extent_index = CMD_ARITY + 1;
455 abstracted_object = _Mem::Get()->build_object(object->code(0));
456 abstracted_object->code(CMD_FUNCTION) =
object->code(CMD_FUNCTION);
457 abstract_member(
object, CMD_ARGS, abstracted_object, CMD_ARGS, extent_index);
458 abstracted_object->code(CMD_ARITY) = Atom::Wildcard();
459 }
else if (opcode == Opcodes::MkVal) {
461 uint16 extent_index = MK_VAL_ARITY + 1;
462 abstracted_object = _Mem::Get()->build_object(object->code(0));
463 abstract_member(
object, MK_VAL_OBJ, abstracted_object, MK_VAL_OBJ, extent_index);
464 abstract_member(
object, MK_VAL_ATTR, abstracted_object, MK_VAL_ATTR, extent_index);
465 abstract_member(
object, MK_VAL_VALUE, abstracted_object, MK_VAL_VALUE, extent_index);
466 abstracted_object->code(MK_VAL_ARITY) = Atom::Wildcard();
467 }
else if (opcode == Opcodes::IMdl || opcode == Opcodes::ICst) {
469 uint16 extent_index = I_HLP_ARITY + 1;
470 abstracted_object = _Mem::Get()->build_object(object->code(0));
471 abstract_member(
object, I_HLP_OBJ, abstracted_object, I_HLP_OBJ, extent_index);
473 abstract_member(
object, I_HLP_TPL_ARGS, abstracted_object, I_HLP_TPL_ARGS, extent_index, 0);
475 abstract_member(
object, I_HLP_EXPOSED_ARGS, abstracted_object, I_HLP_EXPOSED_ARGS, extent_index, -1);
476 abstracted_object->code(I_HLP_WEAK_REQUIREMENT_ENABLED) = Atom::Wildcard();
477 abstracted_object->code(I_HLP_ARITY) = Atom::Wildcard();
480 return abstracted_object;
484 if (!(ihlp->code(0).asOpcode() != Opcodes::IMdl || ihlp->code(0).asOpcode() != Opcodes::ICst))
488 uint16 template_args_index = ihlp->code(I_HLP_TPL_ARGS).asIndex();
490 return template_args_index + 1 + ihlp->code(template_args_index).getAtomCount();
493 void BindingMap::abstract_member(
const Code *
object, uint16 index,
Code *abstracted_object, uint16 write_index, uint16 &extent_index,
int first_search_index) {
495 Atom a =
object->code(index);
496 uint16 ai = a.asIndex();
497 switch (a.getDescriptor()) {
499 Code *reference =
object->get_reference(ai);
500 if (reference->code(0).asOpcode() == Opcodes::Ont) {
502 abstracted_object->code(write_index) = Atom::RPointer(abstracted_object->references_size());
503 abstracted_object->add_reference(reference);
504 }
else if (reference->code(0).asOpcode() == Opcodes::Ent)
505 abstracted_object->code(write_index) = get_object_variable(reference);
508 abstracted_object->code(write_index) = Atom::RPointer(abstracted_object->references_size());
509 abstracted_object->add_reference(abstract_object(reference,
false, first_search_index));
514 if (hasUserDefinedOperators(object->code(ai).asOpcode()))
516 else if (object->code(ai).getDescriptor() == Atom::SET || object->code(ai).getDescriptor() == Atom::OBJECT) {
518 abstracted_object->code(write_index) = Atom::IPointer(extent_index);
520 uint16 element_count =
object->code(ai).getAtomCount();
521 abstracted_object->code(extent_index) =
object->code(ai);
522 uint16 _write_index = extent_index;
523 extent_index += element_count + 1;
524 for (uint16 i = 1; i <= element_count; ++i)
525 abstract_member(
object, ai + i, abstracted_object, _write_index + i, extent_index, first_search_index);
530 abstracted_object->code(write_index) = get_atom_variable(a);
535 void BindingMap::init(
const Code *
object, uint16 index) {
537 Atom a =
object->code(index);
538 switch (a.getDescriptor()) {
540 get_object_variable(object->get_reference(a.asIndex()));
543 if (object->code(a.asIndex()).getDescriptor() == Atom::SET &&
544 object->code(a.asIndex()).getAtomCount() == 1)
547 return init(
object, a.asIndex() + 1);
552 get_atom_variable(a);
557 Atom BindingMap::get_atom_variable(
Atom a) {
559 for (uint32 i = 0; i < map_.size(); ++i) {
561 if (map_[i]->contains(a))
562 return Atom::VLPointer(i);
565 uint32 size = map_.size();
566 map_.push_back(
new AtomValue(
this, a));
567 return Atom::VLPointer(size);
572 if (first_search_index >= 0 && map_.size() > 0) {
573 if (first_search_index > map_.size())
574 first_search_index = map_.size() - 1;
576 for (uint32 i = first_search_index;
true;) {
578 if (map_[i]->contains(&object->code(index)))
579 return Atom::VLPointer(i);
582 if (i >= map_.size())
585 if (i == first_search_index)
591 uint32 size = map_.size();
592 map_.push_back(
new StructureValue(
this, &object->code(0), index));
593 return Atom::VLPointer(size);
596 Atom BindingMap::get_object_variable(
Code *
object) {
598 for (uint32 i = 0; i < map_.size(); ++i) {
600 if (map_[i]->contains(
object))
601 return Atom::VLPointer(i);
604 uint32 size = map_.size();
605 map_.push_back(
new ObjectValue(
this,
object));
606 return Atom::VLPointer(size);
609 BindingMap::BindingMap() :
_Object(), first_index_(-1), fwd_after_index_(-1), fwd_before_index_(-1), unbound_values_(0) {
612 BindingMap::BindingMap(
const BindingMap *source) :
_Object() {
617 BindingMap::BindingMap(
const BindingMap &source) :
_Object() {
622 BindingMap::~BindingMap() {
625 void BindingMap::clear() {
628 fwd_after_index_ = fwd_before_index_ = -1;
631 BindingMap &BindingMap::operator =(
const BindingMap &source) {
634 for (uint8 i = 0; i < source.map_.size(); ++i)
635 map_.push_back(source.map_[i]->copy(
this));
636 first_index_ = source.first_index_;
637 fwd_after_index_ = source.fwd_after_index_;
638 fwd_before_index_ = source.fwd_before_index_;
639 unbound_values_ = source.unbound_values_;
643 void BindingMap::load(
const BindingMap *source) {
648 void BindingMap::add_unbound_value(uint8
id) {
650 if (
id >= map_.size())
652 map_[id] =
new UnboundValue(
this,
id);
655 bool BindingMap::match(
const Code *
object, uint16 o_base_index, uint16 o_index,
const Code *pattern, uint16 p_index, uint16 o_arity) {
657 uint16 o_full_index = o_base_index + o_index;
658 Atom o_atom =
object->code(o_full_index);
659 Atom p_atom = pattern->code(p_index);
660 switch (o_atom.getDescriptor()) {
661 case Atom::T_WILDCARD:
666 switch (p_atom.getDescriptor()) {
668 if (!map_[p_atom.asIndex()]->match(
object, o_full_index))
672 if (!match_structure(
object, o_atom.asIndex(), 0, pattern, p_atom.asIndex()))
675 case Atom::T_WILDCARD:
683 switch (p_atom.getDescriptor()) {
685 if (!map_[p_atom.asIndex()]->match(
object, o_full_index))
689 if (!match_object(object->get_reference(o_atom.asIndex()), pattern->get_reference(p_atom.asIndex())))
692 case Atom::T_WILDCARD:
700 switch (p_atom.getDescriptor()) {
702 if (!map_[p_atom.asIndex()]->match(
object, o_full_index))
705 case Atom::T_WILDCARD:
709 if (!match_atom(o_atom, p_atom))
716 if (o_index == o_arity)
718 return match(
object, o_base_index, o_index + 1, pattern, p_index + 1, o_arity);
721 bool BindingMap::match_atom(
Atom o_atom,
Atom p_atom) {
723 if (p_atom == o_atom)
726 if (p_atom.isFloat() && o_atom.isFloat())
727 return Utils::Equal(o_atom.asFloat(), p_atom.asFloat());
732 bool BindingMap::match_structure(
const Code *
object, uint16 o_base_index, uint16 o_index,
const Code *pattern, uint16 p_index) {
734 uint16 o_full_index = o_base_index + o_index;
735 Atom o_atom =
object->code(o_full_index);
736 Atom p_atom = pattern->code(p_index);
737 if (o_atom != p_atom)
739 uint16 arity = o_atom.getAtomCount();
742 if (o_atom.getDescriptor() == Atom::TIMESTAMP)
743 return Utils::Synchronous(Utils::GetTimestamp(&object->code(o_full_index)), Utils::GetTimestamp(&pattern->code(p_index)));
744 if (p_atom == Atom::Object(Opcodes::TI, 2)) {
746 Atom after_atom = pattern->code(p_index + 1);
747 Atom before_atom = pattern->code(p_index + 2);
748 if (after_atom.getDescriptor() == Atom::VL_PTR && before_atom.getDescriptor() == Atom::VL_PTR &&
749 map_[after_atom.asIndex()]->get_code() != NULL && map_[before_atom.asIndex()]->get_code() != NULL) {
751 if (Utils::HasTimestamp<Code>(
object, o_full_index + 1) &&
752 Utils::HasTimestamp<Code>(
object, o_full_index + 2))
756 Utils::GetTimestamp<Code>(
object, o_full_index + 1),
757 Utils::GetTimestamp<Code>(
object, o_full_index + 2), after_atom.asIndex(), before_atom.asIndex());
760 return match(
object, o_base_index, o_index + 1, pattern, p_index + 1, arity);
763 void BindingMap::reset_fwd_timings(_Fact *reference_fact) {
765 if (fwd_after_index_ >= 0 && fwd_after_index_ < map_.size())
766 map_[fwd_after_index_] =
new StructureValue(
this, reference_fact, reference_fact->code(FACT_AFTER).asIndex());
767 if (fwd_before_index_ >= 0 && fwd_before_index_ < map_.size())
768 map_[fwd_before_index_] =
new StructureValue(
this, reference_fact, reference_fact->code(FACT_BEFORE).asIndex());
773 Atom* after_code = map_[after_index]->get_code();
774 Atom* before_code = map_[before_index]->get_code();
775 if (after_code[0].getDescriptor() != Atom::TIMESTAMP ||
776 before_code[0].getDescriptor() != Atom::TIMESTAMP)
778 Timestamp stored_after = Utils::GetTimestamp(after_code);
779 Timestamp stored_before = Utils::GetTimestamp(before_code);
781 if (stored_after <= after) {
783 if (stored_before >= before) {
785 Utils::SetTimestamp(after_code, after);
786 Utils::SetTimestamp(before_code, before);
790 if (stored_before > after) {
792 Utils::SetTimestamp(after_code, after);
799 if (stored_before <= before)
801 else if (stored_after < before) {
803 Utils::SetTimestamp(before_code, before);
810 bool BindingMap::match_fwd_timings(
const _Fact *f_object) {
812 return match_fwd_timings(f_object->get_after(), f_object->get_before());
815 bool BindingMap::match_fwd_strict(
const _Fact *f_object,
const _Fact *f_pattern) {
817 if (match_object(f_object->get_reference(0), f_pattern->get_reference(0))) {
819 if (f_object->code(0) != f_pattern->code(0))
822 return match_fwd_timings(f_object);
827 MatchResult BindingMap::match_fwd_lenient(
const _Fact *f_object,
const _Fact *f_pattern) {
829 if (match_object(f_object->get_reference(0), f_pattern->get_reference(0))) {
832 if (f_pattern->code(0) == f_object->code(0))
833 r = MATCH_SUCCESS_POSITIVE;
835 r = MATCH_SUCCESS_NEGATIVE;
837 if (match_fwd_timings(f_object))
839 return MATCH_FAILURE;
841 return MATCH_FAILURE;
844 Timestamp BindingMap::get_fwd_after()
const {
846 return Utils::GetTimestamp(map_[fwd_after_index_]->get_code());
849 Timestamp BindingMap::get_fwd_before()
const {
851 return Utils::GetTimestamp(map_[fwd_before_index_]->get_code());
854 bool BindingMap::match_object(
const Code *
object,
const Code *pattern) {
856 if (object->code(0) != pattern->code(0))
858 uint16 pattern_opcode = pattern->code(0).asOpcode();
859 if (pattern_opcode == Opcodes::Ent ||
860 pattern_opcode == Opcodes::Ont ||
861 pattern_opcode == Opcodes::Mdl ||
862 pattern_opcode == Opcodes::Cst)
863 return object == pattern;
864 return match(
object, 0, 1, pattern, 1, object->code(0).getAtomCount());
867 void BindingMap::bind_variable(BoundValue *value, uint8
id) {
872 void BindingMap::bind_variable(
Atom *code, uint8
id, uint16 value_index,
Atom *intermediate_results) {
874 Atom v_atom = code[value_index];
875 if (v_atom.isFloat())
876 bind_variable(
new AtomValue(
this, v_atom),
id);
877 else switch (v_atom.getDescriptor()) {
880 bind_variable(
new StructureValue(
this, code, value_index),
id);
882 case Atom::VALUE_PTR:
883 bind_variable(
new StructureValue(
this, intermediate_results, v_atom.asIndex()),
id);
888 Atom *BindingMap::get_value_code(uint16
id)
const {
890 return map_[id]->get_code();
893 uint16 BindingMap::get_value_code_size(uint16
id)
const {
895 return map_[id]->get_code_size();
898 bool BindingMap::scan_variable(uint16
id)
const {
900 if (
id < first_index_)
902 return (map_[
id]->get_code() != NULL);
907 for (uint32 i = 0; i < map_.size();) {
909 if (i == fwd_after_index_) {
915 for (uint32 j = 0; j < bm->map_.size();) {
917 if (j == bm->fwd_after_index_) {
935 bool BindingMap::is_fully_specified()
const {
937 return unbound_values_ == 0;
942 HLPBindingMap::HLPBindingMap() : BindingMap(), bwd_after_index_(-1), bwd_before_index_(-1) {
945 HLPBindingMap::HLPBindingMap(
const HLPBindingMap *source) : BindingMap() {
950 HLPBindingMap::HLPBindingMap(
const HLPBindingMap &source) : BindingMap() {
955 HLPBindingMap::~HLPBindingMap() {
958 void HLPBindingMap::clear() {
961 bwd_after_index_ = bwd_before_index_ = -1;
964 HLPBindingMap &HLPBindingMap::operator =(
const HLPBindingMap &source) {
967 for (uint8 i = 0; i < source.map_.size(); ++i)
968 map_.push_back(source.map_[i]->copy(
this));
969 first_index_ = source.first_index_;
970 fwd_after_index_ = source.fwd_after_index_;
971 fwd_before_index_ = source.fwd_before_index_;
972 bwd_after_index_ = source.bwd_after_index_;
973 bwd_before_index_ = source.bwd_before_index_;
974 unbound_values_ = source.unbound_values_;
978 void HLPBindingMap::load(
const HLPBindingMap *source) {
983 void HLPBindingMap::add_unbound_values(
const Code* hlp, uint16 structure_index) {
984 uint16 arg_count = hlp->code(structure_index).getAtomCount();
985 for (uint16 i = 1; i <= arg_count; ++i) {
987 Atom a = hlp->code(structure_index + i);
988 if (a.getDescriptor() == Atom::VL_PTR)
989 add_unbound_value(a.asIndex());
990 else if (a.getDescriptor() == Atom::I_PTR)
992 add_unbound_values(hlp, hlp->code(structure_index + i).asIndex());
996 void HLPBindingMap::init_from_hlp(
const Code* hlp,
const Code* packed_hlp) {
998 add_unbound_values(hlp, hlp->code(HLP_TPL_ARGS).asIndex());
1000 first_index_ = map_.size();
1002 uint16 obj_set_index = hlp->code(HLP_OBJS).asIndex();
1003 uint16 obj_count = hlp->code(obj_set_index).getAtomCount();
1005 init_timing_indexes(hlp->get_reference(hlp->code(obj_set_index + 1).asIndex()),
1006 fwd_after_index_, fwd_before_index_);
1008 init_timing_indexes(hlp->get_reference(hlp->code(obj_set_index + 2).asIndex()),
1009 bwd_after_index_, bwd_before_index_);
1013 for (uint16 i = 1; i < packed_hlp->code_size(); ++i) {
1014 Atom s = packed_hlp->code(i);
1015 if (s.getDescriptor() == Atom::VL_PTR)
1016 add_unbound_value(s.asIndex());
1020 void HLPBindingMap::init_from_ihlp_args(
1021 const Code* hlp, uint16 hlp_args_index,
const Code* ihlp, uint16 ihlp_args_index) {
1022 if (hlp->code(hlp_args_index) != ihlp->code(ihlp_args_index))
1026 uint16 count = ihlp->code(ihlp_args_index).getAtomCount();
1028 for (uint16 i = 0; i < count; ++i) {
1030 Atom hlp_atom = hlp->code(hlp_args_index + 1 + i);
1031 Atom ihlp_atom = ihlp->code(ihlp_args_index + 1 + i);
1033 if (hlp_atom.getDescriptor() == Atom::I_PTR) {
1034 if (ihlp_atom.getDescriptor() != Atom::I_PTR)
1038 init_from_ihlp_args(hlp, hlp_atom.asIndex(), ihlp, ihlp_atom.asIndex());
1041 if (hlp_atom.getDescriptor() != Atom::VL_PTR)
1045 switch (ihlp_atom.getDescriptor()) {
1047 map_[hlp_atom.asIndex()] =
new ObjectValue(
this, ihlp->get_reference(ihlp_atom.asIndex()));
1050 map_[hlp_atom.asIndex()] =
new StructureValue(
this, ihlp, ihlp_atom.asIndex());
1053 map_[hlp_atom.asIndex()] =
new AtomValue(
this, ihlp_atom);
1059 void HLPBindingMap::init_from_f_ihlp(
const _Fact *f_ihlp) {
1061 Code *ihlp = f_ihlp->get_reference(0);
1063 Code* hlp = ihlp->get_reference(0);
1064 init_from_ihlp_args(hlp, hlp->code(HLP_TPL_ARGS).asIndex(), ihlp, ihlp->code(I_HLP_TPL_ARGS).asIndex());
1066 uint16 val_set_index = ihlp->code(I_HLP_EXPOSED_ARGS).asIndex() + 1;
1068 for (uint32 j = first_index_; j < map_.size(); ++j) {
1070 if (j == fwd_after_index_ || j == fwd_before_index_)
1074 Atom atom = ihlp->code(val_set_index + i);
1075 switch (atom.getDescriptor()) {
1077 map_[j] =
new ObjectValue(
this, ihlp->get_reference(atom.asIndex()));
1080 map_[j] =
new StructureValue(
this, ihlp, atom.asIndex());
1082 case Atom::WILDCARD:
1083 case Atom::T_WILDCARD:
1087 map_[j] =
new AtomValue(
this, atom);
1096 map_[fwd_after_index_] =
new StructureValue(
this, f_ihlp, f_ihlp->code(FACT_AFTER).asIndex());
1097 map_[fwd_before_index_] =
new StructureValue(
this, f_ihlp, f_ihlp->code(FACT_BEFORE).asIndex());
1100 void HLPBindingMap::build_ihlp_structure(
1101 const Code* hlp, uint16 hlp_structure_index,
Code* ihlp, uint16& extent_index)
const
1103 uint16 count = hlp->code(hlp_structure_index).getAtomCount();
1104 ihlp->code(extent_index) = hlp->code(hlp_structure_index);
1105 uint16 write_index = extent_index + 1;
1106 extent_index = write_index + count;
1107 bool is_ti = (hlp->code(hlp_structure_index) == Atom::Object(Opcodes::TI, 2));
1110 for (uint16 i = 0; i < count; ++i) {
1111 Atom a = hlp->code(hlp_structure_index + 1 + i);
1113 if (a.getDescriptor() == Atom::VL_PTR && !is_ti)
1115 map_[a.asIndex()]->valuate(ihlp, write_index, extent_index);
1116 else if (a.getDescriptor() == Atom::I_PTR) {
1117 ihlp->code(write_index) = Atom::IPointer(extent_index);
1119 build_ihlp_structure(hlp, a.asIndex(), ihlp, extent_index);
1122 ihlp->code(write_index) = a;
1128 Fact *HLPBindingMap::build_f_ihlp(
Code *hlp, uint16 opcode,
bool wr_enabled)
const {
1130 Code *ihlp = _Mem::Get()->build_object(Atom::Object(opcode, I_HLP_ARITY));
1131 ihlp->code(I_HLP_OBJ) = Atom::RPointer(0);
1132 ihlp->add_reference(hlp);
1134 uint16 tpl_arg_index = I_HLP_ARITY + 1;
1135 ihlp->code(I_HLP_TPL_ARGS) = Atom::IPointer(tpl_arg_index);
1136 uint16 extent_index = tpl_arg_index;
1137 build_ihlp_structure(hlp, hlp->code(HLP_TPL_ARGS).asIndex(), ihlp, extent_index);
1139 ihlp->code(I_HLP_EXPOSED_ARGS) = Atom::IPointer(extent_index);
1140 uint16 exposed_arg_start = first_index_;
1141 uint16 exposed_arg_count = map_.size() - exposed_arg_start - 2;
1142 ihlp->code(extent_index) = Atom::Set(exposed_arg_count);
1144 uint16 write_index = extent_index + 1;
1145 extent_index = write_index + exposed_arg_count;
1146 for (uint16 i = exposed_arg_start; i < map_.size(); ++i) {
1148 if (i == fwd_after_index_)
1150 if (i == fwd_before_index_)
1152 map_[i]->valuate(ihlp, write_index, extent_index);
1156 ihlp->code(I_HLP_WEAK_REQUIREMENT_ENABLED) = Atom::Boolean(wr_enabled);
1157 ihlp->code(I_HLP_ARITY) = Atom::Float(1);
1159 Fact *f_ihlp =
new Fact(ihlp, Timestamp(seconds(0)), Timestamp(seconds(0)), 1, 1);
1160 extent_index = FACT_ARITY + 1;
1161 map_[fwd_after_index_]->valuate(f_ihlp, FACT_AFTER, extent_index);
1162 map_[fwd_before_index_]->valuate(f_ihlp, FACT_BEFORE, extent_index);
1168 uint16 exposed_arg_start = first_index_;
1169 if (index == fwd_after_index_ || index == fwd_before_index_ ||
1170 index < exposed_arg_start || index >= map_.size())
1173 uint16 exposed_arg_count = map_.size() - exposed_arg_start - 2;
1174 uint16 position = 0;
1175 for (uint16 i = exposed_arg_start; i < map_.size(); ++i) {
1176 if (i == fwd_after_index_ || i == fwd_before_index_)
1188 Code *HLPBindingMap::bind_pattern(
Code *pattern)
const {
1190 if (!need_binding(pattern))
1193 Code *bound_pattern = _Mem::Get()->build_object(pattern->code(0));
1195 for (uint16 i = 0; i < pattern->references_size(); ++i) {
1197 Code *reference = pattern->get_reference(i);
1198 if (need_binding(reference))
1199 bound_pattern->set_reference(i, bind_pattern(reference));
1201 bound_pattern->set_reference(i, reference);
1204 uint16 extent_index = pattern->code_size();
1205 for (uint16 i = 1; i < pattern->code_size(); ++i) {
1207 Atom p_atom = pattern->code(i);
1208 switch (p_atom.getDescriptor()) {
1210 map_[p_atom.asIndex()]->valuate(bound_pattern, i, extent_index);
1212 case Atom::TIMESTAMP:
1213 case Atom::DURATION:
1214 case Atom::STRING: {
1215 bound_pattern->code(i) = p_atom;
1216 uint16 atom_count = p_atom.getAtomCount();
1217 for (uint16 j = i + 1; j <= i + atom_count; ++j)
1218 bound_pattern->code(j) = pattern->code(j);
1222 bound_pattern->code(i) = p_atom;
1227 return bound_pattern;
1230 bool HLPBindingMap::need_binding(
Code *pattern)
const {
1232 if (pattern->code(0).asOpcode() == Opcodes::Ont ||
1233 pattern->code(0).asOpcode() == Opcodes::Ent ||
1234 pattern->code(0).asOpcode() == Opcodes::Mdl ||
1235 pattern->code(0).asOpcode() == Opcodes::Cst)
1238 for (uint16 i = 0; i < pattern->references_size(); ++i) {
1240 if (need_binding(pattern->get_reference(i)))
1244 for (uint16 i = 1; i < pattern->code_size(); ++i) {
1246 Atom p_atom = pattern->code(i);
1247 switch (p_atom.getDescriptor()) {
1250 case Atom::TIMESTAMP:
1251 case Atom::DURATION:
1253 i += p_atom.getAtomCount();
1263 void HLPBindingMap::reset_bwd_timings(_Fact *reference_fact) {
1265 if (bwd_after_index_ >= 0 && bwd_after_index_ < map_.size())
1266 map_[bwd_after_index_] =
new StructureValue(
this, reference_fact, reference_fact->code(FACT_AFTER).asIndex());
1267 if (bwd_before_index_ >= 0 && bwd_before_index_ < map_.size())
1268 map_[bwd_before_index_] =
new StructureValue(
this, reference_fact, reference_fact->code(FACT_BEFORE).asIndex());
1271 bool HLPBindingMap::match_bwd_timings(
const _Fact *f_object,
const _Fact *f_pattern) {
1273 return match_timings(f_object->get_after(), f_object->get_before(), bwd_after_index_, bwd_before_index_);
1276 bool HLPBindingMap::match_bwd_strict(
const _Fact *f_object,
const _Fact *f_pattern) {
1278 if (match_object(f_object->get_reference(0), f_pattern->get_reference(0))) {
1280 if (f_object->code(0) != f_pattern->code(0))
1283 return match_bwd_timings(f_object, f_pattern);
1288 MatchResult HLPBindingMap::match_bwd_lenient(
const _Fact *f_object,
const _Fact *f_pattern) {
1290 if (match_object(f_object->get_reference(0), f_pattern->get_reference(0))) {
1293 if (f_pattern->code(0) == f_object->code(0))
1294 r = MATCH_SUCCESS_POSITIVE;
1296 r = MATCH_SUCCESS_NEGATIVE;
1298 if (match_bwd_timings(f_object, f_pattern))
1300 return MATCH_FAILURE;
1302 return MATCH_FAILURE;
1305 Timestamp HLPBindingMap::get_bwd_after()
const {
1307 return Utils::GetTimestamp(map_[bwd_after_index_]->get_code());
1310 Timestamp HLPBindingMap::get_bwd_before()
const {
1312 return Utils::GetTimestamp(map_[bwd_before_index_]->get_code());