Eigenpoll : D wish list : suffix identifiers. 

Recently, there has been some discussion about suffix identifiers.
I thought a little bit about it myself and got inspired to write this proposal.

One suggestion has been to introduce suffix identifiers at the lexical level, but this wouldn't be a good idea, because it's not very flexible and implementing it would add more weight to the value data structures of tokens.
A much more elegant and powerful solution would be to simply introduce a new syntax.

We already have these postfix expressions (written in pseudo EBNF):
*) DotId: Expression "." (Identifier | TemplateInstance)
*) NewNestedClass: E "." NewExpression
*) PostIncrement: E "++"
*) PostDecrement: E "--"
*) CallExpression: E "(" ArgumentList? ")"
*) IndexExpression: E "[" ArgumentList "]"
*) SliceExpression: E "[" (E ".." E)? "]"

The new syntax would look like:
*) SuffixId: E Identifier

In the semantic pass the compiler would map suffix identifiers to global functions of this form:

R opSuffix_Identifier(T t);

Concrete examples:

module std.complex;
struct complex
{ /*implementation*/ }
// Imaginary unit 'i' for mathematicians.
complex opSuffix_i(real x)
{ return complex(0, x); }
alias opSuffix_i opSuffix_j; // For engineers.

import std.complex;
auto a = 24;
auto b = 42;
auto c = a + b i; // space is required
auto x = 1 + (3*27)j;

float opSuffix_e(float f)
{ return f * 2.71828183; }
float opSuffix_pi(float f)
{ return f * 3.14159265; }
// The most beatiful equation in the world?
// Would look much nicer if we had ** for power: 1e**(1i*1pi)+1
auto zero = pow(1e, 1i*1pi) + 1;

// Byte units.
uint opSuffix_B(uint x)
{ return x; }
uint opSuffix_KB(uint x)
{ return x * 1024; }
uint opSuffix_MB(uint x)
{ return x KB * 1024; /**/ }
uint opSuffix_GiB(uint x)
{ return x MB * 1024; /**/ }

auto filesize = 3MB + 282KB+ 10B;
assert(filesize == 3434506)

To make things more interesting we could extend the syntax to:
*) SuffixId: E Identifier("."Identifier)*

This would allow for the following:

module SI;
/// SI units.
struct SI
{
static: // Make all following functions static.
uint opSuffix_B(uint x)
{ return x; }
uint opSuffix_KiB(uint x)
{ return x * 1024; }
uint opSuffix_MiB(uint x)
{ return x KiB * 1024; /**/ }
uint opSuffix_GiB(uint x)
{ return x MiB * 1024; /**/ }
opSuffix_kg(
}

import SI;
auto filesize = 1 SI.MiB + 345 SI.KiB + 23 SI.B;

Advantages:
*) Suffix identifiers don't conflict with ordinary symbols.
*) D2.0 could have this and be backwards compatible to D1.0 code.
*) Easy to implement.

Disadvantages:
*) Don't know any.

Regards,
Aziz

Report this item for cleanup