Teaching new tricks to an old dog (C++ -->Ada)

  • Thread starter Turamnvia Suouriviaskimatta
  • Start date
M

Martin Dowie

Ioannis said:
With Ada aside (I find no reason why one should not learn it), C++ is a
powerful and systems programming language, and power implies painful low
level details. However it also provides all major high level facilities,
and if you stick in high level programming it is very safe, while it
maintains the maximum space and run-time efficiency principle.

It does NOT provide multi-tasking... or fixed-point numbers...

In general, we cannot compare the two languages because they have
different design ideals.

We we _can_ compare them... but you are correct that we must take their
design considerations into account. Ada95 was design specifically to
support efficient, real-time safe environments (the OP of the original
thread question), C++ was designed to produce an object-orientated
extension to C.

C++ supports 4 paradigms. Each paradigm is supported well with maximum
run-time/space *efficiency*. At the same time it leaves no room for a
lower level language except of assembly.

Ada83 suffered from some pretty poor implementations, but Ada95 has
never had the same problems. My own experience is that Ada95 compilers
produce as efficient code as any other language with the exception of
assembler. Not scientific I know but...

On the other hand I do not know ADAs ideals (for example I do not think
it supports the generic programming paradigm - templates), but I suspect
they are to be an easy (restricted to easy parts), safe (not letting you
do low level operations), application development language, which is OK
for usual application development.

Oh dear! That's a shocker!!!! Ada had generics back in Ada83 - and _all_
Ada83 compiler supported it then! The debugger support back then was
pretty shabby, but hey, at least the compilers all supported it and in a
completely uniform fashion.

Cheers

-- Martin
 
M

Martin Dowie

Peter said:
It is not a question of prevention. C++ allows you to do some really
dangerous things - in my mind rightfully so. When you do program in C++ you
must "constrain yourself" and not use the dangeous stuff - unless you need
to do so, of course ;-)

And Ada lets you do all that but you have to be explicit that you are
doing it - I don't know of any other language that forces you to be
explicit that you are doing something dangerous.

Cheers

-- Martin
 
I

Ioannis Vranos

Jim said:
All this can be done in Ada.


It would be great if we saw the code and its output.


How good is C++ at exactly representing bit fields?

Can C++ do this portably:


Some explanations with remarks in the code along with the output, would
make things easier to understand.


type Byte is mod 2**8;
type Sign_Flag is mod 2;

type Mouse_Status_Type is record
Left_Button_Pressed : Boolean;
Right_Button_Pressed : Boolean;
X_Movement_Sign : Sign_Flag;
Y_Movement_Sign : Sign_Flag;
X_Movement_Overflow : Boolean;
Y_Movement_Overflow : Boolean;
X_Movement_Magnitude : Byte;
Y_Movement_Magnitude : Byte;
end record;

for Mouse_Status_Type use record
Left_Button_Pressed at 0 range 0..0;
Right_button_Pressed at 0 range 1..1;
X_Movement_Sign at 0 range 4..4;
Y_Movement_Sign at 0 range 5..5;
X_Movement_Overflow at 0 range 6..6;
Y_Movement_Overflow at 0 range 7..7;
X_Movement_Magnitude at 1 range 0..7;
Y_Movement_Magnitude at 2 range 0..7;
end record;

The type Mouse_Status_Type defines a data
structure that occupies three bytes.


I guess the C++ equivalent is:

struct SomeStruct
{
unsigned Left_Button_Pressed: 1;
unsigned Right_button_Pressed: 1;
unsigned X_Movement_Sign: 1;
unsigned Y_Movement_Sign: 1;
unsigned X_Movement_Overflow: 1;
unsigned Y_Movement_Overflow: 1;
unsigned X_Movement_Magnitude: 8;
unsigned Y_Movement_Magnitude: 8;
};


It is interesting to see that ADA supports this.




The
first 6 fields of the record occupy a single
bit each, with bits 2 and 3 unused.

Furthermore, access to the individual fields of this record
are very direct, not requiring arcane bit masks.

foo : Mouse_Status_Type;


if foo.Left_Button_Pressed then
do_something;
end if;


The above in a simple C++ program:


#include <iostream>


