コード例 #1
0
ファイル: CompileVisitor.cs プロジェクト: CMM-IDE/CMM-IDE
 /*
  * 处理leftValue,需要将变量对应在局部变量区的位置压入栈中
  * add的结果是保存在栈上
  */
 public override object VisitLeftValue([NotNull] CMMParser.LeftValueContext context)
 {
     if (context.ChildCount == 1)
     {
         //只定义成了identifier,将identifier对应的索引地址压栈
         if (!curLocalVariablesTable.ContainsKey(context.GetChild(0).GetText()))
         {
             throw new VariableNotFountException(context.GetChild(0).GetText(), context);
         }
         curLocalVariablesTable.TryGetValue(context.GetChild(0).GetText(), out int addr);
         IntermediateCode code = new IntermediateCode(addr, InstructionType.push, context.Start.Line);
         codes.Add(code);
     }
     else
     {
         // 定义成数组的那种形式a[i]
         if (!curLocalVariablesTable.ContainsKey(context.GetChild(0).GetText()))
         {
             throw new VariableNotFountException(context.GetChild(0).GetText(), context);
         }
         curLocalVariablesTable.TryGetValue(context.GetChild(0).GetText(), out int addr);
         // 把基地址也push到操作栈上
         IntermediateCode code0 = new IntermediateCode(addr, InstructionType.push, context.Start.Line);
         Visit(context.expression());
         // 使用add指令,获得addr+expression,add指令使得这个值已经压入栈中
         IntermediateCode code1 = new IntermediateCode(InstructionType.add, context.expression().Start.Line);
         codes.Add(code0);
         codes.Add(code1);
     }
     return(null);
 }
コード例 #2
0
        /// <summary>
        /// 替换中间代码为int
        /// </summary>
        /// <param name="address">中间代码地址</param>
        /// <returns>被替换掉的中间代码</returns>
        public IntermediateCode ReplaceWithInt(int address)
        {
            IntermediateCode saved = codesArray[address];

            codesArray[address] = new IntermediateCode(InstructionType.i, saved.lineNum);
            return(saved);
        }
コード例 #3
0
ファイル: CompileVisitor.cs プロジェクト: CMM-IDE/CMM-IDE
        /*
         * jumpStatement
         * return 语句在第一遍扫描结束之后回填
         * break continue 可以在for while语句的时候,直接转换成为jump语句
         */
        public override object VisitJumpStatement([NotNull] CMMParser.JumpStatementContext context)
        {
            IntermediateCode code = null;

            switch (context.GetChild(0).GetText())
            {
            case "break":
                code = new IntermediateCode(InstructionType.b, context.Start.Line);
                break;

            case "continue":
                code = new IntermediateCode(InstructionType.cnt, context.Start.Line);
                break;

            case "return":
                if (context.ChildCount == 2)
                {
                    // 向操作栈压入0表示没有返回值
                    codes.Add(new IntermediateCode(0, InstructionType.push, context.Start.Line));
                }
                else
                {
                    Visit(context.expression());
                    // 向操作栈压入1表示有返回值
                    codes.Add(new IntermediateCode(1, InstructionType.push, context.Start.Line));
                }
                code = new IntermediateCode(InstructionType.ret, context.Start.Line);
                break;
            }
            codes.Add(code);

            return(null);
        }
コード例 #4
0
ファイル: CompileVisitor.cs プロジェクト: CMM-IDE/CMM-IDE
        // 替换codes[addr0, addr2]中所有的break和continue语句,其中break -> jump addr2, continue -> jump addr1
        private void replaceBreakAndConti(List <IntermediateCode> codes, int addr0, int addr2, int addr1)
        {
            IntermediateCode[] codeArray = codes.ToArray();
            for (int i = addr0; i <= addr2; i++)
            {
                IntermediateCode code;
                switch (codeArray[i].getType())
                {
                case InstructionType.b:
                    code = new IntermediateCode(addr2 + 1, InstructionType.j, codeArray[i].lineNum);
                    codes.RemoveAt(i);
                    codes.Insert(i, code);
                    break;

                case InstructionType.cnt:
                    code = new IntermediateCode(addr1, InstructionType.j, codeArray[i].lineNum);
                    codes.RemoveAt(i);
                    codes.Insert(i, code);
                    break;

                default:
                    break;
                }
            }
        }
コード例 #5
0
ファイル: CompileVisitor.cs プロジェクト: CMM-IDE/CMM-IDE
        /*
         *
         * 用于initializer的编译,分成两种情况。
         * 一种情况是直接对已经定义的普通变量进行赋值,另外一种情况是对数组的操作,没看出来。a[1]=[1],[1]
         * 前提:Expression Visit的结果已经被push到操作栈中
         */
        public override object VisitInitializer([NotNull] CMMParser.InitializerContext context)
        {
            if (context.ChildCount == 3)
            {
                // 直接对已经定义的普通变量进行赋值
                if (curLocalVariablesTable.ContainsKey(context.GetChild(0).GetText()))
                {
                    throw new VariableRedefinedException(context.GetChild(0).GetText(), context);
                }
                curLocalVariablesTable.Add(context.GetChild(0).GetText(), curLocalVariablesTableLength);
                curLocalVariablesTableLength++;
                Visit(context.GetChild(2));
                curLocalVariablesTable.TryGetValue(context.GetChild(0).GetText(), out int index);
                IntermediateCode code = new IntermediateCode(index, InstructionType.pop, context.Start.Line);
                codes.Add(code);
            }
            else
            {
                // 定义数组
                // 首先visit a[exp] exp的值被压到当前stack上
                // expStack.Clear();
                // Visit(context.GetChild(2));
                // Double expValue = (Double)expStack.Pop();
                // if (Math.Ceiling(expValue) != expValue) {
                //     throw new CompileException("数组元素个数必须为整数!");
                // }

                // 支支持常量定义
                int size = Convert.ToInt32(context.GetChild(2).GetText());
                curLocalVariablesTable.Add(context.GetChild(0).GetText(), curLocalVariablesTableLength);

                int initialExpCount = context.expression().Length - 1;


                for (int i = 1; i < context.expression().Length; i++)
                {
                    // 求出所有子表达式的值 放在栈上
                    Visit(context.expression()[i]);
                }
                for (int i = 0; i < size - initialExpCount; i++)
                {
                    // 剩下的元素全部赋值为0
                    codes.Add(new IntermediateCode(0, InstructionType.push, context.Start.Line));
                }
                for (int i = size - 1; i >= 0; i--)
                {
                    // 从后往前给数组赋值
                    codes.Add(new IntermediateCode(curLocalVariablesTableLength + i, InstructionType.pop, context.Start.Line));
                }
                // 更新局部变量表大小
                curLocalVariablesTableLength += size;
            }
            return(null);
        }
コード例 #6
0
ファイル: CompileVisitor.cs プロジェクト: CMM-IDE/CMM-IDE
        /*
         * 处理if语句
         */
        public override object VisitIfStatement([NotNull] CMMParser.IfStatementContext context)
        {
            // 查看expression的结果
            Visit(context.expression());
            IntermediateCode code0 = new IntermediateCode(0, InstructionType.push, context.expression().Start.Line);

            codes.Add(code0);
            // 比较expression的结果和0的关系,等于0的话就跳转走,code1的目的地址待回填
            IntermediateCode code1 = new IntermediateCode(InstructionType.je, context.expression().Stop.Line);

            codes.Add(code1);
            if (context.codeBlock() != null)
            {
                Visit(context.codeBlock());
            }
            IntermediateCode code3 = new IntermediateCode(InstructionType.j, context.codeBlock().Stop.Line);

            codes.Add(code3);
            // 条件不符合的情况应该执行的代码行号为addr0,回填一下
            int addr0 = codes.Count;

            code1.setOperant(addr0);
            List <IntermediateCode> needToAddFinishAddrCodes = new List <IntermediateCode>();

            needToAddFinishAddrCodes.Add(code3);

            // 每个else语句都执行一下
            if (context.elseClause() != null)
            {
                foreach (CMMParser.ElseClauseContext ctx in context.elseClause())
                {
                    if (ctx.ifStatement() == null)
                    {
                        Visit(ctx.codeBlock());
                        IntermediateCode code = new IntermediateCode(InstructionType.j, ctx.codeBlock().Stop.Line);
                        needToAddFinishAddrCodes.Add(code);
                        codes.Add(code);
                    }
                    else
                    {
                        Visit(ctx.ifStatement());
                    }
                }
            }
            foreach (IntermediateCode c in needToAddFinishAddrCodes)
            {
                c.operant = codes.Count;
            }

            return(null);
        }
