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); } } }
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); } } }