public override void WriteBlock(Context context, Scope scope, TextWriter writer, TextWriter metaWriter,
                                        IStatement statement)
        {
            if (!(statement is FunctionStatement funcDefStt))
            {
                throw new InvalidOperationException();
            }

            var functionName = funcDefStt.Name;

            if (scope.IsIdentifierExists(functionName))
            {
                throw new IdentifierNameExistsCompilerException(functionName, funcDefStt.Info);
            }

            var        funcScope        = scope.BeginNewScope(ScopeType.MethodRoot);
            IStatement inlinedStatement = null;

            funcScope.SetConfig(c => c.ExplicitEchoStream, context.Flags.DefaultExplicitEchoStream);

            if (context.Flags.UseComments && context.Flags.CommentParameterInfos)
            {
                BashTranspilerHelpers.WriteComment(writer, $"! {funcDefStt.TypeDescriptor} {functionName}");
            }

            if (funcDefStt.Parameters != null && funcDefStt.Parameters.Length > 0)
            {
                for (var i = 0; i < funcDefStt.Parameters.Length; i++)
                {
                    var param           = funcDefStt.Parameters[i];
                    var paramMappedName = (i + 1).ToString(CultureInfo.InvariantCulture);
                    funcScope.ReserveNewParameter(param.TypeDescriptor, param.Name, paramMappedName);

                    if (context.Flags.UseComments && context.Flags.CommentParameterInfos)
                    {
                        BashTranspilerHelpers.WriteComment(writer,
                                                           $"\\param ${paramMappedName} {param.TypeDescriptor} - {param.Name}");
                    }
                }
            }

            writer.WriteLine($"function {functionName}() {{");

            BashBlockStatementTranspiler.WriteBlockStatement(context, funcScope, writer, metaWriter,
                                                             funcDefStt.Statement, ScopeType.MethodRoot, false, typeof(ReturnStatement));
            TryGetInlinedStatement(context, funcScope, funcDefStt, out inlinedStatement);


            var func = new FunctionInfo(funcDefStt.TypeDescriptor, functionName, null, null, funcDefStt.IsParams,
                                        funcDefStt.Parameters, inlinedStatement);

            scope.ReserveNewFunction(func);

            writer.WriteLine("}");

            scope.IncrementStatements();
        }
        public static void WriteIf(Context context, Scope scope, TextWriter writer, TextWriter nonInlinePartWriter,
                                   TextWriter metaWriter, IfElseStatement ifElseStatement)
        {
            var ifEscaped = false;
            var skipElse  = false;

            var condition =
                EvaluationStatementTranspilerBase.ProcessEvaluation(context, scope, ifElseStatement.MainIf.Condition);

            if (StatementHelpers.IsAbsoluteBooleanValue(condition, out var isTrue))
            {
                if (isTrue)
                {
                    BashBlockStatementTranspiler.WriteBlockStatement(context, scope, writer, metaWriter,
                                                                     ifElseStatement.MainIf.Statement, ScopeType.Block, true);

                    return;
                }

                ifEscaped = true;
            }
            else
            {
                writer.Write("if ");
                WriteCondition(context, scope, writer, metaWriter, nonInlinePartWriter, ifElseStatement, condition);
                writer.WriteLine();
                writer.WriteLine("then");
                BashBlockStatementTranspiler.WriteBlockStatement(context, scope, writer, metaWriter,
                                                                 ifElseStatement.MainIf.Statement, ScopeType.IfMainBlock, true);
            }

            if (ifElseStatement.ElseIfs != null)
            {
                foreach (var elseIf in ifElseStatement.ElseIfs)
                {
                    condition = EvaluationStatementTranspilerBase.ProcessEvaluation(context, scope, elseIf.Condition);

                    if (StatementHelpers.IsAbsoluteBooleanValue(condition, out isTrue))
                    {
                        if (isTrue)
                        {
                            if (!ifEscaped)
                            {
                                writer.WriteLine("else");
                            }

                            BashBlockStatementTranspiler.WriteBlockStatement(context, scope, writer, metaWriter,
                                                                             elseIf.Statement, ScopeType.IfElseBlock, true);

                            skipElse = true;
                            break;
                        }
                    }
                    else
                    {
                        if (ifEscaped)
                        {
                            writer.Write("if ");
                            ifEscaped = false;
                        }
                        else
                        {
                            writer.Write("elif ");
                        }

                        WriteCondition(context, scope, writer, metaWriter, nonInlinePartWriter, ifElseStatement,
                                       condition);
                        writer.WriteLine();
                        writer.WriteLine("then");
                        BashBlockStatementTranspiler.WriteBlockStatement(context, scope, writer, metaWriter,
                                                                         elseIf.Statement, ScopeType.IfIfElseBlock, true);
                    }
                }
            }

            if (!skipElse && ifElseStatement.Else != null)
            {
                if (ifEscaped)
                {
                    BashBlockStatementTranspiler.WriteBlockStatement(context, scope, writer, metaWriter,
                                                                     ifElseStatement.Else, ScopeType.IfMainBlock, true);
                }
                else
                {
                    writer.WriteLine("else");
                    BashBlockStatementTranspiler.WriteBlockStatement(context, scope, writer, metaWriter,
                                                                     ifElseStatement.Else, ScopeType.IfElseBlock, true);
                }
            }

            if (!ifEscaped)
            {
                writer.WriteLine("fi");

                scope.IncrementStatements();
            }
        }