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 void WritePrologue(Context context, TextWriter writer)
        {
            //https://stackoverflow.com/questions/10376206/what-is-the-preferred-bash-shebang
            writer.WriteLine("#!/usr/bin/env bash");

            if (context.Flags.WriteShellScriptVersion)
            {
                writer.Write("#ShellScript v");
                writer.Write(ApplicationContext.Version);
                writer.Write(" - [");
                writer.Write(ApplicationContext.Url);
                writer.WriteLine("]");
            }

//            if (context.WriteAutoGeneratedCodeNotice)
//            {
//                writer.Write("#NOTICE: This file generated automatically with a transpiler tool, ");
//                writer.Write("use of this code requires you to accept the terms available at [");
//                writer.Write(ApplicationContext.Url);
//                writer.WriteLine("].");
//            }

            if (!string.IsNullOrWhiteSpace(context.Flags.Author))
            {
                writer.Write("Author: ");
                writer.WriteLine(context.Flags.Author);
            }

            if (!string.IsNullOrWhiteSpace(context.Flags.ContactInfo))
            {
                writer.Write("ContactInfo: ");
                writer.WriteLine(context.Flags.ContactInfo);
            }

            if (!string.IsNullOrWhiteSpace(context.Flags.WikiUrl))
            {
                writer.Write("Wiki: ");
                writer.WriteLine(context.Flags.WikiUrl);
            }

            if (context.Flags.UseSegments)
            {
                BashTranspilerHelpers.WriteSeparator(writer);
            }
        }
        public void WriteBlock(Context context, Scope scope, TextWriter writer, TextWriter metaWriter,
                               IStatement statement)
        {
            if (!(statement is DelegateStatement delegateStatement))
            {
                throw new InvalidOperationException();
            }

            scope.ReserveNewPrototype(
                new FunctionInfo(
                    delegateStatement.ReturnTypeDescriptor,
                    delegateStatement.Name,
                    null,
                    null,
                    false,
                    delegateStatement.Parameters,
                    null,
                    false)
                );

            BashTranspilerHelpers.WriteComment(writer, $"delegate {delegateStatement.ReturnTypeDescriptor} {delegateStatement.Name}");

            scope.IncrementStatements();
        }
 public void WriteSeparator(Context context, TextWriter writer)
 {
     BashTranspilerHelpers.WriteSeparator(writer);
 }
 public void WriteComment(Context context, TextWriter writer, string comment)
 {
     BashTranspilerHelpers.WriteComment(writer, comment);
 }