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

Feature: Member of Operator #16161

Closed
wants to merge 14 commits into from
Closed
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
16 changes: 16 additions & 0 deletions compiler/src/dmd/astbase.d
Original file line number Diff line number Diff line change
Expand Up @@ -5409,6 +5409,22 @@ struct ASTBase
}
}

extern (C++) class MemberOfOperatorExp : Expression
{
Identifier ident;

extern (D) this(const ref Loc loc, Identifier ident)
{
super(loc, EXP.memberOf, __traits(classInstanceSize, MemberOfOperatorExp));
this.ident = ident;
}

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

extern (C++) class ThisExp : Expression
{
final extern (D) this(const ref Loc loc)
Expand Down
2 changes: 2 additions & 0 deletions compiler/src/dmd/astenums.d
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ enum TY : ubyte
Tchar,
Twchar,
Tdchar,
Tmemberof,
Terror,
Tinstance,
Ttypeof,
Expand Down Expand Up @@ -251,6 +252,7 @@ alias Tbool = TY.Tbool;
alias Tchar = TY.Tchar;
alias Twchar = TY.Twchar;
alias Tdchar = TY.Tdchar;
alias Tmemberof = TY.Tmemberof;
alias Terror = TY.Terror;
alias Tinstance = TY.Tinstance;
alias Ttypeof = TY.Ttypeof;
Expand Down
1 change: 1 addition & 0 deletions compiler/src/dmd/basicmangle.d
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ immutable char[TMAX] mangleChar =
Tmixin : '@',
Ttag : '@',
Tnoreturn : '@', // becomes 'Nn'
Tmemberof : '@', // member of is an internal rewrite for delayed semantic
];

unittest
Expand Down
17 changes: 17 additions & 0 deletions compiler/src/dmd/expression.d
Original file line number Diff line number Diff line change
Expand Up @@ -717,6 +717,7 @@ extern (C++) abstract class Expression : ASTNode
inout(ComplexExp) isComplexExp() { return op == EXP.complex80 ? cast(typeof(return))this : null; }
inout(IdentifierExp) isIdentifierExp() { return op == EXP.identifier ? cast(typeof(return))this : null; }
inout(DollarExp) isDollarExp() { return op == EXP.dollar ? cast(typeof(return))this : null; }
inout(MemberOfOperatorExp) isMemberOfExp() { return op == EXP.memberOf ? cast(typeof(return))this : null; }
inout(DsymbolExp) isDsymbolExp() { return op == EXP.dSymbol ? cast(typeof(return))this : null; }
inout(ThisExp) isThisExp() { return op == EXP.this_ ? cast(typeof(return))this : null; }
inout(SuperExp) isSuperExp() { return op == EXP.super_ ? cast(typeof(return))this : null; }
Expand Down Expand Up @@ -1352,6 +1353,22 @@ extern (C++) final class DollarExp : IdentifierExp
}
}

extern (C++) class MemberOfOperatorExp : Expression
{
Identifier ident;

extern (D) this(const ref Loc loc, Identifier ident) scope @safe
{
super(loc, EXP.memberOf);
this.ident = ident;
}

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

/***********************************************************
* Won't be generated by parser.
*/
Expand Down
8 changes: 8 additions & 0 deletions compiler/src/dmd/expression.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ class Expression : public ASTNode
ComplexExp* isComplexExp();
IdentifierExp* isIdentifierExp();
DollarExp* isDollarExp();
MemberOfOperatorExp* isMemberOfExp();
DsymbolExp* isDsymbolExp();
ThisExp* isThisExp();
SuperExp* isSuperExp();
Expand Down Expand Up @@ -1057,6 +1058,13 @@ class AddAssignExp final : public BinAssignExp
void accept(Visitor *v) override { v->visit(this); }
};

class MemberOfOperator : public Expression
{
public:
Identifier* ident;
void accept(Visitor* v) override { v->visit(this); }
};

