About ChaiScript

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.

Download

Version: 2.3.3 Released: 5/15/2010

Source
Windows
Linux

Recent comments

  • ChaiScript 2.2 Released   42 weeks 1 day ago

    Yay for is_null() and is_undef() :D

  • ChaiScript Questions   44 weeks 6 days ago

    OK interesting, thanks :)

  • ChaiScript Questions   44 weeks 6 days ago

    The short answer is that C++ operators are just functions. So, one option is to register them as such:

    chai.add(fun(&MyClass::operator<), "<");

    The above gets a bit tricky if your operator is a free function instead of a member, making it become something like:

    chai.add(fun<bool (const MyClass &, const MyClass &)>(&operator<), "<");

    A third option, which is not yet recommended, is to use the internal helpers that we have:

    chai.add(fun(&bootstrap::detail::less_than<const MyClass&, const MyClass&>), "<");

    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:

    chai.add(less_than<MyClass&>());
  • ChaiScript Questions   45 weeks 12 hours ago

    Interesting, but how would you bind C++ defined operators?

  • ChaiScript Questions   45 weeks 1 day ago

    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:

    def Bob::`+`(y) { this.x + y.x }
    def Bob::Bob() { }
    attr Bob::x
    var b = Bob()
    var c = Bob()
    b.x = 4
    c.x = 5
    print(b+c)

    And... operator as a function

    def Bob::Bob() { }
    attr Bob::x
    def `-`(a, b) : is_type(a, "Bob") && is_type(b, "Bob") { a.x - b.x }
    var b = Bob()
    var c = Bob()
    b.x = 4
    c.x = 5
    print(b-c)
  • ChaiScript Questions   45 weeks 4 days ago

    Apparently the newest version supports operator overloading, but how does it work? I cannot find a sample demonstrating the functionality.

  • ChaiScript Questions   46 weeks 2 days ago

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

  • ChaiScript Questions   46 weeks 3 days ago

    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.

  • ChaiScript Questions   46 weeks 3 days ago

    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:

    void doCommand(const string &name, const boost::any &value) { ... }
  • ChaiScript Questions   46 weeks 4 days ago

    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:

    boxed_cast<Type>(bv);
    boxed_cast<Type &>(bv);
    boxed_cast<const Type &>(bv);
    boxed_cast<shared_ptr<Type> >(bv);
    boxed_cast<shared_ptr<const Type> >(bv);
    boxed_cast<const shared_ptr<Type> &>(bv);
    boxed_cast<const shared_ptr<const Type> &>(bv);

    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.

  • ChaiScript Questions   46 weeks 4 days ago

    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:

    boost::shared_ptr<someClass> foo; // null pointer
    chai.add(var(foo), "foo");
    foo.doStuff() // woops, it's null - but how can we check?

    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:

    void doCommand(const string &cmd, const boost::any &param0, const boost::any &param1) // or a vector of any's
    {
       // do stuff with cmd and the proper parameters, assuming they hold value types, not shared_ptrs
    }

    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:

    template<typename T>
    T custom_cast(const boost::any &a)
    {
        try
        {
            // try value type first
            return boost::any_cast<T>(a);
        }
        catch (...)
        {
        }
     
        try
        {
            // try pointer type second
            return boost::any_cast<boost::shared_ptr<T> >(a);
        }
        catch (...)
        {
        }
     
        throw bad_cast();
    }

    But then we have the issue of const-correctness, etc. Perhaps there is an easier, more integrated way of doing this...

  • ChaiScript Questions   46 weeks 4 days ago

    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:

    var i = 5;
    var v = [1,2,4];
    v[0] = i;

    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 Questions   46 weeks 4 days ago

    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:

    // share a value with C++ and Chai, nice!
    var someValue = someSharedPtrFromCPP()
     
    // make another reference to this value
    var theSameValue = someValue
    // WOOPS, error! the shared_ptr isn't copied, but the value is copied instead
    // and if you don't have a copy constructor for that value type, then you're screwed

    The above problem becomes much more important when you do something like this:

    def doStuff(obj)
    {
        obj.val = 42
    }
     
    var obj = someSharedPtrFromCPP()
     
    doStuff(obj) // oh no!

    I propose the following:

    var obj = foo()
    var sharedObj = obj // shared, no copy constructor is needed
     
    var copyObj = foo(obj) // explicit copy, *not* shared with the original obj

    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.

  • ChaiScript Questions   47 weeks 6 days ago

    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.

  • ChaiScript Questions   48 weeks 1 day ago

    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.

  • ChaiScript Questions   48 weeks 1 day ago

    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.

  • ChaiScript Questions   48 weeks 3 days ago

    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.

  • ChaiScript Questions   49 weeks 2 days ago

    I bet we can get that in the next release, it should be easy enough I would think.

  • ChaiScript Questions   49 weeks 3 days ago

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

  • ChaiScript Questions   50 weeks 4 days ago

    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.

  • ChaiScript Questions   50 weeks 4 days ago

    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.

    class Test
    {
    public:
    	Test(){
    		chai.eval_file("test.chai");
    		func = chai.functor<void ()>("func");
    	}
    	void begin(){
    		func();
    	}
    private:
            ChaiScript chai;
    	boost::function<void ()> func;
    };

    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.

  • ChaiScript Questions   50 weeks 4 days ago

    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.

    ChaiScript chai;
    chai.add(const_var(East), "East");
    chai.add(const_var(South), "South");
    chai.add(const_var(West), "West");
    chai.add(const_var(North), "North");

    This will allow you to share your enum constants between ChaiScript and C++.

    ChaiScript 2.0 will be released hopefully within the week.

    -Jason

  • ChaiScript Questions   51 weeks 15 hours ago

    like

    enum DIRECTOR
    {
    	East,
    	South ,
    	West,
    	North 
    }

    how to realize?

  • ChaiScript Questions   51 weeks 1 day ago

    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.

  • ChaiScript Questions   1 year 1 week ago

    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.

Syndicate content