コード例 #7
0
ファイル: CompileVisitor.cs プロジェクト: CMM-IDE/CMM-IDE
        /*
         * 访问do while表达式
         */
        public override object VisitDoWhileStatement([NotNull] CMMParser.DoWhileStatementContext context)
        {
            // addr0是codeBlock开始地址
            int addr0 = codes.Count;

            Visit(context.codeBlock());

            IntermediateCode code0 = new IntermediateCode(0, InstructionType.push, context.expression().Start.Line);

            // 查看expression的结果
            Visit(context.expression());

            // 比较expression的结果和0的关系,如果不相等的话,就要跳转回去执行codeBlock
            IntermediateCode code1 = new IntermediateCode(addr0, InstructionType.jne, context.expression().Start.Line);

            codes.Add(code0);
            codes.Add(code1);
            return(null);
        }
コード例 #8
0
ファイル: CompileVisitor.cs プロジェクト: CMM-IDE/CMM-IDE
        /*
         * 写指令
         */
        public override object VisitWriteStatement([NotNull] CMMParser.WriteStatementContext context)
        {
            IntermediateCode code;

            if (context.ChildCount == 4)
            {
                // write不带参数
                code = new IntermediateCode(0, InstructionType.write, context.Start.Line);
            }
            else
            {
                // write带参数 先访问参数 将其压栈
                VisitChildren(context);
                // 打印栈顶元素
                code = new IntermediateCode(1, InstructionType.write, context.Start.Line);
            }

            codes.Add(code);
            return(null);
        }
コード例 #9
0
ファイル: CompileVisitor.cs プロジェクト: CMM-IDE/CMM-IDE
        /**
         * 处理生成函数的中间代码时
         * 在函数的第一行地址前加入j指令跳转到函数的最后一行地址之后
         *
         */
        public override object VisitFunctionDeclaration([NotNull] CMMParser.FunctionDeclarationContext context)
        {
            string funcName = context.GetChild(1).GetText();
            // jump到函数ret的下一行代码 最后再回填
            IntermediateCode jumpCode = new IntermediateCode(InstructionType.j, context.Start.Line);

            codes.Add(jumpCode);
            // 保存局部变量表和大小
            Dictionary <string, int> storedVariableTable = curLocalVariablesTable;
            int storedVariableTableSize = curLocalVariablesTableLength;

            curLocalVariablesTable       = new Dictionary <string, int>();
            curLocalVariablesTableLength = 0;

            // 用于记录该函数的各种信息
            FunctionInformation funcInfo = new FunctionInformation(funcName);

            // 记录函数的起始地址
            int funcAddress = codes.Count;

            functionAddressTable.Add(funcName, funcAddress);
            funcInfo.enrtyAddress = funcAddress;

            // 访问参数列表
            Visit(context.parameterClause());
            // visit code block生成当前函数的中间代码
            Visit(context.codeBlock());

            // 填入函数的出口地址
            funcInfo.outAddress = codes.Count - 1;
            // 回填jump指令
            jumpCode.setOperant(codes.Count);
            funcInfo.localVariableTable = curLocalVariablesTable;
            // 将函数信息保存到函数信息表中
            functionInformations.Add(funcName, funcInfo);

            // 恢复局部变量表和大小
            curLocalVariablesTable       = storedVariableTable;
            curLocalVariablesTableLength = storedVariableTableSize;
            return(null);
        }
コード例 #10
0
ファイル: CompileVisitor.cs プロジェクト: CMM-IDE/CMM-IDE
        /*
         *
         * 访问while表达式
         */
        public override object VisitWhileStatement([NotNull] CMMParser.WhileStatementContext context)
        {
            /*
             * 如果expression的操作结果是false,就在栈中压入0,否则压入1.
             *
             */
            int curSize            = curLocalVariablesTableLength;
            int idx                = codes.Count;
            IntermediateCode code0 = new IntermediateCode(0, InstructionType.push, context.Start.Line);

            codes.Add(code0);
            // 查看expression的结果
            Visit(context.expression());

            // 比较expression的结果和1的关系
            // code1的目的地址等待后续回填。因为如果与0相等,说明是false,则需要跳转到codeBlock后面的位置。
            IntermediateCode code1 = new IntermediateCode(InstructionType.je, context.expression().Start.Line);

            codes.Add(code1);
            // addr0是codeBlock的开始地址。
            int addr0 = codes.Count;

            Visit(context.codeBlock());
            IntermediateCode code2 = new IntermediateCode(0, InstructionType.j, context.codeBlock().Stop.Line);

            codes.Add(code2);
            int addr1 = codes.Count;

            // 这个时候回填地址,如果刚才的条件判断不满足,那么目的地址是codeBlock结束的地址addr1
            code1.setOperant(addr1);
            code2.setOperant(idx);
            codes.Add(new IntermediateCode(curSize, InstructionType.delv, context.codeBlock().Stop.Line));
            curLocalVariablesTableLength = curSize;
            removeVariableBiggerThanK(curSize);



            return(null);
        }
コード例 #11
0
ファイル: CompileVisitor.cs プロジェクト: CMM-IDE/CMM-IDE
        /**
         *
         */
        public override object VisitAdditiveExpression([NotNull] CMMParser.AdditiveExpressionContext context)
        {
            Double           op1, op2;
            IntermediateCode code = new IntermediateCode(context.Start.Line);

            // 先遍历左右子树
            VisitChildren(context);
            if (context.ChildCount.Equals(3))
            {
                // 左右
                switch (context.GetChild(1).GetText())
                {
                case "+":
                    code.type = InstructionType.add;
                    // 计算当前表达式的值 以便万一要给数组分配大小
                    // op1 = (Double)expStack.Pop();
                    // op2 = (Double)expStack.Pop();
                    // expStack.Push(op2 + op1);
                    break;

                case "-":
                    code.type = InstructionType.sub;
                    // 计算当前表达式的值 以便万一要给数组分配大小
                    // op1 = (Double)expStack.Pop();
                    // op2 = (Double)expStack.Pop();
                    // expStack.Push(op2 - op1);
                    break;
                }
                codes.Add(code);
            }
            else
            {
                // 子树是term的情况 不用处理
            }


            return(null);
        }
コード例 #12
0
ファイル: CompileVisitor.cs プロジェクト: CMM-IDE/CMM-IDE
        /**
         * 读取identifier的text,然后从函数地址表中读取该函数的中间代码起始地址
         * 调用call指令
         * 将expression List压入被调用函数的局部变量表中
         */
        public override object VisitCallStatement([NotNull] CMMParser.CallStatementContext context)
        {
            // 看一下有多少参数
            VisitExpressionList(context.expressionList());
            int count = 0;

            if (context.expressionList() != null)
            {
                count = getLen(context.expressionList());
            }

            //

            IntermediateCode code1 = new IntermediateCode(count, InstructionType.push, context.Start.Line);

            codes.Add(code1);

            IntermediateCode code0 = new IntermediateCode(context.Identifier().GetText(), InstructionType.call, context.Start.Line);

            codes.Add(code0);

            return(null);
        }
