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);
        }
Beispiel #2
0
        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
            }
        }
Beispiel #8
0
        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;
        }
Beispiel #9
0
        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;
        }