/// <summary> /// 関数呼び出しの履歴をスクリプト形式で列挙します. /// </summary> /// <param name="useReturnValueAsArguments">呼び出しの引数がそれ以前の戻り値と一致する場合に,その戻り値が入った変数を引数として用いるかどうか</param> /// <param name="pauseSpan">前回の処理との間隔がこの値以上あいている場合に開始時刻がコメントとして表示される</param> /// <returns></returns> public string GetSerializedCallHistory(bool useReturnValueAsArguments, bool pickUpCommonArgument, TimeSpan pauseSpan) { ParameterizedHistories history = new ParameterizedHistories(this.EnumerateCallHistory(), new char[] { ' ', ' ', '/', '_' }); VariableReplaceMap pickUpReplaces = new VariableReplaceMap(); ICollection <string> usedVariableNames = new HashSet <string>(); if (useReturnValueAsArguments) { history.ReplaceByResult(ScriptVariableType.List | ScriptVariableType.String, "result", true, VariableNamedState.AllElementsNamed); } if (pickUpCommonArgument) { // 複数回発生した引数を変数に置き換える pickUpReplaces = history.GetDefaultReplacement(2, ScriptVariableType.List | ScriptVariableType.String, 32); history.ReplaceByName(pickUpReplaces, VariableNamedState.AllElementsNamed); } usedVariableNames = history.GetUsedVariableNames(); StringBuilder str = new StringBuilder(); if (pickUpReplaces.Count > 0) { // 複数回発生した引数を変数に置き換えたものの,変数の宣言 str.AppendLine("// Common Arguments"); VariableReplaceMap pickupDependencyResolved = new VariableReplaceMap(); foreach (var pair in from p in pickUpReplaces where usedVariableNames.Contains(p.Value) orderby p.Value select p) { pickupDependencyResolved.Add(pair); } foreach (var pair in pickupDependencyResolved.GetRecursivelyRenamedVariables(ScriptVariableType.List | ScriptVariableType.String)) { str.AppendLine(string.Format("var {0} = {1};", pair.Value, pair.Key.Serialize())); } str.AppendLine(); } // 関数呼び出しの出力 DateTime prev = DateTime.MinValue; int index = 0; foreach (var call in history.Enumerate()) { // 間があいたら実行日時をコメントとして出力 bool showDate = call.CreatedTime - prev >= pauseSpan; if (call.CreatedTime - prev >= pauseSpan) { str.AppendLine("// " + call.CreatedTime.ToString()); } string format = call.GetScriptExpression() + ";"; index++; if (useReturnValueAsArguments) { format = string.Format("var result{0} = {1}", index, format); } str.AppendLine(format); prev = call.CreatedTime; } return(str.ToString()); }
/// <summary> /// 標準的な引数の置き換えのディクショナリを返します /// </summary> /// <param name="minimumOccurance">置き換え対象とする変数の値の生起回数の条件</param> /// <param name="targetTypes">置き換えの対象とする変数の値の型</param> /// <param name="maxIdentifierLength">置き換える名前のプレフィックス部の最大長</param> /// <returns></returns> public VariableReplaceMap GetDefaultReplacement(int minimumOccurance, ScriptVariableType targetTypes, int maxIdentifierLength) { HashSet <ScriptVariable> replacement = new HashSet <ScriptVariable>(new VariableValueEqualityComparer()); bool replaced = true; while (replaced) { replaced = false; var none = this.GetOccuranceOfVariables(ScriptVariableType.List | targetTypes, VariableNamedState.AnyElementNamed, replacement); var sub = none.Where(p => p.Key.IsTypeOf(targetTypes) && p.Value >= minimumOccurance).ToList(); if (sub.Any()) { int maxOccur = sub.Max(p => p.Value); foreach (var pair in sub.Where(p => p.Value == maxOccur)) { if (replacement.Add(pair.Key)) { replaced = true; } } } } var one = this.GetOccuranceOfVariables(ScriptVariableType.List | targetTypes, VariableNamedState.AllElementsNamed, replacement); var subOne = one.Where(p => p.Key.IsTypeOf(targetTypes) && !p.Key.IsTypeOf(ScriptVariableType.List) && p.Value >= minimumOccurance).ToList(); foreach (var pair in subOne) { if (replacement.Add(pair.Key)) { replaced = true; } } VariableReplaceMap ret = new VariableReplaceMap(); foreach (ScriptVariable v in replacement) { string abbrev = Parse.ScriptParser.ConvertStringIntoIdentifier(v.ToString()); string identifier = abbrev; int index = 0; while (ret.ContainsValue(identifier) || _replacements.ContainsValue(identifier)) { index++; identifier = abbrev + index.ToString(); } ret.AddWithRename(v, identifier, maxIdentifierLength); } return(ret); }
private void replaceByResultAux(ScriptVariable resultElem, VariableReplaceMap map, string resultName, ScriptVariableType targetTypes) { if (resultElem != null && (resultElem.Type & targetTypes) != 0) { map[resultElem] = resultName; if (resultElem.Type == ScriptVariableType.List) { int index = 0; foreach (ScriptVariable elem in resultElem.ToList()) { replaceByResultAux(elem, map, string.Format("{0}[{1}]", resultName, index), targetTypes); index++; } } } }
private void setMap(ScriptVariable resultElem, VariableReplaceMap map, string resultName) { if (resultElem != null && (resultElem.Type == ScriptVariableType.List || resultElem.Type == ScriptVariableType.String)) { map[resultElem] = resultName; if (resultElem.Type == ScriptVariableType.List) { int index = 0; foreach (ScriptVariable elem in resultElem.ToList()) { setMap(elem, map, string.Format("{0}[{1}]", resultName, index)); index++; } } } }