diff --git a/include/loki/details/parser.hpp b/include/loki/details/parser.hpp index 8ad8dfbd..166ef5da 100644 --- a/include/loki/details/parser.hpp +++ b/include/loki/details/parser.hpp @@ -45,7 +45,7 @@ class DomainParser friend class ProblemParser; public: - explicit DomainParser(const fs::path& file_path); + DomainParser(const fs::path& file_path, bool quiet = true); /// @brief Get factories to create additional PDDL objects. PDDLFactories& get_factories(); @@ -73,7 +73,7 @@ class ProblemParser Problem m_problem; public: - explicit ProblemParser(const fs::path& file_path, DomainParser& domain_parser); + explicit ProblemParser(const fs::path& file_path, DomainParser& domain_parser, bool quiet = true); /// @brief Get position caches to be able to reference back to the input PDDL file. const PDDLPositionCache& get_position_cache() const; diff --git a/include/loki/details/pddl/exceptions.hpp b/include/loki/details/pddl/exceptions.hpp index 33aa539f..b346c982 100644 --- a/include/loki/details/pddl/exceptions.hpp +++ b/include/loki/details/pddl/exceptions.hpp @@ -155,10 +155,10 @@ class MismatchedFunctionSkeletonTermListError : public SemanticParserError MismatchedFunctionSkeletonTermListError(const FunctionSkeleton& function_skeleton, const TermList& term_list, const std::string& error_handler_output); }; -class IncompatibleObjectTypeError : public SemanticParserError +class IncompatibleObjectToVariableError : public SemanticParserError { public: - IncompatibleObjectTypeError(const Object& object, const Variable& variable, const std::string& error_handler_output); + IncompatibleObjectToVariableError(const Object& object, const Variable& variable, const std::string& error_handler_output); }; class UnexpectedDerivedPredicateInEffect : public SemanticParserError diff --git a/include/loki/details/pddl/scope.hpp b/include/loki/details/pddl/scope.hpp index b4e7ea1a..3431fcdc 100644 --- a/include/loki/details/pddl/scope.hpp +++ b/include/loki/details/pddl/scope.hpp @@ -67,8 +67,6 @@ class Scope Bindings m_predicates; Bindings m_derived_predicates; - std::unordered_map m_variable_types; - public: Scope(const PDDLErrorHandler& error_handler, const Scope* parent_scope = nullptr); @@ -85,7 +83,6 @@ class Scope std::optional> get_variable(const std::string& name) const; std::optional> get_predicate(const std::string& name) const; std::optional> get_derived_predicate(const std::string& name) const; - const TypeSet& get_variable_types(const Variable& variable) const; /// @brief Insert a binding. void insert_type(const std::string& name, const Type& type, const std::optional& position); @@ -94,7 +91,6 @@ class Scope void insert_variable(const std::string& name, const Variable& variable, const std::optional& position); void insert_predicate(const std::string& name, const Predicate& predicate, const std::optional& position); void insert_derived_predicate(const std::string& name, const Predicate& derived_predicate, const std::optional& position); - void insert_variable_types(const Variable& variable, const TypeSet& types); /// @brief Get the error handler to print an error message. const PDDLErrorHandler& get_error_handler() const; diff --git a/src/utils/exceptions.cpp b/src/exceptions.cpp similarity index 100% rename from src/utils/exceptions.cpp rename to src/exceptions.cpp diff --git a/src/utils/parser.cpp b/src/parser.cpp similarity index 84% rename from src/utils/parser.cpp rename to src/parser.cpp index c3d2e06d..9f00387b 100644 --- a/src/utils/parser.cpp +++ b/src/parser.cpp @@ -35,14 +35,17 @@ namespace loki { -DomainParser::DomainParser(const fs::path& file_path) : +DomainParser::DomainParser(const fs::path& file_path, bool quiet) : m_file_path(file_path), m_source(loki::read_file(file_path)), m_position_cache(nullptr), m_scopes(nullptr) { const auto start = std::chrono::high_resolution_clock::now(); - std::cout << "Started parsing domain file: " << file_path << std::endl; + if (!quiet) + { + std::cout << "Started parsing domain file: " << file_path << std::endl; + } /* Parse the AST */ auto node = ast::Domain(); @@ -83,9 +86,12 @@ DomainParser::DomainParser(const fs::path& file_path) : const auto [vm_usage, resident_set] = process_mem_usage(); const auto stop = std::chrono::high_resolution_clock::now(); auto duration = std::chrono::duration_cast(stop - start); - std::cout << "Finished parsing after " << duration.count() << " milliseconds." << std::endl; - std::cout << "Peak virtual memory: " << vm_usage << " KB." << std::endl; - std::cout << "Peak resident set size: " << resident_set << " KB." << std::endl; + if (!quiet) + { + std::cout << "Finished parsing after " << duration.count() << " milliseconds." << std::endl; + std::cout << "Peak virtual memory: " << vm_usage << " KB." << std::endl; + std::cout << "Peak resident set size: " << resident_set << " KB." << std::endl; + } } PDDLFactories& DomainParser::get_factories() { return m_factories; } @@ -94,14 +100,17 @@ const PDDLPositionCache& DomainParser::get_position_cache() const { return *m_po const Domain& DomainParser::get_domain() const { return m_domain; } -ProblemParser::ProblemParser(const fs::path& file_path, DomainParser& domain_parser) : +ProblemParser::ProblemParser(const fs::path& file_path, DomainParser& domain_parser, bool quiet) : m_file_path(file_path), m_source(loki::read_file(file_path)), m_position_cache(nullptr), m_scopes(nullptr) { const auto start = std::chrono::high_resolution_clock::now(); - std::cout << "Started parsing problem file: " << file_path << std::endl; + if (!quiet) + { + std::cout << "Started parsing problem file: " << file_path << std::endl; + } /* Parse the AST */ auto problem_node = ast::Problem(); @@ -128,9 +137,12 @@ ProblemParser::ProblemParser(const fs::path& file_path, DomainParser& domain_par const auto [vm_usage, resident_set] = process_mem_usage(); const auto stop = std::chrono::high_resolution_clock::now(); auto duration = std::chrono::duration_cast(stop - start); - std::cout << "Finished parsing after " << duration.count() << " milliseconds." << std::endl; - std::cout << "Peak virtual memory: " << vm_usage << " KB." << std::endl; - std::cout << "Peak resident set size: " << resident_set << " KB." << std::endl; + if (!quiet) + { + std::cout << "Finished parsing after " << duration.count() << " milliseconds." << std::endl; + std::cout << "Peak virtual memory: " << vm_usage << " KB." << std::endl; + std::cout << "Peak resident set size: " << resident_set << " KB." << std::endl; + } } const PDDLPositionCache& ProblemParser::get_position_cache() const { return *m_position_cache; } diff --git a/src/pddl/exceptions.cpp b/src/pddl/exceptions.cpp index de5d6e4d..76aaa5df 100644 --- a/src/pddl/exceptions.cpp +++ b/src/pddl/exceptions.cpp @@ -154,7 +154,7 @@ UnexpectedDerivedPredicateInEffect::UnexpectedDerivedPredicateInEffect(const std { } -IncompatibleObjectTypeError::IncompatibleObjectTypeError(const Object& object, const Variable& variable, const std::string& error_handler_output) : +IncompatibleObjectToVariableError::IncompatibleObjectToVariableError(const Object& object, const Variable& variable, const std::string& error_handler_output) : SemanticParserError("The object with name \"" + object->get_name() + "\" does not satisfy the type requirement of variable with name \"" + variable->get_name() + "\".", error_handler_output) diff --git a/src/pddl/parser/ground_literal.cpp b/src/pddl/parser/ground_literal.cpp index 3dd9b01f..9d43c7c8 100644 --- a/src/pddl/parser/ground_literal.cpp +++ b/src/pddl/parser/ground_literal.cpp @@ -20,6 +20,7 @@ #include "common.hpp" #include "loki/details/pddl/exceptions.hpp" #include "objects.hpp" +#include "reference_utils.hpp" namespace loki { @@ -34,15 +35,18 @@ Atom parse(const ast::AtomicFormulaOfNamesPredicate& node, Context& context) throw UndefinedPredicateError(name, context.scopes.top().get_error_handler()(node, "")); } auto term_list = TermList(); + auto positions = PositionList(); for (const auto& name_node : node.names) { term_list.push_back(context.factories.get_or_create_term_object(parse_object_reference(name_node, context))); + positions.push_back(name_node); } const auto [predicate, _position, _error_handler] = binding.value(); if (predicate->get_parameters().size() != term_list.size()) { throw MismatchedPredicateTermListError(predicate, term_list, context.scopes.top().get_error_handler()(node, "")); } + test_consistent_object_to_variable_assignment(predicate->get_parameters(), term_list, positions, context); const auto atom = context.factories.get_or_create_atom(predicate, term_list); context.positions.push_back(atom, node); return atom; diff --git a/src/pddl/parser/literal.cpp b/src/pddl/parser/literal.cpp index a4c95ddc..26c14f61 100644 --- a/src/pddl/parser/literal.cpp +++ b/src/pddl/parser/literal.cpp @@ -19,6 +19,7 @@ #include "common.hpp" #include "loki/details/pddl/exceptions.hpp" +#include "reference_utils.hpp" namespace loki { @@ -32,15 +33,18 @@ Atom parse(const ast::AtomicFormulaOfTermsPredicate& node, Context& context) throw UndefinedPredicateError(predicate_name, context.scopes.top().get_error_handler()(node.predicate, "")); } auto term_list = TermList(); + auto positions = PositionList(); for (const auto& term_node : node.terms) { term_list.push_back(boost::apply_visitor(TermReferenceTermVisitor(context), term_node)); + positions.push_back(term_node); } const auto [predicate, _position, _error_handler] = binding.value(); if (predicate->get_parameters().size() != term_list.size()) { throw MismatchedPredicateTermListError(predicate, term_list, context.scopes.top().get_error_handler()(node, "")); } + test_consistent_object_to_variable_assignment(predicate->get_parameters(), term_list, positions, context); context.references.untrack(predicate); const auto atom = context.factories.get_or_create_atom(predicate, term_list); context.positions.push_back(atom, node); diff --git a/src/pddl/parser/reference_utils.cpp b/src/pddl/parser/reference_utils.cpp index 90ae513f..3b234b23 100644 --- a/src/pddl/parser/reference_utils.cpp +++ b/src/pddl/parser/reference_utils.cpp @@ -17,6 +17,7 @@ #include "reference_utils.hpp" +#include "loki/details/ast/ast.hpp" #include "loki/details/pddl/exceptions.hpp" namespace loki @@ -42,21 +43,14 @@ void test_variable_references(const ParameterList& parameter_list, const Context } } -void track_variable_type_information(const ParameterList& parameter_list, Context& context) +static void test_object_type_consistent_with_variable(const Parameter& parameter, const Object& object, const Position& position, const Context& context) { - for (const auto& parameter : parameter_list) - { - context.scopes.top().insert_variable_types(parameter->get_variable(), collect_types_from_hierarchy(parameter->get_bases())); - } -} - -void test_object_type_consistent_with_variable(const Object& object, const Variable& variable, const Context& context) -{ - const auto& variable_types = context.scopes.top().get_variable_types(variable); + // Object type must match any of those types. + const auto& parameter_types = TypeSet(parameter->get_bases().begin(), parameter->get_bases().end()); bool is_consistent = false; for (const auto& type : collect_types_from_hierarchy(object->get_bases())) { - if (variable_types.count(type)) + if (parameter_types.count(type)) { is_consistent = true; break; @@ -64,8 +58,23 @@ void test_object_type_consistent_with_variable(const Object& object, const Varia } if (!is_consistent) { - const auto [_object, position, error_handler] = context.scopes.top().get_object(object->get_name()).value(); - throw IncompatibleObjectTypeError(object, variable, error_handler(position.value(), "")); + throw IncompatibleObjectToVariableError(object, parameter->get_variable(), context.scopes.top().get_error_handler()(position, "")); + } +} + +void test_consistent_object_to_variable_assignment(const ParameterList& parameters, + const TermList& terms, + const PositionList& positions, + const Context& context) +{ + assert(parameters.size() == terms.size()); + + for (size_t i = 0; i < parameters.size(); ++i) + { + if (const auto term_object = std::get_if(terms[i])) + { + test_object_type_consistent_with_variable(parameters[i], term_object->get_object(), positions[i], context); + } } } diff --git a/src/pddl/parser/reference_utils.hpp b/src/pddl/parser/reference_utils.hpp index 37bb209f..1d2c250e 100644 --- a/src/pddl/parser/reference_utils.hpp +++ b/src/pddl/parser/reference_utils.hpp @@ -31,9 +31,8 @@ extern void track_variable_references(const ParameterList& parameter_list, Conte extern void test_variable_references(const ParameterList& parameter_list, const Context& context); -extern void track_variable_type_information(const ParameterList& parameter_list, Context& context); - -extern void test_object_type_consistent_with_variable(const Object& object, const Variable& variable, const Context& context); +extern void +test_consistent_object_to_variable_assignment(const ParameterList& parameters, const TermList& terms, const PositionList& positions, const Context& context); extern void track_predicate_references(const PredicateList& predicate_list, Context& context); diff --git a/src/pddl/scope.cpp b/src/pddl/scope.cpp index ed4a4994..1108b316 100644 --- a/src/pddl/scope.cpp +++ b/src/pddl/scope.cpp @@ -25,7 +25,7 @@ std::optional> Scope::get_type(const std::string& name { const auto it = m_types.find(name); if (it != m_types.end()) - return std::make_tuple(it->second.first, it->second.second, m_error_handler); + return std::make_tuple(it->second.first, it->second.second, std::cref(m_error_handler)); if (m_parent_scope) { return m_parent_scope->get_type(name); @@ -37,7 +37,7 @@ std::optional> Scope::get_object(const std::string& { const auto it = m_objects.find(name); if (it != m_objects.end()) - return std::make_tuple(it->second.first, it->second.second, m_error_handler); + return std::make_tuple(it->second.first, it->second.second, std::cref(m_error_handler)); if (m_parent_scope) { return m_parent_scope->get_object(name); @@ -49,7 +49,7 @@ std::optional> Scope::get_function_skeleto { const auto it = m_function_skeletons.find(name); if (it != m_function_skeletons.end()) - return std::make_tuple(it->second.first, it->second.second, m_error_handler); + return std::make_tuple(it->second.first, it->second.second, std::cref(m_error_handler)); if (m_parent_scope) { return m_parent_scope->get_function_skeleton(name); @@ -61,7 +61,7 @@ std::optional> Scope::get_variable(const std::stri { const auto it = m_variables.find(name); if (it != m_variables.end()) - return std::make_tuple(it->second.first, it->second.second, m_error_handler); + return std::make_tuple(it->second.first, it->second.second, std::cref(m_error_handler)); if (m_parent_scope) { return m_parent_scope->get_variable(name); @@ -73,7 +73,7 @@ std::optional> Scope::get_predicate(const std::st { const auto it = m_predicates.find(name); if (it != m_predicates.end()) - return std::make_tuple(it->second.first, it->second.second, m_error_handler); + return std::make_tuple(it->second.first, it->second.second, std::cref(m_error_handler)); if (m_parent_scope) { return m_parent_scope->get_predicate(name); @@ -85,7 +85,7 @@ std::optional> Scope::get_derived_predicate(const { const auto it = m_derived_predicates.find(name); if (it != m_derived_predicates.end()) - return std::make_tuple(it->second.first, it->second.second, m_error_handler); + return std::make_tuple(it->second.first, it->second.second, std::cref(m_error_handler)); if (m_parent_scope) { return m_parent_scope->get_derived_predicate(name); @@ -93,23 +93,6 @@ std::optional> Scope::get_derived_predicate(const return std::nullopt; } -const TypeSet& Scope::get_variable_types(const Variable& variable) const -{ - const auto it = m_variable_types.find(variable); - if (it != m_variable_types.end()) - { - return it->second; - } - if (m_parent_scope) - { - return m_parent_scope->get_variable_types(variable); - } - else - { - throw std::logic_error("Expected types of variable to be known."); - } -} - void Scope::insert_type(const std::string& name, const Type& element, const std::optional& position) { assert(!this->get_type(name)); @@ -146,12 +129,6 @@ void Scope::insert_derived_predicate(const std::string& name, const Predicate& e m_derived_predicates.emplace(name, BindingValueType(element, position)); } -void Scope::insert_variable_types(const Variable& variable, const TypeSet& types) -{ - assert(!this->m_variable_types.count(variable)); - m_variable_types.emplace(variable, types); -} - const PDDLErrorHandler& Scope::get_error_handler() const { return m_error_handler; } ScopeStack::ScopeStack(const PDDLErrorHandler& error_handler, const ScopeStack* parent) : m_error_handler(error_handler), m_parent(parent) {}