class MinAssignExp final : public BinAssignExp
{
public:
Expand Down
21 changes: 21 additions & 0 deletions compiler/src/dmd/expressionsem.d
Original file line number Diff line number Diff line change
Expand Up @@ -3149,6 +3149,14 @@ private bool functionParameters(const ref Loc loc, Scope* sc,
if (!((hasCopyCtor && typesMatch) || tprm.equals(arg.type)))
{
//printf("arg.type = %s, p.type = %s\n", arg.type.toChars(), p.type.toChars());

if (auto moexp = arg.isMemberOfExp)
{
TypeExp paramExpr = new TypeExp(moexp.loc, tprm);
Expression getMember = cast(Expression)new DotIdExp(moexp.loc, paramExpr, moexp.ident);
arg = getMember.expressionSemantic(sc);
}

arg = arg.implicitCastTo(sc, tprm);
arg = arg.optimize(WANTvalue, p.isReference());
}
Expand Down Expand Up @@ -3982,6 +3990,13 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
result = ErrorExp.get();
}

override void visit(MemberOfOperatorExp e)
{
// this will be handled elsewhere
e.type = Type.tmemberOfOperator;
result = e;
}

override void visit(DsymbolExp e)
{
result = symbolToExp(e.s, e.loc, sc, e.hasOverloads);
Expand Down Expand Up @@ -10527,7 +10542,13 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
* depends on the result of e1 in assignments.
*/
{
// If the expression is a member of operator,
// rewrite it to be typeof(var).Identifier
if (auto moexp = exp.e2.isMemberOfExp)
exp.e2 = new DotIdExp(exp.e2.loc, exp.e1, moexp.ident);

Expression e2x = inferType(exp.e2, t1.baseElemOf());

e2x = e2x.expressionSemantic(sc);
if (!t1.isTypeSArray())
e2x = e2x.arrayFuncConv(sc);
Expand Down
119 changes: 68 additions & 51 deletions compiler/src/dmd/frontend.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ class RealExp;
class ComplexExp;
class IdentifierExp;
class DollarExp;
class MemberOfOperatorExp;
class DsymbolExp;
class ThisExp;
class SuperExp;
Expand Down Expand Up @@ -1103,6 +1104,7 @@ class ParseTimeVisitor
virtual void visit(typename AST::TypeExp e);
virtual void visit(typename AST::ScopeExp e);
virtual void visit(typename AST::IdentifierExp e);
virtual void visit(typename AST::MemberOfOperatorExp e);
virtual void visit(typename AST::UnaExp e);
virtual void visit(typename AST::DefaultInitExp e);
virtual void visit(typename AST::BinExp e);
Expand Down Expand Up @@ -1685,20 +1687,21 @@ enum class TY : uint8_t
Tchar = 31u,
Twchar = 32u,
Tdchar = 33u,
Terror = 34u,
Tinstance = 35u,
Ttypeof = 36u,
Ttuple = 37u,
Tslice = 38u,
Treturn = 39u,
Tnull = 40u,
Tvector = 41u,
Tint128 = 42u,
Tuns128 = 43u,
Ttraits = 44u,
Tmixin = 45u,
Tnoreturn = 46u,
Ttag = 47u,
Tmemberof = 34u,
Terror = 35u,
Tinstance = 36u,
Ttypeof = 37u,
Ttuple = 38u,
Tslice = 39u,
Treturn = 40u,
Tnull = 41u,
Tvector = 42u,
Tint128 = 43u,
Tuns128 = 44u,
Ttraits = 45u,
Tmixin = 46u,
Tnoreturn = 47u,
Ttag = 48u,
};

typedef uint64_t dinteger_t;
Expand Down Expand Up @@ -1783,6 +1786,7 @@ class Type : public ASTNode
static Type* tsize_t;
static Type* tptrdiff_t;
static Type* thash_t;
static Type* tmemberOfOperator;
static ClassDeclaration* dtypeinfo;
static ClassDeclaration* typeinfoclass;
static ClassDeclaration* typeinfointerface;
Expand All @@ -1801,7 +1805,7 @@ class Type : public ASTNode
static ClassDeclaration* typeinfoshared;
static ClassDeclaration* typeinfowild;
static TemplateDeclaration* rtinfo;
static Type* basic[48LLU];
static Type* basic[49LLU];
virtual const char* kind() const;
Type* copy() const;
virtual Type* syntaxCopy();
Expand Down Expand Up @@ -2053,39 +2057,40 @@ enum class EXP : uint8_t
halt = 92u,
tuple = 93u,
error = 94u,
void_ = 95u,
int64 = 96u,
float64 = 97u,
complex80 = 98u,
import_ = 99u,
delegate_ = 100u,
function_ = 101u,
mixin_ = 102u,
in_ = 103u,
break_ = 104u,
continue_ = 105u,
goto_ = 106u,
scope_ = 107u,
traits = 108u,
overloadSet = 109u,
line = 110u,
file = 111u,
fileFullPath = 112u,
moduleString = 113u,
functionString = 114u,
prettyFunction = 115u,
pow = 116u,
powAssign = 117u,
vector = 118u,
voidExpression = 119u,
cantExpression = 120u,
showCtfeContext = 121u,
objcClassReference = 122u,
vectorArray = 123u,
compoundLiteral = 124u,
_Generic_ = 125u,
interval = 126u,
loweredAssignExp = 127u,
memberOf = 95u,
void_ = 96u,
int64 = 97u,
float64 = 98u,
complex80 = 99u,
import_ = 100u,
delegate_ = 101u,
function_ = 102u,
mixin_ = 103u,
in_ = 104u,
break_ = 105u,
continue_ = 106u,
goto_ = 107u,
scope_ = 108u,
traits = 109u,
overloadSet = 110u,
line = 111u,
file = 112u,
fileFullPath = 113u,
moduleString = 114u,
functionString = 115u,
prettyFunction = 116u,
pow = 117u,
powAssign = 118u,
vector = 119u,
voidExpression = 120u,
cantExpression = 121u,
showCtfeContext = 122u,
objcClassReference = 123u,
vectorArray = 124u,
compoundLiteral = 125u,
_Generic_ = 126u,
interval = 127u,
loweredAssignExp = 128u,
};

struct complex_t final
Expand Down Expand Up @@ -2148,6 +2153,7 @@ class Expression : public ASTNode
ComplexExp* isComplexExp();
IdentifierExp* isIdentifierExp();
DollarExp* isDollarExp();
MemberOfOperatorExp* isMemberOfExp();
DsymbolExp* isDsymbolExp();
ThisExp* isThisExp();
SuperExp* isSuperExp();
Expand Down Expand Up @@ -3069,6 +3075,13 @@ class LoweredAssignExp final : public AssignExp
void accept(Visitor* v) override;
};

class MemberOfOperatorExp : public Expression
{
public:
Identifier* ident;
void accept(Visitor* v) override;
};

class MinAssignExp final : public BinAssignExp
{
public:
Expand Down Expand Up @@ -5775,6 +5788,7 @@ struct ASTCodegen final
using LineInitExp = ::LineInitExp;
using LogicalExp = ::LogicalExp;
using LoweredAssignExp = ::LoweredAssignExp;
using MemberOfOperatorExp = ::MemberOfOperatorExp;
using MemorySet = ::MemorySet;
using MinAssignExp = ::MinAssignExp;
using MinExp = ::MinExp;
Expand Down Expand Up @@ -6243,6 +6257,7 @@ struct CompileEnv final
bool previewIn;
bool ddocOutput;
bool masm;
bool ignoreMemberOf;
CompileEnv() :
versionNumber(),
date(),
Expand All @@ -6251,18 +6266,20 @@ struct CompileEnv final
timestamp(),
previewIn(),
ddocOutput(),
masm()
masm(),
ignoreMemberOf()
{
}
CompileEnv(uint32_t versionNumber, _d_dynamicArray< const char > date = {}, _d_dynamicArray< const char > time = {}, _d_dynamicArray< const char > vendor = {}, _d_dynamicArray< const char > timestamp = {}, bool previewIn = false, bool ddocOutput = false, bool masm = false) :
CompileEnv(uint32_t versionNumber, _d_dynamicArray< const char > date = {}, _d_dynamicArray< const char > time = {}, _d_dynamicArray< const char > vendor = {}, _d_dynamicArray< const char > timestamp = {}, bool previewIn = false, bool ddocOutput = false, bool masm = false, bool ignoreMemberOf = false) :
versionNumber(versionNumber),
date(date),
time(time),
vendor(vendor),
timestamp(timestamp),
previewIn(previewIn),
ddocOutput(ddocOutput),
masm(masm)
masm(masm),
ignoreMemberOf(ignoreMemberOf)
{}
};

Expand Down
2 changes: 2 additions & 0 deletions compiler/src/dmd/globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,8 @@ struct CompileEnv
DString timestamp;
d_bool previewIn;
d_bool ddocOutput;
d_bool masm;
d_bool ignoreMemberOf;
};

struct Global
Expand Down
1 change: 1 addition & 0 deletions compiler/src/dmd/hdrgen.d
Original file line number Diff line number Diff line change
Expand Up @@ -4401,6 +4401,7 @@ string EXPtoString(EXP op)
EXP.void_ : "void",
EXP.vectorArray : "vectorarray",
EXP._Generic : "_Generic",
EXP.memberOf : "memberofoperator",

// post
EXP.dotTemplateInstance : "dotti",
Expand Down
10 changes: 8 additions & 2 deletions compiler/src/dmd/iasmgcc.d
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,9 @@
{
//printf("GccAsmStatement.semantic()\n");
const bool doUnittests = global.params.parsingUnittestsRequired();
scope p = new Parser!ASTCodegen(sc._module, ";", false, global.errorSink, &global.compileEnv, doUnittests);
CompileEnv cenv = global.compileEnv;
cenv.ignoreMemberOf = true;
scope p = new Parser!ASTCodegen(sc._module, ";", false, global.errorSink, &cenv, doUnittests);

Check warning on line 308 in compiler/src/dmd/iasmgcc.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/iasmgcc.d#L306-L308

Added lines #L306 - L308 were not covered by tests

// Make a safe copy of the token list before parsing.
Token *toklist = null;
Expand Down Expand Up @@ -412,8 +414,12 @@
const errors = global.errors;
scope gas = new GccAsmStatement(Loc.initial, tokens);
const bool doUnittests = false;
scope p = new Parser!ASTCodegen(null, ";", false, global.errorSink, &global.compileEnv, doUnittests);

CompileEnv cenv = global.compileEnv;
cenv.ignoreMemberOf = true;
scope p = new Parser!ASTCodegen(null, ";", false, global.errorSink, &cenv, doUnittests);
p.token = *tokens;

p.parseGccAsm(gas);
return global.errors - errors;
}
Expand Down
1 change: 1 addition & 0 deletions compiler/src/dmd/impcnvtab.d
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ ImpCnvTab generateImpCnvTab()
Tchar,
Twchar,
Tdchar,
Tmemberof,
Terror,
Tinstance,
Ttypeof,
Expand Down
Loading
Loading