예제 #1
0
        protected void EmitIdentifierListNode(Node node, ref ProtoCore.Type inferedType, bool isBooleanOp = false, ProtoCore.AssociativeGraph.GraphNode graphNode = null, ProtoCore.DSASM.AssociativeSubCompilePass subPass = ProtoCore.DSASM.AssociativeSubCompilePass.kNone)
        {
            if (subPass == ProtoCore.DSASM.AssociativeSubCompilePass.kUnboundIdentifier)
            {
                //to process all unbounded parameters if any
                dynamic iNode = node;
                while (iNode is ProtoCore.AST.AssociativeAST.IdentifierListNode || iNode is ProtoCore.AST.ImperativeAST.IdentifierListNode)
                {
                    dynamic rightNode = iNode.RightNode;
                    if (rightNode is ProtoCore.AST.AssociativeAST.FunctionCallNode || rightNode is ProtoCore.AST.ImperativeAST.FunctionCallNode)
                    {
                        foreach (dynamic paramNode in rightNode.FormalArguments)
                        {
                            ProtoCore.Type paramType = new ProtoCore.Type();
                            paramType.UID         = (int)ProtoCore.PrimitiveType.kTypeVoid;
                            paramType.IsIndexable = false;
                            DfsTraverse(paramNode, ref paramType, false, graphNode, ProtoCore.DSASM.AssociativeSubCompilePass.kUnboundIdentifier);
                        }
                    }
                    iNode = iNode.LeftNode;
                }
                return;
            }

            int depth = 0;

            ProtoCore.Type leftType = new ProtoCore.Type();
            leftType.UID         = (int)PrimitiveType.kInvalidType;
            leftType.IsIndexable = false;
            bool isFirstIdent = true;

            bool isIdentReference = DfsEmitIdentList(node, null, globalClassIndex, ref leftType, ref depth, ref inferedType, false, ref isFirstIdent, graphNode, subPass);

            inferedType.UID = isBooleanOp ? (int)PrimitiveType.kTypeBool : inferedType.UID;
        }
예제 #2
0
        public int Emit(CodeBlockNode codeblock)
        {
            bool isTopBlock = null == codeBlock.parent;
            if (!isTopBlock)
            {
                // If this is an inner block where there can be no classes, we can start at parsing at the global function state
                compilePass = ProtoCore.DSASM.ImperativeCompilePass.kGlobalFuncSig;
            }

            CodeRangeTable.AddCodeBlockRangeEntry(codeBlock.codeBlockId,
                codeblock.line,
                codeblock.col,
                codeblock.endLine,
                codeblock.endCol,
                compileState.CurrentDSFileName);

            ProtoCore.Type type = new ProtoCore.Type();
            while (ProtoCore.DSASM.ImperativeCompilePass.kDone != compilePass)
            {
                foreach (ImperativeNode node in codeblock.Body)
                {
                    type = new ProtoCore.Type();
                    type.UID = (int)PrimitiveType.kTypeVar;
                    type.IsIndexable = false;
                    DfsTraverse(node, ref type);
                }
                compilePass++;
            }
            compileState.InferedType = type;

            return codeBlock.codeBlockId;
        }
예제 #3
0
파일: CodeGen.cs 프로젝트: YanmengLi/Dynamo
        /// <summary>
        /// </summary>
        /// <param name="codeBlock"></param>
        /// <param name="inferedType"></param>
        /// <param name="subPass"></param>
        private void EmitCodeBlock(
            List<ImperativeNode> codeBlock, 
            ref ProtoCore.Type inferedType, 
            bool isBooleanOp = false, 
            ProtoCore.AssociativeGraph.GraphNode graphNode = null)
        {
            foreach (ImperativeNode bodyNode in codeBlock)
            {
                inferedType = new ProtoCore.Type();
                inferedType.UID = (int)PrimitiveType.Var;

                if (bodyNode is LanguageBlockNode)
                {
                    BinaryExpressionNode langBlockNode = new BinaryExpressionNode();
                    langBlockNode.LeftNode = nodeBuilder.BuildIdentfier(core.GenerateTempLangageVar());
                    langBlockNode.Optr = ProtoCore.DSASM.Operator.assign;
                    langBlockNode.RightNode = bodyNode;
                    DfsTraverse(langBlockNode, ref inferedType, isBooleanOp, graphNode);
                }
                else
                {
                    DfsTraverse(bodyNode, ref inferedType, isBooleanOp, graphNode);
                }
            }
        }
예제 #4
0
        protected void EmitNullNode(Node node, ref ProtoCore.Type inferedType, bool isBooleanOp = false, ProtoCore.DSASM.AssociativeSubCompilePass subPass = ProtoCore.DSASM.AssociativeSubCompilePass.kNone)
        {
            if (subPass == ProtoCore.DSASM.AssociativeSubCompilePass.kUnboundIdentifier)
            {
                return;
            }

            dynamic nullNode = node;

            inferedType.UID = (int)PrimitiveType.kTypeNull;

            inferedType.UID = isBooleanOp ? (int)PrimitiveType.kTypeBool : inferedType.UID;
        }
예제 #5
0
        internal ArrayElementType AppendChildType(ProtoCore.Type type)
        {
            if (null == childNodes)
            {
                childNodes = new List <ArrayElementType>();
            }

            ArrayElementType element = new ArrayElementType(
                type, this.elementDepth + 1);

            childNodes.Add(element);
            return(element);
        }
예제 #6
0
        protected void EmitReturnStatement(Node node, ProtoCore.Type inferedType)
        {
            // Check the returned type against the declared return type
            if (null != localProcedure && core.IsFunctionCodeBlock(codeBlock))
            {
                if (localProcedure.isConstructor)
                {
                    Debug.Assert(ProtoCore.DSASM.Constants.kInvalidIndex != inferedType.UID);

                    ProtoCore.DSASM.ClassNode typeNode = core.ClassTable.ClassNodes[inferedType.UID];
                    Debug.Assert(null != typeNode);
                }
            }
        }
예제 #7
0
        protected void EmitBooleanNode(Node node, ref ProtoCore.Type inferedType, ProtoCore.DSASM.AssociativeSubCompilePass subPass = ProtoCore.DSASM.AssociativeSubCompilePass.kNone)
        {
            if (subPass == ProtoCore.DSASM.AssociativeSubCompilePass.kUnboundIdentifier)
            {
                return;
            }

            dynamic bNode = node;

            // We need to get inferedType for boolean variable so that we can perform type check
            if (enforceTypeCheck || core.TypeSystem.IsHigherRank((int)PrimitiveType.kTypeBool, inferedType.UID))
            {
                inferedType.UID = (int)PrimitiveType.kTypeBool;
            }
        }
예제 #8
0
        protected void EmitStringNode(Node node, ref ProtoCore.Type inferedType, ProtoCore.DSASM.AssociativeSubCompilePass subPass = ProtoCore.DSASM.AssociativeSubCompilePass.kNone)
        {
            if (subPass == ProtoCore.DSASM.AssociativeSubCompilePass.kUnboundIdentifier)
            {
                return;
            }

            dynamic sNode = node;

            if (!enforceTypeCheck || core.TypeSystem.IsHigherRank((int)PrimitiveType.kTypeString, inferedType.UID))
            {
                inferedType.UID = (int)PrimitiveType.kTypeString;
            }
            throw new NotImplementedException();
        }
예제 #9
0
        protected void EmitDoubleNode(Node node, ref ProtoCore.Type inferedType, bool isBooleanOp = false, ProtoCore.DSASM.AssociativeSubCompilePass subPass = ProtoCore.DSASM.AssociativeSubCompilePass.kNone)
        {
            if (subPass == ProtoCore.DSASM.AssociativeSubCompilePass.kUnboundIdentifier)
            {
                return;
            }

            dynamic dNode = node;

            if (!enforceTypeCheck || core.TypeSystem.IsHigherRank((int)PrimitiveType.kTypeDouble, inferedType.UID))
            {
                inferedType.UID = (int)PrimitiveType.kTypeDouble;
            }
            inferedType.UID = isBooleanOp ? (int)PrimitiveType.kTypeBool : inferedType.UID;
        }
예제 #10
0
        protected void EmitCharNode(Node node, ref ProtoCore.Type inferedType, bool isBooleanOp = false, ProtoCore.DSASM.AssociativeSubCompilePass subPass = ProtoCore.DSASM.AssociativeSubCompilePass.kNone)
        {
            if (subPass == ProtoCore.DSASM.AssociativeSubCompilePass.kUnboundIdentifier)
            {
                return;
            }

            dynamic cNode = node;

            if (!enforceTypeCheck || core.TypeSystem.IsHigherRank((int)PrimitiveType.kTypeChar, inferedType.UID))
            {
                inferedType.UID = (int)PrimitiveType.kTypeChar;
            }
            inferedType.UID = isBooleanOp ? (int)PrimitiveType.kTypeBool : inferedType.UID;
            throw new NotImplementedException();
        }
예제 #11
0
        public FunctionDescriptor(
            string assembly, string className, string functionName, string summary,
            IEnumerable <TypedParameter> parameters, ProtoCore.Type returnType, FunctionType type,
            bool isVisibleInLibrary = true, IEnumerable <string> returnKeys = null, bool isVarArg = false, string obsoleteMsg = "")
        {
            this.summary = summary;
            Assembly     = assembly;
            ClassName    = className;
            FunctionName = functionName;

            if (parameters == null)
            {
                Parameters = new List <TypedParameter>();
            }
            else
            {
                Parameters = parameters.Select(
                    x =>
                {
                    x.Function = this;
                    return(x);
                });
            }

            if (Parameters.Any())
            {
                InputParameters = Parameters.Select(
                    par =>
                {
                    return(Tuple.Create <string, string>(par.Name, par.DisplayTypeName));
                }
                    );
            }
            else
            {
                InputParameters = new List <Tuple <string, string> >();
            }

            ReturnType         = returnType.ToShortString();
            Type               = type;
            ReturnKeys         = returnKeys ?? new List <string>();
            IsVarArg           = isVarArg;
            IsVisibleInLibrary = isVisibleInLibrary;
            ObsoleteMessage    = obsoleteMsg;
        }
예제 #12
0
 public FunctionDescriptor(
     string assembly, string className, string functionName, IEnumerable <TypedParameter> parameters,
     ProtoCore.Type returnType, FunctionType type, bool isVisibleInLibrary = true,
     IEnumerable <string> returnKeys = null, bool isVarArg = false, string obsoleteMsg = "")
     : this(
         assembly,
         className,
         functionName,
         null,
         parameters,
         returnType,
         type,
         isVisibleInLibrary,
         returnKeys,
         isVarArg,
         obsoleteMsg)
 {
 }
예제 #13
0
        protected void EmitExprListNode(Node node, ref ProtoCore.Type inferedType, ProtoCore.AssociativeGraph.GraphNode graphNode = null, ProtoCore.DSASM.AssociativeSubCompilePass subPass = ProtoCore.DSASM.AssociativeSubCompilePass.kNone)
        {
            int     firstType = (int)PrimitiveType.kTypeVoid;
            dynamic exprlist  = node;

            int rank = 0;

            if (subPass != ProtoCore.DSASM.AssociativeSubCompilePass.kUnboundIdentifier)
            {
                //get the rank
                dynamic ltNode = exprlist;
                while ((ltNode is ProtoCore.AST.ImperativeAST.ExprListNode || ltNode is ProtoCore.AST.AssociativeAST.ExprListNode) && ltNode.list.Count > 0)
                {
                    rank++;
                    ltNode = ltNode.list[0];
                }
            }

            foreach (Node listNode in exprlist.list)
            {
                // The infered type is the type of the first element
                DfsTraverse(listNode, ref inferedType, false, graphNode, subPass);

                if ((listNode is ProtoCore.AST.AssociativeAST.ExprListNode) == false)
                {
                    // If 'listNode' was another sub-array, then don't bother adding
                    // it here, as it has added itself in the call to 'DfsTraverse'.
                    if (null != this.arrayElementType)
                    {
                        this.arrayElementType.AppendChildType(inferedType);
                    }
                }

                if ((int)PrimitiveType.kTypeVoid == firstType)
                {
                    firstType = inferedType.UID;
                }
            }

            inferedType.UID         = firstType;
            inferedType.IsIndexable = true;
            inferedType.rank        = rank;
        }
예제 #14
0
        protected int DfsEmitArrayIndexHeap(Node node)
        {
            int indexCnt = 0;

            Debug.Assert(node is ProtoCore.AST.AssociativeAST.ArrayNode || node is ProtoCore.AST.ImperativeAST.ArrayNode);

            dynamic arrayNode = node;

            while (arrayNode is ProtoCore.AST.AssociativeAST.ArrayNode || arrayNode is ProtoCore.AST.ImperativeAST.ArrayNode)
            {
                ++indexCnt;
                dynamic        array    = arrayNode;
                ProtoCore.Type lastType = new ProtoCore.Type();
                lastType.UID         = (int)PrimitiveType.kTypeVoid;
                lastType.IsIndexable = false;
                DfsTraverse(array.Expr, ref lastType);
                arrayNode = array.Type;
            }
            return(indexCnt);
        }
예제 #15
0
        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");
            }
        }
예제 #16
0
        // 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");
            }
        }
예제 #17
0
        /// <summary>
        ///     Compiles a collection of Dynamo nodes into a function definition for a custom node.
        /// </summary>
        /// <param name="functionId"></param>
        /// <param name="returnKeys"></param>
        /// <param name="functionName"></param>
        /// <param name="funcBody"></param>
        /// <param name="outputNodes"></param>
        /// <param name="parameters"></param>
        /// <param name="verboseLogging"></param>
        public void CompileCustomNodeDefinition(
            Guid functionId, IEnumerable <string> returnKeys, string functionName,
            IEnumerable <NodeModel> funcBody, IEnumerable <AssociativeNode> outputNodes,
            IEnumerable <TypedParameter> parameters, bool verboseLogging)
        {
            OnAstNodeBuilding(functionId);

            var functionBody = new CodeBlockNode();
            var asts         = CompileToAstNodes(funcBody, CompilationContext.None, verboseLogging);

            functionBody.Body.AddRange(asts.SelectMany(t => t.Item2));

            var outputs = outputNodes.ToList();

            if (outputs.Count > 1)
            {
                /* rtn_array = {};
                 * rtn_array[key0] = out0;
                 * rtn_array[key1] = out1;
                 * ...
                 * return = rtn_array;
                 */

                // return array, holds all outputs
                string rtnName = "__temp_rtn_" + functionId.ToString().Replace("-", String.Empty);
                functionBody.Body.Add(
                    AstFactory.BuildAssignment(
                        AstFactory.BuildIdentifier(rtnName),
                        AstFactory.BuildExprList(new List <string>())));

                // indexers for each output
                IEnumerable <AssociativeNode> indexers = returnKeys != null
                    ? returnKeys.Select(AstFactory.BuildStringNode) as IEnumerable <AssociativeNode>
                    : Enumerable.Range(0, outputs.Count).Select(AstFactory.BuildIntNode);

                functionBody.Body.AddRange(
                    outputs.Zip(
                        indexers,
                        (outputId, indexer) => // for each outputId and return key
                        // pack the output into the return array
                        AstFactory.BuildAssignment(AstFactory.BuildIdentifier(rtnName, indexer), outputId)));

                // finally, return the return array
                functionBody.Body.Add(AstFactory.BuildReturnStatement(AstFactory.BuildIdentifier(rtnName)));
            }
            else
            {
                // For single output, directly return that identifier or null.
                AssociativeNode returnValue = outputs.Count == 1 ? outputs[0] : new NullNode();
                functionBody.Body.Add(AstFactory.BuildReturnStatement(returnValue));
            }

            Type allTypes = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar);

            //Create a new function definition
            var functionDef = new FunctionDefinitionNode
            {
                Name      = functionName.Replace("-", string.Empty),
                Signature =
                    new ArgumentSignatureNode
                {
                    Arguments =
                        parameters.Select(param => AstFactory.BuildParamNode(param.Name, param.Type)).ToList()
                },
                FunctionBody = functionBody,
                ReturnType   = allTypes
            };

            OnAstNodeBuilt(functionId, new[] { functionDef });
        }
