Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Fun with macros :)

49 views
Skip to first unread message

Alf P. Steinbach

unread,
Feb 1, 2017, 2:42:38 AM2/1/17
to
Example of using macros to introduce more expressive (but weird)
pseudo-keywords in the Niklaus Wirth-languages direction:

[code]
// Encoding: UTF-8 with BOM.
// Copyright © 2017 Alf P. Steinbach

#include "windowsx_h/parsing.hpp" // windowsx_h::(Crackers, parse*)
#include <nlohmann/json.hpp> // nlohmann::*

#include <iostream> // std::(cin, cout, <<, endl)

#include <p/cppx/expressive.hpp> // progrock::cppx::expressive::*
using_nested_namespacE( progrock, cppx );

namespace windowsx_h {
namespace nlm = nlohmann;
using_all_from_namespacE( cppx::expressive );

procedurE to_json( ref_<nlm::json> j, ref_<Function const> func )
{
namE o = func;
j = nlm::json
{
{ "args", o.args },
{ "base_name", o.base_name },
{ "result_type", o.result_type }
};
}

procedurE to_json( ref_<nlm::json> j, ref_<Argument const> arg )
{
namE o = arg;
j = nlm::json
{
{ "name", o.name },
{ "type", o.type }
};
}

procedurE to_json( ref_<nlm::json> j, ref_<Call_spec const> call_spec )
{
namE o = call_spec;
j = nlm::json
{
{ "arg_expressions", o.arg_expressions },
{ "result_cast", o.result_cast }
};
}

procedurE to_json( ref_<nlm::json> j, ref_<Message_cracker const>
cracker )
{
namE o = cracker;
j = nlm::json
{
{ "handler", o.handler },
{ "call_spec", o.call_spec }
};
}

procedurE to_json( ref_<nlm::json> j, ref_<Crackers const> crackers )
{
namE o = crackers;
j = nlm::json
{
{ "by_message", o.by_message }
};
}
} // namespace windowsx_h

using namespace std;
namespace nlm = nlohmann;
using_all_from_namespacE( cppx::expressive );
namespace app {
procedurE generate_json_for(
ref_<windowsx_h::Crackers const> crackers,
ref_<ostream> stream
)
{
nlm::json const j{ crackers };
stream << j.dump( 4 ) << endl;
}

procedurE cpp_main()
{
leT crackers = windowsx_h::parse( cin );
app::generate_json_for( crackers, cout );
}
} // namespace app

functioN main()
-> int
{
using cppx::Exit_code;
try
{
app::cpp_main();
return Exit_code::success;
}
catch( exception const& x )
{
cerr << "!" << x.what() << endl;
}
return Exit_code::failure;
}
[/code]


where


[code]
#pragma once
// #include <p/cppx/expressive/pseudo_keywords.hpp>
// Copyright © 2017 Alf P. Steinbach

#define functioN auto
#define procedurE void

#define leT auto const
#define namE auto&
#define readonly_namE auto const&

#define repeaT do{
#define untiL }while

#define for_eacH for

// TODO: make variadic
#define using_from_namespaceE( ns, thingy ) \
using ns::thingy

#define using_all_from_namespacE( ns ) \
using namespace ns;

#define using_nested_namespacE( ns, nested ) \
namespace nested = ns::nested

#define lambdA( ... ) [__VA_ARGS__]
[/code]


Cheers!, :-p

- Alf

Juha Nieminen

unread,
Feb 1, 2017, 2:58:20 AM2/1/17
to
Alf P. Steinbach <alf.p.stein...@gmail.com> wrote:
> #include "windowsx_h/parsing.hpp" // windowsx_h::(Crackers, parse*)
> #include <nlohmann/json.hpp> // nlohmann::*

And this should be of interest to us why, exactly?

Alf P. Steinbach

unread,
Feb 1, 2017, 3:55:32 AM2/1/17
to
Apparently you're speaking for you family. I guess they're not into C++
much, and I didn't mean my posting to be read by them. Regarding your
quote it's pretty irrelevant about anything, except if you don't know a
nice JSON parser and generator: then, Nils Lohmann's is ¹pretty OK.

Cheers & hth.,

- Alf

Notes:
¹ I had to fix his source just a tiny teeny little bit to make it
compile with Visual C++ 2015 update 2.

Alf P. Steinbach

unread,
Feb 1, 2017, 11:31:45 AM2/1/17
to
On 01.02.2017 08:41, Alf P. Steinbach wrote:
> procedurE cpp_main()
> {
> leT crackers = windowsx_h::parse( cin );
> app::generate_json_for( crackers, cout );
> }

Instead of avoiding name clashes via that silly trailing uppercase
convention, I figured one could use a special leading character.

After all C++ supports a wide range of Unicode in identifiers.

However, the g++ compiler doesn't support that, even with option
`-fextended-identifiers`.

