Thread overview
compile-time access to parsed code
Feb 11, 2007
Hasan Aljudy
Feb 22, 2007
Serg Kovrov
Feb 22, 2007
Serg Kovrov
Feb 11, 2007
janderson
Feb 11, 2007
janderson
February 11, 2007
alot of ideas for DSL that are coming up are really just additions of feature to already existing concepts in D.

For example, mapping a DB table/row to a D class/object.
One would probably do something like:
mixin( Model!(
   "Person:
     char[100] name;
     int       age;
     ForeignKey(Car)  car;
   "
))

and then one would have to write a parser for that, which will essentially produce a regular D class, with the same attributes, plus some additional magic:

class Person
{
     char[100] name;
     int       age;
     ForeignKey!(Car)  car;

     //magic
     load( ... );
     save( ... );
     query( ... );
     //etc
}


Here, one is essentially adding magic features to classes, but there's a lot of re-invention of the wheel going on here.

Wouldn't it be much better if we simply write the code in D, and get access to its parsed form at compile-time and modify it?

like, just write:
class Person
{
     char[100] name;
     int       age;
     ForeignKey!(Car)  car;

     mixin(DBMagic!( typeof(this) ));
}

then, somewhere else, we define DBMagic as a template or function or whatever, and this function would recieve a paramter of type Class which would have all the attributes of the Person class, the function can read those attributes and figure out how to return a string containing definitions of magic methods.

A better alternative is reading the class at compile-time and /changing/ the class (without emitting code) by adding attributes and methods to it, using something like:
class.addAttribute( Type, name );
class.addMethod( Type, name, params, ..... )

That would be much more robust than emitting strings .. no?

February 11, 2007
Hasan Aljudy wrote:
> alot of ideas for DSL that are coming up are really just additions of feature to already existing concepts in D.
> 
> For example, mapping a DB table/row to a D class/object.
> One would probably do something like:
> mixin( Model!(
>    "Person:
>      char[100] name;
>      int       age;
>      ForeignKey(Car)  car;
>    "
> ))

I don't think so. The underlying motivation for mapping DB structure to D code is to "not repeat yourself". Here you are repeating yourself, because you specify a snippet of what looks like SQL, but inside D code so you'll need to write that somewhere in the database itself.

The DRY approach is to have the D code peek the database structure directly and generate the appropriate code. Then you benefit of keeping the two in sync without effort.

> and then one would have to write a parser for that, which will essentially produce a regular D class, with the same attributes, plus some additional magic:
> 
> class Person
> {
>      char[100] name;
>      int       age;
>      ForeignKey!(Car)  car;
> 
>      //magic
>      load( ... );
>      save( ... );
>      query( ... );
>      //etc
> }
> 
> 
> Here, one is essentially adding magic features to classes, but there's a lot of re-invention of the wheel going on here.
> 
> Wouldn't it be much better if we simply write the code in D, and get access to its parsed form at compile-time and modify it?
> 
> like, just write:
> class Person
> {
>      char[100] name;
>      int       age;
>      ForeignKey!(Car)  car;
> 
>      mixin(DBMagic!( typeof(this) ));
> }
> 
> then, somewhere else, we define DBMagic as a template or function or whatever, and this function would recieve a paramter of type Class which would have all the attributes of the Person class, the function can read those attributes and figure out how to return a string containing definitions of magic methods.
> 
> A better alternative is reading the class at compile-time and /changing/ the class (without emitting code) by adding attributes and methods to it, using something like:
> class.addAttribute( Type, name );
> class.addMethod( Type, name, params, ..... )
> 
> That would be much more robust than emitting strings .. no?

I don't think so. This is pretty much getting back to the old way of doing things - writing things twice and crossing fingers that they'll stay in sync.


Andrei
February 11, 2007
Hasan Aljudy wrote:
> alot of ideas for DSL that are coming up are really just additions of feature to already existing concepts in D.
> 
> For example, mapping a DB table/row to a D class/object.
> One would probably do something like:
> mixin( Model!(
>    "Person:
>      char[100] name;
>      int       age;
>      ForeignKey(Car)  car;
>    "
> ))
> 
> and then one would have to write a parser for that, which will essentially produce a regular D class, with the same attributes, plus some additional magic:
> 

In this case all the parser would do is find Token: and re-write it as "class Person"  Then find ( and replace it with !(.  Finally it would append the magic on the end.  I hope we will eventually get lots of library functions to help this process out.

This essentially makes the reuseable part easy to write at a cost of spending a little time writing the Model! library.

In some respects I agree, when I originally posted an idea like this a few years ago, one of my suggestions asked to have access to D's symbolic tree passed into the template.

-Joel
February 11, 2007
janderson > In some respects I agree, when I originally posted an idea like this a
> few years ago, one of my suggestions asked to have access to D's symbolic tree passed into the template.
> 
> -Joel

Actually now that I think about it, this is probably not possible or would be very difficult to do.

-Joel
February 22, 2007
Andrei Alexandrescu (See Website For Email) wrote:
> The DRY approach is to have the D code peek the database structure directly and generate the appropriate code. Then you benefit of keeping the two in sync without effort.

I disagree. Hasan meant different (from Rails) approach. I believe he referring to Django. And it is perfectly valid point.

> This is pretty much getting back to the old way of doing things - writing things twice and crossing fingers that they'll stay in sync.

Could not agree on that either. An analogy is a binary file format - once defined it should not be changed. If changed externally (you would say out of sync) it's integrity should be considered broken.

-- 
serg.
February 22, 2007
Serg Kovrov wrote:
> Andrei Alexandrescu (See Website For Email) wrote:
>> The DRY approach is to have the D code peek the database structure directly and generate the appropriate code. Then you benefit of keeping the two in sync without effort.
> 
> I disagree. Hasan meant different (from Rails) approach. I believe he referring to Django. And it is perfectly valid point.

I'm lost here.

>> This is pretty much getting back to the old way of doing things - writing things twice and crossing fingers that they'll stay in sync.
> 
> Could not agree on that either. An analogy is a binary file format - once defined it should not be changed. If changed externally (you would say out of sync) it's integrity should be considered broken.

You are supporting my viewpoint. Because all I'm saying is that any "broken integrity" should be detected early and swiftly.


Andrei
February 22, 2007
Andrei Alexandrescu (See Website For Email) wrote:
> You are supporting my viewpoint. Because all I'm saying is that any "broken integrity" should be detected early and swiftly.

It might be, or there might be some misunderstanding... Anyway my point is that primary (and sole, if adhering DRY) 'source' of database config (schema), should be code.

Detecting broken integrity has nothing to do with subject, it's just a matter of defensive coding techniques.

Original point was, to have ability to introspect code on compile time to generate SQL from classes representing data. Django (http://www.djangoproject.com/) is good example of such approach.

-- 
serg.