Skip to content

Commit

Permalink
Translate Python property getters.
Browse files Browse the repository at this point in the history
  • Loading branch information
uxmal committed Sep 27, 2017
1 parent 00c50dd commit 8c74f66
Show file tree
Hide file tree
Showing 9 changed files with 213 additions and 5 deletions.
Binary file added external/NUnit-2.6.3/nunit.framework.dll
Binary file not shown.
5 changes: 5 additions & 0 deletions src/CodeModel/CSharpExpressionWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,11 @@ public class CSharpExpressionWriter : ICodeExpressionVisitor
{ CodeOperatorType.XorEq, PrecAssignment },
};

internal void VisitTypeReference(object propertyType)
{
throw new NotImplementedException();
}

private IndentingTextWriter writer;
private int precedence;

Expand Down
31 changes: 31 additions & 0 deletions src/CodeModel/CSharpTypeWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,37 @@ public int VisitField(CodeMemberField field)
return 0;
}

public int VisitProperty(CodeMemberProperty property)
{
RenderMemberFieldAttributes(property.Attributes);
var expWriter = new CSharpExpressionWriter(writer);
expWriter.VisitTypeReference(property.PropertyType);
writer.Write(" ");
writer.WriteName(property.Name);
writer.Write(" ");
writer.Write("{");
writer.WriteLine();
++writer.IndentLevel;
writer.Write("get");

var stmWriter = new CSharpStatementWriter(writer);
stmWriter.WriteStatements(property.GetStatements);
writer.WriteLine();

if (property.SetStatements.Count > 0)
{
writer.Write("set");
stmWriter = new CSharpStatementWriter(writer);
stmWriter.WriteStatements(property.SetStatements);
writer.WriteLine();
}

--writer.IndentLevel;
writer.Write("}");
writer.WriteLine();
return 0;
}

public int VisitMethod(CodeMemberMethod method)
{
foreach (var comment in method.Comments)
Expand Down
27 changes: 26 additions & 1 deletion src/CodeModel/CodeGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,10 @@ public CodeCatchClause CatchClause(string localName, CodeTypeReference type, Act
return clause;
}

public CodeTypeDeclaration Class(string name, IEnumerable<string> baseClasses, Action body)
public CodeTypeDeclaration Class(
string name,
IEnumerable<string> baseClasses,
Action body)
{
var c = new CodeTypeDeclaration
{
Expand Down Expand Up @@ -453,5 +456,27 @@ internal CodeUsingStatement Using(
Scope = old;
return u;
}

internal CodeMemberProperty PropertyDef(string name, Action generatePropertyGetter, Action generatePropertySetter)
{
var prop = new CodeMemberProperty
{
Name = name,
Attributes = MemberAttributes.Public,
PropertyType = new CodeTypeReference(typeof(object))
};
var mem = new System.CodeDom.CodeMemberProperty();
var old = Scope;
this.Scope = prop.GetStatements;
generatePropertyGetter();
if (generatePropertySetter != null)
{
this.Scope = prop.SetStatements;
generatePropertySetter();
}
Scope = old;
CurrentType.Members.Add(prop);
return prop;
}
}
}
42 changes: 42 additions & 0 deletions src/CodeModel/CodeMemberProperty.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#region License
// Copyright 2015 John Källén
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#endregion

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Pytocs.CodeModel
{
public class CodeMemberProperty : CodeMember
{
public CodeMemberProperty()
{
this.GetStatements = new List<CodeStatement>();
this.SetStatements = new List<CodeStatement>();
}

public CodeTypeReference PropertyType { get; set; }
public List<CodeStatement> GetStatements { get; set; }
public List<CodeStatement> SetStatements { get; set; }

public override T Accept<T>(ICodeMemberVisitor<T> visitor)
{
return visitor.VisitProperty(this);
}
}
}
1 change: 1 addition & 0 deletions src/CodeModel/ICodeMemberVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public interface ICodeMemberVisitor<T>
T VisitField(CodeMemberField field);
T VisitMethod(CodeMemberMethod method);
T VisitTypeDefinition(CodeTypeDeclaration type);
T VisitProperty(CodeMemberProperty codeMemberProperty);
T VisitConstructor(CodeConstructor codeConstructor);
}
}
26 changes: 26 additions & 0 deletions src/Translate/StatementTranslator.Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1119,6 +1119,32 @@ with open(args.wasm_file, 'rb') as raw:
var sExp = "@@@";
Assert.AreEqual(sExp, XlatModule(pySrc));
}

