private void _def_function(NakoNodeDefFunction node) { // 必要なラベルを定義 NakoILCode end_of_def_func = createLABEL("END_OF_DEF_FUNC_" + node.func.name); NakoILCode ret_of_def_func = createLABEL("RETURN_OF_DEF_FUNC_" + node.func.name); NakoILCode begin_def_func = createLABEL("FUNC_" + node.func.name); node.defLabel = begin_def_func; // 関数の定義は実行しないので、end_of_def_func へ飛ぶ result.Add(createJUMP(end_of_def_func)); // 関数の始まりラベルを定義 result.Add(begin_def_func); // 引数をPOPする処理 NakoFunc func = node.func; for (int i = 0; i < func.ArgCount; i++) { NakoFuncArg arg = func.args[i]; NakoILCode c = new NakoILCode(NakoILType.ST_LOCAL, i); result.Add(c); } // 本文を定義 _func_check_return(node.funcBody, ret_of_def_func); Write_r(node.funcBody); // 戻り値(変数「それ」)をスタックに載せる result.Add(ret_of_def_func); result.Add(new NakoILCode(NakoILType.LD_GLOBAL, (int)0)); result.Add(new NakoILCode(NakoILType.RET, func.updateSore)); // 関数の終わりを定義 result.Add(end_of_def_func); }
/// <summary> /// ラベルを解決する /// </summary> public void FixLabel() { // 現在のラベル位置を調べる for (int i = 0; i < result.Count; i++) { NakoILCode code = result[i]; if (code.type != NakoILType.NOP) { continue; } if (labels.ContainsKey(code)) { labels[code] = i; } } // JUMP/BRANCH_TRUE/BRANCH_FALSE/CALL/USRCALL を解決する for (int i = 0; i < result.Count; i++) { NakoILCode code = result[i]; switch (code.type) { case NakoILType.JUMP: case NakoILType.BRANCH_TRUE: case NakoILType.BRANCH_FALSE: case NakoILType.USRCALL: break; default: continue; } if (code.type == NakoILType.USRCALL && code.value is NakoNodeDefFunction) { //一旦ラベルを設定出来なかったユーザー関数呼び出しコードには定義のオブジェクトそのものを入れたので、ラベルを張り替える NakoNodeDefFunction def = (NakoNodeDefFunction)code.value; code.value = def.defLabel; } if (!(code.value is NakoILCode)) { continue; } if (code.value is NakoILCode) { if (labels.ContainsKey((NakoILCode)code.value)) { code.value = (object)labels[(NakoILCode)code.value]; continue; } throw new NakoILWriterException("ラベルが解決できません"); } } }
//> _def_function : DEF_FUNCTION _def_function_args _scope //> ; private bool _def_function() { if (!Accept(NakoTokenType.DEF_FUNCTION)) { return(false); } NakoToken t = tok.CurrentToken; tok.MoveNext(); // '*' NakoFunc userFunc = new NakoFunc(); userFunc.funcType = NakoFuncType.UserCall; // 引数 + 関数名の取得 _def_function_args(userFunc); // ブロックの取得 PushFrame(); NakoNodeDefFunction funcNode = new NakoNodeDefFunction(); funcNode.func = userFunc; parentNode = funcNode.funcBody = new NakoNode(); funcNode.RegistArgsToLocalVar(); localVar = funcNode.localVar; if (!_scope()) { throw new NakoParserException("関数定義中のエラー。", t); } PopFrame(); // グローバル変数に登録 NakoVariable v = new NakoVariable(); v.SetBody(funcNode, NakoVarType.UserFunc); globalVar.CreateVar(userFunc.name, v); // 関数の宣言は、ノードのトップ直下に追加する if (!this.topNode.hasChildren()) { this.topNode.AddChild(new NakoNode()); } this.topNode.Children.Insert(0, funcNode); return(true); }
//> _def_function : DEF_FUNCTION _def_function_args _scope //> ; private bool _def_function() { if (!Accept(NakoTokenType.DEF_FUNCTION)) return false; NakoToken t = tok.CurrentToken; tok.MoveNext(); // '*' NakoFunc userFunc = new NakoFunc(); userFunc.funcType = NakoFuncType.UserCall; // 引数 + 関数名の取得 _def_function_args(userFunc); // ブロックの取得 PushFrame(); NakoNodeDefFunction funcNode = new NakoNodeDefFunction(); funcNode.func = userFunc; parentNode = funcNode.funcBody = new NakoNode(); funcNode.RegistArgsToLocalVar(); localVar = funcNode.localVar; if (!_scope()) { throw new NakoParserException("関数定義中のエラー。", t); } PopFrame(); // グローバル変数に登録 NakoVariable v = new NakoVariable(); v.SetBody(funcNode, NakoVarType.UserFunc); globalVar.CreateVar(userFunc.name, v); // 関数の宣言は、ノードのトップ直下に追加する if (!this.topNode.hasChildren()) { this.topNode.AddChild(new NakoNode()); } this.topNode.Children.Insert(0, funcNode); return true; }
//> _callfunc : FUNCTION_NAME //> | FUNCTION_NAME _arglist //> ; private bool _callfunc() { NakoToken t = tok.CurrentToken; if (!Accept(NakoTokenType.FUNCTION_NAME)) { return(false); } tok.MoveNext(); // skip FUNCTION_NAME string fname = t.GetValueAsName(); NakoVariable var = globalVar.GetVar(fname); if (var == null) { throw new NakoParserException("関数『" + fname + "』が見あたりません。", t); } // NakoNodeCallFunction callNode = new NakoNodeCallFunction(); NakoFunc func = null; callNode.Token = t; if (var.Type == NakoVarType.SystemFunc) { int funcNo = (int)var.Body; func = NakoAPIFuncBank.Instance.FuncList[funcNo]; callNode.func = func; } else { NakoNodeDefFunction defNode = (NakoNodeDefFunction)var.Body; func = callNode.func = defNode.func; callNode.value = defNode; } // --------------------------------- if (Accept(NakoTokenType.PARENTHESES_L)) { _arglist(callNode); // TODO ここで引数の数をチェックする処理 } // 引数の数だけノードを取得 for (int i = 0; i < func.ArgCount; i++) { NakoFuncArg arg = func.args[func.ArgCount - i - 1]; NakoNode argNode; if (arg.defaultValue != null && calcStack.Count < (func.ArgCount - i)) //初期値があって引数が無い場合に引数に初期値を与える { argNode = new NakoNodeConst(); argNode.value = arg.defaultValue; if (arg.defaultValue is int) { argNode.type = NakoNodeType.INT; argNode.Token = new NakoToken(NakoTokenType.INT); } else if (arg.defaultValue is string) { argNode.type = NakoNodeType.STRING; argNode.Token = new NakoToken(NakoTokenType.STRING); } } else { argNode = calcStack.Pop(arg); } if (arg.varBy == VarByType.ByRef) { if (argNode.type == NakoNodeType.LD_VARIABLE) { ((NakoNodeVariable)argNode).varBy = VarByType.ByRef; } } callNode.AddChild(argNode); } // --------------------------------- // 計算スタックに関数の呼び出しを追加 calcStack.Push(callNode); this.lastNode = callNode; return(true); }