A new, C++-meant-for scripting language: IonScript

Started by
9 comments, last by Kevin2k 13 years, 5 months ago


Hello dear community,

I would like to present a new lightweight scripting system I've been working on during the last couple of months. It is called IonScript and it has entirely been made in modern C++ for easy embedding in C++ applications.

Some time ago I was looking for an easy to use and straightforward to embed scripting language for my everyday game development. The only real solution I found was LUA of course, but I am somewhat against cumbersome language-to-language API wrappers while I found the native C LUA API requiring a lot of extra code for real embedding in C++ applications. For this and more reasons, I started working on IonScript and I recently reached a pretty usable release. I am actually using it in my new indie game for several scripting environments (from resource loading, to world generation procedures, to AI, to game logics).

You can find a detailed page about the language at the official page.
While the source code can be found on Github.

The language has a trivial syntax, with some sugar, it handles null, numeric, string, boolean, list, dictionary, managed and unmanaged object values and it is extremely lightweight.

Making any of your existent classes internally scriptable or building from ground-up a complete scripting system tied to your needs is only a matter of minutes.

For any question, information, help, request and, especially, critics feel free to post here or write me an email.

Sincerely,
Massimo

[Edited by - Keebus on October 18, 2010 11:53:44 AM]
Advertisement
Hrm, interesting! I'll have to check this out and see how easily I can integrate it with my engine. Since I just started thinking about supporting script languages, this could be a good time for me to try this out. Thanks for the time and effort in providing developers other options!
Good news! Well,I've been working on this for a while, and I'm currently using it, but it would be a pity if others have my same needs and face the same lack of suitable technology. I'd be happy to give you any hint you desire for the testdrive.
Sounds good! I'll send you a PM once I start to add this to my engine. If I have some time later on tonight after work, I'll see if I can add it then.
I'm surprised someone hasn't griped about "LUA" vs Lua lol.

Anyways, I think your C++ embed impl is interesting.

I like your examples, but have you challenged your language yet?

for example, an xml parser? an event system? what about operator overloading? performance?

is parsing a vector of byte code really fast? I think that will be your biggest challenge in trying to compete with Lua (along with the whole community support thing).

------------------------------

redwoodpixel.com

Dear AverageJoeSSU, thanks for your interesting reply.

The point is: is it really necessary? For "scripting" I intend a quick, easy, trivial way for driving your C++ application (which indeed should be fast!) using the (as limited as possible) API you set up for your specific scripting domain. I would like to give you a couple of examples.

Suppose you're writing (as I am) a world generator that simply generates a new whole world (full of details and tweakable parameters). You have a generate() method that properly calls a bunch of submethods for specific stages of the world generation. Each of this private methods take quite a few parameters (map size, number of cities, perlin noise persistence, scale, octaves, etc). During the tuning process, it's normal to change parameters continuously to get to the best result. You definitely know how long a compilation can take.

This is surely a case where you would use IonScript. Take your World class and inherit from script::VirtualMachine. Add one single private static method to your class to handle multiple script-side functions and properly call your own methods. Make the generate() method call your own script placed somewhere. In a matter of minutes (this is what it took me) I have a system that can be tuned at runtime, and can even contain a pretty complex logic.

The second example consists of AI scripting. IonScript makes latent functions simply trivial. This means that script-side functions and host-side functions are decoupled, and a single script-side funciton can "last" a few game cycles. Take a look at the following snippet (it is meant to run within a kind of NPC C++ class).
agent = get("agent") // retrieves the value "agent" from the global values                     // you set from C++enemy = agent.findEnemy()agent.kill(enemy)

Here both findEnemy() and kill() are latent functions. So for example findEnemy() says "agent, go looking for an enemy now and continue when you find it" so that the function actually returns when the enemy is found, which can take seconds, minutes.

So the whole point is: IonScript is not meant for the purposes you were talking about. Parsing an array of bytes, or a bunch of ugly XML would be possilbe ONLY IF you implement needed functions in your C++ program and you provide an interface to the IonScript to call them.

Please let me stress this point one last time. IonScript is made for embedding, more like a "driver" language that drives your C++ objects/functions easily. It is not a general purpose language such as Python, Ruby (or even Lua), but it is strictly related to your own scripting needs (built-in functions are in fact less then ten).

Despite all this, IonScript is yet pretty fast. It compiles really quickly and some benchmarks perform even better than Python in some cases. Anyway, I haven't made too many benchmarks just yet since I'm pretty satisfied by its performance (both in compiling and execution).

Finally, I would like to invite you to try to embed the VirtualMachine in any of your existent classes and add some scripting facilities and see how small and intuitive the API is (in my humble opinion, of course).

