/// <summary> /// 引数をローカル変数として定義する /// </summary> public void RegistArgsToLocalVar(NakoVariableManager globalVar) { for (int i = 0; i < func.args.Count; i++) { NakoFuncArg arg = func.args[i]; NakoPlugin.NakoVariable var = new NakoPlugin.NakoVariable(); if (arg.type != null) { //引数が関数定義の場合 if (arg.type == NakoFuncType.UserCall.ToString()) { NakoFunc userFunc = new NakoFunc(); userFunc.funcType = NakoFuncType.UserCall; for (int j = 0; j < (int)arg.defaultValue; j++) { userFunc.args.Add(new NakoFuncArg()); } NakoNodeDefFunction funcNode = new NakoNodeDefFunction(); funcNode.func = userFunc; funcNode.funcBody = new NakoNode(); var.SetBody(funcNode, NakoPlugin.NakoVarType.UserFunc); } else { //引数がインスタンスの場合 var.SetBody(null, NakoPlugin.NakoVarType.Instance); var.InstanceType = arg.type; } } localVar.CreateVar(arg.name, var); } }
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> /// 関数を追加 Use instance /// </summary> /// <param name="name"></param> /// <param name="argdef"></param> /// <param name="resultType"></param> /// <param name="f"></param> /// <param name="desc"></param> /// <param name="kana"></param> public void AddInstanceFunc(string name, string argdef, NakoVarType resultType, NakoPlugin.SysCallDelegate f, string desc, string kana) { name = NakoToken.TrimOkurigana(name); NakoAPIFunc s = new NakoAPIFunc(name, argdef, kana, NakoFunc.GetFullName(PluginInstance.Name, name), resultType, f); s.PluginInstance = PluginInstance; this.AddFuncToList(s); }
//> _def_function_args : empty //> | '(' { WORD } ')' FUNCTION_NAME //> | { WORD } FUNCTION_NAME //> | FUNCTION_NAME '(' { WORD } ')' //> ; private bool _def_function_args(NakoFunc func) { NakoToken firstT = tok.CurrentToken; NakoTokenList argTokens = new NakoTokenList(); bool argMode = false; NakoToken funcName = null; // 関数の引数宣言を取得する while (!tok.IsEOF()) { // '(' .. ')' の中は全部、関数の引数です if (argMode) { if (Accept(NakoTokenType.PARENTHESES_R)) { argMode = false; tok.MoveNext(); continue; } argTokens.Add(tok.CurrentToken); tok.MoveNext(); continue; } if (Accept(NakoTokenType.PARENTHESES_L)) { tok.MoveNext(); argMode = true; continue; } if (Accept(NakoTokenType.SCOPE_BEGIN)) { break; } if (Accept(NakoTokenType.FUNCTION_NAME)) { funcName = tok.CurrentToken; tok.MoveNext(); continue; } argTokens.Add(tok.CurrentToken); tok.MoveNext(); } if (funcName == null) { throw new NakoParserException("関数名がありません。", firstT); } func.name = funcName.GetValueAsName(); //TODO: check namespace and class name func.args.analizeArgTokens(argTokens); 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); }