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

Configurable LUA_COMPAT_FLOATSTRING #113

Closed
timkurvers opened this issue Mar 2, 2018 · 13 comments
Closed

Configurable LUA_COMPAT_FLOATSTRING #113

timkurvers opened this issue Mar 2, 2018 · 13 comments

Comments

@timkurvers
Copy link

timkurvers commented Mar 2, 2018

As @fallenoak mentioned in fengari-lua/fengari-interop#31, we're dealing with Lua scripts from a game client that we'd like to use unmodified.

These scripts were originally written for Lua 5.1 and do not use any string formatting utils, solely relying on integer interpolation into strings.

A (dumbed down) example of a script that causes issues:

dropdown.numButtons = 0 -- a JS object, with fengari-interop setting numButtons to 0
...
local index = dropdown.numButtons + 1 -- index is 1.0 here as JS numbers become floats in fengari-interop
local name = "Object"..index;
print(name)
-- "Object1.0"

In addition, these scripts are a global bonanza and frequently require referencing objects through named globals. Object1.0 is not a valid identifier and that is essentially as far as we get.

As kindly pointed out by @daurnimator, Fengari currently assumes LUA_COMPAT_FLOATSTRING is not set when dealing with float to string conversion:

let str = lua_number2str(obj.value);
// Assume no LUA_COMPAT_FLOATSTRING
if (/^[-0123456789]+$/.test(str)) {  /* looks like an int? */
  str += String.fromCharCode(lua_getlocaledecpoint()) + '0'; /* adds '.0' to result */
}
buff = to_luastring(str);

Would it be possible to make LUA_COMPAT_FLOATSTRING configurable?

@daurnimator
Copy link
Member

daurnimator commented Mar 4, 2018

Added with b2c7f18. However, it wasn't easily configurable.

Now with 96f8515 I think this should work:

const fengari = require("fengari");
fengari.luaconf.LUA_COMPAT_FLOATSTRING = true;
// normal fengari things...

I don't love that it's a global setting. But not sure what else to do while staying in the spirit of the lua C api.

@daurnimator
Copy link
Member

Wait no that won't work: lobject.js squirrels away the original value before you get a chance to modify it

@daurnimator daurnimator reopened this Mar 4, 2018
@daurnimator
Copy link
Member

I'm still looking for ways to make luaconf.js... configurable.

  • Needs to happen at build time
  • Need to be able to provide defaults in JS source

Let me know if you have any ideas @timkurvers @fallenoak

  • webpack DefinePlugin doesn't work, as it only replaces globals.
  • maybe could make it runtime configurable? possible for LUA_COMPAT_FLOATSTRING but not so much for other vars (e.g. LUAI_MAXSTACK)
  • would like to avoid telling you to use sed
  • want something I can use from travis

@timkurvers
Copy link
Author

timkurvers commented Mar 6, 2018

Thanks for looking into this @daurnimator, appreciated!

Using the module syntax from ES6 would make this relatively easy as all bindings are live, e.g:

let LUA_COMPAT_FLOATSTRING = false;
export {
  LUA_COMPAT_FLOATSTRING,
};
import { LUA_COMPAT_FLOATSTRING } from './luaconf.js'`

The value can be changed at runtime (although most likely not from an import, may have to happen with a function call in luaconf or something similar). This even works with Babel and the likes, as they are clever enough to emulate these live bindings.

Using only CJS, I suppose the best bet would be to emulate those live bindings, by fetching values from luaconf rather than extracting values early, e.g:

const {
    ldexp,
    lua_getlocaledecpoint,
    lua_integer2str,
    lua_number2str
} = require('./luaconf.js');
const luaconf = require('./luaconf');

// later, at runtime:
luaconf.LUA_COMPAT_FLOATSTRING

@giann giann closed this as completed Mar 6, 2018
@daurnimator
Copy link
Member

@giann did you mean to close this?

@timkurvers huh. I didn't realise ES6 imports worked like that.
That would be a relativly big change to make before release; it was brought up before in #76

@giann
Copy link
Member

giann commented Mar 7, 2018

My bad. Didn’t mean to close this.

@giann giann reopened this Mar 7, 2018
@timkurvers
Copy link
Author

timkurvers commented Mar 10, 2018

@daurnimator Yeah, I can see how that would be a pretty large overhaul.

What do you think about the approach of fetching values at runtime from a luaconf object?

@daurnimator
Copy link
Member

@timkurvers the problem is that we need to make sure that the values don't change at runtime. They can only ever be changed before the first fengari call.

So maybe we e.g. call Object.freeze() as soon as the first non-luaconf module is loaded? Or before the first lua_newstate call?
Even then: I'd prefer it was only configurable at "compile" time (i.e. when you run webpack).
Hrm.

@timkurvers
Copy link
Author

timkurvers commented Mar 10, 2018

Ah sorry @daurnimator, I see.

Had you considered using Node's process.env in combination with Webpack's environment plugin?

Edit: What's neat about process.env is that when combined with Travis' build matrix and the env configuration, it'll test those scenarios separately: https://docs.travis-ci.com/user/customizing-the-build/#Build-Matrix

@daurnimator
Copy link
Member

FYI LUA_COMPAT_FLOATSTRING got removed in lua 5.4-work1. This makes me want to remove it too...

@daurnimator
Copy link
Member

daurnimator commented Mar 14, 2018

Had you considered using Node's process.env in combination with Webpack's environment plugin?

process.env can change at runtime.
I'm looking for something that is hardcoded at 'compile' time, but has a default.
It could be simple as a webpack find/replace plugin (but I don't know of such a thing :( )

@daurnimator
Copy link
Member

@timkurvers let me know what you think about #116

@timkurvers
Copy link
Author

Looks great!

FYI LUA_COMPAT_FLOATSTRING got removed in lua 5.4-work1. This makes me want to remove it too...

Yeah, once it's gone we'll probably have to look into other options or perhaps maintain a fork or something. Thanks again for now! 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants