Problem using implicit value cast to a user registered type

Started by
7 comments, last by 39ster 14 years, 12 months ago
With the current WIP revision (398) I can't seem to get asBEHAVE_IMPLICIT_VALUE_CAST to work when the type being cast to is not a built-in type. Sample code:

#include "angelscript.h"
#include <cassert>
#include <cstdio>

void MessageCallback(const asSMessageInfo *msg, void *param)
{
	const char *type = "ERR ";
	if( msg->type == asMSGTYPE_WARNING ) 
		type = "WARN";
	else if( msg->type == asMSGTYPE_INFORMATION ) 
		type = "INFO";

	printf("%s (%d, %d) : %s : %s\n", msg->section, msg->row, msg->col, type, msg->message);
}

struct Simple {
};

struct Complex {
};

void implicit(asIScriptGeneric * gen) {
}

int main(int, char **) {
  asIScriptEngine * engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
  engine->SetMessageCallback(asFUNCTION(MessageCallback), 0, asCALL_CDECL);
  int r;
  r = engine->RegisterObjectType("simple", sizeof(Simple), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE); assert(r >= 0);
  r = engine->RegisterObjectType("complex", sizeof(Complex), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE); assert(r >= 0);
  r = engine->RegisterObjectBehaviour("complex", asBEHAVE_IMPLICIT_VALUE_CAST, "int f()", asFUNCTION(implicit), asCALL_GENERIC);
  r = engine->RegisterObjectBehaviour("complex", asBEHAVE_IMPLICIT_VALUE_CAST, "double f()", asFUNCTION(implicit), asCALL_GENERIC);
  r = engine->RegisterObjectBehaviour("complex", asBEHAVE_IMPLICIT_VALUE_CAST, "simple f()", asFUNCTION(implicit), asCALL_GENERIC);

  const char script[] =
    "void main() {\n"
    "  int i;\n"
    "  double d;\n"
    "  simple s;\n"
    "  complex c;\n"
    "  i = c;\n"
    "  d = c;\n"
    "  s = c;\n"
    "}";
  asIScriptModule * mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
  r = mod->AddScriptSection("script", script, sizeof(script) - 1); assert(r >= 0);
  r = mod->Build(); assert(r >= 0);
  
  int func_id = mod->GetFunctionIdByDecl("void main()"); assert(func_id >= 0);
  asIScriptContext * ctx = engine->CreateContext();

  r = ctx->Prepare(func_id); assert(r >= 0);
  r = ctx->Execute(); assert(r >= 0);

  ctx->Release();
  engine->Release();
}

The implicit value cast works just fine with the built-in types I've tried: int and double, and I can register the object behavior without complaint from the runtime but if I try actually using the implicit conversion, the compiler complains that it "Can't implicitly convert from 'complex' to 'simple'."
Advertisement
I'll take a look at this. Thanks for the simple code for testing it.

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

This is a rather complex bug. It will probably take me a while to fix it.

You can work around it by registering an assignment behaviour for the 'simple' that take a 'complex'. I know you probably don't want that, but it is only temporary until I can come up with a solution for the bug.

Regards,
Andreas

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Thanks for looking at it. Also, though you've probably already noticed it, this also seems to affect the explicit value cast as well.
This may be what was happening for me: http://www.gamedev.net/community/forums/topic.asp?topic_id=531119 (as described further down)

    //Register the casting (Variable should be able to cast to int, float and string)    r = engine->RegisterObjectBehaviour("var", asBEHAVE_IMPLICIT_VALUE_CAST, "int f()",         asFUNCTION(VariableCastInt),            asCALL_CDECL_OBJFIRST);       assert( r >= 0 );    r = engine->RegisterObjectBehaviour("var", asBEHAVE_IMPLICIT_VALUE_CAST, "float f()",       asFUNCTION(VariableCastFloat),          asCALL_CDECL_OBJFIRST);       assert( r >= 0 );    r = engine->RegisterObjectBehaviour("var", asBEHAVE_IMPLICIT_VALUE_CAST, "string@ f()",     asFUNCTION(VariableCastString),         asCALL_CDECL_OBJFIRST);       assert( r >= 0 );


I tried changing the string addon to the OBJ_VALUE one and it still doesn't work (although it does give a different error. The previous one would say there are more than one matching operators. The code below reports the same error as SiCrane)

    //Register the casting (Variable should be able to cast to int, float and string)    r = engine->RegisterObjectBehaviour("var", asBEHAVE_IMPLICIT_VALUE_CAST, "int f()",         asFUNCTION(VariableCastInt),            asCALL_CDECL_OBJFIRST); assert( r >= 0 );    r = engine->RegisterObjectBehaviour("var", asBEHAVE_IMPLICIT_VALUE_CAST, "float f()",       asFUNCTION(VariableCastFloat),          asCALL_CDECL_OBJFIRST); assert( r >= 0 );    r = engine->RegisterObjectBehaviour("var", asBEHAVE_IMPLICIT_VALUE_CAST, "string f()",      asFUNCTION(VariableCastString),         asCALL_CDECL_OBJFIRST); assert( r >= 0 );


Only the string one reports an error.

Also, SiCrane, what tags are you using for your code? I use
and it doesn't put it in a box.
The [source] tag is used to get the white code box.
I've fixed both problems now. This was a well overdue change that I had planned to do for quite some time. It took me a while as I had to reorganize the way the implicit casts were compiled, but luckily I found some free time to really concentrate on this yesterday.

Implicit casts are definitely one of the most complicated parts in a compiler like this. If I were to start a new scripting library with my current knowledge I would definitely take the easier path of dynamic types. But then, again were's the fun in taking the easy path. :)

39ster, you'll probably have some benefit of these fixes as well. But AS still doesn't support implicit casts from primitive to object. I'll try to get that implemented soon.

Regards,
Andreas

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

Thanks, everything seems to be working in revision 400.
Sweet, it works.

void main(){  var foo = "This is a string";  string bar = foo;  Print(bar);}

This topic is closed to new replies.

Advertisement