Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move prepare, lowerNonArrayAggregate and lowerArrayAggregate methods to statementsem #17011

Draft
wants to merge 16 commits into
base: master
Choose a base branch
from
Draft
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Move prepare, lowerNonArrayAggregate and lowerArrayAggregate methods …
…to statementsem
  • Loading branch information
dchidindu5 committed Oct 17, 2024
commit 7eac6e52d6a18409b9b5c75d62f399ee379e9f32
194 changes: 0 additions & 194 deletions compiler/src/dmd/cond.d
Original file line number Diff line number Diff line change
Expand Up @@ -239,200 +239,6 @@ extern (C++) final class StaticForeach : RootObject
return new CallExp(loc, new TypeExp(loc, type), e);
}


/*****************************************
* Lower any aggregate that is not an array to an array using a
* regular foreach loop within CTFE. If there are multiple
* `static foreach` loop variables, an array of tuples is
* generated. In thise case, the field `needExpansion` is set to
* true to indicate that the static foreach loop expansion will
* need to expand the tuples into multiple variables.
*
* For example, `static foreach (x; range) { ... }` is lowered to:
*
* static foreach (x; {
* typeof({
* foreach (x; range) return x;
* }())[] __res;
* foreach (x; range) __res ~= x;
* return __res;
* }()) { ... }
*
* Finally, call `lowerArrayAggregate` to turn the produced
* array into an expression tuple.
*
* Params:
* sc = The current scope.
*/

private void lowerNonArrayAggregate(Scope* sc)
{
auto nvars = aggrfe ? aggrfe.parameters.length : 1;
auto aloc = aggrfe ? aggrfe.aggr.loc : rangefe.lwr.loc;
// We need three sets of foreach loop variables because the
// lowering contains three foreach loops.
Parameters*[3] pparams = [new Parameters(), new Parameters(), new Parameters()];
foreach (i; 0 .. nvars)
{
foreach (params; pparams)
{
auto p = aggrfe ? (*aggrfe.parameters)[i] : rangefe.prm;
params.push(new Parameter(aloc, p.storageClass, p.type, p.ident, null, null));
}
}
Expression[2] res;
TypeStruct tplty = null;
if (nvars == 1) // only one `static foreach` variable, generate identifiers.
{
foreach (i; 0 .. 2)
{
res[i] = new IdentifierExp(aloc, (*pparams[i])[0].ident);
}
}
else // multiple `static foreach` variables, generate tuples.
{
foreach (i; 0 .. 2)
{
auto e = new Expressions(pparams[0].length);
foreach (j, ref elem; *e)
{
auto p = (*pparams[i])[j];
elem = new IdentifierExp(aloc, p.ident);
}
if (!tplty)
{
tplty = createTupleType(aloc, e, sc);
}
res[i] = createTuple(aloc, tplty, e);
}
needExpansion = true; // need to expand the tuples later
}
// generate remaining code for the new aggregate which is an
// array (see documentation comment).
if (rangefe)
{
sc = sc.startCTFE();
rangefe.lwr = rangefe.lwr.expressionSemantic(sc);
rangefe.lwr = resolveProperties(sc, rangefe.lwr);
rangefe.upr = rangefe.upr.expressionSemantic(sc);
rangefe.upr = resolveProperties(sc, rangefe.upr);
sc = sc.endCTFE();
rangefe.lwr = rangefe.lwr.optimize(WANTvalue);
rangefe.lwr = rangefe.lwr.ctfeInterpret();
rangefe.upr = rangefe.upr.optimize(WANTvalue);
rangefe.upr = rangefe.upr.ctfeInterpret();
}
auto s1 = new Statements();
auto sfe = new Statements();
if (tplty) sfe.push(new ExpStatement(loc, tplty.sym));
sfe.push(new ReturnStatement(aloc, res[0]));
s1.push(createForeach(aloc, pparams[0], new CompoundStatement(aloc, sfe)));
s1.push(new ExpStatement(aloc, new AssertExp(aloc, IntegerExp.literal!0)));
Type ety = new TypeTypeof(aloc, wrapAndCall(aloc, new CompoundStatement(aloc, s1)));
auto aty = ety.arrayOf();
auto idres = Identifier.generateId("__res");
auto vard = new VarDeclaration(aloc, aty, idres, null, STC.temp);
auto s2 = new Statements();

// Run 'typeof' gagged to avoid duplicate errors and if it fails just create
// an empty foreach to expose them.
const olderrors = global.startGagging();
ety = ety.typeSemantic(aloc, sc);
if (global.endGagging(olderrors))
s2.push(createForeach(aloc, pparams[1], null));
else
{
s2.push(new ExpStatement(aloc, vard));
auto catass = new CatAssignExp(aloc, new IdentifierExp(aloc, idres), res[1]);
s2.push(createForeach(aloc, pparams[1], new ExpStatement(aloc, catass)));
s2.push(new ReturnStatement(aloc, new IdentifierExp(aloc, idres)));
}

Expression aggr = void;
Type indexty = void;

if (rangefe && (indexty = ety).isIntegral())
{
rangefe.lwr.type = indexty;
rangefe.upr.type = indexty;
auto lwrRange = getIntRange(rangefe.lwr);
auto uprRange = getIntRange(rangefe.upr);

const lwr = rangefe.lwr.toInteger();
auto upr = rangefe.upr.toInteger();
size_t length = 0;

if (lwrRange.imin <= uprRange.imax)
length = cast(size_t) (upr - lwr);

auto exps = new Expressions(length);

if (rangefe.op == TOK.foreach_)
{
foreach (i; 0 .. length)
(*exps)[i] = new IntegerExp(aloc, lwr + i, indexty);
}
else
{
--upr;
foreach (i; 0 .. length)
(*exps)[i] = new IntegerExp(aloc, upr - i, indexty);
}
aggr = new ArrayLiteralExp(aloc, indexty.arrayOf(), exps);
}
else
{
aggr = wrapAndCall(aloc, new CompoundStatement(aloc, s2));
sc = sc.startCTFE();
aggr = aggr.expressionSemantic(sc);
aggr = resolveProperties(sc, aggr);
sc = sc.endCTFE();
aggr = aggr.optimize(WANTvalue);
aggr = aggr.ctfeInterpret();
}

assert(!!aggrfe ^ !!rangefe);
aggrfe = new ForeachStatement(loc, TOK.foreach_, pparams[2], aggr,
aggrfe ? aggrfe._body : rangefe._body,
aggrfe ? aggrfe.endloc : rangefe.endloc);
rangefe = null;
lowerArrayAggregate(sc); // finally, turn generated array into expression tuple
}

/*****************************************
* Perform `static foreach` lowerings that are necessary in order
* to finally expand the `static foreach` using
* `dmd.statementsem.makeTupleForeach`.
*/
extern(D) void prepare(Scope* sc)
{
assert(sc);

if (aggrfe)
{
sc = sc.startCTFE();
aggrfe.aggr = aggrfe.aggr.expressionSemantic(sc);
sc = sc.endCTFE();
}

if (aggrfe && aggrfe.aggr.type.toBasetype().ty == Terror)
{
return;
}

if (!ready())
{
if (aggrfe && aggrfe.aggr.type.toBasetype().ty == Tarray)
{
lowerArrayAggregate(sc);
}
else
{
lowerNonArrayAggregate(sc);
}
}
}

/*****************************************
* Returns:
* `true` iff ready to call `dmd.statementsem.makeTupleForeach`.
Expand Down
Loading