Wrong lowering for a[b][c]++

Jonathan M Davis jmdavisProg at gmx.com
Wed Mar 21 11:39:04 PDT 2012


On Wednesday, March 21, 2012 11:29:14 H. S. Teoh wrote:
> A question was asked on the d-learn forum about why this throws a
> RangeError:
> 
> int[string][int] map;
> map["abc"][20]++;
> 
> This is understandable, since the compiler translates the second line to:
> 
> map.opIndex("abc").opIndexUnary!"++"(20);
> 
> Since map["abc"] doesn't exist yet, opIndex throws RangeError before we
> ever get to the ++.
> 
> I'd like to propose the following fix: if a given chained indexing
> expression has any operator applied to its final result (either a unary
> operator like ++ or --, or an assignment operator like +=), then instead
> of translating previous indexes into opIndex, the compiler should map it
> to a new operator overload, say opIndexCreate, which creates the
> relevant entry with default value if it doesn't exist yet. That is to
> say:
> 
> map["abc"][20]++;
> 
> should be translated to:
> 
> map.opIndexCreate("abc").opIndexUnary!"++"(20);
> 
> where opIndexCreate looks something like:
> 
> Slot opIndexCreate(Key k) {
> Slot *s = findSlot(k);
> if (s is null) {
> s = createNewSlot(k);
> }
> return s;
> }
> 
> Similar changes should be made for expressions like a[b][c][d]=100, or
> a[b][c][d]+=100.
> 
> In other words, if the tail of a chain of indexing operations maps to
> opIndexAssign, opIndexUnary, or opIndexOpAssign, then all preceding
> opIndex calls should be converted to opIndexCreate instead.
> 
> Comments?

IMHO, it's _horrible_ that C++ creates entries in a std::map when you ask for 
values that aren't there. A RangeError is _exactly_ what should be happening 
here. There's no element to increment, because it hasn't been added yet. I 
think that the current behavior is very much what the behavior _should_ be.

- Jonathan M Davis


More information about the Digitalmars-d mailing list