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

[WIP] Implement DIP 1044 #14650

Closed
wants to merge 13 commits into from
72 changes: 68 additions & 4 deletions compiler/src/dmd/dcast.d
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,11 @@ Expression implicitCastTo(Expression e, Scope* sc, Type t)
return result;
}

Expression visitInference(InferenceExp e)
{
return inferType(e, t);
}

switch (e.op)
{
default : return visit (e);
Expand All @@ -213,6 +218,7 @@ Expression implicitCastTo(Expression e, Scope* sc, Type t)
case EXP.function_ : return visitFunc (e.isFuncExp());
case EXP.arrayLiteral: return visitArrayLiteral(e.isArrayLiteralExp());
case EXP.slice : return visitSlice (e.isSliceExp());
case EXP.inference : return visitInference (e.isInferenceExp());
}
}

Expand Down Expand Up @@ -2647,6 +2653,17 @@ Expression inferType(Expression e, Type t, int flag = 0)
{
Expression visitAle(ArrayLiteralExp ale)
{
// treat inference exps if there are any.
for (size_t i = 0; i < ale.elements.length; i++)
{
Expression e = (*ale.elements)[i];
if (e && e.isInferenceExp())
{
e = inferType(e, t, flag);
(*ale.elements)[i] = e;
}
}

Type tb = t.toBasetype();
if (tb.ty == Tarray || tb.ty == Tsarray)
{
Expand All @@ -2665,6 +2682,39 @@ Expression inferType(Expression e, Type t, int flag = 0)
return ale;
}

Expression visitInfer(InferenceExp infe)
{
TypeEnum et = t.isTypeEnum();

if (!et)
{
infe.error("$id will only work for enums");
return ErrorExp.get();
}

auto member = et.sym.symtab.lookup(infe.id);

if (!member || !member.isEnumMember)
{
uint gag;
if (flag)
{
gag = global.startGagging();
}
infe.error("Could not find %s in %s", infe.id.toChars(), infe.type.toPrettyChars());
scope(exit)
{
global.endGagging(gag);
}
return ErrorExp.get();
}

(*cast(Expression*)&infe) = member.isEnumMember.value();
infe.type = t;

return infe;
}

Expression visitAar(AssocArrayLiteralExp aale)
{
Type tb = t.toBasetype();
Expand Down Expand Up @@ -2710,12 +2760,26 @@ Expression inferType(Expression e, Type t, int flag = 0)
return ce;
}

Expression visitBin(BinExp be)
{
if (!be) return e;
// the range we are dispatching on has things in it
// which are not binary exps
// so we need to early exit on null
Type tb = t.ty == TY.Tenum ? t : t.toBasetype();
be.e1 = inferType(be.e1, tb, flag);
be.e2 = inferType(be.e2, tb, flag);
return be;
}

if (t) switch (e.op)
{
case EXP.arrayLiteral: return visitAle(e.isArrayLiteralExp());
case EXP.assocArrayLiteral: return visitAar(e.isAssocArrayLiteralExp());
case EXP.function_: return visitFun(e.isFuncExp());
case EXP.question: return visitTer(e.isCondExp());
case EXP.arrayLiteral: return visitAle(e.isArrayLiteralExp());
case EXP.assocArrayLiteral: return visitAar(e.isAssocArrayLiteralExp());
case EXP.function_: return visitFun(e.isFuncExp());
case EXP.question: return visitTer(e.isCondExp());
case EXP.inference: return visitInfer(e.isInferenceExp());
case EXP.lessThan: .. case EXP.assign: return visitBin(e.isBinExp());
default:
}
return e;
Expand Down
8 changes: 8 additions & 0 deletions compiler/src/dmd/dinterpret.d
Original file line number Diff line number Diff line change
Expand Up @@ -2160,6 +2160,12 @@ public:
return e;
}

override void visit(InferenceExp e)
{
result = e;
return ;
}

override void visit(VarExp e)
{
debug (LOG)
Expand Down Expand Up @@ -7028,6 +7034,8 @@ private Expression copyRegionExp(Expression e)
case EXP.null_:
case EXP.void_:
case EXP.symbolOffset:
case EXP.char_:
case EXP.inference:
break;

case EXP.cantExpression:
Expand Down
18 changes: 18 additions & 0 deletions compiler/src/dmd/expression.d
Original file line number Diff line number Diff line change
Expand Up @@ -1846,6 +1846,8 @@ extern (C++) abstract class Expression : ASTNode
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(InferenceExp) isInferenceExp() { return op == EXP.inference ? cast(typeof(return)) this : null; }

inout(UnaExp) isUnaExp() pure inout nothrow @nogc
{
return exptab[op] & EXPFLAGS.unary ? cast(typeof(return))this : null;
Expand Down Expand Up @@ -4898,6 +4900,22 @@ extern (C++) final class DotIdExp : UnaExp
}
}

extern (C++) final class InferenceExp : Expression
{
Identifier id;

extern (D) this(const ref Loc loc, Identifier id)
{
super(loc, EXP.inference, __traits(classInstanceSize, InferenceExp));
this.id = id;
}

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

/***********************************************************
* Mainly just a placeholder
*/
Expand Down
18 changes: 17 additions & 1 deletion compiler/src/dmd/expressionsem.d
Original file line number Diff line number Diff line change
Expand Up @@ -9109,7 +9109,23 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
* depends on the result of e1 in assignments.
*/
{
Expression e2x = inferType(exp.e2, t1.baseElemOf());
Type infType = t1;
if (auto tsa = t1.isTypeSArray())
{
infType = tsa.next;
}
else if (auto ta = t1.isTypeDArray())
{
infType = ta.next;
}

if (!infType.isTypeEnum())
{
infType = t1.baseElemOf();
}


Expression e2x = inferType(exp.e2, infType);
e2x = e2x.expressionSemantic(sc);
if (!t1.isTypeSArray())
e2x = e2x.arrayFuncConv(sc);
Expand Down
14 changes: 13 additions & 1 deletion compiler/src/dmd/frontend.h
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ class PrettyFuncInitExp;
class ObjcClassReferenceExp;
class ClassReferenceExp;
class ThrownExceptionExp;
class InferenceExp;
class UnaExp;
class BinExp;
class BinAssignExp;
Expand Down Expand Up @@ -925,7 +926,8 @@ enum class EXP : uint8_t
compoundLiteral = 123u,
_Generic = 124u,
interval = 125u,
loweredAssignExp = 126u,
inference = 126u,
loweredAssignExp = 127u,
};

typedef uint64_t dinteger_t;
Expand Down Expand Up @@ -1118,6 +1120,7 @@ class Expression : public ASTNode
ObjcClassReferenceExp* isObjcClassReferenceExp();
ClassReferenceExp* isClassReferenceExp();
ThrownExceptionExp* isThrownExceptionExp();
InferenceExp* isInferenceExp();
UnaExp* isUnaExp();
BinExp* isBinExp();
BinAssignExp* isBinAssignExp();
Expand Down Expand Up @@ -4953,6 +4956,7 @@ struct ASTCodegen final
using ImportExp = ::ImportExp;
using InExp = ::InExp;
using IndexExp = ::IndexExp;
using InferenceExp = ::InferenceExp;
using IntegerExp = ::IntegerExp;
using IntervalExp = ::IntervalExp;
using IsExp = ::IsExp;
Expand Down Expand Up @@ -5222,6 +5226,7 @@ class Visitor : public ParseTimeVisitor<ASTCodegen >
virtual void visit(ClassReferenceExp* e);
virtual void visit(VoidInitExp* e);
virtual void visit(ThrownExceptionExp* e);
virtual void visit(InferenceExp* e);
virtual void visit(LoweredAssignExp* e);
};

Expand Down Expand Up @@ -7482,6 +7487,13 @@ class DotIdExp final : public UnaExp
void accept(Visitor* v) override;
};

class InferenceExp final : public Expression
{
public:
Identifier* id;
void accept(Visitor* v) override;
};

class DotTemplateExp final : public UnaExp
{
public:
Expand Down
7 changes: 7 additions & 0 deletions compiler/src/dmd/hdrgen.d
Original file line number Diff line number Diff line change
Expand Up @@ -2627,6 +2627,12 @@ private void expressionPrettyPrint(Expression e, OutBuffer* buf, HdrGenState* hg
buf.writestring(e.value.toChars());
}

void visitInference(InferenceExp e)
{
buf.writeByte('$');
buf.writestring(e.id.toString());
}

switch (e.op)
{
default:
Expand Down Expand Up @@ -2700,6 +2706,7 @@ private void expressionPrettyPrint(Expression e, OutBuffer* buf, HdrGenState* hg
case EXP.remove: return visitRemove(e.isRemoveExp());
case EXP.question: return visitCond(e.isCondExp());
case EXP.classReference: return visitClassReference(e.isClassReferenceExp());
case EXP.inference: return visitInference(e.isInferenceExp());
case EXP.loweredAssignExp: return visitLoweredAssignExp(e.isLoweredAssignExp());
}
}
Expand Down
22 changes: 20 additions & 2 deletions compiler/src/dmd/mtype.d
Original file line number Diff line number Diff line change
Expand Up @@ -7310,12 +7310,30 @@ private extern(D) bool isCopyConstructorCallable (StructDeclaration argStruct,
private extern(D) MATCH argumentMatchParameter (TypeFunction tf, Parameter p,
Expression arg, ubyte wildmatch, int flag, Scope* sc, const(char)** pMessage)
{
//printf("arg: %s, type: %s\n", arg.toChars(), arg.type.toChars());
// printf("arg: %s, type: %s\n", arg.toChars(), arg.type.toChars());
MATCH m;
Type targ = arg.type;
Type tprm = wildmatch ? p.type.substWildTo(wildmatch) : p.type;

if (p.isLazy() && tprm.ty == Tvoid && targ.ty != Tvoid)
if (InferenceExp ie = arg.isInferenceExp())
{
// asm {int 3;}
TypeEnum tEnum = p.type.isTypeEnum();
if (!tEnum)
{
m = MATCH.nomatch;
}
else
{
import dmd.dcast : inferType;
Expression inf = inferType(ie, tEnum, 1);
if (!inf.isErrorExp())
{
m = MATCH.convert;
}
}
}
else if (p.isLazy() && tprm.ty == Tvoid && targ.ty != Tvoid)
m = MATCH.convert;
else if (flag)
{
Expand Down
16 changes: 13 additions & 3 deletions compiler/src/dmd/parse.d
Original file line number Diff line number Diff line change
Expand Up @@ -7987,9 +7987,18 @@ LagainStc:
break;
}
case TOK.dollar:
if (!inBrackets)
error("`$` is valid only inside [] of index or slice");
e = new AST.DollarExp(loc);
if (peekNext() == TOK.identifier)
{
nextToken();
id = token.ident;
e = new AST.InferenceExp(loc, id);
}
else
{
if (!inBrackets)
error("`$` is valid only inside [] of index or slice");
e = new AST.DollarExp(loc);
}
nextToken();
break;

Expand Down Expand Up @@ -9570,6 +9579,7 @@ immutable PREC[EXP.max + 1] precedence =
EXP.delegateFunctionPointer : PREC.primary,
EXP.remove : PREC.primary,
EXP.tuple : PREC.primary,
EXP.inference : PREC.primary,
EXP.traits : PREC.primary,
EXP.overloadSet : PREC.primary,
EXP.void_ : PREC.primary,
Expand Down
1 change: 1 addition & 0 deletions compiler/src/dmd/tokens.d
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,7 @@ enum EXP : ubyte
compoundLiteral, // ( type-name ) { initializer-list }
_Generic,
interval,
inference, // $id

loweredAssignExp,
}
Expand Down
1 change: 1 addition & 0 deletions compiler/src/dmd/visitor.d
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ public:
void visit(ASTCodegen.ClassReferenceExp e) { visit(cast(ASTCodegen.Expression)e); }
void visit(ASTCodegen.VoidInitExp e) { visit(cast(ASTCodegen.Expression)e); }
void visit(ASTCodegen.ThrownExceptionExp e) { visit(cast(ASTCodegen.Expression)e); }
void visit(ASTCodegen.InferenceExp e) { visit(cast(ASTCodegen.Expression)e); }
void visit(ASTCodegen.LoweredAssignExp e) { visit(cast(ASTCodegen.AssignExp)e); }
}

Expand Down
Loading