-module(gwr@execution@stack). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([create/0, length/1, push/2, peek/1, pop/1, pop_repeat/2]). -export_type([stack/0, stack_entry/0, label/0, activation_frame/0, frame_state/0]). -type stack() :: {stack, list(stack_entry())}. -type stack_entry() :: {value_entry, gwr@execution@runtime:value()} | {label_entry, label()} | {activation_entry, activation_frame()}. -type label() :: {label, integer(), list(gwr@syntax@instruction:instruction())}. -type activation_frame() :: {activation_frame, integer(), frame_state()}. -type frame_state() :: {frame_state, list(gwr@execution@runtime:value()), gwr@execution@runtime:module_instance()}. -spec create() -> stack(). create() -> {stack, []}. -spec length(stack()) -> integer(). length(Stack) -> erlang:length(erlang:element(2, Stack)). -spec push(stack(), stack_entry()) -> stack(). push(Stack, New_entry) -> {stack, lists:append(erlang:element(2, Stack), [New_entry])}. -spec peek(stack()) -> gleam@option:option(stack_entry()). peek(Stack) -> gleam@option:from_result(gleam@list:last(erlang:element(2, Stack))). -spec pop(stack()) -> {stack(), gleam@option:option(stack_entry())}. pop(Stack) -> {{stack, gleam@list:take(erlang:element(2, Stack), length(Stack) - 1)}, peek(Stack)}. -spec pop_repeat(stack(), integer()) -> {stack(), list(gleam@option:option(stack_entry()))}. pop_repeat(Stack, Count) -> gleam@iterator:fold( gleam@iterator:range(1, Count), {Stack, []}, fun(State, _) -> {Stack@1, Results} = pop(erlang:element(1, State)), {Stack@1, lists:append(erlang:element(2, State), [Results])} end ).