Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
38 changes: 38 additions & 0 deletions compiler/src/dmd/astbase.d
Original file line number Diff line number Diff line change
Expand Up @@ -4760,6 +4760,7 @@ struct ASTBase
inout(PrettyFuncInitExp) isPrettyFuncInitExp() { return op == EXP.prettyFunction ? cast(typeof(return))this : null; }
inout(AssignExp) isConstructExp() { return op == EXP.construct ? cast(typeof(return))this : null; }
inout(AssignExp) isBlitExp() { return op == EXP.blit ? cast(typeof(return))this : null; }
inout(UnpackExp) isUnpackExp() { return op == EXP.unpack ? cast(typeof(return))this : null; }

inout(UnaExp) isUnaExp() pure inout nothrow @nogc
{
Expand Down Expand Up @@ -4799,6 +4800,43 @@ struct ASTBase
}
}

extern (C++) final class UnpackExp : Expression
{
Expressions* components;
Expression _init;

extern (D) this(Loc loc, Expressions* components, Expression _init)
{
super(loc, EXP.unpack, __traits(classInstanceSize, UnpackExp));
this.components = components;
this._init = _init;
}

override UnpackExp syntaxCopy()
{
static Expressions* arraySyntaxCopy(Expressions* exps)
{
Expressions* a = null;
if (exps)
{
a = new Expressions(exps.length);
foreach (i, e; *exps)
{
(*a)[i] = e ? e.syntaxCopy() : null;
}
}
return a;
}

return new UnpackExp(loc, arraySyntaxCopy(components), _init.syntaxCopy());
}

override void accept(Visitor v)
{
v.visit(this);
}
}

extern (C++) final class IntegerExp : Expression
{
dinteger_t value;
Expand Down
94 changes: 54 additions & 40 deletions compiler/src/dmd/attrib.d
Original file line number Diff line number Diff line change
Expand Up @@ -813,7 +813,6 @@ extern (C++) final class UnpackDeclaration : AttribDeclaration
{
assert(0);
}
import dmd.errors;
if (d_storage_class & STC.static_ && !(storage_class & STC.static_))
{
dmd.errors.error(loc, "cannot specify `static` for individual components of an unpack declaration");
Expand All @@ -833,6 +832,54 @@ extern (C++) final class UnpackDeclaration : AttribDeclaration
return true;
}

static TupleExp getTupleExp(Scope* sc, Expression _init)
{
TupleExp tup = null;

import dmd.tokens : EXP;
if (_init.type.ty == Ttuple && _init.op == EXP.tuple)
{
tup = cast(TupleExp)_init;
}
else
{
import dmd.dsymbolsem : resolveAliasThis;
_init = resolveAliasThis(sc, _init);
if (_init.type.ty == Ttuple && _init.op == EXP.tuple)
{
tup = cast(TupleExp)_init;
}
}
return tup;
}

static Expressions* expandTupleExp(Scope* sc, TupleExp tup, STC storage_class)
{
import dmd.expressionsem;

Expressions* exps = null;
if (tup.isAliasThisTuple())
{
import dmd.sideeffect: copyToTemp;
auto v = copyToTemp(storage_class, "__tup", tup);
import dmd.dsymbolsem : dsymbolSemantic;
v.dsymbolSemantic(sc);
auto ve = new VarExp(v.loc, v);
ve.type = tup.type;

exps = new Expressions();
exps.setDim(1);
(*exps)[0] = ve;
expandAliasThisTuples(exps, 0);
}
else
{
exps = tup.exps;
expandTuples(exps);
}
return exps;
}

final void lower(Scope* sc)
{
if (lowered)
Expand Down Expand Up @@ -874,28 +921,12 @@ extern (C++) final class UnpackDeclaration : AttribDeclaration
return fail();
}

TupleExp tup = null;
auto tinit = _init.type;

import dmd.tokens: EXP;
if (_init.type.ty == Ttuple && _init.op == EXP.tuple)
{
tup = cast(TupleExp)_init;
}
else
{
import dmd.dsymbolsem : resolveAliasThis;
_init = resolveAliasThis(sc, _init);
if (_init.type.ty == Ttuple && _init.op == EXP.tuple)
{
tup = cast(TupleExp)_init;
}
}
TupleExp tup = getTupleExp(sc, _init);

if (!tup)
{
dmd.errors.error(loc, "right hand side of unpack declaration must resolve to a tuple or expression sequence, not `%s`",
tinit.toChars());
_init.type.toChars());
return fail();
}
if (decl.length != tup.exps.length)
Expand All @@ -907,27 +938,10 @@ extern (C++) final class UnpackDeclaration : AttribDeclaration
if (!propagateStorageClasses())
return fail();

