Browse Source

Evaluate expressions for enums generated using GenerateEnumFromMacros (#1048)

* Evaluate expressions when generating enum from macros

ExpressionEvaluator taken from https://github.com/codingseb/ExpressionEvaluator

* Set namespace for enums generated from macros.

* Add Tests
pull/1135/head
TheLastRar 8 years ago committed by João Matos
parent
commit
430bbdb257
  1. 33
      src/Generator/Library.cs
  2. 1446
      src/Generator/Utils/ExpressionEvaluator.cs
  3. 1
      src/Generator/premake5.lua
  4. 17
      tests/CSharp/CSharp.Tests.cs
  5. 3
      tests/CSharp/CSharp.cs
  6. 10
      tests/CSharp/CSharp.h

33
src/Generator/Library.cs

@ -91,13 +91,14 @@ namespace CppSharp @@ -91,13 +91,14 @@ namespace CppSharp
{
Name = macro.Name,
Expression = macro.Expression,
Value = ParseMacroExpression(macro.Expression),
Value = ParseMacroExpression(macro.Expression, @enum),
Namespace = @enum
};
}
static bool ParseToNumber(string num, out long val)
static bool ParseToNumber(string num, Enumeration @enum, out long val)
{
//ExpressionEvaluator does not work with hex
if (num.StartsWith("0x", StringComparison.CurrentCultureIgnoreCase))
{
num = num.Substring(2);
@ -106,17 +107,35 @@ namespace CppSharp @@ -106,17 +107,35 @@ namespace CppSharp
CultureInfo.CurrentCulture, out val);
}
return long.TryParse(num, out val);
ExpressionEvaluator evaluator = new ExpressionEvaluator();
//Include values of past items
evaluator.Variables = new Dictionary<string, object>();
foreach (Enumeration.Item item in @enum.Items)
{
//ExpressionEvaluator is requires lowercase variables
evaluator.Variables.Add(item.Name.ToLower(), item.Value);
}
try
{
var ret = evaluator.Evaluate("(long)" + num.ReplaceLineBreaks(" ").Replace('\\',' '));
val = (long)ret;
return true;
}
catch (ExpressionEvaluatorSyntaxErrorException)
{
val = 0;
return false;
}
}
static ulong ParseMacroExpression(string expression)
static ulong ParseMacroExpression(string expression, Enumeration @enum)
{
// TODO: Handle string expressions
if (expression.Length == 3 && expression[0] == '\'' && expression[2] == '\'') // '0' || 'A'
return expression[1]; // return the ASCI code of this character
long val;
return ParseToNumber(expression, out val) ? (ulong)val : 0;
return ParseToNumber(expression, @enum, out val) ? (ulong)val : 0;
}
public static Enumeration GenerateEnumFromMacros(this ASTContext context, string name,
@ -141,6 +160,10 @@ namespace CppSharp @@ -141,6 +160,10 @@ namespace CppSharp
if (@enum.Items.Exists(it => it.Name == macro.Name))
continue;
// Set the namespace to the namespace we found the 1st item in
if (@enum.Namespace == null)
@enum.Namespace = unit;
var item = @enum.GenerateEnumItemFromMacro(macro);
@enum.AddItem(item);

1446
src/Generator/Utils/ExpressionEvaluator.cs

File diff suppressed because it is too large Load Diff

1
src/Generator/premake5.lua

@ -15,6 +15,7 @@ project "CppSharp.Generator" @@ -15,6 +15,7 @@ project "CppSharp.Generator"
{
"System",
"System.Core",
"Microsoft.CSharp",
"CppSharp",
"CppSharp.AST",
"CppSharp.Parser"

17
tests/CSharp/CSharp.Tests.cs

@ -988,6 +988,23 @@ public unsafe class CSharpTests : GeneratorTestFixture @@ -988,6 +988,23 @@ public unsafe class CSharpTests : GeneratorTestFixture
Assert.IsTrue(a == MyMacroTestEnum.MY_MACRO_TEST_1 && b == MyMacroTestEnum.MY_MACRO_TEST_2);
}
[Test]
public void TestMyMacro2TestEnum()
{
var a = (MyMacroTest2Enum)0;
var b = (MyMacroTest2Enum)1;
var c = (MyMacroTest2Enum)0x2;
var d = (MyMacroTest2Enum)(1 << 2);
var e = (MyMacroTest2Enum)(b | c);
var f = (MyMacroTest2Enum)(b | c | d);
var g = (MyMacroTest2Enum)(1 << 3);
var h = (MyMacroTest2Enum)((1 << 4) - 1);
Assert.IsTrue(a == MyMacroTest2Enum.MY_MACRO_TEST2_0 && b == MyMacroTest2Enum.MY_MACRO_TEST2_1 &&
c == MyMacroTest2Enum.MY_MACRO_TEST2_2 && d == MyMacroTest2Enum.MY_MACRO_TEST2_3 &&
e == MyMacroTest2Enum.MY_MACRO_TEST2_1_2 && f == MyMacroTest2Enum.MY_MACRO_TEST2_1_2_3 &&
g == MyMacroTest2Enum.MY_MACRO_TEST2_4 && h == MyMacroTest2Enum.MY_MACRO_TEST2ALL);
}
[Test]
public void TestGenerationOfArraySetter()
{

3
tests/CSharp/CSharp.cs

@ -55,6 +55,9 @@ namespace CppSharp.Tests @@ -55,6 +55,9 @@ namespace CppSharp.Tests
where macroRegex.IsMatch(macro.Name)
select macro.Name).ToList();
var enumTest = ctx.GenerateEnumFromMacros("MyMacroTestEnum", list.ToArray());
var enumTest2 = ctx.GenerateEnumFromMacros("MyMacroTest2Enum", "MY_MACRO_TEST2_*");
enumTest.Namespace = new Namespace()
{
Name = "MacroTest",

10
tests/CSharp/CSharp.h

@ -1198,6 +1198,16 @@ struct StructTestArrayTypeFromTypedef @@ -1198,6 +1198,16 @@ struct StructTestArrayTypeFromTypedef
#define MY_MACRO_TEST_1 '1'
#define MY_MACRO_TEST_2 '2'
#define MY_MACRO_TEST2_0 0_invalid
#define MY_MACRO_TEST2_1 1
#define MY_MACRO_TEST2_2 0x2
#define MY_MACRO_TEST2_3 (1 << 2)
#define MY_MACRO_TEST2_1_2 (MY_MACRO_TEST2_1 | MY_MACRO_TEST2_2)
#define MY_MACRO_TEST2_1_2_3 (MY_MACRO_TEST2_1 | MY_MACRO_TEST2_2 | \
MY_MACRO_TEST2_3)
#define MY_MACRO_TEST2_4 (1 << 3)
#define MY_MACRO_TEST2_ALL (1 << 4) - 1
struct ComplexArrayElement
{
bool BoolField;

Loading…
Cancel
Save