Ejemplo n.º 1
0
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="node">The AST Node of Procedure Call</param>
 public ProcedureStyleCall(Compiler.Nodes.ProcedureStyleCall node)
     : base(null)
 {
     this.Node = node;
     Statement = (ProcedureStyleCallStatement)Node.CodeElement;
     call      = new CallStatement();
     call.ProgramOrProgramEntryOrProcedureOrFunction = new SymbolReferenceVariable(StorageDataType.ProgramName, Statement.ProcedureCall.ProcedureName);
     call.InputParameters = new List <CallSiteParameter>(Statement.ProcedureCall.Arguments);
     call.OutputParameter = null;
     //Add any optional CALL-END statement
     foreach (var child in node.Children)
     {
         this.Add(child);
         if (child.CodeElement != null && child.CodeElement.Type == TypeCobol.Compiler.CodeElements.CodeElementType.CallStatementEnd)
         {
             HasCallEnd = true;
         }
     }
 }
Ejemplo n.º 2
0
            /// <summary>
            /// Checks and handles any procedure call resolution.
            /// </summary>
            /// <param name="items">The items to check if they correspond to the procedure qualified name</param>
            /// <returns>true if it was a Procedure style call, false otherwise.</returns>
            private bool IsProcedureStyleCallItems(IList <SymbolReference> items, out string hashFunction)
            {
                hashFunction = null;

                TypeCobol.Compiler.Nodes.ProcedureStyleCall procStyleCall = CurrentNode as TypeCobol.Compiler.Nodes.ProcedureStyleCall;
                if (procStyleCall != null)
                {
                    ProcedureStyleCallStatement procStyleCallStmt = procStyleCall.CodeElement as ProcedureStyleCallStatement;
                    if (procStyleCallStmt != null)
                    {
                        TypeCobolQualifiedSymbolReference tcqsr = procStyleCallStmt.ProgramOrProgramEntryOrProcedureOrFunctionOrTCProcedureFunction as
                                                                  TypeCobolQualifiedSymbolReference ?? procStyleCallStmt.ProcdurePointerOrTCProcedureFunction as TypeCobolQualifiedSymbolReference;

                        if (tcqsr != null)
                        {
                            IList <SymbolReference> names_items = tcqsr.AsList();
                            if (names_items.Count != items.Count)
                            {
                                return(false);
                            }
                            if (EqualItems(items, names_items))
                            {//This is a reference to a Function Call.
                                hashFunction = procStyleCall.FunctionDeclaration.Hash;
                                if (ProcCallerStack != null && ProcCallerStack.Count > 0)
                                {   //Memorize the (hash,ProcedureStyleCall) In the Program procedure style call dictionary.
                                    var program = ProcCallerStack.Peek();
                                    if (!program.ProcStyleCalls.ContainsKey(hashFunction))
                                    {
                                        program.ProcStyleCalls[hashFunction] = new Tuple <IList <SymbolReference>, TypeCobol.Compiler.Nodes.ProcedureStyleCall>(items, procStyleCall);
                                    }
                                }
                                return(true);
                            }
                        }
                    }
                }
                return(false);
            }
        ////////////////////
        // PROCEDURE CALL //
        ////////////////////

        public override void EnterTcCallStatement(CodeElementsParser.TcCallStatementContext context)
        {
            var cbCallProc = context.procedurePointerOrFunctionPointerVariableOrfunctionNameReference;

            // Register call parameters (shared storage areas) information at the CodeElement level
            CallSite callSite = null;
            ProcedureStyleCallStatement statement = null;

            Context = context;

            //Incomplete CallStatement, create an empty CodeElement and return + Error due to issue #774
            if (cbCallProc == null)
            {
                CodeElement = new ProcedureStyleCallStatement
                {
                    Diagnostics = new List <Diagnostic>
                    {
                        new Diagnostic(MessageCode.SyntaxErrorInParser, context.Start.Column,
                                       context.Stop.Column, context.Start.Line, "Empty CALL is not authorized")
                    }
                };
                return;
            }


            //Here ambiguousSymbolReference with either CandidatesType:
            // - ProgramNameOrProgramEntry
            // - data, condition, UPSISwitch, TCFunctionName
            var ambiguousSymbolReference = CobolExpressionsBuilder.CreateProcedurePointerOrFunctionPointerVariableOrTCFunctionProcedure(cbCallProc);


            //If (inputs, inouts ou outputs).Count > 0, then it's a procedure call
            if (context.callOutputParameter().Length > 0 || context.callInputParameter().Length > 0 || context.callInoutParameter().Length > 0)
            {
                callSite = new CallSite();
                #region Setup Input Output Inout CallSitesParameters

                var inputs  = new List <CallSiteParameter>();
                var inouts  = new List <CallSiteParameter>();
                var outputs = new List <CallSiteParameter>();

                SyntaxProperty <ParameterSharingMode> mode = null;
                foreach (var p in context.callInputParameter())
                {
                    CreateSharingMode(p, ref mode); // TCRFUN_INPUT_BY
                    var callSiteParameter = new CallSiteParameter
                    {
                        SharingMode = mode,
                    };


                    if (p.sharedVariableOrFileName() != null)
                    {
                        callSiteParameter.StorageAreaOrValue = CobolExpressionsBuilder.CreateSharedVariableOrFileName(p.sharedVariableOrFileName());
                    }
                    else if (p.OMITTED() != null)
                    {
                        callSiteParameter.Omitted = new SyntaxProperty <bool>(true, ParseTreeUtils.GetFirstToken(p.OMITTED()));
                    }

                    if (p.sharedVariableOrFileName() != null || p.OMITTED() != null)
                    {
                        inputs.Add(callSiteParameter);
                    }
                }

                foreach (var p in context.callInoutParameter())
                {
                    var callSiteParameter = new CallSiteParameter
                    {
                        // TCRFUN_CALL_INOUT_AND_OUTPUT_BY_REFERENCE
                        SharingMode =
                            new SyntaxProperty <ParameterSharingMode>(ParameterSharingMode.ByReference, null),
                    };

                    if (p.sharedStorageArea1() != null)
                    {
                        callSiteParameter.StorageAreaOrValue = new Variable(CobolExpressionsBuilder.CreateSharedStorageArea(p.sharedStorageArea1()));
                    }
                    else if (p.OMITTED() != null)
                    {
                        callSiteParameter.Omitted = new SyntaxProperty <bool>(true, ParseTreeUtils.GetFirstToken(p.OMITTED()));
                    }

                    if (p.sharedStorageArea1() != null || p.OMITTED() != null)
                    {
                        inouts.Add(callSiteParameter);
                    }
                }

                foreach (var p in context.callOutputParameter())
                {
                    var callSiteParameter = new CallSiteParameter
                    {
                        // TCRFUN_CALL_INOUT_AND_OUTPUT_BY_REFERENCE
                        SharingMode =
                            new SyntaxProperty <ParameterSharingMode>(ParameterSharingMode.ByReference, null),
                    };

                    if (p.sharedStorageArea1() != null)
                    {
                        callSiteParameter.StorageAreaOrValue = new Variable(CobolExpressionsBuilder.CreateSharedStorageArea(p.sharedStorageArea1()));
                    }
                    else if (p.OMITTED() != null)
                    {
                        callSiteParameter.Omitted = new SyntaxProperty <bool>(true, ParseTreeUtils.GetFirstToken(p.OMITTED()));
                    }

                    if (p.sharedStorageArea1() != null || p.OMITTED() != null)
                    {
                        outputs.Add(callSiteParameter);
                    }
                }

                int parametersCount = inputs.Count + outputs.Count + inouts.Count;
                callSite.Parameters = new CallSiteParameter[parametersCount];
                int i = 0;

                //Add inputs to global callsites parameters
                if (inputs.Count > 0)
                {
                    foreach (var param in inputs)
                    {
                        callSite.Parameters[i] = param;
                        i++;
                    }
                }

                //Add outputs to global callsites parameters
                if (outputs.Count > 0)
                {
                    foreach (var param in outputs)
                    {
                        callSite.Parameters[i] = param;
                        i++;
                    }
                }

                //Add inouts to global callsites parameters
                if (inouts.Count > 0)
                {
                    foreach (var param in inouts)
                    {
                        callSite.Parameters[i] = param;
                        i++;
                    }
                }

                #endregion

                //Check Type or CandidatesTypes to see if a TCFunctionName is possible
                if (ambiguousSymbolReference.MainSymbolReference != null &&
                    ambiguousSymbolReference.MainSymbolReference.IsOrCanBeOfType(SymbolType.TCFunctionName))
                {
                    SymbolReferenceVariable TCFunctionNameRefVariable;

                    if (ambiguousSymbolReference.MainSymbolReference.IsQualifiedReference)
                    {
                        var nonAmbiguousHead =
                            new SymbolReference(
                                (ambiguousSymbolReference.MainSymbolReference as TypeCobolQualifiedSymbolReference)?.Head
                                .NameLiteral, SymbolType.TCFunctionName);
                        var nonAmbiguousTail =
                            new SymbolReference(
                                (ambiguousSymbolReference.MainSymbolReference as TypeCobolQualifiedSymbolReference)?.Tail
                                .NameLiteral, SymbolType.ProgramName);

                        TypeCobolQualifiedSymbolReference newQualifiedSymbolReferece =
                            new TypeCobolQualifiedSymbolReference(nonAmbiguousHead, nonAmbiguousTail);
                        TCFunctionNameRefVariable = new SymbolReferenceVariable(StorageDataType.MethodName,
                                                                                newQualifiedSymbolReferece);
                    }
                    else
                    {
                        //If so, create ProcedureStyleCallStatement with a ProcedureCall and fix SymbolReference so it's not ambiguous
                        var nonAmbiguousSymbolRef =
                            new SymbolReference(ambiguousSymbolReference.MainSymbolReference.NameLiteral,
                                                SymbolType.TCFunctionName);
                        TCFunctionNameRefVariable = new SymbolReferenceVariable(StorageDataType.MethodName,
                                                                                nonAmbiguousSymbolRef);
                    }

                    //CobolExpressionsBuilder store every StorageArea created into storageAreaReads and then after
                    //storageAreaReads is set to the CodeElement
                    //We must remove it as TCFunctionNameRefVariable doesn't contains a StorageArea
                    if (ambiguousSymbolReference.StorageArea != null)
                    {
                        CobolExpressionsBuilder.storageAreaReads.Remove(ambiguousSymbolReference.StorageArea);
                    }

                    statement =
                        new ProcedureStyleCallStatement(new ProcedureCall(TCFunctionNameRefVariable.MainSymbolReference,
                                                                          inputs, inouts, outputs))
                    {
                        ProgramOrProgramEntryOrProcedureOrFunctionOrTCProcedureFunction =
                            TCFunctionNameRefVariable.MainSymbolReference
                    };

                    callSite.CallTarget = TCFunctionNameRefVariable.MainSymbolReference;
                }
                else
                {
                    //else it's an error
                    statement =
                        new ProcedureStyleCallStatement(new ProcedureCall(ambiguousSymbolReference.MainSymbolReference,
                                                                          inputs, inouts, outputs))
                    {
                        ProgramOrProgramEntryOrProcedureOrFunctionOrTCProcedureFunction = ambiguousSymbolReference.MainSymbolReference,
                        Diagnostics = new List <Diagnostic>
                        {
                            new Diagnostic(MessageCode.ImplementationError, context.Start.Column,
                                           context.Stop.Column, context.Start.Line,
                                           "A call with arguments is not a TCFunctionName")
                        },
                    };

                    callSite.CallTarget = ambiguousSymbolReference.MainSymbolReference;
                }
            }
            else
            {
                if (ambiguousSymbolReference.MainSymbolReference != null &&
                    ambiguousSymbolReference.MainSymbolReference.IsOrCanBeOfType(SymbolType.DataName, SymbolType.TCFunctionName))
                {
                    //TODO think about uniformity of CandidateTypes inside QualifiedReference.
                    //Maybe just define CandidatesTypes for the Head...
                    if (ambiguousSymbolReference.MainSymbolReference.IsQualifiedReference)
                    {
                        var qualifiedSymbolReference = (QualifiedSymbolReference)ambiguousSymbolReference.MainSymbolReference;


                        AmbiguousSymbolReference.ApplyCandidatesTypes(qualifiedSymbolReference, new[] { SymbolType.DataName, SymbolType.ProgramName });
                        //Adjust candidate types only for the first element
                        if (qualifiedSymbolReference.First.IsAmbiguous)
                        {
                            ((AmbiguousSymbolReference)qualifiedSymbolReference.First).CandidateTypes = new[] { SymbolType.DataName, SymbolType.TCFunctionName };
                        }
                    }
                    else
                    {
                        ((AmbiguousSymbolReference)ambiguousSymbolReference.MainSymbolReference).CandidateTypes = new[] { SymbolType.DataName, SymbolType.TCFunctionName };
                    }

                    statement = new ProcedureStyleCallStatement(new ProcedureCall(ambiguousSymbolReference.MainSymbolReference,
                                                                                  null, null, null))
                    {
                        ProcdurePointerOrTCProcedureFunction = ambiguousSymbolReference.MainSymbolReference
                    };
                    callSite            = new CallSite();
                    callSite.CallTarget = statement.ProcdurePointerOrTCProcedureFunction;
                }
                else     //else, it's an error
                {
                    statement =
                        new ProcedureStyleCallStatement(new ProcedureCall(ambiguousSymbolReference.MainSymbolReference,
                                                                          null, null, null))
                    {
                        ProgramOrProgramEntryOrProcedureOrFunctionOrTCProcedureFunction =
                            ambiguousSymbolReference.MainSymbolReference,
                    };
                    statement.Diagnostics.Add(new Diagnostic(MessageCode.SyntaxErrorInParser, context.Start.Column,
                                                             context.Stop.Column, context.Start.Line, "Error in detecting Procedure Call type"));
                    callSite            = new CallSite();
                    callSite.CallTarget = statement.ProgramOrProgramEntryOrProcedureOrFunctionOrTCProcedureFunction;
                }
            }


            if (callSite != null)
            {
                if (statement.CallSites == null)
                {
                    statement.CallSites = new List <CallSite>();
                }
                statement.CallSites.Add(callSite);
            }

            CodeElement = statement;
        }
Ejemplo n.º 4
0
 public virtual void OnProcedureStyleCall(ProcedureStyleCallStatement stmt, CallStatementEnd end)
 {
     Enter(new ProcedureStyleCall(stmt), stmt);
     AttachEndIfExists(end);
     Exit();
 }