diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 8b08f3be..fc81a5ce 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -2,10 +2,10 @@ name: CMake on: workflow_dispatch: - #push: - # branches: [ "master" ] - #pull_request: - # branches: [ "master" ] + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] env: # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) @@ -26,6 +26,9 @@ jobs: - name: install-deps run: sudo apt install libboost-all-dev wget + + - name: update submodules + run: git submodule update --force --init --checkout - name: install eclipse-clp run: | @@ -43,8 +46,8 @@ jobs: cmake -B ${{github.workspace}}/build \ -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \ -DBUILD_READYLOG_SEMANTICS=TRUE \ - -DBUILD_PARSER=FALSE \ - -DBUILD_TESTING=FALSE \ + -DBUILD_PARSER=TRUE \ + -DBUILD_TESTING=TRUE \ - name: Build # Build your program with the given configuration @@ -54,5 +57,6 @@ jobs: working-directory: ${{github.workspace}}/build # Execute tests defined by the CMake configuration. # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail - run: ctest -C ${{env.BUILD_TYPE}} + run: ctest -C ${{env.BUILD_TYPE}} -VV + timeout-minutes: 10 diff --git a/.gitmodules b/.gitmodules index 2ba5fa68..0236b55a 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "external/taptenc"] path = external/taptenc - url = git@github.com:TarikViehmann/taptenc.git -[submodule "src/semantics/readylog/interpreter"] - path = src/semantics/readylog/interpreter + url = https://github.com/TarikViehmann/taptenc.git +[submodule "src/semantics/readylog/readylog_ecl"] + path = src/semantics/readylog/readylog_ecl url = https://github.com/MASKOR/readylog.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 80148c08..da57e0f5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,8 +15,8 @@ # along with golog++. If not, see . ########################################################################### -project(golog++) cmake_minimum_required(VERSION 3.0) +project(golog++) include(CMakeDependentOption) include(GNUInstallDirs) @@ -72,7 +72,8 @@ set(SEMANTICS_INSTALL_DIR ${CMAKE_INSTALL_DATAROOTDIR}/golog++/semantics) set(GOLOGPP_VERSION 0.1.0) - +file(GLOB_RECURSE GOLOGPP_HEADERS "src/*.h") +add_custom_target(headers SOURCES ${GOLOGPP_HEADERS}) ###################################################################################### # The golog++ language metamodel: libgolog++.so @@ -100,8 +101,8 @@ set(INTERFACE_SRC src/model/mapping.cpp src/model/language.cpp src/model/types.cpp - src/model/compound_expression.cpp - src/model/list_expression.cpp + src/model/compound.cpp + src/model/list.cpp src/model/semantics.cpp src/model/logger.cpp src/model/name.cpp @@ -115,6 +116,7 @@ set(INTERFACE_SRC src/execution/plan.cpp src/execution/platform_backend.cpp src/execution/transformation.cpp + src/execution/event.cpp src/model/platform/component.cpp src/model/platform/constraint.cpp @@ -155,8 +157,8 @@ install(FILES src/model/string.h src/model/mapping.h src/model/types.h - src/model/compound_expression.h - src/model/list_expression.h + src/model/compound.h + src/model/list.h src/model/logger.h src/model/name.h @@ -173,6 +175,7 @@ install(FILES src/execution/plan.h src/execution/platform_backend.h src/execution/transformation.h + src/execution/event.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/golog++/execution ) @@ -225,10 +228,10 @@ if (${BUILD_PARSER}) src/parser/symbolic_expression.cpp src/parser/string_expression.cpp src/parser/domain.cpp - src/parser/compound_expression.cpp + src/parser/compound.cpp src/parser/mixed_member_access.cpp src/parser/mapping.cpp - src/parser/list_expression.cpp + src/parser/list.cpp src/parser/value.cpp src/parser/platform/clock_formula.cpp @@ -262,10 +265,10 @@ if (${BUILD_PARSER}) src/parser/expressions.h src/parser/symbolic_expression.h src/parser/domain.h - src/parser/compound_expression.h + src/parser/compound.h src/parser/mixed_member_access.h src/parser/mapping.h - src/parser/list_expression.h + src/parser/list.h src/parser/value.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/golog++/parser ) @@ -313,10 +316,9 @@ if (${BUILD_READYLOG_SEMANTICS}) src/semantics/readylog/history.cpp src/semantics/readylog/reference.cpp src/semantics/readylog/effect_axiom.cpp - src/semantics/readylog/compound_expression.cpp - src/semantics/readylog/list_expression.cpp + src/semantics/readylog/compound.cpp + src/semantics/readylog/list.cpp src/semantics/readylog/transition.cpp - src/semantics/readylog/activity.cpp src/semantics/readylog/plan.cpp ) @@ -348,24 +350,31 @@ if (${BUILD_READYLOG_SEMANTICS}) src/semantics/readylog/reference.h src/semantics/readylog/string.h src/semantics/readylog/history.h - src/semantics/readylog/compound_expression.h - src/semantics/readylog/list_expression.h + src/semantics/readylog/compound.h + src/semantics/readylog/list.h src/semantics/readylog/transition.h - src/semantics/readylog/activity.h src/semantics/readylog/plan.h src/semantics/readylog/wrap_eclipseclass.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/golog++/semantics/readylog ) + file( + COPY src/semantics/readylog/boilerplate.pl + DESTINATION "${CMAKE_BINARY_DIR}/semantics/readylog" + ) install(FILES src/semantics/readylog/boilerplate.pl DESTINATION ${SEMANTICS_INSTALL_DIR}/readylog ) if (INSTALL_READYLOG_INTERPRETER) + file( + COPY src/semantics/readylog/readylog_ecl + DESTINATION "${CMAKE_BINARY_DIR}/semantics/readylog" + ) install( - DIRECTORY src/semantics/readylog/interpreter + DIRECTORY src/semantics/readylog/readylog_ecl DESTINATION ${SEMANTICS_INSTALL_DIR}/readylog ) endif() @@ -383,6 +392,89 @@ if (${BUILD_READYLOG_SEMANTICS}) endif() + +###################################################################################### +# The golog++ native semantics: libnativegolog++.so +###################################################################################### + +option(BUILD_NATIVE_SEMANTICS "Build the native golog++ semantics" OFF) +if (${BUILD_NATIVE_SEMANTICS}) + set(NATIVE_SRC + src/semantics/native/action.cpp + src/semantics/native/variable.cpp + src/semantics/native/value.cpp + src/semantics/native/domain.cpp + src/semantics/native/arithmetic.cpp + src/semantics/native/execution.cpp + src/semantics/native/fluent.cpp + src/semantics/native/formula.cpp + src/semantics/native/procedural.cpp + src/semantics/native/scope.cpp + src/semantics/native/semantics.cpp + src/semantics/native/utilities.cpp + src/semantics/native/string.cpp + src/semantics/native/history.cpp + src/semantics/native/reference.cpp + src/semantics/native/effect_axiom.cpp + src/semantics/native/compound.cpp + src/semantics/native/list.cpp + src/semantics/native/transition.cpp + ) + + link_directories(${ECLIPSE_LIBRARY_DIRS}) + add_library(nativegolog++ SHARED ${NATIVE_SRC}) + target_compile_definitions(nativegolog++ PUBLIC + -DECLIPSE_DIR=\"${ECLIPSE_DIR}\" + -DUSES_NO_ENGINE_HANDLE + -DSEMANTICS_INSTALL_DIR=\"${CMAKE_INSTALL_PREFIX}/${SEMANTICS_INSTALL_DIR}\" + ) + target_include_directories(nativegolog++ PUBLIC ${ECLIPSE_INCLUDE_DIRS}) + target_link_libraries(nativegolog++ golog++ ${ECLIPSE_LIBRARIES} stdc++fs) + set_property(TARGET nativegolog++ PROPERTY CXX_STANDARD 14) + set_property(TARGET nativegolog++ PROPERTY SOVERSION ${GOLOGPP_VERSION}) + install(TARGETS nativegolog++ DESTINATION ${CMAKE_INSTALL_LIBDIR}) + install(FILES + src/semantics/native/semantics.h + src/semantics/native/formula.h + src/semantics/native/effect_axiom.h + src/semantics/native/variable.h + src/semantics/native/value.h + src/semantics/native/domain.h + src/semantics/native/arithmetic.h + src/semantics/native/procedural.h + src/semantics/native/scope.h + src/semantics/native/fluent.h + src/semantics/native/action.h + src/semantics/native/execution.h + src/semantics/native/utilities.h + src/semantics/native/reference.h + src/semantics/native/string.h + src/semantics/native/history.h + src/semantics/native/compound.h + src/semantics/native/list.h + src/semantics/native/transition.h + + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/golog++/semantics/native + ) + + get_target_property(NATIVEGPP_CXXFLAGS_L nativegolog++ INTERFACE_COMPILE_OPTIONS) + set(NATIVEGPP_CXXFLAGS "-I${ECLIPSE_INCLUDE_DIRS}") + if (${NATIVEGPP_CXXFLAGS_L}) + foreach(i IN LISTS ${NATIVEGPP_CXXFLAGS_L}) + set(NATIVEGPP_CXXFLAGS "${NATIVEGPP_CXXFLAGS} ${i}") + endforeach() + endif() + set(NATIVEGPP_LDFLAGS "${ECLIPSE_LDFLAGS}") + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/nativegolog++.pc.in ${CMAKE_CURRENT_BINARY_DIR}/nativegolog++.pc @ONLY) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/nativegolog++.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) +endif() + + + +###################################################################################### +# The taptenc semantics for platform modeling +###################################################################################### + if (BUILD_TAPTENC_SEMANTICS) set(TAPTENC_SRC external/taptenc/src/constraints/constraints.cpp @@ -461,6 +553,7 @@ set(GPP_TESTS if (BUILD_PARSER AND BUILD_READYLOG_SEMANTICS) include(CTest) + enable_testing() add_executable(gologpp-test src/tests/gologpp-test.cpp) if (USE_LIBASAN) @@ -469,6 +562,7 @@ if (BUILD_PARSER AND BUILD_READYLOG_SEMANTICS) set(TEST_LIBS ${TEST_LIBS} boost_filesystem boost_program_options parsegolog++ readylog++) target_link_libraries(gologpp-test ${TEST_LIBS}) + set_target_properties(gologpp-test PROPERTIES BUILD_RPATH ${ECLIPSE_LIBRARY_DIRS}) if (BUILD_TAPTENC_SEMANTICS) target_link_libraries(gologpp-test taptenc-golog++) @@ -487,3 +581,18 @@ if (BUILD_PARSER AND BUILD_READYLOG_SEMANTICS) endif() + +if (${BUILD_NATIVE_SEMANTICS}) + set(NATIVE_TEST_SRC + src/tools/nativegpp-test.cpp) + add_executable(nativegpp-test ${NATIVE_TEST_SRC}) + target_link_libraries(nativegpp-test nativegolog++ parsegolog++) + set_property(TARGET nativegpp-test PROPERTY CXX_STANDARD 14) + + if (USE_LIBASAN) + target_link_libraries(nativegpp-test asan) + endif() + + install(TARGETS nativegpp-test RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) +endif() + diff --git a/src/execution/activity.cpp b/src/execution/activity.cpp index cc0a3c72..8883bb73 100644 --- a/src/execution/activity.cpp +++ b/src/execution/activity.cpp @@ -25,14 +25,15 @@ namespace gologpp { -Activity::Activity(const shared_ptr &action, vector> &&args, AExecutionController &ctx, State state) -: ReferenceBase(action, std::move(args)) +Activity::Activity(const shared_ptr &action, vector> &&args, AExecutionController &ctx, State state) +: action_ref_(action, std::move(args)) , state_(state) , exec_context_(ctx) {} + Activity::Activity(const Transition &trans, AExecutionController &ctx) -: ReferenceBase(trans.target(), copy(trans.args())) +: action_ref_(trans.action(), copy(trans.ref().args())) , state_(State::IDLE) , exec_context_(ctx) { @@ -40,18 +41,6 @@ Activity::Activity(const Transition &trans, AExecutionController &ctx) throw Bug("Activity must be constructed from a START Transition"); } -const Action &Activity::operator *() const -{ return *this->target(); } - -Action &Activity::operator *() -{ return *this->target(); } - -const Action *Activity::operator ->() const -{ return this->target().get(); } - -Action *Activity::operator ->() -{ return this->target().get(); } - void Activity::set_state(Activity::State state) { state_ = state; } @@ -81,36 +70,50 @@ void Activity::update(Transition::Hook hook) { PlatformBackend::Lock backend_lock = exec_context_.backend().lock(); set_state(target_state(hook)); - exec_context_.exog_queue_push(shared_from_this()); + exec_context_.exog_queue_push( + shared_ptr(new Transition(action(), args(), hook)) + ); + update_condition_.notify_all(); } +void Activity::wait_for_update() +{ + std::unique_lock update_lock { update_mutex_ }; + State prev_state = state(); + update_condition_.wait(update_lock, [&] { + return state() != prev_state; + }); +} Value Activity::mapped_arg_value(const string &name) const { return dynamic_cast &>( - target()->mapping().mapped_expr(name).general_semantics() - ).evaluate({ &this->binding() }, exec_context_.history()); + action()->mapping().mapped_expr(name).general_semantics() + ).evaluate({ &this->ref().binding() }, exec_context_.history()); } - const std::string &Activity::mapped_name() const -{ return target()->mapping().backend_name(); } +{ return action()->mapping().backend_name(); } -string Activity::to_string(const string &pfx) const -{ return pfx + "state(" + ReferenceBase::to_string("") + ") = " + gologpp::to_string(state()); } +shared_ptr Activity::action() const +{ return ref().target(); } -void Activity::attach_semantics(SemanticsFactory &implementor) +vector> Activity::args() const { - if (!semantics_) { - binding().attach_semantics(implementor); - semantics_ = implementor.make_semantics(*this); - for (auto &c : args()) - c->attach_semantics(implementor); - } + vector> rv; + for (const Value *arg : ref().args()) + rv.emplace_back(new Value(*arg)); + return rv; } +const Reference &Activity::ref() const +{ return action_ref_; } + +Reference &Activity::ref() +{ return action_ref_; } + string to_string(Activity::State s) { diff --git a/src/execution/activity.h b/src/execution/activity.h index 4849e43e..edf52c71 100644 --- a/src/execution/activity.h +++ b/src/execution/activity.h @@ -23,46 +23,44 @@ #include #include "transition.h" -#include - +#include namespace gologpp { -class Activity -: public ReferenceBase -, public Reference -, public Instruction -, public LanguageElement -, public std::enable_shared_from_this { +class Activity { public: enum State { IDLE, RUNNING, FINAL, CANCELLED, FAILED }; - Activity(const shared_ptr &action, vector> &&args, AExecutionController &, State state = IDLE); + Activity( + const shared_ptr &action, + vector> &&args, + AExecutionController &, State state = IDLE + ); + Activity(const Transition &, AExecutionController &); - virtual const Action &operator * () const override; - virtual Action &operator * () override; - virtual const Action *operator -> () const override; - virtual Action *operator -> () override; + void update(Transition::Hook hook); + void wait_for_update(); State state() const; void set_state(State s); - - void update(Transition::Hook hook); - const std::string &mapped_name() const; Value mapped_arg_value(const string &name) const; - - virtual string to_string(const string &pfx) const override; - - virtual void attach_semantics(SemanticsFactory &) override; + shared_ptr action() const; + vector> args() const; + const Grounding &ref() const; + Grounding &ref(); static State target_state(Transition::Hook); private: + Grounding action_ref_; + State state_; AExecutionController &exec_context_; + std::condition_variable update_condition_; + std::mutex update_mutex_; }; diff --git a/src/execution/controller.cpp b/src/execution/controller.cpp index 337e6a84..4a50afe9 100644 --- a/src/execution/controller.cpp +++ b/src/execution/controller.cpp @@ -27,7 +27,6 @@ #include #include -#include "plan.h" #include "controller.h" #include "history.h" #include "platform_backend.h" @@ -88,16 +87,17 @@ AExecutionController::AExecutionController(unique_ptr &&platfor } -shared_ptr> AExecutionController::exog_queue_pop() +shared_ptr AExecutionController::exog_queue_pop() { std::lock_guard locked{ exog_mutex_ }; - shared_ptr> rv = std::move(exog_queue_.front()); + shared_ptr rv = std::move(exog_queue_.front()); exog_queue_.pop_front(); + rv->attach_semantics(semantics_factory()); return rv; } -shared_ptr> AExecutionController::exog_queue_poll(optional timeout) +shared_ptr AExecutionController::exog_queue_poll(optional timeout) { exog_queue_block(timeout); return exog_queue_pop(); @@ -137,7 +137,7 @@ void AExecutionController::terminate() } -void AExecutionController::exog_queue_push(shared_ptr> exog) +void AExecutionController::exog_queue_push(shared_ptr exog) { std::lock_guard { exog_mutex_ }; exog_queue_.push_back(std::move(exog)); @@ -147,7 +147,7 @@ void AExecutionController::exog_queue_push(shared_ptr> } } -void AExecutionController::exog_queue_push_front(shared_ptr > exog) +void AExecutionController::exog_queue_push_front(shared_ptr exog) { std::lock_guard { exog_mutex_ }; exog_queue_.push_front(std::move(exog)); @@ -160,14 +160,13 @@ void AExecutionController::exog_queue_push_front(shared_ptr> { - step_time_action_->make_ref( - { new Value( - get_type(), - Clock::now().time_since_epoch().count()) - } - ) - } ); + exog_queue_push_front(shared_ptr { new ExogEvent { + step_time_action_, + { unique_ptr( new Value ( + get_type(), + Clock::now().time_since_epoch().count() + ) ) } + } } ); std::lock_guard l2 { wait_mutex_ }; } @@ -191,24 +190,23 @@ History &AExecutionController::history() void AExecutionController::drain_exog_queue() { while (!exog_empty()) { - shared_ptr> exog = exog_queue_pop(); + shared_ptr exog = exog_queue_pop(); if (!std::dynamic_pointer_cast>(exog)) { // Nothing to do here for SwitchStateAction: // its effects have already been applied to the component model - if (!(*exog)->silent()) { - log(LogLevel::INF) << ">>> Exogenous event: " << exog << flush; + if (!exog->ref()->silent()) { + log(LogLevel::INF) << ">>> Exogenous event: " << exog->ref() << flush; silent_ = false; } - exog->attach_semantics(semantics_factory()); shared_ptr activity = std::dynamic_pointer_cast(exog); - if (activity && activity->target()->senses()) + if (activity && activity->action()->senses()) history().general_semantics().append_sensing_result( activity, - activity->target()->senses()->lhs(), - activity->target()->senses()->rhs().general_semantics().evaluate( - { &activity->binding() }, + activity->action()->senses()->lhs(), + activity->action()->senses()->rhs().general_semantics().evaluate( + { &activity->ref().binding() }, history() ) ); @@ -254,136 +252,5 @@ shared_ptr AExecutionController::switch_state_actio { return switch_state_action_; } -///////////////////////////////////////////////////////////////////////////////////////////////// -/***********************************************************************************************/ -///////////////////////////////////////////////////////////////////////////////////////////////// - -ExecutionController::ExecutionController( - unique_ptr &&exec_backend, - unique_ptr &&plan_transformation -) -: AExecutionController(std::move(exec_backend)) -, plan_transformation_(std::move(plan_transformation)) -{ - if (!plan_transformation_) - plan_transformation_.reset(semantics_factory().platform_semantics_factory().make_transformation()); -} - -ExecutionController::~ExecutionController() -{} - - -void ExecutionController::run(const Instruction &program) -{ - try { - history().attach_semantics(semantics_factory()); - global_scope().implement_globals(semantics_factory(), *this); - - plan_transformation_->init(*this); - - while (!program.general_semantics().final({}, history())) { - set_silent(true); - - unique_ptr plan { - program.general_semantics().trans({}, history()) - }; - - if (plan) { - plan = plan_transformation_->transform(std::move(*plan)); - - log(LogLevel::INF) << "<<< Transformed schedule: " << *plan << flush; - - while (!plan->elements().empty()) { - set_silent(true); - - if (terminated) - throw Terminate(); - - if (!exog_empty()) { - drain_exog_queue(); - if (backend().any_component_state_changed_exog()) - plan = plan_transformation_->transform(std::move(*plan)); - } - - unique_ptr empty_plan; - - if (plan->elements().front().earliest_timepoint() > context_time()) { - backend().schedule_timer_event( - plan->elements().front().earliest_timepoint() - ); - } - else { - // Plan elements are expected to not return plans again (nullptr or empty Plan). - empty_plan = plan->elements().front().instruction() - .general_semantics().trans({}, history()) - ; - } - - Clock::time_point timeout = plan->next_timeout(); - - if (empty_plan) { - // Empty plan: successfully executed - if (!empty_plan->elements().empty()) - throw Bug( - "Plan instruction returned a plan: " - + plan->elements().front().instruction().str() - ); - plan->elements().erase(plan->elements().begin()); - } - else { - // Current Plan element not executable - try { - drain_exog_queue_blocking(timeout); - } catch (ExogTimeout &) - { - exog_timer_wakeup(); - log(LogLevel::ERR) << "=== Next-action timeout " << timeout << " exceeded" << flush; - - auto sw_state = dynamic_cast *>( - &plan->elements().front().instruction() - ); - if (sw_state) { - global_scope().lookup_global( - static_cast(dynamic_cast( - sw_state->arg_for_param(sw_state->target()->param_component()) - )) - )->backend().handle_missed_transition(); - } - - drain_exog_queue(); - } - - if (context_time() > plan->elements().front().latest_timepoint() - || backend().any_component_state_changed_exog() - ) { - // First plan element's time window has passed: replan! - log(LogLevel::INF) << "=== Re-transforming..." << flush; - plan->make_start_slack(Clock::seconds(16384)); - plan = plan_transformation_->transform(std::move(*plan)); - log(LogLevel::INF) << "=== New schedule " << *plan << flush; - } - } - - if (history().general_semantics().should_progress()) { - log(LogLevel::DBG) << "=== Progressing history." << flush; - history().general_semantics().progress(); - } - } - } - else { - drain_exog_queue_blocking(nullopt); - } - - if (terminated) - throw Terminate(); - - } - } catch (Terminate &) { - log(LogLevel::DBG) << ">>> Terminated." << flush; - } -} - - - } diff --git a/src/execution/controller.h b/src/execution/controller.h index 9b04a873..05414f48 100644 --- a/src/execution/controller.h +++ b/src/execution/controller.h @@ -23,7 +23,6 @@ #include "platform_backend.h" #include "history.h" -#include "transformation.h" #include #include @@ -48,7 +47,7 @@ class ExogTimeout { class AExecutionController { public: - typedef std::deque>> ExogQueue; + typedef std::deque> ExogQueue; AExecutionController(unique_ptr &&platform_backend); virtual ~AExecutionController() = default; @@ -67,18 +66,18 @@ class AExecutionController { virtual void run(const Instruction &program) = 0; /// \return Head popped from the exog_queue or nullptr if it is empty. - shared_ptr> exog_queue_pop(); + shared_ptr exog_queue_pop(); /// Block until the exog_queue is non-empty. /// \return Head popped from the exog_queue. - shared_ptr> exog_queue_poll(optional timeout); + shared_ptr exog_queue_poll(optional timeout); /// Block until the exog_queue is non-empty. void exog_queue_block(optional timeout); bool exog_empty(); - void exog_queue_push(shared_ptr> exog); - void exog_queue_push_front(shared_ptr> exog); + void exog_queue_push(shared_ptr exog); + void exog_queue_push_front(shared_ptr exog); /// Update context_time and unblock exog_queue. void exog_timer_wakeup(); @@ -122,24 +121,6 @@ class AExecutionController { -class ExecutionController : public AExecutionController { -public: - ExecutionController( - unique_ptr &&exec_backend, - unique_ptr &&plan_transformation - ); - - virtual ~ExecutionController() override; - - virtual void run(const Instruction &program) override; - -private: - unique_ptr plan_transformation_; -}; - - - - } // namespace gologpp #endif diff --git a/src/execution/dummy_backend.cpp b/src/execution/dummy_backend.cpp index 9ca827c1..daa728e6 100644 --- a/src/execution/dummy_backend.cpp +++ b/src/execution/dummy_backend.cpp @@ -72,13 +72,11 @@ std::function DummyBackend::rnd_exog_generator() break; shared_ptr exog = exogs_[static_cast(rnd_exog_index_(prng_))]; - vector> args; + vector> args; for (shared_ptr p : exog->params()) args.push_back(rnd_value(p->type())); - shared_ptr> event(new Reference(exog, std::move(args))); - event->attach_semantics(exec_context()->semantics_factory()); - + shared_ptr event(new ExogEvent(exog, std::move(args))); exec_context()->exog_queue_push(event); } log(LogLevel::INF) << "exog generator TERMINATED" << flush; @@ -124,7 +122,7 @@ void DummyBackend::preempt_activity(shared_ptr a) { std::lock_guard locked(thread_mtx_); if (activity_threads_.find(a) == activity_threads_.end()) - throw EngineError("No such activity: " + a->str()); + throw EngineError("No such activity: " + a->ref().str()); activity_threads_[a]->cancel(); } diff --git a/src/execution/event.cpp b/src/execution/event.cpp new file mode 100644 index 00000000..fd329a09 --- /dev/null +++ b/src/execution/event.cpp @@ -0,0 +1,83 @@ +/************************************************************************* + * This file is part of golog++. + * + * golog++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * golog++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with golog++. If not, see . +**************************************************************************/ + + +#include "event.h" +#include +#include +#include +#include + +namespace gologpp { + + +string AbstractEvent::to_string(const string &pfx) const +{ return ref().to_string(pfx); } + +template +Event::Event(shared_ptr action, vector> &&args) +: ground_action_(action, std::move(args)) +{} + +template +Event::Event(shared_ptr action, std::initializer_list> &&args) +: ground_action_(action, std::vector> { std::move(args) }) +{} + +template +Event::Event(shared_ptr action, std::initializer_list &&args) +: ground_action_(action, std::vector> { args.begin(), args.end() }) +{} + +template +Event::Event(Event &&other) +: ground_action_(std::move(other.ground_action_)) +{} + +template +Event::Event(const Event &other) +: ground_action_(other.ground_action_) +{} + +template +shared_ptr Event::action() const +{ return ground_action_.target(); } + +template +const vector &Event::args() +{ return ground_action_.args(); } + +template +const Reference &Event::ref() const +{ return ground_action_; } + +template +Reference &Event::ref() +{ return ground_action_; } + + +template +class Event; + +template +class Event; + +template +class Event; + + +} // gologpp diff --git a/src/execution/event.h b/src/execution/event.h new file mode 100644 index 00000000..6f1c5c66 --- /dev/null +++ b/src/execution/event.h @@ -0,0 +1,67 @@ +/************************************************************************* + * This file is part of golog++. + * + * golog++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * golog++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with golog++. If not, see . +**************************************************************************/ + +#pragma once + +#include +#include +#include +#include +#include + +#include + +namespace gologpp { + + +class AbstractEvent +: public virtual AbstractLanguageElement +, public NoScopeOwner +{ +public: + virtual const Reference &ref() const = 0; + virtual Reference &ref() = 0; + + virtual string to_string(const string &pfx) const override; +}; + + +template +class Event +: public AbstractEvent +, public std::enable_shared_from_this> +{ +public: + Event(shared_ptr action, vector> &&args); + Event(shared_ptr action, std::initializer_list> &&args); + Event(shared_ptr action, std::initializer_list &&args); + Event(Event &&other); + explicit Event(const Event &other); + + shared_ptr action() const; + + const vector &args(); + virtual const Reference &ref() const override; + virtual Reference &ref() override; + +protected: + Reference ground_action_; +}; + + + +} diff --git a/src/execution/history.cpp b/src/execution/history.cpp index 18872a85..679c5993 100644 --- a/src/execution/history.cpp +++ b/src/execution/history.cpp @@ -26,7 +26,7 @@ GeneralSemantics::GeneralSemantics(History &h, AExecutionController &co , context_(context) {} -GeneralSemantics::~GeneralSemantics() +GeneralSemantics::~GeneralSemantics() {} @@ -54,7 +54,7 @@ AExecutionController &GeneralSemantics::context() const const ModelElement &GeneralSemantics::model_element() const { return history_; } -void GeneralSemantics::append(shared_ptr> a) +void GeneralSemantics::append(shared_ptr a) { append(*a); } diff --git a/src/execution/history.h b/src/execution/history.h index 2272acd2..822de2ac 100644 --- a/src/execution/history.h +++ b/src/execution/history.h @@ -43,13 +43,11 @@ class History : public LanguageElement, public NoScopeOwner { template<> class GeneralSemantics : public virtual GeneralSemantics { public: - GeneralSemantics(History &history, AExecutionController &context); - virtual ~GeneralSemantics() override; + GeneralSemantics(History &history, AExecutionController &context); + virtual ~GeneralSemantics() override; - virtual shared_ptr get_last_transition() = 0; - virtual void append(const Reference &) = 0; - virtual void append(const Transition &) = 0; - virtual void append(shared_ptr>); + virtual void append(const AbstractEvent &) = 0; + virtual void append(shared_ptr); virtual bool should_progress() const = 0; virtual void progress() = 0; diff --git a/src/execution/plan.cpp b/src/execution/plan.cpp index 612938a7..495b2ee4 100644 --- a/src/execution/plan.cpp +++ b/src/execution/plan.cpp @@ -134,7 +134,7 @@ void Plan::sanitize_time_window(iterator back_from_it) auto it = std::find_if(reverse_iterator(back_from_it), elements().rend(), [&] (TimedInstruction &ti) { try { Transition &trans2 = ti.instruction().cast(); - return trans2.hook() == Transition::Hook::START && trans2 == *trans; + return trans2.hook() == Transition::Hook::START && trans2.ref() == trans->ref(); } catch (std::bad_cast &) { return false; } @@ -143,19 +143,19 @@ void Plan::sanitize_time_window(iterator back_from_it) if (it == elements().rend()) { // Not found: use best guess ti.set_earliest(prev_earliest); - ti.set_latest(prev_latest + trans->target()->duration().max); + ti.set_latest(prev_latest + trans->action()->duration().max); } else { // Found: add on top ti.set_earliest( std::max( - it->earliest_timepoint() + trans->target()->duration().min, + it->earliest_timepoint() + trans->action()->duration().min, prev_earliest ) ); ti.set_latest( std::max( - it->latest_timepoint() + trans->target()->duration().max, + it->latest_timepoint() + trans->action()->duration().max, prev_latest ) ); diff --git a/src/execution/plan.h b/src/execution/plan.h index 3c877bd5..4d0ca129 100644 --- a/src/execution/plan.h +++ b/src/execution/plan.h @@ -73,7 +73,7 @@ class Plan Plan() = default; Plan(Plan &&sub); - Value max_reward(const Binding &binding, const Reference &reward_func); + Value max_reward(const BindingChain &binding, const Reference &reward_func); Plan &append(TimedInstruction &&); Plan &append(Plan &&); diff --git a/src/execution/platform_backend.cpp b/src/execution/platform_backend.cpp index 57d783e2..98c834d9 100644 --- a/src/execution/platform_backend.cpp +++ b/src/execution/platform_backend.cpp @@ -18,6 +18,7 @@ #include "platform_backend.h" #include "controller.h" #include "activity.h" +#include "transition.h" #include #include @@ -42,27 +43,26 @@ shared_ptr PlatformBackend::start_activity(const Transition &trans) { Lock l(lock()); shared_ptr a = std::make_shared(trans, *exec_ctx_); - auto it = activities_.find(a->hash()); + auto it = activities_.find(a->ref().hash()); if (it != activities_.end()) throw UserError( "Cannot start an action while another one with the same arguments is still running." - " Currently: " + it->second->str() + " Currently: " + it->second->ref().str() ); - a->attach_semantics(exec_context()->semantics_factory()); a->set_state(Activity::target_state(trans.hook())); execute_activity(a); - activities_.insert({a->hash(), a}); + activities_.insert({a->ref().hash(), a}); return a; } void PlatformBackend::cancel_activity(const Transition &trans) { Lock l(lock()); - auto it = activities_.find(trans.hash()); + auto it = activities_.find(trans.ref().hash()); if (it == activities_.end()) - throw Bug("Activity lost: " + trans->str()); + throw Bug("Activity lost: " + trans.ref().str()); else if (it->second->state() != Activity::State::RUNNING) - log(LogLevel::ERR) << "Cannot cancel activity " << it->second->str() << flush; + log(LogLevel::ERR) << "Cannot cancel activity " << it->second->ref().str() << flush; else preempt_activity(std::dynamic_pointer_cast(it->second)); } @@ -76,13 +76,13 @@ shared_ptr PlatformBackend::erase_activity(const Transition &trans) { Lock l(lock()); - ActivityMap::iterator it = activities_.find(trans.hash()); + ActivityMap::iterator it = activities_.find(trans.ref().hash()); shared_ptr dur_running; if (it != activities_.end()) dur_running = std::dynamic_pointer_cast(it->second); if (!dur_running) - throw LostTransition(trans->str()); + throw LostTransition(trans.ref().str()); // Either the durative action's state exactly matches the primitive action's hook, // or the hook is END, which may be executed if the durative state is either FINAL, FAILED or CANCELLED @@ -99,7 +99,7 @@ shared_ptr PlatformBackend::erase_activity(const Transition &trans) return dur_running; } else - throw InconsistentTransition(trans->str()); + throw InconsistentTransition(trans.ref().str()); } @@ -110,7 +110,7 @@ void PlatformBackend::set_context(AExecutionController *ctx) } -Activity::State PlatformBackend::current_state(const ReferenceBase &a) +Activity::State PlatformBackend::current_state(const Grounding &a) { Lock l(lock()); @@ -118,7 +118,7 @@ Activity::State PlatformBackend::current_state(const ReferenceBase &a) if (it == activities_.end()) return Activity::State::IDLE; else { - return it->second->cast().state(); + return it->second->state(); } } diff --git a/src/execution/platform_backend.h b/src/execution/platform_backend.h index 1a319a87..80820980 100644 --- a/src/execution/platform_backend.h +++ b/src/execution/platform_backend.h @@ -22,7 +22,6 @@ #include #include -#include "transition.h" #include "activity.h" #include "clock.h" @@ -50,6 +49,7 @@ class PlatformBackend { shared_ptr erase_activity(const Transition &); shared_ptr start_activity(const Transition &); + shared_ptr end_activity(const Transition &); void cancel_activity(const Transition &); Lock lock(); @@ -57,7 +57,7 @@ class PlatformBackend { void set_context(AExecutionController *ctx); AExecutionController *exec_context(); - Activity::State current_state(const ReferenceBase &); + Activity::State current_state(const Grounding &); void terminate(); virtual void schedule_timer_event(Clock::time_point when); diff --git a/src/execution/transition.cpp b/src/execution/transition.cpp index abfc9ae5..8a89e64f 100644 --- a/src/execution/transition.cpp +++ b/src/execution/transition.cpp @@ -21,57 +21,32 @@ #include #include - #include "controller.h" #include "transition.h" -#include "history.h" namespace gologpp { -Transition::Transition(const shared_ptr &action, vector> &&args, Hook hook) -: ReferenceBase(action, std::move(args)) -, hook_(hook) -{} - Transition::Transition(const Transition &other) -: ReferenceBase(other) +: Event(other) , hook_(other.hook()) { - if (other.semantics_) { + if (other.semantics_) semantics_.reset(other.general_semantics().copy(*this)); - } } -const Action &Transition::operator *() const -{ return *this->target(); } - -Action &Transition::operator *() -{ return *this->target(); } - -const Action *Transition::operator ->() const -{ return this->target().get(); } - -Action *Transition::operator ->() -{ return this->target().get(); } +Transition::Transition(shared_ptr action, vector > &&value, Hook hook) +: Event(action, std::move(value)) +, hook_(hook) +{} Transition::Hook Transition::hook() const { return hook_; } - -void Transition::attach_semantics(SemanticsFactory &implementor) -{ - if (!semantics_) { - semantics_ = implementor.make_semantics(*this); - binding().attach_semantics(implementor); - for (auto &c : args()) - c->attach_semantics(implementor); - } -} - string Transition::to_string(const string &pfx) const -{ return pfx + gologpp::to_string(hook()) + "(" + ReferenceBase::to_string(pfx) + ")"; } +{ return pfx + gologpp::to_string(hook()) + "(" + ground_action_.to_string(pfx) + ")"; } + @@ -90,72 +65,20 @@ void GeneralSemantics::update_element(const Transition *new_element) AExecutionController &GeneralSemantics::context() const { return context_; } - -unique_ptr GeneralSemantics::trans(const BindingChain &b, History &history) -{ - BindingChain merged(b); - merged.emplace_back(&element().binding()); - - switch(element().hook()) - { - case Transition::Hook::CANCEL: - if (context().backend().current_state(element()) == Activity::State::RUNNING) - context().backend().cancel_activity(element()); - else - return nullptr; - break; - case Transition::Hook::START: - if ( - context().backend().current_state(element()) != Activity::State::RUNNING - && static_cast( - element().target()->precondition().general_semantics().evaluate( - merged, - history - ) - ) - ) - context().backend().start_activity(element()); - else - return nullptr; - break; - case Transition::Hook::FINISH: - if (context().backend().current_state(element()) == Activity::State::FINAL) { - shared_ptr a = context().backend().erase_activity(element()); - } - else - return nullptr; - break; - case Transition::Hook::FAIL: - if (context().backend().current_state(element()) == Activity::State::FAILED) - context().backend().erase_activity(element()); - else - return nullptr; - break; - case Transition::Hook::END: - if ( - context().backend().current_state(element()) == Activity::State::FAILED - || context().backend().current_state(element()) == Activity::State::FINAL - ) - context().backend().erase_activity(element()); - else - return nullptr; - } - - if (!element()->silent()) { - log(LogLevel::NFY) << "<<< trans: " << element().str() << flush; - context().set_silent(false); - } - - history.general_semantics().append(element()); - - return unique_ptr(new Plan()); -} - const ModelElement &GeneralSemantics::model_element() const { return element(); } const Instruction &GeneralSemantics::instruction() const -{ return element(); } +{ return static_cast(element()); } + + + +ExogEvent::ExogEvent(const ExogEvent &other) +: Event(other) +{ + if (other.semantics_) + semantics_.reset(other.general_semantics().copy(*this)); +} diff --git a/src/execution/transition.h b/src/execution/transition.h index acfab459..97dd08a4 100644 --- a/src/execution/transition.h +++ b/src/execution/transition.h @@ -15,39 +15,37 @@ * along with golog++. If not, see . **************************************************************************/ -#ifndef GOLOGPP_TRANSITION_H_ -#define GOLOGPP_TRANSITION_H_ +#pragma once #include #include #include #include #include +#include namespace gologpp { +template<> +inline constexpr const bool is_copyable = true; + class Transition -: public ReferenceBase -, public Reference -, public Instruction +: public Instruction +, public Event , public LanguageElement -, public std::enable_shared_from_this { public: using Hook = DurativeCall::Hook; - Transition(const shared_ptr &action, vector> &&args, Hook hook); + using Event::Event; Transition(const Transition &); - - virtual const Action &operator * () const override; - virtual Action &operator * () override; - virtual const Action *operator -> () const override; - virtual Action *operator -> () override; + Transition(shared_ptr action, vector> &&value, Hook hook); Hook hook() const; virtual string to_string(const string &pfx) const override; - virtual void attach_semantics(SemanticsFactory &) override; + + DEFINE_ATTACH_SEMANTICS_WITH_MEMBERS(ground_action_) private: Hook hook_; @@ -63,8 +61,6 @@ class GeneralSemantics GeneralSemantics(const Transition &elem, AExecutionController &context); GeneralSemantics(const GeneralSemantics &other); - virtual unique_ptr trans(const BindingChain &, History &) override; - const Transition &element() const; virtual const ModelElement &model_element() const override; virtual const Instruction &instruction() const override; @@ -82,6 +78,22 @@ class GeneralSemantics +template<> +inline constexpr const bool is_copyable = true; + +class ExogEvent +: public Event +, public LanguageElement +, public Instruction +{ +public: + using Event::Event; + ExogEvent(const ExogEvent &other); + + DEFINE_ATTACH_SEMANTICS_WITH_MEMBERS(ground_action_) +}; + + + } -#endif // GOLOGPP_TRANSITION_H_ diff --git a/src/model/action.cpp b/src/model/action.cpp index a95c7c00..8e861d5c 100644 --- a/src/model/action.cpp +++ b/src/model/action.cpp @@ -17,11 +17,11 @@ #include "mapping.h" #include "action.h" -#include "fluent.h" #include "reference.h" #include "effect_axiom.h" -#include "execution/controller.h" #include "error.h" +#include + #include namespace gologpp { @@ -222,7 +222,9 @@ void ExogAction::define( set_mapping(mapping.value()); } -void ExogAction::set_mapping(BackendMapping *m) { + +void ExogAction::set_mapping(BackendMapping *m) +{ string missing; const BackendMapping::ArgMapping &arg_mapping = m->arg_mapping(); diff --git a/src/model/compound_expression.cpp b/src/model/compound.cpp similarity index 77% rename from src/model/compound_expression.cpp rename to src/model/compound.cpp index 569b716f..75f10063 100644 --- a/src/model/compound_expression.cpp +++ b/src/model/compound.cpp @@ -15,7 +15,7 @@ * along with golog++. If not, see . **************************************************************************/ -#include "compound_expression.h" +#include "compound.h" #include "semantics.h" #include @@ -98,5 +98,33 @@ const CompoundType &CompoundExpression::compound_type() const ); } +///////////////////////////////////////////////////////////////////////////////////////////////// +/***********************************************************************************************/ +///////////////////////////////////////////////////////////////////////////////////////////////// + +FieldAccess::FieldAccess(Expression *subject, const string &field_name) +: subject_(subject) +, field_name_(field_name) +{ + subject_->set_parent(this); +} + +const Expression &FieldAccess::subject() const +{ return *subject_; } + +const string &FieldAccess::field_name() const +{ return field_name_; } + +const Type &FieldAccess::type() const +{ + return dynamic_cast( + subject_->type() + ).field_type(field_name_); +} + +string FieldAccess::to_string(const string &pfx) const +{ return pfx + subject().str() + "." + field_name(); } + + } diff --git a/src/model/compound_expression.h b/src/model/compound.h similarity index 64% rename from src/model/compound_expression.h rename to src/model/compound.h index a7f64159..ea323573 100644 --- a/src/model/compound_expression.h +++ b/src/model/compound.h @@ -23,6 +23,7 @@ #include "expressions.h" #include "scope.h" #include "types.h" +#include "semantics.h" #include @@ -35,6 +36,8 @@ class CompoundExpression , public NoScopeOwner { public: + using EntryMap = std::unordered_map>; + CompoundExpression(const Type &type, const vector> &entries); const Expression &entry(const string &key) const; @@ -44,7 +47,32 @@ class CompoundExpression const CompoundType &compound_type() const; private: - std::unordered_map> entries_; + EntryMap entries_; +}; + +///////////////////////////////////////////////////////////////////////////////////////////////// +/***********************************************************************************************/ +///////////////////////////////////////////////////////////////////////////////////////////////// + +class FieldAccess +: public Expression +, public NoScopeOwner +, public LanguageElement +{ +public: + FieldAccess(Expression *subject, const string &field_name); + const Expression &subject() const; + const string &field_name() const; + + DEFINE_ATTACH_SEMANTICS_WITH_MEMBERS(*subject_) + + virtual const Type &type() const override; + + string to_string(const string &pfx) const override; + +private: + SafeExprOwner subject_; + const string field_name_; }; diff --git a/src/model/domain.cpp b/src/model/domain.cpp index bf2d9239..e1a8045d 100644 --- a/src/model/domain.cpp +++ b/src/model/domain.cpp @@ -180,7 +180,7 @@ void Domain::add_elements(const Domain &other) for (const unique_ptr &e : other.elements()) { if (!(element_type() >= *e)) throw TypeError(*e, element_type()); - elements_.emplace(e->copy()); + elements_.emplace(new Value(*e)); } } diff --git a/src/model/domain.h b/src/model/domain.h index e85c7c95..3b60dc3a 100644 --- a/src/model/domain.h +++ b/src/model/domain.h @@ -21,7 +21,6 @@ #include "gologpp.h" #include "language.h" #include "scope.h" -#include "expressions.h" #include "value.h" #include "error.h" diff --git a/src/model/effect_axiom.h b/src/model/effect_axiom.h index 628ac0f7..a1fed6f9 100644 --- a/src/model/effect_axiom.h +++ b/src/model/effect_axiom.h @@ -20,10 +20,8 @@ #include "utilities.h" #include "action.h" -#include "reference.h" #include "language.h" #include "expressions.h" -#include "fluent.h" #include "procedural.h" #include @@ -39,6 +37,8 @@ class AbstractEffectAxiom : public virtual AbstractLanguageElement { public: + using ElementType = ModelElement; + AbstractEffectAxiom(); AbstractEffectAxiom(AbstractEffectAxiom &&) = default; virtual ~AbstractEffectAxiom(); @@ -63,8 +63,6 @@ class EffectAxiom , public LanguageElement> { public: - using ElementType = ModelElement; - EffectAxiom() {} diff --git a/src/model/expressions.h b/src/model/expressions.h index bf2d529e..252c1825 100644 --- a/src/model/expressions.h +++ b/src/model/expressions.h @@ -19,7 +19,6 @@ #define GOLOGPP_EXPRESSIONS_H_ #include "language.h" -#include "utilities.h" #include "gologpp.h" #include "types.h" diff --git a/src/model/gologpp.h b/src/model/gologpp.h index dbca2eaf..65bf059f 100644 --- a/src/model/gologpp.h +++ b/src/model/gologpp.h @@ -43,6 +43,9 @@ template using optional = std::optional; using std::nullopt; +template +using enable_if = typename std::enable_if::type; + using string = std::string; @@ -50,9 +53,10 @@ class Logger; class Expression; class Instruction; +class Value; -class Binding; -using BindingChain = vector; +template class Binding; +class BindingChain; class ModelElement; class Plan; @@ -68,8 +72,12 @@ class ExogAction; class BackendMapping; +class AbstractEvent; +template class Event; class Activity; class Transition; +class ExogEvent; + class Identifier; @@ -99,7 +107,6 @@ class Fluent; class InitialValue; class Variable; -class Value; class Domain; class ArithmeticOperation; @@ -136,25 +143,26 @@ class Procedure; class ExogFunction; class AbstractReference; -template class Reference; +template class Reference; + +template +using Grounding = Reference; class CompoundExpression; class ListExpression; class History; -template class Semantics; -template class GeneralSemantics; +template class Semantics; +template class GeneralSemantics; +template class CopyableSemantics; class SemanticsFactory; class AExecutionController; -class ExecutionController; class PlatformBackend; -using ExogEvent = Reference; - namespace platform { @@ -170,6 +178,7 @@ class Clock; class State; class SwitchStateAction; +class SwitchStateEvent; class ClockFormula; class ClockBound; @@ -212,11 +221,17 @@ class SemanticsFactory; (Conditional) \ (During) \ (Reference) \ + (Grounding) \ + (Grounding) \ (Reference) \ + (Grounding) \ (DurativeCall) \ (Reference) \ (ListPop) \ - (ListPush) + (Transition) \ + (ExogEvent) \ + (ListPush) \ + (platform::SwitchStateEvent) #define GOLOGPP_EXPRESSIONS \ (Variable) \ @@ -239,19 +254,20 @@ class SemanticsFactory; (CompoundExpression) \ (ListExpression) + + #define GOLOGPP_OTHER \ (EffectAxiom>) \ (EffectAxiom) \ (EffectAxiom) \ (InitialValue)(Fluent) \ - (Binding) \ + (Binding) \ + (Binding) \ (Domain) \ (Function) \ (ExogFunction) \ (Procedure) \ (Action) \ - (Activity) \ - (Transition) \ (ExogAction) \ (Scope) \ (History) @@ -286,31 +302,6 @@ class SemanticsFactory; GOLOGPP_OTHER -/* -using elem_types = boost::mpl::map < -boost::mpl::pair>, Instruction>, -boost::mpl::pair>, Instruction>, -boost::mpl::pair, Instruction>, -boost::mpl::pair, Instruction>, -boost::mpl::pair, -boost::mpl::pair, -boost::mpl::pair, -boost::mpl::pair, -boost::mpl::pair, -boost::mpl::pair, -boost::mpl::pair, -boost::mpl::pair, -boost::mpl::pair, -boost::mpl::pair, Instruction>, -boost::mpl::pair, -boost::mpl::pair, Instruction>, -boost::mpl::pair, Instruction>, -boost::mpl::pair, -boost::mpl::pair, Instruction>, -boost::mpl::pair, -boost::mpl::pair - ->;*/ } // namespace gologpp diff --git a/src/model/list.cpp b/src/model/list.cpp new file mode 100644 index 00000000..fd314ec6 --- /dev/null +++ b/src/model/list.cpp @@ -0,0 +1,209 @@ +/************************************************************************* + * This file is part of golog++. + * + * golog++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * golog++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with golog++. If not, see . +**************************************************************************/ + +#include "list.h" +#include "semantics.h" + +namespace gologpp { + + +ListExpression::ListExpression( + const Type &t, + const boost::optional> &entries +) +{ + set_type_unchecked(t); + + if (!AbstractLanguageElement::type().is()) + throw TypeError("Attempt to construct ListExpression, but type name \"" + + t.name() + "\" does not refer to a list type"); + + for (Expression *expr : entries.get_value_or({})) { + if (type().element_type() >= *expr) + entries_.emplace_back(expr); + else + throw ExpressionTypeMismatch("Cannot assign " + expr->str() + + " to a " + type().name() + ); + } +} + + +const Expression &ListExpression::entry(size_t idx) const +{ + if (idx >= entries_.size()) + throw UserError(str() + ": Index " + std::to_string(idx) + " out of range "); + return *entries_[idx]; +} + +const vector > &ListExpression::entries() const +{ return entries_; } + +size_t ListExpression::size() const +{ return entries_.size(); } + + +void ListExpression::attach_semantics(SemanticsFactory &f) +{ + if (semantics_) + return; + + for (auto &expr : entries_) + expr->attach_semantics(f); + set_semantics(f.make_semantics(*this)); +} + + +string ListExpression::to_string(const string &pfx) const +{ + string rv = pfx + "["; + for (const auto &elem : entries_) + rv += elem->str() + ", "; + if (entries_.size() > 0) + rv = rv.substr(0, rv.length() - 2); + return rv + "]"; +} + + +const ListType &ListExpression::type() const +{ + return dynamic_cast( + AbstractLanguageElement::type() + ); +} + + +bool ListExpression::operator <= (const Type &t) const +{ + try { + const ListType < = dynamic_cast(t); + for (const auto &entry : entries()) + if (!(*entry <= lt.element_type())) + return false; + return true; + } catch (std::bad_cast &) {} + + return t >= *this; +} + +///////////////////////////////////////////////////////////////////////////////////////////////// +/***********************************************************************************************/ +///////////////////////////////////////////////////////////////////////////////////////////////// + +ListAccess::ListAccess(Expression *subject, Expression *index) +: subject_(subject) +, index_(index) +{ + subject_->set_parent(this); + index_->set_parent(this); +} + +const Expression &ListAccess::subject() const +{ return *subject_; } + +const Expression &ListAccess::index() const +{ return *index_; } + + +const Type &ListAccess::type() const +{ + return dynamic_cast( + subject_->type() + ).element_type(); +} + +string ListAccess::to_string(const string &pfx) const +{ return subject_->to_string(pfx) + '[' + index_->str() + ']'; } + +///////////////////////////////////////////////////////////////////////////////////////////////// +/***********************************************************************************************/ +///////////////////////////////////////////////////////////////////////////////////////////////// + +ListLength::ListLength(Expression *subject) +: subject_(subject) +{ subject_->set_parent(this); } + +const Expression &ListLength::subject() const +{ return *subject_; } + +string ListLength::to_string(const string &pfx) const +{ return "length(" + subject_->to_string(pfx) + ')'; } + + + +string to_string(ListOpEnd which_end) +{ + switch (which_end) { + case FRONT: + return "front"; + case BACK: + return "back"; + } + throw Bug(string("Unhandled ") + typeid(which_end).name()); +} + +///////////////////////////////////////////////////////////////////////////////////////////////// +/***********************************************************************************************/ +///////////////////////////////////////////////////////////////////////////////////////////////// + +ListPop::ListPop(Expression *list, ListOpEnd which_end) +: list_(list) +, which_end_(which_end) +{ list_->set_parent(this); } + +const Expression &ListPop::list() const +{ return *list_; } + +ListOpEnd ListPop::which_end() const +{ return which_end_; } + +string ListPop::to_string(const string &pfx) const +{ return pfx + "pop_" + gologpp::to_string(which_end_) + '(' + list_->str() + ')'; } + +///////////////////////////////////////////////////////////////////////////////////////////////// +/***********************************************************************************************/ +///////////////////////////////////////////////////////////////////////////////////////////////// + +ListPush::ListPush(Expression *list, ListOpEnd which_end, Expression *what) +: list_(list) +, which_end_(which_end) +{ + list_->set_parent(this); + + what->ensure_type( + dynamic_cast( + list_->type() + ).element_type() + ); + what_.reset(what); + what_->set_parent(this); +} + +const Expression &ListPush::list() const +{ return *list_; } + +ListOpEnd ListPush::which_end() const +{ return which_end_; } + +const Expression &ListPush::what() const +{ return *what_; } + +string ListPush::to_string(const string &pfx) const +{ return pfx + "push_" + gologpp::to_string(which_end_) + '(' + list_->str() + ')'; } + + +} // namespace gologpp diff --git a/src/model/list.h b/src/model/list.h new file mode 100644 index 00000000..3cc0875a --- /dev/null +++ b/src/model/list.h @@ -0,0 +1,161 @@ +/************************************************************************* + * This file is part of golog++. + * + * golog++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * golog++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with golog++. If not, see . +**************************************************************************/ + +#ifndef GOLOGPP_LIST_EXPRESSION_H_ +#define GOLOGPP_LIST_EXPRESSION_H_ + +#include "gologpp.h" +#include "language.h" +#include "expressions.h" +#include "scope.h" +#include "types.h" +#include "semantics.h" + +#include + +#include + +namespace gologpp { + + +class ListExpression +: public Expression +, public LanguageElement +, public NoScopeOwner +{ +public: + ListExpression(const Type &type, const boost::optional> &entries); + + const Expression &entry(size_t idx) const; + const vector> &entries() const; + size_t size() const; + + virtual void attach_semantics(SemanticsFactory &) override; + virtual string to_string(const string &pfx) const override; + virtual const ListType &type() const override; + virtual bool operator <= (const Type &t) const override; + +private: + vector> entries_; +}; + +///////////////////////////////////////////////////////////////////////////////////////////////// +/***********************************************************************************************/ +///////////////////////////////////////////////////////////////////////////////////////////////// + +class ListAccess +: public Expression +, public NoScopeOwner +, public LanguageElement +{ +public: + ListAccess(Expression *subject, Expression *index); + const Expression &subject() const; + const Expression &index() const; + + DEFINE_ATTACH_SEMANTICS_WITH_MEMBERS(*subject_, *index_) + + virtual const Type &type() const override; + + string to_string(const string &pfx) const override; + +private: + SafeExprOwner subject_; + SafeExprOwner index_; +}; + +///////////////////////////////////////////////////////////////////////////////////////////////// +/***********************************************************************************************/ +///////////////////////////////////////////////////////////////////////////////////////////////// + +class ListLength +: public Expression +, public NoScopeOwner +, public LanguageElement +{ +public: + ListLength(Expression *subject); + const Expression &subject() const; + + DEFINE_ATTACH_SEMANTICS_WITH_MEMBERS(*subject_) + + string to_string(const string &pfx) const override; + +private: + SafeExprOwner subject_; +}; + +///////////////////////////////////////////////////////////////////////////////////////////////// +/***********************************************************************************************/ +///////////////////////////////////////////////////////////////////////////////////////////////// + +enum ListOpEnd { + FRONT, BACK +}; + +///////////////////////////////////////////////////////////////////////////////////////////////// +/***********************************************************************************************/ +///////////////////////////////////////////////////////////////////////////////////////////////// + +class ListPop +: public Instruction +, public NoScopeOwner +, public LanguageElement +{ +public: + ListPop(Expression *list, ListOpEnd which_end); + const Expression &list() const; + ListOpEnd which_end() const; + + DEFINE_ATTACH_SEMANTICS_WITH_MEMBERS(*list_) + + string to_string(const string &pfx) const override; + +private: + SafeExprOwner list_; + ListOpEnd which_end_; +}; + +///////////////////////////////////////////////////////////////////////////////////////////////// +/***********************************************************************************************/ +///////////////////////////////////////////////////////////////////////////////////////////////// + +class ListPush +: public Instruction +, public NoScopeOwner +, public LanguageElement +{ +public: + ListPush(Expression *list, ListOpEnd which_end, Expression *what); + const Expression &list() const; + ListOpEnd which_end() const; + const Expression &what() const; + + DEFINE_ATTACH_SEMANTICS_WITH_MEMBERS(*list_, *what_) + + string to_string(const string &pfx) const override; + +private: + SafeExprOwner list_; + ListOpEnd which_end_; + unique_ptr what_; +}; + + +} // namespace gologpp + +#endif // GOLOGPP_LIST_EXPRESSION_H_ diff --git a/src/model/list_expression.cpp b/src/model/list_expression.cpp deleted file mode 100644 index 77b565d7..00000000 --- a/src/model/list_expression.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/************************************************************************* - * This file is part of golog++. - * - * golog++ is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * golog++ is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with golog++. If not, see . -**************************************************************************/ - -#include "list_expression.h" -#include "semantics.h" - -namespace gologpp { - - -ListExpression::ListExpression( - const Type &t, - const boost::optional> &entries -) -{ - set_type_unchecked(t); - - if (!AbstractLanguageElement::type().is()) - throw TypeError("Attempt to construct ListExpression, but type name \"" - + t.name() + "\" does not refer to a list type"); - - for (Expression *expr : entries.get_value_or({})) { - if (type().element_type() >= *expr) - entries_.emplace_back(expr); - else - throw ExpressionTypeMismatch("Cannot assign " + expr->str() - + " to a " + type().name() - ); - } -} - - -const Expression &ListExpression::entry(size_t idx) const -{ - if (idx >= entries_.size()) - throw UserError(str() + ": Index " + std::to_string(idx) + " out of range "); - return *entries_[idx]; -} - -const vector > &ListExpression::entries() const -{ return entries_; } - -size_t ListExpression::size() const -{ return entries_.size(); } - - -void ListExpression::attach_semantics(SemanticsFactory &f) -{ - if (semantics_) - return; - - for (auto &expr : entries_) - expr->attach_semantics(f); - set_semantics(f.make_semantics(*this)); -} - - -string ListExpression::to_string(const string &pfx) const -{ - string rv = pfx + "["; - for (const auto &elem : entries_) - rv += elem->str() + ", "; - if (entries_.size() > 0) - rv = rv.substr(0, rv.length() - 2); - return rv + "]"; -} - - -const ListType &ListExpression::type() const -{ - return dynamic_cast( - AbstractLanguageElement::type() - ); -} - - -bool ListExpression::operator <= (const Type &t) const -{ - try { - const ListType < = dynamic_cast(t); - for (const auto &entry : entries()) - if (!(*entry <= lt.element_type())) - return false; - return true; - } catch (std::bad_cast &) {} - - return t >= *this; -} - - -} // namespace gologpp diff --git a/src/model/list_expression.h b/src/model/list_expression.h deleted file mode 100644 index a7e28536..00000000 --- a/src/model/list_expression.h +++ /dev/null @@ -1,59 +0,0 @@ -/************************************************************************* - * This file is part of golog++. - * - * golog++ is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * golog++ is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with golog++. If not, see . -**************************************************************************/ - -#ifndef GOLOGPP_LIST_EXPRESSION_H_ -#define GOLOGPP_LIST_EXPRESSION_H_ - -#include "language.h" -#include "gologpp.h" -#include "expressions.h" -#include "scope.h" -#include "types.h" - -#include - -#include - -namespace gologpp { - - -class ListExpression -: public Expression -, public LanguageElement -, public NoScopeOwner -{ -public: - ListExpression(const Type &type, const boost::optional> &entries); - - const Expression &entry(size_t idx) const; - const vector> &entries() const; - size_t size() const; - - virtual void attach_semantics(SemanticsFactory &) override; - virtual string to_string(const string &pfx) const override; - virtual const ListType &type() const override; - virtual bool operator <= (const Type &t) const override; - -private: - vector> entries_; -}; - - - -} // namespace gologpp - -#endif // GOLOGPP_LIST_EXPRESSION_H_ diff --git a/src/model/model_element.cpp b/src/model/model_element.cpp index 8b6b7c1b..0ac6f827 100644 --- a/src/model/model_element.cpp +++ b/src/model/model_element.cpp @@ -25,7 +25,7 @@ namespace gologpp { string ModelElement::str() const { return to_string(""); } -void ModelElement::set_semantics(std::unique_ptr> &&impl) +void ModelElement::set_semantics(unique_ptr> &&impl) { semantics_ = std::move(impl); } diff --git a/src/model/model_element.h b/src/model/model_element.h index 2596c724..52413334 100644 --- a/src/model/model_element.h +++ b/src/model/model_element.h @@ -25,6 +25,10 @@ namespace gologpp { +template +static constexpr const bool is_copyable = false; + + class ModelElement { public: @@ -48,11 +52,11 @@ class ModelElement { /// @return The implementation-specific semantics of this model element. /// This method cannot be called (or even instantiated) from the code model context. It /// can only be instantiated and called from the semantics implementation. - template + template Semantics &semantics() const { return dynamic_cast &>(*semantics_); } - void set_semantics(std::unique_ptr> &&impl); + void set_semantics(unique_ptr> &&impl); virtual void attach_semantics(SemanticsFactory &) = 0; virtual string to_string(const string &pfx) const = 0; @@ -67,7 +71,7 @@ class ModelElement { { return dynamic_cast(*this); } protected: - std::unique_ptr> semantics_; + unique_ptr> semantics_; }; diff --git a/src/model/platform/component_backend.cpp b/src/model/platform/component_backend.cpp index 3eba1bf5..3003429c 100644 --- a/src/model/platform/component_backend.cpp +++ b/src/model/platform/component_backend.cpp @@ -20,6 +20,7 @@ #include #include "component_backend.h" +#include "switch_state_action.h" #include @@ -74,9 +75,8 @@ void ComponentBackend::exog_state_change(const shared_ptr &tgt) log(LogLevel::ERR) << "Component backend \"" << model().name() << "\" breached model by going from state \"" << model().current_state() << "\" to \"" << tgt->name() << "\"" << flush; - shared_ptr exog_state_change = exec_context_->switch_state_action(); - shared_ptr> evt { new gologpp::Reference { - exog_state_change, + shared_ptr evt { new SwitchStateEvent { + exec_context_->switch_state_action(), { new Value(get_type(), model_->name()), new Value(get_type(), model_->current_state()->name()), diff --git a/src/model/platform/component_backend.h b/src/model/platform/component_backend.h index 8ba8a01b..398cfadd 100644 --- a/src/model/platform/component_backend.h +++ b/src/model/platform/component_backend.h @@ -24,6 +24,7 @@ #include #include #include +#include namespace gologpp { diff --git a/src/model/platform/reference.h b/src/model/platform/reference.h index c1110fa9..69ccfe43 100644 --- a/src/model/platform/reference.h +++ b/src/model/platform/reference.h @@ -28,12 +28,12 @@ namespace platform { template<> class Reference -: public ReferenceBase +: public ReferenceBase , public ChildElement , public LanguageElement, VoidType> { public: - using ReferenceBase::ReferenceBase; + using ReferenceBase::ReferenceBase; virtual void attach_semantics(gologpp::SemanticsFactory &f) override; }; diff --git a/src/model/platform/switch_state_action.h b/src/model/platform/switch_state_action.h index 82d5ff7a..ded7582f 100644 --- a/src/model/platform/switch_state_action.h +++ b/src/model/platform/switch_state_action.h @@ -18,6 +18,7 @@ #pragma once #include +#include namespace gologpp { namespace platform { @@ -45,6 +46,18 @@ class SwitchStateAction }; +class SwitchStateEvent +: public Event +, public LanguageElement +, public Instruction +{ +public: + using Event::Event; + + DEFINE_ATTACH_SEMANTICS_WITH_MEMBERS(ground_action_) +}; + + } // namespace platform ///////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/model/procedural.cpp b/src/model/procedural.cpp index ff8d1a50..7440f81d 100644 --- a/src/model/procedural.cpp +++ b/src/model/procedural.cpp @@ -19,7 +19,6 @@ #include #include "procedural.h" -#include "formula.h" #include "reference.h" #include "expressions.h" @@ -571,138 +570,6 @@ string to_string(DurativeCall::Hook h) /***********************************************************************************************/ ///////////////////////////////////////////////////////////////////////////////////////////////// -FieldAccess::FieldAccess(Expression *subject, const string &field_name) -: subject_(subject) -, field_name_(field_name) -{ - subject_->set_parent(this); -} - -const Expression &FieldAccess::subject() const -{ return *subject_; } - -const string &FieldAccess::field_name() const -{ return field_name_; } - -const Type &FieldAccess::type() const -{ - return dynamic_cast( - subject_->type() - ).field_type(field_name_); -} - -string FieldAccess::to_string(const string &pfx) const -{ return pfx + subject().str() + "." + field_name(); } - -///////////////////////////////////////////////////////////////////////////////////////////////// -/***********************************************************************************************/ -///////////////////////////////////////////////////////////////////////////////////////////////// - -ListAccess::ListAccess(Expression *subject, Expression *index) -: subject_(subject) -, index_(index) -{ - subject_->set_parent(this); - index_->set_parent(this); -} - -const Expression &ListAccess::subject() const -{ return *subject_; } - -const Expression &ListAccess::index() const -{ return *index_; } - - -const Type &ListAccess::type() const -{ - return dynamic_cast( - subject_->type() - ).element_type(); -} - -string ListAccess::to_string(const string &pfx) const -{ return subject_->to_string(pfx) + '[' + index_->str() + ']'; } - -///////////////////////////////////////////////////////////////////////////////////////////////// -/***********************************************************************************************/ -///////////////////////////////////////////////////////////////////////////////////////////////// - -ListLength::ListLength(Expression *subject) -: subject_(subject) -{ subject_->set_parent(this); } - -const Expression &ListLength::subject() const -{ return *subject_; } - -string ListLength::to_string(const string &pfx) const -{ return "length(" + subject_->to_string(pfx) + ')'; } - - - -string to_string(ListOpEnd which_end) -{ - switch (which_end) { - case FRONT: - return "front"; - case BACK: - return "back"; - } - throw Bug(string("Unhandled ") + typeid(which_end).name()); -} - -///////////////////////////////////////////////////////////////////////////////////////////////// -/***********************************************************************************************/ -///////////////////////////////////////////////////////////////////////////////////////////////// - -ListPop::ListPop(Expression *list, ListOpEnd which_end) -: list_(list) -, which_end_(which_end) -{ list_->set_parent(this); } - -const Expression &ListPop::list() const -{ return *list_; } - -ListOpEnd ListPop::which_end() const -{ return which_end_; } - -string ListPop::to_string(const string &pfx) const -{ return pfx + "pop_" + gologpp::to_string(which_end_) + '(' + list_->str() + ')'; } - -///////////////////////////////////////////////////////////////////////////////////////////////// -/***********************************************************************************************/ -///////////////////////////////////////////////////////////////////////////////////////////////// - -ListPush::ListPush(Expression *list, ListOpEnd which_end, Expression *what) -: list_(list) -, which_end_(which_end) -{ - list_->set_parent(this); - - what->ensure_type( - dynamic_cast( - list_->type() - ).element_type() - ); - what_.reset(what); - what_->set_parent(this); -} - -const Expression &ListPush::list() const -{ return *list_; } - -ListOpEnd ListPush::which_end() const -{ return which_end_; } - -const Expression &ListPush::what() const -{ return *what_; } - -string ListPush::to_string(const string &pfx) const -{ return pfx + "push_" + gologpp::to_string(which_end_) + '(' + list_->str() + ')'; } - -///////////////////////////////////////////////////////////////////////////////////////////////// -/***********************************************************************************************/ -///////////////////////////////////////////////////////////////////////////////////////////////// - During::During( Reference *action_call, Instruction *parallel_block, @@ -753,7 +620,6 @@ string During::to_string(const string &pfx) const - } // namespace gologpp diff --git a/src/model/procedural.h b/src/model/procedural.h index 3e8ffcb2..0f2c68f3 100644 --- a/src/model/procedural.h +++ b/src/model/procedural.h @@ -35,8 +35,6 @@ #include "scope.h" #include "action.h" #include "reference.h" -#include "fluent.h" -#include "mapping.h" namespace gologpp { @@ -452,7 +450,7 @@ class GeneralSemantics> public: GeneralSemantics(const Reference &elem, AExecutionController &context); - virtual ~GeneralSemantics>() = default; + virtual ~GeneralSemantics() = default; virtual Value evaluate(const BindingChain &, const History &) override; @@ -503,133 +501,6 @@ string to_string(DurativeCall::Hook); /***********************************************************************************************/ ///////////////////////////////////////////////////////////////////////////////////////////////// -class FieldAccess -: public Expression -, public NoScopeOwner -, public LanguageElement -{ -public: - FieldAccess(Expression *subject, const string &field_name); - const Expression &subject() const; - const string &field_name() const; - - DEFINE_ATTACH_SEMANTICS_WITH_MEMBERS(*subject_) - - virtual const Type &type() const override; - - string to_string(const string &pfx) const override; - -private: - SafeExprOwner subject_; - const string field_name_; -}; - -///////////////////////////////////////////////////////////////////////////////////////////////// -/***********************************************************************************************/ -///////////////////////////////////////////////////////////////////////////////////////////////// - -class ListAccess -: public Expression -, public NoScopeOwner -, public LanguageElement -{ -public: - ListAccess(Expression *subject, Expression *index); - const Expression &subject() const; - const Expression &index() const; - - DEFINE_ATTACH_SEMANTICS_WITH_MEMBERS(*subject_, *index_) - - virtual const Type &type() const override; - - string to_string(const string &pfx) const override; - -private: - SafeExprOwner subject_; - SafeExprOwner index_; -}; - -///////////////////////////////////////////////////////////////////////////////////////////////// -/***********************************************************************************************/ -///////////////////////////////////////////////////////////////////////////////////////////////// - -class ListLength -: public Expression -, public NoScopeOwner -, public LanguageElement -{ -public: - ListLength(Expression *subject); - const Expression &subject() const; - - DEFINE_ATTACH_SEMANTICS_WITH_MEMBERS(*subject_) - - string to_string(const string &pfx) const override; - -private: - SafeExprOwner subject_; -}; - -///////////////////////////////////////////////////////////////////////////////////////////////// -/***********************************************************************************************/ -///////////////////////////////////////////////////////////////////////////////////////////////// - -enum ListOpEnd { - FRONT, BACK -}; - -///////////////////////////////////////////////////////////////////////////////////////////////// -/***********************************************************************************************/ -///////////////////////////////////////////////////////////////////////////////////////////////// - -class ListPop -: public Instruction -, public NoScopeOwner -, public LanguageElement -{ -public: - ListPop(Expression *list, ListOpEnd which_end); - const Expression &list() const; - ListOpEnd which_end() const; - - DEFINE_ATTACH_SEMANTICS_WITH_MEMBERS(*list_) - - string to_string(const string &pfx) const override; - -private: - SafeExprOwner list_; - ListOpEnd which_end_; -}; - -///////////////////////////////////////////////////////////////////////////////////////////////// -/***********************************************************************************************/ -///////////////////////////////////////////////////////////////////////////////////////////////// - -class ListPush -: public Instruction -, public NoScopeOwner -, public LanguageElement -{ -public: - ListPush(Expression *list, ListOpEnd which_end, Expression *what); - const Expression &list() const; - ListOpEnd which_end() const; - const Expression &what() const; - - DEFINE_ATTACH_SEMANTICS_WITH_MEMBERS(*list_, *what_) - - string to_string(const string &pfx) const override; - -private: - SafeExprOwner list_; - ListOpEnd which_end_; - unique_ptr what_; -}; - -///////////////////////////////////////////////////////////////////////////////////////////////// -/***********************************************************************************************/ -///////////////////////////////////////////////////////////////////////////////////////////////// - class During : public Instruction , public NoScopeOwner diff --git a/src/model/reference.cpp b/src/model/reference.cpp index 87d63ccf..3cdb0bc9 100644 --- a/src/model/reference.cpp +++ b/src/model/reference.cpp @@ -14,36 +14,39 @@ * You should have received a copy of the GNU General Public License * along with golog++. If not, see . **************************************************************************/ - #include "reference.h" +#include "value.h" #include namespace gologpp { - -Binding::Binding(const Binding &other) +template<> +Binding::Binding(const Binding &other) { for (auto &pair : other.var_bindings_) - var_bindings_.emplace(pair.first, dynamic_cast(*pair.second).copy()); + var_bindings_.emplace(pair.first, new Value(*pair.second)); if (other.semantics_) set_semantics(unique_ptr>( - other.general_semantics().copy(*this) + other.general_semantics>().copy(*this) ) ); } -Binding::Binding(Binding &&other) +template +Binding::Binding(Binding &&other) : var_bindings_(std::move(other.var_bindings_)) { if (other.semantics_) throw Bug("Cannot move a Binding after semantics have been assigned"); } -void Binding::bind(shared_ptr var, unique_ptr &&expr) +template +void Binding::bind(shared_ptr var, unique_ptr &&expr) { var_bindings_.insert(std::make_pair(var, std::move(expr))); } -Expression &Binding::get(shared_ptr param) const +template +ExprT &Binding::get(shared_ptr param) const { auto it = var_bindings_.find(param); if (it == var_bindings_.end()) @@ -51,11 +54,13 @@ Expression &Binding::get(shared_ptr param) const return *it->second; } -const Binding::MapT &Binding::map() const +template +const typename Binding::MapT &Binding::map() const { return var_bindings_; } -void Binding::attach_semantics(SemanticsFactory &f) +template +void Binding::attach_semantics(SemanticsFactory &f) { if (!semantics_) { set_semantics(f.make_semantics(*this)); @@ -65,7 +70,8 @@ void Binding::attach_semantics(SemanticsFactory &f) } -string Binding::to_string(const string &pfx) const +template +string Binding::to_string(const string &pfx) const { string rv; for (auto &entry : var_bindings_) @@ -75,25 +81,49 @@ string Binding::to_string(const string &pfx) const return rv; } + +template +class Binding; + +template +class Binding; + ///////////////////////////////////////////////////////////////////////////////////////////////// /***********************************************************************************************/ ///////////////////////////////////////////////////////////////////////////////////////////////// -GeneralSemantics::GeneralSemantics(const Binding &elem, AExecutionController &context) +template +GeneralSemantics>::GeneralSemantics(const Binding &elem, AExecutionController &context) : element_(&elem) , context_(context) {} -const Binding &GeneralSemantics::element() const +template +const Binding &GeneralSemantics>::element() const { return *element_; } -void GeneralSemantics::update_element(const Binding *new_element) +template +void GeneralSemantics>::update_element(const Binding *new_element) { element_ = new_element; } -AExecutionController &GeneralSemantics::context() const +template +AExecutionController &GeneralSemantics>::context() const { return context_; } +template +const ModelElement &GeneralSemantics>::model_element() const +{ return *element_; } + +template +class GeneralSemantics>; + +template +class GeneralSemantics>; + +///////////////////////////////////////////////////////////////////////////////////////////////// +/***********************************************************************************************/ +///////////////////////////////////////////////////////////////////////////////////////////////// void Reference::attach_semantics(SemanticsFactory &implementor) { diff --git a/src/model/reference.h b/src/model/reference.h index 814ab926..ded6b548 100644 --- a/src/model/reference.h +++ b/src/model/reference.h @@ -15,18 +15,17 @@ * along with golog++. If not, see . **************************************************************************/ -#ifndef GOLOGPP_REFERENCE_H_ -#define GOLOGPP_REFERENCE_H_ +#pragma once #include "abstract_reference.h" #include "language.h" #include "expressions.h" +#include "value.h" #include "utilities.h" #include "gologpp.h" #include "scope.h" #include "error.h" #include "variable.h" -#include "domain.h" #include #include @@ -37,21 +36,34 @@ namespace gologpp { -class Binding : public ModelElement { +class ABinding : public ModelElement { +public: + void bind(shared_ptr var, unique_ptr &&value); + virtual Expression &get(shared_ptr param) const = 0; +}; + + +template +class Binding : public ABinding { public: using MapT = std::unordered_map < shared_ptr, - unique_ptr + unique_ptr >; - Binding(const Binding &); - Binding(Binding &&); + Binding(const Binding &); + Binding(Binding &&); + + // Allow cross-conversion between Binding and Binding + template + Binding(const Binding &, enable_if::value> * = 0); + Binding() = default; virtual ~Binding() = default; - void bind(shared_ptr var, unique_ptr &&expr); - virtual Expression &get(shared_ptr param) const; + void bind(shared_ptr var, unique_ptr &&expr); + virtual ExprT &get(shared_ptr param) const override; const MapT &map() const; virtual void attach_semantics(SemanticsFactory &f) override; @@ -65,51 +77,64 @@ class Binding : public ModelElement { /***********************************************************************************************/ ///////////////////////////////////////////////////////////////////////////////////////////////// -template<> -class GeneralSemantics +/// Disambiguate this against the generic GeneralSemantics, which +/// is also a partial specialization but is disabled if this is true. +template +bool partially_specialized>> = true; + + +template +class GeneralSemantics> : public virtual GeneralSemantics { public: - GeneralSemantics(const Binding &elem, AExecutionController &context); + GeneralSemantics(const Binding &elem, AExecutionController &context); - virtual ~GeneralSemantics() = default; + virtual ~GeneralSemantics() = default; - const Binding &element() const; - void update_element(const Binding *new_element); + const Binding &element() const; + void update_element(const Binding *new_element); virtual AExecutionController &context() const override; + virtual const ModelElement &model_element() const override; - virtual GeneralSemantics *copy(const Binding &target_element) const = 0; + virtual GeneralSemantics> *copy(const Binding &target_element) const = 0; private: - const Binding *element_; + const Binding *element_; AExecutionController &context_; }; + +class BindingChain : public vector { +public: + using vector::vector; +}; + ///////////////////////////////////////////////////////////////////////////////////////////////// /***********************************************************************************************/ ///////////////////////////////////////////////////////////////////////////////////////////////// -template +template class ReferenceBase : public virtual AbstractReference , public NoScopeOwner { public: - ReferenceBase(const shared_ptr &target, vector> &&args) + ReferenceBase(const shared_ptr &target, vector> &&args) : target_(target) { size_t idx = 0; while (idx < args.size() && idx < this->target()->params().size()) { - unique_ptr arg { std::move(args[idx]) }; + unique_ptr arg { std::move(args[idx]) }; arg->set_parent(this); - args_.emplace_back(arg.get()); binding_.bind(this->target()->params()[idx], std::move(arg)); + args_.emplace_back(&binding_.get(this->target()->params()[idx])); ++idx; } ensure_consistent(); } - ReferenceBase(const shared_ptr &target, Binding &&binding) + ReferenceBase(const shared_ptr &target, Binding &&binding) : target_(target) , binding_(std::move(binding)) { @@ -118,30 +143,31 @@ class ReferenceBase ensure_consistent(); } - ReferenceBase(const shared_ptr &target, const vector &args) - : ReferenceBase(target, vector>(args.begin(), args.end())) + ReferenceBase(const shared_ptr &target, const vector &args) + : ReferenceBase(target, vector>(args.begin(), args.end())) {} - ReferenceBase(const string &target_name, const vector &args) + ReferenceBase(const string &target_name, const vector &args) : ReferenceBase( global_scope().lookup_global(target_name), args ) {} - ReferenceBase(const string &target_name, const boost::optional> &args) + + ReferenceBase(const string &target_name, const boost::optional> &args) : ReferenceBase(target_name, args.get_value_or({})) {} - ReferenceBase(ReferenceBase &&other) + ReferenceBase(ReferenceBase &&other) : args_(std::move(other.args_)) , target_(std::move(other.target_)) , binding_(std::move(other.binding_)) { ensure_consistent(); } - ReferenceBase(const ReferenceBase &other) + ReferenceBase(const ReferenceBase &other) : args_(copy(other.args_)) , target_(other.target_) , binding_(other.binding_) @@ -163,7 +189,7 @@ class ReferenceBase { return this->target().get(); } - bool operator == (const ReferenceBase &other) const + bool operator == (const ReferenceBase &other) const { if (this->target() != other.target()) return false; @@ -174,7 +200,7 @@ class ReferenceBase return true; } - bool operator != (const ReferenceBase &other) const + bool operator != (const ReferenceBase &other) const { return !(*this == other); } const string &name() const @@ -189,13 +215,13 @@ class ReferenceBase virtual bool bound() const override { return !target_.expired(); } - const vector &args() const + const vector &args() const { return args_; } - vector &args() + vector &args() { return args_; } - virtual const Expression &arg_for_param(shared_ptr param) const override + virtual const ArgsT &arg_for_param(shared_ptr param) const override { return binding_.get(param); } virtual bool consistent() const override @@ -242,21 +268,21 @@ class ReferenceBase return rv; } - virtual Binding &binding() + virtual Binding &binding() { return binding_; } - virtual const Binding &binding() const + virtual const Binding &binding() const { return binding_; } protected: - vector args_; + vector args_; weak_ptr target_; - Binding binding_; + Binding binding_; }; -template<> -class Reference +template +class Reference : public virtual AbstractReference { public: @@ -271,22 +297,30 @@ class Reference ///////////////////////////////////////////////////////////////////////////////////////////////// template +static constexpr const bool is_copyable> = true; + +template class Reference -: public ReferenceBase -, public LanguageElement> +: public ReferenceBase +, public LanguageElement> , public TargetT::SignifierT , public virtual std::conditional < std::is_base_of::value, - Reference, + Reference, AbstractReference >::type { public: - using ReferenceBase::ReferenceBase; + using ReferenceBase::ReferenceBase; - Reference(const Reference &other) - : ReferenceBase(other) - {} + explicit Reference(const Reference &other) + : ReferenceBase(other) + { + if (other.semantics_) + this->semantics_.reset( + other.template general_semantics>().copy(*this) + ); + } virtual ~Reference() override = default; @@ -312,21 +346,18 @@ class Reference } } - unique_ptr> ground_args(const Binding &b, const History &h) const - { - Binding gb; - for (auto &pair : this->binding().map()) - gb.bind( - pair.first, - unique_ptr(new Value( - std::move(pair.second->general_semantics().evaluate(b, h)) - )) - ); - return unique_ptr>(new Reference(this->target(), std::move(gb))); - } - }; + +/*template +static constexpr bool partially_specialized>> = true; + +template +class GeneralSemantics> +: public GeneralSemantics +{ +};*/ + ///////////////////////////////////////////////////////////////////////////////////////////////// /***********************************************************************************************/ ///////////////////////////////////////////////////////////////////////////////////////////////// @@ -526,4 +557,4 @@ struct equal_to *> { } -#endif // GOLOGPP_REFERENCE_H_ + diff --git a/src/model/semantics.h b/src/model/semantics.h index c5ab1eab..1cd76d97 100644 --- a/src/model/semantics.h +++ b/src/model/semantics.h @@ -23,18 +23,144 @@ #include "expressions.h" #include +#include #include namespace gologpp { +/** + * @brief Partially specialize this to true for certain templated GologTs (i.e. Reference, EffectAxiom...) + * if you have generic definitions for Semantics, but also want to supply certain + * partial specializations. + * Use it as a condition in the enable_if that gives Cond to prevent the ambiguous partial specialization + * errors that would otherwise occur. + */ +template +static constexpr bool partially_specialized = false; + +template +static constexpr bool is_instruction = std::is_base_of::value; + +template +static constexpr bool is_expression = std::is_base_of::value; + + ///////////////////////////////////////////////////////////////////////////////////////////////// /***********************************************************************************************/ ///////////////////////////////////////////////////////////////////////////////////////////////// + +template +class CopyableSemantics +{ +public: + virtual GeneralSemantics *copy(const GologT &target_element) const = 0; +}; + + +template +class NonCopyableSemantics +{}; + + + +template +class GeneralSemantics>> +: public virtual GeneralSemantics +, public std::conditional< + is_copyable, + CopyableSemantics, + NonCopyableSemantics + >::type +{ +public: + GeneralSemantics(const GologT &elem, AExecutionController &context) + : element_(&elem) + , context_(context) + {} + + virtual ~GeneralSemantics() = default; + + /// @return A reference to the concrete language element (code model element) covered by this + /// semantics instance + template + const GologT &element() const + { return *element_; } + + virtual AExecutionController &context() const override + { return context_; } + + void update_element(const GologT *new_element) + { element_ = new_element; } + + virtual const ModelElement &model_element() const override + { return *element_; } + + virtual const Instruction &instruction() const override + { return *element_; } + +private: + const GologT *element_; + AExecutionController &context_; +}; + + + +template +class GeneralSemantics>> +: public virtual GeneralSemantics +, public std::conditional< + is_copyable, + CopyableSemantics, + NonCopyableSemantics + >::type +{ +public: + GeneralSemantics(const GologT &elem, AExecutionController &context) + : element_(&elem) + , context_(context) + {} + + virtual ~GeneralSemantics() = default; + + /// @return A reference to the concrete language element (code model element) covered by this + /// semantics instance + template + const GologT &element() const + { return *element_; } + + virtual AExecutionController &context() const override + { return context_; } + + void update_element(const GologT *new_element) + { element_ = new_element; } + + virtual const ModelElement &model_element() const override + { return *element_; } + + virtual const Expression &expression() const override + { return *element_; } + +private: + const GologT *element_; + AExecutionController &context_; +}; + + + template -class GeneralSemantics +class GeneralSemantics + && !is_instruction + && !partially_specialized> +> > : public virtual GeneralSemantics +, public std::conditional< + is_copyable, + CopyableSemantics, + NonCopyableSemantics + >::type { public: GeneralSemantics(const GologT &elem, AExecutionController &context) @@ -42,7 +168,7 @@ class GeneralSemantics , context_(context) {} - virtual ~GeneralSemantics() = default; + virtual ~GeneralSemantics() = default; /// @return A reference to the concrete language element (code model element) covered by this /// semantics instance @@ -68,6 +194,7 @@ class GeneralSemantics /***********************************************************************************************/ ///////////////////////////////////////////////////////////////////////////////////////////////// +/// declare pure virtual make_semantics(...) #define GOLOGPP_DECLARE_ABSTRACT_MAKE_SEMANTICS(r, data, T) \ virtual unique_ptr> make_semantics(T &) = 0; diff --git a/src/model/types.cpp b/src/model/types.cpp index 1fed7404..40a396ac 100644 --- a/src/model/types.cpp +++ b/src/model/types.cpp @@ -18,7 +18,7 @@ #include "types.h" #include "scope.h" #include "domain.h" -#include "list_expression.h" +#include "list.h" #include "logger.h" namespace gologpp { diff --git a/src/model/utilities.cpp b/src/model/utilities.cpp index 1ac114af..281b881e 100644 --- a/src/model/utilities.cpp +++ b/src/model/utilities.cpp @@ -16,8 +16,6 @@ **************************************************************************/ #include "utilities.h" -#include "logger.h" -#include "value.h" namespace gologpp { @@ -42,23 +40,6 @@ string Identifier::signature_str() const { return name() + "/" + std::to_string(arity()); } -vector> copy(const vector> &v) -{ - vector> rv; - for (const unique_ptr &e : v) - rv.emplace_back(dynamic_cast(*e).copy()); - return rv; -} - - -vector copy(const vector &v) -{ - vector rv; - for (const Expression *e : v) - rv.emplace_back(dynamic_cast(*e).copy()); - return rv; -} - #ifdef DEBUG_PARSER const string indent(""); diff --git a/src/model/utilities.h b/src/model/utilities.h index 3a57ec38..fd32ab72 100644 --- a/src/model/utilities.h +++ b/src/model/utilities.h @@ -72,8 +72,17 @@ struct identifier_equals { }; -vector> copy(const vector> &v); -vector copy(const vector &v); +template +vector copy(const vector &v) +{ + vector rv; + for (const EPtrT &e : v) + rv.emplace_back( + new typename std::remove_pointer::type(*e) + ); + return rv; +} + template @@ -186,12 +195,20 @@ string to_string(const T *o, const string &pfx) template typename std::enable_if < - ! std::is_pointer::is_pointer, + ! std::is_pointer::is_pointer && std::is_base_of::value, string >::type to_string(const T &o, const string &pfx) { return o.to_string(pfx); } +template +typename std::enable_if < + ! std::is_pointer::value && !std::is_base_of::value, + string +>::type +to_string(const T &o, const string &pfx) +{ return pfx + std::string(o); } + template diff --git a/src/model/value.cpp b/src/model/value.cpp index d683c6a5..d29917f4 100644 --- a/src/model/value.cpp +++ b/src/model/value.cpp @@ -25,11 +25,11 @@ namespace gologpp { unique_ptr::unique_ptr(const unique_ptr &c) -: std::unique_ptr(c->copy()) +: std::unique_ptr(new Value(*c)) {} gologpp::unique_ptr::unique_ptr(const Value &v) -: std::unique_ptr(v.copy()) +: std::unique_ptr(new Value(v)) {} unique_ptr &unique_ptr::operator = (const unique_ptr &c) @@ -248,9 +248,6 @@ size_t Value::hash() const string Value::to_string(const string &pfx) const { return boost::apply_visitor(to_string_visitor { pfx, !(get_type() >= *this) }, representation_); } -Value *Value::copy() const -{ return new Value(*this); } - bool Value::operator == (const Expression &e) const { diff --git a/src/model/value.h b/src/model/value.h index cfd0a219..2b75b32a 100644 --- a/src/model/value.h +++ b/src/model/value.h @@ -157,8 +157,6 @@ class Value Value operator % (const Value &) const; Value pow(const Value &) const; - virtual Value *copy() const; - virtual void attach_semantics(SemanticsFactory &f) override; static Value undefined(); @@ -208,7 +206,7 @@ class GeneralSemantics public: GeneralSemantics(const Value &elem, AExecutionController &context); - virtual ~GeneralSemantics() = default; + virtual ~GeneralSemantics() = default; virtual AExecutionController &context() const override; diff --git a/src/model/variable.h b/src/model/variable.h index 1d155e87..5f9aee7c 100644 --- a/src/model/variable.h +++ b/src/model/variable.h @@ -23,7 +23,6 @@ #include "utilities.h" #include "expressions.h" #include "scope.h" -#include "domain.h" #include "semantics.h" #include diff --git a/src/parser/action.cpp b/src/parser/action.cpp index 66ea99a7..88e38dee 100644 --- a/src/parser/action.cpp +++ b/src/parser/action.cpp @@ -40,6 +40,8 @@ #include #include +#include +#include #include diff --git a/src/parser/arithmetic.cpp b/src/parser/arithmetic.cpp index a7de3a68..4270cf8f 100644 --- a/src/parser/arithmetic.cpp +++ b/src/parser/arithmetic.cpp @@ -18,7 +18,7 @@ #include "arithmetic.h" #include "variable.h" #include "value.h" -#include "list_expression.h" +#include "list.h" #include "mixed_member_access.h" #include "expressions.h" #include "reference.h" diff --git a/src/parser/assignment.cpp b/src/parser/assignment.cpp index 986217f1..94650e9a 100644 --- a/src/parser/assignment.cpp +++ b/src/parser/assignment.cpp @@ -16,12 +16,14 @@ **************************************************************************/ #include "assignment.h" -#include "arithmetic.h" -#include "formula.h" #include "types.h" #include "expressions.h" #include "mixed_member_access.h" +#include +#include +#include + #include #include #include diff --git a/src/parser/assignment.h b/src/parser/assignment.h index 0bca6b97..127c42dd 100644 --- a/src/parser/assignment.h +++ b/src/parser/assignment.h @@ -19,6 +19,7 @@ #define GOLOGPP_PARSER_ASSIGNMENT_H_ #include +#include #include #include "utilities.h" diff --git a/src/parser/compound_expression.cpp b/src/parser/compound.cpp similarity index 97% rename from src/parser/compound_expression.cpp rename to src/parser/compound.cpp index 5edd71ec..cbbeca93 100644 --- a/src/parser/compound_expression.cpp +++ b/src/parser/compound.cpp @@ -15,7 +15,7 @@ * along with golog++. If not, see . **************************************************************************/ -#include "compound_expression.h" +#include "compound.h" #include "mixed_member_access.h" #include "value.h" #include "variable.h" @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include diff --git a/src/parser/compound_expression.h b/src/parser/compound.h similarity index 100% rename from src/parser/compound_expression.h rename to src/parser/compound.h diff --git a/src/parser/effect_axiom.cpp b/src/parser/effect_axiom.cpp index 7d61b587..6dced24c 100644 --- a/src/parser/effect_axiom.cpp +++ b/src/parser/effect_axiom.cpp @@ -34,6 +34,9 @@ #include #include +#include +#include +#include #include "reference.h" #include "mixed_member_access.h" diff --git a/src/parser/expressions.cpp b/src/parser/expressions.cpp index 32037619..566012c0 100644 --- a/src/parser/expressions.cpp +++ b/src/parser/expressions.cpp @@ -24,6 +24,10 @@ #include #include #include + +// This ends up including deprecated /usr/include/boost/spirit/include/phoenix.hpp, +// So we're silencing the warning until boost is fixed. +#define BOOST_ALLOW_DEPRECATED_HEADERS #include #include @@ -37,13 +41,13 @@ #include #include "types.h" +#include "domain.h" #include "arithmetic.h" #include "formula.h" #include "string_expression.h" #include "symbolic_expression.h" -#include "compound_expression.h" -#include "list_expression.h" -#include "mixed_member_access.h" +#include "compound.h" +#include "list.h" #include diff --git a/src/parser/fluent.cpp b/src/parser/fluent.cpp index 04e35aae..60bc6a68 100644 --- a/src/parser/fluent.cpp +++ b/src/parser/fluent.cpp @@ -17,7 +17,6 @@ #include "fluent.h" #include "types.h" -#include "domain.h" #include "variable.h" #include "value.h" diff --git a/src/parser/fluent.h b/src/parser/fluent.h index c9c0f34d..7ee04508 100644 --- a/src/parser/fluent.h +++ b/src/parser/fluent.h @@ -19,7 +19,6 @@ #define GOLOGPP_PARSER_FLUENT_H_ #include "utilities.h" -#include "domain.h" namespace gologpp { namespace parser { diff --git a/src/parser/list_expression.cpp b/src/parser/list.cpp similarity index 97% rename from src/parser/list_expression.cpp rename to src/parser/list.cpp index d346dbfa..a4415cbc 100644 --- a/src/parser/list_expression.cpp +++ b/src/parser/list.cpp @@ -16,7 +16,7 @@ **************************************************************************/ #include "types.h" -#include "list_expression.h" +#include "list.h" #include "variable.h" #include "value.h" #include "reference.h" @@ -24,7 +24,8 @@ #include "expressions.h" #include -#include +#include +#include #include #include diff --git a/src/parser/list_expression.h b/src/parser/list.h similarity index 98% rename from src/parser/list_expression.h rename to src/parser/list.h index 68c096ba..40137582 100644 --- a/src/parser/list_expression.h +++ b/src/parser/list.h @@ -19,6 +19,7 @@ #define GOLOGPP_PARSER_LIST_EXPRESSION_H_ #include "utilities.h" +#include namespace gologpp { namespace parser { diff --git a/src/parser/mixed_member_access.cpp b/src/parser/mixed_member_access.cpp index 5a866a27..34dfc8f0 100644 --- a/src/parser/mixed_member_access.cpp +++ b/src/parser/mixed_member_access.cpp @@ -17,9 +17,9 @@ #include "mixed_member_access.h" #include "types.h" -#include "compound_expression.h" +#include "compound.h" #include "expressions.h" -#include "list_expression.h" +#include "list.h" #include #include @@ -37,7 +37,8 @@ #include #include -#include +#include +#include namespace gologpp { diff --git a/src/parser/platform/reference.cpp b/src/parser/platform/reference.cpp index aaa8c5ac..502399e1 100644 --- a/src/parser/platform/reference.cpp +++ b/src/parser/platform/reference.cpp @@ -117,7 +117,7 @@ PlatformRefParser::PlatformRefParser() > ")" ) [ _val = phoenix::bind(&get_platform_global_ref, _r2, _1, _2), - if_(!_val || !phoenix::bind(&ReferenceBase::consistent, *_val)) [ + if_(!_val || !phoenix::bind(&ReferenceBase::consistent, *_val)) [ _pass = false, delete_(_val) ] diff --git a/src/parser/reference.cpp b/src/parser/reference.cpp index 4efab203..39a189c5 100644 --- a/src/parser/reference.cpp +++ b/src/parser/reference.cpp @@ -33,11 +33,16 @@ #include #include #include -#include #include #include #include +// This ends up including deprecated /usr/include/boost/spirit/include/phoenix.hpp, +// So we're silencing the warning until boost is fixed. +#define BOOST_ALLOW_DEPRECATED_HEADERS +#include + + #include #include #include @@ -89,7 +94,7 @@ ReferenceParser::ReferenceParser() > ")" ) [ _val = phoenix::bind(&get_ref, _r2, _1, _2), - if_(!_val || !phoenix::bind(&ReferenceBase::consistent, *_val)) [ + if_(!_val || !phoenix::bind(&ReferenceBase::consistent, *_val)) [ _pass = false, delete_(_val) ] diff --git a/src/parser/statements.h b/src/parser/statements.h index 603b3285..1f437598 100644 --- a/src/parser/statements.h +++ b/src/parser/statements.h @@ -23,6 +23,9 @@ #include "assignment.h" #include "formula.h" #include "arithmetic.h" +#include "list.h" + +#include namespace gologpp { diff --git a/src/parser/value.cpp b/src/parser/value.cpp index ba6a8ffb..e779545c 100644 --- a/src/parser/value.cpp +++ b/src/parser/value.cpp @@ -50,6 +50,7 @@ #include #include #include +#include #include #include diff --git a/src/semantics/native/action.cpp b/src/semantics/native/action.cpp new file mode 100644 index 00000000..c1d8c08a --- /dev/null +++ b/src/semantics/native/action.cpp @@ -0,0 +1,35 @@ +/************************************************************************* + * This file is part of golog++. + * + * golog++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * golog++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with golog++. If not, see . +**************************************************************************/ + +#include +#include + +#include "action.h" +#include "effect_axiom.h" +#include "scope.h" +#include "execution.h" +#include "variable.h" +#include "value.h" + +#include + +namespace gologpp { + + + + +} // namespace gologpp diff --git a/src/semantics/native/action.h b/src/semantics/native/action.h new file mode 100644 index 00000000..51a8eb22 --- /dev/null +++ b/src/semantics/native/action.h @@ -0,0 +1,38 @@ +/************************************************************************* + * This file is part of golog++. + * + * golog++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * golog++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with golog++. If not, see . +**************************************************************************/ + +#ifndef READYLOG_ACTION_H_ +#define READYLOG_ACTION_H_ + +#include "semantics.h" +#include "reference.h" + +#include +#include +#include + +namespace gologpp { + +class Action; + + + + +} // namespace gologpp + + +#endif diff --git a/src/semantics/native/arithmetic.cpp b/src/semantics/native/arithmetic.cpp new file mode 100644 index 00000000..14ec0ccb --- /dev/null +++ b/src/semantics/native/arithmetic.cpp @@ -0,0 +1,40 @@ +/************************************************************************* + * This file is part of golog++. + * + * golog++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * golog++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with golog++. If not, see . +**************************************************************************/ + +#include +#include + +#include "arithmetic.h" +#include "semantics.h" + +namespace gologpp { + + +template<> +Value Semantics::evaluate(const BindingChain &b, const History &h) +{ + switch (element().op()) { + case ArithmeticOperation::Operator::POWER: + return element().lhs().semantics().evaluate(b, h).pow( + element().lhs().semantics().evaluate(b, h) + ); + } +} + + + +} diff --git a/src/semantics/native/arithmetic.h b/src/semantics/native/arithmetic.h new file mode 100644 index 00000000..1714caee --- /dev/null +++ b/src/semantics/native/arithmetic.h @@ -0,0 +1,30 @@ +/************************************************************************* + * This file is part of golog++. + * + * golog++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * golog++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with golog++. If not, see . +**************************************************************************/ + +#ifndef READYLOG_ARITHMETIC_H_ +#define READYLOG_ARITHMETIC_H_ + +#include +#include "semantics.h" + +namespace gologpp { + + + +} + +#endif // READYLOG_ARITHMETIC_H_ diff --git a/src/semantics/native/boilerplate.pl b/src/semantics/native/boilerplate.pl new file mode 100644 index 00000000..b25b35f2 --- /dev/null +++ b/src/semantics/native/boilerplate.pl @@ -0,0 +1,337 @@ +:- external(exog_fluent_getValue/3, p_exog_fluent_getValue). +:- dynamic managed_term/2. +:- dynamic durative_action/1, durative_poss/2, durative_causes_val/4. +:- lib(listut). + +% resolve name clash with lib(listut) +:- import delete/3 from eclipse_language. + +should_progress(H) :- length(H, L), L >= 10. + +% execute/3 is useless in golog++. Just ignore it and log a message +execute(Action, _Sr, _H) :- printf("Dummy execute %W%n", [Action]). + +function(strcat(X, Y), R, concat_atoms(X, Y, R)). +function(to_string(V), R, + and(sprintf(S, "%w", V), atom_string(R, S)) +). + + +function(gpp_field_value(Name, Compound), Value, + once(pl_field_value(Name, Compound, Value)) +). +pl_field_value(Name, Compound, Value) :- + ( + atom(Name), var(Value) + , Compound = gpp_compound(_Type, Fields) + , Field_term =.. [Name, Value] + , member(Field_term, Fields) + ; + sprintf(Msg, "Invalid function call: %W", [gpp_field_value(Name, Compound)]) + , throw(Msg) + ) +. + + +function(gpp_mixed_assign(Members, Value, Lhs), Result, + once(pl_mixed_assign(Members, Value, Lhs, Result)) +). +pl_mixed_assign(Members, Value, Lhs, Result) :- + Members = [M|Rest_mems] + , (number(M) -> + % List access + ( Lhs = gpp_list(Type, List), length(List, _) + ; sprintf(Msg, "gpp_mixed_assign: Invalid argument %W", [gpp_mixed_assign(Members, Value, Lhs)]) + , throw(Msg) + ) + , ( nth0(M, List, Mem_current, List_without) + ; sprintf(Msg, "Accessing %W: Index %W is out of bounds", [List, M]) + , throw(Msg) + ) + , ( length(Rest_mems) > 0 -> + % Additional nesting levels: recurse down + pl_mixed_assign(Rest_mems, Value, Mem_current, Val_new) + ; + Val_new = Value + ) + , nth0(M, List_new, Val_new, List_without) + , Result = gpp_list(Type, List_new) + + ; atom(M) -> + % Compound field access + ( Lhs = gpp_compound(Type, Fields), length(Fields, _) + ; sprintf(Msg, "gpp_mixed_assign: Invalid argument %W", [gpp_mixed_assign(Members, Value, Lhs)]) + , throw(Msg) + ) + , Field_acc =.. [M, Field_cur_value] + , delete(Field_acc, Fields, Fields_without) + , ( length(Rest_mems) > 0 -> + % Additional nesting levels: recurse down + pl_mixed_assign(Rest_mems, Value, Field_cur_value, Val_new) + , Field_new =.. [M, Val_new] + ; + Field_new =.. [M, Value] + ) + , Result = gpp_compound(Type, [Field_new | Fields_without]) + ; + sprintf(Msg, "gpp_mixed_assign: %W is not a list index or a field name", [M]) + , throw(Msg) + ) +. + +function(gpp_list_access(Lhs, Idx), Result, + once(pl_list_access(Lhs, Idx, Result)) +). +pl_list_access(Lhs, Idx, Result) :- + ( + Lhs = gpp_list(_Type, List) + , length(List, _) + , number(Idx) + ; + sprintf(Msg, "Invalid function call: %W", [pl_list_access(Lhs, Idx, Result)]) + , throw(Msg) + ) + , nth0(Idx, List, Result) +. + +function(gpp_list_length(Lhs), Result, + once(pl_list_length(Lhs, Result)) +). +pl_list_length(Lhs, Result) :- + ( + Lhs = gpp_list(_Type, List) + , length(List, Result) + ; + sprintf(Msg, "Invalid function call: %W", [pl_list_length(Lhs, Result)]) + , throw(Msg) + ) +. + +function(gpp_list_pop_front(Lhs), Result, + once(pl_list_pop_front(Lhs, Result)) +). +pl_list_pop_front(Lhs, Result) :- + ( + Lhs = gpp_list(Type, List) + , length(List, _) + ; throw("gpp_list_pop_front: Arg must be a list") + ) + , List_new = [_ | Result] + , Result = gpp_list(Type, List_new) +. + +function(gpp_list_pop_back(Lhs), Result, + once(pl_list_pop_back(Lhs, Result)) +). +pl_list_pop_back(Lhs, Result) :- + ( + Lhs = gpp_list(Type, List) + , length(List, _) + ; throw("gpp_list_pop_back: Arg must be a list") + ) + , length(List, Len) + , nth1(Len, List, _, List_new) + , Result = gpp_list(Type, List_new) +. + +function(gpp_list_push_front(Lhs, Elem), Result, + once(pl_list_push_front(Lhs, Elem, Result)) +). +pl_list_push_front(Lhs, Elem, Result) :- + ( + Lhs = gpp_list(Type, List) + , length(List, _) + ; throw("gpp_list_push_front: First arg must be a list") + ) + , ( number(Elem) + ; throw("gpp_list_push_front: Second arg must be instantiated") + ) + , Result = gpp_list(Type, [Elem | List]) +. + +function(gpp_list_push_back(Lhs, Elem), Result, + once(pl_list_push_back(Lhs, Elem, Result)) +). +pl_list_push_back(Lhs, Elem, Result) :- + ( + Lhs = gpp_list(Type, List) + , length(List, _) + ; throw("gpp_list_push_back: First arg must be a list") + ) + , ( number(Elem) + ; throw("gpp_list_push_back: Second arg must be instantiated") + ) + , append(List, [Elem], List_new) + , Result = gpp_list(Type, List_new) +. + + +/******************************** + * Durative Action semantics + * ******************************/ + +exog_prim_fluent(now). + +prim_fluent(state(A)) :- durative_action(A). +initial_val(state(A), idle) :- durative_action(A). +reserved_fluent(state(_A)). + +exog_action(exog_state_change(A, _T, State)) :- durative_action(A). +poss(exog_state_change(A, _T, State), true) :- durative_action(A). +causes_val(exog_state_change(A, _T, State), state(A), State, true) :- durative_action(A). + + +% start action +% ============ +prim_action(start(A, _T)) :- durative_action(A). + +% Precondition only applies to starting a durative action +poss(start(A, T), + and([ + not(state(A) = running) + , now >= T + , C + ]) +) :- + durative_action(A) + , durative_poss(A, C) +. +causes_val(start(A, _T), state(A), running, true) :- durative_action(A). + + +% finish action +% ============ +prim_action(finish(A, _T)) :- durative_action(A). +poss(finish(A, T), + and( + lif(online = true + % Online: Wait for real action to complete + , state(A) = final + % Offline: Final immediately + , true + ) + , now >= T + ) +) :- durative_action(A). +causes_val(finish(A, _T), state(A), final, true) :- durative_action(A). + +% Only the finish action applies a durative action's effects: +causes_val(finish(A, T), F, V, C) :- durative_causes_val(A, F, V, C). + + +% end action +% ========== +prim_action(end(A, _T)) :- durative_action(A). +poss(end(A, T), + and( + lif(online + % Online: Wait for real action to complete + , or( [ + state(A) = final + , state(A) = failed + , state(A) = cancelled + ] ) + % Offline: Final immediately + , true + ) + , now >= T + ) +) :- durative_action(A). + +% ONLY During planning end(A) puts A in the final state. +% Online this happens exogenously. +causes_val(end(A, _T), state(A), final, not(online)) :- durative_action(A). + +% Offline: Just apply effect & disregard state because state is changed +% by another effect. +% Online: Apply effect only if state is final +causes_val( + end(A, _T) + , F, V + , lif(online + , and(state(A) = final, C) + , C + ) +) :- + durative_causes_val(A, F, V, C) +. + + +% stop action +% =========== +prim_action(stop(A, _T)) :- durative_action(A). +poss(stop(A, T), + and( + lif(online = true + , state(A) = running + , true + ) + , now >= T + ) +) :- durative_action(A). +causes_val(stop(A, _T), state(A), cancelled, true) :- durative_action(A). + + +% fail action +% ============= +prim_action(fail(A, _T)) :- durative_action(A). +poss(fail(A, T), + and([ + online = true + , state(A) = failed + , now >= T + ]) +) :- durative_action(A). +causes_val(fail(A, _T), state(A), failed, true) :- durative_action(A). + + + +/********************************/ + + +ssa( online, false, [clipOnline|_69485] ) :- !, true. +ssa( online, true, [setOnline|_69524] ) :- !, true. +ssa( sit_start_time, T, [setTime(T)|_69563] ) :- !, true. +ssa( sit_start_time, T, [ccUpdate(_69409, T)|_69585] ) :- !, true. +ssa( Fluent, Value, [set(Fluent, Value)|_69607] ) :- !, true. + +ssa( eval_exog_functions, _69895, [set(eval_exog_functions, _69895)|_] ) :- !. +ssa( eval_registers, _69906, [set(eval_registers, _69906)|_] ) :- !. +ssa( online, _69917, [set(online, _69917)|_] ) :- !. +ssa( sit_start_time, _69928, [set(sit_start_time, _69928)|_] ) :- !. +ssa( useAbstraction, _69939, [set(useAbstraction, _69939)|_] ) :- !. +ssa( bel(_69762), _69950, [set(bel(_69762), _69950)|_] ) :- !. +ssa( ltp(_69766), _69961, [set(ltp(_69766), _69961)|_] ) :- !. + +ssa( lookahead(_69755, _69756, _69757, _69758), _70148, [set(lookahead(_69755, _69756, _69757, _69758), _70148)|_] ) :- !. +ssa( pll(_69743, _69744, _69745, _69746), _70159, [set(pll(_69743, _69744, _69745, _69746), _70159)|_] ) :- !. +ssa( eval_exog_functions, _70170, [_70174|_70175] ) :- !, has_val(eval_exog_functions, _70170, _70175). +ssa( eval_registers, _70190, [_70194|_70195] ) :- !, has_val(eval_registers, _70190, _70195). +ssa( online, _70210, [_70214|_70215] ) :- !, has_val(online, _70210, _70215). +ssa( sit_start_time, _70230, [_70234|_70235] ) :- !, has_val(sit_start_time, _70230, _70235). +ssa( useAbstraction, _70250, [_70254|_70255] ) :- !, has_val(useAbstraction, _70250, _70255). +ssa( bel(_69762), _70270, [_70274|_70275] ) :- !, has_val(bel(_69762), _70270, _70275). +ssa( ltp(_69766), _70290, [_70294|_70295] ) :- !, has_val(ltp(_69766), _70290, _70295). + +ssa( lookahead(_69755, _69756, _69757, _69758), _70630, [_70634|_70635] ) :- !, has_val(lookahead(_69755, _69756, _69757, _69758), _70630, _70635). +ssa( pll(_69743, _69744, _69745, _69746), _70650, [_70654|_70655] ) :- !, has_val(pll(_69743, _69744, _69745, _69746), _70650, _70655). + +prolog_poss( send(_R, _70692) ). +prolog_poss( send(_R, _70692), _71116 ) :- true. +prolog_poss( reply(_R, _70701) ). +prolog_poss( reply(_R, _70701), _71133 ) :- true. +prolog_poss( setOnline ). +prolog_poss( setOnline, _71150 ) :- true. +prolog_poss( clipOnline ). +prolog_poss( clipOnline, _71167 ) :- true. +prolog_poss( setTime(_70719) ). +prolog_poss( setTime(_70719), _71184 ) :- true. +prolog_poss( clipAbstraction ). +prolog_poss( clipAbstraction, _71201 ) :- true. +prolog_poss( setAbstraction ). +prolog_poss( setAbstraction, _71218 ) :- true. +prolog_poss( set(_Fluent, _Value) ). +prolog_poss( set(_Fluent, _Value), _71235 ) :- true. +prolog_poss( exogf_Update ). +prolog_poss( exogf_Update, _71252 ) :- true. + diff --git a/src/semantics/native/compound_expression.cpp b/src/semantics/native/compound_expression.cpp new file mode 100644 index 00000000..09536ba5 --- /dev/null +++ b/src/semantics/native/compound_expression.cpp @@ -0,0 +1,23 @@ +/************************************************************************* + * This file is part of golog++. + * + * golog++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * golog++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with golog++. If not, see . +**************************************************************************/ + +#include "compound_expression.h" + +namespace gologpp { + + +} // namespace gologpp diff --git a/src/semantics/readylog/compound_expression.h b/src/semantics/native/compound_expression.h similarity index 99% rename from src/semantics/readylog/compound_expression.h rename to src/semantics/native/compound_expression.h index a5261d4e..278e37e0 100644 --- a/src/semantics/readylog/compound_expression.h +++ b/src/semantics/native/compound_expression.h @@ -25,6 +25,7 @@ namespace gologpp { + } #endif // READYLOG_COMPOUND_EXPRESSION_H_ diff --git a/src/semantics/native/domain.cpp b/src/semantics/native/domain.cpp new file mode 100644 index 00000000..53b74836 --- /dev/null +++ b/src/semantics/native/domain.cpp @@ -0,0 +1,25 @@ +/************************************************************************* + * This file is part of golog++. + * + * golog++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * golog++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with golog++. If not, see . +**************************************************************************/ + +#include "domain.h" +#include "value.h" +#include "utilities.h" + +namespace gologpp { + + +} diff --git a/src/semantics/native/domain.h b/src/semantics/native/domain.h new file mode 100644 index 00000000..571d5802 --- /dev/null +++ b/src/semantics/native/domain.h @@ -0,0 +1,32 @@ +/************************************************************************* + * This file is part of golog++. + * + * golog++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * golog++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with golog++. If not, see . +**************************************************************************/ + +#ifndef READYLOG_DOMAIN_H_ +#define READYLOG_DOMAIN_H_ + +#include "semantics.h" + +#include +#include + +namespace gologpp { + + + +} + +#endif // READYLOG_DOMAIN_H_ diff --git a/src/semantics/native/effect_axiom.cpp b/src/semantics/native/effect_axiom.cpp new file mode 100644 index 00000000..617e0a43 --- /dev/null +++ b/src/semantics/native/effect_axiom.cpp @@ -0,0 +1,26 @@ +/************************************************************************* + * This file is part of golog++. + * + * golog++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * golog++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with golog++. If not, see . +**************************************************************************/ + +#include "effect_axiom.h" +#include "procedural.h" + + + +namespace gologpp { + + +} diff --git a/src/semantics/native/effect_axiom.h b/src/semantics/native/effect_axiom.h new file mode 100644 index 00000000..124caf14 --- /dev/null +++ b/src/semantics/native/effect_axiom.h @@ -0,0 +1,37 @@ +/************************************************************************* + * This file is part of golog++. + * + * golog++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * golog++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with golog++. If not, see . +**************************************************************************/ + +#ifndef READYLOG_EFFECTAXIOM_H_ +#define READYLOG_EFFECTAXIOM_H_ + +#include "semantics.h" + +#include +#include "reference.h" +#include +#include +#include "scope.h" +#include "execution.h" + + +namespace gologpp { + + + +} /* namespace gologpp */ + +#endif /* READYLOG_EFFECTAXIOM_H_ */ diff --git a/src/semantics/native/execution.cpp b/src/semantics/native/execution.cpp new file mode 100644 index 00000000..f2f4f711 --- /dev/null +++ b/src/semantics/native/execution.cpp @@ -0,0 +1,99 @@ +/************************************************************************* + * This file is part of golog++. + * + * golog++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * golog++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with golog++. If not, see . +**************************************************************************/ + +#include "execution.h" + +#include + +#include "action.h" +#include "procedural.h" +#include "fluent.h" +#include "utilities.h" +#include "history.h" + +#include + +namespace filesystem = std::experimental::filesystem; + +namespace gologpp { + + +unique_ptr NativeContext::instance_; + + +void NativeContext::init(unique_ptr &&exec_backend) +{ instance_ = unique_ptr(new NativeContext(std::move(exec_backend))); } + +void NativeContext::shutdown() +{ + instance_.reset(); +} + + +NativeContext::NativeContext(unique_ptr &&exec_backend) +: AExecutionController(std::move(exec_backend)) +{ + // TODO +} + + +NativeContext::~NativeContext() +{} + + +NativeContext &NativeContext::instance() +{ return *instance_; } + + +void NativeContext::compile(const Fluent &fluent) +{ +} + + +void NativeContext::compile(const Action &aa) +{ +} + + +void NativeContext::compile(const ExogAction &action) +{ +} + + +void NativeContext::compile(const Function &function) +{ +} + + +void NativeContext::compile(const ExogFunction &function) +{ +} + + +void NativeContext::postcompile() +{ +} + + +void NativeContext::run(const Instruction &program) +{ + +} + + + +} // namespace gologpp diff --git a/src/semantics/native/execution.h b/src/semantics/native/execution.h new file mode 100644 index 00000000..441945ab --- /dev/null +++ b/src/semantics/native/execution.h @@ -0,0 +1,65 @@ +/************************************************************************* + * This file is part of golog++. + * + * golog++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * golog++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with golog++. If not, see . +**************************************************************************/ + +#ifndef READYLOG_EXECUTION_H_ +#define READYLOG_EXECUTION_H_ + +#include + +#include + +#include "semantics.h" +#include "history.h" + + +namespace gologpp { + + +class NativeContext : public AExecutionController { +public: + virtual ~NativeContext() override; + static void init(unique_ptr &&backend = nullptr); + static void shutdown(); + static NativeContext &instance(); + + virtual void precompile() override {} + virtual void compile(const Fluent &fluent) override; + virtual void compile(const Action &action) override; + virtual void compile(const ExogAction &action) override; + virtual void compile(const Function &function) override; + virtual void compile(const ExogFunction &function) override; + virtual void compile(const Procedure &proc) override; + virtual void postcompile() override; + + shared_ptr wait_for_end(Activity &a); + + virtual void run(const Instruction &program) override; + +private: + NativeContext(unique_ptr &&exec_backend); + + static unique_ptr instance_; +}; + + +class NativeFailure { +}; + + +} // namespace gologpp + +#endif // READYLOG_EXECUTION_H_ diff --git a/src/semantics/native/fluent.cpp b/src/semantics/native/fluent.cpp new file mode 100644 index 00000000..03a7a7f3 --- /dev/null +++ b/src/semantics/native/fluent.cpp @@ -0,0 +1,38 @@ +/************************************************************************* + * This file is part of golog++. + * + * golog++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * golog++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with golog++. If not, see . +**************************************************************************/ + +#include "fluent.h" +#include "execution.h" +#include "scope.h" +#include "utilities.h" +#include "value.h" +#include "semantics.h" +#include "variable.h" + +#include +#include + +#include + + + + +namespace gologpp { + + + +} // namespace gologpp diff --git a/src/semantics/native/fluent.h b/src/semantics/native/fluent.h new file mode 100644 index 00000000..8da9a646 --- /dev/null +++ b/src/semantics/native/fluent.h @@ -0,0 +1,34 @@ +/************************************************************************* + * This file is part of golog++. + * + * golog++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * golog++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with golog++. If not, see . +**************************************************************************/ + +#ifndef READYLOG_FLUENT_H_ +#define READYLOG_FLUENT_H_ + +#include "semantics.h" +#include + + +namespace gologpp { + + + + +} // namespace gologpp + + + +#endif // READYLOG_FLUENT_H_ diff --git a/src/semantics/native/formula.cpp b/src/semantics/native/formula.cpp new file mode 100644 index 00000000..ea4ded01 --- /dev/null +++ b/src/semantics/native/formula.cpp @@ -0,0 +1,131 @@ +/************************************************************************* + * This file is part of golog++. + * + * golog++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * golog++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with golog++. If not, see . +**************************************************************************/ + +#include "formula.h" +#include "variable.h" + +#include +#include +#include + +namespace gologpp { + + +template<> +Value Semantics::evaluate(const BindingChain &b, const History &h) +{ return !element().expression().semantics().evaluate(b, h); } + + + +template<> +Value gologpp::Semantics::evaluate(const BindingChain &b, const History &h) +{ + switch(element().op()) { + case Comparison::Operator::EQ: + return Value( + get_type(), + element().lhs().semantics().evaluate(b, h) + == element().lhs().semantics().evaluate(b, h) + ); + case Comparison::Operator::NEQ: + return Value( + get_type(), + element().lhs().semantics().evaluate(b, h) + != element().lhs().semantics().evaluate(b, h) + ); + case Comparison::Operator::GE: + return Value( + get_type(), + element().lhs().semantics().evaluate(b, h) + >= element().lhs().semantics().evaluate(b, h) + ); + case Comparison::Operator::LE: + return Value( + get_type(), + element().lhs().semantics().evaluate(b, h) + <= element().lhs().semantics().evaluate(b, h) + ); + case Comparison::Operator::GT: + return Value( + get_type(), + element().lhs().semantics().evaluate(b, h) + > element().lhs().semantics().evaluate(b, h) + ); + case Comparison::Operator::LT: + return Value( + get_type(), + element().lhs().semantics().evaluate(b, h) + < element().lhs().semantics().evaluate(b, h) + ); + } +} + + + +template<> +Value gologpp::Semantics::evaluate(const BindingChain &b, const History &h) +{ + bool lhs = static_cast(element().lhs().semantics().evaluate(b, h)); + bool rhs = static_cast(element().rhs().semantics().evaluate(b, h)); + + switch (element().op()) { + case BooleanOperator::OR: + return Value(get_type(), lhs || rhs); + case BooleanOperator::AND: + return Value(get_type(), lhs && rhs); + case BooleanOperator::IFF: + return Value(get_type(), lhs == rhs); + case BooleanOperator::XOR: + return Value(get_type(), lhs != rhs); + case BooleanOperator::IMPLIES: + return Value(get_type(), !lhs || rhs); + } +} + + + +template<> +Value gologpp::Semantics::evaluate(const BindingChain &b, const History &h) { + const Domain &d = element().variable().type(); + switch (element().op()) { + case Quantification::Operator::FORALL: + // TODO: Statically check that variable has a domain type + for (const auto &val : d.elements()) { + Binding var_bind; + var_bind.bind(element().variable().shared(), unique_ptr(val->copy())); + BindingChain b_local = b; + b_local.push_back(&var_bind); + if (!static_cast(element().expression().semantics().evaluate(b_local, h))) + return Value(get_type(), false); + } + return Value(get_type(), true); + case Quantification::Operator::EXISTS: + for (const auto &val : d.elements()) { + Binding var_bind; + var_bind.bind(element().variable().shared(), unique_ptr(val->copy())); + BindingChain b_local = b; + b_local.push_back(&var_bind); + if (static_cast(element().expression().semantics().evaluate(b_local, h))) + return Value(get_type(), true); + } + return Value(get_type(), false); + } +} + + + +} diff --git a/src/semantics/native/formula.h b/src/semantics/native/formula.h new file mode 100644 index 00000000..1879f800 --- /dev/null +++ b/src/semantics/native/formula.h @@ -0,0 +1,32 @@ +/************************************************************************* + * This file is part of golog++. + * + * golog++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * golog++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with golog++. If not, see . +**************************************************************************/ + +#ifndef READYLOG_FORMULA_H_ +#define READYLOG_FORMULA_H_ + +#include "semantics.h" +#include +#include + +namespace gologpp { + + + +} // namespace gologpp + + +#endif diff --git a/src/semantics/native/history.cpp b/src/semantics/native/history.cpp new file mode 100644 index 00000000..9a3deae9 --- /dev/null +++ b/src/semantics/native/history.cpp @@ -0,0 +1,32 @@ +/************************************************************************* + * This file is part of golog++. + * + * golog++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * golog++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with golog++. If not, see . +**************************************************************************/ + +#include "history.h" +#include "action.h" +#include "execution.h" +#include "utilities.h" +#include "value.h" + +#include +#include + +namespace gologpp { + + + +} // namespace gologpp + diff --git a/src/semantics/native/history.h b/src/semantics/native/history.h new file mode 100644 index 00000000..7f14aab8 --- /dev/null +++ b/src/semantics/native/history.h @@ -0,0 +1,55 @@ +/************************************************************************* + * This file is part of golog++. + * + * golog++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * golog++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with golog++. If not, see . +**************************************************************************/ + +#ifndef READYLOG_HISTORY_H_ +#define READYLOG_HISTORY_H_ + +#include "semantics.h" +#include "utilities.h" +#include + + +namespace gologpp { + + +template<> +class Semantics : public GeneralSemantics { +public: + using GeneralSemantics::GeneralSemantics; + virtual ~Semantics() override = default; + + virtual shared_ptr get_last_transition() override; + virtual void append(const Reference &) override; + virtual void append(shared_ptr> exog) override; + virtual void append_sensing_result( + shared_ptr a, + const Expression &lhs, + const Value &sensing_result + ) override; + virtual void append(const Transition &trans) override; + virtual bool should_progress() const override; + virtual void progress() override; + +private: + +}; + + + +} // namespace gologpp + +#endif // READYLOG_HISTORY_H_ diff --git a/src/semantics/readylog/list_expression.cpp b/src/semantics/native/list.cpp similarity index 70% rename from src/semantics/readylog/list_expression.cpp rename to src/semantics/native/list.cpp index 74448dc2..08060a9f 100644 --- a/src/semantics/readylog/list_expression.cpp +++ b/src/semantics/native/list.cpp @@ -15,25 +15,18 @@ * along with golog++. If not, see . **************************************************************************/ -#include "list_expression.h" +#include "list.h" +#include namespace gologpp { - template<> -EC_word Semantics::plterm() +Value Semantics::evaluate(const BindingChain &b, const History &h) { - EC_word list = ::nil(); - - for (size_t i = element().size(); i > 0; --i) - list = ::list(element().entry(i - 1).semantics().plterm(), list); - - return ::term(EC_functor("gpp_list", 2), - EC_atom( ( - "#" + dynamic_cast(element().type()).element_type().name() - ).c_str() ), - list - ); + ListType::Representation rv; + for (const unique_ptr &expr : element().entries()) + rv.emplace_back(expr->semantics().evaluate(b, h)); + return Value(element().type(), rv); } diff --git a/src/semantics/readylog/list_expression.h b/src/semantics/native/list.h similarity index 96% rename from src/semantics/readylog/list_expression.h rename to src/semantics/native/list.h index 7011c973..2c5a6321 100644 --- a/src/semantics/readylog/list_expression.h +++ b/src/semantics/native/list.h @@ -20,7 +20,7 @@ #include "semantics.h" -#include +#include namespace gologpp { diff --git a/src/semantics/native/procedural.cpp b/src/semantics/native/procedural.cpp new file mode 100644 index 00000000..696ebe5b --- /dev/null +++ b/src/semantics/native/procedural.cpp @@ -0,0 +1,42 @@ +/************************************************************************* + * This file is part of golog++. + * + * golog++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * golog++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with golog++. If not, see . +**************************************************************************/ + +#include "scope.h" +#include "procedural.h" +#include "reference.h" +#include "execution.h" +#include "value.h" +#include "action.h" + +#include + +#include + + +namespace gologpp { + + +template<> +unique_ptr Semantics::trans(const BindingChain &b, History &h) +{ + for (const unique_ptr &instr : element().elements()) + instr->semantics().trans(b, h); +} + + + +} diff --git a/src/semantics/native/procedural.h b/src/semantics/native/procedural.h new file mode 100644 index 00000000..d429cc68 --- /dev/null +++ b/src/semantics/native/procedural.h @@ -0,0 +1,39 @@ +/************************************************************************* + * This file is part of golog++. + * + * golog++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * golog++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with golog++. If not, see . +**************************************************************************/ + +#ifndef READYLOG_PROCEDURE_H_ +#define READYLOG_PROCEDURE_H_ + +#include "semantics.h" +#include "scope.h" +#include "variable.h" +#include "utilities.h" +#include "fluent.h" +#include "reference.h" + +#include +#include + +namespace gologpp { + + + + +} // namespace gologpp + + +#endif // READYLOG_PROCEDURE_H_ diff --git a/src/semantics/native/reference.cpp b/src/semantics/native/reference.cpp new file mode 100644 index 00000000..464eceaa --- /dev/null +++ b/src/semantics/native/reference.cpp @@ -0,0 +1,91 @@ +/************************************************************************* + * This file is part of golog++. + * + * golog++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * golog++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with golog++. If not, see . +**************************************************************************/ + +#include "reference.h" +#include "variable.h" +#include "history.h" +#include "execution.h" +#include "formula.h" +#include "action.h" +#include "history.h" + +#include +#include +#include + + +namespace gologpp { + + +template<> +unique_ptr Semantics>::trans(const BindingChain &b, History &h) +{ + vector> ground_args; + for (const Expression *e : element().args()) + ground_args.emplace_back(unique_ptr(e->semantics().evaluate(b, h).copy())); + + try { + Transition trans_start(element().target(), ground_args, Transition::Hook::START); + trans_start.attach_semantics(context().semantics_factory()); + trans_start.semantics().trans({}, h); + + Transition trans_end(element().target(), ground_args, Transition::Hook::END); + trans_end.attach_semantics(context().semantics_factory()); + trans_end.semantics().trans({}, h); + } catch (Escalate &e) { + e.set_static_cause(&element()); + throw; + } + + return nullptr; +} + + + +template<> +unique_ptr Semantics::trans(const BindingChain &b, History &h) +{ + if (b.size()) + throw Bug("Attempting to execute transition with non-empty binding"); + + shared_ptr a; + switch (element().hook()) { + case Transition::Hook::START: + context().backend().start_activity(element()); + break; + case Transition::Hook::CANCEL: + context().backend().cancel_activity(element()); + break; + case Transition::Hook::END: + context().backend().end_activity(element()); + break; + case Transition::Hook::FINISH: + a = context().backend().end_activity(element()); + if (a->state() != Activity::target_state(element().hook())) + throw Escalate(nullptr, element().shared_from_this()); + break; + case Transition::Hook::FAIL: + throw Unsupported(element().str() + ": " + to_string(element().hook()) + " not supported"); + } + + h.special_semantics().append(element()); + return nullptr; +} + + + +} // namespace gologpp diff --git a/src/semantics/native/reference.h b/src/semantics/native/reference.h new file mode 100644 index 00000000..c86849d4 --- /dev/null +++ b/src/semantics/native/reference.h @@ -0,0 +1,58 @@ +/************************************************************************* + * This file is part of golog++. + * + * golog++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * golog++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with golog++. If not, see . +**************************************************************************/ + +#ifndef READYLOG_REFERENCE_H_ +#define READYLOG_REFERENCE_H_ + +#include + +#include +#include +#include +#include + +#include + +#include "semantics.h" +#include "utilities.h" +#include "variable.h" + + +namespace gologpp { + + + +template<> +class Semantics +: public GeneralSemantics +{ +public: + using GeneralSemantics::GeneralSemantics; + + virtual GeneralSemantics *copy(const Binding &target_element) const override; + virtual const ModelElement &model_element() const override; +}; + + + + + +} // namespace gologpp + + + +#endif // READYLOG_REFERENCE_H_ diff --git a/src/semantics/native/scope.cpp b/src/semantics/native/scope.cpp new file mode 100644 index 00000000..2263cbe7 --- /dev/null +++ b/src/semantics/native/scope.cpp @@ -0,0 +1,24 @@ +/************************************************************************* + * This file is part of golog++. + * + * golog++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * golog++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with golog++. If not, see . +**************************************************************************/ + +#include "scope.h" +#include "variable.h" + +namespace gologpp { + + +} // namespace gologpp diff --git a/src/semantics/native/scope.h b/src/semantics/native/scope.h new file mode 100644 index 00000000..3e1b7337 --- /dev/null +++ b/src/semantics/native/scope.h @@ -0,0 +1,38 @@ +/************************************************************************* + * This file is part of golog++. + * + * golog++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * golog++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with golog++. If not, see . +**************************************************************************/ + +#ifndef BACKENDS_READYLOG_SCOPE_H_ +#define BACKENDS_READYLOG_SCOPE_H_ + +#include +#include + +#include "semantics.h" + +namespace gologpp { + + +template<> +class Semantics : public GeneralSemantics { +public: + using GeneralSemantics::GeneralSemantics; +}; + + +} // namespace gologpp + +#endif // BACKENDS_READYLOG_SCOPE_H_ diff --git a/src/semantics/native/semantics.cpp b/src/semantics/native/semantics.cpp new file mode 100644 index 00000000..022ddcff --- /dev/null +++ b/src/semantics/native/semantics.cpp @@ -0,0 +1,55 @@ +/************************************************************************* + * This file is part of golog++. + * + * golog++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * golog++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with golog++. If not, see . +**************************************************************************/ + +#include "semantics.h" +#include "effect_axiom.h" +#include "action.h" +#include "fluent.h" +#include "variable.h" +#include "value.h" +#include "formula.h" +#include "procedural.h" +#include "reference.h" +#include "scope.h" +#include "arithmetic.h" +#include "execution.h" +#include "domain.h" +#include "string.h" +#include "history.h" +#include "compound_expression.h" +#include "list_expression.h" +#include "transition.h" + +#include +#include + +namespace gologpp { + + + +#define GOLOGPP_DEFINE_MAKE_SEMANTICS_IMPL(_r, _data, GologT) \ +unique_ptr> NativeSemanticsFactory::make_semantics(GologT &obj) \ +{ return unique_ptr>(new Semantics(obj, context())); } + +BOOST_PP_SEQ_FOR_EACH(GOLOGPP_DEFINE_MAKE_SEMANTICS_IMPL, (), GOLOGPP_SEMANTIC_TYPES) + + + +} // namespace gologpp + + + diff --git a/src/semantics/native/semantics.h b/src/semantics/native/semantics.h new file mode 100644 index 00000000..d2c64b1e --- /dev/null +++ b/src/semantics/native/semantics.h @@ -0,0 +1,111 @@ +/************************************************************************* + * This file is part of golog++. + * + * golog++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * golog++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with golog++. If not, see . +**************************************************************************/ + +#ifndef READYLOG_IMPLEMENTATION_H_ +#define READYLOG_IMPLEMENTATION_H_ + +#include +#include + +#include + +namespace gologpp { + + +template +using enable_if_subclass = std::enable_if < + std::is_base_of::value, + TArg +>; + + +class Escalate { +public: + Escalate(const Instruction *static_cause, shared_ptr dynamic_cause); + + void set_static_cause(const Instruction *cause); + const Instruction *static_cause() const; + void set_dynamic_cause(shared_ptr cause); + shared_ptr dynamic_cause() const; + +private: + const Instruction *static_cause_; + shared_ptr dynamic_cause_; +}; + + + +template +class Semantics>> +: public GeneralSemantics +{ +public: + using GeneralSemantics::GeneralSemantics; + virtual ~Semantics() override = default; + + virtual unique_ptr trans(const BindingChain &b, History &h) override; + + virtual bool final(const BindingChain &, const History &) override + { throw Bug("This method should not be called"); } +}; + + + +template +class Semantics>> +: public GeneralSemantics +{ +public: + using GeneralSemantics::GeneralSemantics; + virtual ~Semantics() override = default; + + virtual Value evaluate(const BindingChain &b, const History &h) override; +}; + + +template +class Semantics + && !is_instruction +>> +: public GeneralSemantics +{ +public: + using GeneralSemantics::GeneralSemantics; + virtual ~Semantics() override = default; +}; + + +#define GOLOGPP_DECL_MAKE_SEMANTICS_OVERRIDE(_r, _data, GologT) \ + virtual unique_ptr> make_semantics(GologT &) override; + + +class NativeSemanticsFactory : public SemanticsFactory { +public: + NativeSemanticsFactory(unique_ptr &&psf); + virtual ~NativeSemanticsFactory() override = default; + + BOOST_PP_SEQ_FOR_EACH(GOLOGPP_DECL_MAKE_SEMANTICS_OVERRIDE, (), GOLOGPP_SEMANTIC_TYPES) +}; + + + +} // namespace gologpp + + + +#endif diff --git a/src/semantics/native/string.cpp b/src/semantics/native/string.cpp new file mode 100644 index 00000000..3c206127 --- /dev/null +++ b/src/semantics/native/string.cpp @@ -0,0 +1,25 @@ +/************************************************************************* + * This file is part of golog++. + * + * golog++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * golog++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with golog++. If not, see . +**************************************************************************/ + +#include "string.h" + +namespace gologpp { + + + + +} diff --git a/src/semantics/native/string.h b/src/semantics/native/string.h new file mode 100644 index 00000000..74812026 --- /dev/null +++ b/src/semantics/native/string.h @@ -0,0 +1,30 @@ +/************************************************************************* + * This file is part of golog++. + * + * golog++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * golog++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with golog++. If not, see . +**************************************************************************/ + +#ifndef READYLOG_STRING_CONCATENATION_H_ +#define READYLOG_STRING_CONCATENATION_H_ + +#include "semantics.h" + +#include + +namespace gologpp { + + +} + +#endif // READYLOG_STRING_CONCATENATION_H_ diff --git a/src/semantics/native/transition.cpp b/src/semantics/native/transition.cpp new file mode 100644 index 00000000..5d797a80 --- /dev/null +++ b/src/semantics/native/transition.cpp @@ -0,0 +1,24 @@ +/************************************************************************* + * This file is part of golog++. + * + * golog++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * golog++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with golog++. If not, see . +**************************************************************************/ + +#include "transition.h" + +namespace gologpp { + + + +} diff --git a/src/semantics/readylog/compound_expression.cpp b/src/semantics/native/transition.h similarity index 65% rename from src/semantics/readylog/compound_expression.cpp rename to src/semantics/native/transition.h index 69ac54c6..c1ecf66b 100644 --- a/src/semantics/readylog/compound_expression.cpp +++ b/src/semantics/native/transition.h @@ -15,27 +15,26 @@ * along with golog++. If not, see . **************************************************************************/ -#include "compound_expression.h" +#pragma once + +#include namespace gologpp { template<> -EC_word Semantics::plterm() +class Semantics +: public GeneralSemantics { - EC_word field_list = ::nil(); - for (auto &field_name : element().compound_type().field_names()) - field_list = ::list( - ::term(EC_functor(("#" + field_name).c_str(), 1), - element().entry(field_name).semantics().plterm() - ), - field_list - ); - return ::term(EC_functor("gpp_compound", 2), - EC_atom(("#" + element().type().name()).c_str()), - field_list - ); -} +public: + using GeneralSemantics::GeneralSemantics; + + virtual GeneralSemantics *copy(const Transition &target_element) const override; + virtual unique_ptr trans(const BindingChain &b, History &h) override; + + virtual bool final(const BindingChain &, const History &) override + { throw Bug("This method should not be called"); } +}; } // namespace gologpp diff --git a/src/semantics/native/utilities.cpp b/src/semantics/native/utilities.cpp new file mode 100644 index 00000000..2b77b7e5 --- /dev/null +++ b/src/semantics/native/utilities.cpp @@ -0,0 +1,24 @@ +/************************************************************************* + * This file is part of golog++. + * + * golog++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * golog++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with golog++. If not, see . +**************************************************************************/ + +#include "utilities.h" + + +namespace gologpp { + + +} diff --git a/src/semantics/native/utilities.h b/src/semantics/native/utilities.h new file mode 100644 index 00000000..e0d7a532 --- /dev/null +++ b/src/semantics/native/utilities.h @@ -0,0 +1,49 @@ +/************************************************************************* + * This file is part of golog++. + * + * golog++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * golog++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with golog++. If not, see . +**************************************************************************/ + +#ifndef READYLOG_UTILITIES_H_ +#define READYLOG_UTILITIES_H_ + +#include +#include +#include + +namespace gologpp { + + +template inline +T &access(T *ptr) +{ return *ptr; } + +template inline +T &access(const unique_ptr &ptr) +{ return *ptr; } + +template inline +const Expression &access(const SafeExprOwner &ptr) +{ return *ptr; } + +template inline +typename std::enable_if::value, T>::type +&access(T &&ptr) +{ return std::forward(ptr); } + + + +} // namespace gologpp + +#endif // READYLOG_UTILITIES_H_ diff --git a/src/semantics/native/value.cpp b/src/semantics/native/value.cpp new file mode 100644 index 00000000..23a249f1 --- /dev/null +++ b/src/semantics/native/value.cpp @@ -0,0 +1,26 @@ +/************************************************************************* + * This file is part of golog++. + * + * golog++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * golog++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with golog++. If not, see . +**************************************************************************/ + +#include "value.h" +#include "execution.h" +#include + +namespace gologpp { + + + +} // namespace gologpp diff --git a/src/semantics/native/value.h b/src/semantics/native/value.h new file mode 100644 index 00000000..e3a17707 --- /dev/null +++ b/src/semantics/native/value.h @@ -0,0 +1,46 @@ +/************************************************************************* + * This file is part of golog++. + * + * golog++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * golog++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with golog++. If not, see . +**************************************************************************/ + +#ifndef READYLOG_CONSTANT_H_ +#define READYLOG_CONSTANT_H_ + +#include "semantics.h" + +#include +#include + + +namespace gologpp { + + +template<> +class Semantics +: public GeneralSemantics +{ +public: + using GeneralSemantics::GeneralSemantics; + virtual ~Semantics() override = default; + + virtual Value evaluate(const BindingChain &b, const History &h) override; + virtual GeneralSemantics *copy(const Value &target_element) const override; +}; + + + +} // namespace gologpp + +#endif // READYLOG_CONSTANT_H_ diff --git a/src/semantics/native/variable.cpp b/src/semantics/native/variable.cpp new file mode 100644 index 00000000..17cc9a69 --- /dev/null +++ b/src/semantics/native/variable.cpp @@ -0,0 +1,27 @@ +/************************************************************************* + * This file is part of golog++. + * + * golog++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * golog++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with golog++. If not, see . +**************************************************************************/ + +#include "variable.h" +#include "reference.h" +#include "domain.h" + +namespace gologpp { + + + + +} // namespace gologpp diff --git a/src/semantics/native/variable.h b/src/semantics/native/variable.h new file mode 100644 index 00000000..e8b6b72b --- /dev/null +++ b/src/semantics/native/variable.h @@ -0,0 +1,33 @@ +/************************************************************************* + * This file is part of golog++. + * + * golog++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * golog++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with golog++. If not, see . +**************************************************************************/ + +#ifndef READYLOG_VARIABLE_H_ +#define READYLOG_VARIABLE_H_ + +#include "semantics.h" + +#include +#include + + +namespace gologpp { + + + +} // namespace gologpp + +#endif // READYLOG_VARIABLE_H_ diff --git a/src/semantics/platform/taptenc/clock_formula.h b/src/semantics/platform/taptenc/clock_formula.h index 3583c500..a82920d2 100644 --- a/src/semantics/platform/taptenc/clock_formula.h +++ b/src/semantics/platform/taptenc/clock_formula.h @@ -26,7 +26,9 @@ namespace gologpp { template<> -class Semantics { +class Semantics +: public TaptencExpressionSemantics +{ public: virtual std::unique_ptr compile() = 0; }; diff --git a/src/semantics/platform/taptenc/constraint.h b/src/semantics/platform/taptenc/constraint.h index 3d4ddb29..b96dee5b 100644 --- a/src/semantics/platform/taptenc/constraint.h +++ b/src/semantics/platform/taptenc/constraint.h @@ -49,6 +49,7 @@ class Semantics template<> class Semantics +: public TaptencExpressionSemantics { public: virtual std::vector compile() = 0; @@ -106,6 +107,7 @@ class Semantics> template<> class Semantics> : public GeneralSemantics> +, public TaptencExpressionSemantics { public: Semantics(const platform::TemporalUnaryOperation &elem, AExecutionController &context); @@ -118,6 +120,7 @@ class Semantics> template<> class Semantics> : public GeneralSemantics> +, TaptencExpressionSemantics { public: Semantics(const platform::TemporalBinaryOperation &elem, AExecutionController &context); @@ -149,6 +152,7 @@ class Semantics template<> class Semantics +: public TaptencExpressionSemantics { public: virtual std::unique_ptr compile( diff --git a/src/semantics/platform/taptenc/semantics.cpp b/src/semantics/platform/taptenc/semantics.cpp index e1435c0e..adbe50b9 100644 --- a/src/semantics/platform/taptenc/semantics.cpp +++ b/src/semantics/platform/taptenc/semantics.cpp @@ -51,7 +51,12 @@ unique_ptr SemanticsFactory::construct() PlanTransformation *TaptencSemanticsFactory::make_transformation() { return new TaptencTransformation(); } -} // namespace platform +} + +Value TaptencExpressionSemantics::evaluate(const BindingChain &, const History &) +{ throw Bug("This method shoudln't be called: Expression evaluation is not implemented here for the Taptenc semantics."); } + +// namespace platform } // namespace gologpp diff --git a/src/semantics/platform/taptenc/semantics.h b/src/semantics/platform/taptenc/semantics.h index 752b88c0..072a3bbf 100644 --- a/src/semantics/platform/taptenc/semantics.h +++ b/src/semantics/platform/taptenc/semantics.h @@ -33,6 +33,16 @@ string uppaal_qualified_name(const ElemT &e) } + +class TaptencExpressionSemantics +: public virtual GeneralSemantics +{ +public: + virtual Value evaluate(const BindingChain &, const History &) override; +}; + + + namespace platform { class TaptencSemanticsFactory : public platform::SemanticsFactory { @@ -42,6 +52,7 @@ class TaptencSemanticsFactory : public platform::SemanticsFactory { BOOST_PP_SEQ_FOR_EACH(GOLOGPP_DECL_MAKE_SEMANTICS_OVERRIDE, (), GOLOGPP_PLATFORM_ELEMENTS) }; + } // namespace platform diff --git a/src/semantics/platform/taptenc/transformation.cpp b/src/semantics/platform/taptenc/transformation.cpp index ac453eb4..eacef677 100644 --- a/src/semantics/platform/taptenc/transformation.cpp +++ b/src/semantics/platform/taptenc/transformation.cpp @@ -138,7 +138,7 @@ vector TaptencTransformation::plan_gpp_to_taptenc(Plan &&p) for (auto &ti : p.elements()) { if (ti.instruction().is_a()) { Transition &trans = ti.instruction().cast(); - std::string actstr = gologpp::to_string(trans.hook()) + "G" + trans->name(); + std::string actstr = gologpp::to_string(trans.hook()) + "G" + trans.ref().name(); std::vector argstr; for (auto &arg : trans.args()) @@ -155,7 +155,7 @@ vector TaptencTransformation::plan_gpp_to_taptenc(Plan &&p) boost::numeric_cast(earliest_shifted), boost::numeric_cast(latest_shifted) ), - taptenc::Bounds(trans->duration().min.count(), trans->duration().max.count()) + taptenc::Bounds(trans.ref()->duration().min.count(), trans.ref()->duration().max.count()) } ); } else { @@ -190,14 +190,14 @@ unique_ptr TaptencTransformation::plan_taptenc_to_gpp(taptenc::timed_trace std::string TaptencTransformation::store_arg(Value &v) { - auto it = arg_to_sym_.find(unique_ptr(v.copy())); + auto it = arg_to_sym_.find(unique_ptr(new Value(v))); if (it != arg_to_sym_.end()) return it->second; else { size_t count = arg_to_sym_.size(); std::string rv = "arg" + std::to_string(count); - arg_to_sym_.insert({ unique_ptr(v.copy()), rv }); - sym_to_arg_.insert({ rv, unique_ptr(v.copy()) }); + arg_to_sym_.insert({ unique_ptr(new Value(v)), rv }); + sym_to_arg_.insert({ rv, unique_ptr(new Value(v)) }); return rv; } } @@ -208,7 +208,7 @@ Value *TaptencTransformation::retrieve_arg(std::string taptenc_symbolic_arg) auto it = sym_to_arg_.find(taptenc_symbolic_arg); if (it == sym_to_arg_.end()) throw Bug("Cannot retrieve argument from storage: " + taptenc_symbolic_arg); - return it->second->copy(); + return new Value(*it->second); } @@ -236,7 +236,7 @@ TimedInstruction TaptencTransformation::parse_domain_action( string act_name = tt_action.substr(hook_sep + 1, brace_opn - (hook_sep + 1)); string argstr = tt_action.substr(brace_opn + 1, brace_cls - (brace_opn + 1)); - vector> args; + vector> args; while (argstr.size()) { auto arg_sep = argstr.find(taptenc::constants::VAR_SEP); args.emplace_back(retrieve_arg(argstr.substr(0, arg_sep))); diff --git a/src/semantics/readylog/action.cpp b/src/semantics/readylog/action.cpp index d507a1d8..244599b4 100644 --- a/src/semantics/readylog/action.cpp +++ b/src/semantics/readylog/action.cpp @@ -15,11 +15,10 @@ * along with golog++. If not, see . **************************************************************************/ -#include "value.h" #include "action.h" #include "effect_axiom.h" -#include "scope.h" #include "variable.h" +#include "domain.h" #include "wrap_eclipseclass.h" @@ -65,7 +64,7 @@ vector Semantics::durative_causes_vals() { vector rv; for (const unique_ptr &effect : element().effects()) - rv.push_back(effect->semantics().plterm()); + rv.push_back(effect->semantics().plterm()); return rv; } @@ -109,7 +108,7 @@ vector Semantics::causes_vals() { vector rv; for (const unique_ptr &effect : element().effects()) - rv.push_back(effect->semantics().plterm()); + rv.push_back(effect->semantics().plterm()); return rv; } @@ -124,11 +123,5 @@ EC_word Semantics::poss() -template<> -EC_word Semantics>::plterm() -{ return reference_term(element()); } - - - } // namespace gologpp diff --git a/src/semantics/readylog/action.h b/src/semantics/readylog/action.h index 23f51c74..6d756c5c 100644 --- a/src/semantics/readylog/action.h +++ b/src/semantics/readylog/action.h @@ -28,15 +28,9 @@ namespace gologpp { -template<> -class Semantics -: public ReadylogSemantics { -}; - - template<> class Semantics -: public Semantics +: public Semantics , public GeneralSemantics { public: @@ -54,7 +48,7 @@ class Semantics template<> class Semantics -: public Semantics +: public Semantics , public GeneralSemantics { public: diff --git a/src/semantics/readylog/activity.h b/src/semantics/readylog/activity.h index 32d36d8b..30926557 100644 --- a/src/semantics/readylog/activity.h +++ b/src/semantics/readylog/activity.h @@ -25,7 +25,7 @@ namespace gologpp { template<> class Semantics -: public Semantics +: public Semantics , public GeneralSemantics { public: diff --git a/src/semantics/readylog/compound.cpp b/src/semantics/readylog/compound.cpp new file mode 100644 index 00000000..8ed19deb --- /dev/null +++ b/src/semantics/readylog/compound.cpp @@ -0,0 +1,104 @@ +/************************************************************************* + * This file is part of golog++. + * + * golog++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * golog++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with golog++. If not, see . +**************************************************************************/ + +#include "compound.h" +#include "list.h" +#include "reference.h" + +namespace gologpp { + + +template<> +EC_word Semantics::plterm() +{ + EC_word field_list = ::nil(); + for (auto &field_name : element().compound_type().field_names()) + field_list = ::list( + ::term(EC_functor(("#" + field_name).c_str(), 1), + element().entry(field_name).semantics().plterm() + ), + field_list + ); + return ::term(EC_functor("gpp_compound", 2), + EC_atom(("#" + element().type().name()).c_str()), + field_list + ); +} + + +/** + * Transform nested field- and list accesses into a pair of the innermost subject (must be a + * list- or compound-valued fluent) and a sequence of list indices and field names. Only one of either + * @a fa or @a la may be set, depending on whether the outermost expression is a list access or a field access. + * + * @param fa The rightmost field access or nullptr + * @param la The rightmost list access or nullptr + * @return A reference to the fluent (either list- or compound-valued), and an eclipse list + * with a mixture of list indices and field names that sequentially index (deeply) into the + * returned fluent. + */ +std::pair *, EC_word> traverse_mixed_field_access(const FieldAccess *fa, const ListAccess *la) { + const Expression *sub; + EC_word field_list = ::nil(); + + do { + if (fa) { + field_list = ::list(fa->special_semantics().pl_field_name(), field_list); + sub = &fa->subject(); + } + else if (la) { + field_list = ::list(la->special_semantics().pl_index(), field_list); + sub = &la->subject(); + } + else + throw Bug("Invalid FieldAccess statement: " + fa->str()); + + fa = dynamic_cast(sub); + la = dynamic_cast(sub); + } while (sub->is_a() || sub->is_a()); + + return { dynamic_cast *>(sub), std::move(field_list) }; +}; + + + +EC_word Semantics::plterm() +{ + return ::term(EC_functor("gpp_field_value", 2), + pl_field_name(), + element().subject().semantics().plterm() + ); +} + + +EC_atom Semantics::pl_field_name() +{ return EC_atom(("#" + element().field_name()).c_str()); } + + +EC_word Semantics::field_assign(const Expression &value) +{ + return ::term(EC_functor("gpp_field_assign", 3), + pl_field_name(), + value.semantics().plterm(), + element().subject().semantics().plterm() + ); +} + + + + +} // namespace gologpp diff --git a/src/semantics/readylog/compound.h b/src/semantics/readylog/compound.h new file mode 100644 index 00000000..6a3a8fb6 --- /dev/null +++ b/src/semantics/readylog/compound.h @@ -0,0 +1,49 @@ +/************************************************************************* + * This file is part of golog++. + * + * golog++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * golog++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with golog++. If not, see . +**************************************************************************/ + +#ifndef READYLOG_COMPOUND_EXPRESSION_H_ +#define READYLOG_COMPOUND_EXPRESSION_H_ + +#include "semantics.h" + +#include + +namespace gologpp { + + +std::pair *, EC_word> +traverse_mixed_field_access(const FieldAccess *fa, const ListAccess *la); + + +template<> +class Semantics +: public Semantics +, public GeneralSemantics +{ +public: + using GeneralSemantics::GeneralSemantics; + + virtual EC_word plterm() override; + EC_word field_assign(const Expression &value); + EC_atom pl_field_name(); +}; + + + +} + +#endif // READYLOG_COMPOUND_EXPRESSION_H_ diff --git a/src/semantics/readylog/domain.h b/src/semantics/readylog/domain.h index 267d4163..4d6d982c 100644 --- a/src/semantics/readylog/domain.h +++ b/src/semantics/readylog/domain.h @@ -28,7 +28,7 @@ namespace gologpp { template<> class Semantics -: public ReadylogSemantics +: public Semantics , public GeneralSemantics { public: diff --git a/src/semantics/readylog/effect_axiom.cpp b/src/semantics/readylog/effect_axiom.cpp index 2774f417..eda47433 100644 --- a/src/semantics/readylog/effect_axiom.cpp +++ b/src/semantics/readylog/effect_axiom.cpp @@ -18,6 +18,8 @@ #include "effect_axiom.h" #include "procedural.h" #include "action.h" +#include "list.h" +#include "compound.h" @@ -50,8 +52,8 @@ EC_word Semantics>>::plterm() } return ::term(EC_functor(cv_functor(element()).c_str(), 4), - element().action().semantics().plterm(), - element().lhs().semantics>().plterm_free_args(), + element().action().semantics().plterm(), + element().lhs().special_semantics().plterm_free_args(), element().value().semantics().plterm(), condition_term ); @@ -75,7 +77,7 @@ EC_word Semantics>::plterm() } return ::term(EC_functor(cv_functor(element()).c_str(), 4), - element().action().semantics().plterm(), + element().action().semantics().plterm(), fluent_access.first->special_semantics().plterm_free_args(), ::term(EC_functor("gpp_mixed_assign", 3), fluent_access.second, @@ -104,7 +106,7 @@ EC_word Semantics>::plterm() } return ::term(EC_functor(cv_functor(element()).c_str(), 4), - element().action().semantics().plterm(), + element().action().semantics().plterm(), fluent_access.first->special_semantics().plterm_free_args(), ::term(EC_functor("gpp_mixed_assign", 3), fluent_access.second, diff --git a/src/semantics/readylog/effect_axiom.h b/src/semantics/readylog/effect_axiom.h index 98876b4b..4a2e134c 100644 --- a/src/semantics/readylog/effect_axiom.h +++ b/src/semantics/readylog/effect_axiom.h @@ -24,26 +24,18 @@ #include #include -#include "reference.h" -#include "scope.h" -#include "execution.h" - #include "wrap_eclipseclass.h" namespace gologpp { -template<> -class Semantics -: public ReadylogSemantics -{ -}; - +template +bool partially_specialized>> = true; template -class Semantics> -: public Semantics +class Semantics, void> +: public Semantics , public GeneralSemantics> { public: @@ -52,6 +44,8 @@ class Semantics> virtual EC_word plterm() override; }; + + } /* namespace gologpp */ #endif /* READYLOG_EFFECTAXIOM_H_ */ diff --git a/src/semantics/readylog/execution.cpp b/src/semantics/readylog/execution.cpp index 8af61d31..5d3f5447 100644 --- a/src/semantics/readylog/execution.cpp +++ b/src/semantics/readylog/execution.cpp @@ -16,7 +16,7 @@ **************************************************************************/ #include "wrap_eclipseclass.h" -#include +#include #include "value.h" #include "execution.h" @@ -26,6 +26,7 @@ #include "utilities.h" #include "history.h" #include "transition.h" +#include "event.h" #include #include @@ -34,11 +35,15 @@ #include #include +#include +#include + +#include -namespace filesystem = std::experimental::filesystem; namespace gologpp { +namespace filesystem = std::filesystem; unique_ptr ReadylogContext::instance_; @@ -54,14 +59,20 @@ void ReadylogContext::shutdown() ReadylogContext::ReadylogContext( const eclipse_opts &options, unique_ptr &&exec_backend, - unique_ptr &&transformation + unique_ptr &&transformation, + const std::initializer_list &add_search_paths ) -: ExecutionController( - std::move(exec_backend), - std::move(transformation) - ) +: AExecutionController(std::move(exec_backend)) , options_(options) +, plan_transformation_(std::move(transformation)) +, search_paths_(add_search_paths.begin(), add_search_paths.end()) { + search_paths_.emplace_back(path(SEMANTICS_INSTALL_DIR) / "readylog"); + search_paths_.emplace_back(path(SOURCE_DIR) / "src" / "semantics" / "readylog"); + + if (!plan_transformation_) + plan_transformation_ = std::make_unique(); + Logger::Guard lg(LogLevel::DBG); ec_set_option_ptr(EC_OPTION_ECLIPSEDIR, const_cast(static_cast(ECLIPSE_DIR))); std::cout << "Using eclipse-clp in " << ECLIPSE_DIR << std::endl; @@ -119,12 +130,17 @@ ReadylogContext::ReadylogContext( ReadylogContext::~ReadylogContext() {} -void ReadylogContext::init(const eclipse_opts &options, unique_ptr &&backend, unique_ptr &&transformation) -{ +void ReadylogContext::init( + const eclipse_opts &options, + unique_ptr &&backend, + unique_ptr &&transformation, + const std::initializer_list &add_search_paths +) { instance_ = unique_ptr(new ReadylogContext( options, std::move(backend), - std::move(transformation) + std::move(transformation), + add_search_paths ) ); } @@ -186,44 +202,35 @@ void ReadylogContext::compile_term(const EC_word &term) } std::string ReadylogContext::find_readylog() { - const char *readylog_pl = std::getenv("READYLOG_PL"); - std::string readylog_path_env = ""; - if (readylog_pl) { - readylog_path_env = std::string(readylog_pl) + ":"; - } - readylog_path_env += (std::string(SEMANTICS_INSTALL_DIR) + "/readylog/interpreter"); - std::size_t last = 0; - std::size_t next; - while (true) { - next = readylog_path_env.find(':', last); - std::string next_path = readylog_path_env.substr(last, next - last); - if (next_path != "") { - filesystem::path readylog_path(next_path); - readylog_path /= "preprocessor.pl"; - if (filesystem::exists(readylog_path)) - return std::string(readylog_path); - } - if (next == std::string::npos) { - throw std::runtime_error("Could not find ReadyLog in \"" + readylog_path_env - + "\" please set READYLOG_PL to the ReadyLog path!"); - } - last = next + 1; + using path = filesystem::path; + + vector paths; + + const char *readylog_env = std::getenv("READYLOG_PL"); + if (readylog_env) + paths.push_back(path(readylog_env) / "preprocessor.pl"); + + for (path p : search_paths_) + paths.emplace_back(p / "readylog_ecl" / "interpreter" / "preprocessor.pl"); + + for (path p : paths) { + if (filesystem::exists(p)) + return string(p); } + throw std::runtime_error("Could not find ReadyLog in \"" + concat_list(paths, ", ") + + "\" please set READYLOG_PL to the ReadyLog path!"); } std::string ReadylogContext::find_boilerplate() { - filesystem::path boilerplate_src_path{SOURCE_DIR}; - boilerplate_src_path /= "src/semantics/readylog/boilerplate.pl"; - if (filesystem::exists(boilerplate_src_path)) { - return boilerplate_src_path.string(); - } - filesystem::path boilerplate_install_path{SEMANTICS_INSTALL_DIR}; - boilerplate_install_path /= "readylog/boilerplate.pl"; - if (filesystem::exists(boilerplate_install_path)) { - return boilerplate_install_path.string(); + using path = filesystem::path; + + for (path p : search_paths_) { + p /= "boilerplate.pl"; + if (filesystem::exists(p)) + return p; } - throw std::runtime_error("Could not find readylog boilerplate in " + boilerplate_src_path.string() - + " or " + boilerplate_install_path.string()); + + throw std::runtime_error("Could not find readylog boilerplate.pl in " + concat_list(search_paths_, ", ")); } @@ -295,5 +302,122 @@ bool ReadylogContext::ec_query(EC_word t) } +void ReadylogContext::run(const Instruction &program) +{ + try { + history().attach_semantics(semantics_factory()); + global_scope().implement_globals(semantics_factory(), *this); + + plan_transformation_->init(*this); + + while (!program.general_semantics().final({}, history())) { + set_silent(true); + + unique_ptr plan { + program.general_semantics().trans({}, history()) + }; + + if (plan) { + plan = plan_transformation_->transform(std::move(*plan)); + + log(LogLevel::INF) << "<<< Transformed schedule: " << *plan << flush; + + while (!plan->elements().empty()) { + set_silent(true); + + if (terminated) + throw Terminate(); + + if (!exog_empty()) { + drain_exog_queue(); + if (backend().any_component_state_changed_exog()) + plan = plan_transformation_->transform(std::move(*plan)); + } + + unique_ptr empty_plan; + + if (plan->elements().front().earliest_timepoint() > context_time()) { + backend().schedule_timer_event( + plan->elements().front().earliest_timepoint() + ); + } + else { + // Plan elements are expected to not return plans again (nullptr or empty Plan). + empty_plan = plan->elements().front().instruction() + .general_semantics().trans({}, history()) + ; + } + + Clock::time_point timeout = plan->next_timeout(); + + if (empty_plan) { + // Empty plan: successfully executed + if (!empty_plan->elements().empty()) + throw Bug( + "Plan instruction returned a plan: " + + plan->elements().front().instruction().str() + ); + plan->elements().erase(plan->elements().begin()); + } + else { + // Current Plan element not executable + try { + drain_exog_queue_blocking(timeout); + } catch (ExogTimeout &) + { + exog_timer_wakeup(); + log(LogLevel::ERR) << "=== Next-action timeout " << timeout << " exceeded" << flush; + + auto sw_state = dynamic_cast *>( + &plan->elements().front().instruction() + ); + if (sw_state) { + global_scope().lookup_global( + static_cast(dynamic_cast( + sw_state->arg_for_param(sw_state->target()->param_component()) + )) + )->backend().handle_missed_transition(); + } + + drain_exog_queue(); + } + + if (context_time() > plan->elements().front().latest_timepoint() + || backend().any_component_state_changed_exog() + ) { + // First plan element's time window has passed: replan! + log(LogLevel::INF) << "=== Re-transforming..." << flush; + plan->make_start_slack(Clock::seconds(16384)); + plan = plan_transformation_->transform(std::move(*plan)); + log(LogLevel::INF) << "=== New schedule " << *plan << flush; + } + } + + if (history().general_semantics().should_progress()) { + log(LogLevel::DBG) << "=== Progressing history." << flush; + history().general_semantics().progress(); + } + } + } + else { + drain_exog_queue_blocking(nullopt); + } + + if (terminated) + throw Terminate(); + + } + } catch (Terminate &) { + log(LogLevel::DBG) << ">>> Terminated." << flush; + } +} + + + +template<> +EC_word Semantics::plterm() +{ return element().ref().semantics().plterm(); } + + } // namespace gologpp diff --git a/src/semantics/readylog/execution.h b/src/semantics/readylog/execution.h index a12a944f..e2960d1e 100644 --- a/src/semantics/readylog/execution.h +++ b/src/semantics/readylog/execution.h @@ -19,8 +19,10 @@ #define READYLOG_EXECUTION_H_ #include +#include #include +#include #include "wrap_eclipseclass.h" namespace gologpp { @@ -33,19 +35,22 @@ struct eclipse_opts { bool toplevel = false; }; -class ReadylogContext : public ExecutionController { +class ReadylogContext : public AExecutionController { public: virtual ~ReadylogContext() override; static void init( const eclipse_opts &options = {false, false, false}, unique_ptr &&backend = nullptr, - unique_ptr &&transformation = nullptr + unique_ptr &&transformation = nullptr, + const std::initializer_list &add_search_paths = {} ); static void shutdown(); static ReadylogContext &instance(); + virtual void run(const Instruction &program) override; + virtual void precompile() override; virtual void compile(const Action &) override; virtual void compile(const ExogAction &) override; @@ -66,10 +71,13 @@ class ReadylogContext : public ExecutionController { ReadylogContext( const eclipse_opts &options, unique_ptr &&exec_backend, - unique_ptr &&transformation + unique_ptr &&transformation, + const std::initializer_list &add_search_paths = {} ); - virtual void compile_term(const EC_word &term); + using path = std::filesystem::path; + + void compile_term(const EC_word &term); std::string find_readylog(); std::string find_boilerplate(); void mark_vars_dead(); @@ -78,6 +86,8 @@ class ReadylogContext : public ExecutionController { int last_rv_; eclipse_opts options_; static unique_ptr instance_; + unique_ptr plan_transformation_; + vector search_paths_; }; diff --git a/src/semantics/readylog/fluent.cpp b/src/semantics/readylog/fluent.cpp index e02ea8f8..6974ce05 100644 --- a/src/semantics/readylog/fluent.cpp +++ b/src/semantics/readylog/fluent.cpp @@ -17,11 +17,10 @@ #include "fluent.h" #include "execution.h" -#include "scope.h" #include "utilities.h" -#include "value.h" #include "semantics.h" #include "variable.h" +#include "domain.h" #include @@ -62,6 +61,7 @@ int p_exog_fluent_getValue() namespace gologpp { +template<> EC_word Semantics::plterm() { EC_word fluent_inst; diff --git a/src/semantics/readylog/fluent.h b/src/semantics/readylog/fluent.h index 5e0ec352..ec7cbe1d 100644 --- a/src/semantics/readylog/fluent.h +++ b/src/semantics/readylog/fluent.h @@ -27,27 +27,16 @@ namespace gologpp { -template<> -class Semantics -: public ReadylogSemantics -, public GeneralSemantics -{ -public: - using GeneralSemantics::GeneralSemantics; - - virtual EC_word plterm() override; -}; - - template<> class Semantics : public GeneralSemantics +, public Semantics { public: using GeneralSemantics::GeneralSemantics; virtual ~Semantics() override = default; - EC_word plterm(); + virtual EC_word plterm() override; vector initially(); EC_word prim_fluent(); }; diff --git a/src/semantics/readylog/history.cpp b/src/semantics/readylog/history.cpp index c0ce60c4..c448b4c2 100644 --- a/src/semantics/readylog/history.cpp +++ b/src/semantics/readylog/history.cpp @@ -63,11 +63,11 @@ shared_ptr Semantics::get_last_transition() } -void Semantics::append(const Transition &trans) -{ extend_history(::list(trans.semantics().plterm(), plterm())); } +void Semantics::append(const AbstractEvent &trans) +{ extend_history(::list(trans.semantics().plterm(), plterm())); } -void Semantics::append(const Reference &trans) -{ extend_history(::list(trans.semantics().plterm(), plterm())); } +void Semantics::append(shared_ptr e) +{ append(*e); } void Semantics::append_sensing_result( @@ -127,5 +127,6 @@ void Semantics::progress() + } // namespace gologpp diff --git a/src/semantics/readylog/history.h b/src/semantics/readylog/history.h index f92efe8b..0a532ac1 100644 --- a/src/semantics/readylog/history.h +++ b/src/semantics/readylog/history.h @@ -30,15 +30,15 @@ namespace gologpp { template<> class Semantics : public GeneralSemantics -, public ReadylogSemantics +, public Semantics { public: Semantics(History &, ReadylogContext &context); virtual ~Semantics() override = default; - virtual shared_ptr get_last_transition() override; - virtual void append(const Transition &exog) override; - virtual void append(const Reference &exog) override; + virtual shared_ptr get_last_transition(); + virtual void append(const AbstractEvent &e) override; + virtual void append(shared_ptr e) override; virtual bool should_progress() const override; virtual void progress() override; diff --git a/src/semantics/readylog/list.cpp b/src/semantics/readylog/list.cpp new file mode 100644 index 00000000..6e20a89b --- /dev/null +++ b/src/semantics/readylog/list.cpp @@ -0,0 +1,117 @@ +/************************************************************************* + * This file is part of golog++. + * + * golog++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * golog++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with golog++. If not, see . +**************************************************************************/ + +#include "list.h" + +namespace gologpp { + + +template<> +EC_word Semantics::plterm() +{ + EC_word list = ::nil(); + + for (size_t i = element().size(); i > 0; --i) + list = ::list(element().entry(i - 1).semantics().plterm(), list); + + return ::term(EC_functor("gpp_list", 2), + EC_atom( ( + "#" + dynamic_cast(element().type()).element_type().name() + ).c_str() ), + list + ); +} + + + +EC_word Semantics::pl_index() +{ return element().index().semantics().plterm(); } + + +EC_word Semantics::plterm() +{ + return ::term(EC_functor("gpp_list_access", 2), + element().subject().semantics().plterm(), + pl_index() + ); +} + + + +template<> +EC_word Semantics::plterm() +{ + string fn; + switch(element().which_end()) { + case ListOpEnd::BACK: + fn = "gpp_list_pop_back"; + break; + case ListOpEnd::FRONT: + fn = "gpp_list_pop_front"; + } + + if (fn.empty()) + throw Bug("Invalid ListOpEnd Enum value: " + std::to_string(element().which_end())); + + return ::term(EC_functor("set", 2), + element().list().semantics().plterm(), + ::term(EC_functor(fn.c_str(), 1), + element().list().semantics().plterm() + ) + ); + +} + + + +template<> +EC_word Semantics::plterm() +{ + string fn; + switch(element().which_end()) { + case ListOpEnd::BACK: + fn = "gpp_list_push_back"; + break; + case ListOpEnd::FRONT: + fn = "gpp_list_push_front"; + } + + if (fn.empty()) + throw Bug("Invalid ListOpEnd Enum value: " + std::to_string(element().which_end())); + + return ::term(EC_functor("set", 2), + element().list().semantics().plterm(), + ::term(EC_functor(fn.c_str(), 2), + element().list().semantics().plterm(), + element().what().semantics().plterm() + ) + ); +} + + + +template<> +EC_word Semantics::plterm() +{ + return ::term(EC_functor("gpp_list_length", 1), + element().subject().semantics().plterm() + ); +} + + + +} // namespace gologpp diff --git a/src/semantics/readylog/list.h b/src/semantics/readylog/list.h new file mode 100644 index 00000000..749554ed --- /dev/null +++ b/src/semantics/readylog/list.h @@ -0,0 +1,43 @@ +/************************************************************************* + * This file is part of golog++. + * + * golog++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * golog++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with golog++. If not, see . +**************************************************************************/ + +#ifndef READYLOG_LIST_EXPRESSION_H_ +#define READYLOG_LIST_EXPRESSION_H_ + +#include "semantics.h" + +#include + +namespace gologpp { + + +template<> +class Semantics +: public Semantics +, public GeneralSemantics +{ +public: + using GeneralSemantics::GeneralSemantics; + + virtual EC_word plterm() override; + EC_word pl_index(); +}; + + +} + +#endif // READYLOG_LIST_EXPRESSION_H_ diff --git a/src/semantics/readylog/procedural.cpp b/src/semantics/readylog/procedural.cpp index 310c46cb..f8f67c05 100644 --- a/src/semantics/readylog/procedural.cpp +++ b/src/semantics/readylog/procedural.cpp @@ -23,6 +23,8 @@ #include "action.h" #include "history.h" #include "plan.h" +#include "list.h" +#include "compound.h" #include @@ -183,9 +185,6 @@ EC_word Semantics::definition() - - - template<> EC_word Semantics::plterm() { @@ -251,40 +250,6 @@ EC_word Semantics>>::plterm() } -/** - * Transform nested field- and list accesses into a pair of the innermost subject (must be a - * list- or compound-valued fluent) and a sequence of list indices and field names. Only one of either - * @a fa or @a la may be set, depending on whether the outermost expression is a list access or a field access. - * - * @param fa The rightmost field access or nullptr - * @param la The rightmost list access or nullptr - * @return A reference to the fluent (either list- or compound-valued), and an eclipse list - * with a mixture of list indices and field names that sequentially index (deeply) into the - * returned fluent. - */ -std::pair *, EC_word> traverse_mixed_field_access(const FieldAccess *fa, const ListAccess *la) { - const Expression *sub; - EC_word field_list = ::nil(); - - do { - if (fa) { - field_list = ::list(fa->special_semantics().pl_field_name(), field_list); - sub = &fa->subject(); - } - else if (la) { - field_list = ::list(la->special_semantics().pl_index(), field_list); - sub = &la->subject(); - } - else - throw Bug("Invalid FieldAccess statement: " + fa->str()); - - fa = dynamic_cast(sub); - la = dynamic_cast(sub); - } while (sub->is_a() || sub->is_a()); - - return { dynamic_cast *>(sub), std::move(field_list) }; -}; - template<> @@ -405,106 +370,6 @@ EC_word Semantics::plterm() -EC_word Semantics::plterm() -{ - return ::term(EC_functor("gpp_field_value", 2), - pl_field_name(), - element().subject().semantics().plterm() - ); -} - - -EC_atom Semantics::pl_field_name() -{ return EC_atom(("#" + element().field_name()).c_str()); } - - -EC_word Semantics::field_assign(const Expression &value) -{ - return ::term(EC_functor("gpp_field_assign", 3), - pl_field_name(), - value.semantics().plterm(), - element().subject().semantics().plterm() - ); -} - - - -EC_word Semantics::pl_index() -{ return element().index().semantics().plterm(); } - - -EC_word Semantics::plterm() -{ - return ::term(EC_functor("gpp_list_access", 2), - element().subject().semantics().plterm(), - pl_index() - ); -} - - - -template<> -EC_word Semantics::plterm() -{ - string fn; - switch(element().which_end()) { - case ListOpEnd::BACK: - fn = "gpp_list_pop_back"; - break; - case ListOpEnd::FRONT: - fn = "gpp_list_pop_front"; - } - - if (fn.empty()) - throw Bug("Invalid ListOpEnd Enum value: " + std::to_string(element().which_end())); - - return ::term(EC_functor("set", 2), - element().list().semantics().plterm(), - ::term(EC_functor(fn.c_str(), 1), - element().list().semantics().plterm() - ) - ); - -} - - - -template<> -EC_word Semantics::plterm() -{ - string fn; - switch(element().which_end()) { - case ListOpEnd::BACK: - fn = "gpp_list_push_back"; - break; - case ListOpEnd::FRONT: - fn = "gpp_list_push_front"; - } - - if (fn.empty()) - throw Bug("Invalid ListOpEnd Enum value: " + std::to_string(element().which_end())); - - return ::term(EC_functor("set", 2), - element().list().semantics().plterm(), - ::term(EC_functor(fn.c_str(), 2), - element().list().semantics().plterm(), - element().what().semantics().plterm() - ) - ); -} - - - -template<> -EC_word Semantics::plterm() -{ - return ::term(EC_functor("gpp_list_length", 1), - element().subject().semantics().plterm() - ); -} - - - template<> EC_word Semantics::plterm() { diff --git a/src/semantics/readylog/procedural.h b/src/semantics/readylog/procedural.h index 39dab27a..aec2473e 100644 --- a/src/semantics/readylog/procedural.h +++ b/src/semantics/readylog/procedural.h @@ -42,7 +42,7 @@ namespace gologpp { template<> class Semantics -: public ReadylogSemantics +: public Semantics , public GeneralSemantics { public: @@ -59,7 +59,7 @@ class Semantics template<> class Semantics -: public ReadylogSemantics +: public Semantics , public GeneralSemantics { public: @@ -73,7 +73,7 @@ class Semantics template<> class Semantics -: public ReadylogSemantics +: public Semantics , public GeneralSemantics { public: @@ -113,38 +113,6 @@ class Semantics }; -std::pair *, EC_word> -traverse_mixed_field_access(const FieldAccess *fa, const ListAccess *la); - - -template<> -class Semantics -: public Semantics -, public GeneralSemantics -{ -public: - using GeneralSemantics::GeneralSemantics; - - virtual EC_word plterm() override; - EC_word field_assign(const Expression &value); - EC_atom pl_field_name(); -}; - - - -template<> -class Semantics -: public Semantics -, public GeneralSemantics -{ -public: - using GeneralSemantics::GeneralSemantics; - - virtual EC_word plterm() override; - EC_word pl_index(); -}; - - } // namespace gologpp diff --git a/src/semantics/readylog/interpreter b/src/semantics/readylog/readylog_ecl similarity index 100% rename from src/semantics/readylog/interpreter rename to src/semantics/readylog/readylog_ecl diff --git a/src/semantics/readylog/reference.cpp b/src/semantics/readylog/reference.cpp index 13fce4c8..c38ea5e6 100644 --- a/src/semantics/readylog/reference.cpp +++ b/src/semantics/readylog/reference.cpp @@ -24,12 +24,11 @@ namespace gologpp { EC_word reference_term(const Reference &ref) { return EC_atom(ref.name().c_str()); } -template<> + EC_word Semantics>::plterm() { return element().target()->special_semantics().plterm(); } - template<> EC_word Semantics>::plterm() { @@ -41,7 +40,14 @@ EC_word Semantics>::plterm() } -EC_word gologpp::Semantics::plterm() +template<> +EC_word Semantics>::plterm() +{ return reference_term(element()); } + + + +template +EC_word Semantics>::plterm() { if (this->element().map().empty()) return EC_atom("true"); @@ -60,11 +66,16 @@ EC_word gologpp::Semantics::plterm() } } -Semantics *Semantics::copy(const Binding &target_element) const -{ return new Semantics(target_element, rl_context()); } +template +Semantics> *Semantics>::copy(const Binding &target_element) const +{ return new Semantics>(target_element, rl_context()); } + + +template +class Semantics>; -const Binding &Semantics::model_element() const -{ return this->element(); } +template +class Semantics>; @@ -72,7 +83,7 @@ EC_word pl_binding_chain(const BindingChain &bc) { EC_word rv = EC_atom("true"); for (auto &b : bc) - rv = ::term(EC_functor(",", 2), rv, b->semantics().plterm()); + rv = ::term(EC_functor(",", 2), rv, b->semantics().plterm()); return rv; } @@ -81,10 +92,10 @@ EC_word pl_binding_chain(const BindingChain &bc) EC_word Semantics >::plterm() { return reference_term(this->element()); } -Value gologpp::Semantics >::evaluate(const BindingChain &bc, const History &h) +Value Semantics >::evaluate(const BindingChain &bc, const History &h) { return GeneralSemantics>::evaluate(bc, h); } -const Expression &gologpp::Semantics >::expression() const +const Expression &Semantics >::expression() const { return GeneralSemantics>::expression(); } diff --git a/src/semantics/readylog/reference.h b/src/semantics/readylog/reference.h index 222ab2ab..5846fe7a 100644 --- a/src/semantics/readylog/reference.h +++ b/src/semantics/readylog/reference.h @@ -25,40 +25,42 @@ #include #include #include +#include #include "semantics.h" #include "utilities.h" #include "variable.h" -#include "value.h" #include "wrap_eclipseclass.h" namespace gologpp { -template class Reference; - EC_word pl_binding_chain(const BindingChain &b); -template<> -class Semantics -: public GeneralSemantics -, public ReadylogSemantics +/// Disambiguate this against the generic Semantics, which +/// is also a partial specialization but requires this to be false in Cond. +template +bool partially_specialized>> = true; + +template +class Semantics> +: public GeneralSemantics> +, public Semantics { public: - using GeneralSemantics::GeneralSemantics; + using GeneralSemantics>::GeneralSemantics; virtual EC_word plterm() override; - virtual Semantics *copy(const Binding &target_element) const override; - virtual const Binding &model_element() const override; + virtual Semantics> *copy(const Binding &target_element) const override; }; -template -EC_word reference_term(const ReferenceBase &ref) +template +EC_word reference_term(const ReferenceBase &ref) { if (ref.arity() > 0) return ::term(EC_functor(ref.mangled_name().c_str(), ref.arity()), @@ -72,21 +74,18 @@ EC_word reference_term(const ReferenceBase &ref) EC_word reference_term(const Reference &ref); -template<> -class Semantics -{ -public: - virtual EC_word plterm() = 0; -}; +/*/// Disambiguate this against the generic Semantics, which +/// is also a partial specialization but requires this to be false in Cond. +template +bool partially_specialized>> = true;*/ -template +template class ReferenceSemantics -: public GeneralSemantics> -, public Semantics +: public GeneralSemantics> { public: - using GeneralSemantics>::GeneralSemantics; + using GeneralSemantics>::GeneralSemantics; bool args_need_eval() { for (auto &expr : this->element().args()) @@ -137,29 +136,35 @@ class ReferenceSemantics }; -template<> -class Semantics> -: public ReferenceSemantics -, public Semantics::ElementType> + +template +bool partially_specialized>> = true; + + +template +class Semantics> +: public ReferenceSemantics +, public Semantics { public: - using ReferenceSemantics::ReferenceSemantics; + using ReferenceSemantics::ReferenceSemantics; - virtual EC_word plterm() override; - virtual Value evaluate(const BindingChain &bc, const History &h) override; - virtual const Expression &expression() const override; -}; + Semantics> *copy(const Reference &target) const override + { return new Semantics>(target, this->context()); } + virtual EC_word plterm() override + { return reference_term(this->element()); } +}; template -class Semantics> -: public ReferenceSemantics -, public Semantics::ElementType> +class Semantics> +: public ReferenceSemantics +, public Semantics { public: - using ReferenceSemantics::ReferenceSemantics; + using ReferenceSemantics::ReferenceSemantics; virtual EC_word plterm() override { return reference_term(this->element()); } @@ -167,6 +172,35 @@ class Semantics> +template<> +class Semantics> +: public Semantics +, public GeneralSemantics> +{ +public: + using GeneralSemantics>::GeneralSemantics; + + virtual EC_word plterm() override; +}; + + + +template<> +class Semantics> +: public GeneralSemantics> +, public Semantics +{ +public: + using GeneralSemantics>::GeneralSemantics; + + virtual EC_word plterm() override; + virtual Value evaluate(const BindingChain &bc, const History &h) override; + virtual const Expression &expression() const override; +}; + + + + } // namespace gologpp diff --git a/src/semantics/readylog/semantics.cpp b/src/semantics/readylog/semantics.cpp index aee0ec44..4425c3dd 100644 --- a/src/semantics/readylog/semantics.cpp +++ b/src/semantics/readylog/semantics.cpp @@ -30,8 +30,8 @@ #include "domain.h" #include "string.h" #include "history.h" -#include "compound_expression.h" -#include "list_expression.h" +#include "compound.h" +#include "list.h" #include "activity.h" #include "transition.h" #include "execution.h" @@ -58,14 +58,12 @@ unique_ptr SemanticsFactory::construct() /***********************************************************************************************/ ///////////////////////////////////////////////////////////////////////////////////////////////// -ReadylogContext &ReadylogSemantics::rl_context() const -{ return dynamic_cast(context()); } +ReadylogContext &Semantics::rl_context() const +{ return dynamic_cast(context()); } + -///////////////////////////////////////////////////////////////////////////////////////////////// -/***********************************************************************************************/ -///////////////////////////////////////////////////////////////////////////////////////////////// Value Semantics::evaluate(const BindingChain &b, const History &h) { @@ -102,9 +100,6 @@ Value Semantics::evaluate(const BindingChain &b, const History &h) } } -const Expression &Semantics::expression() const -{ return dynamic_cast(model_element()); } - ///////////////////////////////////////////////////////////////////////////////////////////////// @@ -179,7 +174,7 @@ unique_ptr Semantics::trans(const BindingChain &, History &hi } -EC_word gologpp::Semantics::next_readylog_term() +EC_word Semantics::next_readylog_term() { if (!next_readylog_term_.initialized()) next_readylog_term_ = plterm(); @@ -187,7 +182,7 @@ EC_word gologpp::Semantics::next_readylog_term() } -bool Semantics::final(const BindingChain &b, const History &h) +bool Semantics::final(const BindingChain &, const History &h) { EC_word final = ::term(EC_functor("final", 2), next_readylog_term(), @@ -197,9 +192,6 @@ bool Semantics::final(const BindingChain &b, const History &h) return rv; } -const Instruction &Semantics::instruction() const -{ return dynamic_cast(model_element()); } - ///////////////////////////////////////////////////////////////////////////////////////////////// @@ -221,7 +213,6 @@ ReadylogContext &ReadylogSemanticsFactory::context() - } // namespace gologpp diff --git a/src/semantics/readylog/semantics.h b/src/semantics/readylog/semantics.h index 162f5556..4b7869cc 100644 --- a/src/semantics/readylog/semantics.h +++ b/src/semantics/readylog/semantics.h @@ -44,31 +44,32 @@ class ReadylogSemanticsFactory : public SemanticsFactory { BOOST_PP_SEQ_FOR_EACH(GOLOGPP_DECL_MAKE_SEMANTICS_OVERRIDE, (), GOLOGPP_SEMANTIC_TYPES) }; +///////////////////////////////////////////////////////////////////////////////////////////////// +/***********************************************************************************************/ +///////////////////////////////////////////////////////////////////////////////////////////////// - -class ReadylogSemantics +template<> +class Semantics : public virtual GeneralSemantics { public: - using GeneralSemantics::GeneralSemantics; + virtual ~Semantics() override = default; + virtual EC_word plterm() = 0; ReadylogContext &rl_context() const; - - virtual EC_word plterm() = 0; }; template<> class Semantics : public virtual GeneralSemantics -, public ReadylogSemantics +, public Semantics { public: using GeneralSemantics::GeneralSemantics; - virtual ~Semantics() override = default; + virtual ~Semantics() override = default; virtual Value evaluate(const BindingChain &b, const History &h) override; - virtual const Expression &expression() const override; }; @@ -76,43 +77,79 @@ class Semantics template<> class Semantics : public virtual GeneralSemantics -, public ReadylogSemantics +, public Semantics { public: using GeneralSemantics::GeneralSemantics; - virtual ~Semantics() override = default; + virtual ~Semantics() override = default; + virtual unique_ptr trans(const BindingChain &b, History &h) override; virtual bool final(const BindingChain &b, const History &h) override; EC_word next_readylog_term(); - virtual const Instruction &instruction() const override; protected: ManagedTerm next_readylog_term_; }; +template +class Semantics> + && is_expression +> > +: public GeneralSemantics +, public Semantics +{ +public: + using GeneralSemantics::GeneralSemantics; + virtual ~Semantics() override = default; -template<> -class Semantics -: public virtual GeneralSemantics + virtual EC_word plterm() override; + + ReadylogContext &rl_context() const + { return dynamic_cast(GeneralSemantics::context()); } +}; + + +template +class Semantics> + && is_instruction +> > +: public GeneralSemantics +, public Semantics { +public: + using GeneralSemantics::GeneralSemantics; + virtual ~Semantics() override = default; + + virtual EC_word plterm() override; + + ReadylogContext &rl_context() const + { return dynamic_cast(GeneralSemantics::context()); } }; template -class Semantics -: public Semantics -, public GeneralSemantics +class Semantics> + && !is_expression + && !is_instruction +> > +: public GeneralSemantics +, public Semantics { public: using GeneralSemantics::GeneralSemantics; + virtual ~Semantics() override = default; + virtual EC_word plterm() override; - virtual const GologT &model_element() const override - { return GeneralSemantics::element(); } + ReadylogContext &rl_context() const + { return dynamic_cast(GeneralSemantics::context()); } }; diff --git a/src/semantics/readylog/transition.cpp b/src/semantics/readylog/transition.cpp index 37a0ed25..fd3cf176 100644 --- a/src/semantics/readylog/transition.cpp +++ b/src/semantics/readylog/transition.cpp @@ -15,27 +15,22 @@ * along with golog++. If not, see . **************************************************************************/ -#include "value.h" #include "transition.h" #include "execution.h" #include "reference.h" #include "utilities.h" #include +#include namespace gologpp { -Semantics::Semantics(const Transition &elem, ExecutionController &context) -: GeneralSemantics(elem, context) -{} - - EC_word Semantics::plterm() { return ::term(EC_functor(to_string(element().hook()).c_str(), 1), - reference_term(element()) + reference_term(element().ref()) ); } @@ -49,7 +44,7 @@ static const ::std::unordered_map<::std::string, Transition::Hook> name2state { }; -shared_ptr gologpp::Semantics::transition_from_plterm(EC_word t) +shared_ptr Semantics::transition_from_plterm(EC_word t) { string headname = functor_name(t); @@ -64,7 +59,7 @@ shared_ptr gologpp::Semantics::transition_from_plterm(EC t.arg(1, t); headname = functor_name(t); - vector> args = plterm_args(t); + vector> args = plterm_args(t); shared_ptr action = global_scope().lookup_global(Name::demangle(headname)); shared_ptr rv { new Transition { action, std::move(args), state_it->second} }; @@ -77,12 +72,77 @@ shared_ptr gologpp::Semantics::transition_from_plterm(EC Semantics *Semantics::copy(const Transition &target_element) const { return new Semantics(target_element, rl_context()); } -unique_ptr Semantics::trans(const BindingChain &b, History &h) -{ return GeneralSemantics::trans(b, h); } -const Instruction &Semantics::instruction() const -{ return GeneralSemantics::instruction(); } +unique_ptr Semantics::trans(const BindingChain &b, History &history) +{ + BindingChain merged(b); + merged.emplace_back(&element().ref().binding()); + + switch(element().hook()) + { + case Transition::Hook::CANCEL: + if (context().backend().current_state(element().ref()) == Activity::State::RUNNING) + context().backend().cancel_activity(element()); + else + return nullptr; + break; + case Transition::Hook::START: + if ( + context().backend().current_state(element().ref()) != Activity::State::RUNNING + && static_cast( + element().action()->precondition().general_semantics().evaluate( + merged, + history + ) + ) + ) + context().backend().start_activity(element()); + else + return nullptr; + break; + case Transition::Hook::FINISH: + if (context().backend().current_state(element().ref()) == Activity::State::FINAL) { + shared_ptr a = context().backend().erase_activity(element()); + } + else + return nullptr; + break; + case Transition::Hook::FAIL: + if (context().backend().current_state(element().ref()) == Activity::State::FAILED) + context().backend().erase_activity(element()); + else + return nullptr; + break; + case Transition::Hook::END: + if ( + context().backend().current_state(element().ref()) == Activity::State::FAILED + || context().backend().current_state(element().ref()) == Activity::State::FINAL + ) + context().backend().erase_activity(element()); + else + return nullptr; + } + + if (!element().action()->silent()) { + log(LogLevel::NFY) << "<<< trans: " << element().str() << flush; + context().set_silent(false); + } + + history.general_semantics().append(element()); + + return unique_ptr(new Plan()); +} + + + +EC_word Semantics::plterm() +{ return element().ref().semantics().plterm(); } + +unique_ptr Semantics::trans(const BindingChain &, History &) +{ throw Bug("trans(...) should not be called on an ExogEvent"); } +Semantics *Semantics::copy(const ExogEvent &target_element) const +{ return new Semantics(target_element, rl_context()); } diff --git a/src/semantics/readylog/transition.h b/src/semantics/readylog/transition.h index 376a6f29..8d676c67 100644 --- a/src/semantics/readylog/transition.h +++ b/src/semantics/readylog/transition.h @@ -30,19 +30,29 @@ class Semantics , public Semantics { public: - Semantics(const Transition &elem, ExecutionController &context); + using GeneralSemantics::GeneralSemantics; virtual ~Semantics() override = default; virtual EC_word plterm() override; virtual unique_ptr trans(const BindingChain &b, History &h) override; - virtual const Instruction &instruction() const override; - virtual Semantics *copy(const Transition &target_element) const override; - static shared_ptr transition_from_plterm(EC_word); }; +template<> +class Semantics +: public GeneralSemantics +, public Semantics +{ +public: + using GeneralSemantics::GeneralSemantics; + + virtual EC_word plterm() override; + virtual unique_ptr trans(const BindingChain &b, History &h) override; + virtual Semantics *copy(const ExogEvent &target_element) const override; +}; + } // namespace gologpp diff --git a/src/semantics/readylog/utilities.cpp b/src/semantics/readylog/utilities.cpp index a9687d68..4c3771e2 100644 --- a/src/semantics/readylog/utilities.cpp +++ b/src/semantics/readylog/utilities.cpp @@ -146,9 +146,9 @@ string functor_name(EC_word term) { } -vector> plterm_args(EC_word head) { +vector> plterm_args(EC_word head) { EC_word term; - vector> rv; + vector> rv; for (int j = 1; j <= head.arity(); j++) { head.arg(j,term); diff --git a/src/semantics/readylog/utilities.h b/src/semantics/readylog/utilities.h index 772136be..6b94f5c2 100644 --- a/src/semantics/readylog/utilities.h +++ b/src/semantics/readylog/utilities.h @@ -117,7 +117,7 @@ EC_word copy_term(EC_word t); string functor_name(EC_word t); -vector> plterm_args(EC_word t); +vector> plterm_args(EC_word t); class ManagedTerm { diff --git a/src/semantics/readylog/value.h b/src/semantics/readylog/value.h index fe707362..93138678 100644 --- a/src/semantics/readylog/value.h +++ b/src/semantics/readylog/value.h @@ -32,14 +32,13 @@ namespace gologpp { template<> class Semantics -: public Semantics -, public GeneralSemantics +: public GeneralSemantics +, public Semantics { public: Semantics(const Value &value, ReadylogContext &context); using GeneralSemantics::evaluate; - using Semantics::expression; virtual ~Semantics() override = default; diff --git a/src/semantics/readylog/variable.h b/src/semantics/readylog/variable.h index cebf62d1..94d8074f 100644 --- a/src/semantics/readylog/variable.h +++ b/src/semantics/readylog/variable.h @@ -33,7 +33,7 @@ namespace gologpp { template<> class Semantics -: public ReadylogSemantics +: public Semantics , public GeneralSemantics { public: @@ -54,7 +54,6 @@ class Semantics bool dead_; EC_atom golog_var_; bool as_golog_var_; - }; diff --git a/src/tests/gologpp-test.cpp b/src/tests/gologpp-test.cpp index b32eef99..16e26211 100644 --- a/src/tests/gologpp-test.cpp +++ b/src/tests/gologpp-test.cpp @@ -37,8 +37,6 @@ - - using namespace gologpp; namespace po = boost::program_options; @@ -111,12 +109,17 @@ int main(int argc, char **argv) { return -2; } + std::filesystem::path arg0_path { argv[0] }; + eclipse_opts options; options.trace = !vm["trace"].empty() || !vm["guitrace"].empty(); options.toplevel = false; options.guitrace = !vm["guitrace"].empty(); - ReadylogContext::init(options); + ReadylogContext::init( + options, nullptr, nullptr, + { arg0_path.parent_path() / "semantics" / "readylog"} + ); int rv = test_file(unique_ptr(mainproc->ref({}))); diff --git a/src/tools/nativegpp-test.cpp b/src/tools/nativegpp-test.cpp new file mode 100644 index 00000000..c03eb867 --- /dev/null +++ b/src/tools/nativegpp-test.cpp @@ -0,0 +1,91 @@ +/************************************************************************* + * This file is part of golog++. + * + * golog++ is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * golog++ is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with golog++. If not, see . +**************************************************************************/ + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +using namespace gologpp; + + +int test_file(unique_ptr &&mainproc) +{ + shared_ptr f_postcond = global_scope().lookup_global("postcond"); + unique_ptr> postcond; + if (f_postcond) { + postcond.reset(f_postcond->make_ref({})); + postcond->attach_semantics(NativeContext::instance().semantics_factory()); + } + + mainproc->attach_semantics(NativeContext::instance().semantics_factory()); + + NativeContext::instance().run(*mainproc); + + if (postcond) { + log(LogLevel::INF) << "Testing postcond(): " << flush; + bool success = static_cast( + postcond->semantics().evaluate({}, NativeContext::instance().history()) + ); + + if (success) { + log(LogLevel::INF) << "OK" << flush; + return 0; + } + else { + log(LogLevel::ERR) << "FAIL" << flush; + return 1; + } + } + else + return 0; +} + + +int main(int argc, const char **argv) +{ + string filename = SOURCE_DIR "/examples/blocksworld.gpp"; + if (argc > 1) + filename = argv[1]; + + parser::parse_file(filename); + shared_ptr mainproc = global_scope().lookup_global("main"); + if (!mainproc) { + log(LogLevel::ERR) << "No procedure main() in " << filename << flush; + return -2; + } + + int rv = test_file(unique_ptr(mainproc->ref({}))); + + return rv; +} + + + + +