예제 #18
0
        private ProtoCore.AssociativeGraph.UpdateNodeRef AutoGenerateUpdateReference(AssociativeNode node, ProtoCore.AssociativeGraph.GraphNode graphNode)
        {
            // Get the lhs symbol list
            ProtoCore.Type type = new ProtoCore.Type();
            type.UID = globalClassIndex;
            ProtoCore.AssociativeGraph.UpdateNodeRef leftNodeRef = new ProtoCore.AssociativeGraph.UpdateNodeRef();
            DFSGetSymbolList(node, ref type, leftNodeRef);


            // Auto-generate the updateNodeRefs for this graphnode given the list 
            // stored in the first procedure found in the assignment expression
            if (functionCallStack.Count > 0)
            {
                ProtoCore.DSASM.ProcedureNode firstProc = functionCallStack[0];
                if (!firstProc.IsAutoGenerated)
                {
                    graphNode.firstProc = firstProc;
                }
            }
            ProtoCore.DSASM.SymbolNode firstSymbol = null;

            // See if the leftmost symbol(updateNodeRef) of the lhs expression is a property of the current class. 
            // If it is, then push the lhs updateNodeRef to the list of modified properties in the procedure node
            if (null != localProcedure && leftNodeRef.nodeList.Count > 0)
            {
                firstSymbol = leftNodeRef.nodeList[0].symbol;

                // Check if this symbol being modified in this function is allocated in the current scope.
                // If it is, then it means this symbol is not a member and is local to this function
                ProtoCore.DSASM.SymbolNode symbolnode = null;
                bool isAccessible = false;
                bool isLocalVariable = VerifyAllocationInScope(firstSymbol.name, globalClassIndex, globalProcIndex, out symbolnode, out isAccessible);
                if (!isLocalVariable)
                {
                    if (null != firstSymbol && leftNodeRef.nodeList[0].nodeType != ProtoCore.AssociativeGraph.UpdateNodeType.kMethod)
                    {
                        if (firstSymbol.functionIndex == ProtoCore.DSASM.Constants.kGlobalScope)
                        {
                            // Does the symbol belong on the same class or class heirarchy as the function calling it
                            if (firstSymbol.classScope == localProcedure.ClassID)
                            {
                                localProcedure.UpdatedProperties.Push(leftNodeRef);
                            }
                            else
                            {
                                if (localProcedure.ClassID > 0)
                                {
                                    if (core.ClassTable.ClassNodes[localProcedure.ClassID].IsMyBase(firstSymbol.classScope))
                                    {
                                        localProcedure.UpdatedProperties.Push(leftNodeRef);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return leftNodeRef;
        }
예제 #19
0
        // 
        //  proc TraverseFunctionDef(node)
        //      ...
        //      def argList
        //      foreach arg in node.argdefinition
        //          ; Store not just the argument types, but also the argument identifier
        //          def argtype = buildtype(arg)
        //          argtype.name = arg.identname
        //          argList.push(argtype)
        //      end
        //      ...
        //  end
        //  

        private ProtoCore.AssociativeGraph.UpdateNodeRef __To__Deprecate__AutoGenerateUpdateArgumentReference(AssociativeNode node, ProtoCore.AssociativeGraph.GraphNode graphNode)
        {
            // Get the lhs symbol list
            ProtoCore.Type type = new ProtoCore.Type();
            type.UID = globalClassIndex;
            ProtoCore.AssociativeGraph.UpdateNodeRef leftNodeRef = new ProtoCore.AssociativeGraph.UpdateNodeRef();
            DFSGetSymbolList(node, ref type, leftNodeRef);

            ProtoCore.DSASM.SymbolNode firstSymbol = null;


            // Check if we are inside a procedure
            if (null != localProcedure)
            {
                // Check if there are at least 2 symbols in the list
                if (leftNodeRef.nodeList.Count >= 2)
                {
                    firstSymbol = leftNodeRef.nodeList[0].symbol;
                    if (null != firstSymbol && leftNodeRef.nodeList[0].nodeType != ProtoCore.AssociativeGraph.UpdateNodeType.kMethod)
                    {
                        // Now check if the first element of the identifier list is an argument
                        foreach (ProtoCore.DSASM.ArgumentInfo argInfo in localProcedure.ArgumentInfos)
                        {
                            if (argInfo.Name == firstSymbol.name)
                            {
                                leftNodeRef.nodeList.RemoveAt(0);

                                List<ProtoCore.AssociativeGraph.UpdateNodeRef> refList = null;
                                bool found = localProcedure.UpdatedArgumentProperties.TryGetValue(argInfo.Name, out refList);
                                if (found)
                                {
                                    refList.Add(leftNodeRef);
                                }
                                else
                                {
                                    refList = new List<ProtoCore.AssociativeGraph.UpdateNodeRef>();
                                    refList.Add(leftNodeRef);
                                    localProcedure.UpdatedArgumentProperties.Add(argInfo.Name, refList);
                                }
                            }
                        }
                    }
                }
            }
            return leftNodeRef;
        }
예제 #20
0
        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
            }
        }
예제 #21
0
 private void AllocateContextGlobals()
 {
     if (null != context && null != context.GlobalVarList && context.GlobalVarList.Count > 0)
     {
         ProtoCore.Type type = new ProtoCore.Type();
         foreach (string globalName in context.GlobalVarList.Keys)
         {
             Allocate(
                 ProtoCore.DSASM.Constants.kInvalidIndex,
                 ProtoCore.DSASM.Constants.kInvalidIndex,
                 ProtoCore.DSASM.Constants.kGlobalScope,
                 globalName,
                 type);
         }
     }
 }
예제 #22
0
        /// <summary>
        ///     Compiles a collection of Dynamo nodes into a function definition for a custom node.
        /// </summary>
        /// <param name="functionId"></param>
        /// <param name="returnKeys"></param>
        /// <param name="functionName"></param>
        /// <param name="funcBody"></param>
        /// <param name="outputNodes"></param>
        /// <param name="parameters"></param>
        /// <param name="verboseLogging"></param>
        internal void CompileCustomNodeDefinition(
            Guid functionId, IEnumerable <string> returnKeys, string functionName,
            IEnumerable <NodeModel> funcBody, IEnumerable <AssociativeNode> outputNodes,
            IEnumerable <TypedParameter> parameters, bool verboseLogging)
        {
            OnAstNodeBuilding(functionId);

            var functionBody = new CodeBlockNode();
            var asts         = CompileToAstNodes(funcBody, CompilationContext.None, verboseLogging);

            functionBody.Body.AddRange(asts.SelectMany(t => t.Item2));

            var outputs = outputNodes.ToList();

            if (outputs.Count > 1)
            {
                /* rtn_dict = Dictionary.ByKeysValues({key0, ..., keyn}, {out0, ..., outn});
                 * return = rtn_dict;
                 */

                // return dictionary, holds all outputs
                string rtnName = "__temp_rtn_" + functionId.ToString().Replace("-", String.Empty);

                //// indexers for each output
                var indexers = returnKeys != null
                    ? returnKeys.Select(AstFactory.BuildStringNode) as IEnumerable <AssociativeNode>
                    : Enumerable.Range(0, outputs.Count).Select(AstFactory.BuildIntNode);

                // Create AST for Dictionary initialization
                var kvps = outputs.Zip(indexers, (outputId, indexer) =>
                                       new KeyValuePair <AssociativeNode, AssociativeNode>(indexer, outputId));
                var dict = new DictionaryExpressionBuilder();
                foreach (var kvp in kvps)
                {
                    dict.AddKey(kvp.Key);
                    dict.AddValue(kvp.Value);
                }
                functionBody.Body.Add(AstFactory.BuildAssignment(AstFactory.BuildIdentifier(rtnName), dict.ToFunctionCall()));

                // finally, return the return array
                functionBody.Body.Add(AstFactory.BuildReturnStatement(AstFactory.BuildIdentifier(rtnName)));
            }
            else
            {
                // For single output, directly return that identifier or null.
                AssociativeNode returnValue = outputs.Count == 1 && outputs[0] != null ? outputs[0] : new NullNode();
                functionBody.Body.Add(AstFactory.BuildReturnStatement(returnValue));
            }

            Type allTypes = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.Var);

            //Create a new function definition
            var functionDef = new FunctionDefinitionNode
            {
                Name      = functionName.Replace("-", string.Empty),
                Signature =
                    new ArgumentSignatureNode
                {
                    Arguments =
                        parameters.Select(param => AstFactory.BuildParamNode(param.Name, param.Type)).ToList()
                },
                FunctionBody = functionBody,
                ReturnType   = allTypes
            };

            OnAstNodeBuilt(functionId, new[] { functionDef });
        }
예제 #23
0
        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);
            }
        }
예제 #24
0
        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;
        }
예제 #25
0
        protected bool DfsEmitIdentList(Node pNode, Node parentNode, int contextClassScope, ref ProtoCore.Type lefttype, ref int depth, ref ProtoCore.Type finalType, bool isLeftidentList, ref bool isFirstIdent, ProtoCore.AssociativeGraph.GraphNode graphNode = null, ProtoCore.DSASM.AssociativeSubCompilePass subPass = ProtoCore.DSASM.AssociativeSubCompilePass.kNone)
        {
            bool isRefFromIdentifier = false;

            dynamic node = pNode;

            if (node is ProtoCore.AST.ImperativeAST.IdentifierListNode || node is ProtoCore.AST.AssociativeAST.IdentifierListNode)
            {
                dynamic bnode = node;
                if (ProtoCore.DSASM.Operator.dot != bnode.Optr)
                {
                    throw new BuildHaltException();
                }

                isRefFromIdentifier = DfsEmitIdentList(bnode.LeftNode, bnode, contextClassScope, ref lefttype, ref depth, ref finalType, isLeftidentList, ref isFirstIdent, graphNode, subPass);

                if (lefttype.rank > 0)
                {
                    lefttype.UID = finalType.UID = (int)PrimitiveType.kTypeNull;
                    return(false);
                }
                node = bnode.RightNode;
            }

            if (node is ProtoCore.AST.ImperativeAST.IdentifierNode || node is ProtoCore.AST.AssociativeAST.IdentifierNode)
            {
                dynamic identnode = node;

                int ci = core.ClassTable.IndexOf(identnode.Value);
                if (ProtoCore.DSASM.Constants.kInvalidIndex != ci)
                {
                    finalType.UID = lefttype.UID = ci;
                }
                else if (identnode.Value == ProtoCore.DSDefinitions.Kw.kw_this)
                {
                    finalType.UID = lefttype.UID = contextClassScope;
                    depth++;
                    return(true);
                }
                else
                {
                    ProtoCore.DSASM.SymbolNode symbolnode = null;
                    bool isAllocated  = false;
                    bool isAccessible = false;
                    if (lefttype.UID != -1)
                    {
                        isAllocated = VerifyAllocation(identnode.Value, lefttype.UID, out symbolnode, out isAccessible);
                    }
                    else
                    {
                        isAllocated = VerifyAllocation(identnode.Value, contextClassScope, out symbolnode, out isAccessible);
                    }

                    bool callOnClass = false;
                    if (pNode is ProtoCore.AST.ImperativeAST.IdentifierListNode ||
                        pNode is ProtoCore.AST.AssociativeAST.IdentifierListNode)
                    {
                        dynamic leftnode = ((dynamic)pNode).LeftNode;
                        if (leftnode != null &&
                            (leftnode is ProtoCore.AST.ImperativeAST.IdentifierNode ||
                             leftnode is ProtoCore.AST.AssociativeAST.IdentifierNode))
                        {
                            string leftClassName = leftnode.Name;
                            int    leftci        = core.ClassTable.IndexOf(leftClassName);
                            if (leftci != ProtoCore.DSASM.Constants.kInvalidIndex)
                            {
                                callOnClass = true;

                                depth = depth + 1;
                            }
                        }
                    }

                    if (null == symbolnode)    //unbound identifier
                    {
                        if (isAllocated && !isAccessible)
                        {
                            lefttype.UID = finalType.UID = (int)PrimitiveType.kTypeNull;
                            return(false);
                        }

                        if (depth == 0)
                        {
                            lefttype.UID = finalType.UID = (int)PrimitiveType.kTypeNull;
                            return(false);
                        }
                        else
                        {
                            ProtoCore.DSASM.DyanmicVariableNode dynamicVariableNode = new ProtoCore.DSASM.DyanmicVariableNode(identnode.Value, globalProcIndex, globalClassIndex);
                            core.DynamicVariableTable.variableTable.Add(dynamicVariableNode);
                            int dim = 0;
                            if (null != identnode.ArrayDimensions)
                            {
                                dim = DfsEmitArrayIndexHeap(identnode.ArrayDimensions);
                            }
                            lefttype.UID = finalType.UID = (int)PrimitiveType.kTypeVar;
                            depth++;
                            return(true);
                        }
                    }
                    else
                    {
                        if (callOnClass && !symbolnode.isStatic)
                        {
                            lefttype.UID = finalType.UID = (int)PrimitiveType.kTypeNull;
                            return(false);
                        }
                    }
                    lefttype = symbolnode.datatype;

                    int dimensions = 0;

                    // Get the symbols' table index
                    int runtimeIndex = symbolnode.runtimeTableIndex;

                    ProtoCore.DSASM.AddressType operandType = ProtoCore.DSASM.AddressType.Pointer;

                    if (null != identnode.ArrayDimensions)
                    {
                        /* Remove static type checking
                         * if (lefttype.UID != (int)PrimitiveType.kTypeArray && !lefttype.IsIndexable)
                         *  buildStatus.LogWarning(BuildData.WarningID.kWarnMax, string.Format("'{0}' is not indexable at compile time", identnode.Name));
                         */
                        dimensions  = DfsEmitArrayIndexHeap(identnode.ArrayDimensions);
                        operandType = ProtoCore.DSASM.AddressType.ArrayPointer;
                    }

                    //update the rank
                    if (lefttype.rank >= 0)
                    {
                        lefttype.rank -= dimensions;
                        if (lefttype.rank < 0)
                        {
                            //throw new Exception("Exceed maximum rank!");
                            lefttype.rank = 0;
                        }
                    }

                    if (0 == depth || (symbolnode != null && symbolnode.isStatic))
                    {
                        if (ProtoCore.DSASM.Constants.kGlobalScope == symbolnode.functionIndex &&
                            ProtoCore.DSASM.Constants.kInvalidIndex != symbolnode.classScope)
                        {
                            // member var
                            operandType = symbolnode.isStatic ? ProtoCore.DSASM.AddressType.StaticMemVarIndex : ProtoCore.DSASM.AddressType.MemVarIndex;
                        }
                        else
                        {
                            operandType = ProtoCore.DSASM.AddressType.VarIndex;
                        }
                    }
                    depth     = depth + 1;
                    finalType = lefttype;
                }
                return(true);
            }
            else if (node is ProtoCore.AST.ImperativeAST.FunctionCallNode || node is ProtoCore.AST.AssociativeAST.FunctionCallNode)
            {
                TraverseFunctionCall(node, pNode, lefttype.UID, depth, ref finalType, graphNode, subPass);
                //finalType.UID = isBooleanOp ? (int)PrimitiveType.kTypeBool : finalType.UID;
                lefttype = finalType;
                depth    = 1;
            }
            //else
            //{
            //    throw new BuildHaltException();
            //}
            return(false);
        }
예제 #26
0
        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
        }
예제 #27
0
        public int AllocateMemberVariable(int classIndex, int classScope, string name, int rank = 0, ProtoCore.CompilerDefinitions.AccessModifier access = ProtoCore.CompilerDefinitions.AccessModifier.kPublic, bool isStatic = false)
        {
            // TODO Jun: Create a class table for holding the primitive and custom data types
            int datasize = ProtoCore.DSASM.Constants.kPointerSize;
            ProtoCore.Type ptrType = new ProtoCore.Type();
            if (rank == 0)
                ptrType.UID = (int)PrimitiveType.kTypePointer;
            else
                ptrType.UID = (int)PrimitiveType.kTypeArray;
            ptrType.rank = rank;
            ProtoCore.DSASM.SymbolNode symnode = Allocate(classIndex, classScope, ProtoCore.DSASM.Constants.kGlobalScope, name, ptrType, datasize, isStatic, access);
            if (null == symnode)
            {
                buildStatus.LogSemanticError(String.Format(Resources.MemberVariableAlreadyDefined, name, core.ClassTable.ClassNodes[classIndex].Name));
                return ProtoCore.DSASM.Constants.kInvalidIndex;
            }


            return symnode.symbolTableIndex;
        }
