Ada's type system is extremely powerful precisely because it's intrinsic to the language and its compilation process--it's a programming paradigm. Separating them out as a separate library misses out on its other benefits. Unfortunately, Ada markets it as a safety feature when it offers so much more. They allow the programmer to model a problem in a declarative way. Let's look at modeling a 6502 microprocessor, for instance: type Register is mod 2**15; — 16 bits with wrap around subtype Accumulator is Register range 0..255; — 8 bits subtype Index_Register range 0..255; subtype Program_Counter is Register; — 8 bits type Status_Register is record N : Boolean; — Negative V: Boolean; — Overflow B: Boolean; — NMI D: Boolean; — BCD I: Boolean; — Interrupt Z: Boolean; — Zero C : Boolean; — Carry end record; type CPU is record A : Accumulator; X : Index_Register; Y: Index_Register; SP: Stack_Pointer; PC: Program_Counter; SR: Status_Register; end record; Run
In the small amount of code, a nearly complete 6502 microprocessor's is modeled. This exercise is a design process where the programmer models the domain as components with their type and constraints. In turn, it supplies the compiler with the programmers intent and optimization clues for how to best allocate memory and generate code. This can all be deduced at compile time! Writing the functions and procedures is not only a walk in the park, but requires less code that's more efficient. Ada compilers can often produce code that's often smaller and faster than even hand coded assembly language! Templates, macros, and generics may not be up to the task. They would have to be insanely complex to be able to perform these optimizations on user defined type annotations. Ada's type annotations is optimized at the local and global level to achieve its performance.