int main()
{
struct SomeStruct
{
unsigned Left_Button_Pressed: 1;
unsigned Right_button_Pressed: 1;
unsigned X_Movement_Sign: 1;
unsigned Y_Movement_Sign: 1;
unsigned X_Movement_Overflow: 1;
unsigned Y_Movement_Overflow: 1;
unsigned X_Movement_Magnitude: 8;
unsigned Y_Movement_Magnitude: 8;
};

SomeStruct obj= {1, 0, true, false, 1, 16, 64};

if(obj.Left_Button_Pressed)
std::cout<<"It is pressed!\n";
}

C:\c>temp
It is pressed!

C:\c>



On the contrary, Ada is frequently used for low level bit manipulation.
Ada was designed to be used in safety-critical hard real-time
embedded systems.


It is interesting to hear that.

We are all free to have our own interests. I do ask that you look at
the capabilities of a language before you decide they are not in your
interest. Ada does not prevent you from doing unsafe things. It
simply does not provide an unsafe behavior as its default.


Perhaps I will check it sometime in the future.


Programming is a human activity. All humans make mistakes. Some of those
mistakes are damned silly. Ada is designed to acknowledge that
programmers are human. Mistakes will be made. Ada attempts to identify
those mistakes as early in the development process as possible.
We all know that it is cheaper to fix mistakes early.


Yes, however I have the feeling that it does so by imposing several
restrictions that apart from protecting from possible misuses, also
prevent from flexible uses.

Again, this is just a feeling, I have not studied the language.

And there is no perfect language. Ada is not meant to satisfy the
desires of all programmers. It is meant to support programming as
a human activity with the goal of producing high quality programs
very efficiently.

OK.
 
I

Ioannis Vranos

Martin said:
It does NOT provide multi-tasking... or fixed-point numbers...


C++ provides whatever the system it is used to provides. In Windows you
can create multithreading applications for example.


We we _can_ compare them... but you are correct that we must take their
design considerations into account. Ada95 was design specifically to
support efficient, real-time safe environments (the OP of the original
thread question), C++ was designed to produce an object-orientated
extension to C.


C++ is not only an OO language, but it is a multiparadigm one.
 
P

Pete Fenelon

In comp.realtime Martin Dowie said:
I think Modula-3 was the prime inspiration but never having used it I
could be wrong! :)

Modula-3 *post*dated Ada by some years; it was designed in the late 80s
and unfortunately "missed the bus" - Ada was (at the time) very expensive,
C++ was (at the time) immature and unstandardised, and for a while I
hoped that Modula-3 would become the language of choice for large-scale
maintstream OOP/procedural programming.

Ada-83's ancestry is, as many have observed, mostly Pascal. (IIRC, three
of the four languages that got to the DoD's bake-off were Pascal-based;
a fourth was PL/1 based. Algol-68 was the other language identified as a
possible basis for the DoD's language, but no (directly) Algol-based
language made it that far.)

pete
 
I

Ioannis Vranos

Ioannis said:
The above in a simple C++ program:


#include <iostream>


