From 3503cee1203ad526c894af1e7fdb334104da3c3d Mon Sep 17 00:00:00 2001 From: s-hadinger <49731213+s-hadinger@users.noreply.github.com> Date: Fri, 2 Jan 2026 20:24:57 +0100 Subject: [PATCH] Berry animation simplify sequence_manager (#24293) --- ...hap_8_30_template_shutter_bidir_flags.anim | 15 +- .../animation_docs/Animation_Tutorial.md | 54 +- .../src/core/sequence_manager.be | 375 +++-- .../src/solidify/solidified_animation.h | 1288 ++++++++--------- .../src/tests/sequence_manager_test.be | 219 ++- 5 files changed, 1043 insertions(+), 908 deletions(-) diff --git a/lib/libesp32/berry_animation/anim_tutorials/chap_8_30_template_shutter_bidir_flags.anim b/lib/libesp32/berry_animation/anim_tutorials/chap_8_30_template_shutter_bidir_flags.anim index 0593b5659..b4055be91 100644 --- a/lib/libesp32/berry_animation/anim_tutorials/chap_8_30_template_shutter_bidir_flags.anim +++ b/lib/libesp32/berry_animation/anim_tutorials/chap_8_30_template_shutter_bidir_flags.anim @@ -6,10 +6,11 @@ template animation shutter_bidir { param colors type palette param period default 2s param inout type bool default true # define to true to enable 'inout' part - param outin type bool default true # define to true to enable 'outin' part + param outin type bool default true # define to true to enable 'outin' part # since 'strip_length()' is a value provider, it must be assigned to a variable before being used set strip_len = strip_length() + set strip_len_2 = (strip_len + 1) / 2 # half length rounded # Define animated value for the size of the shutter, evolving linearly in time (sawtooth from 0% to 100%) set shutter_size = sawtooth(min_value = 0, max_value = strip_len, duration = period) @@ -21,22 +22,18 @@ template animation shutter_bidir { # Shutter moving in in-out animation shutter_inout_animation = beacon_animation( - color = col2 - back_color = col1 - pos = 0 + color = col2 # Use two rotating colors + back_color = col1 # Use two rotating colors + pos = strip_len_2 - (shutter_size + 1) / 2 beacon_size = shutter_size - slew_size = 0 - priority = 5 ) # shutter moving in out-in animation shutter_outin_animation = beacon_animation( color = col1 back_color = col2 - pos = 0 + pos = strip_len_2 - (strip_len - shutter_size + 1) / 2 beacon_size = strip_len - shutter_size - slew_size = 0 - priority = 5 ) # this is the overall sequence composed of two sub-sequences diff --git a/lib/libesp32/berry_animation/animation_docs/Animation_Tutorial.md b/lib/libesp32/berry_animation/animation_docs/Animation_Tutorial.md index 5336ff9e4..56618e87c 100644 --- a/lib/libesp32/berry_animation/animation_docs/Animation_Tutorial.md +++ b/lib/libesp32/berry_animation/animation_docs/Animation_Tutorial.md @@ -1186,62 +1186,65 @@ run main ### 8.3 Advanced Template with Conditional Flags -Template Shutter +Template Shutter -Templates support `bool` parameters that can be used with `if` statements inside sequences. This allows users to enable or disable parts of the animation at instantiation time. Here we create a bidirectional shutter that can optionally run in-out, out-in, or both directions. +Templates support `bool` parameters that can be used with `if` statements inside sequences. This allows users to enable or disable parts of the animation at instantiation time. Here we create a bidirectional shutter (based on chapter 6.4) that can optionally run in-out, out-in, or both directions. **Dynamic parameter changes:** You can also modify template parameters at runtime using Berry code. Note that DSL variable names get an underscore suffix in Berry to avoid collisions with reserved words (e.g., `main` becomes `main_`). For example: `main_.inout = false` disables the in-out animation while it's running. ```berry -# Template with conditional flags for bidirectional shutter +# Template to illustrate the parameters and flags +# Define a template to package the shutter in-out-in from 6.40 +# with flags to enable or disable in-out or out-in template animation shutter_bidir { param colors type palette param period default 2s - param inout type bool default true # Enable in-out animation - param outin type bool default true # Enable out-in animation + param inout type bool default true # define to true to enable 'inout' part + param outin type bool default true # define to true to enable 'outin' part + # since 'strip_length()' is a value provider, it must be assigned to a variable before being used set strip_len = strip_length() + set strip_len_2 = (strip_len + 1) / 2 # half length rounded + + # Define animated value for the size of the shutter, evolving linearly in time (sawtooth from 0% to 100%) set shutter_size = sawtooth(min_value = 0, max_value = strip_len, duration = period) - # Two rotating color providers + # Define two rotating palettes, shifted by one color color col1 = color_cycle(colors=colors, period=0) color col2 = color_cycle(colors=colors, period=0) - col2.next = 1 + col2.next = 1 # move 'col2' to the next color so it's shifte by one compared to 'col1' - # In-out shutter + # Shutter moving in in-out animation shutter_inout_animation = beacon_animation( - color = col2 - back_color = col1 - pos = 0 + color = col2 # Use two rotating colors + back_color = col1 # Use two rotating colors + pos = strip_len_2 - (shutter_size + 1) / 2 beacon_size = shutter_size - slew_size = 0 - priority = 5 ) - # Out-in shutter + # shutter moving in out-in animation shutter_outin_animation = beacon_animation( color = col1 back_color = col2 - pos = 0 + pos = strip_len_2 - (strip_len - shutter_size + 1) / 2 beacon_size = strip_len - shutter_size - slew_size = 0 - priority = 5 ) - # Sequence with conditional blocks + # this is the overall sequence composed of two sub-sequences + # the first in ascending mode, the second in descending sequence shutter_seq repeat forever { - if inout { # Only if inout is true - repeat col1.palette_size times { - restart shutter_size - play shutter_inout_animation for period - col1.next = 1 + if inout { # un only if 'ascending' is true + repeat col1.palette_size times { # run the shutter animation + restart shutter_size # resync all times for this animation, to avoid temporal drift + play shutter_inout_animation for period # run the animation + col1.next = 1 # then move to next color for both palettes col2.next = 1 } } - if outin { # Only if outin is true + if outin { # run only if 'descending' is true repeat col1.palette_size times { restart shutter_size play shutter_outin_animation for period @@ -1253,7 +1256,7 @@ template animation shutter_bidir { run shutter_seq } -# Define palette +# define a palette of rainbow colors including white with constant brightness palette rainbow_with_white = [ 0xFC0000 # Red 0xFF8000 # Orange @@ -1265,7 +1268,6 @@ palette rainbow_with_white = [ 0xCCCCCC # White ] -# Use the template animation main = shutter_bidir(colors = rainbow_with_white, period = 1.5s) run main ``` diff --git a/lib/libesp32/berry_animation/src/core/sequence_manager.be b/lib/libesp32/berry_animation/src/core/sequence_manager.be index b5818e7af..5effaef29 100644 --- a/lib/libesp32/berry_animation/src/core/sequence_manager.be +++ b/lib/libesp32/berry_animation/src/core/sequence_manager.be @@ -4,16 +4,29 @@ # # Extends ParameterizedObject to provide parameter management and playable interface, # allowing sequences to be treated uniformly with animations by the engine. +# +# Memory-optimized: Uses two parallel arrays instead of array of maps +# - step_durations: encodes type and duration in a single integer +# - step_refs: stores references (animation, closure, sequence_manager, or nil) +# +# Duration encoding: +# >= 0: play (ref=animation) or wait (ref=nil) +# -2: closure (ref=closure function) +# -3: subsequence (ref=sequence_manager) import "./core/param_encoder" as encode_constraints class SequenceManager : animation.parameterized_object + # static var DURATION_CLOSURE = -2 + # static var DURATION_SUBSEQUENCE = -3 + # Non-parameter instance variables var active_sequence # Currently running sequence var sequence_state # Current sequence execution state var step_index # Current step in the sequence var step_start_time # When current step started - var steps # List of sequence steps + var step_durations # List of duration/type values (int) + var step_refs # List of references (animation, closure, sequence_manager, or nil) # Repeat-specific properties var repeat_count # Number of times to repeat this sequence (-1 for forever, 0 for no repeat) @@ -29,7 +42,8 @@ class SequenceManager : animation.parameterized_object self.sequence_state = {} self.step_index = 0 self.step_start_time = 0 - self.steps = [] + self.step_durations = [] + self.step_refs = [] # Repeat logic self.repeat_count = repeat_count != nil ? repeat_count : 1 # Default: run once (can be function or number) @@ -37,51 +51,35 @@ class SequenceManager : animation.parameterized_object self.is_repeat_sequence = repeat_count != nil && repeat_count != 1 end - # Add a step to this sequence - def push_step(step) - self.steps.push(step) - return self - end - # Add a play step directly def push_play_step(animation_ref, duration) - self.steps.push({ - "type": "play", - "animation": animation_ref, - "duration": duration != nil ? duration : 0 - }) + self.step_durations.push(duration != nil ? duration : 0) + self.step_refs.push(animation_ref) return self end # Add a wait step directly def push_wait_step(duration) - self.steps.push({ - "type": "wait", - "duration": duration - }) + self.step_durations.push(duration) + self.step_refs.push(nil) return self end # Add a closure step directly (used for both assign and log steps) def push_closure_step(closure) - self.steps.push({ - "type": "closure", - "closure": closure - }) + self.step_durations.push(-2 #-self.DURATION_CLOSURE-#) + self.step_refs.push(closure) return self end # Add a repeat subsequence step directly def push_repeat_subsequence(sequence_manager) - self.steps.push({ - "type": "subsequence", - "sequence_manager": sequence_manager - }) + self.step_durations.push(-3 #-self.DURATION_SUBSEQUENCE-#) + self.step_refs.push(sequence_manager) return self end - + # Start this sequence - # FIXED: More conservative engine clearing to avoid black frames def start(time_ms) # Stop any current sequence if self.is_running @@ -113,23 +111,19 @@ class SequenceManager : animation.parameterized_object end # Start executing if we have steps - if size(self.steps) > 0 + var num_steps = size(self.step_durations) + if num_steps > 0 # Execute all consecutive closure steps at the beginning atomically - while self.step_index < size(self.steps) - var step = self.steps[self.step_index] - if step["type"] == "closure" - var closure_func = step["closure"] - if closure_func != nil - closure_func(self.engine) - end - self.step_index += 1 - else - break + while self.step_index < num_steps && self.step_durations[self.step_index] == -2 #-self.DURATION_CLOSURE-# + var closure_func = self.step_refs[self.step_index] + if closure_func != nil + closure_func(self.engine) end + self.step_index += 1 end # Now execute the next non-closure step (usually play) - if self.step_index < size(self.steps) + if self.step_index < num_steps self.execute_current_step(time_ms) end end @@ -148,14 +142,15 @@ class SequenceManager : animation.parameterized_object end # Stop any currently playing animations - if self.step_index < size(self.steps) - var current_step = self.steps[self.step_index] - if current_step["type"] == "play" - var anim = current_step["animation"] - self.engine.remove(anim) - elif current_step["type"] == "subsequence" - var sub_seq = current_step["sequence_manager"] - sub_seq.stop() + var num_steps = size(self.step_durations) + if self.step_index < num_steps + var dur = self.step_durations[self.step_index] + var ref = self.step_refs[self.step_index] + if dur == -3 #-self.DURATION_SUBSEQUENCE-# + ref.stop() + elif dur != -2 #-self.DURATION_CLOSURE-# && ref != nil + # play step (dur is >= 0 or function, ref is animation) + self.engine.remove(ref) end end @@ -167,215 +162,198 @@ class SequenceManager : animation.parameterized_object # Stop all sub-sequences in our steps def stop_all_subsequences() - for step : self.steps - if step["type"] == "subsequence" - var sub_seq = step["sequence_manager"] - sub_seq.stop() + var num_steps = size(self.step_durations) + var i = 0 + while i < num_steps + if self.step_durations[i] == -3 #-self.DURATION_SUBSEQUENCE-# + self.step_refs[i].stop() end + i += 1 end return self end - + # Update sequence state - called from fast_loop def update(current_time) - if !self.is_running || size(self.steps) == 0 + var num_steps = size(self.step_durations) + if !self.is_running || num_steps == 0 || self.step_index >= num_steps return end - # Safety check: ensure step_index is valid - if self.step_index >= size(self.steps) - return - end + var dur = self.step_durations[self.step_index] - var current_step = self.steps[self.step_index] - - # Handle different step types - if current_step["type"] == "subsequence" - # Handle sub-sequence (including repeat sequences) - var sub_seq = current_step["sequence_manager"] + # Only closure/subsequence have negative int markers, play/wait have >= 0 or function + if dur == -3 #-self.DURATION_SUBSEQUENCE-# + # Handle sub-sequence + var sub_seq = self.step_refs[self.step_index] sub_seq.update(current_time) if !sub_seq.is_running - # Sub-sequence finished, advance to next step self.advance_to_next_step(current_time) end - elif current_step["type"] == "closure" - # Closure steps are handled in batches by advance_to_next_step - # This should not happen in normal flow, but handle it just in case + elif dur == -2 #-self.DURATION_CLOSURE-# + # Closure steps are handled in batches self.execute_closure_steps_batch(current_time) else - # Handle regular steps with duration - if current_step.contains("duration") && current_step["duration"] != nil - # Resolve duration - it can be a number or a closure - var duration_value = current_step["duration"] - if type(duration_value) == "function" - # Duration is a closure - call it to get the actual value - duration_value = duration_value(self.engine) - end - - if duration_value > 0 - var elapsed = current_time - self.step_start_time - if elapsed >= duration_value - self.advance_to_next_step(current_time) - end - else - # Duration is 0 or nil - complete immediately + # Handle regular steps with duration (play or wait) + # dur is either int >= 0, function, or bool + var duration_value = dur + if type(dur) == "function" + duration_value = dur(self.engine) + end + duration_value = int(duration_value) # Force int, works for bool + + if duration_value > 0 + if current_time - self.step_start_time >= duration_value self.advance_to_next_step(current_time) end else - # Steps without duration complete immediately + # Duration is 0 - complete immediately self.advance_to_next_step(current_time) end end end # Execute the current step - def execute_current_step(current_time) - if self.step_index >= size(self.steps) - self.complete_iteration(current_time) + # skip_budget limits how many consecutive immediate skips to prevent infinite loops + def execute_current_step(current_time, skip_budget) + if skip_budget == nil + skip_budget = size(self.step_durations) + 1 # Default: allow skipping all steps once + end + + var num_steps = size(self.step_durations) + if self.step_index >= num_steps + self.complete_iteration(current_time, skip_budget) return end - var step = self.steps[self.step_index] + var dur = self.step_durations[self.step_index] + var ref = self.step_refs[self.step_index] - if step["type"] == "play" - var anim = step["animation"] - - # Check if animation is nil (safety check) - if anim == nil + if dur == -3 #-self.DURATION_SUBSEQUENCE-# + # Start sub-sequence + ref.start(current_time) + # If subsequence immediately completed (e.g., repeat_count resolved to 0), + # advance to next step immediately to avoid black frame (if we have budget) + if !ref.is_running && skip_budget > 0 + self.advance_to_next_step(current_time, skip_budget - 1) return end - - # Check if animation is already in the engine (avoid duplicate adds) + elif dur == -2 #-self.DURATION_CLOSURE-# + # Closure steps should be handled in batches + if ref != nil + ref(self.engine) + end + elif ref != nil + # Play step (dur >= 0 and ref is animation) + # Check if animation is already in the engine var animations = self.engine.get_animations() var already_added = false for existing_anim : animations - if existing_anim == anim + if existing_anim == ref already_added = true break end end if !already_added - self.engine.add(anim) + self.engine.add(ref) end # Always restart the animation to ensure proper timing - anim.start(current_time) - - elif step["type"] == "wait" - # Wait steps are handled by the update loop checking duration - # No animation needed for wait - - elif step["type"] == "stop" - var anim = step["animation"] - self.engine.remove(anim) - - elif step["type"] == "closure" - # Closure steps should be handled in batches by execute_closure_steps_batch - # This should not happen in normal flow, but handle it for safety - var closure_func = step["closure"] - if closure_func != nil - closure_func(self.engine) - end - - elif step["type"] == "subsequence" - # Start sub-sequence (including repeat sequences) - var sub_seq = step["sequence_manager"] - sub_seq.start(current_time) + ref.start(current_time) end + # else: wait step (dur >= 0 and ref is nil) - nothing to do self.step_start_time = current_time end - + # Advance to the next step in the sequence - # FIXED: Atomic transition to eliminate black frames - def advance_to_next_step(current_time) - # Get current step info BEFORE advancing - var current_step = self.steps[self.step_index] - var current_anim = nil + def advance_to_next_step(current_time, skip_budget) + var num_steps = size(self.step_durations) + + if skip_budget == nil + skip_budget = num_steps + 1 + end - # Store reference to current animation but DON'T remove it yet - if current_step["type"] == "play" && current_step.contains("duration") - current_anim = current_step["animation"] + # Get current animation ref BEFORE advancing (for atomic transition) + # If dur is not a special marker and ref is not nil, it's a play step + var dur = self.step_durations[self.step_index] + var ref = self.step_refs[self.step_index] + var current_anim = nil + if dur != -2 #-self.DURATION_CLOSURE-# && dur != -3 #-self.DURATION_SUBSEQUENCE-# && ref != nil + current_anim = ref end self.step_index += 1 - if self.step_index >= size(self.steps) - # Only remove animation when completing iteration + if self.step_index >= num_steps if current_anim != nil self.engine.remove(current_anim) end - self.complete_iteration(current_time) + self.complete_iteration(current_time, skip_budget) else - # Execute closures and start next animation BEFORE removing current one - self.execute_closure_steps_batch_atomic(current_time, current_anim) + self.execute_closure_steps_batch_atomic(current_time, current_anim, skip_budget) end end # Execute all consecutive closure steps in a batch to avoid black frames def execute_closure_steps_batch(current_time) + var num_steps = size(self.step_durations) + # Execute all consecutive closure steps - while self.step_index < size(self.steps) - var step = self.steps[self.step_index] - if step["type"] == "closure" - # Execute closure function - var closure_func = step["closure"] - if closure_func != nil - closure_func(self.engine) - end - self.step_index += 1 - else - break + while self.step_index < num_steps && self.step_durations[self.step_index] == -2 #-self.DURATION_CLOSURE-# + var closure_func = self.step_refs[self.step_index] + if closure_func != nil + closure_func(self.engine) end + self.step_index += 1 end # Now execute the next non-closure step - if self.step_index < size(self.steps) + if self.step_index < num_steps self.execute_current_step(current_time) else self.complete_iteration(current_time) end end - # ADDED: Atomic batch execution to eliminate black frames - def execute_closure_steps_batch_atomic(current_time, previous_anim) - # Execute all consecutive closure steps - while self.step_index < size(self.steps) - var step = self.steps[self.step_index] - if step["type"] == "closure" - var closure_func = step["closure"] - if closure_func != nil - closure_func(self.engine) - end - self.step_index += 1 - else - break - end + # Atomic batch execution to eliminate black frames + def execute_closure_steps_batch_atomic(current_time, previous_anim, skip_budget) + if skip_budget == nil + skip_budget = size(self.step_durations) + 1 end - # CRITICAL FIX: Handle the case where the next step is the SAME animation - # This prevents removing and re-adding the same animation, which causes black frames - var next_step = nil - var is_same_animation = false + var num_steps = size(self.step_durations) - if self.step_index < size(self.steps) - next_step = self.steps[self.step_index] - if next_step["type"] == "play" && previous_anim != nil - is_same_animation = (next_step["animation"] == previous_anim) + # Execute all consecutive closure steps + while self.step_index < num_steps && self.step_durations[self.step_index] == -2 #-self.DURATION_CLOSURE-# + var closure_func = self.step_refs[self.step_index] + if closure_func != nil + closure_func(self.engine) + end + self.step_index += 1 + end + + # Check if the next step is the SAME animation + var is_same_animation = false + if self.step_index < num_steps && previous_anim != nil + var next_dur = self.step_durations[self.step_index] + var next_ref = self.step_refs[self.step_index] + # If not a special marker and same animation ref + if next_dur != -2 #-self.DURATION_CLOSURE-# && next_dur != -3 #-self.DURATION_SUBSEQUENCE-# && next_ref == previous_anim + is_same_animation = true end end if is_same_animation # Same animation continuing - don't remove/re-add, but DO restart for timing sync self.step_start_time = current_time - # CRITICAL: Still need to restart the animation to sync with sequence timing previous_anim.start(current_time) else # Different animation or no next animation # Start the next animation BEFORE removing the previous one - if self.step_index < size(self.steps) - self.execute_current_step(current_time) + if self.step_index < num_steps + self.execute_current_step(current_time, skip_budget) end # NOW it's safe to remove the previous animation (no gap) @@ -385,14 +363,17 @@ class SequenceManager : animation.parameterized_object end # Handle completion - if self.step_index >= size(self.steps) - self.complete_iteration(current_time) + if self.step_index >= num_steps + self.complete_iteration(current_time, skip_budget) end end - + # Complete current iteration and check if we should repeat - # FIXED: Ensure atomic transitions during repeat iterations - def complete_iteration(current_time) + def complete_iteration(current_time, skip_budget) + if skip_budget == nil + skip_budget = size(self.step_durations) + 1 + end + self.current_iteration += 1 # Update iteration context in engine stack if this is a repeat sequence @@ -405,26 +386,29 @@ class SequenceManager : animation.parameterized_object # Check if we should continue repeating if resolved_repeat_count == -1 || self.current_iteration < resolved_repeat_count + # If we've exhausted skip budget, stop here and let next update() continue + # This prevents infinite loops when all steps are skipped + if skip_budget <= 0 + self.step_index = 0 + return + end + # Start next iteration - execute all initial closures atomically self.step_index = 0 + var num_steps = size(self.step_durations) # Execute all consecutive closure steps at the beginning atomically - while self.step_index < size(self.steps) - var step = self.steps[self.step_index] - if step["type"] == "closure" - var closure_func = step["closure"] - if closure_func != nil - closure_func(self.engine) - end - self.step_index += 1 - else - break + while self.step_index < num_steps && self.step_durations[self.step_index] == -2 #-self.DURATION_CLOSURE-# + var closure_func = self.step_refs[self.step_index] + if closure_func != nil + closure_func(self.engine) end + self.step_index += 1 end # Now execute the next non-closure step (usually play) - if self.step_index < size(self.steps) - self.execute_current_step(current_time) + if self.step_index < num_steps + self.execute_current_step(current_time, skip_budget - 1) end else # All iterations complete @@ -455,23 +439,6 @@ class SequenceManager : animation.parameterized_object def is_sequence_running() return self.is_running end - - # # Get current step info for debugging - # def get_current_step_info() - # if !self.is_running || self.step_index >= size(self.steps) - # return nil - # end - - # return { - # "step_index": self.step_index, - # "total_steps": size(self.steps), - # "current_step": self.steps[self.step_index], - # "elapsed_ms": self.engine.time_ms - self.step_start_time, - # "repeat_count": self.repeat_count, - # "current_iteration": self.current_iteration, - # "is_repeat_sequence": self.is_repeat_sequence - # } - # end end return {'sequence_manager': SequenceManager } diff --git a/lib/libesp32/berry_animation/src/solidify/solidified_animation.h b/lib/libesp32/berry_animation/src/solidify/solidified_animation.h index fac399479..a78f4369d 100644 --- a/lib/libesp32/berry_animation/src/solidify/solidified_animation.h +++ b/lib/libesp32/berry_animation/src/solidify/solidified_animation.h @@ -2841,50 +2841,42 @@ be_local_closure(pulsating_color_provider, /* name */ ); /*******************************************************************/ -// compact class 'SequenceManager' ktab size: 42, total: 155 (saved 904 bytes) -static const bvalue be_ktab_class_SequenceManager[42] = { - /* K0 */ be_nested_str_weak(steps), +// compact class 'SequenceManager' ktab size: 34, total: 122 (saved 704 bytes) +static const bvalue be_ktab_class_SequenceManager[34] = { + /* K0 */ be_nested_str_weak(step_durations), /* K1 */ be_nested_str_weak(push), - /* K2 */ be_nested_str_weak(type), - /* K3 */ be_nested_str_weak(wait), - /* K4 */ be_nested_str_weak(duration), - /* K5 */ be_nested_str_weak(repeat_count), - /* K6 */ be_nested_str_weak(function), - /* K7 */ be_nested_str_weak(engine), - /* K8 */ be_nested_str_weak(init), - /* K9 */ be_nested_str_weak(active_sequence), - /* K10 */ be_nested_str_weak(sequence_state), - /* K11 */ be_nested_str_weak(step_index), - /* K12 */ be_const_int(0), - /* K13 */ be_nested_str_weak(step_start_time), - /* K14 */ be_const_int(1), - /* K15 */ be_nested_str_weak(current_iteration), - /* K16 */ be_nested_str_weak(is_repeat_sequence), - /* K17 */ be_nested_str_weak(subsequence), - /* K18 */ be_nested_str_weak(sequence_manager), - /* K19 */ be_nested_str_weak(play), - /* K20 */ be_nested_str_weak(contains), - /* K21 */ be_nested_str_weak(animation), - /* K22 */ be_nested_str_weak(remove), - /* K23 */ be_nested_str_weak(complete_iteration), - /* K24 */ be_nested_str_weak(execute_closure_steps_batch_atomic), - /* K25 */ be_nested_str_weak(is_running), - /* K26 */ be_nested_str_weak(update), - /* K27 */ be_nested_str_weak(advance_to_next_step), - /* K28 */ be_nested_str_weak(closure), - /* K29 */ be_nested_str_weak(execute_closure_steps_batch), - /* K30 */ be_nested_str_weak(stop), - /* K31 */ be_nested_str_weak(stop_iteration), - /* K32 */ be_nested_str_weak(stop_all_subsequences), - /* K33 */ be_nested_str_weak(start_time), - /* K34 */ be_nested_str_weak(get_resolved_repeat_count), - /* K35 */ be_nested_str_weak(push_iteration_context), - /* K36 */ be_nested_str_weak(execute_current_step), - /* K37 */ be_nested_str_weak(update_current_iteration), - /* K38 */ be_nested_str_weak(pop_iteration_context), - /* K39 */ be_nested_str_weak(start), - /* K40 */ be_nested_str_weak(get_animations), - /* K41 */ be_nested_str_weak(add), + /* K2 */ be_nested_str_weak(step_refs), + /* K3 */ be_nested_str_weak(repeat_count), + /* K4 */ be_nested_str_weak(function), + /* K5 */ be_nested_str_weak(engine), + /* K6 */ be_nested_str_weak(init), + /* K7 */ be_nested_str_weak(active_sequence), + /* K8 */ be_nested_str_weak(sequence_state), + /* K9 */ be_nested_str_weak(step_index), + /* K10 */ be_const_int(0), + /* K11 */ be_nested_str_weak(step_start_time), + /* K12 */ be_const_int(1), + /* K13 */ be_nested_str_weak(current_iteration), + /* K14 */ be_nested_str_weak(is_repeat_sequence), + /* K15 */ be_nested_str_weak(update_current_iteration), + /* K16 */ be_nested_str_weak(get_resolved_repeat_count), + /* K17 */ be_nested_str_weak(execute_current_step), + /* K18 */ be_nested_str_weak(is_running), + /* K19 */ be_nested_str_weak(pop_iteration_context), + /* K20 */ be_nested_str_weak(update), + /* K21 */ be_nested_str_weak(advance_to_next_step), + /* K22 */ be_nested_str_weak(execute_closure_steps_batch), + /* K23 */ be_nested_str_weak(stop), + /* K24 */ be_nested_str_weak(stop_all_subsequences), + /* K25 */ be_nested_str_weak(start_time), + /* K26 */ be_nested_str_weak(push_iteration_context), + /* K27 */ be_nested_str_weak(remove), + /* K28 */ be_nested_str_weak(complete_iteration), + /* K29 */ be_nested_str_weak(execute_closure_steps_batch_atomic), + /* K30 */ be_nested_str_weak(start), + /* K31 */ be_nested_str_weak(get_animations), + /* K32 */ be_nested_str_weak(stop_iteration), + /* K33 */ be_nested_str_weak(add), }; @@ -2906,15 +2898,16 @@ be_local_closure(class_SequenceManager_push_wait_step, /* name */ &be_ktab_class_SequenceManager, /* shared constants */ be_str_weak(push_wait_step), &be_const_str_solidified, - ( &(const binstruction[ 8]) { /* code */ + ( &(const binstruction[ 9]) { /* code */ 0x88080100, // 0000 GETMBR R2 R0 K0 0x8C080501, // 0001 GETMET R2 R2 K1 - 0x60100013, // 0002 GETGBL R4 G19 - 0x7C100000, // 0003 CALL R4 0 - 0x98120503, // 0004 SETIDX R4 K2 K3 - 0x98120801, // 0005 SETIDX R4 K4 R1 - 0x7C080400, // 0006 CALL R2 2 - 0x80040000, // 0007 RET 1 R0 + 0x5C100200, // 0002 MOVE R4 R1 + 0x7C080400, // 0003 CALL R2 2 + 0x88080102, // 0004 GETMBR R2 R0 K2 + 0x8C080501, // 0005 GETMET R2 R2 K1 + 0x4C100000, // 0006 LDNIL R4 + 0x7C080400, // 0007 CALL R2 2 + 0x80040000, // 0008 RET 1 R0 }) ) ); @@ -2940,16 +2933,16 @@ be_local_closure(class_SequenceManager_get_resolved_repeat_count, /* name */ ( &(const binstruction[16]) { /* code */ 0x4C040000, // 0000 LDNIL R1 0x60080004, // 0001 GETGBL R2 G4 - 0x880C0105, // 0002 GETMBR R3 R0 K5 + 0x880C0103, // 0002 GETMBR R3 R0 K3 0x7C080200, // 0003 CALL R2 1 - 0x1C080506, // 0004 EQ R2 R2 K6 + 0x1C080504, // 0004 EQ R2 R2 K4 0x780A0004, // 0005 JMPF R2 #000B - 0x8C080105, // 0006 GETMET R2 R0 K5 - 0x88100107, // 0007 GETMBR R4 R0 K7 + 0x8C080103, // 0006 GETMET R2 R0 K3 + 0x88100105, // 0007 GETMBR R4 R0 K5 0x7C080400, // 0008 CALL R2 2 0x5C040400, // 0009 MOVE R1 R2 0x70020000, // 000A JMP #000C - 0x88040105, // 000B GETMBR R1 R0 K5 + 0x88040103, // 000B GETMBR R1 R0 K3 0x60080009, // 000C GETGBL R2 G9 0x5C0C0200, // 000D MOVE R3 R1 0x7C080200, // 000E CALL R2 1 @@ -2976,40 +2969,43 @@ be_local_closure(class_SequenceManager_init, /* name */ &be_ktab_class_SequenceManager, /* shared constants */ be_str_weak(init), &be_const_str_solidified, - ( &(const binstruction[33]) { /* code */ + ( &(const binstruction[36]) { /* code */ 0x600C0003, // 0000 GETGBL R3 G3 0x5C100000, // 0001 MOVE R4 R0 0x7C0C0200, // 0002 CALL R3 1 - 0x8C0C0708, // 0003 GETMET R3 R3 K8 + 0x8C0C0706, // 0003 GETMET R3 R3 K6 0x5C140200, // 0004 MOVE R5 R1 0x7C0C0400, // 0005 CALL R3 2 0x4C0C0000, // 0006 LDNIL R3 - 0x90021203, // 0007 SETMBR R0 K9 R3 + 0x90020E03, // 0007 SETMBR R0 K7 R3 0x600C0013, // 0008 GETGBL R3 G19 0x7C0C0000, // 0009 CALL R3 0 - 0x90021403, // 000A SETMBR R0 K10 R3 - 0x9002170C, // 000B SETMBR R0 K11 K12 - 0x90021B0C, // 000C SETMBR R0 K13 K12 + 0x90021003, // 000A SETMBR R0 K8 R3 + 0x9002130A, // 000B SETMBR R0 K9 K10 + 0x9002170A, // 000C SETMBR R0 K11 K10 0x600C0012, // 000D GETGBL R3 G18 0x7C0C0000, // 000E CALL R3 0 0x90020003, // 000F SETMBR R0 K0 R3 - 0x4C0C0000, // 0010 LDNIL R3 - 0x200C0403, // 0011 NE R3 R2 R3 - 0x780E0001, // 0012 JMPF R3 #0015 - 0x5C0C0400, // 0013 MOVE R3 R2 - 0x70020000, // 0014 JMP #0016 - 0x580C000E, // 0015 LDCONST R3 K14 - 0x90020A03, // 0016 SETMBR R0 K5 R3 - 0x90021F0C, // 0017 SETMBR R0 K15 K12 - 0x4C0C0000, // 0018 LDNIL R3 - 0x200C0403, // 0019 NE R3 R2 R3 - 0x780E0001, // 001A JMPF R3 #001D - 0x200C050E, // 001B NE R3 R2 K14 - 0x740E0000, // 001C JMPT R3 #001E - 0x500C0001, // 001D LDBOOL R3 0 1 - 0x500C0200, // 001E LDBOOL R3 1 0 - 0x90022003, // 001F SETMBR R0 K16 R3 - 0x80000000, // 0020 RET 0 + 0x600C0012, // 0010 GETGBL R3 G18 + 0x7C0C0000, // 0011 CALL R3 0 + 0x90020403, // 0012 SETMBR R0 K2 R3 + 0x4C0C0000, // 0013 LDNIL R3 + 0x200C0403, // 0014 NE R3 R2 R3 + 0x780E0001, // 0015 JMPF R3 #0018 + 0x5C0C0400, // 0016 MOVE R3 R2 + 0x70020000, // 0017 JMP #0019 + 0x580C000C, // 0018 LDCONST R3 K12 + 0x90020603, // 0019 SETMBR R0 K3 R3 + 0x90021B0A, // 001A SETMBR R0 K13 K10 + 0x4C0C0000, // 001B LDNIL R3 + 0x200C0403, // 001C NE R3 R2 R3 + 0x780E0001, // 001D JMPF R3 #0020 + 0x200C050C, // 001E NE R3 R2 K12 + 0x740E0000, // 001F JMPT R3 #0021 + 0x500C0001, // 0020 LDBOOL R3 0 1 + 0x500C0200, // 0021 LDBOOL R3 1 0 + 0x90021C03, // 0022 SETMBR R0 K14 R3 + 0x80000000, // 0023 RET 0 }) ) ); @@ -3032,15 +3028,16 @@ be_local_closure(class_SequenceManager_push_repeat_subsequence, /* name */ &be_ktab_class_SequenceManager, /* shared constants */ be_str_weak(push_repeat_subsequence), &be_const_str_solidified, - ( &(const binstruction[ 8]) { /* code */ + ( &(const binstruction[ 9]) { /* code */ 0x88080100, // 0000 GETMBR R2 R0 K0 0x8C080501, // 0001 GETMET R2 R2 K1 - 0x60100013, // 0002 GETGBL R4 G19 - 0x7C100000, // 0003 CALL R4 0 - 0x98120511, // 0004 SETIDX R4 K2 K17 - 0x98122401, // 0005 SETIDX R4 K18 R1 - 0x7C080400, // 0006 CALL R2 2 - 0x80040000, // 0007 RET 1 R0 + 0x5411FFFC, // 0002 LDINT R4 -3 + 0x7C080400, // 0003 CALL R2 2 + 0x88080102, // 0004 GETMBR R2 R0 K2 + 0x8C080501, // 0005 GETMET R2 R2 K1 + 0x5C100200, // 0006 MOVE R4 R1 + 0x7C080400, // 0007 CALL R2 2 + 0x80040000, // 0008 RET 1 R0 }) ) ); @@ -3048,12 +3045,12 @@ be_local_closure(class_SequenceManager_push_repeat_subsequence, /* name */ /******************************************************************** -** Solidified function: advance_to_next_step +** Solidified function: complete_iteration ********************************************************************/ -be_local_closure(class_SequenceManager_advance_to_next_step, /* name */ +be_local_closure(class_SequenceManager_complete_iteration, /* name */ be_nested_proto( - 8, /* nstack */ - 2, /* argc */ + 9, /* nstack */ + 3, /* argc */ 10, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ @@ -3061,46 +3058,80 @@ be_local_closure(class_SequenceManager_advance_to_next_step, /* name */ NULL, /* no sub protos */ 1, /* has constants */ &be_ktab_class_SequenceManager, /* shared constants */ - be_str_weak(advance_to_next_step), + be_str_weak(complete_iteration), &be_const_str_solidified, - ( &(const binstruction[37]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x880C010B, // 0001 GETMBR R3 R0 K11 - 0x94080403, // 0002 GETIDX R2 R2 R3 - 0x4C0C0000, // 0003 LDNIL R3 - 0x94100502, // 0004 GETIDX R4 R2 K2 - 0x1C100913, // 0005 EQ R4 R4 K19 - 0x78120004, // 0006 JMPF R4 #000C - 0x8C100514, // 0007 GETMET R4 R2 K20 - 0x58180004, // 0008 LDCONST R6 K4 - 0x7C100400, // 0009 CALL R4 2 - 0x78120000, // 000A JMPF R4 #000C - 0x940C0515, // 000B GETIDX R3 R2 K21 - 0x8810010B, // 000C GETMBR R4 R0 K11 - 0x0010090E, // 000D ADD R4 R4 K14 - 0x90021604, // 000E SETMBR R0 K11 R4 - 0x8810010B, // 000F GETMBR R4 R0 K11 - 0x6014000C, // 0010 GETGBL R5 G12 - 0x88180100, // 0011 GETMBR R6 R0 K0 - 0x7C140200, // 0012 CALL R5 1 - 0x28100805, // 0013 GE R4 R4 R5 - 0x7812000A, // 0014 JMPF R4 #0020 - 0x4C100000, // 0015 LDNIL R4 - 0x20100604, // 0016 NE R4 R3 R4 - 0x78120003, // 0017 JMPF R4 #001C - 0x88100107, // 0018 GETMBR R4 R0 K7 - 0x8C100916, // 0019 GETMET R4 R4 K22 - 0x5C180600, // 001A MOVE R6 R3 - 0x7C100400, // 001B CALL R4 2 - 0x8C100117, // 001C GETMET R4 R0 K23 - 0x5C180200, // 001D MOVE R6 R1 - 0x7C100400, // 001E CALL R4 2 - 0x70020003, // 001F JMP #0024 - 0x8C100118, // 0020 GETMET R4 R0 K24 - 0x5C180200, // 0021 MOVE R6 R1 - 0x5C1C0600, // 0022 MOVE R7 R3 - 0x7C100600, // 0023 CALL R4 3 - 0x80000000, // 0024 RET 0 + ( &(const binstruction[71]) { /* code */ + 0x4C0C0000, // 0000 LDNIL R3 + 0x1C0C0403, // 0001 EQ R3 R2 R3 + 0x780E0004, // 0002 JMPF R3 #0008 + 0x600C000C, // 0003 GETGBL R3 G12 + 0x88100100, // 0004 GETMBR R4 R0 K0 + 0x7C0C0200, // 0005 CALL R3 1 + 0x000C070C, // 0006 ADD R3 R3 K12 + 0x5C080600, // 0007 MOVE R2 R3 + 0x880C010D, // 0008 GETMBR R3 R0 K13 + 0x000C070C, // 0009 ADD R3 R3 K12 + 0x90021A03, // 000A SETMBR R0 K13 R3 + 0x880C010E, // 000B GETMBR R3 R0 K14 + 0x780E0003, // 000C JMPF R3 #0011 + 0x880C0105, // 000D GETMBR R3 R0 K5 + 0x8C0C070F, // 000E GETMET R3 R3 K15 + 0x8814010D, // 000F GETMBR R5 R0 K13 + 0x7C0C0400, // 0010 CALL R3 2 + 0x8C0C0110, // 0011 GETMET R3 R0 K16 + 0x7C0C0200, // 0012 CALL R3 1 + 0x5411FFFE, // 0013 LDINT R4 -1 + 0x1C100604, // 0014 EQ R4 R3 R4 + 0x74120002, // 0015 JMPT R4 #0019 + 0x8810010D, // 0016 GETMBR R4 R0 K13 + 0x14100803, // 0017 LT R4 R4 R3 + 0x78120025, // 0018 JMPF R4 #003F + 0x1810050A, // 0019 LE R4 R2 K10 + 0x78120001, // 001A JMPF R4 #001D + 0x9002130A, // 001B SETMBR R0 K9 K10 + 0x80000800, // 001C RET 0 + 0x9002130A, // 001D SETMBR R0 K9 K10 + 0x6010000C, // 001E GETGBL R4 G12 + 0x88140100, // 001F GETMBR R5 R0 K0 + 0x7C100200, // 0020 CALL R4 1 + 0x88140109, // 0021 GETMBR R5 R0 K9 + 0x14140A04, // 0022 LT R5 R5 R4 + 0x78160012, // 0023 JMPF R5 #0037 + 0x88140100, // 0024 GETMBR R5 R0 K0 + 0x88180109, // 0025 GETMBR R6 R0 K9 + 0x94140A06, // 0026 GETIDX R5 R5 R6 + 0x5419FFFD, // 0027 LDINT R6 -2 + 0x1C140A06, // 0028 EQ R5 R5 R6 + 0x7816000C, // 0029 JMPF R5 #0037 + 0x88140102, // 002A GETMBR R5 R0 K2 + 0x88180109, // 002B GETMBR R6 R0 K9 + 0x94140A06, // 002C GETIDX R5 R5 R6 + 0x4C180000, // 002D LDNIL R6 + 0x20180A06, // 002E NE R6 R5 R6 + 0x781A0002, // 002F JMPF R6 #0033 + 0x5C180A00, // 0030 MOVE R6 R5 + 0x881C0105, // 0031 GETMBR R7 R0 K5 + 0x7C180200, // 0032 CALL R6 1 + 0x88180109, // 0033 GETMBR R6 R0 K9 + 0x00180D0C, // 0034 ADD R6 R6 K12 + 0x90021206, // 0035 SETMBR R0 K9 R6 + 0x7001FFE9, // 0036 JMP #0021 + 0x88140109, // 0037 GETMBR R5 R0 K9 + 0x14140A04, // 0038 LT R5 R5 R4 + 0x78160003, // 0039 JMPF R5 #003E + 0x8C140111, // 003A GETMET R5 R0 K17 + 0x5C1C0200, // 003B MOVE R7 R1 + 0x0420050C, // 003C SUB R8 R2 K12 + 0x7C140600, // 003D CALL R5 3 + 0x70020006, // 003E JMP #0046 + 0x50100000, // 003F LDBOOL R4 0 0 + 0x90022404, // 0040 SETMBR R0 K18 R4 + 0x8810010E, // 0041 GETMBR R4 R0 K14 + 0x78120002, // 0042 JMPF R4 #0046 + 0x88100105, // 0043 GETMBR R4 R0 K5 + 0x8C100913, // 0044 GETMET R4 R4 K19 + 0x7C100200, // 0045 CALL R4 1 + 0x80000000, // 0046 RET 0 }) ) ); @@ -3123,81 +3154,71 @@ be_local_closure(class_SequenceManager_update, /* name */ &be_ktab_class_SequenceManager, /* shared constants */ be_str_weak(update), &be_const_str_solidified, - ( &(const binstruction[74]) { /* code */ - 0x88080119, // 0000 GETMBR R2 R0 K25 - 0x780A0004, // 0001 JMPF R2 #0007 - 0x6008000C, // 0002 GETGBL R2 G12 - 0x880C0100, // 0003 GETMBR R3 R0 K0 - 0x7C080200, // 0004 CALL R2 1 - 0x1C08050C, // 0005 EQ R2 R2 K12 - 0x780A0000, // 0006 JMPF R2 #0008 - 0x80000400, // 0007 RET 0 - 0x8808010B, // 0008 GETMBR R2 R0 K11 - 0x600C000C, // 0009 GETGBL R3 G12 - 0x88100100, // 000A GETMBR R4 R0 K0 - 0x7C0C0200, // 000B CALL R3 1 - 0x28080403, // 000C GE R2 R2 R3 - 0x780A0000, // 000D JMPF R2 #000F - 0x80000400, // 000E RET 0 - 0x88080100, // 000F GETMBR R2 R0 K0 - 0x880C010B, // 0010 GETMBR R3 R0 K11 - 0x94080403, // 0011 GETIDX R2 R2 R3 - 0x940C0502, // 0012 GETIDX R3 R2 K2 - 0x1C0C0711, // 0013 EQ R3 R3 K17 - 0x780E0009, // 0014 JMPF R3 #001F - 0x940C0512, // 0015 GETIDX R3 R2 K18 - 0x8C10071A, // 0016 GETMET R4 R3 K26 - 0x5C180200, // 0017 MOVE R6 R1 - 0x7C100400, // 0018 CALL R4 2 - 0x88100719, // 0019 GETMBR R4 R3 K25 - 0x74120002, // 001A JMPT R4 #001E - 0x8C10011B, // 001B GETMET R4 R0 K27 - 0x5C180200, // 001C MOVE R6 R1 - 0x7C100400, // 001D CALL R4 2 - 0x70020029, // 001E JMP #0049 - 0x940C0502, // 001F GETIDX R3 R2 K2 - 0x1C0C071C, // 0020 EQ R3 R3 K28 - 0x780E0003, // 0021 JMPF R3 #0026 - 0x8C0C011D, // 0022 GETMET R3 R0 K29 - 0x5C140200, // 0023 MOVE R5 R1 - 0x7C0C0400, // 0024 CALL R3 2 - 0x70020022, // 0025 JMP #0049 - 0x8C0C0514, // 0026 GETMET R3 R2 K20 - 0x58140004, // 0027 LDCONST R5 K4 - 0x7C0C0400, // 0028 CALL R3 2 - 0x780E001B, // 0029 JMPF R3 #0046 - 0x940C0504, // 002A GETIDX R3 R2 K4 - 0x4C100000, // 002B LDNIL R4 - 0x200C0604, // 002C NE R3 R3 R4 - 0x780E0017, // 002D JMPF R3 #0046 - 0x940C0504, // 002E GETIDX R3 R2 K4 - 0x60100004, // 002F GETGBL R4 G4 - 0x5C140600, // 0030 MOVE R5 R3 - 0x7C100200, // 0031 CALL R4 1 - 0x1C100906, // 0032 EQ R4 R4 K6 - 0x78120003, // 0033 JMPF R4 #0038 - 0x5C100600, // 0034 MOVE R4 R3 - 0x88140107, // 0035 GETMBR R5 R0 K7 - 0x7C100200, // 0036 CALL R4 1 - 0x5C0C0800, // 0037 MOVE R3 R4 - 0x2410070C, // 0038 GT R4 R3 K12 - 0x78120007, // 0039 JMPF R4 #0042 - 0x8810010D, // 003A GETMBR R4 R0 K13 - 0x04100204, // 003B SUB R4 R1 R4 - 0x28140803, // 003C GE R5 R4 R3 - 0x78160002, // 003D JMPF R5 #0041 - 0x8C14011B, // 003E GETMET R5 R0 K27 - 0x5C1C0200, // 003F MOVE R7 R1 - 0x7C140400, // 0040 CALL R5 2 - 0x70020002, // 0041 JMP #0045 - 0x8C10011B, // 0042 GETMET R4 R0 K27 - 0x5C180200, // 0043 MOVE R6 R1 - 0x7C100400, // 0044 CALL R4 2 - 0x70020002, // 0045 JMP #0049 - 0x8C0C011B, // 0046 GETMET R3 R0 K27 - 0x5C140200, // 0047 MOVE R5 R1 - 0x7C0C0400, // 0048 CALL R3 2 - 0x80000000, // 0049 RET 0 + ( &(const binstruction[64]) { /* code */ + 0x6008000C, // 0000 GETGBL R2 G12 + 0x880C0100, // 0001 GETMBR R3 R0 K0 + 0x7C080200, // 0002 CALL R2 1 + 0x880C0112, // 0003 GETMBR R3 R0 K18 + 0x780E0004, // 0004 JMPF R3 #000A + 0x1C0C050A, // 0005 EQ R3 R2 K10 + 0x740E0002, // 0006 JMPT R3 #000A + 0x880C0109, // 0007 GETMBR R3 R0 K9 + 0x280C0602, // 0008 GE R3 R3 R2 + 0x780E0000, // 0009 JMPF R3 #000B + 0x80000600, // 000A RET 0 + 0x880C0100, // 000B GETMBR R3 R0 K0 + 0x88100109, // 000C GETMBR R4 R0 K9 + 0x940C0604, // 000D GETIDX R3 R3 R4 + 0x5411FFFC, // 000E LDINT R4 -3 + 0x1C100604, // 000F EQ R4 R3 R4 + 0x7812000B, // 0010 JMPF R4 #001D + 0x88100102, // 0011 GETMBR R4 R0 K2 + 0x88140109, // 0012 GETMBR R5 R0 K9 + 0x94100805, // 0013 GETIDX R4 R4 R5 + 0x8C140914, // 0014 GETMET R5 R4 K20 + 0x5C1C0200, // 0015 MOVE R7 R1 + 0x7C140400, // 0016 CALL R5 2 + 0x88140912, // 0017 GETMBR R5 R4 K18 + 0x74160002, // 0018 JMPT R5 #001C + 0x8C140115, // 0019 GETMET R5 R0 K21 + 0x5C1C0200, // 001A MOVE R7 R1 + 0x7C140400, // 001B CALL R5 2 + 0x70020021, // 001C JMP #003F + 0x5411FFFD, // 001D LDINT R4 -2 + 0x1C100604, // 001E EQ R4 R3 R4 + 0x78120003, // 001F JMPF R4 #0024 + 0x8C100116, // 0020 GETMET R4 R0 K22 + 0x5C180200, // 0021 MOVE R6 R1 + 0x7C100400, // 0022 CALL R4 2 + 0x7002001A, // 0023 JMP #003F + 0x5C100600, // 0024 MOVE R4 R3 + 0x60140004, // 0025 GETGBL R5 G4 + 0x5C180600, // 0026 MOVE R6 R3 + 0x7C140200, // 0027 CALL R5 1 + 0x1C140B04, // 0028 EQ R5 R5 K4 + 0x78160003, // 0029 JMPF R5 #002E + 0x5C140600, // 002A MOVE R5 R3 + 0x88180105, // 002B GETMBR R6 R0 K5 + 0x7C140200, // 002C CALL R5 1 + 0x5C100A00, // 002D MOVE R4 R5 + 0x60140009, // 002E GETGBL R5 G9 + 0x5C180800, // 002F MOVE R6 R4 + 0x7C140200, // 0030 CALL R5 1 + 0x5C100A00, // 0031 MOVE R4 R5 + 0x2414090A, // 0032 GT R5 R4 K10 + 0x78160007, // 0033 JMPF R5 #003C + 0x8814010B, // 0034 GETMBR R5 R0 K11 + 0x04140205, // 0035 SUB R5 R1 R5 + 0x28140A04, // 0036 GE R5 R5 R4 + 0x78160002, // 0037 JMPF R5 #003B + 0x8C140115, // 0038 GETMET R5 R0 K21 + 0x5C1C0200, // 0039 MOVE R7 R1 + 0x7C140400, // 003A CALL R5 2 + 0x70020002, // 003B JMP #003F + 0x8C140115, // 003C GETMET R5 R0 K21 + 0x5C1C0200, // 003D MOVE R7 R1 + 0x7C140400, // 003E CALL R5 2 + 0x80000000, // 003F RET 0 }) ) ); @@ -3209,7 +3230,7 @@ be_local_closure(class_SequenceManager_update, /* name */ ********************************************************************/ be_local_closure(class_SequenceManager_stop_all_subsequences, /* name */ be_nested_proto( - 6, /* nstack */ + 5, /* nstack */ 1, /* argc */ 10, /* varg */ 0, /* has upvals */ @@ -3220,24 +3241,25 @@ be_local_closure(class_SequenceManager_stop_all_subsequences, /* name */ &be_ktab_class_SequenceManager, /* shared constants */ be_str_weak(stop_all_subsequences), &be_const_str_solidified, - ( &(const binstruction[17]) { /* code */ - 0x60040010, // 0000 GETGBL R1 G16 + ( &(const binstruction[18]) { /* code */ + 0x6004000C, // 0000 GETGBL R1 G12 0x88080100, // 0001 GETMBR R2 R0 K0 0x7C040200, // 0002 CALL R1 1 - 0xA8020008, // 0003 EXBLK 0 #000D - 0x5C080200, // 0004 MOVE R2 R1 - 0x7C080000, // 0005 CALL R2 0 - 0x940C0502, // 0006 GETIDX R3 R2 K2 - 0x1C0C0711, // 0007 EQ R3 R3 K17 - 0x780E0002, // 0008 JMPF R3 #000C - 0x940C0512, // 0009 GETIDX R3 R2 K18 - 0x8C10071E, // 000A GETMET R4 R3 K30 - 0x7C100200, // 000B CALL R4 1 - 0x7001FFF6, // 000C JMP #0004 - 0x5804001F, // 000D LDCONST R1 K31 - 0xAC040200, // 000E CATCH R1 1 0 - 0xB0080000, // 000F RAISE 2 R0 R0 - 0x80040000, // 0010 RET 1 R0 + 0x5808000A, // 0003 LDCONST R2 K10 + 0x140C0401, // 0004 LT R3 R2 R1 + 0x780E000A, // 0005 JMPF R3 #0011 + 0x880C0100, // 0006 GETMBR R3 R0 K0 + 0x940C0602, // 0007 GETIDX R3 R3 R2 + 0x5411FFFC, // 0008 LDINT R4 -3 + 0x1C0C0604, // 0009 EQ R3 R3 R4 + 0x780E0003, // 000A JMPF R3 #000F + 0x880C0102, // 000B GETMBR R3 R0 K2 + 0x940C0602, // 000C GETIDX R3 R3 R2 + 0x8C0C0717, // 000D GETMET R3 R3 K23 + 0x7C0C0200, // 000E CALL R3 1 + 0x0008050C, // 000F ADD R2 R2 K12 + 0x7001FFF2, // 0010 JMP #0004 + 0x80040000, // 0011 RET 1 R0 }) ) ); @@ -3260,72 +3282,66 @@ be_local_closure(class_SequenceManager_start, /* name */ &be_ktab_class_SequenceManager, /* shared constants */ be_str_weak(start), &be_const_str_solidified, - ( &(const binstruction[65]) { /* code */ - 0x88080119, // 0000 GETMBR R2 R0 K25 + ( &(const binstruction[59]) { /* code */ + 0x88080112, // 0000 GETMBR R2 R0 K18 0x780A0003, // 0001 JMPF R2 #0006 0x50080000, // 0002 LDBOOL R2 0 0 - 0x90023202, // 0003 SETMBR R0 K25 R2 - 0x8C080120, // 0004 GETMET R2 R0 K32 + 0x90022402, // 0003 SETMBR R0 K18 R2 + 0x8C080118, // 0004 GETMET R2 R0 K24 0x7C080200, // 0005 CALL R2 1 - 0x9002170C, // 0006 SETMBR R0 K11 K12 - 0x90021A01, // 0007 SETMBR R0 K13 R1 - 0x90021F0C, // 0008 SETMBR R0 K15 K12 + 0x9002130A, // 0006 SETMBR R0 K9 K10 + 0x90021601, // 0007 SETMBR R0 K11 R1 + 0x90021B0A, // 0008 SETMBR R0 K13 K10 0x50080200, // 0009 LDBOOL R2 1 0 - 0x90023202, // 000A SETMBR R0 K25 R2 - 0x90024201, // 000B SETMBR R0 K33 R1 - 0x8C080122, // 000C GETMET R2 R0 K34 + 0x90022402, // 000A SETMBR R0 K18 R2 + 0x90023201, // 000B SETMBR R0 K25 R1 + 0x8C080110, // 000C GETMET R2 R0 K16 0x7C080200, // 000D CALL R2 1 - 0x1C0C050C, // 000E EQ R3 R2 K12 + 0x1C0C050A, // 000E EQ R3 R2 K10 0x780E0002, // 000F JMPF R3 #0013 0x500C0000, // 0010 LDBOOL R3 0 0 - 0x90023203, // 0011 SETMBR R0 K25 R3 + 0x90022403, // 0011 SETMBR R0 K18 R3 0x80040000, // 0012 RET 1 R0 - 0x880C0110, // 0013 GETMBR R3 R0 K16 + 0x880C010E, // 0013 GETMBR R3 R0 K14 0x780E0003, // 0014 JMPF R3 #0019 - 0x880C0107, // 0015 GETMBR R3 R0 K7 - 0x8C0C0723, // 0016 GETMET R3 R3 K35 - 0x8814010F, // 0017 GETMBR R5 R0 K15 + 0x880C0105, // 0015 GETMBR R3 R0 K5 + 0x8C0C071A, // 0016 GETMET R3 R3 K26 + 0x8814010D, // 0017 GETMBR R5 R0 K13 0x7C0C0400, // 0018 CALL R3 2 0x600C000C, // 0019 GETGBL R3 G12 0x88100100, // 001A GETMBR R4 R0 K0 0x7C0C0200, // 001B CALL R3 1 - 0x240C070C, // 001C GT R3 R3 K12 - 0x780E0021, // 001D JMPF R3 #0040 - 0x880C010B, // 001E GETMBR R3 R0 K11 - 0x6010000C, // 001F GETGBL R4 G12 - 0x88140100, // 0020 GETMBR R5 R0 K0 - 0x7C100200, // 0021 CALL R4 1 - 0x140C0604, // 0022 LT R3 R3 R4 - 0x780E0012, // 0023 JMPF R3 #0037 - 0x880C0100, // 0024 GETMBR R3 R0 K0 - 0x8810010B, // 0025 GETMBR R4 R0 K11 - 0x940C0604, // 0026 GETIDX R3 R3 R4 - 0x94100702, // 0027 GETIDX R4 R3 K2 - 0x1C10091C, // 0028 EQ R4 R4 K28 - 0x7812000A, // 0029 JMPF R4 #0035 - 0x9410071C, // 002A GETIDX R4 R3 K28 - 0x4C140000, // 002B LDNIL R5 - 0x20140805, // 002C NE R5 R4 R5 - 0x78160002, // 002D JMPF R5 #0031 - 0x5C140800, // 002E MOVE R5 R4 - 0x88180107, // 002F GETMBR R6 R0 K7 - 0x7C140200, // 0030 CALL R5 1 - 0x8814010B, // 0031 GETMBR R5 R0 K11 - 0x00140B0E, // 0032 ADD R5 R5 K14 - 0x90021605, // 0033 SETMBR R0 K11 R5 - 0x70020000, // 0034 JMP #0036 - 0x70020000, // 0035 JMP #0037 - 0x7001FFE6, // 0036 JMP #001E - 0x880C010B, // 0037 GETMBR R3 R0 K11 - 0x6010000C, // 0038 GETGBL R4 G12 - 0x88140100, // 0039 GETMBR R5 R0 K0 - 0x7C100200, // 003A CALL R4 1 - 0x140C0604, // 003B LT R3 R3 R4 - 0x780E0002, // 003C JMPF R3 #0040 - 0x8C0C0124, // 003D GETMET R3 R0 K36 - 0x5C140200, // 003E MOVE R5 R1 - 0x7C0C0400, // 003F CALL R3 2 - 0x80040000, // 0040 RET 1 R0 + 0x2410070A, // 001C GT R4 R3 K10 + 0x7812001B, // 001D JMPF R4 #003A + 0x88100109, // 001E GETMBR R4 R0 K9 + 0x14100803, // 001F LT R4 R4 R3 + 0x78120012, // 0020 JMPF R4 #0034 + 0x88100100, // 0021 GETMBR R4 R0 K0 + 0x88140109, // 0022 GETMBR R5 R0 K9 + 0x94100805, // 0023 GETIDX R4 R4 R5 + 0x5415FFFD, // 0024 LDINT R5 -2 + 0x1C100805, // 0025 EQ R4 R4 R5 + 0x7812000C, // 0026 JMPF R4 #0034 + 0x88100102, // 0027 GETMBR R4 R0 K2 + 0x88140109, // 0028 GETMBR R5 R0 K9 + 0x94100805, // 0029 GETIDX R4 R4 R5 + 0x4C140000, // 002A LDNIL R5 + 0x20140805, // 002B NE R5 R4 R5 + 0x78160002, // 002C JMPF R5 #0030 + 0x5C140800, // 002D MOVE R5 R4 + 0x88180105, // 002E GETMBR R6 R0 K5 + 0x7C140200, // 002F CALL R5 1 + 0x88140109, // 0030 GETMBR R5 R0 K9 + 0x00140B0C, // 0031 ADD R5 R5 K12 + 0x90021205, // 0032 SETMBR R0 K9 R5 + 0x7001FFE9, // 0033 JMP #001E + 0x88100109, // 0034 GETMBR R4 R0 K9 + 0x14100803, // 0035 LT R4 R4 R3 + 0x78120002, // 0036 JMPF R4 #003A + 0x8C100111, // 0037 GETMET R4 R0 K17 + 0x5C180200, // 0038 MOVE R6 R1 + 0x7C100400, // 0039 CALL R4 2 + 0x80040000, // 003A RET 1 R0 }) ) ); @@ -3333,12 +3349,12 @@ be_local_closure(class_SequenceManager_start, /* name */ /******************************************************************** -** Solidified function: complete_iteration +** Solidified function: advance_to_next_step ********************************************************************/ -be_local_closure(class_SequenceManager_complete_iteration, /* name */ +be_local_closure(class_SequenceManager_advance_to_next_step, /* name */ be_nested_proto( - 7, /* nstack */ - 2, /* argc */ + 12, /* nstack */ + 3, /* argc */ 10, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ @@ -3346,70 +3362,58 @@ be_local_closure(class_SequenceManager_complete_iteration, /* name */ NULL, /* no sub protos */ 1, /* has constants */ &be_ktab_class_SequenceManager, /* shared constants */ - be_str_weak(complete_iteration), + be_str_weak(advance_to_next_step), &be_const_str_solidified, - ( &(const binstruction[61]) { /* code */ - 0x8808010F, // 0000 GETMBR R2 R0 K15 - 0x0008050E, // 0001 ADD R2 R2 K14 - 0x90021E02, // 0002 SETMBR R0 K15 R2 - 0x88080110, // 0003 GETMBR R2 R0 K16 - 0x780A0003, // 0004 JMPF R2 #0009 - 0x88080107, // 0005 GETMBR R2 R0 K7 - 0x8C080525, // 0006 GETMET R2 R2 K37 - 0x8810010F, // 0007 GETMBR R4 R0 K15 - 0x7C080400, // 0008 CALL R2 2 - 0x8C080122, // 0009 GETMET R2 R0 K34 - 0x7C080200, // 000A CALL R2 1 - 0x540DFFFE, // 000B LDINT R3 -1 - 0x1C0C0403, // 000C EQ R3 R2 R3 - 0x740E0002, // 000D JMPT R3 #0011 - 0x880C010F, // 000E GETMBR R3 R0 K15 - 0x140C0602, // 000F LT R3 R3 R2 - 0x780E0023, // 0010 JMPF R3 #0035 - 0x9002170C, // 0011 SETMBR R0 K11 K12 - 0x880C010B, // 0012 GETMBR R3 R0 K11 - 0x6010000C, // 0013 GETGBL R4 G12 - 0x88140100, // 0014 GETMBR R5 R0 K0 - 0x7C100200, // 0015 CALL R4 1 - 0x140C0604, // 0016 LT R3 R3 R4 - 0x780E0012, // 0017 JMPF R3 #002B - 0x880C0100, // 0018 GETMBR R3 R0 K0 - 0x8810010B, // 0019 GETMBR R4 R0 K11 - 0x940C0604, // 001A GETIDX R3 R3 R4 - 0x94100702, // 001B GETIDX R4 R3 K2 - 0x1C10091C, // 001C EQ R4 R4 K28 - 0x7812000A, // 001D JMPF R4 #0029 - 0x9410071C, // 001E GETIDX R4 R3 K28 - 0x4C140000, // 001F LDNIL R5 - 0x20140805, // 0020 NE R5 R4 R5 - 0x78160002, // 0021 JMPF R5 #0025 - 0x5C140800, // 0022 MOVE R5 R4 - 0x88180107, // 0023 GETMBR R6 R0 K7 - 0x7C140200, // 0024 CALL R5 1 - 0x8814010B, // 0025 GETMBR R5 R0 K11 - 0x00140B0E, // 0026 ADD R5 R5 K14 - 0x90021605, // 0027 SETMBR R0 K11 R5 - 0x70020000, // 0028 JMP #002A - 0x70020000, // 0029 JMP #002B - 0x7001FFE6, // 002A JMP #0012 - 0x880C010B, // 002B GETMBR R3 R0 K11 - 0x6010000C, // 002C GETGBL R4 G12 - 0x88140100, // 002D GETMBR R5 R0 K0 - 0x7C100200, // 002E CALL R4 1 - 0x140C0604, // 002F LT R3 R3 R4 - 0x780E0002, // 0030 JMPF R3 #0034 - 0x8C0C0124, // 0031 GETMET R3 R0 K36 - 0x5C140200, // 0032 MOVE R5 R1 - 0x7C0C0400, // 0033 CALL R3 2 - 0x70020006, // 0034 JMP #003C - 0x500C0000, // 0035 LDBOOL R3 0 0 - 0x90023203, // 0036 SETMBR R0 K25 R3 - 0x880C0110, // 0037 GETMBR R3 R0 K16 - 0x780E0002, // 0038 JMPF R3 #003C - 0x880C0107, // 0039 GETMBR R3 R0 K7 - 0x8C0C0726, // 003A GETMET R3 R3 K38 - 0x7C0C0200, // 003B CALL R3 1 - 0x80000000, // 003C RET 0 + ( &(const binstruction[49]) { /* code */ + 0x600C000C, // 0000 GETGBL R3 G12 + 0x88100100, // 0001 GETMBR R4 R0 K0 + 0x7C0C0200, // 0002 CALL R3 1 + 0x4C100000, // 0003 LDNIL R4 + 0x1C100404, // 0004 EQ R4 R2 R4 + 0x78120001, // 0005 JMPF R4 #0008 + 0x0010070C, // 0006 ADD R4 R3 K12 + 0x5C080800, // 0007 MOVE R2 R4 + 0x88100100, // 0008 GETMBR R4 R0 K0 + 0x88140109, // 0009 GETMBR R5 R0 K9 + 0x94100805, // 000A GETIDX R4 R4 R5 + 0x88140102, // 000B GETMBR R5 R0 K2 + 0x88180109, // 000C GETMBR R6 R0 K9 + 0x94140A06, // 000D GETIDX R5 R5 R6 + 0x4C180000, // 000E LDNIL R6 + 0x541DFFFD, // 000F LDINT R7 -2 + 0x201C0807, // 0010 NE R7 R4 R7 + 0x781E0006, // 0011 JMPF R7 #0019 + 0x541DFFFC, // 0012 LDINT R7 -3 + 0x201C0807, // 0013 NE R7 R4 R7 + 0x781E0003, // 0014 JMPF R7 #0019 + 0x4C1C0000, // 0015 LDNIL R7 + 0x201C0A07, // 0016 NE R7 R5 R7 + 0x781E0000, // 0017 JMPF R7 #0019 + 0x5C180A00, // 0018 MOVE R6 R5 + 0x881C0109, // 0019 GETMBR R7 R0 K9 + 0x001C0F0C, // 001A ADD R7 R7 K12 + 0x90021207, // 001B SETMBR R0 K9 R7 + 0x881C0109, // 001C GETMBR R7 R0 K9 + 0x281C0E03, // 001D GE R7 R7 R3 + 0x781E000B, // 001E JMPF R7 #002B + 0x4C1C0000, // 001F LDNIL R7 + 0x201C0C07, // 0020 NE R7 R6 R7 + 0x781E0003, // 0021 JMPF R7 #0026 + 0x881C0105, // 0022 GETMBR R7 R0 K5 + 0x8C1C0F1B, // 0023 GETMET R7 R7 K27 + 0x5C240C00, // 0024 MOVE R9 R6 + 0x7C1C0400, // 0025 CALL R7 2 + 0x8C1C011C, // 0026 GETMET R7 R0 K28 + 0x5C240200, // 0027 MOVE R9 R1 + 0x5C280400, // 0028 MOVE R10 R2 + 0x7C1C0600, // 0029 CALL R7 3 + 0x70020004, // 002A JMP #0030 + 0x8C1C011D, // 002B GETMET R7 R0 K29 + 0x5C240200, // 002C MOVE R9 R1 + 0x5C280C00, // 002D MOVE R10 R6 + 0x5C2C0400, // 002E MOVE R11 R2 + 0x7C1C0800, // 002F CALL R7 4 + 0x80000000, // 0030 RET 0 }) ) ); @@ -3433,7 +3437,7 @@ be_local_closure(class_SequenceManager_is_sequence_running, /* name */ be_str_weak(is_sequence_running), &be_const_str_solidified, ( &(const binstruction[ 2]) { /* code */ - 0x88040119, // 0000 GETMBR R1 R0 K25 + 0x88040112, // 0000 GETMBR R1 R0 K18 0x80040200, // 0001 RET 1 R1 }) ) @@ -3446,8 +3450,8 @@ be_local_closure(class_SequenceManager_is_sequence_running, /* name */ ********************************************************************/ be_local_closure(class_SequenceManager_execute_closure_steps_batch_atomic, /* name */ be_nested_proto( - 8, /* nstack */ - 3, /* argc */ + 10, /* nstack */ + 4, /* argc */ 10, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ @@ -3457,84 +3461,90 @@ be_local_closure(class_SequenceManager_execute_closure_steps_batch_atomic, /* &be_ktab_class_SequenceManager, /* shared constants */ be_str_weak(execute_closure_steps_batch_atomic), &be_const_str_solidified, - ( &(const binstruction[77]) { /* code */ - 0x880C010B, // 0000 GETMBR R3 R0 K11 - 0x6010000C, // 0001 GETGBL R4 G12 - 0x88140100, // 0002 GETMBR R5 R0 K0 - 0x7C100200, // 0003 CALL R4 1 - 0x140C0604, // 0004 LT R3 R3 R4 - 0x780E0012, // 0005 JMPF R3 #0019 - 0x880C0100, // 0006 GETMBR R3 R0 K0 - 0x8810010B, // 0007 GETMBR R4 R0 K11 - 0x940C0604, // 0008 GETIDX R3 R3 R4 - 0x94100702, // 0009 GETIDX R4 R3 K2 - 0x1C10091C, // 000A EQ R4 R4 K28 - 0x7812000A, // 000B JMPF R4 #0017 - 0x9410071C, // 000C GETIDX R4 R3 K28 - 0x4C140000, // 000D LDNIL R5 - 0x20140805, // 000E NE R5 R4 R5 - 0x78160002, // 000F JMPF R5 #0013 - 0x5C140800, // 0010 MOVE R5 R4 - 0x88180107, // 0011 GETMBR R6 R0 K7 - 0x7C140200, // 0012 CALL R5 1 - 0x8814010B, // 0013 GETMBR R5 R0 K11 - 0x00140B0E, // 0014 ADD R5 R5 K14 - 0x90021605, // 0015 SETMBR R0 K11 R5 - 0x70020000, // 0016 JMP #0018 - 0x70020000, // 0017 JMP #0019 - 0x7001FFE6, // 0018 JMP #0000 - 0x4C0C0000, // 0019 LDNIL R3 - 0x50100000, // 001A LDBOOL R4 0 0 - 0x8814010B, // 001B GETMBR R5 R0 K11 - 0x6018000C, // 001C GETGBL R6 G12 - 0x881C0100, // 001D GETMBR R7 R0 K0 - 0x7C180200, // 001E CALL R6 1 - 0x14140A06, // 001F LT R5 R5 R6 - 0x7816000B, // 0020 JMPF R5 #002D - 0x88140100, // 0021 GETMBR R5 R0 K0 - 0x8818010B, // 0022 GETMBR R6 R0 K11 - 0x940C0A06, // 0023 GETIDX R3 R5 R6 - 0x94180702, // 0024 GETIDX R6 R3 K2 - 0x1C180D13, // 0025 EQ R6 R6 K19 - 0x781A0005, // 0026 JMPF R6 #002D - 0x4C180000, // 0027 LDNIL R6 - 0x20180406, // 0028 NE R6 R2 R6 - 0x781A0002, // 0029 JMPF R6 #002D - 0x94180715, // 002A GETIDX R6 R3 K21 - 0x1C180C02, // 002B EQ R6 R6 R2 - 0x5C100C00, // 002C MOVE R4 R6 - 0x78120004, // 002D JMPF R4 #0033 - 0x90021A01, // 002E SETMBR R0 K13 R1 - 0x8C140527, // 002F GETMET R5 R2 K39 - 0x5C1C0200, // 0030 MOVE R7 R1 - 0x7C140400, // 0031 CALL R5 2 - 0x7002000F, // 0032 JMP #0043 - 0x8814010B, // 0033 GETMBR R5 R0 K11 - 0x6018000C, // 0034 GETGBL R6 G12 - 0x881C0100, // 0035 GETMBR R7 R0 K0 - 0x7C180200, // 0036 CALL R6 1 - 0x14140A06, // 0037 LT R5 R5 R6 - 0x78160002, // 0038 JMPF R5 #003C - 0x8C140124, // 0039 GETMET R5 R0 K36 - 0x5C1C0200, // 003A MOVE R7 R1 - 0x7C140400, // 003B CALL R5 2 - 0x4C140000, // 003C LDNIL R5 - 0x20140405, // 003D NE R5 R2 R5 - 0x78160003, // 003E JMPF R5 #0043 - 0x88140107, // 003F GETMBR R5 R0 K7 - 0x8C140B16, // 0040 GETMET R5 R5 K22 - 0x5C1C0400, // 0041 MOVE R7 R2 - 0x7C140400, // 0042 CALL R5 2 - 0x8814010B, // 0043 GETMBR R5 R0 K11 - 0x6018000C, // 0044 GETGBL R6 G12 - 0x881C0100, // 0045 GETMBR R7 R0 K0 - 0x7C180200, // 0046 CALL R6 1 - 0x28140A06, // 0047 GE R5 R5 R6 - 0x78160002, // 0048 JMPF R5 #004C - 0x8C140117, // 0049 GETMET R5 R0 K23 - 0x5C1C0200, // 004A MOVE R7 R1 - 0x7C140400, // 004B CALL R5 2 - 0x80000000, // 004C RET 0 + ( &(const binstruction[83]) { /* code */ + 0x4C100000, // 0000 LDNIL R4 + 0x1C100604, // 0001 EQ R4 R3 R4 + 0x78120004, // 0002 JMPF R4 #0008 + 0x6010000C, // 0003 GETGBL R4 G12 + 0x88140100, // 0004 GETMBR R5 R0 K0 + 0x7C100200, // 0005 CALL R4 1 + 0x0010090C, // 0006 ADD R4 R4 K12 + 0x5C0C0800, // 0007 MOVE R3 R4 + 0x6010000C, // 0008 GETGBL R4 G12 + 0x88140100, // 0009 GETMBR R5 R0 K0 + 0x7C100200, // 000A CALL R4 1 + 0x88140109, // 000B GETMBR R5 R0 K9 + 0x14140A04, // 000C LT R5 R5 R4 + 0x78160012, // 000D JMPF R5 #0021 + 0x88140100, // 000E GETMBR R5 R0 K0 + 0x88180109, // 000F GETMBR R6 R0 K9 + 0x94140A06, // 0010 GETIDX R5 R5 R6 + 0x5419FFFD, // 0011 LDINT R6 -2 + 0x1C140A06, // 0012 EQ R5 R5 R6 + 0x7816000C, // 0013 JMPF R5 #0021 + 0x88140102, // 0014 GETMBR R5 R0 K2 + 0x88180109, // 0015 GETMBR R6 R0 K9 + 0x94140A06, // 0016 GETIDX R5 R5 R6 + 0x4C180000, // 0017 LDNIL R6 + 0x20180A06, // 0018 NE R6 R5 R6 + 0x781A0002, // 0019 JMPF R6 #001D + 0x5C180A00, // 001A MOVE R6 R5 + 0x881C0105, // 001B GETMBR R7 R0 K5 + 0x7C180200, // 001C CALL R6 1 + 0x88180109, // 001D GETMBR R6 R0 K9 + 0x00180D0C, // 001E ADD R6 R6 K12 + 0x90021206, // 001F SETMBR R0 K9 R6 + 0x7001FFE9, // 0020 JMP #000B + 0x50140000, // 0021 LDBOOL R5 0 0 + 0x88180109, // 0022 GETMBR R6 R0 K9 + 0x14180C04, // 0023 LT R6 R6 R4 + 0x781A0011, // 0024 JMPF R6 #0037 + 0x4C180000, // 0025 LDNIL R6 + 0x20180406, // 0026 NE R6 R2 R6 + 0x781A000E, // 0027 JMPF R6 #0037 + 0x88180100, // 0028 GETMBR R6 R0 K0 + 0x881C0109, // 0029 GETMBR R7 R0 K9 + 0x94180C07, // 002A GETIDX R6 R6 R7 + 0x881C0102, // 002B GETMBR R7 R0 K2 + 0x88200109, // 002C GETMBR R8 R0 K9 + 0x941C0E08, // 002D GETIDX R7 R7 R8 + 0x5421FFFD, // 002E LDINT R8 -2 + 0x20200C08, // 002F NE R8 R6 R8 + 0x78220005, // 0030 JMPF R8 #0037 + 0x5421FFFC, // 0031 LDINT R8 -3 + 0x20200C08, // 0032 NE R8 R6 R8 + 0x78220002, // 0033 JMPF R8 #0037 + 0x1C200E02, // 0034 EQ R8 R7 R2 + 0x78220000, // 0035 JMPF R8 #0037 + 0x50140200, // 0036 LDBOOL R5 1 0 + 0x78160004, // 0037 JMPF R5 #003D + 0x90021601, // 0038 SETMBR R0 K11 R1 + 0x8C18051E, // 0039 GETMET R6 R2 K30 + 0x5C200200, // 003A MOVE R8 R1 + 0x7C180400, // 003B CALL R6 2 + 0x7002000D, // 003C JMP #004B + 0x88180109, // 003D GETMBR R6 R0 K9 + 0x14180C04, // 003E LT R6 R6 R4 + 0x781A0003, // 003F JMPF R6 #0044 + 0x8C180111, // 0040 GETMET R6 R0 K17 + 0x5C200200, // 0041 MOVE R8 R1 + 0x5C240600, // 0042 MOVE R9 R3 + 0x7C180600, // 0043 CALL R6 3 + 0x4C180000, // 0044 LDNIL R6 + 0x20180406, // 0045 NE R6 R2 R6 + 0x781A0003, // 0046 JMPF R6 #004B + 0x88180105, // 0047 GETMBR R6 R0 K5 + 0x8C180D1B, // 0048 GETMET R6 R6 K27 + 0x5C200400, // 0049 MOVE R8 R2 + 0x7C180400, // 004A CALL R6 2 + 0x88180109, // 004B GETMBR R6 R0 K9 + 0x28180C04, // 004C GE R6 R6 R4 + 0x781A0003, // 004D JMPF R6 #0052 + 0x8C18011C, // 004E GETMET R6 R0 K28 + 0x5C200200, // 004F MOVE R8 R1 + 0x5C240600, // 0050 MOVE R9 R3 + 0x7C180600, // 0051 CALL R6 3 + 0x80000000, // 0052 RET 0 }) ) ); @@ -3542,12 +3552,12 @@ be_local_closure(class_SequenceManager_execute_closure_steps_batch_atomic, /* /******************************************************************** -** Solidified function: push_step +** Solidified function: stop ********************************************************************/ -be_local_closure(class_SequenceManager_push_step, /* name */ +be_local_closure(class_SequenceManager_stop, /* name */ be_nested_proto( - 5, /* nstack */ - 2, /* argc */ + 7, /* nstack */ + 1, /* argc */ 10, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ @@ -3555,14 +3565,49 @@ be_local_closure(class_SequenceManager_push_step, /* name */ NULL, /* no sub protos */ 1, /* has constants */ &be_ktab_class_SequenceManager, /* shared constants */ - be_str_weak(push_step), + be_str_weak(stop), &be_const_str_solidified, - ( &(const binstruction[ 5]) { /* code */ - 0x88080100, // 0000 GETMBR R2 R0 K0 - 0x8C080501, // 0001 GETMET R2 R2 K1 - 0x5C100200, // 0002 MOVE R4 R1 - 0x7C080400, // 0003 CALL R2 2 - 0x80040000, // 0004 RET 1 R0 + ( &(const binstruction[40]) { /* code */ + 0x88040112, // 0000 GETMBR R1 R0 K18 + 0x78060024, // 0001 JMPF R1 #0027 + 0x50040000, // 0002 LDBOOL R1 0 0 + 0x90022401, // 0003 SETMBR R0 K18 R1 + 0x8804010E, // 0004 GETMBR R1 R0 K14 + 0x78060002, // 0005 JMPF R1 #0009 + 0x88040105, // 0006 GETMBR R1 R0 K5 + 0x8C040313, // 0007 GETMET R1 R1 K19 + 0x7C040200, // 0008 CALL R1 1 + 0x6004000C, // 0009 GETGBL R1 G12 + 0x88080100, // 000A GETMBR R2 R0 K0 + 0x7C040200, // 000B CALL R1 1 + 0x88080109, // 000C GETMBR R2 R0 K9 + 0x14080401, // 000D LT R2 R2 R1 + 0x780A0015, // 000E JMPF R2 #0025 + 0x88080100, // 000F GETMBR R2 R0 K0 + 0x880C0109, // 0010 GETMBR R3 R0 K9 + 0x94080403, // 0011 GETIDX R2 R2 R3 + 0x880C0102, // 0012 GETMBR R3 R0 K2 + 0x88100109, // 0013 GETMBR R4 R0 K9 + 0x940C0604, // 0014 GETIDX R3 R3 R4 + 0x5411FFFC, // 0015 LDINT R4 -3 + 0x1C100404, // 0016 EQ R4 R2 R4 + 0x78120002, // 0017 JMPF R4 #001B + 0x8C100717, // 0018 GETMET R4 R3 K23 + 0x7C100200, // 0019 CALL R4 1 + 0x70020009, // 001A JMP #0025 + 0x5411FFFD, // 001B LDINT R4 -2 + 0x20100404, // 001C NE R4 R2 R4 + 0x78120006, // 001D JMPF R4 #0025 + 0x4C100000, // 001E LDNIL R4 + 0x20100604, // 001F NE R4 R3 R4 + 0x78120003, // 0020 JMPF R4 #0025 + 0x88100105, // 0021 GETMBR R4 R0 K5 + 0x8C10091B, // 0022 GETMET R4 R4 K27 + 0x5C180600, // 0023 MOVE R6 R3 + 0x7C100400, // 0024 CALL R4 2 + 0x8C080118, // 0025 GETMET R2 R0 K24 + 0x7C080200, // 0026 CALL R2 1 + 0x80040000, // 0027 RET 1 R0 }) ) ); @@ -3574,8 +3619,8 @@ be_local_closure(class_SequenceManager_push_step, /* name */ ********************************************************************/ be_local_closure(class_SequenceManager_execute_current_step, /* name */ be_nested_proto( - 9, /* nstack */ - 2, /* argc */ + 11, /* nstack */ + 3, /* argc */ 10, /* varg */ 0, /* has upvals */ NULL, /* no upvals */ @@ -3585,91 +3630,92 @@ be_local_closure(class_SequenceManager_execute_current_step, /* name */ &be_ktab_class_SequenceManager, /* shared constants */ be_str_weak(execute_current_step), &be_const_str_solidified, - ( &(const binstruction[84]) { /* code */ - 0x8808010B, // 0000 GETMBR R2 R0 K11 - 0x600C000C, // 0001 GETGBL R3 G12 - 0x88100100, // 0002 GETMBR R4 R0 K0 - 0x7C0C0200, // 0003 CALL R3 1 - 0x28080403, // 0004 GE R2 R2 R3 - 0x780A0003, // 0005 JMPF R2 #000A - 0x8C080117, // 0006 GETMET R2 R0 K23 - 0x5C100200, // 0007 MOVE R4 R1 - 0x7C080400, // 0008 CALL R2 2 - 0x80000400, // 0009 RET 0 - 0x88080100, // 000A GETMBR R2 R0 K0 - 0x880C010B, // 000B GETMBR R3 R0 K11 - 0x94080403, // 000C GETIDX R2 R2 R3 - 0x940C0502, // 000D GETIDX R3 R2 K2 - 0x1C0C0713, // 000E EQ R3 R3 K19 - 0x780E0022, // 000F JMPF R3 #0033 - 0x940C0515, // 0010 GETIDX R3 R2 K21 - 0x4C100000, // 0011 LDNIL R4 - 0x1C100604, // 0012 EQ R4 R3 R4 - 0x78120000, // 0013 JMPF R4 #0015 - 0x80000800, // 0014 RET 0 - 0x88100107, // 0015 GETMBR R4 R0 K7 - 0x8C100928, // 0016 GETMET R4 R4 K40 - 0x7C100200, // 0017 CALL R4 1 - 0x50140000, // 0018 LDBOOL R5 0 0 - 0x60180010, // 0019 GETGBL R6 G16 - 0x5C1C0800, // 001A MOVE R7 R4 - 0x7C180200, // 001B CALL R6 1 - 0xA8020008, // 001C EXBLK 0 #0026 - 0x5C1C0C00, // 001D MOVE R7 R6 - 0x7C1C0000, // 001E CALL R7 0 - 0x1C200E03, // 001F EQ R8 R7 R3 - 0x78220001, // 0020 JMPF R8 #0023 - 0x50140200, // 0021 LDBOOL R5 1 0 - 0x70020000, // 0022 JMP #0024 - 0x7001FFF8, // 0023 JMP #001D - 0xA8040001, // 0024 EXBLK 1 1 - 0x70020002, // 0025 JMP #0029 - 0x5818001F, // 0026 LDCONST R6 K31 - 0xAC180200, // 0027 CATCH R6 1 0 - 0xB0080000, // 0028 RAISE 2 R0 R0 - 0x5C180A00, // 0029 MOVE R6 R5 - 0x741A0003, // 002A JMPT R6 #002F - 0x88180107, // 002B GETMBR R6 R0 K7 - 0x8C180D29, // 002C GETMET R6 R6 K41 - 0x5C200600, // 002D MOVE R8 R3 - 0x7C180400, // 002E CALL R6 2 - 0x8C180727, // 002F GETMET R6 R3 K39 - 0x5C200200, // 0030 MOVE R8 R1 - 0x7C180400, // 0031 CALL R6 2 - 0x7002001E, // 0032 JMP #0052 - 0x940C0502, // 0033 GETIDX R3 R2 K2 - 0x1C0C0703, // 0034 EQ R3 R3 K3 - 0x780E0000, // 0035 JMPF R3 #0037 - 0x7002001A, // 0036 JMP #0052 - 0x940C0502, // 0037 GETIDX R3 R2 K2 - 0x1C0C071E, // 0038 EQ R3 R3 K30 - 0x780E0005, // 0039 JMPF R3 #0040 - 0x940C0515, // 003A GETIDX R3 R2 K21 - 0x88100107, // 003B GETMBR R4 R0 K7 - 0x8C100916, // 003C GETMET R4 R4 K22 - 0x5C180600, // 003D MOVE R6 R3 - 0x7C100400, // 003E CALL R4 2 - 0x70020011, // 003F JMP #0052 - 0x940C0502, // 0040 GETIDX R3 R2 K2 - 0x1C0C071C, // 0041 EQ R3 R3 K28 - 0x780E0007, // 0042 JMPF R3 #004B - 0x940C051C, // 0043 GETIDX R3 R2 K28 - 0x4C100000, // 0044 LDNIL R4 - 0x20100604, // 0045 NE R4 R3 R4 - 0x78120002, // 0046 JMPF R4 #004A - 0x5C100600, // 0047 MOVE R4 R3 - 0x88140107, // 0048 GETMBR R5 R0 K7 - 0x7C100200, // 0049 CALL R4 1 - 0x70020006, // 004A JMP #0052 - 0x940C0502, // 004B GETIDX R3 R2 K2 - 0x1C0C0711, // 004C EQ R3 R3 K17 - 0x780E0003, // 004D JMPF R3 #0052 - 0x940C0512, // 004E GETIDX R3 R2 K18 - 0x8C100727, // 004F GETMET R4 R3 K39 - 0x5C180200, // 0050 MOVE R6 R1 - 0x7C100400, // 0051 CALL R4 2 - 0x90021A01, // 0052 SETMBR R0 K13 R1 - 0x80000000, // 0053 RET 0 + ( &(const binstruction[85]) { /* code */ + 0x4C0C0000, // 0000 LDNIL R3 + 0x1C0C0403, // 0001 EQ R3 R2 R3 + 0x780E0004, // 0002 JMPF R3 #0008 + 0x600C000C, // 0003 GETGBL R3 G12 + 0x88100100, // 0004 GETMBR R4 R0 K0 + 0x7C0C0200, // 0005 CALL R3 1 + 0x000C070C, // 0006 ADD R3 R3 K12 + 0x5C080600, // 0007 MOVE R2 R3 + 0x600C000C, // 0008 GETGBL R3 G12 + 0x88100100, // 0009 GETMBR R4 R0 K0 + 0x7C0C0200, // 000A CALL R3 1 + 0x88100109, // 000B GETMBR R4 R0 K9 + 0x28100803, // 000C GE R4 R4 R3 + 0x78120004, // 000D JMPF R4 #0013 + 0x8C10011C, // 000E GETMET R4 R0 K28 + 0x5C180200, // 000F MOVE R6 R1 + 0x5C1C0400, // 0010 MOVE R7 R2 + 0x7C100600, // 0011 CALL R4 3 + 0x80000800, // 0012 RET 0 + 0x88100100, // 0013 GETMBR R4 R0 K0 + 0x88140109, // 0014 GETMBR R5 R0 K9 + 0x94100805, // 0015 GETIDX R4 R4 R5 + 0x88140102, // 0016 GETMBR R5 R0 K2 + 0x88180109, // 0017 GETMBR R6 R0 K9 + 0x94140A06, // 0018 GETIDX R5 R5 R6 + 0x5419FFFC, // 0019 LDINT R6 -3 + 0x1C180806, // 001A EQ R6 R4 R6 + 0x781A000C, // 001B JMPF R6 #0029 + 0x8C180B1E, // 001C GETMET R6 R5 K30 + 0x5C200200, // 001D MOVE R8 R1 + 0x7C180400, // 001E CALL R6 2 + 0x88180B12, // 001F GETMBR R6 R5 K18 + 0x741A0006, // 0020 JMPT R6 #0028 + 0x2418050A, // 0021 GT R6 R2 K10 + 0x781A0004, // 0022 JMPF R6 #0028 + 0x8C180115, // 0023 GETMET R6 R0 K21 + 0x5C200200, // 0024 MOVE R8 R1 + 0x0424050C, // 0025 SUB R9 R2 K12 + 0x7C180600, // 0026 CALL R6 3 + 0x80000C00, // 0027 RET 0 + 0x70020029, // 0028 JMP #0053 + 0x5419FFFD, // 0029 LDINT R6 -2 + 0x1C180806, // 002A EQ R6 R4 R6 + 0x781A0006, // 002B JMPF R6 #0033 + 0x4C180000, // 002C LDNIL R6 + 0x20180A06, // 002D NE R6 R5 R6 + 0x781A0002, // 002E JMPF R6 #0032 + 0x5C180A00, // 002F MOVE R6 R5 + 0x881C0105, // 0030 GETMBR R7 R0 K5 + 0x7C180200, // 0031 CALL R6 1 + 0x7002001F, // 0032 JMP #0053 + 0x4C180000, // 0033 LDNIL R6 + 0x20180A06, // 0034 NE R6 R5 R6 + 0x781A001C, // 0035 JMPF R6 #0053 + 0x88180105, // 0036 GETMBR R6 R0 K5 + 0x8C180D1F, // 0037 GETMET R6 R6 K31 + 0x7C180200, // 0038 CALL R6 1 + 0x501C0000, // 0039 LDBOOL R7 0 0 + 0x60200010, // 003A GETGBL R8 G16 + 0x5C240C00, // 003B MOVE R9 R6 + 0x7C200200, // 003C CALL R8 1 + 0xA8020008, // 003D EXBLK 0 #0047 + 0x5C241000, // 003E MOVE R9 R8 + 0x7C240000, // 003F CALL R9 0 + 0x1C281205, // 0040 EQ R10 R9 R5 + 0x782A0001, // 0041 JMPF R10 #0044 + 0x501C0200, // 0042 LDBOOL R7 1 0 + 0x70020000, // 0043 JMP #0045 + 0x7001FFF8, // 0044 JMP #003E + 0xA8040001, // 0045 EXBLK 1 1 + 0x70020002, // 0046 JMP #004A + 0x58200020, // 0047 LDCONST R8 K32 + 0xAC200200, // 0048 CATCH R8 1 0 + 0xB0080000, // 0049 RAISE 2 R0 R0 + 0x5C200E00, // 004A MOVE R8 R7 + 0x74220003, // 004B JMPT R8 #0050 + 0x88200105, // 004C GETMBR R8 R0 K5 + 0x8C201121, // 004D GETMET R8 R8 K33 + 0x5C280A00, // 004E MOVE R10 R5 + 0x7C200400, // 004F CALL R8 2 + 0x8C200B1E, // 0050 GETMET R8 R5 K30 + 0x5C280200, // 0051 MOVE R10 R1 + 0x7C200400, // 0052 CALL R8 2 + 0x90021601, // 0053 SETMBR R0 K11 R1 + 0x80000000, // 0054 RET 0 }) ) ); @@ -3681,7 +3727,7 @@ be_local_closure(class_SequenceManager_execute_current_step, /* name */ ********************************************************************/ be_local_closure(class_SequenceManager_push_play_step, /* name */ be_nested_proto( - 7, /* nstack */ + 6, /* nstack */ 3, /* argc */ 10, /* varg */ 0, /* has upvals */ @@ -3692,22 +3738,21 @@ be_local_closure(class_SequenceManager_push_play_step, /* name */ &be_ktab_class_SequenceManager, /* shared constants */ be_str_weak(push_play_step), &be_const_str_solidified, - ( &(const binstruction[15]) { /* code */ + ( &(const binstruction[14]) { /* code */ 0x880C0100, // 0000 GETMBR R3 R0 K0 0x8C0C0701, // 0001 GETMET R3 R3 K1 - 0x60140013, // 0002 GETGBL R5 G19 - 0x7C140000, // 0003 CALL R5 0 - 0x98160513, // 0004 SETIDX R5 K2 K19 - 0x98162A01, // 0005 SETIDX R5 K21 R1 - 0x4C180000, // 0006 LDNIL R6 - 0x20180406, // 0007 NE R6 R2 R6 - 0x781A0001, // 0008 JMPF R6 #000B - 0x5C180400, // 0009 MOVE R6 R2 - 0x70020000, // 000A JMP #000C - 0x5818000C, // 000B LDCONST R6 K12 - 0x98160806, // 000C SETIDX R5 K4 R6 - 0x7C0C0400, // 000D CALL R3 2 - 0x80040000, // 000E RET 1 R0 + 0x4C140000, // 0002 LDNIL R5 + 0x20140405, // 0003 NE R5 R2 R5 + 0x78160001, // 0004 JMPF R5 #0007 + 0x5C140400, // 0005 MOVE R5 R2 + 0x70020000, // 0006 JMP #0008 + 0x5814000A, // 0007 LDCONST R5 K10 + 0x7C0C0400, // 0008 CALL R3 2 + 0x880C0102, // 0009 GETMBR R3 R0 K2 + 0x8C0C0701, // 000A GETMET R3 R3 K1 + 0x5C140200, // 000B MOVE R5 R1 + 0x7C0C0400, // 000C CALL R3 2 + 0x80040000, // 000D RET 1 R0 }) ) ); @@ -3730,15 +3775,16 @@ be_local_closure(class_SequenceManager_push_closure_step, /* name */ &be_ktab_class_SequenceManager, /* shared constants */ be_str_weak(push_closure_step), &be_const_str_solidified, - ( &(const binstruction[ 8]) { /* code */ + ( &(const binstruction[ 9]) { /* code */ 0x88080100, // 0000 GETMBR R2 R0 K0 0x8C080501, // 0001 GETMET R2 R2 K1 - 0x60100013, // 0002 GETGBL R4 G19 - 0x7C100000, // 0003 CALL R4 0 - 0x9812051C, // 0004 SETIDX R4 K2 K28 - 0x98123801, // 0005 SETIDX R4 K28 R1 - 0x7C080400, // 0006 CALL R2 2 - 0x80040000, // 0007 RET 1 R0 + 0x5411FFFD, // 0002 LDINT R4 -2 + 0x7C080400, // 0003 CALL R2 2 + 0x88080102, // 0004 GETMBR R2 R0 K2 + 0x8C080501, // 0005 GETMET R2 R2 K1 + 0x5C100200, // 0006 MOVE R4 R1 + 0x7C080400, // 0007 CALL R2 2 + 0x80040000, // 0008 RET 1 R0 }) ) ); @@ -3761,105 +3807,43 @@ be_local_closure(class_SequenceManager_execute_closure_steps_batch, /* name */ &be_ktab_class_SequenceManager, /* shared constants */ be_str_weak(execute_closure_steps_batch), &be_const_str_solidified, - ( &(const binstruction[39]) { /* code */ - 0x8808010B, // 0000 GETMBR R2 R0 K11 - 0x600C000C, // 0001 GETGBL R3 G12 - 0x88100100, // 0002 GETMBR R4 R0 K0 - 0x7C0C0200, // 0003 CALL R3 1 - 0x14080403, // 0004 LT R2 R2 R3 - 0x780A0012, // 0005 JMPF R2 #0019 - 0x88080100, // 0006 GETMBR R2 R0 K0 - 0x880C010B, // 0007 GETMBR R3 R0 K11 - 0x94080403, // 0008 GETIDX R2 R2 R3 - 0x940C0502, // 0009 GETIDX R3 R2 K2 - 0x1C0C071C, // 000A EQ R3 R3 K28 - 0x780E000A, // 000B JMPF R3 #0017 - 0x940C051C, // 000C GETIDX R3 R2 K28 - 0x4C100000, // 000D LDNIL R4 - 0x20100604, // 000E NE R4 R3 R4 - 0x78120002, // 000F JMPF R4 #0013 - 0x5C100600, // 0010 MOVE R4 R3 - 0x88140107, // 0011 GETMBR R5 R0 K7 - 0x7C100200, // 0012 CALL R4 1 - 0x8810010B, // 0013 GETMBR R4 R0 K11 - 0x0010090E, // 0014 ADD R4 R4 K14 - 0x90021604, // 0015 SETMBR R0 K11 R4 - 0x70020000, // 0016 JMP #0018 - 0x70020000, // 0017 JMP #0019 - 0x7001FFE6, // 0018 JMP #0000 - 0x8808010B, // 0019 GETMBR R2 R0 K11 - 0x600C000C, // 001A GETGBL R3 G12 - 0x88100100, // 001B GETMBR R4 R0 K0 - 0x7C0C0200, // 001C CALL R3 1 - 0x14080403, // 001D LT R2 R2 R3 - 0x780A0003, // 001E JMPF R2 #0023 - 0x8C080124, // 001F GETMET R2 R0 K36 - 0x5C100200, // 0020 MOVE R4 R1 - 0x7C080400, // 0021 CALL R2 2 - 0x70020002, // 0022 JMP #0026 - 0x8C080117, // 0023 GETMET R2 R0 K23 - 0x5C100200, // 0024 MOVE R4 R1 - 0x7C080400, // 0025 CALL R2 2 - 0x80000000, // 0026 RET 0 - }) - ) -); -/*******************************************************************/ - - -/******************************************************************** -** Solidified function: stop -********************************************************************/ -be_local_closure(class_SequenceManager_stop, /* name */ - be_nested_proto( - 6, /* nstack */ - 1, /* argc */ - 10, /* varg */ - 0, /* has upvals */ - NULL, /* no upvals */ - 0, /* has sup protos */ - NULL, /* no sub protos */ - 1, /* has constants */ - &be_ktab_class_SequenceManager, /* shared constants */ - be_str_weak(stop), - &be_const_str_solidified, ( &(const binstruction[36]) { /* code */ - 0x88040119, // 0000 GETMBR R1 R0 K25 - 0x78060020, // 0001 JMPF R1 #0023 - 0x50040000, // 0002 LDBOOL R1 0 0 - 0x90023201, // 0003 SETMBR R0 K25 R1 - 0x88040110, // 0004 GETMBR R1 R0 K16 - 0x78060002, // 0005 JMPF R1 #0009 - 0x88040107, // 0006 GETMBR R1 R0 K7 - 0x8C040326, // 0007 GETMET R1 R1 K38 - 0x7C040200, // 0008 CALL R1 1 - 0x8804010B, // 0009 GETMBR R1 R0 K11 - 0x6008000C, // 000A GETGBL R2 G12 - 0x880C0100, // 000B GETMBR R3 R0 K0 - 0x7C080200, // 000C CALL R2 1 - 0x14040202, // 000D LT R1 R1 R2 - 0x78060011, // 000E JMPF R1 #0021 - 0x88040100, // 000F GETMBR R1 R0 K0 - 0x8808010B, // 0010 GETMBR R2 R0 K11 - 0x94040202, // 0011 GETIDX R1 R1 R2 - 0x94080302, // 0012 GETIDX R2 R1 K2 - 0x1C080513, // 0013 EQ R2 R2 K19 - 0x780A0005, // 0014 JMPF R2 #001B - 0x94080315, // 0015 GETIDX R2 R1 K21 - 0x880C0107, // 0016 GETMBR R3 R0 K7 - 0x8C0C0716, // 0017 GETMET R3 R3 K22 - 0x5C140400, // 0018 MOVE R5 R2 - 0x7C0C0400, // 0019 CALL R3 2 - 0x70020005, // 001A JMP #0021 - 0x94080302, // 001B GETIDX R2 R1 K2 - 0x1C080511, // 001C EQ R2 R2 K17 - 0x780A0002, // 001D JMPF R2 #0021 - 0x94080312, // 001E GETIDX R2 R1 K18 - 0x8C0C051E, // 001F GETMET R3 R2 K30 - 0x7C0C0200, // 0020 CALL R3 1 - 0x8C040120, // 0021 GETMET R1 R0 K32 - 0x7C040200, // 0022 CALL R1 1 - 0x80040000, // 0023 RET 1 R0 + 0x6008000C, // 0000 GETGBL R2 G12 + 0x880C0100, // 0001 GETMBR R3 R0 K0 + 0x7C080200, // 0002 CALL R2 1 + 0x880C0109, // 0003 GETMBR R3 R0 K9 + 0x140C0602, // 0004 LT R3 R3 R2 + 0x780E0012, // 0005 JMPF R3 #0019 + 0x880C0100, // 0006 GETMBR R3 R0 K0 + 0x88100109, // 0007 GETMBR R4 R0 K9 + 0x940C0604, // 0008 GETIDX R3 R3 R4 + 0x5411FFFD, // 0009 LDINT R4 -2 + 0x1C0C0604, // 000A EQ R3 R3 R4 + 0x780E000C, // 000B JMPF R3 #0019 + 0x880C0102, // 000C GETMBR R3 R0 K2 + 0x88100109, // 000D GETMBR R4 R0 K9 + 0x940C0604, // 000E GETIDX R3 R3 R4 + 0x4C100000, // 000F LDNIL R4 + 0x20100604, // 0010 NE R4 R3 R4 + 0x78120002, // 0011 JMPF R4 #0015 + 0x5C100600, // 0012 MOVE R4 R3 + 0x88140105, // 0013 GETMBR R5 R0 K5 + 0x7C100200, // 0014 CALL R4 1 + 0x88100109, // 0015 GETMBR R4 R0 K9 + 0x0010090C, // 0016 ADD R4 R4 K12 + 0x90021204, // 0017 SETMBR R0 K9 R4 + 0x7001FFE9, // 0018 JMP #0003 + 0x880C0109, // 0019 GETMBR R3 R0 K9 + 0x140C0602, // 001A LT R3 R3 R2 + 0x780E0003, // 001B JMPF R3 #0020 + 0x8C0C0111, // 001C GETMET R3 R0 K17 + 0x5C140200, // 001D MOVE R5 R1 + 0x7C0C0400, // 001E CALL R3 2 + 0x70020002, // 001F JMP #0023 + 0x8C0C011C, // 0020 GETMET R3 R0 K28 + 0x5C140200, // 0021 MOVE R5 R1 + 0x7C0C0400, // 0022 CALL R3 2 + 0x80000000, // 0023 RET 0 }) ) ); @@ -3871,35 +3855,35 @@ be_local_closure(class_SequenceManager_stop, /* name */ ********************************************************************/ extern const bclass be_class_ParameterizedObject; be_local_class(SequenceManager, - 8, + 9, &be_class_ParameterizedObject, be_nested_map(25, ( (struct bmapnode*) &(const bmapnode[]) { - { be_const_key_weak(is_repeat_sequence, -1), be_const_var(7) }, - { be_const_key_weak(steps, -1), be_const_var(4) }, - { be_const_key_weak(stop, -1), be_const_closure(class_SequenceManager_stop_closure) }, + { be_const_key_weak(is_repeat_sequence, -1), be_const_var(8) }, + { be_const_key_weak(current_iteration, -1), be_const_var(7) }, + { be_const_key_weak(step_refs, -1), be_const_var(5) }, { be_const_key_weak(push_wait_step, -1), be_const_closure(class_SequenceManager_push_wait_step_closure) }, - { be_const_key_weak(step_index, -1), be_const_var(2) }, - { be_const_key_weak(init, 24), be_const_closure(class_SequenceManager_init_closure) }, + { be_const_key_weak(advance_to_next_step, -1), be_const_closure(class_SequenceManager_advance_to_next_step_closure) }, + { be_const_key_weak(init, 4), be_const_closure(class_SequenceManager_init_closure) }, { be_const_key_weak(push_repeat_subsequence, -1), be_const_closure(class_SequenceManager_push_repeat_subsequence_closure) }, { be_const_key_weak(is_sequence_running, -1), be_const_closure(class_SequenceManager_is_sequence_running_closure) }, - { be_const_key_weak(step_start_time, 4), be_const_var(3) }, + { be_const_key_weak(step_start_time, 24), be_const_var(3) }, { be_const_key_weak(update, -1), be_const_closure(class_SequenceManager_update_closure) }, { be_const_key_weak(stop_all_subsequences, -1), be_const_closure(class_SequenceManager_stop_all_subsequences_closure) }, - { be_const_key_weak(start, 15), be_const_closure(class_SequenceManager_start_closure) }, + { be_const_key_weak(start, 1), be_const_closure(class_SequenceManager_start_closure) }, { be_const_key_weak(sequence_state, -1), be_const_var(1) }, { be_const_key_weak(complete_iteration, 7), be_const_closure(class_SequenceManager_complete_iteration_closure) }, { be_const_key_weak(execute_closure_steps_batch_atomic, 12), be_const_closure(class_SequenceManager_execute_closure_steps_batch_atomic_closure) }, - { be_const_key_weak(current_iteration, -1), be_const_var(6) }, { be_const_key_weak(execute_current_step, -1), be_const_closure(class_SequenceManager_execute_current_step_closure) }, - { be_const_key_weak(push_step, 2), be_const_closure(class_SequenceManager_push_step_closure) }, - { be_const_key_weak(get_resolved_repeat_count, 16), be_const_closure(class_SequenceManager_get_resolved_repeat_count_closure) }, + { be_const_key_weak(step_durations, -1), be_const_var(4) }, + { be_const_key_weak(stop, -1), be_const_closure(class_SequenceManager_stop_closure) }, + { be_const_key_weak(get_resolved_repeat_count, 15), be_const_closure(class_SequenceManager_get_resolved_repeat_count_closure) }, { be_const_key_weak(push_play_step, -1), be_const_closure(class_SequenceManager_push_play_step_closure) }, - { be_const_key_weak(repeat_count, -1), be_const_var(5) }, + { be_const_key_weak(repeat_count, -1), be_const_var(6) }, { be_const_key_weak(active_sequence, -1), be_const_var(0) }, { be_const_key_weak(push_closure_step, -1), be_const_closure(class_SequenceManager_push_closure_step_closure) }, { be_const_key_weak(execute_closure_steps_batch, -1), be_const_closure(class_SequenceManager_execute_closure_steps_batch_closure) }, - { be_const_key_weak(advance_to_next_step, -1), be_const_closure(class_SequenceManager_advance_to_next_step_closure) }, + { be_const_key_weak(step_index, -1), be_const_var(2) }, })), be_str_weak(SequenceManager) ); diff --git a/lib/libesp32/berry_animation/src/tests/sequence_manager_test.be b/lib/libesp32/berry_animation/src/tests/sequence_manager_test.be index c388221da..2a8c5491d 100644 --- a/lib/libesp32/berry_animation/src/tests/sequence_manager_test.be +++ b/lib/libesp32/berry_animation/src/tests/sequence_manager_test.be @@ -21,8 +21,10 @@ def test_sequence_manager_basic() # Test initialization var seq_manager = animation.sequence_manager(engine) assert(seq_manager.engine == engine, "Engine should be set correctly") - assert(seq_manager.steps != nil, "Steps list should be initialized") - assert(seq_manager.steps.size() == 0, "Steps list should be empty initially") + assert(seq_manager.step_durations != nil, "Step durations list should be initialized") + assert(seq_manager.step_refs != nil, "Step refs list should be initialized") + assert(size(seq_manager.step_durations) == 0, "Step durations list should be empty initially") + assert(size(seq_manager.step_refs) == 0, "Step refs list should be empty initially") assert(seq_manager.step_index == 0, "Step index should be 0 initially") assert(seq_manager.is_running == false, "Sequence should not be running initially") @@ -48,26 +50,22 @@ def test_sequence_manager_step_creation() # Test push_play_step seq_manager.push_play_step(test_anim, 5000) - assert(seq_manager.steps.size() == 1, "Should have one step after push_play_step") - var play_step = seq_manager.steps[0] - assert(play_step["type"] == "play", "Play step should have correct type") - assert(play_step["animation"] == test_anim, "Play step should have correct animation") - assert(play_step["duration"] == 5000, "Play step should have correct duration") + assert(size(seq_manager.step_durations) == 1, "Should have one step after push_play_step") + assert(seq_manager.step_durations[0] == 5000, "Play step should have correct duration") + assert(seq_manager.step_refs[0] == test_anim, "Play step should have correct animation") # Test push_wait_step seq_manager.push_wait_step(2000) - assert(seq_manager.steps.size() == 2, "Should have two steps after push_wait_step") - var wait_step = seq_manager.steps[1] - assert(wait_step["type"] == "wait", "Wait step should have correct type") - assert(wait_step["duration"] == 2000, "Wait step should have correct duration") + assert(size(seq_manager.step_durations) == 2, "Should have two steps after push_wait_step") + assert(seq_manager.step_durations[1] == 2000, "Wait step should have correct duration") + assert(seq_manager.step_refs[1] == nil, "Wait step should have nil ref") # Test push_closure_step var test_closure = def (engine) test_anim.opacity = 128 end seq_manager.push_closure_step(test_closure) - assert(seq_manager.steps.size() == 3, "Should have three steps after push_closure_step") - var assign_step = seq_manager.steps[2] - assert(assign_step["type"] == "closure", "Assign step should have correct type") - assert(assign_step["closure"] == test_closure, "Assign step should have correct closure") + assert(size(seq_manager.step_durations) == 3, "Should have three steps after push_closure_step") + assert(seq_manager.step_durations[2] == -2, "Closure step should have correct duration marker (-2)") + assert(seq_manager.step_refs[2] == test_closure, "Closure step should have correct closure") print("āœ“ Step creation tests passed") end @@ -109,7 +107,7 @@ def test_sequence_manager_execution() seq_manager.start() assert(seq_manager.is_running == true, "Sequence should be running after start") - assert(seq_manager.steps.size() == 3, "Sequence should have 3 steps") + assert(size(seq_manager.step_durations) == 3, "Sequence should have 3 steps") assert(seq_manager.step_index == 0, "Should start at step 0") # Check that first animation was started @@ -921,6 +919,189 @@ def test_sequence_manager_boolean_repeat_counts() print("āœ“ Boolean repeat count tests passed") end +def test_sequence_manager_false_conditional_immediate_skip() + print("=== SequenceManager False Conditional Immediate Skip Tests ===") + + # This test verifies that when a conditional subsequence (if block) has a false condition, + # the parent sequence immediately advances to the next step without waiting for a tick. + # This prevents the "black frame" issue where no animation runs for one tick. + + # Create strip and engine + var strip = global.Leds(30) + var engine = animation.create_engine(strip) + + # Create test animations + var color_provider1 = animation.static_color(engine) + color_provider1.color = 0xFFFF0000 # Red + var anim1 = animation.solid(engine) + anim1.color = color_provider1 + anim1.priority = 0 + anim1.duration = 0 + anim1.loop = true + + var color_provider2 = animation.static_color(engine) + color_provider2.color = 0xFF00FF00 # Green + var anim2 = animation.solid(engine) + anim2.color = color_provider2 + anim2.priority = 0 + anim2.duration = 0 + anim2.loop = true + + # Create a parent sequence with: + # 1. A conditional subsequence that is FALSE (should skip immediately) + # 2. A play step for anim2 + + # Create the false conditional subsequence (simulating "if false { ... }") + var false_condition = def (engine) return false end + var false_subseq = animation.sequence_manager(engine, false_condition) + false_subseq.push_play_step(anim1, 1000) # This should never execute + + # Create the parent sequence + var parent_seq = animation.sequence_manager(engine, 1) # Run once + parent_seq.push_repeat_subsequence(false_subseq) # This should skip immediately + parent_seq.push_play_step(anim2, 500) # This should start immediately after the skip + + # Start the parent sequence + tasmota.set_millis(200000) + engine.add(parent_seq) + engine.run() + engine.on_tick(200000) + + # At this point, the false subsequence should have been skipped immediately, + # and anim2 should already be playing (step_index should be 1) + assert(parent_seq.is_running == true, "Parent sequence should be running") + assert(parent_seq.step_index == 1, f"Parent should have advanced past false conditional to step 1, got {parent_seq.step_index}") + + # Verify anim2 is in the engine (not anim1) + var animations = engine.get_animations() + var anim2_found = false + var anim1_found = false + for anim : animations + if anim == anim2 + anim2_found = true + end + if anim == anim1 + anim1_found = true + end + end + assert(anim2_found == true, "anim2 should be playing after false conditional skip") + assert(anim1_found == false, "anim1 should NOT be playing (false conditional was skipped)") + + # Test 2: Multiple consecutive false conditionals should all skip immediately + # Create fresh engine and animations + var strip2 = global.Leds(30) + var engine2 = animation.create_engine(strip2) + + var color_provider3 = animation.static_color(engine2) + color_provider3.color = 0xFFFF0000 # Red + var anim3 = animation.solid(engine2) + anim3.color = color_provider3 + anim3.priority = 0 + anim3.duration = 0 + anim3.loop = true + + var color_provider4 = animation.static_color(engine2) + color_provider4.color = 0xFF00FF00 # Green + var anim4 = animation.solid(engine2) + anim4.color = color_provider4 + anim4.priority = 0 + anim4.duration = 0 + anim4.loop = true + + var false_condition2 = def (engine) return false end + + var false_subseq2 = animation.sequence_manager(engine2, false_condition2) + false_subseq2.push_play_step(anim3, 1000) + + var false_subseq3 = animation.sequence_manager(engine2, false_condition2) + false_subseq3.push_play_step(anim3, 1000) + + var parent_seq2 = animation.sequence_manager(engine2, 1) + parent_seq2.push_repeat_subsequence(false_subseq2) # Skip + parent_seq2.push_repeat_subsequence(false_subseq3) # Skip + parent_seq2.push_play_step(anim4, 500) # Should start immediately + + engine2.add(parent_seq2) + + tasmota.set_millis(201000) + engine2.run() + engine2.on_tick(201000) + + # Should have skipped both false conditionals and be at step 2 + assert(parent_seq2.is_running == true, "Parent sequence 2 should be running") + assert(parent_seq2.step_index == 2, f"Parent should have advanced past both false conditionals to step 2, got {parent_seq2.step_index}") + + print("āœ“ False conditional immediate skip tests passed") +end + +def test_sequence_manager_all_false_conditionals_no_infinite_loop() + print("=== SequenceManager All False Conditionals No Infinite Loop Tests ===") + + # This test verifies that when ALL conditional subsequences in a repeat-forever + # sequence are false, the sequence doesn't go into an infinite loop. + # Instead, it should yield control back after one pass through all steps. + + # Create strip and engine + var strip = global.Leds(30) + var engine = animation.create_engine(strip) + + # Create test animation (should never be used) + var color_provider = animation.static_color(engine) + color_provider.color = 0xFFFF0000 + var test_anim = animation.solid(engine) + test_anim.color = color_provider + test_anim.priority = 0 + test_anim.duration = 0 + test_anim.loop = true + + # Track how many times closures are executed + var closure_count = 0 + + # Create two false conditional subsequences (simulating "if inout" and "if outin" both false) + var false_condition = def (engine) return false end + + var false_subseq1 = animation.sequence_manager(engine, false_condition) + false_subseq1.push_play_step(test_anim, 1000) + + var false_subseq2 = animation.sequence_manager(engine, false_condition) + false_subseq2.push_play_step(test_anim, 1000) + + # Create parent sequence that repeats forever with both false conditionals + var parent_seq = animation.sequence_manager(engine, -1) # Repeat forever + parent_seq.push_closure_step(def (engine) closure_count += 1 end) # Track iterations + parent_seq.push_repeat_subsequence(false_subseq1) # if inout (false) + parent_seq.push_repeat_subsequence(false_subseq2) # if outin (false) + + # Start the sequence + tasmota.set_millis(300000) + engine.add(parent_seq) + engine.run() + engine.on_tick(300000) + + # The sequence should be running but not in an infinite loop + assert(parent_seq.is_running == true, "Parent sequence should still be running") + + # The closure should have been executed a limited number of times (not infinite) + # With skip_budget, it should execute at most a few times before yielding + assert(closure_count < 100, f"Closure should not execute infinitely, got {closure_count}") + + # Simulate a few update cycles - should not hang + var update_count = 0 + var max_updates = 10 + while update_count < max_updates + tasmota.set_millis(300000 + update_count * 100) + engine.on_tick(300000 + update_count * 100) + parent_seq.update(300000 + update_count * 100) + update_count += 1 + end + + # Should still be running (repeat forever) but not have executed infinitely + assert(parent_seq.is_running == true, "Parent sequence should still be running after updates") + assert(closure_count < 1000, f"Closure count should be bounded, got {closure_count}") + + print("āœ“ All false conditionals no infinite loop tests passed") +end + # Run all tests def run_all_sequence_manager_tests() print("Starting SequenceManager Unit Tests...") @@ -943,6 +1124,8 @@ def run_all_sequence_manager_tests() test_sequence_manager_zero_iterations() test_sequence_manager_zero_palette_size() test_sequence_manager_boolean_repeat_counts() + test_sequence_manager_false_conditional_immediate_skip() + test_sequence_manager_all_false_conditionals_no_infinite_loop() print("\nšŸŽ‰ All SequenceManager tests passed!") return true @@ -970,5 +1153,7 @@ return { "test_sequence_manager_complex_parametric_scenario": test_sequence_manager_complex_parametric_scenario, "test_sequence_manager_zero_iterations": test_sequence_manager_zero_iterations, "test_sequence_manager_zero_palette_size": test_sequence_manager_zero_palette_size, - "test_sequence_manager_boolean_repeat_counts": test_sequence_manager_boolean_repeat_counts + "test_sequence_manager_boolean_repeat_counts": test_sequence_manager_boolean_repeat_counts, + "test_sequence_manager_false_conditional_immediate_skip": test_sequence_manager_false_conditional_immediate_skip, + "test_sequence_manager_all_false_conditionals_no_infinite_loop": test_sequence_manager_all_false_conditionals_no_infinite_loop } \ No newline at end of file