Mach7 icon indicating copy to clipboard operation
Mach7 copied to clipboard

Compile time error with if Members macro gets more than 10 arguments

Open forflo opened this issue 8 years ago • 8 comments

Hi Yuriy,

I'm not sure whether this is a bug or a known limitation of C's macro system, although I can hardly believe the latter.

I tried to add all members of the huge class ScopeBase. My first attempt caused the compiler to emit about 140 lines of error messages, quickly resigning after 20 reported errors. I later realized that the compilation error depends on the number of arguments passed to Members. The file traverse_all.cc shows exactly what I mean. The current version of the file does not compile. However, if one comments out an arbitrary argument (for example ScopeBase::use_types_), the example builds again.

Here is the error message:

traverse_all.cc:69:9: error: use of undeclared identifier 'XTL_REPEAT_WITH_ScopeBase'
        Members(ScopeBase::old_signals_, //map<perm_string, Signal*>
        ^
mach7/patterns/bindings.hpp:169:87: note: expanded from macro 'Members'
    #define Members(...)                                                XTL...
                                                                                      ^
mach7/macros.hpp:121:29: note: expanded from macro 'XTL_REPEAT'
#define XTL_REPEAT(n,m,...) XTL_REPEAT_WITH(,n,m,__VA_ARGS__)
                            ^
mach7/macros.hpp:119:36: note: expanded from macro 'XTL_REPEAT_WITH'
#define XTL_REPEAT_WITH(s,n,m,...) XTL_REPEAT_WITH_ ## n(s,m,__VA_ARGS__)
                                   ^
<scratch space>:181:1: note: expanded from here
XTL_REPEAT_WITH_ScopeBase
^
traverse_all.cc:69:9: error: expected parameter declarator
mach7/patterns/bindings.hpp:169:87: note: expanded from macro 'Members'
    #define Members(...)                                                 XTL...
                                                                                      ^
mach7/macros.hpp:121:29: note: expanded from macro 'XTL_REPEAT'
#define XTL_REPEAT(n,m,...) XTL_REPEAT_WITH(,n,m,__VA_ARGS__)
                            ^
mach7/macros.hpp:119:59: note: expanded from macro 'XTL_REPEAT_WITH'
#define XTL_REPEAT_WITH(s,n,m,...) XTL_REPEAT_WITH_ ## n(s,m,__VA_ARGS__)
                                                          ^
traverse_all.cc:69:9: error: C++ requires a type specifier for all declarations
mach7/patterns/bindings.hpp:169:120: note: expanded from macro 'Members'
  ...XTL_REPEAT(XTL_NARG(__VA_ARGS__),CMa,__VA_ARGS__)
                                      ^
traverse_all.cc:69:28: error: no type named 'old_signals_' in 'ScopeBase'
        Members(ScopeBase::old_signals_, //map<perm_string, Signal*>
                ~~~~~~~~~~~^
mach7/patterns/bindings.hpp:169:124: note: expanded from macro 'Members'
  ...XTL_REPEAT(XTL_NARG(__VA_ARGS__),CMa,__VA_ARGS__)
                                          ^~~~~~~~~~~
mach7/macros.hpp:121:50: note: expanded from macro 'XTL_REPEAT'
#define XTL_REPEAT(n,m,...) XTL_REPEAT_WITH(,n,m,__VA_ARGS__)
                                                 ^~~~~~~~~~~
mach7/macros.hpp:119:62: note: expanded from macro 'XTL_REPEAT_WITH'
#define XTL_REPEAT_WITH(s,n,m,...) XTL_REPEAT_WITH_ ## n(s,m,__VA_ARGS__)

Best regards

forflo avatar Jul 01 '16 23:07 forflo

I'd have to look in details to tell you anything with certainty, but here are a few things to try. First of all, remove all the comments after each argument just to eliminate the potential for errors. Second, put all arguments on one line to see whether that helps. Third, and the most important one, pay attention to whether any of the arguments have any coma inside them e.g. MyTemplate<A,B,C> is a single term for C++, but that would be treated as 3 different arguments by the preprocessor. Preprocessor respects only ( and ) scoping, so you might need to explicitly take such arguments into ( ) when possible or typedef to a dedicated name before passing into a variadic macro Members.

solodon4 avatar Jul 02 '16 00:07 solodon4

P.S. Also you seem to have 11 arguments and AFAIR I only made the overloaded macro expansion work for up to 10 arguments, so check if it works with smaller number of arguments.

solodon4 avatar Jul 02 '16 00:07 solodon4

P.P.S. Just read the title of your post: if it works for 10, yes, that's the current limitation, which I thought would be more than sufficient. I've never seen product types with 10 arguments in functional programs, can you elaborate on why you need this many? You sure don't need to expose everything. What are you trying to do?

The library also supports views where a given class can have multiple layouts for pattern matching: e.g. a complex number can be viewed in Cartesian and Polar representation. See this example for how it works and then check the adapter it includes

#include <mach7/adapters/std/complex.hpp>  // Mach7 bindings for std::complex<T>

for how to define multiple views into the same datatype.

solodon4 avatar Jul 02 '16 00:07 solodon4

functional programs, can you elaborate on why you need this many?

Yes, of course.

I'm writing this VHDL frontend for my graduation. Because of the lack of time, I had to reuse a (more or less) ready-to-use Bison/C++ Parser that already provided the underlying classes used to create an AST. The author of this parser had to cope with the fact that the ambiguity of VHDL's grammar can only be resolved in linear time if the parser itself is scope aware. Therefore there exists a huge class ScopeBase carrying around all scope related details. This class has a lot more than 10 non-static members which are intensely used throughout the remaining code base.

But as I already had to make all members public, I can as well just use the normal member access operator on the ScopeBase object.

forflo avatar Jul 02 '16 11:07 forflo

My motivation for the excessive binding declaration from traverse_all.cc simply was improved code clarity.

forflo avatar Jul 02 '16 11:07 forflo

What I meant was you don't have to expose all of them via pattern matching positions - you can expose only the most typical ones, for example when they can be used to do nested checks etc. For all others, you can access directly the members of the class. Each Case clause made for N subjects declares variables match0, match1, ... matchN-1 that are bound to the most derived type uncovered by that clause. See this example and how it accesses members of match0 depending of what case was uncovered (e.g. member e is only available for Not, while e1, e2 available for binary operations).

solodon4 avatar Jul 02 '16 22:07 solodon4

By writing,

But as I already had to make all members public, I can as well just use the normal member access operator on the ScopeBase object.

I meant exactly the same thing.

forflo avatar Jul 03 '16 12:07 forflo

@solodon4

I've never seen product types with 10 arguments in functional programs, can you elaborate on why you need this many?

I'm one of developers of Scala language that currently has limitation on 22 elements in tupples & pattern matching. We're working on lifting this limitations due to demand from the community. The common use-case when this limit hits hard is when your data-type represents an enty in a database, and while it's not very common to have a table with more than 22 entries, the SQL JOIN operation can easily create a result set with a big number of columns.

DarkDimius avatar Feb 24 '17 12:02 DarkDimius