Ada 'hello world' for Android; success!

159 views
Skip to first unread message

Stephen Leake

unread,
Oct 26, 2011, 9:18:47 PM10/26/11
to
I've managed to get an Ada 'hello world' working on Android. It follows
the example at
http://developer.android.com/resources/tutorials/hello-world.html
translated to Ada.

Here's the Ada 'main program':

with Android.App.Activity;
with Android.OS.Bundle;
package Hello is

-- <Ada package>$<Ada type> must match ../AndroidManifest.xml manifest | application | activity | android:name
type Typ is new Android.App.Activity.Typ with null record;

overriding procedure OnCreate
(This : access Typ;
savedInstanceState : access Standard.Android.Os.Bundle.Typ'Class);
pragma Export (Java, OnCreate, "onCreate");

end Hello;
-- Prefix must match ../AndroidManifest.xml manifest | package
pragma Export (Java, Hello, "net.example.helloada.hello");

package body Hello is

overriding procedure OnCreate
(This : access Typ;
savedInstanceState : access Standard.Android.Os.Bundle.Typ'class)
is
type Super_Ref is access all Android.App.Activity.Typ;
begin
Android.App.Activity.Oncreate (Super_Ref (This), savedInstanceState);

-- FIXME: use R.layout
--
-- need to run jvm2ada on ../gen/net/example/R.java, but that's
-- generated by the ant process that runs after this code is
-- compiled, so we have to learn how to break that up or
-- something.
--
-- until then, get this constant from R.java (value for 'layout')
Android.App.Activity.SetContentView (Android.App.Activity.Ref (This), 16#7f030000#);
end OnCreate;

end Hello;

It runs on the Android emulator provided with the Android SDK, and on my
HTC Inspire.

As you can see, there are still some rough edges in the build process. I
could have hard-coded the 'hello' string here, but that's not what the
Java program does; this demonstrates that the Ada code really is using
all the Java GUI resources and classes properly.

Mostly I didn't want to spend any more time figuring out how to
customize the Android SDK build tools. They work really nicely if you
are doing simple Java stuff, but really get in the way when you want to
do something more complicated.

I started with GNAT GPL 2011, jvm target. I had to fix two bugs in
jvm2ada, one bug in the jvm-gnat backend (all reported to AdaCore with
patches), and work around another bug in the gnat front end (also
reported to AdaCore). Not too bad :).

Any suggestions for where to post more info?
wikibooks.org/wiki/Ada_Programming looks like a good place, but I'm not
sure where this fits in that hierarchy.

I can post a .tar.gz (or just the .apk :) on my own website if anyone is
interested in getting a quick look now.

There are some interesting issues in the Ada <-> Java mapping; for
example, Ada packages map to Java nested classes, so you have to put the
desired Java package name in the 'pragma Export' external name.

Figuring out how to tell the SDK build tools exactly what was going on
was the most frustrating; the documentation on those is totally
inadequate. I managed to find some answers in the source code for the
tools; at least it is all open source.

Fixing the bugs in the GNAT tools was easy by comparison, once I had
test cases.

Now I can work on my music player app, and get away from Java ;).

--
-- Stephe

Alex R. Mosteo

unread,
Oct 27, 2011, 3:12:44 AM10/27/11
to
Wow congrats! To me this is impressive. And having these patches available
in some place is definitely great.

Alex.

Brian Drummond

unread,
Oct 27, 2011, 6:58:15 AM10/27/11
to
On Wed, 26 Oct 2011 21:18:47 -0400, Stephen Leake wrote:

> I've managed to get an Ada 'hello world' working on Android. It follows
> the example at
> http://developer.android.com/resources/tutorials/hello-world.html
> translated to Ada.
>
Great news! And yes, I would be interested in getting hold of the further
information.

I still intend to pursue the NDK approach, though a new job and house
relocation have somewhat intervened...

- Brian

Jeffrey Creem

unread,
Oct 27, 2011, 6:50:55 AM10/27/11
to
Perhaps a new sourceforge project, or get it posted into the existing
GNU Ada project?

Shark8

unread,
Oct 27, 2011, 9:37:25 PM10/27/11
to

Congrats! / Nicely done.

Anatoly Chernyshev

unread,
Oct 28, 2011, 8:22:24 AM10/28/11
to
Looks like a Pyrrhic victory to me. All elegance of Ada is suddenly
dissipated.

Stephen Leake

unread,
Oct 28, 2011, 8:51:19 AM10/28/11
to
"Alex R. Mosteo" <alej...@mosteo.invalid> writes:

> Wow congrats! To me this is impressive.

Thanks.

> And having these patches available in some place is definitely great.

Ok, I'll put them up on my website next week (I'm on travel this weekend).

--
-- Stephe

Stephen Leake

unread,
Oct 28, 2011, 9:01:41 AM10/28/11
to
Jeffrey Creem <je...@thecreems.com> writes:

> On 10/26/2011 9:18 PM, Stephen Leake wrote:
>> I've managed to get an Ada 'hello world' working on Android. It follows
>> the example at
>> http://developer.android.com/resources/tutorials/hello-world.html
>> translated to Ada.
>>
>
> Perhaps a new sourceforge project, or get it posted into the existing
> GNU Ada project?

I'll contact them to see if it would be appropriate. It's not clear
they maintain patches.

--
-- Stephe

Stephen Leake

unread,
Oct 29, 2011, 9:37:41 AM10/29/11
to
Anatoly Chernyshev <acher...@gmail.com> writes:

> Looks like a Pyrrhic victory to me. All elegance of Ada is suddenly
> dissipated.

I gather you feel that Android is inelegant in some way; can you be more
specific?

I find my Android PDA to be much more useful than my previous Palm PDA.
And certainly easier to program at this level; there were no open source
tools for the Palm.

What would be a better platform for PDA applications?

--
-- Stephe

Anatoly Chernyshev

unread,
Oct 29, 2011, 10:46:43 AM10/29/11
to
Well, I have HTC too, and might be willing to do some programming on
it (to have some use of GPS data for instance). But your example above
just scares me away.
And I'm happy to have no employer to force me digging into this. I
will not approach any Android programming in Ada until it gets back to
the simplicity of e.g.

with Android.total.coverage, text_io;
use Android.total.coverage, text_io;
procedure Hello is
begin
Put_Line("Hello, world!");
end Hello;

At the moment, I would opt for Python. Here is its version of "Hello,
world":

import android
droid = android.Android()
droid.makeToast('Hello, World!')

Georg Bauhaus

unread,
Oct 29, 2011, 11:32:48 AM10/29/11
to
On 29.10.11 15:37, Stephen Leake wrote:
> Anatoly Chernyshev<acher...@gmail.com> writes:
>
>> Looks like a Pyrrhic victory to me. All elegance of Ada is suddenly
>> dissipated.
>
> I gather you feel that Android is inelegant in some way; can you be more
> specific?

The example is a little non-Ada, IMHO. I don't know Anatoly's reasons,
but to me the example has an air of "Fortran in any language",
except that one has to replace Fortran with pointers or
Java-with-covers-removed, viz. explicit access A.B.C.Typ all over
the place.

FWIW, the programs I have once written using SofCheck's version
of Ada on JVMs looked and felt more like Ada and a less
like explicit anonymous pointer to A.B.C.Typ everywhere.
Note that the thorny appearance of the HelloWorld example
isn't present in Java, which allows O-O without forcing
the programmers to write pointers, pointers, pointers.

