FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Don's Compile-time Symbol Mangler
Goto page Previous  1, 2, 3  Next
 
Post new topic   Reply to topic     Forum Index -> DDL - D Dynamic Libraries
View previous topic :: View next topic  
Author Message
kris



Joined: 27 Mar 2004
Posts: 1494
Location: South Pacific

PostPosted: Mon Dec 05, 2005 11:45 am    Post subject: Re: Update for DMD 0.141 Reply with quote

pragma wrote:
Don Clugston wrote:
Here's the COMPLETE code, updated for the fantastic new .mangleof keyword from DMD 0.141. This code works with any type.
Except...
now there are more possibilities!
We could also have, for example:

auto addfunc = m.loadFunc!(uint function (uint, uint), "test.testmodule.add")();

which is maybe not superior, but is interesting because (a) it requires much less duplication in the mangling code (you would not need overloads for each set of parameters), and (b) allows you to specify the calling convention seperately for each function (although this could be done easily enough).


I like the new form that you propose as it would appear to eliminate the need for separate methods for fields and functions: is this still the case? At the very least, I can do away with the zillion or so template overloads to accomodate up to n function parameters.

Anyway its way more clear as it now reads "Get me a symbol of this type with this name". Great stuff.

I like that form also. Especially if it eliminates the N parameter problem, and supports different calling conventions at the same time Shocked
Back to top
View user's profile Send private message
JJR



Joined: 22 Feb 2004
Posts: 1104

PostPosted: Mon Dec 05, 2005 4:02 pm    Post subject: Reply with quote

Looking good! Very good! Now if only .mangleof would do a little more...
Back to top
View user's profile Send private message
Don Clugston



Joined: 05 Oct 2005
Posts: 91
Location: Germany (expat Australian)

PostPosted: Tue Dec 06, 2005 2:00 am    Post subject: Two more ways... Reply with quote

I couldn't quite get the previous method to work. But here's one I like better. Interestingly, this should also work for variables as well as functions (you just need to declare a pointer to a variable).

The other thing that I like about this one, is that it's closer to a traditional header file. The "addfunc" declarations could be automatically generated from the lib or obj file, using one of those tools you made.

I wonder if it could even be possible to combine the name into the declaration somehow. I think the ideal would be something like:
Code:

// autogenerated header file:
Declare!(uint function(uint, uint), "test.testmodule.add") addfunc;

// user code:
int main()
{
   m.load!(addfunc)();
   return addfunc(20, 30);
}

Not sure if that is actually possible, but I'm not yet convinced that it is not.

But anyway, the one below works.

Code:
// Aargh, I need to bring this back as a compiler workaround.
template strlen(char [] str)
{
  const int strlen = str.length;
}

// in class Module

template load(alias f, char [] name) {
  void load() {
  // mangleof(function pointer) gives a "P" at the start of the mangled name,
  // which we need to remove
   f = cast(typeof(f)) LoadExport("_D" ~
   mangleText!(name) ~ slice!(f.mangleof, 1, strlen!(f.mangleof)) ); }
}


// Note, this must be a static variable
uint function(uint, uint) addfunc;

int main()
{
  auto m = LoadModule("testmodule.obj");
  m.load!(addfunc, "test.testmodule.add")();

 return addfunc(35, 20);
}
Back to top
View user's profile Send private message
pragma



Joined: 28 May 2004
Posts: 607
Location: Washington, DC

PostPosted: Tue Dec 06, 2005 8:17 am    Post subject: Re: Two more ways... Reply with quote

Don Clugston wrote:
I couldn't quite get the previous method to work. But here's one I like better. Interestingly, this should also work for variables as well as functions (you just need to declare a pointer to a variable).

The other thing that I like about this one, is that it's closer to a traditional header file. The "addfunc" declarations could be automatically generated from the lib or obj file, using one of those tools you made.

I wonder if it could even be possible to combine the name into the declaration somehow. I think the ideal would be something like:
Code:

// autogenerated header file:
Declare!(uint function(uint, uint), "test.testmodule.add") addfunc;

// user code:
int main()
{
   m.load!(addfunc)();
   return addfunc(20, 30);
}

Not sure if that is actually possible, but I'm not yet convinced that it is not.


Hrm... we have several use patterns to work with now, I guess the only thing left to do is integrate them all and support the lot with a few good tutorials. I can see where its merely a matter a style that would lead the developer to one or the other. BTW, I kind of like being able to do this simply becuase it decouples the name-mangling from the loading process: there are plenty of reasons to want to do this.

But the more straightforward "give me this ident here and now" technique has its place too.

Quote:

But anyway, the one below works.

Code:
// Aargh, I need to bring this back as a compiler workaround.
template strlen(char [] str)
{
  const int strlen = str.length;
}

// in class Module

template load(alias f, char [] name) {
  void load() {
  // mangleof(function pointer) gives a "P" at the start of the mangled name,
  // which we need to remove
   f = cast(typeof(f)) LoadExport("_D" ~
   mangleText!(name) ~ slice!(f.mangleof, 1, strlen!(f.mangleof)) ); }
}


// Note, this must be a static variable
uint function(uint, uint) addfunc;

int main()
{
  auto m = LoadModule("testmodule.obj");
  m.load!(addfunc, "test.testmodule.add")();

 return addfunc(35, 20);
}


Neat! Shame that has to be a static var instead of a typedef or type alias... or just a plain type like before.

Don, I really appreciate the work you're doing on all this. When I get the chance this week, I'll try integrating some of these template changes into the repository.
_________________
-- !Eric.t.Anderton at gmail
Back to top
View user's profile Send private message Yahoo Messenger
Don Clugston



Joined: 05 Oct 2005
Posts: 91
Location: Germany (expat Australian)

PostPosted: Tue Dec 06, 2005 9:12 am    Post subject: Reply with quote

Quote:
Neat! Shame that has to be a static var instead of a typedef or type alias... or just a plain type like before.


Well, you can do this instead:

Code:
template load(F, char [] name) {
  typeof(F) load() {
   return cast(typeof(F)) LoadExport("_D" ~
   mangleText!(name) ~ slice!(F.mangleof, 1, strlen!(F.mangleof)) ); }
}

int main()
{
:
    auto addfunc = m.load!(uint function(uint, uint), "test.testmodule.add")();
}



Yes, I recently told you that was impossible. Well, it works actually. It's probably better.
Spoilt for choice, aren't we!
I've just put in two bug reports; when fixed, we should be able to get rid of the slice!() and strlen!(). It should be just
Code:

template load(F, char [] name) {
  typeof(F) load() {
   return cast(typeof(F)) LoadExport("_D" ~   mangleText!(name) ~ F.mangleof[1 ..$] ); }
}

which makes it clear that Walter's been the one doing all the work Smile.
Back to top
View user's profile Send private message
kris



Joined: 27 Mar 2004
Posts: 1494
Location: South Pacific

PostPosted: Tue Dec 06, 2005 12:38 pm    Post subject: Reply with quote

Don Clugston wrote:
Quote:
Neat! Shame that has to be a static var instead of a typedef or type alias... or just a plain type like before.


Well, you can do this instead:

Code:
template load(F, char [] name) {
  typeof(F) load() {
   return cast(typeof(F)) LoadExport("_D" ~
   mangleText!(name) ~ slice!(F.mangleof, 1, strlen!(F.mangleof)) ); }
}

int main()
{
:
    auto addfunc = m.load!(uint function(uint, uint), "test.testmodule.add")();
}



Yes, I recently told you that was impossible. Well, it works actually. It's probably better.
Spoilt for choice, aren't we!
I've just put in two bug reports; when fixed, we should be able to get rid of the slice!() and strlen!(). It should be just
Code:

template load(F, char [] name) {
  typeof(F) load() {
   return cast(typeof(F)) LoadExport("_D" ~   mangleText!(name) ~ F.mangleof[1 ..$] ); }
}

which makes it clear that Walter's been the one doing all the work Smile.

Awesome! This is getting better and better Shocked
Back to top
View user's profile Send private message
pragma



Joined: 28 May 2004
Posts: 607
Location: Washington, DC

PostPosted: Wed Dec 07, 2005 10:00 pm    Post subject: Tweaked Reply with quote

I had to make a little adjustment:

Code:
template mangleTest(T, char [] name) {
   char[] mangleTest() {
      static if(T.mangleof[0] == 'P'){
         return "_D" ~  mangleText!(name) ~ slice!(T.mangleof, 1, strlen!(T.mangleof));
      }
      else{
         return "_D" ~  mangleText!(name) ~ T.mangleof;
      }
   }
}

alias void function(int,char) T;
alias T* TP;

void main(){
   writefln("?s",mangleTest!(void function(int,char),"simple.function"));
   writefln("?s",mangleTest!(T,"type.alias"));
   writefln("?s",mangleTest!(TP,"type.alias.ptr"));
   writefln("?s",mangleTest!(int,"int.field"));   
}


Output:
Code:
_D6simple8functionFiaZv
_D4type5aliasFiaZv
_D4type5alias3ptrPFiaZv
_D3int5fieldi


The problem was that slicing the first char off the mangled name was "decapitating" perfectly innocent types like "int" or "char[]". This version only removes a preceeding "P" for any type that is passed.

The result is that you must add an extra level of indirection if you want to actually retrieve a pointer type from the module. While this may seem somewhat inconsistent across all types, it *is* consistent for all pointer types.

Thoughts?
_________________
-- !Eric.t.Anderton at gmail
Back to top
View user's profile Send private message Yahoo Messenger
Don Clugston



Joined: 05 Oct 2005
Posts: 91
Location: Germany (expat Australian)

PostPosted: Thu Dec 08, 2005 1:45 am    Post subject: Reply with quote

Right.
In the non-pointer case, you'll also need to add a * to the return type of load(), so that auto will work. Something like (untested):

Code:

template load(T, char [] name) {
      static if(T.mangleof[0] == 'P'){
       typeof(T) load() { return cast(typeof(T))LoadExport( "_D" ~  mangleText!(name) ~ slice!(T.mangleof, 1, strlen!(T.mangleof)));
      } else{
       typeof(T*) load() { return cast(typeof(T*))LoadExport("_D" ~  mangleText!(name) ~ T.mangleof);
      }
   }
}


Another fun situation is templates. I think we already have everything we need to link to an instance of a template:

Code:
auto addfunc = load(uint function(uint, uint), "test.add!(uint)");


but of course this will only work if the template was instantiated in the obj file. This one only requires improving the string parser to deal with ! and ().

The situation that worries me is, can we do classes? I didn't see an example of that in your code (but I didn't look very hard). The compiler is allowed to turn virtual functions into non-virtual, but does that happen at link time, or before?
Back to top
View user's profile Send private message
pragma



Joined: 28 May 2004
Posts: 607
Location: Washington, DC

PostPosted: Thu Dec 08, 2005 8:20 am    Post subject: Reply with quote

Don Clugston wrote:
Right.
In the non-pointer case, you'll also need to add a * to the return type of load(), so that auto will work. Something like (untested):

Code:

template load(T, char [] name) {
      static if(T.mangleof[0] == 'P'){
       typeof(T) load() { return cast(typeof(T))LoadExport( "_D" ~  mangleText!(name) ~ slice!(T.mangleof, 1, strlen!(T.mangleof)));
      } else{
       typeof(T*) load() { return cast(typeof(T*))LoadExport("_D" ~  mangleText!(name) ~ T.mangleof);
      }
   }
}


Cool.

Quote:
Another fun situation is templates. I think we already have everything we need to link to an instance of a template:

Code:
auto addfunc = load(uint function(uint, uint), "test.add!(uint)");


but of course this will only work if the template was instantiated in the obj file. This one only requires improving the string parser to deal with ! and ().


I'll add that to my list of things to test. FYI, I sat down to do some more aggressive tests last night and found some more OMF bugs. I'll post more on this in the status log.

Quote:
The situation that worries me is, can we do classes? I didn't see an example of that in your code (but I didn't look very hard). The compiler is allowed to turn virtual functions into non-virtual, but does that happen at link time, or before?


AFAIK, I haven't tried this but I think it's merely a matter of loading the class' ctor and calling it like a typical method as though you were masqerading as a call to 'new'.

In order to do that, you have to bind the class' TypeInfo and interrogate its size, then pass an allocated lump of memory to the ctor as the first argument -- there may be another step w/writing the vtable pointer in as well. Of course, this process would be better handled by a 'reflection' kind of lib, but there's no reason why you can't do it "manually".
_________________
-- !Eric.t.Anderton at gmail
Back to top
View user's profile Send private message Yahoo Messenger
Don Clugston



Joined: 05 Oct 2005
Posts: 91
Location: Germany (expat Australian)

PostPosted: Tue Dec 13, 2005 2:56 am    Post subject: Wonder if I should put my 'meta' library in here? Reply with quote

I'd really like to clean up the name-mangling code, and prevent code duplication.

All of my metaprogramming code is in a library called 'meta', which I hope will one day become a standard library, perhaps as a parallel to 'std' -- it's really fundamental stuff.

Right now, DDL is the only practical use of it. It might make sense to store it in the DDL repository temporarily, even though it doesn't belong there in the long term. Hopefully it could move straight from DDL into the standard libraries.

Thoughts?
Back to top
View user's profile Send private message
pragma



Joined: 28 May 2004
Posts: 607
Location: Washington, DC

PostPosted: Tue Dec 13, 2005 9:44 am    Post subject: Re: Wonder if I should put my 'meta' library in here? Reply with quote

Don Clugston wrote:
I'd really like to clean up the name-mangling code, and prevent code duplication.

All of my metaprogramming code is in a library called 'meta', which I hope will one day become a standard library, perhaps as a parallel to 'std' -- it's really fundamental stuff.

Right now, DDL is the only practical use of it. It might make sense to store it in the DDL repository temporarily, even though it doesn't belong there in the long term. Hopefully it could move straight from DDL into the standard libraries.

Thoughts?


I love this idea. If you're imagining an entire tree of .d files, then it should probably live under trunk/meta for right now. This should allow you to develop with impunity, without fear of crumbling anything DDL related as there's a lot of changes going on right now. Wink

When it becomes its own lib/project, then the process will change to either requiring developers to have version X of the meta lib. SDK releases will likely pre-package this along with the DDL trunk, just for ease of development.
_________________
-- !Eric.t.Anderton at gmail
Back to top
View user's profile Send private message Yahoo Messenger
pragma



Joined: 28 May 2004
Posts: 607
Location: Washington, DC

PostPosted: Sat Dec 17, 2005 4:51 pm    Post subject: Reply with quote

Status

Refactoring is moving along, although slowly.

I've moved almost all of the phobos dependent code out into Utils.d and began refactoring all the parsers into a single read/write cursor class tree -- this may take on a more Mango-ish flare later on.

The loaders have been refined to work with the LoaderRegistry scheme, and load-time binary type detection is working well.

The only util that hasn't been converted to the new scheme is the in-situ util, for no particular reason. It seems time is not on my side today.

The SVN repos is presently "dirty", so while it will compile it is largely untested in this state. If you absolutely need to use DDL during this beta phase, please see the downloads directory for the last quasi-stable beta package. Keep checking here to see what the state of things is, and when the SVN repository firms up. Smile

Compile-Time Regular Expressions

Thanks to Don's /meta library, I threw together a compile-time regular expression engine this week to try and exploit both Don's code as well as D's capability to work with string data at compile time. While it works well, it does have some limitations and could be refined far beyond its current incarnation. I am waiting for some improvements to DMD before I can make the big push to a design that I want.

Its hiding under /meta/regex.d and /meta/regexPredicate.d. Wink
_________________
-- !Eric.t.Anderton at gmail
Back to top
View user's profile Send private message Yahoo Messenger
Don Clugston



Joined: 05 Oct 2005
Posts: 91
Location: Germany (expat Australian)

PostPosted: Wed Dec 21, 2005 2:10 am    Post subject: Regexp Reply with quote

Do you have a test file for meta/regexp.d? I'd like to experiment with refactoring a few bits with code from the rest of meta, and want some confidence that I wouldn't be breaking anything.

For example, I want to see if you get simpler code when you implement atoi!() as two functions, one returning the int, the other (countLeadingDigits!() ?) returning the number of characters consumed; or is it better to have a single function with two return values?
Back to top
View user's profile Send private message
pragma



Joined: 28 May 2004
Posts: 607
Location: Washington, DC

PostPosted: Wed Dec 21, 2005 6:30 am    Post subject: Re: Regexp Reply with quote

Don Clugston wrote:
Do you have a test file for meta/regexp.d? I'd like to experiment with refactoring a few bits with code from the rest of meta, and want some confidence that I wouldn't be breaking anything.

For example, I want to see if you get simpler code when you implement atoi!() as two functions, one returning the int, the other (countLeadingDigits!() ?) returning the number of characters consumed; or is it better to have a single function with two return values?


Here's the test program I was using to develop the regex compiler:

Code:
import meta.regex;
import std.stdio;

import std.regexp;

const char[] phoneTest = `\(?\d{3}\)?([-\/\.])?\d{3}([-\/\.])?\d{4}`;
const char[] miscTest = `\w{1,5}`;
const char[] unionTest = `\d*|\d*`;
void main(){
   writefln("test: ",parseUntil!(unionTest,'|',true).consumed);
   
   // setup   
   auto staticPhoneTest = &regexMatch!(phoneTest);
   auto staticMiscTest = &regexMatch!(miscTest);
   
   auto dynamicPhoneTest = new RegExp(phoneTest,"");
   auto dyanmicMiscTest = new RegExp(miscTest,"");
   
   // test #1 (static)
   writefln("result: ?s",staticPhoneTest("(555)-123-4567"));
   writefln("result: ?s",staticMiscTest("hello world"));
   
   // test #2 (dynamic)
   writefln("result: ?s",dynamicPhoneTest.exec("(555)-123-4567"));
   writefln("result: ?s",dyanmicMiscTest.exec("hello world"));   
   
   const char[] foobar = `\w*$`;
   auto matchTest = &compileMatch!(foobar).fn;
   
   writefln("matchTest1: ?s",matchTest("asd;lkasf"));
   writefln("matchTest2: ?s",matchTest("12"));
   
   auto dynMatchTest = new RegExp(foobar,"");

   writefln("result: ?s",dynMatchTest.exec("asd;lkasf"));   
   writefln("result: ?s",dynMatchTest.exec("12"));   
}


It doesn't do much and I was hoping to get around to putting some timing code in there to drag-race it against std.regexp at some point... Anyway, feel free to tear it up.

Also, feel free to refactor things out of regex.d as you see fit. Smile
_________________
-- !Eric.t.Anderton at gmail
Back to top
View user's profile Send private message Yahoo Messenger
Don Clugston



Joined: 05 Oct 2005
Posts: 91
Location: Germany (expat Australian)

PostPosted: Mon Jan 02, 2006 4:15 am    Post subject: Demangling interface for dynamically loading classes Reply with quote

Given an interface definition:

Code:
interface ITestClass {
 void callable();
}


this is the code for creating two instances of the concrete TestClass, and then using a member function:

Code:
   
        // Constructor with one parameter: 
       // equivalent to ITestClass x = new TestClass(int);
   auto newTestClass = testLibrary.getCtor!(ITestClass, "test.testmodule.TestClass", int)();
   auto x = newTestClass(31415);
        auto y = newTestClass(58);

   // Call a member function of the interface
   x.callable();
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic     Forum Index -> DDL - D Dynamic Libraries All times are GMT - 6 Hours
Goto page Previous  1, 2, 3  Next
Page 2 of 3

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group