Exemplo n.º 1
0
        private void dfsTraverse(Node node)
        {
            if (node is TerminalNode)
            {
                TerminalNode t = node as TerminalNode;
                emit("push " + t.Value + ";\n");

                FusionCore.DSASM.Operand op = buildOperand(t);
                emitPush(op);
            }
            else if (node is FunctionDefinitionNode)
            {
                FunctionDefinitionNode funcDef = node as FunctionDefinitionNode;

                // TODO jun: Add semantics for checking overloads (different parameter types)
                FusionCore.DSASM.FunctionNode fnode = new FusionCore.DSASM.FunctionNode();
                fnode.name = funcDef.Name;
                fnode.paramCount = null == funcDef.Signature ? 0 : funcDef.Signature.Arguments.Count;
                fnode.pc = pc;
                fnode.localCount = funcDef.localVars;
                fnode.returntype = FusionCore.TypeSystem.getType(funcDef.ReturnType.Name);
                functionindex = functions.Append(fnode);

                // Append arg symbols
                if (fnode.paramCount > 0)
                {
                    foreach (VarDeclNode argNode in funcDef.Signature.Arguments)
                    {
                        AllocateArg(argNode.NameNode.Value, functionindex, FusionCore.TypeSystem.getType(argNode.ArgumentType.Name));
                    }
                }

                // Traverse definition
                foreach (Node bnode in funcDef.FunctionBody.Body)
                {
                    dfsTraverse(bnode);
                }

                // Append to the function group functiontable
                FusionCore.FunctionGroup funcGroup = new FusionCore.FunctionGroup();

                // ArgList
                if (fnode.paramCount > 0)
                {
                    List<FusionCore.Type> parameterTypes = new List<FusionCore.Type>();
                    foreach (VarDeclNode argNode in funcDef.Signature.Arguments)
                    {
                        parameterTypes.Add(FusionCore.TypeSystem.buildTypeObject(FusionCore.TypeSystem.getType(argNode.ArgumentType.Name), false));
                    }
                }

                // function return
                emit("ret" + FusionCore.DSASM.Constants.termline);
                emitReturn();
                functionindex = (int)FusionCore.DSASM.Constants.kGlobalScope;
                argOffset = 0;
                baseOffset = 0;
            }
            else if (node is FunctionCallNode)
            {
                FunctionCallNode funcCall = node as FunctionCallNode;
                FusionCore.DSASM.FunctionNode fnode = new FusionCore.DSASM.FunctionNode();
                fnode.name = funcCall.Function.Name;
                fnode.paramCount = funcCall.FormalArguments.Count;

                // Traverse the function args
                foreach (Node paramNode in funcCall.FormalArguments)
                {
                    dfsTraverse(paramNode);
                }

                int fIndex = functions.getIndex(fnode);
                if ((int)FusionCore.DSASM.Constants.kInvalidIndex != fIndex)
                {
                    emit("call " + fnode.name + FusionCore.DSASM.Constants.termline);
                    emitCall(fIndex);

                    if (FusionCore.PrimitiveType.kTypeVoid != functions.functionList[fIndex].returntype)
                    {
                        emit("push " + FusionCore.DSASM.kw.regRX + FusionCore.DSASM.Constants.termline);
                        FusionCore.DSASM.Operand opRes;
                        opRes.optype = FusionCore.DSASM.AddressType.Register;
                        opRes.opdata = (int)FusionCore.DSASM.Registers.RX;
                        emitPush(opRes);
                    }
                }
                else
                {
                    System.Console.WriteLine("Method '" + fnode.name + "' not found\n");
                }
            }
            else if (node is IfStmtNode)
            {

/*
           

                def backpatch(bp, pc)
	                instr = instrstream[bp]
	                if instr.opcode is jmp
		                instr.op1 = pc
	                elseif instr.opcode is cjmp
		                instr.op2 = pc
	                end
                end

                def backpatch(table, pc)
	                foreach node in table
		                backpatch(node.pc, pc)
	                end
                end

*/
                /*
                 if(E)		->	traverse E	
				                bpTable = new instance
				                L1 = pc + 1
				                L2 = null 
                                bp = pc
				                emit(jmp, _cx, L1, L2) 
                {
                    S		->	traverse S
                                L1 = null
			                    bpTable.append(pc)
			                    emit(jmp,labelEnd)
			                    backpatch(bp,pc)
                }
                 * */

                // TODO jun: Try to break up this emitter without while retaining theoretical meaning
                int bp = (int)FusionCore.DSASM.Constants.kInvalidIndex; 
                int L1 = (int)FusionCore.DSASM.Constants.kInvalidIndex;
                int L2 = (int)FusionCore.DSASM.Constants.kInvalidIndex;
                FusionCore.DSASM.Operand opCX;


                // If-expr
                IfStmtNode ifnode = node as IfStmtNode;
                dfsTraverse(ifnode.IfExprNode);

                emit("pop " + FusionCore.DSASM.kw.regCX + FusionCore.DSASM.Constants.termline);
                opCX.optype = FusionCore.DSASM.AddressType.Register;
                opCX.opdata = (int)FusionCore.DSASM.Registers.CX;
                emitPop(opCX);

                L1 = pc + 1;
                L2 = (int)FusionCore.DSASM.Constants.kInvalidIndex;
                bp = pc;
                emitCJmp(L1, L2);

                // If-body
                foreach (Node ifBody in ifnode.IfBody)
                {
                    dfsTraverse(ifBody);
                }

                L1 = (int)FusionCore.DSASM.Constants.kInvalidIndex;
                backpatchTable.append(pc, L1);
                emitJmp(L1);
                backpatch(bp, pc);


                /*		
                else if(E)	->	traverse E
                                L1 = pc + 1
				                L2 = null 
                                bp = pc
				                emit(jmp, _cx, L1, L2) 
                {				
                    S		->	traverse S
                                L1 = null
                                bpTable.append(pc)
			                    emit(jmp,labelEnd) 
			                    backpatch(bp,pc)
                }
                 * */

                // Elseif-expr
                foreach (ElseIfBlock elseifNode in ifnode.ElseIfList)
                {
                    dfsTraverse(elseifNode.Expr);

                    emit("pop " + FusionCore.DSASM.kw.regCX + FusionCore.DSASM.Constants.termline);
                    opCX.optype = FusionCore.DSASM.AddressType.Register;
                    opCX.opdata = (int)FusionCore.DSASM.Registers.CX;
                    emitPop(opCX);

                    L1 = pc + 1;
                    L2 = (int)FusionCore.DSASM.Constants.kInvalidIndex;
                    bp = pc;
                    emitCJmp(L1, L2);

                    // Elseif-body   
                    if (null != elseifNode.Body)
                    {
                        foreach (Node elseifBody in elseifNode.Body)
                        {
                            dfsTraverse(elseifBody);
                        }
                    }

                    L1 = (int)FusionCore.DSASM.Constants.kInvalidIndex;
                    backpatchTable.append(pc, L1);
                    emitJmp(L1);
                    backpatch(bp, pc);
                }

                /*
                else 			
                {				
                    S		->	traverse S
                                L1 = null
                                bpTable.append(pc)
			                    emit(jmp,labelEnd) 
			                    backpatch(bp,pc)
                }		
                 * */
                // Else-body     
                if (null != ifnode.ElseBody)
                {
                    foreach (Node elseBody in ifnode.ElseBody)
                    {
                        dfsTraverse(elseBody);
                    }

                    L1 = (int)FusionCore.DSASM.Constants.kInvalidIndex;
                    backpatchTable.append(pc, L1);
                    emitJmp(L1);
                    //backpatch(bp, pc);
                }

                /*
                 * 
			              ->	backpatch(bpTable, pc) 
                 */
                // ifstmt-exit
                backpatch(backpatchTable.backpatchList, pc);


            }
            else if (node is VarDeclNode)
            {
                VarDeclNode varNode = node as VarDeclNode;
                Allocate(varNode.NameNode.Value, functionindex, FusionCore.TypeSystem.getType(varNode.ArgumentType.Name));
            }
            else if (node is BinaryExpressionNode)
            {
                BinaryExpressionNode b = node as BinaryExpressionNode;
                if (Operator.assign != b.Operator)
                {
                    dfsTraverse(b.LeftNode);
                }
                dfsTraverse(b.RightNode);

                if (Operator.assign == b.Operator)
                {
                    if (b.LeftNode is TerminalNode)
                    {
                        TerminalNode t = b.LeftNode as TerminalNode;

                        bool isReturn = false;
                        string s = t.Value;
                        if (s == "return")
                        {
                            s = "_rx";
                            //isReturn = true;
                        }

                        // TODO jun: the emit string are only for console logging, 
                        // wrap them together with the actual emit function and flag them out as needed
                        emit("pop " + s + FusionCore.DSASM.Constants.termline);

                        FusionCore.DSASM.Operand op = buildOperand(t);
                        emitPop(op);

                        //if (isReturn)
                        //{
                        //    emit("ret" + FusionCore.DSASM.Constants.termline);
                        //    emitReturn();
                        //    functionindex = (int)FusionCore.DSASM.Constants.kGlobalScope;
                        //}
                    }
                }
                else
                {
                    emit("pop " + FusionCore.DSASM.kw.regBX + FusionCore.DSASM.Constants.termline);
                    FusionCore.DSASM.Operand opBX;
                    opBX.optype = FusionCore.DSASM.AddressType.Register;
                    opBX.opdata = (int)FusionCore.DSASM.Registers.BX;
                    emitPop(opBX);


                    emit("pop " + FusionCore.DSASM.kw.regAX + FusionCore.DSASM.Constants.termline);
                    FusionCore.DSASM.Operand opAX;
                    opAX.optype = FusionCore.DSASM.AddressType.Register;
                    opAX.opdata = (int)FusionCore.DSASM.Registers.AX;
                    emitPop(opAX);


                    string op = getOperator(b.Operator);
                    emit(op + " " + FusionCore.DSASM.kw.regAX + ", " + FusionCore.DSASM.kw.regBX + FusionCore.DSASM.Constants.termline);
                    emitBinary(getOpCode(b.Operator), opAX, opBX);


                    emit("push " + FusionCore.DSASM.kw.regAX + FusionCore.DSASM.Constants.termline);
                    FusionCore.DSASM.Operand opRes;
                    opRes.optype = FusionCore.DSASM.AddressType.Register;
                    opRes.opdata = (int)FusionCore.DSASM.Registers.AX;
                    emitPush(opRes);
                }
            }
        }
Exemplo n.º 2
0
        private void dfsTraverse(Node node)
        {
            if (node is TerminalNode)
            {
                TerminalNode t = node as TerminalNode;
                emit("push " + t.Value + ";\n");

                FusionCore.DSASM.Operand op = buildOperand(t);
                emitPush(op);
            }
            else if (node is FunctionDefinitionNode)
            {
                FunctionDefinitionNode funcDef = node as FunctionDefinitionNode;

                // TODO jun: Add semantics for checking overloads (different parameter types)
                FusionCore.DSASM.FunctionNode fnode = new FusionCore.DSASM.FunctionNode();
                fnode.name       = funcDef.Name;
                fnode.paramCount = null == funcDef.Signature ? 0 : funcDef.Signature.Arguments.Count;
                fnode.pc         = pc;
                fnode.localCount = funcDef.localVars;
                fnode.returntype = FusionCore.TypeSystem.getType(funcDef.ReturnType.Name);
                functionindex    = functions.Append(fnode);

                // Append arg symbols
                if (fnode.paramCount > 0)
                {
                    foreach (VarDeclNode argNode in funcDef.Signature.Arguments)
                    {
                        AllocateArg(argNode.NameNode.Value, functionindex, FusionCore.TypeSystem.getType(argNode.ArgumentType.Name));
                    }
                }

                // Traverse definition
                foreach (Node bnode in funcDef.FunctionBody.Body)
                {
                    dfsTraverse(bnode);
                }

                // Append to the function group functiontable
                FusionCore.FunctionGroup funcGroup = new FusionCore.FunctionGroup();

                // ArgList
                if (fnode.paramCount > 0)
                {
                    List <FusionCore.Type> parameterTypes = new List <FusionCore.Type>();
                    foreach (VarDeclNode argNode in funcDef.Signature.Arguments)
                    {
                        parameterTypes.Add(FusionCore.TypeSystem.buildTypeObject(FusionCore.TypeSystem.getType(argNode.ArgumentType.Name), false));
                    }
                }

                // function return
                emit("ret" + FusionCore.DSASM.Constants.termline);
                emitReturn();
                functionindex = (int)FusionCore.DSASM.Constants.kGlobalScope;
                argOffset     = 0;
                baseOffset    = 0;
            }
            else if (node is FunctionCallNode)
            {
                FunctionCallNode funcCall           = node as FunctionCallNode;
                FusionCore.DSASM.FunctionNode fnode = new FusionCore.DSASM.FunctionNode();
                fnode.name       = funcCall.Function.Name;
                fnode.paramCount = funcCall.FormalArguments.Count;

                // Traverse the function args
                foreach (Node paramNode in funcCall.FormalArguments)
                {
                    dfsTraverse(paramNode);
                }

                int fIndex = functions.getIndex(fnode);
                if ((int)FusionCore.DSASM.Constants.kInvalidIndex != fIndex)
                {
                    emit("call " + fnode.name + FusionCore.DSASM.Constants.termline);
                    emitCall(fIndex);

                    if (FusionCore.PrimitiveType.kTypeVoid != functions.functionList[fIndex].returntype)
                    {
                        emit("push " + FusionCore.DSASM.kw.regRX + FusionCore.DSASM.Constants.termline);
                        FusionCore.DSASM.Operand opRes;
                        opRes.optype = FusionCore.DSASM.AddressType.Register;
                        opRes.opdata = (int)FusionCore.DSASM.Registers.RX;
                        emitPush(opRes);
                    }
                }
                else
                {
                    System.Console.WriteLine("Method '" + fnode.name + "' not found\n");
                }
            }
            else if (node is IfStmtNode)
            {
/*
 *
 *
 *              def backpatch(bp, pc)
 *                      instr = instrstream[bp]
 *                      if instr.opcode is jmp
 *                              instr.op1 = pc
 *                      elseif instr.opcode is cjmp
 *                              instr.op2 = pc
 *                      end
 *              end
 *
 *              def backpatch(table, pc)
 *                      foreach node in table
 *                              backpatch(node.pc, pc)
 *                      end
 *              end
 *
 */
                /*
                 * if(E)		->	traverse E
                 *                              bpTable = new instance
                 *                              L1 = pc + 1
                 *                              L2 = null
                 *              bp = pc
                 *                              emit(jmp, _cx, L1, L2)
                 * {
                 *  S		->	traverse S
                 *              L1 = null
                 *                          bpTable.append(pc)
                 *                          emit(jmp,labelEnd)
                 *                          backpatch(bp,pc)
                 * }
                 * */

                // TODO jun: Try to break up this emitter without while retaining theoretical meaning
                int bp = (int)FusionCore.DSASM.Constants.kInvalidIndex;
                int L1 = (int)FusionCore.DSASM.Constants.kInvalidIndex;
                int L2 = (int)FusionCore.DSASM.Constants.kInvalidIndex;
                FusionCore.DSASM.Operand opCX;


                // If-expr
                IfStmtNode ifnode = node as IfStmtNode;
                dfsTraverse(ifnode.IfExprNode);

                emit("pop " + FusionCore.DSASM.kw.regCX + FusionCore.DSASM.Constants.termline);
                opCX.optype = FusionCore.DSASM.AddressType.Register;
                opCX.opdata = (int)FusionCore.DSASM.Registers.CX;
                emitPop(opCX);

                L1 = pc + 1;
                L2 = (int)FusionCore.DSASM.Constants.kInvalidIndex;
                bp = pc;
                emitCJmp(L1, L2);

                // If-body
                foreach (Node ifBody in ifnode.IfBody)
                {
                    dfsTraverse(ifBody);
                }

                L1 = (int)FusionCore.DSASM.Constants.kInvalidIndex;
                backpatchTable.append(pc, L1);
                emitJmp(L1);
                backpatch(bp, pc);


                /*
                 * else if(E)	->	traverse E
                 *              L1 = pc + 1
                 *                              L2 = null
                 *              bp = pc
                 *                              emit(jmp, _cx, L1, L2)
                 * {
                 *  S		->	traverse S
                 *              L1 = null
                 *              bpTable.append(pc)
                 *                          emit(jmp,labelEnd)
                 *                          backpatch(bp,pc)
                 * }
                 * */

                // Elseif-expr
                foreach (ElseIfBlock elseifNode in ifnode.ElseIfList)
                {
                    dfsTraverse(elseifNode.Expr);

                    emit("pop " + FusionCore.DSASM.kw.regCX + FusionCore.DSASM.Constants.termline);
                    opCX.optype = FusionCore.DSASM.AddressType.Register;
                    opCX.opdata = (int)FusionCore.DSASM.Registers.CX;
                    emitPop(opCX);

                    L1 = pc + 1;
                    L2 = (int)FusionCore.DSASM.Constants.kInvalidIndex;
                    bp = pc;
                    emitCJmp(L1, L2);

                    // Elseif-body
                    if (null != elseifNode.Body)
                    {
                        foreach (Node elseifBody in elseifNode.Body)
                        {
                            dfsTraverse(elseifBody);
                        }
                    }

                    L1 = (int)FusionCore.DSASM.Constants.kInvalidIndex;
                    backpatchTable.append(pc, L1);
                    emitJmp(L1);
                    backpatch(bp, pc);
                }

                /*
                 * else
                 * {
                 *  S		->	traverse S
                 *              L1 = null
                 *              bpTable.append(pc)
                 *                          emit(jmp,labelEnd)
                 *                          backpatch(bp,pc)
                 * }
                 * */
                // Else-body
                if (null != ifnode.ElseBody)
                {
                    foreach (Node elseBody in ifnode.ElseBody)
                    {
                        dfsTraverse(elseBody);
                    }

                    L1 = (int)FusionCore.DSASM.Constants.kInvalidIndex;
                    backpatchTable.append(pc, L1);
                    emitJmp(L1);
                    //backpatch(bp, pc);
                }

                /*
                 *
                 *                    ->	backpatch(bpTable, pc)
                 */
                // ifstmt-exit
                backpatch(backpatchTable.backpatchList, pc);
            }
            else if (node is VarDeclNode)
            {
                VarDeclNode varNode = node as VarDeclNode;
                Allocate(varNode.NameNode.Value, functionindex, FusionCore.TypeSystem.getType(varNode.ArgumentType.Name));
            }
            else if (node is BinaryExpressionNode)
            {
                BinaryExpressionNode b = node as BinaryExpressionNode;
                if (Operator.assign != b.Operator)
                {
                    dfsTraverse(b.LeftNode);
                }
                dfsTraverse(b.RightNode);

                if (Operator.assign == b.Operator)
                {
                    if (b.LeftNode is TerminalNode)
                    {
                        TerminalNode t = b.LeftNode as TerminalNode;

                        bool   isReturn = false;
                        string s        = t.Value;
                        if (s == "return")
                        {
                            s = "_rx";
                            //isReturn = true;
                        }

                        // TODO jun: the emit string are only for console logging,
                        // wrap them together with the actual emit function and flag them out as needed
                        emit("pop " + s + FusionCore.DSASM.Constants.termline);

                        FusionCore.DSASM.Operand op = buildOperand(t);
                        emitPop(op);

                        //if (isReturn)
                        //{
                        //    emit("ret" + FusionCore.DSASM.Constants.termline);
                        //    emitReturn();
                        //    functionindex = (int)FusionCore.DSASM.Constants.kGlobalScope;
                        //}
                    }
                }
                else
                {
                    emit("pop " + FusionCore.DSASM.kw.regBX + FusionCore.DSASM.Constants.termline);
                    FusionCore.DSASM.Operand opBX;
                    opBX.optype = FusionCore.DSASM.AddressType.Register;
                    opBX.opdata = (int)FusionCore.DSASM.Registers.BX;
                    emitPop(opBX);


                    emit("pop " + FusionCore.DSASM.kw.regAX + FusionCore.DSASM.Constants.termline);
                    FusionCore.DSASM.Operand opAX;
                    opAX.optype = FusionCore.DSASM.AddressType.Register;
                    opAX.opdata = (int)FusionCore.DSASM.Registers.AX;
                    emitPop(opAX);


                    string op = getOperator(b.Operator);
                    emit(op + " " + FusionCore.DSASM.kw.regAX + ", " + FusionCore.DSASM.kw.regBX + FusionCore.DSASM.Constants.termline);
                    emitBinary(getOpCode(b.Operator), opAX, opBX);


                    emit("push " + FusionCore.DSASM.kw.regAX + FusionCore.DSASM.Constants.termline);
                    FusionCore.DSASM.Operand opRes;
                    opRes.optype = FusionCore.DSASM.AddressType.Register;
                    opRes.opdata = (int)FusionCore.DSASM.Registers.AX;
                    emitPush(opRes);
                }
            }
        }