BTW, is it possible in the Android model to have an
equivalent of Ada's

procedure Op (This : access constant Typ);

where a programmer can state the intent of read-only
access?


Is the traditional O-O model of Ada impossible to support
in a compiler for Android devices or is it just that no one
is paying for such a compiler? So that the best we can do is
juggle the pointers that the other languages can hide?


Simon Wright

unread,
Oct 29, 2011, 12:09:27 PM10/29/11
to
Georg Bauhaus <rm.dash...@futureapps.de> writes:

> Is the traditional O-O model of Ada impossible to support
> in a compiler for Android devices or is it just that no one
> is paying for such a compiler? So that the best we can do is
> juggle the pointers that the other languages can hide?

I'd have thought it was more a problem of the bindings being
thin? Making thick bindings to a moving target is quite a challenge, of
course.

tmo...@acm.org

unread,
Oct 29, 2011, 1:32:50 PM10/29/11
to
> I'd have thought it was more a problem of the bindings being thin?
The original Petzold "Programming Windows" book shows a "Hello, Windows!"
program - it's two pages long. Thick bindings like Claw, and "languages"
like Python, and of course personal libraries, are what made it practical
to code for Windows.

> Making thick bindings to a moving target is quite a challenge, of course.
In successive versions of the Google Earth API, they changed one
parameter of a function (GetPointOnTerrainFromScreenCoords) from a pointer
to a safearray to a pointer to a terrain point. That may be aesthetically
nicer, but it breaks existing code. I'm told that in one version of the
Android OS angles are clockwise from North while in another version they
are counterclockwise from East. Google's software is not a very solid
foundation on which to build a binding.

Brad Moore

unread,
Oct 29, 2011, 4:47:55 PM10/29/11
to
On 29/10/2011 8:46 AM, Anatoly Chernyshev wrote:
> Well, I have HTC too, and might be willing to do some programming on
> it (to have some use of GPS data for instance). But your example above
> just scares me away.
> And I'm happy to have no employer to force me digging into this. I
> will not approach any Android programming in Ada until it gets back to
> the simplicity of e.g.
>
> with Android.total.coverage, text_io;
> use Android.total.coverage, text_io;
> procedure Hello is
> begin
> Put_Line("Hello, world!");
> end Hello;
>
> At the moment, I would opt for Python. Here is its version of "Hello,
> world":
>
> import android
> droid = android.Android()
> droid.makeToast('Hello, World!')

Note if you just interested in writing "Hello World" to a console for
Android, you can still use the traditional Hello world program for Ada.

namely;

with Text_IO; use Text_IO;
procedure Hello is
begin
Put_Line("Hello, world!");
end Hello;

You may have to root your phone to get this to execute, but it will run
and produce the desired output in a terminal console. It wont show up
as an app however.

Brad Moore

Brad Moore

unread,
Oct 29, 2011, 4:51:16 PM10/29/11
to
That can be one of the advantages of a thick binding though.
It can insulate client code from changes to the lower level API,
(as long as the low level changes aren't too drastic)

It just takes someone to maintain the bindings.

Anatoly Chernyshev

unread,
Oct 29, 2011, 5:59:32 PM10/29/11
to
I see. So, it's all about making a nice GUI for "Hello world"? Then
I'm relieved, as I commonly don't do the interface.
For that simple example below, should I just compile it for jvm, and
then it can be run on Android?

Brad Moore

unread,
Oct 29, 2011, 11:51:31 PM10/29/11
to
On 29/10/2011 3:59 PM, Anatoly Chernyshev wrote:
> I see. So, it's all about making a nice GUI for "Hello world"? Then
> I'm relieved, as I commonly don't do the interface.
> For that simple example below, should I just compile it for jvm, and
> then it can be run on Android?

Yes, Stephen Leake's example shows how to integrate a GUI into an app
written in Ada on Android. The GUI libraries are written in Java, so Ada
has to interface with Java to use those.

To build the native Ada console executable however, the jvm isn't
in the picture at all, as I understand it.

I found the following post helpful in getting Ada code to compile on
Android.

http://www.rhinocerus.net/forum/lang-ada/684457-gnatdroid-ada-cross-compiler-arm-android-incorporated-intofreebsd-ports-tree.html

Basically, what I did was create a virtual machine that runs FreeBSD,
on my desktop,
Next I followed the instructions in the above post to install the
compiler into the virtual machine.

Then I used the gnatmake executable (arm-android-eabi-gnatmake) on the
virtual machine to cross-compile my source code for Android.

This built the executable, which I then transferred to my smartphone's
sdcard. (I used AndFTP to do the transfer, though in theory one should
also be able to use one of the ssh apps (eg SSHDroid) to transfer from
the virtual machine to the android. I didn't have any luck getting
SSHDroid to work, but AndFTP did work fine.

Since you can't execute files from the sdcard, I had to root the phone,
so that I could then copy the executable to /data/data.

To root my phone, I followed the procedure for SuperOneClick, which
you can find with google.

One rooted, I installed an app called "Terminal Emulator" on my Android,
which allowed me to enter commands in a linux like environment. I also
installed BusyBox to give me linux commands I am familiar with.

Within the terminal emulator, I issued

su
mv /sdcard/executable_name /data/data
cd /data/data
chmod 755 ./executable_name

then ./executable_name to run the Ada executable natively.

Brad Moore

>
> On Oct 30, 12:47 am, Brad Moore<brad.mo...@shaw.ca> wrote:
>> On 29/10/2011 8:46 AM, Anatoly Chernyshev wrote:
>>
>>
>>
>>> Well, I have HTC too, and might be willing to do some programming on
>>> it (to have some use of GPS data for instance). But your example above
>>> just scares me away.
>>> And I'm happy to have no employer to force me digging into this. I
>>> will not approach any Android programming in Ada until it gets back to
>>> the simplicity of e.g.
>>
>>

Anatoly Chernyshev

unread,
Oct 30, 2011, 3:20:41 AM10/30/11
to
Thanks Brad for such detailed answer. I rooted my phone first thing I
got it from the store. Now it will be good to try some Ada programs on
it.

On Oct 30, 7:51 am, Brad Moore <brad.mo...@shaw.ca> wrote:
> On 29/10/2011 3:59 PM, Anatoly Chernyshev wrote:
>
> > I see. So, it's all about making a nice GUI for "Hello world"? Then
> > I'm relieved, as I commonly don't do the interface.
> > For that simple example below, should I just compile it for jvm, and
> > then it can be run on Android?
>
> Yes, Stephen Leake's example shows how to integrate a GUI into an app
> written in Ada on Android. The GUI libraries are written in Java, so Ada
> has to interface with Java to use those.
>
> To build the native Ada console executable however, the jvm isn't
> in the picture at all, as I understand it.
>
> I found the following post helpful in getting Ada code to compile on
> Android.
>
> http://www.rhinocerus.net/forum/lang-ada/684457-gnatdroid-ada-cross-c...

Stephen Leake

unread,
Oct 30, 2011, 6:56:52 AM10/30/11
to
Anatoly Chernyshev <acher...@gmail.com> writes:

> Well, I have HTC too, and might be willing to do some programming on
> it (to have some use of GPS data for instance). But your example above
> just scares me away.
> And I'm happy to have no employer to force me digging into this. I
> will not approach any Android programming in Ada until it gets back to
> the simplicity of e.g.
>
> with Android.total.coverage, text_io;
> use Android.total.coverage, text_io;
> procedure Hello is
> begin
> Put_Line("Hello, world!");
> end Hello;

You can do that now (with an ARM native cross compiler), and if you are
happy with command-line programs, that's fine.

But the point of my effort is to make GUI Android applications, in
particular a music player that is easy to operate while in a car and at
home. A command line application will _not_ meet my needs; I need to
take full advantage of the Android GUI application framework.

> At the moment, I would opt for Python. Here is its version of "Hello,
> world":
>
> import android
> droid = android.Android()
> droid.makeToast('Hello, World!')

Hmm. By definition, the 'main program' of an Android GUI app must be an
overriding of Android.App.Activity.onCreate. So I'm guessing that the
'android' Python package (is that the right term?) declares an onCreate
that does nothing.

How and when does the 'makeToast' statement get called? What shows on
the screen when this app is invoked?

The biggest problem I have with the current Android documentation is
that it does not document threading behavior, even though it has
multiple threads, and "callbacks" that must operate across threads.
Which means it is impossible to avoid deadlocks and race conditions. As
part of my Ada on Android development work, I'll be attempting to
reverse engineer and document the threading behavior of the various
features I use.

Ada could provide similar functionality to Python; provide a package
that is "simpler" than Android.App.Activity.

I don't see the point; doing useful stuff with a solid multi-tasking GUI
is not trivial, so you need complex structures to make it work. From
what I have seen so far, the Android GUI framework is easier to use, yet
just as powerful, as GtkAda.

It will be interesting to see if Ada tasks are useful with Android.

--
-- Stephe

Stephen Leake

unread,
Oct 30, 2011, 7:32:59 AM10/30/11
to
Georg Bauhaus <rm.dash...@futureapps.de> writes:

> On 29.10.11 15:37, Stephen Leake wrote:
>> Anatoly Chernyshev<acher...@gmail.com> writes:
>>
>>> Looks like a Pyrrhic victory to me. All elegance of Ada is suddenly
>>> dissipated.
>>
>> I gather you feel that Android is inelegant in some way; can you be more
>> specific?
>
> The example is a little non-Ada, IMHO.

In one sense, any trivial program is non-Ada, since Ada is meant for
complexity :).

> I don't know Anatoly's reasons, but to me the example has an air of
> "Fortran in any language", except that one has to replace Fortran with
> pointers or Java-with-covers-removed, viz. explicit access A.B.C.Typ
> all over the place.

Part of that is style. In examples like this, I tend to not use 'use',
to make it very clear what is going on.

But most of the "non-Ada" feel comes from the fact that it is a GUI
program.

Interestingly, I could not find a true GUI hello world example for Gtk;
'hello world' in the Gtk tutorial uses Ada.Text_IO.Put_Line!

Here's Qt:

with Qt_Ada.Application;
with Qt4.Push_Buttons.Constructors;
with Qt4.Strings;

procedure Main is
begin
Qt_Ada.Application.Initialize;

declare
Hello : constant not null access Qt4.Push_Buttons.Q_Push_Button'Class
:= Qt4.Push_Buttons.Constructors.Create
(Qt4.Strings.From_Utf_16 ("Hello world!"));

begin
Hello.Resize (100, 30);
Hello.Show;
Qt_Ada.Application.Execute;
end;
end Main;

The string 'hello world' is actually present in this source; it is not
in my example. As I said, that's because I plan to use the 'resource'
features of Android; that's how internationalization is implemented. I'm
not clear how Qt does internationalization.

> FWIW, the programs I have once written using SofCheck's version
> of Ada on JVMs looked and felt more like Ada and a less
> like explicit anonymous pointer to A.B.C.Typ everywhere.
> Note that the thorny appearance of the HelloWorld example
> isn't present in Java, which allows O-O without forcing
> the programmers to write pointers, pointers, pointers.

Here's the Java source for 'hello world':

package com.example.helloandroid;

import android.app.Activity;
import android.os.Bundle;

public class HelloAndroid extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}

