If you’re an embedded programmer and not familiar with programming in the large, it might be time to become acquainted. That’s because more often than not, projects include a number of developers working on projects that may last months, sometimes years. C, and to some extent C++, remain the de facto languages for embedded programming. C is deficient when it comes to support for large projects. It’s definitely used in large projects, but the language lacks even the most rudimentary modularity that’s found in languages like C++ and Java. Still, C remains the mainstay for embedded applications.
One up-and-coming language is Rust, developed by Graydon Hoare. What caught my eye recently was a Slashdot entry entitled “Rust Creator Graydon Hoare Says Current Software Development Practices Terrify Him.” I tend to agree with the comment with respect to embedded programming, because C is where it’s at. I also ran across another Slashdot entry “Why ESR Hates C++, Respects Java, and Thinks Go (But Not Rust) Will Replace C.” ESR refers to open-source guru Eric S. Raymond. A significant amount of embedded open source is written in C.
What I find about most of the comments in these streams is how very few comments mention Ada or SPARK, a provable subset of Ada. This highlights how little most commenters know about Ada and how myths about Ada tend to discount any discussion of the language as an alternative to C.
This brings me back to programming in the large.
Adacore, an Ada/SPARK vendor, actually has an online tutorial entitled “Programming in the Large.” Interestingly, it covers topics like exceptions, type safety, access types, encapsulation, and genericity. These are useful features, but they overlook two features I think are key to Ada: the language’s module system, and support for nested functions/procedures (see figure).
Ada supports nested procedures while languages like C do not.
Many programming languages like C, C++, and Java don’t support nested functions. C++ and Java now support lambda functions that are essentially nested functions, but the feature is actually less powerful than nested functions. The reason I think this is important with respect to programming in the large is that it keeps the definition of nested functions within the context of where they will be used.
What I find interesting is how Ada features are being added to other languages as features that advance the current language implementation. Nested functions tend to be more verbose than lambdas that are unnamed functions, but there are advantages to named functions, including the possibility to reuse them with the outer procedure definition.
Ada’s package system is hierarchical with support for nested packages. Most languages with package systems don’t support nested packages. For small projects, nested packages would not be an issue. However, the feature is more useful as systems grow in size and software reuse becomes necessary.
Now for the kicker.
What Flavor Do You Prefer?
Languages like Rust are very new and commercial compilers are still on the horizon. That doesn’t stop developers from using new tools, but embedded developers often choose C because the commercial tools are available.
Developers unfamiliar with language design often flock to new languages simply because they address problems they are having. For example, one of Rust’s claims to fame is its memory-management support. Ada addresses different aspects and doesn’t necessarily match Rust feature for feature. On the other hand, Ada compilers are available from a number of vendors, and many have been certified for use with "trivial" applications like avionics and military applications.
Ada 95 support features like object-oriented programming and features discussed here. Ada 2012 includes many new capabilities like contracts, but compiler availability is more limited. Contracts also extend to nested procedures and Ada packages. Contracts are also the basis of SPARK and provable programs, which is beyond the scope of this article.
Ada tends to be slightly more verbose than C or C++ because of the use of begin/end instead of curly brackets. This tends to be rather trivial difference, though, when one considers the advantages like recognizable termination of a block. IDEs and templates have eliminated the need to actually type begin/end.
Of all the languages that could replace C and possibly C++, Ada actually fills the bill better than any of the alternatives discussed these days. On the plus side, the tools are available and well tested. Turning a C or C++ programmer into an Ada/SPARK programmer is easy compared to most of the alternatives.
Open-source versions of Ada/SPARK compilers are available. And vendors like Green Hills Software, DDC-I, PTC and Adacore offer commercial compilers. Ada is also already designed to handle many of the aspects of embedded programming that aren’t supported by other languages like fixed-point support and small memory platforms. Developers often forget that Ada was designed to support embedded systems that are on the order of today’s microcontrollers. Popular platforms like the 32-bit ARM Cortex-M are supported by Ada.
Oh, and did I mention that Ada has built-in multitasking support?
Check out Ada if you dare.