diff --git a/hscript/Async.hx b/hscript/Async.hx index de3f264..233a32f 100644 --- a/hscript/Async.hx +++ b/hscript/Async.hx @@ -79,8 +79,10 @@ class Async { function buildSync( e : Expr, exit : Expr ) : Expr { switch( expr(e) ) { - case EFunction(_): - return toCps(e, null, null); + case EFunction(_,_,name,_): + if( name != null ) + return toCps(e, null, null); + return e; case EBlock(el): var v = saveVars(); for( e in el ) @@ -96,7 +98,7 @@ class Async { case EBreak if( currentBreak != null ): return currentBreak(e); case EContinue if( currentLoop != null ): - return block([call(currentLoop, [nullId], e), mk(EReturn(),e)],e); + return block([retNull(currentLoop, e), mk(EReturn(),e)],e); case EFor(_), EWhile(_): var oldLoop = currentLoop, oldBreak = currentBreak; currentLoop = null; @@ -106,7 +108,7 @@ class Async { currentBreak = oldBreak; return e; case EReturn(eret) if( exit != null ): - return block([call(exit,[eret == null ? nullId : eret], e), mk(EReturn(),e)], e); + return block([eret == null ? retNull(exit, e) : call(exit,[eret], e), mk(EReturn(),e)], e); default: return Tools.map(e, buildSync.bind(_, exit)); } @@ -133,7 +135,9 @@ class Async { return mk(EFunction([for( a in arg ) { name : a, t : null }], e, name), e); } - inline function block(arr, e) { + inline function block(arr:Array, e) { + if( arr.length == 1 && expr(arr[0]).match(EBlock(_)) ) + return arr[0]; return mk(EBlock(arr), e); } @@ -149,8 +153,12 @@ class Async { return mk(ECall(e, args), inf); } - function retNull(e) : Expr { - return call(e, [nullId],e); + function retNull(e:Expr,?pos) : Expr { + switch( expr(e) ) { + case EFunction([{name:"_"}], e, _, _): return e; + default: + } + return call(e, [nullId], pos == null ? e : pos); } function makeCall( ecall, args : Array, rest : Expr, exit, sync = false ) { @@ -179,7 +187,9 @@ class Async { if( !syncFlag ) return; switch( expr(e) ) { - case ECall(_), EFunction(_): + case ECall(_): + syncFlag = false; + case EFunction(_,_,name,_) if( name != null ): syncFlag = false; case EMeta("sync" | "async", _, _): // isolated from the sync part @@ -206,7 +216,7 @@ class Async { // local recursion for( e in el ) switch( expr(e) ) { - case EFunction(_, _, name, null): varNames.push(name); + case EFunction(_, _, name, null): if( name != null ) varNames.push(name); default: } while( el.length > 0 ) { @@ -250,7 +260,7 @@ class Async { var oldLoop = currentLoop, oldBreak = currentBreak; var loop = ident("_loop" + id,e); currentLoop = loop; - currentBreak = function(inf) return block([call(rest, [nullId], inf), mk(EReturn(),inf)], inf); + currentBreak = function(inf) return block([retNull(rest, inf), mk(EReturn(),inf)], inf); var efor = block([ mk(EVar("_i" + id, call(ident("makeIterator",eit),[eit],eit)),eit), fun("_", block([ @@ -258,7 +268,7 @@ class Async { mk(EVar(v, call(field(it, "next",it), [], it)), it), toCps(eloop, loop, exit), ], it),"_loop" + id), - call(loop, [nullId], e), + retNull(loop, e), ], e); currentLoop = oldLoop; currentBreak = oldBreak; @@ -306,18 +316,18 @@ class Async { var loop = ident("_loop" + id, cond); var oldLoop = currentLoop, oldBreak = currentBreak; currentLoop = loop; - currentBreak = function(e) return block([call(rest, [nullId], e), mk(EReturn(),e)],e); + currentBreak = function(e) return block([retNull(rest,e), mk(EReturn(),e)],e); var ewhile = block([ fun("_r", - toCps(cond, fun("_c", mk(EIf(ident("_c", cond), toCps(ewh, loop, exit), call(rest, [nullId], cond)),cond)), exit) + toCps(cond, fun("_c", mk(EIf(ident("_c", cond), toCps(ewh, loop, exit), retNull(rest,cond)),cond)), exit) , "_loop"+id), - call(loop, [nullId], cond), + retNull(loop, cond), ],e); currentLoop = oldLoop; currentBreak = oldBreak; return ewhile; case EReturn(eret): - return eret == null ? call(exit, [nullId], e) : toCps(eret, exit, exit); + return eret == null ? retNull(exit, e) : toCps(eret, exit, exit); case EObject(fields): var id = "_o" + uid++; var rest = call(rest, [ident(id,e)], e); @@ -353,10 +363,10 @@ class Async { return toCps(earr, fun(id1, toCps(eindex, fun(id2, call(rest, [mk(EArray(ident(id1,e), ident(id2,e)),e)], e)), exit)), exit); case EVar(v, t, ev): if( ev == null ) - return block([e, call(rest, [nullId],e)], e); + return block([e, retNull(rest, e)], e); return block([ mk(EVar(v, t),e), - toCps(ev, fun("_r", block([binop("=", ident(v,e), ident("_r",e), e), call(rest,[nullId],e)], e)), exit), + toCps(ev, fun("_r", block([binop("=", ident(v,e), ident("_r",e), e), retNull(rest,e)], e)), exit), ],e); case EConst(_), EIdent(_), EUnop(_), EField(_): return call(rest, [e], e); @@ -375,7 +385,7 @@ class Async { return currentBreak(e); case EContinue: if( currentLoop == null ) throw "Continue outside loop"; - return block([call(currentLoop, [nullId], e), mk(EReturn(),e)], e); + return block([retNull(currentLoop, e), mk(EReturn(),e)], e); case ESwitch(v, cases, def): var cases = [for( c in cases ) { values : c.values, expr : toCps(c.expr, rest, exit) } ]; return toCps(v, mk(EFunction([ { name : "_c", t : null } ], mk(ESwitch(ident("_c",v), cases, def == null ? retNull(rest) : toCps(def, rest, exit)),e)),e), exit );