And here is the Ada version (just the package body):

package body Hello is

overriding procedure OnCreate
(This : access Typ;
savedInstanceState : access Standard.Android.Os.Bundle.Typ'class)
is
type Super_Ref is access all Android.App.Activity.Typ;
begin
Android.App.Activity.Oncreate (Super_Ref (This), savedInstanceState);

Android.App.Activity.SetContentView (Android.App.Activity.Ref (This), 16#7f030000#);
end OnCreate;

end Hello;

By defintion, every non-scalar type in Java _is_ a pointer; Bundle and
'this' are pointers. The fact that the code doesn't say 'access' just
hides that fact. Java also hides the existence of 'this'. Making those
features explicit is definitely the Ada way. So I don't think the Ada
version is "non-Ada" because it uses pointers!

We could try to define "Typ" to be an access type, so the words "access"
would be replaced by "in" above. That issue has been discussed elsewhere
(for my take on it, see
http://www.stephe-leake.org/ada/access_vs_object.html).

In brief, _any_ framework that uses dispatching on class-wide
objects needs reference semantics. In Ada, that is indicated by the
explicit word 'access'. In Java, it is implicit. I prefer explicit.

> BTW, is it possible in the Android model to have an
> equivalent of Ada's
>
> procedure Op (This : access constant Typ);
>
> where a programmer can state the intent of read-only
> access?

Certainly, as long as all uses of This treat it that way.

However, since Java lacks this feature, none of the imported Android
APIs will have the 'constant' keyword. It would be possible (but
error-prone and tedious) to add 'constant' in appropriate places in the
generated API; that would make the system better. It might even be worth
adding a feature to jvm2ada to automate that, given a hand-generated
list of subprogram args that should be labeled 'constant'. The hard part
would be figuring out if a particular argument is in fact treated as a
constant.

> Is the traditional O-O model of Ada impossible to support
> in a compiler for Android devices or is it just that no one
> is paying for such a compiler?

I don't know what you mean. The Ada I'm using is fully Ada 2005
compliant. Any 'non-OO'ness you see is because of the Android design,
not because of the compiler.

> So that the best we can do is juggle the pointers that the other
> languages can hide?

Yes. And as I said above, that's a Good Thing.

--
-- Stephe

Stephen Leake

unread,
Oct 30, 2011, 7:38:35 AM10/30/11
to
tmo...@acm.org writes:

>> I'd have thought it was more a problem of the bindings being thin?
> The original Petzold "Programming Windows" book shows a "Hello, Windows!"
> program - it's two pages long. Thick bindings like Claw, and "languages"
> like Python, and of course personal libraries, are what made it practical
> to code for Windows.

Ah, I remember those days :). That's why I started Windex.

>> Making thick bindings to a moving target is quite a challenge, of course.
> In successive versions of the Google Earth API, they changed one
> parameter of a function (GetPointOnTerrainFromScreenCoords) from a pointer
> to a safearray to a pointer to a terrain point. That may be aesthetically
> nicer, but it breaks existing code. I'm told that in one version of the
> Android OS angles are clockwise from North while in another version they
> are counterclockwise from East. Google's software is not a very solid
> foundation on which to build a binding.

Or any app, apparently. This is scary!

Windex died in part because Microsoft kept changing the API, and I
didn't have the man-hours to keep up with them.

At least with jvm2ada and a strongly typed language on both sides, we
automatically learn of any API changes that are visible in the types.
That's a big step forward from the Windex days. Changes in behavior
are another problem.

--
-- Stephe

Brad Moore

unread,
Oct 30, 2011, 1:32:02 PM10/30/11
to
On 30/10/2011 4:56 AM, Stephen Leake wrote:
> The biggest problem I have with the current Android documentation is
> that it does not document threading behavior, even though it has
> multiple threads, and "callbacks" that must operate across threads.
> Which means it is impossible to avoid deadlocks and race conditions. As
> part of my Ada on Android development work, I'll be attempting to
> reverse engineer and document the threading behavior of the various
> features I use.

> doing useful stuff with a solid multi-tasking GUI
> is not trivial, so you need complex structures to make it work. From
> what I have seen so far, the Android GUI framework is easier to use, yet
> just as powerful, as GtkAda.
>
> It will be interesting to see if Ada tasks are useful with Android.

Just to clarify, Ada tasks are definitely useful with Android, the
Paraffin release uses Ada tasks which interact with protected objects
to provide parallelism with dual core Android devices.
Ada tasks work well with Ada tasks. I believe what you are wondering
about is whether Ada tasks play nicely with Java threads,
(threads that perhaps get created via GUI API calls.)
I haven't tried that, though I suspect they can interact the same
that they do on Linux, through GNAT specific packages such as via the
GNAT.Threads package. I haven't experimented yet with Ada-Java threading.
It would be good to see an Ada GUI app such as your music player project
available for Android.

Randy Brukardt

unread,
Oct 31, 2011, 6:34:48 PM10/31/11
to
"Stephen Leake" <stephe...@stephe-leake.org> wrote in message
news:82mxcio...@stephe-leake.org...
...
> In brief, _any_ framework that uses dispatching on class-wide
> objects needs reference semantics. In Ada, that is indicated by the
> explicit word 'access'. In Java, it is implicit. I prefer explicit.

I don't follow this. All tagged objects in Ada are by-reference, so you
never need explicit "access" for parameter passing. And class-wide objects
can be stored in the Ada containers without using "access" as well.

Claw is a framework that uses dispatching and reference semantics, yet it
almost never uses explicit "access". So to claim it can't be done is
disingenious.

The problem with "access" in Ada is that it puts all of the burden of the
storage management on the user, and it locks the user out of using the
containers for storage management (as well as making stack-based object
management much more wordy). It's much better to put that burden on the Ada
implementation, and to give the clients maximum flexibility in how to
structure their programs.

Randy.


Stephen Leake

unread,
Nov 1, 2011, 4:41:27 AM11/1/11
to
"Randy Brukardt" <ra...@rrsoftware.com> writes:

> "Stephen Leake" <stephe...@stephe-leake.org> wrote in message
> news:82mxcio...@stephe-leake.org...
> ...
>> In brief, _any_ framework that uses dispatching on class-wide
>> objects needs reference semantics. In Ada, that is indicated by the
>> explicit word 'access'. In Java, it is implicit. I prefer explicit.
>
> I don't follow this. All tagged objects in Ada are by-reference, so you
> never need explicit "access" for parameter passing.

Yes, but that's not the meaning of "reference semantics" I intended; I
mean "an explicit pointer of some sort".

> And class-wide objects can be stored in the Ada containers without
> using "access" as well.

In which case a Cursor provides the explicit pointer.

We've been around on this before; see
http://stephe-leake.org/ada/access_vs_object.html

I guess it's time to update that with Ada 2012 features.

--
-- Stephe

Georg Bauhaus

unread,
Nov 1, 2011, 5:30:12 AM11/1/11
to
On 30.10.11 12:32, Stephen Leake wrote:

> And here is the Ada version (just the package body):
>
> package body Hello is
>
> overriding procedure OnCreate
> (This : access Typ;
> savedInstanceState : access Standard.Android.Os.Bundle.Typ'class)
> is
> type Super_Ref is access all Android.App.Activity.Typ;
> begin
> Android.App.Activity.Oncreate (Super_Ref (This), savedInstanceState);
>
> Android.App.Activity.SetContentView (Android.App.Activity.Ref (This), 16#7f030000#);
> end OnCreate;
>
> end Hello;
>
> By defintion, every non-scalar type in Java _is_ a pointer; Bundle and
> 'this' are pointers. The fact that the code doesn't say 'access' just
> hides that fact. Java also hides the existence of 'this'.

Java does not really hide the existence of "this", but there are a
few places where you cannot make "this" explicit (e.g. when declaring a method).
This is part of how Java, the language, is defined.

> Making those
> features explicit is definitely the Ada way.

But Ada does not use "access" for O-O; one or more parameters of a tagged type
indicate O-O (or 'Class if you want dispatching.) Can't have O-O with just
access:

procedure Plain (This: access Integer; That : ...);

has no trace of O-O even though "access" is present with the first
parameter. Hence, with Android, I'd find this to be just as good:

package body Hello is

overriding procedure OnCreate
(This : in out Hello.Typ;
savedInstanceState : Android.Os.Bundle.Typ'Class)
is
begin
Android.App.Activity.OnCreate (
Android.App.Activity.Typ(This),
savedInstanceState);

Android.App.Activity.SetContentView (
Android.App.Activity.Typ(This),
16#7f030000#);
end OnCreate;

end Hello;

Why is Super_Ref called Super_Ref, BTW? Isn't this name another hint at
writing Java in Ada?

It's not like I won't get used to writing access routinely, or think
in terms of the Java like Android model when writing Ada. It's just that
I'll then have to think in terms of two models of an O-O system:
one model uses pointers, the other doesn't, since it doesn't need them.


> http://www.stephe-leake.org/ada/access_vs_object.html).

(When the problem domain is grammars, my goal of an application is to allow
the user to build a structure of subprograms that represent a grammar,
so the application can then call the subprogram matching the start symbol
(or other symbols) to parse input strings.

(Typical grammars have recursion in them. This suggests recursion of some
form in the subprograms. The subprograms in my scanners use explicit access
to local procedures as necessary, guided by the grammar.
The sequence of tokens is stored in an instance of Indefinite_Vectors.

(Class-wide parameters are one way to invoke users' even handlers.
Users will pass objects that have overridden prim ops.

(Another option for event handlers is to ask for them to be
passed as actuals matching formal generic parameters/packages.

(The program construction techniques are different, but I think the
solution that follows from these alternative premises solve the
same problem, without needing O-O pointers.)


> In brief, _any_ framework that uses dispatching on class-wide
> objects needs reference semantics. In Ada, that is indicated by the
> explicit word 'access'.

+1 to Randy's remarks; tagged types being by-reference types for
a reason, in Ada, is the first thing I thought when I saw
"access Typ['Class]".

And 'Class makes dispatching explicit enough IMHO.

Dmitry A. Kazakov

unread,
Nov 1, 2011, 5:52:08 AM11/1/11
to
On Sun, 30 Oct 2011 07:32:59 -0400, Stephen Leake wrote:

> In brief, _any_ framework that uses dispatching on class-wide
> objects needs reference semantics.

Wrong. Reference semantics is required to maintain object's identity.
Without identity there is no need in it. This is unrelated to being
class-wide which requires *type identity* rather than the object's one. You
could have any combination of those two. One of the key advantages of Ada's
OO model is that it decouples them.

> In Ada, that is indicated by the explicit word 'access'.

Possibly yes, though tagged types are by-reference anyway. Actually
"limited" is the indicator for object's identity. What about freshly
introduced by Ada 2012 "aliased"?

BTW, Consider an architecture where the object address may change, while
keeping its identity. Thin pointers won't work for such "wandering"
objects...

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

Stephen Leake

unread,
Nov 2, 2011, 11:55:43 AM11/2/11
to
Georg Bauhaus <rm.dash...@futureapps.de> writes:

>> And here is the Ada version (just the package body):
>>
>> package body Hello is
>>
>> overriding procedure OnCreate
>> (This : access Typ;
>> savedInstanceState : access Standard.Android.Os.Bundle.Typ'class)
>> is
>> type Super_Ref is access all Android.App.Activity.Typ;
>> begin
>> Android.App.Activity.Oncreate (Super_Ref (This), savedInstanceState);
>>
>> Android.App.Activity.SetContentView (Android.App.Activity.Ref (This), 16#7f030000#);
>> end OnCreate;
>>
>> end Hello;
>>
>> By defintion, every non-scalar type in Java _is_ a pointer; Bundle and
>> 'this' are pointers. The fact that the code doesn't say 'access' just
>> hides that fact. Java also hides the existence of 'this'.
>
> Java does not really hide the existence of "this",

All I mean is it is not present in the parameter list; that's hidden.

> .. Hence, with Android, I'd find this to be just as good:
>
> package body Hello is
>
> overriding procedure OnCreate
> (This : in out Hello.Typ;
> savedInstanceState : Android.Os.Bundle.Typ'Class)
> is
> begin
> Android.App.Activity.OnCreate (
> Android.App.Activity.Typ(This),
> savedInstanceState);
>
> Android.App.Activity.SetContentView (
> Android.App.Activity.Typ(This),
> 16#7f030000#);
> end OnCreate;
>
> end Hello;

Yes, that is one possible design.

But it certainly does not match the Android Java API.

And in my real Ada program at work, I started with that style, but ended
up needing to store pointers to objects, so lots of 'access' crept in.

> Why is Super_Ref called Super_Ref, BTW? Isn't this name another hint at
> writing Java in Ada?

Yes. In this case, because I'm explicitly following the Android example.
But in general, the 'super' keyword in Java is a nice feature. There has
been discussion of adding that feature to Ada; I forget what the problem
was that ended up killing it.

>> http://www.stephe-leake.org/ada/access_vs_object.html).
>
> (When the problem domain is grammars, my goal of an application is to allow
> the user to build a structure of subprograms that represent a grammar,
> so the application can then call the subprogram matching the start symbol
> (or other symbols) to parse input strings.

I'd love to see your solution to this problem. It's easy to talk about
general principles and design goals; only complete actual solutions
flesh out all the problems and details.

>> In brief, _any_ framework that uses dispatching on class-wide
>> objects needs reference semantics. In Ada, that is indicated by the
>> explicit word 'access'.
>
> +1 to Randy's remarks; tagged types being by-reference types for
> a reason, in Ada, is the first thing I thought when I saw
> "access Typ['Class]".
>
> And 'Class makes dispatching explicit enough IMHO.

Then you really did not understand the point of my access_vs_object
example. I tried as hard as I could to eliminate 'access'; I succeeded,
but at too great a cost.

Do you agree with my conclusion in that example? If not, why not?

--
-- Stephe

Stephen Leake

unread,
Nov 2, 2011, 11:59:46 AM11/2/11
to
"Dmitry A. Kazakov" <mai...@dmitry-kazakov.de> writes:

> On Sun, 30 Oct 2011 07:32:59 -0400, Stephen Leake wrote:
>
>> In brief, _any_ framework that uses dispatching on class-wide
>> objects needs reference semantics.
>
> Wrong. Reference semantics is required to maintain object's identity.

Well, yes. What good is a system that does not maintain object identity?

Please rewrite my access_vs_object example, without using reference
semantics. Note that I am explicitly including container cursors as a
"reference type".

Or show me another real system that has dispatching on collections of
heterogeneous objects without reference semantics.

The proof is in the details.

--
-- Stephe

Dmitry A. Kazakov

unread,
Nov 2, 2011, 12:27:07 PM11/2/11
to
On Wed, 02 Nov 2011 11:59:46 -0400, Stephen Leake wrote:

> "Dmitry A. Kazakov" <mai...@dmitry-kazakov.de> writes:
>
>> On Sun, 30 Oct 2011 07:32:59 -0400, Stephen Leake wrote:
>>
>>> In brief, _any_ framework that uses dispatching on class-wide
>>> objects needs reference semantics.
>>
>> Wrong. Reference semantics is required to maintain object's identity.
>
> Well, yes. What good is a system that does not maintain object identity?

Why should it? Most of the objects Ada creates lack run-time identity. Ada
also prevents the programmer from identifying such objects. E.g. by
X'Access for X without "aliased".

> Please rewrite my access_vs_object example, without using reference
> semantics. Note that I am explicitly including container cursors as a
> "reference type".

That is OK, cursor is a referential type, which identities the object it
points to. If the cursor is a publicly access type, that is fine to me.
Moreover I wished that all cursor types implemented "abstract access
interface".

> Or show me another real system that has dispatching on collections of
> heterogeneous objects without reference semantics.

Note that Ada does not have MD. So you just cannot dispatch on the
collection *and* the object in the collection. You probably meant a
different thing: to dispatch on an element of some collection. The word
"dispatch" is irrelevant to identity here, because identity comes from the
collection: the element must stay in the collection while the operation is
performed on it. Is it so?

Or did you mean that it would be impossible to implement a collection of
class-wide objects without pointers? This is true, but it does not imply
referential semantics. E.g. the objects still could be copied in and out
when accessed.

Robert A Duff

unread,
Nov 2, 2011, 1:37:50 PM11/2/11
to
Stephen Leake <stephe...@stephe-leake.org> writes:

> But in general, the 'super' keyword in Java is a nice feature. There has
> been discussion of adding that feature to Ada; I forget what the problem
> was that ended up killing it.

I don't remember, either. I can't think of any fatal flaws right now.

You would need to deal with the fact that a private type can have
a different parent from the corresponding full type.

Without this feature, you can use a coding convention:

subtype Parent is T1;
type T2 is new Parent with ...;

and then convert to Parent.

- Bob

Simon Wright

unread,
Nov 2, 2011, 1:38:09 PM11/2/11
to
I hadn't considered this before, because when I was designing an
OOA-related framework it was in Ada 95, so there were no indefinite
containers to be considered for instance storage; I ended up storing
Handles, which were access-to-classwide-limited.

The fact that they had to be limited, to maintain object identity, would
have eliminated Ada 2005 (and now 2012) indefinite containers
immediately.

Georg Bauhaus

unread,
Nov 2, 2011, 8:37:20 PM11/2/11
to
On 02.11.11 16:55, Stephen Leake wrote:

>>> http://www.stephe-leake.org/ada/access_vs_object.html).
>>
>> (When the problem domain is grammars, my goal of an application is to allow
>> the user to build a structure of subprograms that represent a grammar,
>> so the application can then call the subprogram matching the start symbol
>> (or other symbols) to parse input strings.
>
> I'd love to see your solution to this problem. It's easy to talk about
> general principles and design goals; only complete actual solutions
> flesh out all the problems and details.

http://home.arcor.de/bauhaus/Ada/recdecnoptr.ada

This example features:

- a hierarchy of "tokens", though barely: Terminal and Non_Terminal,
with some info in each, derived from abstract Token.

- a handler derived from an abstract handler type, overriding a
primitive operation. The operation, On_Token, receives an object
of type Token'Class when some "grammatical event" happens.

procedure On_Token
(Manager : in out Handler;
Found : in Tokens.Token'Class)
is abstract;

- a recursive descent parser (exhaustive). The parser is structured
just as the grammar, which in this demo is

S -> a S | a

A similar program using the same parsing technique was
built around 28 productions. It also had the necessary level of
abstraction that is absent from the above demo, such as functions
that would query the state of a token (Image etc.).

No token is ever stored, though the handler types are free to
do whatever they want with the tokens, including storing them.
There are no allocators for tokens. The program uses access,
but for different purposes.

In a different program, I had used objects separate from tokens
for keeping more information about the tokens. The tokens and
the info objects were then associated in a has-a relationship,
using pointers to 'Class. But I could have passed these
additional objects without using pointers, too, just for the record.

In summary, then, I do not see that it is necessity to add pointers
to a parser interface. Storing polymorphic objects of polymorphic
components seems a different subject of a very general nature.

Stephen Leake

unread,
Nov 3, 2011, 7:36:01 AM11/3/11
to
Georg Bauhaus <rm.dash...@futureapps.de> writes:

> On 02.11.11 16:55, Stephen Leake wrote:
>
>>>> http://www.stephe-leake.org/ada/access_vs_object.html).
>>>
>>> (When the problem domain is grammars, my goal of an application is to allow
>>> the user to build a structure of subprograms that represent a grammar,
>>> so the application can then call the subprogram matching the start symbol
>>> (or other symbols) to parse input strings.
>>
>> I'd love to see your solution to this problem. It's easy to talk about
>> general principles and design goals; only complete actual solutions
>> flesh out all the problems and details.
>
> http://home.arcor.de/bauhaus/Ada/recdecnoptr.ada

Ok. The recursion in the grammar is represented by recursive subprogram
calls.

> This example features:
>
> - a hierarchy of "tokens", though barely: Terminal and Non_Terminal,
> with some info in each, derived from abstract Token.

Sufficient to illustrate the point, but a more complex example would
make the relative costs of the various solutions more apparent.

In particular, the operations in the 'access vs object' example require
a separate stack when using a recursive descent parser (see OpenToken
asu_example_5_10 for more on this). Implementing that stack could easily
require pointers, for complex objects.

> - a handler derived from an abstract handler type, overriding a
> primitive operation. The operation, On_Token, receives an object
> of type Token'Class when some "grammatical event" happens.
>
> procedure On_Token
> (Manager : in out Handler;
> Found : in Tokens.Token'Class)
> is abstract;
>
> - a recursive descent parser (exhaustive). The parser is structured
> just as the grammar, which in this demo is
>
> S -> a S | a

This grammar is rewritten from the original grammar. This is an accepted
technique, but it is a way to introduce errors, so it must be counted as
a cost.

> A similar program using the same parsing technique was
> built around 28 productions. It also had the necessary level of
> abstraction that is absent from the above demo, such as functions
> that would query the state of a token (Image etc.).

I'm impressed.

> No token is ever stored, though the handler types are free to
> do whatever they want with the tokens, including storing them.
> There are no allocators for tokens. The program uses access,
> but for different purposes.

I agree this use of 'access' is different, since it is 'access
procedure', not 'access object'; no allocations are needed. But I
suspect some purists would still object :).

> In a different program, I had used objects separate from tokens
> for keeping more information about the tokens. The tokens and
> the info objects were then associated in a has-a relationship,
> using pointers to 'Class. But I could have passed these
> additional objects without using pointers, too, just for the record.

But you chose not to.

And that is really the point. There are various solution techniques,
some using 'access object', some not. They have various costs. We each
chose a technique that we fell minimizes the cost while maximizing the
gain.

In my opinion, this recursive descent style is much harder to
understand. In particular, it is very difficult to see that the program
structure matches the grammar structure.

With OpenToken's data structure approach, it is very easy to see that
the data structure matches the grammar structure. That is one goal of
high level programming; make the solution space match the problem space,
so we can trust the solutions without too much work.

In addition, recursive descent in general requires far more lookahead
and backtracking than LR parsing. See OpenToken asu_example_5_10 for
more on this.

So I see this solution as far more costly than one using 'access
object'.

> In summary, then, I do not see that it is necessity to add pointers
> to a parser interface.

I said "some form of reference semantics is required to represent the
recursion".

In your program, the recursion is represented by a recursive subprogram
call. I don't think I can twist the definition of "reference semantics"
to include recursive subprogram calls (although the use of 'access
subprogram' gives me some wiggle room), so I'll grant you have proven me
wrong.

> Storing polymorphic objects of polymorphic components seems a
> different subject of a very general nature.

Yes; if we restrict the solution space for the grammar problem to data
structures, then my statement stands.

Thanks for taking the time to implement the example. Perhaps we should
put both on the Ada Programming Wikibook somewhere?

--
-- Stephe

Robert A Duff

unread,
Nov 3, 2011, 11:24:43 AM11/3/11
to
Stephen Leake <stephe...@stephe-leake.org> writes:

> I agree this use of 'access' is different, since it is 'access
> procedure', not 'access object'; no allocations are needed. But I
> suspect some purists would still object :).

"not null access procedure" is pretty safe. It can't fail a null check.
And there's no Unchecked_Deallocation or Unchecked_Access, so it
can't dangle. (In GNAT, you can use the non-standard
'Unrestricted_Access to create dangling access-to-proc.)
So, yes, it's totally different from an access to object.

I wish the syntax were just "procedure...", leaving off the
"not null access", which is just noise.

- Bob

Pascal Obry

unread,
Nov 3, 2011, 2:43:09 PM11/3/11
to Robert A Duff
Le 03/11/2011 16:24, Robert A Duff a écrit :
> I wish the syntax were just "procedure...", leaving off the
> "not null access", which is just noise.

If I can somewhat agree for the "not null access" case it would have
introduced some irregular syntax as for the "access" case we can have null:

type P is procedure;
V : P := null;

Makes quite evident that this is an access no :) So at this point why not:

type P is access procedure;
V : P := null;

Which makes things clear, and from there:

type P is not null access procedure;

Which is consistent with other declarations.

Pascal.

--

--|------------------------------------------------------
--| Pascal Obry Team-Ada Member
--| 45, rue Gabriel Peri - 78114 Magny Les Hameaux FRANCE
--|------------------------------------------------------
--| http://www.obry.net - http://v2p.fr.eu.org
--| "The best way to travel is by means of imagination"
--|
--| gpg --keyserver keys.gnupg.net --recv-key F949BD3B

Georg Bauhaus

unread,
Nov 3, 2011, 6:14:24 PM11/3/11
to
On 03.11.11 12:36, Stephen Leake wrote:

> In my opinion, this recursive descent style is much harder to
> understand. In particular, it is very difficult to see that the program
> structure matches the grammar structure.

Yes, recursion does take getting used to. I am sketching a generator
that will remove the burden of writing the recursive subprograms.
Its input will be compatible with OpenToken's operator based notation.
Currently, the interesting part looks like the following. This is
just exploring ideas, there is no real business going on.
(The usual suspects like proper lexical scanning, generating tokens,
etc., might be compatible.)

with Tokens, -- tokens, and lists of tokens
Rules; -- productions, and lists of productions
with Templates; -- what should a recursive subprogram look like

procedure Generate_Recursive_Descent is

------------------------------------------------------------------------
-- "Define the Grammar productions.
--
-- "The text in the example in the book looks something like:
--
-- S' -> S
-- S -> L = R | R
-- L -> * R | id
-- R -> L"
--

type Token_ID is (S_Prime_Nonterminal,
S_Nonterminal,
L_Nonterminal,
R_Nonterminal);

package Example_Tokens is new Tokens (Token_ID);
package Example_Rules is new Rules (Example_Tokens);
package Writers is new Templates (Example_Tokens);

S_Prime : Example_Tokens.Nonterminal(S_Prime_Nonterminal);
S : Example_Tokens.Nonterminal(S_Nonterminal);
L : Example_Tokens.Nonterminal(L_Nonterminal);
R : Example_Tokens.Nonterminal(R_Nonterminal);

Asterisk : Example_Tokens.Terminal
(Name => new String'("Asterisk"),
Match => '*');

ID : Example_Tokens.Terminal
(Name => new String'("id"),
Match => 'I');

Equals : Example_Tokens.Terminal
(Name => new String'("EQ"),
Match => '=');

use Example_Rules; -- operators

Example : constant Example_Rules.Grammar := Example_Rules.Null_Grammar and
S_Prime <= S and
S <= L & Equals & R and
S <= R and
L <= Asterisk & R and
L <= ID and
R <= L;

procedure Produce_Subprograms (Position: Lists_of_Rules.Cursor);

That is it, if one of the parsing models and Templates is acceptable
for the hypothetical programmer.


> Perhaps we should
> put both on the Ada Programming Wikibook somewhere?

It might be a starting point, although I'd prefer more generally relevant,
stripped down topics. For example the design pattern of delegation and its
consequences, or the meaning of distributed overhead of design choices:
show classical opposites, such as passive vs active, call vs callback,
Iterate vs for-loop, assignment-then-loop vs new-parameter-then-recursion,
heap allocation vs automatic objects etc.

If parsers can be stripped to the minimum matching one such subject,
they should serve as good examples? (Surely my example would need
overhaul, and polishing.)


Dmitry A. Kazakov

unread,
Nov 4, 2011, 4:48:50 AM11/4/11
to
On Thu, 03 Nov 2011 23:14:24 +0100, Georg Bauhaus wrote:

> On 03.11.11 12:36, Stephen Leake wrote:
>
>> In my opinion, this recursive descent style is much harder to
>> understand. In particular, it is very difficult to see that the program
>> structure matches the grammar structure.
>
> Yes, recursion does take getting used to. I am sketching a generator
> that will remove the burden of writing the recursive subprograms.

Hmm, actually recursive descent parser is the simplest thing in the world.
I never could understand why anybody would need to write some library for
that. What is wrong with

case Token_Table.Match (Source) is
when Boo_Token => Do_Boo;
when Foo_Token => Do_Foo;
...
end case;

Stephen Leake

unread,
Nov 4, 2011, 8:18:15 AM11/4/11
to
Georg Bauhaus <rm.dash...@futureapps.de> writes:

> On 03.11.11 12:36, Stephen Leake wrote:
>
>> In my opinion, this recursive descent style is much harder to
>> understand. In particular, it is very difficult to see that the program
>> structure matches the grammar structure.
>
> Yes, recursion does take getting used to. I am sketching a generator
> that will remove the burden of writing the recursive subprograms.

That would help a lot. I much prefer debugging tools to debugging
individual applications; my effort is magnified by the number of times
the tool is used.

> Its input will be compatible with OpenToken's operator based notation.

Excellent!

> Example : constant Example_Rules.Grammar := Example_Rules.Null_Grammar and
> S_Prime <= S and
> S <= L & Equals & R and
> S <= R and
> L <= Asterisk & R and
> L <= ID and
> R <= L;
>
> procedure Produce_Subprograms (Position: Lists_of_Rules.Cursor);

In current OpenToken, we have 'procedure Parse' instead of 'procedure
Produce_Subprograms'; the rest is the same. I gather
'Produce_Subprograms' generates Ada code, that must then be compiled.

I'm not clear what the benefit of this is over the current OpenToken
approach. It avoids the run-time allocation currently in OpenToken, but
since that's hidden from the user, and (presumably) fully
tested/debugged, why does that matter?

On the other side, LR parsing is much more efficient than recursive
descent (except in special cases).

One thing in OpenToken that really needs improving is the lexer. It is
horribly inefficient compared to Lex. It does have the advantage of
being much simpler to implement and test.

--
-- Stephe

Georg Bauhaus

unread,
Nov 4, 2011, 11:03:28 AM11/4/11
to
On 04.11.11 13:18, Stephen Leake wrote:

> In current OpenToken, we have 'procedure Parse' instead of 'procedure
> Produce_Subprograms'; the rest is the same. I gather
> 'Produce_Subprograms' generates Ada code, that must then be compiled.

Yes.

> I'm not clear what the benefit of this is over the current OpenToken
> approach.

Meant only to be a possible alternative, its implementation is trivial,
and it automatically reuses mechanisms such as a stack that
a traditional computer features as a built-in. :-)

The given method is exhaustive, if that's needed, it's there.
If there are no loops in the grammar itself (such as left recursion),
then the length of input determines the number of recursive
calls for this method, too, so use of stack space has a known
maximum.

From a programmer's perspective, the method shown will pass tokens
to handlers. Writers of SAX style content handlers will recognize
the scheme and find it familiar, I think.

Following are some ideas that I would find fairly easy to add
to the resulting parsers, to make them more useful, more efficient,
or even more powerful.
Are they equally easy to add to, for example, bottom up parsers?

1. A simple extension, using functions as subprograms, allows more
control: Start another rule (call another subprogram) only if the
previous one (a function) has returned False. IOW, parsing does
not need to be exhaustive. (A variation can use non-local
transfer of control, i.e. exception handlers added to subprograms
where desired.)
<hack>Let r be the return value, then f(r) is the next rule.
Assumption: this choice is not to be determined by the grammer
alone if modeling it accordingly would be awkward.</hack>

2. Or keep some state information along the way that can be
queried for (pseudo-)context, making the grammar less static,
and react to input: Only if rule R (m) has hit token T (j)
before, assume that the parser should now choose rule R (k).
The conditionals would be added to the generated code,
thus specializing the parsing process. OK, a.k.a hacking.
But see "Fence", next.

3. Or introduce pseudo-symbols such as "Fence" that have no
meaning in the language but will have an effect on backtracking:
backwards motion stops at a "Fence".
(Another possible pseudo-symbol is "User-Input".)

4. One can use (or misuse?) the mechanism to perform lexical
scanning. A first run produces tokens from a sub-grammar describing
the language in terms of lexemes only.

The basic mechanism never changes, and the number of topics
from which the parsers' logic can be understood is, I think,
pleasantly small.

Stephen Leake

unread,
Nov 5, 2011, 12:56:23 PM11/5/11
to
Georg Bauhaus <rm.dash...@futureapps.de> writes:

> On 04.11.11 13:18, Stephen Leake wrote:
>
>> In current OpenToken, we have 'procedure Parse' instead of 'procedure
>> Produce_Subprograms'; the rest is the same. I gather
>> 'Produce_Subprograms' generates Ada code, that must then be compiled.
>
> Yes.
>
>> I'm not clear what the benefit of this is over the current OpenToken
>> approach.
>
> Meant only to be a possible alternative, its implementation is trivial,
> and it automatically reuses mechanisms such as a stack that
> a traditional computer features as a built-in. :-)

It occured to me that one reason to not use the current OpenToken is the
need to run on Ravenscar, with a "no allocations" restriction. But I
think I'd rather use bounded containers in that case; it should not be
too hard to build a generic common interface.

> The given method is exhaustive, if that's needed, it's there.
> If there are no loops in the grammar itself (such as left recursion),
> then the length of input determines the number of recursive
> calls for this method, too, so use of stack space has a known
> maximum.

Ah; I hadn't thought of it that way. That makes this approach ok for
Ravenscar.

> From a programmer's perspective, the method shown will pass tokens
> to handlers. Writers of SAX style content handlers will recognize
> the scheme and find it familiar, I think.

Yes. The equivalent "handlers" in OpenToken are just dispatching
subprograms.

> Following are some ideas that I would find fairly easy to add
> to the resulting parsers, to make them more useful, more efficient,
> or even more powerful.
> Are they equally easy to add to, for example, bottom up parsers?

I think these are all just moving towards LR parsing; might as well just
go there!

--
-- Stephe

Randy Brukardt

unread,
Nov 7, 2011, 10:56:17 PM11/7/11
to
"Robert A Duff" <bob...@shell01.TheWorld.com> wrote in message
news:wccpqha...@shell01.TheWorld.com...
> Stephen Leake <stephe...@stephe-leake.org> writes:
>
>> But in general, the 'super' keyword in Java is a nice feature. There has
>> been discussion of adding that feature to Ada; I forget what the problem
>> was that ended up killing it.
>
> I don't remember, either. I can't think of any fatal flaws right now.

It wasn't really killed, it's just useless. (I.e., we have Parent_Tag in
package Ada.Tags, there just isn't a way to use that tag to directly control
dispatching. *That* we tried to do, but the solutions were all considered
heavy and not likely to be used. We ended up with the more specialized
generic dispatching constructor.)

> You would need to deal with the fact that a private type can have
> a different parent from the corresponding full type.

A private type doesn't have a parent, it has an "ancestor". That's probably
what killed any high-level feature (Ada.Tags ignores privacy, of course,
it's a runtime thing). There isn't any reasonable way to define the "parent"
of a private type, and it would be trouble to have the result of T'Parent to
be different depending on visibility.

Randy.



Stephen Leake

unread,
Nov 10, 2011, 12:25:30 PM11/10/11
to
Stephen Leake <stephe...@stephe-leake.org> writes:

> I've managed to get an Ada 'hello world' working on Android. It follows
> the example at
> http://developer.android.com/resources/tutorials/hello-world.html
> translated to Ada.

I've posted the relevant files to my website; I'm having a hard time
figuring out where to put them on the GnuAda SourceForge site.

http://www.stephe-leake.org/ada/android.html

enjoy, and let me know if it works for you (I'm sure there will be
questions :).

--
-- Stephe

mockturtle

unread,
Nov 27, 2011, 10:18:15 AM11/27/11
to
Your post is almost one month old (I did not check the group for a while), but I wanted to add my congratulations to the thread. I had this idea in the background for a while (maybe there is also and old post of mine), but I never had the time to start the project. As someone else pointed out, maybe there are some rough spot to smooth, but it is a start and that (IMHO) is important.

Stephen Leake

unread,
Nov 28, 2011, 5:35:26 PM11/28/11
to
mockturtle <frame...@gmail.com> writes:

> Your post is almost one month old (I did not check the group for a
> while), but I wanted to add my congratulations to the thread.

Thanks.

However, I have now finished writing a first draft of a (very small)
music player app, and it does not work.

I encountered more bugs, both in jvm2ada and jvm-gnat. I fixed a few,
found workarounds for more, and finally got the thing to compile,
install, and get past the first "can't find the main class name" error.

Now it can't find many methods, so this is _not_ a case of "if it
compiles, it will run". Which is a good reason to give up.

Another reason to give up; I could not use Ada.Containers (due to more
jgnat bugs). So I had to use java.util.LinkedLists. Which is generic,
but jgnat doesn't support Java generics, so the linked list just
contains java.Lang.Object, and we lose type safety.

Another reason to give up; Java interfaces don't map to Ada interfaces
(because jgnat was initially designed before Ada interfaces were
invented), so using Java interfaces is awkward.

At this point, my opinion of GNAT for JVM is:

1) it probably works well if you are writing a stand-alone Ada program
that is compiled for the JVM target.

2) it is _not_ good enough when trying to import large amounts of Java
code, and export the Ada main programs (as is the case for a real
Android app).

So I'm giving up, and going back to Java.

We need a major player to decide they need secure, reliable apps on
Android, so they will pay to fix jgnat.

Here's a scenario; convert President Obama to Android (he currently uses
a Blackberry), so the Pentagon has to get secure apps for him. :).

--
-- Stephe

Georg Bauhaus

unread,
Nov 29, 2011, 6:23:27 AM11/29/11
to
On 28.11.11 23:35, Stephen Leake wrote:

> So I'm giving up, and going back to Java.

Maybe not yet ...

> We need a major player to decide they need secure, reliable apps on
> Android, so they will pay to fix jgnat.
>
> Here's a scenario; convert President Obama to Android (he currently uses
> a Blackberry), so the Pentagon has to get secure apps for him. :).

Alternatively, get good hardware and have SofCheck's Ada compiler---which
outputs good C---connect your program to the Objective-C world. ;-)

Stephen Leake

unread,
Nov 29, 2011, 10:33:17 PM11/29/11
to
I don't see why introducing yet another language would help things.

--
-- Stephe

Georg Bauhaus

unread,
Nov 30, 2011, 1:57:16 PM11/30/11
to
On 30.11.11 04:33, Stephen Leake wrote:

>> Alternatively, get good hardware and have SofCheck's Ada compiler---which
>> outputs good C---connect your program to the Objective-C world. ;-)
>
> I don't see why introducing yet another language would help things.

Introducing one single language besides Ada will work,
which helps things a bit, in comparison.

The idea is to write the "logic" part of the programs not in
[Objective-]C, but in Ada, when it is considered superior to C.
Then, use the Cocoa framework (or GNUStep) for I/O, including GUI,
and use Objective-C.

Apple asks us to write in "plain C" the parts of our programs that
require the highest efficiency. With a seamless Ada->C compiler,
I can instead write these parts in plain Ada, or SPARK.
Since the Ada standard essentially guarantees that interfacing
to and from C works well, any additional work when writing
logic parts in Ada will be the writing of pragma Export and calling
Ada operations from view controllers, for example.

Where Ada has something to offer, such as a more expressive type system,
or source text that would typically input more information to code
analysis, these advantages will stay, and still I can play by the
rules, using GCC or Clang/LLVM as terminal compilers.


(The current state of portable GUI programming results first and foremost
from the way we let a handful of companies/organizations create mutually
incompatible, yet conceptually compatible, GUI programming
environments, again and again. We pay them, or support them in other ways ...
Sadly, the least promising solution today is wishing to pick
a language such as Ada for writing GUI applications. The choice of Ada
always results is some layered approach, lacking integration.
Be it GTK+, AWT etc, Tk, WPF/.NET, Qt, ... If industry does not
wish to change this state, then a separation of concerns can still
lead to something reasonably productive, and stadard:
the separation of logic (written in Ada) and GUI (written
in software corporation's choice).)


Reply all
Reply to author
Forward
0 new messages