Apologies for the third post in a row. I wanted to highlight the speed increases I am getting on JavaScript and C++ and would like opinions as to why this might be the case.
src/Test.hx:17: *** Running without inlines ***
src/Test.hx:53: Haxe function type: 0.3874378
src/Test.hx:59: Delegate: 0.0279917
src/Test.hx:24: *** Running with inlines ***
src/Test.hx:53: Haxe function type: 0.3732177
src/Test.hx:59: Delegate: 0.0155093000000001
src/Test.hx:31: *** Running with anonymous functions ***
src/Test.hx:53: Haxe function type: 0.3604134
src/Test.hx:59: Delegate: 0.0193384999999999
In other words, the Delegate type executes 24 times faster and 14 times faster with and without inlines respectively.
JavaScript:
app.js:24 src/Test.hx:17: *** Running without inlines ***
app.js:60 src/Test.hx:53: Haxe function type: 0.008699999999254943
app.js:68 src/Test.hx:59: Delegate: 0.007800000000745058
app.js:30 src/Test.hx:24: *** Running with inlines ***
app.js:60 src/Test.hx:53: Haxe function type: 0.09140000000037253
app.js:68 src/Test.hx:59: Delegate: 0.012100000001490113
app.js:37 src/Test.hx:31: *** Running with anonymous functions ***
app.js:60 src/Test.hx:53: Haxe function type: 0.06580000000074504
app.js:68 src/Test.hx:59: Delegate: 0.014500000000000013
Here, the Delegate type executes in roughly the same time as a function type, but 8 times faster with inlines and 4 times faster with anonymous functions.
Some obvious limitations still exist:
Oddly enough, anonymous functions break if we try to reference imported types that expect type parameters, and so need to be preceded by their package in order to work.
Larger output size, and so balancing the cost of runtime execution and output size as expected from generics should be considered.
Delegate types cannot be generated from functions or classes with type parameters.
So I have a solution. I’ll push it to the repo once I tidy things up (which it very much needs)… All delegates will have to have their argument types and return types unified explicitly, like so:
Can you catch exception in your macro? And then generate temporary variable used for assignment. Error is thrown because there is no object present in array/vector field (it’s null by default) I think.
The exception is thrown because the builder expects the lhs of the assignment to be of a specific type, namely a delegate abstract class which it then tries to unify against. It’s not always possible to retrieve the lhs type it seems, which is why your example was failing. It also failed for local assignments too. Not sure if catching an exception would have worked?
Explictly defining the argument types and having a return type check for (Int, Int)->Int lets us just determine if a Delegate_Int_Int_Int was generated and if so we can set it as the superclass to the delegate we generate from the function expression. This then lets us assign delegates locally or to positions in a Vector.
Yes, unification fails because there is no type present (null doesn’t unify), but in that case you can use temporary variable of delegate type for assignment. So that you support both typed and not-typed (dynamic).