From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,fcdd0f6139250dc5,start X-Google-Attributes: gid103376,public From: "Robert C. Leif, Ph.D." Subject: Tagged Types and Generics Date: 1997/04/21 Message-ID: <3.0.32.19970421225247.007129f4@mail.4dcomm.com> X-Deja-AN: 236919101 Sender: Ada programming language X-Sender: rleif@mail.4dcomm.com Comments: Gated by NETNEWS@AUVM.AMERICAN.EDU Newsgroups: comp.lang.ada Date: 1997-04-21T00:00:00+00:00 List-Id: From: Bob Leif, Ph.D. To: Comp.Lang.Ada Date: 21 April, 1997 Subject: Tagged Types and Generics. Background: Recently, Tom Moran, Randy Brukard and I wrote a paper. "Ada 95, The Language Speaks for Itself". This paper will appear in the May Object Magazine. In this paper we modeled money as a decimal type and did inheritance directly via a generic. I had suggested modeling money as a tagged type. My co-authors very wisely vetoed that approach. After the paper was submitted, I attempted to do my suggestion and model money as a tagged type with the child libraries being the different currencies. If one makes the exchange rate a decimal type, then currency conversion requires a decimal division of the same field from two of the child library units. I created a function with class based types and tried to instantiate the generic procedure Divide in the Annex F Package Ada.Decimal. My lack of success is described in the listing of the body below. The program has been reduced and modified to demonstrate the problem. I know that I could probably get away with using a floating point type. However, if we are to sell Ada to the MIS world based in part on its capacity to do decimal arithmetic, then we should employ decimal arithmetic in our programs. I do not know how to pass the type an element in a tagged record to a generic. I tried recreating the type by including the values of the Scale and Digits attributes in the tagged record. I would appreciate suggestions and hope for a solution that I could show at the ACM SigAda booth at Object Expo in New York City from 2-5 June, 1997. Both the specification and body were compiled under GNAT for Windows. gcc -c -gnatlv dec_divide.adb > dec_divide.txt Specification source. generic type Num_Or_Denom is delta <> digits <>; type Ratio is delta <> digits <>; package Dec_Divide is type Num_Or_Denoms is abstract tagged private; --This the start of the class Function Ratio_Test(Numerator : in Num_Or_Denoms'Class; Denominator : in Num_Or_Denoms'Class) return Ratio; Private type Num_Or_Denoms is abstract tagged record The_Num_Or_Denom : Num_Or_Denom; Num_Or_Denom_Scale: Integer := Num_Or_Denom'Scale; Num_Or_Denom_digits: Integer := Num_Or_Denom'digits ; end record; end Dec_Divide; ---------------------------------------------------------------------------- ------------------------------ Listing of body. GNAT 3.09 (970121) Copyright 1991-1996 Free Software Foundation, Inc. Compiling: dec_divide.adb (source file time stamp: 1997-04-22 05:24:59) 1. -- From Ada 95 Referance Manual pages 47-48 Section 3.5.10 2. -- S'Scale 3. -- S'Scale denotes the scale of the subtype S, defined as the 4. -- value N such that S'Delta = 10.0**(-N). The scale indicates 5. -- the position of the point relative to the rightmost 6. -- significant digits of values of subtype S. The value 7. -- of this attribute is of the type universal_integer. 8. 9. -- Note 38. S'Scale is not always the same as S'Aft for a 10. -- decimal subtype; for example, if S'Delta = 1.0 then S'Aft 11. -- is 1 while S'Scale is 0. 12. 13. --S'Digits 14. --S'Digits denotes the digits of the decimal fixed point subtype S, 15. --which corresponds to the number of decimal digits that are 16. --representable in objects of the subtype. The value of this attribute 17. --is of the type universal_integer. 18. 19. -- Note 39. The predefined operations of a fixed point type 20. -- include the assignment operation, qualification, 21. -- the membership tests, and explicit conversion to and 22. -- from other numeric types. They also include the relational 23. -- operators and the following predefined arithmetic operators: 24. -- the binary and unary adding operators - and +, 25. -- multiplying operators, and the unary operator abs. 26. 27. with Ada.Decimal; 28. 29. package body Dec_Divide is 30. Function Ratio_Test(Numerator : in Num_Or_Denoms'Class; 31. Denominator : in Num_Or_Denoms'Class) 32. return Ratio is 33. 34. --This may require access types for the decimals types, which are 35. --dynamic rather than static. Maybe define box with a generic in the 36. --specification and pass over. With a pointer, one gets a general 37. --structure. 38. 39. Type Gen_Numerator is delta 10.0**(-Numerator.Num_Or_Denom_Scale) | >>> non-static expression used for delta value 40. digits Numerator.Num_Or_Denom_digits; | >>> non-static expression used for digits value 41. 42. Type Gen_Denominator is delta 10.0**(- Denominator.Num_Or_Denom_Scale) | >>> non-static expression used for delta value 43. digits Denominator.Num_Or_Denom_digits; | >>> non-static expression used for digits value 44. 45. 46. Procedure Divide is new Ada.Decimal.Divide 47. (Dividend_type => Gen_Numerator, 48. Divisor_Type => Gen_Denominator, 49. Quotient_Type => Ratio, 50. Remainder_Type => Ratio); 51. 52. Use Divide; | >>> "Divide" is not a usable package 53. The_Numerator: Gen_Numerator := Gen_Numerator(Numerator.The_Num_Or_Denom); 54. 55. The_Denominator:Gen_Denominator := Gen_Denominator(Denominator.The_Num_Or_Denom); 56. The_Ratio: Ratio; 57. The_Remainder: Ratio; 58. begin --Ratio_Test 59. 60. Divide 61. (Dividend => The_Numerator, 62. Divisor => The_Denominator, 63. Quotient => The_Ratio, 64. Remainder => The_Remainder); 65. Return The_Ratio; 66. end Ratio_Test; 67. end Dec_Divide; 67 lines: Robert C. Leif, Ph.D., PMIAC Vice President & Research Director Ada_Med, a Division of Newport Instruments 5648 Toyon Road San Diego, CA 92115-1022 Tel. & Fax (619) 582-0437 E-mail rleif@rleif.com