public override bool Compile( out int blockId, ProtoCore.DSASM.CodeBlock parentBlock, ProtoCore.LanguageCodeBlock langBlock, ProtoCore.CompileTime.Context callContext, ProtoCore.DebugServices.EventSink sink = null, ProtoCore.AST.Node codeBlockNode = null, ProtoCore.AssociativeGraph.GraphNode graphNode = null) { Validity.Assert(langBlock != null); bool buildSucceeded = true; blockId = 0; core.assocCodegen = new ProtoVHDL.CodeGen(core, callContext, parentBlock); System.IO.MemoryStream memstream = new System.IO.MemoryStream(System.Text.Encoding.UTF8.GetBytes(langBlock.body)); ProtoCore.DesignScriptParser.Scanner s = new ProtoCore.DesignScriptParser.Scanner(memstream); ProtoCore.DesignScriptParser.Parser p = new ProtoCore.DesignScriptParser.Parser(s, core, core.builtInsLoaded); p.Parse(); core.builtInsLoaded = true; codeBlockNode = p.root; List <ProtoCore.AST.Node> astNodes = ProtoCore.Utils.ParserUtils.GetAstNodes(codeBlockNode); core.AstNodeList = astNodes; core.assocCodegen.Emit(codeBlockNode as ProtoCore.AST.AssociativeAST.CodeBlockNode); buildSucceeded = core.BuildStatus.BuildSucceeded; return(buildSucceeded); }
public override bool Compile(out int blockId, ProtoCore.DSASM.CodeBlock parentBlock, ProtoCore.LanguageCodeBlock langBlock, ProtoCore.CompileTime.Context callContext, ProtoCore.DebugServices.EventSink sink, ProtoCore.AST.Node codeBlockNode, ProtoCore.AssociativeGraph.GraphNode graphNode = null) { Validity.Assert(langBlock != null); blockId = ProtoCore.DSASM.Constants.kInvalidIndex; bool buildSucceeded = false; bool isLanguageSignValid = isLanguageSignValid = core.Langverify.Verify(langBlock); if (isLanguageSignValid) { try { ProtoImperative.CodeGen codegen = new ProtoImperative.CodeGen(core, callContext, parentBlock); codegen.context = callContext; codegen.codeBlock.EventSink = sink; blockId = codegen.Emit(codeBlockNode as ProtoCore.AST.ImperativeAST.CodeBlockNode, graphNode); } catch (ProtoCore.BuildHaltException) { } buildSucceeded = core.BuildStatus.BuildSucceeded; } return(buildSucceeded); }
public CodeGen(ProtoLanguage.CompileStateTracker coreObj, ProtoCore.DSASM.CodeBlock parentBlock = null) : base(coreObj, parentBlock) { // dumpbytecode is optionally enabled // astNodes = new List<ImperativeNode>(); SetCompileOptions(); // Create a new symboltable for this block // Set the new symbol table's parent // Set the new table as a child of the parent table codeBlock = new ProtoCore.DSASM.CodeBlock( ProtoCore.DSASM.CodeBlockType.kLanguage, ProtoCore.Language.kImperative, compileStateTracker.CodeBlockIndex, new ProtoCore.DSASM.SymbolTable("imperative lang block", compileStateTracker.RuntimeTableIndex), new ProtoCore.DSASM.ProcedureTable(compileStateTracker.RuntimeTableIndex), false, compileStateTracker); ++compileStateTracker.CodeBlockIndex; ++compileStateTracker.RuntimeTableIndex; if (null == parentBlock) { // This is a top level block compileStateTracker.CodeBlockList.Add(codeBlock); } else { // This is a nested block parentBlock.children.Add(codeBlock); codeBlock.parent = parentBlock; } compileStateTracker.CompleteCodeBlockList.Add(codeBlock); blockScope = 0; // Bouncing to this language codeblock from a function should immediatlet se the first instruction as the entry point if (ProtoCore.DSASM.Constants.kGlobalScope != globalProcIndex) { isEntrySet = true; codeBlock.instrStream.entrypoint = 0; } backpatchMap = new BackpatchMap(); nodeBuilder = new NodeBuilder(compileStateTracker); }
public override bool Compile(out int blockId, ProtoCore.DSASM.CodeBlock parentBlock, ProtoCore.LanguageCodeBlock langBlock, ProtoCore.CompileTime.Context callContext, ProtoCore.DebugServices.EventSink sink, ProtoCore.AST.Node codeBlockNode, ProtoCore.AssociativeGraph.GraphNode graphNode = null) { Validity.Assert(langBlock != null); blockId = ProtoCore.DSASM.Constants.kInvalidIndex; bool buildSucceeded = false; bool isLanguageSignValid = isLanguageSignValid = core.Langverify.Verify(langBlock); if (isLanguageSignValid) { try { ProtoImperative.CodeGen codegen = new ProtoImperative.CodeGen(core, parentBlock); //(Fuqiang, Ayush) : The below code is to parse an Imperative code block. An imoerative code block should // never need to be parsed at this stage, as it would be parsed by the Assoc parser. //System.IO.MemoryStream memstream = new System.IO.MemoryStream(System.Text.Encoding.UTF8.GetBytes(langBlock.body)); //ProtoCore.DesignScriptParser.Scanner s = new ProtoCore.DesignScriptParser.Scanner(memstream); //ProtoCore.DesignScriptParser.Parser p = new ProtoCore.DesignScriptParser.Parser(s, core); //System.IO.StringWriter parseErrors = new System.IO.StringWriter(); //p.errors.errorStream = parseErrors; //p.Parse(); //if (parseErrors.ToString() != String.Empty) //{ // core.BuildStatus.LogSyntaxError(parseErrors.ToString()); //} //core.BuildStatus.errorCount += p.errors.count; codegen.context = callContext; codegen.codeBlock.EventSink = sink; blockId = codegen.Emit(codeBlockNode as ProtoCore.AST.ImperativeAST.CodeBlockNode, graphNode); } catch (ProtoCore.BuildHaltException e) { #if DEBUG //core.BuildStatus.LogSemanticError(e.errorMsg); #endif } buildSucceeded = core.BuildStatus.BuildSucceeded; } return(buildSucceeded); }
private void EmitForLoopNode(ImperativeNode node, ref ProtoCore.Type inferredType, bool isBooleanOp = false, ProtoCore.AssociativeGraph.GraphNode graphNode = null) { if (core.IsParsingCodeBlockNode || core.IsParsingPreloadedAssembly) { return; } if (IsParsingGlobal() || IsParsingGlobalFunctionBody()) { /* x = 0; a = {10,20,30,40} for(val in a) { x = x + val; } Compiles down to: x = 0; a = {10,20,30,40}; val = null; %forloop_key = a.key; %forloop_expr = a; while( %forloop_key != null) { val = %forloop_expr[%forloop_key]; %forloop_key = %forloop_key + 1; x = x + val; } */ DebugProperties.BreakpointOptions oldOptions = core.DebuggerProperties.breakOptions; DebugProperties.BreakpointOptions newOptions = oldOptions; newOptions |= DebugProperties.BreakpointOptions.EmitCallrForTempBreakpoint; core.DebuggerProperties.breakOptions = newOptions; // TODO Jun: This compilation unit has many opportunities for optimization // 1. Compiling to while need not be necessary if 'expr' has exactly one element // 2. For-loop can have its own semantics without the need to convert to a while node ForLoopNode forNode = node as ForLoopNode; ++core.ForLoopBlockIndex; //new forloop beginning. increment loop counter // Insert a dummy block for for-loop so that loopvar is in scope. ProtoCore.DSASM.CodeBlock localCodeBlock = new ProtoCore.DSASM.CodeBlock( context.guid, ProtoCore.DSASM.CodeBlockType.kConstruct, Language.kInvalid, core.CodeBlockIndex++, new ProtoCore.DSASM.SymbolTable(GetConstructBlockName("dummy"), core.RuntimeTableIndex++), null, true, core); core.CodeBlockIndex++; localCodeBlock.instrStream = codeBlock.instrStream; localCodeBlock.parent = codeBlock; codeBlock.children.Add(localCodeBlock); codeBlock = localCodeBlock; EmitPushBlockID(localCodeBlock.codeBlockId); ProtoCore.Type type = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVoid, 0); // val = null; IdentifierNode loopvar = nodeBuilder.BuildIdentfier(forNode.loopVar.Name) as IdentifierNode; { loopvar.ArrayName = forNode.expression.Name; ProtoCore.Utils.NodeUtils.CopyNodeLocation(loopvar, forNode.loopVar); BinaryExpressionNode loopvarInit = new BinaryExpressionNode(); loopvarInit.Optr = ProtoCore.DSASM.Operator.assign; loopvarInit.LeftNode = loopvar; loopvarInit.RightNode = new NullNode(); ProtoCore.Utils.NodeUtils.CopyNodeLocation(loopvarInit, forNode); loopvarInit.endLine = loopvarInit.line; loopvarInit.endCol = loopvarInit.col + 3; EmitBinaryExpressionNode(loopvarInit, ref type, isBooleanOp, graphNode); } // %key = null; string keyIdent = GetForLoopKeyIdent(); Allocate(keyIdent, globalProcIndex, TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVoid, 0)); var key = nodeBuilder.BuildIdentfier(keyIdent); // %array = complicated expr in for...in loop, so that we could // index into it. string identName = GetForExprIdent(); var arrayExpr = nodeBuilder.BuildIdentfier(identName); NodeUtils.CopyNodeLocation(arrayExpr, forNode.expression); BinaryExpressionNode arrayexprAssignment = new BinaryExpressionNode(); arrayexprAssignment.Optr = ProtoCore.DSASM.Operator.assign; arrayexprAssignment.LeftNode = arrayExpr; arrayexprAssignment.RightNode = forNode.expression; NodeUtils.UpdateBinaryExpressionLocation(arrayexprAssignment); switch (forNode.expression.GetType().ToString()) { case "ProtoCore.AST.ImperativeAST.IdentifierNode": case "ProtoCore.AST.ImperativeAST.ExprListNode": newOptions |= DebugProperties.BreakpointOptions.EmitPopForTempBreakpoint; core.DebuggerProperties.breakOptions = newOptions; break; } type.UID = (int)ProtoCore.PrimitiveType.kTypeVoid; EmitBinaryExpressionNode(arrayexprAssignment, ref type, isBooleanOp, graphNode); core.DebuggerProperties.breakOptions = oldOptions; // Restore breakpoint behaviors. // Get the size of expr and assign it to the autogen iteration var int symbolIndex = Constants.kInvalidIndex; SymbolNode symbol = null; if (ProtoCore.DSASM.Constants.kInvalidIndex != globalClassIndex && !IsInLanguageBlockDefinedInFunction()) { symbolIndex = core.ClassTable.ClassNodes[globalClassIndex].symbols.IndexOf(identName); if (symbolIndex != Constants.kInvalidIndex) { symbol = core.ClassTable.ClassNodes[globalClassIndex].symbols.symbolList[symbolIndex]; } } else { symbolIndex = codeBlock.symbolTable.IndexOf(identName); if (symbolIndex != Constants.kInvalidIndex) { symbol = codeBlock.symbolTable.symbolList[symbolIndex]; } } EmitInstrConsole(ProtoCore.DSASM.kw.pushvarsize, identName); EmitPushArrayKey(symbolIndex, codeBlock.symbolTable.RuntimeIndex, (symbol == null) ? globalClassIndex : symbol.classScope); // Push the identifier local block information // Push the array dimensions int dimensions = 0; EmitPushVarData(dimensions); if (ProtoCore.DSASM.Constants.kInvalidIndex != globalClassIndex && !IsInLanguageBlockDefinedInFunction()) { symbolIndex = core.ClassTable.ClassNodes[globalClassIndex].symbols.IndexOf(keyIdent); if (symbolIndex != Constants.kInvalidIndex) { symbol = core.ClassTable.ClassNodes[globalClassIndex].symbols.symbolList[symbolIndex]; } } else { symbolIndex = codeBlock.symbolTable.IndexOf(keyIdent); if (symbolIndex != Constants.kInvalidIndex) { symbol = codeBlock.symbolTable.symbolList[symbolIndex]; } } StackValue opDest = StackValue.BuildVarIndex(symbolIndex); EmitInstrConsole(ProtoCore.DSASM.kw.pop, keyIdent); EmitPop(opDest, (symbol == null) ? globalClassIndex : symbol.classScope, symbol.runtimeTableIndex); // key == null ? BinaryExpressionNode condition = new BinaryExpressionNode(); { condition.Optr = ProtoCore.DSASM.Operator.nq; condition.LeftNode = key; condition.RightNode = new NullNode(); condition.line = forNode.KwInLine; condition.col = forNode.KwInCol; condition.endLine = forNode.KwInLine; condition.endCol = forNode.KwInCol + 2; // 2 character for keyword "in". } // val = array[key]; BinaryExpressionNode arrayIndexing = new BinaryExpressionNode(); { arrayIndexing.Optr = ProtoCore.DSASM.Operator.assign; arrayIndexing.LeftNode = loopvar; // Array index into the expr ident ArrayNode arrayIndex = new ArrayNode(); arrayIndex.Expr = key; arrayIndex.Type = null; (arrayExpr as IdentifierNode).ArrayDimensions = arrayIndex; arrayIndexing.RightNode = arrayExpr; arrayIndexing.line = loopvar.line; arrayIndexing.col = loopvar.col; arrayIndexing.endLine = loopvar.endLine; arrayIndexing.endCol = loopvar.endCol; } // key = key + 1; BinaryExpressionNode nextKey = new BinaryExpressionNode(); { nextKey.LeftNode = key; nextKey.Optr = Operator.assign; nextKey.RightNode = nodeBuilder.BuildBinaryExpression(key, new IntNode(1), Operator.add); } // Append the array indexing and key increment expressions into // the for-loop body forNode.body.Insert(0, arrayIndexing); forNode.body.Insert(1, nextKey); // Construct and populate the equivalent while node WhileStmtNode whileStatement = new WhileStmtNode(); whileStatement.Expr = condition; whileStatement.Body = forNode.body; whileStatement.endLine = node.endLine; whileStatement.endCol = node.endCol; type.UID = (int)ProtoCore.PrimitiveType.kTypeVoid; EmitWhileStmtNode(whileStatement, ref type, isBooleanOp, graphNode); // As we add a dummy code block around forloop node, RETCN // instruction will get debugging information from // localCodeBlockNode, which is forloop node. We temporarily set // lcoalCodeBlockNode to a dummy node so that RETCN won't have // debugging information. var dummyCodeBlockNode = new CodeBlockNode(); var backUpLocalCodeBlockNode = localCodeBlockNode; localCodeBlockNode = dummyCodeBlockNode; EmitInstrConsole(ProtoCore.DSASM.kw.retcn); EmitRetcn(localCodeBlock.codeBlockId); codeBlock = localCodeBlock.parent; localCodeBlockNode = backUpLocalCodeBlockNode; //} // Comment Jun: The for loop counter must be unique and does not need to reset //forloopCounter--; //for loop ended. decrement counter } }
private void ProcessCodeBlock(CodeBlock codeBlock) { if (null == codeBlock) return; int parent = ((null == codeBlock.parent) ? -1 : codeBlock.parent.codeBlockId); DefineHierarchy(parent, codeBlock.codeBlockId, false); ProcedureTable procTable = codeBlock.procedureTable; foreach (ProcedureNode procNode in procTable.procList) ProcessProcedureNode(procNode); SymbolTable symbolTable = codeBlock.symbolTable; foreach (var symbolNode in symbolTable.symbolList) ProcessSymbolNode(symbolNode.Value); }
private ProtoCore.DSASM.CodeBlock BuildNewCodeBlock(ProcedureTable procTable = null) { ProcedureTable pTable = procTable == null ? new ProtoCore.DSASM.ProcedureTable(core.RuntimeTableIndex) : procTable; // Create a new symboltable for this block // Set the new symbol table's parent // Set the new table as a child of the parent table ProtoCore.DSASM.CodeBlock cb = new ProtoCore.DSASM.CodeBlock( context.guid, ProtoCore.DSASM.CodeBlockType.kLanguage, ProtoCore.Language.Associative, core.CodeBlockIndex, new ProtoCore.DSASM.SymbolTable("associative lang block", core.RuntimeTableIndex), pTable, false, core); ++core.CodeBlockIndex; ++core.RuntimeTableIndex; return cb; }
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); } }
private void BfsBuildProcedureTable(CodeBlock codeBlock, ProcedureTable[] procTable) { if (CodeBlockType.Language == codeBlock.blockType || CodeBlockType.Function == codeBlock.blockType) { Validity.Assert(codeBlock.procedureTable.RuntimeIndex < RuntimeTableIndex); procTable[codeBlock.procedureTable.RuntimeIndex] = codeBlock.procedureTable; } foreach (CodeBlock child in codeBlock.children) { BfsBuildProcedureTable(child, procTable); } }
public bool IsFunctionCodeBlock(CodeBlock cblock) { // Determine if the immediate block is a function block // Construct blocks are ignored Validity.Assert(null != cblock); while (null != cblock) { if (CodeBlockType.Function == cblock.blockType) { return true; } else if (CodeBlockType.Language == cblock.blockType) { return false; } cblock = cblock.parent; } return false; }
private void BfsBuildProcedureTable(CodeBlock codeBlock, ProcedureTable[] procTable) { if (DSASM.CodeBlockType.kLanguage == codeBlock.blockType || DSASM.CodeBlockType.kFunction == codeBlock.blockType) { Debug.Assert(codeBlock.procedureTable.runtimeIndex < RuntimeTableIndex); procTable[codeBlock.procedureTable.runtimeIndex] = codeBlock.procedureTable; } foreach (DSASM.CodeBlock child in codeBlock.children) { BfsBuildProcedureTable(child, procTable); } }
private void BfsBuildInstructionStreams(CodeBlock codeBlock, InstructionStream[] istreamList) { if (null != codeBlock) { if (DSASM.CodeBlockType.kLanguage == codeBlock.blockType || DSASM.CodeBlockType.kFunction == codeBlock.blockType) { Debug.Assert(codeBlock.codeBlockId < CodeBlockIndex); istreamList[codeBlock.codeBlockId] = codeBlock.instrStream; } foreach (DSASM.CodeBlock child in codeBlock.children) { BfsBuildInstructionStreams(child, istreamList); } } }
public bool IsFunctionCodeBlock(CodeBlock cblock) { // Determine if the immediate block is a function block // Construct blocks are ignored Debug.Assert(null != cblock); while (null != cblock) { if (ProtoCore.DSASM.CodeBlockType.kFunction == cblock.blockType) { return true; } else if (ProtoCore.DSASM.CodeBlockType.kLanguage == cblock.blockType) { return false; } cblock = cblock.parent; } return false; }
public SymbolNode GetFirstVisibleSymbol(string name, int classscope, int function, CodeBlock codeblock) { Validity.Assert(null != codeblock); int symbolIndex = Constants.kInvalidIndex; // For variables defined nested language block, their function index // is always Constants.kGlobalScope CodeBlock searchBlock = codeblock; while (searchBlock != null) { // For imported node, it is possbile that the block is not the // topmost block. // // For expression interpreter, as the code has been compiled, the // outmost block wouldn't be function block (CodeBlockType.Function). // CodeBlockType.Function is a temporary block type which is set when // the compile is generating code for function defintion node and will // be set back to Associative. var isSearchBoundry = searchBlock.blockType == CodeBlockType.Function || (Options.RunMode == InterpreterMode.Expression && searchBlock.parent == null); if (isSearchBoundry) { break; } symbolIndex = searchBlock.symbolTable.IndexOf(name, classscope, Constants.kGlobalScope); if (symbolIndex == Constants.kInvalidIndex) { searchBlock = searchBlock.parent; } else { return searchBlock.symbolTable.symbolList[symbolIndex]; } } // Search variable might be defined in function. // If we are not in class defintion, then just stop here, otherwise // we should search global block's symbol table. if (searchBlock != null && (searchBlock.blockType == CodeBlockType.Function || (Options.RunMode == InterpreterMode.Expression && searchBlock.parent == null)) && classscope == Constants.kGlobalScope) { symbolIndex = searchBlock.symbolTable.IndexOf(name, classscope, function); } return symbolIndex == Constants.kInvalidIndex ? null : searchBlock.symbolTable.symbolList[symbolIndex]; }
public static ProcedureNode GetFunctionByName(string name, CodeBlock codeBlock) { if (null == codeBlock) { return null; } CodeBlock searchBlock = codeBlock; while (null != searchBlock) { if (null == searchBlock.procedureTable) { searchBlock = searchBlock.parent; continue; } // The class table is passed just to check for coercion values var procNode = searchBlock.procedureTable.GetFunctionsByName(name).FirstOrDefault(); if (procNode != null) return procNode; searchBlock = searchBlock.parent; } return null; }
public SymbolNode GetSymbolInFunction(string name, int classScope, int functionScope, CodeBlock codeBlock) { Validity.Assert(functionScope != Constants.kGlobalScope); if (Constants.kGlobalScope == functionScope) { return null; } int symbolIndex = Constants.kInvalidIndex; if (classScope != Constants.kGlobalScope) { //Search local variable for the class member function symbolIndex = ClassTable.ClassNodes[classScope].Symbols.IndexOf(name, classScope, functionScope); if (symbolIndex != Constants.kInvalidIndex) { return ClassTable.ClassNodes[classScope].Symbols.symbolList[symbolIndex]; } //Search class members symbolIndex = ClassTable.ClassNodes[classScope].Symbols.IndexOf(name, classScope, Constants.kGlobalScope); if (symbolIndex != Constants.kInvalidIndex) { return ClassTable.ClassNodes[classScope].Symbols.symbolList[symbolIndex]; } } while (symbolIndex == Constants.kInvalidIndex && codeBlock != null && codeBlock.blockType != CodeBlockType.Function) { symbolIndex = codeBlock.symbolTable.IndexOf(name, classScope, functionScope); if (symbolIndex != Constants.kInvalidIndex) { return codeBlock.symbolTable.symbolList[symbolIndex]; } else { codeBlock = codeBlock.parent; } } if (symbolIndex == Constants.kInvalidIndex && codeBlock != null && codeBlock.blockType == CodeBlockType.Function) { symbolIndex = codeBlock.symbolTable.IndexOf(name, classScope, functionScope); if (symbolIndex != Constants.kInvalidIndex) { return codeBlock.symbolTable.symbolList[symbolIndex]; } } return null; }
public SymbolNode GetFirstVisibleSymbol(string name, int classscope, int function, CodeBlock codeblock) { // // Validity.Assert(null != codeblock); if (null == codeblock) { return null; } int symbolIndex = Constants.kInvalidIndex; bool stillInsideFunction = function != Constants.kInvalidIndex; CodeBlock searchBlock = codeblock; // TODO(Jiong): Code Duplication, Consider moving this if else block inside the while loop if (stillInsideFunction) { symbolIndex = searchBlock.symbolTable.IndexOf(name, classscope, function); if (function != Constants.kInvalidIndex && searchBlock.procedureTable != null && searchBlock.procedureTable.Procedures.Count > function && // Note: This check assumes we can not define functions inside a fucntion symbolIndex == Constants.kInvalidIndex) symbolIndex = searchBlock.symbolTable.IndexOf(name, classscope, Constants.kInvalidIndex); } else { symbolIndex = searchBlock.symbolTable.IndexOf(name, classscope, Constants.kInvalidIndex); } while (Constants.kInvalidIndex == symbolIndex) { // if the search block is of type function, it means our search has gone out of the function itself // so, we should ignore the given function index and only search its parent block's global variable if (searchBlock.blockType == CodeBlockType.Function) stillInsideFunction = false; searchBlock = searchBlock.parent; if (null == searchBlock) { return null; } // Continue searching if (stillInsideFunction) { // we are still inside a function, first search the local variable defined in this function // if not found, then search the enclosing block by specifying the function index as -1 symbolIndex = searchBlock.symbolTable.IndexOf(name, classscope, function); // this check is to avoid unnecessary search // for example if we have a for loop inside an imperative block which is further inside a function // when we are searching inside the for loop or language block, there is no need to search twice // we need to search twice only when we are searching directly inside the function, if (function != Constants.kInvalidIndex && searchBlock.procedureTable != null && searchBlock.procedureTable.Procedures.Count > function && // Note: This check assumes we can not define functions inside a fucntion symbolIndex == Constants.kInvalidIndex) symbolIndex = searchBlock.symbolTable.IndexOf(name, classscope, Constants.kInvalidIndex); } else { symbolIndex = searchBlock.symbolTable.IndexOf(name, classscope, Constants.kInvalidIndex); } } return searchBlock.symbolTable.symbolList[symbolIndex]; }
private void BfsBuildSequenceTable(CodeBlock codeBlock, SymbolTable[] runtimeSymbols) { if (DSASM.CodeBlockType.kLanguage == codeBlock.blockType || DSASM.CodeBlockType.kFunction == codeBlock.blockType || DSASM.CodeBlockType.kConstruct == codeBlock.blockType) { Debug.Assert(codeBlock.symbolTable.runtimeIndex < RuntimeTableIndex); runtimeSymbols[codeBlock.symbolTable.runtimeIndex] = codeBlock.symbolTable; } foreach (DSASM.CodeBlock child in codeBlock.children) { BfsBuildSequenceTable(child, runtimeSymbols); } }
private void BfsBuildSequenceTable(CodeBlock codeBlock, SymbolTable[] runtimeSymbols) { if (CodeBlockType.Language == codeBlock.blockType || CodeBlockType.Function == codeBlock.blockType || CodeBlockType.Construct == codeBlock.blockType) { Validity.Assert(codeBlock.symbolTable.RuntimeIndex < RuntimeTableIndex); runtimeSymbols[codeBlock.symbolTable.RuntimeIndex] = codeBlock.symbolTable; } foreach (CodeBlock child in codeBlock.children) { BfsBuildSequenceTable(child, runtimeSymbols); } }
public SymbolNode GetFirstVisibleSymbol(string name, int classscope, int function, CodeBlock codeblock) { // // Validity.Assert(null != codeblock); if (null == codeblock) { return null; } int symbolIndex = ProtoCore.DSASM.Constants.kInvalidIndex; bool stillInsideFunction = function != ProtoCore.DSASM.Constants.kInvalidIndex; DSASM.CodeBlock searchBlock = codeblock; // TODO(Jiong): Code Duplication, Consider moving this if else block inside the while loop if (stillInsideFunction) { symbolIndex = searchBlock.symbolTable.IndexOf(name, classscope, function); if (function != ProtoCore.DSASM.Constants.kInvalidIndex && searchBlock.procedureTable != null && searchBlock.procedureTable.procList.Count > function && // Note: This check assumes we can not define functions inside a fucntion symbolIndex == ProtoCore.DSASM.Constants.kInvalidIndex) symbolIndex = searchBlock.symbolTable.IndexOf(name, classscope, ProtoCore.DSASM.Constants.kInvalidIndex); } else { symbolIndex = searchBlock.symbolTable.IndexOf(name, classscope, ProtoCore.DSASM.Constants.kInvalidIndex); } while (ProtoCore.DSASM.Constants.kInvalidIndex == symbolIndex) { // if the search block is of type function, it means our search has gone out of the function itself // so, we should ignore the given function index and only search its parent block's global variable if (searchBlock.blockType == DSASM.CodeBlockType.kFunction) stillInsideFunction = false; searchBlock = searchBlock.parent; if (null != searchBlock) { // Continue searching if (stillInsideFunction) { // we are still inside a function, first search the local variable defined in this function // if not found, then search the enclosing block by specifying the function index as -1 symbolIndex = searchBlock.symbolTable.IndexOf(name, classscope, function); // this check is to avoid unnecessary search // for example if we have a for loop inside an imperative block which is further inside a function // when we are searching inside the for loop or language block, there is no need to search twice // we need to search twice only when we are searching directly inside the function, if (function != ProtoCore.DSASM.Constants.kInvalidIndex && searchBlock.procedureTable != null && searchBlock.procedureTable.procList.Count > function && // Note: This check assumes we can not define functions inside a fucntion symbolIndex == ProtoCore.DSASM.Constants.kInvalidIndex) symbolIndex = searchBlock.symbolTable.IndexOf(name, classscope, ProtoCore.DSASM.Constants.kInvalidIndex); } else { symbolIndex = searchBlock.symbolTable.IndexOf(name, classscope, ProtoCore.DSASM.Constants.kInvalidIndex); } } else { // End of nested blocks /* // Not found? Look at the class scope if (ProtoCore.DSASM.Constants.kInvalidIndex != classscope) { // Look at the class members and base class members bool hasSymbol = false; ProtoCore.DSASM.AddressType addrType = DSASM.AddressType.Invalid; ProtoCore.DSASM.ClassNode cnode = classTable.list[classscope]; symbolIndex = cnode.GetFirstVisibleSymbol(name, classscope, function, out hasSymbol, out addrType); if (ProtoCore.DSASM.Constants.kInvalidIndex != symbolIndex) { if (addrType == DSASM.AddressType.StaticMemVarIndex) { return codeBlockList[0].symbolTable.symbolList[symbolIndex]; } else { return classTable.list[classscope].symbols.symbolList[symbolIndex]; } } // Look at the class constructors and functions symbolIndex = classTable.list[classscope].symbols.IndexOf(name, classscope, function); if (ProtoCore.DSASM.Constants.kInvalidIndex != symbolIndex) { return classTable.list[classscope].symbols.symbolList[symbolIndex]; } } // Not found? Look at the global scope symbolIndex = searchBlock.symbolTable.IndexOf(name, ProtoCore.DSASM.Constants.kInvalidIndex, ProtoCore.DSASM.Constants.kGlobalScope); if (ProtoCore.DSASM.Constants.kInvalidIndex == symbolIndex) { return null; } break; * */ return null; } } return searchBlock.symbolTable.symbolList[symbolIndex]; }
private void BfsBuildInstructionStreams(CodeBlock codeBlock, InstructionStream[] istreamList) { if (null != codeBlock) { if (CodeBlockType.Language == codeBlock.blockType || CodeBlockType.Function == codeBlock.blockType) { Validity.Assert(codeBlock.codeBlockId < RuntimeTableIndex); istreamList[codeBlock.codeBlockId] = codeBlock.instrStream; } foreach (CodeBlock child in codeBlock.children) { BfsBuildInstructionStreams(child, istreamList); } } }
public abstract bool Compile(out int blockId, ProtoCore.DSASM.CodeBlock parentBlock, ProtoCore.LanguageCodeBlock codeblock, ProtoCore.CompileTime.Context callContext, ProtoCore.DebugServices.EventSink sink = null, ProtoCore.AST.Node codeBlockNode = null, ProtoCore.AssociativeGraph.GraphNode graphNode = null);
private void EmitWhileStmtNode(ImperativeNode node, ref ProtoCore.Type inferedType, bool isBooleanOp = false, ProtoCore.AssociativeGraph.GraphNode graphNode = null) { if (IsParsingGlobal() || IsParsingGlobalFunctionBody()) { /* while(E) -> entry = pc traverse E emit(pop,cx) L1 = pc + 1 L2 = null bp = pc emit(jmp, _cx, L1, L2) * */ int bp = (int)ProtoCore.DSASM.Constants.kInvalidIndex; int L1 = (int)ProtoCore.DSASM.Constants.kInvalidIndex; int L2 = (int)ProtoCore.DSASM.Constants.kInvalidIndex; int entry = (int)ProtoCore.DSASM.Constants.kInvalidIndex; entry = pc; WhileStmtNode whileNode = node as WhileStmtNode; DfsTraverse(whileNode.Expr, ref inferedType); ProtoCore.DSASM.StackValue opCX = new ProtoCore.DSASM.StackValue(); 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, whileNode.Expr.line, whileNode.Expr.col, whileNode.Expr.endLine, whileNode.Expr.endCol); EmitSetExpressionUID(compileStateTracker.ExpressionUID++); /* { S -> traverse S bptable.append(pc) emit(jmp, entry) } -> backpatch(bp, pc) */ if (null != whileNode.Body) { // 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 ProtoCore.DSASM.CodeBlock localCodeBlock = new ProtoCore.DSASM.CodeBlock( ProtoCore.DSASM.CodeBlockType.kConstruct, Language.kInvalid, compileStateTracker.CodeBlockIndex++, new ProtoCore.DSASM.SymbolTable(GetConstructBlockName("while"), compileStateTracker.RuntimeTableIndex++), null, true); localCodeBlock.instrStream = codeBlock.instrStream; localCodeBlock.parent = codeBlock; codeBlock.children.Add(localCodeBlock); codeBlock = localCodeBlock; compileStateTracker.CompleteCodeBlockList.Add(localCodeBlock); backpatchMap.EntryTable[localCodeBlock.codeBlockId] = entry; backpatchMap.BreakTable[localCodeBlock.codeBlockId] = new BackpatchTable(); EmitPushBlockID(localCodeBlock.codeBlockId); foreach (ImperativeNode bodyNode in whileNode.Body) { inferedType = new ProtoCore.Type(); inferedType.UID = (int)PrimitiveType.kTypeVar; if (bodyNode is LanguageBlockNode) { BinaryExpressionNode langBlockNode = new BinaryExpressionNode(); langBlockNode.LeftNode = nodeBuilder.BuildIdentfier(compileStateTracker.GenerateTempLangageVar()); langBlockNode.Optr = ProtoCore.DSASM.Operator.assign; langBlockNode.RightNode = bodyNode; DfsTraverse(langBlockNode, ref inferedType, isBooleanOp, graphNode); } else { DfsTraverse(bodyNode, ref inferedType, isBooleanOp, graphNode); } } ProtoCore.AST.Node oldBlockNode = localCodeBlockNode; localCodeBlockNode = node; EmitInstrConsole(ProtoCore.DSASM.kw.retcn); EmitRetcn(localCodeBlock.codeBlockId); localCodeBlockNode = oldBlockNode; // Restore - Set the local codeblock parent to be the current codeblock codeBlock = localCodeBlock.parent; EmitJmp(entry); EmitPopBlockID(); Backpatch(backpatchMap.BreakTable[localCodeBlock.codeBlockId].backpatchList, pc); } Backpatch(bp, pc); } }
public static ProcedureNode GetFirstVisibleProcedure(string name, List<Type> argTypeList, CodeBlock codeblock) { if (null == codeblock) { return null; } CodeBlock searchBlock = codeblock; while (null != searchBlock) { if (null == searchBlock.procedureTable) { searchBlock = searchBlock.parent; continue; } // The class table is passed just to check for coercion values int procIndex = searchBlock.procedureTable.IndexOf(name, argTypeList); if (Constants.kInvalidIndex != procIndex) { return searchBlock.procedureTable.procList[procIndex]; } searchBlock = searchBlock.parent; } return null; }
public override bool Compile(out int blockId, ProtoCore.DSASM.CodeBlock parentBlock, ProtoCore.LanguageCodeBlock langBlock, ProtoCore.CompileTime.Context callContext, ProtoCore.DebugServices.EventSink sink = null, ProtoCore.AST.Node codeBlockNode = null, ProtoCore.AssociativeGraph.GraphNode graphNode = null) { Validity.Assert(langBlock != null); blockId = ProtoCore.DSASM.Constants.kInvalidIndex; bool buildSucceeded = false; bool isLangSignValid = core.Langverify.Verify(langBlock); if (isLangSignValid) { try { ProtoCore.CodeGen oldCodegen = core.assocCodegen; if (ProtoCore.DSASM.InterpreterMode.kNormal == core.ExecMode) { if ((core.IsParsingPreloadedAssembly || core.IsParsingCodeBlockNode) && parentBlock == null) { if (core.CodeBlockList.Count == 0) { core.assocCodegen = new ProtoAssociative.CodeGen(core, callContext, parentBlock); } else { // We reuse the existing toplevel CodeBlockList's for the procedureTable's // by calling this overloaded constructor - pratapa core.assocCodegen = new ProtoAssociative.CodeGen(core); } } else { core.assocCodegen = new ProtoAssociative.CodeGen(core, callContext, parentBlock); } } if (null != core.AssocNode) { ProtoCore.AST.AssociativeAST.CodeBlockNode cnode = new ProtoCore.AST.AssociativeAST.CodeBlockNode(); cnode.Body.Add(core.AssocNode as ProtoCore.AST.AssociativeAST.AssociativeNode); core.assocCodegen.context = callContext; blockId = core.assocCodegen.Emit((cnode as ProtoCore.AST.AssociativeAST.CodeBlockNode), graphNode); } else { //if not null, Compile has been called from DfsTraverse. No parsing is needed. if (codeBlockNode == null) { var p = ParserUtils.CreateParser(langBlock.body, core); p.Parse(); // TODO Jun: Set this flag inside a persistent object core.builtInsLoaded = true; codeBlockNode = p.root; //core.AstNodeList = p.GetParsedASTList(codeBlockNode as ProtoCore.AST.AssociativeAST.CodeBlockNode); List <ProtoCore.AST.Node> astNodes = ProtoCore.Utils.ParserUtils.GetAstNodes(codeBlockNode); core.AstNodeList = astNodes; } else { if (!core.builtInsLoaded) { // Load the built-in methods manually ProtoCore.Utils.CoreUtils.InsertPredefinedAndBuiltinMethods(core, codeBlockNode, false); core.builtInsLoaded = true; } } core.assocCodegen.context = callContext; //Temporarily change the code block for code gen to the current block, in the case it is an imperative block //CodeGen for ProtoImperative is modified to passing in the core object. ProtoCore.DSASM.CodeBlock oldCodeBlock = core.assocCodegen.codeBlock; if (core.ExecMode == ProtoCore.DSASM.InterpreterMode.kExpressionInterpreter) { int tempBlockId = core.GetCurrentBlockId(); ProtoCore.DSASM.CodeBlock tempCodeBlock = core.GetCodeBlock(core.CodeBlockList, tempBlockId); while (null != tempCodeBlock && tempCodeBlock.blockType != ProtoCore.DSASM.CodeBlockType.kLanguage) { tempCodeBlock = tempCodeBlock.parent; } core.assocCodegen.codeBlock = tempCodeBlock; } core.assocCodegen.codeBlock.EventSink = sink; if (core.BuildStatus.ErrorCount == 0) //if there is syntax error, no build needed { blockId = core.assocCodegen.Emit((codeBlockNode as ProtoCore.AST.AssociativeAST.CodeBlockNode), graphNode); } if (core.ExecMode == ProtoCore.DSASM.InterpreterMode.kExpressionInterpreter) { blockId = core.assocCodegen.codeBlock.codeBlockId; //Restore the code block. core.assocCodegen.codeBlock = oldCodeBlock; } } // @keyu: we have to restore asscoCodegen here. It may be // reused later on. Suppose for an inline expression // "x = 1 == 2 ? 3 : 4", we dynamically create assocCodegen // to compile true and false expression in this inline // expression, and if we don't restore assocCodegen, the pc // is totally messed up. // // But if directly replace with old assocCodegen, will it // replace some other useful information? Need to revisit it. // // Also refer to defect IDE-2120. if (oldCodegen != null && core.assocCodegen != oldCodegen) { core.assocCodegen = oldCodegen; } } catch (ProtoCore.BuildHaltException) { #if DEBUG //core.BuildStatus.LogSemanticError(e.errorMsg); #endif } buildSucceeded = core.BuildStatus.BuildSucceeded; } return(buildSucceeded); }
private ProtoCore.DSASM.CodeBlock BuildNewCodeBlock(ProcedureTable procTable = null) { ProtoCore.DSASM.CodeBlock cb = new ProtoCore.DSASM.CodeBlock( context.guid, ProtoCore.DSASM.CodeBlockType.kLanguage, ProtoCore.Language.kImperative, core.CodeBlockIndex, new ProtoCore.DSASM.SymbolTable("imperative lang block", core.RuntimeTableIndex), new ProtoCore.DSASM.ProcedureTable(core.RuntimeTableIndex), false, core); ++core.CodeBlockIndex; ++core.RuntimeTableIndex; return cb; }
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 EmitWhileStmtNode(ImperativeNode node, ref ProtoCore.Type inferedType, bool isBooleanOp = false, ProtoCore.AssociativeGraph.GraphNode graphNode = null) { if (core.IsParsingCodeBlockNode || core.IsParsingPreloadedAssembly) { return; } if (IsParsingGlobal() || IsParsingGlobalFunctionBody()) { /* while(E) -> entry = pc traverse E emit(pop,cx) L1 = pc + 1 L2 = null bp = pc emit(jmp, _cx, L1, L2) * */ int bp = (int)ProtoCore.DSASM.Constants.kInvalidIndex; int L1 = (int)ProtoCore.DSASM.Constants.kInvalidIndex; int entry = (int)ProtoCore.DSASM.Constants.kInvalidIndex; entry = pc; WhileStmtNode whileNode = node as WhileStmtNode; DfsTraverse(whileNode.Expr, ref inferedType); L1 = ProtoCore.DSASM.Constants.kInvalidIndex; bp = pc; EmitCJmp(L1, whileNode.Expr.line, whileNode.Expr.col, whileNode.Expr.endLine, whileNode.Expr.endCol); EmitSetExpressionUID(core.ExpressionUID++); /* { S -> traverse S bptable.append(pc) emit(jmp, entry) } -> backpatch(bp, pc) */ if (null != whileNode.Body) { // 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 ProtoCore.DSASM.CodeBlock localCodeBlock = new ProtoCore.DSASM.CodeBlock( context.guid, ProtoCore.DSASM.CodeBlockType.kConstruct, Language.kInvalid, core.CodeBlockIndex++, new ProtoCore.DSASM.SymbolTable(GetConstructBlockName("while"), core.RuntimeTableIndex++), null, true, core); core.CodeBlockIndex++; localCodeBlock.instrStream = codeBlock.instrStream; localCodeBlock.parent = codeBlock; codeBlock.children.Add(localCodeBlock); codeBlock = localCodeBlock; backpatchMap.EntryTable[localCodeBlock.codeBlockId] = entry; backpatchMap.BreakTable[localCodeBlock.codeBlockId] = new BackpatchTable(); EmitPushBlockID(localCodeBlock.codeBlockId); EmitCodeBlock(whileNode.Body, ref inferedType, isBooleanOp, graphNode); ProtoCore.AST.Node oldBlockNode = localCodeBlockNode; localCodeBlockNode = node; EmitInstrConsole(ProtoCore.DSASM.kw.retcn); EmitRetcn(localCodeBlock.codeBlockId); localCodeBlockNode = oldBlockNode; // Restore - Set the local codeblock parent to be the current codeblock codeBlock = localCodeBlock.parent; EmitJmp(entry); Backpatch(backpatchMap.BreakTable[localCodeBlock.codeBlockId].backpatchList, pc); } Backpatch(bp, pc); } }