But both g++, Visual C++ and clang, and I suspect also most other C++
compilers, support `$` in identifiers. The `$` sign is not formally part
of the basic C++ source character set, I think because of politics: at
one time the `$` was changed to the über-silly completely and utterly
useless ¹“universal currency sign” `¤` in ASCII. And the name of ASCII
was changed too, I don't recall the details.

So, as a concrete example, instead of the above one can write,

$procedure cpp_main()
{
$let crackers = windowsx_h::parse( cin );
app::generate_json_for( crackers, cout );
}

as a Pascal/Modula/Oberon-like more-readable-for-novices C++, with
pretty clear meaning, which after macro replacement is

void cpp_main()
{
auto const crackers = windowsx_h::parse( cin );
app::generate_json_for( crackers, cout );
}

using keywords `void` and `auto` with multiple context-dependent
meanings which must be figured out.

The use of `$` here is non-standard, and consequently clang emits a
warning in pedantic mode unless the option
`-Wdollar-in-identifier-extension` is used. Formally, after emitting a
diagnostic for use of a language extension, a compiler can just go on
compiling and accepting the source code. And the standard doesn't define
what a diagnostic is, it doesn't impose any requirements on diagnostics,
so the requisite diagnostic can be e.g. that the compiler blinks a
single pixel on the screen for about 1/70th of a second, say. Anyway the
nice thing about non-standard is that it's extremely unlikely that
anyone has used these identifiers. Yet. They're up for grabs, with the 3
main compilers. :)


Cheers!,

- Alf

Links:
¹ <url: https://en.wikipedia.org/wiki/Currency_sign_(typography)>

red floyd

unread,
Feb 1, 2017, 11:42:29 AM2/1/17
to
Not to mention that the semantics of his untiL macro are wrong.

Alf P. Steinbach

unread,
Feb 1, 2017, 11:46:58 AM2/1/17
to
Bah, who cares about exclamation marks!!!!!

Cheers?,

- Alf

Mr Flibble

unread,
Feb 1, 2017, 1:09:10 PM2/1/17
to
On 01/02/2017 07:41, Alf P. Steinbach wrote:
> Example of using macros to introduce more expressive (but weird)
> pseudo-keywords in the Niklaus Wirth-languages direction:
>
> [code]
> #pragma once
> // #include <p/cppx/expressive/pseudo_keywords.hpp>
> // Copyright © 2017 Alf P. Steinbach
>
> #define functioN auto
> #define procedurE void
>
> #define leT auto const
> #define namE auto&
> #define readonly_namE auto const&
>
> #define repeaT do{
> #define untiL }while
>
> #define for_eacH for
>
> // TODO: make variadic
> #define using_from_namespaceE( ns, thingy ) \
> using ns::thingy
>
> #define using_all_from_namespacE( ns ) \
> using namespace ns;
>
> #define using_nested_namespacE( ns, nested ) \
> namespace nested = ns::nested
>
> #define lambdA( ... ) [__VA_ARGS__]
> [/code]

Doing such things makes C++ code harder to read not easier. Avoid
macros, period.

/Flibble

Daniel

unread,
Feb 1, 2017, 1:26:21 PM2/1/17
to
On Wednesday, February 1, 2017 at 1:09:10 PM UTC-5, Mr Flibble wrote:
>
> Doing such things makes C++ code harder to read not easier. Avoid
> macros, period.
>
Except when you can't, of course.

Alf P. Steinbach

unread,
Feb 2, 2017, 10:06:16 AM2/2/17
to
On 01.02.2017 19:08, Mr Flibble wrote:
>
> Doing such things makes C++ code harder to read not easier. Avoid
> macros, period.

Well, I wonder.

I enjoy exploring things to see where and what it leads to, and here's
some example (real) code – the `$xxx` names are macros:

struct Argument
{
string name;
string type;
};

struct Function
{
string base_name;
string result_type;
vector<Argument> args;
};

inline $function to_string( ref_<const Argument> arg )
-> string
{ return arg.type + " " + arg.name; }

inline $function to_string( ref_<const Function> f )
-> string
{
string result = f.base_name;
for( $each item : enumerated( f.args ) )
{
if( not item.is_first() ) { result += ", "; }
result += to_string( item.object() );
}
if( n_items_in( f.args ) > 0 ) { result = ' ' + result + ' '; }
result = '(' + result + ')';
return
$case( f.result_type == "void", "void " + result )
$default( "inline auto " + result + " -> " + f.result_type );
}

The readability goal I set here was to get rid of all `auto` (it really
has a lot of meanings now, conceptually quite different meanings), and
all `&` and `*` used as type builders, and all weird operator notation
like `:?`, plus, support prefix `const` in general.

I think, maybe inside C++ there's a more streamlined and readable
language struggling to get out. Possibly. :)

Maybe I should continue my exploration of Rust, though; I barely started...


Cheers!,

- Alf

0 new messages