* how to organize source code for a complete software? Thanks! @ 2011-10-09 16:20 Jinsong Zhao 2011-10-09 17:16 ` stefan-lucks ` (2 more replies) 0 siblings, 3 replies; 14+ messages in thread From: Jinsong Zhao @ 2011-10-09 16:20 UTC (permalink / raw) Hi there, I am new to Ada, and I just have some experiences in using Fortran. When using Fortran, I generally put each subroutine or function in a separate file, e.g., dot.for for dot product of two vectors. Then a main.for that call the necessary subroutine or functions. It seems to be rational. When I using Ada, I don't know how to do. There are procedure, function, package, package body, and so on (with different file extension, e.g., ada, adb, ads, ...). And there is no main program. Would anyone here like to give a an analogy between the source code organization in Fortran and the one in Ada? And, please, if you like, point me a small, complete open source software in Ada (not a library or package). I should be compiled and run. I just hope to learn how to start a software in Ada by example. Any suggestions or comments will be really appreciated. Thanks in advance. Regards, Jinsong ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: how to organize source code for a complete software? Thanks! 2011-10-09 16:20 how to organize source code for a complete software? Thanks! Jinsong Zhao @ 2011-10-09 17:16 ` stefan-lucks 2011-10-10 5:52 ` Jinsong Zhao 2011-10-09 17:37 ` Yannick Duchêne (Hibou57) 2011-10-09 17:48 ` Niklas Holsti 2 siblings, 1 reply; 14+ messages in thread From: stefan-lucks @ 2011-10-09 17:16 UTC (permalink / raw) > I am new to Ada, and I just have some experiences in using Fortran. > > When using Fortran, I generally put each subroutine or function in a separate > file, e.g., dot.for for dot product of two vectors. Then a main.for that call > the necessary subroutine or functions. It seems to be rational. > > When I using Ada, I don't know how to do. There are procedure, function, > package, package body, and so on (with different file extension, e.g., ada, > adb, ads, ...). And there is no main program. 1. Any parameterless procedure, which is not "local" inside another function/procedure or inside a package, can be the main program. 2. As a rule of thumb for beginners: Put your auxiliary subprograms (in Ada: a subprogram is either a function or a procedure) and the requited type definition into packages. Write a single parameterless main procedure as the "main" procedure, but give it a meaningful name ("Solve_Linear_Equations" or "Delete_File" rather than "Main"). Put that procedure into a file of its own. 2a. Note that a package consists of a specification and an implementation, which are usually put into TWO different files (e.g., "name.ads" for the spec and "name.adb" for the implementation body). 2b. When you are more advanced in programming in Ada, you may sometimes want to compile "separate" subprograms without wrapping them into packages. 3. Compile the main procedure (e.g., by calling "gnatmake" if you use the gnat Ada compiler) -- your compiler will know which packages it needs to compile. > And, please, if you like, point me a small, complete open source software in > Ada (not a library or package). I should be compiled and run. I just hope to > learn how to start a software in Ada by example. Examples: <http://rosettacode.org/wiki/Linear_congruential_generator#Ada> <http://rosettacode.org/wiki/Ternary_logic#Ada> The linear congruential example would consist of three files: 1. the specification "lcg.ads", 2. the implementation "lcg.adb", and 3. the main program "run_lcgs.adb". (These are the gnat/gcc naming conventions, look into your compiler documentation if you use another compiler.) As an easy exercise for the reader, try to figure out which three files the ternary logic example would consist of. -- ------ Stefan Lucks -- Bauhaus-University Weimar -- Germany ------ Stefan dot Lucks at uni minus weimar dot de ------ I love the taste of Cryptanalysis in the morning! ------ ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: how to organize source code for a complete software? Thanks! 2011-10-09 17:16 ` stefan-lucks @ 2011-10-10 5:52 ` Jinsong Zhao 0 siblings, 0 replies; 14+ messages in thread From: Jinsong Zhao @ 2011-10-10 5:52 UTC (permalink / raw) On 2011-10-10 1:16, stefan-lucks@see-the.signature wrote: >> I am new to Ada, and I just have some experiences in using Fortran. >> >> When using Fortran, I generally put each subroutine or function in a separate >> file, e.g., dot.for for dot product of two vectors. Then a main.for that call >> the necessary subroutine or functions. It seems to be rational. >> >> When I using Ada, I don't know how to do. There are procedure, function, >> package, package body, and so on (with different file extension, e.g., ada, >> adb, ads, ...). And there is no main program. > > 1. Any parameterless procedure, which is not "local" inside another > function/procedure or inside a package, can be the main program. > > 2. As a rule of thumb for beginners: Put your auxiliary subprograms (in > Ada: a subprogram is either a function or a procedure) and the requited > type definition into packages. Write a single parameterless main > procedure as the "main" procedure, but give it a meaningful name > ("Solve_Linear_Equations" or "Delete_File" rather than "Main"). Put > that procedure into a file of its own. > > 2a. Note that a package consists of a specification and an implementation, > which are usually put into TWO different files (e.g., "name.ads" for > the spec and "name.adb" for the implementation body). > > 2b. When you are more advanced in programming in Ada, you may sometimes > want to compile "separate" subprograms without wrapping them into > packages. > > 3. Compile the main procedure (e.g., by calling "gnatmake" if you use the > gnat Ada compiler) -- your compiler will know which packages it needs > to compile. Thank you very much. The above statements give me more information than what I get from the books available to me here. Now, I think I know how to layout my small program. > >> And, please, if you like, point me a small, complete open source software in >> Ada (not a library or package). I should be compiled and run. I just hope to >> learn how to start a software in Ada by example. > > Examples: > <http://rosettacode.org/wiki/Linear_congruential_generator#Ada> > <http://rosettacode.org/wiki/Ternary_logic#Ada> It's a nice place for me. Thanks! > > The linear congruential example would consist of three files: > 1. the specification "lcg.ads", > 2. the implementation "lcg.adb", and > 3. the main program "run_lcgs.adb". > (These are the gnat/gcc naming conventions, look into your compiler > documentation if you use another compiler.) > > As an easy exercise for the reader, try to figure out which three files > the ternary logic example would consist of. > > I think I can get the answer: 1. the specification "logic.ads", 2. the implementation "logic.adb", and 3. the main program "test_tri_logic.adb". Thanks again for your informative reply and the example codes. Regards, Jinsong ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: how to organize source code for a complete software? Thanks! 2011-10-09 16:20 how to organize source code for a complete software? Thanks! Jinsong Zhao 2011-10-09 17:16 ` stefan-lucks @ 2011-10-09 17:37 ` Yannick Duchêne (Hibou57) 2011-10-10 6:02 ` Jinsong Zhao 2011-10-09 17:48 ` Niklas Holsti 2 siblings, 1 reply; 14+ messages in thread From: Yannick Duchêne (Hibou57) @ 2011-10-09 17:37 UTC (permalink / raw) Welcome Jinsong :-) Le Sun, 09 Oct 2011 18:20:53 +0200, Jinsong Zhao <jszhao@yeah.net> a écrit: > When I using Ada, I don't know how to do. There are procedure, function, > package, package body, and so on (with different file extension, e.g., > ada, adb, ads, ...). And there is no main program. *.ada is not that common. Where did you see it ? *.adb and *.ads are not Ada specific, these are GNAT specific instead. The Ada Reference Manual does not specify file layout, nor file extensions. So this all depend on your compiler, which is GNAT here it seems (you may also have a look at Janus Ada from RRSoftware, if Ada 95 is enough for you). The file layout for GNAT is as this: Package specification in *.ads files Package body in *.adb Main procedure in *.adb Separate body in *.adb In few words: specifications goes to *.ads, which stands for Ada Specification, and implementations goes to *.adb, which stands for Ada Body. File names (not extensions) must be derived from compilation unit names, with this transformation applied: all uppercase characters turned into lowercase and periods turned into dashes. Example: your have a package name My_AI_Lib.Knowledge (to say we play with fun things). Then the specification will be in my_ai_lib-knowledge.ads, the body will be in my_ai_lib-knowledge.adb. If your test main program is a procedure named Test_My_AI, then it will belong to a file named test_my_ai.adb Similar things applies with separate bodies and child packages. Worth to read at your stage: http://www.adacore.com/wp-content/files/auto_update/gnat-unw-docs/html/gnat_ugn_2.html > Would anyone here like to give a an analogy between the source code > organization in Fortran and the one in Ada? Unless you use separate bodies all over the place, there is no way to compare Ada layout and Fortran layout. With Ada, multiple procedure may belong to a single package. May be there exist some compiler which requires each procedure to reside in its own file, but GNAT don't use such a layout. Keep in mind this is compiler specific! > And, please, if you like, point me a small, complete open source > software in Ada (not a library or package). I should be compiled and > run. I just hope to learn how to start a software in Ada by example. I did not checked all of it, but here is a good list of samples (there may be some others too): http://sandbox.mc.edu/~bennet/ada/examples/ > Any suggestions or comments will be really appreciated. Thanks in > advance. Yes, start with this: >>> -- Hello World, the quick easy form. with Ada.Text_IO; use Ada.Text_IO; procedure Hello is begin Put_Line ("Hello, Bonjour, Ohayo"); end; >>> Second alternative, for people who enjoy to be more formal or strict: >>> -- Hello World, the proud form (lol). with Ada.Text_IO; procedure Hello is package IO renames Ada.Text_IO; Greeting_Message : constant String := "Hello, Bonjour, Ohayo"; begin IO.Put_Line (Greeting_Message); end Hello; >>> > Regards, > Jinsong Have a nice time Jinsong -- “Syntactic sugar causes cancer of the semi-colons.” [Epigrams on Programming — Alan J. — P. Yale University] “Structured Programming supports the law of the excluded muddle.” [Idem] Java: Write once, Never revisit ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: how to organize source code for a complete software? Thanks! 2011-10-09 17:37 ` Yannick Duchêne (Hibou57) @ 2011-10-10 6:02 ` Jinsong Zhao 2011-10-10 13:15 ` Paul Colin Gloster 0 siblings, 1 reply; 14+ messages in thread From: Jinsong Zhao @ 2011-10-10 6:02 UTC (permalink / raw) On 2011-10-10 1:37, Yannick Duchêne (Hibou57) wrote: > Welcome Jinsong :-) > > Le Sun, 09 Oct 2011 18:20:53 +0200, Jinsong Zhao <jszhao@yeah.net> a écrit: >> When I using Ada, I don't know how to do. There are procedure, >> function, package, package body, and so on (with different file >> extension, e.g., ada, adb, ads, ...). And there is no main program. > *.ada is not that common. Where did you see it ? *.adb and *.ads are not > Ada specific, these are GNAT specific instead. The Ada Reference Manual > does not specify file layout, nor file extensions. Oops, I have seen *.ada somewhere, but I don't recall it... > > So this all depend on your compiler, which is GNAT here it seems (you > may also have a look at Janus Ada from RRSoftware, if Ada 95 is enough > for you). > > The file layout for GNAT is as this: > Package specification in *.ads files > Package body in *.adb > Main procedure in *.adb > Separate body in *.adb > > In few words: specifications goes to *.ads, which stands for Ada > Specification, and implementations goes to *.adb, which stands for Ada > Body. > > File names (not extensions) must be derived from compilation unit names, > with this transformation applied: all uppercase characters turned into > lowercase and periods turned into dashes. > > Example: your have a package name My_AI_Lib.Knowledge (to say we play > with fun things). Then the specification will be in > my_ai_lib-knowledge.ads, the body will be in my_ai_lib-knowledge.adb. If > your test main program is a procedure named Test_My_AI, then it will > belong to a file named test_my_ai.adb > > Similar things applies with separate bodies and child packages. > > Worth to read at your stage: > http://www.adacore.com/wp-content/files/auto_update/gnat-unw-docs/html/gnat_ugn_2.html > Yes, I use GNAT as the compiler. However, I didn't find a way to obtain those information before I post and get help here. > >> Would anyone here like to give a an analogy between the source code >> organization in Fortran and the one in Ada? > Unless you use separate bodies all over the place, there is no way to > compare Ada layout and Fortran layout. With Ada, multiple procedure may > belong to a single package. May be there exist some compiler which > requires each procedure to reside in its own file, but GNAT don't use > such a layout. Keep in mind this is compiler specific! There is many difference between the Ada layout and Fortran layout, however, I just have some experiences in Fortran. I will try my best to do something similar with the Ada style. > >> And, please, if you like, point me a small, complete open source >> software in Ada (not a library or package). I should be compiled and >> run. I just hope to learn how to start a software in Ada by example. > I did not checked all of it, but here is a good list of samples (there > may be some others too): > http://sandbox.mc.edu/~bennet/ada/examples/ Yes it's a good place for learn Ada from piece of Ada sample code. > >> Any suggestions or comments will be really appreciated. Thanks in >> advance. > Yes, start with this: > >>>> > -- Hello World, the quick easy form. > > with Ada.Text_IO; use Ada.Text_IO; > > procedure Hello is > begin > Put_Line ("Hello, Bonjour, Ohayo"); > end; >>>> > > Second alternative, for people who enjoy to be more formal or strict: > >>>> > -- Hello World, the proud form (lol). > > with Ada.Text_IO; > > procedure Hello is > package IO renames Ada.Text_IO; > Greeting_Message : constant String := "Hello, Bonjour, Ohayo"; > begin > IO.Put_Line (Greeting_Message); > end Hello; >>>> > >> Regards, >> Jinsong > Have a nice time Jinsong > Thank you very much for your kind help. Regards, Jinsong ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: how to organize source code for a complete software? Thanks! 2011-10-10 6:02 ` Jinsong Zhao @ 2011-10-10 13:15 ` Paul Colin Gloster 2011-10-10 15:46 ` Simon Wright ` (2 more replies) 0 siblings, 3 replies; 14+ messages in thread From: Paul Colin Gloster @ 2011-10-10 13:15 UTC (permalink / raw) Jinsong Zhao <jszhao@yeah.net> sent on October 10th, 2011: |-----------------------------------------------------------| |"[..] | | | |Oops, I have seen *.ada somewhere, but I don't recall it...| | | |[..]" | |-----------------------------------------------------------| Hi, That is not a mistake. There are compilers which support *.ada. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: how to organize source code for a complete software? Thanks! 2011-10-10 13:15 ` Paul Colin Gloster @ 2011-10-10 15:46 ` Simon Wright 2011-10-10 19:03 ` RasikaSrinivasan@gmail.com 2011-10-10 22:12 ` Randy Brukardt 2 siblings, 0 replies; 14+ messages in thread From: Simon Wright @ 2011-10-10 15:46 UTC (permalink / raw) Paul Colin Gloster <Colin_Paul_Gloster@ACM.org> writes: > Jinsong Zhao <jszhao@yeah.net> sent on October 10th, 2011: > |-----------------------------------------------------------| > |"[..] | > | | > |Oops, I have seen *.ada somewhere, but I don't recall it...| > | | > |[..]" | > |-----------------------------------------------------------| > > Hi, > > That is not a mistake. There are compilers which support *.ada. GNAT comes with a tool 'gnatchop' which will split an Ada source file containing multiple units into the separate files that GNAT expects; and it makes sense to use .ada for such a file. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: how to organize source code for a complete software? Thanks! 2011-10-10 13:15 ` Paul Colin Gloster 2011-10-10 15:46 ` Simon Wright @ 2011-10-10 19:03 ` RasikaSrinivasan@gmail.com 2011-10-10 22:12 ` Randy Brukardt 2 siblings, 0 replies; 14+ messages in thread From: RasikaSrinivasan@gmail.com @ 2011-10-10 19:03 UTC (permalink / raw) On Oct 10, 9:15 am, Paul Colin Gloster <Colin_Paul_Glos...@ACM.org> wrote: > Jinsong Zhao <jsz...@yeah.net> sent on October 10th, 2011: > |-----------------------------------------------------------| > |"[..] | > | | > |Oops, I have seen *.ada somewhere, but I don't recall it...| > | | > |[..]" | > |-----------------------------------------------------------| > > Hi, > > That is not a mistake. There are compilers which support *.ada. Way back when - DEC Ada (on VMS) was around: conventions were : Package Specs => *_.ADA Package Body => *.ADA Upon compilation the same sources used to get copied into an Ada library *.ADC ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: how to organize source code for a complete software? Thanks! 2011-10-10 13:15 ` Paul Colin Gloster 2011-10-10 15:46 ` Simon Wright 2011-10-10 19:03 ` RasikaSrinivasan@gmail.com @ 2011-10-10 22:12 ` Randy Brukardt 2 siblings, 0 replies; 14+ messages in thread From: Randy Brukardt @ 2011-10-10 22:12 UTC (permalink / raw) "Paul Colin Gloster" <Colin_Paul_Gloster@ACM.org> wrote in message news:alpine.LFD.2.00.1110101413140.20260@localhost.localdomain... >> Jinsong Zhao <jszhao@yeah.net> sent on October 10th, 2011: >> Oops, I have seen *.ada somewhere, but I don't recall it... > That is not a mistake. There are compilers which support *.ada. Pretty much any Ada compiler will support .ada, as that is the native extension of (most of) the ACATS tests. A compiler could rename all of the tests, but it is a lot easier to support processing that extension. Other ACATS tests use .dep, .a, and .tst -- so most Ada compilers allow arbitrary extensions. (The default extensions, important for tools like Gnatmake, are a different story, and differ between some compilers.) Randy. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: how to organize source code for a complete software? Thanks! 2011-10-09 16:20 how to organize source code for a complete software? Thanks! Jinsong Zhao 2011-10-09 17:16 ` stefan-lucks 2011-10-09 17:37 ` Yannick Duchêne (Hibou57) @ 2011-10-09 17:48 ` Niklas Holsti 2011-10-09 18:37 ` Ludovic Brenta 2011-10-10 6:45 ` Jinsong Zhao 2 siblings, 2 replies; 14+ messages in thread From: Niklas Holsti @ 2011-10-09 17:48 UTC (permalink / raw) On 11-10-09 18:20 , Jinsong Zhao wrote: > Hi there, > > I am new to Ada, and I just have some experiences in using Fortran. Welcome, then. May I ask what attracted you to Ada? I am asking partly out of curiosity, but also because if you tell us what you hope to gain by using Ada, we may better advise you on how to organize your code, and on other Ada usage. > When using Fortran, I generally put each subroutine or function in a > separate file, e.g., dot.for for dot product of two vectors. Then a > main.for that call the necessary subroutine or functions. It seems to be > rational. > > When I using Ada, I don't know how to do. If you like, you can do exactly as you are accustomed to doing in Fortran (although this would be an unusual style for Ada). You can put each Ada function or procedure in its own compilation unit. The only difference is that you will typically write two files per subprogram, one to specify the subprogram (its name, its parameters, and its return type, if it is a function) and one to implement the subprogram by giving its body, which contains the declarations of the local variables and the statements that are executed in the subprogram. For example, let's make a function that adds two Float numbers and returns their sum, and let's call this function Add. In the following, I assume you are using the GNAT Ada compiler and its default conventions for source file names. The Add function will have a specification (or declaration) file add.ads, which contains this one line: function Add (A, B : Float) return Float; Any other subprogram that needs to use (call) the Add function will start with the line with Add; which makes the compiler read the file add.ads, so that the compiler knows the name, parameters, and return type of Add. The Add function will have an implementation (or body) file add.adb, which contains these five lines: function Add (A, B : Float) return Float is begin return A + B; end Add; Assume that your main subprogram should use Add to compute the sum of the numbers 15.6 and 88.2 and print out the sum, and you give this procedure the name Main, then you would write it as the file main.adb with the following content: with Add; -- So that we can call Add, below. with Ada.Text_IO; -- So that we can call Put_Line, below. procedure Main is begin Ada.Text_IO.Put_Line (Float'Image (Add (15.6, 88.2))); end Main; This program thus consists of three files: add.ads, add.adb, main.adb. To compile this program with GNAT, you only have to give the command gnatmake main and GNAT will compile all three files and create an executable called main. > There are procedure, function, > package, package body, and so on (with different file extension, e.g., > ada, adb, ads, ...). And there is no main program. The main program is just a parameterless procedure, like the Main above. It can be called anything you like; its name usually (but not necessarily) becomes the name of the program executable. The one-subprogram-per-file method shown above, which is what you have been doing in Fortran, breaks down when you have subprograms that need to access some global data, for example like Fortran COMMON data. If you don't want to pass all this data in parameters, you must put it in a package. Then you can have two Ada designs, one that is very similar to Fortran COMMON, and the other that is more typical for Ada. Here is how to do the Fortran-like design. Suppose that the Add function, above, should also include in the sum the value of a global variable Offset, that relates to some "scale" that the program is using, but you don't want to pass Offset as a parameter to Add. In Fortran, you could declare a COMMON area called Scale, containing a variable called Offset. In Ada, this can be implemented as a package Scale with a public variable Offset. Such a package is written in one file, scale.ads, as follows: package Scale is Offset : Float := 0.0; end Scale; Here I also gave the Offset an initial value, just to avoid using an undefined value. The Add function would now be written as follows, in add.adb: with Scale; function Add (A, B : Float) return Float is begin return A + B + Scale.Offset; end Add; Note that: - the line "with Scale" gives us access to the data in Scale, but - you still have to use the qualified name, Scale.Offset, to refer to the variable Offset in the package Scale. If you add a line after "with Scale", saying "use Scale", you can use just the name Offset instead of Scale.Offset. But many Ada programmers think that such "use clauses" should be used very sparingly, and that writing Scale.Offset is clearer. Note that the file add.ads was not changed, since the text in that file does not have to refer to the Scale package. Suppose now that your Main subprogram needs to Add the same two numbers as before, but with an Offset of 3.2. This would be written as follows, in main.adb: with Add; -- So that we can call Add, below. with Scale; -- So that we can access Scale.Offset, below. with Ada.Text_IO; -- So that we can call Put_Line, below. procedure Main is begin Scale.Offset := 3.2; Ada.Text_IO.Put_Line (Float'Image (Add (15.6, 88.2)); end Main; > Would anyone here like to give a an analogy between the source code > organization in Fortran and the one in Ada? The example above was how one would represent Fortran COMMON in Ada packages, in a Fortran-like way: write the COMMON area as a package (*.ads file) with public variables representing the COMMON data, and then "with" this package in any subprogram (*.adb file) that needs to use this data. However, this style is not the typical Ada style. The more common style in Ada is to make packages that contain both data and subprograms, and to make the data private as far as possible. This is stretching the above example a bit, but the principle would be to put the Add function in the Scale package, since it needs to use Scale.Offset, and to move the Offset variable into the package body, so that it cannot be accessed from outside the package. The file scale.ads would now look like this: package Scale is function Add (A, B : Float) return Float; procedure Set_Offset (To : in Float); end Scale; The declaration of the Offset variable, and the bodies of the two subprograms, would now be written in the "body file" for Scale, which is called scale.adb and contains this: package body Scale is Offset : Float := 0.0; function Add (A, B : Float) return Float is begin return A + B + Offset; end Add; procedure Set_Offset (To : in Float) is begin Offset := To; end Set_Offset; end Scale; Of course, the files add.ads and add.adb are now unnecessary, since Add is both declared and implemented within package Scale, thus in the files scale.ads and scale.adb. The Main subprogram in main.adb would now have this form: with Scale; -- So that we can use it, below. with Ada.Text_IO; -- So that we can call Put_Line, below. procedure Main is begin Scale.Set_Offset (3.2); Ada.Text_IO.Put_Line (Float'Image (Scale.Add (15.6, 88.2)); end Main; The single command "gnatmake main" is still enough to compile the program, although Main now uses other packages. If you have any other subprograms that are also related to the Scale, and need to use Scale.Offset, you would put them in package Scale, too. Of course, finding a good package structure can become complex if you have something like a Fortran program with several COMMON areas, and have several subprograms that use different subsets of the COMMON areas. You can fall back on the Fortran-like structure (one package per COMMON area, with public data), or look up some texts on "information hiding" and "software architecture", but even so, there are usually several ways to slice the cake, and the best way is often a matter of taste. > And, please, if you like, point me a small, complete open source > software in Ada (not a library or package). I should be compiled and > run. I just hope to learn how to start a software in Ada by example. Sorry, my internet access at present (on travel) is so wonky that I have no web access, in practice. -- Niklas Holsti Tidorum Ltd niklas holsti tidorum fi . @ . ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: how to organize source code for a complete software? Thanks! 2011-10-09 17:48 ` Niklas Holsti @ 2011-10-09 18:37 ` Ludovic Brenta 2011-10-09 21:24 ` J-P. Rosen 2011-10-10 12:09 ` Jinsong Zhao 2011-10-10 6:45 ` Jinsong Zhao 1 sibling, 2 replies; 14+ messages in thread From: Ludovic Brenta @ 2011-10-09 18:37 UTC (permalink / raw) Niklas Holsti writes on comp.lang.ada: > On 11-10-09 18:20 , Jinsong Zhao wrote: >> Hi there, >> >> I am new to Ada, and I just have some experiences in using Fortran. > > Welcome, then. May I ask what attracted you to Ada? I am asking partly > out of curiosity, but also because if you tell us what you hope to > gain by using Ada, we may better advise you on how to organize your > code, and on other Ada usage. I am curious, too. >> When using Fortran, I generally put each subroutine or function in a >> separate file, e.g., dot.for for dot product of two vectors. Then a >> main.for that call the necessary subroutine or functions. It seems to >> be rational. OK but where do you place variables that are shared by multiple subroutines or functions? Where do you place type declarations? This is quite crucial for my point below. >> When I using Ada, I don't know how to do. In addition to the rules of thumb given by others, I'll now explain the reasoning behind a proper choice of where to place your subprograms. It's all about _visibility_. package P is -- this part is visible to anyone who says "with P;" private -- this part is visible only from the body of P end P; package body P is -- this part is completely hidden end P; procedure Proc is -- this part is completely hidden begin -- this part is completely hidden end Proc; A subprogram declared in the package P can see everything in the public and private parts of the spec; it can also see everything that has been declared above it inside the body. Thus, a package spec will normally look like: package P is type T is private; procedure Foo (Param : in out T); private type T is ...; end P; If several subprograms use the same type T in their specs, then they should all be declared in the same package. So, my advice to you is to organize your sources not in terms of subprograms, but in terms of types; each major type should be in a package of its own, along with all the subprograms that operate on it. One example that I wrote is here: http://green.ada-france.org:8081/revision/browse/108fe173864fa16185a547d486849a475dd3c2a3 You will find one main subprogram (test.adb), one spec (s_expression.ads) declaring a type T and all subprograms operating on it (the type T is private and its details are in the private part of the spec), and one package body (s_expression.adb) containing the implementation of those subprograms. -- Ludovic Brenta. ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: how to organize source code for a complete software? Thanks! 2011-10-09 18:37 ` Ludovic Brenta @ 2011-10-09 21:24 ` J-P. Rosen 2011-10-10 12:09 ` Jinsong Zhao 1 sibling, 0 replies; 14+ messages in thread From: J-P. Rosen @ 2011-10-09 21:24 UTC (permalink / raw) Le 09/10/2011 20:37, Ludovic Brenta a �crit : > OK but where do you place variables that are shared by multiple > subroutines or functions? Where do you place type declarations? This > is quite crucial for my point below. In Fortran, you would place them in Common blocks. You can have the same effect in Ada by having packages that contain only (types and) variables. I'm not saying it is recommended practice in Ada, although some design methods (SA) lead you to group subprograms on one side and data on the other side. Of course, the OO wave does the opposite (group related subprograms and data). -- --------------------------------------------------------- J-P. Rosen (rosen@adalog.fr) Adalog a d�m�nag� / Adalog has moved: 2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00 ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: how to organize source code for a complete software? Thanks! 2011-10-09 18:37 ` Ludovic Brenta 2011-10-09 21:24 ` J-P. Rosen @ 2011-10-10 12:09 ` Jinsong Zhao 1 sibling, 0 replies; 14+ messages in thread From: Jinsong Zhao @ 2011-10-10 12:09 UTC (permalink / raw) On 2011-10-10 2:37, Ludovic Brenta wrote: > Niklas Holsti writes on comp.lang.ada: >> On 11-10-09 18:20 , Jinsong Zhao wrote: >>> Hi there, >>> >>> I am new to Ada, and I just have some experiences in using Fortran. >> >> Welcome, then. May I ask what attracted you to Ada? I am asking partly >> out of curiosity, but also because if you tell us what you hope to >> gain by using Ada, we may better advise you on how to organize your >> code, and on other Ada usage. > > I am curious, too. > >>> When using Fortran, I generally put each subroutine or function in a >>> separate file, e.g., dot.for for dot product of two vectors. Then a >>> main.for that call the necessary subroutine or functions. It seems to >>> be rational. > > OK but where do you place variables that are shared by multiple > subroutines or functions? Where do you place type declarations? This > is quite crucial for my point below. In Fortran 90 or newer standard, those variables and type declaration can be put into module. In Fortran 77, the variable are put into COMMON, and block data section. > >>> When I using Ada, I don't know how to do. > > In addition to the rules of thumb given by others, I'll now explain the > reasoning behind a proper choice of where to place your subprograms. > It's all about _visibility_. > > package P is > -- this part is visible to anyone who says "with P;" > private > -- this part is visible only from the body of P > end P; > > package body P is > -- this part is completely hidden > end P; > > procedure Proc is > -- this part is completely hidden > begin > -- this part is completely hidden > end Proc; > > A subprogram declared in the package P can see everything in the public > and private parts of the spec; it can also see everything that has been > declared above it inside the body. Thus, a package spec will normally > look like: > > package P is > type T is private; > procedure Foo (Param : in out T); > private > type T is ...; > end P; > > If several subprograms use the same type T in their specs, then they > should all be declared in the same package. So, my advice to you is to > organize your sources not in terms of subprograms, but in terms of > types; each major type should be in a package of its own, along with all > the subprograms that operate on it. One example that I wrote is here: > > http://green.ada-france.org:8081/revision/browse/108fe173864fa16185a547d486849a475dd3c2a3 > > You will find one main subprogram (test.adb), one spec > (s_expression.ads) declaring a type T and all subprograms operating on > it (the type T is private and its details are in the private part of the > spec), and one package body (s_expression.adb) containing the > implementation of those subprograms. > Thank you very much for your example and advices on visibility. Regards, Jinsong ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: how to organize source code for a complete software? Thanks! 2011-10-09 17:48 ` Niklas Holsti 2011-10-09 18:37 ` Ludovic Brenta @ 2011-10-10 6:45 ` Jinsong Zhao 1 sibling, 0 replies; 14+ messages in thread From: Jinsong Zhao @ 2011-10-10 6:45 UTC (permalink / raw) On 2011-10-10 1:48, Niklas Holsti wrote: > On 11-10-09 18:20 , Jinsong Zhao wrote: >> Hi there, >> >> I am new to Ada, and I just have some experiences in using Fortran. > > Welcome, then. May I ask what attracted you to Ada? I am asking partly > out of curiosity, but also because if you tell us what you hope to gain > by using Ada, we may better advise you on how to organize your code, and > on other Ada usage. At first, I should express my thanks for your kind, detailed, and informative reply. Long time ago, I have read a introductory material about Ada, and know it's a excellent programming language. So, I hope to try it, and write some small program in numerical computation, for which I used to code in Fortran. > >> When using Fortran, I generally put each subroutine or function in a >> separate file, e.g., dot.for for dot product of two vectors. Then a >> main.for that call the necessary subroutine or functions. It seems to be >> rational. >> >> When I using Ada, I don't know how to do. > > If you like, you can do exactly as you are accustomed to doing in > Fortran (although this would be an unusual style for Ada). You can put > each Ada function or procedure in its own compilation unit. > > The only difference is that you will typically write two files per > subprogram, one to specify the subprogram (its name, its parameters, and > its return type, if it is a function) and one to implement the > subprogram by giving its body, which contains the declarations of the > local variables and the statements that are executed in the subprogram. > > For example, let's make a function that adds two Float numbers and > returns their sum, and let's call this function Add. In the following, I > assume you are using the GNAT Ada compiler and its default conventions > for source file names. > > The Add function will have a specification (or declaration) file > add.ads, which contains this one line: > > function Add (A, B : Float) return Float; > > Any other subprogram that needs to use (call) the Add function will > start with the line > > with Add; > > which makes the compiler read the file add.ads, so that the compiler > knows the name, parameters, and return type of Add. > > The Add function will have an implementation (or body) file add.adb, > which contains these five lines: > > function Add (A, B : Float) return Float > is > begin > return A + B; > end Add; > > Assume that your main subprogram should use Add to compute the sum of > the numbers 15.6 and 88.2 and print out the sum, and you give this > procedure the name Main, then you would write it as the file main.adb > with the following content: > > with Add; -- So that we can call Add, below. > with Ada.Text_IO; -- So that we can call Put_Line, below. > procedure Main > is > begin > Ada.Text_IO.Put_Line (Float'Image (Add (15.6, 88.2))); > end Main; > > This program thus consists of three files: add.ads, add.adb, main.adb. > To compile this program with GNAT, you only have to give the command > > gnatmake main > > and GNAT will compile all three files and create an executable called main. > >> There are procedure, function, >> package, package body, and so on (with different file extension, e.g., >> ada, adb, ads, ...). And there is no main program. > > The main program is just a parameterless procedure, like the Main above. > It can be called anything you like; its name usually (but not > necessarily) becomes the name of the program executable. > > The one-subprogram-per-file method shown above, which is what you have > been doing in Fortran, breaks down when you have subprograms that need > to access some global data, for example like Fortran COMMON data. If you > don't want to pass all this data in parameters, you must put it in a > package. Then you can have two Ada designs, one that is very similar to > Fortran COMMON, and the other that is more typical for Ada. > > Here is how to do the Fortran-like design. Suppose that the Add > function, above, should also include in the sum the value of a global > variable Offset, that relates to some "scale" that the program is using, > but you don't want to pass Offset as a parameter to Add. In Fortran, you > could declare a COMMON area called Scale, containing a variable called > Offset. In Ada, this can be implemented as a package Scale with a public > variable Offset. Such a package is written in one file, scale.ads, as > follows: > > package Scale > is > Offset : Float := 0.0; > end Scale; > > Here I also gave the Offset an initial value, just to avoid using an > undefined value. > > The Add function would now be written as follows, in add.adb: > > with Scale; > function Add (A, B : Float) return Float > is > begin > return A + B + Scale.Offset; > end Add; > > Note that: > > - the line "with Scale" gives us access to the data in Scale, but > > - you still have to use the qualified name, Scale.Offset, to refer > to the variable Offset in the package Scale. > > If you add a line after "with Scale", saying "use Scale", you can use > just the name Offset instead of Scale.Offset. But many Ada programmers > think that such "use clauses" should be used very sparingly, and that > writing Scale.Offset is clearer. > > Note that the file add.ads was not changed, since the text in that file > does not have to refer to the Scale package. > > Suppose now that your Main subprogram needs to Add the same two numbers > as before, but with an Offset of 3.2. This would be written as follows, > in main.adb: > > with Add; -- So that we can call Add, below. > with Scale; -- So that we can access Scale.Offset, below. > with Ada.Text_IO; -- So that we can call Put_Line, below. > procedure Main > is > begin > Scale.Offset := 3.2; > Ada.Text_IO.Put_Line (Float'Image (Add (15.6, 88.2)); > end Main; > >> Would anyone here like to give a an analogy between the source code >> organization in Fortran and the one in Ada? > > The example above was how one would represent Fortran COMMON in Ada > packages, in a Fortran-like way: write the COMMON area as a package > (*.ads file) with public variables representing the COMMON data, and > then "with" this package in any subprogram (*.adb file) that needs to > use this data. > > However, this style is not the typical Ada style. The more common style > in Ada is to make packages that contain both data and subprograms, and > to make the data private as far as possible. > > This is stretching the above example a bit, but the principle would be > to put the Add function in the Scale package, since it needs to use > Scale.Offset, and to move the Offset variable into the package body, so > that it cannot be accessed from outside the package. The file scale.ads > would now look like this: > > package Scale > is > function Add (A, B : Float) return Float; > procedure Set_Offset (To : in Float); > end Scale; > > The declaration of the Offset variable, and the bodies of the two > subprograms, would now be written in the "body file" for Scale, which is > called scale.adb and contains this: > > package body Scale > is > > Offset : Float := 0.0; > > function Add (A, B : Float) return Float > is > begin > return A + B + Offset; > end Add; > > procedure Set_Offset (To : in Float) > is > begin > Offset := To; > end Set_Offset; > > end Scale; > > Of course, the files add.ads and add.adb are now unnecessary, since Add > is both declared and implemented within package Scale, thus in the files > scale.ads and scale.adb. > > The Main subprogram in main.adb would now have this form: > > with Scale; -- So that we can use it, below. > with Ada.Text_IO; -- So that we can call Put_Line, below. > procedure Main > is > begin > Scale.Set_Offset (3.2); > Ada.Text_IO.Put_Line (Float'Image (Scale.Add (15.6, 88.2)); > end Main; > > The single command "gnatmake main" is still enough to compile the > program, although Main now uses other packages. > > If you have any other subprograms that are also related to the Scale, > and need to use Scale.Offset, you would put them in package Scale, too. > I think that described in above is a excellent tutorial for a Fortran user who hope to learn Ada as a second language. Thank you very much for simplifying the complex problem. > Of course, finding a good package structure can become complex if you > have something like a Fortran program with several COMMON areas, and > have several subprograms that use different subsets of the COMMON areas. > You can fall back on the Fortran-like structure (one package per COMMON > area, with public data), or look up some texts on "information hiding" > and "software architecture", but even so, there are usually several ways > to slice the cake, and the best way is often a matter of taste. Yes, the programs that I have read in Fortran all have many COMMON areas. I will try to learn how to deal with those situation using Ada. Of course, your tutors above gave me many help. > >> And, please, if you like, point me a small, complete open source >> software in Ada (not a library or package). I should be compiled ands >> run. I just hope to learn how to start a software in Ada by example. > > Sorry, my internet access at present (on travel) is so wonky that I have > no web access, in practice. > Thanks again! Regards, Jinsong ^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2011-10-10 22:12 UTC | newest] Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2011-10-09 16:20 how to organize source code for a complete software? Thanks! Jinsong Zhao 2011-10-09 17:16 ` stefan-lucks 2011-10-10 5:52 ` Jinsong Zhao 2011-10-09 17:37 ` Yannick Duchêne (Hibou57) 2011-10-10 6:02 ` Jinsong Zhao 2011-10-10 13:15 ` Paul Colin Gloster 2011-10-10 15:46 ` Simon Wright 2011-10-10 19:03 ` RasikaSrinivasan@gmail.com 2011-10-10 22:12 ` Randy Brukardt 2011-10-09 17:48 ` Niklas Holsti 2011-10-09 18:37 ` Ludovic Brenta 2011-10-09 21:24 ` J-P. Rosen 2011-10-10 12:09 ` Jinsong Zhao 2011-10-10 6:45 ` Jinsong Zhao
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox