"$$$" C++ Extension: Ruby Symbols and Lazy Enums

Anything and everything that's related to OGRE or the wider graphics field that doesn't fit into the other forums.
User avatar
betajaen
OGRE Moderator
OGRE Moderator
Posts: 3447
Joined: Mon Jul 18, 2005 4:15 pm
Location: Wales, UK
Contact:

"$$$" C++ Extension: Ruby Symbols and Lazy Enums

Post by betajaen » Thu Feb 11, 2010 9:47 pm

Betajaen, What is this?

"$$$" is a Ruby script that browses your source code before compilation and generates extra source code for you. It's main purpose is to extend C++ to include Ruby Symbols and Lazy Enum definition.

1. It borrows the idea of "Symbols" from Ruby, which is a class that is both an integer and a string. Symbols are very fast with maps (due to the integer component), but be usefull and readable when you want to serialise them (due to the string component). The symbol code is very small and only takes the same amount of bytes as an unsigned int.

2. Being pestered by Jacmoe, I've added "Lazy" enums. You can define enums in the middle of the code, which the Ruby parser will pre-create the Enum, and even classes to convert them into strings back and forth.

It doesn't alter your source code at all, it just writes two extra files for your compiler to use.

How do I use it? Is it complicated?

To introduce a Symbol or String into code, you need to prefix it with a dollar sign. "$", it should be on every keyboard and Visual Studio seems fine with it as syntax. Next you just need to follow the simple rules; Use CamelCase and if it has an underscore (_) then it's an enum.

Code: Select all

$name // Symbol
$wowThisIsAReallyLongNameForASymbolIsntIt // Symbol
$aaaaa // Symbol
$name // Symbol, already defined.

$Priority_Low  // Enum named Priority, with a value Low.
$Priority_High // Same as above but High
To the C++ compiler; A Symbol is an instance of the Symbol class in the global namespace, and a Lazy Enum is an actual Enum value. You can use them both normally in your code.

Features

Symbols and Lazy Enums can be converted into strings and back if you so wish.

Code: Select all

std::string name = $Name.str();        => "Name"
std::cout << $Name << "\n";            => "Name"
Enums<Priority>::str($Priority_Low)    => "Low"
Enums<Priority>::priority("Low")       => $Priority_Low
Using it in real code

Code: Select all

#include "AutoGenerated.h"

#include "ExampleWorkQueue.h"
#include <string>
#include <map>

class Message
{
  public:
        
        Message(const std::string& to, const std::string& from, Priority = $Priority_Medium)
        : mTo(to), mFrom(from), mPriority(priority)
        {
        }
        
        void addData(const Symbol& field_name, const std::string& value)
        {
            data[field_name] = value;
        }
  
        void send()
        {
            if (mPriority == $Priority_Important)
                gWorkQueue.push_front(*this);
            else
                gWorkQueue.push_back(*this);
        }  
        
  protected:
        
        std::string mTo, mFrom;
        Priority mPriority;
        std::map<Symbol, std::string> mData;
};

void main()
{
    Message message1("betajaen", "jacmoe", $Priority_Low);
    message1.addData($Content, "Begon fowl beastie!");
    message1.send();
    
    Message message2("betajaen", "sinbad", $Priority_Important);
    message2.addData($Content, "Help! Message server is on fire!");
    message2.addData($Attachment, base64(get_photo()));
    message2.send();
}
Wow, I want this. How do I install and use it?

1. Ruby is required. So you can fetch that off the internet somewhere. Use the Windows installer if you can.
2. Download the attachment.
3. Copy "$$$.rb", "AutoGenerated.cpp", "AutoGenerated.h" to your source folder
4. Add both .cpp and .h files into your project file.
5. In Visual Studio (other compilers would be similar), Goto your project settings, BuildEvents, Pre-Build Event then add "ruby $$$.rb" to the CommandLine option.
6. Compile.

Each time you now do a compile, it'll browse the source and generate the enums and symbols for you.

Future plans?

- Ruby "Intern" function which will turn any string to a Symbol.
Attachments
$$$_0.2.1.zip
(3.39 KiB) Downloaded 19 times
Last edited by betajaen on Fri Feb 12, 2010 9:10 pm, edited 2 times in total.
0 x

User avatar
jacmoe
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 20570
Joined: Thu Jan 22, 2004 10:13 am
Location: Denmark
Contact:

Re: C++ Extension: Ruby style Symbols

Post by jacmoe » Thu Feb 11, 2010 10:07 pm

If this is as neat in practice as it looks, it's really neat! :)
Definitely going to try that - even if it means installing Ruby.
So, thumbs up from me. :D

Anything which can make C++ less sucky is appreciated.
0 x
/* Less noise. More signal. */
Ogitor Scenebuilder - powered by Ogre, presented by Qt, fueled by Passion.
OgreAddons - the Ogre code suppository.

User avatar
betajaen
OGRE Moderator
OGRE Moderator
Posts: 3447
Joined: Mon Jul 18, 2005 4:15 pm
Location: Wales, UK
Contact:

Re: C++ Extension: Ruby style Symbols

Post by betajaen » Thu Feb 11, 2010 11:06 pm

jacmoe wrote:Definitely going to try that - even if it means installing Ruby
Oh everyone should have Ruby. It's a neat little language to annoying problems which would take too long to implement in C++. Over half my utility scripts are Ruby based.
0 x

CABAListic
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 2903
Joined: Thu Jan 18, 2007 2:48 pm
Contact:

Re: C++ Extension: Ruby style Symbols

Post by CABAListic » Thu Feb 11, 2010 11:14 pm

I'm assuming that the Ruby script is only a cosmetic extra for parsing things like "$identifier"? I mean, you could just use normal C++ like Symbol("identifier") instead. :)
0 x

User avatar
betajaen
OGRE Moderator
OGRE Moderator
Posts: 3447
Joined: Mon Jul 18, 2005 4:15 pm
Location: Wales, UK
Contact:

Re: C++ Extension: Ruby style Symbols

Post by betajaen » Thu Feb 11, 2010 11:30 pm

A bit of both. Your way it has to recalculate the hash for "identifier", allocate memory and so forth. So if you use Symbol("mime") ten times, you have ten allocations

My Ruby way, it just allocates it once in the global namespace for you. Only one mime, shared many times. ;)

Code: Select all

// Autogenerated file by do_symbols.rb
#ifndef SYMBOLS_H
#define SYMBOLS_H

#include "Symbol.h"

static const Symbol $mime("mime");
static const Symbol $mime_version("mime_version");
static const Symbol $data("data");
static const Symbol $sender("sender");

#endif
0 x

User avatar
jacmoe
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 20570
Joined: Thu Jan 22, 2004 10:13 am
Location: Denmark
Contact:

Re: C++ Extension: Ruby style Symbols

Post by jacmoe » Thu Feb 11, 2010 11:43 pm

It does save time for lots of 'mimes' - whatever it is :)
Looking forward to seeing this develop.

I found this, but it uses Lisp (Good for me!) ->
http://code.google.com/p/enumgen/
Slightly different thing, but related.

But I like the Betajaen approach. :wink:
0 x
/* Less noise. More signal. */
Ogitor Scenebuilder - powered by Ogre, presented by Qt, fueled by Passion.
OgreAddons - the Ogre code suppository.

User avatar
betajaen
OGRE Moderator
OGRE Moderator
Posts: 3447
Joined: Mon Jul 18, 2005 4:15 pm
Location: Wales, UK
Contact:

Re: C++ Extension: Ruby style Symbols

Post by betajaen » Thu Feb 11, 2010 11:47 pm

You could probably alter my script to do your enums:

- Just remove the string bits from Symbol and the hashing function.
- Have a static int counter.
- Set "i" in Symbol to counter++ in the Symbol constructor.

Instant on the fly enums!

[Edit]

Code: Select all

#include "enums.h"

Enum getTransferMode()
{
 if (data > 50)
  return $$Mixed;
 else
  return $$Half;
}
Use "$$EnumName" to define the Enum.

See attached. Haven't tested or compiled it though. ;)
Attachments
Enums.zip
(1.05 KiB) Downloaded 13 times
0 x

User avatar
Klaim
Old One
Posts: 2565
Joined: Sun Sep 11, 2005 1:04 am
Location: Paris, France
Contact:

Re: C++ Extension: Ruby style Symbols

Post by Klaim » Fri Feb 12, 2010 12:04 am

I'm not a C++ specialist but could that have been possible with some kind of C++ ninja tricks involving Boost.Proto?

I mean, maybe using a different syntax? (but as simple)

Anyway it seem that it would be really simple to implement using the next C++ standard "custom literals" feature. That will be cool.
0 x

User avatar
jacmoe
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 20570
Joined: Thu Jan 22, 2004 10:13 am
Location: Denmark
Contact:

Re: C++ Extension: Ruby style Symbols

Post by jacmoe » Fri Feb 12, 2010 12:08 am

Exactly. I don't like Boost myself, but I forgot the name of that library. :)
0 x
/* Less noise. More signal. */
Ogitor Scenebuilder - powered by Ogre, presented by Qt, fueled by Passion.
OgreAddons - the Ogre code suppository.

User avatar
betajaen
OGRE Moderator
OGRE Moderator
Posts: 3447
Joined: Mon Jul 18, 2005 4:15 pm
Location: Wales, UK
Contact:

Re: C++ Extension: Ruby style Symbols

Post by betajaen » Fri Feb 12, 2010 12:13 am

My head exploded when I started to read that website.

Even if it could be done by Proto (or a similar library), What about compilation speed? I've found Boost pretty slow. Ruby is really fast and creating the Enum/Symbols file for you took no time what soever.

Besides, what I like about my method is that everything is defined inline, and not in some special file tucked away.
0 x

User avatar
_tommo_
Gnoll
Posts: 677
Joined: Tue Sep 19, 2006 6:09 pm
Contact:

Re: C++ Extension: Ruby style Symbols

Post by _tommo_ » Fri Feb 12, 2010 2:26 am

Code: Select all

typedef
    proto::expr<
        proto::tag::plus
      , proto::list2<
            proto::expr<
                proto::tag::terminal
              , proto::term< placeholder<0> >
              , 0
            > const &
          , proto::expr<
                proto::tag::terminal
              , proto::term< int const & >
              , 0
            >
        >
      , 2
    >
I fail in deducing the purpose of that whole library... and together with 20-lines #defines of typedefs, and template-typedef-tree-leaf-function-reference-casting it made my head explode too :shock:
It's hands-down the worst single piece of code that is really meant to be used :wink:
0 x
OverMindGames Blog
IndieVault.it: Il nuovo portale italiano su Game Dev & Indie Games

User avatar
Praetor
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 3335
Joined: Tue Jun 21, 2005 8:26 pm
Location: Rochester, New York, US
Contact:

Re: C++ Extension: Ruby style Symbols

Post by Praetor » Fri Feb 12, 2010 3:04 am

Holy crap. I haven't been monitoring boost lately. Proto is.... ridiculous. Impressively so. It reminds of me of my days of trying to make C++ be like something it isn't by using all sorts of crazy tricks like that, until I realized you can combine languages in one program and use the best tool for the job.
0 x
Game Development, Engine Development, Porting
http://www.darkwindmedia.com

User avatar
jacmoe
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 20570
Joined: Thu Jan 22, 2004 10:13 am
Location: Denmark
Contact:

Re: C++ Extension: Ruby style Symbols

Post by jacmoe » Fri Feb 12, 2010 10:35 am

That basically how I feel about most of Boost. :)
Impressively ridiculous.
0 x
/* Less noise. More signal. */
Ogitor Scenebuilder - powered by Ogre, presented by Qt, fueled by Passion.
OgreAddons - the Ogre code suppository.

User avatar
Klaim
Old One
Posts: 2565
Joined: Sun Sep 11, 2005 1:04 am
Location: Paris, France
Contact:

Re: C++ Extension: Ruby style Symbols

Post by Klaim » Fri Feb 12, 2010 3:45 pm

_tommo_ > The purpose of the lib is to allow "extending" the language with domain-specific language(with specific grammar).

Yes it looks like something overkill and ridiculous...at first.


You don't feel the same once you've used libs based on it. Like boost Spirit or even the coming "Meta State" lib.

Now, sure, most of us don't need all that, and most of us will not pay the compilation time price :)

That said, if you want to add some behaviour or specific sub-language to C++, it's certainly the most C++-only way to do it.
0 x

User avatar
_tommo_
Gnoll
Posts: 677
Joined: Tue Sep 19, 2006 6:09 pm
Contact:

Re: C++ Extension: Ruby style Symbols

Post by _tommo_ » Fri Feb 12, 2010 5:28 pm

Klaim wrote:_tommo_ > The purpose of the lib is to allow "extending" the language with domain-specific language(with specific grammar).
I understand it just as before :wink:

There's no doubt that someone, eventually, will need that... but it still fails to a very simple question:
WHY in C++?

As Praetor pointed out, if you have precise and strict requirements there's absolutely no reason to use native C++, for example, Spirit implements a scripted BNF in compiled C++, which is absolutely ridicolous:
creating a parser that reads some txts and feeds the data to the application is brain-dead easy compared to what they have done, and it's better in many ways.
So it's not the library per-se that is stupid, but the idea of using only C++ at any cost.
0 x
OverMindGames Blog
IndieVault.it: Il nuovo portale italiano su Game Dev & Indie Games

User avatar
betajaen
OGRE Moderator
OGRE Moderator
Posts: 3447
Joined: Mon Jul 18, 2005 4:15 pm
Location: Wales, UK
Contact:

Re: "$$$" C++ Extension: Ruby Symbols and Lazy Enums

Post by betajaen » Fri Feb 12, 2010 6:53 pm

I did a full rewrite, and it now does much better Symbols and Jacmoe's Enums. Check out my first post for details.
0 x

User avatar
Klaim
Old One
Posts: 2565
Joined: Sun Sep 11, 2005 1:04 am
Location: Paris, France
Contact:

Re: "$$$" C++ Extension: Ruby Symbols and Lazy Enums

Post by Klaim » Fri Feb 12, 2010 7:05 pm

WHY in C++?

As Praetor pointed out, if you have precise and strict requirements there's absolutely no reason to use native C++, for example, Spirit implements a scripted BNF in compiled C++, which is absolutely ridicolous:
creating a parser that reads some txts and feeds the data to the application is brain-dead easy compared to what they have done, and it's better in many ways.
So it's not the library per-se that is stupid, but the idea of using only C++ at any cost.
Not sure but AFAIK, making a "complex" parser like a programming language parser is far easier with something like Spirit than writing it yourself with any language, as you just have to explicit the grammar and add the code executed when reading the parsed code.
I don't know if you can extend another language than C++ that way (adding new grammars inside the C++ language). I heard that it's feasable only in C++ due to the way templates works (meta-language executed at compile-time, not at runtime).

Not sure it answers your question. :)
0 x

User avatar
jacmoe
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 20570
Joined: Thu Jan 22, 2004 10:13 am
Location: Denmark
Contact:

Re: "$$$" C++ Extension: Ruby Symbols and Lazy Enums

Post by jacmoe » Fri Feb 12, 2010 7:20 pm

You obviously don't know much about Lisp. :)
With Lisp you can rewrite the language itself on the fly. Data is code and code is data. All pretty neat.
I just wish C++ wasn't such a beast to wrap with other languages.
0 x
/* Less noise. More signal. */
Ogitor Scenebuilder - powered by Ogre, presented by Qt, fueled by Passion.
OgreAddons - the Ogre code suppository.

User avatar
jacmoe
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 20570
Joined: Thu Jan 22, 2004 10:13 am
Location: Denmark
Contact:

Re: "$$$" C++ Extension: Ruby Symbols and Lazy Enums

Post by jacmoe » Fri Feb 12, 2010 7:27 pm

Want to know why Lisp is the king of DSL ?
Start here: http://bc.tech.coop/blog/050704.html
C++ has a lot of catching up to do. :)
0 x
/* Less noise. More signal. */
Ogitor Scenebuilder - powered by Ogre, presented by Qt, fueled by Passion.
OgreAddons - the Ogre code suppository.

User avatar
Klaim
Old One
Posts: 2565
Joined: Sun Sep 11, 2005 1:04 am
Location: Paris, France
Contact:

Re: "$$$" C++ Extension: Ruby Symbols and Lazy Enums

Post by Klaim » Fri Feb 12, 2010 8:43 pm

You're right I don't know Lisp :)
0 x

User avatar
betajaen
OGRE Moderator
OGRE Moderator
Posts: 3447
Joined: Mon Jul 18, 2005 4:15 pm
Location: Wales, UK
Contact:

Re: "$$$" C++ Extension: Ruby Symbols and Lazy Enums

Post by betajaen » Fri Feb 12, 2010 9:11 pm

0.2.1

Minor update posted.

- Now only writes the AutoGenerated files if there have been any changes to the Symbols/Enums.
- Can now have a precompiled header include if needed (see the configuration section in the source of the ruby file)
0 x

JDX_John
Gnome
Posts: 397
Joined: Sat Nov 08, 2008 1:59 pm

Re: "$$$" C++ Extension: Ruby Symbols and Lazy Enums

Post by JDX_John » Sat Feb 13, 2010 10:24 pm

Boost slow, Ruby fast? That seems unlikely on both counts. You did remember not to profile your C++ app in debug mode, right? :mrgreen:

All those complaining C++ is painful, you are correct. That's why business software rarely uses it these days. What reason do you feel forced to use C++, to the extent of using tools to bolt on extra functionality, when you could use Java or .net? If you're developing for consoles then fair enough (although I don't know Ruby is around on consoles yet). If you develop for non-Windows platforms then .net is out for high-performant apps using 3D graphics, fine. But I reckon most Ogre people only develop against Windows... .net lets you write lots of functional stuff even in C# not to mention F#. And Ogre is ported (I think) to both Java and .net?


The first person to say "but Java's slow" is going to get sent back to the 1990s when that was last true :D Unless you're writing an AAA game or targeting old hardware, even beautiful 3D games don't need C++ any more to run like stink.

All that said, from a nerdy point of view, I like the project. I'm just not entirely sure what it's for, when the Java JVM supports languages like Groovy and .NET has F#.
0 x

User avatar
_tommo_
Gnoll
Posts: 677
Joined: Tue Sep 19, 2006 6:09 pm
Contact:

Re: "$$$" C++ Extension: Ruby Symbols and Lazy Enums

Post by _tommo_ » Sun Feb 14, 2010 10:47 am

But Java IS slow :D

It requires an awful second to pop a simple JOptionPane in my university exercises, and most applications have that nice startup bar which takes hours to be filled.
I also ported a rather complex assigment from Java to C++ just copying it and changing the syntax, the speedup was more than 10x.

So, IMHO Java is fast as C++ ONLY for basic academic tests like incrementing a pointer or allocating/deallocating objects, and that's why it performs well on test.
But, the Library and the "Java way of thinking" or worst Swing and the interface things are slow and bloated, you use them once and you app becomes unresponsive and slow :)
So if you want to reach some "speed" in Java you end up fighting against the language just as in C++, but on the other side.

Did you know that an empty foreach is 10x slower than the standard for just because it uses iterators?
0 x
OverMindGames Blog
IndieVault.it: Il nuovo portale italiano su Game Dev & Indie Games

jjp
Silver Sponsor
Silver Sponsor
Posts: 597
Joined: Sun Jan 07, 2007 11:55 pm
Location: Cologne, Germany
Contact:

Re: "$$$" C++ Extension: Ruby Symbols and Lazy Enums

Post by jjp » Sun Feb 14, 2010 10:58 am

_tommo_ wrote:Did you know that an empty foreach is 10x slower than the standard for just because it uses iterators?
I suppose this is because of boxing/unboxing (wrapping integral data types in classes)? But since you are dismissing academical performance measurements: this comparison is also academical. Unless you only do very little work in the loop the additional cost over the for loop probably won't make much of a difference.
0 x
Enough is never enough.

User avatar
_tommo_
Gnoll
Posts: 677
Joined: Tue Sep 19, 2006 6:09 pm
Contact:

Re: "$$$" C++ Extension: Ruby Symbols and Lazy Enums

Post by _tommo_ » Sun Feb 14, 2010 11:45 am

In fact i used to use it often because "10x more than ++i" is not that much... but it is a good indicator of the performances of the Library IMHO.
0 x
OverMindGames Blog
IndieVault.it: Il nuovo portale italiano su Game Dev & Indie Games

Post Reply