Exemplo n.º 1
0
        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);
        }
Exemplo n.º 2
0
        /// <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("ラベルが解決できません");
                }
            }
        }
Exemplo n.º 3
0
        //> _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);
        }
Exemplo n.º 4
0
        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);
        }
Exemplo n.º 5
0
        //> _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;
        }
Exemplo n.º 6
0
        //> _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);
        }