Returning a constant from the ffi
This isn't a bug but more of a question/potential point for documentation. I've been able to successfully implement functions in the FFI, but constants are proving a bit elusive for me. If I try to implement Global.infinity this way:
exports["infinity"] = []() -> boxed {
return 1000.0;
};
And then I print it out later like this:
std::cout << "infinity " << unbox<double>(Global::infinity()) << std::endl;
I see the following output on the console:
infinity 6.90463e-310
I'm probably doing something wrong in the export, but I'm not quite sure how to get it to print the right number (in this case 1000.0, eventually I'll use the C++ infinity, but this is just a sanity check). Thanks in advance for your advice!
The thunk for foreign values is implicit – the compiler creates the nullary accessor function for you – so your exports should just be the values you want to set. This is why foreign functions don't need to be wrapped in a nullary function either. So for your case, infinity should just be set to 1000.0 directly. See these examples from prelude.
Great, thanks!
I also hit this trying to bind to some enum values, following an example here https://github.com/lettier/purescript-native-ffi/blob/lambda-lantern/panda3d/panda3d.cpp#L910,
exports["textAlignCenter"] = []() -> boxed {
return box<TextProperties::Alignment>(TextNode::A_center);
};
which is bound like so
foreign import data TextAlignment :: Type
foreign import textAlignCenter :: TextAlignment
I was getting garbage values as well and eventually guessed it was a pointer and removed the function and the box I had wrapped it in. But it makes me wonder if that example worked at some point. Did this behavior change?
The FFI definitely changed when going from the older (pure11) implementation to the current one, so there might be some things left over from when people ported their code.
Could this be a compiler warning? I realized recently that the purescript compiler actually parses the js in some way to detect unimplemented foreign values. I'd find this a very convenient alternative to the current runtime errors. I found this on stackage https://hackage.haskell.org/package/language-go.
Yeah, it could be done, especially with a library like that available. However, I haven't planned on doing it. Earlier backends I created required the full FFI implemented (for every module dependency) during build time, but the issue there is that it's a big commitment (for one person, at least) to write them all. The dynamic method allows for just implementing whatever one needs for their program. Warnings (as you suggest) wouldn't be a bad compromise, but you'd get a lot of them and thus maybe lose some of that benefit (of seeing what's missing). However, I've been doing a bit of performance testing on the panic-on-type-assertion question (in the other issue comments) and I can't see any performance loss with the latest version of golang, so I'm inclined to move to the friendlier panic error messages (single return from type assertion) by default (or altogether), asap.
There's also the idea of checking implemented ffi values to make sure they are correct (which maybe you were also getting at earlier). I haven't made plans for that either at this point.