Exemplo n.º 1
0
        public void LogWarning(Runtime.WarningID ID, string message, string filename, int line, int col)
        {
            filename = filename ?? string.Empty;

            if (!runtimeCore.Options.IsDeltaExecution && (string.IsNullOrEmpty(filename) ||
                                                          line == Constants.kInvalidIndex ||
                                                          col == Constants.kInvalidIndex))
            {
                AuditCodeLocation(ref filename, ref line, ref col);
            }

            var warningMsg = string.Format(Resources.kConsoleWarningMessage,
                                           message, filename, line, col);

            if (runtimeCore.Options.Verbose)
            {
                System.Console.WriteLine(warningMsg);
            }

            if (WebMessageHandler != null)
            {
                var outputMessage = new OutputMessage(warningMsg);
                WebMessageHandler.Write(outputMessage);
            }

            if (MessageHandler != null)
            {
                var outputMessage = new OutputMessage(OutputMessage.MessageType.Warning,
                                                      message.Trim(), filename, line, col);
                MessageHandler.Write(outputMessage);
            }

            AssociativeGraph.GraphNode executingGraphNode = null;
            var executive = runtimeCore.CurrentExecutive.CurrentDSASMExec;

            if (executive != null)
            {
                executingGraphNode = executive.Properties.executingGraphNode;
                // In delta execution mode, it means the warning is from some
                // internal graph node.
                if (executingGraphNode != null && executingGraphNode.guid.Equals(System.Guid.Empty))
                {
                    executingGraphNode = runtimeCore.DSExecutable.RuntimeData.ExecutingGraphnode;
                }
            }

            var entry = new Runtime.WarningEntry
            {
                ID            = ID,
                Message       = message,
                Column        = col,
                Line          = line,
                ExpressionID  = runtimeCore.RuntimeExpressionUID,
                GraphNodeGuid = executingGraphNode == null ? Guid.Empty : executingGraphNode.guid,
                AstID         = executingGraphNode == null ? Constants.kInvalidIndex : executingGraphNode.OriginalAstID,
                Filename      = filename
            };

            warnings.Add(entry);
        }
Exemplo n.º 2
0
 /// <summary>
 /// Set the value of a variable at runtime
 /// Returns the entry pc
 /// </summary>
 /// <param name="astID"></param>
 /// <param name="sv"></param>
 /// <returns></returns>
 public int SetValue(List <AssociativeNode> modifiedNodes, StackValue sv)
 {
     ExecutionInstance.CurrentDSASMExec.SetAssociativeUpdateRegister(sv);
     AssociativeGraph.GraphNode gnode = ProtoCore.AssociativeEngine.Utils.MarkGraphNodesDirtyAtGlobalScope
                                            (this, modifiedNodes);
     Validity.Assert(gnode != null);
     return(gnode.updateBlock.startpc);
 }
Exemplo n.º 3
0
        /// <summary>
        /// Retrieves an existing instance of a callsite associated with a UID
        /// It creates a new callsite if non was found
        /// </summary>
        /// <param name="core"></param>
        /// <param name="uid"></param>
        /// <returns></returns>
        public CallSite GetCallSite(GraphNode graphNode,
                                    int classScope,
                                    string methodName,
                                    Executable executable,
                                    int runningBlock,
                                    Options options,
                                    RuntimeStatus runtimeStatus
             )
        {
            Validity.Assert(null != executable.FunctionTable);
            CallSite csInstance = null;

            // TODO Jun: Currently generates a new callsite for imperative and 
            // internally generated functions.
            // Fix the issues that cause the cache to go out of sync when 
            // attempting to cache internal functions. This may require a 
            // secondary callsite cache for internal functions so they dont 
            // clash with the graphNode UID key
            var language = executable.instrStreamList[runningBlock].language;
            bool isImperative = language == Language.kImperative;
            bool isInternalFunction = CoreUtils.IsInternalFunction(methodName);

            if (isInternalFunction || isImperative)
            {
                csInstance = new CallSite(classScope,
                                          methodName,
                                          executable.FunctionTable,
                                          options.ExecutionMode);
            }
            else if (!CallsiteCache.TryGetValue(graphNode.CallsiteIdentifier, out csInstance))
            {
                // Attempt to retrieve a preloaded callsite data (optional).
                var traceData = GetAndRemoveTraceDataForNode(graphNode.guid);

                csInstance = new CallSite(classScope,
                                          methodName,
                                          executable.FunctionTable,
                                          options.ExecutionMode,
                                          traceData);

                CallsiteCache[graphNode.CallsiteIdentifier] = csInstance;
                CallSiteToNodeMap[csInstance.CallSiteID] = graphNode.guid;
                ASTToCallSiteMap[graphNode.AstID] = csInstance;

            }

            if (graphNode != null && !CoreUtils.IsDisposeMethod(methodName))
            {
                csInstance.UpdateCallSite(classScope, methodName);
                if (options.IsDeltaExecution)
                {
                    runtimeStatus.ClearWarningForExpression(graphNode.exprUID);
                }
            }

            return csInstance;
        }
Exemplo n.º 4
0
 /// <summary>
 /// Logs the unbound variable warning and sets the unbound symbol
 /// </summary>
 /// <param name="unboundSymbol"></param>
 /// <param name="message"></param>
 /// <param name="fileName"></param>
 /// <param name="line"></param>
 /// <param name="col"></param>
 /// <param name="graphNode"></param>
 public void LogUnboundVariableWarning(
     SymbolNode unboundSymbol,
     string message,
     string fileName = null,
     int line        = -1,
     int col         = -1,
     AssociativeGraph.GraphNode graphNode = null)
 {
     LogWarning(BuildData.WarningID.IdUnboundIdentifier, message, core.CurrentDSFileName, line, col, graphNode, unboundSymbol);
 }
Exemplo n.º 5
0
        public void LogWarning(BuildData.WarningID warningID,
                               string message,
                               string fileName = null,
                               int line        = -1,
                               int col         = -1,
                               AssociativeGraph.GraphNode graphNode = null,
                               SymbolNode associatedSymbol          = null)
        {
            var entry = new BuildData.WarningEntry
            {
                ID                        = warningID,
                Message                   = message,
                Line                      = line,
                Column                    = col,
                GraphNodeGuid             = graphNode == null ? default(Guid) : graphNode.guid,
                AstID                     = graphNode == null? DSASM.Constants.kInvalidIndex : graphNode.OriginalAstID,
                FileName                  = fileName,
                UnboundVariableSymbolNode = associatedSymbol
            };

            warnings.Add(entry);

            if (core.Options.IsDeltaExecution)
            {
            }

            if (LogWarnings)
            {
                System.Console.WriteLine("{0}({1},{2}) Warning:{3}", fileName, line, col, message);

                OutputMessage outputmessage = new OutputMessage(OutputMessage.MessageType.Warning, message.Trim(), fileName, line, col);
                if (MessageHandler != null)
                {
                    MessageHandler.Write(outputmessage);
                    if (WebMsgHandler != null)
                    {
                        OutputMessage webOutputMsg = new OutputMessage(OutputMessage.MessageType.Warning, message.Trim(), "", line, col);
                        WebMsgHandler.Write(webOutputMsg);
                    }
                    if (!outputmessage.Continue)
                    {
                        throw new BuildHaltException(message);
                    }
                }
            }
        }
 public FFIPropertyChangedEventArgs(string propertyName, GraphNode graphNode):
     base(propertyName)
 {
     hostGraphNode = graphNode;
 }
Exemplo n.º 7
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;
        }
Exemplo n.º 8
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;
        }
Exemplo n.º 9
0
        private void EmitRangeExprNode(AssociativeNode node, 
                                       ref ProtoCore.Type inferedType, 
                                       GraphNode graphNode = null,
                                       ProtoCore.CompilerDefinitions.Associative.SubCompilePass subPass = ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kNone)
        {
            RangeExprNode range = node as RangeExprNode;

            // Do some static checking...
            var fromNode = range.From;
            var toNode = range.To;
            var stepNode = range.Step;
            var stepOp = range.StepOperator;
            var hasAmountOperator = range.HasRangeAmountOperator;

            bool isStepValid = true;
            string warningMsg = string.Empty;

            if ((fromNode is IntNode || fromNode is DoubleNode) &&
                (toNode is IntNode || toNode is DoubleNode) &&
                (stepNode == null || stepNode is IntNode || stepNode is DoubleNode))
            {
                double current = (fromNode is IntNode) ?
                    (fromNode as IntNode).Value : (fromNode as DoubleNode).Value;
                double end = (toNode is IntNode) ?
                    (toNode as IntNode).Value : (toNode as DoubleNode).Value;

                double step = 1;
                if (stepNode != null)
                {
                    step = (stepNode is IntNode) ?
                        (stepNode as IntNode).Value : (stepNode as DoubleNode).Value;
                }

                switch (stepOp)
                {
                    case ProtoCore.DSASM.RangeStepOperator.StepSize:

                        if (!hasAmountOperator)
                        {
                            if (stepNode == null && end < current)
                            {
                                step = -1;
                            }

                            if (step == 0)
                            {
                                isStepValid = false;
                                warningMsg = ProtoCore.Properties.Resources.kRangeExpressionWithStepSizeZero;
                            }
                            else if ((end > current && step < 0) || (end < current && step > 0))
                            {
                                isStepValid = false;
                                warningMsg = ProtoCore.Properties.Resources.kRangeExpressionWithInvalidStepSize;
                            }
                        }

                       break;

                    case ProtoCore.DSASM.RangeStepOperator.Number:

                       if (hasAmountOperator)
                       {
                           isStepValid = false;
                           warningMsg = ProtoCore.Properties.Resources.kRangeExpressionWithStepSizeZero;
                       }
                       else
                       {
                           if (stepNode != null && stepNode is DoubleNode &&
                               subPass == ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kNone)
                           {
                               buildStatus.LogWarning(WarningID.kInvalidRangeExpression,
                                                      ProtoCore.Properties.Resources.kRangeExpressionWithNonIntegerStepNumber,
                                                      core.CurrentDSFileName,
                                                      stepNode.line,
                                                      stepNode.col, 
                                                      graphNode);
                           }
                           else if (step <= 0)
                           {
                               isStepValid = false;
                               warningMsg = ProtoCore.Properties.Resources.kRangeExpressionWithNegativeStepNumber;
                           }
                       }

                       break;

                    case ProtoCore.DSASM.RangeStepOperator.ApproximateSize:
                        if (hasAmountOperator)
                        {
                            isStepValid = false;
                            warningMsg = ProtoCore.Properties.Resources.kRangeExpressionConflictOperator;
                        }
                        else if (step == 0)
                        {
                            isStepValid = false;
                            warningMsg = ProtoCore.Properties.Resources.kRangeExpressionWithStepSizeZero;
                        }
                        break;

                    default:
                        break;
                }
            }

            if (!isStepValid && subPass == ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kNone)
            {
                buildStatus.LogWarning(WarningID.kInvalidRangeExpression,
                                       warningMsg,
                                       core.CurrentDSFileName,
                                       stepNode.line,
                                       stepNode.col, 
                                       graphNode);

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

            // Replace with build-in RangeExpression() function. - Yu Ke
            bool emitReplicationgGuideState = emitReplicationGuide;
            emitReplicationGuide = false;

            IntNode op = null;
            switch (stepOp)
            {
                case RangeStepOperator.StepSize:
                    op = new IntNode(0);
                    break;
                case RangeStepOperator.Number:
                    op = new IntNode(1);
                    break;
                case RangeStepOperator.ApproximateSize:
                    op = new IntNode(2);
                    break;
                default:
                    op = new IntNode(-1);
                    break;
            }
            var arguments = new List<AssociativeNode> 
            {
                fromNode, 
                toNode, 
                stepNode ?? new NullNode(), 
                op, 
                AstFactory.BuildBooleanNode(stepNode != null),
                AstFactory.BuildBooleanNode(hasAmountOperator),
            };
            var rangeExprFunc = AstFactory.BuildFunctionCall(Constants.kFunctionRangeExpression, 
                                                             arguments);

            EmitFunctionCallNode(rangeExprFunc, ref inferedType, false, graphNode, subPass);

            emitReplicationGuide = emitReplicationgGuideState;

            if (subPass != ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kUnboundIdentifier)
            {
                if (range.ArrayDimensions != null)
                {
                    int dim = DfsEmitArrayIndexHeap(range.ArrayDimensions, graphNode);
                    EmitInstrConsole(kw.pushindex, dim + "[dim]");
                    EmitPushArrayIndex(dim);
                }

                if (emitReplicationGuide)
                {
                    EmitAtLevel(range.AtLevel);
                    EmitReplicationGuides(range.ReplicationGuides);
                }
            }
        }
Exemplo n.º 10
0
        private void EmitIdentifierNode(AssociativeNode node, ref ProtoCore.Type inferedType, bool isBooleanOp = false, ProtoCore.AssociativeGraph.GraphNode graphNode = null, ProtoCore.CompilerDefinitions.Associative.SubCompilePass subPass = ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kNone, BinaryExpressionNode parentNode = null)
        {
            IdentifierNode t = node as IdentifierNode;
            if (t.Name.Equals(ProtoCore.DSDefinitions.Keyword.This))
            {
                if (subPass != ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kNone)
                {
                    return;
                }

                if (localProcedure != null)
                {
                    if (localProcedure.IsStatic)
                    {
                        string message = ProtoCore.Properties.Resources.kUsingThisInStaticFunction;
                        core.BuildStatus.LogWarning(ProtoCore.BuildData.WarningID.kInvalidThis, message, core.CurrentDSFileName, t.line, t.col, graphNode);
                        EmitPushNull();
                        return;
                    }
                    else if (localProcedure.ClassID == Constants.kGlobalScope)
                    {
                        string message = ProtoCore.Properties.Resources.kInvalidThis;
                        core.BuildStatus.LogWarning(ProtoCore.BuildData.WarningID.kInvalidThis, message, core.CurrentDSFileName, t.line, t.col, graphNode);
                        EmitPushNull();
                        return;
                    }
                    else
                    {
                        EmitThisPointerNode(subPass);
                        return;
                    }
                }
                else
                {
                    string message = ProtoCore.Properties.Resources.kInvalidThis;
                    core.BuildStatus.LogWarning(ProtoCore.BuildData.WarningID.kInvalidThis, message, core.CurrentDSFileName, t.line, t.col, graphNode);
                    EmitPushNull();
                    return;
                }
            }

            int dimensions = 0;

            ProtoCore.DSASM.SymbolNode symbolnode = null;
            int runtimeIndex = codeBlock.symbolTable.RuntimeIndex;

            ProtoCore.Type type = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, 0);

            bool isAccessible = false;
            bool isAllocated = VerifyAllocation(t.Name, globalClassIndex, globalProcIndex, out symbolnode, out isAccessible);
            if (!isAllocated && null == t.ArrayDimensions)
            {
                //check if it is a function instance
                ProtoCore.DSASM.ProcedureNode procNode = null;
                procNode = CoreUtils.GetFunctionByName(t.Name, codeBlock);
                if (null != procNode)
                {
                    if (ProtoCore.DSASM.Constants.kInvalidIndex != procNode.ID)
                    {
                        // A global function
                        inferedType = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeFunctionPointer, 0);
                        if (ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kUnboundIdentifier != subPass)
                        {
                            int fptr = core.FunctionPointerTable.functionPointerDictionary.Count;
                            var fptrNode = new FunctionPointerNode(procNode);
                            core.FunctionPointerTable.functionPointerDictionary.TryAdd(fptr, fptrNode);
                            core.FunctionPointerTable.functionPointerDictionary.TryGetBySecond(fptrNode, out fptr);

                            EmitPushVarData(0);

                            EmitInstrConsole(ProtoCore.DSASM.kw.push, t.Name);
                            StackValue opFunctionPointer = StackValue.BuildFunctionPointer(fptr);
                            EmitPush(opFunctionPointer, runtimeIndex, t.line, t.col);
                        }
                        return;
                    }
         
                }
            }            

            if (ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kUnboundIdentifier == subPass)
            {
                if (symbolnode == null)
                {
                    // The variable is unbound
                    ProtoCore.DSASM.SymbolNode unboundVariable = null;
                    if (ProtoCore.DSASM.InterpreterMode.kExpressionInterpreter != core.Options.RunMode)
                    {
                        inferedType.UID = (int)ProtoCore.PrimitiveType.kTypeNull;

                        // Jun Comment: Specification 
                        //      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)

                        // Set the first symbol that triggers the cycle to null
                        ProtoCore.AssociativeGraph.GraphNode nullAssignGraphNode = new ProtoCore.AssociativeGraph.GraphNode();
                        nullAssignGraphNode.updateBlock.startpc = pc;


                        EmitPushNull();

                        // Push the identifier local block  
                        dimensions = 0;
                        EmitPushVarData(dimensions);
                        ProtoCore.Type varType = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, 0);

                        // TODO Jun: Refactor Allocate() to just return the symbol node itself
                        unboundVariable = Allocate(globalClassIndex, globalClassIndex, globalProcIndex, t.Value, varType, ProtoCore.DSASM.Constants.kPrimitiveSize,
                            false, ProtoCore.CompilerDefinitions.AccessModifier.kPublic, ProtoCore.DSASM.MemoryRegion.kMemStack, t.line, t.col, graphNode);
                        Validity.Assert(unboundVariable != null);

                        int symbolindex = unboundVariable.symbolTableIndex;
                        if (ProtoCore.DSASM.Constants.kInvalidIndex != globalClassIndex)
                        {
                            symbolnode = core.ClassTable.ClassNodes[globalClassIndex].Symbols.symbolList[symbolindex];
                        }
                        else
                        {
                            symbolnode = codeBlock.symbolTable.symbolList[symbolindex];
                        }

                        EmitInstrConsole(ProtoCore.DSASM.kw.pop, t.Value);
                        EmitPopForSymbol(unboundVariable, runtimeIndex);


                        nullAssignGraphNode.PushSymbolReference(symbolnode);
                        nullAssignGraphNode.procIndex = globalProcIndex;
                        nullAssignGraphNode.classIndex = globalClassIndex;
                        nullAssignGraphNode.updateBlock.endpc = pc - 1;

                        PushGraphNode(nullAssignGraphNode);
                        EmitDependency(ProtoCore.DSASM.Constants.kInvalidIndex, ProtoCore.DSASM.Constants.kInvalidIndex, false);
                    }

                    if (isAllocated)
                    {
                        string message = String.Format(ProtoCore.Properties.Resources.kPropertyIsInaccessible, t.Value);
                        if (localProcedure != null && localProcedure.IsStatic)
                        {
                            SymbolNode tempSymbolNode;

                            VerifyAllocation(
                                t.Name,
                                globalClassIndex,
                                Constants.kGlobalScope,
                                out tempSymbolNode,
                                out isAccessible);

                            if (tempSymbolNode != null && !tempSymbolNode.isStatic && isAccessible)
                            {
                                message = String.Format(ProtoCore.Properties.Resources.kUsingNonStaticMemberInStaticContext, t.Value);
                            }
                        }
                        buildStatus.LogWarning(
                            WarningID.kAccessViolation,
                            message,
                            core.CurrentDSFileName,
                            t.line,
                            t.col,
                            graphNode);
                    }
                    else
                    {
                        string message = String.Format(ProtoCore.Properties.Resources.kUnboundIdentifierMsg, t.Value);
                        buildStatus.LogUnboundVariableWarning(unboundVariable, message, core.CurrentDSFileName, t.line, t.col, graphNode);
                    }
                }

                if (null != t.ArrayDimensions)
                {
                    dimensions = DfsEmitArrayIndexHeap(t.ArrayDimensions, graphNode, parentNode, subPass);
                }
            }
            else
            {
                if (core.Options.RunMode == ProtoCore.DSASM.InterpreterMode.kExpressionInterpreter &&
                    !isAllocated)
                {
                    // It happens when the debugger try to watch a variable 
                    // which has been out of scope (as watch is done through
                    // execute an expression "t = v;" where v is the variable
                    // to be watched.
                    EmitPushNull();
                    return;
                }

                Validity.Assert(isAllocated);

                if (graphNode != null 
                    && IsAssociativeArrayIndexing 
                    && !CoreUtils.IsAutoGeneratedVar(symbolnode.name))
                {
                    UpdateNode updateNode = new UpdateNode();
                    updateNode.symbol = symbolnode;
                    updateNode.nodeType = UpdateNodeType.kSymbol;

                    if (graphNode.isIndexingLHS)
                    {
                        graphNode.dimensionNodeList.Add(updateNode);
                    }
                    else
                    {
                        int curDepIndex = graphNode.dependentList.Count - 1;
                        if (curDepIndex >= 0)
                        {
                            var curDep = graphNode.dependentList[curDepIndex].updateNodeRefList[0].nodeList[0];
                            curDep.dimensionNodeList.Add(updateNode);

                            if (core.Options.GenerateSSA)
                            {
                                if (null != firstSSAGraphNode)
                                {
                                    curDepIndex = firstSSAGraphNode.dependentList.Count - 1;
                                    if (curDepIndex >= 0)
                                    {
                                        ProtoCore.AssociativeGraph.UpdateNode firstSSAUpdateNode = firstSSAGraphNode.dependentList[curDepIndex].updateNodeRefList[0].nodeList[0];
                                        firstSSAUpdateNode.dimensionNodeList.Add(updateNode);
                                    }
                                }
                            }
                        }
                    }
                }

                // If it is a property, replaced it with getter: %get_prop()
                if (symbolnode.classScope != ProtoCore.DSASM.Constants.kInvalidIndex &&
                    symbolnode.functionIndex == ProtoCore.DSASM.Constants.kGlobalScope &&
                    localProcedure != null)
                {
                    string getterName = ProtoCore.DSASM.Constants.kGetterPrefix + t.Name;
                    if (!string.Equals(localProcedure.Name, getterName))
                    {
                        var thisNode =AstFactory.BuildIdentifier(ProtoCore.DSDefinitions.Keyword.This);
                        var identListNode = AstFactory.BuildIdentList(thisNode, t);
                        EmitIdentifierListNode(identListNode, ref inferedType, false, graphNode, ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kNone);

                        if (null != graphNode)
                        {
                            PushSymbolAsDependent(symbolnode, graphNode);
                        }

                        return;
                    }
                }

                type = symbolnode.datatype;
                runtimeIndex = symbolnode.runtimeTableIndex;

                // The graph node always depends on this identifier
                GraphNode dependendNode = null;
                if (null != graphNode)
                {
                    dependendNode = PushSymbolAsDependent(symbolnode, graphNode);
                }


                // Flags if the variable is allocated in the current scope
                bool isAllocatedWithinCurrentBlock = symbolnode.codeBlockId == codeBlock.codeBlockId;
                bool isValidDependent = dependendNode != null && !CoreUtils.IsSSATemp(symbolnode.name);
                if (!isAllocatedWithinCurrentBlock && isValidDependent)
                {
                    /*
                    a = 1;
                    i = [Associative]
                    {
                        // In an inner language block:
                        //  Add all rhs to the parent graphnode dependency list if the rhs was not allocated at the current scope
                        //  Only those not allocated are added to the parent.
                        //  This is because external nodes should not be able to update the local block if the affected variable is local to the block
                        //  Variable 'x' is local and the outer block statement x = 2 (where x is allocated globally), should not update this inner block
                        x = 10;
                        b = x + 1;
                        return = a + b + 10; 
                    }
                    x = 2;
                    a = 2;
                    */
                    context.DependentVariablesInScope.Add(dependendNode);
                }

                bool emitReplicationGuideFlag = emitReplicationGuide;
                emitReplicationGuide = false;
                if (null != t.ArrayDimensions)
                {
                    dimensions = DfsEmitArrayIndexHeap(t.ArrayDimensions, graphNode, parentNode, subPass);
                }
                emitReplicationGuide = emitReplicationGuideFlag;

                //fix type's rank   
                if (type.rank >= 0)
                {
                    type.rank -= dimensions;
                    if (type.rank < 0)
                    {
                        //throw new Exception("Exceed maximum rank!");
                        type.rank = 0;
                    }
                }

                EmitPushVarData(dimensions);

                if (ProtoCore.DSASM.InterpreterMode.kExpressionInterpreter == core.Options.RunMode)
                {
                    EmitInstrConsole(ProtoCore.DSASM.kw.pushw, t.Value);
                    EmitPushForSymbolW(symbolnode, runtimeIndex, t.line, t.col);
                }
                else
                {
                    EmitInstrConsole(ProtoCore.DSASM.kw.push, t.Value);
                    EmitPushForSymbol(symbolnode, runtimeIndex, t);

                    if (emitReplicationGuide)
                    {
                        EmitAtLevel(t.AtLevel);
                        EmitReplicationGuides(t.ReplicationGuides);
                    }
                }

                if (core.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 : inferedType.UID;
            }

        }