コード例 #13
0
ファイル: CompileVisitor.cs プロジェクト: CMM-IDE/CMM-IDE
        /*
         * 处理赋值操作,
         * 前提:leftValue将待赋值的变量在局部变更量表中的索引已经压入栈中,expression处理的结果已经压入操作栈中
         */
        public override object VisitAssignment([NotNull] CMMParser.AssignmentContext context)
        {
            Visit(context.leftValue());

            // tmp是一个虚拟的变量,用于 存储leftVal的索引 在局部变量表的位置
            int tmp = curLocalVariablesTableLength;

            // 把leftVal的值放到局部变更量表Count位置上
            IntermediateCode code0 = new IntermediateCode(tmp, InstructionType.pop, context.leftValue().Start.Line);

            codes.Add(code0);

            // 把Expression的值压入栈中
            Visit(context.expression());

            //将Experession的值放入Count中
            IntermediateCode code1 = new IntermediateCode("(" + tmp + ")", InstructionType.pop, context.expression().Start.Line);

            // 这个过程中,局部变量表并没有增加新的元素,所以curLocalVariable并没有Add操作
            codes.Add(code1);

            // 局部变量表里面,1号位置的值是0
            return(null);
        }
コード例 #14
0
        /// <summary>
        /// 开始调试
        /// </summary>
        public void Run()
        {
            // 初始化栈
            stack       = new Stack <StackFrame>();
            entryStacks = new Stack <int>();
            stacks.Add(stack);

            // 当前栈帧
            currentStackFrame = new StackFrame(0);
            globalStackFrame  = currentStackFrame;
            stack.Push(currentStackFrame);

            // 代码区长度
            int length = codesArray.Count;

            // 初始化程序计数器
            pc = 0;

            isStop = false;

            // 设置当前符号表
            currentSymbolTable = globalSymbolTable;

            // 执行中间代码
            while (pc < length && !isStop)
            {
                IntermediateCode code = codesArray[pc];
                InterpretSingleInstruction(code);
                pc++;
            }

            // 停止运行
            // 运行结束销毁
            stacks.Remove(stack);
            RunFinish?.Invoke();
        }
コード例 #15
0
        /// <summary>
        /// 获取源代码-中间代码信息
        /// </summary>
        /// <returns>源代码-中间代码信息</returns>
        public Dictionary <int, IntermediateCodeInformation> GetIntermediateCodeInformation()
        {
            int length = codesArray.Count;
            Dictionary <int, IntermediateCodeInformation> informations = new Dictionary <int, IntermediateCodeInformation>();

            // 遍历中间代码
            for (int i = 0; i < length; i++)
            {
                IntermediateCode current = codesArray[i];
                int currentLine          = current.lineNum;
                IntermediateCodeInformation currentInformation;

                // 判断该中间指令对应源代码的行是否已经加入信息表中
                if (informations.TryGetValue(currentLine, out currentInformation))
                {
                    // 该行含函数调用则更新函数入口地址列表
                    if (current.type == InstructionType.call)
                    {
                        currentInformation.IsFunctionCall = true;
                        currentInformation.FuncionEntryList.AddLast((int)current.operant);
                        informations[currentLine] = currentInformation;
                    }
                }
                else
                {
                    // 该行源代码首条中间指令
                    currentInformation                  = new IntermediateCodeInformation();
                    currentInformation.Address          = i;
                    currentInformation.Line             = currentLine;
                    currentInformation.IsFunctionCall   = false;
                    currentInformation.FuncionEntryList = new LinkedList <int>();
                    informations.Add(currentLine, currentInformation);
                }
            }
            return(informations);
        }
