Ada: Expressions

Ada: Expressions

Learn about simple and complex expressions.

An expression in Ada is a combination of literals, variables, function calls and operators that evaluates to a single value.

For example:

10        -- Literal 
Count     -- Variable
Abs(X)    -- Function call
Count + 1 -- Addition operator

All of the above are valid expressions in Ada. Expressions in Ada can be used:

  • As arguments to subprograms

  • On the right-hand side of the assignments

  • In if statements, loops, case statements etc.

For example:

-- As argument     
Abs(Count + 1)

-- In assignment   
Result := Count + 1

-- In if statement
if Count + 1 > 10 then
   ...
end if;

So in short, expressions in Ada allow you to compute a single value by combining literals, variables, functions and operators, which can then be used in statements.


Role of expressions:

You're right, Ada is not an expression-oriented language like Lisp or Haskell, but a statement-oriented imperative language. While expressions are an important part of the Ada language, statements are the primary means of expressing computations.

Some key points regarding expressions vs statements in Ada:

  • As we discussed, expressions in Ada are used to compute values from literals, variables and function calls using operators.

  • Statements in Ada are used to perform actions and cause side effects. They include assignments, procedure calls, if statements, loops, etc.

  • While expressions return a value, statements do not. They are executed for their side effects.

  • Ada focuses on statements, not expressions, to structure the code. The basic building blocks of Ada programs are statements, not expressions.

  • Expressions can only be used as part of statements. They cannot stand alone as in expression-oriented languages.

For example:

-- Expression  
Result := Count + 1;

-- Statement  
Count := Count + 1;

Here the first line uses an expression as part of an assignment statement, while the second line is a standalone statement - an assignment.

So in summary, while expressions are an important part of Ada to compute values, the language focuses on statements as the primary means of structuring the program. Ada uses statements to perform actions and cause side effects, making it a statement-oriented language.


Data Literals

Here is a table of different data literals in Ada with examples and descriptions:

Literal TypeExampleDescription
Numeric10

3.14 | Integer and floating point numeric literals | | Character | 'A' | Single character literal enclosed in apostrophes | | String | "Hello" | String literal enclosed in double quotes | | Boolean | True
False | Boolean literals | | Null | Null | Represents the absence of a value |

Numeric Literals:

  • Integer literals can be written in decimal (10), hexadecimal (0x1A), octal (012) or binary (0b1010)

  • Floating point literals use a decimal point (3.14) or exponent (1.0e10)

Character Literals:

  • Single character enclosed in apostrophes.

  • ASCII, wide and universal character literals are supported.

String Literals:

  • Sequence of characters enclosed in double quotes.

  • Can span multiple lines using & at the end.

Boolean Literals:

  • True and False represent the two boolean values.

Null Literal:

  • Represents the absence of a value. Used to initialize access types.

So in summary, Ada supports a variety of numeric, character, string, boolean and null literals to represent values of different types in the language.


Symbols

A symbol in Ada is basically an identifier that has a specific meaning within the language. Some examples of symbols in Ada are:

  • Keywords: words that have a special meaning in the language like if, then, else, loop, etc. Keywords cannot be used as identifiers.

  • Operators: symbols that represent operations like + (addition), - (subtraction), * (multiplication), etc.

  • Punctuators: symbols used to delimit constructs like , (comma), ; (semicolon), . (dot), => (arrow), := (assignment), etc.

  • Literals: symbols representing constant values like 10, 'A', "Hello", True, etc.

  • Comments: -- (for single line comments) and -- (for multi-line comments).

So in summary, symbols in Ada include keywords, operators, punctuators, literals and comments. These symbols give the Ada language its structure and syntax and allow it to be parsed and compiled correctly.

The Ada Reference Manual precisely defines all the symbols that are part of the language and their meaning and usage. Compilers use this information to validate Ada programs and generate object code.


Description of symbols

Expression symbols in Ada with their names and descriptions:

SymbolNameDescription
, (comma)SeparatorSeparates expressions, function arguments
+ (plus)AdditionAdds two operands
- (minus)SubtractionSubtracts right operand from left
* (asterisk)MultiplicationMultiplies two operands
/ (forward slash)DivisionDivides left operand by right
**ExponentiationRaises left operand to the power of right
( )ParenthesesUsed to alter operator precedence and evaluate expressions

Separators:

  • Commas are used to separate expressions and function arguments.

Operators:

  • Ada supports various arithmetic, relational and logical operators.

  • Operators can be unary (one operand) or binary (two operands).

Parentheses:

  • Used to explicitly specify the order of evaluation of an expression.

  • Overrides the default precedence of operators.

For example:

A + B * C   -- Evaluated as A + (B * C) 
(A + B) * C -- Evaluated as (A + B) * C

Other symbols:

  • \=> used for function definitions

  • := for assignments

  • .. for range

So in summary, Ada uses various symbols like separators, operators and parentheses to denote the structure of expressions and determine their evaluation order.


Complexity

Simple and complex examples refer to the level of difficulty and intricacy of examples used to illustrate or explain a concept.

