sequence of code inside function changed (?)

Posted on
  • Just updated to actual firmware and got problems (function undefined)
    I'm pretty sure it worked fine with older version of firmware.

    function xyz(){
      var me = this;
      me.foo = foo;
      function foo(){}
    }
    

    After changing sequence it worked fine as before

    function xyz(){
      var me = this;
      function foo(){}
      me.foo = foo;
    }
    
  • Thanks, but I'm not sure that would have ever worked - Espruino executes functions top-to-bottom, so the normal JavaScript 'function hoisting' wouldn't work.

  • Wait, what is that supposed to do? I think I may be missing something about JS here.

    How do function statements inside another function call work in js? Does it make a global, or does it do something else?

  • The functions aren't global, but in normal JS it's as if they were defined right at the top of the function. You can use them before they are defined.

    Because Espruino doesn't precompile, that doesn't happen though :(

  • That is some freaky shit.

    I did not know JS let you do that. Is there a reason for allowing such deviant syntax? That seems to break all sorts of normal conventions...

  • ...js is first parsed and jit'ed, and only after it made it syntactically through, it starts to execute... at least what my gut had do accept... and yes, I had a bit a similar idea, because when you then look in (some) browser debugger walking step by step, you see the vars already defined even though you r programm pointer is not there yet / has not passed the var blaBla =... yet.

    I saw this pattern quite frequently in some code... and it did not feel right to me, becuase it assumes that walking through on load happens, which does not happen in Espruino.

    My other half gut - no a bit Espruino trained - also tells me when done this way, the function is created all over again... since Espruino runs/interprets of the source...

    @Gorden is frank enough that I ran into the woods again... (would not be the first time) - but every time I learn something. Over time I hope to stay better in the middle of the road...

  • Is there a reason for allowing such deviant syntax?

    I often wonder that about a lot of JS :)

    function a() {
      function foo() { return "All is well with the world..." }
      return foo();
      function foo() { return "Oh God no. This is horrible!" }
    }
    
    function b() {
      var foo = function() { return "All is well with the world..." }
      return foo();
      foo = function() { return "Oh God no. This is horrible!" }
    }
    
    a(); // "Oh God no. This is horrible!"
    b(); // "All is well with the world..."
    

    I think it was a side-effect of turning it into Bytecode first as @allObjects says, but then they thought it was handy so they left it in...

    At some point I will implement this properly, there are some nice side-effects when applied to Espruino:

    function a() {
      function b() {
        // ...
      }
      setTimeout(b,500);
    }
    

    The code above would have had the function b parsed beforehand, so execution would be faster, and if you called it twice it'd be able to use the same copy of b's code, saving memory.

  • Assumed in the top / global level:

    A) What is the difference between line 1 and 2 below?

    function b() { console.log("b()"); }
    var b = function() { console.log("b()"); };
    

    B) With A) answered, what is the difference between the two blocks below?

    function a() {
      function b() { console.log("b()"); }
      setTimeout(b,500);
    }
    
    function a() {
      var b = function(){ console.log("b()"); }
      setTimeout(b,500);
    }
    

    C):

    if you called it twice it'd be able to use the same copy of b's code, saving memory.

    I assume you mean: called it twice within funcation a(), correct?

    I expect that assigning a function to a variable var b = function(){} is just putting a pointer - like the entry point of the function (the source address) - into the (scoped) variable - same as function b(){} , and then 'skips' the whole function in regard of execution 'to just find the end of the function' in order to resume execution.

    function b parsed beforehand, so execution would be faster.

    ...is that not a contradiction to Espruino executes from source code?

    Because what is created on parsing? If it is more than some 'isParsed' flag that is stored within the 'variable/function' value reference store, then it goes towards JIT compiling and uses unpredictable amounts of memory. And if it is just a flag, what would be the use of it? ...so far I did not find the time - or guts(?) - yet to dive into the interpreter's gut (source code).

  • There is no difference between the two types at the moment...

    But:

    function a() {
      function b() { foo(); }
      doSomething();
    }
    

    What happens now

    • A variable for a is created
    • Inside it, a variable >cod it set to the function's code.

    Result:

    var a = { ">cod" : "{\n  function b() { foo(); }\n  doSomething();\n}" };
    

    What will happen in a later version of Espruino

    • A variable for a is created
    • The function's code is parsed, and the Espruino recursively does the same thing on any functions inside the current one
    • Inside it, a variable >cod it set to the function's code, minus any functions defined inside it.

    Result:

    var a = { 
     "b": { ">cod" : "{ foo(); }"} 
     ">cod" : "{\n  doSomething();\n}" 
    };
    

    Does that make more sense? If you used var b = function() { ... } exactly the same thing would happen in the future as happens now (what's described above).

  • ...@Gordon, I gues I got your (Espruino) 'byte' code... I like it a lot: a hybrid between jit and running 'on' the source...

    I always wondered how running 'solely and purely' on the source still can perform, because, for example, in an if-then at the end, the else - if present - including all its 'content' would have to be parsed, in order to find the end... that would perform 'poorly'... so much for '...purely'.

    Ever since you posted the pseudo code above, my back burner (mind) explored the potential VM construct you are using. Now, I guess, I know also why code uses up variables (variable space) - not just variables for variables and function entry points (which is just another type of variable) - but also unconditioned code segments: the code is parsed and 'code segment variables' are created (in a special variable space in a three structure), on which the VM then 'executes'. That's the way I would be able to handle quickly control structures. Separation of the souce into control structure and linear source fragments.

    Because you mention '...later version of Espruino', I wonder about proper coding for now: less nesting (of function declarations) and all in global (root) level of code gives you faster exection?

    For example:

    function f() { /* do something */ }
    setInterval(f,intervalTime);
    

    is more efficient than

    setInterval(function(){ /*do something*/ },intervalTime);
    

    This could/would(? - or at least partially) explain that the .bind() you implemented 'internally' is faster (AND variable space saving) than the 'self-built' construct with an anonymous function and - most of the time needed - _this or that variable holding on to the this (for proper resolution in the closure / deferred execution context, which has a different context / this...).

  • Ahh - well, in the root scope:

    function f() { /* do something */ }
    setInterval(f,intervalTime);
    

    is slightly less efficient than this:

    setInterval(function(){ /*do something*/ },intervalTime);
    

    As the first has to also define a named variable for the function.

    However,

    function f() { /* do something */ }
    function onInit() {
      setInterval(f,intervalTime);
    }
    

    Is definitely more efficient than:

    function onInit() {
      setInterval(function(){ /*do something*/ },intervalTime);
    }
    

    as the function only exists in memory once. In that last example, it exists in onInit, but after onInit is run, there's another copy in memory.

    Again, that's something that could potentially be changed in the future though - it could just re-use the same characters.

  • Ic. thanks. ...the details create the excitement... ;-)

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

sequence of code inside function changed (?)

Posted by Avatar for JumJum @JumJum

Actions