int main()
{
struct SomeStruct
{
unsigned Left_Button_Pressed: 1;
unsigned Right_button_Pressed: 1;
unsigned X_Movement_Sign: 1;
unsigned Y_Movement_Sign: 1;
unsigned X_Movement_Overflow: 1;
unsigned Y_Movement_Overflow: 1;
unsigned X_Movement_Magnitude: 8;
unsigned Y_Movement_Magnitude: 8;
};

SomeStruct obj= {1, 0, true, false, 1, 1, 16, 64};
 
I

Ioannis Vranos

[Reposted because follow-ups had redirected it]

Jim said:
All this can be done in Ada.



It would be great if we saw the code and its output.


How good is C++ at exactly representing bit fields?

Can C++ do this portably:



Some explanations with remarks in the code along with the output, would
make things easier to understand.


type Byte is mod 2**8;
type Sign_Flag is mod 2;

type Mouse_Status_Type is record
Left_Button_Pressed : Boolean;
Right_Button_Pressed : Boolean;
X_Movement_Sign : Sign_Flag;
Y_Movement_Sign : Sign_Flag;
X_Movement_Overflow : Boolean;
Y_Movement_Overflow : Boolean;
X_Movement_Magnitude : Byte;
Y_Movement_Magnitude : Byte;
end record;

for Mouse_Status_Type use record
Left_Button_Pressed at 0 range 0..0;
Right_button_Pressed at 0 range 1..1;
X_Movement_Sign at 0 range 4..4;
Y_Movement_Sign at 0 range 5..5;
X_Movement_Overflow at 0 range 6..6;
Y_Movement_Overflow at 0 range 7..7;
X_Movement_Magnitude at 1 range 0..7;
Y_Movement_Magnitude at 2 range 0..7;
end record;

The type Mouse_Status_Type defines a data
structure that occupies three bytes.



I guess the C++ equivalent is:

struct SomeStruct
{
unsigned Left_Button_Pressed: 1;
unsigned Right_button_Pressed: 1;
unsigned X_Movement_Sign: 1;
unsigned Y_Movement_Sign: 1;
unsigned X_Movement_Overflow: 1;
unsigned Y_Movement_Overflow: 1;
unsigned X_Movement_Magnitude: 8;
unsigned Y_Movement_Magnitude: 8;
};


It is interesting to see that ADA supports this.




The
first 6 fields of the record occupy a single
bit each, with bits 2 and 3 unused.

Furthermore, access to the individual fields of this record
are very direct, not requiring arcane bit masks.

foo : Mouse_Status_Type;


if foo.Left_Button_Pressed then
do_something;
end if;



The above in a simple C++ program:


#include <iostream>


int main()
{
struct SomeStruct
{
unsigned Left_Button_Pressed: 1;
unsigned Right_button_Pressed: 1;
unsigned X_Movement_Sign: 1;
unsigned Y_Movement_Sign: 1;
unsigned X_Movement_Overflow: 1;
unsigned Y_Movement_Overflow: 1;
unsigned X_Movement_Magnitude: 8;
unsigned Y_Movement_Magnitude: 8;
};

SomeStruct obj= {1, 0, true, false, 1, 1, 16, 64};

if(obj.Left_Button_Pressed)
std::cout<<"It is pressed!\n";
}

C:\c>temp
It is pressed!

C:\c>



On the contrary, Ada is frequently used for low level bit manipulation.
Ada was designed to be used in safety-critical hard real-time
embedded systems.



It is interesting to hear that.

We are all free to have our own interests. I do ask that you look at
the capabilities of a language before you decide they are not in your
interest. Ada does not prevent you from doing unsafe things. It
simply does not provide an unsafe behavior as its default.



Perhaps I will check it sometime in the future.


his mistakes, probably ADA is better than C++ on this.
Programming is a human activity. All humans make mistakes. Some of those
mistakes are damned silly. Ada is designed to acknowledge that
programmers are human. Mistakes will be made. Ada attempts to identify
those mistakes as early in the development process as possible.
We all know that it is cheaper to fix mistakes early.



Yes, however I have the feeling that it does so by imposing several
restrictions that apart from protecting from possible misuses, also
prevent from flexible uses.

Again, this is just a feeling, I have not studied the language.

And there is no perfect language. Ada is not meant to satisfy the
desires of all programmers. It is meant to support programming as
a human activity with the goal of producing high quality programs
very efficiently.


OK.
 
I

Ioannis Vranos

Larry said:
I'm afraid you don't know much about Ada and much of what you do know is
not correct. That was one of the specific problem domains Ada was
designed for -- hard real-time embedded systems.


Yes, after some things I have read in the thread, Ada is upper in my
interest scale.

I did not know that it was designed for low level stuff.
 
L

Larry Elmore

Ioannis said:
I suppose you mean in the application-programming domain. But I do not
think this is true in the systems programming domain, that is efficiency
under *severe* run-time and space constraints.

I'm afraid you don't know much about Ada and much of what you do know is
not correct. That was one of the specific problem domains Ada was
designed for -- hard real-time embedded systems.
Also I am not sure if ADA is suitable for library writing, or you will
have to switch to another language to do that.

I do not say this is bad, since the design ideals of ADA are different
from C++. In effect, we are comparing different things here.

No, you only think that's the case. I encourage you to learn more about
Ada. You might be very surprised.

Also, it's spelled "Ada", not ADA (which in the US usually means the
American Dental Association, or the Americans with Disabilities Act).
It's not an acronym. It was named after a woman, Ada Augusta Lovelace.
No one who knows anything about the language spells it ADA (unless
they're on an ancient machine that has no lowercase letters) anymore
than they spell "Pascal" as "PASCAL".

--Larry
 
L

Larry Elmore

Martin said:
I think Modula-3 was the prime inspiration but never having used it I
could be wrong! :)

