Browse Source

Added support for call expressions in default args.

The conversion of an expression to a string has been moved to the generator because a function may have been renamed or converted to a property.
However, since that string is language-specific, it should be created in the generator anyway. Therefore we should (over time):
1. Move any string manipulation from the pass for default args to the printer for expressions which is in turn used only by the generator;
2. Remove the Statement.String property (when 1. is entirely complete).

Signed-off-by: Dimitar Dobrev <dpldobrev@yahoo.com>
pull/256/merge
Dimitar Dobrev 10 years ago
parent
commit
8ebefa1f37
  1. 5
      src/AST/Expression.cs
  2. 1
      src/AST/Statement.cs
  3. 44
      src/Generator/Generators/CSharp/CSharpExpressionPrinter.cs
  4. 2
      src/Generator/Generators/CSharp/CSharpGenerator.cs
  5. 10
      src/Generator/Generators/CSharp/CSharpTextTemplate.cs
  6. 3
      src/Generator/Passes/HandleDefaultParamValuesPass.cs
  7. 10
      tests/CSharp/CSharp.Tests.cs
  8. 18
      tests/CSharp/CSharp.cpp
  9. 4
      tests/CSharp/CSharp.h

5
src/AST/Expression.cs

@ -31,8 +31,7 @@ namespace CppSharp.AST @@ -31,8 +31,7 @@ namespace CppSharp.AST
{
var printAsHex = IsHexadecimal && Type.IsUnsigned;
var format = printAsHex ? "x" : string.Empty;
var value = Type.IsUnsigned ? Value.ToString(format) :
((long)Value).ToString(format);
var value = Value.ToString(format);
return printAsHex ? "0x" + value : value;
}
@ -66,6 +65,7 @@ namespace CppSharp.AST @@ -66,6 +65,7 @@ namespace CppSharp.AST
{
public CallExpr()
{
Class = StatementClass.Call;
Arguments = new List<Expression>();
}
@ -81,6 +81,7 @@ namespace CppSharp.AST @@ -81,6 +81,7 @@ namespace CppSharp.AST
{
public CXXConstructExpr()
{
Class = StatementClass.ConstructorReference;
Arguments = new List<Expression>();
}

1
src/AST/Statement.cs

@ -5,6 +5,7 @@ @@ -5,6 +5,7 @@
Any,
BinaryOperator,
DeclarationReference,
Call,
ConstructorReference,
CXXOperatorCall,
ImplicitCast,

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

@ -1,5 +1,7 @@ @@ -1,5 +1,7 @@
using CppSharp.AST;
using System.Linq;
using CppSharp.AST;
using CppSharp.Types;
using Type = CppSharp.AST.Type;
namespace CppSharp.Generators.CSharp
{
@ -21,20 +23,52 @@ namespace CppSharp.Generators.CSharp @@ -21,20 +23,52 @@ namespace CppSharp.Generators.CSharp
}
}
public class CSharpExpressionPrinter : IExpressionPrinter<CSharpExpressionPrinterResult>,
IExpressionVisitor<CSharpExpressionPrinterResult>
public class CSharpExpressionPrinter : IExpressionPrinter<CSharpExpressionPrinterResult>
{
public CSharpExpressionPrinter(CSharpTypePrinter typePrinter)
{
this.typePrinter = typePrinter;
}
public CSharpExpressionPrinterResult VisitExpression(Expression expr)
{
return new CSharpExpressionPrinterResult()
switch (expr.Class)
{
case StatementClass.Call:
var callExpr = (CallExpr) expr;
switch (callExpr.Declaration.GenerationKind)
{
case GenerationKind.Generate:
case GenerationKind.Link:
return new CSharpExpressionPrinterResult
{
Value = expr.ToString(),
Value = string.Format("{0}.{1}({2})",
typePrinter.VisitDeclaration(callExpr.Declaration.Namespace),
callExpr.Declaration.Name,
string.Join(", ", callExpr.Arguments.Select(VisitExpression)))
};
case GenerationKind.Internal:
// a non-ctor can only be internal if it's been converted to a property
return new CSharpExpressionPrinterResult
{
Value = string.Format("{0}.{1}",
typePrinter.VisitDeclaration(callExpr.Declaration.Namespace),
callExpr.Declaration.Name)
};
default:
return new CSharpExpressionPrinterResult { Value = expr.String };
}
default:
return new CSharpExpressionPrinterResult { Value = expr.String };
}
}
public string ToString(Type type)
{
throw new System.NotImplementedException();
}
private readonly CSharpTypePrinter typePrinter;
}
}

2
src/Generator/Generators/CSharp/CSharpGenerator.cs

@ -12,7 +12,7 @@ namespace CppSharp.Generators.CSharp @@ -12,7 +12,7 @@ namespace CppSharp.Generators.CSharp
public CSharpGenerator(Driver driver) : base(driver)
{
typePrinter = new CSharpTypePrinter(driver);
expressionPrinter = new CSharpExpressionPrinter();
expressionPrinter = new CSharpExpressionPrinter(typePrinter);
CppSharp.AST.Type.TypePrinterDelegate += type => type.Visit(typePrinter).Type;
}

10
src/Generator/Generators/CSharp/CSharpTextTemplate.cs

@ -2065,7 +2065,7 @@ namespace CppSharp.Generators.CSharp @@ -2065,7 +2065,7 @@ namespace CppSharp.Generators.CSharp
string.Join(", ",
method.Parameters.Where(
p => p.Kind == ParameterKind.Regular).Select(
p => p.Ignore ? p.DefaultArgument.String : p.Name)));
p => p.Ignore ? ExpressionPrinter.VisitExpression(p.DefaultArgument).Value : p.Name)));
}
if (method.IsPure)
@ -2145,11 +2145,11 @@ namespace CppSharp.Generators.CSharp @@ -2145,11 +2145,11 @@ namespace CppSharp.Generators.CSharp
PopBlock(NewLineKind.BeforeNextBlock);
}
private static string OverloadParamNameWithDefValue(Parameter p, ref int index)
private string OverloadParamNameWithDefValue(Parameter p, ref int index)
{
return (p.Type.IsPointerToPrimitiveType() && p.Usage == ParameterUsage.InOut && p.HasDefaultValue)
return p.Type.IsPointerToPrimitiveType() && p.Usage == ParameterUsage.InOut && p.HasDefaultValue
? "ref param" + index++
: p.DefaultArgument.String;
: ExpressionPrinter.VisitExpression(p.DefaultArgument).Value;
}
private void GenerateOverloadCall(Function function)
@ -2745,7 +2745,7 @@ namespace CppSharp.Generators.CSharp @@ -2745,7 +2745,7 @@ namespace CppSharp.Generators.CSharp
select string.Format("{0}{1} {2}", GetParameterUsage(param.Usage),
typeName, param.Name +
(param.DefaultArgument == null || !Options.GenerateDefaultValuesForArguments ?
string.Empty : " = " + param.DefaultArgument.String)));
string.Empty : " = " + ExpressionPrinter.VisitExpression(param.DefaultArgument))));
}
#endregion

3
src/Generator/Passes/HandleDefaultParamValuesPass.cs

@ -66,6 +66,9 @@ namespace CppSharp.Passes @@ -66,6 +66,9 @@ namespace CppSharp.Passes
if (CheckForDefaultPointer(desugared, ref result))
return true;
if (expression.Class == StatementClass.Call)
return expression.Declaration.Ignore ? false : (bool?) null;
var defaultConstruct = CheckForDefaultConstruct(desugared, expression, ref result);
if (defaultConstruct != false)
return defaultConstruct;

10
tests/CSharp/CSharp.Tests.cs

@ -197,6 +197,8 @@ public class CSharpTests : GeneratorTestFixture @@ -197,6 +197,8 @@ public class CSharpTests : GeneratorTestFixture
methodsWithDefaultValues.DefaultIntExpressionWithEnum();
methodsWithDefaultValues.DefaultCtorWithMoreThanOneArg();
methodsWithDefaultValues.DefaultWithRefManagedLong();
methodsWithDefaultValues.DefaultWithFunctionCall();
methodsWithDefaultValues.DefaultWithPropertyCall();
}
}
@ -238,11 +240,15 @@ public class CSharpTests : GeneratorTestFixture @@ -238,11 +240,15 @@ public class CSharpTests : GeneratorTestFixture
public void TestImplicitCtor()
{
Foo foo = new Foo { A = 10 };
MethodsWithDefaultValues m = foo;
using (MethodsWithDefaultValues m = foo)
{
Assert.AreEqual(foo.A, m.A);
MethodsWithDefaultValues m1 = 5;
}
using (MethodsWithDefaultValues m1 = 5)
{
Assert.AreEqual(5, m1.A);
}
}
[Test]
public void TestStructWithPrivateFields()

18
tests/CSharp/CSharp.cpp

@ -43,6 +43,16 @@ void Foo::setNoParams() @@ -43,6 +43,16 @@ void Foo::setNoParams()
const int Foo::rename;
int Foo::makeFunctionCall()
{
return 1;
}
int Foo::propertyCall()
{
return 1;
}
const Foo& Bar::operator[](int i) const
{
return m_foo;
@ -484,6 +494,14 @@ void MethodsWithDefaultValues::defaultWithRefManagedLong(long long* i) @@ -484,6 +494,14 @@ void MethodsWithDefaultValues::defaultWithRefManagedLong(long long* i)
{
}
void MethodsWithDefaultValues::defaultWithFunctionCall(int f)
{
}
void MethodsWithDefaultValues::defaultWithPropertyCall(int f)
{
}
int MethodsWithDefaultValues::getA()
{
return m_foo.A;

4
tests/CSharp/CSharp.h

@ -17,6 +17,8 @@ public: @@ -17,6 +17,8 @@ public:
void setNoParams();
static const int rename = 5;
static int makeFunctionCall();
static int propertyCall();
protected:
int P;
@ -364,6 +366,8 @@ public: @@ -364,6 +366,8 @@ public:
void defaultCtorWithMoreThanOneArg(QMargins m = QMargins(0, 0, 0, 0));
void defaultWithComplexArgs(const QRect& rectangle = QRect(QPoint(0, 0), QSize(-1, -1)));
void defaultWithRefManagedLong(long long* i = 0);
void defaultWithFunctionCall(int f = Foo::makeFunctionCall());
void defaultWithPropertyCall(int f = Foo::propertyCall());
int getA();
private:
Foo m_foo;

Loading…
Cancel
Save