2015-12-01:情報が古くなったので古い部分を修正しました。

なでしこ2でプラグインを作りたい人向けというニッチすぎるネタです。現在なでしこの時期バージョンなでしこ2が開発中です(えらい長いこと開発中です)が、構文の実装がある程度終わっているので、プラグインを開発することが出来ます。try catchの実装どうするかなーとか考えて進んでないですが、それはそれ。

なでしこ2はC#で組まれているので、プラグインもC#で組むことができます。

準備

~~まずは準備として、なでしこ2のソースをsvnでチェックアウトします。 URL~~

まずは準備として、なでしこ2のソースをGithubからクローンします。 ~~

$ git clone https://github.com/kujirahand/nadesiko2.git

~~SharpDevelopで開発中なので、SharpDevelopでソリューションを開きます。~~XamarinやVisualStudioで開発出来るので、そこらへんでソリューションを開きます。

cnakoをビルドする必要があるので、Nako2_CNakoソリューション(Nako2_CNako.sln)を開いて、cnako2プロジェクトをビルドしておきます。cnako2/bin/Debugフォルダにcnako2.exeが出来ます。これをなでしこ2のコード実行に使います。

プラグイン作成

プラグイン作成には今まで作成したプラグインがNakoPluginXXXというプロジェクト名であるので、それを参考にすれば良いわけですが、軽く説明しておきます。

プラグインのソースは下のようになります。

/*
 * Created by SharpDevelop.
 * User: shigepon
 * Date: 2011/04/04
 * Time: 9:42
 *
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
using System;
using System.Collections.Generic;
using System.Text;
using Libnako.JPNCompiler;
using NakoPlugin;
namespace NakoPluginSample{
    public class NakoPluginSample : INakoPlugin    {
    string _description = "サンプルプラグイン";
        double _version = 1.0;
        //<del> プラグイン共通の部分 </del>
        public double TargetNakoVersion { get { return 2.0; } }
        public bool Used { get; set; }
        public string Name { get { return this.GetType().FullName; } }
        public double PluginVersion { get { return _version; } }
        public string Description { get { return _description; } }
        //<del> 関数の定義 </del>
        public void DefineFunction(INakoPluginBank bank)        {
            bank.AddFunc({関数名}&cedil; {なでしこ形式の引数}&cedil; {戻り値の形式}&cedil; {実際の呼び出し先}&cedil;{関数の説明}&cedil; {関数のよみかた});
        }
    // プラグインの初期化処理
        public void PluginInit(INakoInterpreter runner)        {
        }
        // プラグインの終了処理
        public void PluginFin(INakoInterpreter runner)        {
        }
       public Object {実際の処理}(INakoFuncCallInfo info){
            ...
        }
    }
}

実装時に大事なとこを説明します。

  • まずプラグイン共通部分とPluginInit、PluginFinはコピペでもかまわないと思います。私もまだ初期処理、終了処理の必要なプラグインは作っていません。
  • なでしこ上での関数呼び出し方法の定義はDefineFunctionで行います。bank.AddFuncメソッドで関数を追加できます。メソッド内の引数は下のように設定します。 ++ 関数名はなでしこで呼び出す名前になります。(例:文字検索)なでしこで使う助詞を使わないとか、他の命令の名称とかぶらないなどの制限があります。 ++ なでしこ形式の引数は「SでAを」のようになでしこで一般的に使う形式で指定します。引数を参照渡しにしたい場合は「{参照渡し}SでAを」のように指定します。助詞を複数指定したい場合は「SでAを|Sが」という形式で指定します。参照渡しを使う場合は実装が少々複雑になります。後日やり方を書こうと思います。 ++ 戻り値の形式はenum NakoVarTypeで指定します。(Void¸ Int¸ Double¸ String¸ Array) ++ 実際の呼び出し先はそのままメソッド名を指定します。(_hogeとか) ++ 関数の説明と関数のよみかたは分かりやすさの為に必要です。個人用なら適当でも良いと思います。(多分今後エディタとかそういうのにつかわれると思います)
  • 実際の処理は必ずINakoFuncCallInfo型のインスタンスを引数に取ります。なでしこで渡された引数はこのインスタンスから取得します。取得方法は以下
long l = info.StackPopAsInt();
double d = info.StackPopAsDouble();
String s = info.StackPopAsString();
Object o = info.StackPop();//配列の場合はこれを使う

~~StackPopメソッドで得られる値はNakoVariable型なので、ちょっと扱いが難しくなります。実際の処理の実装方法はまた今度~~

簡単なプラグイン

例として「なでしこ」という文字があったら、「なでしこ2最高!」と変換するだけの命令として「アピール」という命令を作ってみます。仕様は次のようにしてみます。

  • 引数は文字列として助詞は「を」を使う
  • 引数は1つ
  • プラグイン名はNakoPluginAppealとする
  • 実装用のメソッドは_appealとする

Xamarinでの作成手順は次のようになります(多分VisualStudioでも似たようなもん)

  • Nako2_Pluginsソリューション(Nako2_Plugins.slnを開く)で新しいプロジェクトとしてNakoPluginAppealという名前のC#のライブラリを作ります。(ソリューションで歯車アイコンクリック(又は右クリック))→追加→新しいプロジェクトを追加→ダイアログでC#をクリック→ライブラリを選択→名前をNakoPluginAppealとする→OK)
  • 参照にNakoPluginを追加する(NakoPluginAppealの参照で歯車アイコンクリック(又は右クリック)→参照アセンブリの編集→ダイアログで.NETアセンブリタブを選択→NakoPlugin.dllをチェック、又は閲覧ボタンからNakoPlugin.dllを選ぶ→OK)
  • NakoPluginAppeal.csを編集する
# NakoPluginAppeal.cs
using System;
using System.Text;
using Libnako.JPNCompiler;
using NakoPlugin;
namespace NakoPluginAppeal{
    public class NakoPluginAppeal : INakoPlugin    {
    string _description = &quot;サンプルプラグイン&quot;;
        double _version = 1.0;
        //<del> プラグイン共通の部分 </del>
        public double TargetNakoVersion { get { return 2.0; } }
        public bool Used { get; set; }
        public string Name { get { return this.GetType().FullName; } }
        public double PluginVersion { get { return _version; } }
        public string Description { get { return _description; } }
        //<del> 関数の定義 </del>
        public void DefineFunction(INakoPluginBank bank)        {
            bank.AddFunc("アピール", "Aを", NakoVarType.String, _appeal, "なでしこ2をアピールする", "あぴーる");
        }
    // プラグインの初期化処理
        public void PluginInit(INakoInterpreter runner)        {
        }
        // プラグインの終了処理
        public void PluginFin(INakoInterpreter runner)        {
        }
        public string _appeal(INakoFuncCallInfo info){
            string fr = info.StackPopAsString();
            return fr.Replace("なでしこ", "なでしこ2最高!");
        }
    }
}
  • ビルドする
  • NakoPluginAppeal/bin/Debug/NakoPluginAppeal.dllをcnako2/bin/Debug/にコピー

実行するなでしこ2のコードは次のようになります。

A = 「なでしこ」をアピール
Aを表示
  • これをcnako2/bin/Debug/test.nakoに保存

あとは下のコマンドを実行すれば結果が表示されます

$ cd cnako2/bin/Debug/
$ mono cnako2.exe test.nako
なでしこ最高!