Definitely not Modula 3, which dates from the latter half of the 1980s.
I remember the introduction to the original book published about it
mentioning how they learned from errors made in the designs of Modula 2
and Ada83. I've never used it, but I remember thinking it did have some
good ideas (although they kept the damnable 'begin .. end' keywords and
a couple of other things that I no longer remember instead of using
Ada's much better syntax).

--Larry
 
D

Dennis Lee Bieber

I think Modula-3 was the prime inspiration but never having used it I
could be wrong! :)

Considering that the Ada effort started in the mid-70s, I don't
even think Modula-2 was available. See
http://www.cs.fit.edu/~ryan/ada/ada-hist.html for dates.

As I recall from my studies (the choice Green to become Ada
occurred in time for me to use it in a language report for a college
class) the four teams that competed in the proposal all chose Pascal as
their starting point.

--
 
J

Jim Rogers

It would be great if we saw the code and its output.

Ok. That is certainly a fair requirement.

with Ada.Text_Io;
with Ada.Integer_Text_Io;
with System;

procedure String_Bits is
S : String := "This is a text message";
L : Natural := S'Size;
type Bits_Array is array (1..L) of Boolean;
pragma Pack (Bits_Array);
Bits : Bits_Array;
for Bits'Address use S'Address;
begin
-- Display the bits of each character
for I in Bits'range loop
Ada.Integer_Text_Io.Put(Item => Boolean'Pos(Bits(I)), Width => 1);
if I mod System.Storage_Unit = 0 then
Ada.Text_Io.New_Line;
end if;
end loop;
end String_Bits;

The output is:
00101010
00010110
10010110
11001110
00000100
10010110
11001110
00000100
10000110
00000100
00101110
10100110
00011110
00101110
00000100
10110110
10100110
11001110
11001110
10000110
11100110
10100110

The program declares a string S initialized to "This is a text message".
It then declares an array type named Bits_Array. That array type is an
array of Boolean, with the number of elements equal to the number of
bits in used by S. The variable L is set to equal the value returned
by the Size attribute of the String S. Ada reports size as the number
of bits, not the number of bytes.

A packed array of boolean allocates one storage element to each bit.
Therefore, the statement
pragma Pack(Bits_Array);
causes all instances of Bits_Array to be a packed array.
The variable Bits is declared to be of the type Bits_Array.
The next statement forces Bits to overlay S. Both variables
are the same size and start at the same address.

The body of the procedure simply iterates through all the bits in
the Bits variable and prints the numeric value of each bit.
A new line is output whenever the loop control variable mod
System.Storage_Unit evaluates to 0. System.Storage_Unit is
provided by Ada so that the program will properly represent
each storage unit (sometimes called a byte) no matter what the
size of that unit is.

As you can clearly see, Ada can represent the bits of a
variable with very little difficulty.

Ada does not store a null at the end of a string. This is
why there is no indication of a null value for the last byte.

Jim Rogers
 
J

Jim Rogers

C++ provides whatever the system it is used to provides. In Windows
you can create multithreading applications for example.

Of course it can, by calling C libraries such as pThreads.

Concurrency has been a native part of Ada since the 1983 standard.
C++ is not only an OO language, but it is a multiparadigm one.


I agree. One of the original goals of C++ was to produce a language
that extends C into the OO paradigm without loosing any of the
inherited C capabilities. In 1996 C++ standardized generic programming
as another paradigm.

Ada is also a multi-paradigm language. In fact, it can be used in all
the paradigms familiar to C++.

Jim Rogers
 
F

Frank J. Lhota

Ioannis Vranos said:
You can also express constraints in templates. An important thing is this.
Are Ada's generics run-time or compile time?

Compile time with every Ada compiler I've used.
It looks like they are run-time, and in C++ you can do all the above.
Actually Ada's compilers are probably written in C++.

GNAT is written in Ada.
 
F

Frank J. Lhota

Pascal Obry said:
At least GNAT (GNU/Ada) is written in Ada and DEC Ada was written in Ada
IIRC.

Half right. GNAT is written in Ada, DEC Ada was written in Bliss.
 
I

Ioannis Vranos

Jim said:
Of course it can, by calling C libraries such as pThreads.


Actually I am using .NET facilities (posted an example in another
message in the thread).

I agree. One of the original goals of C++ was to produce a language
that extends C into the OO paradigm without loosing any of the
inherited C capabilities. In 1996 C++ standardized generic programming
as another paradigm.

Ada is also a multi-paradigm language. In fact, it can be used in all
the paradigms familiar to C++.

OK.
 
I

Ioannis Vranos

Jim said:
The program declares a string S initialized to "This is a text message".
It then declares an array type named Bits_Array. That array type is an
array of Boolean, with the number of elements equal to the number of
bits in used by S. The variable L is set to equal the value returned
by the Size attribute of the String S. Ada reports size as the number
of bits, not the number of bytes.

A packed array of boolean allocates one storage element to each bit.
Therefore, the statement
pragma Pack(Bits_Array);
causes all instances of Bits_Array to be a packed array.
The variable Bits is declared to be of the type Bits_Array.
The next statement forces Bits to overlay S. Both variables
are the same size and start at the same address.


Does this mean that Boolean always occupies 1 bit and has no padding bits?

The body of the procedure simply iterates through all the bits in
the Bits variable and prints the numeric value of each bit.
A new line is output whenever the loop control variable mod
System.Storage_Unit evaluates to 0. System.Storage_Unit is
provided by Ada so that the program will properly represent
each storage unit (sometimes called a byte) no matter what the
size of that unit is.

As you can clearly see, Ada can represent the bits of a
variable with very little difficulty.

Ada does not store a null at the end of a string. This is
why there is no indication of a null value for the last byte.


While this is an interesting thing, I have the feeling that this
approach does not print all bits, including padding bits, of a
*user-defined type*.


In C++ you can read (and thus copy, print or anything) every byte of any
type.

In the example you provided, I have the feeling that you allocated a
character array (the string) and then treated is a boolean array
(somewhat a hacking attempt to imitate the behaviour).


However what happens in the case of a user defined type (I suppose Ada
supports OO programming) or a record. Can you print the byte
implementation of such an object?


Also for a built in type, say a floating point, can you print its
implementation bytes too (including padding bits)?


Consider this:

#include <iostream>
#include <bitset>
#include <limits>

int main()
{
using namespace std;

double obj= 0.45435;

unsigned char *p= reinterpret_cast<unsigned char *>(&obj);


p= reinterpret_cast<unsigned char *>(&obj);
// Displays the decimal values of the
// individual bytes that obj consists of.
for(unsigned i=0; i<sizeof(obj); ++i)
cout<<static_cast<unsigned>(p)<<" ";

cout<<"\n\n";


// Displays the bits of each byte that consist
// this SomeClass object
p= reinterpret_cast<unsigned char *>(&obj);
for(unsigned i=0; i<sizeof(obj); ++i)
{
// A byte is not necessarily 8 bits
// numeric_limits<unsigned char>::digits retrieves the number
// of byte's bits, which *is* 8 usually.
bitset<numeric_limits<unsigned char>::digits> bits(p);

for(unsigned j=0; j<bits.size(); ++j)
cout<<bits[j];

cout<<"\n";
}
}


C:\c>temp
163 1 188 5 18 20 221 63

11000101
10000000
00111101
10100000
01001000
00101000
10111011
11111100

C:\c>
 
L

Larry Kilgallen

It's kind of like driving. You can get into a lot of trouble if you do not
follow the traffic laws (you just have to obey the physicla ones ;-), but so
long as you do driving is a fairly safe practice.

Although I attempt to drive safely, I also rely on seat belts and air bags.
 
L

Larry Kilgallen

Oh dear! That's a shocker!!!! Ada had generics back in Ada83 - and _all_
Ada83 compiler supported it then! The debugger support back then was
pretty shabby,

Speak for your own compiler, VAX Ada has (and had) excellent debugger
support.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,273
Latest member
DamonShoem

Latest Threads

Top