[Test]
public void Stmt_Property()
{
var pySrc =
@"class foo:
@property
def size():
return 3
";
var sExp =
@"public static class testModule {
public class foo {
public object size {
get {
return 3;
}
}
}
}
";
Assert.AreEqual(sExp, XlatModule(pySrc));
}
}
}
#endif
81 changes: 79 additions & 2 deletions src/Translate/StatementTranslator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public class StatementTranslator : IStatementVisitor
private SymbolGenerator gensym;
private ClassDef currentClass;
private IEnumerable<CodeAttributeDeclaration> customAttrs;
private Dictionary<Decorated, PropertyDefinition> properties;
private CodeConstructor classConstructor;

public StatementTranslator(CodeGenerator gen, SymbolGenerator gensym)
Expand All @@ -47,6 +48,7 @@ public void VisitClass(ClassDef c)
var gensym = new SymbolGenerator();
var stmtXlt = new StatementTranslator(gen, gensym);
stmtXlt.currentClass = c;
stmtXlt.properties = FindProperties(c.body.stmts);
var csClass = gen.Class(c.name.Name, baseClasses, () => c.body.Accept(stmtXlt));
csClass.Comments.AddRange(comments);
if (customAttrs != null)
Expand All @@ -56,6 +58,34 @@ public void VisitClass(ClassDef c)
}
}

public Dictionary<Decorated, PropertyDefinition> FindProperties(List<Statement> stmts)
{
var decs = stmts.OfType<Decorated>();
var propdefs = new Dictionary<string, PropertyDefinition>();
var result = new Dictionary<Decorated, PropertyDefinition>();
foreach (var dec in decs)
{
foreach (var decoration in dec.Decorations)
{
if (decoration.className.segs.Count == 1 &&
decoration.className.segs[0].Name == "property")
{
var def = (FunctionDef)dec.Statement;
PropertyDefinition propdef;
if (!propdefs.TryGetValue(def.name.Name, out propdef))
{
propdef = new PropertyDefinition(def.name.Name);
propdefs.Add(def.name.Name, propdef);
}
result[dec] = propdef;
propdef.Getter = dec;
propdef.GetterDecoration = decoration;
}
}
}
return result;
}

public static IEnumerable<CodeCommentStatement> ConvertFirstStringToComments(List<Statement> statements)
{
var nothing = new CodeCommentStatement[0];
Expand Down Expand Up @@ -544,8 +574,40 @@ public void VisitContinue(ContinueStatement c)

public void VisitDecorated(Decorated d)
{
this.customAttrs = d.Decorations.Select(dd => VisitDecorator(dd));
d.Statement.Accept(this);
var decorators = d.Decorations.ToList();
PropertyDefinition propdef;
if (this.properties.TryGetValue(d, out propdef))
{
if (propdef.IsTranslated)
return;
decorators.Remove(propdef.GetterDecoration);
decorators.Remove(propdef.SetterDecoration);
this.customAttrs = decorators.Select(dd => VisitDecorator(dd));
gen.PropertyDef(
propdef.Name,
() => GeneratePropertyGetter(propdef.Getter),
() => GeneratePropertySetter(propdef.Setter));
propdef.IsTranslated = true;
}
else
{
this.customAttrs = d.Decorations.Select(dd => VisitDecorator(dd));
d.Statement.Accept(this);
}
}

private void GeneratePropertyGetter(Decorated getter)
{
var def = (FunctionDef)getter.Statement;
def.body.Accept(this);
}

private void GeneratePropertySetter(Decorated setter)
{
if (setter == null)
return;
var def = (FunctionDef)setter.Statement;
def.body.Accept(this);
}

public CodeAttributeDeclaration VisitDecorator(Decorator d)
Expand Down Expand Up @@ -638,4 +700,19 @@ public void VisitYield(YieldStatement y)
gen.Yield(y.Expression.Accept(xlat));
}
}

public class PropertyDefinition
{
public string Name;
public Decorated Getter;
public Decorated Setter;
public Decorator GetterDecoration;
public Decorator SetterDecoration;
public bool IsTranslated;

public PropertyDefinition(string name)
{
this.Name = name;
}
}
}
5 changes: 3 additions & 2 deletions src/pytocs.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="nunit.framework, Version=2.6.3.13283, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<Reference Include="nunit.framework">
<HintPath>..\external\NUnit-2.6.3\nunit.framework.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
Expand All @@ -60,6 +60,7 @@
<Compile Include="CodeModel\CodeFieldReferenceExpression.cs" />
<Compile Include="CodeModel\CodeInitializerExpression.cs" />
<Compile Include="CodeModel\CodeLambdaExpression.cs" />
<Compile Include="CodeModel\CodeMemberProperty.cs" />
<Compile Include="CodeModel\CodeMethodReferenceExpression.cs" />
<Compile Include="CodeModel\CodeMethodReturnStatement.cs" />
<Compile Include="CodeModel\CodeObjectCreateExpression.cs" />
Expand Down

0 comments on commit 8c74f66

Please sign in to comment.