예제 #28
0
        private int EmitExpressionInterpreter(ProtoCore.AST.Node codeBlockNode)
        {
            compileStateTracker.startPC = this.pc;
            compilePass = ProtoCore.DSASM.ImperativeCompilePass.kGlobalScope;
            ProtoCore.AST.ImperativeAST.CodeBlockNode codeblock = codeBlockNode as ProtoCore.AST.ImperativeAST.CodeBlockNode;

            ProtoCore.Type inferedType = new ProtoCore.Type();
            foreach (ImperativeNode node in codeblock.Body)
            {
                inferedType = new ProtoCore.Type();
                inferedType.UID = (int)ProtoCore.PrimitiveType.kTypeVar;
                inferedType.IsIndexable = false;

                DfsTraverse(node, ref inferedType);

                BinaryExpressionNode binaryNode = node as BinaryExpressionNode;
            }
            compileStateTracker.InferedType = inferedType;

            this.pc = compileStateTracker.startPC;

            return codeBlock.codeBlockId;
        }
예제 #29
0
        private void EmitFunctionDefinitionNode(AssociativeNode node, ref ProtoCore.Type inferedType, ProtoCore.CompilerDefinitions.Associative.SubCompilePass subPass = ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kNone, GraphNode graphNode = null)
        {
            bool parseGlobalFunctionBody = null == localProcedure && ProtoCore.CompilerDefinitions.Associative.CompilePass.kGlobalFuncBody == compilePass;
            bool parseMemberFunctionBody = ProtoCore.DSASM.Constants.kGlobalScope != globalClassIndex && ProtoCore.CompilerDefinitions.Associative.CompilePass.kClassMemFuncBody == compilePass;

            FunctionDefinitionNode funcDef = node as FunctionDefinitionNode;
            localFunctionDefNode = funcDef;

            if (funcDef.IsAssocOperator)
            {
                isAssocOperator = true;
            }
            else
            {
                isAssocOperator = false;
            }

            bool hasReturnStatement = false;
            ProtoCore.DSASM.CodeBlockType origCodeBlockType = codeBlock.blockType;
            codeBlock.blockType = ProtoCore.DSASM.CodeBlockType.kFunction;
            if (IsParsingGlobalFunctionSig() || IsParsingMemberFunctionSig())
            {
                Validity.Assert(null == localProcedure);
                localProcedure = new ProtoCore.DSASM.ProcedureNode();

                localProcedure.Name = funcDef.Name;
                localProcedure.PC = ProtoCore.DSASM.Constants.kInvalidIndex;
                localProcedure.LocalCount = 0; // Defer till all locals are allocated
                var uid = core.TypeSystem.GetType(funcDef.ReturnType.Name);
                var rank = funcDef.ReturnType.rank;
                var returnType = core.TypeSystem.BuildTypeObject(uid, rank); 
                if (returnType.UID == (int)PrimitiveType.kInvalidType)
                {
                    string message = String.Format(ProtoCore.Properties.Resources.kReturnTypeUndefined, funcDef.ReturnType.Name, funcDef.Name);
                    buildStatus.LogWarning(WarningID.kTypeUndefined, message, core.CurrentDSFileName, funcDef.line, funcDef.col, graphNode);
                    returnType = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, rank);
                }
                localProcedure.ReturnType = returnType;
                localProcedure.IsConstructor = false;
                localProcedure.IsStatic = funcDef.IsStatic;
                localProcedure.RuntimeIndex = codeBlock.codeBlockId;
                localProcedure.AccessModifier = funcDef.Access;
                localProcedure.IsExternal = funcDef.IsExternLib;
                localProcedure.IsAutoGenerated = funcDef.IsAutoGenerated;
                localProcedure.ClassID = globalClassIndex;
                localProcedure.IsAssocOperator = funcDef.IsAssocOperator;
                localProcedure.IsAutoGeneratedThisProc = funcDef.IsAutoGeneratedThisProc;

                localProcedure.MethodAttribute = funcDef.MethodAttributes;

                int peekFunctionindex = ProtoCore.DSASM.Constants.kInvalidIndex;

                if (ProtoCore.DSASM.Constants.kInvalidIndex == globalClassIndex)
                {
                    peekFunctionindex = codeBlock.procedureTable.Procedures.Count;
                }
                else
                {
                    peekFunctionindex = core.ClassTable.ClassNodes[globalClassIndex].ProcTable.Procedures.Count;
                }

                // Append arg symbols
                List<KeyValuePair<string, ProtoCore.Type>> argsToBeAllocated = new List<KeyValuePair<string, ProtoCore.Type>>();
                string functionDescription = localProcedure.Name;
                if (null != funcDef.Signature)
                {
                    foreach (VarDeclNode argNode in funcDef.Signature.Arguments)
                    {
                        var argInfo = BuildArgumentInfoFromVarDeclNode(argNode);
                        localProcedure.ArgumentInfos.Add(argInfo);

                        var argType = BuildArgumentTypeFromVarDeclNode(argNode, graphNode);
                        localProcedure.ArgumentTypes.Add(argType);

                        argsToBeAllocated.Add(new KeyValuePair<string, ProtoCore.Type>(argInfo.Name, argType));

                        functionDescription += argNode.ArgumentType.ToString();
                    }
                    localProcedure.HashID = functionDescription.GetHashCode();
                    localProcedure.IsVarArg = funcDef.Signature.IsVarArg;
                }

                if (ProtoCore.DSASM.Constants.kInvalidIndex == globalClassIndex)
                {
                    globalProcIndex = codeBlock.procedureTable.Append(localProcedure);
                }
                else
                {
                    globalProcIndex = core.ClassTable.ClassNodes[globalClassIndex].ProcTable.Append(localProcedure);
                }

                // Comment Jun: Catch this assert given the condition as this type of mismatch should never occur
                if (ProtoCore.DSASM.Constants.kInvalidIndex != globalProcIndex)
                {
                    argsToBeAllocated.ForEach(arg =>
                    {
                        int symbolIndex = AllocateArg(arg.Key, globalProcIndex, arg.Value);
                        if (ProtoCore.DSASM.Constants.kInvalidIndex == symbolIndex)
                        {
                            throw new BuildHaltException("B2CB2093");
                        }
                    });                   
                }
                else
                {
                    string message = String.Format(ProtoCore.Properties.Resources.kMethodAlreadyDefined, localProcedure.Name);
                    buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kFunctionAlreadyDefined, message, core.CurrentDSFileName, funcDef.line, funcDef.col, graphNode);
                    funcDef.skipMe = true;
                }
            }
            else if (parseGlobalFunctionBody || parseMemberFunctionBody)
            {
                if (CoreUtils.IsDisposeMethod(node.Name))
                {
                    core.Options.EmitBreakpoints = false;
                }

                // 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, graphNode);
                        argList.Add(argType);
                    }
                }

                // Get the exisitng procedure that was added on the previous pass
                if (ProtoCore.DSASM.Constants.kInvalidIndex == globalClassIndex)
                {
                    var procNode = codeBlock.procedureTable.GetFunctionBySignature(funcDef.Name, argList);
                    globalProcIndex = procNode == null ? Constants.kInvalidIndex : procNode.ID;
                    localProcedure = codeBlock.procedureTable.Procedures[globalProcIndex];
                }
                else
                {
                    var procNode = core.ClassTable.ClassNodes[globalClassIndex].ProcTable.GetFunctionBySignature(funcDef.Name, argList);
                    globalProcIndex = procNode == null ? Constants.kInvalidIndex : procNode.ID;
                    localProcedure = core.ClassTable.ClassNodes[globalClassIndex].ProcTable.Procedures[globalProcIndex];
                }

                Validity.Assert(null != localProcedure);

                // code gen the attribute 
                localProcedure.Attributes = PopulateAttributes(funcDef.Attributes);
                // Its only on the parse body pass where the real pc is determined. Update this procedures' pc
                //Validity.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
                core.ProcNode = localProcedure;

                ProtoCore.FunctionEndPoint fep = null;
                if (!funcDef.IsExternLib)
                {
                    //Traverse default argument
                    emitDebugInfo = false;
                    foreach (ProtoCore.DSASM.ArgumentInfo argNode in localProcedure.ArgumentInfos)
                    {
                        if (!argNode.IsDefault)
                        {
                            continue;
                        }
                        BinaryExpressionNode bNode = argNode.DefaultExpression as BinaryExpressionNode;
                        // build a temporay node for statement : temp = defaultarg;
                        var iNodeTemp = AstFactory.BuildIdentifier(core.GenerateTempVar());
                        var bNodeTemp = AstFactory.BuildAssignment(iNodeTemp, bNode.LeftNode);
                        bNodeTemp.IsProcedureOwned = true;
                        EmitBinaryExpressionNode(bNodeTemp, ref inferedType, false, null, ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kUnboundIdentifier);
                        //duild an inline conditional node for statement: defaultarg = (temp == DefaultArgNode) ? defaultValue : temp;
                        InlineConditionalNode icNode = new InlineConditionalNode();
                        icNode.IsAutoGenerated = true;
                        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, false, null, ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kUnboundIdentifier);
                    }
                    emitDebugInfo = true;

                    EmitCompileLogFunctionStart(GetFunctionSignatureString(funcDef.Name, funcDef.ReturnType, funcDef.Signature));

                    ProtoCore.Type itype = new ProtoCore.Type();

                    hasReturnStatement = EmitCodeBlock(funcDef.FunctionBody.Body, ref itype, subPass, true);

                    // Build dependency within the function
                    ProtoCore.AssociativeEngine.Utils.BuildGraphNodeDependencies(
                        codeBlock.instrStream.dependencyGraph.GetGraphNodesAtScope(globalClassIndex, globalProcIndex));


                    EmitCompileLogFunctionEnd();

                    // All locals have been stack allocated, update the local count of this function
                    localProcedure.LocalCount = core.BaseOffset;

                    if (ProtoCore.DSASM.Constants.kInvalidIndex == globalClassIndex)
                    {
                        localProcedure.LocalCount = core.BaseOffset;

                        // Update the param stack indices of this function
                        foreach (ProtoCore.DSASM.SymbolNode symnode in codeBlock.symbolTable.symbolList.Values)
                        {
                            if (symnode.functionIndex == localProcedure.ID && symnode.isArgument)
                            {
                                symnode.index -= localProcedure.LocalCount;
                            }
                        }
                    }
                    else
                    {
                        core.ClassTable.ClassNodes[globalClassIndex].ProcTable.Procedures[localProcedure.ID].LocalCount = core.BaseOffset;

                        // Update the param stack indices of this function
                        foreach (ProtoCore.DSASM.SymbolNode symnode in core.ClassTable.ClassNodes[globalClassIndex].Symbols.symbolList.Values)
                        {
                            if (symnode.functionIndex == localProcedure.ID && symnode.isArgument)
                            {
                                symnode.index -= localProcedure.LocalCount;
                            }
                        }
                    }

                    ProtoCore.Lang.JILActivationRecord record = new ProtoCore.Lang.JILActivationRecord();
                    record.pc = localProcedure.PC;
                    record.locals = localProcedure.LocalCount;
                    record.classIndex = globalClassIndex;
                    record.funcIndex = localProcedure.ID;
                    fep = new ProtoCore.Lang.JILFunctionEndPoint(record);
                }
                else if (funcDef.BuiltInMethodId != ProtoCore.Lang.BuiltInMethods.MethodID.kInvalidMethodID)
                {
                    fep = new ProtoCore.Lang.BuiltInFunctionEndPoint(funcDef.BuiltInMethodId);
                }
                else
                {
                    ProtoCore.Lang.JILActivationRecord jRecord = new ProtoCore.Lang.JILActivationRecord();
                    jRecord.pc = localProcedure.PC;
                    jRecord.locals = localProcedure.LocalCount;
                    jRecord.classIndex = globalClassIndex;
                    jRecord.funcIndex = localProcedure.ID;

                    ProtoCore.Lang.FFIActivationRecord record = new ProtoCore.Lang.FFIActivationRecord();
                    record.JILRecord = jRecord;
                    record.FunctionName = funcDef.Name;
                    record.ModuleName = funcDef.ExternLibName;
                    record.ModuleType = "dll";
                    record.IsDNI = funcDef.IsDNI;
                    record.ReturnType = funcDef.ReturnType;
                    record.ParameterTypes = localProcedure.ArgumentTypes;
                    fep = new ProtoCore.Lang.FFIFunctionEndPoint(record);
                }

                // Construct the fep arguments
                fep.FormalParams = new ProtoCore.Type[localProcedure.ArgumentTypes.Count];
                fep.BlockScope = codeBlock.codeBlockId;
                fep.ClassOwnerIndex = localProcedure.ClassID;
                fep.procedureNode = localProcedure;
                localProcedure.ArgumentTypes.CopyTo(fep.FormalParams, 0);

                // 'classIndexAtCallsite' is the class index as it is stored at the callsite function tables
                int classIndexAtCallsite = globalClassIndex + 1;
                core.FunctionTable.InitGlobalFunctionEntry(classIndexAtCallsite);

                // Get the function group of the current class and see if the current function exists
                Dictionary<string, FunctionGroup> fgroup = core.FunctionTable.GlobalFuncTable[classIndexAtCallsite];
                if (!fgroup.ContainsKey(funcDef.Name))
                {
                    // If any functions in the base class have the same name, append them here
                    int ci = classIndexAtCallsite - 1;
                    if (ProtoCore.DSASM.Constants.kInvalidIndex != ci)
                    {
                        ProtoCore.DSASM.ClassNode cnode = core.ClassTable.ClassNodes[ci];
                        if (cnode.Bases.Count > 0)
                        {
                            Validity.Assert(1 == cnode.Bases.Count, "We don't support multiple inheritance yet");

                            ci = cnode.Bases[0];

                            Dictionary<string, FunctionGroup> tgroup = new Dictionary<string, FunctionGroup>();
                            int callsiteCI = ci + 1;
                            bool bSucceed = core.FunctionTable.GlobalFuncTable.TryGetValue(callsiteCI, out tgroup);
                            if (bSucceed)
                            {
                                if (tgroup.ContainsKey(funcDef.Name))
                                {
                                    // Get that base group - the group of function from the baseclass
                                    FunctionGroup basegroup = new FunctionGroup();
                                    bSucceed = tgroup.TryGetValue(funcDef.Name, out basegroup);
                                    if (bSucceed)
                                    {
                                        // Copy all non-private feps from the basegroup into this the new group
                                        FunctionGroup newGroup = new FunctionGroup();
                                        newGroup.CopyVisible(basegroup.FunctionEndPoints);

                                        // Append the new fep 
                                        newGroup.FunctionEndPoints.Add(fep);

                                        // Copy the new group to this class table
                                        core.FunctionTable.GlobalFuncTable[classIndexAtCallsite].Add(funcDef.Name, newGroup);
                                    }
                                }
                                else
                                {
                                    // Create a new function group in this class
                                    ProtoCore.FunctionGroup funcGroup = new ProtoCore.FunctionGroup();
                                    funcGroup.FunctionEndPoints.Add(fep);

                                    // Add this group to the class function tables
                                    core.FunctionTable.GlobalFuncTable[classIndexAtCallsite].Add(funcDef.Name, funcGroup);
                                }
                            }
                            else
                            {
                                // Create a new function group in this class
                                ProtoCore.FunctionGroup funcGroup = new ProtoCore.FunctionGroup();
                                funcGroup.FunctionEndPoints.Add(fep);

                                // Add this group to the class function tables
                                core.FunctionTable.GlobalFuncTable[classIndexAtCallsite].Add(funcDef.Name, funcGroup);
                            }
                            cnode = core.ClassTable.ClassNodes[ci];
                        }
                        else
                        {
                            // Create a new function group in this class
                            ProtoCore.FunctionGroup funcGroup = new ProtoCore.FunctionGroup();
                            funcGroup.FunctionEndPoints.Add(fep);

                            // Add this group to the class function tables
                            core.FunctionTable.GlobalFuncTable[classIndexAtCallsite].Add(funcDef.Name, funcGroup);
                        }
                    }
                    else
                    {
                        // Create a new function group in this class
                        ProtoCore.FunctionGroup funcGroup = new ProtoCore.FunctionGroup();
                        funcGroup.FunctionEndPoints.Add(fep);

                        // Add this group to the class function tables
                        core.FunctionTable.GlobalFuncTable[classIndexAtCallsite].Add(funcDef.Name, funcGroup);
                    }
                }
                else
                {
                    // Add this fep into the exisitng function group
                    core.FunctionTable.GlobalFuncTable[classIndexAtCallsite][funcDef.Name].FunctionEndPoints.Add(fep);
                }

                if (!hasReturnStatement && !funcDef.IsExternLib)
                {
                    if (!core.Options.SuppressFunctionResolutionWarning)
                    {
                        string message = String.Format(ProtoCore.Properties.Resources.kFunctionNotReturnAtAllCodePaths, localProcedure.Name);
                        buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kMissingReturnStatement, message, core.CurrentDSFileName, funcDef.line, funcDef.col, graphNode);
                    }
                    EmitReturnNull();
                }

                if (CoreUtils.IsDisposeMethod(node.Name))
                {
                    core.Options.EmitBreakpoints = true;
                }
            }

            core.ProcNode = localProcedure = null;
            codeBlock.blockType = origCodeBlockType;
            globalProcIndex = ProtoCore.DSASM.Constants.kGlobalScope;
            localFunctionDefNode = null;
            core.BaseOffset = 0;
            argOffset = 0;
            isAssocOperator = false;
        }
예제 #30
0
        public override ProtoCore.DSASM.ProcedureNode 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,
            ProtoCore.AST.Node bnode = null)
        {
            if (!IsParsingGlobal() && !IsParsingGlobalFunctionBody())
            {
                return null;
            }

            //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, false, graphNode, AssociativeSubCompilePass.kNone, bnode);
                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.ImperativeAST.IdentifierListNode)
            {
                ProtoCore.AST.Node leftnode = (parentNode as ProtoCore.AST.ImperativeAST.IdentifierListNode).LeftNode;
                if (leftnode != null && leftnode is ProtoCore.AST.ImperativeAST.IdentifierNode)
                {
                    refClassIndex = compileStateTracker.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 (procName != ProtoCore.DSASM.Constants.kFunctionPointerCall)
                {
                    bool isStaticOrConstructor = refClassIndex != ProtoCore.DSASM.Constants.kInvalidIndex;
                    procNode = compileStateTracker.ClassTable.ClassNodes[inferedType.UID].GetMemberFunction(procName, arglist, globalClassIndex, out isAccessible, out realType, isStaticOrConstructor);

                    if (procNode != null)
                    {
                        Debug.Assert(realType != ProtoCore.DSASM.Constants.kInvalidIndex);
                        isConstructor = procNode.isConstructor;
                        isStatic = procNode.isStatic;
                        type = lefttype = realType;

                        if (!isAccessible)
                        {
                            type = lefttype = realType;
                            string message = String.Format(ProtoCore.BuildData.WarningMessage.kMethodIsInaccessible, procName);
                            buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kAccessViolation, message, compileStateTracker.CurrentDSFileName, funcCall.line, funcCall.col);
                            hasLogError = true;
                        }
                    }
                    // To support unamed constructor, x = A();
                    else if (refClassIndex != Constants.kInvalidIndex)
                    {
                        string message = String.Format(ProtoCore.BuildData.WarningMessage.kCallingNonStaticMethod, compileStateTracker.ClassTable.ClassNodes[refClassIndex].name, procName);
                        buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kCallingNonStaticMethodOnClass, message, compileStateTracker.CurrentDSFileName, funcCall.line, funcCall.col);
                        inferedType.UID = (int)PrimitiveType.kTypeNull;
                        EmitPushNull();
                        return null;
                    }
                    else
                    {
                        int classIndex = compileStateTracker.ClassTable.IndexOf(procName);
                        int dummy;

                        if (classIndex != Constants.kInvalidIndex)
                        {
                            procNode = compileStateTracker.ClassTable.ClassNodes[classIndex].GetMemberFunction(procName, arglist, globalClassIndex, out isAccessible, out dummy, true);
                            if (procNode != null && procNode.isConstructor)
                            {
                                type = classIndex;
                            }
                            else
                            {
                                procNode = null;
                            }
                        }
                    }
                }
            }

            // Try function pointer firstly
            if ((procNode == null) && (procName != ProtoCore.DSASM.Constants.kFunctionPointerCall))
            {
                bool isAccessibleFp;
                ProtoCore.DSASM.SymbolNode symbolnode = null;
                bool isAllocated = VerifyAllocation(procName, globalClassIndex, globalProcIndex, out symbolnode, out isAccessibleFp);
                if (isAllocated) // not checking the type against function pointer, as the type could be var
                {
                    procName = ProtoCore.DSASM.Constants.kFunctionPointerCall;
                    // The graph node always depends on this function pointer
                    if (null != graphNode)
                    {
                        ProtoCore.AssociativeGraph.GraphNode dependentNode = new ProtoCore.AssociativeGraph.GraphNode();
                        dependentNode.PushSymbolReference(symbolnode);
                        graphNode.PushDependent(dependentNode);
                    }
                }
            }

            // Always try global function firstly. Because we dont have syntax
            // support for calling global function (say, ::foo()), if we try
            // member function firstly, there is no way to call a global function
            // For member function, we can use this.foo() to distinguish it from
            // global function.
            if ((procNode == null) && (procName != ProtoCore.DSASM.Constants.kFunctionPointerCall))
            {
                procNode = compileStateTracker.GetFirstVisibleProcedure(procName, arglist, codeBlock);
                if (null != procNode)
                {
                    type = ProtoCore.DSASM.Constants.kGlobalScope;
                    if (compileStateTracker.TypeSystem.IsHigherRank(procNode.returntype.UID, inferedType.UID))
                    {
                        inferedType = procNode.returntype;
                    }
                }
            }

            // Try member functions in global class scope
            if ((procNode == null) && (procName != ProtoCore.DSASM.Constants.kFunctionPointerCall) && (parentNode == null))
            {
                if (globalClassIndex != ProtoCore.DSASM.Constants.kInvalidIndex)
                {
                    int realType;
                    bool isAccessible;
                    bool isStaticOrConstructor = refClassIndex != ProtoCore.DSASM.Constants.kInvalidIndex;
                    ProtoCore.DSASM.ProcedureNode memProcNode = compileStateTracker.ClassTable.ClassNodes[globalClassIndex].GetMemberFunction(procName, arglist, globalClassIndex, out isAccessible, out realType, isStaticOrConstructor);

                    if (memProcNode != null)
                    {
                        Debug.Assert(realType != ProtoCore.DSASM.Constants.kInvalidIndex);
                        procNode = memProcNode;
                        inferedType = procNode.returntype;
                        type = realType;

                        if (!isAccessible)
                        {
                            string message = String.Format(ProtoCore.BuildData.WarningMessage.kMethodIsInaccessible, procName);
                            buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kAccessViolation, message, compileStateTracker.CurrentDSFileName, funcCall.line, funcCall.col);

                            inferedType.UID = (int)PrimitiveType.kTypeNull;
                            EmitPushNull();
                            return null;
                        }
                    }
                }
            }

            if (null != procNode)
            {
                inferedType = procNode.returntype;
                //if call is replication call
                if (procNode.isThisCallReplication)
                {
                    inferedType.IsIndexable = true;
                    inferedType.rank++;
                }

                if (ProtoCore.DSASM.Constants.kInvalidIndex != procNode.procId)
                {
                    // The function is at block 0 if its a constructor, member or at the globals scope.
                    // Its at block 1 if its inside a language block.
                    // Its limited to block 1 as of R1 since we dont support nested function declarations yet
                    int blockId = procNode.runtimeIndex;

                    //push value-not-provided default argument
                    for (int i = arglist.Count; i < procNode.argInfoList.Count; i++)
                    {
                        EmitDefaultArgNode();
                    }

                    // Push the function declaration block
                    // Jun TODO: Implementeation of indexing into a function call:
                    //  x = f()[0][1]
                    int dimensions = 0;
                    EmitPushVarData(blockId, dimensions);

                    // The function call
                    EmitInstrConsole(ProtoCore.DSASM.kw.callr, procNode.name);

                    DebugProperties.BreakpointOptions oldOptions = compileStateTracker.DebugProps.breakOptions;
                    if(procNode.name.StartsWith(Constants.kSetterPrefix))
                    {
                        EmitCall(procNode.procId, type, depth, parentNode.line, parentNode.col, parentNode.endLine, parentNode.endCol);
                    }
                    /*else if(procNode.isExternal)
                    {
                        EmitCall(procNode.procId, type, depth);
                    }*/
                    else if (bnode != null)
                    {
                        EmitCall(procNode.procId, type, depth, bnode.line, bnode.col, bnode.endLine, bnode.endCol);
                    }
                    else if (!procNode.name.Equals(Constants.kFunctionRangeExpression) ||
                        oldOptions.HasFlag(DebugProperties.BreakpointOptions.EmitCallrForTempBreakpoint))
                    {
                        EmitCall(procNode.procId, type, depth, node.line, node.col, node.endLine, node.endCol);
                    }
                    else
                    {
                        EmitCall(procNode.procId, type, depth);
                    }
                    EmitInstrConsole(ProtoCore.DSASM.kw.push, ProtoCore.DSASM.kw.regRX);
                    ProtoCore.DSASM.StackValue opReturn = new ProtoCore.DSASM.StackValue();
                    opReturn.optype = ProtoCore.DSASM.AddressType.Register;
                    opReturn.opdata = (int)ProtoCore.DSASM.Registers.RX;
                    EmitPush(opReturn);
                }
            }
            else
            {
                if (depth <= 0 && procName != ProtoCore.DSASM.Constants.kFunctionPointerCall)
                {
                    if (!hasLogError)
                    {
                        if (!compileStateTracker.Options.SuppressFunctionResolutionWarning || parentNode == null)
                        {
                            string property;
                            if (CoreUtils.TryGetPropertyName(procName, out property))
                            {
                                string message = String.Format(ProtoCore.BuildData.WarningMessage.kPropertyNotFound, property);
                                buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kPropertyNotFound, message, compileStateTracker.CurrentDSFileName, funcCall.line, funcCall.col);
                            }
                            else
                            {
                                string message = String.Format(ProtoCore.BuildData.WarningMessage.kMethodNotFound, procName);
                                buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kFunctionNotFound, message, compileStateTracker.CurrentDSFileName, funcCall.line, funcCall.col);
                            }
                        }
                        inferedType.UID = (int)PrimitiveType.kTypeNull;
                        EmitPushNull();
                    }
                }
                else
                {
                    if (procName == ProtoCore.DSASM.Constants.kFunctionPointerCall && depth == 0)
                    {
                        ProtoCore.DSASM.DynamicFunctionNode dynamicFunctionNode = new ProtoCore.DSASM.DynamicFunctionNode(procName, arglist, lefttype);
                        compileStateTracker.DynamicFunctionTable.functionTable.Add(dynamicFunctionNode);
                        var iNode = nodeBuilder.BuildIdentfier(funcCall.Function.Name);
                        EmitIdentifierNode(iNode, ref inferedType);
                    }
                    else
                    {
                        ProtoCore.DSASM.DynamicFunctionNode dynamicFunctionNode = new ProtoCore.DSASM.DynamicFunctionNode(funcCall.Function.Name, arglist, lefttype);
                        compileStateTracker.DynamicFunctionTable.functionTable.Add(dynamicFunctionNode);
                    }
                    // The function call
                    EmitInstrConsole(ProtoCore.DSASM.kw.callr, funcCall.Function.Name + "[dynamic]");
                    EmitDynamicCall(compileStateTracker.DynamicFunctionTable.functionTable.Count - 1, globalClassIndex, depth, funcCall.line, funcCall.col, funcCall.endLine, funcCall.endCol);

                    // The function return value
                    EmitInstrConsole(ProtoCore.DSASM.kw.push, ProtoCore.DSASM.kw.regRX);
                    ProtoCore.DSASM.StackValue opReturn = new ProtoCore.DSASM.StackValue();
                    opReturn.optype = ProtoCore.DSASM.AddressType.Register;
                    opReturn.opdata = (int)ProtoCore.DSASM.Registers.RX;
                    EmitPush(opReturn);

                    //assign inferedType to var
                    inferedType.UID = (int)PrimitiveType.kTypeVar;
                }
            }
            return procNode;
        }
예제 #31
0
 public abstract void TraverseFunctionCall(Node node, Node parentNode, int lefttype, int depth, ref ProtoCore.Type inferedType, ProtoCore.AssociativeGraph.GraphNode graphNode = null, ProtoCore.DSASM.AssociativeSubCompilePass subPass = ProtoCore.DSASM.AssociativeSubCompilePass.kNone);
예제 #32
0
        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);
            }
        }
예제 #33
0
        protected void EmitThrowNode(ProtoCore.AST.Node node, ProtoCore.AssociativeGraph.GraphNode graphNode = null, ProtoCore.DSASM.AssociativeSubCompilePass subPass = ProtoCore.DSASM.AssociativeSubCompilePass.kNone)
        {
            #if ENABLE_EXCEPTION_HANDLING
            if (!IsParsingGlobal() && !IsParsingGlobalFunctionBody())
            {
                return;
            }

            ThrowNode throwNode = node as ThrowNode;
            if (throwNode == null)
            {
                return;
            }

            ProtoCore.Type inferedType = new ProtoCore.Type();
            inferedType.UID = (int)ProtoCore.PrimitiveType.kTypeVar;
            inferedType.IsIndexable = false;
            DfsTraverse(throwNode.expression, ref inferedType, false, graphNode, subPass);

            EmitInstrConsole(ProtoCore.DSASM.kw.pop, ProtoCore.DSASM.kw.regLX);
            ProtoCore.DSASM.StackValue opLx = new ProtoCore.DSASM.StackValue();
            opLx.optype = ProtoCore.DSASM.AddressType.Register;
            opLx.opdata = (int)ProtoCore.DSASM.Registers.LX;
            EmitPop(opLx, Constants.kGlobalScope);

            EmitInstrConsole(ProtoCore.DSASM.kw.throwexception);
            EmitThrow();
            #endif
        }
예제 #34
0
        protected void EmitExceptionHandlingNode(ProtoCore.AST.Node node, ProtoCore.AssociativeGraph.GraphNode graphNode = null, ProtoCore.DSASM.AssociativeSubCompilePass subPass = ProtoCore.DSASM.AssociativeSubCompilePass.kNone)
        {
            #if ENABLE_EXCEPTION_HANDLING
            if (!IsParsingGlobal() && !IsParsingGlobalFunctionBody())
            {
                return;
            }

            ExceptionHandlingNode exceptionNode = node as ExceptionHandlingNode;
            if (exceptionNode == null)
                return;

            tryLevel++;
            ExceptionHandler exceptionHandler = new ExceptionHandler();
            exceptionHandler.TryLevel = tryLevel;

            ExceptionRegistration registration = core.ExceptionHandlingManager.Register(codeBlock.codeBlockId, globalProcIndex, globalClassIndex);
            registration.Add(exceptionHandler);

            exceptionHandler.StartPc = pc;
            TryBlockNode tryNode = exceptionNode.tryBlock;
            Debug.Assert(tryNode != null);
            foreach (var subnode in tryNode.body)
            {
                ProtoCore.Type inferedType = new ProtoCore.Type();
                inferedType.UID = (int)ProtoCore.PrimitiveType.kTypeVar;
                inferedType.IsIndexable = false;
                DfsTraverse(subnode, ref inferedType, false, graphNode, subPass);
            }
            exceptionHandler.EndPc = pc;

            // Jmp to code after catch block
            BackpatchTable backpatchTable = new BackpatchTable();
            backpatchTable.Append(pc);
            EmitJmp(ProtoCore.DSASM.Constants.kInvalidIndex);

            foreach (var catchBlock in exceptionNode.catchBlocks)
            {
                CatchHandler catchHandler = new CatchHandler();
                exceptionHandler.AddCatchHandler(catchHandler);

                CatchFilterNode filterNode = catchBlock.catchFilter;
                Debug.Assert(filterNode != null);
                catchHandler.FilterTypeUID = core.TypeSystem.GetType(filterNode.type.Name);
                if (catchHandler.FilterTypeUID == (int)PrimitiveType.kInvalidType)
                {
                    string message = String.Format(ProtoCore.BuildData.WarningMessage.kExceptionTypeUndefined, filterNode.type.Name);
                    buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kTypeUndefined, message, null, filterNode.line, filterNode.col);
                    catchHandler.FilterTypeUID = (int)PrimitiveType.kTypeVar;
                }

                // For filter expression catch(e:int), generate an assignment
                //    e = LX;
                catchHandler.Entry = pc;

                EmitInstrConsole(ProtoCore.DSASM.kw.push, ProtoCore.DSASM.kw.regLX);
                ProtoCore.DSASM.StackValue opLx = new ProtoCore.DSASM.StackValue();
                opLx.optype = ProtoCore.DSASM.AddressType.Register;
                opLx.opdata = (int)ProtoCore.DSASM.Registers.LX;
                EmitPush(opLx);

                ProtoCore.DSASM.SymbolNode excpVarSymbol = null;
                bool stub;
                bool isAllocated = VerifyAllocation(filterNode.var.Value, globalClassIndex, globalProcIndex, out excpVarSymbol, out stub);
                int runtimeIndex = (!isAllocated) ? codeBlock.symbolTable.runtimeIndex : excpVarSymbol.runtimeTableIndex;
                if (!isAllocated)
                {
                    excpVarSymbol = Allocate(filterNode.var.Value, globalProcIndex, new ProtoCore.Type());
                }
                EmitPushVarData(runtimeIndex, 0, (int)PrimitiveType.kTypeVar, 0);
                EmitInstrConsole(ProtoCore.DSASM.kw.pop, filterNode.var.Value);
                EmitPopForSymbol(excpVarSymbol, filterNode.var.line, filterNode.var.col, filterNode.var.endLine, filterNode.var.endCol);

                ProtoCore.Type inferedType = new ProtoCore.Type();
                inferedType.UID = (int)ProtoCore.PrimitiveType.kTypeVar;
                inferedType.IsIndexable = false;

                foreach (var subnode in catchBlock.body)
                {
                    inferedType.UID = (int)ProtoCore.PrimitiveType.kTypeVar;
                    inferedType.IsIndexable = false;
                    DfsTraverse(subnode, ref inferedType, false, graphNode, subPass);
                }

                // Jmp to code after catch block
                backpatchTable.Append(pc);
                EmitJmp(ProtoCore.DSASM.Constants.kInvalidIndex);
            }

            Backpatch(backpatchTable.backpatchList, pc);

            tryLevel--;
            #endif
        }
예제 #35
0
        public override ProcedureNode TraverseFunctionCall(
            ProtoCore.AST.Node node, 
            ProtoCore.AST.Node parentNode, 
            int lefttype, 
            int depth, 
            ref ProtoCore.Type inferedType,             
            GraphNode graphNode = null,
            ProtoCore.CompilerDefinitions.Associative.SubCompilePass subPass = ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kNone,                 
            ProtoCore.AST.Node bnode = null)
        {
            ProcedureNode procNode = null;
            if (node is FunctionDotCallNode)
            {
                procNode = TraverseDotFunctionCall(node, 
                                               parentNode, 
                                               lefttype, 
                                               depth, 
                                               graphNode, 
                                               subPass, 
                                               bnode as BinaryExpressionNode,
                                               ref inferedType);

                if (graphNode != null && procNode != null)
                {
                    GenerateCallsiteIdentifierForGraphNode(graphNode, procNode.Name);
                }
                return procNode;
            }

            var arglist = new List<ProtoCore.Type>();
            var funcCall = node as FunctionCallNode;
            var procName = funcCall.Function.Name;
            int classIndex = core.ClassTable.IndexOf(procName);

            // To support unamed constructor
            if (classIndex != Constants.kInvalidIndex)
            {
                bool isAccessible;
                int dummy;

                ProcedureNode constructor = core.ClassTable.ClassNodes[classIndex].GetMemberFunction(procName, arglist, globalClassIndex, out isAccessible, out dummy, true);
                if (constructor != null && constructor.IsConstructor)
                {
                    var rhsFNode = node as FunctionCallNode;
                    var classNode = AstFactory.BuildIdentifier(procName);
                    var dotCallNode = CoreUtils.GenerateCallDotNode(classNode, rhsFNode, core);

                    procNode = TraverseDotFunctionCall(dotCallNode, 
                                                   parentNode, 
                                                   lefttype, 
                                                   depth, 
                                                   graphNode, 
                                                   subPass, 
                                                   bnode as BinaryExpressionNode,
                                                   ref inferedType);
                    if (graphNode != null && procNode != null)
                    {
                        GenerateCallsiteIdentifierForGraphNode(graphNode, procNode.Name);
                    }
                    return procNode;
                }
            }

            foreach (AssociativeNode paramNode in funcCall.FormalArguments)
            {
                var paramType = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, 0);

                // The range expression function does not need replication guides
                emitReplicationGuide = !procName.Equals(Constants.kFunctionRangeExpression)  
                                    && !CoreUtils.IsGetterSetter(procName);

                // 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, false, graphNode, subPass, bnode);

                emitReplicationGuide = false;
                enforceTypeCheck = true;

                arglist.Add(paramType);
            }
           
            if (subPass == ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kUnboundIdentifier)
            {
                return null;   
            }
                    
            int refClassIndex = Constants.kInvalidIndex;
            if (parentNode != null && parentNode is IdentifierListNode)
            {
                var leftnode = (parentNode as IdentifierListNode).LeftNode;
                if (leftnode != null && leftnode is IdentifierNode)
                {
                    refClassIndex = core.ClassTable.IndexOf(leftnode.Name);
                }
            }

            int type = Constants.kInvalidIndex;

            // Check for the actual method, not the dot method
            // If lefttype is a valid class then check if calling a constructor
            if ((int)PrimitiveType.kInvalidType != inferedType.UID
                && (int)PrimitiveType.kTypeVoid != inferedType.UID
                && procName != Constants.kFunctionPointerCall)
            {

                bool isAccessible;
                int realType;

                bool isStaticOrConstructor = refClassIndex != Constants.kInvalidIndex;
                procNode = core.ClassTable.ClassNodes[inferedType.UID].GetMemberFunction(procName, arglist, globalClassIndex, out isAccessible, out realType, isStaticOrConstructor);

                if (procNode != null)
                {
                    Validity.Assert(realType != Constants.kInvalidIndex);
                    type = lefttype = realType;

                    if (!isAccessible)
                    {
                        type = lefttype = realType;
                        procNode = null;
                        string message = String.Format(ProtoCore.Properties.Resources.kMethodIsInaccessible, procName);
                        buildStatus.LogWarning(WarningID.kAccessViolation, message, core.CurrentDSFileName, funcCall.line, funcCall.col, graphNode);
                        inferedType.UID = (int)PrimitiveType.kTypeNull;

                        EmitPushNull();
                        if (graphNode != null && procNode != null)
                        {
                            GenerateCallsiteIdentifierForGraphNode(graphNode, procNode.Name);
                        }
                        return procNode;
                    }

                }
            }

            // Try function pointer firstly
            if ((procNode == null) && (procName != ProtoCore.DSASM.Constants.kFunctionPointerCall))
            {
                bool isAccessibleFp;
                SymbolNode symbolnode = null;
                bool isAllocated = VerifyAllocation(procName, globalClassIndex, globalProcIndex, out symbolnode, out isAccessibleFp);

                if (isAllocated) 
                {
                    // The graph node always depends on this function pointer
                    if (null != graphNode)
                    {
                        PushSymbolAsDependent(symbolnode, graphNode);
                        GenerateCallsiteIdentifierForGraphNode(graphNode, procName);
                    }

                    // not checking the type against function pointer, as the 
                    // type could be var
                    procName = Constants.kFunctionPointerCall;
                }
            }

            // Always try global function firstly. Because we dont have syntax
            // support for calling global function (say, ::foo()), if we try
            // member function firstly, there is no way to call a global function
            // For member function, we can use this.foo() to distinguish it from 
            // global function. 
            if ((procNode == null) && (procName != Constants.kFunctionPointerCall))
            {
                procNode = CoreUtils.GetFunctionBySignature(procName, arglist, codeBlock);
                if (null != procNode)
                {
                    type = ProtoCore.DSASM.Constants.kGlobalScope;
                    if (core.TypeSystem.IsHigherRank(procNode.ReturnType.UID, inferedType.UID))
                    {
                        inferedType = procNode.ReturnType;
                    }
                }
            }

            // Try member functions in global class scope
            if ((procNode == null) && (procName != Constants.kFunctionPointerCall) && (parentNode == null))
            {
                if (globalClassIndex != Constants.kInvalidIndex)
                {
                    int realType;
                    bool isAccessible;
                    bool isStaticOrConstructor = refClassIndex != Constants.kInvalidIndex;
                    ProtoCore.DSASM.ProcedureNode memProcNode = core.ClassTable.ClassNodes[globalClassIndex].GetMemberFunction(procName, arglist, globalClassIndex, out isAccessible, out realType, isStaticOrConstructor);

                    if (memProcNode != null)
                    {
                        Validity.Assert(realType != Constants.kInvalidIndex);
                        procNode = memProcNode;
                        inferedType = procNode.ReturnType;
                        type = realType;

                        if (!isAccessible)
                        {
                            string message = String.Format(ProtoCore.Properties.Resources.kMethodIsInaccessible, procName);
                            buildStatus.LogWarning(WarningID.kAccessViolation, message, core.CurrentDSFileName, funcCall.line, funcCall.col, graphNode);

                            inferedType.UID = (int)PrimitiveType.kTypeNull;
                            EmitPushNull();
                            if (graphNode != null && procNode != null)
                            {
                                GenerateCallsiteIdentifierForGraphNode(graphNode, procNode.Name);
                            }
                            return procNode;
                        }
                    }
                }
            }

            if (null != procNode)
            {
                if (procNode.IsConstructor && 
                    (globalClassIndex != Constants.kInvalidIndex) && 
                    (globalProcIndex != Constants.kInvalidIndex) && 
                    (globalClassIndex == inferedType.UID))
                {
                    ProcedureNode contextProcNode = core.ClassTable.ClassNodes[globalClassIndex].ProcTable.Procedures[globalProcIndex];
                    if (contextProcNode.IsConstructor &&
                        string.Equals(contextProcNode.Name, procNode.Name) &&
                        contextProcNode.RuntimeIndex == procNode.RuntimeIndex)
                    {
                        string message = String.Format(ProtoCore.Properties.Resources.kCallingConstructorInConstructor, procName);
                        buildStatus.LogWarning(WarningID.kCallingConstructorInConstructor, message, core.CurrentDSFileName, node.line, node.col, graphNode);
                        inferedType.UID = (int)PrimitiveType.kTypeNull;
                        EmitPushNull();
                        if (graphNode != null && procNode != null)
                        {
                            GenerateCallsiteIdentifierForGraphNode(graphNode, procNode.Name);
                        }
                        return procNode;
                    }
                }

                inferedType = procNode.ReturnType;

                if (procNode.ID != Constants.kInvalidIndex)
                {
                    foreach (AssociativeNode paramNode in funcCall.FormalArguments)
                    {
                        // Get the lhs symbol list
                        ProtoCore.Type ltype = new ProtoCore.Type();
                        ltype.UID = globalClassIndex;
                        UpdateNodeRef argNodeRef = new UpdateNodeRef();
                        DFSGetSymbolList(paramNode, ref ltype, argNodeRef);

                        if (null != graphNode)
                        {
                            if (argNodeRef.nodeList.Count > 0)
                            {
                                graphNode.updatedArguments.Add(argNodeRef);
                            }
                        }
                    }

                    // The function is at block 0 if its a constructor, member 
                    // or at the globals scope.  Its at block 1 if its inside a 
                    // language block. Its limited to block 1 as of R1 since we 
                    // dont support nested function declarations yet
                    int blockId = procNode.RuntimeIndex;

                    //push value-not-provided default argument
                    for (int i = arglist.Count; i < procNode.ArgumentInfos.Count; i++)
                    {
                        EmitDefaultArgNode();
                    }
                    
                    // Push the function declaration block and indexed array
                    // Jun TODO: Implementeation of indexing into a function call:
                    //  x = f()[0][1]
                    int dimensions = 0;
                    EmitPushVarData(dimensions);

                    // Emit depth
                    EmitInstrConsole(kw.push, depth + "[depth]");
                    EmitPush(StackValue.BuildInt(depth));

                    // The function call
                    EmitInstrConsole(kw.callr, procNode.Name);

                    // Do not emit breakpoints at built-in methods like _add/_sub etc. - pratapa
                    if (procNode.IsAssocOperator || procNode.Name.Equals(Constants.kInlineConditionalMethodName))
                    {
                        EmitCall(procNode.ID, 
                                 blockId,
                                 type, 
                                 Constants.kInvalidIndex, 
                                 Constants.kInvalidIndex, 
                                 Constants.kInvalidIndex, 
                                 Constants.kInvalidIndex, 
                                 procNode.PC);
                    }
                    // Break at function call inside dynamic lang block created for a 'true' or 'false' expression inside an inline conditional
                    else if (core.DebuggerProperties.breakOptions.HasFlag(DebugProperties.BreakpointOptions.EmitInlineConditionalBreakpoint))
                    {
                        var codeRange = core.DebuggerProperties.highlightRange;

                        var startInclusive = codeRange.StartInclusive;
                        var endExclusive = codeRange.EndExclusive;

                        EmitCall(procNode.ID, 
                                 blockId,
                                 type, 
                                 startInclusive.LineNo, 
                                 startInclusive.CharNo, 
                                 endExclusive.LineNo, 
                                 endExclusive.CharNo, 
                                 procNode.PC);
                    }
                    // Use startCol and endCol of binary expression node containing function call except if it's a setter
                    else if (bnode != null && !procNode.Name.StartsWith(Constants.kSetterPrefix))
                    {
                        EmitCall(procNode.ID, 
                                 blockId,
                                 type, 
                                 bnode.line, 
                                 bnode.col, 
                                 bnode.endLine, 
                                 bnode.endCol, 
                                 procNode.PC);
                    }
                    else
                    {
                        EmitCall(procNode.ID, 
                                 blockId,
                                 type, 
                                 funcCall.line, 
                                 funcCall.col, 
                                 funcCall.endLine, 
                                 funcCall.endCol, 
                                 procNode.PC);
                    }

                    // The function return value
                    EmitInstrConsole(kw.push, kw.regRX);
                    StackValue opReturn = StackValue.BuildRegister(Registers.RX);
                    EmitPush(opReturn);
                }
            }
            else
            {
                if (depth <= 0 && procName != ProtoCore.DSASM.Constants.kFunctionPointerCall)
                {
                    string property;
                    if (CoreUtils.TryGetPropertyName(procName, out property))
                    {
                        string message = String.Format(ProtoCore.Properties.Resources.kPropertyNotFound, property);
                        buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kPropertyNotFound, message, core.CurrentDSFileName, funcCall.line, funcCall.col, graphNode);
                    }
                    else
                    {
                        string message = String.Format(ProtoCore.Properties.Resources.kMethodNotFound, procName);
                        buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kFunctionNotFound, message, core.CurrentDSFileName, funcCall.line, funcCall.col, graphNode);
                    }

                    inferedType.UID = (int)PrimitiveType.kTypeNull;
                    EmitPushNull();
                }
                else
                {
                    DynamicFunction dynFunc = null;
                    if (procName == Constants.kFunctionPointerCall && depth == 0)
                    {
                        if (!core.DynamicFunctionTable.TryGetFunction(procName, arglist.Count, lefttype, out dynFunc))
                        {
                            dynFunc = core.DynamicFunctionTable.AddNewFunction(procName, arglist.Count, lefttype);
                        }
                        var iNode =AstFactory.BuildIdentifier(funcCall.Function.Name);
                        EmitIdentifierNode(iNode, ref inferedType);
                    }
                    else
                    {
                        if (!core.DynamicFunctionTable.TryGetFunction(procName, arglist.Count, lefttype, out dynFunc))
                        {
                            dynFunc = core.DynamicFunctionTable.AddNewFunction(procName, arglist.Count, lefttype);
                        }
                    }

                    // Emit depth
                    EmitInstrConsole(kw.push, depth + "[depth]");
                    EmitPush(StackValue.BuildInt(depth));

                    // The function call
                    EmitInstrConsole(kw.callr, funcCall.Function.Name + "[dynamic]");
                    EmitDynamicCall(dynFunc.Index, 
                                    globalClassIndex, 
                                    funcCall.line, 
                                    funcCall.col, 
                                    funcCall.endLine, 
                                    funcCall.endCol);

                    // The function return value
                    EmitInstrConsole(kw.push, kw.regRX);
                    StackValue opReturn = StackValue.BuildRegister(Registers.RX);
                    EmitPush(opReturn);

                    //assign inferedType to var
                    inferedType.UID = (int)PrimitiveType.kTypeVar;
                }
            }

            if (graphNode != null && procNode != null)
            {
                GenerateCallsiteIdentifierForGraphNode(graphNode, procNode.Name);
            }
            
            return procNode;
        }
