Пример #1
0
 FusionCore.DSASM.Operand buildOperand(TerminalNode node)
 {
     FusionCore.DSASM.Operand op = new FusionCore.DSASM.Operand();
     op.optype = getOpType((FusionCore.PrimitiveType)node.type);
     if (FusionCore.DSASM.AddressType.VarIndex == op.optype)
     {
         //FusionCore.DSASM.SymbolNode
         int size = symbols.symbolList.Count;
         for (int n = 0; n < size; ++n)
         {
             // TODO jun: Hash the string
             if (functionindex == symbols.symbolList[n].functionIndex && symbols.symbolList[n].name == node.Value)
             {
                 op.opdata = n; // symbols.symbolList[n].index;
                 break;
             }
         }
     }
     else if (FusionCore.DSASM.AddressType.Int == op.optype)
     {
         op.opdata = System.Convert.ToInt32(node.Value);
     }
     else if (FusionCore.DSASM.AddressType.Register == op.optype)
     {
         op.opdata = (int)FusionCore.DSASM.Registers.RX;
     }
     else
     {
         Debug.Assert(false);
     }
     return(op);
 }
Пример #2
0
        private void emitCJmp(int L1, int L2)
        {
            emit(FusionCore.DSASM.kw.cjmp + " " + FusionCore.DSASM.kw.regCX + " L1(" + L1 + ") L2(" + L2 + ")" + FusionCore.DSASM.Constants.termline);

            FusionCore.DSASM.Instruction instr = new FusionCore.DSASM.Instruction();
            instr.opCode = FusionCore.DSASM.OpCode.CJMP;

            FusionCore.DSASM.Operand op1 = new FusionCore.DSASM.Operand();
            op1.optype = FusionCore.DSASM.AddressType.Register;
            op1.opdata = (int)FusionCore.DSASM.Registers.CX;
            instr.op1  = op1;

            FusionCore.DSASM.Operand op2 = new FusionCore.DSASM.Operand();
            op2.optype = FusionCore.DSASM.AddressType.LabelIndex;
            op2.opdata = L1;
            instr.op2  = op2;

            FusionCore.DSASM.Operand op3 = new FusionCore.DSASM.Operand();
            op3.optype = FusionCore.DSASM.AddressType.LabelIndex;
            op3.opdata = L2;
            instr.op3  = op3;

            pc++;
            executable.instructionList.Add(instr);
        }
Пример #3
0
        private void emitPush(FusionCore.DSASM.Operand op)
        {
            setEntry();
            FusionCore.DSASM.Instruction instr = new FusionCore.DSASM.Instruction();
            instr.opCode = FusionCore.DSASM.OpCode.PUSH;
            instr.op1    = op;

            pc++;
            executable.instructionList.Add(instr);
        }
Пример #4
0
        private void emitPop(FusionCore.DSASM.Operand op)
        {
            FusionCore.DSASM.Instruction instr = new FusionCore.DSASM.Instruction();
            instr.opCode = FusionCore.DSASM.OpCode.POP;
            instr.op1    = op;

            // For debugging, assert here but these should raise runtime errors in the VM
            Debug.Assert(FusionCore.DSASM.AddressType.VarIndex == op.optype || FusionCore.DSASM.AddressType.Register == op.optype);

            pc++;
            executable.instructionList.Add(instr);
        }
Пример #5
0
        private void emitCall(int funcIndex)
        {
            setEntry();
            FusionCore.DSASM.Instruction instr = new FusionCore.DSASM.Instruction();
            instr.opCode = FusionCore.DSASM.OpCode.CALL;

            FusionCore.DSASM.Operand op = new FusionCore.DSASM.Operand();
            op.optype = FusionCore.DSASM.AddressType.FunctionIndex;
            op.opdata = funcIndex;
            instr.op1 = op;

            pc++;
            executable.instructionList.Add(instr);
        }
Пример #6
0
        private void emitBinary(FusionCore.DSASM.OpCode opcode, FusionCore.DSASM.Operand op1, FusionCore.DSASM.Operand op2)
        {
            setEntry();
            FusionCore.DSASM.Instruction instr = new FusionCore.DSASM.Instruction();
            instr.opCode = opcode;
            instr.op1    = op1;
            instr.op2    = op2;

            // For debugging, assert here but these should raise runtime errors in the VM
            Debug.Assert(FusionCore.DSASM.AddressType.VarIndex == op1.optype || FusionCore.DSASM.AddressType.Register == op1.optype);

            pc++;
            executable.instructionList.Add(instr);
        }
