Difference between revisions of "DIP23 Counter Proposal"

From D Wiki
Jump to: navigation, search
(Created page with "== DIP23 Counter Proposal: Fixing properties and optional parens. == {| class="wikitable" !Title: !'''Fixing properties and optional parens. Only those. In a general and stra...")
 
(Redirected page to DIP24)
 
(8 intermediate revisions by 2 users not shown)
Line 1: Line 1:
== DIP23 Counter Proposal: Fixing properties and optional parens. ==
+
#REDIRECT [[DIP24]]
{| class="wikitable"
 
!Title:
 
!'''Fixing properties and optional parens. Only those. In a general and straightforward way.'''
 
|-
 
|DIP:
 
|23 (counter proposal)
 
|-
 
|Version:
 
|1
 
|-
 
|Status:
 
|Draft
 
|-
 
|Created:
 
|2013-02-06
 
|-
 
|Last Modified:
 
|2013-02-06
 
|-
 
|Author:
 
|Timon Gehr
 
|-
 
|Links:
 
|
 
|}
 
 
 
== Motivation ==
 
 
 
The DIP23 draft does not address all requests and only deals with a subset of cases. Furthermore, it does not translate easily into a implementation.
 
 
 
 
 
== Optional parens ==
 
 
 
A symbol 'foo' that refers to a non-@property-qualified function or function template is rewritten to foo() iff it does not occur in one of the following contexts:
 
 
 
  1. Function call position ( foo(args) )
 
  2. Address-taken position ( &foo )
 
  3. Instantiation position ( foo!args )
 
  4. Template argument position ( tmpl!(args1, foo, args2) )
 
 
 
(Note that redundant parentheses are assumed to be dropped in the parsing stage.)
 
 
 
== @property: basic design ==
 
 
 
A global @property function may have one or two arguments. (those are indended to be used UFCS-style only)
 
A member @property function may have zero or one argument. (additionally to the optional implicit this pointer)
 
 
 
In the first cases, the function is a @property getter. In the second cases, it is a @property setter.
 
 
 
(For templated functions, this restriction is checked after template instantiation as is usual.)
 
 
 
The following rewrite is assumed to have been applied on the entire AST WLOG: (this gets rid of an annoying border case)
 
  (exprs, b) (op)= exp is rewritten to (exprs, b (op)= exp)
 
 
 
 
 
The following __traits is introduced:
 
  __traits(propertyAccessors, propertySymbol)
 
 
 
This expression behaves like the propertySymbol, except that it is not subject to any of the rewrite rules below.
 
 
 
A symbol 'prop' that refers to a @property-qualified function or function template is rewritten to __traits(propertyAccessors, prop)() iff it does not occur in one of the following contexts:
 
 
 
  1. Assignment position: prop = exp
 
  -- In this case, there are two possibilities:
 
  -- - typeof(__traits(propertyAccessors, prop)(exp)) is void => The whole expression is rewritten to (__traits(propertyAccessors, prop)(exp), prop)
 
  -- - otherwise, the whole expression is rewritten to __traits(propertyAccessors, prop)(exp)
 
 
 
 
 
== @property: possible extensions ==
 
 
 
Everything below should be appended to the proposal if the consensus is to support simple "semantic rewrites":
 
--------------------------------------------------------------------------------------------------------------
 
 
 
  2. OpAssign position: prop op= exp
 
  -- In this case, the whole expression is rewritten to {auto val=prop; val op= exp; return prop=val; }(), where 'val' is choosen such that it does not occur free in exp or prop.
 
 
 
  3. Prefix increment/decrement position: ++prop or --prop
 
  -- In this case, the whole expression is rewritten to prop+=1 or prop-=1 respectively.
 
 
 
  4. Suffix increment/decrement position: prop++ and prop--
 
  -- In this case, the usual rewrites for prop++ and prop-- are applied before prop is rewritten.
 
 
 
Everything below should be appended to the proposal if the consensus is to support full "semantic rewrites":
 
------------------------------------------------------------------------------------------------------------
 
 
 
The following cases only apply if typeof(prop) can be successfully evaluated to a value type. i.e. a type that is not a class reference, pointer, slice, function pointer, or delegate.
 
 
 
  5. IndexAssign and OpIndexOpAssign: prop[indexes] (op)= exp
 
  -- In this case, the whole expression is rewritten to {auto val=prop; val[indexes] (op)= exp; return prop=val; }(), where 'val' is choosen such that it does not occur free in exp or prop.
 
 
 
  6. Field access position: (context) prop.ident (context), if the context corresponds to any one context from 1 to 6, but not only 6
 
  -- In this case, the expression is rewritten to {auto val1=prop, val2=(context) val1.ident (context); prop=val1; return val2 }(), where 'val1'/'val2' are choosen such that they does not occur free in exp or prop or in each other.
 
(This last rule is formulated in a somewhat informal way and could be stated more rigorously if the need arises.)
 
 
 
== Applicability of "semantic rewrites" to operator overloading ==
 
 
 
The "semantic rewrite" strategy would probably need to be employed for operator overloading as well:
 
 
 
  S s; // s is a struct, s.x is a field
 
  ++s[i].x;
 
 
 
the last expression would be rewritten according to almost identical rules to
 
 
 
  {auto val1=s[i], val2=++val1.x; s[i]=val1; return val2; }()
 
 
 
== A note on implementation ==
 
 
 
The compiler is of course free to use more efficient strategies that lead to the same semantics.
 
Error messages should ideally not expose the rewritten code.
 

Latest revision as of 01:39, 6 February 2013

Redirect to: