HaxeFoundation / HaxeFoundation/haxe
Enum/Switch Fusion
- Dominant language
- Haxe
- Stars
- 6.9k
- Forks
- 715
- Avg merge
- 2d 2h
- Merged PRs (30d)
- 11
Description
It would be nice to add the Enum/Switch Fusion feature, which eliminates intermediate `enum` and `switch`. It is similar to inlining, which eliminates intermediate function call, and brings zero-cost abstraction.
Here is a sample code to show how `enum` and `switch` should be optimized.
http://try.haxe.org/#2b610
The original code:
``` haxe
enum Option {
None;
Some(v : T);
}
class Test {
static inline function sqrt(x:Float) {
return if (x >= 0) Some(Math.sqrt(x)) else None;
}
static function trace_sqrt(x) {
switch (sqrt(x)) {
case None:
trace("none");
case Some(v):
trace('sqrt($x) = $v');
}
}
static function trace_sqrt_fused(x:Float) {
if (x >= 0) {
var v = Math.sqrt(x);
trace('sqrt($x) = $v');
} else {
trace("none");
}
}
static function main() {
trace_sqrt(9.0);
trace_sqrt_fused(9.0);
}
}
```
In that program, the `sqrt` function generates `Option`. The function `trace_sqrt` uses `sqrt` and immediately decompose the enum with `switch` expression. `trace_sqrt_fused` is a comparison case that doesn't use `Option`.
The following is the compiled code (with Full DCE and Analyzer options):
``` js
Test.trace_sqrt = function(x) {
{
var _g = x >= 0?Option.Some(Math.sqrt(x)):Option.None;
switch(_g[1]) {
case 0:
console.log("none");
break;
case 1:
console.log("sqrt(" + x + ") = " + _g[2]);
break;
}
}
};
Test.trace_sqrt_fused = function(x) {
if(x >= 0) {
var v = Math.sqrt(x);
console.log("sqrt(" + x + ") = " + v);
} else console.log("none");
};
```
`trace_sqrt` uses intermediate data structures, so it looks less efficient than `trace_sqrt_fused`.
The fused version would be acquired like the following steps.
```
switch (if (x >= 0) Some(Math.sqrt(x)) else None) { case None: f(); case Some(v): g(v); }
=
if (x >= 0) (switch (Some(Math.sqrt(x))) { case None: f(); case Some(v): g(v); })
else (switch (None) { case None: f(); case Some(v): g(v); });
=
if (x >= 0) { var v = Math.sqrt(x); g(v); }
else { f(); }
```
Contributor guide
Assessment
This issue has not been assessed yet.