comp.lang.ada
 help / color / mirror / Atom feed
* load and use a ".o" file?
@ 2003-12-18 23:31 lifetime n00b
  2003-12-18 23:59 ` Stephen Leake
  2003-12-19  1:51 ` tmoran
  0 siblings, 2 replies; 29+ messages in thread
From: lifetime n00b @ 2003-12-18 23:31 UTC (permalink / raw)


I've been trying to educate myself on how to do this, but I can't seem 
to find the answers I need. In concept, what I need to be able to do 
seems like it should be simple, and so I'll give a simple example.

There is a main program loop already running, and there is a ".o" 
compiled object file (compiled with gnat) which *hasn't* been linked 
into the main program, but it has a procedure or function in it I want 
to call. Let's say it is very simple function which was compiled from this:

function HiThere return String is
begin
	return "Hi there!";
end HiThere;

Instead of linking this into an executable, it is just compiled with 
say, "gnatmake -c hithere", to get the "hithere.o" file we're interested in.

Now, how can I load this "hithere.o" file into an already running 
program (without linking it in beforehand) and then call the "HiThere" 
function from that program (which was also written in Ada)? Would the 
information in the corresponding .ali file be of use? Maybe I'm thinking 
about it wrong, and the source which compiles to the object file needs 
to have some access types or some other mechanisms in place? Note that 
I'm not talking about using a .dll or .so file, just the .o file.

Any guidance would be appreciated.




^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: load and use a ".o" file?
  2003-12-18 23:31 load and use a ".o" file? lifetime n00b
@ 2003-12-18 23:59 ` Stephen Leake
  2003-12-19  1:51 ` tmoran
  1 sibling, 0 replies; 29+ messages in thread
From: Stephen Leake @ 2003-12-18 23:59 UTC (permalink / raw)
  To: lifetime n00b; +Cc: comp.lang.ada

lifetime n00b <anonymous@yahoo.com> writes:

> There is a main program loop already running, and there is a ".o"
> compiled object file (compiled with gnat) which *hasn't* been linked
> into the main program, but it has a procedure or function in it I want
> to call. 

You need to compile and link it into a "dynamically linked library"
(dll on windows, so (shared object) on Unix). Then you need to import
your OS's dynamic linking API (which may be done somewhere already),
and you're all set.

To get more specific, you need to say what OS you are on. And someone
else will have to reply; I've not actually done this as yet.

-- 
-- Stephe




^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: load and use a ".o" file?
  2003-12-18 23:31 load and use a ".o" file? lifetime n00b
  2003-12-18 23:59 ` Stephen Leake
@ 2003-12-19  1:51 ` tmoran
  2003-12-19 15:28   ` lifetime n00b
  1 sibling, 1 reply; 29+ messages in thread
From: tmoran @ 2003-12-19  1:51 UTC (permalink / raw)


>Let's say it is very simple function which was compiled from this:
>
>function HiThere return String is
>begin
>        return "Hi there!";
>end HiThere;
>
>Instead of linking this into an executable, it is just compiled with
>say, "gnatmake -c hithere", to get the "hithere.o" file we're interested in.
>
>Now, how can I load this "hithere.o" file into an already running
>program (without linking it in beforehand) and then call the "HiThere"
>...
>I'm not talking about using a .dll or .so file, just the .o file.

  If you are not talking about using an existing dynamic linker/loader,
then you are clearly talking about developing your own.  In your example,
HiThere may need to make calls (for memory allocation for the string, for
instance) on the Ada Run Time System of the main program.  So you will
need to load the code from the .o file and then modify call addresses, ie,
link, the loaded HiThere function.  You should be able to find the
information you need by looking at the Gnat source code.
  What problem are you trying to solve?  Perhaps there's an easier way.



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: load and use a ".o" file?
  2003-12-19  1:51 ` tmoran
@ 2003-12-19 15:28   ` lifetime n00b
  2003-12-19 18:08     ` Stephen Leake
  2003-12-19 21:28     ` Simon Wright
  0 siblings, 2 replies; 29+ messages in thread
From: lifetime n00b @ 2003-12-19 15:28 UTC (permalink / raw)


tmoran@acm.org wrote:
>   If you are not talking about using an existing dynamic linker/loader,
> then you are clearly talking about developing your own.  In your example,
> HiThere may need to make calls (for memory allocation for the string, for
> instance) on the Ada Run Time System of the main program.  So you will
> need to load the code from the .o file and then modify call addresses, ie,
> link, the loaded HiThere function.  You should be able to find the
> information you need by looking at the Gnat source code.
>   What problem are you trying to solve?  Perhaps there's an easier way.


Well, the "Big Picture" is that I'm wanting to write a Common Lisp 
system in Ada (yes I know, it probably sounds like heresy to both the 
Lisp and Ada camps), and I want to use gnat as the back-end compiler. 
Contrary to popular opinion, Lisp is not simply an interpreted language. 
One feature of a complete Common Lisp system is that source files can be 
compiled and loaded while the top-level system is running. Some 
implementations (such as CLISP) use byte-code compilation, but most 
compile to native code. Some use their own built-in compilers, while 
others first translate the Lisp code to C and use gcc as the back-end 
compiler and then load and use that compiled file. From what I can tell, 
it seems that GCL and ECL use gcc to compile the files as dynamic load 
(.so) files and then call dlopen() on that file.

I was thinking that it would be more efficient (and more portable) to 
not use .dll or .so files, but to load and use the .o object files 
directly in some way. And if I could figure out how to do it with the 
example I described in the OP, then I could just expand on that to 
accomplish what I'm ultimately aiming towards.




^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: load and use a ".o" file?
  2003-12-19 15:28   ` lifetime n00b
@ 2003-12-19 18:08     ` Stephen Leake
  2003-12-20 20:12       ` lifetime n00b
  2003-12-19 21:28     ` Simon Wright
  1 sibling, 1 reply; 29+ messages in thread
From: Stephen Leake @ 2003-12-19 18:08 UTC (permalink / raw)
  To: comp.lang.ada

lifetime n00b <anonymous@yahoo.com> writes:

> I was thinking that it would be more efficient (and more portable) to
> not use .dll or .so files, but to load and use the .o object files
> directly in some way. 

.dll and .so files are designed to do _precisely_ what you are trying
to do; they are the most efficient solution!

Hmm. Well, they were designed in the context of a lot of heritage. If
you want to design an object file format and dynamic linker from
scratch, you might be able to do better. But there's no point; .dll
and .so are the only reasonable choices at this point.

-- 
-- Stephe




^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: load and use a ".o" file?
  2003-12-19 15:28   ` lifetime n00b
  2003-12-19 18:08     ` Stephen Leake
@ 2003-12-19 21:28     ` Simon Wright
  1 sibling, 0 replies; 29+ messages in thread
From: Simon Wright @ 2003-12-19 21:28 UTC (permalink / raw)


lifetime n00b <anonymous@yahoo.com> writes:

> I was thinking that it would be more efficient (and more portable)
> to not use .dll or .so files, but to load and use the .o object
> files directly in some way. And if I could figure out how to do it
> with the example I described in the OP, then I could just expand on
> that to accomplish what I'm ultimately aiming towards.

I realise it is most unlikely that your target OS is VxWorks, but
there may be some help to be gleaned ..

The way you build Ada for VxWorks (well, with GNAT) is

* you do the bind as normal, this generates (among other things) the
  elaboration code in adainit and a call to it followed by a call to
  your program entry point

* the link is done (like any other VxWorks link) as a partial link (I
  think that's the right word, the basic command is ld -r), so that no
  VxWorks runtime is included but the GNAT runtime is

* the result is downloaded to the target and relocations resolved
  there, against the symbol table (I am a little hazy about exact
  details here, but it is certainly possible to do this download from
  eg flash memory, so the symbols must be resident).

For C under VxWorks there is no elaboration so you can just download a
.o.

For Ada it would be more tricky. You really do need that elaboration
code to get called. And you have to be sure that the runtime is
already present. And it may need elaboration too. And it may be wrong
to re-elaborate parts of the runtime that have been elaborated by the
already-running program.

All this sounds like a very interesting project!

One thought -- I'm not sure what the difference is between a .o and a
.so, they are both ELF files (on Linux anyway), I wonder if dlopen etc
would work with .o's?

-S



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: load and use a ".o" file?
  2003-12-19 18:08     ` Stephen Leake
@ 2003-12-20 20:12       ` lifetime n00b
  2003-12-20 21:15         ` tmoran
                           ` (3 more replies)
  0 siblings, 4 replies; 29+ messages in thread
From: lifetime n00b @ 2003-12-20 20:12 UTC (permalink / raw)


Stephen Leake wrote:
> .dll and .so files are designed to do _precisely_ what you are trying
> to do; they are the most efficient solution!

Well, not _precisely_, since a typical program using the .dll or .so 
files needs to know about those files when it is compiled itself, right? 
Maybe I wasn't clear on exactly what I need to do. The program that 
needs to load and use the object file is *already running* before the 
object file is compiled. This "main program" has no prior information 
about the data or routines which may be in the object file it is being 
told to load.

The "main program" operates much like a command prompt, and when 
(compile-file "hithere") is typed at the prompt, gnat will be called to 
compile an object file. Then when (load "hithere") is typed at the 
prompt, the object file is loaded and the data and/or functions in 
"hithere" are now available to the main program. Some additional 
information may have to be included in a supporting file produced at the 
same time the object file is produced, and this supporting file would be 
loaded when the object file is loaded.

That's the idea anyway. But I'm having a difficult time trying to figure 
out how to accomplish this seemingly straightforward task.




^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: load and use a ".o" file?
  2003-12-20 20:12       ` lifetime n00b
@ 2003-12-20 21:15         ` tmoran
  2003-12-20 23:41           ` lifetime n00b
  2003-12-21 11:46         ` Simon Wright
                           ` (2 subsequent siblings)
  3 siblings, 1 reply; 29+ messages in thread
From: tmoran @ 2003-12-20 21:15 UTC (permalink / raw)


>The "main program" operates much like a command prompt, and when
>(compile-file "hithere") is typed at the prompt, gnat will be called to
>compile an object file. Then when (load "hithere") is typed at the
>prompt, the object file is loaded and the data and/or functions in
>"hithere" are now available to the main program. Some additional
  How about making the freshly generated "hithere" file a server program
with remotely accessible procedures etc and use Annex E.



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: load and use a ".o" file?
  2003-12-20 21:15         ` tmoran
@ 2003-12-20 23:41           ` lifetime n00b
  2003-12-21  7:15             ` tmoran
  0 siblings, 1 reply; 29+ messages in thread
From: lifetime n00b @ 2003-12-20 23:41 UTC (permalink / raw)


tmoran@acm.org wrote:
>   How about making the freshly generated "hithere" file a server program
> with remotely accessible procedures etc and use Annex E.

That would be horribly inefficient. Conceptually, the contents of these 
object files become part of the "main program" when they are loaded and 
share the same address space with the main program. For example, a call 
to a function normally involves putting the arguments on the stack, 
executing the function, and reading the return value from a register. In 
the distributed case, the partition containing the function must be 
located and placed on the stream, the arguments to the function are 
placed on the stream, the stream is sent to the receiving partition 
which executes the function locally, and the result of the function call 
is placed back on the stream which is then read as the return value.




^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: load and use a ".o" file?
  2003-12-20 23:41           ` lifetime n00b
@ 2003-12-21  7:15             ` tmoran
  0 siblings, 0 replies; 29+ messages in thread
From: tmoran @ 2003-12-21  7:15 UTC (permalink / raw)


> > with remotely accessible procedures etc and use Annex E.
>
> That would be horribly inefficient.
  The question is, would it take too long.  If you are going to make
billions of these calls and subroutine call efficiency is a real problem,
perhaps you should write out an entire new program, including the
freshly generated code, and compile that with full global optimization,
subroutine inlining, etc.



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: load and use a ".o" file?
  2003-12-20 20:12       ` lifetime n00b
  2003-12-20 21:15         ` tmoran
@ 2003-12-21 11:46         ` Simon Wright
  2003-12-21 13:57         ` Stephen Leake
  2003-12-22 15:50         ` Mark H Johnson
  3 siblings, 0 replies; 29+ messages in thread
From: Simon Wright @ 2003-12-21 11:46 UTC (permalink / raw)


lifetime n00b <anonymous@yahoo.com> writes:

> Well, not _precisely_, since a typical program using the .dll or .so
> files needs to know about those files when it is compiled itself,
> right? Maybe I wasn't clear on exactly what I need to do. The
> program that needs to load and use the object file is *already
> running* before the object file is compiled. This "main program" has
> no prior information about the data or routines which may be in the
> object file it is being told to load.

man dlopen (assuming you're on a Unix box of course). What the
equivalent for win32 is I don't know, but I'm sure there is one.

-- 
Simon Wright                               100% Ada, no bugs.



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: load and use a ".o" file?
  2003-12-20 20:12       ` lifetime n00b
  2003-12-20 21:15         ` tmoran
  2003-12-21 11:46         ` Simon Wright
@ 2003-12-21 13:57         ` Stephen Leake
  2003-12-22 19:29           ` lifetime n00b
  2003-12-22 20:49           ` Jon S. Anthony
  2003-12-22 15:50         ` Mark H Johnson
  3 siblings, 2 replies; 29+ messages in thread
From: Stephen Leake @ 2003-12-21 13:57 UTC (permalink / raw)
  To: lifetime n00b; +Cc: comp.lang.ada

lifetime n00b <anonymous@yahoo.com> writes:

> Stephen Leake wrote:
> > .dll and .so files are designed to do _precisely_ what you are trying
> > to do; they are the most efficient solution!
> 
> Well, not _precisely_, since a typical program using the .dll or .so
> files needs to know about those files when it is compiled itself,
> right? 

That's one way to use dynamically linked libraries. But if you look
under the hood, you will see that is just a variant of what you are
doing.

When a program that uses dlls starts up, it dynamically links the dll.
What you want is a program that dynamically links a dll at some later
time. In either case, the dynamic linking is the key.

> Maybe I wasn't clear on exactly what I need to do. The program that
> needs to load and use the object file is *already running* before
> the object file is compiled. This "main program" has no prior
> information about the data or routines which may be in the object
> file it is being told to load.

Well, it can't have absolutely _no_ information. It has to know the
list of subroutines (and their parameter profiles) that are in the
dll. Or, in COM style, it has to have a way of finding out what
subroutines are in the dll; which means it has to know the names of
the introspection subroutines in the dll.

When you dynamically link the compiled file into the main program, you
look up the addresses of those known routines.

> The "main program" operates much like a command prompt, and when
> (compile-file "hithere") is typed at the prompt, gnat will be called
> to compile an object file. Then when (load "hithere") is typed at
> the prompt, the object file is loaded and the data and/or functions
> in "hithere" are now available to the main program. 

Yes, that is what I thought you were doing. But how does the main
program know the names of the functions in "hithere"?

> Some additional information may have to be included in a supporting
> file produced at the same time the object file is produced, and this
> supporting file would be loaded when the object file is loaded.

Ah; perhaps that's the names of the functions? In Windows, that's a
.def file, which lists the names of the functions in a dll.

> That's the idea anyway. But I'm having a difficult time trying to
> figure out how to accomplish this seemingly straightforward task.

Go read the manuals on dlls, and dynamic linking in general, and on
COM. You are re-inventing the wheel! It may seem straightforward, but
it gets quite complicated. Fortunately, it has been solved.

Most good ideas have been thought of before :).

-- 
-- Stephe




^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: load and use a ".o" file?
  2003-12-20 20:12       ` lifetime n00b
                           ` (2 preceding siblings ...)
  2003-12-21 13:57         ` Stephen Leake
@ 2003-12-22 15:50         ` Mark H Johnson
  2003-12-22 19:46           ` lifetime n00b
  3 siblings, 1 reply; 29+ messages in thread
From: Mark H Johnson @ 2003-12-22 15:50 UTC (permalink / raw)


lifetime n00b wrote:
> Stephen Leake wrote:
> 
>> .dll and .so files are designed to do _precisely_ what you are trying
>> to do; they are the most efficient solution!
> 
> 
> Well, not _precisely_, since a typical program using the .dll or .so 
> files needs to know about those files when it is compiled itself, right? 
> Maybe I wasn't clear on exactly what I need to do. The program that 
> needs to load and use the object file is *already running* before the 
> object file is compiled. This "main program" has no prior information 
> about the data or routines which may be in the object file it is being 
> told to load.
> 
What you are describing sounds a lot like the mechanism used on Multics 
for dynamic linking of object files. There is a better explanation in 
the references at
   http://www.multicians.org/
or by reading
   "The Multics System: An Examination of its Structure" by E.I. Organick
but a quick summary follows.

When a file is compiled on Multics, an object file is created. Part of 
the data in that object file is a list of public symbols, including 
entry points. For a subroutine named xyz, compiled from xyz.fortran, the 
  entry point would simply be xyz. Let's say you have a main program 
main, calling xyz. This is an external reference to xyz (since it is not 
found in the current segment), and the first call works something like this:
  - call xyz (dispatched to an activation function)
  - the activation function checks first the active segments for a 
symbol within them called xyz. If found, it fixes up the dispatch to go 
directly to that xyz and resumes execution.
  - if not in an active segment, it uses the search path (similar to 
PATH on Unix) to find a file named xyz. If found, it loads that file 
into a segment, makes it active, and does the work of the second step.
  - if no such file is found, it calls the command line interpreter with 
an error status. At this point, you can fix your search path, create the 
object file xyz, start the debugger, or abandon execution. If you either 
of the first two, you can resume and the attempt to load xyz repeats.

The subsequent calls to xyz is done just like any other cross segment 
function call, basically running at (or near) full speed. It is this 
part that eliminates most of the concerns about performance since the 
expensive look up is only done once per symbol.

This capability, and I/O redirection are two of the things I really miss 
from Multics. The development flexibility provided were great to enhance 
the performance of developers and the overhead was quite modest with the 
hardware provided. The lack of effective paged / segmentation hardware 
is one thing that makes this hard to implement in software.

You can probably get close if you modify the build of objects to 
generate .so's instead of .o's and then put a wrapper around dlopen to 
do the semantics you are looking for. If you use GNAT, you could 
probably even bury this in the runtime by adding a pragma (or command 
line option) to denote external references as dynamic calls.

If you get this to work, I'd like to hear about it.
   --Mark





^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: load and use a ".o" file?
  2003-12-21 13:57         ` Stephen Leake
@ 2003-12-22 19:29           ` lifetime n00b
  2003-12-22 20:49           ` Jon S. Anthony
  1 sibling, 0 replies; 29+ messages in thread
From: lifetime n00b @ 2003-12-22 19:29 UTC (permalink / raw)


Stephen Leake wrote:
> You are re-inventing the wheel! 

No, I'm just trying to find the wheel I need! Honest. If I thought I'd 
have to reinvent the thing, I'd be the first to point out that I'm the 
last one qualified to do so, and then I'd just try to find a square I 
could use instead (in this case, maybe a byte-code VM?). :-)

> It may seem straightforward, but it gets quite complicated. 

So I have found.

 > Fortunately, it has been solved.

I think I may be able to use dlopen and dlsym on Linux with an Ada 
wrapper, but I was hoping for an Ada-only solution that would be 
cross-platform (letting gnat take all the nasty details from me). But 
that's just me hoping for a wheel that can fly...

> Most good ideas have been thought of before :).

And almost all of them were thought of by Kepler (just don't tell that 
to Newton)! :)




^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: load and use a ".o" file?
  2003-12-22 15:50         ` Mark H Johnson
@ 2003-12-22 19:46           ` lifetime n00b
  2003-12-22 22:58             ` Mark H Johnson
  0 siblings, 1 reply; 29+ messages in thread
From: lifetime n00b @ 2003-12-22 19:46 UTC (permalink / raw)


Mark H Johnson wrote:
>  - call xyz (dispatched to an activation function)
>  - the activation function checks first the active segments for a symbol 
> within them called xyz. If found, it fixes up the dispatch to go 
> directly to that xyz and resumes execution.
>  - if not in an active segment, it uses the search path (similar to PATH 
> on Unix) to find a file named xyz. If found, it loads that file into a 
> segment, makes it active, and does the work of the second step.
>  - if no such file is found, it calls the command line interpreter with 
> an error status. 

This actually sounds a lot like using a distributed system (Annex E) 
with both active and passive partitions on the same local machine, 
though probably more efficient.


> The subsequent calls to xyz is done just like any other cross segment 
> function call, basically running at (or near) full speed. It is this 
> part that eliminates most of the concerns about performance since the 
> expensive look up is only done once per symbol.

Unfortunately, I won't be programming this for Multics. I may need to 
suck it up and just do some benchmarks using the Annex E method. Passing 
data, arguments, and return values along streams between paritions just 
to call a function sure seems like a huge performance drain, but maybe 
in practice it's not as bad as I imagine.

> If you get this to work, I'd like to hear about it.

Me too! :)




^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: load and use a ".o" file?
  2003-12-21 13:57         ` Stephen Leake
  2003-12-22 19:29           ` lifetime n00b
@ 2003-12-22 20:49           ` Jon S. Anthony
  2003-12-22 23:15             ` Stephen Leake
  1 sibling, 1 reply; 29+ messages in thread
From: Jon S. Anthony @ 2003-12-22 20:49 UTC (permalink / raw)


Stephen Leake <stephen_leake@acm.org> writes:

> lifetime n00b <anonymous@yahoo.com> writes:
> 
...
> > Maybe I wasn't clear on exactly what I need to do. The program that
> > needs to load and use the object file is *already running* before
> > the object file is compiled. This "main program" has no prior
> > information about the data or routines which may be in the object
> > file it is being told to load.

This sort of thing is perfectly reasonable and something that is
extremely useful in a wide range of applications.

What I don't understand is why people don't just use technology that
has solved this problem since "for ever".  No, dll's and so's are not
the answer - they are intended to solve a different (related) problem
and are at best a poor mans hack for what you are talking about.

What you really "need"[1] here is a true dynamic language.


> Most good ideas have been thought of before :).

Indeed.  I see that Greenspun's 10th is alive and well on c.l.a :-|...


/Jon




^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: load and use a ".o" file?
  2003-12-22 19:46           ` lifetime n00b