Пример #7
0
        private void emitJmp(int L1)
        {
            emit(FusionCore.DSASM.kw.jmp + " L1(" + L1 + ")" + FusionCore.DSASM.Constants.termline);

            FusionCore.DSASM.Instruction instr = new FusionCore.DSASM.Instruction();
            instr.opCode = FusionCore.DSASM.OpCode.JMP;

            FusionCore.DSASM.Operand op1 = new FusionCore.DSASM.Operand();
            op1.optype = FusionCore.DSASM.AddressType.LabelIndex;
            op1.opdata = L1;
            instr.op1  = op1;

            pc++;
            executable.instructionList.Add(instr);
        }
Пример #8
0
        private void emitCJmp(int L1, int L2)
        {
            emit(FusionCore.DSASM.kw.cjmp + " " + FusionCore.DSASM.kw.regCX + " L1(" + L1 + ") L2(" + L2 + ")" + FusionCore.DSASM.Constants.termline);

            FusionCore.DSASM.Instruction instr = new FusionCore.DSASM.Instruction();
            instr.opCode = FusionCore.DSASM.OpCode.CJMP;
            
            FusionCore.DSASM.Operand op1 = new FusionCore.DSASM.Operand();
            op1.optype = FusionCore.DSASM.AddressType.Register;
            op1.opdata = (int)FusionCore.DSASM.Registers.CX;
            instr.op1 = op1;
            
            FusionCore.DSASM.Operand op2 = new FusionCore.DSASM.Operand();
            op2.optype = FusionCore.DSASM.AddressType.LabelIndex;
            op2.opdata = L1;
            instr.op2 = op2;

            FusionCore.DSASM.Operand op3 = new FusionCore.DSASM.Operand();
            op3.optype = FusionCore.DSASM.AddressType.LabelIndex;
            op3.opdata = L2;
            instr.op3 = op3;

            pc++;
            executable.instructionList.Add(instr);
        }
Пример #9
0
        private void emitJmp(int L1)
        {
            emit(FusionCore.DSASM.kw.jmp + " L1(" + L1 + ")" + FusionCore.DSASM.Constants.termline);

            FusionCore.DSASM.Instruction instr = new FusionCore.DSASM.Instruction();
            instr.opCode = FusionCore.DSASM.OpCode.JMP;

            FusionCore.DSASM.Operand op1 = new FusionCore.DSASM.Operand();
            op1.optype = FusionCore.DSASM.AddressType.LabelIndex;
            op1.opdata = L1;
            instr.op1 = op1;

            pc++;
            executable.instructionList.Add(instr);
        }
Пример #10
0
        private void emitCall(int funcIndex)
        {
            setEntry();
            FusionCore.DSASM.Instruction instr = new FusionCore.DSASM.Instruction();
            instr.opCode = FusionCore.DSASM.OpCode.CALL;

            FusionCore.DSASM.Operand op = new FusionCore.DSASM.Operand();
            op.optype = FusionCore.DSASM.AddressType.FunctionIndex;
            op.opdata = funcIndex;
            instr.op1 = op;

            pc++;
            executable.instructionList.Add(instr);
        }
Пример #11
0
 FusionCore.DSASM.Operand buildOperand(TerminalNode node)
 {
     FusionCore.DSASM.Operand op = new FusionCore.DSASM.Operand();
     op.optype = getOpType((FusionCore.PrimitiveType)node.type);
     if (FusionCore.DSASM.AddressType.VarIndex == op.optype)
     {
         //FusionCore.DSASM.SymbolNode
         int size = symbols.symbolList.Count;
         for (int n = 0; n < size; ++n)
         {
             // TODO jun: Hash the string
             if (functionindex == symbols.symbolList[n].functionIndex && symbols.symbolList[n].name == node.Value)
             {
                 op.opdata = n; // symbols.symbolList[n].index;
                 break;
             }
         }
     }
     else if (FusionCore.DSASM.AddressType.Int == op.optype)
     {
         op.opdata = System.Convert.ToInt32(node.Value);
     }
     else if (FusionCore.DSASM.AddressType.Register == op.optype)
     {
         op.opdata = (int)FusionCore.DSASM.Registers.RX;
     }
     else
     {
         Debug.Assert(false);
     }
     return op;
 }
Пример #12
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);
                }
            }
        }