-module(plushie@testing@command_processor). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/plushie/testing/command_processor.gleam"). -export([process_commands/4]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. ?MODULEDOC( " Synchronous command processor for test backends.\n" "\n" " Executes async, stream, done, and batch commands synchronously so that\n" " update side effects resolve immediately in tests. Widget ops, window\n" " ops, timers, and cancel are silently skipped (they need a renderer).\n" "\n" " Since execution is synchronous, await_async returns immediately --\n" " commands have already completed by the time it is called.\n" ). -file("src/plushie/testing/command_processor.gleam", 100). -spec batch_process( plushie@app:app(QPU, QPV), QPU, list(plushie@command:command(QPV)), integer(), integer(), list(plushie@event:event()) ) -> {QPU, list(plushie@event:event())}. batch_process(App, Model, Commands, Depth, Max_depth, Events) -> case Commands of [] -> {Model, Events}; [Cmd | Rest] -> {Model@1, Events@1} = do_process( App, Model, Cmd, Depth, Max_depth, Events ), batch_process(App, Model@1, Rest, Depth, Max_depth, Events@1) end. -file("src/plushie/testing/command_processor.gleam", 38). -spec do_process( plushie@app:app(QPN, QPO), QPN, plushie@command:command(QPO), integer(), integer(), list(plushie@event:event()) ) -> {QPN, list(plushie@event:event())}. do_process(App, Model, Cmd, Depth, Max_depth, Events) -> case Depth > Max_depth of true -> {Model, Events}; false -> case Cmd of none -> {Model, Events}; {batch, Commands} -> batch_process( App, Model, Commands, Depth, Max_depth, Events ); {done, Value, Mapper} -> Msg = Mapper(Value), Update_fn = plushie@app:get_update(App), {New_model, New_commands} = Update_fn(Model, Msg), do_process( App, New_model, New_commands, Depth + 1, Max_depth, Events ); {async, Work, Tag} -> Result = Work(), dispatch_async_result( App, Model, Tag, {ok, Result}, Depth, Max_depth, Events ); {stream, Work@1, Tag@1} -> Values = plushie_test_ffi:collect_stream_values(Work@1), {Model@1, Events@1} = drain_stream_values( App, Model, Tag@1, erlang:element(1, Values), Depth, Max_depth, Events ), dispatch_async_result( App, Model@1, Tag@1, {ok, erlang:element(2, Values)}, Depth, Max_depth, Events@1 ); _ -> {Model, Events} end end. -file("src/plushie/testing/command_processor.gleam", 25). ?DOC( " Process commands synchronously, threading model state through each\n" " update dispatch. Returns the final model and list of events processed.\n" "\n" " `max_depth` controls recursion depth: `None` uses the default limit,\n" " `Some(n)` uses n.\n" ). -spec process_commands( plushie@app:app(QPG, QPH), QPG, plushie@command:command(QPH), gleam@option:option(integer()) ) -> {QPG, list(plushie@event:event())}. process_commands(App, Model, Commands, Max_depth) -> Effective_max = case Max_depth of {some, N} -> N; none -> 100 end, do_process(App, Model, Commands, 0, Effective_max, []). -file("src/plushie/testing/command_processor.gleam", 118). -spec dispatch_async_result( plushie@app:app(QQC, any()), QQC, binary(), {ok, gleam@dynamic:dynamic_()} | {error, gleam@dynamic:dynamic_()}, integer(), integer(), list(plushie@event:event()) ) -> {QQC, list(plushie@event:event())}. dispatch_async_result(App, Model, Tag, Result, Depth, Max_depth, Events) -> Raw_event = {async_result, Tag, Result}, Events@1 = [Raw_event | Events], case plushie@app:get_on_event(App) of {some, On_event} -> Msg = On_event(Raw_event), Update_fn = plushie@app:get_update(App), {New_model, New_commands} = Update_fn(Model, Msg), do_process( App, New_model, New_commands, Depth + 1, Max_depth, Events@1 ); none -> Msg@1 = plushie_test_ffi:identity(Raw_event), Update_fn@1 = plushie@app:get_update(App), {New_model@1, New_commands@1} = Update_fn@1(Model, Msg@1), do_process( App, New_model@1, New_commands@1, Depth + 1, Max_depth, Events@1 ) end. -file("src/plushie/testing/command_processor.gleam", 145). -spec dispatch_stream_value( plushie@app:app(QQK, any()), QQK, binary(), gleam@dynamic:dynamic_(), integer(), integer(), list(plushie@event:event()) ) -> {QQK, list(plushie@event:event())}. dispatch_stream_value(App, Model, Tag, Value, Depth, Max_depth, Events) -> Raw_event = {stream_value, Tag, Value}, Events@1 = [Raw_event | Events], case plushie@app:get_on_event(App) of {some, On_event} -> Msg = On_event(Raw_event), Update_fn = plushie@app:get_update(App), {New_model, New_commands} = Update_fn(Model, Msg), do_process( App, New_model, New_commands, Depth + 1, Max_depth, Events@1 ); none -> Msg@1 = plushie_test_ffi:identity(Raw_event), Update_fn@1 = plushie@app:get_update(App), {New_model@1, New_commands@1} = Update_fn@1(Model, Msg@1), do_process( App, New_model@1, New_commands@1, Depth + 1, Max_depth, Events@1 ) end. -file("src/plushie/testing/command_processor.gleam", 172). -spec drain_stream_values( plushie@app:app(QQQ, any()), QQQ, binary(), list(gleam@dynamic:dynamic_()), integer(), integer(), list(plushie@event:event()) ) -> {QQQ, list(plushie@event:event())}. drain_stream_values(App, Model, Tag, Values, Depth, Max_depth, Events) -> case Values of [] -> {Model, Events}; [Value | Rest] -> {Model@1, Events@1} = dispatch_stream_value( App, Model, Tag, Value, Depth, Max_depth, Events ), drain_stream_values( App, Model@1, Tag, Rest, Depth, Max_depth, Events@1 ) end.