////////////////////
        // 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;
        }
Beispiel #2
0
 /// <summary>
 /// Detecting call site parameter
 /// </summary>
 /// <param name="callSiteParameter"></param>
 /// <returns></returns>
 public override bool Visit(CallSiteParameter callSiteParameter)
 {
     return(false);
 }