D Primary Type Syntax is Essentially Implemented!

Quirin Schroll qs.il.paperinik at gmail.com
Tue May 23 22:18:35 UTC 2023


#### Recap

“D primary type syntax” is this recurrence:

 [`Type`](https://dlang.org/spec/type.html#Type) → 
[`BasicType`](https://dlang.org/spec/type.html#BasicType)
 [`BasicType`](https://dlang.org/spec/type.html#BasicType) → 
[`TypeCtor`](https://dlang.org/spec/type.html#TypeCtor)? 
**`(`**[`Type`](https://dlang.org/spec/type.html#Type)**`)`** 
(The novelty is that `TypeCtor` is optional.)

This allows to add these additional grammar rules:

 [`Type`](https://dlang.org/spec/type.html#Type) → **`ref`** 
[`TypeCtors`](https://dlang.org/spec/type.html#TypeCtor)? 
[`BasicType`](https://dlang.org/spec/type.html#BasicType) 
*CallableSuffix* 
[`TypeSuffixes`](https://dlang.org/spec/type.html#TypeSuffix)?
 *CallableSuffix* → **`delegate`** 
[`Parameters`](https://dlang.org/spec/function.html#Parameters) 
[`MemberFunctionAttributes`](https://dlang.org/spec/function.html#MemberFunctionAttributes)?
 *CallableSuffix* → **`function`** 
[`Parameters`](https://dlang.org/spec/function.html#Parameters) 
[`FunctionAttributes`](https://dlang.org/spec/function.html#FunctionAttributes)?

The goal was to make e.g. `(ref const int function() @safe)[]` 
parse as a type. As of today, [this is 
possible](https://github.com/dlang/dmd/pull/15245).

I borrowed the nomenclature of “primary types” from “primary 
expressions”:
* Primary expressions are something like fundamental or 
parenthesized expressions.
* Primary types (in D’s grammar: basic types) are something like 
fundamental types or parenthesized types.

### Basic Intro
#### Parameters
```d
// `a` takes its parameter by value;     the parameter returns by 
reference.
// `b` takes its parameter by reference; the parameter returns by 
value.
void a( ref (int function()) ) { }
void b((ref  int function()) ) { }
// Note: The parameter storage class has priority
//       over the value category of the parameter’s return type.

// `c` is `a` without clarifiying parentheses.
void c( ref  int function()  ) { }

static assert(!is( typeof(&a) == typeof(&b) ));
static assert( is( typeof(&a) == typeof(&c) ));
```
#### Return types
```d
// `x` returns by reference; the returned function ptr returns an 
`int` by value.
// `y` returns by vale;      the returned function ptr returns an 
`int` by reference.
  ref (int function()) x() { static typeof(return) fp = null; 
return fp; }
(ref  int function()) y() => null;
// Note: The value category of the declared function has priority
//       over the value category of the return type.

// `z` is `x` without clarifiying parentheses.
  ref  int function()  z() => x();

static assert(!is( typeof(&x) == typeof(&y) ));
static assert( is( typeof(&x) == typeof(&z) ));
```

#### Satisfying the Inner Monk

Especially pleasing is the congruence between function 
declaration and function type:
```d
static int i = 0;
  ref int funcName() @safe  => i;
(ref int delegate() @safe) fptr = &funcName;
```
The parentheses are necessary. Not only is that an artifact of 
the implementation, but also the way I think it’s clearer. If we 
ever add `ref` local variables, they would change meaning.

#### Error Messages vs. Source Files

I also changed the pretty-print so that `ref` appears at the 
*beginning* of a function pointer or delegate type. This is where 
it should be according to my eye and the D grammar, but 
pretty-print gave us `ref` among `pure` and `@safe`. This meant 
that if you copied the type from the error message to your source 
file, it would not parse. Now, it will parse. (It might still not 
compile for other reasons, such as visibility.)

With `pragma(msg)`:
```d
pragma(msg, typeof( function ref int { static x = 0; return x; } 
));
// Old: int function() nothrow @nogc ref @safe
// New: (ref int function() nothrow @nogc @safe)
```

With `.stringof`:
```d
// Old:
alias FP = ref int function();
static assert(FP.stringof == "int function() ref");

// New:
static assert((ref int function()).stringof == "(ref int 
function())" );
// No alias required!
```
The parentheses on the right are somewhat intentional. I didn’t 
even try to make the pretty-print use parentheses only when 
necessary because it costs time and is not the main issue. As of 
now, it mindlessly inserts them. The pretty-print can be improved 
later.

---

All the examples are tested and work as intended on my local 
machine. The code is 
[here](https://github.com/Bolpat/dmd/tree/patch-3). (I know the 
branch has a stupid name.)

I hope you like it.


More information about the Digitalmars-d mailing list