View previous topic :: View next topic |
Author |
Message |
kris
Joined: 27 Mar 2004 Posts: 1494 Location: South Pacific
|
Posted: Mon Dec 05, 2005 11:45 am Post subject: Re: Update for DMD 0.141 |
|
|
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 |
|
Back to top |
|
|
JJR
Joined: 22 Feb 2004 Posts: 1104
|
Posted: Mon Dec 05, 2005 4:02 pm Post subject: |
|
|
Looking good! Very good! Now if only .mangleof would do a little more... |
|
Back to top |
|
|
Don Clugston
Joined: 05 Oct 2005 Posts: 91 Location: Germany (expat Australian)
|
Posted: Tue Dec 06, 2005 2:00 am Post subject: Two more ways... |
|
|
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 |
|
|
pragma
Joined: 28 May 2004 Posts: 607 Location: Washington, DC
|
Posted: Tue Dec 06, 2005 8:17 am Post subject: Re: Two more ways... |
|
|
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 |
|
|
Don Clugston
Joined: 05 Oct 2005 Posts: 91 Location: Germany (expat Australian)
|
Posted: Tue Dec 06, 2005 9:12 am Post subject: |
|
|
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 . |
|
Back to top |
|
|
kris
Joined: 27 Mar 2004 Posts: 1494 Location: South Pacific
|
Posted: Tue Dec 06, 2005 12:38 pm Post subject: |
|
|
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 . |
Awesome! This is getting better and better |
|
Back to top |
|
|
pragma
Joined: 28 May 2004 Posts: 607 Location: Washington, DC
|
Posted: Wed Dec 07, 2005 10:00 pm Post subject: Tweaked |
|
|
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 |
|
|
Don Clugston
Joined: 05 Oct 2005 Posts: 91 Location: Germany (expat Australian)
|
Posted: Thu Dec 08, 2005 1:45 am Post subject: |
|
|
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 |
|
|
pragma
Joined: 28 May 2004 Posts: 607 Location: Washington, DC
|
Posted: Thu Dec 08, 2005 8:20 am Post subject: |
|
|
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 |
|
|
Don Clugston
Joined: 05 Oct 2005 Posts: 91 Location: Germany (expat Australian)
|
Posted: Tue Dec 13, 2005 2:56 am Post subject: Wonder if I should put my 'meta' library in here? |
|
|
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 |
|
|
pragma
Joined: 28 May 2004 Posts: 607 Location: Washington, DC
|
Posted: Tue Dec 13, 2005 9:44 am Post subject: Re: Wonder if I should put my 'meta' library in here? |
|
|
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.
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 |
|
|
pragma
Joined: 28 May 2004 Posts: 607 Location: Washington, DC
|
Posted: Sat Dec 17, 2005 4:51 pm Post subject: |
|
|
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.
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. _________________ -- !Eric.t.Anderton at gmail |
|
Back to top |
|
|
Don Clugston
Joined: 05 Oct 2005 Posts: 91 Location: Germany (expat Australian)
|
Posted: Wed Dec 21, 2005 2:10 am Post subject: Regexp |
|
|
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 |
|
|
pragma
Joined: 28 May 2004 Posts: 607 Location: Washington, DC
|
Posted: Wed Dec 21, 2005 6:30 am Post subject: Re: Regexp |
|
|
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 = ®exMatch!(phoneTest);
auto staticMiscTest = ®exMatch!(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. _________________ -- !Eric.t.Anderton at gmail |
|
Back to top |
|
|
Don Clugston
Joined: 05 Oct 2005 Posts: 91 Location: Germany (expat Australian)
|
Posted: Mon Jan 02, 2006 4:15 am Post subject: Demangling interface for dynamically loading classes |
|
|
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 |
|
|
|
|
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
|