Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
forflo opened this issue Jul 1, 2016 · 8 comments
Open

Comments

@forflo
Copy link

forflo commented Jul 1, 2016

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

@solodon4
Copy link
Owner

solodon4 commented Jul 2, 2016

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
Copy link
Owner

solodon4 commented Jul 2, 2016

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
Copy link
Owner

solodon4 commented Jul 2, 2016

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.

@forflo
Copy link
Author

forflo commented Jul 2, 2016

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
Copy link
Author

forflo commented Jul 2, 2016

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

@solodon4
Copy link
Owner

solodon4 commented Jul 2, 2016

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).

@forflo
Copy link
Author

forflo commented Jul 3, 2016

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.

@DarkDimius
Copy link

@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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants