February 11, 2007
On Sun, 11 Feb 2007 07:39:25 +0300, janderson <askme@me.com> wrote:

> Personally I see this new mixin format as giving us the power to extend D in whatever way meets our goals.  As Walter adds more features some of them will be rarely used (law of demising returns) because they are special case.  Mixin Expressions circumvent this because now the programmer has the power to create the language features they need.

Thaks for your examples.

This is one of my own. We use an agent-oriented framework in the development of our SMS-routing software. In C++ description of agents, their events, messages and states requires a lot of C++-macroses:

// C++
// Agent class description
SOL4_CLASS_START( aag_3::smsc_map::a_router_t )

	// Messages ...
	MBAPI3_ROUTER_SOL4_MSG( msg_configure,
			aag_3::smsc_map::a_router_t::msg_configure )
	MBAPI3_ROUTER_SOL4_MSG( msg_send,
			aag_3::smsc_map::a_router_t::msg_send )
	MBAPI3_ROUTER_SOL4_MSG( msg_send_result,
			aag_3::smsc_map::a_router_t::msg_send_result )
	MBAPI3_ROUTER_SOL4_MSG( msg_send_finish,
			aag_3::smsc_map::a_router_t::msg_send_finish )
	...

	// Events...
	SOL4_EVENT( evt_start )
	SOL4_EVENT_STC(
			evt_configure,
			aag_3::smsc_map::a_router_t::msg_configure )
	SOL4_EVENT_STC(
			evt_send,
			aag_3::smsc_map::a_router_t::msg_send )
	SOL4_EVENT_STC(
			evt_send_result,
			aag_3::smsc_map::a_router_t::msg_send_result )
	SOL4_EVENT_STC(
			evt_send_finish,
			aag_3::smsc_map::a_router_t::msg_send_finish )
	...

	// States...
	SOL4_STATE_START( st_initial )
		SOL4_STATE_EVENT( evt_start )
		SOL4_STATE_EVENT( evt_configure )
	SOL4_STATE_FINISH()

	SOL4_STATE_START( st_configured )
		SOL4_STATE_EVENT( evt_configure )
		SOL4_STATE_EVENT( evt_send )
		SOL4_STATE_EVENT( evt_send_result )
		SOL4_STATE_EVENT( evt_send_finish )
		...
	SOL4_STATE_FINISH()

	SOL4_STATE_START( st_not_configured )
		SOL4_STATE_EVENT( evt_configure )
	SOL4_STATE_FINISH()
SOL4_CLASS_FINISH()

Each C++-macros hides a lot of auxilary code for agent support.

In D, I hope, it may be expressed as something like:

mixin( AgentClass( Aag3.SmscMap.ARouter,
`
	mbapi3_router_messages {
		MsgConfigure => Aag3.SmscMap.ARouter.MsgConfigure
		MsgSend => Aag3.SmscMap.ARouter.MsgSend
                     MsgSendResult => Aag.SmscMap.ARouter.MsgSendResult
		MsgSendFinish => Aag.SmscMap.ARouter.MsgSendFinish
		...
	}

	events {
		evtStart
		evtConfigure
		evtSend
		evtSendResult
		evtSendFinish
		...
	}

	state st_initial {
		events {
			evtStart
			evtConfigure
		}
	}

	state st_configured {
		events {
			evtConfigure
			evtSend
			evtSendResult
			evtSendFinish
			...
		}
	}

	state st_not_configured {
		events { evt_configure }
	}
` ) );




-- 
Regards,
Yauheni Akhotnikau
February 11, 2007
Andrei Alexandrescu (See Website For Email) wrote:
> janderson wrote:
>>
>> ect...
>>
>>
>> ");
>> //Note that there should be a way to disable CheckCode in the general case to save compile time
> 
> I guess this is an obvious:
> 
> mixin(CheckCode(import "program.d"));

Now that I think about it, what about:

version (CheckCode) { mixin(checkCode(__FILE__)) }

//Rest of file
...

checkCode would probably make use of static asserts.  Is it possible to write a message to compiler output?  That would be a handy static-compilation tool.

Or maybe it could be in the unit-tests.  Actually you can probably do that in unit tests already even without mixin Expressions.

-Joel
February 11, 2007
janderson wrote:
> Andrei Alexandrescu (See Website For Email) wrote:
>> janderson wrote:
>>>
>>> ect...
>>>
>>>
>>> ");
>>> //Note that there should be a way to disable CheckCode in the general case to save compile time
>>
>> I guess this is an obvious:
>>
>> mixin(CheckCode(import "program.d"));
> 
> Now that I think about it, what about:
> 
> version (CheckCode) { mixin(checkCode(__FILE__)) }
> 
> //Rest of file
> ...
> 
> checkCode would probably make use of static asserts.  Is it possible to write a message to compiler output?  That would be a handy static-compilation tool.
> 

There are two ways:

pragma(msg, "Compile-time output.");

And:

static assert(false, "Making the compiler die, now...");

> Or maybe it could be in the unit-tests.  Actually you can probably do that in unit tests already even without mixin Expressions.
> 
> -Joel


-- 
Kirk McDonald
http://kirkmcdonald.blogspot.com
Pyd: Connecting D and Python
http://pyd.dsource.org
February 11, 2007
String literals with mixins are a bit awkward sometimes (editor highlighting etc).

Some special marks -- I use @{ }@ here -- could be used to mark a part of a source file as a string literal, just like /* */ marks a part of code as a comment. For example:

  mixin(
    @{
      //this is a string literal block
      if(...) {
        ...
      }
    }@
  );

The @{ }@ marks have a close relation, of course, with quotation marks "". But because there is a starting mark and an ending mark, you can nest them. (And because they are used to mark a part of a file as a string literal, they are not actually the part of the 'working code' just like the "" literals are, if you get what I'm trying to say.)

E.g.

  alias @{
    str = @{ foo }@ ~ @{ bar }@;
    str ~= "blah";
    if(...) {
      ...
    }
  }@ MyCode;

   mixin(MyCode);
February 11, 2007
Argh, I hit the 'reply' button instead of 'new mail' button, so this mail was send to this thread. I'm posting this to the root thread also... Sorry. (So please don't reply to this one.)



On Sun, 11 Feb 2007 17:52:20 +0200, Kristian Kilpi <kjkilpi@gmail.com> wrote:
>
> String literals with mixins are a bit awkward sometimes (editor highlighting etc).
>
> Some special marks -- I use @{ }@ here -- could be used to mark a part of a source file as a string literal, just like /* */ marks a part of code as a comment. For example:
>
>    mixin(
>      @{
>        //this is a string literal block
>        if(...) {
>          ...
>        }
>      }@
>    );
>
> The @{ }@ marks have a close relation, of course, with quotation marks "". But because there is a starting mark and an ending mark, you can nest them. (And because they are used to mark a part of a file as a string literal, they are not actually the part of the 'working code' just like the "" literals are, if you get what I'm trying to say.)
>
> E.g.
>
>    alias @{
>      str = @{ foo }@ ~ @{ bar }@;
>      str ~= "blah";
>      if(...) {
>        ...
>      }
>    }@ MyCode;
>
>     mixin(MyCode);

February 11, 2007
Kristian Kilpi wrote:
> Argh, I hit the 'reply' button instead of 'new mail' button, so this mail was send to this thread. I'm posting this to the root thread also... Sorry. (So please don't reply to this one.)

With certain news clients (e.g. Thunderbird) you can cancel a message, and the effect in this group is immediate. In Thunderbird, just focus on the message you want to delete (it must originate from you) and hit Del.

Andrei
February 11, 2007
On Sun, 11 Feb 2007 18:16:26 +0200, Andrei Alexandrescu (See Website For Email) <SeeWebsiteForEmail@erdani.org> wrote:
> Kristian Kilpi wrote:
>> Argh, I hit the 'reply' button instead of 'new mail' button, so this mail was send to this thread. I'm posting this to the root thread also... Sorry. (So please don't reply to this one.)
>
> With certain news clients (e.g. Thunderbird) you can cancel a message, and the effect in this group is immediate. In Thunderbird, just focus on the message you want to delete (it must originate from you) and hit Del.
>
> Andrei

That's a good to known. Thanks.

Hmmm, yes, in Opera (what I'm using) you can right click a message in the Send view and select 'Cancel post'.
February 11, 2007
Kristian Kilpi wrote:
> On Sun, 11 Feb 2007 18:16:26 +0200, Andrei Alexandrescu (See Website For Email) <SeeWebsiteForEmail@erdani.org> wrote:
>> Kristian Kilpi wrote:
>>> Argh, I hit the 'reply' button instead of 'new mail' button, so this mail was send to this thread. I'm posting this to the root thread also... Sorry. (So please don't reply to this one.)
>>
>> With certain news clients (e.g. Thunderbird) you can cancel a message, and the effect in this group is immediate. In Thunderbird, just focus on the message you want to delete (it must originate from you) and hit Del.
>>
>> Andrei
> 
> That's a good to known. Thanks.
> 
> Hmmm, yes, in Opera (what I'm using) you can right click a message in the Send view and select 'Cancel post'.

The only issue being that if the post is to a widely available newsgroup, if you wait too long then it may have already propagated to other servers.


Sean
February 11, 2007
Nice ideas.

I'm also thinking on few powerful things.

Compile time XML parser:
 - configuration files:

   config.xml:
     <start><tag v="aa"></start>

   mixin(buildclasses!(xml(import("config.xml")));
   writefln(xml.start.tag.v);  // will print aa

   mixin(xpath!(xml, val, "start/tag.v"));
   writefln(val);    // "aa"

   not so usefull, but:

 - glade gui:
   mixin(glade!(xml(import("gui.glade")));
   with automatic bindings?

Compile time type safe SQL (working on it!):

  create_tables.sql:
    CREATE TABLE sale (id INT, name VARCHAR, price FLOAT);

  mixin(addtables!("create_tables.sql"));

  float p = 100.00;
  auto rows = sql!("SELECT id, name, price FROM sale WHERE price < $1").sql(p); // p MUST BE float

  foreach (r; rows) {
    writefln("%d: %s = %f", r.id, r.name, r.price);
         // yes! p.price, not p["price"].getFloat(), or sth similiar
    char[] sid = r.id;       // error!
  }

  Note: it is very VERY complicated to parse sql select with all features in compile
  time, but i have made some progress...

Pattern matching system (like in erlang, or nemerle):
  struct Eqn {
     enum typ {
       SYMBOL, FUNC, ENVVAR, DOUBLE
     };
     union u {
       char[] s;
       F f;
       char[] var;
       double d;
     };
  }

  Eqn e = { typ: DOUBLE, u.d: 3.4 };

  mixin(match!(
       case e of
         (SYMBOL, u.s as s) =>
            writefln(\"s=%s\", s),
         (DOUBLE, u.d as d) =>
            writefln(\"d=%f\", d),
         _ =>
            writefln(\"other\");
       end."));

   or:

   int[] a = [1,6,7];

   mixin(match!(
       case %1 of
         [Head | Tail] =>
            writefln(\"do something with head %d\", Head),
            Head + self(Tail), // recursion
         [Last] =>
            writefln(\"Last\"),
            Last
         [] =>
            writefln(\"empty\"),
            0
         _ =>
            assert(false, \"error\"),
         end.", "funk(int[]) : int"));

   writefln(funk(a));     //14



There is endless posibilities to extend syntax.
We can practicly implement some small langauages in this way,
and emit D code with some templates.

This is pretty cool, but we will need even quicker compilation time, for this to be fully useful.

Even after compiler optimalisations, IDE will have problems with parsing such things.

I think we also should have regexp functions accessible in compile time. It is painful to parse things by hand.

-- 
Witold Baryluk
February 12, 2007
Witold Baryluk wrote:
> Nice ideas.
>
> I'm also thinking on few powerful things.
>
> Compile time XML parser:
>  - configuration files:
>
>    config.xml:
>      <start><tag v="aa"></start>
>
>    mixin(buildclasses!(xml(import("config.xml")));
>    writefln(xml.start.tag.v);  // will print aa
>
>    mixin(xpath!(xml, val, "start/tag.v"));
>    writefln(val);    // "aa"
>

I think XML reading will be really useful.  In my game - programming - experience XML (including the binary version) is good for proto-typing but it eventually needs to be replaced by a binary format.  It's just to slow to phase, you want your data in the same order as the data structures, not all over the place.   Compile time xml would solve that (sort of because you've moved the bottleneck).

However most of the time in my field design/art can't compile the executables themselves.  A possible work around is to compile XML dll's on the fly, the final version would not need to do this.


> There is endless posibilities to extend syntax.
> We can practicly implement some small langauages in this way,
> and emit D code with some templates.
>
> This is pretty cool, but we will need even quicker compilation time, for this to be
> fully useful.

Agreed.
>
> Even after compiler optimalisations, IDE will have problems with parsing such things.

They could always be put into another file if this is of concern.  That way xml will look fine (if the editor is smart enough).  Having said that most DSL scripting languages don't get syntax highlighting, and its not worth the effort.

>
> I think we also should have regexp functions accessible in compile time. It is painful to
> parse things by hand.
>
I agree, but I think they are only a sub-set of what we need.  I think regex extentions could be implemented by a suped-up template/compile-time language.