diff --git a/courses/fundamentals_of_ada/075_type_derivation.rst b/courses/fundamentals_of_ada/075_type_derivation.rst index f1eb7e9e9..a5c9d848f 100644 --- a/courses/fundamentals_of_ada/075_type_derivation.rst +++ b/courses/fundamentals_of_ada/075_type_derivation.rst @@ -49,24 +49,92 @@ Type Derivation - Tagged derivation **is** OOP in Ada -------------------------------------- -Ada Mechanisms for Type Inheritance -------------------------------------- +--------------------------- +Reminder: What is a Type? +--------------------------- -* :dfn:`Primitive` operations on types +* A type is characterized by two elements + + - Its data structure + - The set of operations that applies to it + +* The operations are called **primitive operations** in Ada + +.. container:: latex_environment small + + .. code:: Ada + + package Types is + type Integer_T is range -(2**63) .. 2**63-1 with Size => 64; + procedure Increment_With_Truncation (Val : in out Integer_T); + procedure Increment_With_Rounding (Val : in out Integer_T); + end Types; + +=================== +Simple Derivation +=================== + +------------------------ +Simple Type Derivation +------------------------ + +* Any type (except :ada:`tagged`) can be derived + + .. code:: Ada + + type Natural_T is new Integer_T range 0 .. Integer_T'Last; + +* :ada:`Natural_T` inherits from: + + - The data **representation** of the parent + + * Integer based, 64 bits + + - The **primitives** of the parent + + * :ada:`Increment_With_Truncation` and :ada:`Increment_With_Rounding` + +* The types are not the same + + .. code:: Ada + + I_Obj : Integer_T := 0; + N_Obj : Natural_T := 0; + + * :ada:`I_Obj := N_Obj;` |rightarrow| generates a compile error + + :color-red:`expected type "Integer_T" defined at line 2` - - Standard operations like **+** and **-** - - Any operation that acts on the type + * But a child can be converted to the parent -* Type derivation + * :ada:`I_Obj := Integer_T (N_Obj);` - - Define types from other types that can add limitations - - Can add operations to the type +-------------------------------------- +Simple Derivation and Type Structure +-------------------------------------- + +* The type "structure" can not change + + - :ada:`array` cannot become :ada:`record` + - Integers cannot become floats + +* But can be **constrained** further +* Scalar ranges can be reduced -* Tagged derivation + .. code:: Ada - - **This** is OOP in Ada - - Seen in other chapter + type Positive_T is new Natural_T range 1 .. Natural_T'Last; + +* Unconstrained types can be constrained + + .. code:: Ada + + type Arr_T is array (Integer range <>) of Integer; + type Ten_Elem_Arr_T is new Arr_T (1 .. 10); + type Rec_T (Size : Integer) is record + Elem : Arr_T (1 .. Size); + end record; + type Ten_Elem_Rec_T is new Rec_T (10); ============ Primitives @@ -76,36 +144,46 @@ Primitives Primitive Operations -------------------- -* A type is characterized by two elements +* Primitive Operations are those subprograms associated with a type - - Its data structure - - The set of operations that applies to it +.. code:: Ada -* The operations are called **primitive operations** in Ada + type Integer_T is range -(2**63) .. 2**63-1 with Size => 64; + procedure Increment_With_Truncation (Val : in out Integer_T); + procedure Increment_With_Rounding (Val : in out Integer_T); + +* Most types have some primitive operations defined by the language + + * e.g. equality operators for most types, numeric operators for integers and floats + +* A primitive operation on the parent can receive an object of a child type with no conversion .. code:: Ada - type T is new Integer; - procedure Attrib_Function (Value : T); + declare + N_Obj : Natural_T := 1234; + begin + Increment_With_Truncation (N_Obj); + end; ------------------------------- -General Rule for a Primitive ------------------------------- +--------------------------------------- +General Rule for Defining a Primitive +--------------------------------------- * Primitives are subprograms -* `S` is a primitive of type `T` iff +* Subprogram :ada:`S` is a primitive of type :ada:`T` if and only if: - - `S` is declared in the scope of `T` - - `S` "uses" type `T` + - :ada:`S` is declared in the scope of :ada:`T` + - :ada:`S` uses type :ada:`T` + As a parameter - + As its return type (for :ada:`function`) + + As its return type (for a :ada:`function`) - - `S` is above :dfn:`freeze-point` + - :ada:`S` is above :dfn:`freeze-point` (see next section) -* Rule of thumb +* Standard practice - - Primitives must be declared **right after** the type itself + - Primitives should be declared **right after** the type itself - In a scope, declare at most a **single** type with primitives .. code:: Ada @@ -117,65 +195,55 @@ General Rule for a Primitive function F return T; end P; -=================== -Simple Derivation -=================== - ------------------------- -Simple Type Derivation ------------------------- - -* Any type (except :ada:`tagged`) can be derived - - .. code:: Ada - - type Child is new Parent; - -* Child inherits from: - - - The data **representation** of the parent - - The **primitives** of the parent +------------------------------ +Primitive of Multiple Types +------------------------------ -* Conversions are possible from child to parent +A subprogram can be a primitive of several types .. code:: Ada - type Parent is range 1 .. 10; - procedure Prim (V : Parent); - type Child is new Parent; -- Freeze Parent - procedure Not_A_Primitive (V : Parent); - C : Child; - ... - Prim (C); -- Implicitly declared - Not_A_Primitive (Parent (C)); + package P is + type Distance_T is range 0 .. 9999; + type Percentage_T is digits 2 range 0.0 .. 1.0; + type Units_T is (Meters, Feet, Furlongs); --------------------------------------- -Simple Derivation and Type Structure --------------------------------------- + procedure Convert (Value : in out Distance_T; + Source : Units_T; + Result : Units_T; + procedure Shrink (Value : in out Distance_T; + Percent : Percentage_T); -* The type "structure" can not change + end P; - - :ada:`array` cannot become :ada:`record` - - Integers cannot become floats +* :ada:`Convert` and :ada:`Shrink` are primitives for :ada:`Distance_T` +* :ada:`Convert` is also a primitive of :ada:`Units_T` +* :ada:`Shrink` is also a primitive of :ada:`Percentage_T` -* But can be **constrained** further -* Scalar ranges can be reduced +---------------------------------- +Creating Primitives for Children +---------------------------------- - .. code:: Ada +* Just because we can inherit a primitive from out parent doesn't mean we want to - type Tiny_Int is range -100 .. 100; - type Tiny_Positive is new Tiny_Int range 1 .. 100; +* We can create a new primitive (with the same name as the parent) for the child -* Unconstrained types can be constrained + * Very similar to overloaded subprograms + * But added benefit of visibility to grandchildren - .. code:: Ada +* We can also remove a primitive (see next slide) - type Arr is array (Integer range <>) of Integer; - type Ten_Elem_Arr is new Arr (1 .. 10); - type Rec (Size : Integer) is record - Elem : Arr (1 .. Size); - end record; - type Ten_Elem_Rec is new Rec (10); +.. code:: Ada + + type Integer_T is range -(2**63) .. 2**63-1; + procedure Increment_With_Truncation (Val : in out Integer_T); + procedure Increment_With_Rounding (Val : in out Integer_T); + + type Child_T is new Integer_T range -1000 .. 1000; + procedure Increment_With_Truncation (Val : in out Child_T); + + type Grandchild_T is new Child_T range -100 .. 100; + procedure Increment_With_Rounding (Val : in out Grandchild_T); ------------------------ Overriding Indications @@ -184,29 +252,44 @@ Overriding Indications * **Optional** indications * Checked by compiler - .. code:: Ada + .. container:: latex_environment footnotesize + + .. code:: Ada - type Root is range 1 .. 100; - procedure Prim (V : Root); - type Child is new Root; + type Child_T is new Integer_T range -1000 .. 1000; + procedure Increment_With_Truncation + (Val : in out Child_T); + procedure Just_For_Child + (Val : in out Child_T); * **Replacing** a primitive: :ada:`overriding` indication - .. code:: Ada + .. container:: latex_environment footnotesize + + .. code:: Ada - overriding procedure Prim (V : Child); + overriding procedure Increment_With_Truncation + (Val : in out Child_T); * **Adding** a primitive: :ada:`not overriding` indication - .. code:: Ada + .. container:: latex_environment footnotesize - not overriding procedure Prim2 (V : Child); + .. code:: Ada + + not overriding procedure Just_For_Child + (Val : in out Child_T); * **Removing** a primitive: :ada:`overriding` as :ada:`abstract` - .. code:: Ada + .. container:: latex_environment footnotesize + + .. code:: Ada - overriding procedure Prim (V : Child) is abstract; + overriding procedure Just_For_Child + (Val : in out Grandchild_T) is abstract; + +* Using :ada:`overriding` or :ada:`not overriding` incorrectly will generate a compile error .. language_version 2005 @@ -215,32 +298,112 @@ Overriding Indications Quiz ------ +.. include:: quiz/operators_override_simple/quiz.rst + +============== +Freeze Point +============== + +----------------------------- +What is the "Freeze Point"? +----------------------------- + +* Ada doesn't explicitly identify the end of the "scope" of a type + + * The compiler needs to know it for determining primitive operations + * Also needed for other situations (described elsewhere) + +* This end is the implicit **freeze point** occurring whenever: + + - A **variable** of the type is **declared** + - The type is **derived** + - The **end of the scope** is reached + +* Subprograms past this "freeze point" are not primitive operations + .. code:: Ada - type T1 is range 1 .. 100; - procedure Proc_A (X : in out T1); + type Parent is Integer; + procedure Prim (V : Parent); + + type Child is new Parent; + + -- Parent has been derived, so it is frozen. + -- Prim2 is not a primitive + procedure Prim2 (V : Parent); + + V : Child; + + -- Child used in an object declaration, so it is frozen + -- Prim3 is not a primitive + procedure Prim3 (V : Child); + +----------------------- +Debugging Type Freeze +----------------------- + +* Freeze |rightarrow| Type **completely** defined +* Compiler does **need** to determine the freeze point + + - To instantiate, derive, get info on the type (:ada:`'Size`)... + - Freeze rules are a guide to place it + - Actual choice is more technical + + + May contradict the standard + +* :command:`-gnatDG` to get **expanded** source + + - **Pseudo-Ada** debug information + +:filename:`pkg.ads` + + .. code:: Ada + + type Up_To_Eleven is range 0 .. 11; + +:filename:`/pkg.ads.dg` + +.. container:: latex_environment tiny + + :: + + type example__up_to_eleven_t is range 0 .. 11; -- type declaration + [type example__Tup_to_eleven_tB is new short_short_integer] -- representation + freeze example__Tup_to_eleven_tB [] -- freeze representation + freeze example__up_to_eleven_t [] -- freeze representation + +------ +Quiz +------ + +.. container:: latex_environment tiny + + .. code:: Ada + + type Parent is range 1 .. 100; + procedure Proc_A (X : in out Parent); - type T2 is new T1 range 2 .. 99; - procedure Proc_B (X : in out T1); - procedure Proc_B (X : in out T2); + type Child is new Parent range 2 .. 99; + procedure Proc_B (X : in out Parent); + procedure Proc_B (X : in out Child); - -- Other scope - procedure Proc_C (X : in out T2); + -- Other scope + procedure Proc_C (X : in out Child); - type T3 is new T2 range 3 .. 98; + type Grandchild is new Child range 3 .. 98; - procedure Proc_C (X : in out T3); + procedure Proc_C (X : in out Grandchild); .. container:: columns .. container:: column - Which are :ada:`T1`'s primitives + Which are :ada:`Parent`'s primitives? A. :answermono:`Proc_A` B. ``Proc_B`` C. ``Proc_C`` - D. No primitives of :ada:`T1` + D. No primitives of :ada:`Parent` .. container:: column @@ -249,11 +412,10 @@ Quiz Explanations A. Correct - B. Freeze: :ada:`T1` has been derived + B. Freeze: :ada:`Parent` has been derived C. Freeze: scope change D. Incorrect -. ========= Summary