Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lua fix try #6326

Closed
wants to merge 1 commit into from
Closed

Lua fix try #6326

wants to merge 1 commit into from

Conversation

jdonaldson
Copy link
Member

Here's a changelist to fix up some of the try/catch/loop issues that were spotted recently. It's messy, so I'm happy to discuss it if folks have the stomach for it. I'm guessing there's a more elgant way of doing some of this.

@jdonaldson
Copy link
Member Author

jdonaldson commented Jun 3, 2017

The TLDR of why this is a problem:

Lua lacks a continue operator. So, it's necessary to emulate it. The fastest way to do this is with :

Haxe

while(true){
    break; // normal break
    continue; // continue
}

Lua

local _hx_continue = true;
while(true) do 
 repeat  
   _hx_continue = false; break;  -- normal break
   break; -- continue
   break; -- default end of block marker
 until true end;
 if !_hx_continue then break end;
end;

That looks awful, but it runs the fastest. This gets even more complicated with try/catch blocks. In Lua, these are not just blocks, but function calls:

Haxe

try (throw("error")) catch (e:Dynamic) trace(e);

Lua

local _hx_status, _hx_result = pcall(function() 
  _G.error("error");
  return _hx_pcall_default;
end);
if not _hx_status then
   print(_hx_result); -- an error was caught, trace it.
-- ... etc.

This gets really complicated when trying to mix the semantics of these two features. Standard loop operators like break won't work inside a pcall body. So, everything must turn into a thrown error, and caught. However, we really want to avoid using pcall if possible, it's a slower operation than plain code.

Anyways, I wanted to give a brain dump here... mainly just so I can rubber duck this and think through it by explaining it.

@jdonaldson
Copy link
Member Author

jdonaldson commented Jun 7, 2017

I came up with a workaround here. The general gist is that the TWhile type handlers will be responsible for tracking continue usage, and will set up some variables to track those. It's not necessary to use pcall/error there, and I want to avoid that if possible. The TWhile handler will also set a ctx.in_loop variable marking parts of code that need special loop semantics.

The TTry handler will check for the ctx.in_loop variable, and set the ctx.in_loop_try variable. This means special semantics for break inside of try inside of (e.g.) while. It will set up a special error handler for breaks thrown within the loop if ctx.in_loop is set. If it catches one of those, it will emit a plain break statement that gets picked up by the enclosing loop.

Finally, the TBreak and TContinue handlers will check for both of these variables. If they're in a plain loop, they emit plain break and/or set the _hx_continue_# variable. Otherwise, they emit a _G.error("_hx_pcall_break") error, which will get caught by the TTry handler.

@jdonaldson jdonaldson closed this Jun 7, 2017
@jdonaldson jdonaldson deleted the lua_fix_try branch June 8, 2017 16:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant