非専門的シンギュラリティー研究所

無限に動き続けるシステムを表す方法を AI なども使って考えていきます。

自由モノイドのイテレーター(22)

自由モノイドプログラミング言語の作成(MonIter バージョン1.2 仕様(6))

構文要素に対応するクラス(Expression クラス:式(無限自由モノイド))

    /// <summary>
    /// 式(無限自由モノイド)を表すクラス:数値を表す項の無限個のリストで構成されます。
    /// </summary>
    internal class Expression : CodeGeneratable
    {
        /// <summary>
        /// 数値を表す項の無限個のリスト
        /// </summary>
        private readonly IEnumerable<Term> terms;
        public Expression(IEnumerable<Term> terms)
        {
            this.terms = terms;
        }
        /// <summary>
        /// 一つの項だけの式を作成します。(C# 形式のソースから変換するため追加)
        /// </summary>
        /// <param name="term">数値を表す項</param>
        /// <returns>一つの項だけの式</returns>
        public static Expression Unit(Term term)
        {
            return new Expression([term]);
        }
        /// <summary>
        /// 二つの式の積を作成します。(C# 形式のソースから変換するため追加)
        /// </summary>
        /// <param name="expression">二つ目の式</param>
        /// <returns>二つの式の積</returns>
        public Expression Concat(Expression expression)
        {
            return new Expression(terms.Concat(expression.terms));
        }
        /// <summary>
        /// 式を評価して無限自由モノイドの値を取得します。
        /// </summary>
        /// <param name="env">引数の値が記録されています。</param>
        /// <param name="prog">構文木の全体。関数の定義をここから取得します。</param>
        /// <returns>式の値(無限自由モノイド)</returns>
        public FreeMonoid<int> Eval(Env<FreeMonoidUnion> env, Prog prog)
        {
            IEnumerable<FreeMonoid<int>> monlist = terms.Select(e => e.Eval(env, prog));
            return FreeMonoid<int>.Collect(monlist);
        }
        /// <summary>
        /// 式を MonIter のコードの文字列に変換して取得します。
        /// </summary>
        /// <returns>MonIter のコードの文字列</returns>
        public string Print()
        {
            return string.Join(" & ", terms.Select(x => x.Print()));
        }
        /// <summary>
        /// 式を Python のコードの文字列に変換して取得します。
        /// </summary>
        /// <param name="yieldp">yield を表示するかどうか</param>
        /// <param name="typep">型名を表示するかどうか</param>
        /// <param name="indp">インデントを表示するかどうか</param>
        /// <param name="indcount">インデントの個数</param>
        /// <param name="perf">式のステートメントの文字列を変換する関数</param>
        /// <returns>Python のコードの文字列</returns>
        public string GeneratePython(bool yieldp, bool typep, bool indp, int indcount, Func<string, string> perf)
        {
            if (yieldp)
            {
                return Prog.ListGeneratePython(yieldp, typep, indp, indcount, perf, "", terms);
            }
            else
            {
                return Prog.ListGeneratePython(yieldp, typep, indp, indcount, perf, " & ", terms);
            }
        }
        /// <summary>
        /// 式を C# のコードの文字列に変換して取得します。
        /// </summary>
        /// <param name="yieldp">yield return を表示するかどうか</param>
        /// <param name="typep">型名を表示するかどうか</param>
        /// <param name="indp">インデントを表示するかどうか</param>
        /// <param name="indcount">インデントの個数</param>
        /// <param name="perf">式のステートメントの文字列を変換する関数</param>
        /// <returns>C# のコードの文字列</returns>
        public string GenerateCS(bool yieldp, bool typep, bool indp, int indcount, Func<string, string> perf)
        {
            if (yieldp)
            {
                return Prog.ListGenerateCS(yieldp, typep, indp, indcount, perf, "", terms);
            }
            else
            {
                return Prog.ListGenerateCS(yieldp, typep, indp, indcount, perf, " & ", terms);
            }
        }
    }