Expressions* exps = null;
if (tup.isAliasThisTuple())
{
assert(decl.length != 0);
import dmd.sideeffect: copyToTemp;
auto v = copyToTemp(storage_class, "__tup", tup);
import dmd.dsymbolsem : dsymbolSemantic;
v.dsymbolSemantic(sc);
auto ve = new VarExp(loc, v);
ve.type = tup.type;

exps = new Expressions();
exps.setDim(1);
(*exps)[0] = ve;
expandAliasThisTuples(exps, 0);
}
else
{
exps = tup.exps;
expandTuples(exps);
}
// if there's an `alias this` the length can't be zero
// see: https://github.com/dlang/dmd/issues/20842
assert(_init is tup || decl.length != 0);
Expressions* exps = expandTupleExp(sc, tup, storage_class);
assert(exps.length == decl.length);

foreach (i, d; *decl)
Expand Down
32 changes: 32 additions & 0 deletions compiler/src/dmd/expression.d
Original file line number Diff line number Diff line change
Expand Up @@ -728,6 +728,7 @@ extern (C++) abstract class Expression : ASTNode
inout(ObjcClassReferenceExp) isObjcClassReferenceExp() { return op == EXP.objcClassReference ? cast(typeof(return))this : null; }
inout(ClassReferenceExp) isClassReferenceExp() { return op == EXP.classReference ? cast(typeof(return))this : null; }
inout(ThrownExceptionExp) isThrownExceptionExp() { return op == EXP.thrownException ? cast(typeof(return))this : null; }
inout(UnpackExp) isUnpackExp() { return op == EXP.unpack ? cast(typeof(return))this : null; }

inout(UnaExp) isUnaExp() pure inout nothrow @nogc
{
Expand Down Expand Up @@ -2836,6 +2837,36 @@ extern (C++) final class DeclarationExp : Expression
}
}

/**
* `(x, auto y) = expressionSeq`
*
* Note: Not allowed as a general expression because it can introduce variable declarations.
*/
extern (C++) final class UnpackExp : Expression
{
// some can be DeclarationExp
Expressions* components;
Expression _init;

/// rhs = RHS seq/tuple expression
extern (D) this(Loc loc, Expressions* components, Expression _init) @safe
{
super(loc, EXP.unpack);
this.components = components;
this._init = _init;
}

override UnpackExp syntaxCopy()
{
return new UnpackExp(loc, arraySyntaxCopy(components), _init.syntaxCopy());
}

override void accept(Visitor v)
{
v.visit(this);
}
}

/***********************************************************
* typeid(int)
*/
Expand Down Expand Up @@ -5418,4 +5449,5 @@ private immutable ubyte[EXP.max+1] expSize = [
EXP._Generic: __traits(classInstanceSize, GenericExp),
EXP.interval: __traits(classInstanceSize, IntervalExp),
EXP.loweredAssignExp : __traits(classInstanceSize, LoweredAssignExp),
EXP.unpack : __traits(classInstanceSize, UnpackExp),
];
84 changes: 81 additions & 3 deletions compiler/src/dmd/expressionsem.d
Original file line number Diff line number Diff line change
Expand Up @@ -7015,9 +7015,7 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor

const olderrors = global.errors;

UnpackDeclaration u = e.declaration.isUnpackDeclaration();

if (u)
if (UnpackDeclaration u = e.declaration.isUnpackDeclaration())
{
Expression c = null;
import dmd.dsymbolsem : include;
Expand Down Expand Up @@ -13860,6 +13858,86 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
e.type = Type.tstring;
result = e.resolveLoc(e.loc, sc);
}

// lower to declarations and assignments
// E.g. `auto __tup = _init; auto x = __tup[0], y = __tup[1]`
override void visit(UnpackExp ue)
{
//printf("UnpackExp::semantic()\n");
import dmd.expressionsem;

auto _init = ue._init.expressionSemantic(sc);
_init = resolveProperties(sc, _init);
if (_init.type.ty == Terror)
return setError();

auto tup = UnpackDeclaration.getTupleExp(sc, _init);
if (!tup)
{
error(ue.loc, "right hand side of unpack statement must resolve to a tuple or expression sequence, not `%s`",
_init.type.toChars());
return setError();
}
if (ue.components.length != tup.exps.length)
{
error(ue.loc, "incompatible number of components for unpack statement (`%d` vs. `%d`)",
cast(int)ue.components.length, cast(int)tup.exps.length);
return setError();
}
// get elements of tup
auto exps = UnpackDeclaration.expandTupleExp(sc, tup, STC.none);
auto r = tup.e0; // __tup declaration if tup is struct

foreach (i, c; *ue.components)
{
auto exp = (*exps)[i];

if (auto de = c.isDeclarationExp())
{
auto sym = de.declaration;
STC stc;

if (auto vd = sym.isVarDeclaration())
{
stc = vd.storage_class;
vd._init = new ExpInitializer(exp.loc, exp);
}
else if (auto ud = sym.isUnpackDeclaration())
{
stc = ud.storage_class;
ud._init = exp;
}
else
{
assert(0, "unexpected unpack component");
}
if (stc & STC.static_)
{
error(sym.loc, "cannot specify `static` for unpack statement components");
return setError();
}
if (stc & STC.manifest)
{
error(sym.loc, "cannot specify `enum` for unpack statement components");
return setError();
}
r = Expression.combine(r, de);
}
else if (auto inner = c.isUnpackExp())
{
inner._init = exp;
r = Expression.combine(r, inner);
}
else
{
auto e = new AssignExp(c.loc, c, exp);
r = Expression.combine(r, e);
}
}
r.expressionSemantic(sc);
r = resolveProperties(sc, r);
result = r;
}
}

/**********************************
Expand Down
17 changes: 17 additions & 0 deletions compiler/src/dmd/hdrgen.d
Original file line number Diff line number Diff line change
Expand Up @@ -3029,6 +3029,21 @@ private void expressionPrettyPrint(Expression e, ref OutBuffer buf, ref HdrGenSt
buf.writestring(e.value.toChars());
}

void visitUnpackExp(UnpackExp e)
{
buf.writeByte('(');
argsToBuffer(e.components, buf, hgs, null);
if (e.components.length == 1)
buf.writeByte(',');

buf.writeByte(')');
if (e._init)
{
buf.writestring(" = ");
expressionPrettyPrint(e._init, buf, hgs);
}
}

if (e.rvalue)
buf.writestring("__rvalue(");

Expand Down Expand Up @@ -3112,6 +3127,7 @@ private void expressionPrettyPrint(Expression e, ref OutBuffer buf, ref HdrGenSt
case EXP.question: return visitCond(e.isCondExp());
case EXP.classReference: return visitClassReference(e.isClassReferenceExp());
case EXP.loweredAssignExp: return visitLoweredAssignExp(e.isLoweredAssignExp());
case EXP.unpack: return visitUnpackExp(e.isUnpackExp());
}
}

Expand Down Expand Up @@ -4594,6 +4610,7 @@ string EXPtoString(EXP op)
EXP.void_ : "void",
EXP.vectorArray : "vectorarray",
EXP._Generic : "_Generic",
EXP.unpack : "unpack",

// post
EXP.dotTemplateInstance : "dotti",
Expand Down
Loading
Loading