Exemplo n.º 11
0
        private GraphNode GetFinanlStatementOfSSA(GraphNode subNode, ref int index)
        {
            if (subNode.updateNodeRefList.Count <= 0)
            {
                return subNode;
            }

            Validity.Assert(null != subNode.updateNodeRefList[0].nodeList);
            Validity.Assert(subNode.updateNodeRefList[0].nodeList.Count > 0);
            if (subNode.updateNodeRefList[0].nodeList[0].nodeType != ProtoCore.AssociativeGraph.UpdateNodeType.kMethod)
            {
                bool isSSAStatement = ProtoCore.Utils.CoreUtils.IsSSATemp(subNode.updateNodeRefList[0].nodeList[0].symbol.name);
                if (isSSAStatement)
                {
                    if (null != subNode.lastGraphNode)
                    {
                        return subNode.lastGraphNode;
                    }
                }
            }
            return subNode;
        }
Exemplo n.º 12
0
        /// <summary>
        /// Pushes the symbol as a dependent to graphNode if codegeneration semantic conditions are met
        /// </summary>
        /// <param name="symbol"></param>
        /// <param name="graphNode"></param>
        private ProtoCore.AssociativeGraph.GraphNode PushSymbolAsDependent(SymbolNode symbol, ProtoCore.AssociativeGraph.GraphNode graphNode)
        {
            // Check for symbols that need to be pushed as dependents
            // Temporary properties and default args are autogenerated and are not part of the assocaitve behavior
            // For temp properties, refer to: EmitGettersForRHSIdentList
            // For default arg temp vars, refer to usage of: Constants.kTempDefaultArg
            if (CoreUtils.IsPropertyTemp(symbol.name) || CoreUtils.IsDefaultArgTemp(symbol.name))
            {
                return null;
            }

            ProtoCore.AssociativeGraph.GraphNode dependentNode = new ProtoCore.AssociativeGraph.GraphNode();
            dependentNode.PushSymbolReference(symbol, UpdateNodeType.kSymbol);
            graphNode.PushDependent(dependentNode);
            return dependentNode;
        }
Exemplo n.º 13
0
        private void EmitConstructorDefinitionNode(AssociativeNode node, ref ProtoCore.Type inferedType, ProtoCore.DSASM.AssociativeSubCompilePass subPass = ProtoCore.DSASM.AssociativeSubCompilePass.kNone)
        {
            ConstructorDefinitionNode funcDef = node as ConstructorDefinitionNode;
            ProtoCore.DSASM.CodeBlockType originalBlockType = codeBlock.blockType;
            codeBlock.blockType = ProtoCore.DSASM.CodeBlockType.kFunction;

            if (IsParsingMemberFunctionSig())
            {
                Debug.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
                localProcedure.returntype.UID = globalClassIndex;
                localProcedure.returntype.IsIndexable = false;
                localProcedure.isConstructor = true;
                localProcedure.runtimeIndex = 0;
                localProcedure.isExternal = funcDef.IsExternLib;
                Debug.Assert(ProtoCore.DSASM.Constants.kInvalidIndex != globalClassIndex, "A constructor node must be associated with class");
                localProcedure.localCount = 0;
                localProcedure.classScope = globalClassIndex;

                int peekFunctionindex = compileStateTracker.ClassTable.ClassNodes[globalClassIndex].vtable.procList.Count;

                // Append arg symbols
                List<KeyValuePair<string, ProtoCore.Type>> argsToBeAllocated = new List<KeyValuePair<string, ProtoCore.Type>>();
                if (null != funcDef.Signature)
                {
                    int argNumber = 0;
                    foreach (VarDeclNode argNode in funcDef.Signature.Arguments)
                    {
                        ++argNumber;

                        IdentifierNode paramNode = null;
                        bool aIsDefault = false;
                        ProtoCore.AST.Node aDefaultExpression = null;
                        if (argNode.NameNode is IdentifierNode)
                        {
                            paramNode = argNode.NameNode as IdentifierNode;
                        }
                        else if (argNode.NameNode is BinaryExpressionNode)
                        {
                            BinaryExpressionNode bNode = argNode.NameNode as BinaryExpressionNode;
                            paramNode = bNode.LeftNode as IdentifierNode;
                            aIsDefault = true;
                            aDefaultExpression = bNode;
                            //buildStatus.LogSemanticError("Default parameters are not supported");
                            //throw new BuildHaltException();
                        }
                        else
                        {
                            Debug.Assert(false, "Check generated AST");
                        }

                        ProtoCore.Type argType = BuildArgumentTypeFromVarDeclNode(argNode);
                        argsToBeAllocated.Add(new KeyValuePair<string, ProtoCore.Type>(paramNode.Value, argType));
                        localProcedure.argTypeList.Add(argType);
                        ProtoCore.DSASM.ArgumentInfo argInfo = new ProtoCore.DSASM.ArgumentInfo { Name = paramNode.Value, isDefault = aIsDefault, defaultExpression = aDefaultExpression };
                        localProcedure.argInfoList.Add(argInfo);
                    }
                }

                int findex = compileStateTracker.ClassTable.ClassNodes[globalClassIndex].vtable.Append(localProcedure);

                // Comment Jun: Catch this assert given the condition as this type of mismatch should never occur
                if (ProtoCore.DSASM.Constants.kInvalidIndex != findex)
                {
                    Debug.Assert(peekFunctionindex == localProcedure.procId);
                    argsToBeAllocated.ForEach(arg =>
                    {
                        int symbolIndex = AllocateArg(arg.Key, findex, arg.Value);
                        if (ProtoCore.DSASM.Constants.kInvalidIndex == symbolIndex)
                        {
                            throw new BuildHaltException("44B557F1");
                        }
                    });
                }
                else
                {
                    string message = String.Format(ProtoCore.BuildData.WarningMessage.kMethodAlreadyDefined, localProcedure.name);
                    buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kFunctionAlreadyDefined, message, compileStateTracker.CurrentDSFileName, funcDef.line, funcDef.col);
                    funcDef.skipMe = true;
                }
            }
            else if (IsParsingMemberFunctionBody())
            {
                EmitCompileLogFunctionStart(GetFunctionSignatureString(funcDef.Name, funcDef.ReturnType, funcDef.Signature, true));
                // Build arglist for comparison
                List<ProtoCore.Type> argList = new List<ProtoCore.Type>();
                if (null != funcDef.Signature)
                {
                    foreach (VarDeclNode argNode in funcDef.Signature.Arguments)
                    {
                        ProtoCore.Type argType = BuildArgumentTypeFromVarDeclNode(argNode);
                        argList.Add(argType);
                    }
                }

                globalProcIndex = compileStateTracker.ClassTable.ClassNodes[globalClassIndex].vtable.IndexOfExact(funcDef.Name, argList);

                Debug.Assert(null == localProcedure);
                localProcedure = compileStateTracker.ClassTable.ClassNodes[globalClassIndex].vtable.procList[globalProcIndex];

                Debug.Assert(null != localProcedure);
                localProcedure.Attributes = PopulateAttributes(funcDef.Attributes);
                // Its only on the parse body pass where the real pc is determined. Update this procedures' pc
                //Debug.Assert(ProtoCore.DSASM.Constants.kInvalidIndex == localProcedure.pc);
                localProcedure.pc = pc;

                EmitInstrConsole(ProtoCore.DSASM.kw.allocc, localProcedure.name);
                EmitAllocc(globalClassIndex);
                setConstructorStartPC = true;

                EmitCallingForBaseConstructor(globalClassIndex, funcDef.baseConstr);

                ProtoCore.FunctionEndPoint fep = null;
                if (!funcDef.IsExternLib)
                {
                    // Traverse default assignment for the class
                    emitDebugInfo = false;
                    foreach (BinaryExpressionNode bNode in compileStateTracker.ClassTable.ClassNodes[globalClassIndex].defaultArgExprList)
                    {

                        ProtoCore.AssociativeGraph.GraphNode graphNode = new ProtoCore.AssociativeGraph.GraphNode();
                        graphNode.isParent = true;
                        graphNode.exprUID = bNode.exprUID;
                        graphNode.modBlkUID = bNode.modBlkUID;
                        graphNode.procIndex = globalProcIndex;
                        graphNode.classIndex = globalClassIndex;
                        graphNode.isAutoGenerated = true;

                        EmitBinaryExpressionNode(bNode, ref inferedType, false, graphNode, subPass);
                    }

                    //Traverse default argument for the constructor
                    foreach (ProtoCore.DSASM.ArgumentInfo argNode in localProcedure.argInfoList)
                    {
                        if (!argNode.isDefault)
                        {
                            continue;
                        }
                        BinaryExpressionNode bNode = argNode.defaultExpression as BinaryExpressionNode;
                        // build a temporay node for statement : temp = defaultarg;
                        var iNodeTemp = nodeBuilder.BuildIdentfier(Constants.kTempDefaultArg);
                        BinaryExpressionNode bNodeTemp = new BinaryExpressionNode();
                        bNodeTemp.LeftNode = iNodeTemp;
                        bNodeTemp.Optr = ProtoCore.DSASM.Operator.assign;
                        bNodeTemp.RightNode = bNode.LeftNode;
                        EmitBinaryExpressionNode(bNodeTemp, ref inferedType);
                        //duild an inline conditional node for statement: defaultarg = (temp == DefaultArgNode) ? defaultValue : temp;
                        InlineConditionalNode icNode = new InlineConditionalNode();
                        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);
                    }
                    emitDebugInfo = true;

                    // Traverse definition
                    foreach (AssociativeNode bnode in funcDef.FunctionBody.Body)
                    {
                        inferedType.UID = (int)PrimitiveType.kTypeVoid;
                        inferedType.rank = 0;

                        if (bnode is LanguageBlockNode)
                        {
                            // Build a binaryn node with a temporary lhs for every stand-alone language block
                            var iNode = nodeBuilder.BuildIdentfier(compileStateTracker.GenerateTempLangageVar());
                            BinaryExpressionNode langBlockNode = new BinaryExpressionNode();
                            langBlockNode.LeftNode = iNode;
                            langBlockNode.Optr = ProtoCore.DSASM.Operator.assign;
                            langBlockNode.RightNode = bnode;
                            DfsTraverse(langBlockNode, ref inferedType, false, null, subPass);
                        }
                        else
                        {
                            DfsTraverse(bnode, ref inferedType, false, null, subPass);
                        }
                    }

                    // All locals have been stack allocated, update the local count of this function
                    localProcedure.localCount = compileStateTracker.BaseOffset;
                    compileStateTracker.ClassTable.ClassNodes[globalClassIndex].vtable.procList[globalProcIndex].localCount = compileStateTracker.BaseOffset;

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

                    // JIL FEP
                    ProtoCore.Lang.JILActivationRecord record = new ProtoCore.Lang.JILActivationRecord();
                    record.pc = localProcedure.pc;
                    record.locals = localProcedure.localCount;
                    record.classIndex = globalClassIndex;
                    record.funcIndex = globalProcIndex;

                    // Construct the fep arguments
                    fep = new ProtoCore.Lang.JILFunctionEndPoint(record);
                }
                else
                {
                    ProtoCore.Lang.JILActivationRecord jRecord = new ProtoCore.Lang.JILActivationRecord();
                    jRecord.pc = localProcedure.pc;
                    jRecord.locals = localProcedure.localCount;
                    jRecord.classIndex = globalClassIndex;
                    jRecord.funcIndex = localProcedure.procId;

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

                // Construct the fep arguments
                fep.FormalParams = new ProtoCore.Type[localProcedure.argTypeList.Count];
                fep.procedureNode = localProcedure;
                localProcedure.argTypeList.CopyTo(fep.FormalParams, 0);

                // TODO Jun: 'classIndexAtCallsite' is the class index as it is stored at the callsite function tables
                // Determine whether this still needs to be aligned to the actual 'classIndex' variable
                // The factors that will affect this is whether the 2 function tables (compiler and callsite) need to be merged
                int classIndexAtCallsite = globalClassIndex + 1;
                compileStateTracker.FunctionTable.AddFunctionEndPointer(classIndexAtCallsite, funcDef.Name, fep);

                int startpc = pc;

                // Constructors auto return
                EmitInstrConsole(ProtoCore.DSASM.kw.retc);

                // Stepping out of a constructor body will have the execution cursor
                // placed right at the closing curly bracket of the constructor definition.
                //
                int closeCurlyBracketLine = 0, closeCurlyBracketColumn = -1;
                if (null != funcDef.FunctionBody)
                {
                    closeCurlyBracketLine = funcDef.FunctionBody.endLine;
                    closeCurlyBracketColumn = funcDef.FunctionBody.endCol;
                }

                // The execution cursor covers exactly one character -- the closing
                // curly bracket. Note that we decrement the start-column by one here
                // because end-column of "FunctionBody" here is *after* the closing
                // curly bracket, so we want one before that.
                //
                EmitRetc(closeCurlyBracketLine, closeCurlyBracketColumn - 1,
                    closeCurlyBracketLine, closeCurlyBracketColumn);

                // Build and append a graphnode for this return statememt
                ProtoCore.DSASM.SymbolNode returnNode = new ProtoCore.DSASM.SymbolNode();
                returnNode.name = ProtoCore.DSDefinitions.Keyword.Return;

                ProtoCore.AssociativeGraph.GraphNode retNode = new ProtoCore.AssociativeGraph.GraphNode();
                //retNode.symbol = returnNode;
                retNode.PushSymbolReference(returnNode);
                retNode.procIndex = globalProcIndex;
                retNode.classIndex = globalClassIndex;
                retNode.updateBlock.startpc = startpc;
                retNode.updateBlock.endpc = pc - 1;

                codeBlock.instrStream.dependencyGraph.Push(retNode);
                EmitCompileLogFunctionEnd();
            }

            // Constructors have no return statemetns, reset variables here
            compileStateTracker.ProcNode = localProcedure = null;
            globalProcIndex = ProtoCore.DSASM.Constants.kGlobalScope;
            compileStateTracker.BaseOffset = 0;
            argOffset = 0;
            classOffset = 0;
            codeBlock.blockType = originalBlockType;
        }
Exemplo n.º 14
0
        public ProtoCore.DSASM.ProcedureNode TraverseDotFunctionCall(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.AssociativeAST.BinaryExpressionNode bnode = null)
        {
            FunctionCallNode funcCall = null;
            ProtoCore.DSASM.ProcedureNode procCallNode = null;
            ProtoCore.DSASM.ProcedureNode procDotCallNode = null;
            string procName = null;
            List<ProtoCore.Type> arglist = new List<ProtoCore.Type>();
            ProtoCore.Type dotCallType = new ProtoCore.Type();
            dotCallType.UID = (int)PrimitiveType.kTypeVar;
            dotCallType.IsIndexable = false;

            bool isConstructor = false;
            bool isStaticCall = false;
            bool isStaticCallAllowed = false;
            bool isUnresolvedDot = false;
            bool isUnresolvedMethod = false;

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

            ProtoCore.AST.AssociativeAST.FunctionDotCallNode dotCall = node as ProtoCore.AST.AssociativeAST.FunctionDotCallNode;
            funcCall = dotCall.DotCall;
            procName = dotCall.FunctionCall.Function.Name;

            List<AssociativeNode> replicationGuide = (dotCall.FunctionCall.Function as IdentifierNode).ReplicationGuides;

            var dotCallFirstArgument = dotCall.DotCall.FormalArguments[0];
            if (dotCallFirstArgument is FunctionDotCallNode)
            {
                isUnresolvedDot = true;
            }
            else if (dotCallFirstArgument is IdentifierNode || dotCallFirstArgument is ThisPointerNode)
            {
                // Check if the lhs identifer is a class name
                string lhsName = "";
                int ci = Constants.kInvalidIndex;

                if (dotCallFirstArgument is IdentifierNode)
                {
                    lhsName = (dotCallFirstArgument as IdentifierNode).Name;
                    ci = compileStateTracker.ClassTable.IndexOf(lhsName);
                    classIndex = ci;
                    className = lhsName;

                    // As a class name can be used as property name, we need to
                    // check if this identifier is a property or a class name.
                    //
                    if (ci != Constants.kInvalidIndex && globalClassIndex != Constants.kInvalidIndex)
                    {
                        ProtoCore.DSASM.SymbolNode symbolnode;
                        bool isAccessbile = false;
                        bool hasAllocated = VerifyAllocation(lhsName, globalClassIndex, globalProcIndex, out symbolnode, out isAccessbile);

                        // Well, found a property whose name is class name. Now
                        // we need to check if the RHS function call is
                        // constructor or not.
                        if (hasAllocated && isAccessbile && symbolnode.functionIndex == ProtoCore.DSASM.Constants.kInvalidIndex)
                        {
                            var procnode = GetProcedureFromInstance(ci, dotCall.FunctionCall);
                            if (procnode != null && !procnode.isConstructor)
                            {
                                ci = Constants.kInvalidIndex;
                                lhsName = "";
                            }
                        }
                    }
                }

                if (ci != ProtoCore.DSASM.Constants.kInvalidIndex)
                {
                    // It is a class name
                    dotCall.DotCall.FormalArguments[0] = new IntNode { value = ci.ToString() };
                    dotCallFirstArgument = dotCall.DotCall.FormalArguments[0];

                    inferedType.UID = dotCallType.UID = ci;

                    string rhsName = dotCall.FunctionCall.Function.Name;
                    procCallNode = GetProcedureFromInstance(ci, dotCall.FunctionCall, graphNode);
                    if (null != procCallNode)
                    {
                        isConstructor = procCallNode.isConstructor;

                        // It's a static call if its not a constructor
                        isStaticCall = !procCallNode.isConstructor;

                        // If this is a static call and the first method found was not static
                        // Look further
                        if (isStaticCall && !procCallNode.isStatic)
                        {
                            ProtoCore.DSASM.ProcedureNode staticProcCallNode = compileStateTracker.ClassTable.ClassNodes[ci].GetFirstStaticMemberFunction(procName);
                            if (null != staticProcCallNode)
                            {
                                procCallNode = staticProcCallNode;
                            }
                        }

                        isStaticCallAllowed = procCallNode.isStatic && isStaticCall;
                    }
                    else
                    {
                        ProtoCore.DSASM.ProcedureNode staticProcCallNode = compileStateTracker.ClassTable.ClassNodes[ci].GetFirstStaticMemberFunction(procName);
                        string functionName = dotCall.FunctionCall.Function.Name;
                        string property;

                        if (null != staticProcCallNode)
                        {
                            string message = String.Format(ProtoCore.BuildData.WarningMessage.kMethodHasInvalidArguments, functionName);
                            buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kCallingNonStaticMethodOnClass, message, compileStateTracker.CurrentDSFileName, dotCall.line, dotCall.col);
                        }
                        else if (CoreUtils.TryGetPropertyName(functionName, out property))
                        {
                            string message = String.Format(ProtoCore.BuildData.WarningMessage.kCallingNonStaticProperty, lhsName, property);
                            buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kCallingNonStaticMethodOnClass, message, compileStateTracker.CurrentDSFileName, dotCall.line, dotCall.col);
                        }
                        else
                        {
                            string message = String.Format(ProtoCore.BuildData.WarningMessage.kCallingNonStaticMethod, lhsName, functionName);
                            buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kCallingNonStaticMethodOnClass, message, compileStateTracker.CurrentDSFileName, dotCall.line, dotCall.col);
                        }
                    }
                }

                if (dotCall.DotCall.FormalArguments.Count == ProtoCore.DSASM.Constants.kDotCallArgCount)
                {
                    if (dotCallFirstArgument is IdentifierNode)
                    {
                        ProtoCore.DSASM.SymbolNode symbolnode = null;
                        bool isAccessible = false;
                        bool isAllocated = VerifyAllocation((dotCallFirstArgument as IdentifierNode).Name, globalClassIndex, globalProcIndex, out symbolnode, out isAccessible);
                        if (isAllocated && symbolnode.datatype.UID != (int)PrimitiveType.kTypeVar)
                        {
                            inferedType.UID = symbolnode.datatype.UID;

                            if (ProtoCore.DSASM.Constants.kInvalidIndex != inferedType.UID)
                            {
                                procCallNode = GetProcedureFromInstance(symbolnode.datatype.UID, dotCall.FunctionCall);
                            }

                            if (null != procCallNode)
                            {
                                if (procCallNode.isConstructor)
                                {
                                    if (subPass != ProtoCore.DSASM.AssociativeSubCompilePass.kUnboundIdentifier)
                                    {
                                        // A constructor cannot be called from an instance
                                        string message = String.Format(ProtoCore.BuildData.WarningMessage.KCallingConstructorOnInstance, procName);
                                        buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kCallingConstructorOnInstance, message, compileStateTracker.CurrentDSFileName, funcCall.line, funcCall.col);
                                    }

                                    isUnresolvedDot = true;
                                    isUnresolvedMethod = true;
                                }
                                else
                                {
                                   isAccessible =
                                       procCallNode.access == ProtoCore.DSASM.AccessSpecifier.kPublic
                                        || (procCallNode.access == ProtoCore.DSASM.AccessSpecifier.kPrivate && procCallNode.classScope == globalClassIndex);

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

                                    if (null != procCallNode)
                                    {
                                        int dynamicRhsIndex = int.Parse((dotCall.DotCall.FormalArguments[1] as IntNode).value);
                                        compileStateTracker.DynamicFunctionTable.functionTable[dynamicRhsIndex].classIndex = procCallNode.classScope;
                                        compileStateTracker.DynamicFunctionTable.functionTable[dynamicRhsIndex].procedureIndex = procCallNode.procId;
                                        compileStateTracker.DynamicFunctionTable.functionTable[dynamicRhsIndex].pc = procCallNode.pc;
                                    }
                                }
                            }
                        }
                        else
                        {
                            isUnresolvedDot = true;
                        }
                    }
                    else if (dotCallFirstArgument is ThisPointerNode)
                    {
                        if (globalClassIndex != Constants.kInvalidIndex)
                        {
                            procCallNode = GetProcedureFromInstance(globalClassIndex, dotCall.FunctionCall);
                            if (null != procCallNode && procCallNode.isConstructor)
                            {
                                dotCall.DotCall.FormalArguments[0] = new IntNode { value = globalClassIndex.ToString() };
                                dotCallFirstArgument = dotCall.DotCall.FormalArguments[0];
                                inferedType.UID = dotCallType.UID = ci;
                            }
                        }
                    }
                }
            }
            else if (funcCall.FormalArguments[0] is IntNode)
            {
                inferedType.UID = dotCallType.UID = int.Parse((funcCall.FormalArguments[0] as IntNode).value);
                classIndex = inferedType.UID;
                procCallNode = GetProcedureFromInstance(dotCallType.UID, dotCall.FunctionCall, graphNode);

                if (null != procCallNode)
                {
                    // It's a static call if its not a constructor
                    isConstructor = procCallNode.isConstructor;
                    isStaticCall = !procCallNode.isConstructor;

                    // If this is a static call and the first method found was not static
                    // Look further
                    if (isStaticCall && !procCallNode.isStatic)
                    {
                        ProtoCore.DSASM.ProcedureNode staticProcCallNode = compileStateTracker.ClassTable.ClassNodes[inferedType.UID].GetFirstStaticMemberFunction(procName);
                        if (null != staticProcCallNode)
                        {
                            procCallNode = staticProcCallNode;
                        }
                    }

                    isStaticCallAllowed = procCallNode.isStatic && isStaticCall;
                    className = compileStateTracker.ClassTable.ClassNodes[dotCallType.UID].name;

                    if (isStaticCall && !isStaticCallAllowed)
                    {
                        if (subPass != ProtoCore.DSASM.AssociativeSubCompilePass.kUnboundIdentifier)
                        {
                            string property;
                            className = compileStateTracker.ClassTable.ClassNodes[dotCallType.UID].name;
                            ProtoCore.DSASM.ProcedureNode staticProcCallNode = compileStateTracker.ClassTable.ClassNodes[inferedType.UID].GetFirstStaticMemberFunction(procName);

                            if (null != staticProcCallNode)
                            {
                                string message = String.Format(ProtoCore.BuildData.WarningMessage.kMethodHasInvalidArguments, procName);
                                buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kCallingNonStaticMethodOnClass, message, compileStateTracker.CurrentDSFileName, dotCall.line, dotCall.col);
                            }
                            else if (CoreUtils.TryGetPropertyName(procName, out property))
                            {
                                string message = String.Format(ProtoCore.BuildData.WarningMessage.kCallingNonStaticProperty, property, className);
                                buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kCallingNonStaticMethodOnClass, message, compileStateTracker.CurrentDSFileName, dotCall.line, dotCall.col);
                            }
                            else
                            {
                                string message = String.Format(ProtoCore.BuildData.WarningMessage.kCallingNonStaticMethod, procName, className);
                                buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kCallingNonStaticMethodOnClass, message, compileStateTracker.CurrentDSFileName, dotCall.line, dotCall.col);
                            }
                        }
                        isUnresolvedMethod = true;
                    }
                    else
                    {
                        inferedType = procCallNode.returntype;
                    }
                }
            }

            // Its an accceptable method at this point
            if (!isUnresolvedMethod)
            {
                int funtionArgCount = 0;

                //foreach (AssociativeNode paramNode in funcCall.FormalArguments)
                for (int n = 0; n < funcCall.FormalArguments.Count; ++n)
                {
                    AssociativeNode paramNode = funcCall.FormalArguments[n];
                    ProtoCore.Type paramType = new ProtoCore.Type();
                    paramType.UID = (int)ProtoCore.PrimitiveType.kTypeVoid;
                    paramType.IsIndexable = false;

                    emitReplicationGuide = 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);

                    // TODO Jun: Cleansify me
                    // What im doing is just taking the second parameter of the dot op (The method call)
                    // ...and adding it to the graph node dependencies
                    if (ProtoCore.DSASM.Constants.kDotArgIndexDynTableIndex == n)
                    {
                        if (subPass != ProtoCore.DSASM.AssociativeSubCompilePass.kUnboundIdentifier)
                        {
                            if (!isConstructor)
                            {
                                if (null != procCallNode)
                                {
                                    if (graphNode.dependentList.Count > 0)
                                    {
                                        ProtoCore.AssociativeGraph.UpdateNodeRef nodeRef = new ProtoCore.AssociativeGraph.UpdateNodeRef();
                                        ProtoCore.AssociativeGraph.UpdateNode updateNode = new ProtoCore.AssociativeGraph.UpdateNode();
                                        ProtoCore.DSASM.ProcedureNode procNodeDummy = new ProtoCore.DSASM.ProcedureNode();
                                        if (procCallNode.isAutoGenerated)
                                        {
                                            ProtoCore.DSASM.SymbolNode sym = new ProtoCore.DSASM.SymbolNode();
                                            sym.name = procName.Remove(0, ProtoCore.DSASM.Constants.kSetterPrefix.Length);
                                            updateNode.nodeType = ProtoCore.AssociativeGraph.UpdateNodeType.kSymbol;
                                            updateNode.symbol = sym;
                                        }
                                        else
                                        {
                                            procNodeDummy.name = procName;
                                            updateNode.nodeType = ProtoCore.AssociativeGraph.UpdateNodeType.kMethod;
                                            updateNode.procNode = procNodeDummy;
                                        }
                                        graphNode.dependentList[0].updateNodeRefList[0].nodeList.Add(updateNode);
                                    }
                                }
                                else
                                {
                                    // comment Jun:
                                    // This is dotarg whos first argument is also a dotarg
                                    // dotarg(dorarg...)...)
                                    if (graphNode.dependentList.Count > 0)
                                    {
                                        if (ProtoCore.Utils.CoreUtils.IsGetterSetter(procName))
                                        {
                                            ProtoCore.AssociativeGraph.UpdateNode updateNode = new ProtoCore.AssociativeGraph.UpdateNode();
                                            ProtoCore.DSASM.SymbolNode sym = new ProtoCore.DSASM.SymbolNode();
                                            sym.name = procName.Remove(0, ProtoCore.DSASM.Constants.kSetterPrefix.Length);
                                            updateNode.nodeType = ProtoCore.AssociativeGraph.UpdateNodeType.kSymbol;
                                            updateNode.symbol = sym;

                                            graphNode.dependentList[0].updateNodeRefList[0].nodeList.Add(updateNode);
                                        }
                                    }
                                }
                            }
                        }
                    }

                    // Traversing the first arg (the LHS pointer/Static instanct/Constructor
                    if (ProtoCore.DSASM.Constants.kDotArgIndexPtr == n)
                    {
                        // Comment Jun:
                        //      Allow guides only on 'this' pointers for non getter/setter methods
                        //      No guides for 'this' pointers in constructors calls (There is no this pointer yet)
                        //
                        /*
                            class C
                            {
                                def f(a : int)
                                {
                                    return = 10;
                                }
                            }
                            p = {C.C(), C.C()};
                            x = p<1>.f({1,2}<2>); // guides allowed on the pointer 'p'

                            class A
                            {
                                x : var[];
                                constructor A()
                                {
                                    x = {1,2};
                                }
                            }
                            a = A.A();
                            b = A.A();
                            c = a<1>.x<2>; // guides not allowed on getter

                         */
                        if (!ProtoCore.Utils.CoreUtils.IsGetterSetter(procName) && !isConstructor)
                        {
                            emitReplicationGuide = true;
                        }

                        DfsTraverse(paramNode, ref paramType, false, graphNode, subPass, bnode);
                        if (subPass != ProtoCore.DSASM.AssociativeSubCompilePass.kUnboundIdentifier)
                        {
                            if (isStaticCall && isStaticCallAllowed)
                            {
                                Validity.Assert(ProtoCore.DSASM.Constants.kInvalidIndex != classIndex);
                                Validity.Assert(string.Empty != className);
                                SymbolNode classSymbol = new SymbolNode();
                                classSymbol.name = className;
                                classSymbol.classScope = classIndex;

                                ProtoCore.AssociativeGraph.GraphNode dependentNode = new ProtoCore.AssociativeGraph.GraphNode();
                                dependentNode.PushSymbolReference(classSymbol, ProtoCore.AssociativeGraph.UpdateNodeType.kSymbol);
                                graphNode.PushDependent(dependentNode);
                            }
                        }
                    }

                    // Traversing the actual arguments passed into the function (not the dot function)
                    else if (ProtoCore.DSASM.Constants.kDotArgIndexArrayArgs == n)
                    {
                        int defaultAdded = 0;

                        // If its null this is the second call in a chained dot
                        if (null != procCallNode)
                        {
                            // Check how many args were passed in.... against what is expected
                            defaultAdded = procCallNode.argInfoList.Count - dotCall.FunctionCall.FormalArguments.Count;
                        }

                        // Enable graphnode dependencies if its a setter method
                        bool allowDependentState = null != graphNode ? graphNode.allowDependents : false;
                        if (ProtoCore.Utils.CoreUtils.IsSetter(procName))
                        {
                            // If the arguments are not temporaries
                            ProtoCore.AST.AssociativeAST.ExprListNode exprList = paramNode as ExprListNode;
                            Validity.Assert(1 == exprList.list.Count);

                            string varname = string.Empty;
                            if (exprList.list[0] is IdentifierNode)
                            {
                                varname = (exprList.list[0] as IdentifierNode).Name;

                                // Only allow the acutal function variables and SSA temp vars
                                // TODO Jun: determine what temp could be passed in that is autodegenerated and non-SSA
                                if (!ProtoCore.Utils.CoreUtils.IsAutoGeneratedVar(varname)
                                    || ProtoCore.Utils.CoreUtils.IsSSATemp(varname))
                                {
                                    graphNode.allowDependents = true;
                                }
                            }
                            else
                            {
                                graphNode.allowDependents = true;
                            }

                        }

                        emitReplicationGuide = true;

                        if (defaultAdded > 0)
                        {
                            ProtoCore.AST.AssociativeAST.ExprListNode exprList = paramNode as ExprListNode;

                            if (subPass != AssociativeSubCompilePass.kUnboundIdentifier)
                            {
                                for (int i = 0; i < defaultAdded; i++)
                                {
                                    exprList.list.Add(new DefaultArgNode());
                                }

                            }
                            DfsTraverse(paramNode, ref paramType, false, graphNode, subPass);
                            funtionArgCount = exprList.list.Count;
                        }
                        else
                        {
                            Validity.Assert(paramNode is ProtoCore.AST.AssociativeAST.ExprListNode);
                            ProtoCore.AST.AssociativeAST.ExprListNode exprList = paramNode as ProtoCore.AST.AssociativeAST.ExprListNode;

                            // Comment Jun: This is a getter/setter or a an auto-generated thisarg function...
                            // ...add the dynamic sv that will be resolved as a pointer at runtime
                            if (!isStaticCall && !isConstructor)
                            {
                                //if (null != procCallNode && ProtoCore.Utils.CoreUtils.IsGetterSetter(procCallNode.name) && AssociativeSubCompilePass.kNone == subPass)
                                // TODO Jun: pls get rid of subPass checking outside the core travesal
                                if (ProtoCore.DSASM.AssociativeSubCompilePass.kNone == subPass)
                                {
                                    exprList.list.Insert(0, new DynamicNode());
                                }
                            }

                            if (exprList.list.Count > 0)
                            {
                                foreach (ProtoCore.AST.AssociativeAST.AssociativeNode exprListNode in exprList.list)
                                {
                                    bool repGuideState = emitReplicationGuide;
                                    if (subPass != ProtoCore.DSASM.AssociativeSubCompilePass.kUnboundIdentifier)
                                    {
                                        if (exprListNode is ProtoCore.AST.AssociativeAST.ExprListNode
                                            || exprListNode is ProtoCore.AST.AssociativeAST.GroupExpressionNode)
                                        {
                                            if (compileStateTracker.Options.TempReplicationGuideEmptyFlag)
                                            {
                                                // Emit the replication guide for the exprlist
                                                List<ProtoCore.AST.AssociativeAST.AssociativeNode> repGuideList = GetReplicationGuides(exprListNode);
                                                EmitReplicationGuides(repGuideList, true);

                                                emitReplicationGuide = false;

                                                // Pop off the guide if the current element was an array
                                                if (null != repGuideList)
                                                {
                                                    EmitInstrConsole(ProtoCore.DSASM.kw.popg);
                                                    EmitPopGuide();
                                                }
                                            }
                                        }
                                    }
                                    else
                                    {
                                        emitReplicationGuide = false;
                                    }

                                    DfsTraverse(exprListNode, ref paramType, false, graphNode, subPass, bnode);
                                    emitReplicationGuide = repGuideState;
                                }

                                if (subPass != ProtoCore.DSASM.AssociativeSubCompilePass.kUnboundIdentifier)
                                {

                                    EmitInstrConsole(ProtoCore.DSASM.kw.alloca, exprList.list.Count.ToString());
                                    EmitPopArray(exprList.list.Count);

                                    if (exprList.ArrayDimensions != null)
                                    {
                                        int dimensions = DfsEmitArrayIndexHeap(exprList.ArrayDimensions, graphNode);
                                        EmitInstrConsole(ProtoCore.DSASM.kw.pushindex, dimensions.ToString() + "[dim]");
                                        EmitPushArrayIndex(dimensions);
                                    }
                                }
                            }
                            else
                            {
                                if (exprList != null)
                                {
                                    bool emitReplicationGuideState = emitReplicationGuide;
                                    emitReplicationGuide = false;
                                    DfsTraverse(paramNode, ref paramType, false, graphNode, subPass);
                                    emitReplicationGuide = emitReplicationGuideState;
                                }
                                else
                                {
                                    DfsTraverse(paramNode, ref paramType, false, graphNode, subPass);
                                }
                            }

                            funtionArgCount = exprList.list.Count;
                        }

                        emitReplicationGuide = false;

                        // Restore the state only if it is a setter method
                        if (ProtoCore.Utils.CoreUtils.IsSetter(procName))
                        {
                            graphNode.allowDependents = allowDependentState;
                        }
                    }
                    else if (ProtoCore.DSASM.Constants.kDotArgIndexArgCount == n)
                    {
                        ProtoCore.AST.AssociativeAST.IntNode argNumNode = new ProtoCore.AST.AssociativeAST.IntNode() { value = funtionArgCount.ToString() };
                        DfsTraverse(argNumNode, ref paramType, false, graphNode, subPass);
                    }
                    else
                    {
                        DfsTraverse(paramNode, ref paramType, false, graphNode, subPass);
                    }

                    emitReplicationGuide = false;
                    enforceTypeCheck = true;

                    arglist.Add(paramType);
                }
            }

            if (subPass == ProtoCore.DSASM.AssociativeSubCompilePass.kUnboundIdentifier)
            {
                return null;
            }

            // Comment Jun: Append the lhs pointer as an argument to the overloaded function
            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.list.Insert(0, dotCall.DotCall.FormalArguments[ProtoCore.DSASM.Constants.kDotArgIndexPtr]);
            }

            if (isUnresolvedMethod)
            {
                EmitNullNode(new NullNode(), ref inferedType);
                return null;
            }

            procDotCallNode = compileStateTracker.GetFirstVisibleProcedure(ProtoCore.DSASM.Constants.kDotArgMethodName, arglist, codeBlock);

            // 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 ProtoCore.AST.AssociativeAST.IdentifierListNode)
            {
                ProtoCore.AST.Node leftnode = (parentNode as ProtoCore.AST.AssociativeAST.IdentifierListNode).LeftNode;
                if (leftnode != null && leftnode is ProtoCore.AST.AssociativeAST.IdentifierNode)
                {
                    refClassIndex = compileStateTracker.ClassTable.IndexOf(leftnode.Name);
                }
            }

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

            // 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
                && procName != ProtoCore.DSASM.Constants.kFunctionPointerCall)
            {
                bool isStaticOrConstructor = refClassIndex != ProtoCore.DSASM.Constants.kInvalidIndex;
                procCallNode = compileStateTracker.ClassTable.ClassNodes[inferedType.UID].GetFirstMemberFunction(procName);
            }

            // Try function pointer firstly
            if ((procCallNode == 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 ((procCallNode == null) && (procName != ProtoCore.DSASM.Constants.kFunctionPointerCall))
            {
                procCallNode = compileStateTracker.GetFirstVisibleProcedure(procName, arglist, codeBlock);
                if (null != procCallNode)
                {
                    type = ProtoCore.DSASM.Constants.kGlobalScope;
                    if (compileStateTracker.TypeSystem.IsHigherRank(procCallNode.returntype.UID, inferedType.UID))
                    {
                        inferedType = procCallNode.returntype;
                    }
                }
            }

            // Try member functions in global class scope
            if ((procCallNode == 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);
                        procCallNode = memProcNode;
                        inferedType = procCallNode.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 procCallNode;
                        }
                    }
                }
            }

            if (isUnresolvedDot)
            {
                // Get the dot call procedure
                ProtoCore.DSASM.ProcedureNode procNode = procDotCallNode;
                if (!isConstructor && !isStaticCall)
                {
                    procNode = compileStateTracker.GetFirstVisibleProcedure(ProtoCore.DSASM.Constants.kDotMethodName, null, codeBlock);
                }

                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;
                }

                return procCallNode;
            }

            if (null != procCallNode)
            {
                if (procCallNode.isConstructor &&
                        (globalClassIndex != ProtoCore.DSASM.Constants.kInvalidIndex) &&
                        (globalProcIndex != ProtoCore.DSASM.Constants.kInvalidIndex) &&
                        (globalClassIndex == inferedType.UID))
                {
                    ProtoCore.DSASM.ProcedureNode contextProcNode = compileStateTracker.ClassTable.ClassNodes[globalClassIndex].vtable.procList[globalProcIndex];
                    if (contextProcNode.isConstructor &&
                        string.Equals(contextProcNode.name, procCallNode.name) &&
                        contextProcNode.runtimeIndex == procCallNode.runtimeIndex)
                    {
                        string message = String.Format(ProtoCore.BuildData.WarningMessage.kCallingConstructorInConstructor, procName);
                        buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kCallingConstructorInConstructor, message, compileStateTracker.CurrentDSFileName, node.line, node.col);
                        inferedType.UID = (int)PrimitiveType.kTypeNull;
                        EmitPushNull();
                        return procCallNode;
                    }
                }

                inferedType = procCallNode.returntype;

                //if call is replication call
                if (procCallNode.isThisCallReplication)
                {
                    inferedType.IsIndexable = true;
                    inferedType.rank++;
                }

                // Get the dot call procedure
                ProtoCore.DSASM.ProcedureNode procNode = procDotCallNode;
                if (!isConstructor && !isStaticCall)
                {
                    procNode = compileStateTracker.GetFirstVisibleProcedure(ProtoCore.DSASM.Constants.kDotMethodName, null, 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;
                        ProtoCore.AssociativeGraph.UpdateNodeRef argNodeRef = new ProtoCore.AssociativeGraph.UpdateNodeRef();
                        DFSGetSymbolList(paramNode, ref ltype, argNodeRef);

                        if (null != graphNode)
                        {
                            graphNode.updatedArguments.Add(argNodeRef);
                        }
                    }

                    graphNode.firstProc = procCallNode;
                }

                return procCallNode;
            }
            else
            {
                // Function does not exist at this point but we try to reolve at runtime
                if (depth <= 0 && procName != ProtoCore.DSASM.Constants.kFunctionPointerCall)
                {
                    if (inferedType.UID != (int)PrimitiveType.kTypeVar)
                    {
                        if (!compileStateTracker.Options.SuppressFunctionResolutionWarning)
                        {
                            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;
                    }

                    // Get the dot call procedure
                    ProtoCore.DSASM.ProcedureNode procNode = procDotCallNode;
                    if (!isConstructor && !isStaticCall)
                    {
                        procNode = compileStateTracker.GetFirstVisibleProcedure(ProtoCore.DSASM.Constants.kDotMethodName, null, codeBlock);
                    }

                    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;
                    }
                }
                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);

                    if (compileStateTracker.Options.TempReplicationGuideEmptyFlag && emitReplicationGuide)
                    {
                        int guides = EmitReplicationGuides(replicationGuide);
                        EmitInstrConsole(ProtoCore.DSASM.kw.pushindex, guides + "[guide]");
                        EmitPushReplicationGuide(guides);
                    }

                    //assign inferedType to var
                    inferedType.UID = (int)PrimitiveType.kTypeVar;
                }
            }
            return procDotCallNode;
        }
Exemplo n.º 15
0
        private void EmitBinaryExpressionNode(AssociativeNode node, ref ProtoCore.Type inferedType, bool isBooleanOp = false, ProtoCore.AssociativeGraph.GraphNode graphNode = null, ProtoCore.DSASM.AssociativeSubCompilePass subPass = ProtoCore.DSASM.AssociativeSubCompilePass.kNone, bool isTempExpression = false)
        {
            BinaryExpressionNode bnode = null;

            if (!IsParsingGlobal() && !IsParsingGlobalFunctionBody() && !IsParsingMemberFunctionBody())
                return;

            bool isBooleanOperation = false;
            bnode = node as BinaryExpressionNode;
            ProtoCore.Type leftType = new ProtoCore.Type();
            leftType.UID = (int)ProtoCore.PrimitiveType.kTypeVar;
            leftType.IsIndexable = false;

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

            DebugProperties.BreakpointOptions oldOptions = compileStateTracker.DebugProps.breakOptions;

            /*
            proc emitbinaryexpression(node)
                if node is assignment
                    if graphnode is not valid
                        graphnode = BuildNewGraphNode()
                    end
                    dfstraverse(node.right, graphnode)

                    def lefttype = invalid
                    def updateNodeRef = null
                    dfsgetsymbollist(node.left, lefttype, updateNodeRef)

                    // Get the first procedure call in the rhs
                    // This stack is populated on traversing the entire RHS
                    def firstProc = functionCallStack.first()

                    graphnode.pushUpdateRef(updateNodeRef)

                    // Auto-generate the updateNodeRefs for this graphnode given
                    the list stored in the first procedure found in the assignment expression
                    foreach noderef in firstProc.updatedProperties
                        def autogenRef = updateNodeRef
                        autogenRef.append(noderef)
                        graphnode.pushUpdateRef(autogenRef)
                    end

                    // 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
                    def symbol = classtable[ci].verifyalloc(updateNodeRef[0])
                    if symbol is valid
                        def localproc = getlocalproc(ci,fi)
                        localproc.push(updateNodeRef)
                    end
                    functionCallStack.Clear();
                end
            end
            */

            /*
                Building the graphnode dependencies from the SSA transformed identifier list is illustrated in the following functions:

                ssaPtrList = new List

                proc EmitBinaryExpression(bnode, graphnode)
                    if bnode is assignment
                        graphnode = new graphnode

                        if bnode is an SSA pointer expression
                            if bnode.rhs is an identifier
                                // Push the start pointer
                                ssaPtrList.push(node.rhs)
                            else if bnode.rhs is an identifierlist
                                // Push the rhs of the dot operator
                                ssaPtrList.push(node.rhs.rhs)
                            else
                                Assert unhandled
                            end
                        end

                        emit(bnode.rhs)
                        emit(bnode.lhs)

                        if (bnode is an SSA pointer expression
                            and bnode is the last expression in the SSA factor/term
                            ssaPtrList.Clear()
                        end
                    end
                end

            */

            // If this is an assignment statement, setup the top level graph node
            bool isGraphInScope = false;
            if (ProtoCore.DSASM.Operator.assign == bnode.Optr)
            {
                if (null == graphNode)
                {
                    isGraphInScope = true;
                    EmitCompileLog("==============Start Node==============\n");
                    graphNode = new ProtoCore.AssociativeGraph.GraphNode();
                    graphNode.isParent = true;
                    graphNode.exprUID = bnode.exprUID;
                    graphNode.modBlkUID = bnode.modBlkUID;
                    graphNode.procIndex = globalProcIndex;
                    graphNode.classIndex = globalClassIndex;
                    graphNode.languageBlockId = codeBlock.codeBlockId;

                    if (bnode.isSSAFirstAssignment)
                    {
                        firstSSAGraphNode = graphNode;
                    }

                    // All associative code is SSA'd and we want to keep track of the original identifier nodes of an identifier list:
                    //      i.e. x.y.z
                    // These identifiers will be used to populate the real graph nodes dependencies
                    if (bnode.isSSAPointerAssignment)
                    {
                        Validity.Assert(null != ssaPointerList);

                        if (bnode.RightNode is IdentifierNode)
                        {
                            ssaPointerList.Add(bnode.RightNode);
                        }
                        else if (bnode.RightNode is IdentifierListNode)
                        {
                            ssaPointerList.Add((bnode.RightNode as IdentifierListNode).RightNode);
                        }
                        else if (bnode.RightNode is FunctionDotCallNode)
                        {
                            FunctionDotCallNode dotcall = bnode.RightNode as FunctionDotCallNode;
                            Validity.Assert(dotcall.FunctionCall.Function is IdentifierNode);

                            if (ProtoCore.Utils.CoreUtils.IsGetterSetter(dotcall.FunctionCall.Function.Name))
                            {
                                // This function is an internal getter or setter, store the identifier node
                                ssaPointerList.Add(dotcall.FunctionCall.Function);
                            }
                            else
                            {
                                // This function is a member function, store the functioncall node
                                ssaPointerList.Add(dotcall.FunctionCall);
                            }
                        }
                        else if (bnode.RightNode is FunctionCallNode)
                        {
                            FunctionCallNode fcall = bnode.RightNode as FunctionCallNode;
                            Validity.Assert(fcall.Function is IdentifierNode);
                            ssaPointerList.Add(fcall.Function);
                        }
                        else
                        {
                            Validity.Assert(false);
                        }

                        /*
                           The following functions on codegen will perform the static call backtracking:

                           string staticClass = null
                           bool resolveStatic = false

                           proc EmitBinaryExpr(node)
                               if node.right is identifier
                                   if node.right is a class
                                       staticClass = node.right.name
                                       resolveStatic = true
                                   end
                               end
                           end

                           proc EmitIdentifierList(node, graphnode)
                               if resolveStatic
                                   node.left = new IdentifierNode(staticClass)
                               end
                           end
                        */
                        if (bnode.RightNode is IdentifierNode)
                        {
                            string identName = (bnode.RightNode as IdentifierNode).Name;
                            if (compileStateTracker.ClassTable.DoesExist(identName))
                            {
                                ssaPointerList.Clear();
                                staticClass = identName;
                                resolveStatic = true;
                                return;
                            }
                        }
                    }

                    //
                    // Comment Jun:
                    //      If the expression ID of the assignment node in the context execDirtyFlag list is false,
                    //      it means that it was already executed. This needs to be marked as not dirty
                    if (compileStateTracker.Options.IsDeltaExecution)
                    {
                        if (context.exprExecutionFlags.ContainsKey(bnode.exprUID))
                        {
                            graphNode.isDirty = context.exprExecutionFlags[bnode.exprUID];
                        }
                    }
                }
                if (bnode.LeftNode is IdentifierListNode)
                {
                    EmitLHSIdentifierListForBinaryExpr(bnode, ref inferedType, isBooleanOp, graphNode, subPass);
                    if (isGraphInScope)
                    {
                        EmitCompileLog("==============End Node==============\n");
                    }
                    return;
                }
                else if (bnode.LeftNode is IdentifierNode)
                {
                    if (bnode.LeftNode.Name.Equals(ProtoCore.DSDefinitions.Keyword.This))
                    {
                        string errorMessage = ProtoCore.BuildData.WarningMessage.kInvalidThis;
                        if (localProcedure != null)
                        {
                            if (localProcedure.isStatic)
                            {
                                errorMessage = ProtoCore.BuildData.WarningMessage.kUsingThisInStaticFunction;
                            }
                            else if (localProcedure.classScope == Constants.kGlobalScope)
                            {
                                errorMessage = ProtoCore.BuildData.WarningMessage.kInvalidThis;
                            }
                            else
                            {
                                errorMessage = ProtoCore.BuildData.WarningMessage.kAssingToThis;
                            }
                        }
                        compileStateTracker.BuildStatus.LogWarning(ProtoCore.BuildData.WarningID.kInvalidThis, errorMessage, compileStateTracker.CurrentDSFileName, bnode.line, bnode.col);

                        if (isGraphInScope)
                        {
                            EmitCompileLog("==============End Node==============\n");
                        }

                        return;
                    }

                    if (EmitLHSThisDotProperyForBinaryExpr(bnode, ref inferedType, isBooleanOp, graphNode, subPass))
                    {
                        if (isGraphInScope)
                        {
                            EmitCompileLog("==============End Node==============\n");
                        }
                        return;
                    }
                }
            }
            else //(ProtoCore.DSASM.Operator.assign != b.Optr)
            {
                // Traversing the left node if this binary expression is not an assignment
                //
                isBooleanOperation = ProtoCore.DSASM.Operator.lt == bnode.Optr
                     || ProtoCore.DSASM.Operator.gt == bnode.Optr
                     || ProtoCore.DSASM.Operator.le == bnode.Optr
                     || ProtoCore.DSASM.Operator.ge == bnode.Optr
                     || ProtoCore.DSASM.Operator.eq == bnode.Optr
                     || ProtoCore.DSASM.Operator.nq == bnode.Optr
                     || ProtoCore.DSASM.Operator.and == bnode.Optr
                     || ProtoCore.DSASM.Operator.or == bnode.Optr;

                DfsTraverse(bnode.LeftNode, ref inferedType, isBooleanOperation, graphNode, subPass);

                if (inferedType.UID == (int)PrimitiveType.kTypeFunctionPointer && subPass != ProtoCore.DSASM.AssociativeSubCompilePass.kUnboundIdentifier && emitDebugInfo)
                {
                    buildStatus.LogSemanticError("Function pointer is not allowed at binary expression other than assignment!", compileStateTracker.CurrentDSFileName, bnode.LeftNode.line, bnode.LeftNode.col);
                }

                leftType.UID = inferedType.UID;
                leftType.IsIndexable = inferedType.IsIndexable;
            }

            int startpc = ProtoCore.DSASM.Constants.kInvalidIndex;
            // (Ayush) in case of PostFixNode, only traverse the identifier now. Post fix operation will be applied later.
            #if ENABLE_INC_DEC_FIX
                if (bnode.RightNode is PostFixNode)
                {
                    DfsTraverse((bnode.RightNode as PostFixNode).Identifier, ref inferedType, isBooleanOperation, graphNode);
                }
                else
                {
            #endif
            if ((ProtoCore.DSASM.Operator.assign == bnode.Optr) && (bnode.RightNode is LanguageBlockNode))
            {
                inferedType.UID = (int)ProtoCore.PrimitiveType.kTypeVar;
                inferedType.IsIndexable = false;
            }

            if (null != localProcedure && localProcedure.isConstructor && setConstructorStartPC)
            {
                startpc -= 1;
                setConstructorStartPC = false;
            }

            if (bnode.RightNode == null && bnode.Optr == Operator.assign && bnode.LeftNode is IdentifierNode)
            {
                DebugProperties.BreakpointOptions newOptions = oldOptions;
                newOptions |= DebugProperties.BreakpointOptions.SuppressNullVarDeclarationBreakpoint;
                compileStateTracker.DebugProps.breakOptions = newOptions;

                IdentifierNode t = bnode.LeftNode as IdentifierNode;
                ProtoCore.DSASM.SymbolNode symbolnode = null;
                bool isAccessible = false;
                bool hasAllocated = VerifyAllocation(t.Value, globalClassIndex, globalProcIndex, out symbolnode, out isAccessible);
                if (hasAllocated)
                {
                    bool allowDependent = graphNode.allowDependents;
                    graphNode.allowDependents = false;
                    bnode.RightNode = nodeBuilder.BuildIdentfier(t.Value);
                    graphNode.allowDependents = false;
                }
                else
                {
                    bnode.RightNode = new NullNode();
                }
            }

            // Keep track of current pc, because when travese right node it
            // may generate null assignment ( x = null; if x hasn't been defined
            // yet - Yu Ke
            startpc = pc;

            DfsTraverse(bnode.RightNode, ref inferedType, isBooleanOperation, graphNode, subPass);
            #if ENABLE_INC_DEC_FIX
                }
            #endif

            rightType.UID = inferedType.UID;
            rightType.IsIndexable = inferedType.IsIndexable;

            BinaryExpressionNode rightNode = bnode.RightNode as BinaryExpressionNode;
            if ((rightNode != null) && (ProtoCore.DSASM.Operator.assign == rightNode.Optr))
            {
                DfsTraverse(rightNode.LeftNode, ref inferedType, false, graphNode);
            }

            if (bnode.Optr != ProtoCore.DSASM.Operator.assign)
            {
                if (subPass == ProtoCore.DSASM.AssociativeSubCompilePass.kUnboundIdentifier)
                {
                    return;
                }

                if (inferedType.UID == (int)PrimitiveType.kTypeFunctionPointer && emitDebugInfo)
                {
                    buildStatus.LogSemanticError("Function pointer is not allowed at binary expression other than assignment!", compileStateTracker.CurrentDSFileName, bnode.RightNode.line, bnode.RightNode.col);
                }
                EmitBinaryOperation(leftType, rightType, bnode.Optr);
                isBooleanOp = false;

                //if post fix, now traverse the post fix
            #if ENABLE_INC_DEC_FIX
                if (bnode.RightNode is PostFixNode)
                    EmitPostFixNode(bnode.RightNode, ref inferedType);
            #endif
                return;
            }

            Debug.Assert(null != graphNode);
            if (!isTempExpression)
            {
                // Only set startpc if isn't temporary assignment expression
                if (compileStateTracker.Options.IsDeltaExecution)
                    graphNode.updateBlock.startpc = startpc;
                else
                    graphNode.updateBlock.startpc = pc;
            }

            currentBinaryExprUID = bnode.exprUID;

            // These have been integrated into "EmitGetterSetterForIdentList" so
            // that stepping through class properties can be supported. Setting
            // these values here will cause issues with statements like this to
            // be highlighted in its entirety (all the way up to closing bracket
            // without highlighting the semi-colon).
            //
            //      x = foo(a, b);
            //
            // bnode.RightNode.line = bnode.line;
            // bnode.RightNode.col = bnode.col;
            // bnode.RightNode.endLine = bnode.endLine;
            // bnode.RightNode.endCol = bnode.endCol;

            // Traverse the entire RHS expression
            DfsTraverse(bnode.RightNode, ref inferedType, isBooleanOperation, graphNode, ProtoCore.DSASM.AssociativeSubCompilePass.kNone, bnode);
            subPass = ProtoCore.DSASM.AssociativeSubCompilePass.kUnboundIdentifier;

            if (bnode.LeftNode is IdentifierNode)
            {
                // TODO Jun: Cleansify this block where the lhs is being handled.
                // For one, make the return as a return node
                IdentifierNode t = bnode.LeftNode as IdentifierNode;
                ProtoCore.DSASM.SymbolNode symbolnode = null;

                ProtoCore.AssociativeGraph.UpdateNodeRef leftNodeGlobalRef = null;

                string s = t.Value;
                if (s == ProtoCore.DSDefinitions.Keyword.Return)
                {
                    Debug.Assert(null == symbolnode);
                    symbolnode = new ProtoCore.DSASM.SymbolNode();
                    symbolnode.name = s;
                    symbolnode.isTemp = s.StartsWith("%");
                    symbolnode.functionIndex = globalProcIndex;
                    symbolnode.classScope = globalClassIndex;

                    EmitReturnStatement(node, inferedType);

                    // Comment Jun: The inline conditional holds a graphnode and traversing its body will set isReturn = true
                    // Resolve that here as an inline conditional is obviosuly not a return graphnode
                    if (!graphNode.isInlineConditional)
                    {
                        graphNode.isReturn = true;
                    }
                }
                else
                {
                    leftNodeGlobalRef = GetUpdatedNodeRef(bnode.LeftNode);

                    // right node is statement which wont return any value, so push null to stack
                    if ((bnode.RightNode is IfStatementNode) || (bnode.RightNode is ForLoopNode))
                    {
                        EmitPushNull();
                    }
                    {
                        // 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);
                            }
                        }
                    }

                    //int type = (int)ProtoCore.PrimitiveType.kTypeVoid;
                    bool isAccessible = false;
                    bool isAllocated = VerifyAllocation(t.Name, globalClassIndex, globalProcIndex, out symbolnode, out isAccessible);
                    int runtimeIndex = (!isAllocated || !isAccessible) ? codeBlock.symbolTable.runtimeIndex : symbolnode.runtimeTableIndex;

                    if (isAllocated && !isAccessible)
                    {
                        string message = String.Format(ProtoCore.BuildData.WarningMessage.kPropertyIsInaccessible, t.Name);
                        buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kAccessViolation, message, compileStateTracker.CurrentDSFileName, t.line, t.col);
                    }

                    int dimensions = 0;
                    if (null != t.ArrayDimensions)
                    {
                        graphNode.isIndexingLHS = true;
                        dimensions = DfsEmitArrayIndexHeap(t.ArrayDimensions, graphNode, bnode);
                    }

                    // Comment Jun: Attempt to get the modified argument arrays in the current method
                    // Comment Jun: As of R1 - arrays are copy constructed and cannot propagate update unless explicitly returned
                    //ProtoCore.AssociativeGraph.UpdateNodeRef leftNodeArgArray = AutoGenerateUpdateArgumentArrayReference(bnode.LeftNode, graphNode);

                    ProtoCore.Type castType = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, false);
                    var tident = bnode.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)
                        {
                            castType = TypeSystem.BuildPrimitiveTypeObject(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 (ProtoCore.DSASM.Constants.kInvalidIndex != globalClassIndex)
                    {
                        // In a class
                        if (ProtoCore.DSASM.Constants.kInvalidIndex == globalProcIndex)
                        {
                            string message = "A binary assignment inside a class must be inside a function (AB5E3EC1)";
                            buildStatus.LogSemanticError(message, compileStateTracker.CurrentDSFileName, bnode.line, bnode.col);
                            throw new BuildHaltException(message);
                        }

                        // TODO Jun: refactor this by having symbol table functions for retrieval of node index
                        int symbol = ProtoCore.DSASM.Constants.kInvalidIndex;
                        bool isMemVar = false;
                        if (symbolnode != null)
                        {
                            if (symbolnode.classScope != ProtoCore.DSASM.Constants.kInvalidIndex
                                && symbolnode.functionIndex == ProtoCore.DSASM.Constants.kGlobalScope)
                            {
                                isMemVar = true;
                            }
                            symbol = symbolnode.symbolTableIndex;
                        }

                        ProtoCore.DSASM.StackValue op = new ProtoCore.DSASM.StackValue();

                        if (!isMemVar)
                        {
                            // This is local variable
                            // TODO Jun: If this local var exists globally, should it allocate a local copy?
                            if (!isAllocated || !isAccessible)
                            {
                                symbolnode = Allocate(globalClassIndex, globalClassIndex, globalProcIndex, t.Name, inferedType, ProtoCore.DSASM.Constants.kPrimitiveSize,
                                    false, ProtoCore.DSASM.AccessSpecifier.kPublic, ProtoCore.DSASM.MemoryRegion.kMemStack, bnode.line, bnode.col);

                                // Add the symbols during watching process to the watch symbol list.
                                if (compileStateTracker.ExecMode == ProtoCore.DSASM.InterpreterMode.kExpressionInterpreter)
                                {
                                    compileStateTracker.watchSymbolList.Add(symbolnode);
                                }

                                Debug.Assert(symbolnode != null);
                            }
                            else
                            {
                                symbolnode.datatype = inferedType;
                            }

                            if (bnode.LeftNode is TypedIdentifierNode)
                            {
                                symbolnode.SetStaticType(castType);
                            }
                            castType = symbolnode.staticType;
                            EmitPushVarData(runtimeIndex, dimensions, castType.UID, castType.rank);

                            symbol = symbolnode.symbolTableIndex;
                            if (t.Name == ProtoCore.DSASM.Constants.kTempArg)
                            {
                                EmitInstrConsole(ProtoCore.DSASM.kw.pop, t.Name);
                                EmitPopForSymbol(symbolnode);
                            }
                            else
                            {
                                if (compileStateTracker.ExecMode != ProtoCore.DSASM.InterpreterMode.kExpressionInterpreter)
                                {
                                    EmitInstrConsole(ProtoCore.DSASM.kw.pop, t.Name);
                                    EmitPopForSymbol(symbolnode, node.line, node.col, node.endLine, node.endCol);
                                }
                                else
                                {
                                    EmitInstrConsole(ProtoCore.DSASM.kw.popw, t.Name);
                                    EmitPopForSymbolW(symbolnode, node.line, node.col, node.endLine, node.endCol);
                                }
                            }
                        }
                        else
                        {
                            if (bnode.LeftNode is TypedIdentifierNode)
                            {
                                symbolnode.SetStaticType(castType);
                            }
                            castType = symbolnode.staticType;
                            EmitPushVarData(runtimeIndex, dimensions, castType.UID, castType.rank);

                            EmitInstrConsole(ProtoCore.DSASM.kw.popm, t.Name);

                            op.optype = (symbolnode.isStatic) ? ProtoCore.DSASM.AddressType.StaticMemVarIndex : ProtoCore.DSASM.AddressType.MemVarIndex;
                            op.opdata = symbol;
                            EmitPopm(op, node.line, node.col, node.endLine, node.endCol);
                        }

                        //if (t.Name[0] != '%')
                        {
                            AutoGenerateUpdateReference(bnode.LeftNode, graphNode);
                        }

                        // Dependency
                        if (!isTempExpression)
                        {
                            // Dependency graph top level symbol
                            graphNode.PushSymbolReference(symbolnode);
                            EmitDependency(bnode.exprUID, bnode.modBlkUID, bnode.isSSAAssignment);
                            functionCallStack.Clear();
                        }
                    }
                    else
                    {
                        if (!isAllocated)
                        {
                            symbolnode = Allocate(globalClassIndex, globalClassIndex, globalProcIndex, t.Name, inferedType, ProtoCore.DSASM.Constants.kPrimitiveSize,
                                    false, ProtoCore.DSASM.AccessSpecifier.kPublic, ProtoCore.DSASM.MemoryRegion.kMemStack, bnode.line, bnode.col);

                            if (compileStateTracker.ExecMode == ProtoCore.DSASM.InterpreterMode.kExpressionInterpreter)
                            {
                                compileStateTracker.watchSymbolList.Add(symbolnode);
                            }

                            if (dimensions > 0)
                            {
                                symbolnode.datatype.rank = dimensions;
                            }
                        }
                        else if (dimensions == 0)
                        {
                            symbolnode.datatype = inferedType;
                        }

                        //
                        // Jun Comment:
                        //      Update system uses the following registers:
                        //      _ex stores prev value of ident 't'  - VM assigned
                        //      _fx stores new value                - VM assigned
                        //

                        if (bnode.LeftNode is TypedIdentifierNode)
                        {
                            symbolnode.SetStaticType(castType);
                        }
                        castType = symbolnode.staticType;
                        EmitPushVarData(runtimeIndex, dimensions, castType.UID, castType.rank);

                        if (compileStateTracker.ExecMode != ProtoCore.DSASM.InterpreterMode.kExpressionInterpreter)
                        {
                            EmitInstrConsole(ProtoCore.DSASM.kw.pop, symbolnode.name);
                            EmitPopForSymbol(symbolnode, node.line, node.col, node.endLine, node.endCol);
                        }
                        else
                        {
                            EmitInstrConsole(ProtoCore.DSASM.kw.popw, symbolnode.name);
                            EmitPopForSymbolW(symbolnode, node.line, node.col, node.endLine, node.endCol);
                        }

                        AutoGenerateUpdateReference(bnode.LeftNode, graphNode);

                        // Dependency
                        if (!isTempExpression)
                        {
                            // Dependency graph top level symbol
                            graphNode.PushSymbolReference(symbolnode);
                            EmitDependency(bnode.exprUID, bnode.modBlkUID, bnode.isSSAAssignment);
                            functionCallStack.Clear();
                        }
                    }
                }

                // Dependency graph top level symbol
                //graphNode.symbol = symbolnode;

                // Assign the end pc to this graph node's update block
                // Dependency graph construction is complete for this expression
                if (!isTempExpression)
                {
                    if (null != leftNodeGlobalRef)
                    {
                        if (null != localProcedure)
                        {
                            // Track for updated globals only in user defined functions
                            if (!localProcedure.isAssocOperator && !localProcedure.isAutoGenerated)
                            {
                                localProcedure.updatedGlobals.Push(leftNodeGlobalRef);
                            }
                        }
                    }

                    graphNode.ResolveLHSArrayIndex();
                    graphNode.updateBlock.endpc = pc - 1;
                    codeBlock.instrStream.dependencyGraph.Push(graphNode);

                    SymbolNode cyclicSymbol1 = null;
                    SymbolNode cyclicSymbol2 = null;
                    if (compileStateTracker.Options.staticCycleCheck)
                    {
                        //UpdateGraphNodeDependency(graphNode);
                        if (!CyclicDependencyTest(graphNode, ref cyclicSymbol1, ref cyclicSymbol2))
                        {
                            Validity.Assert(null != cyclicSymbol1);
                            Validity.Assert(null != cyclicSymbol2);

                            //
                            // Set the first symbol that triggers the cycle to null
                            ProtoCore.AssociativeGraph.GraphNode nullAssignGraphNode1 = new ProtoCore.AssociativeGraph.GraphNode();
                            nullAssignGraphNode1.updateBlock.startpc = pc;

                            EmitPushNull();
                            EmitPushVarData(cyclicSymbol1.runtimeTableIndex, 0);
                            EmitInstrConsole(ProtoCore.DSASM.kw.pop, cyclicSymbol1.name);
                            EmitPopForSymbol(cyclicSymbol1, node.line, node.col, node.endLine, node.endCol);

                            nullAssignGraphNode1.PushSymbolReference(cyclicSymbol1);
                            nullAssignGraphNode1.procIndex = globalProcIndex;
                            nullAssignGraphNode1.classIndex = globalClassIndex;
                            nullAssignGraphNode1.updateBlock.endpc = pc - 1;

                            codeBlock.instrStream.dependencyGraph.Push(nullAssignGraphNode1);
                            EmitDependency(ProtoCore.DSASM.Constants.kInvalidIndex, ProtoCore.DSASM.Constants.kInvalidIndex, false);

                            //
                            // Set the second symbol that triggers the cycle to null
                            ProtoCore.AssociativeGraph.GraphNode nullAssignGraphNode2 = new ProtoCore.AssociativeGraph.GraphNode();
                            nullAssignGraphNode2.updateBlock.startpc = pc;

                            EmitPushNull();
                            EmitPushVarData(cyclicSymbol2.runtimeTableIndex, 0);
                            EmitInstrConsole(ProtoCore.DSASM.kw.pop, cyclicSymbol2.name);
                            EmitPopForSymbol(cyclicSymbol2, node.line, node.col, node.endLine, node.endCol);

                            nullAssignGraphNode2.PushSymbolReference(cyclicSymbol2);
                            nullAssignGraphNode2.procIndex = globalProcIndex;
                            nullAssignGraphNode2.classIndex = globalClassIndex;
                            nullAssignGraphNode2.updateBlock.endpc = pc - 1;

                            codeBlock.instrStream.dependencyGraph.Push(nullAssignGraphNode2);
                            EmitDependency(ProtoCore.DSASM.Constants.kInvalidIndex, ProtoCore.DSASM.Constants.kInvalidIndex, false);
                        }
                    }
                    if (isGraphInScope)
                    {
                        EmitCompileLog("==============End Node==============\n");
                    }
                }

                // Jun Comment: If it just so happens that the inline conditional is in the return statement
                if (graphNode.isInlineConditional)
                {
                    graphNode.isReturn = false;
                    if (0 == graphNode.updateNodeRefList.Count)
                    {
                        graphNode.isReturn = true;
                    }
                }
            }
            else
            {
                string message = "Illegal assignment (90787393)";
                buildStatus.LogSemanticError(message, compileStateTracker.CurrentDSFileName, bnode.line, bnode.col);
                throw new BuildHaltException(message);
            }
            compileStateTracker.DebugProps.breakOptions = oldOptions;

            //if post fix, now traverse the post fix

            #if ENABLE_INC_DEC_FIX
                if (bnode.RightNode is PostFixNode)
                    EmitPostFixNode(bnode.RightNode, ref inferedType);
            #endif
        }
Exemplo n.º 16
0
        private ProtoCore.DSASM.SymbolNode Allocate(
            int classIndex,  // In which class table this variable will be allocated to ?
            int classScope,  // Variable's class scope. For example, it is a variable in base class
            int funcIndex,   // In which function this variable is defined?
            string ident,
            ProtoCore.Type datatype,
            int datasize = ProtoCore.DSASM.Constants.kPrimitiveSize,
            bool isStatic = false,
            ProtoCore.DSASM.AccessSpecifier access = ProtoCore.DSASM.AccessSpecifier.kPublic,
            ProtoCore.DSASM.MemoryRegion region = ProtoCore.DSASM.MemoryRegion.kMemStack,
            int line = -1,
            int col = -1,
            GraphNode graphNode = null
            )
        {
            bool allocateForBaseVar = classScope < classIndex;
            bool isProperty = classIndex != Constants.kInvalidIndex && funcIndex == Constants.kInvalidIndex;
            if (!allocateForBaseVar && !isProperty && compileStateTracker.ClassTable.IndexOf(ident) != ProtoCore.DSASM.Constants.kInvalidIndex)
                buildStatus.LogSemanticError(ident + " is a class name, can't be used as a variable.", null, line, col, graphNode);

            ProtoCore.DSASM.SymbolNode symbolnode = new ProtoCore.DSASM.SymbolNode();
            symbolnode.name = ident;
            symbolnode.isTemp = ident.StartsWith("%");
            symbolnode.size = datasize;
            symbolnode.functionIndex = funcIndex;
            symbolnode.absoluteFunctionIndex = funcIndex;
            symbolnode.datatype = datatype;
            symbolnode.staticType = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, false);
            symbolnode.isArgument = false;
            symbolnode.memregion = region;
            symbolnode.classScope = classScope;
            symbolnode.absoluteClassScope = classScope;
            symbolnode.runtimeTableIndex = codeBlock.symbolTable.runtimeIndex;
            symbolnode.isStatic = isStatic;
            symbolnode.access = access;
            symbolnode.codeBlockId = codeBlock.codeBlockId;
            if (this.isEmittingImportNode)
                symbolnode.ExternLib = compileStateTracker.CurrentDSFileName;

            int symbolindex = ProtoCore.DSASM.Constants.kInvalidIndex;

            if (IsInLanguageBlockDefinedInFunction())
            {
                symbolnode.classScope = Constants.kGlobalScope;
                symbolnode.functionIndex = Constants.kGlobalScope;
            }

            if (ProtoCore.DSASM.Constants.kInvalidIndex != classIndex && !IsInLanguageBlockDefinedInFunction())
            {
                // NOTE: the following comment and code is OBSOLETE - member
                // variable is not supported now
                //
                // Yu Ke: it is possible that class table contains same-named
                // symbols if a class inherits some member variables from base
                // class, so we need to check name + class index + function
                // index.
                //
                //if (core.classTable.list[classIndex].symbols.IndexOf(ident, classIndex, funcIndex) != (int)ProtoCore.DSASM.Constants.kInvalidIndex)
                //    return null;

                symbolindex = compileStateTracker.ClassTable.ClassNodes[classIndex].symbols.IndexOf(ident);
                if (symbolindex != ProtoCore.DSASM.Constants.kInvalidIndex)
                {
                    ProtoCore.DSASM.SymbolNode node = compileStateTracker.ClassTable.ClassNodes[classIndex].symbols.symbolList[symbolindex];
                    if (node.functionIndex == ProtoCore.DSASM.Constants.kGlobalScope &&
                        funcIndex == ProtoCore.DSASM.Constants.kGlobalScope)
                        return null;
                }

                symbolindex = compileStateTracker.ClassTable.ClassNodes[classIndex].symbols.Append(symbolnode);
                if (symbolindex == ProtoCore.DSASM.Constants.kInvalidIndex)
                {
                    return null;
                }

                if (isStatic)
                {
                    Debug.Assert(funcIndex == ProtoCore.DSASM.Constants.kGlobalScope);
                    ProtoCore.DSASM.SymbolNode staticSymbolnode = new ProtoCore.DSASM.SymbolNode();
                    staticSymbolnode.name = ident;
                    staticSymbolnode.isTemp = ident.StartsWith("%");
                    staticSymbolnode.size = datasize;
                    staticSymbolnode.functionIndex = funcIndex;
                    staticSymbolnode.datatype = datatype;
                    staticSymbolnode.staticType = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, false);
                    staticSymbolnode.isArgument = false;
                    staticSymbolnode.memregion = region;
                    staticSymbolnode.classScope = classScope;
                    staticSymbolnode.runtimeTableIndex = codeBlock.symbolTable.runtimeIndex;
                    staticSymbolnode.isStatic = isStatic;
                    staticSymbolnode.access = access;
                    staticSymbolnode.codeBlockId = codeBlock.codeBlockId;
                    if (this.isEmittingImportNode)
                        staticSymbolnode.ExternLib = compileStateTracker.CurrentDSFileName;

                    // If inherits a static property from base class, that propery
                    // symbol should have been added to code block's symbol table,
                    // so we just update symbolTableIndex
                    int staticSymbolindex = codeBlock.symbolTable.IndexOf(ident, classScope);
                    if (staticSymbolindex == ProtoCore.DSASM.Constants.kInvalidIndex)
                    {
                        AllocateVar(staticSymbolnode);
                        staticSymbolindex = codeBlock.symbolTable.Append(staticSymbolnode);
                        if (staticSymbolindex == ProtoCore.DSASM.Constants.kInvalidIndex)
                        {
                            return null;
                        }
                        staticSymbolnode.symbolTableIndex = staticSymbolindex;
                    }
                    symbolnode.symbolTableIndex = staticSymbolindex;
                }
                else
                {
                    AllocateVar(symbolnode);
                }
            }
            else
            {
                // Do not import global symbols from external libraries
                //if(this.isEmittingImportNode && core.IsParsingPreloadedAssembly)
                //{
                //    bool importGlobalSymbolFromLib = !string.IsNullOrEmpty(symbolnode.ExternLib) &&
                //        symbolnode.functionIndex == -1 && symbolnode.classScope == -1;

                //    if (importGlobalSymbolFromLib)
                //    {
                //        return symbolnode;
                //    }
                //}

                AllocateVar(symbolnode);

                symbolindex = codeBlock.symbolTable.Append(symbolnode);
                if (symbolindex == ProtoCore.DSASM.Constants.kInvalidIndex)
                {
                    return null;
                }
                symbolnode.symbolTableIndex = symbolindex;

            }

            // TODO Jun: Set the symbol table index of the first local variable of 'funcIndex'
            if (null != localProcedure && null == localProcedure.firstLocal && !IsInLanguageBlockDefinedInFunction())
            {
                localProcedure.firstLocal = symbolnode.index;
            }

            if (ProtoCore.DSASM.Constants.kInvalidIndex == symbolindex)
            {
                return null;
            }
            return symbolnode;
        }
Exemplo n.º 17
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)
        {
            FunctionCallNode funcCall = null;
            string procName = null;
            List<ProtoCore.Type> arglist = new List<ProtoCore.Type>();
            ProtoCore.Type dotCallType = new ProtoCore.Type();
            dotCallType.UID = (int)PrimitiveType.kTypeVar;
            dotCallType.IsIndexable = false;

            ProtoCore.AssociativeGraph.UpdateNode updateNode = new ProtoCore.AssociativeGraph.UpdateNode();

            if (node is ProtoCore.AST.AssociativeAST.FunctionDotCallNode)
            {
                return TraverseDotFunctionCall(node, parentNode, lefttype, depth, ref inferedType, graphNode, subPass, bnode as BinaryExpressionNode);
            }
            else
            {
                funcCall = node as FunctionCallNode;
                procName = funcCall.Function.Name;

                int classIndex = compileStateTracker.ClassTable.IndexOf(procName);
                bool isAccessible;
                int dummy;

                // To support unamed constructor
                if (classIndex != Constants.kInvalidIndex)
                {
                    ProcedureNode constructor = compileStateTracker.ClassTable.ClassNodes[classIndex].GetMemberFunction(procName, arglist, globalClassIndex, out isAccessible, out dummy, true);
                    if (constructor != null && constructor.isConstructor)
                    {
                        FunctionCallNode rhsFNode = node as ProtoCore.AST.AssociativeAST.FunctionCallNode;
                        AssociativeNode classNode = nodeBuilder.BuildIdentfier(procName);
                        FunctionDotCallNode dotCallNode = ProtoCore.Utils.CoreUtils.GenerateCallDotNode(classNode, rhsFNode, compileStateTracker);
                        return TraverseDotFunctionCall(dotCallNode, parentNode, lefttype, depth, ref inferedType, graphNode, subPass, bnode as BinaryExpressionNode);
                    }
                }
            }

            foreach (AssociativeNode paramNode in funcCall.FormalArguments)
            {
                ProtoCore.Type paramType = new ProtoCore.Type();
                paramType.UID = (int)ProtoCore.PrimitiveType.kTypeVoid;
                paramType.IsIndexable = false;

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

                // 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.DSASM.AssociativeSubCompilePass.kUnboundIdentifier)
            {
                return null;
            }

            ProtoCore.DSASM.ProcedureNode procNode = null;
            int type = ProtoCore.DSASM.Constants.kInvalidIndex;

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

            // Check for the actual method, not the dot method
            // 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
                && procName != ProtoCore.DSASM.Constants.kFunctionPointerCall)
            {

                bool isAccessible;
                int realType;

                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);
                    type = lefttype = realType;

                    if (!isAccessible)
                    {
                        type = lefttype = realType;
                        procNode = null;
                        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 procNode;
                    }

                }
            }

            // 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 procNode;
                        }
                    }
                }
            }

            if (null != procNode)
            {
                if (procNode.isConstructor &&
                        (globalClassIndex != ProtoCore.DSASM.Constants.kInvalidIndex) &&
                        (globalProcIndex != ProtoCore.DSASM.Constants.kInvalidIndex) &&
                        (globalClassIndex == inferedType.UID))
                {
                    ProtoCore.DSASM.ProcedureNode contextProcNode = compileStateTracker.ClassTable.ClassNodes[globalClassIndex].vtable.procList[globalProcIndex];
                    if (contextProcNode.isConstructor &&
                        string.Equals(contextProcNode.name, procNode.name) &&
                        contextProcNode.runtimeIndex == procNode.runtimeIndex)
                    {
                        string message = String.Format(ProtoCore.BuildData.WarningMessage.kCallingConstructorInConstructor, procName);
                        buildStatus.LogWarning(ProtoCore.BuildData.WarningID.kCallingConstructorInConstructor, message, compileStateTracker.CurrentDSFileName, node.line, node.col );
                        inferedType.UID = (int)PrimitiveType.kTypeNull;
                        EmitPushNull();
                        return procNode;
                    }
                }

                inferedType = procNode.returntype;

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

                if (ProtoCore.DSASM.Constants.kInvalidIndex != procNode.procId)
                {

                    //
                    // ==============Establishing graphnode links in modified arguments=============
                    //
                    //  proc TraverseCall(node, graphnode)
                    //      ; Get the first procedure, this will only be the first visible procedure
                    //      ; Overloads will be handled at runtime
                    //      def fnode = getProcedure(node)
                    //
                    //      ; For every argument in the function call,
                    //      ; attach the modified property list and append it to the graphnode update list
                    //      foreach arg in node.args
                    //          if fnode.updatedArgProps is not null
                    //              def noderef = arg.ident (or identlist)
                    //              noderef.append(fnode.updatedArgProps)
                    //              graphnode.pushUpdateRef(noderef)
                    //          end
                    //      end
                    //  end
                    //
                    // =============================================================================
                    //

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

                        if (null != graphNode)
                        {
                            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.argInfoList.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(blockId, dimensions);

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

                    // Do not emit breakpoints at built-in methods like _add/_sub etc. - pratapa
                    if (procNode.isAssocOperator || procNode.name.Equals(ProtoCore.DSASM.Constants.kInlineConditionalMethodName))
                    {
                        EmitCall(procNode.procId, type, depth, ProtoCore.DSASM.Constants.kInvalidIndex, ProtoCore.DSASM.Constants.kInvalidIndex,
                                    ProtoCore.DSASM.Constants.kInvalidIndex, ProtoCore.DSASM.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 (compileStateTracker.DebugProps.breakOptions.HasFlag(DebugProperties.BreakpointOptions.EmitInlineConditionalBreakpoint))
                    {
                        Validity.Assert(compileStateTracker.DebugProps.highlightRange != null);

                        ProtoCore.CodeModel.CodePoint startInclusive = compileStateTracker.DebugProps.highlightRange.StartInclusive;
                        ProtoCore.CodeModel.CodePoint endExclusive = compileStateTracker.DebugProps.highlightRange.EndExclusive;

                        EmitCall(procNode.procId, type, depth, 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.procId, type, depth, bnode.line, bnode.col, bnode.endLine, bnode.endCol, procNode.pc);
                    }
                    else
                    {
                        EmitCall(procNode.procId, type, depth, funcCall.line, funcCall.col, funcCall.endLine, funcCall.endCol, procNode.pc);
                    }

                    // 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);

                    if (dotCallType.UID != (int)PrimitiveType.kTypeVar)
                    {
                        inferedType.UID = dotCallType.UID;
                    }
                }
            }
            else
            {
                if (depth <= 0 && procName != ProtoCore.DSASM.Constants.kFunctionPointerCall)
                {
                    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;
        }
Exemplo n.º 18
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;
            }
        }
Exemplo n.º 19
0
        /*
         proc EmitIdentNode(identnode, graphnode)
            if ssa
                // Check an if this identifier is array indexed
                // The array index is a secondary property and is not the original array property of the AST. this is required because this array index is meant only to resolve graphnode dependency with arrays
                if node.arrayindex.secondary is valid
                    dimension = traverse(node.arrayindex.secondary)

                    // Create a new dependent with the array indexing
                    dependent = new GraphNode(identnode.name, dimension)
                    graphnode.pushdependent(dependent)
                end
            end
        end

         */
        private void EmitIdentifierNode(AssociativeNode node, ref ProtoCore.Type inferedType, bool isBooleanOp = false, ProtoCore.AssociativeGraph.GraphNode graphNode = null, ProtoCore.DSASM.AssociativeSubCompilePass subPass = ProtoCore.DSASM.AssociativeSubCompilePass.kNone, BinaryExpressionNode parentNode = null)
        {
            IdentifierNode t = node as IdentifierNode;
            if (t.Name.Equals(ProtoCore.DSDefinitions.Keyword.This))
            {
                if (subPass != AssociativeSubCompilePass.kNone)
                {
                    return;
                }

                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(subPass);
                        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;

            ProtoCore.DSASM.SymbolNode symbolnode = null;
            int runtimeIndex = codeBlock.symbolTable.runtimeIndex;

            ProtoCore.Type type = new ProtoCore.Type();
            type.UID = (int)ProtoCore.PrimitiveType.kTypeVoid;
            type.IsIndexable = false;

            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;
                        if (ProtoCore.DSASM.AssociativeSubCompilePass.kUnboundIdentifier != subPass)
                        {
                            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.Name, globalClassIndex, globalProcIndex, out symbolnode, out isAccessible);

            // If its executing in interpreter mode - attempt to find and anubond identifer in a child block
            // Remove this, because if we are watching cases like:
            //c1 = [Imperative]
            //{
            //    a = 1;
            //    b = 2;
            //}
            //
            //c2 = [Associative]
            //{
            //    a = 3;
            //    b = 4;
            //}
            //After c2 is executed, the watch value for a, b will be 1, 2.
            //if (ProtoCore.DSASM.ExecutionMode.kExpressionInterpreter == core.ExecMode)
            //{
            //    if (!isAllocated)
            //    {
            //        isAllocated = VerifyAllocationIncludingChildBlock(t.Name, globalClassIndex, globalProcIndex, out symbolnode, out isAccessible);
            //    }
            //}

            if (AssociativeSubCompilePass.kUnboundIdentifier == subPass)
            {
                if (symbolnode == null)
                {
                    if (isAllocated)
                    {
                        string message = String.Format(WarningMessage.kPropertyIsInaccessible, t.Value);
                        if (localProcedure != null && localProcedure.isStatic)
                        {
                            SymbolNode tempSymbolNode;

                            VerifyAllocation(
                                t.Name,
                                globalClassIndex,
                                Constants.kGlobalScope,
                                out tempSymbolNode,
                                out isAccessible);

                            if (tempSymbolNode != null && !tempSymbolNode.isStatic && isAccessible)
                            {
                                message = String.Format(WarningMessage.kUsingNonStaticMemberInStaticContext, t.Value);
                            }
                        }
                        buildStatus.LogWarning(
                            ProtoCore.BuildData.WarningID.kAccessViolation,
                            message,
                            compileStateTracker.CurrentDSFileName,
                            t.line,
                            t.col);
                    }
                    else
                    {
                        string message = String.Format(WarningMessage.kUnboundIdentifierMsg, t.Value);
                        buildStatus.LogWarning(WarningID.kIdUnboundIdentifier, message, compileStateTracker.CurrentDSFileName, t.line, t.col);
                    }

                    if (ProtoCore.DSASM.InterpreterMode.kExpressionInterpreter != compileStateTracker.ExecMode)
                    {
                        inferedType.UID = (int)ProtoCore.PrimitiveType.kTypeNull;

                        // Jun Comment: Specification
                        //      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)

                        int startpc = pc;
                        EmitPushNull();

                        // Push the identifier local block
                        dimensions = 0;
                        EmitPushVarData(runtimeIndex, dimensions);

                        ProtoCore.Type varType = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, false, 0);

                        // TODO Jun: Refactor Allocate() to just return the symbol node itself
                        ProtoCore.DSASM.SymbolNode symnode = Allocate(globalClassIndex, globalClassIndex, globalProcIndex, t.Value, varType, ProtoCore.DSASM.Constants.kPrimitiveSize,
                            false, ProtoCore.DSASM.AccessSpecifier.kPublic, ProtoCore.DSASM.MemoryRegion.kMemStack, t.line, t.col, graphNode);
                        Debug.Assert(symnode != null);

                        int symbolindex = symnode.symbolTableIndex;
                        if (ProtoCore.DSASM.Constants.kInvalidIndex != globalClassIndex)
                        {
                            symbolnode = compileStateTracker.ClassTable.ClassNodes[globalClassIndex].symbols.symbolList[symbolindex];
                        }
                        else
                        {
                            symbolnode = codeBlock.symbolTable.symbolList[symbolindex];
                        }

                        EmitInstrConsole(ProtoCore.DSASM.kw.pop, t.Value);
                        EmitPopForSymbol(symnode);

                        // Comment it out. It doesn't work for the following
                        // case:
                        //
                        //     x = foo.X;
                        //     x = bar.X;
                        //
                        // where bar hasn't defined yet, so a null assign
                        // graph is generated for this case:
                        //
                        //    bar = null;
                        //    x = %dot(.., {bar}, ...);
                        //
                        // unfortunately the expression UID of this null graph
                        // node is 0, which is wrong. Some update routines have
                        // the assumption that the exprUID of graph node is
                        // incremental.
                        //
                        // We may generate SSA for all expressions to fix this
                        // issue. -Yu Ke
                        /*
                        ProtoCore.AssociativeGraph.GraphNode nullAssignGraphNode = new ProtoCore.AssociativeGraph.GraphNode();
                        nullAssignGraphNode.PushSymbolReference(symbolnode);
                        nullAssignGraphNode.procIndex = globalProcIndex;
                        nullAssignGraphNode.classIndex = globalClassIndex;
                        nullAssignGraphNode.updateBlock.startpc = startpc;
                        nullAssignGraphNode.updateBlock.endpc = pc - 1;

                        codeBlock.instrStream.dependencyGraph.Push(nullAssignGraphNode);
                        */
                    }
                }

                if (null != t.ArrayDimensions)
                {
                    dimensions = DfsEmitArrayIndexHeap(t.ArrayDimensions, graphNode, parentNode, subPass);
                }
            }
            else
            {
                if (compileStateTracker.ExecMode == ProtoCore.DSASM.InterpreterMode.kExpressionInterpreter &&
                    !isAllocated)
                {
                    // It happens when the debugger try to watch a variable
                    // which has been out of scope (as watch is done through
                    // execute an expression "t = v;" where v is the variable
                    // to be watched.
                    EmitPushNull();
                    return;
                }

                Validity.Assert(isAllocated);

                if (graphNode != null
                    && IsAssociativeArrayIndexing
                    && !CoreUtils.IsAutoGeneratedVar(symbolnode.name))
                {
                    ProtoCore.AssociativeGraph.UpdateNode updateNode = new ProtoCore.AssociativeGraph.UpdateNode();
                    updateNode.symbol = symbolnode;
                    updateNode.nodeType = ProtoCore.AssociativeGraph.UpdateNodeType.kSymbol;

                    if (graphNode.isIndexingLHS)
                    {
                        graphNode.dimensionNodeList.Add(updateNode);
                    }
                    else
                    {
                        int curDepIndex = graphNode.dependentList.Count - 1;
                        if (curDepIndex >= 0)
                        {
                            var curDep = graphNode.dependentList[curDepIndex].updateNodeRefList[0].nodeList[0];
                            curDep.dimensionNodeList.Add(updateNode);

                            if (null != firstSSAGraphNode)
                            {
                                curDepIndex = firstSSAGraphNode.dependentList.Count - 1;
                                if (curDepIndex >= 0)
                                {
                                    ProtoCore.AssociativeGraph.UpdateNode firstSSAUpdateNode = firstSSAGraphNode.dependentList[curDepIndex].updateNodeRefList[0].nodeList[0];
                                    firstSSAUpdateNode.dimensionNodeList.Add(updateNode);
                                }
                            }
                        }
                    }
                }

                // If it is a property, replaced it with getter: %get_prop()
                if (symbolnode.classScope != ProtoCore.DSASM.Constants.kInvalidIndex &&
                    symbolnode.functionIndex == ProtoCore.DSASM.Constants.kGlobalScope &&
                    localProcedure != null)
                {
                    string getterName = ProtoCore.DSASM.Constants.kGetterPrefix + t.Name;
                    if (!string.Equals(localProcedure.name, getterName))
                    {
                        var thisNode = nodeBuilder.BuildIdentfier(ProtoCore.DSDefinitions.Keyword.This);
                        var identListNode = nodeBuilder.BuildIdentList(thisNode, t);
                        EmitIdentifierListNode(identListNode, ref inferedType, false, graphNode, ProtoCore.DSASM.AssociativeSubCompilePass.kNone);

                        if (null != graphNode)
                        {
                            ProtoCore.AssociativeGraph.GraphNode dependentNode = new ProtoCore.AssociativeGraph.GraphNode();
                            dependentNode.PushSymbolReference(symbolnode);
                            graphNode.PushDependent(dependentNode);
                        }

                        return;
                    }
                }

                type = symbolnode.datatype;
                runtimeIndex = symbolnode.runtimeTableIndex;

                // The graph node always depends on this identifier
                if (null != graphNode)
                {
                    ProtoCore.AssociativeGraph.GraphNode dependentNode = new ProtoCore.AssociativeGraph.GraphNode();
                    dependentNode.PushSymbolReference(symbolnode);
                    graphNode.PushDependent(dependentNode);
                }

                bool emitReplicationGuideFlag = emitReplicationGuide;
                emitReplicationGuide = false;
                if (null != t.ArrayDimensions)
                {
                    dimensions = DfsEmitArrayIndexHeap(t.ArrayDimensions, graphNode, parentNode, subPass);
                }
                emitReplicationGuide = emitReplicationGuideFlag;

                //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);

                if (ProtoCore.DSASM.InterpreterMode.kExpressionInterpreter == compileStateTracker.ExecMode)
                {
                    EmitInstrConsole(ProtoCore.DSASM.kw.pushw, t.Value);
                    EmitPushForSymbolW(symbolnode, t.line, t.col);
                }
                else
                {
                    EmitInstrConsole(ProtoCore.DSASM.kw.push, t.Value);
                    EmitPushForSymbol(symbolnode, t);

                    if (compileStateTracker.Options.TempReplicationGuideEmptyFlag && emitReplicationGuide)
                    {
                        int guides = EmitReplicationGuides(t.ReplicationGuides);
                        EmitInstrConsole(ProtoCore.DSASM.kw.pushindex, guides + "[guide]");
                        EmitPushReplicationGuide(guides);
                    }
                }

                if (ignoreRankCheck || 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 : inferedType.UID;
            }
        }
Exemplo n.º 20
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;
        }
Exemplo n.º 21
0
        private void EmitLHSIdentifierListForBinaryExpr(AssociativeNode bnode, ref ProtoCore.Type inferedType, bool isBooleanOp = false, ProtoCore.AssociativeGraph.GraphNode graphNode = null, ProtoCore.DSASM.AssociativeSubCompilePass subPass = ProtoCore.DSASM.AssociativeSubCompilePass.kNone, bool isTempExpression = false)
        {
            BinaryExpressionNode binaryExpr = bnode as BinaryExpressionNode;
            if (binaryExpr == null || !(binaryExpr.LeftNode is IdentifierListNode))
            {
                return;
            }

            if (ProtoCore.DSASM.Constants.kInvalidIndex == graphNode.updateBlock.startpc)
            {
                graphNode.updateBlock.startpc = pc;
            }

            // This is a setter, so disable dependents
            graphNode.allowDependents = false;
            IdentifierListNode theLeftNode = binaryExpr.LeftNode as IdentifierListNode;
            bool isThisPtr = null != theLeftNode.LeftNode.Name && theLeftNode.LeftNode.Name.Equals(ProtoCore.DSDefinitions.Keyword.This);
            if (isThisPtr)
            {
                graphNode.allowDependents = true;
            }

            ProtoCore.AssociativeGraph.UpdateNodeRef leftNodeRef = AutoGenerateUpdateReference(binaryExpr.LeftNode, graphNode);
            ProtoCore.AssociativeGraph.UpdateNodeRef leftNodeArgRef = AutoGenerateUpdateArgumentReference(binaryExpr.LeftNode, graphNode);

            ProtoCore.AST.Node lnode = binaryExpr.LeftNode;
            NodeUtils.CopyNodeLocation(lnode, binaryExpr);

            ProtoCore.AST.Node rnode = binaryExpr.RightNode;
            bool isCollapsed = false;
            EmitGetterSetterForIdentList(lnode, ref inferedType, graphNode, subPass, out isCollapsed, rnode);

            graphNode.allowDependents = true;

            // Dependency
            if (!isTempExpression)
            {
                // Dependency graph top level symbol
                graphNode.updateNodeRefList.Add(leftNodeRef);
                graphNode.updateNodeRefList[0].nodeList[0].dimensionNodeList = graphNode.dimensionNodeList;

                // @keyu: foo.id = 42; will generate same leftNodeRef and leftNodeArgRef
                if (!isThisPtr && !leftNodeRef.IsEqual(leftNodeArgRef))
                {
                    graphNode.updateNodeRefList.Add(leftNodeArgRef);
                }

                //
                // If the lhs of the expression is an identifier list, it could have been modified.
                // It must then be a dependent of its own graphnode
                //
                //      class C
                //      {
                //          x : int;
                //          constructor C(i:int)
                //          {
                //              x = i;
                //          }
                //      }
                //
                //      i = 10;
                //      a = C.C(i);
                //      a.x = 15; -> re-execute this line ... as 'a' was redefined and its members now changed
                //      val = a.x;
                //      i = 7;
                //

                //
                // If inside a member function, and the lhs is a property, make sure it is not just:
                //      x = y (this.x = y)
                //

                if (compileStateTracker.Options.LHSGraphNodeUpdate)
                {
                    if (!isThisPtr || graphNode.updateNodeRefList[0].nodeList.Count > 1)
                    {
                        ProtoCore.AssociativeGraph.GraphNode dependentNode = new ProtoCore.AssociativeGraph.GraphNode();
                        dependentNode.isLHSNode = true;
                        dependentNode.updateNodeRefList.Add(graphNode.updateNodeRefList[0]);
                        graphNode.dependentList.Add(dependentNode);
                    }
                }

                // Move the pointer to FX
                ProtoCore.DSASM.StackValue opFX = new ProtoCore.DSASM.StackValue();
                opFX.optype = ProtoCore.DSASM.AddressType.Register;
                opFX.opdata = (int)ProtoCore.DSASM.Registers.FX;

                ProtoCore.DSASM.SymbolNode firstSymbol = leftNodeRef.nodeList[0].symbol;
                if (null != firstSymbol)
                {
                    EmitDependency(binaryExpr.exprUID, binaryExpr.modBlkUID, false);
                }

                // Assign the end pc to this graph node's update block
                // Dependency graph construction is complete for this expression
                graphNode.updateBlock.endpc = pc - 1;
                codeBlock.instrStream.dependencyGraph.Push(graphNode);

                functionCallStack.Clear();
            }
        }
Exemplo n.º 22
0
        private bool IsDependentSubNode(GraphNode node, GraphNode subNode)
        {
            if (subNode.UID == node.UID
                || subNode.exprUID == node.exprUID
                || subNode.ssaSubExpressionID == node.ssaSubExpressionID
                || subNode.procIndex != node.procIndex
                || subNode.classIndex != node.classIndex
                || subNode.isReturn)
            {
                return false;
            }

            ProtoCore.AssociativeGraph.GraphNode matchingNode = null;
            if (!subNode.DependsOn(node.updateNodeRefList[0], ref matchingNode))
            {
                return false;
            }

            return true;
        }
Exemplo n.º 23
0
        private GraphNode GetFinanlStatementOfSSA(GraphNode subNode, ref int index)
        {
            if (subNode.updateNodeRefList.Count <= 0)
            {
                return subNode;
            }

            Validity.Assert(null != subNode.updateNodeRefList[0].nodeList);
            Validity.Assert(subNode.updateNodeRefList[0].nodeList.Count > 0);
            if (subNode.updateNodeRefList[0].nodeList[0].nodeType != ProtoCore.AssociativeGraph.UpdateNodeType.kMethod)
            {
                bool isSSAStatement = ProtoCore.Utils.CoreUtils.IsSSATemp(subNode.updateNodeRefList[0].nodeList[0].symbol.name);
                if (isSSAStatement)
                {
                    while (ProtoCore.DSASM.Constants.kInvalidIndex != subNode.exprUID)
                    {
                        subNode = codeBlock.instrStream.dependencyGraph.GraphList[++index];
                        if (!ProtoCore.Utils.CoreUtils.IsSSATemp(subNode.updateNodeRefList[0].nodeList[0].symbol.name))
                        {
                            break;
                        }
                    }
                }
            }
            return subNode;
        }
Exemplo n.º 24
0
        // @keyu: Tarjan's strongly connected components algorithm is used here... 
        // http://en.wikipedia.org/wiki/Tarjan's_strongly_connected_components_algorithm
        // 
        // Returns the first strongly connected component
        private List<GraphNode> StrongConnectComponent(GraphNode node, ref int index, Dictionary<GraphNode, int> lowlinkMap, Dictionary<GraphNode, int> indexMap, Stack<GraphNode> S)
        {
            indexMap[node] = index;
            lowlinkMap[node] = index;
            index++;
            S.Push(node);

            for (int n = 0; n < codeBlock.instrStream.dependencyGraph.GraphList.Count; ++n)
            {
                ProtoCore.AssociativeGraph.GraphNode subNode = codeBlock.instrStream.dependencyGraph.GraphList[n];

                if (!subNode.isActive)
                {
                    continue;
                }

                if (!IsDependentSubNode(node, subNode))
                {
                    continue;
                }

                bool equalIdentList = ProtoCore.AssociativeEngine.Utils.AreLHSEqualIdentList(node, subNode);
                if (equalIdentList)
                {
                    continue;
                }

                // No update for auto generated temps
                bool isTempVarUpdate = ProtoCore.AssociativeEngine.Utils.IsTempVarLHS(node);
                if (isTempVarUpdate)
                {
                    continue;
                }

                subNode = GetFinanlStatementOfSSA(subNode, ref n);

                if (indexMap[subNode] == Constants.kInvalidIndex)
                {
                    StrongConnectComponent(subNode, ref index, lowlinkMap, indexMap, S);
                    lowlinkMap[node] = Math.Min(lowlinkMap[node], lowlinkMap[subNode]);
                }
                else if (S.Contains(subNode))
                {
                    lowlinkMap[node] = Math.Min(lowlinkMap[node], indexMap[subNode]);
                }
            }

            if (lowlinkMap[node] == indexMap[node] && S.Count > 1)
            {
                List<GraphNode> dependencyList = new List<GraphNode>();
                while (true)
                {
                    GraphNode w = S.Pop();
                    dependencyList.Add(w);
                    if (w.UID == node.UID)
                    {
                        break;
                    }
                }

                return dependencyList;
            }

            return null;
        }
Exemplo n.º 25
0
        private bool IsDependentSubNode(GraphNode node, GraphNode subNode)
        {
            if (subNode.UID == node.UID
                || subNode.exprUID == node.exprUID
                || (subNode.modBlkUID == node.modBlkUID && node.modBlkUID != ProtoCore.DSASM.Constants.kInvalidIndex)
                || subNode.procIndex != node.procIndex
                || subNode.classIndex != node.classIndex
                || subNode.isReturn)
            {
                return false;
            }

            ProtoCore.AssociativeGraph.GraphNode matchingNode = null;
            if (!subNode.DependsOn(node.updateNodeRefList[0], ref matchingNode))
            {
                return false;
            }

            return true;
        }
Exemplo n.º 26
0
        private ProtoCore.DSASM.SymbolNode Allocate(
            int classIndex,  // In which class table this variable will be allocated to ?
            int classScope,  // Variable's class scope. For example, it is a variable in base class
            int funcIndex,   // In which function this variable is defined? 
            string ident, 
            ProtoCore.Type datatype, 
            int datasize = ProtoCore.DSASM.Constants.kPrimitiveSize, 
            bool isStatic = false,
            ProtoCore.CompilerDefinitions.AccessModifier access = ProtoCore.CompilerDefinitions.AccessModifier.kPublic,
            ProtoCore.DSASM.MemoryRegion region = ProtoCore.DSASM.MemoryRegion.kMemStack,
            int line = -1,
            int col = -1,
            GraphNode graphNode = null
            )
        {
            bool allocateForBaseVar = classScope < classIndex;
            bool isProperty = classIndex != Constants.kInvalidIndex && funcIndex == Constants.kInvalidIndex;
            if (!allocateForBaseVar && !isProperty && core.ClassTable.IndexOf(ident) != ProtoCore.DSASM.Constants.kInvalidIndex)
                buildStatus.LogSemanticError(String.Format(Resources.ClassNameAsVariableError, ident), null, line, col, graphNode);

            ProtoCore.DSASM.SymbolNode symbolnode = new ProtoCore.DSASM.SymbolNode();
            symbolnode.name = ident;
            symbolnode.isTemp = ident.StartsWith("%");
            symbolnode.size = datasize;
            symbolnode.functionIndex = funcIndex;
            symbolnode.absoluteFunctionIndex = funcIndex;
            symbolnode.datatype = datatype;
            symbolnode.staticType = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, Constants.kArbitraryRank);
            symbolnode.isArgument = false;
            symbolnode.memregion = region;
            symbolnode.classScope = classScope;
            symbolnode.absoluteClassScope = classScope;
            symbolnode.runtimeTableIndex = codeBlock.symbolTable.RuntimeIndex;
            symbolnode.isStatic = isStatic;
            symbolnode.access = access;
            symbolnode.codeBlockId = codeBlock.codeBlockId;
            if (this.isEmittingImportNode)
                symbolnode.ExternLib = core.CurrentDSFileName;

            int symbolindex = ProtoCore.DSASM.Constants.kInvalidIndex;

            if (IsInLanguageBlockDefinedInFunction())
            {
                symbolnode.classScope = Constants.kGlobalScope;
                symbolnode.functionIndex = Constants.kGlobalScope;
            }

            if (ProtoCore.DSASM.Constants.kInvalidIndex != classIndex && !IsInLanguageBlockDefinedInFunction())
            {
                // NOTE: the following comment and code is OBSOLETE - member
                // variable is not supported now
                // 
                // Yu Ke: it is possible that class table contains same-named 
                // symbols if a class inherits some member variables from base 
                // class, so we need to check name + class index + function 
                // index.
                // 
                //if (core.classTable.list[classIndex].symbols.IndexOf(ident, classIndex, funcIndex) != (int)ProtoCore.DSASM.Constants.kInvalidIndex)
                //    return null;

                symbolindex = core.ClassTable.ClassNodes[classIndex].Symbols.IndexOf(ident);
                if (symbolindex != ProtoCore.DSASM.Constants.kInvalidIndex)
                {
                    ProtoCore.DSASM.SymbolNode node = core.ClassTable.ClassNodes[classIndex].Symbols.symbolList[symbolindex];
                    if (node.functionIndex == ProtoCore.DSASM.Constants.kGlobalScope &&
                        funcIndex == ProtoCore.DSASM.Constants.kGlobalScope)
                        return null;
                }

                symbolindex = core.ClassTable.ClassNodes[classIndex].Symbols.Append(symbolnode);
                if (symbolindex == ProtoCore.DSASM.Constants.kInvalidIndex)
                {
                    return null;
                }

                if (isStatic)
                {
                    Validity.Assert(funcIndex == ProtoCore.DSASM.Constants.kGlobalScope);
                    ProtoCore.DSASM.SymbolNode staticSymbolnode = new ProtoCore.DSASM.SymbolNode();
                    staticSymbolnode.name = ident;
                    staticSymbolnode.isTemp = ident.StartsWith("%");
                    staticSymbolnode.size = datasize;
                    staticSymbolnode.functionIndex = funcIndex;
                    staticSymbolnode.datatype = datatype;
                    staticSymbolnode.staticType = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, Constants.kArbitraryRank);
                    staticSymbolnode.isArgument = false;
                    staticSymbolnode.memregion = region;
                    staticSymbolnode.classScope = classScope;
                    staticSymbolnode.runtimeTableIndex = codeBlock.symbolTable.RuntimeIndex;
                    staticSymbolnode.isStatic = isStatic;
                    staticSymbolnode.access = access;
                    staticSymbolnode.codeBlockId = codeBlock.codeBlockId;
                    if (this.isEmittingImportNode)
                        staticSymbolnode.ExternLib = core.CurrentDSFileName;

                    // If inherits a static property from base class, that propery
                    // symbol should have been added to code block's symbol table,
                    // so we just update symbolTableIndex 
                    int staticSymbolindex = codeBlock.symbolTable.IndexOf(ident, classScope);
                    if (staticSymbolindex == ProtoCore.DSASM.Constants.kInvalidIndex)
                    {
                        AllocateVar(staticSymbolnode);
                        staticSymbolindex = codeBlock.symbolTable.Append(staticSymbolnode);
                        if (staticSymbolindex == ProtoCore.DSASM.Constants.kInvalidIndex)
                        {
                            return null;
                        }
                        staticSymbolnode.symbolTableIndex = staticSymbolindex;
                    }
                    symbolnode.symbolTableIndex = staticSymbolindex;
                }
                else
                {
                    AllocateVar(symbolnode);
                }
            }
            else
            {               
                AllocateVar(symbolnode);

                symbolindex = codeBlock.symbolTable.Append(symbolnode);
                if (symbolindex == ProtoCore.DSASM.Constants.kInvalidIndex)
                {
                    return null;
                }
                symbolnode.symbolTableIndex = symbolindex;
                
            }

            if (ProtoCore.DSASM.Constants.kInvalidIndex == symbolindex)
            {
                return null;
            }
            return symbolnode;
        }
Exemplo n.º 27
0
        private void EmitBinaryExpressionNode(AssociativeNode node, ref ProtoCore.Type inferedType, bool isBooleanOp = false, ProtoCore.AssociativeGraph.GraphNode graphNode = null, ProtoCore.CompilerDefinitions.Associative.SubCompilePass subPass = ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kNone, bool isTempExpression = false)
        {
            BinaryExpressionNode bnode = null;

            if (!IsParsingGlobal() && !IsParsingGlobalFunctionBody() && !IsParsingMemberFunctionBody())
                return;

            bool isBooleanOperation = false;
            bnode = node as BinaryExpressionNode;
            ProtoCore.Type leftType = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, 0);
            ProtoCore.Type rightType = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, 0);

            DebugProperties.BreakpointOptions oldOptions = core.DebuggerProperties.breakOptions;
            
            // If this is an assignment statement, setup the top level graph node
            bool isGraphInScope = false;
            if (ProtoCore.DSASM.Operator.assign == bnode.Optr)
            {
                if (null == graphNode)
                {
                    isGraphInScope = true;
                    EmitCompileLog("==============Start Node==============\n");
                    graphNode = new ProtoCore.AssociativeGraph.GraphNode();
                    graphNode.AstID = bnode.ID;
                    graphNode.OriginalAstID = bnode.OriginalAstID; 
                    graphNode.exprUID = bnode.ExpressionUID;
                    graphNode.ssaSubExpressionID = bnode.SSASubExpressionID;
                    graphNode.ssaExpressionUID = bnode.SSAExpressionUID;
                    graphNode.IsModifier = bnode.IsModifier;
                    graphNode.guid = bnode.guid;
                    graphNode.procIndex = globalProcIndex;
                    graphNode.classIndex = globalClassIndex;
                    graphNode.languageBlockId = codeBlock.codeBlockId;
                    graphNode.ProcedureOwned = bnode.IsProcedureOwned;


                    //
                    // Comment Jun: 
                    //      If the expression ID of the assignment node in the context execDirtyFlag list is false,
                    //      it means that it was already executed. This needs to be marked as not dirty
                    if (core.Options.IsDeltaExecution)
                    {
                        if (context.exprExecutionFlags.ContainsKey(bnode.ExpressionUID))
                        {
                            graphNode.isDirty = context.exprExecutionFlags[bnode.ExpressionUID];
                        }
                    }
                }

                if (bnode.isSSAFirstAssignment)
                {
                    firstSSAGraphNode = graphNode;
                }
                HandlePointerList(bnode);
                        

                if (bnode.LeftNode is IdentifierListNode)
                {
                    // If the lhs is an identifierlist then emit the entire expression here
                    // This also handles the dependencies of expressions where the lhs is a member variable (this.x = y)
                    EmitLHSIdentifierListForBinaryExpr(bnode, ref inferedType, isBooleanOp, graphNode, subPass);
                    if (isGraphInScope)
                    {
                        EmitCompileLog("==============End Node==============\n");
                    }
                    return;
                }
                else if (bnode.LeftNode is IdentifierNode)
                {
                    if (bnode.LeftNode.Name.Equals(ProtoCore.DSDefinitions.Keyword.This))
                    {
                        string errorMessage = ProtoCore.Properties.Resources.kInvalidThis;
                        if (localProcedure != null)
                        {
                            if (localProcedure.IsStatic)
                            {
                                errorMessage = ProtoCore.Properties.Resources.kUsingThisInStaticFunction;
                            }
                            else if (localProcedure.ClassID == Constants.kGlobalScope)
                            {
                                errorMessage = ProtoCore.Properties.Resources.kInvalidThis;
                            }
                            else
                            {
                                errorMessage = ProtoCore.Properties.Resources.kAssingToThis;
                            }
                        }
                        core.BuildStatus.LogWarning(WarningID.kInvalidThis, errorMessage, core.CurrentDSFileName, bnode.line, bnode.col, graphNode);

                        if (isGraphInScope)
                        {
                            EmitCompileLog("==============End Node==============\n");
                        }

                        return;
                    }

                    if (EmitLHSThisDotProperyForBinaryExpr(bnode, ref inferedType, isBooleanOp, graphNode, subPass))
                    {
                        if (isGraphInScope)
                        {
                            EmitCompileLog("==============End Node==============\n");
                        }
                        return;
                    }
                }
            }
            else //(ProtoCore.DSASM.Operator.assign != b.Optr)
            {
                // Traversing the left node if this binary expression is not an assignment
                //
                isBooleanOperation = ProtoCore.DSASM.Operator.lt == bnode.Optr
                     || ProtoCore.DSASM.Operator.gt == bnode.Optr
                     || ProtoCore.DSASM.Operator.le == bnode.Optr
                     || ProtoCore.DSASM.Operator.ge == bnode.Optr
                     || ProtoCore.DSASM.Operator.eq == bnode.Optr
                     || ProtoCore.DSASM.Operator.nq == bnode.Optr
                     || ProtoCore.DSASM.Operator.and == bnode.Optr
                     || ProtoCore.DSASM.Operator.or == bnode.Optr;

                DfsTraverse(bnode.LeftNode, ref inferedType, isBooleanOperation, graphNode, subPass);

                if (inferedType.UID == (int)PrimitiveType.kTypeFunctionPointer && subPass != ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kUnboundIdentifier && emitDebugInfo)
                {
                    buildStatus.LogSemanticError(Resources.FunctionPointerNotAllowedAtBinaryExpression, core.CurrentDSFileName, bnode.LeftNode.line, bnode.LeftNode.col);
                }

                leftType.UID = inferedType.UID;
                leftType.rank = inferedType.rank;
            }

            int startpc = ProtoCore.DSASM.Constants.kInvalidIndex;
            if ((ProtoCore.DSASM.Operator.assign == bnode.Optr) && (bnode.RightNode is LanguageBlockNode))
            {
                inferedType = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, 0);
            }

            if (null != localProcedure && localProcedure.IsConstructor && setConstructorStartPC)
            {
                startpc -= 1;
                setConstructorStartPC = false;
            }

            if (bnode.RightNode == null && bnode.Optr == Operator.assign && bnode.LeftNode is IdentifierNode)
            {
                DebugProperties.BreakpointOptions newOptions = oldOptions;
                newOptions |= DebugProperties.BreakpointOptions.SuppressNullVarDeclarationBreakpoint;
                core.DebuggerProperties.breakOptions = newOptions;

                IdentifierNode t = bnode.LeftNode as IdentifierNode;
                ProtoCore.DSASM.SymbolNode symbolnode = null;
                bool isAccessible = false;
                bool hasAllocated = VerifyAllocation(t.Value, globalClassIndex, globalProcIndex, out symbolnode, out isAccessible);
                if (hasAllocated)
                {
                    bool allowDependent = graphNode.allowDependents;
                    graphNode.allowDependents = false;
                    bnode.RightNode =AstFactory.BuildIdentifier(t.Value);
                    graphNode.allowDependents = false;
                }
                else
                {
                    bnode.RightNode = new NullNode();
                }
            }

            // Keep track of current pc, because when travese right node it
            // may generate null assignment ( x = null; if x hasn't been defined
            // yet - Yu Ke
            startpc = pc;

            DfsTraverse(bnode.RightNode, ref inferedType, isBooleanOperation, graphNode, subPass, node);

            rightType.UID = inferedType.UID;
            rightType.rank = inferedType.rank;

            BinaryExpressionNode rightNode = bnode.RightNode as BinaryExpressionNode;
            if ((rightNode != null) && (ProtoCore.DSASM.Operator.assign == rightNode.Optr))
            {
                DfsTraverse(rightNode.LeftNode, ref inferedType, false, graphNode);
            }

            if (bnode.Optr != ProtoCore.DSASM.Operator.assign)
            {
                if (subPass == ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kUnboundIdentifier)
                {
                    return;
                }

                if (inferedType.UID == (int)PrimitiveType.kTypeFunctionPointer && emitDebugInfo)
                {
                    buildStatus.LogSemanticError(Resources.FunctionPointerNotAllowedAtBinaryExpression, core.CurrentDSFileName, bnode.RightNode.line, bnode.RightNode.col);
                }
                EmitBinaryOperation(leftType, rightType, bnode.Optr);
                isBooleanOp = false;

                return;
            }

            Validity.Assert(null != graphNode);
            if (!isTempExpression)
            {
                graphNode.updateBlock.startpc = pc;
            }

            currentBinaryExprUID = bnode.ExpressionUID;

            // These have been integrated into "EmitGetterSetterForIdentList" so 
            // that stepping through class properties can be supported. Setting 
            // these values here will cause issues with statements like this to 
            // be highlighted in its entirety (all the way up to closing bracket 
            // without highlighting the semi-colon).
            // 
            //      x = foo(a, b);
            // 
            // bnode.RightNode.line = bnode.line;
            // bnode.RightNode.col = bnode.col;
            // bnode.RightNode.endLine = bnode.endLine;
            // bnode.RightNode.endCol = bnode.endCol;

            // Traverse the entire RHS expression
            DfsTraverse(bnode.RightNode, ref inferedType, isBooleanOperation, graphNode, ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kNone, bnode);
            subPass = ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kUnboundIdentifier;

            if (bnode.LeftNode is IdentifierNode)
            {
                // TODO Jun: Cleansify this block where the lhs is being handled.
                // For one, make the return as a return node
                IdentifierNode t = bnode.LeftNode as IdentifierNode;
                ProtoCore.DSASM.SymbolNode symbolnode = null;


                ProtoCore.AssociativeGraph.UpdateNodeRef leftNodeGlobalRef = null; 

                string s = t.Value;
                if (s == ProtoCore.DSDefinitions.Keyword.Return)
                {
                    Validity.Assert(null == symbolnode);
                    symbolnode = new ProtoCore.DSASM.SymbolNode();
                    symbolnode.name = s;
                    symbolnode.isTemp = s.StartsWith("%");
                    symbolnode.functionIndex = globalProcIndex;
                    symbolnode.classScope = globalClassIndex;

                    EmitReturnStatement(node, inferedType);


                    // Comment Jun: The inline conditional holds a graphnode and traversing its body will set isReturn = true
                    // Resolve that here as an inline conditional is obviosuly not a return graphnode
                    if (!graphNode.isInlineConditional)
                    {
                        graphNode.isReturn = true;
                    }
                }
                else
                {
                    leftNodeGlobalRef = GetUpdatedNodeRef(bnode.LeftNode);

                    // check whether the variable name is a function name
                    if (globalClassIndex != ProtoCore.DSASM.Constants.kGlobalScope)
                    {
                        bool isAccessibleFp;
                        int realType;
                        var procNode = core.ClassTable.ClassNodes[globalClassIndex].GetMemberFunction(t.Name, null, globalClassIndex, out isAccessibleFp, out realType);
                        if (procNode != null && procNode.ID != Constants.kInvalidIndex && emitDebugInfo)
                        {
                            buildStatus.LogSemanticError(String.Format(Resources.FunctionAsVariableError, t.Name), core.CurrentDSFileName, t.line, t.col);
                        }
                    }

                    //int type = (int)ProtoCore.PrimitiveType.kTypeVoid;
                    bool isLocalDeclaration = t.IsLocal;
                    bool isAccessible = false;
                    bool isAllocated = false;

                    if (isLocalDeclaration)
                    {
                        isAllocated = VerifyAllocationInScope(t.Name, globalClassIndex, globalProcIndex, out symbolnode, out isAccessible);
                    }
                    else
                    {
                        isAllocated = VerifyAllocation(t.Name, globalClassIndex, globalProcIndex, out symbolnode, out isAccessible);
                    }

                    int runtimeIndex = (!isAllocated || !isAccessible) ? codeBlock.symbolTable.RuntimeIndex : symbolnode.runtimeTableIndex;
                    if (isAllocated && !isAccessible)
                    {
                        string message = String.Format(ProtoCore.Properties.Resources.kPropertyIsInaccessible, t.Name);
                        buildStatus.LogWarning(WarningID.kAccessViolation, message, core.CurrentDSFileName, t.line, t.col, graphNode);
                    }

                    int dimensions = 0;
                    if (null != t.ArrayDimensions)   
                    {
                        graphNode.isIndexingLHS = true;
                        dimensions = DfsEmitArrayIndexHeap(t.ArrayDimensions, graphNode, bnode);
                    }


                    // Comment Jun: Attempt to get the modified argument arrays in the current method
                    // Comment Jun: As of R1 - arrays are copy constructed and cannot propagate update unless explicitly returned
                    ProtoCore.Type castType = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, Constants.kArbitraryRank);
                    var tident = bnode.LeftNode as TypedIdentifierNode;
                    if (tident != null)
                    {
                        int castUID = core.ClassTable.IndexOf(tident.datatype.Name);
                        if ((int)PrimitiveType.kInvalidType == castUID)
                        {
                            castType = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kInvalidType, 0);
                            castType.Name = tident.datatype.Name;
                            castType.rank = tident.datatype.rank;
                        }
                        else
                        {
                            castType = core.TypeSystem.BuildTypeObject(castUID, tident.datatype.rank);
                        }
                    }

                    if (ProtoCore.DSASM.Constants.kInvalidIndex != globalClassIndex)
                    {
                        // In a class
                        if (ProtoCore.DSASM.Constants.kInvalidIndex == globalProcIndex)
                        {
                            string message = "A binary assignment inside a class must be inside a function (AB5E3EC1)";
                            buildStatus.LogSemanticError(message, core.CurrentDSFileName, bnode.line, bnode.col);
                            throw new BuildHaltException(message);
                        }

                        // TODO Jun: refactor this by having symbol table functions for retrieval of node index
                        int symbol = ProtoCore.DSASM.Constants.kInvalidIndex;
                        bool isMemVar = false;
                        if (symbolnode != null)
                        {
                            if (symbolnode.classScope != ProtoCore.DSASM.Constants.kInvalidIndex 
                                && symbolnode.functionIndex == ProtoCore.DSASM.Constants.kGlobalScope)
                            {
                                isMemVar = true;
                            }
                            symbol = symbolnode.symbolTableIndex;
                        }

                        if (!isMemVar)
                        {
                            // This is local variable
                            // TODO Jun: If this local var exists globally, should it allocate a local copy?
                            if (!isAllocated || !isAccessible)
                            {
                                symbolnode = Allocate(globalClassIndex, globalClassIndex, globalProcIndex, t.Name, inferedType, ProtoCore.DSASM.Constants.kPrimitiveSize,
                                    false, ProtoCore.CompilerDefinitions.AccessModifier.kPublic, ProtoCore.DSASM.MemoryRegion.kMemStack, bnode.line, bnode.col);

                                // Add the symbols during watching process to the watch symbol list.
                                if (core.Options.RunMode == ProtoCore.DSASM.InterpreterMode.kExpressionInterpreter)
                                {
                                    core.watchSymbolList.Add(symbolnode);
                                }

                                Validity.Assert(symbolnode != null);
                            }
                            else
                            {
                                symbolnode.datatype = inferedType;
                            }

                            if (bnode.LeftNode is TypedIdentifierNode)
                            {
                                symbolnode.SetStaticType(castType);
                            }
                            castType = symbolnode.staticType;
                            EmitPushVarData(dimensions, castType.UID, castType.rank);

                            symbol = symbolnode.symbolTableIndex;
                            if (t.Name == ProtoCore.DSASM.Constants.kTempArg)
                            {
                                EmitInstrConsole(ProtoCore.DSASM.kw.pop, t.Name);
                                EmitPopForSymbol(symbolnode, runtimeIndex);
                            }
                            else
                            {
                                if (core.Options.RunMode != ProtoCore.DSASM.InterpreterMode.kExpressionInterpreter)
                                {
                                    EmitInstrConsole(ProtoCore.DSASM.kw.pop, t.Name);
                                    EmitPopForSymbol(symbolnode, runtimeIndex, node.line, node.col, node.endLine, node.endCol);
                                }
                                else
                                {
                                    EmitInstrConsole(ProtoCore.DSASM.kw.popw, t.Name);
                                    EmitPopForSymbolW(symbolnode, runtimeIndex, node.line, node.col, node.endLine, node.endCol);
                                }
                            }
                        }
                        else
                        {
                            if (bnode.LeftNode is TypedIdentifierNode)
                            {
                                symbolnode.SetStaticType(castType);
                            }
                            castType = symbolnode.staticType;
                            EmitPushVarData(dimensions, castType.UID, castType.rank);

                            EmitInstrConsole(ProtoCore.DSASM.kw.popm, t.Name);

                            if (symbolnode.isStatic)
                            {
                                var op = StackValue.BuildStaticMemVarIndex(symbol);
                                EmitPopm(op, runtimeIndex, node.line, node.col, node.endLine, node.endCol);
                            }
                            else
                            {
                                var op = StackValue.BuildMemVarIndex(symbol);
                                EmitPopm(op, runtimeIndex, node.line, node.col, node.endLine, node.endCol);
                            }
                        }

                        //if (t.Name[0] != '%')
                        {
                            AutoGenerateUpdateReference(bnode.LeftNode, graphNode);
                        }

                        // Dependency
                        if (!isTempExpression)
                        {
                            // Dependency graph top level symbol 
                            graphNode.PushSymbolReference(symbolnode);
                            EmitDependency(bnode.ExpressionUID, bnode.modBlkUID, bnode.isSSAAssignment);
                            functionCallStack.Clear();
                        }
                    }
                    else
                    {
                        if (!isAllocated)
                        {
                            symbolnode = Allocate(globalClassIndex, globalClassIndex, globalProcIndex, t.Name, inferedType, ProtoCore.DSASM.Constants.kPrimitiveSize,
                                    false, ProtoCore.CompilerDefinitions.AccessModifier.kPublic, ProtoCore.DSASM.MemoryRegion.kMemStack, bnode.line, bnode.col);

                            if (core.Options.RunMode == ProtoCore.DSASM.InterpreterMode.kExpressionInterpreter)
                            {
                                core.watchSymbolList.Add(symbolnode);
                            }

                            if (dimensions > 0)
                            {
                                symbolnode.datatype.rank = dimensions;
                            }
                        }
                        else if (dimensions == 0)
                        {
                            symbolnode.datatype = inferedType;
                        }

                        //
                        // Jun Comment: 
                        //      Update system uses the following registers:  
                        //      _ex stores prev value of ident 't'  - VM assigned
                        //      _fx stores new value                - VM assigned
                        //

                        if (bnode.LeftNode is TypedIdentifierNode)
                        {
                            symbolnode.SetStaticType(castType);
                        }
                        castType = symbolnode.staticType;


                        if (bnode.IsInputExpression)
                        {
                            StackValue regLX = StackValue.BuildRegister(Registers.LX);
                            EmitInstrConsole(ProtoCore.DSASM.kw.pop, ProtoCore.DSASM.kw.regLX);
                            EmitPop(regLX, globalClassIndex);

                            graphNode.updateBlock.updateRegisterStartPC = pc;

                            EmitInstrConsole(ProtoCore.DSASM.kw.push, ProtoCore.DSASM.kw.regLX);
                            EmitPush(regLX);
                        }

                        EmitPushVarData(dimensions, castType.UID, castType.rank);

                        if (core.Options.RunMode != ProtoCore.DSASM.InterpreterMode.kExpressionInterpreter)
                        {
                            EmitInstrConsole(ProtoCore.DSASM.kw.pop, symbolnode.name);
                            EmitPopForSymbol(symbolnode, runtimeIndex, node.line, node.col, node.endLine, node.endCol);
                        }
                        else
                        {
                            EmitInstrConsole(ProtoCore.DSASM.kw.popw, symbolnode.name);
                            EmitPopForSymbolW(symbolnode, runtimeIndex, node.line, node.col, node.endLine, node.endCol);                            
                        }

                        AutoGenerateUpdateReference(bnode.LeftNode, graphNode);

                        // Dependency
                        if (!isTempExpression)
                        {
                            // Dependency graph top level symbol 
                            graphNode.PushSymbolReference(symbolnode);
                            EmitDependency(bnode.ExpressionUID, bnode.modBlkUID, bnode.isSSAAssignment);
                            functionCallStack.Clear();
                        }
                    }
                }

                // Dependency graph top level symbol 
                //graphNode.symbol = symbolnode;

                // Assign the end pc to this graph node's update block
                // Dependency graph construction is complete for this expression
                if (!isTempExpression)
                {
                    if (null != leftNodeGlobalRef)
                    {
                        if (null != localProcedure)
                        {
                            // Track for updated globals only in user defined functions
                            if (!localProcedure.IsAssocOperator && !localProcedure.IsAutoGenerated)
                            {
                                localProcedure.UpdatedGlobalVariables.Push(leftNodeGlobalRef);
                            }
                        }
                    }

                    {
                        if (!graphNode.IsSSANode() && !ProtoCore.AssociativeEngine.Utils.IsTempVarLHS(graphNode))
                        {
                            // This is the last expression in the SSA'd expression
                            // Backtrack and assign the this last final assignment graphnode to its associated SSA graphnodes
                            for (int n = codeBlock.instrStream.dependencyGraph.GraphList.Count - 1; n >= 0; --n)
                            {
                                GraphNode currentNode = codeBlock.instrStream.dependencyGraph.GraphList[n];
                                bool isWithinSameScope = currentNode.classIndex == graphNode.classIndex
                                    && currentNode.procIndex == graphNode.procIndex;
                                bool isWithinSameExpressionID = currentNode.exprUID == graphNode.exprUID;
                                if (isWithinSameScope && isWithinSameExpressionID)
                                {
                                    graphNode.IsLastNodeInSSA = true;
                                    if (null == codeBlock.instrStream.dependencyGraph.GraphList[n].lastGraphNode)
                                    {
                                        codeBlock.instrStream.dependencyGraph.GraphList[n].lastGraphNode = graphNode;
                                    }
                                }
                            }
                        }
                    }

                    graphNode.ResolveLHSArrayIndex();
                    graphNode.updateBlock.endpc = pc - 1;

                    PushGraphNode(graphNode);
                    if (core.InlineConditionalBodyGraphNodes.Count > 0)
                    {
                        core.InlineConditionalBodyGraphNodes.Last().Add(graphNode);
                    }

                    SymbolNode cyclicSymbol1 = null;
                    SymbolNode cyclicSymbol2 = null;
                    if (core.Options.staticCycleCheck)
                    {
                        if (!CyclicDependencyTest(graphNode, ref cyclicSymbol1, ref cyclicSymbol2))
                        {
                            Validity.Assert(null != cyclicSymbol1);
                            Validity.Assert(null != cyclicSymbol2);

                            //
                            // Set the first symbol that triggers the cycle to null
                            ProtoCore.AssociativeGraph.GraphNode nullAssignGraphNode1 = new ProtoCore.AssociativeGraph.GraphNode();
                            nullAssignGraphNode1.updateBlock.startpc = pc;

                            EmitPushNull();
                            EmitPushVarData(0);
                            EmitInstrConsole(ProtoCore.DSASM.kw.pop, cyclicSymbol1.name);
                            EmitPopForSymbol(cyclicSymbol1, cyclicSymbol1.runtimeTableIndex, node.line, node.col, node.endLine, node.endCol);

                            nullAssignGraphNode1.PushSymbolReference(cyclicSymbol1);
                            nullAssignGraphNode1.procIndex = globalProcIndex;
                            nullAssignGraphNode1.classIndex = globalClassIndex;
                            nullAssignGraphNode1.updateBlock.endpc = pc - 1;

                            PushGraphNode(nullAssignGraphNode1);
                            EmitDependency(ProtoCore.DSASM.Constants.kInvalidIndex, ProtoCore.DSASM.Constants.kInvalidIndex, false);


                            //
                            // Set the second symbol that triggers the cycle to null
                            ProtoCore.AssociativeGraph.GraphNode nullAssignGraphNode2 = new ProtoCore.AssociativeGraph.GraphNode();
                            nullAssignGraphNode2.updateBlock.startpc = pc;

                            EmitPushNull();
                            EmitPushVarData(0);
                            EmitInstrConsole(ProtoCore.DSASM.kw.pop, cyclicSymbol2.name);
                            EmitPopForSymbol(cyclicSymbol2, cyclicSymbol2.runtimeTableIndex, node.line, node.col, node.endLine, node.endCol);

                            nullAssignGraphNode2.PushSymbolReference(cyclicSymbol2);
                            nullAssignGraphNode2.procIndex = globalProcIndex;
                            nullAssignGraphNode2.classIndex = globalClassIndex;
                            nullAssignGraphNode2.updateBlock.endpc = pc - 1;

                            PushGraphNode(nullAssignGraphNode2);
                            EmitDependency(ProtoCore.DSASM.Constants.kInvalidIndex, ProtoCore.DSASM.Constants.kInvalidIndex, false);
                        }
                    }
                    if (isGraphInScope)
                    {
                        EmitCompileLog("==============End Node==============\n");
                    }
                }

                // Jun Comment: If it just so happens that the inline conditional is in the return statement
                if (graphNode.isInlineConditional)
                {
                    graphNode.isReturn = false;
                    if (0 == graphNode.updateNodeRefList.Count)
                    {
                        graphNode.isReturn = true;
                    }
                }
            }
            else
            {
                string message = "Illegal assignment (90787393)";
                buildStatus.LogSemanticError(message, core.CurrentDSFileName, bnode.line, bnode.col);
                throw new BuildHaltException(message);
            }
            core.DebuggerProperties.breakOptions = oldOptions;
        }
Exemplo n.º 28
0
        private void EmitMemberVariables(ClassDeclNode classDecl, GraphNode graphNode = null)
        {
            // Class member variable pass
            // Populating each class entry symbols with their respective member variables

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

            if (!unPopulatedClasses.ContainsKey(thisClassIndex))
            {
                return;
            }
            ProtoCore.DSASM.ClassNode thisClass = core.ClassTable.ClassNodes[thisClassIndex];

            // Handle member vars from base class
            if (null != classDecl.BaseClasses)
            {
                for (int n = 0; n < classDecl.BaseClasses.Count; ++n)
                {
                    int baseClassIndex = core.ClassTable.GetClassId(classDecl.BaseClasses[n]);
                    if (ProtoCore.DSASM.Constants.kInvalidIndex != baseClassIndex)
                    {
                        // To handle the case that a base class is defined after
                        // this class.
                        if (unPopulatedClasses.ContainsKey(baseClassIndex))
                        {
                            EmitMemberVariables(unPopulatedClasses[baseClassIndex], graphNode);
                            globalClassIndex = thisClassIndex;
                        }

                        ClassNode baseClass = core.ClassTable.ClassNodes[baseClassIndex];
                        // Append the members variables of every class that this class inherits from
                        foreach (ProtoCore.DSASM.SymbolNode symnode in baseClass.Symbols.symbolList.Values)
                        {
                            // It is a member variables
                            if (ProtoCore.DSASM.Constants.kGlobalScope == symnode.functionIndex)
                            {
                                Validity.Assert(!symnode.isArgument);
                                int symbolIndex = AllocateMemberVariable(thisClassIndex, symnode.isStatic ? symnode.classScope : baseClassIndex, symnode.name, symnode.datatype.rank, symnode.access, symnode.isStatic);

                                if (symbolIndex != ProtoCore.DSASM.Constants.kInvalidIndex)
                                    thisClass.Size += ProtoCore.DSASM.Constants.kPointerSize;
                            }
                        }
                    }
                    else
                    {
                        Validity.Assert(false, "n-pass compile error, fixme Jun....");
                    }
                }
            }

            // This list will store all static properties initialization
            // expression (say x = 1).
            List<BinaryExpressionNode> staticPropertyInitList = new List<BinaryExpressionNode>();

            foreach (VarDeclNode vardecl in classDecl.Variables)
            {
                IdentifierNode varIdent = null;
                if (vardecl.NameNode is IdentifierNode)
                {   
                    varIdent = vardecl.NameNode as IdentifierNode;

                    BinaryExpressionNode bNode = new BinaryExpressionNode();

                    var thisNode =AstFactory.BuildIdentifier(ProtoCore.DSDefinitions.Keyword.This);
                    var propNode =AstFactory.BuildIdentifier(varIdent.Value);
                    bNode.LeftNode = AstFactory.BuildIdentList(thisNode, propNode);

                    NodeUtils.CopyNodeLocation(bNode, vardecl);
                    bNode.Optr = ProtoCore.DSASM.Operator.assign;

                    bool skipInitialization = false;

                    // Initialize it to default value by manually add the right hand side node
                    if (vardecl.ArgumentType.rank == 0)
                    {
                        switch (vardecl.ArgumentType.Name)
                        {
                            case "double": bNode.RightNode = new DoubleNode(0); break;
                            case "int": bNode.RightNode = new IntNode(0); break;
                            case "bool": bNode.RightNode = new BooleanNode(false); break;
                            default: skipInitialization = true; break;
                        }
                    }
                    else if (vardecl.ArgumentType.rank > 0)
                    {
                        if (!vardecl.ArgumentType.Name.Equals("var"))
                            bNode.RightNode = new ExprListNode();
                        else
                            skipInitialization = true;
                    }
                    else if(vardecl.ArgumentType.rank.Equals(ProtoCore.DSASM.Constants.kArbitraryRank))
                    {
                        if (!vardecl.ArgumentType.Name.Equals("var"))
                            bNode.RightNode = new NullNode();
                        else
                            skipInitialization = true;
                    }

                    if (!skipInitialization)
                    {
                        if (vardecl.IsStatic)
                            staticPropertyInitList.Add(bNode);
                        else
                            thisClass.DefaultArgExprList.Add(bNode);
                    }
                }
                else if (vardecl.NameNode is BinaryExpressionNode)
                {
                    BinaryExpressionNode bNode = vardecl.NameNode as BinaryExpressionNode;
                    varIdent = bNode.LeftNode as IdentifierNode;

                    bNode.endCol = vardecl.endCol;
                    bNode.endLine = vardecl.endLine;

                    if (vardecl.IsStatic)
                        staticPropertyInitList.Add(bNode);
                    else
                        thisClass.DefaultArgExprList.Add(bNode);
                }
                else
                {
                    Validity.Assert(false, "Check generated AST");
                }

                // It is possible that fail to allocate variable. In that 
                // case we should remove initializing expression from 
                // cnode's defaultArgExprList
                int symbolIndex = AllocateMemberVariable(thisClassIndex, thisClassIndex, varIdent.Value, vardecl.ArgumentType.rank, vardecl.Access, vardecl.IsStatic);
                if (symbolIndex == ProtoCore.DSASM.Constants.kInvalidIndex)
                {
                    Validity.Assert(thisClass.DefaultArgExprList.Count > 0);
                    thisClass.DefaultArgExprList.RemoveAt(thisClass.DefaultArgExprList.Count - 1);
                }
                // Only generate getter/setter for non-ffi class
                else if (!classDecl.IsExternLib)
                {
                    ProtoCore.DSASM.SymbolNode prop =
                        vardecl.IsStatic
                        ? core.CodeBlockList[0].symbolTable.symbolList[symbolIndex]
                        : core.ClassTable.ClassNodes[thisClassIndex].Symbols.symbolList[symbolIndex];
                    string typeName = vardecl.ArgumentType.Name;
                    if (String.IsNullOrEmpty(typeName))
                    {
                        prop.datatype = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, Constants.kArbitraryRank);
                    }
                    else
                    {
                        int type = core.TypeSystem.GetType(typeName);
                        if (type == (int)PrimitiveType.kInvalidType)
                        {
                            string message = String.Format(ProtoCore.Properties.Resources.kTypeUndefined, typeName);
                            core.BuildStatus.LogWarning(ProtoCore.BuildData.WarningID.kTypeUndefined, message, core.CurrentDSFileName, vardecl.line, vardecl.col, graphNode);
                            prop.datatype = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, 0);
                        }
                        else
                        {
                            int rank = vardecl.ArgumentType.rank;
                            prop.datatype = core.TypeSystem.BuildTypeObject(type, rank);
                            if (type != (int)PrimitiveType.kTypeVar || prop.datatype.IsIndexable)
                            {
                                prop.staticType = prop.datatype;
                            }
                        }
                    }

                    EmitGetterForProperty(classDecl, prop);
                    EmitSetterForProperty(classDecl, prop);
                }
            }
            classOffset = 0;

            // Now we are going to create a static function __init_static_properties()
            // which will initialize all static properties. We will emit a 
            // call to this function after all classes have been compiled.
            if (staticPropertyInitList.Count > 0 && !classDecl.IsExternLib)
            {
                FunctionDefinitionNode initFunc = new FunctionDefinitionNode
                {
                    Name = ProtoCore.DSASM.Constants.kStaticPropertiesInitializer,
                    Signature = new ArgumentSignatureNode(),
                    Pattern = null,
                    ReturnType = new ProtoCore.Type { Name = core.TypeSystem.GetType((int)PrimitiveType.kTypeNull), UID = (int)PrimitiveType.kTypeNull },
                    FunctionBody = new CodeBlockNode(),
                    IsExternLib = false,
                    IsDNI = false,
                    ExternLibName = null,
                    Access = ProtoCore.CompilerDefinitions.AccessModifier.kPublic,
                    IsStatic = true
                };
                classDecl.Procedures.Add(initFunc);

                staticPropertyInitList.ForEach(bNode => initFunc.FunctionBody.Body.Add(bNode));
                initFunc.FunctionBody.Body.Add(AstFactory.BuildReturnStatement(new NullNode()));
            }

            unPopulatedClasses.Remove(thisClassIndex);
        }
Exemplo n.º 29
0
        private ProtoCore.Type BuildArgumentTypeFromVarDeclNode(VarDeclNode argNode, GraphNode graphNode = null)
        {
            Validity.Assert(argNode != null);
            if (argNode == null)
            {
                return new ProtoCore.Type();
            }

            int uid = core.TypeSystem.GetType(argNode.ArgumentType.Name);
            if (uid == (int)PrimitiveType.kInvalidType && !core.IsTempVar(argNode.NameNode.Name))
            {
                string message = String.Format(ProtoCore.Properties.Resources.kArgumentTypeUndefined, argNode.ArgumentType.Name, argNode.NameNode.Name);
                buildStatus.LogWarning(WarningID.kTypeUndefined, message, core.CurrentDSFileName, argNode.line, argNode.col, graphNode);
            }

            int rank = argNode.ArgumentType.rank;

            return core.TypeSystem.BuildTypeObject(uid, rank);
        }
Exemplo n.º 30
0
        private void EmitConstructorDefinitionNode(AssociativeNode node, ref ProtoCore.Type inferedType, ProtoCore.CompilerDefinitions.Associative.SubCompilePass subPass = ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kNone, GraphNode gNode = null)
        {
            ConstructorDefinitionNode funcDef = node as ConstructorDefinitionNode;
            ProtoCore.DSASM.CodeBlockType originalBlockType = codeBlock.blockType;
            codeBlock.blockType = ProtoCore.DSASM.CodeBlockType.kFunction;

            if (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
                ProtoCore.Type returnType = localProcedure.ReturnType; 
                if (globalClassIndex != -1)
                    returnType.Name = core.ClassTable.ClassNodes[globalClassIndex].Name;
                returnType.UID = globalClassIndex;
                returnType.rank = 0;
                localProcedure.ReturnType = returnType;
                localProcedure.IsConstructor = true;
                localProcedure.RuntimeIndex = 0;
                localProcedure.IsExternal = funcDef.IsExternLib;
                Validity.Assert(ProtoCore.DSASM.Constants.kInvalidIndex != globalClassIndex, "A constructor node must be associated with class");
                localProcedure.LocalCount = 0;
                localProcedure.ClassID = globalClassIndex;

                localProcedure.MethodAttribute = funcDef.MethodAttributes;

                int peekFunctionindex = core.ClassTable.ClassNodes[globalClassIndex].ProcTable.Procedures.Count;

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

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

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

                    localProcedure.IsVarArg = funcDef.Signature.IsVarArg;
                }

                int findex = 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 != findex)
                {
                    Validity.Assert(peekFunctionindex == localProcedure.ID);
                    argsToBeAllocated.ForEach(arg =>
                    {
                        int symbolIndex = AllocateArg(arg.Key, findex, arg.Value);
                        if (ProtoCore.DSASM.Constants.kInvalidIndex == symbolIndex)
                        {
                            throw new BuildHaltException("44B557F1");
                        }
                    });
                }
                else
                {
                    string message = String.Format(ProtoCore.Properties.Resources.kMethodAlreadyDefined, localProcedure.Name);
                    buildStatus.LogWarning(WarningID.kFunctionAlreadyDefined, message, core.CurrentDSFileName, funcDef.line, funcDef.col, gNode);
                    funcDef.skipMe = true;
                }
            }
            else if (IsParsingMemberFunctionBody())
            {
                EmitCompileLogFunctionStart(GetFunctionSignatureString(funcDef.Name, funcDef.ReturnType, funcDef.Signature, true));
                // 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, gNode);
                        argList.Add(argType);
                    }
                }

                var procNode = core.ClassTable.ClassNodes[globalClassIndex].ProcTable.GetFunctionBySignature(funcDef.Name, argList);
                globalProcIndex = procNode == null ? Constants.kInvalidIndex : procNode.ID;

                Validity.Assert(null == localProcedure);
                localProcedure = core.ClassTable.ClassNodes[globalClassIndex].ProcTable.Procedures[globalProcIndex];

                Validity.Assert(null != localProcedure);
                localProcedure.Attributes = PopulateAttributes(funcDef.Attributes);
                // Its only on the parse body pass where the real pc is determined. Update this procedures' pc
                //Validity.Assert(ProtoCore.DSASM.Constants.kInvalidIndex == localProcedure.pc);
                localProcedure.PC = pc;

                EmitInstrConsole(ProtoCore.DSASM.kw.allocc, localProcedure.Name);
                EmitAllocc(globalClassIndex);
                setConstructorStartPC = true;

                EmitCallingForBaseConstructor(globalClassIndex, funcDef.BaseConstructor);

                ProtoCore.FunctionEndPoint fep = null;
                if (!funcDef.IsExternLib)
                {
                    // Traverse default assignment for the class
                    emitDebugInfo = false;

                    List<AssociativeNode> defaultArgList = core.ClassTable.ClassNodes[globalClassIndex].DefaultArgExprList;
                    defaultArgList = BuildSSA(defaultArgList, context);
                    foreach (BinaryExpressionNode bNode in defaultArgList)
                    {
                        ProtoCore.AssociativeGraph.GraphNode graphNode = new ProtoCore.AssociativeGraph.GraphNode();
                        graphNode.exprUID = bNode.ExpressionUID;
                        graphNode.ssaExpressionUID = bNode.SSAExpressionUID;
                        graphNode.procIndex = globalProcIndex;
                        graphNode.classIndex = globalClassIndex;
                        graphNode.languageBlockId = codeBlock.codeBlockId;
                        graphNode.isAutoGenerated = true;
                        bNode.IsProcedureOwned = graphNode.ProcedureOwned = true;

                        EmitBinaryExpressionNode(bNode, ref inferedType, false, graphNode, subPass);
                    }

                    //Traverse default argument for the constructor
                    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(Constants.kTempDefaultArg);
                        BinaryExpressionNode bNodeTemp = new BinaryExpressionNode();
                        bNodeTemp.LeftNode = iNodeTemp;
                        bNodeTemp.Optr = ProtoCore.DSASM.Operator.assign;
                        bNodeTemp.RightNode = bNode.LeftNode;
                        EmitBinaryExpressionNode(bNodeTemp, ref inferedType);
                        //duild an inline conditional node for statement: defaultarg = (temp == DefaultArgNode) ? defaultValue : temp;
                        InlineConditionalNode icNode = new InlineConditionalNode();
                        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);
                    }
                    emitDebugInfo = true;

                    EmitCodeBlock(funcDef.FunctionBody.Body, ref inferedType, subPass, true);

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

                    // All locals have been stack allocated, update the local count of this function
                    localProcedure.LocalCount = core.BaseOffset;
                    core.ClassTable.ClassNodes[globalClassIndex].ProcTable.Procedures[globalProcIndex].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 == globalProcIndex && symnode.isArgument)
                        {
                            symnode.index -= localProcedure.LocalCount;
                        }
                    }

                    // JIL FEP
                    ProtoCore.Lang.JILActivationRecord record = new ProtoCore.Lang.JILActivationRecord();
                    record.pc = localProcedure.PC;
                    record.locals = localProcedure.LocalCount;
                    record.classIndex = globalClassIndex;
                    record.funcIndex = globalProcIndex;

                    // Construct the fep arguments
                    fep = new ProtoCore.Lang.JILFunctionEndPoint(record);
                }
                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 = false;
                    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.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);

                Dictionary<string, FunctionGroup> fgroup = core.FunctionTable.GlobalFuncTable[classIndexAtCallsite];
                if (!fgroup.ContainsKey(funcDef.Name))
                {
                    // 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);
                }

                int startpc = pc;

                // Constructors auto return
                EmitInstrConsole(ProtoCore.DSASM.kw.retc);

                // Stepping out of a constructor body will have the execution cursor 
                // placed right at the closing curly bracket of the constructor definition.
                // 
                int closeCurlyBracketLine = 0, closeCurlyBracketColumn = -1;
                if (null != funcDef.FunctionBody)
                {
                    closeCurlyBracketLine = funcDef.FunctionBody.endLine;
                    closeCurlyBracketColumn = funcDef.FunctionBody.endCol;
                }

                // The execution cursor covers exactly one character -- the closing 
                // curly bracket. Note that we decrement the start-column by one here 
                // because end-column of "FunctionBody" here is *after* the closing 
                // curly bracket, so we want one before that.
                // 
                EmitRetc(closeCurlyBracketLine, closeCurlyBracketColumn - 1,
                    closeCurlyBracketLine, closeCurlyBracketColumn);

                // Build and append a graphnode for this return statememt
                ProtoCore.DSASM.SymbolNode returnNode = new ProtoCore.DSASM.SymbolNode();
                returnNode.name = ProtoCore.DSDefinitions.Keyword.Return;

                ProtoCore.AssociativeGraph.GraphNode retNode = new ProtoCore.AssociativeGraph.GraphNode();
                //retNode.symbol = returnNode;
                retNode.PushSymbolReference(returnNode);
                retNode.procIndex = globalProcIndex;
                retNode.classIndex = globalClassIndex;
                retNode.updateBlock.startpc = startpc;
                retNode.updateBlock.endpc = pc - 1;

                PushGraphNode(retNode);
                EmitCompileLogFunctionEnd();
            }

            // Constructors have no return statemetns, reset variables here
            core.ProcNode = localProcedure = null;
            globalProcIndex = ProtoCore.DSASM.Constants.kGlobalScope;
            core.BaseOffset = 0;
            argOffset = 0;
            classOffset = 0;
            codeBlock.blockType = originalBlockType;
        }
Exemplo n.º 31
0
        public void LogSemanticError(string msg, string fileName = null, int line = -1, int col = -1, AssociativeGraph.GraphNode graphNode = null)
        {
            /*if (fileName == null)
             * {
             *  fileName = "N.A.";
             * }*/

            if (logErrors)
            {
                System.Console.WriteLine("{0}({1},{2}) Error:{3}", fileName, line, col, msg);
            }

            if (compileState.Options.IsDeltaExecution)
            {
                compileState.LogErrorInGlobalMap(ProtoLanguage.CompileStateTracker.ErrorType.Error, msg, fileName, line, col);
            }

            BuildData.ErrorEntry errorEntry = new BuildData.ErrorEntry
            {
                FileName = fileName,
                Message  = msg,
                Line     = line,
                Col      = col
            };
            errors.Add(errorEntry);

            // Comment: This is true for example in Graph Execution mode

            /*if (errorAsWarning)
             * {
             *  if (graphNode != null)
             *  {
             *      graphNode.isDirty = false;
             *      return;
             *  }
             * }*/

            OutputMessage outputmessage = new OutputMessage(OutputMessage.MessageType.Error, msg.Trim(), fileName, line, col);

            if (MessageHandler != null)
            {
                MessageHandler.Write(outputmessage);
                if (WebMsgHandler != null)
                {
                    OutputMessage webOutputMsg = new OutputMessage(OutputMessage.MessageType.Error, msg.Trim(), "", line, col);
                    WebMsgHandler.Write(webOutputMsg);
                }
                if (!outputmessage.Continue)
                {
                    throw new BuildHaltException(msg);
                }
            }
            throw new BuildHaltException(msg);
        }
Exemplo n.º 32
0
        private void EmitLHSIdentifierListForBinaryExpr(AssociativeNode bnode, ref ProtoCore.Type inferedType, bool isBooleanOp = false, ProtoCore.AssociativeGraph.GraphNode graphNode = null, ProtoCore.CompilerDefinitions.Associative.SubCompilePass subPass = ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kNone, bool isTempExpression = false)
        {
            BinaryExpressionNode binaryExpr = bnode as BinaryExpressionNode;
            if (binaryExpr == null || !(binaryExpr.LeftNode is IdentifierListNode))
            {
                return;
            }

            if (ProtoCore.DSASM.Constants.kInvalidIndex == graphNode.updateBlock.startpc)
            {
                graphNode.updateBlock.startpc = pc;
            }

            // This is a setter, so disable dependents
            graphNode.allowDependents = false;
            IdentifierListNode theLeftNode = binaryExpr.LeftNode as IdentifierListNode;
            bool isThisPtr = null != theLeftNode.LeftNode.Name && theLeftNode.LeftNode.Name.Equals(ProtoCore.DSDefinitions.Keyword.This);
            if (isThisPtr)
            {
                graphNode.allowDependents = true;
            }

            ProtoCore.AssociativeGraph.UpdateNodeRef leftNodeRef = AutoGenerateUpdateReference(binaryExpr.LeftNode, graphNode);
            ProtoCore.AssociativeGraph.UpdateNodeRef leftNodeArgRef = __To__Deprecate__AutoGenerateUpdateArgumentReference(binaryExpr.LeftNode, graphNode);

            ProtoCore.AST.Node lnode = binaryExpr.LeftNode;
            NodeUtils.CopyNodeLocation(lnode, binaryExpr);

            ProtoCore.AST.Node rnode = binaryExpr.RightNode;
            bool isCollapsed = false;
            EmitGetterSetterForIdentList(lnode, ref inferedType, graphNode, subPass, out isCollapsed, rnode);

            graphNode.allowDependents = true;

            // Dependency
            if (!isTempExpression)
            {
                // Dependency graph top level symbol 
                graphNode.updateNodeRefList.Add(leftNodeRef);
                graphNode.updateNodeRefList[0].nodeList[0].dimensionNodeList = graphNode.dimensionNodeList;

                // @keyu: foo.id = 42; will generate same leftNodeRef and leftNodeArgRef
                if (!isThisPtr && !leftNodeRef.Equals(leftNodeArgRef))
                {
                    graphNode.updateNodeRefList.Add(leftNodeArgRef);
                }

                //
                // If the lhs of the expression is an identifier list, it could have been modified. 
                // It must then be a dependent of its own graphnode
                //
                //      class C
                //      {
                //          x : int;
                //          constructor C(i:int)
                //          {
                //              x = i;
                //          }
                //      }
                //
                //      i = 10;
                //      a = C.C(i);
                //      a.x = 15; -> re-execute this line ... as 'a' was redefined and its members now changed
                //      val = a.x;
                //      i = 7;
                //

                //
                // If inside a member function, and the lhs is a property, make sure it is not just:
                //      x = y (this.x = y)
                //

                if (core.Options.LHSGraphNodeUpdate)
                {
                    if (!isThisPtr || graphNode.updateNodeRefList[0].nodeList.Count > 1)
                    {
                        ProtoCore.AssociativeGraph.GraphNode dependentNode = new ProtoCore.AssociativeGraph.GraphNode();
                        dependentNode.isLHSNode = true;
                        dependentNode.updateNodeRefList.Add(graphNode.updateNodeRefList[0]);
                        graphNode.dependentList.Add(dependentNode);
                    }
                }


                ProtoCore.DSASM.SymbolNode firstSymbol = leftNodeRef.nodeList[0].symbol;
                if (null != firstSymbol)
                {
                    EmitDependency(binaryExpr.ExpressionUID, binaryExpr.modBlkUID, false);
                }

                if (core.Options.GenerateSSA)
                {
                    if (!graphNode.IsSSANode() && !ProtoCore.AssociativeEngine.Utils.IsTempVarLHS(graphNode))
                    {
                        // This is the last expression in the SSA'd expression
                        // Backtrack and assign the this last final assignment graphnode to its associated SSA graphnodes
                        for (int n = codeBlock.instrStream.dependencyGraph.GraphList.Count - 1; n >= 0; --n)
                        {
                            GraphNode currentNode = codeBlock.instrStream.dependencyGraph.GraphList[n];
                            bool isWithinSameScope = currentNode.classIndex == graphNode.classIndex
                                && currentNode.procIndex == graphNode.procIndex;
                            bool isWithinSameExpressionID = currentNode.exprUID == graphNode.exprUID;
                            if (isWithinSameScope && isWithinSameExpressionID)
                            {
                                graphNode.IsLastNodeInSSA = true;
                                codeBlock.instrStream.dependencyGraph.GraphList[n].lastGraphNode = graphNode;
                            }
                        }
                    }
                }


                // Assign the end pc to this graph node's update block
                // Dependency graph construction is complete for this expression
                graphNode.updateBlock.endpc = pc - 1;
                PushGraphNode(graphNode);
                functionCallStack.Clear();
            }
        }
Exemplo n.º 33
0
        public void Push(GraphNode node)
        {
            Validity.Assert(null != core);
            Validity.Assert(core.GraphNodeUID >= 0);
            node.UID = core.GraphNodeUID++;
            node.dependencyGraphListID = graphList.Count;
            graphList.Add(node);

            ulong key = GetGraphNodeKey(node.classIndex, node.procIndex);
            List<GraphNode> nodes = null;
            if (graphNodeMap.TryGetValue(key, out nodes))
            {
                nodes.Add(node);
            }
            else
            {
                nodes = new List<GraphNode> {node};
                graphNodeMap[key] = nodes;
            }
        }
Exemplo n.º 34
0
        protected override void EmitReturnNull()
        {
            int startpc = pc;

            EmitPushNull();
            EmitReturnToRegister();

            // Build and append a graphnode for this return statememt
            ProtoCore.DSASM.SymbolNode returnNode = new ProtoCore.DSASM.SymbolNode();
            returnNode.name = ProtoCore.DSDefinitions.Keyword.Return;

            ProtoCore.AssociativeGraph.GraphNode retNode = new ProtoCore.AssociativeGraph.GraphNode();
            //retNode.symbol = returnNode;
            retNode.PushSymbolReference(returnNode);
            retNode.procIndex = globalProcIndex;
            retNode.classIndex = globalClassIndex;
            retNode.updateBlock.startpc = startpc;
            retNode.updateBlock.endpc = pc - 1;
            retNode.isReturn = true;

            PushGraphNode(retNode);
        }
Exemplo n.º 35
0
        public void LogSemanticError(string msg, string fileName = null, int line = -1, int col = -1, AssociativeGraph.GraphNode graphNode = null)
        {
#if DEBUG
            if (logErrors)
            {
                System.Console.WriteLine("{0}({1},{2}) Error:{3}", fileName, line, col, msg);
            }
#endif

            if (core.Options.IsDeltaExecution)
            {
            }

            BuildData.ErrorEntry errorEntry = new BuildData.ErrorEntry
            {
                ID       = ErrorType.SemanticError,
                FileName = fileName,
                Message  = msg,
                Line     = line,
                Column   = col
            };
            errors.Add(errorEntry);

            OutputMessage outputmessage = new OutputMessage(OutputMessage.MessageType.Error, msg.Trim(), fileName, line, col);
            if (MessageHandler != null)
            {
                MessageHandler.Write(outputmessage);
                if (!outputmessage.Continue)
                {
                    throw new BuildHaltException(msg);
                }
            }
            throw new BuildHaltException(msg);
        }
Exemplo n.º 36
0
        private void TraverseDotCallArguments(FunctionCallNode funcCall, 
                                              FunctionDotCallNode dotCall,
                                              ProcedureNode procCallNode,
                                              List<ProtoCore.Type> arglist,
                                              string procName,
                                              int classIndex,
                                              string className,
                                              bool isStaticCall,
                                              bool isConstructor,
                                              GraphNode graphNode,
                                              ProtoCore.CompilerDefinitions.Associative.SubCompilePass subPass,
                                              BinaryExpressionNode bnode)
        {
            // Update graph dependencies
            if (subPass != ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kUnboundIdentifier && graphNode != null)
            {
                if (isStaticCall)
                {
                    Validity.Assert(classIndex != Constants.kInvalidIndex);
                    Validity.Assert(!string.IsNullOrEmpty(className));

                    SymbolNode classSymbol = new SymbolNode();
                    classSymbol.name = className;
                    classSymbol.classScope = classIndex;
                    PushSymbolAsDependent(classSymbol, graphNode);
                }
            }

            int funtionArgCount = 0;
            for (int n = 0; n < funcCall.FormalArguments.Count; ++n)
            {
                if (isStaticCall || isConstructor)
                {
                    if (n != Constants.kDotArgIndexArrayArgs)
                    {
                        continue;
                    }
                }

                AssociativeNode paramNode = funcCall.FormalArguments[n];
                ProtoCore.Type paramType = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, 0);

                emitReplicationGuide = false;

                // If it's a binary node then continue type check, otherwise 
                // disable type check and just take the type of paramNode itself
                enforceTypeCheck = !(paramNode is BinaryExpressionNode);

                if (ProtoCore.DSASM.Constants.kDotArgIndexPtr == n)
                {
                    // Traversing the first arg (the LHS pointer/Static instanct/Constructor
                    
                    // Replication guides only allowed on method, e.g.,
                    // 
                    //    x = p<1>.f({1,2}<2>); 
                    //
                    // But not on getter, e.g.,
                    // 
                    //    c = a<1>.x<2>; 
                    if (!CoreUtils.IsGetterSetter(procName) && !isConstructor)
                    {
                        emitReplicationGuide = true;
                    }

                    DfsTraverse(paramNode, ref paramType, false, graphNode, subPass, bnode);
                }
                else if (ProtoCore.DSASM.Constants.kDotArgIndexArrayArgs == n)
                {
                    // Traversing the actual arguments passed into the function 
                    // (not the dot function)
                    int defaultArgNumber = 0;

                    // If its null this is the second call in a chained dot
                    if (null != procCallNode)
                    {
                        defaultArgNumber = procCallNode.ArgumentInfos.Count - dotCall.FunctionCall.FormalArguments.Count;
                    }

                    // Enable graphnode dependencies if its a setter method
                    bool allowDependentState = null != graphNode ? graphNode.allowDependents : false;
                    if (CoreUtils.IsSetter(procName))
                    {
                        // If the arguments are not temporaries
                        ExprListNode exprList = paramNode as ExprListNode;
                        Validity.Assert(1 == exprList.Exprs.Count);

                        string varname = string.Empty;
                        if (exprList.Exprs[0] is IdentifierNode)
                        {
                            varname = (exprList.Exprs[0] as IdentifierNode).Name;

                            if (!CoreUtils.IsAutoGeneratedVar(varname))
                            {
                                graphNode.allowDependents = true;
                            }
                            else if (CoreUtils.IsSSATemp(varname) && core.Options.GenerateSSA)
                            {
                                graphNode.allowDependents = true;
                            }
                        }
                        else
                        {
                            graphNode.allowDependents = true;
                        }

                    }

                    emitReplicationGuide = true;

                    if (defaultArgNumber > 0)
                    {
                        ExprListNode exprList = paramNode as ExprListNode;

                        if (subPass != ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kUnboundIdentifier)
                        {
                            for (int i = 0; i < defaultArgNumber; i++)
                            {
                                exprList.Exprs.Add(new DefaultArgNode());
                            }

                        }

                        if (!isStaticCall && !isConstructor)
                        {
                            DfsTraverse(paramNode, ref paramType, false, graphNode, subPass);
                            funtionArgCount = exprList.Exprs.Count;
                        }
                        else
                        {
                            foreach (AssociativeNode exprListNode in exprList.Exprs)
                            {
                                bool repGuideState = emitReplicationGuide;
                                if (subPass == ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kUnboundIdentifier)
                                {
                                    emitReplicationGuide = false;
                                }

                                DfsTraverse(exprListNode, ref paramType, false, graphNode, subPass, bnode);
                                emitReplicationGuide = repGuideState;

                                arglist.Add(paramType);
                            }
                        }
                    }
                    else
                    {
                        ExprListNode exprList = paramNode as ExprListNode;

                        // Comment Jun: This is a getter/setter or a an auto-generated thisarg function...
                        // ...add the dynamic sv that will be resolved as a pointer at runtime
                        if (!isStaticCall && !isConstructor)
                        {
                            // TODO Jun: pls get rid of subPass checking outside the core travesal
                            if (ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kNone == subPass)
                            {
                                exprList.Exprs.Insert(0, new DynamicNode());
                            }
                        }

                        if (exprList.Exprs.Count > 0)
                        {
                            foreach (AssociativeNode exprListNode in exprList.Exprs)
                            {
                                bool repGuideState = emitReplicationGuide;
                                if (subPass == ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kUnboundIdentifier)
                                {
                                    emitReplicationGuide = false;
                                }

                                DfsTraverse(exprListNode, ref paramType, false, graphNode, subPass, bnode);
                                emitReplicationGuide = repGuideState;

                                arglist.Add(paramType);
                            }

                            if (subPass != ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kUnboundIdentifier &&
                                !isStaticCall &&
                                !isConstructor)
                            {
                                EmitInstrConsole(ProtoCore.DSASM.kw.alloca, exprList.Exprs.Count.ToString());
                                EmitPopArray(exprList.Exprs.Count);

                                if (exprList.ArrayDimensions != null)
                                {
                                    int dimensions = DfsEmitArrayIndexHeap(exprList.ArrayDimensions, graphNode);
                                    EmitInstrConsole(ProtoCore.DSASM.kw.pushindex, dimensions.ToString() + "[dim]");
                                    EmitPushArrayIndex(dimensions);
                                }
                            }
                        }
                        else
                        {
                            if (!isStaticCall && !isConstructor)
                            {
                                if (exprList != null)
                                {
                                    bool emitReplicationGuideState = emitReplicationGuide;
                                    emitReplicationGuide = false;
                                    DfsTraverse(paramNode, ref paramType, false, graphNode, subPass);
                                    emitReplicationGuide = emitReplicationGuideState;
                                }
                                else
                                {
                                    DfsTraverse(paramNode, ref paramType, false, graphNode, subPass);
                                }
                            }
                        }

                        funtionArgCount = exprList.Exprs.Count;
                    }

                    emitReplicationGuide = false;

                    // Restore the state only if it is a setter method
                    if (ProtoCore.Utils.CoreUtils.IsSetter(procName))
                    {
                        graphNode.allowDependents = allowDependentState;
                    }
                }
                else if (ProtoCore.DSASM.Constants.kDotArgIndexArgCount == n)
                {
                    IntNode argNumNode = new IntNode(funtionArgCount);
                    DfsTraverse(argNumNode, ref paramType, false, graphNode, subPass);
                }
                else
                {
                    DfsTraverse(paramNode, ref paramType, false, graphNode, subPass);
                }

                emitReplicationGuide = false;
                enforceTypeCheck = true;

                if (!isStaticCall || !isConstructor)
                {
                    arglist.Add(paramType);
                }
            } 
        }
Exemplo n.º 37
0
        public void LogSemanticError(string msg, string fileName = null, int line = -1, int col = -1, AssociativeGraph.GraphNode graphNode = null)
        {
            if (logErrors)
            {
                System.Console.WriteLine("{0}({1},{2}) Error:{3}", fileName, line, col, msg);
            }

            if (compileState.Options.IsDeltaExecution)
            {
                compileState.LogErrorInGlobalMap(ProtoLanguage.CompileStateTracker.ErrorType.Error, msg, fileName, line, col);
            }

            BuildData.ErrorEntry errorEntry = new BuildData.ErrorEntry
            {
                FileName = fileName,
                Message  = msg,
                Line     = line,
                Col      = col
            };
            errors.Add(errorEntry);

            OutputMessage outputmessage = new OutputMessage(OutputMessage.MessageType.Error, msg.Trim(), fileName, line, col);

            if (MessageHandler != null)
            {
                MessageHandler.Write(outputmessage);
                if (WebMsgHandler != null)
                {
                    OutputMessage webOutputMsg = new OutputMessage(OutputMessage.MessageType.Error, msg.Trim(), "", line, col);
                    WebMsgHandler.Write(webOutputMsg);
                }
                if (!outputmessage.Continue)
                {
                    throw new BuildHaltException(msg);
                }
            }
            throw new BuildHaltException(msg);
        }