Jump to content

Welcome to Smart Home Forum by FIBARO

Dear Guest,


as you can notice parts of Smart Home Forum by FIBARO is not available for you. You have to register in order to view all content and post in our community. Don't worry! Registration is a simple free process that requires minimal information for you to sign up. Become a part of of Smart Home Forum by FIBARO by creating an account.


As a member you can:

  •     Start new topics and reply to others
  •     Follow topics and users to get email updates
  •     Get your own profile page and make new friends
  •     Send personal messages
  •     ... and learn a lot about our system!



Smart Home Forum by FIBARO Team

The missing loadstring...


Recommended Posts

Here is another hack for people a bit deeper into Lua.


A Lua "compiler" written in vanilla Lua, i.e. the sandbox we have to our disposal on the HC2.

A good way to really learn Lua is to write a Lua compiler :-) (and "hand-coding" a parser is really old-school)

Please login or register to see this attachment.


It compiles Lua src code to nested Lua functions that execute "resonable" ok. About a factor 10-50 slower than native Lua. (it depends a lot on the type of Lua code).

It complies the whole Lua language (except labels and goto, and it doesn't support 'meta tables', but it's doable..).


It consists of 2 functions, 'parser' and 'compiler' - 'parser' is around ~500 lines and 'compiler' around ~230 lines.


...and it allows us to easily implement 'loadstring'

Please login or register to see this code.

A simple example, a factorial function defined in Lua.

Please login or register to see this code.

fac1 is our compiled function, and fac2 is a native Lua version. On the HC2 we run them 50 times each and calculate 50!

The result: (times may vary a bit)

Please login or register to see this code.

This gives us 50x slower, but the emulated version still calculate 50! in 1,25 milliseconds... that's ok-ish. fac2 is a recursive function and the lookup of the fac2 function binding gets increasingly expensive for each depth of recursion in the current implementation - so this type of function may unfortunately be exceptional slow compared to native versions. See a later post where a 'between' function is only 10x more expensive.

This means that it could be useful for loading Lua library code into scenes - if they are long running scenes that is, because bringing in the compiler and compiling a function has an overhead in itself.  I may consider it for my EventRunner scene.


The parser can parse itself so only the code for the compiler needs to be included (the parse-tree for the parser can be stored in a fibaro global, read in and compiled). It can parse and compile EventRunner3 (~3000 lines of code, but I didn't dare to try to execute the code yet :-) )


These test examples compiles and executes correctly:

Please login or register to see this code.



Edited by jgab
argument lists with nil compiled wrong. more bugfixes
  • Like 2
  • Thanks 1
Link to comment
Share on other sites

  • Topic Author
  • So, here is a more real application of loadstring.

    In this case we define a loadstring function that fetches the parser part (500+ lines) from my GitHub and stores it in a fibaro global (LUAPARSER).

    When loadstring is defined in the scene it will read in the parser and compile it. Then it will use the compiled parser to parse the lua string given to loadstring, and then compile the parsed function and return it. 

    This means that we only need to include the code for the compiler part in the scene (~200lines). In the example below the loadstring definition is a "on-liner" run through

    Please login or register to see this link.

     and placed at the end of the scene.


    In the example we load a "between" function discussed in the forum thread 

    Please login or register to see this link.


    We benchmark it with a native version of the function:

    Please login or register to see this code.

    Our loadstring version takes 3ms, and the native Lua version 30us.

    10-15 times slower - that's reasonable.

    Please login or register to see this code.

    Because fetching the parser uses httprequest and is asynchronous, the setup ends by calling 'main' if 'main' exists.

    If you don't have a main I would suggest just running the setup so that the fibaro global is ready.


    Edited by jgab
    • Like 1
    Link to comment
    Share on other sites

    Join the conversation

    You can post now and register later. If you have an account, sign in now to post with your account.

    Reply to this topic...

    ×   Pasted as rich text.   Paste as plain text instead

      Only 75 emoji are allowed.

    ×   Your link has been automatically embedded.   Display as a link instead

    ×   Your previous content has been restored.   Clear editor

    ×   You cannot paste images directly. Upload or insert images from URL.

    • Create New...