コード例 #16
0
ファイル: CompileVisitor.cs プロジェクト: CMM-IDE/CMM-IDE
        /**
         * 判断子表达式的值并压入栈中
         *
         *
         */
        public override object VisitBoolExpression([NotNull] CMMParser.BoolExpressionContext context)
        {
            Object res = VisitChildren(context);
            Double op1, op2;

            if (context.ChildCount.Equals(3))
            {
                string relationalOperator = context.GetChild(1).GetText();

                IntermediateCode code = new IntermediateCode(context.Start.Line);
                switch (relationalOperator)
                {
                case "<=":
                    code.type = InstructionType.le;

                    // op1 = (Double)expStack.Pop();
                    // op2 = (Double)expStack.Pop();
                    // expStack.Push(op2 <= op1 ? 1 : 0);
                    break;

                case ">=":
                    code.type = InstructionType.ge;
                    // op1 = (Double)expStack.Pop();
                    // op2 = (Double)expStack.Pop();
                    // expStack.Push(op2 >= op1 ? 1 : 0);
                    break;

                case "==":
                    code.type = InstructionType.eq;
                    // op1 = (Double)expStack.Pop();
                    // op2 = (Double)expStack.Pop();
                    // expStack.Push(op2 == op1 ? 1 : 0);
                    break;

                case "<":
                    code.type = InstructionType.l;
                    // op1 = (Double)expStack.Pop();
                    // op2 = (Double)expStack.Pop();
                    // expStack.Push(op2 < op1 ? 1 : 0);
                    break;

                case ">":
                    code.type = InstructionType.g;
                    // op1 = (Double)expStack.Pop();
                    // op2 = (Double)expStack.Pop();
                    // expStack.Push(op2 > op1 ? 1 : 0);
                    break;

                case "<>":
                    code.type = InstructionType.ne;
                    // op1 = (Double)expStack.Pop();
                    // op2 = (Double)expStack.Pop();
                    // expStack.Push(op2 != op1 ? 1 : 0);
                    break;

                default:
                    break;
                }
                codes.Add(code);
            }
            else
            {
                // additiveExpression的情况不用处理 直接把值压栈
            }

            return(res);
        }
コード例 #17
0
 /// <summary>
 /// 恢复中间代码
 /// </summary>
 /// <param name="address">中间代码地址</param>
 /// <param name="code">中间代码</param>
 public void Resume(int address, IntermediateCode code)
 {
     codesArray[address] = code;
 }
コード例 #18
0
ファイル: CompileVisitor.cs プロジェクト: CMM-IDE/CMM-IDE
        /*
         * 处理for语句
         */
        public override object VisitForStatement([NotNull] CMMParser.ForStatementContext context)
        {
            // 当前局部变量表的大小,访问完ForStatement之后要恢复局部变量表
            int curSize = curLocalVariablesTableLength;

            // 这里面可能会定义新的变量,不过没关系,直接插入局部变量表中就可以了,最后我们恢复的。
            if (context.forInitializer() != null)
            {
                Visit(context.forInitializer());
            }
            // 访问expression,将执行的结果压入栈中
            // addr_expression是expression(比较)的地址
            int addr_expression = codes.Count;
            IntermediateCode code0, code1 = null;

            if (context.expression() != null)
            {
                Visit(context.expression());


                // 如果expression的结果是真,才会访问
                // 这里的0是数字,不是索引,要加上范围!!
                code0 = new IntermediateCode(0, InstructionType.push, context.Start.Line);
                // 如果是0的话,就直接跳转到codeBlock之后,并且释放局部变量。目的地址待回填
                code1 = new IntermediateCode(InstructionType.je, context.Start.Line);

                // addr0是codeBlock的起始地址
                codes.Add(code0);
                codes.Add(code1);
            }
            int addr0 = codes.Count;

            // 访问codeBlock
            if (context.codeBlock() != null)
            {
                Visit(context.codeBlock());
            }

            // 访问更新操作,更新操作的起始地址是addr1
            int addr1 = codes.Count;

            if (context.assignment() != null)
            {
                Visit(context.assignment());
            }
            // 跳转回去expression去判断
            codes.Add(new IntermediateCode(addr_expression, InstructionType.j, context.Start.Line));

            // addr2是执行完codeBlock,而且判断确定不跳转的代码
            int addr2 = codes.Count;

            if (code1 != null)
            {
                code1.setOperant(addr2);
            }
            // 替换所有出现的continue break,代码的范围是addr0-add2, 更新操作的代码在addr1
            replaceBreakAndConti(codes, addr0, addr2 - 1, addr1);
            //局部变量表大于curSize的部分全部删掉!
            codes.Add(new IntermediateCode(curSize, InstructionType.delv, context.Stop.Line));
            curLocalVariablesTableLength = curSize;
            removeVariableBiggerThanK(curSize);
            return(null);
        }
