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

1
src/AST/Statement.cs

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

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

@ -1,5 +1,7 @@
using CppSharp.AST; using System.Linq;
using CppSharp.AST;
using CppSharp.Types; using CppSharp.Types;
using Type = CppSharp.AST.Type;
namespace CppSharp.Generators.CSharp 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) public CSharpExpressionPrinterResult VisitExpression(Expression expr)
{ {
return new CSharpExpressionPrinterResult() switch (expr.Class)
{ {
Value = expr.ToString(), case StatementClass.Call:
}; var callExpr = (CallExpr) expr;
switch (callExpr.Declaration.GenerationKind)
{
case GenerationKind.Generate:
case GenerationKind.Link:
return new CSharpExpressionPrinterResult
{
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) public string ToString(Type type)
{ {
throw new System.NotImplementedException(); throw new System.NotImplementedException();
} }
private readonly CSharpTypePrinter typePrinter;
} }
} }

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

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

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

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

3
src/Generator/Passes/HandleDefaultParamValuesPass.cs

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

14
tests/CSharp/CSharp.Tests.cs

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

18
tests/CSharp/CSharp.cpp

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

4
tests/CSharp/CSharp.h

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

Loading…
Cancel
Save