2

I have a boost::spirit parser that is supposed to simply assign a pointer to its attribute:

rule<CompoundExpression *(Scope &)> var_ref = var<CompoundExpression>()(_r1) [
    _val = new_<Reference<Variable<CompoundExpression>>>(_1)
];

where var<CompoundExpression>() is a just function that returns a reference to a static rule that does the actual parsing. I use the same assignment action with other instantiations of the Reference<Variable<T>> template all over the code and it's fine, except for the one that uses the CompoundExpression parameter.

The literal GCC error is this:

In file included from /usr/include/boost/phoenix/core/actor.hpp:20,
                 from /usr/include/boost/phoenix/core.hpp:12,
                 from /usr/include/boost/spirit/include/phoenix_core.hpp:11,
                 from /usr/include/boost/spirit/home/support/argument.hpp:18,
                 from /usr/include/boost/spirit/home/qi/nonterminal/rule.hpp:29,
                 from /usr/include/boost/spirit/home/qi/nonterminal.hpp:14,
                 from /usr/include/boost/spirit/include/qi_nonterminal.hpp:16,
                 from /home/ich/sync/ConTrAkt/gologpp/src/parser/utilities.h:7,
                 from /home/ich/sync/ConTrAkt/gologpp/src/parser/compound_expression.h:4,
                 from /home/ich/sync/ConTrAkt/gologpp/src/parser/compound_expression.cpp:1:
/usr/include/boost/phoenix/core/is_nullary.hpp: In instantiation of ‘struct boost::phoenix::result_of::is_nullary<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::assign, boost::proto::argsns_::list2<boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::attribute<0> >, 0>, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::phoenix::tag::new_, boost::proto::argsns_::list2<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::phoenix::detail::target<gologpp::Reference<gologpp::Variable<gologpp::TypedExpression<gologpp::CompoundType> > > > >, 0>, boost::phoenix::actor<boost::spirit::argument<0> > >, 2> > >, 2>, void>’:
/usr/include/boost/phoenix/core/actor.hpp:178:13:   required from ‘struct boost::phoenix::result_of::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::assign, boost::proto::argsns_::list2<boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::attribute<0> >, 0>, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::phoenix::tag::new_, boost::proto::argsns_::list2<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::phoenix::detail::target<gologpp::Reference<gologpp::Variable<gologpp::TypedExpression<gologpp::CompoundType> > > > >, 0>, boost::phoenix::actor<boost::spirit::argument<0> > >, 2> > >, 2> >’
/usr/include/boost/phoenix/core/actor.hpp:271:9:   required from ‘struct boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::assign, boost::proto::argsns_::list2<boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::attribute<0> >, 0>, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::phoenix::tag::new_, boost::proto::argsns_::list2<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::phoenix::detail::target<gologpp::Reference<gologpp::Variable<gologpp::TypedExpression<gologpp::CompoundType> > > > >, 0>, boost::phoenix::actor<boost::spirit::argument<0> > >, 2> > >, 2> >’
/home/ich/sync/ConTrAkt/gologpp/src/parser/compound_expression.cpp:22:58:   required from here
/usr/include/boost/phoenix/core/is_nullary.hpp:115:16: error: base type ‘boost::phoenix::evaluator::impl<const boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::assign, boost::proto::argsns_::list2<boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::attribute<0> >, 0>, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::phoenix::tag::new_, boost::proto::argsns_::list2<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::phoenix::detail::target<gologpp::Reference<gologpp::Variable<gologpp::TypedExpression<gologpp::CompoundType> > > > >, 0>, boost::phoenix::actor<boost::spirit::argument<0> > >, 2> > >, 2>&, boost::phoenix::vector2<mpl_::bool_<true>, boost::phoenix::is_nullary>, boost::proto::envns_::empty_env>::result_type’ {aka ‘const boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::assign, boost::proto::argsns_::list2<boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::attribute<0> >, 0>, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::phoenix::tag::new_, boost::proto::argsns_::list2<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::phoenix::detail::target<gologpp::Reference<gologpp::Variable<gologpp::TypedExpression<gologpp::CompoundType> > > > >, 0>, boost::phoenix::actor<boost::spirit::argument<0> > >, 2> > >, 2>&’} fails to be a struct or class type
         struct is_nullary
                ^~~~~~~~~~

Since that is virtually unreadable, I'll try to clang-format it. So I guess it comes down to the last line:

