LogicalLine.cs 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. using System;
  2. using System.Collections.Generic;
  3. using MinorShift.Emuera.GameData.Expression;
  4. using MinorShift.Emuera.GameData.Variable;
  5. using MinorShift.Emuera.GameProc.Function;
  6. using MinorShift.Emuera.Sub;
  7. namespace MinorShift.Emuera.GameProc
  8. {
  9. /// <summary>
  10. /// 命令文1行に相当する抽象クラス
  11. /// </summary>
  12. internal abstract class LogicalLine
  13. {
  14. protected ScriptPosition position;
  15. //LogicalLine prevLine;
  16. LogicalLine nextLine;
  17. public ScriptPosition Position => position;
  18. public FunctionLabelLine ParentLabelLine { get; set; }
  19. public LogicalLine NextLine
  20. {
  21. get => nextLine;
  22. set { nextLine = value; }
  23. }
  24. public override string ToString()
  25. {
  26. if (position == null)
  27. return base.ToString();
  28. return string.Format("{0}:{1}:{2}", position.Filename, position.LineNo, position.RowLine);
  29. }
  30. protected bool isError;
  31. protected string errMes = "";
  32. public virtual string ErrMes
  33. {
  34. get => errMes;
  35. set { errMes = value; }
  36. }
  37. public virtual bool IsError
  38. {
  39. get => isError;
  40. set { isError = value; }
  41. }
  42. }
  43. ///// <summary>
  44. ///// コメント行。
  45. ///// </summary>
  46. //internal sealed class CommentLine : LogicalLine
  47. //{
  48. // public CommentLine(ScriptPosition thePosition, string str)
  49. // {
  50. // base.position = thePosition;
  51. // //comment = str;
  52. // }
  53. // //string comment;
  54. // public override bool IsError
  55. // {
  56. // get { return false; }
  57. // }
  58. //}
  59. /// <summary>
  60. /// 無効な行。
  61. /// </summary>
  62. internal sealed class InvalidLine : LogicalLine
  63. {
  64. public InvalidLine(ScriptPosition thePosition, string err)
  65. {
  66. position = thePosition;
  67. errMes = err;
  68. }
  69. public override bool IsError => true;
  70. }
  71. /// <summary>
  72. /// 命令文
  73. /// </summary>
  74. internal sealed class InstructionLine : LogicalLine
  75. {
  76. public InstructionLine(ScriptPosition thePosition, FunctionIdentifier theFunc, StringStream theArgPrimitive)
  77. {
  78. position = thePosition;
  79. func = theFunc;
  80. argprimitive = theArgPrimitive;
  81. }
  82. public InstructionLine(ScriptPosition thePosition, FunctionIdentifier functionIdentifier, OperatorCode assignOP, WordCollection dest, StringStream theArgPrimitive)
  83. {
  84. position = thePosition;
  85. func = functionIdentifier;
  86. AssignOperator = assignOP;
  87. assigndest = dest;
  88. argprimitive = theArgPrimitive;
  89. }
  90. readonly FunctionIdentifier func;
  91. StringStream argprimitive;
  92. WordCollection assigndest;
  93. public OperatorCode AssignOperator { get; private set; }
  94. Int64 subData;
  95. public FunctionCode FunctionCode => func.Code;
  96. public FunctionIdentifier Function => func;
  97. public Argument Argument { get; set; }
  98. public StringStream PopArgumentPrimitive()
  99. {
  100. StringStream ret = argprimitive;
  101. argprimitive = null;
  102. return ret;
  103. }
  104. public WordCollection PopAssignmentDestStr()
  105. {
  106. WordCollection ret = assigndest;
  107. assigndest = null;
  108. return ret;
  109. }
  110. /// <summary>
  111. /// 繰り返しの終了を記憶する
  112. /// </summary>
  113. public Int64 LoopEnd
  114. {
  115. get => subData;
  116. set { subData = value; }
  117. }
  118. VariableTerm cnt;
  119. /// <summary>
  120. /// 繰り返しにつかう変数を記憶する
  121. /// </summary>
  122. public VariableTerm LoopCounter
  123. {
  124. get => cnt;
  125. set { cnt = value; }
  126. }
  127. Int64 step;
  128. /// <summary>
  129. /// 繰り返しのたびに増加する値を記憶する
  130. /// </summary>
  131. public Int64 LoopStep
  132. {
  133. get => step;
  134. set { step = value; }
  135. }
  136. private LogicalLine jumpto;
  137. private LogicalLine jumptoendcatch;
  138. //IF文とSELECT文のみが使う。
  139. public List<InstructionLine> IfCaseList = null;
  140. //PRINTDATA文のみが使う。
  141. public List<List<InstructionLine>> dataList = null;
  142. //TRYCALLLIST系が使う
  143. public List<InstructionLine> callList = null;
  144. public LogicalLine JumpTo
  145. {
  146. get => jumpto;
  147. set { jumpto = value; }
  148. }
  149. public LogicalLine JumpToEndCatch
  150. {
  151. get => jumptoendcatch;
  152. set { jumptoendcatch = value; }
  153. }
  154. }
  155. /// <summary>
  156. /// ファイルの始端と終端
  157. /// </summary>
  158. internal sealed class NullLine : LogicalLine { }
  159. /// <summary>
  160. /// ラベルがエラーになっている関数行専用のクラス
  161. /// </summary>
  162. internal sealed class InvalidLabelLine : FunctionLabelLine
  163. {
  164. public InvalidLabelLine(ScriptPosition thePosition, string labelname, string err)
  165. {
  166. position = thePosition;
  167. LabelName = labelname != null ? String.Intern(labelname) : labelname;
  168. errMes = err;
  169. IsSingle = false;
  170. Index = -1;
  171. Depth = -1;
  172. IsMethod = false;
  173. MethodType = typeof(void);
  174. }
  175. public override bool IsError => true;
  176. }
  177. /// <summary>
  178. /// @で始まるラベル行
  179. /// </summary>
  180. internal class FunctionLabelLine : LogicalLine, IComparable<FunctionLabelLine>
  181. {
  182. protected FunctionLabelLine() { }
  183. public FunctionLabelLine(ScriptPosition thePosition, string labelname, WordCollection wc)
  184. {
  185. position = thePosition;
  186. LabelName = labelname != null ? String.Intern(labelname) : labelname;
  187. IsSingle = false;
  188. hasPrivDynamicVar = false;
  189. Index = -1;
  190. Depth = -1;
  191. LocalLength = 0;
  192. LocalsLength = 0;
  193. ArgLength = 0;
  194. ArgsLength = 0;
  195. IsMethod = false;
  196. MethodType = typeof(void);
  197. this.wc = wc;
  198. //ArgOptional = true;
  199. //ArgAutoConvert = true;
  200. }
  201. WordCollection wc;
  202. public WordCollection PopRowArgs()
  203. {
  204. WordCollection ret = wc;
  205. wc = null;
  206. return ret;
  207. }
  208. public string LabelName { get; protected set; }
  209. public bool IsEvent { get; set; }
  210. public bool IsSystem { get; set; }
  211. public bool IsSingle { get; set; }
  212. public bool IsPri { get; set; }
  213. public bool IsLater { get; set; }
  214. public bool IsOnly { get; set; }
  215. public bool hasPrivDynamicVar { get; set; }
  216. public int LocalLength { get; set; }
  217. public int LocalsLength { get; set; }
  218. public int ArgLength { get; set; }
  219. public int ArgsLength { get; set; }
  220. //public bool ArgOptional { get; set; }
  221. //public bool ArgAutoConvert { get; set; }
  222. public bool IsMethod { get; set; }
  223. public Type MethodType { get; set; }
  224. public VariableTerm[] Arg { get; set; }
  225. public SingleTerm[] Def { get; set; }
  226. //public SingleTerm[] SubNames { get; set; }
  227. public int Depth { get; set; }
  228. #region IComparable<FunctionLabelLine> メンバ
  229. //ソート用情報
  230. public int Index { get; set; }
  231. public int FileIndex { get; set; }
  232. public int CompareTo(FunctionLabelLine other)
  233. {
  234. if (FileIndex != other.FileIndex)
  235. return FileIndex.CompareTo(other.FileIndex);
  236. //position == nullであるLine(デバッグコマンドなど)をSortすることはないはず
  237. if (position.LineNo != other.position.LineNo)
  238. return position.LineNo.CompareTo(other.position.LineNo);
  239. return Index.CompareTo(other.Index);
  240. }
  241. #endregion
  242. #region private変数
  243. Dictionary<string, UserDefinedVariableToken> privateVar = new Dictionary<string, UserDefinedVariableToken>();
  244. internal bool AddPrivateVariable(UserDefinedVariableData data)
  245. {
  246. if (privateVar.ContainsKey(data.Name))
  247. return false;
  248. UserDefinedVariableToken var = GlobalStatic.VariableData.CreatePrivateVariable(data);
  249. privateVar.Add(data.Name, var);
  250. //静的な変数のみの場合は関数呼び出し時に何もする必要がない
  251. if (!data.Static)
  252. hasPrivDynamicVar = true;
  253. return true;
  254. }
  255. internal UserDefinedVariableToken GetPrivateVariable(string key)
  256. {
  257. UserDefinedVariableToken var = null;
  258. privateVar.TryGetValue(key, out var);
  259. return var;
  260. }
  261. /// <summary>
  262. /// 引数の値の確定後、引数の代入より前に呼ぶこと
  263. /// </summary>
  264. internal void In()
  265. {
  266. #if DEBUG
  267. GlobalStatic.StackList.Add(this);
  268. #endif
  269. foreach (UserDefinedVariableToken var in privateVar.Values)
  270. if (!var.IsStatic)
  271. var.In();
  272. }
  273. internal void Out()
  274. {
  275. #if DEBUG
  276. GlobalStatic.StackList.Remove(this);
  277. #endif
  278. foreach (UserDefinedVariableToken var in privateVar.Values)
  279. if (!var.IsStatic)
  280. var.Out();
  281. }
  282. #endregion
  283. }
  284. /// <summary>
  285. /// $で始まるラベル行
  286. /// </summary>
  287. internal sealed class GotoLabelLine : LogicalLine, IEqualityComparer<GotoLabelLine>
  288. {
  289. public GotoLabelLine(ScriptPosition thePosition, string labelname)
  290. {
  291. position = thePosition;
  292. this.labelname = String.Intern(labelname);
  293. }
  294. readonly string labelname = "";
  295. public string LabelName => labelname;
  296. #region IEqualityComparer<GotoLabelLine> メンバ
  297. public bool Equals(GotoLabelLine x, GotoLabelLine y)
  298. {
  299. if ((x == null) || (y == null))
  300. return false;
  301. return ((x.ParentLabelLine == y.ParentLabelLine) && (x.labelname == y.labelname));
  302. }
  303. public int GetHashCode(GotoLabelLine obj)
  304. {
  305. return labelname.GetHashCode() ^ ParentLabelLine.GetHashCode();
  306. }
  307. #endregion
  308. }
  309. }