Skip to content

Commit

Permalink
Fix jacob-carlborg#199: Define of types results in incorrect output
Browse files Browse the repository at this point in the history
  • Loading branch information
ciechowoj committed Sep 30, 2018
1 parent a99c8c9 commit 6b9b3a5
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 15 deletions.
1 change: 1 addition & 0 deletions changelog.md
Expand Up @@ -69,6 +69,7 @@
* [Issue 160](https://github.com/jacob-carlborg/dstep/issues/160): Translating typedef of function pointer doesn't take line length into consideration.
* [Issue 166](https://github.com/jacob-carlborg/dstep/issues/166): macro used in struct declaration not translated properly
* [Issue 192](https://github.com/jacob-carlborg/dstep/issues/192): Fail to convert nuklear
* [Issue 199](https://github.com/jacob-carlborg/dstep/issues/199): `#define` of types results in incorrect output

## Version 0.2.1
### New/Changed Features
Expand Down
24 changes: 17 additions & 7 deletions dstep/translator/MacroDefinition.d
Expand Up @@ -579,22 +579,32 @@ string spelling(Expression expression)
return identifier.spelling;
}

void translateMacroDefinitionConstant(
void translateMacroDefinitionAliasOrConst(
Output output,
Context context,
TypedMacroDefinition definition)
{
auto expressionContext = ExpressionContext.make(context);

version (D1)
enum formatString = "const %s = %s;";
string formatString;
auto debraced = definition.definition.expr.debraced;

if (debraced.peek!TypeIdentifier)
{
formatString = "alias %s = %s;";
}
else
enum formatString = "enum %s = %s;";
{
version (D1)
formatString = "const %s = %s;";
else
formatString = "enum %s = %s;";
}

output.singleLine(
formatString,
definition.definition.spelling,
definition.definition.expr.debraced.translate(expressionContext));
debraced.translate(expressionContext));
}

void translateMacroDefinition(
Expand All @@ -606,9 +616,9 @@ void translateMacroDefinition(
import std.conv;
import std.range;

if (definition.constant)
if (definition.alias_or_const)
{
translateMacroDefinitionConstant(output, context, definition);
translateMacroDefinitionAliasOrConst(output, context, definition);
}
else if (!translateFunctAlias(output, context, definition))
{
Expand Down
10 changes: 5 additions & 5 deletions dstep/translator/MacroParser.d
Expand Up @@ -1464,18 +1464,18 @@ class MacroDefinition
Cursor cursor;
string spelling;
string[] params;
bool constant;
bool alias_or_const;
Expression expr;

override string toString()
{
import std.format : format;

return format(
"MacroDefinition(spelling = %s, params = %s, constant = %s, expr = %s)",
"MacroDefinition(spelling = %s, params = %s, alias_or_const = %s, expr = %s)",
spelling,
params,
constant,
alias_or_const,
expr);
}

Expand All @@ -1487,7 +1487,7 @@ class MacroDefinition

result.put(" ".replicate(indent));

if (constant)
if (alias_or_const)
formattedWrite(result, "MacroDefinition %s", spelling);
else
formattedWrite(result, "MacroDefinition %s(%s)", spelling, join(params, ", "));
Expand Down Expand Up @@ -1551,7 +1551,7 @@ MacroDefinition parsePartialMacroDefinition(
}
else
{
result.constant = true;
result.alias_or_const = true;
}

result.expr = parseExpr(local, table, defined);
Expand Down
6 changes: 3 additions & 3 deletions tests/unit/MacroParsingTests.d
Expand Up @@ -32,18 +32,18 @@ unittest
auto y = parse("#define FOO");
assert(y !is null);
assert(y.spelling == "FOO");
assert(y.constant == true);
assert(y.alias_or_const == true);

auto z = parse("#define FOO()");
assert(z !is null);
assert(z.spelling == "FOO");
assert(z.constant == false);
assert(z.alias_or_const == false);
assert(z.params == []);

auto w = parse("#define FOO(a, b)");
assert(w !is null);
assert(w.spelling == "FOO");
assert(w.constant == false);
assert(w.alias_or_const == false);
assert(w.params.length == 2);
assert(w.params[0] == "a");
assert(w.params[1] == "b");
Expand Down
25 changes: 25 additions & 0 deletions tests/unit/MacroTranslTests.d
Expand Up @@ -764,3 +764,28 @@ enum FOO = 0;
D",
translateMacrosTrue);
}

// If the identifier is known to be a type translate is as an alias.
unittest
{
assertTranslates(q"C
typedef unsigned long long uint64_type;
#define __le64 uint64_type
C", q"D
extern (C):
alias uint64_type = ulong;
alias __le64 = uint64_type;
D");

assertTranslates(q"C
#define __le32 unsigned
#define __le64 unsigned long long
C", q"D
extern (C):
alias __le32 = uint;
alias __le64 = ulong;
D");
}

25 changes: 25 additions & 0 deletions tests/unit/issues/Issue199.d
@@ -0,0 +1,25 @@
/**
* Copyright: Copyright (c) 2018 Wojciech Szęszoł. All rights reserved.
* Authors: Wojciech Szęszoł
* Version: Initial created: September 29, 2018
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
*/

import Common;

unittest
{
assertTranslates(
q"C
#include <stdint.h>
#define __le64 uint64_t
C",
q"D
extern (C):
alias __le64 = ulong;
D");

}

0 comments on commit 6b9b3a5

Please sign in to comment.