diff options
Diffstat (limited to 'ada.html.markdown')
| -rw-r--r-- | ada.html.markdown | 416 | 
1 files changed, 416 insertions, 0 deletions
| diff --git a/ada.html.markdown b/ada.html.markdown new file mode 100644 index 00000000..7191c5dc --- /dev/null +++ b/ada.html.markdown @@ -0,0 +1,416 @@ +--- +language: Ada +filename: learn.ada +contributors: +    - ["Luke A. Guest", "https://github.com/Lucretia"] +    - ["Fernando Oleo Blanco", "https://github.com/Irvise"] +    - ["Fabien Chouteau", "https://github.com/Fabien-Chouteau"] +    - ["Manuel", "https://github.com/mgrojo"] +--- + +Ada is a strong statically typed imperative, [object-oriented](https://ada-lang.io/docs/arm/AA-3/AA-3.9), [real-time](https://ada-lang.io/docs/arm/AA-D), [parallel](https://ada-lang.io/docs/arm/AA-9) and [distributed](https://ada-lang.io/docs/arm/AA-9) programming language from the Pascal/Algol family of languages, but nowadays, it only has a passing resemblance to Pascal, with the only remnants left being the ```begin/end``` keyword pair, the ```:=``` assignment symbol, records and ```if/case``` control statement structures. + +Ada was originally designed to be an [object-based](https://ada-lang.io/docs/arm/AA-3/AA-3.3) language and to replace 100's of languages in use by the US government. This means that all entities are objects, not in the object-oriented sense. The language became [Object-Oriented](https://ada-lang.io/docs/arm/AA-3/AA-3.9) in 1995, and added [interfaces](https://ada-lang.io/docs/arm/AA-3/AA-3.9#Subclause_3.9.4) derived from Java in 2005. [Contract based](https://ada-lang.io/docs/arm/AA-13/AA-13.1#Subclause_13.1.1) programming was introduced with Ada 2012. + +Ada was designed to be easy to read and learn, even for non-programmers, e.g. management within an organisation, therefore programs written in the language tend to be a bit more verbose. + +Ada is a modern programming language, and now has a package manager like other modern languages, Alire, see below. + +```ada +--  Comments are written with a double hyphen and exist until the end of +--  the line. + +--  You do not need to call the entry point "Main" or "main," you should +--  name it based on what the program does. +procedure Empty is +   --  This is a declarative part. +begin +   --  Statements go here. +   null;  --  Do nothing here. +end Empty; + +--  Ada compilers accept compilation units which can be library packages, +--  tasks, sub-programs, generics, etc. + +--  This is where "context clauses" go, these can be pragmas or "with" +--  statements. "with" is equivalent to "include" or "import" in other +--  languages. +with Ada.Text_IO;  --  Get access to a library package. + +procedure Hello is +begin +   Ada.Text_IO.Put_Line ("Hello, world"); + +   Ada.Text_IO.Put ("Hello again, world"); +   Ada.Text_IO.New_Line; +end Hello; + + +--  Ada has a real module system. Modules are called packages and are split into +--  two component parts, the specification and a body. +--  It is important to introduce packages early, as you will be using them from +--  the start. +package Stuff is +   --  We could add the following line in order to tell the compiler that this +   --  package does not have to run any code before the "main" procedure starts. +   --  pragma Preelaborate; + +   --  Packages can be nested within the same file or externally. +   --  Nested packages are accessed via dot notation, e.g. Stuff.Things.My. +   package Things is +      My : constant Integer := 100; +   end Things; + +   --  If there are sub-programs declared within the specification, the body +   --  of the sub-program must be declared within the package body. +   procedure Do_Something;  --  If a subprogram takes no parameters, empty +                            --  parentheses are not required, unlike other +                            --  languages. + +   --  We can also make generic sub-programs. +   generic +      type Element is (<>);  --  The "(<>)" notation specifies that only +                             --  discrete types can be passed into the generic. +   procedure Swap (Left, Right : in out Element); + +   --  Sometimes we want to hide how a type is defined from the outside world +   --  so that nobody can mess with it directly. The full type must be defined +   --  within the private section below. +   type Blobs is private; + +   --  We can also make types "limited" by putting this keyword after the "is" +   --  keyword, this means that the user cannot copy objects of that type +   --  around, like they normally could. +private +   type Blobs is new Integer range -25 .. 25; +end Stuff; + + +package body Stuff is +   --  Sub-program body. +   procedure Do_Something is +      --  We can nest sub-programs too. +      --  Parameters are defined with the direction of travel, in, in out, out. +      --  If the direction of travel is not specified, they are in by default. +      function Times_4 (Value : in Integer) return Integer is +      begin +         return Value * 4; +      end Times_4; + +      I : Integer := 4; +   begin +      I := Times_4 (I); +   end Do_Something; + + +   --  Generic procedure body. +   procedure Swap (Left, Right : in out Element) is +      Temp : Element := Left; +   begin +      Left  := Right; +      Right := Temp; +   end Swap; +begin +   --  If we need to initialise something within the package, we can do it +   --  here. +   Do_Something; +end Stuff; + + +with Ada.Unchecked_Conversion; +with Ada.Text_IO; +with Stuff; + +procedure LearnAdaInY is +   --  Indentation is 3 spaces. + +   --  The most important feature in Ada is the type. Objects have types and an +   --  object of one type cannot be assigned to an object of another type. + +   --  You can, and should, define your own types for the domain you are +   --  modelling. But you can use the standard types to start with and then +   --  replace them later with your own types, this could be called a form of +   --  gradual typing. + +   --  The standard types would only really be a good starting point for binding +   --  to other languages, like C. Ada is the only language with a standardised +   --  way to bind with C, Fortran and COBOL! See the links in the References +   --  section with more information on binding to these languages. + +   type Degrees is range 0 .. 360;  --  This is a type. Its underlying +                                    --  representation is an Integer. + +   type Hues is (Red, Green, Blue, Purple, Yellow);  --  So is this. Here, we +                                                     --  are declaring an +                                                     --  Enumeration. + +   --  This is a modular type. They behave like Integers that automatically +   --  wrap around. In this specific case, the range would be 0 .. 359. +   --  If we added 1 to a variable containing the value 359, we would receive +   --  back 0. They are very useful for arrays. +   type Degrees_Wrap is mod 360; + +   --  You can restrict a type's range using a subtype, this makes them +   --  compatible with each other, i.e. the subtype can be assigned to an +   --  object of the type, as can be seen below. +   subtype Primaries is Hues range Red .. Blue;  --  This is a range. + +   --  You can define variables or constants like this: +   --  Var_Name : Type := Value; + +   --  10 is a universal integer. These universal numerics can be used with +   --  any type which matches the base type. +   Angle : Degrees := 10; +   Value : Integer := 20; +   --  New_Angle : Degrees := Value;  --  Incompatible types won't compile. +   --  New_Value : Integer := Angle; + +   Blue_Hue   :          Primaries := Blue;  --  A variable. +   Red_Hue    : constant Primaries := Red;   --  A constant. +   Yellow_Hue : constant Hues      := Yellow; +   Colour_1   : constant Hues      := Red_Hue; +   --  Colour_2   : constant Primaries := Yellow_Hue;  --  uncomment to compile. + +   --  You can force conversions, but then you are warned by the name of the +   --  package that you may be doing something unsafe. +   function Degrees_To_Int is new Ada.Unchecked_Conversion +     (Source => Degrees,   --  Line continuations are indented by 2 spaces. +      Target => Integer); + +   New_Value_2 : Integer := Degrees_To_Int (Angle);  --  Note, space before (. + +   --  GNAT is the GNU Ada Translator (compiler). +   --  Ada has a style guide and GNAT will warn you to adhere to it, and has +   --  option to check your style so that you can correct it so that all Ada +   --  source looks consistent. However, the style can be customized. + +   --  Yes, you can even define your own floating and fixed point types, this +   --  is a very rare and unique ability. "digits" refers to the minimum +   --  digit precision that the type should support. "delta" is for fixed +   --  point types and refers to the smallest change that the type will support. +   type Real_Angles is digits 3 range 0.0 .. 360.0; +   type Fixed_Angles is delta 0.01 digits 5 range 0.0 .. 360.0; + +   RA : constant Real_Angles  := 36.45; +   FA : constant Fixed_Angles := 360.0;  --  ".0" in order to make it a Float. + +   --  You can have normal Latin 1 based strings by default. +   Str  : constant String    := "This is a constant string"; +   --  When initialising from a string literal, the compiler knows the bounds, +   --  so we don't have to define them. + +   --  Strings are arrays. Note how parentheses are used to access elements of +   --  an array? This is mathematical notation and was used because square +   --  brackets were not available on all keyboards at the time Ada was +   --  created. Also, because an array can be seen as a function from a +   --  mathematical perspective, so it made converting between arrays and +   --  functions easier. +   Char : constant Character := Str (Str'First);  --  "'First" is a type +                                                  --  attribute. + +   --  Ada 2022 includes the use of [] for array initialisation when using +   --  containers, which were added in Ada 2012. + +   --  Arrays are usually always defined as a type. +   --  They can be any dimension. +   type My_Array_1 is array (1 .. 4, 3 .. 7, -20 .. 20) of Integer; + +   --  Yes, unlike other languages, you can index arrays with other discrete +   --  types such as enumerations and modular types or arbitrary ranges. +   type Axes is (X, Y, Z); + +   --  You can define the array's range using the 'Range attribute from +   --  another type. +   type Vector is array (Axes'Range) of Float; + +   V1 : constant Vector := (0.0, 0.0, 1.0); + +   --  A record is the same as a structure in C, C++. +   type Entities is record +      Name     : String (1 .. 10);  --  Always starts at a positive value, +                                    --  inclusive range. +      Position : Vector; +   end record; + +   --  In Ada, array bounds are immutable. You therefore have to provide a +   --  string literal with a value for every character. +   E1 : constant Entities := ("Blob      ", (0.0, 0.0, 0.0)); + +   --  An alternative is to use an array aggregate and assign a default value +   --  to every element that wasn't previously assigned in this aggregate. +   --  "others" is used to indicate anything else that has not been +   --  explicitly initialized. +   E2 : constant Entities := (('B', 'l', 'o', 'b', others => ' '), +                              (0.0, 0.0, 0.0)); + +   --  There are dynamic length strings (see references section) available in +   --  the standard library. + +   --  We can make an object be initialised to its default values with the box +   --  notation, "<>". "others" is used to indicate anything else that has not +   --  been explicitly initialized. +   Null_Entity : constant Entities := (others => <>); + +   --  Object-orientation is accomplished via an extension of record syntax, +   --  tagged records, see link above in first paragraph. + +   --  We can rename objects (aliases) to make readability a bit better. +   package IO renames Ada.Text_IO; +begin +   --  We can output enumerations as names. +   IO.Put_Line ("Blue_Hue   = " &  --  & is the string concatenation operator. +                Blue'Image);       --  ' accesses attributes on objects. +                  --  The Image attribute converts a value to a string. +                  --  Ada 2022 has extended Image to custom types too. +                  --  Access this with -gnat2022 compiler flag. +   IO.Put_Line ("Yellow_Hue = " & +                --  We can use the type's attribute. +                Primaries'Image (Yellow_Hue)); + +   --  We can define local variables within a declare block, this can be made +   --  more readable by giving it a label. +   Enum_IO : declare +      package Hue_IO is new IO.Enumeration_IO (Hues); + +      --  Using a package makes everything inside that package visible within +      --  this block, it is good practice to only do this locally and not on +      --  a whole package within the context clause. +      use Hue_IO; +   begin +      --  We can print out the enumeration values too. +      Put (Purple); --  Note we don't have to prefix the Put procedure with +                    --  Hue_IO. +      IO.New_Line;  --  We still need to prefix with IO here. +      Put (Red_Hue); +      IO.New_Line; +   end Enum_IO; + +   --  Loops have a consistent form. "<form> loop ... end loop". +   --  Where "form" can be "while" or "for" or missing as below, if +   --  you place the "loop ... end loop;" construct on their own lines, +   --  you can comment out or experiment with different loop constructs more +   --  easily. +   declare +      Counter : Positive := Positive'First;  --  This is 1. +   begin +      --  We can label loops so we can exit from them more easily if we need to. +      Infinite : +      loop +         IO.Put_Line ("[Infinite loop] Counter = " & Counter'Image); + +         Counter := Counter + 1; + +         --  This next line implements a repeat ... until or do ... while loop construct. +         --  Comment it out for an infinite loop. +         exit Infinite when Counter = 5;  --  Equality tests use a single "=". +      end loop Infinite;  --  Useful when implementing state machines. +   end; + +   declare  --  We don't have to have a label. +      Counter : Positive := Positive'First;  --  This is 1. +   begin +      while Counter < 10 +      loop +         IO.Put_Line ("Counter = " & Counter'Image); + +         Counter := Counter + 1;  --  There is no explicit inc/decrement. + +         --  Ada 2022 introduced @ for LHS, so the above would be written as +         --  Counter := @ + 1;  --  Try it, -gnat2022. +      end loop; +   end; + +   declare +      package Hue_IO is new IO.Enumeration_IO (Hues); + +      --  We can have multiple packages on one line, but I tend to use one +      --  package per line for readability. +      use IO, Hue_IO; +   begin +      Put ("Hues : ");  --  Note, no prefix. + +      --  Because we are using the 'Range attribute, the compiler knows it is +      --  safe and can omit run-time checks here. +      for Hue in Hues'Range +      loop +         Put (Hue); + +         --  Types and objects know about their bounds, their First .. Last +         --  values. These can be specified as range types. +         if Hue /= Hues'Last then  --  The /= means "not equal to" like the +                                   --  maths symbol ≠. +            Put (", "); +         end if; +      end loop; + +      IO.New_Line; +   end; + +   --  All objects know their bounds, including strings. +   declare +      C : Character := Str (50);  --  Warning caused and exception raised at +                                  --  runtime. +      --  The exception raised above can only be handled by an outer scope, +      --  see wikibook link below. +   begin +      null;  --  We will never get to this point because of the above. +   end; +exception +   when Constraint_Error => +      IO.Put_Line ("Caught the exception"); +end LearnAdaInY; +``` + +Now, that's a lot of information for a basic intro to Ada, and I've only touched the surface, there's much more to look at in the references section below. I haven't even touched on dynamic memory allocation which includes [pools](https://ada-lang.io/docs/arm/AA-13/AA-13.11), this is because for the most part, Ada programs don't need it, you can do a lot without it. + +As I stated above, Ada barely looks like Pascal and if you look at the original [Green specification](https://apps.dtic.mil/sti/trecms/pdf/ADB950587.pdf) (Warning: Huge 4575 page scanned PDF - starting on page 460), it looks nothing like it at all (page 505 of that PDF). + +The above source code will compile, but also will give warnings showing the power of the strong static type system. + +## Download this source + +If you already have the GNAT toolchain installed, you can cut and paste the above into a new file, e.g. ```learn-ada-in-y.ada``` and then run the following: + +```bash +$ gnatchop learn-ada-in-y.ada # This breaks the program into its specification ".ads" and body ".adb". +$ gnatmake empty.adb # gnatmake takes care of compilation of all units and linking. +$ gnatmake hello.adb +$ gnatmake learnadainy.adb +``` + +Or, download [Alire](https://alire.ada.dev), copy it to somewhere in your PATH and then do the following: + +**N.B.** Alire will automatically install the toolchain for you if you don't have one installed and will ask you to select which you want to use. + +```bash +$ alr search learnadainy +$ alr get learnadainy +$ cd learnadainy +$ alr run empty +$ alr run hello +$ alr run learnadainy +``` + +## Further Reading + +* [Ada Programming Language](https://ada-lang.io) +* [Ada 2022 Reference Manual](https://ada-lang.io/docs/arm) +* [Ada Style Guide](https://ada-lang.io/docs/style-guide/Ada_Style_Guide) +* [Learn more Ada/Spark at AdaCore's site](https://learn.adacore.com) + +## References from the source above + +1. [wikibook](https://en.wikibooks.org/wiki/Ada_Programming/Exceptions#Exception_handlers) +2. [C](https://ada-lang.io/docs/arm/AA-B/AA-B.3) +3. [Fortran](https://ada-lang.io/docs/arm/AA-B/AA-B.5/) +4. [COBOL](https://ada-lang.io/docs/arm/AA-B/AA-B.4/) +5. [dynamic length strings](https://ada-lang.io/docs/arm/AA-A/AA-A.4#Subclause_A.4.5) + +### Multi-line comments + +Multi-line comments are not allowed as they are error prone. + +> Such comments would require a closing comment delimiter and this would again raise the dangers associated with the (unintentional) omission of the closing delimiter: entire sections of a program could be ignored by the compiler without the programmer realizing it +> +> [Ada 83 Rationale](http://archive.adaic.com/standards/83rat/html/ratl-02-01.html#2.1) + | 
