private int DfsExprValue(ImperativeNode node) { if (node is IdentifierNode) { int val = 0; IdentifierNode t = node as IdentifierNode; try { val = System.Convert.ToInt32(t.Value); return val; } catch (OverflowException) { } catch (FormatException) { } } else if (node is BinaryExpressionNode) { BinaryExpressionNode b = node as BinaryExpressionNode; Debug.Assert(ProtoCore.DSASM.Operator.mul == b.Optr); int left = DfsExprValue(b.LeftNode); int right = DfsExprValue(b.RightNode); return left * right; } return 1; }
public ForLoopNode(ForLoopNode rhs) : base(rhs) { body = new List <ImperativeNode>(); foreach (ImperativeNode iNode in rhs.body) { ImperativeNode newNode = ProtoCore.Utils.NodeUtils.Clone(iNode); body.Add(newNode); } loopVar = ProtoCore.Utils.NodeUtils.Clone(rhs.loopVar); expression = ProtoCore.Utils.NodeUtils.Clone(rhs.expression); KwForLine = rhs.KwForLine; KwForCol = rhs.KwForCol; KwInLine = rhs.KwInLine; KwInCol = rhs.KwInCol; }
public ForLoopNode(ForLoopNode rhs) : base(rhs) { Body = new List <ImperativeNode>(); foreach (ImperativeNode iNode in rhs.Body) { ImperativeNode newNode = NodeUtils.Clone(iNode); Body.Add(newNode); } LoopVariable = NodeUtils.Clone(rhs.LoopVariable); Expression = NodeUtils.Clone(rhs.Expression); KwForLine = rhs.KwForLine; KwForCol = rhs.KwForCol; KwInLine = rhs.KwInLine; KwInCol = rhs.KwInCol; }
public IfStmtNode(IfStmtNode rhs) : base(rhs) { // IfExprNode = ProtoCore.Utils.NodeUtils.Clone(rhs.IfExprNode); // IfBody = new List <ImperativeNode>(); foreach (ImperativeNode stmt in rhs.IfBody) { ImperativeNode body = ProtoCore.Utils.NodeUtils.Clone(stmt); IfBody.Add(body); } // IfBodyPosition = ProtoCore.Utils.NodeUtils.Clone(rhs.IfBodyPosition); // ElseIfList = new List <ElseIfBlock>(); foreach (ElseIfBlock elseBlock in rhs.ElseIfList) { ImperativeNode elseNode = ProtoCore.Utils.NodeUtils.Clone(elseBlock); ElseIfList.Add(elseNode as ElseIfBlock); } // ElseBody = new List <ImperativeNode>(); foreach (ImperativeNode stmt in rhs.ElseBody) { ImperativeNode tmpNode = ProtoCore.Utils.NodeUtils.Clone(stmt); ElseBody.Add(tmpNode); } // ElseBodyPosition = ProtoCore.Utils.NodeUtils.Clone(rhs.ElseBodyPosition); }
private void EmitPostFixNode(ImperativeNode node, ref ProtoCore.Type inferedType) { bool parseGlobal = null == localProcedure && ProtoCore.DSASM.ImperativeCompilePass.kAll == compilePass; bool parseGlobalFunction = null != localProcedure && ProtoCore.DSASM.ImperativeCompilePass.kGlobalFuncBody == compilePass; if (parseGlobal || parseGlobalFunction) { PostFixNode pfNode = node as PostFixNode; //convert post fix operation to a binary operation BinaryExpressionNode binRight = new BinaryExpressionNode(); BinaryExpressionNode bin = new BinaryExpressionNode(); binRight.LeftNode = pfNode.Identifier; binRight.RightNode = new IntNode() { value = "1" }; binRight.Optr = (ProtoCore.DSASM.UnaryOperator.Increment == pfNode.Operator) ? ProtoCore.DSASM.Operator.add : ProtoCore.DSASM.Operator.sub; bin.LeftNode = pfNode.Identifier; bin.RightNode = binRight; bin.Optr = ProtoCore.DSASM.Operator.assign; EmitBinaryExpressionNode(bin, ref inferedType); } }
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); } }
private void EmitUnaryExpressionNode(ImperativeNode node, ref ProtoCore.Type inferedType, ProtoCore.AST.ImperativeAST.BinaryExpressionNode parentNode) { if (IsParsingGlobal() || IsParsingGlobalFunctionBody()) { UnaryExpressionNode u = node as UnaryExpressionNode; bool isPrefixOperation = ProtoCore.DSASM.UnaryOperator.Increment == u.Operator || ProtoCore.DSASM.UnaryOperator.Decrement == u.Operator; //(Ayush) In case of prefix, apply prefix operation first if (isPrefixOperation) { if (u.Expression is IdentifierListNode || u.Expression is IdentifierNode) { BinaryExpressionNode binRight = new BinaryExpressionNode(); BinaryExpressionNode bin = new BinaryExpressionNode(); binRight.LeftNode = u.Expression; binRight.RightNode = new IntNode { value = "1" }; binRight.Optr = (ProtoCore.DSASM.UnaryOperator.Increment == u.Operator) ? ProtoCore.DSASM.Operator.add : ProtoCore.DSASM.Operator.sub; bin.LeftNode = u.Expression; bin.RightNode = binRight; bin.Optr = ProtoCore.DSASM.Operator.assign; EmitBinaryExpressionNode(bin, ref inferedType); } else throw new BuildHaltException("Invalid use of prefix operation (15BB9C10)."); } DfsTraverse(u.Expression, ref inferedType, false, null, AssociativeSubCompilePass.kNone, parentNode); if (!isPrefixOperation) { EmitInstrConsole(ProtoCore.DSASM.kw.pop, ProtoCore.DSASM.kw.regAX); ProtoCore.DSASM.StackValue opAX = new ProtoCore.DSASM.StackValue(); opAX.optype = ProtoCore.DSASM.AddressType.Register; opAX.opdata = (int)ProtoCore.DSASM.Registers.AX; EmitPop(opAX, Constants.kGlobalScope); string op = opKwData.unaryOpStringTable[u.Operator]; EmitInstrConsole(op, ProtoCore.DSASM.kw.regAX); EmitUnary(opKwData.unaryOpCodeTable[u.Operator], opAX); EmitInstrConsole(ProtoCore.DSASM.kw.push, ProtoCore.DSASM.kw.regAX); ProtoCore.DSASM.StackValue opRes = new ProtoCore.DSASM.StackValue(); opRes.optype = ProtoCore.DSASM.AddressType.Register; opRes.opdata = (int)ProtoCore.DSASM.Registers.AX; EmitPush(opRes); } } }
private void EmitLanguageBlockNode(ImperativeNode node, ref ProtoCore.Type inferedType, ProtoCore.AssociativeGraph.GraphNode propogateUpdateGraphNode = null) { // // TODO Jun: // Add support for language blocks, classes and functions in GRAPH post july release // This Temporary guard will no longer be necessary bool disableLanguageBlocks = compileStateTracker.IsParsingCodeBlockNode || compileStateTracker.IsParsingPreloadedAssembly; if (disableLanguageBlocks) { compileStateTracker.BuildStatus.LogSemanticError("Defining language blocks are not yet supported"); } if (IsParsingGlobal() || IsParsingGlobalFunctionBody()) { LanguageBlockNode langblock = node as LanguageBlockNode; //(Fuqiang, Ayush) : Throwing an assert stops NUnit. Negative tests expect to catch a // CompilerException, so we throw that instead. //Debug.Assert(ProtoCore.Language.kInvalid != langblock.codeblock.language); if (ProtoCore.Language.kInvalid == langblock.codeblock.language) { throw new ProtoCore.Exceptions.CompileErrorsOccured("Invalid language block"); } ProtoCore.CompileTime.Context context = new ProtoCore.CompileTime.Context(); int entry = 0; int blockId = ProtoCore.DSASM.Constants.kInvalidIndex; if (ProtoCore.Language.kImperative == langblock.codeblock.language) { // TODO Jun: Move the associative and all common string into some table buildStatus.LogSyntaxError("An imperative language block is declared within an imperative language block.", compileStateTracker.CurrentDSFileName, langblock.line, langblock.col); } if (globalProcIndex != ProtoCore.DSASM.Constants.kInvalidIndex && compileStateTracker.ProcNode == null) { compileStateTracker.ProcNode = codeBlock.procedureTable.procList[globalProcIndex]; } compileStateTracker.Executives[langblock.codeblock.language].Compile(compileStateTracker, out blockId, codeBlock, langblock.codeblock, context, codeBlock.EventSink, langblock.CodeBlockNode); if (propogateUpdateGraphNode != null) { propogateUpdateGraphNode.languageBlockId = blockId; CodeBlock childBlock = compileStateTracker.CompleteCodeBlockList[blockId]; foreach (var subGraphNode in childBlock.instrStream.dependencyGraph.GraphList) { foreach (var depentNode in subGraphNode.dependentList) { if (depentNode.updateNodeRefList != null && depentNode.updateNodeRefList.Count > 0 && depentNode.updateNodeRefList[0].nodeList != null && depentNode.updateNodeRefList[0].nodeList.Count > 0) { SymbolNode dependentSymbol = depentNode.updateNodeRefList[0].nodeList[0].symbol; int symbolBlockId = dependentSymbol.codeBlockId; if (symbolBlockId != Constants.kInvalidIndex) { CodeBlock symbolBlock = compileStateTracker.CompleteCodeBlockList[symbolBlockId]; if (!symbolBlock.IsMyAncestorBlock(codeBlock.codeBlockId)) { propogateUpdateGraphNode.PushDependent(depentNode); } } } } } } setBlkId(blockId); inferedType = compileStateTracker.InferedType; //Debug.Assert(codeBlock.children[codeBlock.children.Count - 1].blockType == ProtoCore.DSASM.CodeBlockType.kLanguage); codeBlock.children[codeBlock.children.Count - 1].Attributes = PopulateAttributes(langblock.Attributes); #if ENABLE_EXCEPTION_HANDLING core.ExceptionHandlingManager.Register(blockId, globalProcIndex, globalClassIndex); #endif EmitInstrConsole("bounce " + blockId + ", " + entry.ToString()); EmitBounceIntrinsic(blockId, entry); // The callee language block will have stored its result into the RX register. EmitInstrConsole(ProtoCore.DSASM.kw.push, ProtoCore.DSASM.kw.regRX); ProtoCore.DSASM.StackValue opRes = new ProtoCore.DSASM.StackValue(); opRes.optype = ProtoCore.DSASM.AddressType.Register; opRes.opdata = (int)ProtoCore.DSASM.Registers.RX; EmitPush(opRes); } }
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 EmitFunctionDefinitionNode(ImperativeNode node, ref ProtoCore.Type inferedType) { bool parseGlobalFunctionSig = null == localProcedure && ProtoCore.DSASM.ImperativeCompilePass.kGlobalFuncSig == compilePass; bool parseGlobalFunctionBody = null == localProcedure && ProtoCore.DSASM.ImperativeCompilePass.kGlobalFuncBody == compilePass; FunctionDefinitionNode funcDef = node as FunctionDefinitionNode; localFunctionDefNode = funcDef; ProtoCore.DSASM.CodeBlockType originalBlockType = codeBlock.blockType; codeBlock.blockType = ProtoCore.DSASM.CodeBlockType.kFunction; if (parseGlobalFunctionSig) { Debug.Assert(null == localProcedure); // TODO jun: Add semantics for checking overloads (different parameter types) localProcedure = new ProtoCore.DSASM.ProcedureNode(); localProcedure.name = funcDef.Name; localProcedure.pc = pc; localProcedure.localCount = funcDef.localVars; localProcedure.returntype.UID = compileStateTracker.TypeSystem.GetType(funcDef.ReturnType.Name); if (localProcedure.returntype.UID == (int)PrimitiveType.kInvalidType) { string message = String.Format(ProtoCore.BuildData.WarningMessage.kReturnTypeUndefined, funcDef.ReturnType.Name, funcDef.Name); buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kTypeUndefined, message, null, funcDef.line, funcDef.col); localProcedure.returntype.UID = (int)PrimitiveType.kTypeVar; } localProcedure.returntype.IsIndexable = funcDef.ReturnType.IsIndexable; localProcedure.returntype.rank = funcDef.ReturnType.rank; localProcedure.runtimeIndex = codeBlock.codeBlockId; globalProcIndex = codeBlock.procedureTable.Append(localProcedure); compileStateTracker.ProcNode = localProcedure; // Append arg symbols if (null != funcDef.Signature) { foreach (VarDeclNode argNode in funcDef.Signature.Arguments) { IdentifierNode paramNode = null; bool aIsDefault = false; ProtoCore.AST.Node aDefaultExpression = null; if (argNode.NameNode is IdentifierNode) { paramNode = argNode.NameNode as IdentifierNode; } else if (argNode.NameNode is BinaryExpressionNode) { BinaryExpressionNode bNode = argNode.NameNode as BinaryExpressionNode; paramNode = bNode.LeftNode as IdentifierNode; aIsDefault = true; aDefaultExpression = bNode; //buildStatus.LogSemanticError("Defualt parameters are not supported"); //throw new BuildHaltException(); } else { Debug.Assert(false, "Check generated AST"); } ProtoCore.Type argType = BuildArgumentTypeFromVarDeclNode(argNode); int symbolIndex = AllocateArg(paramNode.Value, localProcedure.procId, argType); if (ProtoCore.DSASM.Constants.kInvalidIndex == symbolIndex) { throw new BuildHaltException("26384684"); } localProcedure.argTypeList.Add(argType); ProtoCore.DSASM.ArgumentInfo argInfo = new ProtoCore.DSASM.ArgumentInfo { isDefault = aIsDefault, defaultExpression = aDefaultExpression }; localProcedure.argInfoList.Add(argInfo); } } // TODO Jun: Remove this once agree that alltest cases assume the default assoc block is block 0 // NOTE: Only affects mirror, not actual execution if (null == codeBlock.parent && pc <= 0) { // The first node in the top level block is a function compileStateTracker.DSExecutable.isSingleAssocBlock = false; } #if ENABLE_EXCEPTION_HANDLING core.ExceptionHandlingManager.Register(codeBlock.codeBlockId, globalProcIndex, globalClassIndex); #endif } else if (parseGlobalFunctionBody) { EmitCompileLogFunctionStart(GetFunctionSignatureString(funcDef.Name, funcDef.ReturnType, funcDef.Signature)); // Build arglist for comparison List<ProtoCore.Type> argList = new List<ProtoCore.Type>(); if (null != funcDef.Signature) { foreach (VarDeclNode argNode in funcDef.Signature.Arguments) { ProtoCore.Type argType = BuildArgumentTypeFromVarDeclNode(argNode); argList.Add(argType); } } // Get the exisitng procedure that was added on the previous pass globalProcIndex = codeBlock.procedureTable.IndexOfExact(funcDef.Name, argList); localProcedure = codeBlock.procedureTable.procList[globalProcIndex]; Debug.Assert(null != localProcedure); localProcedure.Attributes = PopulateAttributes(funcDef.Attributes); // Its only on the parse body pass where the real pc is determined. Update this procedures' pc //Debug.Assert(ProtoCore.DSASM.Constants.kInvalidIndex == localProcedure.pc); localProcedure.pc = pc; // Copy the active function to the core so nested language blocks can refer to it compileStateTracker.ProcNode = localProcedure; // Arguments have been allocated, update the baseOffset localProcedure.localCount = compileStateTracker.BaseOffset; ProtoCore.FunctionEndPoint fep = null; //Traverse default argument emitDebugInfo = false; foreach (ProtoCore.DSASM.ArgumentInfo argNode in localProcedure.argInfoList) { if (!argNode.isDefault) { continue; } BinaryExpressionNode bNode = argNode.defaultExpression as BinaryExpressionNode; // build a temporay node for statement : temp = defaultarg; var iNodeTemp = nodeBuilder.BuildIdentfier(Constants.kTempDefaultArg); BinaryExpressionNode bNodeTemp = nodeBuilder.BuildBinaryExpression(iNodeTemp, bNode.LeftNode) as BinaryExpressionNode; EmitBinaryExpressionNode(bNodeTemp, ref inferedType); //duild an inline conditional node for statement: defaultarg = (temp == DefaultArgNode) ? defaultValue : temp; InlineConditionalNode icNode = new InlineConditionalNode(); icNode.ConditionExpression = nodeBuilder.BuildBinaryExpression(iNodeTemp, new DefaultArgNode(), Operator.eq); icNode.TrueExpression = bNode.RightNode; icNode.FalseExpression = iNodeTemp; bNodeTemp.LeftNode = bNode.LeftNode; bNodeTemp.RightNode = icNode; EmitBinaryExpressionNode(bNodeTemp, ref inferedType); } emitDebugInfo = true; // Traverse definition bool hasReturnStatement = false; foreach (ImperativeNode bnode in funcDef.FunctionBody.Body) { DfsTraverse(bnode, ref inferedType); if (ProtoCore.Utils.NodeUtils.IsReturnExpressionNode(bnode)) { hasReturnStatement = true; } if (bnode is FunctionCallNode) { EmitSetExpressionUID(compileStateTracker.ExpressionUID++); } } // All locals have been stack allocated, update the local count of this function localProcedure.localCount = compileStateTracker.BaseOffset; // Update the param stack indices of this function foreach (ProtoCore.DSASM.SymbolNode symnode in codeBlock.symbolTable.symbolList.Values) { if (symnode.functionIndex == localProcedure.procId && symnode.isArgument) { symnode.index -= localProcedure.localCount; } } ProtoCore.Lang.JILActivationRecord record = new ProtoCore.Lang.JILActivationRecord(); record.pc = localProcedure.pc; record.locals = localProcedure.localCount; record.classIndex = ProtoCore.DSASM.Constants.kInvalidIndex; record.funcIndex = localProcedure.procId; fep = new ProtoCore.Lang.JILFunctionEndPoint(record); // Construct the fep arguments fep.FormalParams = new ProtoCore.Type[localProcedure.argTypeList.Count]; fep.BlockScope = codeBlock.codeBlockId; fep.procedureNode = localProcedure; localProcedure.argTypeList.CopyTo(fep.FormalParams, 0); // TODO Jun: 'classIndexAtCallsite' is the class index as it is stored at the callsite function tables // Determine whether this still needs to be aligned to the actual 'classIndex' variable // The factors that will affect this is whether the 2 function tables (compiler and callsite) need to be merged int classIndexAtCallsite = ProtoCore.DSASM.Constants.kInvalidIndex + 1; compileStateTracker.FunctionTable.AddFunctionEndPointer(classIndexAtCallsite, funcDef.Name, fep); if (!hasReturnStatement) { if (!compileStateTracker.Options.SuppressFunctionResolutionWarning) { string message = String.Format(ProtoCore.BuildData.WarningMessage.kFunctionNotReturnAtAllCodePaths, localProcedure.name); compileStateTracker.BuildStatus.LogWarning(ProtoCore.BuildData.WarningID.kMissingReturnStatement, message, compileStateTracker.CurrentDSFileName, funcDef.line, funcDef.col); } EmitReturnNull(); } EmitCompileLogFunctionEnd(); //Fuqiang: return is already done in traversing the function body //// function return //EmitInstrConsole(ProtoCore.DSASM.kw.ret); //EmitReturn(); } compileStateTracker.ProcNode = localProcedure = null; globalProcIndex = ProtoCore.DSASM.Constants.kGlobalScope; argOffset = 0; compileStateTracker.BaseOffset = 0; codeBlock.blockType = originalBlockType; localFunctionDefNode = null; }
public UnaryExpressionNode(UnaryExpressionNode rhs) : base(rhs) { Operator = rhs.Operator; Expression = ProtoCore.Utils.NodeUtils.Clone(rhs.Expression); }
private void EmitClassDeclNode(ImperativeNode node) { throw new NotImplementedException(); }
// this method is used in conjuction with array indexing private void DfsEmitArrayIndex(ImperativeNode node, int symbolindex, int index = 0) { // s = b + ((i * i.w) + (j * j.w) + (n * n.w)) if (node is ArrayNode) { ArrayNode array = node as ArrayNode; ProtoCore.Type type = new ProtoCore.Type(); type.UID = (int)ProtoCore.PrimitiveType.kTypeVoid; type.IsIndexable = false; DfsTraverse(array.Expr, ref type); // Max size of the current dimension int w = codeBlock.symbolTable.symbolList[symbolindex].arraySizeList[index]; // TODO Jun: Performance improvement // Avoid having to generate instructions for the current index if 'w' is 0 if (array.Type is ArrayNode) { DfsEmitArrayIndex(array.Type, symbolindex, index + 1); } } else { Debug.Assert(false, "ast error – check ast construction"); } }
public BinaryExpressionNode(BinaryExpressionNode rhs) : base(rhs) { Optr = rhs.Optr; LeftNode = rhs.LeftNode == null ? null : ProtoCore.Utils.NodeUtils.Clone(rhs.LeftNode); RightNode = rhs.RightNode == null ? null : ProtoCore.Utils.NodeUtils.Clone(rhs.RightNode); }
public BinaryExpressionNode(ImperativeNode left = null, ImperativeNode right = null, ProtoCore.DSASM.Operator optr = DSASM.Operator.none) { LeftNode = left; Optr = optr; RightNode = right; }
public ImperativeNode(ImperativeNode rhs) : base(rhs) { }
public IdentifierListNode(IdentifierListNode rhs) : base(rhs) { Optr = rhs.Optr; LeftNode = ProtoCore.Utils.NodeUtils.Clone(rhs.LeftNode); RightNode = ProtoCore.Utils.NodeUtils.Clone(rhs.RightNode); }
public ImperativeNode BuildIdentList(ImperativeNode leftNode, ImperativeNode rightNode) { var identList = new IdentifierListNode(); identList.LeftNode = leftNode; identList.RightNode = rightNode; identList.Optr = ProtoCore.DSASM.Operator.dot; return identList; }
private void DfsEmitArraySize(ImperativeNode node) { // s = size * ( i * j * k..n ) if (node is ArrayNode) { ArrayNode array = node as ArrayNode; ProtoCore.Type type = new ProtoCore.Type(); type.UID = (int)ProtoCore.PrimitiveType.kInvalidType; type.IsIndexable = false; DfsTraverse(array.Expr, ref type); if (array.Type is ArrayNode) { DfsEmitArraySize(array.Type); } } else { Debug.Assert(false, "ast error – check ast construction"); } }
private void EmitForLoopNode(ImperativeNode node, ref ProtoCore.Type inferredType, bool isBooleanOp = false, ProtoCore.AssociativeGraph.GraphNode graphNode = null) { 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; __autogen_count = 0; __autogen_iterations = a.size; while( __autogen_count < __autogen_iterations) { val = a[__autogen_count]; __autogen_count = __autogen_count + 1; x = x + val; } */ DebugProperties.BreakpointOptions oldOptions = compileStateTracker.DebugProps.breakOptions; DebugProperties.BreakpointOptions newOptions = oldOptions; newOptions |= DebugProperties.BreakpointOptions.EmitCallrForTempBreakpoint; compileStateTracker.DebugProps.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; ++forloopCounter; //new forloop beginning. increment loop counter // Generate the expression for ‘id’ initialized to null BinaryExpressionNode forIdentInit = new BinaryExpressionNode(); forIdentInit.Optr = ProtoCore.DSASM.Operator.assign; IdentifierNode forIdent = nodeBuilder.BuildIdentfier(forNode.loopVar.Name) as IdentifierNode; forIdent.ArrayName = forNode.expression.Name; //IdentifierNode forLoopArrayIdent = nodeBuilder.BuildIdentfier(forNode.expression.Name) as IdentifierNode; ProtoCore.Utils.NodeUtils.CopyNodeLocation(forIdent, forNode.loopVar); forIdentInit.LeftNode = forIdent; forIdentInit.RightNode = new NullNode(); ProtoCore.Type type = new ProtoCore.Type(); type.UID = (int)PrimitiveType.kTypeVoid; type.IsIndexable = false; ProtoCore.Utils.NodeUtils.CopyNodeLocation(forIdentInit, forNode); forIdentInit.endLine = forIdentInit.line; forIdentInit.endCol = forIdentInit.col + 3; EmitBinaryExpressionNode(forIdentInit, ref type, isBooleanOp, graphNode); // Generate the expression for autogen counter initialized to 0 string forCountIdent = GetForCountIdent(); var nodeCounter = nodeBuilder.BuildIdentfier(forCountIdent); BinaryExpressionNode forcounterExpr = new BinaryExpressionNode(); forcounterExpr.Optr = ProtoCore.DSASM.Operator.assign; forcounterExpr.LeftNode = nodeCounter; forcounterExpr.RightNode = new IntNode { value = "0" }; type.UID = (int)ProtoCore.PrimitiveType.kTypeVoid; EmitBinaryExpressionNode(forcounterExpr, ref type, isBooleanOp, graphNode); // Generate the expression for autogen iterations initialized to 0 string forIterCountVar = GetForIterationVar(); var nodeIterCount = nodeBuilder.BuildIdentfier(forIterCountVar); BinaryExpressionNode forIterations = new BinaryExpressionNode(); forIterations.Optr = ProtoCore.DSASM.Operator.assign; forIterations.LeftNode = nodeIterCount; forIterations.RightNode = new IntNode { value = "0" }; type.UID = (int)ProtoCore.PrimitiveType.kTypeVoid; EmitBinaryExpressionNode(forIterations, ref type, isBooleanOp, graphNode); // Generate the expression for autogen iteration count assigned to the size of ‘expr’ // Create a temp array variable if 'expr' is an array string identName = GetForExprIdent(); var exprIdent = nodeBuilder.BuildIdentfier(identName); NodeUtils.CopyNodeLocation(exprIdent, forNode.expression); BinaryExpressionNode arrayexprAssignment = new BinaryExpressionNode(); arrayexprAssignment.Optr = ProtoCore.DSASM.Operator.assign; arrayexprAssignment.LeftNode = exprIdent; arrayexprAssignment.RightNode = forNode.expression; NodeUtils.UpdateBinaryExpressionLocation(arrayexprAssignment); bool shouldBreakOnTemporary = false; switch (forNode.expression.GetType().ToString()) { case "ProtoCore.AST.ImperativeAST.IdentifierNode": case "ProtoCore.AST.ImperativeAST.ExprListNode": shouldBreakOnTemporary = true; break; } if (false == shouldBreakOnTemporary) { type.UID = (int)ProtoCore.PrimitiveType.kTypeVoid; EmitBinaryExpressionNode(arrayexprAssignment, ref type, isBooleanOp, graphNode); } else { newOptions |= DebugProperties.BreakpointOptions.EmitPopForTempBreakpoint; compileStateTracker.DebugProps.breakOptions = newOptions; type.UID = (int)ProtoCore.PrimitiveType.kTypeVoid; EmitBinaryExpressionNode(arrayexprAssignment, ref type, isBooleanOp, graphNode); } compileStateTracker.DebugProps.breakOptions = oldOptions; // Restore breakpoint behaviors. // Comment Jun: Compile such that the the forloop 'expr' is always assumed to be an array // If it was passed a singleton, the runtime will handle it accordingly ////if ((int)PrimitiveType.kTypeArray != type) //if (false) //{ // // 'expr' is not an array so it can be assigned directly to 'id' // BinaryExpressionNode exprToIdent = new BinaryExpressionNode(); // exprToIdent.Optr = ProtoCore.DSASM.Operator.assign; // exprToIdent.LeftNode = forIdent; // exprToIdent.RightNode = forNode.expression; // forNode.body.Insert(0, exprToIdent); // // There is no loop since 'expr' is a single element. Traverse the for loop body directly // type = (int)ProtoCore.PrimitiveType.kTypeVoid; // if (null != forNode.body) // { // foreach (ImperativeNode bodyNode in forNode.body) // { // DfsTraverse(bodyNode, ref type); // } // } //} //else //{ // 'expr' is an array // 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 = compileStateTracker.ClassTable.ClassNodes[globalClassIndex].symbols.IndexOf(identName); if (symbolIndex != Constants.kInvalidIndex) { symbol = compileStateTracker.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); EmitPushVarSize(symbolIndex, codeBlock.symbolTable.runtimeIndex, (symbol == null) ? globalClassIndex : symbol.classScope); // Push the identifier local block information // Push the array dimensions int dimensions = 0; EmitPushVarData(codeBlock.symbolTable.runtimeIndex, dimensions); ProtoCore.DSASM.StackValue opDest = new ProtoCore.DSASM.StackValue(); opDest.optype = ProtoCore.DSASM.AddressType.VarIndex; if (ProtoCore.DSASM.Constants.kInvalidIndex != globalClassIndex && !IsInLanguageBlockDefinedInFunction()) { symbolIndex = compileStateTracker.ClassTable.ClassNodes[globalClassIndex].symbols.IndexOf(forIterCountVar); if (symbolIndex != Constants.kInvalidIndex) { symbol = compileStateTracker.ClassTable.ClassNodes[globalClassIndex].symbols.symbolList[symbolIndex]; } } else { symbolIndex = codeBlock.symbolTable.IndexOf(forIterCountVar); if (symbolIndex != Constants.kInvalidIndex) { symbol = codeBlock.symbolTable.symbolList[symbolIndex]; } } opDest.opdata = symbolIndex; EmitInstrConsole(ProtoCore.DSASM.kw.pop, forIterCountVar); EmitPop(opDest, (symbol == null) ? globalClassIndex : symbol.classScope); // Generate the comparison expression between the autogen counter and the autogen iteration count BinaryExpressionNode iterCondition = new BinaryExpressionNode(); iterCondition.Optr = ProtoCore.DSASM.Operator.lt; iterCondition.LeftNode = nodeCounter; iterCondition.RightNode = nodeIterCount; iterCondition.line = forNode.KwInLine; iterCondition.col = forNode.KwInCol; iterCondition.endLine = forNode.KwInLine; iterCondition.endCol = forNode.KwInCol + 2; // 2 character for keyword "in". // Generate the assignment statement from where lhs is ‘id’ and rhs is ‘expr’ indexed into the autogen count BinaryExpressionNode IndexedExprToId = new BinaryExpressionNode(); IndexedExprToId.Optr = ProtoCore.DSASM.Operator.assign; IndexedExprToId.LeftNode = forIdent; // Array index into the expr ident ArrayNode arrayIndex = new ArrayNode(); arrayIndex.Expr = nodeCounter; arrayIndex.Type = null; (exprIdent as IdentifierNode).ArrayDimensions = arrayIndex; IndexedExprToId.RightNode = exprIdent; IndexedExprToId.line = forIdent.line; IndexedExprToId.col = forIdent.col; IndexedExprToId.endLine = forIdent.endLine; IndexedExprToId.endCol = forIdent.endCol; // Generate the expression for increment by 1 of the autogen count var countIncrement = nodeBuilder.BuildBinaryExpression(nodeCounter, new IntNode { value = "1" }, Operator.add); var countIncrementAssign = nodeBuilder.BuildBinaryExpression(nodeCounter, countIncrement); // Append the array indexing and increment expressions into the for-loop body forNode.body.Insert(0, IndexedExprToId); forNode.body.Insert(1, countIncrementAssign); // Construct and populate the equivalent while node WhileStmtNode whileNode = new WhileStmtNode(); whileNode.Expr = iterCondition; whileNode.Body = forNode.body; whileNode.endLine = node.endLine; whileNode.endCol = node.endCol; type.UID = (int)ProtoCore.PrimitiveType.kTypeVoid; EmitWhileStmtNode(whileNode, ref type, isBooleanOp, graphNode); //} // Comment Jun: The for loop counter must be unique and does not need to reset //forloopCounter--; //for loop ended. decrement counter } }
private void EmitConstructorDefinitionNode(ImperativeNode node) { throw new NotImplementedException(); }
private void EmitBinaryExpressionNode(ImperativeNode node, ref ProtoCore.Type inferedType, bool isBooleanOp = false) { if (!IsParsingGlobal() && !IsParsingGlobalFunctionBody()) return; bool isBooleanOperation = false; BinaryExpressionNode b = node as BinaryExpressionNode; ProtoCore.Type leftType = new ProtoCore.Type(); leftType.UID = (int)ProtoCore.PrimitiveType.kTypeVar; ProtoCore.Type rightType = new ProtoCore.Type(); rightType.UID = (int)ProtoCore.PrimitiveType.kTypeVar; if (ProtoCore.DSASM.Operator.assign != b.Optr) { isBooleanOperation = ProtoCore.DSASM.Operator.lt == b.Optr || ProtoCore.DSASM.Operator.gt == b.Optr || ProtoCore.DSASM.Operator.le == b.Optr || ProtoCore.DSASM.Operator.ge == b.Optr || ProtoCore.DSASM.Operator.eq == b.Optr || ProtoCore.DSASM.Operator.nq == b.Optr || ProtoCore.DSASM.Operator.and == b.Optr || ProtoCore.DSASM.Operator.or == b.Optr; DfsTraverse(b.LeftNode, ref inferedType, isBooleanOperation); leftType.UID = inferedType.UID; leftType.IsIndexable = inferedType.IsIndexable; } // (Ayush) in case of PostFixNode, only traverse the identifier now. Post fix operation will be applied later. #if ENABLE_INC_DEC_FIX if (b.RightNode is PostFixNode) DfsTraverse((b.RightNode as PostFixNode).Identifier, ref inferedType, isBooleanOperation); else { #endif if ((ProtoCore.DSASM.Operator.assign == b.Optr) && (b.RightNode is LanguageBlockNode)) { inferedType.UID = (int)ProtoCore.PrimitiveType.kTypeVar; inferedType.IsIndexable = false; } DfsTraverse(b.RightNode, ref inferedType, isBooleanOperation); #if ENABLE_INC_DEC_FIX } #endif rightType.UID = inferedType.UID; rightType.IsIndexable = inferedType.IsIndexable; BinaryExpressionNode rightNode = b.RightNode as BinaryExpressionNode; if ((rightNode != null) && (ProtoCore.DSASM.Operator.assign == rightNode.Optr)) DfsTraverse(rightNode.LeftNode, ref inferedType); if (b.Optr != ProtoCore.DSASM.Operator.assign) { isBooleanOp = false; //if post fix, now traverse the post fix #if ENABLE_INC_DEC_FIX if (b.RightNode is PostFixNode) EmitPostFixNode(b.RightNode, ref inferedType); #endif return; } if (b.LeftNode is IdentifierNode) { IdentifierNode t = b.LeftNode as IdentifierNode; ProtoCore.DSASM.SymbolNode symbolnode = null; string s = t.Value; bool isReturn = (s == ProtoCore.DSDefinitions.Keyword.Return); if (isReturn) { EmitReturnStatement(node, inferedType); } else { { // check whether the variable name is a function name bool isAccessibleFp; int realType; ProtoCore.DSASM.ProcedureNode procNode = null; if (globalClassIndex != ProtoCore.DSASM.Constants.kGlobalScope) { procNode = compileState.ClassTable.ClassNodes[globalClassIndex].GetMemberFunction(t.Name, null, globalClassIndex, out isAccessibleFp, out realType); } if (procNode == null) { procNode = compileState.GetFirstVisibleProcedure(t.Name, null, codeBlock); } } bool isAccessible = false; bool isAllocated = VerifyAllocation(t.Value, globalClassIndex, out symbolnode, out isAccessible); int runtimeIndex = (!isAllocated) ? codeBlock.symbolTable.runtimeIndex : symbolnode.runtimeTableIndex; // TODO Jun: Update mechanism work in progress - a flag to manually enable update bool enableUpdate = false; if (enableUpdate) { bool isExternal = false; // isAllocated && currentLangBlock != codeBlockId; //bool isAssociative = ProtoCore.Language.kAssociative == core.exeList[currentLangBlock].language; bool isAssociative = false; if (isExternal && isAssociative) { // Check if this is a modifier variable bool isVariableAModifierStack = false; if (isVariableAModifierStack) { // Check if modifying a named modifier state bool isNameModifierState = false; if (isNameModifierState) { //bool isStateIntermediate = false; } else { } //targetLangBlock = blockId; } } } int dimensions = 0; if (null != t.ArrayDimensions) { dimensions = DfsEmitArrayIndexHeap(t.ArrayDimensions); } ProtoCore.Type castType = compileState.TypeSystem.BuildTypeObject((int)PrimitiveType.kTypeVar, false); var tident = b.LeftNode as TypedIdentifierNode; if (tident != null) { int castUID = tident.datatype.UID; if ((int)PrimitiveType.kInvalidType == castUID) { castUID = compileState.ClassTable.IndexOf(tident.datatype.Name); } if ((int)PrimitiveType.kInvalidType == castUID) { castType = compileState.TypeSystem.BuildTypeObject((int)PrimitiveType.kInvalidType, false); castType.Name = tident.datatype.Name; castType.rank = tident.datatype.rank; castType.IsIndexable = (castType.rank != 0); } else { castType = compileState.TypeSystem.BuildTypeObject(castUID, tident.datatype.IsIndexable, tident.datatype.rank); } } if (globalClassIndex != ProtoCore.DSASM.Constants.kInvalidIndex) { int symbol = ProtoCore.DSASM.Constants.kInvalidIndex; for (int n = 0; n < compileState.ClassTable.ClassNodes[globalClassIndex].symbols.symbolList.Count; ++n) { //Fuqiang: Not a member variable if it is a local variable inside a function with the same name bool localVarInMemFunc = false; if (localProcedure != null) { if (symbolnode == null) { if (!isAllocated) // if isAllocated, inaccessible member variable { localVarInMemFunc = true; } } else if (symbolnode.functionIndex != ProtoCore.DSASM.Constants.kGlobalScope && !localProcedure.isConstructor) { localVarInMemFunc = true; } } bool isMemberVar = ProtoCore.DSASM.Constants.kGlobalScope == compileState.ClassTable.ClassNodes[globalClassIndex].symbols.symbolList[n].functionIndex && compileState.ClassTable.ClassNodes[globalClassIndex].symbols.symbolList[n].name == t.Name && !localVarInMemFunc; if (isMemberVar) { symbol = n; break; } } if (symbol == ProtoCore.DSASM.Constants.kInvalidIndex) { if (!isAllocated) { symbolnode = Allocate(t.Name, globalProcIndex, inferedType); IdentLocation.AddEntry(symbolnode, t.line, t.col, compileState.CurrentDSFileName); } symbol = symbolnode.symbolTableIndex; } if (b.LeftNode is TypedIdentifierNode) { symbolnode.SetStaticType(castType); } } else { if (0 == dimensions) { if (!isAllocated) { symbolnode = Allocate(t.Value, globalProcIndex, inferedType); IdentLocation.AddEntry(symbolnode, t.line, t.col, compileState.CurrentDSFileName); } else { if (compileState.TypeSystem.IsHigherRank(inferedType.UID, symbolnode.datatype.UID)) { symbolnode.datatype = inferedType; } } if (b.LeftNode is TypedIdentifierNode) { symbolnode.SetStaticType(castType); } } } } } else if (b.LeftNode is IdentifierListNode) { int depth = 0; ProtoCore.Type lastType = new ProtoCore.Type(); lastType.UID = (int)PrimitiveType.kInvalidType; lastType.IsIndexable = false; bool isFirstIdent = false; bool isIdentReference = DfsEmitIdentList(b.LeftNode, b, globalClassIndex, ref lastType, ref depth, ref inferedType, true, ref isFirstIdent); inferedType.UID = isBooleanOp ? (int)PrimitiveType.kTypeBool : inferedType.UID; } //if post fix, now traverse the post fix #if ENABLE_INC_DEC_FIX if (b.RightNode is PostFixNode) EmitPostFixNode(b.RightNode, ref inferedType); #endif }
private void EmitFunctionCallNode(ImperativeNode node, ref ProtoCore.Type inferedType, bool isBooleanOp = false, ProtoCore.AssociativeGraph.GraphNode graphNode = null, ProtoCore.AST.ImperativeAST.BinaryExpressionNode bnode = null) { FunctionCallNode fnode = node as FunctionCallNode; ProtoCore.DSASM.ProcedureNode procNode = TraverseFunctionCall(node, null, ProtoCore.DSASM.Constants.kInvalidIndex, 0, ref inferedType, graphNode, AssociativeSubCompilePass.kNone, bnode); if (fnode != null && fnode.ArrayDimensions != null) { int dimensions = DfsEmitArrayIndexHeap(fnode.ArrayDimensions); EmitInstrConsole(ProtoCore.DSASM.kw.pushindex, dimensions.ToString() + "[dim]"); EmitPushArrayIndex(dimensions); fnode.ArrayDimensions = null; } if(bnode == null) EmitSetExpressionUID(compileStateTracker.ExpressionUID++); }
private ProtoCore.DSASM.SymbolNode Allocate( string ident, int funcIndex, ProtoCore.Type datatype, int size = 1, int datasize = ProtoCore.DSASM.Constants.kPrimitiveSize, ImperativeNode nodeArray = null, ProtoCore.DSASM.MemoryRegion region = ProtoCore.DSASM.MemoryRegion.kMemStack) { if (compileStateTracker.ClassTable.IndexOf(ident) != ProtoCore.DSASM.Constants.kInvalidIndex) buildStatus.LogSemanticError(ident + " is a class name, can't be used as a variable."); ProtoCore.DSASM.SymbolNode symbolnode = new ProtoCore.DSASM.SymbolNode( ident, ProtoCore.DSASM.Constants.kInvalidIndex, ProtoCore.DSASM.Constants.kInvalidIndex, funcIndex, datatype, compileStateTracker.TypeSystem.BuildTypeObject((int)PrimitiveType.kTypeVar, false), size, datasize, false, codeBlock.symbolTable.runtimeIndex, region, false, null, globalClassIndex, ProtoCore.DSASM.AccessSpecifier.kPublic, false, codeBlock.codeBlockId); if (this.isEmittingImportNode) symbolnode.ExternLib = compileStateTracker.CurrentDSFileName; Debug.Assert(ProtoCore.DSASM.Constants.kInvalidIndex == symbolnode.symbolTableIndex); if (null == nodeArray) { AllocateVar(symbolnode); } else { AllocateArray(symbolnode, nodeArray); } // This is to handle that a variable is defined in a language // block which defined in a function, so the variable's scope // is that language block instead of function if (IsInLanguageBlockDefinedInFunction()) { symbolnode.classScope = Constants.kGlobalScope; symbolnode.functionIndex = Constants.kGlobalScope; } int symbolindex = ProtoCore.DSASM.Constants.kInvalidIndex; if (ProtoCore.DSASM.Constants.kInvalidIndex != globalClassIndex && !IsInLanguageBlockDefinedInFunction()) { symbolindex = compileStateTracker.ClassTable.ClassNodes[globalClassIndex].symbols.Append(symbolnode); } else { // Do not import global symbols from external libraries //if (this.isEmittingImportNode && core.IsParsingPreloadedAssembly) //{ // bool importGlobalSymbolFromLib = !string.IsNullOrEmpty(symbolnode.ExternLib) && // symbolnode.functionIndex == -1 && symbolnode.classScope == -1; // if (importGlobalSymbolFromLib) // { // return symbolnode; // } //} symbolindex = codeBlock.symbolTable.Append(symbolnode); } // TODO Jun: Set the symbol table index of the first local variable of 'funcIndex' // This will no longer required once the functiontable is refactored to include a symbol table // if the current codeblock is a while block, the procedureTable will be null if (null != localProcedure && null == localProcedure.firstLocal && !IsInLanguageBlockDefinedInFunction()) { localProcedure.firstLocal = symbolnode.index; } if (ProtoCore.DSASM.MemoryRegion.kMemHeap == symbolnode.memregion) { EmitInstrConsole(ProtoCore.DSASM.kw.alloca, symbolindex.ToString()); EmitAlloc(symbolindex); } symbolnode.symbolTableIndex = symbolindex; return symbolnode; }
private void EmitIdentifierNode(ImperativeNode node, ref ProtoCore.Type inferedType, bool isBooleanOp = false, ProtoCore.AssociativeGraph.GraphNode graphNode = null) { IdentifierNode t = node as IdentifierNode; if (t.Name.Equals(ProtoCore.DSDefinitions.Kw.kw_this)) { if (localProcedure != null) { if (localProcedure.isStatic) { string message = ProtoCore.BuildData.WarningMessage.kUsingThisInStaticFunction; compileStateTracker.BuildStatus.LogWarning(ProtoCore.BuildData.WarningID.kInvalidThis, message, compileStateTracker.CurrentDSFileName, t.line, t.col); EmitPushNull(); return; } else if (localProcedure.classScope == Constants.kGlobalScope) { string message = ProtoCore.BuildData.WarningMessage.kInvalidThis; compileStateTracker.BuildStatus.LogWarning(ProtoCore.BuildData.WarningID.kInvalidThis, message, compileStateTracker.CurrentDSFileName, t.line, t.col); EmitPushNull(); return; } else { EmitThisPointerNode(); return; } } else { string message = ProtoCore.BuildData.WarningMessage.kInvalidThis; compileStateTracker.BuildStatus.LogWarning(ProtoCore.BuildData.WarningID.kInvalidThis, message, compileStateTracker.CurrentDSFileName, t.line, t.col); EmitPushNull(); return; } } int dimensions = 0; int runtimeIndex = codeBlock.symbolTable.runtimeIndex; ProtoCore.Type type = new ProtoCore.Type(); type.UID = (int)ProtoCore.PrimitiveType.kTypeVoid; type.IsIndexable = false; ProtoCore.DSASM.SymbolNode symbolnode = null; //bool isAllocated = VerifyAllocation(t.Value, out blockId, out localAllocBlock, out symindex, ref type); //bool allocatedLocally = isAllocated && core.runtimeTableIndex == localAllocBlock; //bool allocatedExternally = isAllocated && core.runtimeTableIndex > localAllocBlock; //bool isVisible = isAllocated && core.runtimeTableIndex >= localAllocBlock; bool isAccessible = false; if (null == t.ArrayDimensions) { //check if it is a function instance ProtoCore.DSASM.ProcedureNode procNode = null; procNode = compileStateTracker.GetFirstVisibleProcedure(t.Name, null, codeBlock); if (null != procNode) { if (ProtoCore.DSASM.Constants.kInvalidIndex != procNode.procId) { // A global function inferedType.IsIndexable = false; inferedType.UID = (int)PrimitiveType.kTypeFunctionPointer; int fptr = compileStateTracker.FunctionPointerTable.functionPointerDictionary.Count; ProtoCore.DSASM.FunctionPointerNode fptrNode = new ProtoCore.DSASM.FunctionPointerNode(procNode.procId, procNode.runtimeIndex); compileStateTracker.FunctionPointerTable.functionPointerDictionary.TryAdd(fptr, fptrNode); compileStateTracker.FunctionPointerTable.functionPointerDictionary.TryGetBySecond(fptrNode, out fptr); EmitPushVarData(runtimeIndex, 0); EmitInstrConsole(ProtoCore.DSASM.kw.push, t.Name); ProtoCore.DSASM.StackValue opFunctionPointer = new ProtoCore.DSASM.StackValue(); opFunctionPointer.optype = ProtoCore.DSASM.AddressType.FunctionPointer; opFunctionPointer.opdata = fptr; opFunctionPointer.opdata_d = fptr; EmitPush(opFunctionPointer, t.line, t.col); return; } } } bool isAllocated = VerifyAllocation(t.Value, globalClassIndex, globalProcIndex, out symbolnode, out isAccessible); if (!isAllocated || !isAccessible) { if (isAllocated) { if (!isAccessible) { string message = String.Format(ProtoCore.BuildData.WarningMessage.kPropertyIsInaccessible, t.Value); buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kAccessViolation, message, compileStateTracker.CurrentDSFileName, t.line, t.col); } } else { string message = String.Format(ProtoCore.BuildData.WarningMessage.kUnboundIdentifierMsg, t.Value); buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kIdUnboundIdentifier, message, compileStateTracker.CurrentDSFileName, t.line, t.col); } inferedType.UID = (int)ProtoCore.PrimitiveType.kTypeNull; // Jun Comment: Specification excerpt // If resolution fails at this point a com.Design-Script.Imperative.Core.UnboundIdentifier // warning is emitted during pre-execute phase, and at the ID is bound to null. (R1 - Feb) EmitPushNull(); EmitPushVarData(runtimeIndex, dimensions); ProtoCore.Type varType = compileStateTracker.TypeSystem.BuildTypeObject((int)PrimitiveType.kTypeVar, false, 0); symbolnode = Allocate(t.Value, globalProcIndex, varType); EmitInstrConsole(ProtoCore.DSASM.kw.pop, t.Value); EmitPopForSymbol(symbolnode); } else { type = symbolnode.datatype; runtimeIndex = symbolnode.runtimeTableIndex; if (compileStateTracker.Options.AssociativeToImperativePropagation) { // Comment Jun: If this symbol belongs to an outer block, then append it to this language blocks dependent if (symbolnode.codeBlockId != codeBlock.codeBlockId) { // A parent codeblock owns this symbol if (null != graphNode) { ProtoCore.AssociativeGraph.GraphNode dependentNode = new ProtoCore.AssociativeGraph.GraphNode(); dependentNode.PushSymbolReference(symbolnode); graphNode.PushDependent(dependentNode); } } } } if (null != t.ArrayDimensions) { dimensions = DfsEmitArrayIndexHeap(t.ArrayDimensions); } //fix type's rank //fix type's rank if (type.rank >= 0) { type.rank -= dimensions; if (type.rank < 0) { //throw new Exception("Exceed maximum rank!"); type.rank = 0; } } //check whether the value is an array if (type.rank == 0) { type.IsIndexable = false; } EmitPushVarData(runtimeIndex, dimensions); EmitInstrConsole(ProtoCore.DSASM.kw.push, t.Value); EmitPushForSymbol(symbolnode, t); if (compileStateTracker.TypeSystem.IsHigherRank(type.UID, inferedType.UID)) { inferedType = type; } // We need to get inferedType for boolean variable so that we can perform type check inferedType.UID = (isBooleanOp || (type.UID == (int)PrimitiveType.kTypeBool)) ? (int)PrimitiveType.kTypeBool : type.UID; }
private int AllocateArg( string ident, int funcIndex, ProtoCore.Type datatype, int size = 1, int datasize = ProtoCore.DSASM.Constants.kPrimitiveSize, ImperativeNode nodeArray = null, ProtoCore.DSASM.MemoryRegion region = ProtoCore.DSASM.MemoryRegion.kMemStack) { ProtoCore.DSASM.SymbolNode symbolnode = new ProtoCore.DSASM.SymbolNode( ident, ProtoCore.DSASM.Constants.kInvalidIndex, ProtoCore.DSASM.Constants.kInvalidIndex, funcIndex, datatype, datatype, size, datasize, true, codeBlock.symbolTable.runtimeIndex, region); symbolnode.codeBlockId = codeBlock.codeBlockId; if (this.isEmittingImportNode) symbolnode.ExternLib = compileStateTracker.CurrentDSFileName; int symbolindex = ProtoCore.DSASM.Constants.kInvalidIndex; if (ProtoCore.DSASM.Constants.kInvalidIndex != codeBlock.symbolTable.IndexOf(symbolnode)) { buildStatus.LogSemanticError("redefinition of identifier '" + ident + "'"); } else { int locOffset = localProcedure.localCount; locOffset = localProcedure.localCount; symbolnode.index = -1 - ProtoCore.DSASM.StackFrame.kStackFrameSize - (locOffset + argOffset); ++argOffset; symbolindex = codeBlock.symbolTable.Append(symbolnode); } return symbolindex; }
private void EmitInlineConditionalNode(ImperativeNode node, ref ProtoCore.Type inferedType, ProtoCore.AST.ImperativeAST.BinaryExpressionNode parentNode = null) { InlineConditionalNode inlineConNode = node as InlineConditionalNode; IfStmtNode ifNode = new IfStmtNode(); ifNode.IfExprNode = inlineConNode.ConditionExpression; List<ImperativeNode> trueBody = new List<ImperativeNode>(); trueBody.Add(inlineConNode.TrueExpression); List<ImperativeNode> falseBody = new List<ImperativeNode>(); falseBody.Add(inlineConNode.FalseExpression); ifNode.IfBody = trueBody; ifNode.ElseBody = falseBody; DebugProperties.BreakpointOptions oldOptions = compileStateTracker.DebugProps.breakOptions; DebugProperties.BreakpointOptions newOptions = oldOptions; newOptions |= DebugProperties.BreakpointOptions.EmitInlineConditionalBreakpoint; compileStateTracker.DebugProps.breakOptions = newOptions; EmitIfStmtNode(ifNode, ref inferedType, parentNode, true); compileStateTracker.DebugProps.breakOptions = oldOptions; }
private void AllocateArray(ProtoCore.DSASM.SymbolNode symbol, ImperativeNode nodeArray) { symbol.isArray = true; //=================================================== // TODO Jun: // Determine which is optimal- // 1. Storing the array flag in the symbol, or... // 2. Storing the array flag as an instruction operand //=================================================== // TODO Jun: allocate to the stack is the array has empty expressions ArrayNode array = nodeArray as ArrayNode; bool heapAlloc = null != array.Expr; symbol.memregion = heapAlloc ? ProtoCore.DSASM.MemoryRegion.kMemHeap : ProtoCore.DSASM.MemoryRegion.kMemStack; if (ProtoCore.DSASM.MemoryRegion.kMemStack == symbol.memregion) { symbol.arraySizeList = new List<int>(); List<int> indexlist = new List<int>(); // TODO Jun: Optimize this DfsBuildIndex(nodeArray, indexlist); foreach (int indexVal in indexlist) { if (0 != indexVal) { symbol.size *= indexVal; } } // Rebuild the array that is needed to compute the size at each index indexlist.RemoveAt(0); indexlist.Add(symbol.datasize); for (int n = 0; n < indexlist.Count; ++n) { symbol.arraySizeList.Add(1); for (int i = n; i < indexlist.Count; ++i) { symbol.arraySizeList[n] *= indexlist[i]; } } } else if (ProtoCore.DSASM.MemoryRegion.kMemHeap == symbol.memregion) { int indexCnt = DfsEmitArrayIndexHeap(nodeArray); EmitInstrConsole(ProtoCore.DSASM.kw.push, indexCnt.ToString()); ProtoCore.DSASM.StackValue opSize = new ProtoCore.DSASM.StackValue(); opSize.optype = ProtoCore.DSASM.AddressType.Int; opSize.opdata = indexCnt; EmitPush(opSize); SetHeapData(symbol); } else { Debug.Assert(false, "Invalid memory region"); } SetStackIndex(symbol); }
private void EmitRangeExprNode(ImperativeNode node, ref ProtoCore.Type inferedType, ProtoCore.AssociativeGraph.GraphNode graphNode = null) { RangeExprNode range = node as RangeExprNode; // Do some static checking...probably it is not necessary. // Need to move these checkings to built-in function. if ((range.FromNode is IntNode || range.FromNode is DoubleNode) && (range.ToNode is IntNode || range.ToNode is DoubleNode) && (range.StepNode == null || (range.StepNode != null && (range.StepNode is IntNode || range.StepNode is DoubleNode)))) { decimal current = (range.FromNode is IntNode) ? Int64.Parse((range.FromNode as IntNode).value) : Decimal.Parse((range.FromNode as DoubleNode).value); decimal end = (range.ToNode is IntNode) ? Int64.Parse((range.ToNode as IntNode).value) : Decimal.Parse((range.ToNode as DoubleNode).value); ProtoCore.DSASM.RangeStepOperator stepoperator = range.stepoperator; decimal step = 1; if (range.StepNode != null) { step = (range.StepNode is IntNode) ? Int64.Parse((range.StepNode as IntNode).value) : Decimal.Parse((range.StepNode as DoubleNode).value); } if (stepoperator == ProtoCore.DSASM.RangeStepOperator.stepsize) { if (range.StepNode == null && end < current) { step = -1; } if (step == 0) { buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kInvalidRangeExpression, ProtoCore.BuildData.WarningMessage.kRangeExpressionWithStepSizeZero, compileStateTracker.CurrentDSFileName, range.StepNode.line, range.StepNode.col); EmitNullNode(new NullNode(), ref inferedType); return; } if ((end > current && step < 0) || (end < current && step > 0)) { buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kInvalidRangeExpression, ProtoCore.BuildData.WarningMessage.kRangeExpressionWithInvalidStepSize, compileStateTracker.CurrentDSFileName, range.StepNode.line, range.StepNode.col); EmitNullNode(new NullNode(), ref inferedType); return; } } else if (stepoperator == ProtoCore.DSASM.RangeStepOperator.num) { if (range.StepNode != null && !(range.StepNode is IntNode)) { buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kInvalidRangeExpression, ProtoCore.BuildData.WarningMessage.kRangeExpressionWithNonIntegerStepNumber, compileStateTracker.CurrentDSFileName, range.StepNode.line, range.StepNode.col); EmitNullNode(new NullNode(), ref inferedType); return; } if (step <= 0) { buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kInvalidRangeExpression, ProtoCore.BuildData.WarningMessage.kRangeExpressionWithNegativeStepNumber, compileStateTracker.CurrentDSFileName, range.StepNode.line, range.StepNode.col); EmitNullNode(new NullNode(), ref inferedType); return; } } else if (stepoperator == ProtoCore.DSASM.RangeStepOperator.approxsize) { if (step == 0) { buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kInvalidRangeExpression, ProtoCore.BuildData.WarningMessage.kRangeExpressionWithStepSizeZero, compileStateTracker.CurrentDSFileName, range.StepNode.line, range.StepNode.col); EmitNullNode(new NullNode(), ref inferedType); return; } } } // Replace with build-in RangeExpression() function. - Yu Ke var tmpFrom = nodeBuilder.BuildTempVariable(); var assignFrom = nodeBuilder.BuildBinaryExpression(tmpFrom, range.FromNode); EmitBinaryExpressionNode(assignFrom, ref inferedType); var tmpTo = nodeBuilder.BuildTempVariable(); var assignTo = nodeBuilder.BuildBinaryExpression(tmpTo, range.ToNode); EmitBinaryExpressionNode(assignTo, ref inferedType); var tmpStep = nodeBuilder.BuildTempVariable(); var assignStep = nodeBuilder.BuildBinaryExpression(tmpStep, range.StepNode == null ? new NullNode() : range.StepNode); EmitBinaryExpressionNode(assignStep, ref inferedType); BooleanNode hasStep = new BooleanNode { value = range.StepNode == null ? "false" : "true" }; var tmpStepSkip = nodeBuilder.BuildTempVariable(); var assignStepSkip = nodeBuilder.BuildBinaryExpression(tmpStepSkip, hasStep); EmitBinaryExpressionNode(assignStepSkip, ref inferedType); IntNode op = new IntNode(); switch (range.stepoperator) { case ProtoCore.DSASM.RangeStepOperator.stepsize: op.value = "0"; break; case ProtoCore.DSASM.RangeStepOperator.num: op.value = "1"; break; case ProtoCore.DSASM.RangeStepOperator.approxsize: op.value = "2"; break; default: op.value = "-1"; break; } var rangeExprFunc = nodeBuilder.BuildFunctionCall(Constants.kFunctionRangeExpression, new List<ImperativeNode> { tmpFrom, tmpTo, tmpStep, op, tmpStepSkip }); NodeUtils.CopyNodeLocation(rangeExprFunc, range); EmitFunctionCallNode(rangeExprFunc, ref inferedType, false, graphNode); if (range.ArrayDimensions != null) { int dimensions = DfsEmitArrayIndexHeap(range.ArrayDimensions); EmitInstrConsole(ProtoCore.DSASM.kw.pushindex, dimensions.ToString() + "[dim]"); EmitPushArrayIndex(dimensions); } }
// this method is used in conjuction with array var declarations private void DfsBuildIndex(ImperativeNode node, List<int> indexlist) { if (node is ArrayNode) { ArrayNode array = node as ArrayNode; int exprval = 0; if (null != array.Expr) { exprval = DfsExprValue(array.Expr); } indexlist.Add(exprval); DfsBuildIndex(array.Type, indexlist); } }
private void EmitVarDeclNode(ImperativeNode node, ref ProtoCore.Type inferedType) { VarDeclNode varNode = node as VarDeclNode; ProtoCore.Type type = BuildArgumentTypeFromVarDeclNode(varNode); type.IsIndexable = false; // TODO Jun: Create a class table for holding the primitive and custom data types const int primitivesize = 1; int datasize = primitivesize; int symindex = ProtoCore.DSASM.Constants.kInvalidIndex; IdentifierNode tVar = null; if (varNode.NameNode is IdentifierNode) { // Allocate with no initializer tVar = varNode.NameNode as IdentifierNode; ProtoCore.DSASM.SymbolNode symnode = Allocate(tVar.Value, globalProcIndex, type, datasize, datasize, tVar.ArrayDimensions, varNode.memregion); symindex = symnode.symbolTableIndex; } else if (varNode.NameNode is BinaryExpressionNode) { BinaryExpressionNode bNode = varNode.NameNode as BinaryExpressionNode; tVar = bNode.LeftNode as IdentifierNode; Debug.Assert(null != tVar, "Check generated AST"); Debug.Assert(null != bNode.RightNode, "Check generated AST"); ProtoCore.DSASM.SymbolNode symnode = null; // Is it an array if (null != tVar.ArrayDimensions) { // Allocate an array with initializer if (bNode.RightNode is ExprListNode) { ExprListNode exprlist = bNode.RightNode as ExprListNode; int size = datasize * exprlist.list.Count; symnode = Allocate(tVar.Value, globalProcIndex, type, size, datasize, tVar.ArrayDimensions, varNode.memregion); symindex = symnode.symbolTableIndex; for (int n = 0; n < exprlist.list.Count; ++n) { DfsTraverse(exprlist.list[n], ref inferedType); ArrayNode array = new ArrayNode(); array.Expr = nodeBuilder.BuildIdentfier(n.ToString(), PrimitiveType.kTypeInt); array.Type = null; DfsEmitArrayIndex(array, symindex); EmitInstrConsole(ProtoCore.DSASM.kw.pop, ProtoCore.DSASM.kw.regDX); ProtoCore.DSASM.StackValue opRes = new ProtoCore.DSASM.StackValue(); opRes.optype = ProtoCore.DSASM.AddressType.Register; opRes.opdata = (int)ProtoCore.DSASM.Registers.DX; EmitPop(opRes, Constants.kGlobalScope); EmitInstrConsole(ProtoCore.DSASM.kw.pop, tVar.Value); EmitPopForSymbol(symnode); } } else { buildStatus.LogSemanticError("array initializer must be an expression list", compileStateTracker.CurrentDSFileName, bNode.RightNode.line, bNode.RightNode.col); } } else { // Allocate a single variable with initializer symnode = Allocate(tVar.Value, globalProcIndex, type, datasize, datasize, tVar.ArrayDimensions, varNode.memregion); symindex = symnode.symbolTableIndex; DfsTraverse(bNode.RightNode, ref inferedType); EmitInstrConsole(ProtoCore.DSASM.kw.pop, tVar.Value); EmitPopForSymbol(symnode); } } else { Debug.Assert(false, "Check generated AST"); } if (ProtoCore.DSASM.Constants.kInvalidIndex == symindex) { throw new BuildHaltException("0CB5BD17"); } }
// this method is used in conjuction with array indexing private void DfsEmitArrayIndex(ImperativeNode node, int symbolindex, int index = 0) { // s = b + ((i * i.w) + (j * j.w) + (n * n.w)) if (node is ArrayNode) { ArrayNode array = node as ArrayNode; ProtoCore.Type type = new ProtoCore.Type(); type.UID = (int)ProtoCore.PrimitiveType.kTypeVoid; type.IsIndexable = false; DfsTraverse(array.Expr, ref type); // Max size of the current dimension int w = codeBlock.symbolTable.symbolList[symbolindex].arraySizeList[index]; // TODO Jun: Performance improvement // Avoid having to generate instructions for the current index if 'w' is 0 EmitInstrConsole(ProtoCore.DSASM.kw.push, w.ToString()); ProtoCore.DSASM.StackValue opWidth = new ProtoCore.DSASM.StackValue(); opWidth.optype = ProtoCore.DSASM.AddressType.Int; opWidth.opdata = w; EmitPush(opWidth); string op = null; ProtoCore.DSASM.StackValue opAX = new ProtoCore.DSASM.StackValue(); opAX.optype = ProtoCore.DSASM.AddressType.Register; opAX.opdata = (int)ProtoCore.DSASM.Registers.AX; ProtoCore.DSASM.StackValue opBX = new ProtoCore.DSASM.StackValue(); opBX.optype = ProtoCore.DSASM.AddressType.Register; opBX.opdata = (int)ProtoCore.DSASM.Registers.BX; ProtoCore.DSASM.StackValue opRes = new ProtoCore.DSASM.StackValue(); opRes.optype = ProtoCore.DSASM.AddressType.Register; opRes.opdata = (int)ProtoCore.DSASM.Registers.AX; // Multiplying the max array size by the number of elements EmitInstrConsole(ProtoCore.DSASM.kw.pop, ProtoCore.DSASM.kw.regBX); EmitPop(opBX, Constants.kGlobalScope); EmitInstrConsole(ProtoCore.DSASM.kw.pop, ProtoCore.DSASM.kw.regAX); EmitPop(opAX, Constants.kGlobalScope); op = opKwData.opStringTable[ProtoCore.DSASM.Operator.mul]; EmitInstrConsole(op, ProtoCore.DSASM.kw.regAX, ProtoCore.DSASM.kw.regBX); EmitBinary(opKwData.opCodeTable[ProtoCore.DSASM.Operator.mul], opAX, opBX); EmitInstrConsole(ProtoCore.DSASM.kw.push, ProtoCore.DSASM.kw.regAX); EmitPush(opRes); if (array.Type is ArrayNode) { DfsEmitArrayIndex(array.Type, symbolindex, index + 1); // Adding the previous arraysize to the current one EmitInstrConsole(ProtoCore.DSASM.kw.pop, ProtoCore.DSASM.kw.regBX); EmitPop(opBX, Constants.kGlobalScope); EmitInstrConsole(ProtoCore.DSASM.kw.pop, ProtoCore.DSASM.kw.regAX); EmitPop(opAX, Constants.kGlobalScope); op = opKwData.opStringTable[ProtoCore.DSASM.Operator.add]; EmitInstrConsole(op, ProtoCore.DSASM.kw.regAX, ProtoCore.DSASM.kw.regBX); EmitBinary(opKwData.opCodeTable[ProtoCore.DSASM.Operator.add], opAX, opBX); EmitInstrConsole(ProtoCore.DSASM.kw.push, ProtoCore.DSASM.kw.regAX); EmitPush(opRes); } } else { Debug.Assert(false, "ast error – check ast construction"); } }
private bool IsNoValueStatement(ImperativeNode node) { return (node is IfStmtNode) || (node is ForLoopNode) || (node is WhileStmtNode); }
private void DfsEmitArraySize(ImperativeNode node) { // s = size * ( i * j * k..n ) if (node is ArrayNode) { ArrayNode array = node as ArrayNode; ProtoCore.Type type = new ProtoCore.Type(); type.UID = (int)ProtoCore.PrimitiveType.kInvalidType; type.IsIndexable = false; DfsTraverse(array.Expr, ref type); if (array.Type is ArrayNode) { DfsEmitArraySize(array.Type); EmitInstrConsole(ProtoCore.DSASM.kw.pop, ProtoCore.DSASM.kw.regBX); ProtoCore.DSASM.StackValue opBX = new ProtoCore.DSASM.StackValue(); opBX.optype = ProtoCore.DSASM.AddressType.Register; opBX.opdata = (int)ProtoCore.DSASM.Registers.BX; EmitPop(opBX, Constants.kGlobalScope); EmitInstrConsole(ProtoCore.DSASM.kw.pop, ProtoCore.DSASM.kw.regAX); ProtoCore.DSASM.StackValue opAX = new ProtoCore.DSASM.StackValue(); opAX.optype = ProtoCore.DSASM.AddressType.Register; opAX.opdata = (int)ProtoCore.DSASM.Registers.AX; EmitPop(opAX, Constants.kGlobalScope); string op = opKwData.opStringTable[ProtoCore.DSASM.Operator.add]; EmitInstrConsole(op, ProtoCore.DSASM.kw.regAX, ProtoCore.DSASM.kw.regBX); EmitBinary(opKwData.opCodeTable[ProtoCore.DSASM.Operator.add], opAX, opBX); EmitInstrConsole(ProtoCore.DSASM.kw.push, ProtoCore.DSASM.kw.regAX); EmitPush(opAX); } } else { Debug.Assert(false, "ast error – check ast construction"); } }
public ImperativeNode BuildBinaryExpression(ImperativeNode leftNode, ImperativeNode rightNode, Operator op = Operator.assign) { var binaryExpr = new BinaryExpressionNode(); binaryExpr.LeftNode = leftNode; binaryExpr.Optr = op; binaryExpr.RightNode = rightNode; return binaryExpr; }
private int DfsExprValue(ImperativeNode node) { if (node is IdentifierNode) { int val = 0; IdentifierNode t = node as IdentifierNode; try { val = System.Convert.ToInt32(t.Value); return val; } catch (OverflowException) { buildStatus.LogSemanticError("Array size overflow", compileStateTracker.CurrentDSFileName, t.line, t.col); } catch (FormatException) { buildStatus.LogSemanticError("Array declaration expected constant expression", compileStateTracker.CurrentDSFileName, t.line, t.col); } } else if (node is BinaryExpressionNode) { BinaryExpressionNode b = node as BinaryExpressionNode; Debug.Assert(ProtoCore.DSASM.Operator.mul == b.Optr); int left = DfsExprValue(b.LeftNode); int right = DfsExprValue(b.RightNode); return left * right; } return 1; }
protected void EmitGropuExpressionNode(ImperativeNode node, ref ProtoCore.Type inferedType) { GroupExpressionNode group = node as GroupExpressionNode; if (group == null) { return; } var tmpVar = nodeBuilder.BuildTempVariable(); var binaryExpr = nodeBuilder.BuildBinaryExpression(tmpVar, group.Expression); EmitBinaryExpressionNode(binaryExpr, ref inferedType, false); if (group.ArrayDimensions != null) { (tmpVar as IdentifierNode).ArrayDimensions = group.ArrayDimensions; } EmitIdentifierNode(tmpVar, ref inferedType, false); }
private void EmitBinaryExpressionNode(ImperativeNode node, ref ProtoCore.Type inferedType, bool isBooleanOp = false, ProtoCore.AssociativeGraph.GraphNode graphNode = null, ProtoCore.AST.ImperativeAST.BinaryExpressionNode parentNode = null) { if (!IsParsingGlobal() && !IsParsingGlobalFunctionBody()) return; bool isBooleanOperation = false; BinaryExpressionNode b = node as BinaryExpressionNode; ProtoCore.Type leftType = new ProtoCore.Type(); leftType.UID = (int)ProtoCore.PrimitiveType.kTypeVar; ProtoCore.Type rightType = new ProtoCore.Type(); rightType.UID = (int)ProtoCore.PrimitiveType.kTypeVar; if (ProtoCore.DSASM.Operator.assign != b.Optr) { isBooleanOperation = ProtoCore.DSASM.Operator.lt == b.Optr || ProtoCore.DSASM.Operator.gt == b.Optr || ProtoCore.DSASM.Operator.le == b.Optr || ProtoCore.DSASM.Operator.ge == b.Optr || ProtoCore.DSASM.Operator.eq == b.Optr || ProtoCore.DSASM.Operator.nq == b.Optr || ProtoCore.DSASM.Operator.and == b.Optr || ProtoCore.DSASM.Operator.or == b.Optr; DfsTraverse(b.LeftNode, ref inferedType, isBooleanOperation, graphNode, AssociativeSubCompilePass.kNone, parentNode); if (inferedType.UID == (int)PrimitiveType.kTypeFunctionPointer && emitDebugInfo) { buildStatus.LogSemanticError("Function pointer is not allowed at binary expression other than assignment!", compileStateTracker.CurrentDSFileName, b.LeftNode.line, b.LeftNode.col); } leftType.UID = inferedType.UID; leftType.IsIndexable = inferedType.IsIndexable; } else { if (b.LeftNode is IdentifierListNode) { ProtoCore.AST.Node lnode = b.LeftNode; bool isCollapsed; if (parentNode != null) { NodeUtils.SetNodeLocation(lnode, parentNode, parentNode); } else { NodeUtils.SetNodeLocation(lnode, b, b); } EmitGetterSetterForIdentList(lnode, ref inferedType, null, ProtoCore.DSASM.AssociativeSubCompilePass.kNone, out isCollapsed, b.RightNode); // Get the lhs symbol list ProtoCore.Type type = new ProtoCore.Type(); type.UID = globalClassIndex; ProtoCore.AssociativeGraph.UpdateNodeRef leftNodeRef = new ProtoCore.AssociativeGraph.UpdateNodeRef(); DFSGetSymbolList(lnode, ref type, leftNodeRef); // Get the first identifier symbol runtime index as it is required for the pushdep List<ProtoCore.DSASM.SymbolNode> symbolList = new List<ProtoCore.DSASM.SymbolNode>(); symbolList.Add(leftNodeRef.nodeList[0].symbol); int runtimeIndex = leftNodeRef.nodeList[0].symbol.runtimeTableIndex; // Append the rest of the symbols in the identifierlist for (int n = 1; n < leftNodeRef.nodeList.Count; ++n) { if (leftNodeRef.nodeList[n].symbol != null) symbolList.Add(leftNodeRef.nodeList[n].symbol); } EmitPushDepData(symbolList); EmitPushDep(runtimeIndex, symbolList.Count, globalClassIndex); return; } } // (Ayush) in case of PostFixNode, only traverse the identifier now. Post fix operation will be applied later. #if ENABLE_INC_DEC_FIX if (b.RightNode is PostFixNode) DfsTraverse((b.RightNode as PostFixNode).Identifier, ref inferedType, isBooleanOperation); else { #endif if ((ProtoCore.DSASM.Operator.assign == b.Optr) && (b.RightNode is LanguageBlockNode)) { inferedType.UID = (int)ProtoCore.PrimitiveType.kTypeVar; inferedType.IsIndexable = false; } if (b.RightNode == null && b.Optr == Operator.assign && b.LeftNode is IdentifierNode) { IdentifierNode t = b.LeftNode as IdentifierNode; ProtoCore.DSASM.SymbolNode symbolnode = null; bool isAccessible = false; bool hasAllocated = VerifyAllocation(t.Value, globalClassIndex, globalProcIndex, out symbolnode, out isAccessible); if (hasAllocated) { b.RightNode = nodeBuilder.BuildIdentfier(t.Value); } else { b.RightNode = new NullNode(); } } if (parentNode != null) { DfsTraverse(b.RightNode, ref inferedType, isBooleanOperation, graphNode, ProtoCore.DSASM.AssociativeSubCompilePass.kNone, parentNode); } else { DfsTraverse(b.RightNode, ref inferedType, isBooleanOperation, graphNode, ProtoCore.DSASM.AssociativeSubCompilePass.kNone, b); } #if ENABLE_INC_DEC_FIX } #endif rightType.UID = inferedType.UID; rightType.IsIndexable = inferedType.IsIndexable; BinaryExpressionNode rightNode = b.RightNode as BinaryExpressionNode; if ((rightNode != null) && (ProtoCore.DSASM.Operator.assign == rightNode.Optr)) DfsTraverse(rightNode.LeftNode, ref inferedType); if (b.Optr != ProtoCore.DSASM.Operator.assign) { if (inferedType.UID == (int)PrimitiveType.kTypeFunctionPointer && emitDebugInfo) { buildStatus.LogSemanticError("Function pointer is not allowed at binary expression other than assignment!", compileStateTracker.CurrentDSFileName, b.RightNode.line, b.RightNode.col); } EmitBinaryOperation(leftType, rightType, b.Optr); isBooleanOp = false; //if post fix, now traverse the post fix #if ENABLE_INC_DEC_FIX if (b.RightNode is PostFixNode) EmitPostFixNode(b.RightNode, ref inferedType); #endif return; } if (b.LeftNode is IdentifierNode) { IdentifierNode t = b.LeftNode as IdentifierNode; ProtoCore.DSASM.SymbolNode symbolnode = null; string s = t.Value; bool isReturn = (s == ProtoCore.DSDefinitions.Kw.kw_return); if (isReturn) { EmitReturnStatement(node, inferedType); } else { { // check whether the variable name is a function name bool isAccessibleFp; int realType; ProtoCore.DSASM.ProcedureNode procNode = null; if (globalClassIndex != ProtoCore.DSASM.Constants.kGlobalScope) { procNode = compileStateTracker.ClassTable.ClassNodes[globalClassIndex].GetMemberFunction(t.Name, null, globalClassIndex, out isAccessibleFp, out realType); } if (procNode == null) { procNode = compileStateTracker.GetFirstVisibleProcedure(t.Name, null, codeBlock); } if (procNode != null) { if (ProtoCore.DSASM.Constants.kInvalidIndex != procNode.procId && emitDebugInfo) { buildStatus.LogSemanticError("\"" + t.Name + "\"" + "is a function and not allowed as a variable name", compileStateTracker.CurrentDSFileName, t.line, t.col); } } } bool isAccessible = false; bool isAllocated = false; // if it's forloop, verify allocation with its original arrayname if (t.ArrayName != null && !t.ArrayName.Equals("")) { isAllocated = VerifyAllocation(t.Value, t.ArrayName, globalClassIndex, globalProcIndex, out symbolnode, out isAccessible); } else { isAllocated = VerifyAllocation(t.Value, globalClassIndex, globalProcIndex, out symbolnode, out isAccessible); } int runtimeIndex = (!isAllocated) ? codeBlock.symbolTable.runtimeIndex : symbolnode.runtimeTableIndex; // Comment Jun: Add modifeid properties into the updatedProperties list of the current function // This propagates upated of mproperties taht were modified in an imperative block if (null != localProcedure && ProtoCore.DSASM.Constants.kGlobalScope != localProcedure.classScope) { if (isAllocated) { Validity.Assert(null != symbolnode); // Get the lhs symbol list ProtoCore.Type type = new ProtoCore.Type(); type.UID = globalClassIndex; ProtoCore.AssociativeGraph.UpdateNodeRef leftNodeRef = new ProtoCore.AssociativeGraph.UpdateNodeRef(); DFSGetSymbolList(b.LeftNode, ref type, leftNodeRef); localProcedure.updatedProperties.Push(leftNodeRef); } } // TODO Jun: Update mechanism work in progress - a flag to manually enable update bool enableUpdate = false; if (enableUpdate) { bool isExternal = false; // isAllocated && currentLangBlock != codeBlockId; //bool isAssociative = ProtoCore.Language.kAssociative == core.exeList[currentLangBlock].language; bool isAssociative = false; if (isExternal && isAssociative) { // Check if this is a modifier variable bool isVariableAModifierStack = false; if (isVariableAModifierStack) { // Check if modifying a named modifier state bool isNameModifierState = false; if (isNameModifierState) { //bool isStateIntermediate = false; } else { } //targetLangBlock = blockId; } } } int dimensions = 0; if (null != t.ArrayDimensions) { dimensions = DfsEmitArrayIndexHeap(t.ArrayDimensions); } ProtoCore.Type castType = compileStateTracker.TypeSystem.BuildTypeObject((int)PrimitiveType.kTypeVar, false); var tident = b.LeftNode as TypedIdentifierNode; if (tident != null) { int castUID = tident.datatype.UID; if ((int)PrimitiveType.kInvalidType == castUID) { castUID = compileStateTracker.ClassTable.IndexOf(tident.datatype.Name); } if ((int)PrimitiveType.kInvalidType == castUID) { string message = String.Format(ProtoCore.BuildData.WarningMessage.kTypeUndefined, tident.datatype.Name); buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kTypeUndefined, message, compileStateTracker.CurrentDSFileName, b.line, b.col); castType = compileStateTracker.TypeSystem.BuildTypeObject((int)PrimitiveType.kInvalidType, false); castType.Name = tident.datatype.Name; castType.rank = tident.datatype.rank; castType.IsIndexable = (castType.rank != 0); } else { castType = compileStateTracker.TypeSystem.BuildTypeObject(castUID, tident.datatype.IsIndexable, tident.datatype.rank); } } if (globalClassIndex != ProtoCore.DSASM.Constants.kInvalidIndex) { int symbol = ProtoCore.DSASM.Constants.kInvalidIndex; for (int n = 0; n < compileStateTracker.ClassTable.ClassNodes[globalClassIndex].symbols.symbolList.Count; ++n) { //Fuqiang: Not a member variable if it is a local variable inside a function with the same name bool localVarInMemFunc = false; if (localProcedure != null) { if (symbolnode == null) { if (!isAllocated) // if isAllocated, inaccessible member variable { localVarInMemFunc = true; } } else if (symbolnode.functionIndex != ProtoCore.DSASM.Constants.kGlobalScope && !localProcedure.isConstructor) { localVarInMemFunc = true; } } bool isMemberVar = ProtoCore.DSASM.Constants.kGlobalScope == compileStateTracker.ClassTable.ClassNodes[globalClassIndex].symbols.symbolList[n].functionIndex && compileStateTracker.ClassTable.ClassNodes[globalClassIndex].symbols.symbolList[n].name == t.Name && !localVarInMemFunc; if (isMemberVar) { if (t.ArrayDimensions == null) compileStateTracker.ClassTable.ClassNodes[globalClassIndex].symbols.symbolList[n].datatype = inferedType; else if (dimensions == inferedType.rank) compileStateTracker.ClassTable.ClassNodes[globalClassIndex].symbols.symbolList[n].datatype.UID = inferedType.UID; symbol = symbolnode.symbolTableIndex; break; } } if (symbol == ProtoCore.DSASM.Constants.kInvalidIndex) { if (!isAllocated) { symbolnode = Allocate(t.Name, globalProcIndex, inferedType); } symbol = symbolnode.symbolTableIndex; if (b.LeftNode is TypedIdentifierNode) { symbolnode.SetStaticType(castType); } castType = symbolnode.staticType; EmitPushVarData(runtimeIndex, dimensions, castType.UID, castType.rank); EmitInstrConsole(ProtoCore.DSASM.kw.pop, s); ProtoCore.DSASM.StackValue operand = new ProtoCore.DSASM.StackValue(); operand.optype = ProtoCore.DSASM.AddressType.VarIndex; operand.opdata = symbol; EmitPop(operand, symbolnode.classScope, node.line, node.col, node.endLine, node.endCol); } else { if (b.LeftNode is TypedIdentifierNode) { symbolnode.SetStaticType(castType); } castType = symbolnode.staticType; EmitPushVarData(runtimeIndex, dimensions, castType.UID, castType.rank); EmitInstrConsole(ProtoCore.DSASM.kw.popm, t.Name); ProtoCore.DSASM.StackValue operand = new ProtoCore.DSASM.StackValue(); operand.optype = symbolnode.isStatic ? ProtoCore.DSASM.AddressType.StaticMemVarIndex : ProtoCore.DSASM.AddressType.MemVarIndex; operand.opdata = symbol; EmitPopm(operand, node.line, node.col, node.endLine, node.endCol); } } else { if (!isAllocated) { symbolnode = Allocate(t.Value, globalProcIndex, inferedType); if (dimensions > 0) { symbolnode.datatype.rank = dimensions; } } else if (dimensions == 0) { if (compileStateTracker.TypeSystem.IsHigherRank(inferedType.UID, symbolnode.datatype.UID)) { symbolnode.datatype = inferedType; } } if (b.LeftNode is TypedIdentifierNode) { symbolnode.SetStaticType(castType); } castType = symbolnode.staticType; EmitPushVarData(runtimeIndex, dimensions, castType.UID, castType.rank); EmitInstrConsole(ProtoCore.DSASM.kw.pop, t.Value); if (parentNode != null) { EmitPopForSymbol(symbolnode, parentNode.line, parentNode.col, parentNode.endLine, parentNode.endCol); } else { EmitPopForSymbol(symbolnode, node.line, node.col, node.endLine, node.endCol); } // Check if the symbol was not here, only then it becomes a valid propagation symbol // TODO Jun: check if the symbol was allocated from an associative block if (!ProtoCore.Utils.CoreUtils.IsAutoGeneratedVar(symbolnode.name)) { if (codeBlock.symbolTable.runtimeIndex != symbolnode.runtimeTableIndex) { List<ProtoCore.DSASM.SymbolNode> symbolList = new List<ProtoCore.DSASM.SymbolNode>(); symbolList.Add(symbolnode); EmitPushDepData(symbolList); EmitPushDep(runtimeIndex, symbolList.Count, globalClassIndex); } } } } } else if (b.LeftNode is IdentifierListNode) { // keyu: the left hand side of an assignment statement won't be an // identifier list anymore after replacing all properties (not // including the left-most property) with getters/setter. // // If this case really happens, we need to look into that. Debug.Assert(false, "The left hand of an assignment statement never will be an identifier list node"); /* int depth = 0; ProtoCore.Type lastType = new ProtoCore.Type(); lastType.UID = (int)PrimitiveType.kInvalidType; lastType.IsIndexable = false; bool isFirstIdent = false; bool isIdentReference = DfsEmitIdentList(b.LeftNode, b, globalClassIndex, ref lastType, ref depth, ref inferedType, true, ref isFirstIdent); inferedType.UID = isBooleanOp ? (int)PrimitiveType.kTypeBool : inferedType.UID; if (!isIdentReference) { buildStatus.LogSemanticError("The left hand side of an operation cannot be a function call", core.CurrentDSFileName, b.LeftNode.line, b.LeftNode.col); throw new BuildHaltException(); } EmitInstrConsole(ProtoCore.DSASM.kw.poplist, depth.ToString(), globalClassIndex.ToString()); // TODO Jun: Get blockid int blockId = 0; EmitPopList(depth, globalClassIndex, blockId, node.line, node.col, node.endLine, node.endCol); */ } else { string message = "Illegal assignment (38A37EA5)"; buildStatus.LogSemanticError(message, compileStateTracker.CurrentDSFileName, b.line, b.col); throw new BuildHaltException(message); } if ((node as BinaryExpressionNode).Optr == Operator.assign) EmitSetExpressionUID(compileStateTracker.ExpressionUID++); //if post fix, now traverse the post fix #if ENABLE_INC_DEC_FIX if (b.RightNode is PostFixNode) EmitPostFixNode(b.RightNode, ref inferedType); #endif }