Search code examples
actionscript-3flashruntimegenerated-codeopcodes

as3commons generate function call at runtime


For reasons I am generating a class at runtime which has an existing super class with a protected member and implements an existing interface. Each method (and accessor) of the interface needs to get generated, too. The point where I'm struggeling is to fill the method body with the correct opcodes. Here is an example which i want to generate or translate into opcode:

public function myFunction(arg1:String, arg2:int):Boolean
{
    return member.my_namespace::myFunction(arg1, arg2);
}

All Informations are available, like the name of the function, the arguments, the return type and the namespace. And I am able to create the function itself and return a default value, like seen in the as3commons tests/examples

Maybe I should use another lib than as3commons?


Solution

  • I found the answer by myself. All I was missing was the (correct) using of the QualifiedName to have access to the member and the function of it. I removed just the namespace. That is all I modified at the template code:

    public function myFunction(arg1:String, arg2:int):Boolean
    {
        return member.myFunction(arg1, arg2);
    }
    

    Here is the needed sourcecode to generate that function inclusive the Opcodes for the method body:

    var abcBuilder:AbcBuilder = new AbcBuilder();
    
    //build the class with the super class and the interface
    var packageBuilder:IPackageBuilder = abcBuilder.definePackage("my.package");
    var classBuilder:IClassBuilder = packageBuilder.defineClass("RuntimeClass", "my.package.BaseClass");
    classBuilder.implementInterface("my.package.IMyInterface");
    
    //build the function
    var methodBuilder:IMethodBuilder = classBuilder.defineMethod("myFunction");
    methodBuilder.returnType = "Boolean";
    methodBuilder.visibility = MemberVisibility.PUBLIC;
    methodBuilder.isFinal = true;
    
    //add the parameters
    methodBuilder.defineArgument("String");
    methodBuilder.defineArgument("int");
    
    //here begins the method body with the opcode
    methodBuilder.addOpcode(Opcode.getlocal_0);
    methodBuilder.addOpcode(Opcode.pushscope);
    //call the member "member"
    methodBuilder.addOpcode(Opcode.getlex, [new QualifiedName("member", LNamespace.PUBLIC)]);
    //access to the function args
    methodBuilder.addOpcode(Opcode.getlocal_1);
    methodBuilder.addOpcode(Opcode.getlocal_2);
    //call the function at the above prepared member with the prepared args
    methodBuilder.addOpcode(Opcode.callproperty, [new QualifiedName("myFunction", LNamespace.PUBLIC), 2]);
    //return the result
    methodBuilder.addOpcode(Opcode.returnvalue);
    
    //fire at own will
    abcBuilder.addEventListener(Event.COMPLETE, loadedHandler);
    abcBuilder.addEventListener(IOErrorEvent.IO_ERROR, errorHandler);
    abcBuilder.addEventListener(IOErrorEvent.VERIFY_ERROR, errorHandler);
    abcBuilder.buildAndLoad();
    

    I give no garanty that the code works. I adjusted it with some dynamically stuff and loops in my own project where it works very well. The libs I use(d) are:

    • as3commons-bytecode-1.1.1
    • as3commons-lang-0.3.7
    • as3commons-logging-2.7
    • as3commons-reflect-1.6.4

    All available under the as3commons downloads