Simple examples tend to be:

  • Short - They focus on one or two main ideas and use minimal code.

  • Straightforward - They use basic language constructs and data types.

  • Easy to understand - They avoid complex logic and abstractions.

Complex examples, on the other hand, tend to be:

  • Longer - They cover multiple related concepts and use more code.

  • Involved - They employ advanced language features and data structures.

  • Harder to follow - They involve complex logic, algorithms and design patterns.

Simple examples are useful for:

  • New learners - They can grasp basic concepts without getting overwhelmed.

  • Basic explanations - They illustrate the core meaning and usage of a concept.

Complex examples are useful for:

  • Advanced learners - They show how concepts are applied in real-world scenarios.

  • In-depth explanations - They demonstrate more nuanced and sophisticated uses.

Both types of examples serve different purposes:

  • Simple examples help build foundational understanding.

  • Complex examples help extend and solidify that understanding.

So when explaining concepts, it's good to provide:

  • Simple examples to illustrate basic usage and meaning.

  • Complex examples to demonstrate more practical application.

This allows learners at different levels to benefit from the examples and develop a well-rounded understanding of the concept.


Examples

Here are some examples of simple and complex expressions in Ada:

Simple expressions:

  • A + B - Adds two variables

  • X * 5 - Multiplies a variable by a constant

  • Y / 2 - Divides a variable by a constant

Complex expressions:

  • (A + B) * C - Adds two variables and multiplies the result by a third variable

  • X ** Y % Z - Raises X to the power of Y and takes the remainder when divided by Z

  • A / (B - C) - Subtracts two variables and divides a third variable by the result

More complex expression:

((A + B * C) / (D - E)) ** 2
  • Adds a variable and multiplies it by another

  • Divide the result by the difference of two variables

  • Raises the whole expression to the power of 2

The simple expressions use basic operators (+, -, *, /) and constants or variables.

The complex expressions:

  • Use multiple operators

  • Involve intermediate calculations in parentheses

  • Use functions like power (**) and modulo (%)

The more complex expression:

  • Combines multiple operations

  • Uses nested parentheses to dictate evaluation order

So in summary, simple expressions focus on one or two basic operations while complex expressions combine multiple operations, variables and functions in a sophisticated manner.


Type checking

In Ada, expressions have an implicit type and are subject to strict type-checking. This is beneficial in several ways:

  1. It ensures type safety - The compiler checks that expressions of different types are not mixed inappropriately. This helps catch type-related errors at compile time.

  2. It detects type mismatches early - Since type checking is done at compile time, any type mismatches in expressions are detected then, rather than at runtime. This makes debugging easier.

  3. It documents the types used - The implicit types of expressions document what types of data are being operated on, which helps readability and maintainability.

  4. It enables automatic type conversions - Ada can automatically convert between related types as needed, following a set of predefined conversion rules. This simplifies code.

  5. It enforces type consistency - All parts of an expression must be of a compatible type. This ensures the result has a well-defined type.

For example:

X : Integer := 5;
Y : Float := 2.5;
Z := X + Y; -- Error! Cannot add Integer and Float directly

Here, Ada detects that X and Y are of incompatible types (Integer and Float), and issues a compile-time error.

If the types are compatible:

X, Y : Integer;  
Z := X + Y; -- OK! Z is also of type Integer

Here, Z has an implicit type of Integer, derived from the types of X and Y.

So in summary, Ada's strict type checking of expressions catches errors early, documents types used, enables automatic conversions, and enforces type consistency. This makes Ada code more robust and maintainable.


Encoding

Symbol encoding is the process of representing symbols (like characters, numbers, etc.) in a format that can be processed by a computer. This typically involves assigning a numeric code to each symbol.

In Ada, all symbols are encoded using the standard ASCII or Unicode encoding schemes. This allows Ada programs to manipulate and process text data.

Some key points about symbol encoding in Ada:

  1. Characters are represented using the standard ASCII encoding up to 127, and Unicode encoding above that.

  2. Ada has a Char type to represent individual characters, and String types to represent text data.

  3. Ada defines a set of standard character and string handling procedures. For example:

  • To convert a character to its ASCII code:
Code : Integer := Character'Pos('a');  -- Code = 97
  • To convert an ASCII code to a character:
Letter := Character'Val(97); -- Letter = 'a'
  • To compare strings:
if Word1 = Word2 then ...
  • To concatenate strings:
Phrase := Word1 & Word2;
  1. Ada can also handle Unicode characters and strings.

So symbol encoding in Ada allows the language to represent and manipulate:

  • Individual characters

  • Text strings

  • Numbers

  • Symbols (like +, -, *, /)

This enables Ada programs to process human-readable data, communicate with users, and interface with other systems.

In summary, symbol encoding is an important concept that allows Ada to represent the basic building blocks of information - symbols and characters. The standard ASCII and Unicode encoding schemes enable interoperability and portability of Ada text data.


Disclaim: This information is provided by Rix. My role is to ask questions in logic order so you don't have to. But you can ask more questions if you want and post comments below.