Force `new` to be called as method in Lua

Hello.

I have a lua library that must be created like this

local Job = require"plenary.job"
local job = Job:new()

This forces me to do some weird things in the Haxe side. First, I need it to be a class because all the methods must be called with :method syntax, including the new method, which in Haxe seems to be always static.
In order for this to work I had to define it like this:

@:luaRequire("plenary.job")
extern class Job {
	function new();
	@:native('new')
        function make(args:JobOpts):Job;
	function start():Job;
}

Then called like this (which is a bit tedious)

final job = new Job().make(real_opts);

Is there any better way? I see Haxe has one annotation to force dot notation, but does not seem to have one to do the opposite.

Ok, it does not work even in that way. The generated lua code still calls new without colon first, then my method:

  local job = __plenary_Job.new();
  local ret = ({});
  local _g = 0;
  local _g1 = args.length;
  while (_g < _g1) do 
    _g = _g + 1;
    local idx = _g - 1;
    ret[idx + 1] = args[idx];
  end;
  local this1 = ({command = "chezmoi", arguments = ret});
  local job = job:new(this1);

This was close to work:

@:luaRequire("plenary.job")
extern class Job {
	static inline function make(args:JobOpts):Job {
		return untyped Job._make(Job, args);
	}
	@:native('new')
	function _make(args:JobOpts):Job;
	function start():Job;
}

But the generated lua code was still wrong:

  local this1 = ({command = "chezmoi", arguments = ret});
  local job = __plenary_Job:_make(__plenary_Job, this1);
  do return job:start() end;

Thanks to some help on discord, this is, what I think, a reasonable tradeoff:

@:luaRequire("plenary.job")
extern class Job {
	static inline function make(args:JobOpts):Job {
		return Job._make(Job, args);
	}
	@:native('new')
	private static function _make(self:Dynamic, args:JobOpts):Job;
	function start():Job;
}

Also, another shorter alternative is this

@:luaRequire("plenary.job")
extern class Job {
	static inline function make(args:JobOpts):Job {
		return untyped __lua__("{0}:new({1})", Job, args);
	}
	function start():Job;
}

Posting it here in case anyone ends in the same situation as me, since Discord conversations do not appear on google.

1 Like