/usr/include/boost/phoenix/core/is_nullary.hpp:115:16: error: base type
‘boost::phoenix::evaluator::impl<
    const boost::proto::exprns_::basic_expr<
        boost::proto::tagns_::tag::assign,
        boost::proto::argsns_::list2<
            boost::proto::exprns_::expr<
                boost::proto::tagns_::tag::terminal,
                boost::proto::argsns_::term<boost::spirit::attribute<0>>, 0>,
            boost::phoenix::actor<boost::proto::exprns_::basic_expr<
                boost::phoenix::tag::new_,
                boost::proto::argsns_::list2<
                    boost::proto::exprns_::basic_expr<
                        boost::proto::tagns_::tag::terminal,
                        boost::proto::argsns_::term<
                            boost::phoenix::detail::target<gologpp::Reference<
                                gologpp::Variable<gologpp::TypedExpression<
                                    gologpp::CompoundType>>>>>,
                        0>,
                    boost::phoenix::actor<boost::spirit::argument<0>>>,
                2>>>,
        2> &,
    boost::phoenix::vector2<mpl_::bool_<true>, boost::phoenix::is_nullary>,
    boost::proto::envns_::empty_env>::result_type’ {
    aka ‘const boost::proto::exprns_::basic_expr<
        boost::proto::tagns_::tag::assign,
        boost::proto::argsns_::list2<
            boost::proto::exprns_::expr<
                boost::proto::tagns_::tag::terminal,
                boost::proto::argsns_::term<boost::spirit::attribute<0>>, 0>,
            boost::phoenix::actor<boost::proto::exprns_::basic_expr<
                boost::phoenix::tag::new_,
                boost::proto::argsns_::list2<
                    boost::proto::exprns_::basic_expr<
                        boost::proto::tagns_::tag::terminal,
                        boost::proto::argsns_::term<
                            boost::phoenix::detail::target<gologpp::Reference<
                                gologpp::Variable<gologpp::TypedExpression<
                                    gologpp::CompoundType>>>>>,
                        0>,
                    boost::phoenix::actor<boost::spirit::argument<0>>>,
                2>>>,
        2> &’}
fails to be a struct or class type

Note that gologpp::TypedExpression<gologpp::CompoundType is typedef'd as gologpp::CompoundExpression

Now if I'm reading that correctly, this base type of result_of::is_nullary (/usr/include/boost/phoenix/core/is_nullary.hpp:115) somehow happens to be a reference type and that is the problem. My Reference<Variable<CompoundExpression>> type seems perfectly fine, I can construct objects from it and otherwise use it as I'd expect. Also the problem it seems is with the whole phoenix assignment expression, and not with its LHS or RHS.

Looking at boost/phoenix/core/is_nullary.hpp:115:

        struct is_nullary
            : boost::phoenix::evaluator::impl<
                Expr const &
              , vector2<
                    mpl::true_
                  , boost::phoenix::is_nullary
                >
              , proto::empty_env
            >::result_type
        {};

It seems to that somehow Expr const & (which in my case is the assignment expression) is becoming the result_type, which shouldn't happen. But then why does it and how could I be causing it?

Victor Mataré
  • 2,446
  • 2
  • 16
  • 20
  • btw, I know I shouldn't be using `new_` in spirit actions, but I need the polymorphism, so I'm compromising there for the sake of simplicity. – Victor Mataré Mar 01 '19 at 20:56
  • You also shouldn't be returning rules from functions, mostly. But we don't have the relevant code to see what is the actuall issue. Try making a SSCCE/MVCE – sehe Mar 01 '19 at 21:58
  • Is it from https://github.com/MASKOR/gologpp/tree/master/src/parser ? If so, what revision has the problem? – sehe Mar 01 '19 at 22:00
  • It wasn't on github, yet, but I've pushed it now: https://github.com/MASKOR/gologpp/tree/vmatare/composite_types – Victor Mataré Mar 02 '19 at 13:17
  • To trigger the error you'll probably have to `cmake` with `-DBUILD_READYLOG_IMPL=off` because that part isn't ready yet. – Victor Mataré Mar 02 '19 at 13:23
  • 2
    Oh I think I've found it. I had a hunch it was something stupid. Looks like I forgot an include on the header side. But the error message resulting from that has quite the potential to confuse... – Victor Mataré Mar 02 '19 at 14:29

1 Answers1

6

OK, so it looks like I also need to

#include <boost/phoenix/object/dynamic_cast.hpp>
#include <boost/phoenix/operator/self.hpp>

for the polymorphic assignment to work. Something I didn't notice because it was indirectly included in other cases.

Victor Mataré
  • 2,446
  • 2
  • 16
  • 20