public static CalledFunction CallFunction(Process parent, string label, LogicalLine retAddress) { CalledFunction called = new CalledFunction(label); called.Finished = false; FunctionLabelLine labelline = parent.LabelDictionary.GetNonEventLabel(label); if (labelline == null) { if (parent.LabelDictionary.GetEventLabels(label) != null) { throw new CodeEE("イベント関数@" + label + "に対し通常のCALLが行われました(このエラーは互換性オプション「" + Config.GetConfigName(ConfigCode.CompatiCallEvent) + "」により無視できます)"); } return(null); } else if (labelline.IsMethod) { throw new CodeEE("#FUCNTION(S)が定義された関数@" + labelline.LabelName + "(" + labelline.Position.Filename + ":" + labelline.Position.LineNo.ToString() + "行目)に対し通常のCALLが行われました"); } called.TopLabel = labelline; called.CurrentLabel = labelline; called.returnAddress = retAddress; called.IsEvent = false; return(called); }
public FunctionLabelLine GetNonEventLabel(string key) { FunctionLabelLine ret = null; noneventLabelDic.TryGetValue(key, out ret); return(ret); }
public static CalledFunction CreateCalledFunctionMethod(FunctionLabelLine labelline, string label) { var called = new CalledFunction(label); called.TopLabel = labelline; called.CurrentLabel = labelline; called.ReturnAddress = null; called.IsEvent = false; return(called); }
public GotoLabelLine GetLabelDollar(string key, FunctionLabelLine labelAtLine) { foreach (GotoLabelLine label in labelDollarList) { if ((label.LabelName == key) && (label.ParentLabelLine == labelAtLine)) { return(label); } } return(null); }
public void AddLabel(FunctionLabelLine point) { point.Index = count; point.FileIndex = currentFileCount; count++; string id = point.LabelName; List <FunctionLabelLine> function_label_line_list = null; if (!labelAtDic.TryGetValue(id, out function_label_line_list)) { function_label_line_list = new List <FunctionLabelLine>(); labelAtDic.Add(id, function_label_line_list); } function_label_line_list.Add(point); }
public void AddLabel(FunctionLabelLine point) { point.Index = count; point.FileIndex = currentFileCount; count++; string id = point.LabelName; if (labelAtDic.ContainsKey(id)) { labelAtDic[id].Add(point); } else { List <FunctionLabelLine> labelList = new List <FunctionLabelLine>(); labelList.Add(point); labelAtDic.Add(id, labelList); } }
public FunctionLabelLine GetSameNameLabel(FunctionLabelLine point) { string id = point.LabelName; if (!labelAtDic.ContainsKey(id)) { return(null); } if (point.IsError) { return(null); } List <FunctionLabelLine> labelList = labelAtDic[id]; if (labelList.Count <= 1) { return(null); } return(labelList[0]); }
public static CalledFunction CallEventFunction(Process parent, string label, LogicalLine retAddress) { CalledFunction called = new CalledFunction(label); List <FunctionLabelLine> newLabelList = new List <FunctionLabelLine>(); called.Finished = false; called.eventLabelList = parent.LabelDictionary.GetEventLabels(label); if (called.eventLabelList == null) { FunctionLabelLine line = parent.LabelDictionary.GetNonEventLabel(label); if (parent.LabelDictionary.GetNonEventLabel(label) != null) { throw new CodeEE("イベント関数でない関数@" + label + "(" + line.Position.Filename + ":" + line.Position.LineNo + "行目)に対しEVENT呼び出しが行われました"); } return(null); } called.counter = -1; called.group = 0; called.ShiftNext(); called.TopLabel = called.CurrentLabel; called.returnAddress = retAddress; called.IsEvent = true; return(called); }
public static LogicalLine ParseLabelLine(StringStream stream, ScriptPosition position, EmueraConsole console) { var isFunction = stream.Current == '@'; var lineNo = position.LineNo; var labelName = ""; var errMes = ""; try { var warnLevel = -1; stream.ShiftNext(); //@か$を除去 var wc = LexicalAnalyzer.Analyse(stream, LexEndWith.EoL, LexAnalyzeFlag.AllowAssignment); if (wc.EOL || !(wc.Current is IdentifierWord)) { errMes = "関数名が不正であるか存在しません"; goto err; } labelName = ((IdentifierWord)wc.Current).Code; wc.ShiftNext(); if (Config.ICVariable) { labelName = labelName.ToUpper(); } GlobalStatic.IdentifierDictionary.CheckUserLabelName(ref errMes, ref warnLevel, isFunction, labelName); if (warnLevel >= 0) { if (warnLevel >= 2) { goto err; } ParserMediator.Warn(errMes, position, warnLevel); } if (!isFunction) //$ならこの時点で終了 { if (!wc.EOL) { ParserMediator.Warn("$で始まるラベルに引数が設定されています", position, 1); } return(new GotoLabelLine(position, labelName)); } //labelName = LexicalAnalyzer.ReadString(stream, StrEndWith.LeftParenthesis_Bracket_Comma_Semicolon); //labelName = labelName.Trim(); //if (Config.ICVariable) // labelName = labelName.ToUpper(); //GlobalStatic.IdentifierDictionary.CheckUserLabelName(ref errMes, ref warnLevel, isFunction, labelName); //if(warnLevel >= 0) //{ // if (warnLevel >= 2) // goto err; // ParserMediator.Warn(errMes, position, warnLevel); //} //if (!isFunction)//$ならこの時点で終了 //{ // LexicalAnalyzer.SkipWhiteSpace(stream); // if (!stream.EOS) // ParserMediator.Warn("$で始まるラベルに引数が設定されています", position, 1); // return new GotoLabelLine(position, labelName); //} ////関数名部分に_renameを使えないように変更 //if (ParserMediator.RenameDic != null && ((stream.ToString().IndexOf("[[") >= 0) && (stream.ToString().IndexOf("]]") >= 0))) //{ // string line = stream.ToString(); // foreach (KeyValuePair<string, string> pair in ParserMediator.RenameDic) // line = line.Replace(pair.Key, pair.Value); // stream = new StringStream(line); //} //WordCollection wc = null; //wc = LexicalAnalyzer.Analyse(stream, LexEndWith.EoL, LexAnalyzeFlag.AllowAssignment); if (Program.AnalysisMode) { console.PrintC("@" + labelName, false); } var funclabelLine = new FunctionLabelLine(position, labelName, wc); if (IdentifierDictionary.IsEventLabelName(labelName)) { funclabelLine.IsEvent = true; funclabelLine.IsSystem = true; funclabelLine.Depth = 0; } else if (IdentifierDictionary.IsSystemLabelName(labelName)) { funclabelLine.IsSystem = true; funclabelLine.Depth = 0; } return(funclabelLine); } catch (CodeEE e) { errMes = e.Message; } err: SystemSounds.Hand.Play(); if (isFunction) { if (labelName.Length == 0) { labelName = "<Error>"; } return(new InvalidLabelLine(position, labelName, errMes)); } return(new InvalidLine(position, errMes)); }
public static bool ParseSharpLine(FunctionLabelLine label, StringStream st, ScriptPosition position, List <string> OnlyLabel) { st.ShiftNext(); //'#'を飛ばす var token = LexicalAnalyzer.ReadSingleIdentifier(st); //#~自体にはマクロ非適用 if (Config.ICFunction) { token = token.ToUpper(); } //#行として不正な行でもAnalyzeに行って引っかかることがあるので、先に存在しない#~は弾いてしまう if (token == null || token != "SINGLE" && token != "LATER" && token != "PRI" && token != "ONLY" && token != "FUNCTION" && token != "FUNCTIONS" && token != "LOCALSIZE" && token != "LOCALSSIZE" && token != "DIM" && token != "DIMS") { ParserMediator.Warn("解釈できない#行です", position, 1); return(false); } try { var wc = LexicalAnalyzer.Analyse(st, LexEndWith.EoL, LexAnalyzeFlag.AllowAssignment); switch (token) { case "SINGLE": if (label.IsMethod) { ParserMediator.Warn("式中関数では#SINGLEは機能しません", position, 1); break; } else if (!label.IsEvent) { ParserMediator.Warn("イベント関数以外では#SINGLEは機能しません", position, 1); break; } else if (label.IsSingle) { ParserMediator.Warn("#SINGLEが重複して使われています", position, 1); break; } else if (label.IsOnly) { ParserMediator.Warn("#ONLYが指定されたイベント関数では#SINGLEは機能しません", position, 1); break; } label.IsSingle = true; break; case "LATER": if (label.IsMethod) { ParserMediator.Warn("式中関数では#LATERは機能しません", position, 1); break; } else if (!label.IsEvent) { ParserMediator.Warn("イベント関数以外では#LATERは機能しません", position, 1); break; } else if (label.IsLater) { ParserMediator.Warn("#LATERが重複して使われています", position, 1); break; } else if (label.IsOnly) { ParserMediator.Warn("#ONLYが指定されたイベント関数では#LATERは機能しません", position, 1); break; } else if (label.IsPri) { ParserMediator.Warn("#PRIと#LATERが重複して使われています(この関数は2度呼ばれます)", position, 1); } label.IsLater = true; break; case "PRI": if (label.IsMethod) { ParserMediator.Warn("式中関数では#PRIは機能しません", position, 1); break; } else if (!label.IsEvent) { ParserMediator.Warn("イベント関数以外では#PRIは機能しません", position, 1); break; } else if (label.IsPri) { ParserMediator.Warn("#PRIが重複して使われています", position, 1); break; } else if (label.IsOnly) { ParserMediator.Warn("#ONLYが指定されたイベント関数では#PRIは機能しません", position, 1); break; } else if (label.IsLater) { ParserMediator.Warn("#PRIと#LATERが重複して使われています(この関数は2度呼ばれます)", position, 1); } label.IsPri = true; break; case "ONLY": if (label.IsMethod) { ParserMediator.Warn("式中関数では#ONLYは機能しません", position, 1); break; } else if (!label.IsEvent) { ParserMediator.Warn("イベント関数以外では#ONLYは機能しません", position, 1); break; } else if (label.IsOnly) { ParserMediator.Warn("#ONLYが重複して使われています", position, 1); break; } else if (OnlyLabel.Contains(label.LabelName)) { ParserMediator.Warn("このイベント関数\"@" + label.LabelName + "\"にはすでに#ONLYが宣言されています(この関数は実行されません)", position, 1); } OnlyLabel.Add(label.LabelName); label.IsOnly = true; if (label.IsPri) { ParserMediator.Warn("このイベント関数には#PRIが宣言されていますが無視されます", position, 1); label.IsPri = false; } if (label.IsLater) { ParserMediator.Warn("このイベント関数には#LATERが宣言されていますが無視されます", position, 1); label.IsLater = false; } if (label.IsSingle) { ParserMediator.Warn("このイベント関数には#SINGLEが宣言されていますが無視されます", position, 1); label.IsSingle = false; } break; case "FUNCTION": case "FUNCTIONS": if (!string.IsNullOrEmpty(label.LabelName) && char.IsDigit(label.LabelName[0])) { ParserMediator.Warn("#" + token + "属性は関数名が数字で始まる関数には指定できません", position, 1); label.IsError = true; label.ErrMes = "関数名が数字で始まっています"; break; } if (label.IsMethod) { if (label.MethodType == typeof(long) && token == "FUNCTION" || label.MethodType == typeof(string) && token == "FUNCTIONS") { ParserMediator.Warn("関数" + label.LabelName + "にはすでに#" + token + "が宣言されています(この行は無視されます)", position, 1); return(false); } if (label.MethodType == typeof(long) && token == "FUNCTIONS") { ParserMediator.Warn("関数" + label.LabelName + "にはすでに#FUNCTIONが宣言されています", position, 2); } else if (label.MethodType == typeof(string) && token == "FUNCTION") { ParserMediator.Warn("関数" + label.LabelName + "にはすでに#FUNCTIONSが宣言されています", position, 2); } return(false); } if (label.Depth == 0) { ParserMediator.Warn("システム関数に#" + token + "が指定されています", position, 2); return(false); } label.IsMethod = true; label.Depth = 0; if (token == "FUNCTIONS") { label.MethodType = typeof(string); } else { label.MethodType = typeof(long); } if (label.IsPri) { ParserMediator.Warn("式中関数では#PRIは機能しません", position, 1); label.IsPri = false; } if (label.IsLater) { ParserMediator.Warn("式中関数では#LATERは機能しません", position, 1); label.IsLater = false; } if (label.IsSingle) { ParserMediator.Warn("式中関数では#SINGLEは機能しません", position, 1); label.IsSingle = false; } if (label.IsOnly) { ParserMediator.Warn("式中関数では#ONLYは機能しません", position, 1); label.IsOnly = false; } break; case "LOCALSIZE": case "LOCALSSIZE": { if (wc.EOL) { ParserMediator.Warn("#" + token + "の後に有効な数値が指定されていません", position, 2); break; } //イベント関数では指定しても無視される if (label.IsEvent) { ParserMediator.Warn( "イベント関数では#" + token + "による" + token.Substring(0, token.Length - 4) + "のサイズ指定は無視されます", position, 1); break; } var arg = ExpressionParser.ReduceIntegerTerm(wc, TermEndWith.EoL); var sizeTerm = arg.Restructure(null) as SingleTerm; if (sizeTerm == null || sizeTerm.GetOperandType() != typeof(long)) { ParserMediator.Warn("#" + token + "の後に有効な定数式が指定されていません", position, 2); break; } if (sizeTerm.Int <= 0) { ParserMediator.Warn("#" + token + "に0以下の値(" + sizeTerm.Int + ")が与えられました。設定は無視されます", position, 1); break; } if (sizeTerm.Int >= int.MaxValue) { ParserMediator.Warn("#" + token + "に大きすぎる値(" + sizeTerm.Int + ")が与えられました。設定は無視されます", position, 1); break; } var size = (int)sizeTerm.Int; if (token == "LOCALSIZE") { if (GlobalStatic.IdentifierDictionary.getLocalIsForbid("LOCAL")) { ParserMediator.Warn("#" + token + "が指定されていますが変数LOCALは使用禁止されています", position, 2); break; } if (label.LocalLength > 0) { ParserMediator.Warn("この関数にはすでに#LOCALSIZEが定義されています。(以前の定義は無視されます)", position, 1); } label.LocalLength = size; } else { if (GlobalStatic.IdentifierDictionary.getLocalIsForbid("LOCALS")) { ParserMediator.Warn("#" + token + "が指定されていますが変数LOCALSは使用禁止されています", position, 2); break; } if (label.LocalsLength > 0) { ParserMediator.Warn("この関数にはすでに#LOCALSSIZEが定義されています。(以前の定義は無視されます)", position, 1); } label.LocalsLength = size; } } break; case "DIM": case "DIMS": { var data = UserDefinedVariableData.Create(wc, token == "DIMS", true, position); if (!label.AddPrivateVariable(data)) { ParserMediator.Warn("変数名" + data.Name + "は既に使用されています", position, 2); return(false); } break; } default: ParserMediator.Warn("解釈できない#行です", position, 1); break; } if (!wc.EOL) { ParserMediator.Warn("#の識別子の後に余分な文字があります", position, 1); } } catch (Exception e) { ParserMediator.Warn(e.Message, position, 2); goto err; } return(true); err: return(false); }
internal void AddInvalidLabel(FunctionLabelLine invalidLabelLine) { invalidList.Add(invalidLabelLine); }
public void IntoFunction(CalledFunction call, UserDefinedFunctionArgument srcArgs, ExpressionMediator exm) { if (call.IsEvent) { foreach (CalledFunction called in functionList) { if (called.IsEvent) { throw new CodeEE("EVENT関数の解決前にCALLEVENT命令が行われました"); } } } if (Program.DebugMode) { FunctionLabelLine label = call.CurrentLabel; if (call.IsJump) { console.DebugAddTraceLog("JUMP :@" + label.LabelName + ":" + label.Position.ToString() + "行目"); } else { console.DebugAddTraceLog("CALL :@" + label.LabelName + ":" + label.Position.ToString() + "行目"); } } if (srcArgs != null) { //引数の値を確定させる srcArgs.SetTransporter(exm); //プライベート変数更新 if (call.TopLabel.hasPrivDynamicVar) { call.TopLabel.In(); } //更新した変数へ引数を代入 for (int i = 0; i < call.TopLabel.Arg.Length; i++) { if (srcArgs.Arguments[i] != null) { if (call.TopLabel.Arg[i].Identifier.IsReference) { ((ReferenceToken)(call.TopLabel.Arg[i].Identifier)).SetRef(srcArgs.TransporterRef[i]); } else if (srcArgs.Arguments[i].GetOperandType() == typeof(Int64)) { call.TopLabel.Arg[i].SetValue(srcArgs.TransporterInt[i], exm); } else { call.TopLabel.Arg[i].SetValue(srcArgs.TransporterStr[i], exm); } } } } else//こっちに来るのはシステムからの呼び出し=引数は存在しない関数のみ ifネストの外に出していい気もしないでもないがはてさて { //プライベート変数更新 if (call.TopLabel.hasPrivDynamicVar) { call.TopLabel.In(); } } functionList.Add(call); //sequential = false; currentLine = call.CurrentLabel; lineCount++; //ShfitNextLine(); }
public void Return(Int64 ret) { if (IsFunctionMethod) { ReturnF(null); return; } //sequential = false;//いずれにしろ順列ではない。 //呼び出し元は全部スクリプト処理 //if (functionList.Count == 0) //{ // throw new ExeEE("実行中の関数が存在しません"); //} CalledFunction called = functionList[functionList.Count - 1]; if (called.IsJump) { //JUMPした場合。即座にRETURN RESULTする。 if (called.TopLabel.hasPrivDynamicVar) { called.TopLabel.Out(); } functionList.Remove(called); if (Program.DebugMode) { console.DebugRemoveTraceLog(); } Return(ret); return; } if (!called.IsEvent) { if (called.TopLabel.hasPrivDynamicVar) { called.TopLabel.Out(); } currentLine = null; } else { if (called.CurrentLabel.hasPrivDynamicVar) { called.CurrentLabel.Out(); } //#Singleフラグ付き関数で1が返された。 //1752 非0ではなく1と等価であることを見るように修正 //1756 全てを終了ではなく#PRIや#LATERのグループごとに修正 if (called.IsOnly) { called.FinishEvent(); } else if ((called.HasSingleFlag) && (ret == 1)) { called.ShiftNextGroup(); } else { called.ShiftNext(); //次の同名関数に進む。 } currentLine = called.CurrentLabel; //関数の始点(@~~)へ移動。呼ぶべき関数が無ければnull if (called.CurrentLabel != null) { lineCount++; if (called.CurrentLabel.hasPrivDynamicVar) { called.CurrentLabel.In(); } } } if (Program.DebugMode) { console.DebugRemoveTraceLog(); } //関数終了 if (currentLine == null) { currentLine = called.ReturnAddress; functionList.RemoveAt(functionList.Count - 1); if (currentLine == null) { //この時点でfunctionListは空のはず //functionList.Clear();//全て終了。stateEndProcessに処理を返す if (begintype != BeginType.NULL) //BEGIN XXが行なわれていれば { Begin(); } return; } lineCount++; //ShfitNextLine(); return; } else if (Program.DebugMode) { FunctionLabelLine label = called.CurrentLabel; console.DebugAddTraceLog("CALL :@" + label.LabelName + ":" + label.Position.ToString() + "行目"); } lineCount++; //ShfitNextLine(); return; }
/// <summary> /// 1803beta005 予め引数の数を合わせて規定値を代入しておく /// 1806+v6.99 式中関数の引数に無効な#DIM変数を与えている場合に例外になるのを修正 /// 1808beta009 REF型に対応 /// </summary> public UserDefinedFunctionArgument ConvertArg(IOperandTerm[] srcArgs, out string errMes) { errMes = null; if (TopLabel.IsError) { errMes = TopLabel.ErrMes; return(null); } FunctionLabelLine func = TopLabel; IOperandTerm[] convertedArg = new IOperandTerm[func.Arg.Length]; if (convertedArg.Length < srcArgs.Length) { errMes = "引数の数が関数\"@" + func.LabelName + "\"に設定された数を超えています"; return(null); } IOperandTerm term = null; VariableTerm destArg = null; bool isString = false; for (int i = 0; i < func.Arg.Length; i++) { term = (i < srcArgs.Length) ? srcArgs[i] : null; destArg = func.Arg[i]; isString = destArg.IsString; if (destArg.Identifier.IsReference) //参照渡しの場合 { if (term == null) { errMes = "\"@" + func.LabelName + "\"の" + (i + 1).ToString() + "番目の引数は参照渡しのため省略できません"; return(null); } VariableTerm vTerm = term as VariableTerm; if (vTerm == null || vTerm.Identifier.Dimension == 0) { errMes = "\"@" + func.LabelName + "\"の" + (i + 1).ToString() + "番目の引数は参照渡しのための配列変数でなければなりません"; return(null); } //TODO 1810alpha007 キャラ型を認めるかどうかはっきりしたい 今のところ認めない方向 //型チェック if (!((ReferenceToken)destArg.Identifier).MatchType(vTerm.Identifier, false, out errMes)) { errMes = "\"@" + func.LabelName + "\"の" + (i + 1).ToString() + "番目の引数:" + errMes; return(null); } } else if (term == null) //引数が省略されたとき { term = func.Def[i]; //デフォルト値を代入 //1808beta001 デフォルト値がない場合はエラーにする //一応逃がす if (term == null && !Config.CompatiFuncArgOptional) { errMes = "\"@" + func.LabelName + "\"の" + (i + 1).ToString() + "番目の引数は省略できません(この警告は互換性オプション「" + Config.GetConfigName(ConfigCode.CompatiFuncArgOptional) + "」により無視できます)"; return(null); } } else if (term.GetOperandType() != destArg.GetOperandType()) { if (term.GetOperandType() == typeof(string)) { errMes = "\"@" + func.LabelName + "\"の" + (i + 1).ToString() + "番目の引数を文字列型から整数型に変換できません"; return(null); } else { if (!Config.CompatiFuncArgAutoConvert) { errMes = "\"@" + func.LabelName + "\"の" + (i + 1).ToString() + "番目の引数を整数型から文字列型に変換できません(この警告は互換性オプション「" + Config.GetConfigName(ConfigCode.CompatiFuncArgAutoConvert) + "」により無視できます)"; return(null); } if (tostrMethod == null) { tostrMethod = FunctionMethodCreator.GetMethodList()["TOSTR"]; } term = new FunctionMethodTerm(tostrMethod, new IOperandTerm[] { term }); } } convertedArg[i] = term; } return(new UserDefinedFunctionArgument(convertedArg, func.Arg)); }