86 #include "pgm_overlay.h"
93 using namespace r_code;
97 bool IPGMContext::operator ==(
const IPGMContext &c)
const {
98 IPGMContext lhs = dereference();
99 IPGMContext rhs = c.dereference();
101 if (lhs.data_ == REFERENCE && lhs.index_ == 0 &&
102 rhs.data_ == REFERENCE && rhs.index_ == 0)
103 return lhs.object_ == rhs.object_;
106 if (lhs[0] != rhs[0])
109 if (lhs[0].isStructural()) {
111 uint16 atom_count = lhs.get_children_count();
112 for (uint16 i = 1; i <= atom_count; ++i)
113 if (lhs.get_child_deref(i) != rhs.get_child_deref(i))
120 inline bool IPGMContext::operator !=(
const IPGMContext &c)
const {
122 return !(*
this == c);
125 bool IPGMContext::match(
const IPGMContext &input)
const {
127 if (data_ == REFERENCE && index_ == 0 &&
128 input.data_ == REFERENCE && input.index_ == 0) {
130 if (object_ == input.object_)
135 if (code_[index_].isStructural()) {
137 uint16 atom_count = get_children_count();
138 if (input.get_children_count() != atom_count)
141 if (((*
this)[0].atom_ & 0xFFFFFFF8) != (input[0].atom_ & 0xFFFFFFF8))
144 for (uint16 i = 1; i <= atom_count; ++i) {
146 IPGMContext pc = get_child_deref(i);
147 IPGMContext ic = input.get_child_deref(i);
154 switch ((*
this)[0].getDescriptor()) {
156 case Atom::T_WILDCARD:
159 return dereference().match(input);
161 return (*
this)[0] == input[0];
165 void IPGMContext::dereference_once() {
167 switch ((*
this)[0].getDescriptor()) {
169 index_ = (*this)[0].asIndex();
176 IPGMContext IPGMContext::dereference()
const {
178 switch ((*
this)[0].getDescriptor()) {
179 case Atom::CODE_VL_PTR: {
182 Atom a = code_[(*this)[0].asIndex()];
183 uint16 structure_index;
184 if (a.getDescriptor() == Atom::I_PTR)
185 a = code_[structure_index = a.asIndex()];
186 if (a.isStructural()) {
188 IPGMContext s(object_, view_, code_, structure_index, (InputLessPGMOverlay *)overlay_, data_);
189 if (s.evaluate_no_dereference())
192 return IPGMContext();
194 return IPGMContext(object_, view_, code_, (*
this)[0].asIndex(), (InputLessPGMOverlay *)overlay_, data_).dereference();
196 return IPGMContext(object_, view_, code_, (*
this)[0].asIndex(), (InputLessPGMOverlay *)overlay_, data_).dereference();
198 Code *o = object_->get_reference((*
this)[0].asIndex());
199 return IPGMContext(o, NULL, &o->code(0), 0, NULL, REFERENCE);
202 IPGMContext c = get_child_deref(1);
203 for (uint16 i = 2; i <= get_children_count(); ++i) {
205 switch ((*
this)[i].getDescriptor()) {
208 c = IPGMContext(c.get_object(), c.view_, &c.view_->code(0), 0, NULL, VIEW);
210 return IPGMContext();
213 return IPGMContext(c.get_object(), MKS);
216 return IPGMContext(c.get_object(), VWS);
219 c = c.get_child_deref((*
this)[i].asIndex());
225 return IPGMContext(overlay_->get_object(), overlay_->get_view(), &overlay_->get_object()->code(0), 0, (InputLessPGMOverlay *)overlay_, REFERENCE);
227 if (overlay_ && object_ == overlay_->get_object())
228 return IPGMContext(object_, view_, &view_->code(0), 0, NULL, VIEW);
231 return IPGMContext(object_, MKS);
233 return IPGMContext(object_, VWS);
234 case Atom::VALUE_PTR:
235 return IPGMContext(object_, view_, &overlay_->values_[0], (*
this)[0].asIndex(), (InputLessPGMOverlay *)overlay_, VALUE_ARRAY);
237 return IPGMContext(overlay_->get_object(), (*
this)[0].asIndex()).dereference();
238 case Atom::IN_OBJ_PTR: {
239 Code *input_object = ((PGMOverlay *)overlay_)->getInputObject((*
this)[0].asInputIndex());
240 View *input_view = (
r_exec::View*)((PGMOverlay *)overlay_)->getInputView((*
this)[0].asInputIndex());
241 return IPGMContext(input_object, input_view, &input_object->code(0), (*
this)[0].asIndex(), NULL, REFERENCE).dereference();
242 }
case Atom::D_IN_OBJ_PTR: {
243 IPGMContext parent = IPGMContext(object_, view_, code_, (*
this)[0].asRelativeIndex(), (InputLessPGMOverlay *)overlay_, data_).dereference();
244 Code *parent_object = parent.object_;
245 return IPGMContext(parent_object, NULL, &parent_object->code(0), (*
this)[0].asIndex(), NULL, REFERENCE).dereference();
246 }
case Atom::PROD_PTR:
247 return IPGMContext(((InputLessPGMOverlay *)overlay_)->productions_[(*
this)[0].asIndex()], 0);
253 bool IPGMContext::evaluate_no_dereference()
const {
266 switch (code_[index_].getDescriptor()) {
267 case Atom::OPERATOR: {
269 Operator op = Operator::Get((*
this)[0].asOpcode());
274 uint16 atom_count = get_children_count();
275 for (uint16 i = 1; i <= atom_count; ++i) {
277 if (!get_child_deref(i).evaluate_no_dereference())
281 IPGMContext *__c =
new IPGMContext(*
this);
285 if ((*
this)[0].asOpcode() == Opcodes::Ptn || (*
this)[0].asOpcode() == Opcodes::AntiPtn) {
290 case Atom::INSTANTIATED_PROGRAM:
291 case Atom::INSTANTIATED_CPP_PROGRAM:
292 case Atom::INSTANTIATED_INPUT_LESS_PROGRAM:
293 case Atom::INSTANTIATED_ANTI_PROGRAM:
294 case Atom::COMPOSITE_STATE:
300 uint16 atom_count = get_children_count();
301 for (uint16 i = 1; i <= atom_count; ++i) {
303 if (!get_child_deref(i).evaluate_no_dereference())
312 inline bool IPGMContext::evaluate()
const {
314 if (data_ == REFERENCE || data_ == VALUE_ARRAY)
317 IPGMContext c = dereference();
318 return c.evaluate_no_dereference();
321 void IPGMContext::copy_to_value_array(uint16 &position) {
323 position = overlay_->values_.size();
325 if (code_[index_].isStructural())
326 copy_structure_to_value_array(
false, overlay_->values_.size(), extent_index,
true);
328 copy_member_to_value_array(0,
false, overlay_->values_.size(), extent_index,
true);
331 void IPGMContext::copy_structure_to_value_array(
bool prefix, uint16 write_index, uint16 &extent_index,
bool dereference_cptr) {
333 if (code_[index_].getDescriptor() == Atom::OPERATOR && Operator::Get(code_[index_].asOpcode()).is_syn())
334 copy_member_to_value_array(1, prefix, write_index, extent_index, dereference_cptr);
337 uint16 atom_count = get_children_count();
338 overlay_->values_[write_index++] = code_[index_];
339 extent_index = write_index + atom_count;
340 switch (code_[index_].getDescriptor()) {
341 case Atom::TIMESTAMP:
342 for (uint16 i = 1; i <= atom_count; ++i)
343 overlay_->values_[write_index++] = code_[index_ + i];
346 for (uint16 i = 1; i <= atom_count; ++i)
347 overlay_->values_[write_index++] = code_[index_ + i];
350 if (!dereference_cptr) {
352 copy_member_to_value_array(1, prefix, write_index++, extent_index,
false);
353 for (uint16 i = 2; i <= atom_count; ++i)
354 overlay_->values_[write_index++] = code_[index_ + i];
358 if (is_cmd_with_cptr()) {
360 for (uint16 i = 1; i <= atom_count; ++i)
361 copy_member_to_value_array(i, prefix, write_index++, extent_index, i != 2);
364 for (uint16 i = 1; i <= atom_count; ++i)
365 copy_member_to_value_array(i, prefix, write_index++, extent_index, !(!dereference_cptr && i == 1));
371 void IPGMContext::copy_member_to_value_array(uint16 child_index,
bool prefix, uint16 write_index, uint16 &extent_index,
bool dereference_cptr) {
373 uint16 _index = index_ + child_index;
376 head = code_[_index];
377 switch (head.getDescriptor()) {
379 case Atom::CODE_VL_PTR:
380 _index = head.asIndex();
382 case Atom::VALUE_PTR:
383 overlay_->values_[write_index] = Atom::IPointer(head.asIndex());
386 case Atom::IN_OBJ_PTR:
387 case Atom::D_IN_OBJ_PTR:
389 overlay_->values_[write_index] = head;
392 if (dereference_cptr) {
394 uint16 saved_index = index_;
396 IPGMContext cptr = dereference();
397 overlay_->values_[write_index] = cptr[0];
398 index_ = saved_index;
403 if (head.isStructural()) {
405 uint16 saved_index = index_;
409 overlay_->values_[write_index] = Atom::IPointer(extent_index);
410 copy_structure_to_value_array(
true, extent_index, extent_index, dereference_cptr);
412 copy_structure_to_value_array(
true, write_index, extent_index, dereference_cptr);
413 index_ = saved_index;
415 overlay_->values_[write_index] = head;
418 void IPGMContext::getMember(
void *&
object, uint32 &view_oid, ObjectType &object_type, int16 &member_index)
const {
420 if ((*
this)[0].getDescriptor() != Atom::I_PTR) {
423 object_type = TYPE_UNDEFINED;
428 IPGMContext cptr = IPGMContext(object_, view_, code_, (*
this)[0].asIndex(), (InputLessPGMOverlay *)overlay_, data_);
430 if (cptr[0].getDescriptor() != Atom::C_PTR) {
433 object_type = TYPE_UNDEFINED;
438 IPGMContext c = cptr.get_child_deref(1);
440 uint16 atom_count = cptr.get_children_count();
441 for (uint16 i = 2; i < atom_count; ++i) {
443 if (cptr[i].getDescriptor() == Atom::VIEW)
444 c = IPGMContext(c.get_object(), c.view_, &c.view_->code(0), 0, NULL, VIEW);
446 c = c.get_child_deref(cptr[i].asIndex());
451 switch (c[0].getDescriptor()) {
454 case Atom::INSTANTIATED_PROGRAM:
455 case Atom::INSTANTIATED_CPP_PROGRAM:
456 case Atom::INSTANTIATED_INPUT_LESS_PROGRAM:
457 case Atom::INSTANTIATED_ANTI_PROGRAM:
458 case Atom::COMPOSITE_STATE:
460 object_type = TYPE_OBJECT;
461 object = c.get_object();
466 if (c.data_ == VALUE_ARRAY)
467 object = (Group *)c[VIEW_CODE_MAX_SIZE].atom_;
469 object = c.view_->get_host();
470 view_oid = c[VIEW_OID].atom_;
471 object_type = TYPE_VIEW;
475 object_type = TYPE_UNDEFINED;
480 member_index = cptr[atom_count].asIndex();
483 bool IPGMContext::is_cmd_with_cptr()
const {
485 if ((*
this)[0].getDescriptor() != Atom::OBJECT)
487 if ((*
this)[0].asOpcode() != Opcodes::ICmd)
489 return (*
this)[1].asOpcode() == Opcodes::Mod ||
490 (*this)[1].asOpcode() == Opcodes::Set;
493 uint16 IPGMContext::addProduction(
Code *
object,
bool check_for_existence)
const {
495 ((InputLessPGMOverlay *)overlay_)->productions_.push_back(_Mem::Get()->check_existence(
object));
496 return ((InputLessPGMOverlay *)overlay_)->productions_.size() - 1;
501 bool match(
const IPGMContext &input,
const IPGMContext &pattern) {
504 if (input.is_reference()) {
506 uint16 ptr = pattern.addProduction(input.get_object(),
false);
507 pattern.patch_code(pattern.getIndex() + 1, Atom::ProductionPointer(ptr));
509 pattern.patch_code(pattern.getIndex() + 1, Atom::IPointer(input.getIndex()));
512 IPGMContext guard_set = pattern.get_child_deref(2);
513 uint16 guard_count = guard_set.get_children_count();
514 for (uint16 i = 1; i <= guard_count; ++i) {
516 if (!guard_set.get_child_deref(i).evaluate_no_dereference())
523 bool match(
const IPGMContext &input,
const IPGMContext &pattern,
const IPGMContext &productions, vector<uint16> &production_indices) {
525 uint16 last_patch_index;
526 if (pattern[0].asOpcode() == Opcodes::Ptn) {
528 auto skeleton = pattern.get_child_deref(1);
529 if (!skeleton.match(input))
531 last_patch_index = pattern.get_last_patch_index();
532 if (!match(input, pattern))
535 goto build_productions;
538 if (pattern[0].asOpcode() == Opcodes::AntiPtn) {
540 auto skeleton = pattern.get_child_deref(1);
541 if (skeleton.match(input))
543 last_patch_index = pattern.get_last_patch_index();
544 if (match(input, pattern))
547 goto build_productions;
554 uint16 production_count = productions.get_children_count();
555 uint16 production_index;
556 for (uint16 i = 1; i <= production_count; ++i) {
558 IPGMContext prod = productions.get_child(i);
560 prod.copy_to_value_array(production_index);
561 production_indices.push_back(production_index);
564 pattern.unpatch_code(last_patch_index);
568 void reduce(
const IPGMContext &context,
const IPGMContext &input_set,
const IPGMContext §ion, vector<uint16> &input_indices, vector<uint16> &production_indices) {
570 IPGMContext pattern = section.get_child_deref(1);
571 if (pattern[0].asOpcode() != Opcodes::Ptn && pattern[0].asOpcode() != Opcodes::AntiPtn)
574 IPGMContext productions = section.get_child_deref(2);
575 if (productions[0].getDescriptor() != Atom::SET)
578 uint16 production_count = productions.get_children_count();
579 if (!production_count)
582 vector<uint16>::iterator i;
583 for (i = input_indices.begin(); i != input_indices.end();) {
585 IPGMContext c = input_set.get_child_deref(*i);
586 if (c.is_undefined()) {
588 i = input_indices.erase(i);
592 bool failure =
false;
593 if (!match(c, pattern, productions, production_indices)) {
602 i = input_indices.erase(i);
606 bool IPGMContext::Red(
const IPGMContext &context) {
607 IPGMContext input_set = context.get_child_deref(1);
608 if (!input_set.evaluate_no_dereference())
612 IPGMContext positive_section = context.get_child_deref(2);
613 if (!positive_section.get_child_deref(1).evaluate_no_dereference())
616 IPGMContext negative_section = context.get_child_deref(3);
617 if (!negative_section.get_child_deref(1).evaluate_no_dereference())
620 vector<uint16> input_indices;
621 for (uint16 i = 1; i <= input_set.get_children_count(); ++i)
622 input_indices.push_back(i);
624 vector<uint16> production_indices;
626 uint16 input_count = input_set.get_children_count();
627 if (input_set[0].getDescriptor() != Atom::SET &&
628 input_set[0].getDescriptor() != Atom::S_SET &&
629 positive_section[0].getDescriptor() != Atom::SET &&
630 negative_section[0].getDescriptor() != Atom::SET)
636 reduce(context, input_set, positive_section, input_indices, production_indices);
637 reduce(context, input_set, negative_section, input_indices, production_indices);
638 if (production_indices.size()) {
641 context.setCompoundResultHead(Atom::Set(production_indices.size()));
642 for (uint16 i = 0; i < production_indices.size(); ++i)
643 context.addCompoundResultPart(Atom::IPointer(production_indices[i]));
647 context.setCompoundResultHead(Atom::Set(0));
651 bool IPGMContext::Ins(
const IPGMContext &context) {
653 IPGMContext
object = context.get_child_deref(1);
654 IPGMContext args = context.get_child_deref(2);
655 IPGMContext run = context.get_child_deref(3);
656 IPGMContext tsc = context.get_child_deref(4);
657 IPGMContext res = context.get_child_deref(5);
658 IPGMContext nfr = context.get_child_deref(6);
660 Code *pgm =
object.get_object();
661 uint16 pgm_opcode = pgm->code(0).asOpcode();
662 if (pgm_opcode != Opcodes::Pgm &&
663 pgm_opcode != Opcodes::AntiPgm) {
665 context.setAtomicResult(Atom::Nil());
669 if (pgm && args[0].getDescriptor() == Atom::SET) {
671 uint16 pattern_set_index = pgm->code(PGM_TPL_ARGS).asIndex();
672 uint16 arg_count = args[0].getAtomCount();
673 if (pgm->code(pattern_set_index).getAtomCount() != arg_count) {
675 context.setAtomicResult(Atom::Nil());
680 IPGMContext pattern_set(pgm, pattern_set_index);
681 for (uint16 i = 1; i <= arg_count; ++i) {
683 IPGMContext arg = args.get_child_deref(i);
684 IPGMContext skel = pattern_set.get_child_deref(i).get_child_deref(1);
685 if (!skel.match(arg)) {
687 context.setAtomicResult(Atom::Nil());
693 if (pgm_opcode == Opcodes::AntiPgm)
694 ipgm = context.build_object(Atom::InstantiatedAntiProgram(Opcodes::IPgm, IPGM_ARITY));
697 uint16 input_index = pgm->code(PGM_INPUTS).asIndex();
698 uint16 input_count = pgm->code(input_index).getAtomCount();
699 if (input_count == 0)
700 ipgm = context.build_object(Atom::InstantiatedInputLessProgram(Opcodes::IPgm, IPGM_ARITY));
702 ipgm = context.build_object(Atom::InstantiatedProgram(Opcodes::IPgm, IPGM_ARITY));
705 ipgm->code(IPGM_PGM) = Atom::RPointer(0);
706 ipgm->add_reference(pgm);
708 uint16 extent_index = 0;
709 ipgm->code(IPGM_ARGS) = Atom::IPointer(IPGM_ARITY + 1);
710 args.copy(ipgm, IPGM_ARITY + 1, extent_index);
712 ipgm->code(IPGM_RUN) = run[0];
713 ipgm->code(IPGM_TSC) = Atom::IPointer(extent_index);
715 ipgm->code(extent_index++) = tsc[0];
716 ipgm->code(extent_index++) = tsc[1];
717 ipgm->code(extent_index++) = tsc[2];
719 ipgm->code(IPGM_RES) = res[0];
720 ipgm->code(IPGM_NFR) = nfr[0];
721 ipgm->code(IPGM_ARITY) = Atom::Float(1);
723 context.setAtomicResult(Atom::ProductionPointer(context.addProduction(ipgm,
true)));
727 context.setAtomicResult(Atom::Nil());
731 bool IPGMContext::Fvw(
const IPGMContext &context) {
733 IPGMContext
object = context.get_child_deref(1);
734 IPGMContext group = context.get_child_deref(2);
736 Code *_object =
object.get_object();
737 Group *_group = (Group *)group.get_object();
738 if (!_object || !_group) {
740 context.setAtomicResult(Atom::Nil());
744 View *v = (View *)_object->get_view(_group,
true);
747 context.setCompoundResultHead(v->code(0));
748 for (uint16 i = 1; i < VIEW_CODE_MAX_SIZE; ++i)
749 context.addCompoundResultPart(v->code(i));
750 context.addCompoundResultPart(
Atom((uint32)v->references_[0]));
751 context.addCompoundResultPart(
Atom((uint32)v->references_[1]));
756 context.setAtomicResult(Atom::Nil());