Pliant forum message

Concerning release: 32
Subject: Questions
Title: tail recursions and external global variables
initial message posted by John Eikenberry on 2000/02/29 15:15:30
2 questions:

1. Does pliant optimize tail recursion for memory use (ie. does it free the
   memory as it goes along)? Based on some simple tests, it doesn't look like
   it. Is this an example of an optimization that can be done via the 
   meta-programming? If so I may give it a whirl... though any help would
   be appreciated, as it would be my first real foray into meta-programming.

2. Is there any special syntax for accessing a global variable in an external
   C library. The slang library keeps the terminal's rows and columns in
   global variables (SLtt_Screen_Rows and SLtt_Screen_Cols) and there are
   no functions for accessing them. I tried a couple of naive things (like
   treating it as a function) with no luck.

Thanks.
answer posted by Hubert Tonneau on 2000/02/29 16:52:51
> Is there any special syntax for accessing a global variable in an external
> C library.

No.
The C function used to get the address of a function in a dynamicly loaded
library is 'external_function_address' in module
/pliant/language/os/dll.c
but it's a Pliant compiler private function not available at Pliant level.
Maybe it should.

> I tried a couple of naive things (like  treating it as a function) with no
> luck.

This is exactly what I would do, but then, the address of the variable is
the address of the executable part of the function.
Try something like:

function foo
  external "..." "..."

gvar Pointer:t external_int :> (the_function foo):executable map t

where 't' is the type of the variable you want to map.
Be warned that even if it works for you, this is not enough since the
address of the global variable may change from a run to the other, so
you should also add a 'DelayedAction' in 'pliant_restore_actions' list
in order to update the pointer each time your module is loaded with
a .dump file rather than being compiled.
answer posted by Hubert Tonneau on 2000/02/29 17:54:08
> Does pliant optimize tail recursion for memory use (ie. does it free the
> memory as it goes along)? Based on some simple tests, it doesn't look like
> it.

Pliant code generator currently does not perform any sophisticated
optimisations.
The most important ones to add are:
- evaluating only once commun sub expressions.
- moving outside the loop computations that are constant for all laps.
- better local variables -> processor registers assignment.
- floating point optimisations.

I may write a sample optimizer (that would for example replace any
x*2 operation with x+x) if it can help you start with, just as I did for
Gordon with the parser, but the real problem is that we need somebody
that will spend time on the code generator, because I have not enough
time to write all required algorithms in order to turn it to a state
of the art code generator.
It's currently the biggest problem with Pliant, because on the language
side, I assert that, even with the potencial remaining design flows, we
already are ahead of anything else, and design flows are rapidely
decreasing due to the very good feed back I get from the forum, so freeze
time will also come soon, but on the code generator side, things improved
much last summer since I completely rewrote and debugged the code generator,
but since then, nothing append.
The need for extending GCC interface so that the low level part of
the Pliant compiler be written in Pliant (see Ben requests for a better
Pliant -> C translation), then translated from Pliant to C by Pliant, so
that we get rid of chicken and eggs problem in the low level parts of the
PDEE is also an unassigned task.
I will cover extending Pliant to a full feature development tool
through introducing the database server, and the graphical toolkit,
because it's what is required for my compagny needs, and as far as they
are paying me, their needs will be covered first. So the main trouble is
that, I have not enough ressources to cover everything so what I basicaly
expect is to have some external peoples focus on uncovered aspects. Providing
them support will not be a big deal ... if I can expect usable results.
answer posted by John Eikenberry on 2000/03/01 02:06:41
> The C function used to get the address of a function in a dynamicly loaded
> library is 'external_function_address' in module
> /pliant/language/os/dll.c
> but it's a Pliant compiler private function not available at Pliant level.
> Maybe it should.

Well, I guess I'd like it to be. Personally I think using global variables
in this way is a bad design decision, but it seems the standard way to do this 
(both slang and ncurses handle column and row data this way). 

If you'd like you could just give me a patch or tell me how to make it public
and I can test it before you put it in a release.

BTW, when I try to use the function trick I  get an error:

--- code snip---
function sltt_screen_rows
  external "libslang.so.1" "SLtt_Screen_Rows"

gvar Pointer:Int rows :> (the_function sltt_screen_rows):executable map Int
---

Failed to compile the_function   ('sltt_screen_rows')
  compile file:slang.pli (internals) 56 27
  etc...
(line 56 is the gvar line above, col 27 is the 't' in the_function)

Oh... and the SLtt_Screen_Rows is defined in slang.h as: 
extern int SLtt_Screen_Rows;
answer posted by John Eikenberry on 2000/03/01 02:24:32
> I may write a sample optimizer (that would for example replace any
> x*2 operation with x+x) if it can help you start with

This would definatly help if I try to do this. Also, pointers to some good 
examples of memory handling in pliant would be helpful.

If I'm successful in figuring this out, I may take a shot at a couple of the 
others on your list. Though I'm sure my first versions will likely suck, and 
it may take a while for me to produce anything usable in the main release.
answer posted by Hubert Tonneau on 2000/03/01 02:52:30
This sample code worked for me (you probably simply forgot to include
the compiler.pli module):

module "/pliant/language/compiler.pli"

function sltt_screen_rows
  external "libslang.so.1" "SLtt_Screen_Rows"

gvar Pointer:Int rows :> (the_function sltt_screen_rows):executable map Int
console rows eol
answer posted by John Eikenberry on 2000/03/01 03:09:52
Yes, I am an idiot... :P

Thanks.
answer posted by John Eikenberry on 2000/03/03 13:37:07
>> The C function used to get the address of a function in a dynamicly loaded
>> library is 'external_function_address' in module
>> /pliant/language/os/dll.c
>> but it's a Pliant compiler private function not available at Pliant level.
>> Maybe it should.

> Well, I guess I'd like it to be. Personally I think using global variables
> in this way is a bad design decision, but it seems the standard way to do this 
> (both slang and ncurses handle column and row data this way). 

I really think I'd like 'external_function_address' to be made public. I just 
finished doing a basic wrapper around the slang library. I wrapped around 60 
functions and 6 global variables... and the 6 global variables make up around 
1/4 of the lines of code in the module.

If making 'external_function_address' public would reduce this, it would suite 
me much more. I mean it doesn't seem to be really a functionality issue, but 
more of an aesthetic one. Pliant's C interface is so clean, I hate to pollute 
it with complications just for global variables.

Thanks as always.
answer posted by Hubert Tonneau on 2000/03/03 19:11:40
> I really think I'd like 'external_function_address' to be made public. I just 
> finished doing a basic wrapper around the slang library. I wrapped around 60 
> functions and 6 global variables... and the 6 global variables make up around 
> 1/4 of the lines of code in the module.

This is a bit too simple.

The 'external_function_address' in the C code does only half of the job.
Let's say that in a module 'foo.pli' you have defined a function 'foo'
that is mapping an external function from dll 'foo.so'
Now let's assume you also have built a .dump file including the 'foo.pli'
module.
When you restart your program and get the .dump file loaded back, there
is also the function 'restore_externals' in /pliant/language/basic/extend.c
which is called and will translate any call to 'foo' in any other function
to a call to the new 'foo' address because IT MAY WELL HAVE CHANGED.

This is done transparently for external functions, so you don't have to
care about, but if you map external variables, you have to record a
DelayedAction in 'pliant_restore_actions' list that will update the
pointer to the external variable.

So, the conclusion is that you have to define a 'evar' meta function
that will do the all thing so that then, mapping an external variable
be as strait forward as mapping an external function.