92 #include "../submodules/CoreLibrary/CoreLibrary/utils.h"
93 #include "../r_code/utils.h"
95 #include "hlp_context.h"
98 using namespace std::chrono;
99 using namespace r_code;
105 void Operator::Register(uint16 opcode,
bool(*o)(
const Context &)) {
107 if (Operators_[opcode].operator_)
108 Operators_[opcode].setOverload(o);
110 Operators_[opcode] = Operator(o);
114 std::vector<r_code::Atom> OpContext::build_and_evaluate_expression(_Fact* q0, _Fact* q1,
Atom op) {
115 if (q0->get_reference(0)->code(MK_VAL_VALUE).isFloat() && q1->get_reference(0)->code(MK_VAL_VALUE).isFloat()) {
117 float32 _q0 = q0->get_reference(0)->code(MK_VAL_VALUE).asFloat();
118 float32 _q1 = q1->get_reference(0)->code(MK_VAL_VALUE).asFloat();
121 auto opcode = op.asOpcode();
122 if (opcode == Opcodes::Gtr) { result = Atom::Boolean(_q1 > _q0); }
123 else if (opcode == Opcodes::Lsr) { result = Atom::Boolean(_q1 < _q0); }
124 else if (opcode == Opcodes::Gte) { result = Atom::Boolean(_q1 >= _q0); }
125 else if (opcode == Opcodes::Lse) { result = Atom::Boolean(_q1 <= _q0); }
126 else if (opcode == Opcodes::Add) { result = Atom::Float(_q1 + _q0); }
127 else if (opcode == Opcodes::Sub) { result = Atom::Float(_q1 - _q0); }
128 else if (opcode == Opcodes::Mul) { result = Atom::Float(_q1 * _q0); }
129 else if (opcode == Opcodes::Div) {
131 return std::vector<r_code::Atom>();
132 result = Atom::Float(_q1 / _q0);
134 if (!result.isUndefined()) {
135 std::vector<r_code::Atom> out;
136 out.push_back(result);
141 return evaluate_expression(expression);
146 uint16 target_source_index = 0;
147 uint16 consequent_source_index = 0;
149 Atom target_val = q0->get_reference(0)->code(MK_VAL_VALUE);
150 Atom consequent_val = q1->get_reference(0)->code(MK_VAL_VALUE);
154 uint16 extent_index = 1;
155 expression->code(0) = op;
156 Atom* copy_ptr = &consequent_val;
157 if (consequent_val.getDescriptor() == Atom::I_PTR) {
158 consequent_source_index = consequent_val.asIndex();
159 copy_ptr = &q1->get_reference(0)->code(0);
161 expression->code(1) = Atom::IPointer(extent_index);
163 StructureValue::copy_structure(expression, extent_index, copy_ptr, consequent_source_index);
165 copy_ptr = &target_val;
166 if (target_val.getDescriptor() == Atom::I_PTR) {
167 target_source_index = target_val.asIndex();
168 copy_ptr = &q0->get_reference(0)->code(0);
169 expression->code(2) = Atom::IPointer(extent_index);
171 StructureValue::copy_structure(expression, extent_index, copy_ptr, target_source_index);
176 std::vector<r_code::Atom> OpContext::evaluate_expression(
r_code::LocalObject* expression) {
178 Overlay overlay((
size_t)0);
179 HLPContext c(&expression->code(0), 0, (HLPOverlay*)&overlay);
181 uint16 atom_count = c.get_children_count();
182 for (uint16 i = 1; i <= atom_count; ++i) {
184 if (!c.get_child_deref(i).evaluate_no_dereference())
185 return std::vector<r_code::Atom>();
188 Operator op = Operator::Get(c[0].asOpcode());
189 HLPContext* _c =
new HLPContext(c);
190 OpContext op_context(_c);
192 return op_context.result();
199 bool now(
const Context &context) {
201 context.setTimestampResult(Now());
207 bool rnd(
const Context &context) {
209 Context range = *context.get_child(1);
211 if (!range[0].isFloat()) {
213 context.setAtomicResult(Atom::Nil());
220 float32 result = (((float32)(rand() % 100)) / 100)*range[0].asFloat();
221 context.setAtomicResult(Atom::Float(result));
227 bool equ(
const Context &context) {
229 Context lhs = *context.get_child(1);
230 Context rhs = *context.get_child(2);
232 bool r = (lhs == rhs);
233 context.setAtomicResult(Atom::Boolean(r));
239 bool neq(
const Context &context) {
241 bool r = *context.get_child(1) != *context.get_child(2);
242 context.setAtomicResult(Atom::Boolean(r));
248 bool gtr(
const Context &context) {
250 Context lhs = *context.get_child(1);
251 Context rhs = *context.get_child(2);
253 if (lhs[0].isFloat()) {
255 if (rhs[0].isFloat()) {
257 bool r = lhs[0].asFloat() > rhs[0].asFloat();
258 context.setAtomicResult(Atom::Boolean(r));
261 }
else if (lhs[0].getDescriptor() == Atom::TIMESTAMP) {
263 if (rhs[0].getDescriptor() == Atom::TIMESTAMP) {
265 bool r = Utils::GetTimestamp(&lhs[0]) > Utils::GetTimestamp(&rhs[0]);
266 context.setAtomicResult(Atom::Boolean(r));
270 else if (lhs[0].getDescriptor() == Atom::DURATION) {
271 if (rhs[0].getDescriptor() == Atom::DURATION) {
272 bool r = Utils::GetDuration(&lhs[0]) > Utils::GetDuration(&rhs[0]);
273 context.setAtomicResult(Atom::Boolean(r));
278 context.setAtomicResult(Atom::UndefinedBoolean());
284 bool lsr(
const Context &context) {
286 Context lhs = *context.get_child(1);
287 Context rhs = *context.get_child(2);
289 if (lhs[0].isFloat()) {
291 if (rhs[0].isFloat()) {
293 bool r = lhs[0].asFloat() < rhs[0].asFloat();
294 context.setAtomicResult(Atom::Boolean(r));
297 }
else if (lhs[0].getDescriptor() == Atom::TIMESTAMP) {
299 if (rhs[0].getDescriptor() == Atom::TIMESTAMP) {
301 bool r = Utils::GetTimestamp(&lhs[0]) < Utils::GetTimestamp(&rhs[0]);
302 context.setAtomicResult(Atom::Boolean(r));
306 else if (lhs[0].getDescriptor() == Atom::DURATION) {
307 if (rhs[0].getDescriptor() == Atom::DURATION) {
308 bool r = Utils::GetDuration(&lhs[0]) < Utils::GetDuration(&rhs[0]);
309 context.setAtomicResult(Atom::Boolean(r));
314 context.setAtomicResult(Atom::UndefinedBoolean());
320 bool gte(
const Context &context) {
322 Context lhs = *context.get_child(1);
323 Context rhs = *context.get_child(2);
325 if (lhs[0].isFloat()) {
327 if (rhs[0].isFloat()) {
329 bool r = lhs[0].asFloat() >= rhs[0].asFloat();
330 context.setAtomicResult(Atom::Boolean(r));
333 }
else if (lhs[0].getDescriptor() == Atom::TIMESTAMP) {
335 if (rhs[0].getDescriptor() == Atom::TIMESTAMP) {
337 bool r = Utils::GetTimestamp(&lhs[0]) >= Utils::GetTimestamp(&rhs[0]);
338 context.setAtomicResult(Atom::Boolean(r));
342 else if (lhs[0].getDescriptor() == Atom::DURATION) {
343 if (rhs[0].getDescriptor() == Atom::DURATION) {
344 bool r = Utils::GetDuration(&lhs[0]) >= Utils::GetDuration(&rhs[0]);
345 context.setAtomicResult(Atom::Boolean(r));
350 context.setAtomicResult(Atom::UndefinedBoolean());
356 bool lse(
const Context &context) {
358 Context lhs = *context.get_child(1);
359 Context rhs = *context.get_child(2);
361 if (lhs[0].isFloat()) {
363 if (rhs[0].isFloat()) {
365 bool r = lhs[0].asFloat() <= rhs[0].asFloat();
366 context.setAtomicResult(Atom::Boolean(r));
369 }
else if (lhs[0].getDescriptor() == Atom::TIMESTAMP) {
371 if (rhs[0].getDescriptor() == Atom::TIMESTAMP) {
373 bool r = Utils::GetTimestamp(&lhs[0]) <= Utils::GetTimestamp(&rhs[0]);
374 context.setAtomicResult(Atom::Boolean(r));
378 else if (lhs[0].getDescriptor() == Atom::DURATION) {
379 if (rhs[0].getDescriptor() == Atom::DURATION) {
380 bool r = Utils::GetDuration(&lhs[0]) <= Utils::GetDuration(&rhs[0]);
381 context.setAtomicResult(Atom::Boolean(r));
386 context.setAtomicResult(Atom::UndefinedBoolean());
392 bool add(
const Context &context) {
394 Context lhs = *context.get_child(1);
395 Context rhs = *context.get_child(2);
397 if (lhs[0].isFloat()) {
399 if (rhs[0].isFloat()) {
401 if (lhs[0] == Atom::PlusInfinity()) {
403 context.setAtomicResult(Atom::PlusInfinity());
407 if (rhs[0] == Atom::PlusInfinity()) {
409 context.setAtomicResult(Atom::PlusInfinity());
413 context.setAtomicResult(Atom::Float(lhs[0].asFloat() + rhs[0].asFloat()));
415 }
else if (rhs[0].getDescriptor() == Atom::TIMESTAMP) {
417 if (lhs[0] != Atom::PlusInfinity()) {
419 context.setTimestampResult(Utils::GetTimestamp(&rhs[0]) + microseconds((int64)lhs[0].asFloat()));
423 else if (rhs[0].getDescriptor() == Atom::DURATION) {
424 if (lhs[0] != Atom::PlusInfinity()) {
425 context.setDurationResult(Utils::GetDuration(&rhs[0]) + microseconds((int64)lhs[0].asFloat()));
429 }
else if (lhs[0].getDescriptor() == Atom::TIMESTAMP) {
431 if (rhs[0].isFloat()) {
433 if (rhs[0] != Atom::PlusInfinity()) {
435 context.setTimestampResult(Utils::GetTimestamp(&lhs[0]) + microseconds((int64)rhs[0].asFloat()));
439 else if (rhs[0].getDescriptor() == Atom::DURATION) {
440 context.setTimestampResult(Utils::GetTimestamp(&lhs[0]) + Utils::GetDuration(&rhs[0]));
444 else if (lhs[0].getDescriptor() == Atom::DURATION) {
445 if (rhs[0].getDescriptor() == Atom::DURATION) {
446 context.setDurationResult(Utils::GetDuration(&lhs[0]) + Utils::GetDuration(&rhs[0]));
449 else if (rhs[0].getDescriptor() == Atom::TIMESTAMP) {
450 context.setTimestampResult(Utils::GetDuration(&lhs[0]) + Utils::GetTimestamp(&rhs[0]));
453 else if (rhs[0].isFloat()) {
454 if (rhs[0] != Atom::PlusInfinity()) {
455 context.setDurationResult(Utils::GetDuration(&lhs[0]) + microseconds((int64)rhs[0].asFloat()));
461 context.setAtomicResult(Atom::Nil());
467 bool sub(
const Context &context) {
469 Context lhs = *context.get_child(1);
470 Context rhs = *context.get_child(2);
472 if (lhs[0].isFloat()) {
474 if (rhs[0].isFloat()) {
476 if (lhs[0] == Atom::PlusInfinity()) {
478 context.setAtomicResult(Atom::PlusInfinity());
482 if (rhs[0] == Atom::PlusInfinity()) {
484 context.setAtomicResult(Atom::Float(0));
488 context.setAtomicResult(Atom::Float(lhs[0].asFloat() - rhs[0].asFloat()));
491 }
else if (lhs[0].getDescriptor() == Atom::TIMESTAMP) {
493 if (rhs[0].getDescriptor() == Atom::TIMESTAMP) {
495 context.setDurationResult(duration_cast<microseconds>(Utils::GetTimestamp(&lhs[0]) - Utils::GetTimestamp(&rhs[0])));
497 }
else if (rhs[0].isFloat()) {
499 if (rhs[0] != Atom::PlusInfinity()) {
501 context.setTimestampResult(Utils::GetTimestamp(&lhs[0]) - microseconds((int64)rhs[0].asFloat()));
505 else if (rhs[0].getDescriptor() == Atom::DURATION) {
506 context.setTimestampResult(Utils::GetTimestamp(&lhs[0]) - Utils::GetDuration(&rhs[0]));
510 else if (lhs[0].getDescriptor() == Atom::DURATION) {
511 if (rhs[0].getDescriptor() == Atom::DURATION) {
512 context.setDurationResult(Utils::GetDuration(&lhs[0]) - Utils::GetDuration(&rhs[0]));
515 else if (rhs[0].isFloat()) {
516 if (rhs[0] != Atom::PlusInfinity()) {
517 context.setDurationResult(Utils::GetDuration(&lhs[0]) - microseconds((int64)rhs[0].asFloat()));
523 context.setAtomicResult(Atom::Nil());
529 bool mul(
const Context &context) {
531 Context lhs = *context.get_child(1);
532 Context rhs = *context.get_child(2);
534 if (lhs[0].isFloat()) {
536 if (rhs[0].isFloat()) {
538 if (lhs[0] == Atom::PlusInfinity()) {
540 if (rhs[0] == Atom::PlusInfinity()) {
542 context.setAtomicResult(Atom::PlusInfinity());
546 if (rhs[0].asFloat() > 0) {
548 context.setAtomicResult(Atom::PlusInfinity());
552 if (rhs[0].asFloat() <= 0) {
554 context.setAtomicResult(Atom::Float(0));
559 if (rhs[0] == Atom::PlusInfinity()) {
561 if (lhs[0].asFloat() > 0) {
563 context.setAtomicResult(Atom::PlusInfinity());
567 if (lhs[0].asFloat() <= 0) {
569 context.setAtomicResult(Atom::Float(0));
574 context.setAtomicResult(Atom::Float(lhs[0].asFloat()*rhs[0].asFloat()));
577 else if (rhs[0].getDescriptor() == Atom::DURATION) {
578 if (lhs[0] != Atom::PlusInfinity()) {
579 context.setAtomicResult(Atom::Float(lhs[0].asFloat() * (float32)Utils::GetDuration(&rhs[0]).count()));
584 else if (lhs[0].getDescriptor() == Atom::DURATION) {
585 if (rhs[0].isFloat()) {
586 if (rhs[0] != Atom::PlusInfinity()) {
587 float64 lhs_float = (float64)Utils::GetDuration(&lhs[0]).count();
588 context.setDurationResult(microseconds((int64)(lhs_float * rhs[0].asFloat())));
592 else if (rhs[0].getDescriptor() == Atom::DURATION) {
594 context.setAtomicResult(Atom::Float((float32)Utils::GetDuration(&lhs[0]).count() * (float32)Utils::GetDuration(&rhs[0]).count()));
599 context.setAtomicResult(Atom::Nil());
605 bool div(
const Context &context) {
607 Context lhs = *context.get_child(1);
608 Context rhs = *context.get_child(2);
610 if (lhs[0].isFloat()) {
612 if (rhs[0].isFloat()) {
614 if (rhs[0].asFloat() != 0) {
616 if (lhs[0] == Atom::PlusInfinity()) {
618 if (rhs[0] == Atom::PlusInfinity()) {
620 context.setAtomicResult(Atom::PlusInfinity());
624 if (rhs[0].asFloat() > 0) {
626 context.setAtomicResult(Atom::PlusInfinity());
630 if (rhs[0].asFloat() <= 0) {
632 context.setAtomicResult(Atom::Float(0));
637 if (rhs[0] == Atom::PlusInfinity()) {
639 if (lhs[0].asFloat() > 0) {
641 context.setAtomicResult(Atom::PlusInfinity());
645 if (lhs[0].asFloat() <= 0) {
647 context.setAtomicResult(Atom::Float(0));
652 context.setAtomicResult(Atom::Float(lhs[0].asFloat() / rhs[0].asFloat()));
656 else if (rhs[0].getDescriptor() == Atom::DURATION) {
657 if (lhs[0] != Atom::PlusInfinity()) {
658 context.setAtomicResult(Atom::Float(lhs[0].asFloat() / (float32)Utils::GetDuration(&rhs[0]).count()));
663 else if (lhs[0].getDescriptor() == Atom::DURATION) {
664 if (rhs[0].isFloat()) {
665 if (rhs[0] != Atom::PlusInfinity()) {
666 float64 lhs_float = (float64)Utils::GetDuration(&lhs[0]).count();
667 context.setDurationResult(microseconds((int64)(lhs_float / rhs[0].asFloat())));
671 else if (rhs[0].getDescriptor() == Atom::DURATION) {
673 context.setAtomicResult(Atom::Float((float32)Utils::GetDuration(&lhs[0]).count() / (float32)Utils::GetDuration(&rhs[0]).count()));
678 context.setAtomicResult(Atom::Nil());
684 bool dis(
const Context &context) {
686 Context lhs = *context.get_child(1);
687 Context rhs = *context.get_child(2);
689 if (lhs[0].isFloat()) {
691 if (rhs[0].isFloat()) {
693 context.setAtomicResult(Atom::Float(abs(lhs[0].asFloat() - rhs[0].asFloat())));
696 }
else if (lhs[0].getDescriptor() == Atom::TIMESTAMP) {
698 if (rhs[0].getDescriptor() == Atom::TIMESTAMP) {
700 context.setDurationResult(abs(duration_cast<microseconds>(Utils::GetTimestamp(&lhs[0]) - Utils::GetTimestamp(&rhs[0]))));
704 else if (lhs[0].getDescriptor() == Atom::DURATION) {
705 if (rhs[0].getDescriptor() == Atom::DURATION) {
706 context.setDurationResult(abs(Utils::GetDuration(&lhs[0]) - Utils::GetDuration(&rhs[0])));
711 context.setAtomicResult(Atom::Nil());
717 bool ln(
const Context &context) {
719 Context arg = *context.get_child(1);
721 if (arg[0].isFloat()) {
723 if (arg[0].asFloat() != 0) {
725 context.setAtomicResult(Atom::Float(::log(arg[0].asFloat())));
730 context.setAtomicResult(Atom::Nil());
736 bool exp(
const Context &context) {
738 Context arg = *context.get_child(1);
740 if (arg[0].isFloat()) {
742 context.setAtomicResult(Atom::Float(::exp(arg[0].asFloat())));
746 context.setAtomicResult(Atom::Nil());
752 bool log(
const Context &context) {
754 Context arg = *context.get_child(1);
756 if (arg[0].isFloat()) {
758 if (arg[0].asFloat() != 0) {
760 context.setAtomicResult(Atom::Float(log10(arg[0].asFloat())));
765 context.setAtomicResult(Atom::Nil());
771 bool e10(
const Context &context) {
773 Context arg = *context.get_child(1);
775 if (arg[0].isFloat()) {
777 context.setAtomicResult(Atom::Float(pow(10, arg[0].asFloat())));
781 context.setAtomicResult(Atom::Nil());
787 bool syn(
const Context &context) {
794 bool ins(
const Context &context) {
796 return IPGMContext::Ins(*(IPGMContext *)context.get_implementation());
801 bool red(
const Context &context) {
803 return IPGMContext::Red(*(IPGMContext *)context.get_implementation());
808 bool fvw(
const Context &context) {
810 return IPGMContext::Fvw(*(IPGMContext *)context.get_implementation());
815 bool is_sim(
const Context &context) {
817 const IPGMContext &ipgm_context = *(IPGMContext *)context.get_implementation();
818 IPGMContext arg = ipgm_context.get_child_deref(1);
819 Code* obj = arg.get_object();
822 if (obj->code(0).asOpcode() == Opcodes::Goal)
823 result = ((Goal*)obj)->is_simulation();
824 else if (obj->code(0).asOpcode() == Opcodes::Pred)
825 result = ((Pred*)obj)->is_simulation();
827 context.setAtomicResult(Atom::Boolean(result));
831 bool minimum(
const Context &context) {
832 Context lhs = *context.get_child(1);
833 Context rhs = *context.get_child(2);
835 if (lhs[0].isFloat() && rhs[0].isFloat()) {
836 if (lhs[0] == Atom::MinusInfinity() || rhs[0] == Atom::MinusInfinity()) {
837 context.setAtomicResult(Atom::MinusInfinity());
841 if (lhs[0] == Atom::PlusInfinity()) {
842 context.setAtomicResult(Atom::Float(rhs[0].asFloat()));
845 if (rhs[0] == Atom::PlusInfinity()) {
846 context.setAtomicResult(Atom::Float(lhs[0].asFloat()));
850 context.setAtomicResult(Atom::Float(min(lhs[0].asFloat(), rhs[0].asFloat())));
853 else if (lhs[0].getDescriptor() == Atom::TIMESTAMP && rhs[0].getDescriptor() == Atom::TIMESTAMP) {
854 context.setTimestampResult(min(Utils::GetTimestamp(&lhs[0]), Utils::GetTimestamp(&rhs[0])));
857 else if (lhs[0].getDescriptor() == Atom::DURATION && rhs[0].getDescriptor() == Atom::DURATION) {
858 context.setDurationResult(min(Utils::GetDuration(&lhs[0]), Utils::GetDuration(&rhs[0])));
862 context.setAtomicResult(Atom::Nil());
866 bool maximum(
const Context &context) {
867 Context lhs = *context.get_child(1);
868 Context rhs = *context.get_child(2);
870 if (lhs[0].isFloat() && rhs[0].isFloat()) {
871 if (lhs[0] == Atom::PlusInfinity() || rhs[0] == Atom::PlusInfinity()) {
872 context.setAtomicResult(Atom::PlusInfinity());
876 if (lhs[0] == Atom::MinusInfinity()) {
877 context.setAtomicResult(Atom::Float(rhs[0].asFloat()));
880 if (rhs[0] == Atom::MinusInfinity()) {
881 context.setAtomicResult(Atom::Float(lhs[0].asFloat()));
885 context.setAtomicResult(Atom::Float(max(lhs[0].asFloat(), rhs[0].asFloat())));
888 else if (lhs[0].getDescriptor() == Atom::TIMESTAMP && rhs[0].getDescriptor() == Atom::TIMESTAMP) {
889 context.setTimestampResult(max(Utils::GetTimestamp(&lhs[0]), Utils::GetTimestamp(&rhs[0])));
892 else if (lhs[0].getDescriptor() == Atom::DURATION && rhs[0].getDescriptor() == Atom::DURATION) {
893 context.setDurationResult(max(Utils::GetDuration(&lhs[0]), Utils::GetDuration(&rhs[0])));
897 context.setAtomicResult(Atom::Nil());
901 bool id(
const Context& context) {
902 Context arg = *context.get_child(1);
904 if (arg[0].isFloat()) {
906 context.setAtomicResult(Atom::Float(arg[0].asFloat()));
911 context.setAtomicResult(Atom::Nil());