コード例 #19
0
        /// <summary>
        /// 执行单条指令
        /// </summary>
        /// <param name="code">单条指令</param>
        public void InterpretSingleInstruction(IntermediateCode code)
        {
            switch (code.type)
            {
            case InstructionType.add:
                add(currentStackFrame, pc);
                break;

            case InstructionType.sub:
                sub(currentStackFrame, pc);
                break;

            case InstructionType.mul:
                mul(currentStackFrame);
                break;

            case InstructionType.div:
                div(currentStackFrame);
                break;

            case InstructionType.neg:
                neg(currentStackFrame);
                break;

            case InstructionType.and:
                and(currentStackFrame);
                break;

            case InstructionType.or:
                or(currentStackFrame);
                break;

            case InstructionType.not:
                not(currentStackFrame);
                break;

            case InstructionType.push:
                push(currentStackFrame, code.operant);
                break;

            case InstructionType.pop:
                pop(currentStackFrame, code.operant);
                break;

            case InstructionType.g:
                g(currentStackFrame);
                break;

            case InstructionType.l:
                l(currentStackFrame);
                break;

            case InstructionType.ge:
                ge(currentStackFrame);
                break;

            case InstructionType.le:
                le(currentStackFrame);
                break;

            case InstructionType.eq:
                eq(currentStackFrame);
                break;

            case InstructionType.ne:
                ne(currentStackFrame);
                break;

            case InstructionType.j:
                j(code.operant);
                break;

            case InstructionType.je:
                je(currentStackFrame, code.operant);
                break;

            case InstructionType.jg:
                jg(currentStackFrame, code.operant);
                break;

            case InstructionType.jl:
                jl(currentStackFrame, code.operant);
                break;

            case InstructionType.jne:
                jne(currentStackFrame, code.operant);
                break;

            case InstructionType.call:
                // 创建新的函数栈帧 传入pc
                StackFrame newStackFrame = new StackFrame(pc);
                // 首先获取参数个数
                int paraNum = (int)currentStackFrame.popFromOperantStack();
                // 向新的栈帧中压入参数
                Stack <Object> tmp = new Stack <Object>();
                for (int i = 0; i < paraNum; i++)
                {
                    tmp.Push(currentStackFrame.popFromOperantStack());
                }
                for (int i = 0; i < paraNum; i++)
                {
                    newStackFrame.pushToVariableStack(tmp.Pop());
                }
                // 压入新栈
                stack.Push(newStackFrame);
                entryStacks.Push((int)code.operant);
                currentStackFrame  = newStackFrame;
                currentSymbolTable = functionSymbolTable[(int)code.operant];
                pc = (int)code.operant - 1;
                break;

            case InstructionType.read:
                read(currentStackFrame);
                break;

            case InstructionType.write:
                write(currentStackFrame, code.operant);
                break;

            case InstructionType.delv:
                delv(currentStackFrame);
                break;

            case InstructionType.b:
                b(currentStackFrame);
                break;

            case InstructionType.cnt:
                cnt(currentStackFrame);
                break;

            case InstructionType.pushv:
                pushv(currentStackFrame, code.operant);
                break;

            case InstructionType.i:
                i();
                break;

            case InstructionType.ret:
                pc = currentStackFrame.getReturnAddress();
                int flag = (int)currentStackFrame.popFromOperantStack();

                Object returnValue = currentStackFrame.peek();
                // 函数返回 移除当前栈帧
                stack.Pop();
                entryStacks.Pop();
                if (flag == 1)
                {
                    // 将函数返回值压入到调用者的栈帧中
                    stack.Peek().pushToOperantStack(returnValue);
                }
                currentStackFrame  = stack.Peek();
                currentSymbolTable = globalSymbolTable;
                break;

            default:
                break;
            }
        }
コード例 #20
0
        /// <summary>
        /// 解释执行代码
        /// </summary>
        /// <param name="codes">中间代码</param>
        /// <returns>是否成功运行</returns>
        public Boolean interpret(List <IntermediateCode> codes)
        {
            // 初始化栈
            Stack <StackFrame> stack = new Stack <StackFrame>();

            stacks.Add(stack);
            // 当前栈帧
            StackFrame currentStackFrame = new StackFrame(0);

            stack.Push(currentStackFrame);

            codesArray = codes;
            printCodes();
            for (; pc < codes.Count; pc++)
            {
                IntermediateCode code = codesArray[pc];
                switch (code.type)
                {
                case InstructionType.add:
                    add(currentStackFrame, pc);
                    break;

                case InstructionType.sub:
                    sub(currentStackFrame, pc);
                    break;

                case InstructionType.mul:
                    mul(currentStackFrame);
                    break;

                case InstructionType.div:
                    div(currentStackFrame);
                    break;

                case InstructionType.neg:
                    neg(currentStackFrame);
                    break;

                case InstructionType.and:
                    and(currentStackFrame);
                    break;

                case InstructionType.or:
                    or(currentStackFrame);
                    break;

                case InstructionType.not:
                    not(currentStackFrame);
                    break;

                case InstructionType.push:
                    push(currentStackFrame, code.operant);
                    break;

                case InstructionType.pop:
                    pop(currentStackFrame, code.operant);
                    break;

                case InstructionType.g:
                    g(currentStackFrame);
                    break;

                case InstructionType.l:
                    l(currentStackFrame);
                    break;

                case InstructionType.ge:
                    ge(currentStackFrame);
                    break;

                case InstructionType.le:
                    le(currentStackFrame);
                    break;

                case InstructionType.eq:
                    eq(currentStackFrame);
                    break;

                case InstructionType.ne:
                    ne(currentStackFrame);
                    break;

                case InstructionType.j:
                    j(code.operant);
                    break;

                case InstructionType.je:
                    je(currentStackFrame, code.operant);
                    break;

                case InstructionType.jg:
                    jg(currentStackFrame, code.operant);
                    break;

                case InstructionType.jl:
                    jl(currentStackFrame, code.operant);
                    break;

                case InstructionType.jne:
                    jne(currentStackFrame, code.operant);
                    break;

                case InstructionType.call:
                    // 创建新的函数栈帧 传入pc
                    StackFrame newStackFrame = new StackFrame(pc);
                    // 首先获取参数个数
                    int paraNum = (int)currentStackFrame.popFromOperantStack();
                    // 向新的栈帧中压入参数
                    Stack <Object> tmp = new Stack <Object>();
                    for (int i = 0; i < paraNum; i++)
                    {
                        tmp.Push(currentStackFrame.popFromOperantStack());
                    }
                    for (int i = 0; i < paraNum; i++)
                    {
                        newStackFrame.pushToVariableStack(tmp.Pop());
                    }
                    // 压入新栈
                    stack.Push(newStackFrame);
                    currentStackFrame = newStackFrame;
                    pc = (int)code.operant - 1;
                    break;

                case InstructionType.read:
                    read(currentStackFrame);
                    break;

                case InstructionType.write:
                    write(currentStackFrame, code.operant);
                    break;

                case InstructionType.delv:
                    delv(currentStackFrame);
                    break;

                case InstructionType.b:
                    b(currentStackFrame);
                    break;

                case InstructionType.cnt:
                    cnt(currentStackFrame);
                    break;

                case InstructionType.pushv:
                    pushv(currentStackFrame, code.operant);
                    break;

                case InstructionType.i:
                    break;

                case InstructionType.ret:
                    pc = currentStackFrame.getReturnAddress();
                    int flag = (int)currentStackFrame.popFromOperantStack();

                    Object returnValue = currentStackFrame.peek();
                    // 函数返回 移除当前栈帧
                    stack.Pop();
                    if (flag == 1)
                    {
                        // 将函数返回值压入到调用者的栈帧中
                        stack.Peek().pushToOperantStack(returnValue);
                    }
                    currentStackFrame = stack.Peek();

                    break;

                default:

                    break;
                }
            }


            // 运行结束销毁
            stacks.Remove(stack);
            return(true);
        }