Skip to content
Open
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
6 changes: 6 additions & 0 deletions dstep/translator/MacroDefinition.d
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,9 @@ string translate(Expression expression, ExpressionContext context)
translateBinaryOperator!OrExpr,
translateBinaryOperator!LogicalAndExpr,
translateBinaryOperator!LogicalOrExpr,
translateBinaryOperator!AndAssignExpr,
translateBinaryOperator!XorAssignExpr,
translateBinaryOperator!OrAssignExpr,
delegate string(CondExpr condExpr)
{
return format(
Expand Down Expand Up @@ -403,6 +406,9 @@ void guessParamTypes(Expression expression, ref ExprType[string] params, ExprTyp
guessBinaryOperator!OrExpr,
guessBinaryOperator!LogicalAndExpr,
guessBinaryOperator!LogicalOrExpr,
guessBinaryOperator!AndAssignExpr,
guessBinaryOperator!XorAssignExpr,
guessBinaryOperator!OrAssignExpr,
delegate void(CondExpr condExpr)
{
condExpr.expr.guessParamTypes(params, type);
Expand Down
70 changes: 66 additions & 4 deletions dstep/translator/MacroParser.d
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,15 @@ class LogicalAndExpr : BinaryExpr
class LogicalOrExpr : BinaryExpr
{ }

class AndAssignExpr : BinaryExpr
{ }

class XorAssignExpr : BinaryExpr
{ }

class OrAssignExpr : BinaryExpr
{ }

class CondExpr
{
Expression expr;
Expand Down Expand Up @@ -530,6 +539,9 @@ alias Expression = Algebraic!(
OrExpr,
LogicalAndExpr,
LogicalOrExpr,
AndAssignExpr,
XorAssignExpr,
OrAssignExpr,
CondExpr);

Expression debraced(Expression expression)
Expand Down Expand Up @@ -1032,6 +1044,56 @@ Expression parseCondExpr(ref Token[] tokens, Cursor[string] table, bool defined)
return expr;
}

Expression parseAssignExpr(ref Token[] tokens, Cursor[string] table, bool defined)
{
auto local = tokens;

Expression expr = parseCondExpr(local, table, defined);

if (!expr.hasValue)
return Expression.init;

string op;

if (accept!("&=", "^=", "|=")(local, op, TokenKind.punctuation))
{
Expression rhs = parseAssignExpr(local, table, defined);

if (!rhs.hasValue)
return Expression.init;

tokens = local;

if (op == "&=")
{
auto result = new AndAssignExpr;
result.left = expr;
result.right = rhs;
result.operator = op;
return Expression(result);
}
else if (op == "^=")
{
auto result = new XorAssignExpr;
result.left = expr;
result.right = rhs;
result.operator = op;
return Expression(result);
}
else
{
auto result = new OrAssignExpr;
result.left = expr;
result.right = rhs;
result.operator = op;
return Expression(result);
}
}

tokens = local;
return expr;
}

bool parseBasicSpecifier(ref Token[] tokens, ref string spelling, Cursor[string] table)
{
import std.meta : AliasSeq;
Expand Down Expand Up @@ -1425,10 +1487,10 @@ Expression parseExpr(ref Token[] tokens, Cursor[string] table, bool defined)
if (concatExpr.hasValue)
return concatExpr;

auto condExpr = parseCondExpr(tokens, table, defined);
auto assignExpr = parseAssignExpr(tokens, table, defined);

if (condExpr.hasValue)
return condExpr;
if (assignExpr.hasValue)
return assignExpr;

return Expression.init;
}
Expand All @@ -1437,7 +1499,7 @@ Expression parseExpr(ref Token[] tokens, bool defined)
{
Cursor[string] table;

return parseCondExpr(tokens, table, defined);
return parseAssignExpr(tokens, table, defined);
}

Expression parseEnumMember(Token[] tokens, Cursor[string] table)
Expand Down
3 changes: 3 additions & 0 deletions dstep/translator/TypeInference.d
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,9 @@ InferredType inferExpressionType(Expression expression)
inferBinaryOperator!OrExpr,
inferBinaryOperator!LogicalAndExpr,
inferBinaryOperator!LogicalOrExpr,
inferBinaryOperator!AndAssignExpr,
inferBinaryOperator!XorAssignExpr,
inferBinaryOperator!OrAssignExpr,
delegate InferredType(CondExpr condExpr)
{
return commonType(
Expand Down
34 changes: 34 additions & 0 deletions tests/unit/MacroTranslTests.d
Original file line number Diff line number Diff line change
Expand Up @@ -841,3 +841,37 @@ extern (D) auto fun(T)(auto ref T a)
}
D");
}

// Translate compound assignment operators &=, ^=, |=.
unittest
{
assertTME("#define FOO(a, b) a &= b", "a &= b");
assertTME("#define FOO(a, b) a ^= b", "a ^= b");
assertTME("#define FOO(a, b) a |= b", "a |= b");
}

// Compound assignment operators are right-associative.
unittest
{
assertTME("#define FOO(a, b, c) a &= b |= c", "a &= b |= c");
assertTME("#define FOO(a, b, c) a ^= b &= c", "a ^= b &= c");
assertTME("#define FOO(a, b, c) a |= b ^= c", "a |= b ^= c");
assertTME("#define FOO(a, b, c, d) a &= b |= c ^= d", "a &= b |= c ^= d");
}

// Compound assignment has lower precedence than conditional ?:.
unittest
{
assertTME("#define FOO(a, b, c, d) a &= b ? c : d", "a &= b ? c : d");
assertTME("#define FOO(a, b, c, d) a ^= b ? c : d", "a ^= b ? c : d");
assertTME("#define FOO(a, b, c, d) a |= b ? c : d", "a |= b ? c : d");
}

// Compound assignment mixed with other operators.
unittest
{
assertTME("#define FOO(a, b, c) a &= b & !c", "a &= b & !c");
assertTME("#define FOO(a, b, c) a ^= ~b + c", "a ^= ~b + c");
assertTME("#define FOO(a, b, c, d) d &= a |= b && c", "d &= a |= b && c");
assertTME("#define FOO(a, b, c, d) d ^= a ? ~c % d : c * ~d ^ -(b ? c & d : d) | c", "d ^= a ? ~c % d : c * ~d ^ -(b ? c & d : d) | c");
}