How to inline iterators?

87 views
Skip to first unread message

Ed Ryzhov

unread,
Aug 18, 2013, 7:56:34 AM8/18/13
to haxe...@googlegroups.com
Hello.

When we use arrays or common types from haxe.ds, iterators got inlined into code like this:

Haxe code:
var a = ['qwe', 'cc', 'dd'];
for (t in a)
{
trace(t);
}
var a = new GenericStack<Int>();
a.add(3);
a.add(4);
for (t in a)
{
trace(t);
}

And generated as3 code:

var a : Array = ["qwe","cc","dd"];
{
var _g : int = 0;
while(_g < a.length) {
var t : String = a[_g];
++_g;
haxe.Log._trace(t,{ fileName : "InlineIters.hx", lineNumber : 18, className : "InlineIters", methodName : "main"});
}
};
var a1 : haxe.ds.GenericStack_Int = new haxe.ds.GenericStack_Int();
a1.add(3);
a1.add(4);
{
var _g1 : haxe.ds.GenericCell_Int = a1.head;
while(_g1 != null) {
var t1 : int = _g1.elt;
_g1 = _g1.next;
haxe.Log._trace(t1,{ fileName : "InlineIters.hx", lineNumber : 27, className : "InlineIters", methodName : "main"});
}
};

Just want to know there any way to enable this for custom types or it hardcoded in compiler?

Thanks,
Ed.

Dan Korostelev

unread,
Aug 18, 2013, 3:12:50 PM8/18/13
to haxe...@googlegroups.com
That's quite an interesting question. It would be nice to have some way to alter iterator code generation. For example, one could create an iterator for object fields without creating an intermediate array like Reflect.fields does.

воскресенье, 18 августа 2013 г., 15:56:34 UTC+4 пользователь Ed Ryzhov написал:

TopHattedCoder

unread,
Aug 18, 2013, 9:05:34 PM8/18/13
to haxe...@googlegroups.com
By marking the constructor with inline, it's fields will be inlined into the surrounding block.
For example:
for(i in new FloatIter(0.5, 7.5))
            trace
(i);

class FloatIter {
   
public var v:Float;
   
public var max:Float;
   
public var step:Float;
   
public inline function new(min:Float, max:Float, step:Float = 1.0) {
        v
= min;
       
this.max = max;
       
this.step = step;
   
}
   
public inline function hasNext():Bool
       
return v < max;

   
public inline function next():Float
       
return v += step;
}


Compiles to the following javascript:
var _g_v = 0.5, _g_max = 7.5, _g_step = 1.0;
while(_g_v < _g_max) {
   
var i = _g_v += _g_step;
    haxe
.Log.trace(i,{ fileName : "Game.hx", lineNumber : 14, className : "Game", methodName : "new"});
}

Dan Korostelev

unread,
Aug 19, 2013, 4:59:41 AM8/19/13
to haxe...@googlegroups.com
Wow, thanks for info, that looks great. Is it documented somewhere?

понедельник, 19 августа 2013 г., 5:05:34 UTC+4 пользователь TopHattedCoder написал:

Ed Ryzhov

unread,
Aug 20, 2013, 5:51:08 PM8/20/13
to haxe...@googlegroups.com
Looks like i'm doing something wrong.

Custom single linked list, for example.
Sorry for long code.

Haxe code:
class Int_SLL
{
 
public var head:Int_SLLNode;
 
 
inline public function new()
 
{
 head
= null;
 
}
 
 
inline public function push(a:Int):Int_SLLNode
 
{
 
var node = new Int_SLLNode();
 node
.data = a;
 node
.next = head;
 head
= node;
 
return node;
 
}
 
 
inline public function iterator():Int_SLLIter
 
{
 
return (new Int_SLLIter(head));
 
}
}

class Int_SLLNode
{
 
inline public function new(){}
 
public var next:Int_SLLNode;
 
public var data:Int;
}
class Int_SLLIter
{
 
public var walker:Int_SLLNode;
 
 
inline public function new(a:Int_SLLNode)
 
{
 walker
= a;

 
}
 
public inline function hasNext():Bool
 
{

 
return (walker != null);
 
}
 
public inline function next():Int
 
{
 
var r = walker.data;
 walker
= walker.next;
 
return r;
 
}
}
 
static function main()
 
{

 
var a = ['qwe', 'cc', 'dd'];
 
 
for (t in a)
 
{
 trace
(t);
 
}
 
 
 
var a = new GenericStack<Int>();
 a
.add(3);
 a
.add(4);
 
for (t in a)
 
{
 trace
(t);
 
}

 
 
var a = new Int_SLL();
 a
.push(3);
 a
.push(4);

 
for (t in a)
 
{
 trace
(t);
 
}
 
 
}


as3 code:
 static public function main() : void {

 
var a : Array = ["qwe","cc","dd"];
 
{
 
var _g : int = 0;
 
while(_g < a.length) {
 
var t : String = a[_g];
 
++_g;
 haxe
.Log._trace(t,{ fileName : "InlineIters.hx", lineNumber : 18, className : "InlineIters", methodName : "main"});
 
}
 
};
 
var a1 : haxe.ds.GenericStack_Int = new haxe.ds.GenericStack_Int();
 a1
.add(3);
 a1
.add(4);
 
{
 
var _g1 : haxe.ds.GenericCell_Int = a1.head;
 
while(_g1 != null) {
 
var t1 : int = _g1.elt;
 _g1
= _g1.next;
 haxe
.Log._trace(t1,{ fileName : "InlineIters.hx", lineNumber : 27, className : "InlineIters", methodName : "main"});
 
}
 
};

 
var a2 : haxe.ds.Int_SLL = new haxe.ds.Int_SLL();
 a2
.push(3);
 a2
.push(4);
 
{ var $it : * = a2.iterator();
 
while( $it.hasNext() ) { var t2 : int = $it.next();
 haxe
.Log._trace(t2,{ fileName : "InlineIters.hx", lineNumber : 37, className : "InlineIters", methodName : "main"});
 
}}
 
}

and JS code:
InlineIters.main = function() {
 
var a = ["qwe","cc","dd"];
 
var _g = 0;
 
while(_g < a.length) {
 
var t = a[_g];
 
++_g;
 console
.log(t);
 
}
 
var a1 = new haxe.ds.GenericStack();
 a1
.head = new haxe.ds.GenericCell(3,a1.head);
 a1
.head = new haxe.ds.GenericCell(4,a1.head);
 
var $it0 = a1.iterator();
 
while( $it0.hasNext() ) {
 
var t = $it0.next();
 console
.log(t);
 
}
 
var a2 = new ryz.tmp.Int_SLL();
 a2
.push(3);
 a2
.push(4);
 
var $it1 = a2.iterator();
 
while( $it1.hasNext() ) {
 
var t = $it1.next();
 console
.log(t);
 
}
}

Maybe it works only in nightly builds?
I'm using prebuilt haxe 3.0.0 from official site.

Thanks.

TopHattedCoder

unread,
Aug 20, 2013, 10:33:41 PM8/20/13
to haxe...@googlegroups.com
That might be your problem then.


On Sunday, August 18, 2013 12:56:34 PM UTC+1, Ed Ryzhov wrote:

Ed Ryzhov

unread,
Aug 21, 2013, 11:13:10 AM8/21/13
to haxe...@googlegroups.com
Still doesn't work even with nightly build.
Any ideas?

TopHattedCoder

unread,
Aug 21, 2013, 4:09:28 PM8/21/13
to haxe...@googlegroups.com
They may have to be under a certain simplicity threshold to be inlined. Try something simpler.


On Sunday, August 18, 2013 12:56:34 PM UTC+1, Ed Ryzhov wrote:
Reply all
Reply to author
Forward
0 new messages