private void EmitIfStatementNode(AssociativeNode node, ref ProtoCore.Type inferedType, ProtoCore.AssociativeGraph.GraphNode graphNode = null) { int bp = (int)ProtoCore.DSASM.Constants.kInvalidIndex; int L1 = (int)ProtoCore.DSASM.Constants.kInvalidIndex; // If-expr IfStatementNode ifnode = node as IfStatementNode; DfsTraverse(ifnode.ifExprNode, ref inferedType, false, graphNode); L1 = ProtoCore.DSASM.Constants.kInvalidIndex; bp = pc; EmitCJmp(L1); // Create a new codeblock for this block // Set the current codeblock as the parent of the new codeblock // Set the new codeblock as a new child of the current codeblock // Set the new codeblock as the current codeblock ProtoCore.DSASM.CodeBlock localCodeBlock = new ProtoCore.DSASM.CodeBlock( context.guid, ProtoCore.DSASM.CodeBlockType.kConstruct, Language.NotSpecified, core.CodeBlockIndex++, new ProtoCore.DSASM.SymbolTable(GetConstructBlockName("if"), core.RuntimeTableIndex++), null, false, core); localCodeBlock.instrStream = codeBlock.instrStream; localCodeBlock.parent = codeBlock; codeBlock.children.Add(localCodeBlock); codeBlock = localCodeBlock; // If-body foreach (AssociativeNode ifBody in ifnode.IfBody) { inferedType = new ProtoCore.Type(); inferedType.UID = (int)PrimitiveType.kTypeVar; DfsTraverse(ifBody, ref inferedType, false, graphNode); } // Restore - Set the local codeblock parent to be the current codeblock codeBlock = localCodeBlock.parent; L1 = ProtoCore.DSASM.Constants.kInvalidIndex; BackpatchTable backpatchTable = new BackpatchTable(); backpatchTable.Append(pc, L1); EmitJmp(L1); // Backpatch the L2 destination of the if block 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 /* else { S -> traverse S L1 = null bpTable.append(pc) emit(jmp,labelEnd) backpatch(bp,pc) } * */ // Else-body Validity.Assert(null != ifnode.ElseBody); if (0 != ifnode.ElseBody.Count) { // Create a new symboltable for this block // Set the current table as the parent of the new table // Set the new table as a new child of the current table // Set the new table as the current table // Create a new codeblock for this block // Set the current codeblock as the parent of the new codeblock // Set the new codeblock as a new child of the current codeblock // Set the new codeblock as the current codeblock localCodeBlock = new ProtoCore.DSASM.CodeBlock( context.guid, ProtoCore.DSASM.CodeBlockType.kConstruct, Language.NotSpecified, core.CodeBlockIndex++, new ProtoCore.DSASM.SymbolTable(GetConstructBlockName("else"), core.RuntimeTableIndex++), null, false, core); localCodeBlock.instrStream = codeBlock.instrStream; localCodeBlock.parent = codeBlock; codeBlock.children.Add(localCodeBlock); codeBlock = localCodeBlock; foreach (AssociativeNode elseBody in ifnode.ElseBody) { inferedType = new ProtoCore.Type(); inferedType.UID = (int)PrimitiveType.kTypeVar; DfsTraverse(elseBody, ref inferedType, false, graphNode); } // Restore - Set the local codeblock parent to be the current codeblock codeBlock = localCodeBlock.parent; L1 = ProtoCore.DSASM.Constants.kInvalidIndex; backpatchTable.Append(pc, L1); EmitJmp(L1); } /* * -> backpatch(bpTable, pc) */ // ifstmt-exit // Backpatch all the previous unconditional jumps Backpatch(backpatchTable.backpatchList, pc); }
private void EmitIfStmtNode(ImperativeNode node, ref ProtoCore.Type inferedType, ProtoCore.AST.ImperativeAST.BinaryExpressionNode parentNode = null, bool isForInlineCondition = false, ProtoCore.AssociativeGraph.GraphNode graphNode = null) { if (IsParsingGlobal() || IsParsingGlobalFunctionBody()) { /* 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) } * */ int bp = (int)ProtoCore.DSASM.Constants.kInvalidIndex; int L1 = (int)ProtoCore.DSASM.Constants.kInvalidIndex; int L2 = (int)ProtoCore.DSASM.Constants.kInvalidIndex; ProtoCore.DSASM.StackValue opCX = new ProtoCore.DSASM.StackValue(); // If-expr IfStmtNode ifnode = node as IfStmtNode; DfsTraverse(ifnode.IfExprNode, ref inferedType, false, graphNode, AssociativeSubCompilePass.kNone, parentNode); EmitInstrConsole(ProtoCore.DSASM.kw.pop, ProtoCore.DSASM.kw.regCX); opCX.optype = ProtoCore.DSASM.AddressType.Register; opCX.opdata = (int)ProtoCore.DSASM.Registers.CX; EmitPop(opCX, Constants.kGlobalScope); L1 = pc + 1; L2 = ProtoCore.DSASM.Constants.kInvalidIndex; bp = pc; EmitCJmp(L1, L2, ifnode.IfExprNode.line, ifnode.IfExprNode.col, ifnode.IfExprNode.endLine, ifnode.IfExprNode.endCol); if (!isForInlineCondition) { EmitSetExpressionUID(compileStateTracker.ExpressionUID++); } // Create a new codeblock for this block // Set the current codeblock as the parent of the new codeblock // Set the new codeblock as a new child of the current codeblock // Set the new codeblock as the current codeblock ProtoCore.DSASM.CodeBlock localCodeBlock = new ProtoCore.DSASM.CodeBlock( ProtoCore.DSASM.CodeBlockType.kConstruct, Language.kInvalid, compileStateTracker.CodeBlockIndex++, new ProtoCore.DSASM.SymbolTable(GetConstructBlockName("if"), compileStateTracker.RuntimeTableIndex++), null); localCodeBlock.instrStream = codeBlock.instrStream; localCodeBlock.parent = codeBlock; codeBlock.children.Add(localCodeBlock); codeBlock = localCodeBlock; compileStateTracker.CompleteCodeBlockList.Add(localCodeBlock); EmitPushBlockID(localCodeBlock.codeBlockId); // If-body foreach (ImperativeNode ifBody in ifnode.IfBody) { inferedType = new ProtoCore.Type(); inferedType.UID = (int)PrimitiveType.kTypeVar; DfsTraverse(ifBody, ref inferedType, false, graphNode, AssociativeSubCompilePass.kNone, parentNode); } if (!isForInlineCondition) { ProtoCore.AST.Node oldBlockNode = localCodeBlockNode; localCodeBlockNode = ifnode.IfBodyPosition; EmitInstrConsole(ProtoCore.DSASM.kw.retcn); EmitRetcn(localCodeBlock.codeBlockId); localCodeBlockNode = oldBlockNode; } // Restore - Set the local codeblock parent to be the current codeblock codeBlock = localCodeBlock.parent; L1 = ProtoCore.DSASM.Constants.kInvalidIndex; BackpatchTable backpatchTable = new BackpatchTable(); backpatchTable.Append(pc, L1); EmitJmp(L1); EmitPopBlockID(); // Backpatch the L2 destination of the if block 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, ref inferedType, false, graphNode); EmitInstrConsole(ProtoCore.DSASM.kw.pop, ProtoCore.DSASM.kw.regCX); opCX.optype = ProtoCore.DSASM.AddressType.Register; opCX.opdata = (int)ProtoCore.DSASM.Registers.CX; EmitPop(opCX, Constants.kGlobalScope); L1 = pc + 1; L2 = ProtoCore.DSASM.Constants.kInvalidIndex; bp = pc; EmitCJmp(L1, L2, elseifNode.Expr.line, elseifNode.Expr.col, elseifNode.Expr.endLine, elseifNode.Expr.endCol); EmitSetExpressionUID(compileStateTracker.ExpressionUID++); // Elseif-body if (null != elseifNode.Body) { // Create a new codeblock for this block // Set the current codeblock as the parent of the new codeblock // Set the new codeblock as a new child of the current codeblock // Set the new codeblock as the current codeblock localCodeBlock = new ProtoCore.DSASM.CodeBlock( ProtoCore.DSASM.CodeBlockType.kConstruct, Language.kInvalid, compileStateTracker.CodeBlockIndex++, new ProtoCore.DSASM.SymbolTable(GetConstructBlockName("elseif"), compileStateTracker.RuntimeTableIndex++), null); localCodeBlock.instrStream = codeBlock.instrStream; localCodeBlock.parent = codeBlock; codeBlock.children.Add(localCodeBlock); codeBlock = localCodeBlock; compileStateTracker.CompleteCodeBlockList.Add(localCodeBlock); EmitPushBlockID(localCodeBlock.codeBlockId); foreach (ImperativeNode elseifBody in elseifNode.Body) { inferedType = new ProtoCore.Type(); inferedType.UID = (int)PrimitiveType.kTypeVar; DfsTraverse(elseifBody, ref inferedType, false, graphNode); } if (!isForInlineCondition) { ProtoCore.AST.Node oldBlockNode = localCodeBlockNode; localCodeBlockNode = elseifNode.ElseIfBodyPosition; EmitInstrConsole(ProtoCore.DSASM.kw.retcn); EmitRetcn(localCodeBlock.codeBlockId); localCodeBlockNode = oldBlockNode; } // Restore - Set the local codeblock parent to be the current codeblock codeBlock = localCodeBlock.parent; } L1 = ProtoCore.DSASM.Constants.kInvalidIndex; backpatchTable.Append(pc, L1); EmitJmp(L1); EmitPopBlockID(); // Backpatch the L2 destination of the elseif block Backpatch(bp, pc); } /* else { S -> traverse S L1 = null bpTable.append(pc) emit(jmp,labelEnd) backpatch(bp,pc) } * */ // Else-body Debug.Assert(null != ifnode.ElseBody); if (0 != ifnode.ElseBody.Count) { // Create a new symboltable for this block // Set the current table as the parent of the new table // Set the new table as a new child of the current table // Set the new table as the current table // Create a new codeblock for this block // Set the current codeblock as the parent of the new codeblock // Set the new codeblock as a new child of the current codeblock // Set the new codeblock as the current codeblock localCodeBlock = new ProtoCore.DSASM.CodeBlock( ProtoCore.DSASM.CodeBlockType.kConstruct, Language.kInvalid, compileStateTracker.CodeBlockIndex++, new ProtoCore.DSASM.SymbolTable(GetConstructBlockName("else"), compileStateTracker.RuntimeTableIndex++), null); localCodeBlock.instrStream = codeBlock.instrStream; localCodeBlock.parent = codeBlock; codeBlock.children.Add(localCodeBlock); codeBlock = localCodeBlock; compileStateTracker.CompleteCodeBlockList.Add(localCodeBlock); EmitPushBlockID(localCodeBlock.codeBlockId); foreach (ImperativeNode elseBody in ifnode.ElseBody) { inferedType = new ProtoCore.Type(); inferedType.UID = (int)PrimitiveType.kTypeVar; DfsTraverse(elseBody, ref inferedType, false, graphNode, AssociativeSubCompilePass.kNone, parentNode); } if (!isForInlineCondition) { ProtoCore.AST.Node oldBlockNode = localCodeBlockNode; localCodeBlockNode = ifnode.ElseBodyPosition; EmitInstrConsole(ProtoCore.DSASM.kw.retcn); EmitRetcn(localCodeBlock.codeBlockId); localCodeBlockNode = oldBlockNode; } // Restore - Set the local codeblock parent to be the current codeblock codeBlock = localCodeBlock.parent; L1 = ProtoCore.DSASM.Constants.kInvalidIndex; backpatchTable.Append(pc, L1); EmitJmp(L1); EmitPopBlockID(); } /* * -> backpatch(bpTable, pc) */ // ifstmt-exit // Backpatch all the previous unconditional jumps Backpatch(backpatchTable.backpatchList, pc); } }
protected void EmitExceptionHandlingNode(ProtoCore.AST.Node node, ProtoCore.AssociativeGraph.GraphNode graphNode = null, ProtoCore.DSASM.AssociativeSubCompilePass subPass = ProtoCore.DSASM.AssociativeSubCompilePass.kNone) { #if ENABLE_EXCEPTION_HANDLING if (!IsParsingGlobal() && !IsParsingGlobalFunctionBody()) { return; } ExceptionHandlingNode exceptionNode = node as ExceptionHandlingNode; if (exceptionNode == null) return; tryLevel++; ExceptionHandler exceptionHandler = new ExceptionHandler(); exceptionHandler.TryLevel = tryLevel; ExceptionRegistration registration = core.ExceptionHandlingManager.Register(codeBlock.codeBlockId, globalProcIndex, globalClassIndex); registration.Add(exceptionHandler); exceptionHandler.StartPc = pc; TryBlockNode tryNode = exceptionNode.tryBlock; Debug.Assert(tryNode != null); foreach (var subnode in tryNode.body) { ProtoCore.Type inferedType = new ProtoCore.Type(); inferedType.UID = (int)ProtoCore.PrimitiveType.kTypeVar; inferedType.IsIndexable = false; DfsTraverse(subnode, ref inferedType, false, graphNode, subPass); } exceptionHandler.EndPc = pc; // Jmp to code after catch block BackpatchTable backpatchTable = new BackpatchTable(); backpatchTable.Append(pc); EmitJmp(ProtoCore.DSASM.Constants.kInvalidIndex); foreach (var catchBlock in exceptionNode.catchBlocks) { CatchHandler catchHandler = new CatchHandler(); exceptionHandler.AddCatchHandler(catchHandler); CatchFilterNode filterNode = catchBlock.catchFilter; Debug.Assert(filterNode != null); catchHandler.FilterTypeUID = core.TypeSystem.GetType(filterNode.type.Name); if (catchHandler.FilterTypeUID == (int)PrimitiveType.kInvalidType) { string message = String.Format(ProtoCore.BuildData.WarningMessage.kExceptionTypeUndefined, filterNode.type.Name); buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kTypeUndefined, message, null, filterNode.line, filterNode.col); catchHandler.FilterTypeUID = (int)PrimitiveType.kTypeVar; } // For filter expression catch(e:int), generate an assignment // e = LX; catchHandler.Entry = pc; EmitInstrConsole(ProtoCore.DSASM.kw.push, ProtoCore.DSASM.kw.regLX); ProtoCore.DSASM.StackValue opLx = new ProtoCore.DSASM.StackValue(); opLx.optype = ProtoCore.DSASM.AddressType.Register; opLx.opdata = (int)ProtoCore.DSASM.Registers.LX; EmitPush(opLx); ProtoCore.DSASM.SymbolNode excpVarSymbol = null; bool stub; bool isAllocated = VerifyAllocation(filterNode.var.Value, globalClassIndex, globalProcIndex, out excpVarSymbol, out stub); int runtimeIndex = (!isAllocated) ? codeBlock.symbolTable.runtimeIndex : excpVarSymbol.runtimeTableIndex; if (!isAllocated) { excpVarSymbol = Allocate(filterNode.var.Value, globalProcIndex, new ProtoCore.Type()); } EmitPushVarData(runtimeIndex, 0, (int)PrimitiveType.kTypeVar, 0); EmitInstrConsole(ProtoCore.DSASM.kw.pop, filterNode.var.Value); EmitPopForSymbol(excpVarSymbol, filterNode.var.line, filterNode.var.col, filterNode.var.endLine, filterNode.var.endCol); ProtoCore.Type inferedType = new ProtoCore.Type(); inferedType.UID = (int)ProtoCore.PrimitiveType.kTypeVar; inferedType.IsIndexable = false; foreach (var subnode in catchBlock.body) { inferedType.UID = (int)ProtoCore.PrimitiveType.kTypeVar; inferedType.IsIndexable = false; DfsTraverse(subnode, ref inferedType, false, graphNode, subPass); } // Jmp to code after catch block backpatchTable.Append(pc); EmitJmp(ProtoCore.DSASM.Constants.kInvalidIndex); } Backpatch(backpatchTable.backpatchList, pc); tryLevel--; #endif }
protected void EmitExceptionHandlingNode(AssociativeNode node, ProtoCore.AssociativeGraph.GraphNode graphNode = null, ProtoCore.DSASM.AssociativeSubCompilePass subPass = ProtoCore.DSASM.AssociativeSubCompilePass.kNone) { #if ENABLE_EXCEPTION_HANDLING if (!IsParsingGlobal() && !IsParsingGlobalFunctionBody() && !IsParsingMemberFunctionBody()) { return; } tryLevel++; ExceptionHandlingNode exceptionNode = node as ExceptionHandlingNode; if (exceptionNode == null) return; ExceptionHandler exceptionHandler = new ExceptionHandler(); exceptionHandler.TryLevel = tryLevel; ExceptionRegistration registration = core.ExceptionHandlingManager.Register(codeBlock.codeBlockId, globalProcIndex, globalClassIndex); registration.Add(exceptionHandler); exceptionHandler.StartPc = pc; TryBlockNode tryNode = exceptionNode.tryBlock; Debug.Assert(tryNode != null); foreach (var subnode in tryNode.body) { ProtoCore.Type inferedType = new ProtoCore.Type(); inferedType.UID = (int) ProtoCore.PrimitiveType.kTypeVar; inferedType.IsIndexable = false; DfsTraverse(subnode, ref inferedType, false, graphNode, subPass); } exceptionHandler.EndPc = pc; // Jmp to code after catch block BackpatchTable backpatchTable = new BackpatchTable(); backpatchTable.Append(pc); EmitJmp(ProtoCore.DSASM.Constants.kInvalidIndex); foreach (var catchBlock in exceptionNode.catchBlocks) { CatchHandler catchHandler = new CatchHandler(); exceptionHandler.AddCatchHandler(catchHandler); CatchFilterNode filterNode = catchBlock.catchFilter; Debug.Assert(filterNode != null); catchHandler.FilterTypeUID = core.TypeSystem.GetType(filterNode.type.Name); if (catchHandler.FilterTypeUID == (int)PrimitiveType.kInvalidType) { string message = String.Format(ProtoCore.BuildData.WarningMessage.kExceptionTypeUndefined, filterNode.type.Name); buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kTypeUndefined, message, core.CurrentDSFileName, filterNode.line, filterNode.col); catchHandler.FilterTypeUID = (int)PrimitiveType.kTypeVar; } ProtoCore.Type inferedType = new ProtoCore.Type(); inferedType.UID = (int) ProtoCore.PrimitiveType.kTypeVar; inferedType.IsIndexable = false; DfsTraverse(filterNode.var, ref inferedType, false, graphNode, subPass); catchHandler.Entry = pc; foreach (var subnode in catchBlock.body) { inferedType.UID = (int) ProtoCore.PrimitiveType.kTypeVar; inferedType.IsIndexable = false; DfsTraverse(subnode, ref inferedType, false, graphNode, subPass); } // Jmp to code after catch block backpatchTable.Append(pc); EmitJmp(ProtoCore.DSASM.Constants.kInvalidIndex); } Backpatch(backpatchTable.backpatchList, pc); tryLevel--; #endif }