Chaiscript doesn't throw if a method is not found


#1

Hello, why is Chaiscript not throwing an exception when a function that doesn’t exists is called inside a script? For example:

script code:

class A {
def update() {
this.methodThatNotExists();
}
}


#2

Aha! I Found method_missing, sorry!

I suppose that i have to add a method with this signature from C++


#3

There’s an ‘explicit’ mode to disable the built-in method_missing that’s on ChaiScript defined objects: https://github.com/ChaiScript/ChaiScript/blob/develop/cheatsheet.md#option-explicit

-Jason


#4

Well what I ended doing was this:

module->add(chaiscript::fun([](const chaiscript::Boxed_Value &object, const std::string &funName, const chaiscript::Boxed_Value &params ){ std::cout<<“Function not found: “<< funName <<”\n”; }), “method_missing”);

I know it receives a Vector on the third parameter, but… how can I cast it to Vector of boxed values?
Thank you!


#5

If you want it to throw when a member name is not found, setting explicit will do that. If you want it to simply log, like you are, then you can do it that way too.

You should be able to simply make the 3rd param a vector:

module->add(chaiscript::fun([](const chaiscript::Boxed_Value &object, const std::string &funName, const std::vector<chaiscript::Boxed_Value> &params ){ std::cout<<"Function not found: "<< funName <<"\n"; }), "method_missing");

#6

I tried this:

def MyClass() {
    this.set_explicit(true);
    this.test = 2;
}

And I’m getting this error:
"Error: “Unable to find appropriate’=’ operator.” With parameters: (void, const int) "

But if set_explicit(false) I’m getting the same error. Maybe it’s a bug?


#7

Huh. That does look like a bug. Can you confirm which version of ChaiScript you are using?


#8

tag 5.8.3. going to github.


#9

5.8.3 should have had it, not sure when that would have gotten broken. I’ll make some tests real quick on the 5.x branch


#10

Ok! Thank you! I created an Issue in github for tracking this.


#11

I did this:

class MyClass2 { 
  def MyClass2() { 
    this.set_explicit(true); 
    this.x=2 
  } 
};

var o = MyClass2();

And get the expected error.

Are you wrapping your constructor in a class?


#12

mmmmmm yes, we are using a function to create instances of that class:

   //build the chai creator statement
   std::string creator_statement = (R"(fun() 
               { 
                 var new_instance = )") + className + (R"((); 
                 return new_instance; 
               })");

    auto creator = m_chaiScript->eval<std::function<chaiscript::Boxed_Value ()>>(creator_statement);

This is because we need to delay the creation of that instance and/or to make more instances of the same class. Maybe should we do it different?


#13

It would appear to me that to get the behavior you want you would want to do:

new_instance.set_explicit(true);
return new_instance;

In that block of code?


#14

If I dont touch that block of code (I assume that set_explicit is false) and my script constructor is:

class vegeta
{
def vegeta() {
this.test = 2;
}
};

Should get the error? or should the variable be implicitly declared?


#15

This code:

class vegeta
{
  def vegeta() {
    this.test = 2; // not an error, test is implicitly defined
  }
};

var o = vegeta();
class vegeta
{
  def vegeta() {
    this.set_explicit(true);
    this.test = 2; // error, test is not implicitly defined
  }
};

var o = vegeta();

I just double checked this with my local build of 5.8.3, so if you’re seeing different results, let me know.


#16

I think i found something interesting:
without:
module->add(chaiscript::fun([](const chaiscript::Boxed_Value &object, const std::string &funName, const chaiscript::Boxed_Value &params ){ std::cout<<“Function not found: “<< funName <<”\n”; }), “method_missing”);

it’s working correctly.

If I add the method_missing function no matter what I set to set_explicit, it always throws the same error:
"Error: “Unable to find appropriate’=’ operator.” With parameters: (void, const int) "

:S


#17

Oh yes, I believe that. That would be because your method_missing implementation you show would have higher priority over the built-in one, and you are returning void implicitly. That all makes sense.

-Jason


#18

This means that there is a bug in chaiscript? or that I should have to change my method_missing function?

Thanks!


#19

I believe everything is working as intended, but you are in a gray area. I’ve not tried both creating my own method_missing function and enabling set_explicit

In my opinion, the way it’s currently operating is the correct way, that the method_missing should take priority. In fact I’m not sure how I could change it (at least efficiently).

-Jason


#20

Something to keep in mind:

You are writing a very “big hammer” approach to your method_missing. Your version will be found any time a method is called that doesn’t exist, for either Dynamic_Object’s or not.

You can define method_missing much more granular.

Example:

class vegeta
{
  def vegeta() {
    this.test = 2; // error, test is not implicitly defined
  }

  def method_missing(String funName, Vector params) {
    throw("method not found: ${funName}");
  }
};

Make sense?