It would be simply amazing if anyone of you smart guys gets interested and maybe collaborates for the development of the remaining features. Simple testing is absolutely good too.

p.s.: I'm sorry for eventual english grammar mistakes, I'm not a native speaker.

[Edited by - Keebus on October 18, 2010 7:26:32 PM]
I have a few problems with your statements.
Lua as has been pointed out is the correct name not LUA, this implies to me that you do not know the language or it's "cumbersome" C API, which leads nicely onto my second point why is it cumbersome?

Quote:in the real world, it is often strongly suggested to write the glue-code by hand.

Why is this the case? Did you pull this one out of the air?

Quote:No need to reinvent the wheel.

I had to laugh because this seems exactly what you have done :)

I had a quick look at your code and one thing stood out to me in "Values.h"
inline bool checkObjectType (const std::type_info & type) const {            return strcmp(mObjectTypeName, type.name()) == 0;         }

Firstly type_info.name is not guaranteed to be unique even in the same executable and secondly type_info is not guaranteed to be the same for the same type in two executables. The fact that you are actually using type_info is also somewhat of a surprise as you seem to be aiming at game developers, which also calls into question using exceptions.

The following is personal opinion but it annoys me every time I see it.
   if (mpProgram)      delete mpProgram;



There is a couple of times when you use a union and read data without knowing what the type is, the result of which is undefined.
   type = child.type;   memcpy(&child.number, &number, sizeof (double));


Then there is the case when you are comparing a double to 0.0, what happens if the double is a calculated value?


The biggest problem I would have with your library maybe is the function handling, seriously is it good design to have a big switch statement for "function groups"?


Overall the library show potential yet without knowing have fast it is, without being able to disable exceptions and runtime information I personally could not recommend it; yet these are all things which can be easily fixed.
Quote:
Quote:in the real world, it is often strongly suggested to write the glue-code by hand.

Why is this the case? Did you pull this one out of the air?

This is indeed not always true. If the it are simple functions like IncrementByOne(Value) functions, a glue-code generator will do fine. Only when the functions get real complicated (more then 5 parameters, standard parameters, overloads, etc.) it might be better to do it yourself. But only if you know exactly what you're doing.
I do agree that it is very useful to know how the glue-code works.



Quote:
The following is personal opinion but it annoys me every time I see it.
*** Source Snippet Removed ***

Why? This is just used when you already have started a program.
I see problems with deleting the program right after execution. What if you want to extract values after execution? You would need to add a lot of host functions.

Quote:
The biggest problem I would have with your library maybe is the function handling, seriously is it good design to have a big switch statement for "function groups"?


It's not a bad idea. You can have a function in the VM to add a single function. But that would also result in long code as well.
If your concern is speed:
- It are simple integer comparisons, those are really fast on a computer
- Divide you functions into multiple groups. Instead of adding all the functions into a single group, put them into multiple ones. One for global stuff, one for geometry stuff, etc.
- Put the functions that 'need' speed at the start of the switch. The function 'exit' doesn't exactly need speed so you can put it at the bottom. It doesn't matter if it has a lag of a 1/100 second.

I do see a lot of potential. But you should also build a standard library for it. Stuff like containers (a equivalent of std::vector for example) and file IO (if you like). Since you will (sooner or later) find out that if your language doesn't support these tings, you have to do A LOT to get longer scripts working properly.

assainator
"What? It disintegrated. By definition, it cannot be fixed." - Gru - Dispicable me

"Dude, the world is only limited by your imagination" - Me

Quote:Original post by assainator
Quote:
The following is personal opinion but it annoys me every time I see it.
*** Source Snippet Removed ***

Why? This is just used when you already have started a program.
I see problems with deleting the program right after execution. What if you want to extract values after execution? You would need to add a lot of host functions.



He meant:

http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.8

Did you try luabind (http://www.rasterbar.com/products/luabind.html)? It also does miracles in a matter of minutes.

Quote:Original post by noe
Quote:Original post by assainator
Quote:
The following is personal opinion but it annoys me every time I see it.
*** Source Snippet Removed ***

Why? This is just used when you already have started a program.
I see problems with deleting the program right after execution. What if you want to extract values after execution? You would need to add a lot of host functions.



He meant:

http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.8


Oh didn't know that. Sorry.

But now that I'm reading it, I am wondering why I get a runtime error whenever I try to delete a variable that is NULL.

assainator
"What? It disintegrated. By definition, it cannot be fixed." - Gru - Dispicable me

"Dude, the world is only limited by your imagination" - Me

This topic is closed to new replies.

Advertisement