ChaiScript is the first and only scripting language designed from the ground up with C++ compatibility in mind. It is an ECMAScript-inspired, embedded functional-like language.
ChaiScript is licensed under the BSD license.
ChaiScript is the first and only scripting language designed from the ground up with C++ compatibility in mind. It is an ECMAScript-inspired, embedded functional-like language.
ChaiScript is licensed under the BSD license.
Yay for is_null() and is_undef() :D
OK interesting, thanks :)
The short answer is that C++ operators are just functions. So, one option is to register them as such:
The above gets a bit tricky if your operator is a free function instead of a member, making it become something like:
A third option, which is not yet recommended, is to use the internal helpers that we have:
The helper works for class methods or free functions, but it is in the "detail" namespace, which is not part of the public API.
A better option would be if we were to add helpers for all canonical forms of the operators. This would not be terribly difficult, and I will make a note to work on it for the next release. I'm envisioning something like:
Interesting, but how would you bind C++ defined operators?
It was a late add, but we should probably take some time to document it. The unit tests that covers it look like:
Use operator as a method:
And... operator as a function
Apparently the newest version supports operator overloading, but how does it work? I cannot find a sample demonstrating the functionality.
"You can register a function that takes a Boxed_Value," right, but I can't change the interface ;) I'm saying that since both Boxed_Value and boost::any can hold 'any' value, it would be useful to have a direct Boxed_Value -> boost::any conversion. This isn't a major show stopper, just thought I'd point it out.
So if I understand properly, you want the system to automatically extract the contained shared_ptr value or boost::reference and convert that to a boost::any?
If the Boxed_Value actually contained a boost::any (which should be a perfectly valid thing to do), then this operation should work fine.
If it does not contain a boost::any, I'm at a loss as to why you would want to do this. You can register a function that takes a Boxed_Value, which is the generic way of looking at a type-erased value inside of ChaiScript.
Correct, my point is that there is no direct Boxed_Value -> boost::any conversion, you need to know the held type. Meaning I can't bind a function like this:
1) Added a bug tracker item for this, shouldn't be a problem
2) see 1)
3) There is a wide range of conversions built in to ChaiScript's C++ side. The short story is that Boxed_Value is really meant to be an opaque type. If you'll notice, I did not document any of its methods in the C++ online documentation.
The idea is that all interactions with Boxed_Values should occur through the boxed_cast function. I need to provide documentation for the full set of casts that are possible, but you should generally be able to extract anything you want:
If the boxed_value was instantiated with a boost::reference type then the shared_ptr casts are not possible. Const correctness is honored. If you instantiate it with a const type, you cannot extract non-const.
With these available casts, you should be able to extract any information you would need to at run time.
Cool, thanks. Some other issues I've noticed:
1) there doesn't seem to be any way to tell if a variable is "unknown" or correctly set. This is easily fixed by binding your own "is_unknown" function that returns Boxed_Value::is_unkown(), but it would be nice if this feature was built in like "to_string" is
2) similar to the above, there doesn't seem to be any way of checking for a "null" pointer. For example:
3) at first I thought that Boxed_Value::get() would return a boost::any with the value of the object, but after looking through the code it seems to return the boost::any that has a reference or a shared_ptr to the value. I understand why this is done, but it would be useful if there was a value-based boost::any. For example:
If there was a way to get the value-based boost::any out of a Boxed_Value, the above would be very easy... but there isn't, because the any holds a reference or shared_ptr.
Something like this would work:
But then we have the issue of const-correctness, etc. Perhaps there is an easier, more integrated way of doing this...
There was much debate about this topic before we publicly released ChaiScript. ChaiScript differs from many other scripting languages in that it does not handle built in types and object differently. We did initially have all assignments be references, but it ended up resulting in some unexpected behavior regarding the sharing of references. A simple "weird" example:
With all types using implicit references, it was odd to have both v[0] and i sharing a reference.
I'll make sure the docs are updated to include this information.
ChaiScript, unlike most scripting languages, seems to implicit *copy*, not share, all values. This is a major problem because you end up with the following problem:
The above problem becomes much more important when you do something like this:
I propose the following:
Edit:
Actually, this seems to be a non-issue. Function parameters seem to be implicitly shared, and there exists a completely obscure operator called ":=" which does sharing instead of copying. The documentation doesn't seem to mention this operator at all, I had to look through the source to find it.
I would like to have single instance of chaiengine used from multiple threads (engine initialization takes a while)
however thread might create their own versions of same functions.
what would be cool is to have ability to run script and add functions to a custom scope (temporary possibly)
something like:
static ChaiScript g_chai;
void thread_func()
{
int threadvar;
ChaiScriptScope chaiscope = g_chai.createScope();
chaiscope.add(chaiscript::fun(bind(&myFunc,threadvar,_1,_2)));
chaiscope.eval("script");
}
this way all my threads can use global calls in scripts and still can have same set of local
calls.
This should be available in the next release. If you would like to get it earlier and don't mind using code fresh out of subversion, the most recent revisions should allow for hex and octal.
Good points!
The first issue should be working better in the latest subversion.
The second issue: currently we don't "pun" on types, so you would need to do "if (true)" instead of "if (1)" though we might add value puns like that in the future.
one can't start script with {
it will cause parse error
also if (1) is invalid (that might not be an issue if one is required ot do if (true) or something.
I bet we can get that in the next release, it should be easy enough I would think.
it seems like ChaiScript (2.0) cant recognize/parse hex numbers. is that the case or am i looking at some other issue ?
(hex numbers as 0x10 etc...)
I just wanted to comment that the next version of ChaiScript (2.0) will have shared ChaiScript engine thread safety available. We expect to release it very soon.
The problem here is that your ChaiScript engine is going out of scope and being destroyed before you get the chance to call
begin()because you created your ChaiScript engine inside of your constructor.The main solution would be to extend the lifetime of your ChaiScript engine, to make sure it's available when you need it.
If this does not solve your problem, please copy the contents of your test.chai file here so we can double check what it is doing.
For this one you will need to use a new feature of 2.0 (which is not yet released). You can grab the current version of ChaiScript from svn to try it out.
This will allow you to share your enum constants between ChaiScript and C++.
ChaiScript 2.0 will be released hopefully within the week.
-Jason
like
enum DIRECTOR { East, South , West, North }how to realize?
Hi,I'm confusing with the functor using in a class. below is simple code:
class Test { public: Test(){ ChaiScript chai; chai.eval_file("test.chai"); func = chai.functor<void ()>("func"); } void begin(){ func(); } private: boost::function<void ()> func; };the class can be compiled, but error at runtime.
I found the error point is at begin function, which can not visit "func()",why? plz help me to solve the problem.
The latest SVN version now has thread safety. You can register any functions in one thread and they will be visible to all threads. Context and state are handled for you automatically.
There is a minor caveat, however. If a function is added in one thread, no other currently executing script on a different thread will see that new function. However, any new evaluation started after the function is added will see the new function.
Also, file includes are supported as of the last release in the form of "use." The new threading support works with "use" as well, so that you can safely include the same file in multiple executing threads by calling "use" from each one.
The latest SVN does add library requirements that did not exist before, namely: libboost_thread.
An example of the multithreaded support with "use" is available in svn.