Perlのパッケージを別の言語の型に変換する実験
Perlのコードから型情報、型に定義されてるメソッド情報をJSONに書き出します。
関数・メソッドの情報はFunction::Parameters
やFunction::Return
のメタ情報だけじゃなく、Data::Validator
やASTから引数名や型などをできるだけ取り出しています。
package My::Namespace::B;
use strictures 2;
use Function::Parameters;
use Function::Return;
use Types::Standard -types;
use Data::Validator;
use Mouse;
has name => (is => 'ro', isa => Str, default => 'this is name');
has age => (is => 'ro', isa => Int, required => 1);
has union => (is => 'ro', isa => Str|Int, required => 1);
no Mouse;
__PACKAGE__->meta->make_immutable;
sub a {
return 10;
}
fun b() :Return(Int) {
return 10;
};
method c() :Return(Int) {
return 10;
};
method d(Str $str, $x, Int $y //= 1) {
return 10;
};
sub e {
my $rule = Data::Validator->new(
str => { isa => Str },
x => { isa => Any },
y => { isa => Int, default => 1 },
);
$rule->validate(@_);
return 10;
}
sub f :Return(Str, Int) {
my ($self, $str, $x, $y) = @_;
return [$str, $x+$y];
}
1;
生成されたJSONからC#のASTを構築してC#のソースコードを出力してます。ベース部分はJSON Schemaから生成しているので、アノテーションがついたままになっています。
//----------------------
// <auto-generated>
// Generated using the NJsonSchema v10.9.0.0 (Newtonsoft.Json v9.0.0.0) (http://NJsonSchema.org)
// </auto-generated>
//----------------------
namespace My.Namespace
{
#pragma warning disable // Disable all warnings
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.9.0.0 (Newtonsoft.Json v9.0.0.0)")]
public partial class B
{
/// <summary>
/// original Perl type: Int
/// </summary>
[System.Text.Json.Serialization.JsonPropertyName("age")]
[System.Text.Json.Serialization.JsonIgnore(Condition = System.Text.Json.Serialization.JsonIgnoreCondition.Never)]
public int Age { get; set; }
/// <summary>
/// original Perl type: Dict[age=>Int,name=>Str]
/// </summary>
[System.Text.Json.Serialization.JsonPropertyName("dict")]
[System.Text.Json.Serialization.JsonIgnore(Condition = System.Text.Json.Serialization.JsonIgnoreCondition.Never)]
public Dict Dict { get; set; } = new Dict();
/// <summary>
/// original Perl type: Str
/// </summary>
[System.Text.Json.Serialization.JsonPropertyName("name")]
[System.Text.Json.Serialization.JsonIgnore(Condition = System.Text.Json.Serialization.JsonIgnoreCondition.Never)]
public string Name { get; set; } = "this is name";
/// <summary>
/// original Perl type: Str|Int
/// </summary>
[System.Text.Json.Serialization.JsonPropertyName("union")]
[System.Text.Json.Serialization.JsonIgnore(Condition = System.Text.Json.Serialization.JsonIgnoreCondition.Never)]
public Union Union { get; set; }
private System.Collections.Generic.IDictionary<string, object> _additionalProperties;
[System.Text.Json.Serialization.JsonExtensionData]
public System.Collections.Generic.IDictionary<string, object> AdditionalProperties
{
get
{
return _additionalProperties ?? (_additionalProperties = new System.Collections.Generic.Dictionary<string, object>());
}
set
{
_additionalProperties = value;
}
}
///<summary></summary>
///<returns></returns>
public object a()
{
throw new NotImplementedException();
}
///<summary></summary>
///<param name = "str">original Perl type: Str</param>
///<param name = "x">original Perl type: Any</param>
///<param name = "y">original Perl type: Int</param>
///<returns></returns>
public object e(string str, object x, int y = 1)
{
throw new NotImplementedException();
}
///<summary></summary>
///<returns>original Perl type: Str, Int</returns>
public object f()
{
throw new NotImplementedException();
}
///<summary></summary>
///<returns></returns>
public void g()
{
throw new NotImplementedException();
}
///<summary></summary>
///<param name = "a">original Perl type: Any</param>
///<returns></returns>
public object h(object a)
{
throw new NotImplementedException();
}
///<summary></summary>
///<returns>original Perl type: Int</returns>
public int b()
{
throw new NotImplementedException();
}
///<summary></summary>
///<returns>original Perl type: Int</returns>
public int c()
{
throw new NotImplementedException();
}
///<summary></summary>
///<param name = "str">original Perl type: Str</param>
///<param name = "x">original Perl type: Any</param>
///<param name = "y">original Perl type: Int</param>
///<returns></returns>
public object d(string str, object x, int y)
{
throw new NotImplementedException();
}
}
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.9.0.0 (Newtonsoft.Json v9.0.0.0)")]
public partial class Dict
{
[System.Text.Json.Serialization.JsonPropertyName("age")]
[System.Text.Json.Serialization.JsonIgnore(Condition = System.Text.Json.Serialization.JsonIgnoreCondition.Never)]
public int Age { get; set; }
[System.Text.Json.Serialization.JsonPropertyName("name")]
[System.Text.Json.Serialization.JsonIgnore(Condition = System.Text.Json.Serialization.JsonIgnoreCondition.Never)]
public string Name { get; set; }
private System.Collections.Generic.IDictionary<string, object> _additionalProperties;
[System.Text.Json.Serialization.JsonExtensionData]
public System.Collections.Generic.IDictionary<string, object> AdditionalProperties
{
get
{
return _additionalProperties ?? (_additionalProperties = new System.Collections.Generic.Dictionary<string, object>());
}
set
{
_additionalProperties = value;
}
}
}
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.9.0.0 (Newtonsoft.Json v9.0.0.0)")]
public partial class Union
{
private System.Collections.Generic.IDictionary<string, object> _additionalProperties;
[System.Text.Json.Serialization.JsonExtensionData]
public System.Collections.Generic.IDictionary<string, object> AdditionalProperties
{
get
{
return _additionalProperties ?? (_additionalProperties = new System.Collections.Generic.Dictionary<string, object>());
}
set
{
_additionalProperties = value;
}
}
}
}
- メソッド情報以外の情報はJSON Schemaから得ることにして、メソッド情報はASTやメタ情報からとるようにする
- 型のひな型はJSON Schemaから生成して、メソッドはそこに追加するように書き換える
- メソッドの型情報もJSON Schema準拠?にしたので、上手いこと生成できるとうれしいかもしれない
PerlのパッケージってJSON Schema生成できるんですか?
↑自力でやるしかなかった