using System; using System.Collections.Generic; using NTERA.EmuEra.Game.EraEmu.GameData.Expression; using NTERA.EmuEra.Game.EraEmu.GameData.Variable; using NTERA.EmuEra.Game.EraEmu.GameProc.Function; using NTERA.EmuEra.Game.EraEmu.Sub; namespace NTERA.EmuEra.Game.EraEmu.GameProc { /// /// 命令文1行に相当する抽象クラス /// internal abstract class LogicalLine { protected ScriptPosition position; //LogicalLine prevLine; LogicalLine nextLine; public ScriptPosition Position => position; public FunctionLabelLine ParentLabelLine { get; set; } public LogicalLine NextLine { get => nextLine; set { nextLine = value; } } public override string ToString() { if (position == null) return base.ToString(); return string.Format("{0}:{1}:{2}", position.Filename, position.LineNo, position.RowLine); } protected bool isError; protected string errMes = ""; public virtual string ErrMes { get => errMes; set { errMes = value; } } public virtual bool IsError { get => isError; set { isError = value; } } } ///// ///// コメント行。 ///// //internal sealed class CommentLine : LogicalLine //{ // public CommentLine(ScriptPosition thePosition, string str) // { // base.position = thePosition; // //comment = str; // } // //string comment; // public override bool IsError // { // get { return false; } // } //} /// /// 無効な行。 /// internal sealed class InvalidLine : LogicalLine { public InvalidLine(ScriptPosition thePosition, string err) { position = thePosition; errMes = err; } public override bool IsError => true; } /// /// 命令文 /// internal sealed class InstructionLine : LogicalLine { public InstructionLine(ScriptPosition thePosition, FunctionIdentifier theFunc, StringStream theArgPrimitive) { position = thePosition; func = theFunc; argprimitive = theArgPrimitive; } public InstructionLine(ScriptPosition thePosition, FunctionIdentifier functionIdentifier, OperatorCode assignOP, WordCollection dest, StringStream theArgPrimitive) { position = thePosition; func = functionIdentifier; AssignOperator = assignOP; assigndest = dest; argprimitive = theArgPrimitive; } readonly FunctionIdentifier func; StringStream argprimitive; WordCollection assigndest; public OperatorCode AssignOperator { get; private set; } Int64 subData; public FunctionCode FunctionCode => func.Code; public FunctionIdentifier Function => func; public Argument Argument { get; set; } public StringStream PopArgumentPrimitive() { StringStream ret = argprimitive; argprimitive = null; return ret; } public WordCollection PopAssignmentDestStr() { WordCollection ret = assigndest; assigndest = null; return ret; } /// /// 繰り返しの終了を記憶する /// public Int64 LoopEnd { get => subData; set { subData = value; } } VariableTerm cnt; /// /// 繰り返しにつかう変数を記憶する /// public VariableTerm LoopCounter { get => cnt; set { cnt = value; } } Int64 step; /// /// 繰り返しのたびに増加する値を記憶する /// public Int64 LoopStep { get => step; set { step = value; } } private LogicalLine jumpto; private LogicalLine jumptoendcatch; //IF文とSELECT文のみが使う。 public List IfCaseList = null; //PRINTDATA文のみが使う。 public List> dataList = null; //TRYCALLLIST系が使う public List callList = null; public LogicalLine JumpTo { get => jumpto; set { jumpto = value; } } public LogicalLine JumpToEndCatch { get => jumptoendcatch; set { jumptoendcatch = value; } } } /// /// ファイルの始端と終端 /// internal sealed class NullLine : LogicalLine { } /// /// ラベルがエラーになっている関数行専用のクラス /// internal sealed class InvalidLabelLine : FunctionLabelLine { public InvalidLabelLine(ScriptPosition thePosition, string labelname, string err) { position = thePosition; LabelName = labelname != null ? String.Intern(labelname) : labelname; errMes = err; IsSingle = false; Index = -1; Depth = -1; IsMethod = false; MethodType = typeof(void); } public override bool IsError => true; } /// /// @で始まるラベル行 /// internal class FunctionLabelLine : LogicalLine, IComparable { protected FunctionLabelLine() { } public FunctionLabelLine(ScriptPosition thePosition, string labelname, WordCollection wc) { position = thePosition; LabelName = labelname != null ? String.Intern(labelname) : labelname; IsSingle = false; hasPrivDynamicVar = false; Index = -1; Depth = -1; LocalLength = 0; LocalsLength = 0; ArgLength = 0; ArgsLength = 0; IsMethod = false; MethodType = typeof(void); this.wc = wc; //ArgOptional = true; //ArgAutoConvert = true; } WordCollection wc; public WordCollection PopRowArgs() { WordCollection ret = wc; wc = null; return ret; } public string LabelName { get; protected set; } public bool IsEvent { get; set; } public bool IsSystem { get; set; } public bool IsSingle { get; set; } public bool IsPri { get; set; } public bool IsLater { get; set; } public bool IsOnly { get; set; } public bool hasPrivDynamicVar { get; set; } public int LocalLength { get; set; } public int LocalsLength { get; set; } public int ArgLength { get; set; } public int ArgsLength { get; set; } //public bool ArgOptional { get; set; } //public bool ArgAutoConvert { get; set; } public bool IsMethod { get; set; } public Type MethodType { get; set; } public VariableTerm[] Arg { get; set; } public SingleTerm[] Def { get; set; } //public SingleTerm[] SubNames { get; set; } public int Depth { get; set; } #region IComparable メンバ //ソート用情報 public int Index { get; set; } public int FileIndex { get; set; } public int CompareTo(FunctionLabelLine other) { if (FileIndex != other.FileIndex) return FileIndex.CompareTo(other.FileIndex); //position == nullであるLine(デバッグコマンドなど)をSortすることはないはず if (position.LineNo != other.position.LineNo) return position.LineNo.CompareTo(other.position.LineNo); return Index.CompareTo(other.Index); } #endregion #region private変数 Dictionary privateVar = new Dictionary(); internal bool AddPrivateVariable(UserDefinedVariableData data) { if (privateVar.ContainsKey(data.Name)) return false; UserDefinedVariableToken var = GlobalStatic.VariableData.CreatePrivateVariable(data); privateVar.Add(data.Name, var); //静的な変数のみの場合は関数呼び出し時に何もする必要がない if (!data.Static) hasPrivDynamicVar = true; return true; } internal UserDefinedVariableToken GetPrivateVariable(string key) { UserDefinedVariableToken var = null; privateVar.TryGetValue(key, out var); return var; } /// /// 引数の値の確定後、引数の代入より前に呼ぶこと /// internal void In() { #if DEBUG GlobalStatic.StackList.Add(this); #endif foreach (UserDefinedVariableToken var in privateVar.Values) if (!var.IsStatic) var.In(); } internal void Out() { #if DEBUG GlobalStatic.StackList.Remove(this); #endif foreach (UserDefinedVariableToken var in privateVar.Values) if (!var.IsStatic) var.Out(); } #endregion } /// /// $で始まるラベル行 /// internal sealed class GotoLabelLine : LogicalLine, IEqualityComparer { public GotoLabelLine(ScriptPosition thePosition, string labelname) { position = thePosition; this.labelname = String.Intern(labelname); } readonly string labelname = ""; public string LabelName => labelname; #region IEqualityComparer メンバ public bool Equals(GotoLabelLine x, GotoLabelLine y) { if ((x == null) || (y == null)) return false; return ((x.ParentLabelLine == y.ParentLabelLine) && (x.labelname == y.labelname)); } public int GetHashCode(GotoLabelLine obj) { return labelname.GetHashCode() ^ ParentLabelLine.GetHashCode(); } #endregion } }