예제 #36
0
        public ProcedureNode TraverseDotFunctionCall(
                                ProtoCore.AST.Node node, 
                                ProtoCore.AST.Node parentNode, 
                                int lefttype, 
                                int depth, 
                                GraphNode graphNode, 
                                ProtoCore.CompilerDefinitions.Associative.SubCompilePass subPass,
                                BinaryExpressionNode bnode,
                                ref ProtoCore.Type inferedType)
        {
            ProcedureNode procCallNode = null;

            var dotCallType = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, 0); ;

            bool isConstructor = false;
            bool isStaticCall = false;
            bool isUnresolvedDot = false;

            int classIndex = Constants.kInvalidIndex;
            string className = string.Empty;

            var dotCall = new FunctionDotCallNode(node as FunctionDotCallNode);
            var funcCall = dotCall.DotCall;
            var procName = dotCall.FunctionCall.Function.Name;

            var firstArgument = dotCall.DotCall.FormalArguments[0];
            if (firstArgument is FunctionDotCallNode)
            {
                isUnresolvedDot = true;
            }
            else if (firstArgument is IdentifierNode)
            {
                // Check if the lhs identifer is a class name
                className = (firstArgument as IdentifierNode).Name;
                classIndex = core.ClassTable.IndexOf(className);

                // Check if the lhs is an variable
                SymbolNode symbolnode;
                bool isAccessible;
                bool hasAllocated = VerifyAllocation(className,
                                                     globalClassIndex,
                                                     globalProcIndex,
                                                     out symbolnode,
                                                     out isAccessible);

                bool toResolveMethodOnClass = classIndex != Constants.kInvalidIndex;

                // If the lhs is an variable which happens to have a same name
                // as some class, then check the right hand side is a valid 
                // constructor or static function call. 
                if (toResolveMethodOnClass && hasAllocated && isAccessible)
                {
                    var classes = core.ClassTable.ClassNodes;
                    var classNode = classes[classIndex];
                    int argCount = dotCall.FunctionCall.FormalArguments.Count;
                    var procNode = classNode.GetFirstConstructorBy(procName, argCount);
                    if (procNode == null)
                    {
                        procNode = classNode.GetFirstStaticFunctionBy(procName, argCount);
                    }

                    if (procNode == null)
                    {
                        toResolveMethodOnClass = false;
                        classIndex = Constants.kInvalidIndex;
                        className = string.Empty;
                    }
                }

                if (toResolveMethodOnClass)
                {
                    dotCall.DotCall.FormalArguments[0] = new IntNode(classIndex);
                    inferedType.UID = dotCallType.UID = classIndex;

                    // Now the left hand side of dot call is a valid class name.
                    // There are three cases for the right hand side: calling a 
                    // function, getting a static property or getting a function 
                    // pointer. I.e.,
                    // 
                    //    x = Foo.foo();
                    //
                    // Or
                    //    
                    //    y = Bar.bar;   // static property or funciton pointer
                    //    Bar.bar_2 = z; // static property
                    // 
                    // For the latters, they are converted to getter/setter. 
                    // I.e., 
                    //
                    //    y = Bar.%get_bar();
                    //    %ret = Bar.%set_bar_2(z);
                    //
                    // We need to check each case. 

                    var classes = core.ClassTable.ClassNodes;
                    var classNode = classes[classIndex];

                    var property = String.Empty;
                    if (CoreUtils.TryGetPropertyName(procName, out property))
                    {
                        if (procCallNode == null)
                        {
                            procCallNode = classNode.GetFirstStaticFunctionBy(procName);
                            isStaticCall = procCallNode != null;
                        }

                        if (procCallNode == null)
                        {
                            if (subPass != ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kNone)
                            {
                                return null;
                            }

                            // Try static function firstly
                            procCallNode = classNode.GetFirstStaticFunctionBy(property);
                            if (procCallNode == null)
                            {
                                procCallNode = classNode.GetFirstMemberFunctionBy(property);
                            }

                            if (procCallNode == null)
                            {
                                procCallNode = classNode.GetFirstMemberFunctionBy(procName);
                            }

                            if (procCallNode != null)
                            {
                                EmitFunctionPointer(procCallNode);
                            }
                            else
                            {
                                string message = String.Format(ProtoCore.Properties.Resources.kCallingNonStaticProperty,
                                                               className,
                                                               property);

                                buildStatus.LogWarning(WarningID.kCallingNonStaticMethodOnClass,
                                                       message,
                                                       core.CurrentDSFileName,
                                                       dotCall.line,
                                                       dotCall.col, 
                                                       graphNode);

                                EmitNullNode(new NullNode(), ref inferedType);
                            }
                            
                            return null;
                        }
                    }
                    else
                    {
                        int argCount = dotCall.FunctionCall.FormalArguments.Count;
                        procCallNode = classNode.GetFirstConstructorBy(procName, argCount);
                        isConstructor = procCallNode != null;

                        if (procCallNode == null)
                        {
                            procCallNode = classNode.GetFirstStaticFunctionBy(procName, argCount);
                            isStaticCall = procCallNode != null;
                        }

                        if (!isStaticCall && !isConstructor)
                        {
                            if (subPass == ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kNone)
                            {
                                string message = String.Format(ProtoCore.Properties.Resources.kStaticMethodNotFound,
                                                               className,
                                                               procName);

                                buildStatus.LogWarning(WarningID.kFunctionNotFound,
                                                       message,
                                                       core.CurrentDSFileName,
                                                       dotCall.line,
                                                       dotCall.col, 
                                                       graphNode);

                                EmitNullNode(new NullNode(), ref inferedType);
                            }

                            return null;
                        }
                    }
                }
                else if (hasAllocated && symbolnode.datatype.UID != (int)PrimitiveType.kTypeVar)
                {
                    inferedType.UID = symbolnode.datatype.UID;
                    if (Constants.kInvalidIndex != inferedType.UID)
                    {
                        procCallNode = GetProcedureFromInstance(symbolnode.datatype.UID, dotCall.FunctionCall);
                    }

                    if (null != procCallNode)
                    {
                        if (procCallNode.IsConstructor)
                        {
                            if (subPass == ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kNone)
                            {
                                string message = String.Format(ProtoCore.Properties.Resources.KCallingConstructorOnInstance,
                                                               procName);
                                buildStatus.LogWarning(WarningID.kCallingConstructorOnInstance,
                                                       message,
                                                       core.CurrentDSFileName,
                                                       funcCall.line,
                                                       funcCall.col, 
                                                       graphNode);
                                EmitNullNode(new NullNode(), ref inferedType);
                            }
                            return null;
                        }

                        isAccessible = procCallNode.AccessModifier == ProtoCore.CompilerDefinitions.AccessModifier.kPublic
                             || (procCallNode.AccessModifier == ProtoCore.CompilerDefinitions.AccessModifier.kPrivate && procCallNode.ClassID == globalClassIndex);

                        if (!isAccessible)
                        {
                            if (subPass == ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kNone)
                            {
                                string message = String.Format(ProtoCore.Properties.Resources.kMethodIsInaccessible, procName);
                                buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kAccessViolation, message, core.CurrentDSFileName, funcCall.line, funcCall.col, graphNode);
                            }
                        }

                        var dynamicRhsIndex = (int)(dotCall.DotCall.FormalArguments[1] as IntNode).Value;
                        var dynFunc = core.DynamicFunctionTable.GetFunctionAtIndex(dynamicRhsIndex);
                        dynFunc.ClassIndex = procCallNode.ClassID;
                    }
                }
                else
                {
                    isUnresolvedDot = true;
                }
            }

            // Its an accceptable method at this point
            List<ProtoCore.Type> arglist = new List<ProtoCore.Type>();
            TraverseDotCallArguments(funcCall, 
                                     dotCall,
                                     procCallNode, 
                                     arglist,
                                     procName, 
                                     classIndex, 
                                     className, 
                                     isStaticCall, 
                                     isConstructor,
                                     graphNode, 
                                     subPass, 
                                     bnode);

            if (subPass == ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kUnboundIdentifier)
            {
                return null;
            }

            if (!isConstructor && !isStaticCall)
            {
                Validity.Assert(dotCall.DotCall.FormalArguments[ProtoCore.DSASM.Constants.kDotArgIndexArrayArgs] is ExprListNode);
                ExprListNode functionArgs = dotCall.DotCall.FormalArguments[ProtoCore.DSASM.Constants.kDotArgIndexArrayArgs] as ExprListNode;
                functionArgs.Exprs.Insert(0, dotCall.DotCall.FormalArguments[ProtoCore.DSASM.Constants.kDotArgIndexPtr]);
            }
           
            // From here on, handle the actual procedure call 
            int type = ProtoCore.DSASM.Constants.kInvalidIndex;

            int refClassIndex = ProtoCore.DSASM.Constants.kInvalidIndex;
            if (parentNode != null && parentNode is IdentifierListNode)
            {
                var leftnode = (parentNode as IdentifierListNode).LeftNode;
                if (leftnode != null && leftnode is IdentifierNode)
                {
                    refClassIndex = core.ClassTable.IndexOf(leftnode.Name);
                }
            }

            if (firstArgument is FunctionCallNode ||
                firstArgument is FunctionDotCallNode ||
                firstArgument is ExprListNode)
            {
                inferedType.UID = arglist[0].UID;
            }

            // If lefttype is a valid class then check if calling a constructor
            if (procCallNode == null 
                && (int)PrimitiveType.kInvalidType != inferedType.UID
                && (int)PrimitiveType.kTypeVoid != inferedType.UID
                && procName != Constants.kFunctionPointerCall)
            {
                procCallNode = core.ClassTable.ClassNodes[inferedType.UID].GetFirstMemberFunctionBy(procName);
            }

            // Try function pointer firstly
            if ((procCallNode == null) && (procName != Constants.kFunctionPointerCall))
            {
                bool isAccessibleFp;
                ProtoCore.DSASM.SymbolNode symbolnode = null;
                bool isAllocated = VerifyAllocation(procName, globalClassIndex, globalProcIndex, out symbolnode, out isAccessibleFp);
                if (isAllocated) // not checking the type against function pointer, as the type could be var
                {
                    procName = Constants.kFunctionPointerCall;
                    // The graph node always depends on this function pointer
                    if (null != graphNode)
                    {
                        PushSymbolAsDependent(symbolnode, graphNode);
                    }
                }
            }

            // Always try global function firstly. Because we dont have syntax
            // support for calling global function (say, ::foo()), if we try
            // member function firstly, there is no way to call a global function
            // For member function, we can use this.foo() to distinguish it from 
            // global function. 
            if ((procCallNode == null) && (procName != Constants.kFunctionPointerCall))
            {
                procCallNode = CoreUtils.GetFunctionBySignature(procName, arglist, codeBlock);
                if (null != procCallNode)
                {
                    type = Constants.kGlobalScope;
                    if (core.TypeSystem.IsHigherRank(procCallNode.ReturnType.UID, inferedType.UID))
                    {
                        inferedType = procCallNode.ReturnType;
                    }
                }
            }

            // Try member functions in global class scope
            if ((procCallNode == null) && (procName != Constants.kFunctionPointerCall) && (parentNode == null))
            {
                if (globalClassIndex != Constants.kInvalidIndex)
                {
                    int realType;
                    bool isAccessible;
                    bool isStaticOrConstructor = refClassIndex != Constants.kInvalidIndex;
                    ProcedureNode memProcNode = core.ClassTable.ClassNodes[globalClassIndex].GetMemberFunction(procName, arglist, globalClassIndex, out isAccessible, out realType, isStaticOrConstructor);

                    if (memProcNode != null)
                    {
                        Validity.Assert(realType != Constants.kInvalidIndex);
                        procCallNode = memProcNode;
                        inferedType = procCallNode.ReturnType;
                        type = realType;

                        if (!isAccessible)
                        {
                            string message = String.Format(ProtoCore.Properties.Resources.kMethodIsInaccessible, procName);
                            buildStatus.LogWarning(WarningID.kAccessViolation, message, core.CurrentDSFileName, funcCall.line, funcCall.col, graphNode);

                            inferedType.UID = (int)PrimitiveType.kTypeNull;
                            EmitPushNull();
                            return procCallNode;
                        }
                    }
                }
            }

            if (isUnresolvedDot || procCallNode == null)
            {
                if (dotCallType.UID != (int)PrimitiveType.kTypeVar)
                {
                    inferedType.UID = dotCallType.UID;
                }

                var procNode = CoreUtils.GetFunctionByName(Constants.kDotMethodName, codeBlock);
                if (CoreUtils.IsGetter(procName))
                {
                    EmitFunctionCall(depth, type, arglist, procNode, funcCall, true);
                }
                else
                {
                    EmitFunctionCall(depth, type, arglist, procNode, funcCall, false, bnode);
                }
                return procNode;
            }
            else
            {
                if (procCallNode.IsConstructor &&
                    (globalClassIndex != Constants.kInvalidIndex) &&
                    (globalProcIndex != Constants.kInvalidIndex) &&
                    (globalClassIndex == inferedType.UID))
                {
                    ProcedureNode contextProcNode = core.ClassTable.ClassNodes[globalClassIndex].ProcTable.Procedures[globalProcIndex];
                    if (contextProcNode.IsConstructor &&
                        string.Equals(contextProcNode.Name, procCallNode.Name) &&
                        contextProcNode.RuntimeIndex == procCallNode.RuntimeIndex)
                    {
                        string message = String.Format(ProtoCore.Properties.Resources.kCallingConstructorInConstructor, procName);
                        buildStatus.LogWarning(WarningID.kCallingConstructorInConstructor, message, core.CurrentDSFileName, node.line, node.col, graphNode);
                        inferedType.UID = (int)PrimitiveType.kTypeNull;
                        EmitPushNull();
                        return procCallNode;
                    }
                }

                inferedType = procCallNode.ReturnType;

                // Get the dot call procedure
                if (isConstructor || isStaticCall)
                {
                    bool isGetter = CoreUtils.IsGetter(procName);
                    EmitFunctionCall(depth, procCallNode.ClassID, arglist, procCallNode, funcCall, isGetter, bnode);
                }
                else
                {
                    var procNode = CoreUtils.GetFunctionByName(Constants.kDotMethodName, codeBlock);
                    if (CoreUtils.IsSetter(procName))
                    {
                        EmitFunctionCall(depth, type, arglist, procNode, funcCall);
                    }
                    // Do not emit breakpoint at getters only - pratapa
                    else if (CoreUtils.IsGetter(procName))
                    {
                        EmitFunctionCall(depth, type, arglist, procNode, funcCall, true);
                    }
                    else
                    {
                        EmitFunctionCall(depth, type, arglist, procNode, funcCall, false, bnode);
                    }

                    if (dotCallType.UID != (int)PrimitiveType.kTypeVar)
                    {
                        inferedType.UID = dotCallType.UID;
                    }
                }

                if (isConstructor)
                {
                    foreach (AssociativeNode paramNode in dotCall.FunctionCall.FormalArguments)
                    {
                        // Get the lhs symbol list
                        ProtoCore.Type ltype = new ProtoCore.Type();
                        ltype.UID = globalClassIndex;
                        UpdateNodeRef argNodeRef = new UpdateNodeRef();
                        DFSGetSymbolList(paramNode, ref ltype, argNodeRef);

                        if (null != graphNode)
                        {
                            if (argNodeRef.nodeList.Count > 0)
                            {
                                graphNode.updatedArguments.Add(argNodeRef);
                            }
                        }
                    }

                    graphNode.firstProc = procCallNode;
                }
                
                return procCallNode;
            }
        }
예제 #37
0
 protected abstract void DfsTraverse(Node node, ref ProtoCore.Type inferedType, bool isBooleanOp = false, ProtoCore.AssociativeGraph.GraphNode graphNode = null, ProtoCore.DSASM.AssociativeSubCompilePass subPass = ProtoCore.DSASM.AssociativeSubCompilePass.kNone);
예제 #38
0
        private int EmitExpressionInterpreter(ProtoCore.AST.Node codeBlockNode)
        {
            core.watchStartPC = this.pc;
            compilePass = ProtoCore.CompilerDefinitions.Associative.CompilePass.kGlobalScope;
            ProtoCore.AST.AssociativeAST.CodeBlockNode codeblock = codeBlockNode as ProtoCore.AST.AssociativeAST.CodeBlockNode;

            ProtoCore.Type inferedType = new ProtoCore.Type();

            globalClassIndex = ProtoCore.DSASM.Constants.kInvalidIndex;
            globalProcIndex = ProtoCore.DSASM.Constants.kGlobalScope;

            // check if currently inside a function when the break was called
            if (context.DebugProps.DebugStackFrameContains(DebugProperties.StackFrameFlagOptions.FepRun))
            {
                // Save the current scope for the expression interpreter
                globalClassIndex = context.WatchClassScope = context.MemoryState.CurrentStackFrame.ClassScope;
                globalProcIndex = core.watchFunctionScope = context.MemoryState.CurrentStackFrame.FunctionScope;
                int functionBlock = context.MemoryState.CurrentStackFrame.FunctionBlock;

                if (globalClassIndex != -1)
                    localProcedure = core.ClassTable.ClassNodes[globalClassIndex].ProcTable.Procedures[globalProcIndex];
                else
                {
                    // TODO: to investigate whethter to use the table under executable or in core.FuncTable - Randy, Jun
                    localProcedure = core.DSExecutable.procedureTable[functionBlock].Procedures[globalProcIndex];
                }
            }

            foreach (AssociativeNode node in codeblock.Body)
            {
                inferedType = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, 0);

                DfsTraverse(node, ref inferedType, false, null, ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kUnboundIdentifier);
            }

            core.InferedType = inferedType;

            this.pc = core.watchStartPC;

            return codeBlock.codeBlockId;
        }
예제 #39
0
        /// <summary>
        /// Return possible type of the output at specified output port.
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        public override ProtoCore.Type GetTypeHintForOutput(int index)
        {
            ProtoCore.Type type      = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar);
            var            statement = GetStatementForOutput(index);

            if (statement == null)
            {
                return(type);
            }

            BinaryExpressionNode expr = statement.AstNode as BinaryExpressionNode;

            if (expr == null || expr.Optr != Operator.assign)
            {
                return(type);
            }

            var core = libraryServices.LibraryManagementCore;

            if (expr.RightNode is IdentifierListNode)
            {
                var identListNode = expr.RightNode as IdentifierListNode;
                var funcNode      = identListNode.RightNode as FunctionCallNode;
                if (funcNode == null)
                {
                    return(type);
                }

                string fullyQualitifiedName = CoreUtils.GetIdentifierExceptMethodName(identListNode);
                if (string.IsNullOrEmpty(fullyQualitifiedName))
                {
                    return(type);
                }

                var classIndex = core.ClassTable.IndexOf(fullyQualitifiedName);
                if (classIndex == ProtoCore.DSASM.Constants.kInvalidIndex)
                {
                    return(type);
                }

                var targetClass = core.ClassTable.ClassNodes[classIndex];
                var func        = targetClass.GetFirstMemberFunctionBy(funcNode.Function.Name);
                type = func.ReturnType;
                return(type);
            }
            else if (expr.RightNode is FunctionCallNode)
            {
                var functionCallNode = expr.RightNode as FunctionCallNode;
                ProtoCore.FunctionGroup funcGroup;
                var funcTable = core.FunctionTable.GlobalFuncTable[0];
                if (funcTable.TryGetValue(functionCallNode.Function.Name, out funcGroup))
                {
                    var func = funcGroup.FunctionEndPoints.FirstOrDefault();
                    if (func != null)
                    {
                        return(func.procedureNode.ReturnType);
                    }
                }
            }
            else if (expr.RightNode is IntNode)
            {
                return(TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeInt));
            }
            else if (expr.RightNode is StringNode)
            {
                return(TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeString));
            }
            else if (expr.RightNode is DoubleNode)
            {
                return(TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeDouble));
            }
            else if (expr.RightNode is StringNode)
            {
                return(TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeString));
            }

            return(type);
        }
예제 #40
0
        public override int Emit(ProtoCore.AST.Node codeBlockNode, ProtoCore.AssociativeGraph.GraphNode graphNode = null)
        {
            if (core.Options.IsDeltaExecution)
            {
                if (context != null && context.symbolTable != null)
                {
                    Validity.Assert(context.symbolTable.symbolList != null && context.symbolTable.symbolList.Count > 0);
                    codeBlock.symbolTable = context.symbolTable;
                }
            }

            AllocateContextGlobals();

            core.watchStartPC = this.pc;
            if (core.Options.RunMode == ProtoCore.DSASM.InterpreterMode.kExpressionInterpreter)
            {
                return EmitExpressionInterpreter(codeBlockNode);
            }

            this.localCodeBlockNode = codeBlockNode;
            ProtoCore.AST.AssociativeAST.CodeBlockNode codeblock = codeBlockNode as ProtoCore.AST.AssociativeAST.CodeBlockNode;
            bool isTopBlock = null == codeBlock.parent;
            if (!isTopBlock)
            {
                // If this is an inner block where there can be no classes, we can start at parsing at the global function state
                compilePass = ProtoCore.CompilerDefinitions.Associative.CompilePass.kGlobalFuncSig;
            }

            codeblock.Body = ApplyTransform(codeblock.Body);
            
            bool hasReturnStatement = false;
            ProtoCore.Type inferedType = new ProtoCore.Type();
            bool ssaTransformed = false;
            while (ProtoCore.CompilerDefinitions.Associative.CompilePass.kDone != compilePass)
            {
                // Emit SSA only after generating the class definitions
                if (core.Options.GenerateSSA)
                {
                    if (compilePass > ProtoCore.CompilerDefinitions.Associative.CompilePass.kClassName && !ssaTransformed)
                    {
                        if (!core.IsParsingCodeBlockNode && !core.Options.IsDeltaExecution)
                        {
                            //Audit class table for multiple symbol definition and emit warning.
                            this.core.ClassTable.AuditMultipleDefinition(this.core.BuildStatus, graphNode);
                        }
                        codeblock.Body = BuildSSA(codeblock.Body, context);              
                        ssaTransformed = true;
                        if (core.Options.DumpIL)
                        {
                            CodeGenDS codegenDS = new CodeGenDS(codeblock.Body);
                            EmitCompileLog(codegenDS.GenerateCode());
                        }
                    }
                }

                inferedType = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, 0);
                hasReturnStatement = EmitCodeBlock(codeblock.Body, ref inferedType, ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kUnboundIdentifier, false);
                if (compilePass == ProtoCore.CompilerDefinitions.Associative.CompilePass.kGlobalScope && !hasReturnStatement)
                {
                    EmitReturnNull(); 
                }

                compilePass++;

                // We have compiled all classes
                if (compilePass == ProtoCore.CompilerDefinitions.Associative.CompilePass.kGlobalScope && isTopBlock)
                {
                    EmitFunctionCallToInitStaticProperty(codeblock.Body);
                }

            }

            ResolveFinalNodeRefs();
            ResolveSSADependencies();
            
            ProtoCore.AssociativeEngine.Utils.BuildGraphNodeDependencies(
                codeBlock.instrStream.dependencyGraph.GetGraphNodesAtScope(Constants.kInvalidIndex, Constants.kGlobalScope));
        
            
            if (codeBlock.parent == null)  // top-most langauge block
            {
                ResolveFunctionGroups();
            }

            core.InferedType = inferedType;

            if (core.AsmOutput != Console.Out)
            {
                core.AsmOutput.Flush();
            }

            this.localCodeBlockNode = codeBlockNode;

            // Reset the callsite guids in preparation for the next compilation
            core.CallsiteGuidMap = new Dictionary<Guid, int>();

            return codeBlock.codeBlockId;
        }
예제 #41
0
 private void InferDFSTraverse(AssociativeNode node, ref ProtoCore.Type inferedType)
 {
     if (node is IdentifierNode)
     {
         IdentifierNode t = node as IdentifierNode;
         if (compileStateTracker.TypeSystem.IsHigherRank(t.datatype.UID, inferedType.UID))
         {
             ProtoCore.Type type = new ProtoCore.Type();
             type.UID = t.datatype.UID;
             type.IsIndexable = false;
             inferedType = type;
         }
     }
     else if (node is FunctionCallNode)
     {
         FunctionCallNode f = node as FunctionCallNode;
     }
     else if (node is BinaryExpressionNode)
     {
         BinaryExpressionNode b = node as BinaryExpressionNode;
         InferDFSTraverse(b.LeftNode, ref inferedType);
         InferDFSTraverse(b.RightNode, ref inferedType);
     }
 }
예제 #42
0
        private void EmitClassDeclNode(AssociativeNode node, ref ProtoCore.Type inferedType, ProtoCore.CompilerDefinitions.Associative.SubCompilePass subPass = ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kNone,
            GraphNode graphNode = null)
        {
            ClassDeclNode classDecl = node as ClassDeclNode;
            
            // Restrict classes 
            if (!IsClassAllowed(classDecl))
            {
                return;
            }
            // Handling n-pass on class declaration
            if (ProtoCore.CompilerDefinitions.Associative.CompilePass.kClassName == compilePass)
            {
                // Class name pass
                // Populating the class tables with the class names
                if (null != codeBlock.parent)
                {
                    buildStatus.LogSemanticError(Resources.ClassCannotBeDefinedInsideLanguageBlock, core.CurrentDSFileName, classDecl.line, classDecl.col);
                }


                ProtoCore.DSASM.ClassNode thisClass = new ProtoCore.DSASM.ClassNode();
                thisClass.Name = classDecl.ClassName;
                thisClass.Size = classDecl.Variables.Count;
                thisClass.IsImportedClass = classDecl.IsImportedClass;
                thisClass.TypeSystem = core.TypeSystem;
                thisClass.ClassAttributes = classDecl.ClassAttributes;
                
                if (classDecl.ExternLibName != null)
                    thisClass.ExternLib = classDecl.ExternLibName;
                else
                    thisClass.ExternLib = Path.GetFileName(core.CurrentDSFileName);

                globalClassIndex = core.ClassTable.Append(thisClass);
                if (ProtoCore.DSASM.Constants.kInvalidIndex == globalClassIndex)
                {
                    string message = string.Format("Class redefinition '{0}' (BE1C3285).\n", classDecl.ClassName);
                    buildStatus.LogSemanticError(message, core.CurrentDSFileName, classDecl.line, classDecl.col);
                    throw new BuildHaltException(message);
                }

                unPopulatedClasses.Add(globalClassIndex, classDecl);

                //Always allow us to convert a class to a bool
                thisClass.CoerceTypes.Add((int)PrimitiveType.kTypeBool, (int)ProtoCore.DSASM.ProcedureDistance.kCoerceScore);
            }
            else if (ProtoCore.CompilerDefinitions.Associative.CompilePass.kClassBaseClass == compilePass)
            { 
                // Base class pass
                // Populating each class entry with their immediate baseclass
                globalClassIndex = core.ClassTable.GetClassId(classDecl.ClassName);

                ProtoCore.DSASM.ClassNode thisClass = core.ClassTable.ClassNodes[globalClassIndex];

                // Verify and store the list of classes it inherits from 
                if (null != classDecl.BaseClasses)
                {
                    for (int n = 0; n < classDecl.BaseClasses.Count; ++n)
                    {
                        int baseClass = core.ClassTable.GetClassId(classDecl.BaseClasses[n]);
                        if (baseClass == globalClassIndex)
                        {
                            string message = string.Format("Class '{0}' cannot derive from itself (DED0A61F).\n", classDecl.ClassName);
                            buildStatus.LogSemanticError(message, core.CurrentDSFileName, classDecl.line, classDecl.col);
                            throw new BuildHaltException(message);
                        }

                        if (ProtoCore.DSASM.Constants.kInvalidIndex != baseClass)
                        {
                            if (core.ClassTable.ClassNodes[baseClass].IsImportedClass && !thisClass.IsImportedClass)
                            {
                                string message = string.Format("Cannot derive from FFI class {0} (DA87AC4D).\n",
                                    core.ClassTable.ClassNodes[baseClass].Name);

                                buildStatus.LogSemanticError(message, core.CurrentDSFileName, classDecl.line, classDecl.col);
                                throw new BuildHaltException(message);
                            }

                            thisClass.Bases.Add(baseClass);
                            thisClass.CoerceTypes.Add(baseClass, (int)ProtoCore.DSASM.ProcedureDistance.kCoerceBaseClass);
                        }
                        else
                        {
                            string message = string.Format("Unknown base class '{0}' (9E44FFB3).\n", classDecl.BaseClasses[n]);
                            buildStatus.LogSemanticError(message, core.CurrentDSFileName, classDecl.line, classDecl.col);
                            throw new BuildHaltException(message);
                        }
                    }
                }
            }
            else if (ProtoCore.CompilerDefinitions.Associative.CompilePass.kClassHierarchy == compilePass)
            {
                // Class hierarchy pass
                // Populating each class entry with all sub classes in the hierarchy
                globalClassIndex = core.ClassTable.GetClassId(classDecl.ClassName);

                ProtoCore.DSASM.ClassNode thisClass = core.ClassTable.ClassNodes[globalClassIndex];

                // Verify and store the list of classes it inherits from 
                if (null != classDecl.BaseClasses)
                {
                    for (int n = 0; n < classDecl.BaseClasses.Count; ++n)
                    {
                        int baseClass = core.ClassTable.GetClassId(classDecl.BaseClasses[n]);

                        // baseClass is already resovled in the previous pass
                        Validity.Assert(ProtoCore.DSASM.Constants.kInvalidIndex != baseClass);

                            
                        // Iterate through all the base classes until the the root class
                        // For every base class, add the coercion score
                        ProtoCore.DSASM.ClassNode tmpCNode = core.ClassTable.ClassNodes[baseClass];
                        if (tmpCNode.Bases.Count > 0)
                        {
                            baseClass = tmpCNode.Bases[0];
                            while (ProtoCore.DSASM.Constants.kInvalidIndex != baseClass)
                            {
                                thisClass.CoerceTypes.Add(baseClass, (int)ProtoCore.DSASM.ProcedureDistance.kCoerceBaseClass);
                                tmpCNode = core.ClassTable.ClassNodes[baseClass];

                                baseClass = ProtoCore.DSASM.Constants.kInvalidIndex;
                                if (tmpCNode.Bases.Count > 0)
                                {
                                    baseClass = tmpCNode.Bases[0];
                                }
                            }
                        }
                    }
                }
            }
            else if (ProtoCore.CompilerDefinitions.Associative.CompilePass.kClassMemVar == compilePass)
            {
                EmitMemberVariables(classDecl, graphNode);
            }
            else if (ProtoCore.CompilerDefinitions.Associative.CompilePass.kClassMemFuncSig == compilePass)
            {
                // Class member variable pass
                // Populating each class entry vtables with their respective
                // member variables signatures
                globalClassIndex = core.ClassTable.GetClassId(classDecl.ClassName);

                List<AssociativeNode> thisPtrOverloadList = new List<AssociativeNode>();
                foreach (AssociativeNode funcdecl in classDecl.Procedures)
                {
                    DfsTraverse(funcdecl, ref inferedType);

                    var funcDef = funcdecl as FunctionDefinitionNode;
                    if (funcDef == null || funcDef.IsStatic || funcDef.Name == ProtoCore.DSDefinitions.Keyword.Dispose)
                        continue;

                    bool isGetterSetter = CoreUtils.IsGetterSetter(funcDef.Name);

                    var thisPtrArgName = Constants.kThisPointerArgName;
                    if (!isGetterSetter)
                    {
                        var classsShortName = classDecl.ClassName.Split('.').Last();
                        var typeDepName = classsShortName.ToLower();
                        if (typeDepName != classsShortName && funcDef.Signature.Arguments.All(a => a.NameNode.Name != typeDepName))
                            thisPtrArgName = typeDepName;
                    }

                    // This is a function, create its parameterized this pointer overload
                    ThisPointerProcOverload thisProc = new ThisPointerProcOverload();
                    thisProc.classIndex = globalClassIndex;
                    thisProc.procNode = new FunctionDefinitionNode(funcDef);
                    var thisPtrArg = new VarDeclNode()
                    {
                        Access = ProtoCore.CompilerDefinitions.AccessModifier.kPublic,
                        NameNode = AstFactory.BuildIdentifier(thisPtrArgName),
                        ArgumentType = new ProtoCore.Type { Name = classDecl.ClassName, UID = globalClassIndex, rank = 0 }
                    };
                    thisProc.procNode.Signature.Arguments.Insert(0, thisPtrArg);
                    thisProc.procNode.IsAutoGeneratedThisProc = true;

                    if (CoreUtils.IsGetterSetter(funcDef.Name))
                    {
                        InsertThisPointerAtBody(thisProc);
                    }
                    else
                    {
                        // Generate a static function for member function f():
                        //     satic def f(a: A)
                        //     { 
                        //        return = a.f()
                        //     }
                        thisProc.procNode.IsStatic = true;
                        BuildThisFunctionBody(thisProc);
                    }

                    thisPtrOverloadList.Add(thisProc.procNode);
                }

                foreach (var overloadFunc in thisPtrOverloadList)
                {
                    // Emit the newly defined overloads
                    DfsTraverse(overloadFunc, ref inferedType);
                }

                classDecl.Procedures.AddRange(thisPtrOverloadList);

                if (!classDecl.IsExternLib)
                {
                    ProtoCore.DSASM.ProcedureTable vtable = core.ClassTable.ClassNodes[globalClassIndex].ProcTable;
                    if (vtable.GetFunctionBySignature(classDecl.ClassName, new List<ProtoCore.Type>()) == null)
                    {
                        ConstructorDefinitionNode defaultConstructor = new ConstructorDefinitionNode();
                        defaultConstructor.Name = classDecl.ClassName;
                        defaultConstructor.LocalVariableCount = 0;
                        defaultConstructor.Signature = new ArgumentSignatureNode();
                        defaultConstructor.ReturnType = new ProtoCore.Type { Name = "var", UID = 0 };
                        defaultConstructor.FunctionBody = new CodeBlockNode();
                        defaultConstructor.BaseConstructor = null;
                        defaultConstructor.Access = ProtoCore.CompilerDefinitions.AccessModifier.kPublic;
                        defaultConstructor.IsExternLib = false;
                        defaultConstructor.ExternLibName = null;
                        DfsTraverse(defaultConstructor, ref inferedType);
                        classDecl.Procedures.Add(defaultConstructor);
                    }
                }
            }
            else if (ProtoCore.CompilerDefinitions.Associative.CompilePass.kGlobalScope == compilePass)
            {
                // before populate the attributes, we must know the attribute class constructor signatures
                // in order to check the parameter 
                // populate the attributes for the class and class member variable 
                globalClassIndex = core.ClassTable.GetClassId(classDecl.ClassName);
                if (globalClassIndex != ProtoCore.DSASM.Constants.kInvalidIndex)
                {
                    ProtoCore.DSASM.ClassNode thisClass = core.ClassTable.ClassNodes[globalClassIndex];
                    // class
                    if (classDecl.Attributes != null)
                    {
                        thisClass.Attributes = PopulateAttributes(classDecl.Attributes);
                    }

                    // member variable
                    int ix = -1;
                    int currentClassScope = -1;
                    foreach (ProtoCore.DSASM.SymbolNode sn in thisClass.Symbols.symbolList.Values)
                    {
                        // only populate the attributes for member variabls
                        if (sn.functionIndex != ProtoCore.DSASM.Constants.kInvalidIndex)
                            continue;
                        if (sn.classScope != globalClassIndex)
                        {
                            if (currentClassScope != sn.classScope)
                            {
                                currentClassScope = sn.classScope;
                                ix = 0;
                            }
                            // copy attribute information from base class
                            sn.Attributes = core.ClassTable.ClassNodes[currentClassScope].Symbols.symbolList[ix++].Attributes;
                        }
                        else
                        {
                            if (currentClassScope != globalClassIndex)
                            {
                                currentClassScope = globalClassIndex;
                                ix = 0;
                            }
                        }
                    }
                }
            }
            else if (ProtoCore.CompilerDefinitions.Associative.CompilePass.kClassMemFuncBody == compilePass)
            {
                // Class member variable pass
                // Populating the function body of each member function defined in the class vtables

                globalClassIndex = core.ClassTable.GetClassId(classDecl.ClassName);

                // Initialize the global function table for this class
                // 'classIndexAtCallsite' is the class index as it is stored at the callsite function tables
                int classIndexAtCallsite = globalClassIndex + 1;
                core.FunctionTable.InitGlobalFunctionEntry(classIndexAtCallsite);

                foreach (AssociativeNode funcdecl in classDecl.Procedures)
                {
                    // reset the inferedtype between functions
                    inferedType = new ProtoCore.Type();
                    DfsTraverse(funcdecl, ref inferedType, false, null, subPass);
                }
            }

            // Reset the class index
            core.ClassIndex = globalClassIndex = ProtoCore.DSASM.Constants.kGlobalScope;
        }