@ 2003-12-22 22:58             ` Mark H Johnson
  2003-12-23 17:48               ` Robert I. Eachus
  0 siblings, 1 reply; 29+ messages in thread
From: Mark H Johnson @ 2003-12-22 22:58 UTC (permalink / raw)


lifetime n00b wrote:

> Mark H Johnson wrote:
> 
>>  - call xyz (dispatched to an activation function)
>>  - the activation function checks first the active segments for a 
>> symbol within them called xyz. If found, it fixes up the dispatch to 
>> go directly to that xyz and resumes execution.
>>  - if not in an active segment, it uses the search path (similar to 
>> PATH on Unix) to find a file named xyz. If found, it loads that file 
>> into a segment, makes it active, and does the work of the second step.
>>  - if no such file is found, it calls the command line interpreter 
>> with an error status. 
> 
> 
> This actually sounds a lot like using a distributed system (Annex E) 
> with both active and passive partitions on the same local machine, 
> though probably more efficient.
> 
No, they were actually subroutine calls. The compiler generated slightly 
different code for an "in segment" call and a "cross segment" call due 
to the indirection. The glue code (to do the lookup) was basically a 
system service done by the OS to facilitate activation of new segments.

By the way, when I say segment - I mean a segment of the same address 
space, not a partition. Think to the 386 processor where you have 32 k 
segments in certain processing modes. On Multics, the segments were 256 
Kwords (1 Mbyte) in size which worked quite well in practice.
   --Mark




^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: load and use a ".o" file?
  2003-12-22 20:49           ` Jon S. Anthony
@ 2003-12-22 23:15             ` Stephen Leake
  2003-12-23  1:36               ` tmoran
  2003-12-27 22:55               ` Jon S. Anthony
  0 siblings, 2 replies; 29+ messages in thread
From: Stephen Leake @ 2003-12-22 23:15 UTC (permalink / raw)
  To: comp.lang.ada

j-anthony@rcn.com (Jon S. Anthony) writes:

> This sort of thing is perfectly reasonable and something that is
> extremely useful in a wide range of applications.
> 
> What I don't understand is why people don't just use technology that
> has solved this problem since "for ever".  No, dll's and so's are not
> the answer - they are intended to solve a different (related) problem
> and are at best a poor mans hack for what you are talking about.
> 
> What you really "need"[1] here is a true dynamic language.

Ok, I'll bite. What's a "true dynamic language"? Do you mean
"interpreted from source", like some versions of Basic, and most shell
languages? Or "interpreted from some intermediate byte code", like
most Visual Basic, Lisp implementations, Java, C#, etc? Or something
else?

All interpreters make the job of adding random code at run-time much
easier. 

-- 
-- Stephe




^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: load and use a ".o" file?
  2003-12-22 23:15             ` Stephen Leake
@ 2003-12-23  1:36               ` tmoran
  2003-12-27 22:55               ` Jon S. Anthony
  1 sibling, 0 replies; 29+ messages in thread
From: tmoran @ 2003-12-23  1:36 UTC (permalink / raw)


>All interpreters make the job of adding random code at run-time much
>easier.
  If I understand correctly, the problem is not in adding code, but in
finding code.  The compiler has put the code, in some form, in a .o file
and the OP wants to pluck it out so he can call it - perhaps with an
indirect jump, ie, a software simulation of Multics et al.



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: load and use a ".o" file?
  2003-12-22 22:58             ` Mark H Johnson
@ 2003-12-23 17:48               ` Robert I. Eachus
  2003-12-23 17:59                 ` Mark H Johnson
  0 siblings, 1 reply; 29+ messages in thread
From: Robert I. Eachus @ 2003-12-23 17:48 UTC (permalink / raw)


Mark H Johnson wrote:

> No, they were actually subroutine calls. The compiler generated slightly 
> different code for an "in segment" call and a "cross segment" call due 
> to the indirection. The glue code (to do the lookup) was basically a 
> system service done by the OS to facilitate activation of new segments.

Technically not correct.  The compiler could "in line" some local calls, 
but the binder couldn't.   What happened was that when a segment called 
an entry point for which the local link was null, it trapped.  The trap 
routine tried to snap the link using the current environment, and if it 
failed, bounced out to the user.  You literally could, when an error of 
this type occurred, change the search paths, or write the missing 
routine, compile it, then continue from the condition.  Done it myself....

> By the way, when I say segment - I mean a segment of the same address 
> space, not a partition. Think to the 386 processor where you have 32 k 
> segments in certain processing modes. On Multics, the segments were 256 
> Kwords (1 Mbyte) in size which worked quite well in practice.

Correct.  As I said in another post, there were multisegment files which 
allowed you to have objects larger than 1 Meg.  But in practice they 
were very infrequently used.

-- 
                                           Robert I. Eachus

"The war on terror is a different kind of war, waged capture by capture, 
cell by cell, and victory by victory. Our security is assured by our 
perseverance and by our sure belief in the success of liberty." -- 
George W. Bush




^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: load and use a ".o" file?
  2003-12-23 17:48               ` Robert I. Eachus
@ 2003-12-23 17:59                 ` Mark H Johnson
  2003-12-23 21:53                   ` Robert I. Eachus
  0 siblings, 1 reply; 29+ messages in thread
From: Mark H Johnson @ 2003-12-23 17:59 UTC (permalink / raw)


Robert I. Eachus wrote:

> Mark H Johnson wrote:
> 
>> No, they were actually subroutine calls. The compiler generated 
>> slightly different code for an "in segment" call and a "cross segment" 
>> call due to the indirection. The glue code (to do the lookup) was 
>> basically a system service done by the OS to facilitate activation of 
>> new segments.
> 
> 
> Technically not correct.  The compiler could "in line" some local calls, 
> but the binder couldn't. 
I did not mention the binder (which in many ways I equate to having a 
linker on Unix), just the compiler.

> What happened was that when a segment called 
> an entry point for which the local link was null, it trapped.  The trap 
> routine tried to snap the link using the current environment, and if it 
> failed, bounced out to the user.  You literally could, when an error of 
> this type occurred, change the search paths, or write the missing 
> routine, compile it, then continue from the condition.  Done it myself....
> 
Me to. That is why I described that mechanism in terms the OP would 
likely understand in a previous message.

   --Mark




^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: load and use a ".o" file?
  2003-12-23 17:59                 ` Mark H Johnson
