bakpakin / Fennel

Lua Lisp Language
https://fennel-lang.org
MIT License
2.48k stars 126 forks source link

Issues with `.` and `:` syntax when working with Sol3 bound methods #484

Closed doing-fine-thanks closed 3 months ago

doing-fine-thanks commented 3 months ago

Hi folks,

I am admittedly a very new Fennel user and also a very new Lua user, so I might be missing something pretty basic. Currently I am trying to add a lisp scripting layer to a C++ game engine and decided to you Sol for the Lua bindings. Currently nested object access works on the Lua side of things:

CameraManager.getInstance().camera.zoom = 10

but on the Fennel side I get errors related to unknown identifiers:

(print (. (. (: CameraManager getInstance) camera) zoom))
src/engine/scripting/main.fnl:1:30: Compile error: unknown identifier: getInstance

(print (. (. (: CameraManager getInstance) camera) zoom))
* Try looking to see if there's a typo.
* Try using the _G table instead, eg. _G.getInstance if you really want a global.
* Try moving this code to somewhere that getInstance is in scope.
* Try binding getInstance as a local in the scope of this code.
stack traceback:
    [C]: in function 'base.error'
    ./include/fennel/fennel.lua:4045: in function 'fennel.friend.assert-compile'
    ./include/fennel/fennel.lua:2626: in function 'fennel.compiler.assert'
    ./include/fennel/fennel.lua:2817: in function 'fennel.compiler.symbol-to-expression'
    ./include/fennel/fennel.lua:3274: in function <./include/fennel/fennel.lua:3267>
    (...tail calls...)
    ./include/fennel/fennel.lua:1619: in function <./include/fennel/fennel.lua:1618>
    (...tail calls...)
    ./include/fennel/fennel.lua:3176: in function <./include/fennel/fennel.lua:3175>
    (...tail calls...)
    ./include/fennel/fennel.lua:1198: in local 'special'
    ./include/fennel/fennel.lua:3176: in function <./include/fennel/fennel.lua:3175>
    (...tail calls...)
    ./include/fennel/fennel.lua:1198: in local 'special'
    ./include/fennel/fennel.lua:3176: in function <./include/fennel/fennel.lua:3175>
    (...tail calls...)
    ./include/fennel/fennel.lua:3220: in function <./include/fennel/fennel.lua:3206>
    (...tail calls...)
    ./include/fennel/fennel.lua:3675: in function <./include/fennel/fennel.lua:3661>
    (...tail calls...)
    ./include/fennel/fennel.lua:5735: in function 'include.fennel.fennel.eval'
    (...tail calls...)
    src/engine/scripting/init.lua:3: in main chunk

It seems to work to use the multisym syntax and go one struct depth at a time, but that make the code feel pretty cumbersome:

(local cam-manager (CameraManager:getInstance))
(local camera cam-manager.camera)
(set camera.zoom 10)

For references I am binding the c++ code through Sol like this:

sol::usertype<CameraManager> camera_manager_type = lua->new_usertype<CameraManager>(
    "CameraManager",
    "getInstance",&CameraManager::getInstance,
        "camera",  &CameraManager::camera
);

sol::usertype<Camera2D> camera_type = lua->new_usertype<Camera2D>(
    "Camera2D",
    "zoom",
    &Camera2D::zoom
);

Even if I try the polish-notated object access going step by step, the program still errors when trying to find identifiers.

Sorry if I am missing something obvious and thank you in advanced!

technomancy commented 3 months ago

There's nothing to do with Sol here; it just needs to use strings for the table keys:

(print (. (. (: CameraManager getInstance) camera) zoom))

This should be rewritten as

(print (. (CameraManager:getInstance) :camera :zoom))

In general you can use https://fennel-lang/see to convert a given piece of Lua into Fennel. The other example would look like this:

(tset (. (CameraManager.getInstance) :camera) :zoom 10)
doing-fine-thanks commented 3 months ago

Ah, my bad! thank you so much (the conversion tool is immensely helpful).

doing-fine-thanks commented 3 months ago

feel free to tag as "error-between-keyboard-and-chair."

technomancy commented 3 months ago

Haha cool. Have fun!