Finally, parser stack overflow problem avoiding algo

Discussion in 'KONTAKT: Sampling, Programming & Scripting' started by Levitanus, Jun 27, 2017.

  1. Levitanus

    Levitanus Active Member

    Well, i've met this problem not far ago at first time, because usually my interfaces are laconic, but that one was too comprehensive.
    I've found, that stack overflowing if any function (including callbacks) get much than ~ 5600 lines (depends on variable-names length).
    So, we have to solve several problems:
    • make functions (including callbacks) as short as we can
    • make it readable and editable
    • don't spend too much time to jump from place to place, constructing code
    I'll talk about on init callback as about the usual cause of problems with stack.
    We need to move every line of code, which not declare anything to the function called just after init callback called. Calling of that function will be solved via pgs. So, instead this code:
    Code:
    on init
       declare ui_button $button
       declare $button_id := get_ui_id($button)
       set_control_par ($button_id,$CONTROL_PAR_WIDTH,140)
       set_control_par ($button_id,$CONTROL_PAR_HEGHT,40)
       set_control_par_str ($button_id,$CONTROL_PAR_TEXT,"text")
    end on
    we should have this:
    Code:
    on init
       declare ui_button $button
       declare $button_id := get_ui_id($button)
       pgs_create_key (INIT,1)
       pgs_set_key_val(INIT,0,1)
    end on
    function button_init
       set_control_par ($button_id,$CONTROL_PAR_WIDTH,140)
       set_control_par ($button_id,$CONTROL_PAR_HEGHT,40)
       set_control_par_str ($button_id,$CONTROL_PAR_TEXT,"text")
    end function
    on pgs_changed
       if (pgs_get_key_val(INIT,0) = 1)
         call init_definit
         pgs_set_key_val (INIT,0,0)
       end if
    end on
    Yeah! We did it, no more stack owerflow in init.
    BUT we still love, and it's normal, to write ui in the first manner. We don't want to write declare in the init callback, than go to the some function in 3000 lines forward and make initial assignments.
    So i suggest to use this approach (sublime text only):
    Code:
    on init
      pgs_create_key (INIT,1)
      pgs_set_key_val(INIT,0,1)
    end on
    
    function initialize
      declare ui_button $button
      declare $button_id := get_ui_id($button)
      set_control_par_str ($button_id,$CONTROL_PAR_TEXT,"text")
      set_control_par ($button_id,$CONTROL_PAR_WIDTH,140)
      set_control_par ($button_id,$CONTROL_PAR_HEIGHT,40)
    end function
    
    function button_init
      initialize
    end function
    
    on pgs_changed
      if (pgs_get_key_val(INIT,0) = 1)
      call button_init
      pgs_set_key_val (INIT,0,0)
      end if
    end on
    
    now from sublime text will get out the code:
    Code:
    on init
      pgs_create_key(INIT,1)
      pgs_set_key_val(INIT,0,1)
      declare ui_button $_button
      declare $_button_id
    end on
    
    function button_init
      $_button_id := get_ui_id($_button)
      set_control_par_str($_button_id,$CONTROL_PAR_TEXT,"text")
      set_control_par($_button_id,$CONTROL_PAR_WIDTH,140)
      set_control_par($_button_id,$CONTROL_PAR_HEIGHT,40)
    end function
    
    on pgs_changed
      if (pgs_get_key_val(INIT,0)=1)
        call button_init
        pgs_set_key_val(INIT,0,0)
      end if
    end on
    With this approach we can write all the on_init callback in the proxy-function like initialize and if got parser stack overflow exeption just split it up to the 2 or 3 functions called by the pgs.

    Only minor thing is - add_menu_item function, it should be solved inside the init callback. I'm thinking on it ))
     
  2. kb123

    kb123 Active Member

    199
    14
    Sep 4, 2012
    if you periodically enclose your declarations in the on init with:

    $x := 0
    if ($x = 0)

    declare ctrl 1
    declare ctrl 2
    declare ctrl 3

    end if

    it will clear your stack overflow issue
     
  3. OP
    OP
    Levitanus

    Levitanus Active Member

    How? :) I talk about UI assignments like set_control_par, which takes about 5-10 lines for each controller.
    Also some functions like setting keys color depends on ui values or hiding/showing controls depens on the same ui values.
    They are 80% of initialization code sometimes, and here i suggest to move them to the separate functions, connected with init callback by pgs)
     
  4. kb123

    kb123 Active Member

    199
    14
    Sep 4, 2012
    Did you try what I suggested? All you need to do is put if end if around a block of say 500 declaration lines and you will no longer get the error in Kontakt
     
    Levitanus likes this.
  5. magneto538

    magneto538 KSP Developer

    Another workaround that works perfectly for me, as someone suggested, is to enclose the declarations in init callback within an always-true if statement. To save lines, instead of using x = 0, I would recommend the following (SublimeText only)


    Code:
    on init
        if 1=1
            // Declarations
        end if
        if 1=1
            // Declarations
        end if
    end on
    

    Nice and clean. As far as I remember, the parser stack overflow error isn't related (only?) to the amount of lines of code. The cause seems to be the amount of top-level statements (aka statements at the same level), which (quote from an old post) is restricted to about 995.

    In order to save more lines, I am used to place all the UI/engine loading statements in persistence changed callback, which is called right after the init callback. By doing so, I am splitting the instructions into two separate processes, so I never go beyond the maximum amount of lines per callback (if there is any limitation to this, which I'm not sure of). This is also more correct and useful when dealing with custom presets engines and/or snapshots.

    Regarding the maximum amount of lines per callback, I am working on a very large project which, at the moment, has exactly 17582 lines in the init callback (compiled without empty lines). I'd be lost without the 1=1 workaround.

    We also have to be extremely careful when dealing with PGS callback, as it might be in use by other cross-slot operations (in case you are using multiple script slots). Your solution is interesting indeed, Levitanus, but honestly I think I'll stick with my way for now :)
     
    szcz and Levitanus like this.

Share This Page