@ 2003-12-23 21:53                   ` Robert I. Eachus
  0 siblings, 0 replies; 29+ messages in thread
From: Robert I. Eachus @ 2003-12-23 21:53 UTC (permalink / raw)


Mark H Johnson wrote:

> Robert I. Eachus wrote:
> 
>> Technically not correct.  The compiler could "in line" some local 
>> calls, but the binder couldn't. 
> 
> I did not mention the binder (which in many ways I equate to having a 
> linker on Unix), just the compiler.

I was not trying to be confrontational or whatever.  My point was, that 
in segments created by the binder, all that was done was to provide a 
(static, code-relative)target for the call.  It didn't change the 
calling code at all.  So if you had a program compiled as a collection 
of separate segments, and ran it that way, the first time each entry 
point was used, the link was snapped, and from then on you had no 
additional run-time overhead.  If you used the binder, it eliminated 
some of the run-time link snapping, but the code was exactly as 
efficient as if it had been compiled from one huge source file.

> Me to. That is why I described that mechanism in terms the OP would 
> likely understand in a previous message.

I still miss Multics.  I had accounts on several Multics machines when I 
worked at Honeywell.  When I moved to Stratus, even though Stratus was a 
'spritual' descendent of Multics, I kept an account on MIT_Multics.  (I 
had some Multics PL/I tools I wanted to port to VOS.)  But it has been 
fifteen years now, and I still don't have a development environment as 
good as Multics.

However, Ada is now a much better language than PL/I. ;-)

-- 
                                           Robert I. Eachus

"The war on terror is a different kind of war, waged capture by capture, 
cell by cell, and victory by victory. Our security is assured by our 
perseverance and by our sure belief in the success of liberty." -- 
George W. Bush




^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: load and use a ".o" file?
  2003-12-22 23:15             ` Stephen Leake
  2003-12-23  1:36               ` tmoran
@ 2003-12-27 22:55               ` Jon S. Anthony
  2003-12-28  3:28                 ` Stephen Leake
  1 sibling, 1 reply; 29+ messages in thread
From: Jon S. Anthony @ 2003-12-27 22:55 UTC (permalink / raw)


Stephen Leake <stephen_leake@acm.org> writes:

> j-anthony@rcn.com (Jon S. Anthony) writes:
> 
> > This sort of thing is perfectly reasonable and something that is
> > extremely useful in a wide range of applications.
> > 
> > What I don't understand is why people don't just use technology that
> > has solved this problem since "for ever".  No, dll's and so's are not
> > the answer - they are intended to solve a different (related) problem
> > and are at best a poor mans hack for what you are talking about.
> > 
> > What you really "need"[1] here is a true dynamic language.
> 
> Ok, I'll bite. What's a "true dynamic language"? 

It is true that many folks will/do have different ideas about what
"true dynamic language" means.  In this respect I fear it is a bit
like "true object oriented language".

One characteristic that is neither necessary nor sufficient for any
notion of this is that it be an "interpreted language".  While some
languages (for example, most scripting languages) do imply (mostly
because the language specification _is_ the implementation)
interpretation as part of their definition, "interpreted" interpreted
properly is really an _implementation_ issue, _not_ a language issue.

I think most people in the "dynamic community" would say you need at
least the following characteristics to be "truly dynamic":

1. Dynamic typing.  This is, strong typing on _objects_ as
   differentiated from "variables/locations".

2. Complete introspection of the language's computation and type
   model.  This is directly and explicitly available at the level of
   the programmer (not just the implementer).  NOTE: This does _not_
   mean or imply access to the underlying _implementation_.

   Some things this _does_ imply:

   * New function objects may be added to a running system at any time
     and existing functions may be so modified at any time.

   * The ability to create new types and/or classes at runtime; modify
     existing classes (with complete instance migration).


A couple examples which fully have this would be Common Lisp and
Smalltalk.  Neither are "interpreter" based[1].  Most Common Lisp
implementations have optimizing native compilers that typically
produce code within about 1.5-2.5 of well crafted C code[2].  So,
"interpretation" of either source or byte code is not a relevant
factor/issue.

For more information, here are a couple of links:

"Open Source/Free Software" Implementations:

http://www.cliki.net/Common%20Lisp%20implementation

Commercial Implementations:

http://alu.cliki.net/Implementation

General community information:

http://www.cliki.net/index and, of course, c.l.l


Here are a couple very simple examples concerning the issue at hand of
the OP.  These are done in Allegro Common Lisp at the REPL (read eval
print loop), typically this sort of interaction would be through the
IDE.


CL-USER(1):
 (defun foo (l r)
   (declare (fixnum l r) (optimize (speed 3 safety 1 debug 1)))
   (+ l r))
=> FOO

CL-USER(2): (compile 'foo)
=> FOO

CL-USER(3): (disassemble 'foo) ; Just to show we are native (on Intel...)
;; disassembly of #<Function FOO>
;; formals: L R

;; code start: #x7140a65c:
   0: 83 f9 02    cmpl	ecx,$2
   3: 74 02       jz	7
   5: cd 61       int	$97             ; EXCL::TRAP-ARGERR
   7: 80 7f 97 00 cmpb	[edi-105],$0    ; SYS::C_INTERRUPT
  11: 74 02       jz	15
  13: cd 64       int	$100            ; EXCL::TRAP-SIGNAL-HIT
  15: 03 c2       addl	eax,edx
  17: f8          clc
  18: 8b 75 fc    movl	esi,[ebp-4]
  21: c3          ret




This example shows compiling and loading a set of resources from a
file under program control.

;;;--------------------junk.cl------------

(in-package :cl-user)

(defun foo (l r)
  (declare (fixnum l r) (optimize (speed 3 safety 1 debug 1)))
  (+ l r))


(defun bar (msg)
  (format nil "Here's a message: ~A" msg))

;;;-----------------end junk.cl------------



;;;---------------------load-from.cl-----------

(in-package :cl-user)

;;; Load the function definitions (and other forms) in the file
;;; identified by FILESPEC (a pathname or a string which is a legal
;;; filespec for the underlying OS filesystem).  Compile the file
;;; before loading it.
;;;
;;; WHEN-UNDEFINED indicates a level of conditionality for compiling
;;; and loading the file.  If not given, or explicitly set to NIL,
;;; unconditionally compile and load the file.
;;;
;;; If given, it must be a list of function names, which are tested to
;;; see if they are currently defined.  If _none_ of them are, then
;;; compile and load the file.
;;;
;;; NOTE: no current provision for checking to see if the definitions
;;; in the file are of a later time stamp than the current existing
;;; function definitions (which could be used to conditionally compile
;;; and load when definitions are superceded).
;;;
;;; Errors and serious conditions are handled by sending a message on
;;; the condition to the standard error stream.
;;;
;;; Returns t if file is successfully compiled and loaded, :noaction
;;; if no action is taken (see above), :error if an error is signaled
;;; or :serious if a serious condition is signaled.
;;;
(defun load-from (filespec &key (when-undefined nil))
  (assert (listp when-undefined))
  (handler-case
   (if (or (eql when-undefined nil)
	   (reduce #'(lambda (x y)
		       (and x (not (fboundp y))))
		   when-undefined :initial-value t))
       (load (compile-file filespec))
     :noaction)
   
   ;; Exceptions
   ;;
   (error (condition)
     (format *error-output* "LOAD-FROM crashed with ~S" condition)
     :error)
   (serious-condition (condition)
     (format *error-output* "LOAD-FROM questionable: ~S" condition)
     :serious)))
;;;-----------------end load-from.cl-----------


;;; Load the previously compiled load-from object

CL-USER(1): (load "load-from")
; Fast loading load-from.fasl
T

CL-USER(2): (foo 1 2)
Error: attempt to call `FOO' which is an undefined function.
  [condition type: UNDEFINED-FUNCTION]

CL-USER(4): (fboundp 'foo)
NIL

foo is undefined...


CL-USER(5): (load-from "./junk.cl" :when-undefined '(load-from))
:NOACTION

Since load-from is already defined, this does nothing per the spec.


CL-USER(6): (load-from "./junk.cl" :when-undefined '(foo bar))
;;; Compiling file ./junk.cl
;;; Writing fasl file ./junk.fasl
;;; Fasl write complete
; Fast loading /opt/GoldenThread/ExampleApps/ECDemo/junk.fasl
T


CL-USER(7): (foo 1 2)
3
CL-USER(8): (bar "Hello world!")
"Here's a message: Hello world!"



> Do you mean "interpreted from source"

No, as this is an implementation issue.


> Or "interpreted from some intermediate byte code", like most Visual
> Basic, Lisp implementations, Java, C#, etc?

No, as this is an implementation issue.

BTW, _most_ Lisp implementations have _native compilers_.  Some (e.g.,
CMUCL) _only_ have native compilers - no interpreter at all.

> Or something else?

Yes, as described above.


> All interpreters make the job of adding random code at run-time much
> easier.

Actually, this only seems to be true; with fully compiled versions
_this aspect_ is just as easy.  The hard part, of course, is still the
bits that make up the difference between a compiler and interpreter.


/Jon


[1] The ANSI Common Lisp specification
    http://www.lispworks.com/reference/HyperSpec/Front/index.htm
    requires a compiler, though not necessarily a native code
    generator.

    I'm much more familiar with Common Lisp than Smalltalk, but
    VisualWorks, Squeak, and VisualAge all have JIT compilers.

    Python offers some of this as well, but the "definition/reference
    implementations" are interpreted.

[2] There are several types of basic block structures where CL can
    perform better than such C code.



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: load and use a ".o" file?
  2003-12-27 22:55               ` Jon S. Anthony
@ 2003-12-28  3:28                 ` Stephen Leake
  2003-12-28 16:14                   ` Georg Bauhaus
  2003-12-29 22:42                   ` Jon S. Anthony
  0 siblings, 2 replies; 29+ messages in thread
From: Stephen Leake @ 2003-12-28  3:28 UTC (permalink / raw)
  To: comp.lang.ada

j-anthony@rcn.com (Jon S. Anthony) writes:

> Stephen Leake <stephen_leake@acm.org> writes:
> 
> > j-anthony@rcn.com (Jon S. Anthony) writes:
> > 
> > > This sort of thing is perfectly reasonable and something that is
> > > extremely useful in a wide range of applications.
> > > 
> > > What I don't understand is why people don't just use technology that
> > > has solved this problem since "for ever".  No, dll's and so's are not
> > > the answer - they are intended to solve a different (related) problem
> > > and are at best a poor mans hack for what you are talking about.
> > > 
> > > What you really "need"[1] here is a true dynamic language.
> > 
> > Ok, I'll bite. What's a "true dynamic language"? 
> 
> It is true that many folks will/do have different ideas about what
> "true dynamic language" means.  In this respect I fear it is a bit
> like "true object oriented language".

That's why I asked :).

> I think most people in the "dynamic community" would say you need at
> least the following characteristics to be "truly dynamic":
> 
> 1. Dynamic typing.  This is, strong typing on _objects_ as
>    differentiated from "variables/locations".

Ok. I don't think that impacts on the issue of adding new code at runtime.

> 2. Complete introspection of the language's computation and type
> model. This is directly and explicitly available at the level of the
> programmer (not just the implementer). NOTE: This does _not_ mean or
> imply access to the underlying _implementation_.
> 
>    Some things this _does_ imply:
> 
>    * New function objects may be added to a running system at any time
>      and existing functions may be so modified at any time.

Hmm. The English meaning of "introspection" is "to examine oneself";
that's not the same as creating new code. But you get to use the term
the way you want to ...

>    * The ability to create new types and/or classes at runtime;
>    modify existing classes (with complete instance migration).
> 
> 
> A couple examples which fully have this would be Common Lisp and
> Smalltalk.  Neither are "interpreter" based[1].  Most Common Lisp
> implementations have optimizing native compilers that typically
> produce code within about 1.5-2.5 of well crafted C code[2].  

Hmm. Do those compiled versions include the ability to create new code
at runtime, where the new code is also compiled, not interpreted? I'd
be very surprised if that were true (I have not used a system where
that is true, but I have used only a couple Lisps, and no Smalltalks).
If it is true, what is the linking mechanism used?

> <snip> Here are a couple very simple examples concerning the issue
> at hand of the OP. These are done in Allegro Common Lisp at the REPL
> (read eval print loop), typically this sort of interaction would be
> through the IDE.
> 
> CL-USER(1):
>  (defun foo (l r)
>    (declare (fixnum l r) (optimize (speed 3 safety 1 debug 1)))
>    (+ l r))
> => FOO
> 
> CL-USER(2): (compile 'foo)
> => FOO
> 
> CL-USER(3): (disassemble 'foo) ; Just to show we are native (on Intel...)
> ;; disassembly of #<Function FOO>
> ;; formals: L R
> 
> ;; code start: #x7140a65c:
>    0: 83 f9 02    cmpl	ecx,$2
>    3: 74 02       jz	7
>    5: cd 61       int	$97             ; EXCL::TRAP-ARGERR
>    7: 80 7f 97 00 cmpb	[edi-105],$0    ; SYS::C_INTERRUPT
>   11: 74 02       jz	15
>   13: cd 64       int	$100            ; EXCL::TRAP-SIGNAL-HIT
>   15: 03 c2       addl	eax,edx
>   17: f8          clc
>   18: 8b 75 fc    movl	esi,[ebp-4]
>   21: c3          ret

Hmm. You don't actually demonstrate calling foo, but I'll grant you
that :).

Ok, I stand corrected. Interpretation is not necessary for dynamically
generated and linked code.

But I'd still like to understand what the linking process implied by
(compile 'foo). As far as I can see, it must do the equivalent of
Windows DLL or Unix so. Just because that mechanism is hidden from the
user (as it should be) doesn't mean it isn't there!

That was the OP's question; how to get dynamically generated code
linked in to a running program. Just saying "use CL" doesn't explain
the mechanism.

-- 
-- Stephe




^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: load and use a ".o" file?
  2003-12-28  3:28                 ` Stephen Leake
@ 2003-12-28 16:14                   ` Georg Bauhaus
  2003-12-29 22:45                     ` Jon S. Anthony
  2003-12-29 22:42                   ` Jon S. Anthony
  1 sibling, 1 reply; 29+ messages in thread
From: Georg Bauhaus @ 2003-12-28 16:14 UTC (permalink / raw)


Stephen Leake <stephen_leake@acm.org> wrote:
: Hmm. Do those compiled versions include the ability to create new code
: at runtime, where the new code is also compiled, not interpreted?

If I have understood Jon correctly, there are Lisp compilers without
an interpreter, and with the ability to load compiled code, so
I'd guess, yes. (I think I've seen the thing, too.)

For SNOBOL4, a minimal RE(P)L which runs the compiler at
run time is

read                        :<code(input ' :(read)')>
end

SPITBOL is a "true" SNOBOL4 compiler afaik, so it might offer
the same capability[*]. (If you are interested,
the :<...>  triggers a jump to the beginning of ..., which is compiled
code() from ``input ' :(read)'''; input reads what you
type, ' :(read)' is an unconditional jump to label 'read',
appended to every such input.)

 [*]From the SPITBOL description at www.snobol4.com:
"New program fragments can be compiled during
program execution...
For very complex problems, your program can "evovle" and
modify itself during execution in response to the data it is
processing. New patterns can be built during execution."



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: load and use a ".o" file?
  2003-12-28  3:28                 ` Stephen Leake
  2003-12-28 16:14                   ` Georg Bauhaus
@ 2003-12-29 22:42                   ` Jon S. Anthony
  2003-12-30 15:17                     ` lifetime n00b
  2003-12-30 16:56                     ` Stephen Leake
  1 sibling, 2 replies; 29+ messages in thread
From: Jon S. Anthony @ 2003-12-29 22:42 UTC (permalink / raw)


Stephen Leake <stephen_leake@acm.org> writes:

> (Jon S. Anthony) writes:
> 
> > Stephen Leake <stephen_leake@acm.org> writes:
> > 
> > >  (Jon S. Anthony) writes:
...

> > I think most people in the "dynamic community" would say you need at
> > least the following characteristics to be "truly dynamic":
> > 
> > 1. Dynamic typing.  This is, strong typing on _objects_ as
> >    differentiated from "variables/locations".
> 
> Ok. I don't think that impacts on the issue of adding new code at runtime.

Actually it does, but in non obvious ways.  For this discussion, it is
safe to ignore it.

> > 2. Complete introspection of the language's computation and type
> > model. This is directly and explicitly available at the level of the
> > programmer (not just the implementer). NOTE: This does _not_ mean or
> > imply access to the underlying _implementation_.
> > 
> >    Some things this _does_ imply:
> > 
> >    * New function objects may be added to a running system at any time
> >      and existing functions may be so modified at any time.
> 
> Hmm. The English meaning of "introspection" is "to examine oneself";
> that's not the same as creating new code. But you get to use the term
> the way you want to ...

Fair enough; while the explicit addition of "self modifying" would be
clearer for c.l.a, I believe that is taken for granted in the "dynamic
community".  It is not always easy to clearly change gears in usenet
discussions...

> >    * The ability to create new types and/or classes at runtime;
> >    modify existing classes (with complete instance migration).
> > 
> > 
> > A couple examples which fully have this would be Common Lisp and
> > Smalltalk.  Neither are "interpreter" based[1].  Most Common Lisp
> > implementations have optimizing native compilers that typically
> > produce code within about 1.5-2.5 of well crafted C code[2].  
> 
> Hmm. Do those compiled versions include the ability to create new code
> at runtime, where the new code is also compiled, not interpreted?

Yes.

> I'd be very surprised if that were true (I have not used a system
> where that is true, but I have used only a couple Lisps, and no
> Smalltalks).  If it is true, what is the linking mechanism used?

It is a pleasent surprise, I hope.  The "linking" mechanism is simply
resolution on a symbol's function slot.  This is part of the
introspective aspect of a Lisp system.  The native code is "just"
placed in a code vector.


> > CL-USER(1):
> >  (defun foo (l r)
> >    (declare (fixnum l r) (optimize (speed 3 safety 1 debug 1)))
> >    (+ l r))
> > => FOO
> > 
> > CL-USER(2): (compile 'foo)
> > => FOO
> > 
> > CL-USER(3): (disassemble 'foo) ; Just to show we are native (on Intel...)
> > ;; disassembly of #<Function FOO>
> > ;; formals: L R
> > 
> > ;; code start: #x7140a65c:
> >    0: 83 f9 02    cmpl	ecx,$2
> >    3: 74 02       jz	7
> >    5: cd 61       int	$97             ; EXCL::TRAP-ARGERR
> >    7: 80 7f 97 00 cmpb	[edi-105],$0    ; SYS::C_INTERRUPT
> >   11: 74 02       jz	15
> >   13: cd 64       int	$100            ; EXCL::TRAP-SIGNAL-HIT
> >   15: 03 c2       addl	eax,edx
> >   17: f8          clc
> >   18: 8b 75 fc    movl	esi,[ebp-4]
> >   21: c3          ret
> 
> Hmm. You don't actually demonstrate calling foo, but I'll grant you
> that :).

That was a little further below in the example which compiles and
loads foo from a file.


> But I'd still like to understand what the linking process implied by
> (compile 'foo). As far as I can see, it must do the equivalent of
> Windows DLL or Unix so.

No, this is part of the underlying introspective environment.  It is
actually much simpler than the contortions involved in DLL/so type
stuff.  It is also fine grained - a function at a time or even a
functions symbol at a time.

> Just because that mechanism is hidden from the user (as it should
> be) doesn't mean it isn't there!

Yes, it is there, and you can even get at the important user
(programmer) level bits yourself.  Here is a few interactions after
the compile and load of the junk.cl file:

CL-USER(18): (inspect 'bar)
The symbol BAR @ #x7140990f
  which is an INTERNAL symbol in the COMMON-LISP-USER package
   0 type ---------> Bit field: #x07
   1 flags --------> Bit field: #x00
   2 hash ---------> Bit field: #x61d7
   3 value --------> ..unbound..
   4 package ------> The COMMON-LISP-USER package
   5 function -----> #<Function BAR>
   6 name ---------> A simple-string (3) "BAR"
   7 plist --------> <...>, a proper list with 2 elements
[1i] CL-USER(19): (symbol-function 'bar)
#<Function BAR>
[1i] CL-USER(20): (symbol-function 'my-new-foo)
Error: Symbol MY-NEW-FOO does not have a function definition.
  [condition type: SIMPLE-ERROR]

Restart actions (select using :continue):
 0: Return to Debug Level 1 (an "abort" restart).
 1: Return to Top Level (an "abort" restart).
 2: Abort entirely from this process.
[2] CL-USER(21): :cont 0
[1i] CL-USER(22): :i q ; get out of the inspection of 'bar
BAR
CL-USER(23): (defun my-new-foo (x) x) ; == cl:identity function

MY-NEW-FOO
CL-USER(24): (symbol-function 'my-new-foo)
#<Interpreted Function MY-NEW-FOO>
CL-USER(25): (compile 'my-new-foo)
MY-NEW-FOO
NIL
NIL
CL-USER(26): (symbol-function 'my-new-foo)
#<Function MY-NEW-FOO>
CL-USER(27): (disassemble 'my-new-foo)
;; disassembly of #<Function MY-NEW-FOO>
;; formals: X

;; code start: #x714242c4:
   0: 83 f9 01    cmpl	ecx,$1
   3: 74 02       jz	7
   5: cd 61       int	$97             ; EXCL::TRAP-ARGERR
   7: 80 7f 97 00 cmpb	[edi-105],$0    ; SYS::C_INTERRUPT
  11: 74 02       jz	15
  13: cd 64       int	$100            ; EXCL::TRAP-SIGNAL-HIT
  15: f8          clc
  16: 8b 75 fc    movl	esi,[ebp-4]
  19: c3          ret
CL-USER(28): (my-new-foo (list 1 2 3))
(1 2 3)
CL-USER(29): 
CL-USER(33): (inspect 'my-new-foo)
The symbol MY-NEW-FOO @ #x714221d7
  which is an INTERNAL symbol in the COMMON-LISP-USER package
   0 type ---------> Bit field: #x07
   1 flags --------> Bit field: #x00
   2 hash ---------> Bit field: #xb1bc
   3 value --------> ..unbound..
   4 package ------> The COMMON-LISP-USER package
   5 function -----> #<Function MY-NEW-FOO>
   6 name ---------> A simple-string (10) "MY-NEW-FOO"
   7 plist --------> (EXCL::.ARGS. NIL), a proper list with 2 elements
[1i] CL-USER(34): :i 5 ; let's look into the function slot
#<Function MY-NEW-FOO>
  lambda-list: (X)
   0 excl-type ----> Bit field: #x08
   1 flags --------> Bit field: #xa8
   2 start --------> Bit field: #x714242c4
   3 hash ---------> Bit field: #x00005b4c
   4 symdef -------> The symbol MY-NEW-FOO
   5 code ---------> simple CODE vector (14) = #(63875 29697 52482...)
   6 formals ------> (X), a proper list with 1 element
   7 cframe-size --> fixnum 0 [#x00000000]
   8 immed-args ---> fixnum 0 [#x00000000]
   9 locals -------> fixnum 0 [#x00000000]
[1i] CL-USER(35): :i 5 ; let's look at the code vector
A simple CODE vector (14) @ #x714242d2
   0-> The field #xf983
   1-> The field #x7401
   2-> The field #xcd02
   3-> The field #x8061
   4-> The field #x977f
   5-> The field #x7400
   6-> The field #xcd02
   7-> The field #xf864
   8-> The field #x758b
   9-> The field #xc3fc
  10-> The field #x0000
  11-> The field #x0000
  12-> The field #x0000
  13-> The field #x0000
[1i] CL-USER(36): :i q ; get out of 'my-new-foo inspection
MY-NEW-FOO
CL-USER(38): 


> That was the OP's question; how to get dynamically generated code
> linked in to a running program. Just saying "use CL" doesn't explain
> the mechanism.

In CL you don't need an explaination of the mechanism unless you are
_implementing_ a Common Lisp.  For the user, you don't need to do
anything other than (compile-file ...) (load ...) to get all the
resources in native compiled form "linked" in and ready to use.  Or
for interactive work, just (compile 'your-foo-here).  That's it.  A
pleasent thing indeed.


/Jon




^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: load and use a ".o" file?
  2003-12-28 16:14                   ` Georg Bauhaus
@ 2003-12-29 22:45                     ` Jon S. Anthony
  0 siblings, 0 replies; 29+ messages in thread
From: Jon S. Anthony @ 2003-12-29 22:45 UTC (permalink / raw)


Georg Bauhaus <sb463ba@l1-hrz.uni-duisburg.de> writes:

> Stephen Leake <stephen_leake@acm.org> wrote:
> : Hmm. Do those compiled versions include the ability to create new code
> : at runtime, where the new code is also compiled, not interpreted?
> 
> If I have understood Jon correctly, there are Lisp compilers without
> an interpreter, and with the ability to load compiled code, so
> I'd guess, yes.

Yes.  Though also having an interpreter as part of the implementation
does not change this (it's orthogonal to the discussion).

> (I think I've seen the thing, too.)

Most do this, so you probably did :-)

/Jon



^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: load and use a ".o" file?
  2003-12-29 22:42                   ` Jon S. Anthony
@ 2003-12-30 15:17                     ` lifetime n00b
  2003-12-30 16:56                     ` Stephen Leake
  1 sibling, 0 replies; 29+ messages in thread
From: lifetime n00b @ 2003-12-30 15:17 UTC (permalink / raw)


Jon S. Anthony wrote:

> In CL you don't need an explaination of the mechanism unless you are
> _implementing_ a Common Lisp.  For the user, you don't need to do
> anything other than (compile-file ...) (load ...) to get all the
> resources in native compiled form "linked" in and ready to use.  Or
> for interactive work, just (compile 'your-foo-here).  That's it.  A
> pleasent thing indeed.

See, I just *knew* this was going to turn out more difficult than it 
sounded! :-) First let me say I am not trying to build a complete 
"Common Lisp" implementation, at least not yet. Common Lisp is similar 
to Ada in that both language definitions are very rich and include many 
"libraries" as part of the definition itself that other languages have 
to add on as third party packages. However, one of the nicest features 
of Lisp is that the fundamental syntax of the language is extremely 
elegant and simple.

Right now, it's just this elegant and simple core that I am trying to 
implement, using gnat as the machine-code compiler. It's like a Siren, 
calling me into the deep waters. "Look how beautiful I am! Of course you 
can obtain me, just come a little closer..."

Once I have this core actually working, maybe then I can begin to think 
in terms of adding the myriad functions and operators that make up the 
rest of the Common Lisp definition. And I realize that (compile ...) and 
(load ...) are not part of the core syntax but rather part of the 
"extras" that make up a complete Common Lisp. However, without these, 
there is not much point in continuing on, since the whole point of using 
gnat as the compiler is in the context of these functions.




^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: load and use a ".o" file?
  2003-12-29 22:42                   ` Jon S. Anthony
  2003-12-30 15:17                     ` lifetime n00b
@ 2003-12-30 16:56                     ` Stephen Leake
  1 sibling, 0 replies; 29+ messages in thread
From: Stephen Leake @ 2003-12-30 16:56 UTC (permalink / raw)
  To: comp.lang.ada

j-anthony@rcn.com (Jon S. Anthony) writes:

> Stephen Leake <stephen_leake@acm.org> writes:
> 
> > But I'd still like to understand what the linking process implied by
> > (compile 'foo). As far as I can see, it must do the equivalent of
> > Windows DLL or Unix so.
> 
> No, this is part of the underlying introspective environment.  It is
> actually much simpler than the contortions involved in DLL/so type
> stuff.  It is also fine grained - a function at a time or even a
> functions symbol at a time.

Well, ok. I don't have a DLL manual handy. Fine-grained would be nice.

Maybe sometime I'll find the time to read up on Lisp implementations.

I suspect lambda binding, which is very dynamic, actually simplifies
the issue of dynamic code loading.

> In CL you don't need an explaination of the mechanism unless you are
> _implementing_ a Common Lisp.  

Ok. I'm interested in the implementation details.

> For the user, you don't need to do anything other than (compile-file
> ...) (load ...) to get all the resources in native compiled form
> "linked" in and ready to use. Or for interactive work, just (compile
> 'your-foo-here). That's it. A pleasent thing indeed.

Right. In VxWorks, you get almost the same convenience, except you
have to do the compile on the host, and execute on the target.

-- 
-- Stephe




^ permalink raw reply	[flat|nested] 29+ messages in thread

end of thread, other threads:[~2003-12-30 16:56 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-12-18 23:31 load and use a ".o" file? lifetime n00b
2003-12-18 23:59 ` Stephen Leake
2003-12-19  1:51 ` tmoran
2003-12-19 15:28   ` lifetime n00b
2003-12-19 18:08     ` Stephen Leake
2003-12-20 20:12       ` lifetime n00b
2003-12-20 21:15         ` tmoran
2003-12-20 23:41           ` lifetime n00b
2003-12-21  7:15             ` tmoran
2003-12-21 11:46         ` Simon Wright
2003-12-21 13:57         ` Stephen Leake
2003-12-22 19:29           ` lifetime n00b
2003-12-22 20:49           ` Jon S. Anthony
2003-12-22 23:15             ` Stephen Leake
2003-12-23  1:36               ` tmoran
2003-12-27 22:55               ` Jon S. Anthony
2003-12-28  3:28                 ` Stephen Leake
2003-12-28 16:14                   ` Georg Bauhaus
2003-12-29 22:45                     ` Jon S. Anthony
2003-12-29 22:42                   ` Jon S. Anthony
2003-12-30 15:17                     ` lifetime n00b
2003-12-30 16:56                     ` Stephen Leake
2003-12-22 15:50         ` Mark H Johnson
2003-12-22 19:46           ` lifetime n00b
2003-12-22 22:58             ` Mark H Johnson
2003-12-23 17:48               ` Robert I. Eachus
2003-12-23 17:59                 ` Mark H Johnson
2003-12-23 21:53                   ` Robert I. Eachus
2003-12-19 21:28     ` Simon Wright

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox