Refactor opover.d to improve style (#20807)

This commit is contained in:
Dennis 2025-01-30 23:26:17 +01:00 committed by GitHub
parent f4558fe0fd
commit 193b71e546
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 99 additions and 122 deletions

View file

@ -662,10 +662,9 @@ TupleDeclaration isAliasThisTuple(Expression e)
* Runs semantic on ae.arguments. Declares temporary variables
* if '$' was used.
*/
Expression resolveOpDollar(Scope* sc, ArrayExp ae, Expression* pe0)
Expression resolveOpDollar(Scope* sc, ArrayExp ae, out Expression pe0)
{
assert(!ae.lengthVar);
*pe0 = null;
AggregateDeclaration ad = isAggregate(ae.e1.type);
Dsymbol slice = search_function(ad, Id.opSlice);
//printf("slice = %s %s\n", slice.kind(), slice.toChars());
@ -679,7 +678,7 @@ Expression resolveOpDollar(Scope* sc, ArrayExp ae, Expression* pe0)
foreach (i, e; *ae.arguments)
{
if (i == 0)
*pe0 = extractOpDollarSideEffect(sc, ae);
pe0 = extractOpDollarSideEffect(sc, ae);
if (e.op == EXP.interval && !(slice && slice.isTemplateDeclaration()))
{
@ -702,7 +701,7 @@ Expression resolveOpDollar(Scope* sc, ArrayExp ae, Expression* pe0)
// If $ was used, declare it now
Expression de = new DeclarationExp(ae.loc, ae.lengthVar);
de = de.expressionSemantic(sc);
*pe0 = Expression.combine(*pe0, de);
pe0 = Expression.combine(pe0, de);
}
sc = sc.pop();
@ -725,7 +724,7 @@ Expression resolveOpDollar(Scope* sc, ArrayExp ae, Expression* pe0)
if (!fslice)
return fallback();
e = new DotTemplateInstanceExp(ae.loc, ae.e1, slice.ident, tiargs);
e = new DotTemplateInstanceExp(ae.loc, ae.e1, Id.opSlice, tiargs);
e = new CallExp(ae.loc, e, fargs);
e = e.expressionSemantic(sc);
}
@ -749,7 +748,7 @@ Expression resolveOpDollar(Scope* sc, ArrayExp ae, Expression* pe0)
* Returns:
* ae, or ErrorExp if errors occurred
*/
Expression resolveOpDollar(Scope* sc, ArrayExp ae, IntervalExp ie, Expression* pe0)
Expression resolveOpDollar(Scope* sc, ArrayExp ae, IntervalExp ie, ref Expression pe0)
{
//assert(!ae.lengthVar);
if (!ie)
@ -786,7 +785,7 @@ Expression resolveOpDollar(Scope* sc, ArrayExp ae, IntervalExp ie, Expression* p
// If $ was used, declare it now
Expression de = new DeclarationExp(ae.loc, ae.lengthVar);
de = de.expressionSemantic(sc);
*pe0 = Expression.combine(*pe0, de);
pe0 = Expression.combine(pe0, de);
}
sc = sc.pop();
@ -10335,7 +10334,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (search_function(ad, Id.opIndexAssign))
{
// Deal with $
res = resolveOpDollar(sc, ae, &e0);
res = resolveOpDollar(sc, ae, e0);
if (!res) // a[i..j] = e2 might be: a.opSliceAssign(e2, i, j)
goto Lfallback;
if (res.op == EXP.error)
@ -10365,7 +10364,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
if (maybeSlice && search_function(ad, Id.opSliceAssign))
{
// Deal with $
res = resolveOpDollar(sc, ae, ie, &e0);
res = resolveOpDollar(sc, ae, ie, e0);
if (res.op == EXP.error)
return setResult(res);

View file

@ -178,7 +178,6 @@ Expression checkAliasThisForRhs(AggregateDeclaration ad, Scope* sc, BinExp e, Ty
Expression opOverloadUnary(UnaExp e, Scope* sc)
{
Expression result;
if (auto ae = e.e1.isArrayExp())
{
ae.e1 = ae.e1.expressionSemantic(sc);
@ -197,59 +196,57 @@ Expression opOverloadUnary(UnaExp e, Scope* sc)
{
return ae.e1;
}
Expression e0 = null;
Expression ae1save = ae.e1;
ae.lengthVar = null;
Type t1b = ae.e1.type.toBasetype();
AggregateDeclaration ad = isAggregate(t1b);
AggregateDeclaration ad = isAggregate(ae.e1.type);
if (!ad)
break;
if (search_function(ad, Id.opIndexUnary))
{
Expression e0;
// Deal with $
result = resolveOpDollar(sc, ae, &e0);
if (!result) // op(a[i..j]) might be: a.opSliceUnary!(op)(i, j)
Expression ae2 = resolveOpDollar(sc, ae, e0);
if (!ae2) // op(a[i..j]) might be: a.opSliceUnary!(op)(i, j)
goto Lfallback;
if (result.isErrorExp())
return result;
if (ae2.isErrorExp())
return ae2;
/* Rewrite op(a[arguments]) as:
* a.opIndexUnary!(op)(arguments)
*/
result = dotTemplateCall(ae.e1, Id.opIndexUnary, opToArg(sc, e.op), (*ae.arguments)[]);
Expression result = dotTemplateCall(ae.e1, Id.opIndexUnary, opToArg(sc, e.op), (*ae.arguments)[]);
if (maybeSlice) // op(a[]) might be: a.opSliceUnary!(op)()
result = result.trySemantic(sc);
else
result = result.expressionSemantic(sc);
if (result)
{
return Expression.combine(e0, result);
}
}
Lfallback:
if (maybeSlice && search_function(ad, Id.opSliceUnary))
{
// Deal with $
result = resolveOpDollar(sc, ae, ie, &e0);
if (result.isErrorExp())
return result;
Expression e0;
auto ae2 = resolveOpDollar(sc, ae, ie, e0);
if (ae2.isErrorExp())
return ae2;
/* Rewrite op(a[i..j]) as:
* a.opSliceUnary!(op)(i, j)
*/
if (ie)
result = dotTemplateCall(ae.e1, Id.opSliceUnary, opToArg(sc, e.op), ie.lwr, ie.upr);
else
result = dotTemplateCall(ae.e1, Id.opSliceUnary, opToArg(sc, e.op));
Expression result = ie ?
dotTemplateCall(ae.e1, Id.opSliceUnary, opToArg(sc, e.op), ie.lwr, ie.upr) :
dotTemplateCall(ae.e1, Id.opSliceUnary, opToArg(sc, e.op));
result = result.expressionSemantic(sc);
result = Expression.combine(e0, result);
return result;
return Expression.combine(e0, result.expressionSemantic(sc));
}
// Didn't find it. Forward to aliasthis
if (ad.aliasthis && !isRecursiveAliasThis(att, ae.e1.type))
{
/* Rewrite op(a[arguments]) as:
* op(a.aliasthis[arguments])
*/
* op(a.aliasthis[arguments])
*/
ae.e1 = resolveAliasThis(sc, ae1save, true);
if (ae.e1)
continue;
@ -305,7 +302,7 @@ Expression opOverloadUnary(UnaExp e, Scope* sc)
break;
}
return result;
return null;
}
Expression opOverloadArray(ArrayExp ae, Scope* sc)
@ -319,7 +316,6 @@ Expression opOverloadArray(ArrayExp ae, Scope* sc)
{
ie = (*ae.arguments)[0].isIntervalExp();
}
Expression result;
Type att = null; // first cyclic `alias this` type
while (true)
{
@ -340,63 +336,54 @@ Expression opOverloadArray(ArrayExp ae, Scope* sc)
{
// Convert to SliceExp
if (maybeSlice)
{
result = new SliceExp(ae.loc, ae.e1, ie);
result = result.expressionSemantic(sc);
return result;
}
return new SliceExp(ae.loc, ae.e1, ie).expressionSemantic(sc);
// Convert to IndexExp
if (ae.arguments.length == 1)
{
result = new IndexExp(ae.loc, ae.e1, (*ae.arguments)[0]);
result = result.expressionSemantic(sc);
return result;
}
return new IndexExp(ae.loc, ae.e1, (*ae.arguments)[0]).expressionSemantic(sc);
}
break;
}
if (search_function(ad, Id.opIndex))
{
// Deal with $
result = resolveOpDollar(sc, ae, &e0);
if (!result) // a[i..j] might be: a.opSlice(i, j)
auto ae2 = resolveOpDollar(sc, ae, e0);
if (!ae2) // a[i..j] might be: a.opSlice(i, j)
goto Lfallback;
if (result.isErrorExp())
return result;
if (ae2.isErrorExp())
return ae2;
/* Rewrite e1[arguments] as:
* e1.opIndex(arguments)
*/
Expressions* a = ae.arguments.copy();
result = new DotIdExp(ae.loc, ae.e1, Id.opIndex);
Expression result = new DotIdExp(ae.loc, ae.e1, Id.opIndex);
result = new CallExp(ae.loc, result, a);
if (maybeSlice) // a[] might be: a.opSlice()
result = result.trySemantic(sc);
else
result = result.expressionSemantic(sc);
if (result)
{
return Expression.combine(e0, result);
}
}
Lfallback:
if (maybeSlice && ae.e1.isTypeExp())
{
result = new SliceExp(ae.loc, ae.e1, ie);
Expression result = new SliceExp(ae.loc, ae.e1, ie);
result = result.expressionSemantic(sc);
result = Expression.combine(e0, result);
return result;
return Expression.combine(e0, result);
}
if (maybeSlice && search_function(ad, Id.opSlice))
{
// Deal with $
result = resolveOpDollar(sc, ae, ie, &e0);
auto ae2 = resolveOpDollar(sc, ae, ie, e0);
if (result.isErrorExp())
if (ae2.isErrorExp())
{
if (!e0 && !search_function(ad, Id.dollar))
ad.loc.errorSupplemental("perhaps define `opDollar` for `%s`", ad.toChars());
return result;
return ae2;
}
/* Rewrite a[i..j] as:
* a.opSlice(i, j)
@ -407,11 +394,10 @@ Expression opOverloadArray(ArrayExp ae, Scope* sc)
a.push(ie.lwr);
a.push(ie.upr);
}
result = new DotIdExp(ae.loc, ae.e1, Id.opSlice);
Expression result = new DotIdExp(ae.loc, ae.e1, Id.opSlice);
result = new CallExp(ae.loc, result, a);
result = result.expressionSemantic(sc);
result = Expression.combine(e0, result);
return result;
return Expression.combine(e0, result);
}
// Didn't find it. Forward to aliasthis
if (ad.aliasthis && !isRecursiveAliasThis(att, ae.e1.type))
@ -428,7 +414,7 @@ Expression opOverloadArray(ArrayExp ae, Scope* sc)
}
ae.e1 = ae1old; // recovery
ae.lengthVar = null;
return result;
return null;
}
/***********************************************
@ -437,41 +423,38 @@ Expression opOverloadArray(ArrayExp ae, Scope* sc)
*/
Expression opOverloadCast(CastExp e, Scope* sc, Type att = null)
{
Expression result;
if (AggregateDeclaration ad = isAggregate(e.e1.type))
AggregateDeclaration ad = isAggregate(e.e1.type);
if (!ad)
return null;
// Rewrite as: e1.opCast!(T)()
if (Dsymbol fd = search_function(ad, Id.opCast))
{
// Rewrite as: e1.opCast!(T)()
if (Dsymbol fd = search_function(ad, Id.opCast))
version (all)
{
version (all)
// Backwards compatibility with D1 if opCast is a function, not a template
if (fd.isFuncDeclaration())
{
// Backwards compatibility with D1 if opCast is a function, not a template
if (fd.isFuncDeclaration())
{
// Rewrite as: e1.opCast()
return build_overload(e.loc, sc, e.e1, null, fd);
}
// Rewrite as: e1.opCast()
return build_overload(e.loc, sc, e.e1, null, fd);
}
auto tiargs = new Objects();
tiargs.push(e.to);
return dotTemplateCall(e.e1, Id.opCast, tiargs).expressionSemantic(sc);
}
// Didn't find it. Forward to aliasthis
if (ad.aliasthis && !isRecursiveAliasThis(att, e.e1.type))
auto tiargs = new Objects();
tiargs.push(e.to);
return dotTemplateCall(e.e1, Id.opCast, tiargs).expressionSemantic(sc);
}
// Didn't find it. Forward to aliasthis
if (ad.aliasthis && !isRecursiveAliasThis(att, e.e1.type))
{
// Rewrite `e1.opCast()` as `e1.aliasthis.opCast()`
if (auto e1 = resolveAliasThis(sc, e.e1, true))
{
/* Rewrite op(e1) as:
* op(e1.aliasthis)
*/
if (auto e1 = resolveAliasThis(sc, e.e1, true))
{
result = e.copy();
(cast(UnaExp)result).e1 = e1;
result = opOverloadCast(result.isCastExp(), sc, att);
return result;
}
CastExp result = e.copy().isCastExp();
result.e1 = e1;
return result.opOverloadCast(sc, att);
}
}
return result;
return null;
}
// When no operator overload functions are found for `e`, recursively try with `alias this`
@ -936,65 +919,60 @@ Expression opOverloadBinaryAssign(BinAssignExp e, Scope* sc, Type[2] aliasThisSt
while (true)
{
if (ae.e1.isErrorExp())
{
return ae.e1;
}
Expression e0 = null;
Expression ae1save = ae.e1;
ae.lengthVar = null;
Type t1b = ae.e1.type.toBasetype();
AggregateDeclaration ad = isAggregate(t1b);
AggregateDeclaration ad = isAggregate(ae.e1.type);
if (!ad)
break;
if (search_function(ad, Id.opIndexOpAssign))
{
// Deal with $
Expression result = resolveOpDollar(sc, ae, &e0);
if (!result) // (a[i..j] op= e2) might be: a.opSliceOpAssign!(op)(e2, i, j)
Expression ae2 = resolveOpDollar(sc, ae, e0);
if (!ae2) // (a[i..j] op= e2) might be: a.opSliceOpAssign!(op)(e2, i, j)
goto Lfallback;
if (result.isErrorExp())
return result;
result = e.e2.expressionSemantic(sc);
if (result.isErrorExp())
return result;
e.e2 = result;
if (ae2.isErrorExp())
return ae2;
e.e2 = e.e2.expressionSemantic(sc);
if (e.e2.isErrorExp())
return e.e2;
/* Rewrite a[arguments] op= e2 as:
* a.opIndexOpAssign!(op)(e2, arguments)
*/
Expressions* a = ae.arguments.copy();
a.insert(0, e.e2);
result = dotTemplateCall(ae.e1, Id.opIndexOpAssign, opToArg(sc, e.op), (*a)[]);
Expression result = dotTemplateCall(ae.e1, Id.opIndexOpAssign, opToArg(sc, e.op), (*a)[]);
if (maybeSlice) // (a[] op= e2) might be: a.opSliceOpAssign!(op)(e2)
result = result.trySemantic(sc);
else
result = result.expressionSemantic(sc);
if (result)
{
return Expression.combine(e0, result);
}
}
Lfallback:
if (maybeSlice && search_function(ad, Id.opSliceOpAssign))
{
// Deal with $
Expression result = resolveOpDollar(sc, ae, ie, &e0);
if (result.isErrorExp())
return result;
result = e.e2.expressionSemantic(sc);
if (result.isErrorExp())
return result;
e.e2 = result;
Expression ae2 = resolveOpDollar(sc, ae, ie, e0);
if (ae2.isErrorExp())
return ae2;
e.e2 = e.e2.expressionSemantic(sc);
if (e.e2.isErrorExp())
return e.e2;
/* Rewrite (a[i..j] op= e2) as:
* a.opSliceOpAssign!(op)(e2, i, j)
*/
if (ie)
result = dotTemplateCall(ae.e1, Id.opSliceOpAssign, opToArg(sc, e.op), e.e2, ie.lwr, ie.upr);
else
result = dotTemplateCall(ae.e1, Id.opSliceOpAssign, opToArg(sc, e.op), e.e2);
auto result = ie ?
dotTemplateCall(ae.e1, Id.opSliceOpAssign, opToArg(sc, e.op), e.e2, ie.lwr, ie.upr) :
dotTemplateCall(ae.e1, Id.opSliceOpAssign, opToArg(sc, e.op), e.e2);
result = result.expressionSemantic(sc);
result = Expression.combine(e0, result);
return result;
return Expression.combine(e0, result.expressionSemantic(sc));
}
// Didn't find it. Forward to aliasthis
if (ad.aliasthis && !isRecursiveAliasThis(att, ae.e1.type))
@ -1011,14 +989,14 @@ Expression opOverloadBinaryAssign(BinAssignExp e, Scope* sc, Type[2] aliasThisSt
ae.e1 = ae1old; // recovery
ae.lengthVar = null;
}
Expression result = e.binSemanticProp(sc);
if (result)
if (Expression result = e.binSemanticProp(sc))
return result;
// Don't attempt 'alias this' if an error occurred
if (e.e1.type.isTypeError() || e.e2.type.isTypeError())
{
return ErrorExp.get();
}
AggregateDeclaration ad1 = isAggregate(e.e1.type);
Dsymbol s = search_function(ad1, Id.opOpAssign);
if (s && !s.isTemplateDeclaration())
@ -1031,7 +1009,7 @@ Expression opOverloadBinaryAssign(BinAssignExp e, Scope* sc, Type[2] aliasThisSt
if (auto res = pickBestBinaryOverload(sc, opToArg(sc, e.op), s, null, e, choseReverse))
return res;
result = checkAliasThisForLhs(ad1, sc, e, aliasThisStop);
Expression result = checkAliasThisForLhs(ad1, sc, e, aliasThisStop);
if (result || !s) // no point in trying Rhs alias-this if there's no overload of any kind in lhs
return result;