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

How will this project handle metatables? #4

Closed
CapsAdmin opened this issue May 27, 2019 · 5 comments
Closed

How will this project handle metatables? #4

CapsAdmin opened this issue May 27, 2019 · 5 comments

Comments

@CapsAdmin
Copy link

Is this on the roadmap or is it out of scope for this project?

@hsiaosiyuan0
Copy link
Owner

hsiaosiyuan0 commented May 29, 2019

This question seems about how does this repo handle metatables in its javascript code translation.

Metatable plays a major part in Lua, it has two impressive usages for me:

  1. OOP
  2. Operator Overloading

For OOP, it's implemented over javascript's prototypal inheritance. You could find a example via this demo

For Operator Overloading, it's implemented by translating each binary-expression to a call-expression which traps execution to retrieve custom operator overloading function from the prototype chain of the operands. In order to prove this way is practicable, only '+' operator has been supported right now. It's not too hard to add supports for other operators. For example, you could paste below code into above demo link to see the translated JS:

local a = 1
local b = 2
local c = a + b

Furthermore, there is another metamethod - __call, it could be implemented via some way like how the above Operator Overloading does, but since it's a runtime patch, it will delegate all function calls to the trap function, this will cause a huge performance issue.

Performance issue also bothers the way of Operator Overloading implemented, but thanks to Lua .. operator, string concatenation is split from the addition expression. We know in JS's application, string concatenation is one of the highest frequency expressions. So we can translate .. to + directly without going through the trap function(although demo is not doing so, I'm sorry its my mistake).

As you see, I'd like to let the translated JS code to use the functionalities taken from JS as much as possible to let the translated code could be finally runnable.

@CapsAdmin
Copy link
Author

As far as I can see the only way to properly support metatables is to translate everything into call-expressions (index and newindex too), but then you'll lose so much readability to the javascript output that you might as well make a VM or design a more specialized javascript output.

I'm also looking for a solution to this problem. Maybe the most sane solution is to expose javascript proxies to Lua which would provide access to get, set, apply, etc. Then you'd advertise that metatables are not supported for the reasons above.

@hsiaosiyuan0
Copy link
Owner

hsiaosiyuan0 commented May 30, 2019

As far as I can see the only way to properly support metatables is to translate everything into call-expressions (index and newindex too)

yes, but we'll not only lose the readability but also the performance.

for Every CallExpression when its callee is a MemberExpression in Lua

local a = {}
a.b()

will be translated to JS

let a = {}
runtime.call(a, "b", [/* args */])

runtime.call = function (obj, method, args) {
  let b;
  while(true) {
    b = /* walk up through obj's metatable chain to resolve method 'b' */
  }
  if(b) b.apply(obj, args)
  else throw new BadMethodCallException()
}

Maybe the most sane solution is to expose javascript proxies to Lua which would provide access to get, set, apply, etc

It's intelligent to me, only we have to wrap All objects with Proxy and do method resolving by walking through metatable chain in it. It has the same performance issue to above implementation and in essence, they are very similar.

So what I preferred is supporting the functionalities profited from metatable after doing some tradeoff. I known, it's somewhat cause the language to be a subset of Lua or a dialect, but there is no better way to me now. Yes, as you mention if we implement a LuaVM in JS or WASM we could use the full set of Lua, but this is totally different way to our current implementation, these two different ways have their own advantages.

@rweichler
Copy link

Thank you for making this.

@hsiaosiyuan0
Copy link
Owner

@rweichler @CapsAdmin Thank you guys for interest in this project

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

No branches or pull requests

3 participants