Skip to content

Instantly share code, notes, and snippets.

@rikkimax
Last active September 11, 2024 10:55
Show Gist options
  • Save rikkimax/33d8cac529c1f4e4ea94b2d4b53cfcb5 to your computer and use it in GitHub Desktop.
Save rikkimax/33d8cac529c1f4e4ea94b2d4b53cfcb5 to your computer and use it in GitHub Desktop.

Member of Operator

Field Value
DIP: (number/id -- assigned by DIP Manager)
Author: Richard (Rikki) Andrew Cattermole firstname@lastname.co.nz
Implementation: dlang/dmd#16161
Status: Draft

Abstract

The member of the operator performs a get member operation on a contextual symbol to obtain either a type or a value.

Contents

Rationale

Having a way to specify that an identifier is to be used in lookup given a context is useful both as a syntax sugar for aiding in using D, but it also offers a way to provide a tag for a sumtype or value type exception which is not backed by the type system.

Prior Work

Previously it has been desired to have a member-of-operator for context-aware lookups and it resulted in an ideas thread.

The typing behaviour has a known possible origin from Neat. This is called a symbol identifier or identifier type. It can be used for sumtypes to differentiate same value but different tag types. It also allows for an element to not have a value type associated with it.

Description

The member of operator, is an operator that operates on a contextual symbol with respect to a given statement, declaration or expression.

It may appear only as the first term in an expression.

The syntax of the operator is ':' Identifier.

It is commonly implemented by doing a rewrite to: context.Identifier. Where the context is a symbol which was provided by the usage syntax.

CmpExpression:
+   MemberOfOperator

+ MemberOfOperator:
+    : Identitifer

Type

It is given a non-unique type, when a type is taken of it, of size zero, and cannot have a pointer taken of it.

static assert(typeof(:Identifier).sizeof == 0);

The non-uniqueness of the type dictates that no meta-data is to be associated with it that is not by value.

The only valid value is the initializer as it is no-op.

Taking a string of the type will result in the identifier.

static assert(typeof(:Identifier).stringof == "Identifier");

Validation of a Member

The type that the member of the operator results in is the same as the one it is in the context of.

If it does not match, it will be an error.

enum E {
	First
}

E e = :First; // ok

struct S {
	enum Second = S.init;
	int field;
}

S s1 = :Second; // ok
S s2;
s2 = :field; // Error: Type of the field `field` on `s2` has type `int` not `S`

Valid Statements and Declarations

  • Return expressions The compiler rewrites return :Identifier; as return typeof(return).Identifier;.
  • Variable declarations Type qualifiers may not appear as the variable type, there must be a concrete type. The type of the variable declaration acts as the context.
    alias Type = int;
    Type var = Type.min;
    Instead of: int var = :min;.
  • Switch statements The expression used by the switch statement will need to be aliased as per variable declarations. So
    switch(expr) {
        case :Identifier:
            break;
    }
    would be rewritten as
    alias __Alias = typeof(expr);
    switch(expr) {
        case __Alias.Identifier:
            break;
    }
  • Function calls During parameter-to-argument matching, a check to see if the typeof(param).Identifier is possible for func(:Identifier).
  • Function parameter default initialization It must support the default initialization of a parameter. void func(Enum e = :Start).
  • Comparison The left-hand side type of a comparison is used as the context for the right-hand side e == :Start. This may require an intermediary variable to get the type of, prior to the comparison.

Breaking Changes and Deprecations

There are no expected breaking changes. It is not expected to conflict with any existing D syntax.

It does however conflict with inline assembly for GDC, but this can be worked around within the implementation and is not a concern.

Reference

Copyright & License

Copyright (c) 2024 by the D Language Foundation

Licensed under Creative Commons Zero 1.0

History

The DIP Manager will supplement this section with links to forum discussions and a summary of the formal assessment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment