Browse Source

Simplify handling of initialisation of variables

Signed-off-by: Dimitar Dobrev <dpldobrev@protonmail.com>
pull/1641/head
Dimitar Dobrev 4 years ago
parent
commit
ad6557792f
  1. 1
      src/Generator/Generators/CSharp/CSharpExpressionPrinter.cs
  2. 21
      src/Generator/Generators/CSharp/CSharpSources.cs
  3. 39
      src/Generator/Passes/ExpressionHelper.cs
  4. 24
      src/Generator/Passes/HandleVariableInitializerPass.cs
  5. 6
      tests/CSharp/CSharp.cpp
  6. 3
      tests/CSharp/CSharp.h

1
src/Generator/Generators/CSharp/CSharpExpressionPrinter.cs

@ -1,7 +1,6 @@
using System.Linq; using System.Linq;
using CppSharp.AST; using CppSharp.AST;
using CppSharp.AST.Extensions; using CppSharp.AST.Extensions;
using CppSharp.Types;
using Type = CppSharp.AST.Type; using Type = CppSharp.AST.Type;
namespace CppSharp.Generators.CSharp namespace CppSharp.Generators.CSharp

21
src/Generator/Generators/CSharp/CSharpSources.cs

@ -1192,11 +1192,11 @@ namespace CppSharp.Generators.CSharp
var systemType = Internal.ExpressionHelper.GetSystemType(Context, arrayType.Type.Desugar()); var systemType = Internal.ExpressionHelper.GetSystemType(Context, arrayType.Type.Desugar());
Write($"new {arrayType.Type}[{arrayType.Size}] "); Write($"new {arrayType.Type}[{arrayType.Size}] ");
Write("{ "); Write("{ ");
List<string> elements = Internal.ExpressionHelper.SplitInitListExpr(initializerString); List<string> elements = Internal.ExpressionHelper.SplitInitListExpr(initializerString);
while (elements.Count < arrayType.Size) while (elements.Count < arrayType.Size)
elements.Add(systemType == typeof(string) ? "\"\"" : null); elements.Add(systemType == typeof(string) ? "\"\"" : null);
for (int i = 0; i < elements.Count; ++i) for (int i = 0; i < elements.Count; ++i)
{ {
@ -1204,7 +1204,8 @@ namespace CppSharp.Generators.CSharp
if (e == null) if (e == null)
Write("default"); Write("default");
else { else
{
if (!Internal.ExpressionHelper.TryParseExactLiteralExpression(ref e, systemType)) if (!Internal.ExpressionHelper.TryParseExactLiteralExpression(ref e, systemType))
Write($"({arrayType.Type})"); Write($"({arrayType.Type})");
Write(e); Write(e);
@ -1218,19 +1219,7 @@ namespace CppSharp.Generators.CSharp
} }
else else
{ {
if (Internal.ExpressionHelper.PrintExpression(Context, null, type, Write(initializerString);
variable.Initializer, false, ref initializerString) == null)
{
Write(initializerString);
}
else
{
var systemType = Internal.ExpressionHelper.GetSystemType(Context, type);
if (!Internal.ExpressionHelper.TryParseExactLiteralExpression(ref initializerString, systemType))
Write($"({type}) {initializerString}");
else
Write(initializerString);
}
} }
WriteLine(";"); WriteLine(";");
} }

39
src/Generator/Passes/ExpressionHelper.cs

@ -11,7 +11,7 @@ using TypeCode = System.TypeCode;
namespace CppSharp.Internal namespace CppSharp.Internal
{ {
internal class ExpressionHelper internal static class ExpressionHelper
{ {
private static readonly Regex regexFunctionParams = new Regex(@"\(?(.+)\)?", RegexOptions.Compiled); private static readonly Regex regexFunctionParams = new Regex(@"\(?(.+)\)?", RegexOptions.Compiled);
private static readonly Regex regexDoubleColon = new Regex(@"\w+::", RegexOptions.Compiled); private static readonly Regex regexDoubleColon = new Regex(@"\w+::", RegexOptions.Compiled);
@ -200,7 +200,8 @@ namespace CppSharp.Internal
{ {
return CheckFloatSyntax(desugared, expression, ref result) || return CheckFloatSyntax(desugared, expression, ref result) ||
CheckForEnumValue(context, desugared, expression, ref result) || CheckForEnumValue(context, desugared, expression, ref result) ||
CheckForDefaultChar(context, desugared, ref result); CheckForChar(context, desugared, ref result) ||
CheckForString(context, desugared, ref result);
} }
private static bool CheckForDefaultPointer(BindingContext context, Type desugared, ref string result) private static bool CheckForDefaultPointer(BindingContext context, Type desugared, ref string result)
@ -390,10 +391,9 @@ namespace CppSharp.Internal
((BuiltinTypeExpressionObsolete)defaultArgument).Value == 0; ((BuiltinTypeExpressionObsolete)defaultArgument).Value == 0;
} }
private static bool CheckForDefaultChar(BindingContext context, Type desugared, ref string result) private static bool CheckForChar(BindingContext context, Type desugared, ref string result)
{ {
int value; if (int.TryParse(result, out int value) &&
if (int.TryParse(result, out value) &&
((context.Options.MarshalCharAsManagedChar && ((context.Options.MarshalCharAsManagedChar &&
desugared.IsPrimitiveType(PrimitiveType.Char)) || desugared.IsPrimitiveType(PrimitiveType.Char)) ||
desugared.IsPrimitiveType(PrimitiveType.WideChar))) desugared.IsPrimitiveType(PrimitiveType.WideChar)))
@ -401,7 +401,36 @@ namespace CppSharp.Internal
result = value == 0 ? "'\\0'" : ("(char) " + result); result = value == 0 ? "'\\0'" : ("(char) " + result);
return true; return true;
} }
if (context.Options.MarshalCharAsManagedChar &&
desugared.IsPrimitiveType(PrimitiveType.UChar))
{
result = "(byte) " + result;
return true;
}
return false;
}
private static bool CheckForString(BindingContext context, Type desugared, ref string result)
{
if (context.TypeMaps.FindTypeMap(desugared, out TypeMap typeMap))
{
var typePrinterContext = new TypePrinterContext()
{
Kind = TypePrinterContextKind.Managed,
MarshalKind = MarshalKind.DefaultExpression,
Type = desugared
};
var typeInSignature = typeMap.CSharpSignatureType(typePrinterContext)
.SkipPointerRefs().Desugar();
if (typeInSignature is CILType managed && managed.Type == typeof(string))
{
result = result[result.IndexOf("\"")..];
return true;
}
}
return false; return false;
} }
} }

