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

the use of debug.setmetatable breaks and or exposes unwanted features in an existing environment #3

Open
CapsAdmin opened this issue Sep 12, 2014 · 6 comments

Comments

@CapsAdmin
Copy link

for instance in castl/core_objects.lua#338 the string __index override breaks indexing strings:likethis()

@PaulBernier
Copy link
Owner

You are right, CASTL loads its own environment which is designed to help imitating JS behavior and it may not behave well when mixing with handwritten regular Lua code (i.e not generated by CASTL). But unfortunately I believe there isn't any other solution than using debug.setmetatable (but to modify the Lua VM, which is unwanted in this project and would break still more regular Lua code).
Nonetheless I think it should not bother you too much. For instance if you want to use myString:find(...), you can strill use the non OO version of it, find(myString, ...), you just have to declare find as a local reference to the original find before the CASTL environment is set up.
I hope this answers your concern, let me know.

@daurnimator
Copy link

Could you not just wrap all javascript strings in a wrapper? e.g.

function newJSString(str)
    return setmetatable({raw=str}, JSString_mt)
end

Same with functions.

@CapsAdmin
Copy link
Author

@PaulBernier I don't think this is a good solution. You are breaking and changing things CASTL isn't part of. I would do what daurnimator suggested if you really want the objects. Or use standard lua like str:sub(5, 5)/string.sub(str, 5,5) instead of str[5].

But then again I don't know if this is supposed to work in an existing environment or if you want to keep it separate as some sort of standalone compiler/converter.

@PaulBernier
Copy link
Owner

I originally didn't think about mixing regular Lua with "CASTL Lua", it was aimed to only execute JS scripts on Lua. But I totally agree it's a very interesting feature. So I implemented a way to do that: a method that restores originals metatable of natives types (number, string, function, boolean and nil) and another to set metatables to support JS behaviors. Here is an example of the use:

-- react.js was compiled to react.lua with CASTL
local React = require "react" -- here CASTL runtime is implicitly loaded and JS environment is enabled by default
local cr = require("castl.runtime")
-- you can disable JS environment
cr._disableJSE()

-- behavior of regular Lua
local str = "Hzllo world"
str = str:gsub("z", "e")

-- you have to re-enable JS environment when using "js objects"
cr._enableJSE()
local Object = cr._obj
local c = React.DOM:h1(Object{}, str)
print(React:renderComponentToString(c))

Advantages

  • it was very quick to implement
  • you don't have to think to wrap every single native type to work with JS code

Wrapping all the native types would require much more work inside the lib, and would entail some performance loss, so I found this solution a good compromise.
What do you think about it? (I haven't pushed this fix yet)

@paulcuth
Copy link

Alternatively, you could create generic handler functions for all the operations in your string metatable and check for type there. At least, that's how I handle it in Hamlet (for example __add becomes https://github.com/paulcuth/hamlet/blob/master/src/runtime/core/lang.lua#L263).

@daurnimator
Copy link

I originally didn't think about mixing regular Lua with "CASTL Lua", it was aimed to only execute JS scripts on Lua. But I totally agree it's a very interesting feature.

One of the cooler things available with a JS=>Lua compiler is allowing use of the many JS libraries to be used with lua directly.
Also, it means that developers can work in different languages, but on the same project.

So I implemented a way to do that: a method that restores originals metatable of natives types (number, string, function, boolean and nil) and another to set metatables to support JS behaviors.

I don't think this is a great way forward, unless you add it as a preamble/postamble inside of javascript functions.

Wrapping all the native types would require much more work inside the lib, and would entail some performance loss, so I found this solution a good compromise.

I feel like wrapping is going to be a better solution, and performance kinks can be worked out later :)

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

4 participants