mirror of
https://github.com/dlang/dmd.git
synced 2025-04-29 14:40:12 +03:00
Moved Staticforeach.lowerNonArrayAggregate and Staticforeach.prepare to expressionsem (#20944)
This commit is contained in:
parent
5cd254f9e0
commit
58d3b59dc5
4 changed files with 205 additions and 200 deletions
|
@ -24,7 +24,7 @@ import dmd.dscope;
|
||||||
import dmd.dsymbol;
|
import dmd.dsymbol;
|
||||||
import dmd.errors;
|
import dmd.errors;
|
||||||
import dmd.expression;
|
import dmd.expression;
|
||||||
import dmd.expressionsem : expressionSemantic, evalStaticCondition, resolveProperties;
|
import dmd.expressionsem : expressionSemantic, evalStaticCondition;
|
||||||
import dmd.globals;
|
import dmd.globals;
|
||||||
import dmd.identifier;
|
import dmd.identifier;
|
||||||
import dmd.location;
|
import dmd.location;
|
||||||
|
@ -151,7 +151,7 @@ extern (C++) final class StaticForeach : RootObject
|
||||||
* to
|
* to
|
||||||
* static foreach (x; AliasSeq!(1, 2, 3, 4)) { ... }
|
* static foreach (x; AliasSeq!(1, 2, 3, 4)) { ... }
|
||||||
*/
|
*/
|
||||||
private extern(D) void lowerArrayAggregate(Scope* sc)
|
extern(D) void lowerArrayAggregate(Scope* sc)
|
||||||
{
|
{
|
||||||
auto aggr = aggrfe.aggr;
|
auto aggr = aggrfe.aggr;
|
||||||
Expression el = new ArrayLengthExp(aggr.loc, aggr);
|
Expression el = new ArrayLengthExp(aggr.loc, aggr);
|
||||||
|
@ -198,7 +198,7 @@ extern (C++) final class StaticForeach : RootObject
|
||||||
* Returns:
|
* Returns:
|
||||||
* AST of the expression `(){ s; }()` with location loc.
|
* AST of the expression `(){ s; }()` with location loc.
|
||||||
*/
|
*/
|
||||||
private extern(D) Expression wrapAndCall(Loc loc, Statement s)
|
extern(D) Expression wrapAndCall(Loc loc, Statement s)
|
||||||
{
|
{
|
||||||
auto tf = new TypeFunction(ParameterList(), null, LINK.default_, STC.none);
|
auto tf = new TypeFunction(ParameterList(), null, LINK.default_, STC.none);
|
||||||
auto fd = new FuncLiteralDeclaration(loc, loc, tf, TOK.reserved, null);
|
auto fd = new FuncLiteralDeclaration(loc, loc, tf, TOK.reserved, null);
|
||||||
|
@ -221,7 +221,7 @@ extern (C++) final class StaticForeach : RootObject
|
||||||
* `foreach (parameters; lower .. upper) s;`
|
* `foreach (parameters; lower .. upper) s;`
|
||||||
* Where aggregate/lower, upper are as for the current StaticForeach.
|
* Where aggregate/lower, upper are as for the current StaticForeach.
|
||||||
*/
|
*/
|
||||||
private extern(D) Statement createForeach(Loc loc, Parameters* parameters, Statement s)
|
extern(D) Statement createForeach(Loc loc, Parameters* parameters, Statement s)
|
||||||
{
|
{
|
||||||
if (aggrfe)
|
if (aggrfe)
|
||||||
{
|
{
|
||||||
|
@ -254,7 +254,7 @@ extern (C++) final class StaticForeach : RootObject
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
|
|
||||||
private extern(D) TypeStruct createTupleType(Loc loc, Expressions* e, Scope* sc)
|
extern(D) TypeStruct createTupleType(Loc loc, Expressions* e, Scope* sc)
|
||||||
{ // TODO: move to druntime?
|
{ // TODO: move to druntime?
|
||||||
auto sid = Identifier.generateId("Tuple");
|
auto sid = Identifier.generateId("Tuple");
|
||||||
auto sdecl = new StructDeclaration(loc, sid, false);
|
auto sdecl = new StructDeclaration(loc, sid, false);
|
||||||
|
@ -280,205 +280,11 @@ extern (C++) final class StaticForeach : RootObject
|
||||||
* An AST for the expression `Tuple(e)`.
|
* An AST for the expression `Tuple(e)`.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
private extern(D) Expression createTuple(Loc loc, TypeStruct type, Expressions* e) @safe
|
extern(D) Expression createTuple(Loc loc, TypeStruct type, Expressions* e) @safe
|
||||||
{ // TODO: move to druntime?
|
{ // TODO: move to druntime?
|
||||||
return new CallExp(loc, new TypeExp(loc, type), e);
|
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.param;
|
|
||||||
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:
|
* Returns:
|
||||||
* `true` iff ready to call `dmd.statementsem.makeTupleForeach`.
|
* `true` iff ready to call `dmd.statementsem.makeTupleForeach`.
|
||||||
|
|
|
@ -50,6 +50,7 @@ namespace dmd
|
||||||
{
|
{
|
||||||
// in expressionsem.d
|
// in expressionsem.d
|
||||||
Expression *expressionSemantic(Expression *e, Scope *sc);
|
Expression *expressionSemantic(Expression *e, Scope *sc);
|
||||||
|
void lowerNonArrayAggregate(StaticForeach *sfe, Scope *sc);
|
||||||
// in typesem.d
|
// in typesem.d
|
||||||
Expression *defaultInit(Type *mt, Loc loc, const bool isCfile = false);
|
Expression *defaultInit(Type *mt, Loc loc, const bool isCfile = false);
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ import dmd.astcodegen;
|
||||||
import dmd.astenums;
|
import dmd.astenums;
|
||||||
import dmd.canthrow;
|
import dmd.canthrow;
|
||||||
import dmd.chkformat;
|
import dmd.chkformat;
|
||||||
|
import dmd.cond;
|
||||||
import dmd.ctorflow;
|
import dmd.ctorflow;
|
||||||
import dmd.dscope;
|
import dmd.dscope;
|
||||||
import dmd.dsymbol;
|
import dmd.dsymbol;
|
||||||
|
@ -17406,3 +17407,198 @@ bool fill(StructDeclaration sd, Loc loc, ref Expressions elements, bool ctorinit
|
||||||
|
|
||||||
return !errors;
|
return !errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*****************************************
|
||||||
|
* 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:
|
||||||
|
* sfe = The 'static foreach'.
|
||||||
|
* sc = The current scope.
|
||||||
|
*/
|
||||||
|
extern (C++) void lowerNonArrayAggregate(StaticForeach sfe, Scope* sc)
|
||||||
|
{
|
||||||
|
import dmd.statement;
|
||||||
|
|
||||||
|
auto nvars = sfe.aggrfe ? sfe.aggrfe.parameters.length : 1;
|
||||||
|
auto aloc = sfe.aggrfe ? sfe.aggrfe.aggr.loc : sfe.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 = sfe.aggrfe ? (*sfe.aggrfe.parameters)[i] : sfe.rangefe.param;
|
||||||
|
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 = sfe.createTupleType(aloc, e, sc);
|
||||||
|
}
|
||||||
|
res[i] = sfe.createTuple(aloc, tplty, e);
|
||||||
|
}
|
||||||
|
sfe.needExpansion = true; // need to expand the tuples later
|
||||||
|
}
|
||||||
|
// generate remaining code for the new aggregate which is an
|
||||||
|
// array (see documentation comment).
|
||||||
|
if (sfe.rangefe)
|
||||||
|
{
|
||||||
|
sc = sc.startCTFE();
|
||||||
|
sfe.rangefe.lwr = sfe.rangefe.lwr.expressionSemantic(sc);
|
||||||
|
sfe.rangefe.lwr = resolveProperties(sc, sfe.rangefe.lwr);
|
||||||
|
sfe.rangefe.upr = sfe.rangefe.upr.expressionSemantic(sc);
|
||||||
|
sfe.rangefe.upr = resolveProperties(sc, sfe.rangefe.upr);
|
||||||
|
sc = sc.endCTFE();
|
||||||
|
sfe.rangefe.lwr = sfe.rangefe.lwr.optimize(WANTvalue);
|
||||||
|
sfe.rangefe.lwr = sfe.rangefe.lwr.ctfeInterpret();
|
||||||
|
sfe.rangefe.upr = sfe.rangefe.upr.optimize(WANTvalue);
|
||||||
|
sfe.rangefe.upr = sfe.rangefe.upr.ctfeInterpret();
|
||||||
|
}
|
||||||
|
auto s1 = new Statements();
|
||||||
|
auto stmts = new Statements();
|
||||||
|
if (tplty) stmts.push(new ExpStatement(sfe.loc, tplty.sym));
|
||||||
|
stmts.push(new ReturnStatement(aloc, res[0]));
|
||||||
|
s1.push(sfe.createForeach(aloc, pparams[0], new CompoundStatement(aloc, stmts)));
|
||||||
|
s1.push(new ExpStatement(aloc, new AssertExp(aloc, IntegerExp.literal!0)));
|
||||||
|
Type ety = new TypeTypeof(aloc, sfe.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(sfe.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(sfe.createForeach(aloc, pparams[1], new ExpStatement(aloc, catass)));
|
||||||
|
s2.push(new ReturnStatement(aloc, new IdentifierExp(aloc, idres)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression aggr = void;
|
||||||
|
Type indexty = void;
|
||||||
|
|
||||||
|
if (sfe.rangefe && (indexty = ety).isIntegral())
|
||||||
|
{
|
||||||
|
sfe.rangefe.lwr.type = indexty;
|
||||||
|
sfe.rangefe.upr.type = indexty;
|
||||||
|
auto lwrRange = getIntRange(sfe.rangefe.lwr);
|
||||||
|
auto uprRange = getIntRange(sfe.rangefe.upr);
|
||||||
|
|
||||||
|
const lwr = sfe.rangefe.lwr.toInteger();
|
||||||
|
auto upr = sfe.rangefe.upr.toInteger();
|
||||||
|
size_t length = 0;
|
||||||
|
|
||||||
|
if (lwrRange.imin <= uprRange.imax)
|
||||||
|
length = cast(size_t) (upr - lwr);
|
||||||
|
|
||||||
|
auto exps = new Expressions(length);
|
||||||
|
|
||||||
|
if (sfe.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 = sfe.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(!!sfe.aggrfe ^ !!sfe.rangefe);
|
||||||
|
sfe.aggrfe = new ForeachStatement(sfe.loc, TOK.foreach_, pparams[2], aggr,
|
||||||
|
sfe.aggrfe ? sfe.aggrfe._body : sfe.rangefe._body,
|
||||||
|
sfe.aggrfe ? sfe.aggrfe.endloc : sfe.rangefe.endloc);
|
||||||
|
sfe.rangefe = null;
|
||||||
|
sfe.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(StaticForeach sfe, Scope* sc)
|
||||||
|
{
|
||||||
|
assert(sc);
|
||||||
|
|
||||||
|
if (sfe.aggrfe)
|
||||||
|
{
|
||||||
|
sc = sc.startCTFE();
|
||||||
|
sfe.aggrfe.aggr = sfe.aggrfe.aggr.expressionSemantic(sc);
|
||||||
|
sc = sc.endCTFE();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sfe.aggrfe && sfe.aggrfe.aggr.type.toBasetype().ty == Terror)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sfe.ready())
|
||||||
|
{
|
||||||
|
if (sfe.aggrfe && sfe.aggrfe.aggr.type.toBasetype().ty == Tarray)
|
||||||
|
{
|
||||||
|
sfe.lowerArrayAggregate(sc);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sfe.lowerNonArrayAggregate(sc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -7550,6 +7550,8 @@ public:
|
||||||
void visit(StaticForeachDeclaration* sfd) override;
|
void visit(StaticForeachDeclaration* sfd) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern void lowerNonArrayAggregate(StaticForeach* sfe, Scope* sc);
|
||||||
|
|
||||||
class NrvoWalker final : public StatementRewriteWalker
|
class NrvoWalker final : public StatementRewriteWalker
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue