private void _if(NakoNodeIf node) { int labelId = GetLableId(); // (1) 条件文をコードにする Write_r(node.nodeCond); // (2) コードの結果により分岐する // 分岐先をラベルとして作成 NakoILCode label_endif = createLABEL("ENDIF" + labelId.ToString()); NakoILCode label_else = createLABEL("ELSE" + labelId.ToString()); result.Add(new NakoILCode(NakoILType.BRANCH_FALSE, label_else)); // (3) TRUE if (node.nodeTrue != null) { Write_r(node.nodeTrue); result.Add(createJUMP(label_endif)); } // (4) FALSE result.Add(label_else); if (node.nodeFalse != null) { Write_r(node.nodeFalse); } result.Add(label_endif); }
/// <summary> /// Sets the exception tables. /// </summary> public void SetExceptionTables() { for (int i = 0; i < result.Count; i++) { NakoILCode code = result[i]; if (code.type != NakoILType.EXCEPTIONTABLE) { continue; } if (!(code.value is NakoException)) { continue; } if (code.value is NakoException) { NakoException e = (NakoException)code.value; if (labels.ContainsKey(e.fromLabel)) { e.from = (int)labels[e.fromLabel]; e.to = (int)labels[e.targetLabel] - 1; //endTry? e.target = (int)labels [e.targetLabel]; continue; } throw new NakoILWriterException("ExceptionTableが解決できません"); } } }
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); }
private void _call_function(NakoNodeCallFunction node) { // push args values if (node.argNodes != null) { for (int i = 0; i < node.argNodes.Count; i++) { Write_r(node.argNodes[i]); } } NakoILCode code = new NakoILCode(); if (node.func.funcType == Function.NakoFuncType.SysCall) { // NakoAPIFunc f = (NakoAPIFunc)node.func; code.type = NakoILType.SYSCALL; code.value = node.func.varNo; result.Add(code); } else // UserCall { NakoILCode defLabel = ((NakoNodeDefFunction)node.value).defLabel; code.type = NakoILType.USRCALL; code.value = defLabel; if (code.value == null) { //一旦ラベルを設定出来なかったユーザー関数には定義のオブジェクトそのものを入れて、FixLabel内で設定しなおす code.value = node.value; } result.Add(code); } }
/// <summary> /// 構文解析の行われた TopNode に対して、ILコードの発行を行う /// 結果は、Codes に得られる /// </summary> public NakoILCodeList WriteIL() { var writer = new NakoILWriter(); writer.Write(this.topNode); codes = writer.Result; for (int i = 0; i < this.GlobalVar.Count(); i++) //interpreterで使えるように関数定義が保存されている変数をアドレスに変換 { NakoVariable v = this.GlobalVar.GetVar(i); if (v.Body is NakoNodeDefFunction) { NakoVariable setVar = new NakoVariable(); string label = "FUNC_" + ((NakoNodeDefFunction)v.Body).func.name; NakoILCodeList cl = writer.Result; for (int j = 0; j < cl.Count; j++) { NakoILCode c = cl [j]; if (c.value is string && (string)c.value == label) { setVar.SetBody(j, NakoVarType.Int); break; } } this.GlobalVar.SetVar(i, setVar); } } codes.globalVar = this.GlobalVar; return(Codes); }
//TODO:まだ実装できてない private void _try(NakoNodeTry node) { int labelId = GetLableId(); NakoILCode label_try = createLABEL("TRY" + labelId.ToString()); NakoILCode label_catch = createLABEL("CATCH" + labelId.ToString()); NakoILCode label_finally = createLABEL("FINALLY" + labelId.ToString()); // (0) Tryを埋め込む result.Add(label_try); // (1) 通常実行をコードにする Write_r(node.nodeTry); result.Add(createJUMP(label_finally)); // (2) 例外処理 result.Add(label_catch); //TODO ○○のエラーならば〜☆☆のエラーならば〜への対応 //TODO ○○や☆☆のエラーならばへの対応 if (node.nodeCatch != null) { Write_r(node.nodeCatch); result.Add(createJUMP(label_finally)); NakoILCode c = new NakoILCode(); c.type = NakoILType.EXCEPTIONTABLE; c.value = new NakoException(label_try, label_catch, new Exception()); result.Insert(0, c); } // (3) 最後に必ず実行する処理 result.Add(label_finally); if (node.nodeFinally != null) { Write_r(node.nodeFinally); } }
/// <summary> /// ラベルを生成する /// </summary> /// <param name="labelName"></param> /// <returns></returns> protected NakoILCode createLABEL(string labelName) { NakoILCode r = NakoILCode.newNop(); r.value = labelName; labels[r] = -1; return(r); }
private void _branch_false(NakoILCode code) { object v = calcStack.Pop(); if (NakoValueConveter.ToLong(v) == 0) { autoIncPos = false; runpos = Convert.ToInt32((long)code.value); } }
/// <summary> /// ILコードのタイプを参照型に直す /// </summary> /// <param name="c">変更したいコード</param> private void _varBy_change_ref(NakoILCode c) { switch (c.type) { case NakoILType.LD_LOCAL: c.type = NakoILType.LD_LOCAL_REF; break; case NakoILType.LD_GLOBAL: c.type = NakoILType.LD_GLOBAL_REF; break; case NakoILType.LD_ELEM: c.type = NakoILType.LD_ELEM_REF; break; } }
private void exec_ret(NakoILCode code) { autoIncPos = false; NakoCallStack c = callStack.Pop(); this.runpos = c.nextpos; if (((bool)code.value) == false) { globalVar.SetValue(0, c.sore); // "それ"を関数実行前に戻す } this.localVar = c.localVar; }
private void _for(NakoNodeFor node) { int loopVarNo = node.loopVar.varNo; int labelId = GetLableId(); int kaisuVarNo = node.kaisuVarNo; // (0) NakoILCode label_for_begin = createLABEL("FOR_BEGIN" + labelId.ToString()); NakoILCode label_for_end = createLABEL("FOR_END" + labelId.ToString()); NakoILCode label_for_continue = createLABEL("FOR_CONTINUE" + labelId.ToString()); // (1) 変数を初期化する result.Add(label_for_begin); Write_r(node.nodeFrom); addNewILCode(NakoILType.ST_LOCAL, loopVarNo); addNewILCode(NakoILType.LD_CONST_INT, 0L); addNewILCode(NakoILType.ST_LOCAL, kaisuVarNo); // (2) 条件をコードにする // i <= iTo NakoILCode label_for_cond = createLABEL("FOR_COND" + labelId.ToString()); result.Add(label_for_cond); // L addNewILCode(NakoILType.LD_LOCAL, loopVarNo); // R Write_r(node.nodeTo); // TODO:最適化 // LT_EQ addNewILCode(NakoILType.LT_EQ); // IF BRANCH FALSE addNewILCode(NakoILType.BRANCH_FALSE, label_for_end); //回数設定 addNewILCode(NakoILType.LD_LOCAL, kaisuVarNo); addNewILCode(NakoILType.INC); addNewILCode(NakoILType.ST_LOCAL, kaisuVarNo); // (3) 繰り返し文を実行する _loop_check_break_continue(node.nodeBlocks, label_for_end, label_for_continue); Write_r(node.nodeBlocks); //continue時には変数の加算が必要なので、ここに飛ばす必要がある result.Add(label_for_continue); // (4) 変数を加算する (ここ最適化できそう) addNewILCode(NakoILType.LD_LOCAL, loopVarNo); addNewILCode(NakoILType.INC); addNewILCode(NakoILType.ST_LOCAL, loopVarNo); // (5) 手順2に戻る result.Add(createJUMP(label_for_cond)); result.Add(label_for_end); }
private void exec_usrcall(NakoILCode code) { NakoCallStack c = new NakoCallStack(); c.localVar = localVar; c.nextpos = runpos + 1; c.sore = globalVar.GetValue(0); this.localVar = new NakoVariableManager(NakoVariableScope.Local); callStack.Push(c); // JUMP autoIncPos = false; runpos = Convert.ToInt32((long)code.value); }
private void exec_syscall(NakoILCode code) { int funcNo = (int)code.value; NakoAPIFunc s = NakoAPIFuncBank.Instance.FuncList[funcNo]; NakoFuncCallInfo f = new NakoFuncCallInfo(this); object result = s.FuncDl(f); if (s.updateSore) { globalVar.SetValue(0, result); // 変数「それ」に値をセット } StackPush(result); // 関数の結果を PUSH する }
/// <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("ラベルが解決できません"); } } }
// BREAK/CONTINUE文を解決する private void _loop_check_break_continue(NakoNode block, NakoILCode break_label, NakoILCode continue_label) { if (block == null) { return; } if (!block.hasChildren()) { return; } for (int i = 0; i < block.Children.Count; i++) { NakoNode item = block.Children[i]; switch (item.type) { case NakoNodeType.BREAK: item.type = NakoNodeType.JUMP; ((NakoNodeBreak)item).label = break_label; break; case NakoNodeType.CONTINUE: item.type = NakoNodeType.JUMP; ((NakoNodeContinue)item).label = continue_label; break; // ジャンプポイントが変わる構文があれば、その下層ブロックは処理しない case NakoNodeType.FOR: break; case NakoNodeType.WHILE: break; case NakoNodeType.REPEAT_TIMES: break; case NakoNodeType.FOREACH: break; case NakoNodeType.IF: NakoNodeIf ifnode = (NakoNodeIf)item; _loop_check_break_continue(ifnode.nodeTrue, break_label, continue_label); _loop_check_break_continue(ifnode.nodeFalse, break_label, continue_label); break; default: if (item.hasChildren()) { _loop_check_break_continue(item, break_label, continue_label); } break; } } }
private void _let(NakoNodeLet node) { NakoNodeVariable varNode = node.VarNode; NakoNode valueNode = node.ValueNode; // 配列要素があるか確認 if (!varNode.useElement) { // + 要素なしの代入処理 // - 代入する値を書き込んで... Write_r(valueNode); // - セットする NakoILCode st = new NakoILCode(); st.value = varNode.varNo; st.type = (varNode.scope == NakoVariableScope.Global) ? NakoILType.ST_GLOBAL : NakoILType.ST_LOCAL; result.Add(st); } else // 配列要素があるとき { // + 配列への代入処理 // - 基本となる変数をセット NakoILCode ldvar = new NakoILCode(); ldvar.value = varNode.varNo; ldvar.type = (varNode.scope == NakoVariableScope.Global) ? NakoILType.LD_GLOBAL_REF : NakoILType.LD_LOCAL_REF; result.Add(ldvar); // - アクセス要素をセット int count = varNode.Children.Count; for (int i = 0; i < count; i++) { NakoNode n = varNode.Children[i]; Write_r(n); // ノードの値 if (i < count - 1) { result.Add(new NakoILCode(NakoILType.LD_ELEM_REF)); // 要素 } else { // 値ノード Write_r(valueNode); addNewILCode(NakoILType.ST_ELEM); } } } }
private void newCalc(NakoNodeCalc node) { NakoILCode c = new NakoILCode(); // Write_r(node.nodeL); Write_r(node.nodeR); // switch (node.calc_type) { case CalcType.NOP: c.type = NakoILType.NOP; break; // ( ... ) case CalcType.ADD: c.type = NakoILType.ADD; break; case CalcType.SUB: c.type = NakoILType.SUB; break; case CalcType.MUL: c.type = NakoILType.MUL; break; case CalcType.DIV: c.type = NakoILType.DIV; break; case CalcType.MOD: c.type = NakoILType.MOD; break; case CalcType.ADD_STR: c.type = NakoILType.ADD_STR; break; case CalcType.POWER: c.type = NakoILType.POWER; break; case CalcType.EQ: c.type = NakoILType.EQ; break; case CalcType.NOT_EQ: c.type = NakoILType.NOT_EQ; break; case CalcType.GT: c.type = NakoILType.GT; break; case CalcType.GT_EQ: c.type = NakoILType.GT_EQ; break; case CalcType.LT: c.type = NakoILType.LT; break; case CalcType.LT_EQ: c.type = NakoILType.LT_EQ; break; case CalcType.AND: c.type = NakoILType.AND; break; case CalcType.OR: c.type = NakoILType.OR; break; case CalcType.XOR: c.type = NakoILType.XOR; break; case CalcType.NEG: c.type = NakoILType.NEG; break; } result.Add(c); }
private void _repeat_times(NakoNodeRepeatTimes node) { int labelId = GetLableId(); int kaisuVarNo = node.kaisuVarNo; // (0) NakoILCode label_for_begin = createLABEL("TIMES_BEGIN" + labelId.ToString()); NakoILCode label_for_end = createLABEL("TIMES_END" + labelId.ToString()); // (1) 変数を初期化する result.Add(label_for_begin); addNewILCode(NakoILType.LD_CONST_INT, 1L); addNewILCode(NakoILType.ST_LOCAL, node.loopVarNo); // 何回実行するか回数を評価する Write_r(node.nodeTimes); addNewILCode(NakoILType.ST_LOCAL, node.timesVarNo); // (2) 条件をコードにする // i <= iTo NakoILCode label_for_cond = createLABEL("TIMES_COND" + labelId.ToString()); result.Add(label_for_cond); // L addNewILCode(NakoILType.LD_LOCAL, node.loopVarNo); // R addNewILCode(NakoILType.LD_LOCAL, node.timesVarNo); // LT_EQ addNewILCode(NakoILType.LT_EQ); // IF BRANCH FALSE addNewILCode(NakoILType.BRANCH_FALSE, label_for_end); //回数設定 addNewILCode(NakoILType.LD_LOCAL, node.loopVarNo); addNewILCode(NakoILType.ST_LOCAL, kaisuVarNo); // (3) 繰り返し文を実行する _loop_check_break_continue(node.nodeBlocks, label_for_end, label_for_begin); Write_r(node.nodeBlocks); // (4) 変数を加算する (ここ最適化できそう) addNewILCode(NakoILType.INC_LOCAL, node.loopVarNo); // (5) 手順2に戻る result.Add(createJUMP(label_for_cond)); result.Add(label_for_end); }
/// <summary> /// 実行 /// </summary> /// <returns></returns> protected bool _run() { while (runpos < list.Count) { NakoILCode code = this.list[runpos]; Run_NakoIL(code); if (autoIncPos) { runpos++; } else { autoIncPos = true; } } return(true); }
// RETURN文を解決する private void _func_check_return(NakoNode block, NakoILCode return_label) { if (block == null) { return; } if (!block.hasChildren()) { return; } for (int i = 0; i < block.Children.Count; i++) { NakoNode item = block.Children[i]; switch (item.type) { case NakoNodeType.RETURN: item.type = NakoNodeType.JUMP; ((NakoNodeReturn)item).label = return_label; break; // ジャンプポイントが変わる構文があれば、その下層ブロックは処理しない case NakoNodeType.FOR: break; case NakoNodeType.WHILE: break; case NakoNodeType.REPEAT_TIMES: break; case NakoNodeType.FOREACH: break; case NakoNodeType.IF: NakoNodeIf ifnode = (NakoNodeIf)item; _func_check_return(ifnode.nodeTrue, return_label); _func_check_return(ifnode.nodeFalse, return_label); break; default: if (item.hasChildren()) { _func_check_return(item, return_label); } break; } } }
private void _throw(NakoILCode code) { //TODO:check exception table which include runpos and jump if not throw NakoException int catchpos = (exceptionTable == null)? -1 : exceptionTable.GetCatchLine(runpos, code.value); if (catchpos == this.runpos) { thrownCode = code; } else { thrownCode = null; this.runpos = catchpos; } if (this.runpos == -1) { throw new NakoInterpreterException("例外"); } }
private void _while(NakoNodeWhile node) { int labelId = GetLableId(); // (1) 条件をコードにする NakoILCode label_while_begin = createLABEL("WHILE_BEGIN" + labelId.ToString()); result.Add(label_while_begin); Write_r(node.nodeCond); // (2) コードの結果により分岐する // 分岐先をラベルとして作成 NakoILCode label_while_end = createLABEL("WHILE_END" + labelId.ToString()); addNewILCode(NakoILType.BRANCH_FALSE, label_while_end); // (3) ループブロックを書き込む _loop_check_break_continue(node.nodeBlocks, label_while_end, label_while_begin); Write_r(node.nodeBlocks); result.Add(createJUMP(label_while_begin)); result.Add(label_while_end); }
private void _getVariable(NakoNodeVariable node) { NakoILCode ld = new NakoILCode(); if (!node.useElement) { // + 変数アクセス ld.type = (node.scope == NakoVariableScope.Global) ? NakoILType.LD_GLOBAL : NakoILType.LD_LOCAL; if (node.varBy == VarByType.ByRef) { _varBy_change_ref(ld); } ld.value = node.varNo; result.Add(ld); } else { // + 配列変数アクセス // - 変数 ld.type = (node.scope == NakoVariableScope.Global) ? NakoILType.LD_GLOBAL : NakoILType.LD_LOCAL; ld.value = node.varNo; result.Add(ld); // - 要素 NakoNodeList c = node.Children; for (int i = 0; i < c.Count; i++) { Write_r(c[i]); NakoILCode code = new NakoILCode(); /* * code.type = ((c.Count - 1) == i) * ? NakoILType.LD_ELEM * : NakoILType.LD_ELEM_REF; */ code.type = NakoILType.LD_ELEM; result.Add(code); } } }
/// <summary> /// Callback the specified sender, func_name and args. /// </summary> /// <param name="sender">Sender.</param> /// <param name="func_name">Func name.</param> /// <param name="args">Arguments.</param> public void CallUserFunc(string func_name, params object[] args) { NakoILCode c = null; foreach (NakoILCode tmp in this.list) { if (tmp.type == NakoILType.NOP && (string)tmp.value == "FUNC_" + func_name) { c = tmp; break; } } if (c == null) { return;// _nop; } currentIL = c; //StackPush (sender); foreach (object o in args) { StackPush(o); } NakoCallStack stack = new NakoCallStack(); //escape int currentPos = runpos; bool currentAutoIncPos = autoIncPos; object currentSore = globalVar.GetValue(0); stack.localVar = localVar; stack.nextpos = list.Count + 1; // ストッパー stack.sore = globalVar.GetValue(0); //prepare this.localVar = new NakoVariableManager(NakoVariableScope.Local); autoIncPos = true; runpos = this.list.IndexOf(currentIL); callStack.Push(stack); //int baseStackCount=callStack.Count; _run(); runpos = currentPos; autoIncPos = currentAutoIncPos; globalVar.SetValue(0, currentSore); }
private void _call_function(NakoNodeCallFunction node) { // push args values if (node.argNodes != null) { for (int i = 0; i < node.argNodes.Count; i++) { Write_r(node.argNodes[i]); } } NakoILCode code = new NakoILCode(); if (node.func.funcType == Function.NakoFuncType.SysCall) { // NakoAPIFunc f = (NakoAPIFunc)node.func; code.type = NakoILType.SYSCALL; code.value = node.func.varNo; result.Add(code); } else // UserCall { NakoILCode defLabel = ((NakoNodeDefFunction)node.value).defLabel; code.type = NakoILType.USRCALL; code.value = defLabel; if (code.value == null) { //一旦ラベルを設定出来なかったユーザー関数には定義のオブジェクトそのものを入れて、FixLabel内で設定しなおす if (node.func.name != null) { code.value = node.value; } else { //ユーザー関数名がないもの(引数が関数定義だった場合)は、呼び出し先の情報が入った変数を取り出すILを書く addNewILCode(NakoILType.LD_LOCAL, node.func.varNo); } } result.Add(code); } }
/// <summary> /// ILコードのタイプを参照型に直す /// </summary> /// <param name="c">変更したいコード</param> private void _varBy_change_ref(NakoILCode c) { switch (c.type) { case NakoILType.LD_LOCAL: c.type = NakoILType.LD_LOCAL_REF; break; case NakoILType.LD_GLOBAL: c.type = NakoILType.LD_GLOBAL_REF; break; case NakoILType.LD_ELEM: c.type = NakoILType.LD_ELEM_REF; break; } }
private void exec_usrcall(NakoILCode code) { NakoCallStack c = new NakoCallStack(); c.localVar = localVar; c.nextpos = runpos + 1; c.sore = globalVar.GetValue(0); this.localVar = new NakoVariableManager(NakoVariableScope.Local); callStack.Push(c); // JUMP autoIncPos = false; runpos = Convert.ToInt32((long)code.value); }
// BREAK/CONTINUE文を解決する private void _loop_check_break_continue(NakoNode block, NakoILCode break_label, NakoILCode continue_label) { if (block == null) return; if (!block.hasChildren()) return; for (int i = 0; i < block.Children.Count; i++) { NakoNode item = block.Children[i]; switch (item.type) { case NakoNodeType.BREAK: item.type = NakoNodeType.JUMP; ((NakoNodeBreak)item).label = break_label; break; case NakoNodeType.CONTINUE: item.type = NakoNodeType.JUMP; ((NakoNodeContinue)item).label = continue_label; break; // ジャンプポイントが変わる構文があれば、その下層ブロックは処理しない case NakoNodeType.FOR: break; case NakoNodeType.WHILE: break; case NakoNodeType.REPEAT_TIMES: break; case NakoNodeType.FOREACH: break; case NakoNodeType.IF: NakoNodeIf ifnode = (NakoNodeIf)item; _loop_check_break_continue(ifnode.nodeTrue, break_label, continue_label); _loop_check_break_continue(ifnode.nodeFalse, break_label, continue_label); break; default: if (item.hasChildren()) { _loop_check_break_continue(item, break_label, continue_label); } break; } } }
//TODO:まだ実装できてない private void _try(NakoNodeTry node) { int labelId = GetLableId(); NakoILCode label_try = createLABEL("TRY" + labelId.ToString()); NakoILCode label_catch = createLABEL("CATCH" + labelId.ToString()); NakoILCode label_finally = createLABEL("FINALLY" + labelId.ToString()); // (0) Tryを埋め込む result.Add(label_try); // (1) 通常実行をコードにする Write_r(node.nodeTry); result.Add(createJUMP(label_finally)); // (2) 例外処理 result.Add(label_catch); //TODO ○○のエラーならば〜☆☆のエラーならば〜への対応 //TODO ○○や☆☆のエラーならばへの対応 if (node.nodeCatch != null) { Write_r(node.nodeCatch); result.Add(createJUMP(label_finally)); NakoILCode c = new NakoILCode (); c.type = NakoILType.EXCEPTIONTABLE; c.value = new NakoException (label_try,label_catch,new Exception()); result.Insert (0, c); } // (3) 最後に必ず実行する処理 result.Add(label_finally); if (node.nodeFinally != null) { Write_r(node.nodeFinally); } }
private void _jump(NakoNodeJump node) { NakoILCode jmp = new NakoILCode(NakoILType.JUMP, node.label); result.Add(jmp); }
private void _let(NakoNodeLet node) { NakoNodeVariable varNode = node.VarNode; NakoNode valueNode = node.ValueNode; // 配列要素があるか確認 if (!varNode.useElement) { // + 要素なしの代入処理 // - 代入する値を書き込んで... Write_r(valueNode); // - セットする NakoILCode st = new NakoILCode(); st.value = varNode.varNo; st.type = (varNode.scope == NakoVariableScope.Global) ? NakoILType.ST_GLOBAL : NakoILType.ST_LOCAL; result.Add(st); } else // 配列要素があるとき { // + 配列への代入処理 // - 基本となる変数をセット NakoILCode ldvar = new NakoILCode(); ldvar.value = varNode.varNo; ldvar.type = (varNode.scope == NakoVariableScope.Global) ? NakoILType.LD_GLOBAL_REF : NakoILType.LD_LOCAL_REF; result.Add(ldvar); // - アクセス要素をセット int count = varNode.Children.Count; for (int i = 0; i < count; i++) { NakoNode n = varNode.Children[i]; Write_r(n); // ノードの値 if (i < count - 1) { result.Add(new NakoILCode(NakoILType.LD_ELEM_REF)); // 要素 } else { // 値ノード Write_r(valueNode); addNewILCode(NakoILType.ST_ELEM); } } } }
private void _jump(NakoILCode code) { autoIncPos = false; runpos = Convert.ToInt32((long)(code.value)); }
private void _branch_true(NakoILCode code) { object v = calcStack.Pop(); if (NakoValueConveter.ToLong(v) > 0) { autoIncPos = false; runpos = Convert.ToInt32((long)code.value); } }
private void exec_syscall(NakoILCode code) { int funcNo = (int)code.value; NakoAPIFunc s = NakoAPIFuncBank.Instance.FuncList[funcNo]; NakoFuncCallInfo f = new NakoFuncCallInfo(this); object result = s.FuncDl(f); if (s.updateSore) globalVar.SetValue(0, result); // 変数「それ」に値をセット StackPush(result); // 関数の結果を PUSH する }
private void _exceptionTable(NakoILCode code) { exceptionTable.Add ((NakoException)code.value); }
/// <summary> /// ILを実行する /// </summary> /// <param name="code"></param> protected void Run_NakoIL(NakoILCode code) { if (debugMode) { int i = runpos; string s = ""; s += String.Format("{0,4:X4}:", i); s += String.Format("{0,-14}", code.type.ToString()); s += code.GetDescription(); Console.WriteLine(s); } if (thrownCode != null) { if (code.type == NakoILType.JUMP) { _jump(code); _throw(thrownCode); } else if (code.type == NakoILType.RET) { exec_ret(code); _throw(thrownCode); } else if (code.type == NakoILType.LD_GLOBAL) { ld_global((int)code.value); } return; } switch (code.type) { case NakoILType.NOP: /* do nothing */ break; case NakoILType.POP: StackPop(); break; // 定数をスタックに乗せる case NakoILType.LD_CONST_INT: StackPush(code.value); break; case NakoILType.LD_CONST_REAL: StackPush(code.value); break; case NakoILType.LD_CONST_STR: StackPush(code.value); break; // 変数の値をスタックに乗せる case NakoILType.LD_GLOBAL: ld_global((int)code.value); break; case NakoILType.LD_LOCAL: ld_local((int)code.value); break; case NakoILType.LD_GLOBAL_REF: ld_global_ref((int)code.value); break; case NakoILType.LD_LOCAL_REF: ld_local_ref((int)code.value); break; case NakoILType.ST_GLOBAL: st_global((int)code.value); break; case NakoILType.ST_LOCAL: st_local((int)code.value); break; case NakoILType.LD_ELEM: ld_elem(); break; case NakoILType.LD_ELEM_REF: ld_elem_ref(); break; case NakoILType.ST_ELEM: st_elem(); break; case NakoILType.ARR_LENGTH: arr_length(); break; // 計算処理 case NakoILType.ADD: exec_calc(calc_method_add); break; case NakoILType.SUB: exec_calc(calc_method_sub); break; case NakoILType.MUL: exec_calc(calc_method_mul); break; case NakoILType.DIV: exec_calc(calc_method_div); break; case NakoILType.MOD: exec_calc(calc_method_mod); break; case NakoILType.POWER: exec_calc(calc_method_power); break; case NakoILType.ADD_STR: exec_calc(calc_method_add_str); break; case NakoILType.EQ: exec_calc(calc_method_eq); break; case NakoILType.NOT_EQ: exec_calc(calc_method_not_eq); break; case NakoILType.GT: exec_calc(calc_method_gt); break; case NakoILType.GT_EQ: exec_calc(calc_method_gteq); break; case NakoILType.LT: exec_calc(calc_method_lt); break; case NakoILType.LT_EQ: exec_calc(calc_method_lteq); break; case NakoILType.INC: _inc(); break; case NakoILType.DEC: _dec(); break; case NakoILType.NEG: _neg(); break; case NakoILType.AND: exec_calc(calc_method_and); break; case NakoILType.OR: exec_calc(calc_method_or); break; case NakoILType.XOR: exec_calc(calc_method_xor); break; case NakoILType.NOT: _not(); break; // ジャンプ case NakoILType.JUMP: _jump(code); break; // 条件ジャンプ case NakoILType.BRANCH_TRUE: _branch_true(code); break; case NakoILType.BRANCH_FALSE: _branch_false(code); break; // 関数コール case NakoILType.SYSCALL: exec_syscall(code); break; case NakoILType.USRCALL: exec_usrcall(code); break; case NakoILType.RET: exec_ret(code); break; // デバッグ用 case NakoILType.PRINT: exec_print(); break; // ローカル変数に対する操作 case NakoILType.INC_LOCAL: inc_local(code); break; case NakoILType.DEC_LOCAL: dec_local(code); break; case NakoILType.DUP: dup(); break; //exception case NakoILType.THROW: _throw(code); break; //exceptionTable case NakoILType.EXCEPTIONTABLE: _exceptionTable(code); break; // default: throw new NakoInterpreterException("未実装のILコード"); } }
/// <summary> /// ラベルジャンプを生成する /// </summary> /// <param name="label"></param> /// <returns></returns> protected NakoILCode createJUMP(NakoILCode label) { NakoILCode r = new NakoILCode(NakoILType.JUMP, label); return r; }
private void inc_local(NakoILCode code) { NakoVariable v = localVar.GetVar((int)code.value); v.AsInt++; }
/// <summary> /// 中間コードを書き出す /// </summary> /// <param name="node"></param> protected void Write_r(NakoNode node) { if (node == null) { return; } switch (node.type) { case NakoNodeType.NOP: result.Add(NakoILCode.newNop()); break; case NakoNodeType.CALC: newCalc((NakoNodeCalc)node); return; case NakoNodeType.INT: result.Add(new NakoILCode(NakoILType.LD_CONST_INT, node.value)); return; case NakoNodeType.NUMBER: result.Add(new NakoILCode(NakoILType.LD_CONST_REAL, node.value)); return; case NakoNodeType.STRING: result.Add(new NakoILCode(NakoILType.LD_CONST_STR, node.value)); return; case NakoNodeType.POP: result.Add(new NakoILCode(NakoILType.POP)); return; case NakoNodeType.PRINT: _print(node); return; case NakoNodeType.ST_VARIABLE: _setVariable((NakoNodeVariable)node); return; case NakoNodeType.LET: _let((NakoNodeLet)node); return; case NakoNodeType.LD_VARIABLE: _getVariable((NakoNodeVariable)node); return; case NakoNodeType.IF: _if((NakoNodeIf)node); return; case NakoNodeType.WHILE: _while((NakoNodeWhile)node); return; case NakoNodeType.FOR: _for((NakoNodeFor)node); return; case NakoNodeType.BREAK: addNewILCode(NakoILType.NOP, "BREAK"); return; case NakoNodeType.CONTINUE: addNewILCode(NakoILType.NOP, "CONTINUE"); return; case NakoNodeType.RETURN: addNewILCode(NakoILType.NOP, "RETURN"); return; case NakoNodeType.REPEAT_TIMES: _repeat_times((NakoNodeRepeatTimes)node); return; case NakoNodeType.FOREACH: _foreachUseIterator((NakoNodeForeach)node); //_foreach((NakoNodeForeach)node); return; case NakoNodeType.CALL_FUNCTION: _call_function((NakoNodeCallFunction)node); return; case NakoNodeType.DEF_FUNCTION: _def_function((NakoNodeDefFunction)node); return; case NakoNodeType.JUMP: _jump((NakoNodeJump)node); return; //TODO case NakoNodeType.LET_VALUE: addNewILCode(NakoILType.NOP, "LET_VALUE"); break; case NakoNodeType.TRY: _try((NakoNodeTry)node); return; case NakoNodeType.THROW: _throw((NakoNodeThrow)node); return; default: throw new NakoCompilerException("未定義のノードタイプ: " + node.type.ToString()); } // --- if (!node.hasChildren()) { return; } Write_list(node.Children); }
private void _jump(NakoILCode code) { autoIncPos = false; runpos = Convert.ToInt32((long)(code.value)); }
private void newCalc(NakoNodeCalc node) { NakoILCode c = new NakoILCode(); // Write_r(node.nodeL); Write_r(node.nodeR); // switch (node.calc_type) { case CalcType.NOP: c.type = NakoILType.NOP; break; // ( ... ) case CalcType.ADD: c.type = NakoILType.ADD; break; case CalcType.SUB: c.type = NakoILType.SUB; break; case CalcType.MUL: c.type = NakoILType.MUL; break; case CalcType.DIV: c.type = NakoILType.DIV; break; case CalcType.MOD: c.type = NakoILType.MOD; break; case CalcType.ADD_STR: c.type = NakoILType.ADD_STR; break; case CalcType.POWER: c.type = NakoILType.POWER; break; case CalcType.EQ: c.type = NakoILType.EQ; break; case CalcType.NOT_EQ: c.type = NakoILType.NOT_EQ; break; case CalcType.GT: c.type = NakoILType.GT; break; case CalcType.GT_EQ: c.type = NakoILType.GT_EQ; break; case CalcType.LT: c.type = NakoILType.LT; break; case CalcType.LT_EQ: c.type = NakoILType.LT_EQ; break; case CalcType.AND: c.type = NakoILType.AND; break; case CalcType.OR: c.type = NakoILType.OR; break; case CalcType.XOR: c.type = NakoILType.XOR; break; case CalcType.NEG: c.type = NakoILType.NEG; break; } result.Add(c); }
/// <summary> /// ILを実行する /// </summary> /// <param name="code"></param> protected void Run_NakoIL(NakoILCode code) { if (debugMode) { int i = runpos; string s = ""; s += String.Format("{0,4:X4}:", i); s += String.Format("{0,-14}", code.type.ToString()); s += code.GetDescription(); Console.WriteLine(s); } if (thrownCode != null) { if (code.type == NakoILType.JUMP) { _jump (code); _throw (thrownCode); } else if (code.type == NakoILType.RET) { exec_ret (code); _throw (thrownCode); } else if (code.type == NakoILType.LD_GLOBAL) { ld_global((int)code.value); } return; } switch (code.type) { case NakoILType.NOP: /* do nothing */ break; case NakoILType.POP: StackPop(); break; // 定数をスタックに乗せる case NakoILType.LD_CONST_INT: StackPush(code.value); break; case NakoILType.LD_CONST_REAL: StackPush(code.value); break; case NakoILType.LD_CONST_STR: StackPush(code.value); break; // 変数の値をスタックに乗せる case NakoILType.LD_GLOBAL: ld_global((int)code.value); break; case NakoILType.LD_LOCAL: ld_local((int)code.value); break; case NakoILType.LD_GLOBAL_REF: ld_global_ref((int)code.value); break; case NakoILType.LD_LOCAL_REF: ld_local_ref((int)code.value); break; case NakoILType.ST_GLOBAL: st_global((int)code.value); break; case NakoILType.ST_LOCAL: st_local((int)code.value); break; case NakoILType.LD_ELEM: ld_elem(); break; case NakoILType.LD_ELEM_REF: ld_elem_ref(); break; case NakoILType.ST_ELEM: st_elem(); break; case NakoILType.ARR_LENGTH: arr_length(); break; // 計算処理 case NakoILType.ADD: exec_calc(calc_method_add); break; case NakoILType.SUB: exec_calc(calc_method_sub); break; case NakoILType.MUL: exec_calc(calc_method_mul); break; case NakoILType.DIV: exec_calc(calc_method_div); break; case NakoILType.MOD: exec_calc(calc_method_mod); break; case NakoILType.POWER: exec_calc(calc_method_power); break; case NakoILType.ADD_STR: exec_calc(calc_method_add_str); break; case NakoILType.EQ: exec_calc(calc_method_eq); break; case NakoILType.NOT_EQ: exec_calc(calc_method_not_eq); break; case NakoILType.GT: exec_calc(calc_method_gt); break; case NakoILType.GT_EQ: exec_calc(calc_method_gteq); break; case NakoILType.LT: exec_calc(calc_method_lt); break; case NakoILType.LT_EQ: exec_calc(calc_method_lteq); break; case NakoILType.INC: _inc(); break; case NakoILType.DEC: _dec(); break; case NakoILType.NEG: _neg(); break; case NakoILType.AND: exec_calc(calc_method_and); break; case NakoILType.OR: exec_calc(calc_method_or); break; case NakoILType.XOR: exec_calc(calc_method_xor); break; case NakoILType.NOT: _not(); break; // ジャンプ case NakoILType.JUMP: _jump(code); break; // 条件ジャンプ case NakoILType.BRANCH_TRUE: _branch_true(code); break; case NakoILType.BRANCH_FALSE: _branch_false(code); break; // 関数コール case NakoILType.SYSCALL: exec_syscall(code); break; case NakoILType.USRCALL: exec_usrcall(code); break; case NakoILType.RET: exec_ret(code); break; // デバッグ用 case NakoILType.PRINT: exec_print(); break; // ローカル変数に対する操作 case NakoILType.INC_LOCAL: inc_local(code); break; case NakoILType.DEC_LOCAL: dec_local(code); break; case NakoILType.DUP: dup(); break; //exception case NakoILType.THROW: _throw(code); break; //exceptionTable case NakoILType.EXCEPTIONTABLE: _exceptionTable(code); break; // default: throw new NakoInterpreterException("未実装のILコード"); } }
private void dec_local(NakoILCode code) { NakoVariable v = localVar.GetVar((int)code.value); v.AsInt--; }
private void _call_function(NakoNodeCallFunction node) { // push args values if (node.argNodes != null) { for (int i = 0; i < node.argNodes.Count; i++) { Write_r(node.argNodes[i]); } } NakoILCode code = new NakoILCode(); if (node.func.funcType == Function.NakoFuncType.SysCall) { // NakoAPIFunc f = (NakoAPIFunc)node.func; code.type = NakoILType.SYSCALL; code.value = node.func.varNo; result.Add(code); } else // UserCall { NakoILCode defLabel = ((NakoNodeDefFunction)node.value).defLabel; code.type = NakoILType.USRCALL; code.value = defLabel; if (code.value == null) { //一旦ラベルを設定出来なかったユーザー関数には定義のオブジェクトそのものを入れて、FixLabel内で設定しなおす code.value = node.value; } result.Add(code); } }
private void _exceptionTable(NakoILCode code) { exceptionTable.Add((NakoException)code.value); }
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); }
private void exec_ret(NakoILCode code) { autoIncPos = false; NakoCallStack c = callStack.Pop(); this.runpos = c.nextpos; if (((bool)code.value) == false) globalVar.SetValue(0, c.sore);// "それ"を関数実行前に戻す this.localVar = c.localVar; }
// RETURN文を解決する private void _func_check_return(NakoNode block, NakoILCode return_label) { if (block == null) return; if (!block.hasChildren()) return; for (int i = 0; i < block.Children.Count; i++) { NakoNode item = block.Children[i]; switch (item.type) { case NakoNodeType.RETURN: item.type = NakoNodeType.JUMP; ((NakoNodeReturn)item).label = return_label; break; // ジャンプポイントが変わる構文があれば、その下層ブロックは処理しない case NakoNodeType.FOR: break; case NakoNodeType.WHILE: break; case NakoNodeType.REPEAT_TIMES: break; case NakoNodeType.FOREACH: break; case NakoNodeType.IF: NakoNodeIf ifnode = (NakoNodeIf)item; _func_check_return(ifnode.nodeTrue, return_label); _func_check_return(ifnode.nodeFalse, return_label); break; default: if (item.hasChildren()) { _func_check_return(item, return_label); } break; } } }
private void _throw(NakoILCode code) { //TODO:check exception table which include runpos and jump if not throw NakoException int catchpos = (exceptionTable==null)? -1 : exceptionTable.GetCatchLine (runpos, code.value); if (catchpos == this.runpos) { thrownCode = code; } else { thrownCode = null; this.runpos = catchpos; } if (this.runpos == -1) { throw new NakoInterpreterException ("例外"); } }
private void _getVariable(NakoNodeVariable node) { NakoILCode ld = new NakoILCode(); if (!node.useElement) { // + 変数アクセス ld.type = (node.scope == NakoVariableScope.Global) ? NakoILType.LD_GLOBAL : NakoILType.LD_LOCAL; if (node.varBy == VarByType.ByRef) _varBy_change_ref(ld); ld.value = node.varNo; result.Add(ld); } else { // + 配列変数アクセス // - 変数 ld.type = (node.scope == NakoVariableScope.Global) ? NakoILType.LD_GLOBAL : NakoILType.LD_LOCAL; ld.value = node.varNo; result.Add(ld); // - 要素 NakoNodeList c = node.Children; for (int i = 0; i < c.Count; i++) { Write_r(c[i]); NakoILCode code = new NakoILCode(); /* code.type = ((c.Count - 1) == i) ? NakoILType.LD_ELEM : NakoILType.LD_ELEM_REF; */ code.type = NakoILType.LD_ELEM; result.Add(code); } } }