public override ImperativeNode VisitIdentifierNode(IdentifierNode node) { string variable = node.Value; string newVariable = mapper(variable); var newIdent = new IdentifierNode(node); newIdent.Value = newVariable; return base.VisitIdentifierNode(newIdent); }
public ImperativeNode BuildIdentfier(string name, PrimitiveType type = PrimitiveType.kTypeVar) { var ident = new IdentifierNode(); ident.Name = ident.Value = name; ident.datatype = compileState.TypeSystem.BuildTypeObject(type, false); return ident; }
// TODO Jun: Merge TraverseFunctionCall with the associative version and implement in a codegen utils file //Fuqiang: Cannot merge the two functions. They are different. eg. Associative has "emitReplicationGuide = false;" public override void TraverseFunctionCall(ProtoCore.AST.Node node, ProtoCore.AST.Node parentNode, int lefttype, int depth, ref ProtoCore.Type inferedType, ProtoCore.AssociativeGraph.GraphNode graphNode = null, ProtoCore.DSASM.AssociativeSubCompilePass subPass = ProtoCore.DSASM.AssociativeSubCompilePass.kNone) { Debug.Assert(null == graphNode); FunctionCallNode funcCall = node as FunctionCallNode; string procName = funcCall.Function.Name; List<ProtoCore.Type> arglist = new List<ProtoCore.Type>(); foreach (ImperativeNode paramNode in funcCall.FormalArguments) { ProtoCore.Type paramType = new ProtoCore.Type(); paramType.UID = (int)ProtoCore.PrimitiveType.kTypeVoid; paramType.IsIndexable = false; // If it's a binary node then continue type check, otherwise disable type check and just take the type of paramNode itself // f(1+2.0) -> type check enabled - param is typed as double // f(2) -> type check disabled - param is typed as int enforceTypeCheck = !(paramNode is BinaryExpressionNode); DfsTraverse(paramNode, ref paramType); enforceTypeCheck = true; arglist.Add(paramType); } ProtoCore.DSASM.ProcedureNode procNode = null; int type = ProtoCore.DSASM.Constants.kInvalidIndex; bool isConstructor = false; bool isStatic = false; bool hasLogError = false; int refClassIndex = ProtoCore.DSASM.Constants.kInvalidIndex; if (parentNode != null && parentNode is ProtoCore.AST.AssociativeAST.IdentifierListNode) { ProtoCore.AST.Node leftnode = (parentNode as ProtoCore.AST.AssociativeAST.IdentifierListNode).LeftNode; if (leftnode != null && leftnode is ProtoCore.AST.AssociativeAST.IdentifierNode) { refClassIndex = compileState.ClassTable.IndexOf(leftnode.Name); } } // If lefttype is a valid class then check if calling a constructor if ((int)ProtoCore.PrimitiveType.kInvalidType != inferedType.UID && (int)ProtoCore.PrimitiveType.kTypeVoid != inferedType.UID) { bool isAccessible; int realType; if (inferedType.UID > (int)PrimitiveType.kMaxPrimitives) { //check if it is function pointer ProtoCore.DSASM.SymbolNode symbolnode = null; bool isAllocated = VerifyAllocation(procName, inferedType.UID, out symbolnode, out isAccessible); if (isAllocated) { procName = ProtoCore.DSASM.Constants.kFunctionPointerCall; } } if (procName != ProtoCore.DSASM.Constants.kFunctionPointerCall) { procNode = compileState.ClassTable.ClassNodes[inferedType.UID].GetMemberFunction(procName, arglist, globalClassIndex, out isAccessible, out realType); if (procNode != null) { Debug.Assert(realType != ProtoCore.DSASM.Constants.kInvalidIndex); isConstructor = procNode.isConstructor; isStatic = procNode.isStatic; type = lefttype = realType; if ((refClassIndex != ProtoCore.DSASM.Constants.kInvalidIndex) && !procNode.isStatic && !procNode.isConstructor) { return; } if (!isAccessible) { type = lefttype = realType; hasLogError = true; } } } } if (!isConstructor && !isStatic && procName != ProtoCore.DSASM.Constants.kFunctionPointerCall) { //check if it is function pointer bool isAccessibleFp; ProtoCore.DSASM.SymbolNode symbolnode = null; bool isAllocated = VerifyAllocation(procName, globalClassIndex, out symbolnode, out isAccessibleFp); if (isAllocated) // not checking the type against function pointer, as the type could be var { procName = ProtoCore.DSASM.Constants.kFunctionPointerCall; } else { procNode = compileState.GetFirstVisibleProcedure(procName, arglist, codeBlock); if (null != procNode) { if ((int)ProtoCore.DSASM.Constants.kInvalidIndex != procNode.procId) { // A global function if (compileState.TypeSystem.IsHigherRank((int)procNode.returntype.UID, inferedType.UID)) { inferedType = procNode.returntype; } } else { procNode = null; } } else { type = (lefttype != ProtoCore.DSASM.Constants.kInvalidIndex) ? lefttype : globalClassIndex; if (type != ProtoCore.DSASM.Constants.kInvalidIndex) { int realType; bool isAccessible; ProtoCore.DSASM.ProcedureNode memProcNode = compileState.ClassTable.ClassNodes[type].GetMemberFunction(procName, arglist, globalClassIndex, out isAccessible, out realType); if (memProcNode != null) { Debug.Assert(realType != ProtoCore.DSASM.Constants.kInvalidIndex); procNode = memProcNode; inferedType = procNode.returntype; type = realType; if ((refClassIndex != ProtoCore.DSASM.Constants.kInvalidIndex) && !procNode.isStatic && !procNode.isConstructor) { inferedType.UID = (int)PrimitiveType.kTypeNull; return; } if (!isAccessible) { procNode = null; if (!hasLogError) { hasLogError = true; } } } } } } } if (null != procNode) { //if call is replication call if (procNode.isThisCallReplication) { inferedType.IsIndexable = true; inferedType.rank++; } } else { if (depth <= 0 && procName != ProtoCore.DSASM.Constants.kFunctionPointerCall) { inferedType.UID = (int)PrimitiveType.kTypeNull; } else { if (procName == ProtoCore.DSASM.Constants.kFunctionPointerCall && depth == 0) { ProtoCore.DSASM.DynamicFunctionNode dynamicFunctionNode = new ProtoCore.DSASM.DynamicFunctionNode(procName, arglist, lefttype); compileState.DynamicFunctionTable.functionTable.Add(dynamicFunctionNode); IdentifierNode iNode = new IdentifierNode() { Value = funcCall.Function.Name, Name = funcCall.Function.Name, datatype = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, false) }; EmitIdentifierNode(iNode, ref inferedType); } else { ProtoCore.DSASM.DynamicFunctionNode dynamicFunctionNode = new ProtoCore.DSASM.DynamicFunctionNode(funcCall.Function.Name, arglist, lefttype); compileState.DynamicFunctionTable.functionTable.Add(dynamicFunctionNode); } //assign inferedType to var inferedType.UID = (int)PrimitiveType.kTypeVar; } } }
protected FunctionCallNode EmitGetterSetterForIdent(IdentifierNode inode, bool isSetter = false) { if (isSetter) { FunctionCallNode setter = new FunctionCallNode(); setter.Function = inode; IdentifierNode tmpArg = new IdentifierNode(); tmpArg.Name = tmpArg.Value = ProtoCore.DSASM.Constants.kTempArg; tmpArg.datatype = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, false); setter.FormalArguments.Add(tmpArg); return setter; } else { FunctionCallNode getter = new FunctionCallNode(); getter.Function = inode; return getter; } }
private void EmitVarDeclNode(ImperativeNode node, ref ProtoCore.Type inferedType) { VarDeclNode varNode = node as VarDeclNode; ProtoCore.Type type = new ProtoCore.Type(); type.UID = compileState.TypeSystem.GetType(varNode.ArgumentType.Name); 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); IdentLocation.AddEntry(symnode, tVar.line, tVar.col, compileState.CurrentDSFileName); 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; IdentLocation.AddEntry(symnode, tVar.line, tVar.col, compileState.CurrentDSFileName); for (int n = 0; n < exprlist.list.Count; ++n) { DfsTraverse(exprlist.list[n], ref inferedType); IdentifierNode t = new IdentifierNode(); t.Value = n.ToString(); t.datatype = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeInt, false); ArrayNode array = new ArrayNode(); array.Expr = t; array.Type = null; DfsEmitArrayIndex(array, symindex); } } } else { // Allocate a single variable with initializer symnode = Allocate(tVar.Value, globalProcIndex, type, datasize, datasize, tVar.ArrayDimensions, varNode.memregion); IdentLocation.AddEntry(symnode, tVar.line, tVar.col, compileState.CurrentDSFileName); symindex = symnode.symbolTableIndex; DfsTraverse(bNode.RightNode, ref inferedType); } } else { Debug.Assert(false, "Check generated AST"); } if (ProtoCore.DSASM.Constants.kInvalidIndex == symindex) { throw new BuildHaltException(); } }
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; 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.localCount = funcDef.localVars; localProcedure.returntype.UID = compileState.TypeSystem.GetType(funcDef.ReturnType.Name); if (localProcedure.returntype.UID == ProtoCore.DSASM.Constants.kInvalidIndex) localProcedure.returntype.UID = (int)PrimitiveType.kTypeVar; localProcedure.returntype.Name = compileState.TypeSystem.GetType(localProcedure.returntype.UID); localProcedure.returntype.IsIndexable = funcDef.ReturnType.IsIndexable; localProcedure.returntype.rank = funcDef.ReturnType.rank; localProcedure.runtimeIndex = codeBlock.codeBlockId; globalProcIndex = codeBlock.procedureTable.Append(localProcedure); compileState.ProcNode = localProcedure; CodeRangeTable.AddCodeBlockFunctionEntry(codeBlock.codeBlockId, globalProcIndex, funcDef.FunctionBody.line, funcDef.FunctionBody.col, funcDef.FunctionBody.endLine, funcDef.FunctionBody.endCol, compileState.CurrentDSFileName); // 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 = new ProtoCore.Type(); argType.UID = compileState.TypeSystem.GetType(argNode.ArgumentType.Name); if (argType.UID == ProtoCore.DSASM.Constants.kInvalidIndex) argType.UID = (int)PrimitiveType.kTypeVar; argType.Name = compileState.TypeSystem.GetType(argType.UID); argType.IsIndexable = argNode.ArgumentType.IsIndexable; argType.rank = argNode.ArgumentType.rank; int symbolIndex = AllocateArg(paramNode.Value, localProcedure.procId, argType); if (ProtoCore.DSASM.Constants.kInvalidIndex == symbolIndex) { throw new BuildHaltException(); } localProcedure.argTypeList.Add(argType); ProtoCore.DSASM.ArgumentInfo argInfo = new ProtoCore.DSASM.ArgumentInfo { isDefault = aIsDefault, defaultExpression = aDefaultExpression, Name = paramNode.Name }; localProcedure.argInfoList.Add(argInfo); } } ExceptionRegistration registration = compileState.ExceptionHandlingManager.ExceptionTable.GetExceptionRegistration(codeBlock.codeBlockId, globalProcIndex, globalClassIndex); if (registration == null) { registration = compileState.ExceptionHandlingManager.ExceptionTable.Register(codeBlock.codeBlockId, globalProcIndex, globalClassIndex); Debug.Assert(registration != null); } } else if (parseGlobalFunctionBody) { // Build arglist for comparison List<ProtoCore.Type> argList = new List<ProtoCore.Type>(); if (null != funcDef.Signature) { foreach (VarDeclNode argNode in funcDef.Signature.Arguments) { int argType = compileState.TypeSystem.GetType(argNode.ArgumentType.Name); bool isArray = argNode.ArgumentType.IsIndexable; int rank = argNode.ArgumentType.rank; argList.Add(compileState.TypeSystem.BuildTypeObject(argType, isArray, rank)); } } // 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); // Copy the active function to the core so nested language blocks can refer to it compileState.ProcNode = localProcedure; // Arguments have been allocated, update the baseOffset localProcedure.localCount = compileState.BaseOffset; ProtoCore.FunctionEndPoint fep = null; //Traverse default argument 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; IdentifierNode iNodeTemp = new IdentifierNode() { Value = ProtoCore.DSASM.Constants.kTempDefaultArg, Name = ProtoCore.DSASM.Constants.kTempDefaultArg, datatype = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, false) }; BinaryExpressionNode bNodeTemp = new BinaryExpressionNode(); bNodeTemp.LeftNode = iNodeTemp; bNodeTemp.Optr = ProtoCore.DSASM.Operator.assign; bNodeTemp.RightNode = bNode.LeftNode; EmitBinaryExpressionNode(bNodeTemp, ref inferedType); ////duild an inline conditional node for statement: defaultarg = (temp == DefaultArgNode) ? defaultValue : temp; //InlineConditionalNode icNode = new InlineConditionalNode(); //BinaryExpressionNode cExprNode = new BinaryExpressionNode(); //cExprNode.Optr = ProtoCore.DSASM.Operator.eq; //cExprNode.LeftNode = iNodeTemp; //cExprNode.RightNode = new DefaultArgNode(); //icNode.ConditionExpression = cExprNode; //icNode.TrueExpression = bNode.RightNode; //icNode.FalseExpression = iNodeTemp; //bNodeTemp.LeftNode = bNode.LeftNode; //bNodeTemp.RightNode = icNode; //EmitBinaryExpressionNode(bNodeTemp, ref inferedType); } // Traverse definition bool hasReturnStatement = false; foreach (ImperativeNode bnode in funcDef.FunctionBody.Body) { DfsTraverse(bnode, ref inferedType); BinaryExpressionNode binaryNode = bnode as BinaryExpressionNode; hasReturnStatement = hasReturnStatement || ((binaryNode != null) && (binaryNode.LeftNode.Name == ProtoCore.DSDefinitions.Keyword.Return)); } // All locals have been stack allocated, update the local count of this function localProcedure.localCount = compileState.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 = this.codeBlock.codeBlockId; 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; compileState.FunctionTable.AddFunctionEndPointer(classIndexAtCallsite, funcDef.Name, fep); //Fuqiang: return is already done in traversing the function body //// function return //EmitInstrConsole(ProtoCore.DSASM.kw.ret); //EmitReturn(); } compileState.ProcNode = localProcedure = null; globalProcIndex = ProtoCore.DSASM.Constants.kGlobalScope; argOffset = 0; compileState.BaseOffset = 0; codeBlock.blockType = originalBlockType; }
private void EmitForLoopNode(ImperativeNode node) { 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; } */ // 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 = new IdentifierNode() { Value = forNode.loopVar.Name, Name = forNode.loopVar.Name, datatype = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, false), line = forNode.loopVar.line, col = forNode.loopVar.col, endLine = forNode.loopVar.line, endCol = forNode.loopVar.col + forNode.loopVar.Name.Length - 1 }; forIdentInit.LeftNode = forIdent; forIdentInit.RightNode = new NullNode(); ProtoCore.Type type = new ProtoCore.Type(); type.UID = (int)PrimitiveType.kTypeVoid; type.IsIndexable = false; forIdentInit.line = forNode.KwForLine; forIdentInit.col = forNode.KwForCol; forIdentInit.endLine = forNode.KwForLine; forIdentInit.endCol = forNode.KwForCol + 2; EmitBinaryExpressionNode(forIdentInit, ref type); // Generate the expression for autogen counter initialized to 0 string forCountIdent = GetForCountIdent(); IdentifierNode nodeCounter = new IdentifierNode() { Value = forCountIdent, Name = forCountIdent, datatype = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, false) }; 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); // Generate the expression for autogen iterations initialized to 0 string forIterCountVar = GetForIterationVar(); IdentifierNode nodeIterCount = new IdentifierNode() { Value = forIterCountVar, Name = forIterCountVar, datatype = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, false) }; 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); /* // Generate the expression for autogen iteration count assigned to the size of ‘expr’ string identName = null; IdentifierNode exprIdent = null; if (forNode.expression is IdentifierNode) { exprIdent = forNode.expression as IdentifierNode; identName = exprIdent.Value; } else if (forNode.expression is ExprListNode) { // Create a temp array variable if 'expr' is an array identName = GetForExprIdent(); exprIdent = new IdentifierNode() { Value = identName, Name = identName, type = (int)ProtoCore.PrimitiveType.kTypeVar, datatype = ProtoCore.PrimitiveType.kTypeVar }; BinaryExpressionNode arrayexprAssignment = new BinaryExpressionNode(); arrayexprAssignment.Optr = ProtoCore.DSASM.Operator.assign; arrayexprAssignment.LeftNode = exprIdent; arrayexprAssignment.RightNode = forNode.expression as ExprListNode; type = (int)ProtoCore.PrimitiveType.kTypeVoid; EmitBinaryExpressionNode(arrayexprAssignment, ref type); } */ // 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(); IdentifierNode exprIdent = new IdentifierNode() { Value = identName, Name = identName, datatype = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, false) }; BinaryExpressionNode arrayexprAssignment = new BinaryExpressionNode(); arrayexprAssignment.Optr = ProtoCore.DSASM.Operator.assign; arrayexprAssignment.LeftNode = exprIdent; arrayexprAssignment.RightNode = forNode.expression; arrayexprAssignment.line = forNode.expression.line; arrayexprAssignment.col = forNode.expression.col; arrayexprAssignment.endLine = forNode.expression.endLine; arrayexprAssignment.endCol = forNode.expression.endCol; type.UID = (int)ProtoCore.PrimitiveType.kTypeVoid; EmitBinaryExpressionNode(arrayexprAssignment, ref type); // 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 symbol = ProtoCore.DSASM.Constants.kInvalidIndex; if (ProtoCore.DSASM.Constants.kInvalidIndex != globalClassIndex) { symbol = compileState.ClassTable.ClassNodes[globalClassIndex].symbols.IndexOf(identName); } else { symbol = codeBlock.symbolTable.IndexOf(identName); } // 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 + 1; // 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.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 BinaryExpressionNode countIncrement = new BinaryExpressionNode(); countIncrement.Optr = ProtoCore.DSASM.Operator.add; countIncrement.LeftNode = nodeCounter; countIncrement.RightNode = new IntNode() { value = "1" }; BinaryExpressionNode countIncrementAssign = new BinaryExpressionNode(); countIncrementAssign.Optr = ProtoCore.DSASM.Operator.assign; countIncrementAssign.LeftNode = nodeCounter; countIncrementAssign.RightNode = 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.line = forNode.line; whileNode.col = forNode.col; whileNode.endLine = forNode.endLine; whileNode.endCol = forNode.endCol; type.UID = (int)ProtoCore.PrimitiveType.kTypeVoid; EmitWhileStmtNode(whileNode, ref type); //} // Comment Jun: The for loop counter must be unique and does not need to reset //forloopCounter--; //for loop ended. decrement counter } }
public ImperativeNode BuildIdentfier(string name, PrimitiveType type = PrimitiveType.kTypeVar) { var ident = new IdentifierNode(); ident.Name = ident.Value = name; ident.DataType = TypeSystem.BuildPrimitiveTypeObject(type, 0); return ident; }
public IdentifierNode(IdentifierNode rhs) : base(rhs) { datatype = new ProtoCore.Type { UID = rhs.datatype.UID, rank = rhs.datatype.rank, IsIndexable = rhs.datatype.IsIndexable, Name = rhs.datatype.Name }; Value = rhs.Value; }