예제 #43
0
        private void InferTypes()
        {
            int size = astNodes.Count;
            for (int n = 0; n < size; ++n)
            {
                if (astNodes[n] is BinaryExpressionNode)
                {
                    ProtoCore.Type type = new ProtoCore.Type();
                    type.UID = (int)ProtoCore.PrimitiveType.kTypeVoid;
                    type.IsIndexable = false;

                    BinaryExpressionNode b = astNodes[n] as BinaryExpressionNode;
                    InferDFSTraverse(b.RightNode, ref type);

                    // Do we even need to update lhs?
                    Debug.Assert(b.LeftNode is IdentifierNode);
                    IdentifierNode t = b.LeftNode as IdentifierNode;

                    codeBlock.symbolTable.SetDataType(t.Name, globalProcIndex, type);
                }
            }
        }
예제 #44
0
        private void EmitIfStatementNode(AssociativeNode node, ref ProtoCore.Type inferedType, ProtoCore.AssociativeGraph.GraphNode graphNode = null)
        {
            int bp = (int)ProtoCore.DSASM.Constants.kInvalidIndex;
            int L1 = (int)ProtoCore.DSASM.Constants.kInvalidIndex;

            // If-expr
            IfStatementNode ifnode = node as IfStatementNode;
            DfsTraverse(ifnode.ifExprNode, ref inferedType, false, graphNode);
            L1 = ProtoCore.DSASM.Constants.kInvalidIndex;
            bp = pc;
            EmitCJmp(L1);


            // Create a new codeblock for this block
            // Set the current codeblock as the parent of the new codeblock
            // Set the new codeblock as a new child of the current codeblock
            // Set the new codeblock as the current codeblock
            ProtoCore.DSASM.CodeBlock localCodeBlock = new ProtoCore.DSASM.CodeBlock(
                context.guid,
                ProtoCore.DSASM.CodeBlockType.kConstruct,
                Language.NotSpecified,
                core.CodeBlockIndex++,
                new ProtoCore.DSASM.SymbolTable(GetConstructBlockName("if"), core.RuntimeTableIndex++),
                null,
                false,
                core);


            localCodeBlock.instrStream = codeBlock.instrStream;
            localCodeBlock.parent = codeBlock;
            codeBlock.children.Add(localCodeBlock);
            codeBlock = localCodeBlock;

            // If-body
            foreach (AssociativeNode ifBody in ifnode.IfBody)
            {
                inferedType = new ProtoCore.Type();
                inferedType.UID = (int)PrimitiveType.kTypeVar;
                DfsTraverse(ifBody, ref inferedType, false, graphNode);
            }

            // Restore - Set the local codeblock parent to be the current codeblock
            codeBlock = localCodeBlock.parent;


            L1 = ProtoCore.DSASM.Constants.kInvalidIndex;

            BackpatchTable backpatchTable = new BackpatchTable();
            backpatchTable.Append(pc, L1);
            EmitJmp(L1);

            // Backpatch the L2 destination of the if block
            Backpatch(bp, pc);


            /*		
            else if(E)	->	traverse E
                            L1 = pc + 1
                            L2 = null 
                            bp = pc
                            emit(jmp, _cx, L1, L2) 
            {				
                S		->	traverse S
                            L1 = null
                            bpTable.append(pc)
                            emit(jmp,labelEnd) 
                            backpatch(bp,pc)
            }
             * */

            // Elseif-expr


            /*
            else 			
            {				
                S		->	traverse S
                            L1 = null
                            bpTable.append(pc)
                            emit(jmp,labelEnd) 
                            backpatch(bp,pc)
            }		
             * */
            // Else-body     

            Validity.Assert(null != ifnode.ElseBody);
            if (0 != ifnode.ElseBody.Count)
            {
                // Create a new symboltable for this block
                // Set the current table as the parent of the new table
                // Set the new table as a new child of the current table
                // Set the new table as the current table
                // Create a new codeblock for this block
                // Set the current codeblock as the parent of the new codeblock
                // Set the new codeblock as a new child of the current codeblock
                // Set the new codeblock as the current codeblock
                localCodeBlock = new ProtoCore.DSASM.CodeBlock(
                    context.guid,
                    ProtoCore.DSASM.CodeBlockType.kConstruct,
                    Language.NotSpecified,
                    core.CodeBlockIndex++,
                    new ProtoCore.DSASM.SymbolTable(GetConstructBlockName("else"), core.RuntimeTableIndex++),
                    null,
                    false,
                    core);

                localCodeBlock.instrStream = codeBlock.instrStream;
                localCodeBlock.parent = codeBlock;
                codeBlock.children.Add(localCodeBlock);
                codeBlock = localCodeBlock;
                foreach (AssociativeNode elseBody in ifnode.ElseBody)
                {
                    inferedType = new ProtoCore.Type();
                    inferedType.UID = (int)PrimitiveType.kTypeVar;
                    DfsTraverse(elseBody, ref inferedType, false, graphNode);
                }

                // Restore - Set the local codeblock parent to be the current codeblock
                codeBlock = localCodeBlock.parent;

                L1 = ProtoCore.DSASM.Constants.kInvalidIndex;
                backpatchTable.Append(pc, L1);
                EmitJmp(L1);
            }

            /*
             * 
                      ->	backpatch(bpTable, pc) 
             */
            // ifstmt-exit
            // Backpatch all the previous unconditional jumps
            Backpatch(backpatchTable.backpatchList, pc);
        }
예제 #45
0
        /*
            1 Copy user-defined function definitions (excluding constructors) into a temp

            2 Modify its signature to include an additional this pointer as the first argument.
              The 'this' argument should take the type of the current class being traversed and be the first argument in the function.
              The function name must be name mangled in order to stay unique

            3 Append this temp to the current vtable
        */
        private void InsertThisPointerArg(ThisPointerProcOverload procOverload)
        {
            // Modify its signature to include an additional this pointer as the first argument.
            // The 'this' argument should take the type of the current class being traversed and be the first argument in the function.
            // The function name must be name mangled in order to stay unique

            ProtoCore.AST.AssociativeAST.FunctionDefinitionNode procNode = procOverload.procNode;

            string className = compileStateTracker.ClassTable.ClassNodes[procOverload.classIndex].name;
            string thisPtrArgName = ProtoCore.DSASM.Constants.kThisPointerArgName;

            ProtoCore.AST.AssociativeAST.IdentifierNode ident = new ProtoCore.AST.AssociativeAST.IdentifierNode();
            ident.Name = ident.Value = thisPtrArgName;

            VarDeclNode thisPtrArg = new ProtoCore.AST.AssociativeAST.VarDeclNode()
            {
                memregion = ProtoCore.DSASM.MemoryRegion.kMemStack,
                access = ProtoCore.DSASM.AccessSpecifier.kPublic,
                NameNode = ident,
                ArgumentType = new ProtoCore.Type { Name = className, UID = procOverload.classIndex, IsIndexable = false, rank = 0 }
            };

            procNode.Singnature.Arguments.Insert(0, thisPtrArg);

            ProtoCore.Type type = new ProtoCore.Type();
        }
예제 #46
0
        private ProtoCore.AssociativeGraph.UpdateNodeRef GetUpdatedNodeRef(AssociativeNode node)
        {
            if (null == localProcedure)
            {
                return null;
            }

            // Get the lhs symbol list
            ProtoCore.Type type = new ProtoCore.Type();
            type.UID = globalClassIndex;
            ProtoCore.AssociativeGraph.UpdateNodeRef leftNodeRef = new ProtoCore.AssociativeGraph.UpdateNodeRef();
            DFSGetSymbolList(node, ref type, leftNodeRef);

     
            return leftNodeRef;
        }
예제 #47
0
        public override int Emit(ProtoCore.AST.Node codeBlockNode, ProtoCore.AssociativeGraph.GraphNode graphNode = null)
        {
            compileStateTracker.startPC = this.pc;
            if (compileStateTracker.ExecMode == ProtoCore.DSASM.InterpreterMode.kExpressionInterpreter)
            {
                return EmitExpressionInterpreter(codeBlockNode);
            }

            this.localCodeBlockNode = codeBlockNode;
            ProtoCore.AST.ImperativeAST.CodeBlockNode codeblock = codeBlockNode as ProtoCore.AST.ImperativeAST.CodeBlockNode;
            bool isTopBlock = null == codeBlock.parent;
            if (!isTopBlock)
            {
                // If this is an inner block where there can be no classes, we can start at parsing at the global function state
                compilePass = ProtoCore.DSASM.ImperativeCompilePass.kGlobalFuncSig;
            }

            bool hasReturnStatement = false;
            ProtoCore.Type type = new ProtoCore.Type();
            while (ProtoCore.DSASM.ImperativeCompilePass.kDone != compilePass)
            {
                foreach (ImperativeNode node in codeblock.Body)
                {
                    type = new ProtoCore.Type();
                    type.UID = (int)PrimitiveType.kTypeVar;
                    type.IsIndexable = false;

                    if (node is LanguageBlockNode)
                    {
                        // Build a binary node with a temporary lhs for every stand-alone language block
                        var iNode = nodeBuilder.BuildIdentfier(compileStateTracker.GenerateTempLangageVar());
                        var langBlockNode = nodeBuilder.BuildBinaryExpression(iNode, node);
                        DfsTraverse(langBlockNode, ref type, false, graphNode);
                    }
                    else
                    {
                        DfsTraverse(node, ref type, false, graphNode);
                    }

                    if (ProtoCore.Utils.NodeUtils.IsReturnExpressionNode(node))
                        hasReturnStatement = true;
                }
                if (compilePass == ProtoCore.DSASM.ImperativeCompilePass.kGlobalScope && !hasReturnStatement)
                {
                    EmitReturnNull();
                }

                compilePass++;
            }

            compileStateTracker.InferedType = type;

            if (compileStateTracker.AsmOutput != Console.Out)
            {
                compileStateTracker.AsmOutput.Flush();
            }

            this.localCodeBlockNode = null;
            return codeBlock.codeBlockId;
        }
예제 #48
0
 private void InferDFSTraverse(AssociativeNode node, ref ProtoCore.Type inferedType)
 {
     if (node is IdentifierNode)
     {
         IdentifierNode t = node as IdentifierNode;
         if (core.TypeSystem.IsHigherRank(t.datatype.UID, inferedType.UID))
         {
             ProtoCore.Type type = new ProtoCore.Type();
             type.UID = t.datatype.UID;
             inferedType = type;
         }
     }
     else if (node is BinaryExpressionNode)
     {
         BinaryExpressionNode b = node as BinaryExpressionNode;
         InferDFSTraverse(b.LeftNode, ref inferedType);
         InferDFSTraverse(b.RightNode, ref inferedType);
     }
 }
예제 #49
0
 private ArrayElementType(ProtoCore.Type type, int depth)
 {
     this.elementDepth = depth;
     this.elementType  = type;
 }