COMMUNITY

Output overloaded functions with the same name in Java

I’ve seen several questions about overloaded functions for Haxe, but I haven’t seen one yet for writing an overloaded function in the target language.

Say I have a function like this, which is in a library that is intended to be compiled to Java and used by other applications:

public static function myfunc(arg1:String, ?arg2:String, ?arg3:String):Array<String> { ... }

This is nice if I’m writing code in Haxe, but in Java I end up having to pass null’s for the optional arguments quite a bit. If I were writing this in Java directly, I’d do it like this to make it a little nicer to call:

public static String[] myfunc(String arg1, String arg2, String arg3) { ... }
public static String[] myfunc(String arg1, String arg2) { return myfunc(arg1, arg2, null); }
public static String[] myfunc(String arg1) { return myfunc(arg1, null, null); }

My thinking was that I could use a macro to generate the overloaded calls in Java - and I can, I have a macro that does just that. The issue that I’m having is that I can’t generate the overloaded functions with the same name as the original function, as that gives me a “duplicate class field declaration” error (which makes sense).

Is there a way that - knowing my target language is Java and it supports overloaded functions - I can generate the overloaded functions with the same name as the original function?

For completeness here’s the (very rough) macro function that I’m using to generate the overloaded functions.

/**
 * @param field Original field object, from Context.getBuildFields().
 * @param func The function represented by the field object.
 * @param pos The position.
 * @return Any overloaded functions that should be added to the macro return.
 */
private static function handleFunction(field:Field, func:Function, pos:Position):Array<Field>
{
    var hasOptArgsAtEnd = false;
    var args = new Array<FunctionArg>();
    for(arg in func.args)
    {
        hasOptArgsAtEnd = arg.opt;
        args.push(arg);
    }
    if(!hasOptArgsAtEnd)
    {
        return null;
    }

    var rtrn = new Array<Field>();
    args.pop();
    while(args.length > 0)
    {    
        var nArgs = new Array<Expr>();
        for(arg in args)
        {
            nArgs.push(macro $i{arg.name});
        }  
        for(idx in args.length...func.args.length)
        {
            nArgs.push(macro $v{null});
        }

        var myFunc:Function = { 
            expr: macro return $i{field.name}($a{nArgs}),
            ret: func.ret,
            args: args.copy()
        };

        var f:Field = {
            name: field.name + Std.string(args.length),
            access: field.access,
            kind: FieldType.FFun(myFunc),
            pos: pos
        };

        rtrn.push(f);
        if(!args.pop().opt)
        {
            break;
        }
    }        

    return rtrn;
}

Unless I’m missing something I think that library is the reverse of what I’m trying to do - it seems to allow you to write overloaded functions in Haxe, while I’m trying to take a single Haxe function and generate overloaded functions in the target language.

I mentioned above library because you need @:overload meta, specifically

OverloadMacro.hx

cls.meta.add(OVERLOAD_META_NAME, overload_metadata, Context.currentPos());

Unfortunately I’m still not getting it. It looks like that library is allowing multiple function signatures with the same name in Haxe, then using a build macro to rename them and call the right function signature to avoid having multiple functions with the same name when the compile actually happens. It doesn’t seem to use @:overload at all.

I had tried to use @:overload, and while that does allow me to have multiple signature for the same function on the Haxe side, it doesn’t appear to affect the target language output at all - I still only get a single function when I compile to Java, not multiple functions with the same name.

Yes, @:overload needs extern class, and extern class needs overloaded functions with the same name already generated on the target which support such overload. In short, won’t help you.

I think you need to make a macro which reads generated Java file and adds overloaded functions with the same name.