public FunctionDeclaration(Compiler.Nodes.FunctionDeclaration originalNode) : base(originalNode.CodeElement())
 {
     ProgramName = originalNode.Hash;
     foreach (var child in originalNode.Children)
     {
         if (child is Compiler.Nodes.ProcedureDivision)
         {
             CreateOrUpdateLinkageSection(originalNode, originalNode.CodeElement().Profile);
             var sentences = new List <Node>();
             foreach (var sentence in child.Children)
             {
                 sentences.Add(sentence);
             }
             var pdiv = new ProcedureDivision(originalNode, sentences);
             children.Add(pdiv);
         }
         else
         if (child.CodeElement is FunctionDeclarationEnd)
         {
             children.Add(new ProgramEnd(new URI(ProgramName)));
         }
         else
         {
             // TCRFUN_CODEGEN_NO_ADDITIONAL_DATA_SECTION
             // TCRFUN_CODEGEN_DATA_SECTION_AS_IS
             children.Add(child);
         }
     }
     this.OriginalNode = originalNode;
 }
        private void CreateOrUpdateLinkageSection(Compiler.Nodes.FunctionDeclaration node, ParametersProfile profile)
        {
            var linkage    = node.Get <Compiler.Nodes.LinkageSection>("linkage");
            var parameters = profile.InputParameters.Count + profile.InoutParameters.Count + profile.OutputParameters.Count + (profile.ReturningParameter != null? 1:0);
            IReadOnlyList <DataDefinition> data = new List <DataDefinition>().AsReadOnly();

            if (linkage == null && parameters > 0)
            {
                var datadiv = node.Get <Compiler.Nodes.DataDivision>("data-division");
                if (datadiv == null)
                {
                    datadiv = new DataDivision();
                    children.Add(datadiv);
                }
                linkage = new LinkageSection();
                datadiv.Add(linkage);
            }
            if (linkage != null)
            {
                data = linkage.Children().ToList();
            }
            // TCRFUN_CODEGEN_PARAMETERS_ORDER
            var generated = new List <string>();

            foreach (var parameter in profile.InputParameters)
            {
                if (!generated.Contains(parameter.Name) && !Contains(data, parameter.Name))
                {
                    linkage.Add(CreateParameterEntry(parameter, node.SymbolTable));
                    generated.Add(parameter.Name);
                }
            }
            foreach (var parameter in profile.InoutParameters)
            {
                if (!generated.Contains(parameter.Name) && !Contains(data, parameter.Name))
                {
                    linkage.Add(CreateParameterEntry(parameter, node.SymbolTable));
                    generated.Add(parameter.Name);
                }
            }
            foreach (var parameter in profile.OutputParameters)
            {
                if (!generated.Contains(parameter.Name) && !Contains(data, parameter.Name))
                {
                    linkage.Add(CreateParameterEntry(parameter, node.SymbolTable));
                    generated.Add(parameter.Name);
                }
            }
            if (profile.ReturningParameter != null)
            {
                if (!generated.Contains(profile.ReturningParameter.Name) && !Contains(data, profile.ReturningParameter.Name))
                {
                    linkage.Add(CreateParameterEntry(profile.ReturningParameter, node.SymbolTable));
                    generated.Add(profile.ReturningParameter.Name);
                }
            }
        }
Example #3
0
        public ProcedureDivision(Compiler.Nodes.FunctionDeclaration declaration, [NotNull] List <Compiler.Nodes.Node> sentences) : base(null)
        {
            table           = declaration.SymbolTable;
            UsingParameters = new List <CallTargetParameter>();
            // TCRFUN_CODEGEN_PARAMETERS_ORDER
            foreach (var parameter in declaration.Profile.InputParameters)
            {
                if (parameter.LevelNumber.Value == 1)
                {
                    UsingParameters.Add(new GeneratedParameter(parameter.DataName));
                }
            }
            foreach (var parameter in declaration.Profile.InoutParameters)
            {
                if (parameter.LevelNumber.Value == 1)
                {
                    UsingParameters.Add(new GeneratedParameter(parameter.DataName));
                }
            }
            foreach (var parameter in declaration.Profile.OutputParameters)
            {
                if (parameter.LevelNumber.Value == 1)
                {
                    UsingParameters.Add(new GeneratedParameter(parameter.DataName));
                }
            }
            // TCRFUN_CODEGEN_RETURNING_PARAMETER
            if (declaration.Profile.ReturningParameter != null)
            {
                if (declaration.Profile.ReturningParameter.LevelNumber.Value == 1)
                {
                    ReturningParameter = new CallTargetParameter()
                    {
                        StorageArea = GeneratedParameter.CreateReceivingStorageArea(declaration.Profile.ReturningParameter.DataName)
                    }
                }
            }
            ;

            this.children.AddRange(sentences);

            var signature = new List <TextLineSnapshot>();

            signature.Add(new TextLineSnapshot(-1,
                                               string.Format("*{0}.{1} {2}", declaration.Root.MainProgram.Name, declaration.Name,
                                                             declaration.Profile.Parameters.Count != 0 ? "- Params :" : " - No Params"), null));
            signature.AddRange(declaration.Profile.GetSignatureForComment());

            Signature = signature;
        }
Example #4
0
        public ProcedureDivision(Compiler.Nodes.FunctionDeclaration declaration, List <Compiler.Nodes.Node> sentences) : base(null)
        {
            table           = declaration.SymbolTable;
            UsingParameters = new List <CallTargetParameter>();
            // TCRFUN_CODEGEN_PARAMETERS_ORDER
            foreach (var parameter in declaration.Profile.InputParameters)
            {
                if (parameter.LevelNumber.Value == 1)
                {
                    UsingParameters.Add(new GeneratedParameter(parameter.DataName));
                }
            }
            foreach (var parameter in declaration.Profile.InoutParameters)
            {
                if (parameter.LevelNumber.Value == 1)
                {
                    UsingParameters.Add(new GeneratedParameter(parameter.DataName));
                }
            }
            foreach (var parameter in declaration.Profile.OutputParameters)
            {
                if (parameter.LevelNumber.Value == 1)
                {
                    UsingParameters.Add(new GeneratedParameter(parameter.DataName));
                }
            }
            // TCRFUN_CODEGEN_RETURNING_PARAMETER
            if (declaration.Profile.ReturningParameter != null)
            {
                if (declaration.Profile.ReturningParameter.LevelNumber.Value == 1)
                {
                    ReturningParameter = new CallTargetParameter()
                    {
                        StorageArea = GeneratedParameter.CreateReceivingStorageArea(declaration.Profile.ReturningParameter.DataName)
                    }
                }
            }
            ;

            this.children.AddRange(sentences);
        }
        private void DeclareProceduresParametersIntoLinkage(Compiler.Nodes.FunctionDeclaration node, Compiler.Nodes.LinkageSection linkage, ParametersProfileNode profile)
        {
            var data = linkage.Children();

            // TCRFUN_CODEGEN_PARAMETERS_ORDER
            var generated = new List <string>();

            foreach (var parameter in profile.InputParameters)
            {
                if (!generated.Contains(parameter.Name) && !Contains(data, parameter.Name))
                {
                    linkage.Add(CreateParameterEntry(parameter, node));
                    generated.Add(parameter.Name);
                }
            }
            foreach (var parameter in profile.InoutParameters)
            {
                if (!generated.Contains(parameter.Name) && !Contains(data, parameter.Name))
                {
                    linkage.Add(CreateParameterEntry(parameter, node));
                    generated.Add(parameter.Name);
                }
            }
            foreach (var parameter in profile.OutputParameters)
            {
                if (!generated.Contains(parameter.Name) && !Contains(data, parameter.Name))
                {
                    linkage.Add(CreateParameterEntry(parameter, node));
                    generated.Add(parameter.Name);
                }
            }
            if (profile.ReturningParameter != null)
            {
                if (!generated.Contains(profile.ReturningParameter.Name) &&
                    !Contains(data, profile.ReturningParameter.Name))
                {
                    linkage.Add(CreateParameterEntry(profile.ReturningParameter, node));
                    generated.Add(profile.ReturningParameter.Name);
                }
            }
        }
        public FunctionDeclarationCG(Compiler.Nodes.FunctionDeclaration originalNode) : base(originalNode.CodeElement())
        {
            this.OriginalNode = originalNode;

            //Check if we need to generate something special for this Procedure
            bool needToGenerateParametersIntoLinkage = originalNode.CodeElement().Profile.InputParameters.Count + originalNode.CodeElement().Profile.InoutParameters.Count + originalNode.CodeElement().Profile.OutputParameters.Count +
                                                       (originalNode.CodeElement().Profile.ReturningParameter != null ? 1 : 0) > 0;
            //we'll generate things for public call
            var containsPublicCall = originalNode.ProcStyleCalls != null && originalNode.ProcStyleCalls.Count > 0;

            ProgramHashName = originalNode.Hash;
            //Get procedure original name and truncate it to 22 chars if over.
            OriginalProcName = originalNode.Name.Substring(0, Math.Min(originalNode.Name.Length, 22));

            foreach (var child in originalNode.Children)
            {
                if (child is Compiler.Nodes.ProcedureDivision)
                {
                    Compiler.Nodes.LinkageSection linkageSection = null;
                    Compiler.Nodes.DataDivision   dataDivision   = null;

                    //Create DataDivision and LinkageSection if needed
                    //DataDivision must be created before ProcedureDivision because Program Node doesn't manage order of their children
                    //DataDivision manage order of their children so it's ok
                    if (needToGenerateParametersIntoLinkage || containsPublicCall)
                    {
                        dataDivision   = GetOrCreateNode <Compiler.Nodes.DataDivision>(originalNode, () => new DataDivision());
                        linkageSection = GetOrCreateNode <Compiler.Nodes.LinkageSection>(dataDivision, () => new LinkageSection(originalNode), dataDivision);


                        //declare procedure parameters into linkage
                        DeclareProceduresParametersIntoLinkage(originalNode, linkageSection, originalNode.Profile);
                    }


                    //Replace ProcedureDivision node with a new one and keep all original children
                    var sentences = new List <Node>();
                    foreach (var sentence in child.Children)
                    {
                        sentences.Add(sentence);
                    }
                    var pdiv = new ProcedureDivision(originalNode, sentences);
                    children.Add(pdiv);


                    //Generate code if this procedure call a public procedure in another source

                    if (containsPublicCall)
                    {
                        var workingStorageSection = GetOrCreateNode <Compiler.Nodes.WorkingStorageSection>(dataDivision, () => new WorkingStorageSection(originalNode), dataDivision);

                        ProgramImports imports    = ProgramImportsAttribute.GetProgramImports(originalNode);
                        Node[]         toAddRange =
                        {
                            new GeneratedNode2("01 TC-Call          PIC X     VALUE 'T'.", true),
                            new GeneratedNode2("    88 TC-FirstCall  VALUE 'T'.",          true),
                            new GeneratedNode2("    88 TC-NthCall    VALUE 'F'",           true),
                            new GeneratedNode2("                     X'00' thru 'S'",      true),
                            new GeneratedNode2("                     'U' thru X'FF'.",     true)
                        };
                        workingStorageSection.AddRange(toAddRange, 0);
                        GenerateCodeToCallPublicProc(originalNode, pdiv, workingStorageSection, linkageSection);
                    }
                }
                else
                {
                    if (child.CodeElement is FunctionDeclarationEnd)
                    {
                        children.Add(new ProgramEnd(new URI(ProgramHashName), OriginalProcName));
                    }
                    else
                    {
                        // TCRFUN_CODEGEN_NO_ADDITIONAL_DATA_SECTION
                        // TCRFUN_CODEGEN_DATA_SECTION_AS_IS
                        children.Add(child);
                    }
                }
            }
        }