24
src/Generator/Passes/HandleVariableInitializerPass.cs

@ -1,33 +1,21 @@
using CppSharp.AST; using CppSharp.AST;
using CppSharp.AST.Extensions;
using CppSharp.Internal; using CppSharp.Internal;
namespace CppSharp.Passes namespace CppSharp.Passes
{ {
public class HandleVariableInitializerPass : TranslationUnitPass public class HandleVariableInitializerPass : TranslationUnitPass
{ {
public HandleVariableInitializerPass()
=> VisitOptions.ResetFlags(VisitFlags.NamespaceVariables);
public override bool VisitVariableDecl(Variable variable) public override bool VisitVariableDecl(Variable variable)
{ {
if (!base.VisitVariableDecl(variable) || variable.Ignore || variable.Initializer == null) if (AlreadyVisited(variable) || variable.Ignore || variable.Initializer == null)
return false;
bool supported =
variable.Type.IsPrimitiveType() ||
variable.Type.IsPointerToPrimitiveType(PrimitiveType.Char) ||
variable.Type.IsPointerToPrimitiveType(PrimitiveType.WideChar) ||
(variable.Type is ArrayType arrayType && (
arrayType.Type.IsPrimitiveType() ||
arrayType.Type.IsPointerToPrimitiveType(PrimitiveType.Char) ||
arrayType.Type.IsPointerToPrimitiveType(PrimitiveType.WideChar)));
if (!supported)
{
variable.Initializer = null;
return false; return false;
}
string initializerString = variable.Initializer.String; string initializerString = variable.Initializer.String;
ExpressionHelper.PrintExpression(Context, null, variable.Type, variable.Initializer, allowDefaultLiteral: true, ref initializerString); ExpressionHelper.PrintExpression(Context, null, variable.Type, variable.Initializer,
allowDefaultLiteral: true, ref initializerString);
if (string.IsNullOrWhiteSpace(initializerString)) if (string.IsNullOrWhiteSpace(initializerString))
variable.Initializer = null; variable.Initializer = null;

6
tests/CSharp/CSharp.cpp

@ -613,7 +613,11 @@ void MethodsWithDefaultValues::defaultValueType(QGenericArgument valueType)
{ {
} }
void MethodsWithDefaultValues::defaultChar(char c, char uc, char Uc, char Lc) void MethodsWithDefaultValues::defaultChar(char c, char uc, char Uc, char Lc, unsigned char b)
{
}
void MethodsWithDefaultValues::defaultString(const wchar_t* wideString)
{ {
} }

3
tests/CSharp/CSharp.h

@ -423,7 +423,8 @@ public:
void defaultVoidStar(void* ptr = 0); void defaultVoidStar(void* ptr = 0);
void defaultFunctionPointer(void(*functionPtr)(int p) = nullptr); void defaultFunctionPointer(void(*functionPtr)(int p) = nullptr);
void defaultValueType(QGenericArgument valueType = QGenericArgument()); void defaultValueType(QGenericArgument valueType = QGenericArgument());
void defaultChar(char c = 'a', char uc = u'u', char Uc = U'U', char Lc = L'L'); void defaultChar(char c = 'a', char uc = u'u', char Uc = U'U', char Lc = L'L', unsigned char b = 'z');
void defaultString(const wchar_t* wideString = L"Str");
void defaultEmptyChar(char c = 0); void defaultEmptyChar(char c = 0);
void defaultEmptyEnum(Empty e = Empty(-1)); void defaultEmptyEnum(Empty e = Empty(-1));
void defaultRefTypeBeforeOthers(Foo foo = Foo(), int i = 5, Bar::Items item = Bar::Item2); void defaultRefTypeBeforeOthers(Foo foo = Foo(), int i = 5, Bar::Items item = Bar::Item2);

Loading…
Cancel
Save