Skip to content

Latest commit

 

History

History
273 lines (214 loc) · 9.15 KB

plugins.md

File metadata and controls

273 lines (214 loc) · 9.15 KB

プラグインのAPIの仕様

なでしこ3には、次の二種類のプラグインがある。

なお、(1)のプラグインは、なでしこ自身で関数を定義するもの。 以下では、(2)のJavaScriptで開発したプラグインについて解説する。

JSプラグインを利用する手順

次の2つの方法で利用ができる。

  • (1)「取り込む構文」を使ってプラグインを取り込める。
  • (2) HTMLファイル内でなでしこ本体(wnako3.js)よりも後ろで<script src="(JSプラグイン).js">と記述して読み込む。

なお「wnako3.js」を読み込むと、ブラウザの「navigator」オブジェクトにプロパティ「nako3」(navigator.nako3)にコンパイラのインスタンスが作成される。

最も簡単なプラグイン

足し算するだけの関数「テスト加算」と引き算するだけの関数「テスト減算」を定義するには次のように記述する。 ただし、以下はESModules対応版のため、cnako3から使う場合は拡張子を.mjsで保存する必要がある。

// file: testfunc.mjs
// なでしこ3プラグインはモジュールオブジェクト
export default {
  'meta': {
    type: 'const',
    value: {
      pluginName: 'plugin_***', // プラグインの名前
      description: '説明',
      pluginVersion: '3.6.0', // プラグインのバージョン
      nakoRuntime: ['wnako', 'cnako', 'phpnako'], // 対象ランタイム
      nakoVersion: '3.6.0' // 最小要求なでしこバージョン
    }
  },
  'テスト加算': {
      type: 'func',
      josi: [['と'],['を']],
      fn: function (a, b) {
        return a + b
      }
  },
  'テスト減算': {
      type: 'func',
      josi: [['から'],['を']],
      fn: function (a, b) {
        return a - b
      }
  }
}

上記プログラムを使うには、同じフォルダに次のような、なでしこ3のプログラムを記述する。

!「./testfunc.mjs」を取り込む。
7と2をテスト加算して表示。 # 結果 →9
10から3をテスト減算して表示。# 結果 → 7

プラグイン側の実装方法

プラグインの実体は、Objectである。プラグインには必ず「meta」プロパティを追加する必要がある。

{
  'meta': { type: 'const', value: { ... } },
  '定数名': { 定義 },
  '命令名': { 定義 },
  ...
}

上記の簡単なプラグインやnadesiko3-hogeを参考にして、metaプロパティを指定しよう。 また、追加したい定数と、命令を次のような書式で追加していく。

定義:関数

プラグインの実体は、Object。実際の関数定義は、fnプロパティに行う。実際の関数の引数に加えて、システムを表すsysを用意する。

{
  '関数名': { // @関数の説明 // @ヨミガナ
    type: 'func', // 関数であれば func にする
    josi: [['を', 'から'], ['まで']], // 助詞を配列で宣言する (可変長引数として扱いたい助詞は末尾で宣言する)
    isVariableJosi: false, // 末尾の助詞を可変長引数として扱う場合 true にする
    uses: [], // この関数から別の関数を呼ぶ場合に記述する // (TODO: #282)
    asyncFn: false, // async関数定義かPromiseを返す関数を定義する場合 true にする (参照: #1154)
    fn: function (aFrom, aTo, sys) { ... }, // 関数の実態
    return_none: false // 戻り値を返すかどうか
  },
  ...
}

定義:定数

typeプロパティに「const」を指定して、valueプロパティに値を指定する。

{ type: 'const', value: 100 } // @ヨミガナ

定義:変数

typeプロパティに「var」を指定して、valueプロパティに値を指定する。

{ type: 'var', value: 100 } // @ヨミガナ

プラグインの自動登録

プラグインの末尾に次のコードを仕込むとscriptタグで読み込んだときシステムに登録できる。

if (typeof (navigator) === 'object') {
  navigator.nako3.addPluginObject(プラグイン名, オブジェクト)
}

初期化メソッド

次のようなエントリを用意しておくと、プラグインを取り込み、初回実行するときに初期化メソッドが実行される。 (ただし、プラグイン取り込み時に、 !{プラグイン名}:初期化 というメソッド名にリネームされる)

{
  '初期化': {
    type: 'func',
    josi: [],
    fn: function (sys) { ... }
  }
  ...
}

クリアメソッド

次のようなエントリを用意しておくと、プログラム終了時(あるいはクリア時)にプラグインごとプログラムが実行される。

{
  '!クリア': {
    type: 'func',
    josi: [],
    fn: function (sys) { ... }
  }
  ...
}

プラグイン側からシステム変数へのアクセス

関数を定義したとき、プラグイン関数側からシステムにアクセスしなければならない場合がある。 以下は引数のない関数を定義した例だが、必ず必要とされる引数の末尾に実行したシステムのthisを保持するオブジェクトが渡される。 このオブジェクトを参照することで、システム変数にアクセスできる。

'xxx': {
  type: 'func',
  josi: [],
  fn: function (sys) {
    console.log(sys)
  }
}

例えば、なでしこで管理されている変数「A」にアクセスしたいときは、次のようなコードを記述する。なお、ローカル変数を参照するときpure: trueの関数は正しく動作しない。

'xxx': {
  type: 'func',
  josi: [],
  fn: function (sys) {
    const a = sys.__findVar('A')
    console.log(a)
  }
}

そのほかに、なでしこ側で定義した関数「HOGE」を実行したいときは、次のように記述する。

'xxx': {
  type: 'func',
  josi: [],
  fn: function (sys) {
    const result = sys.__exec('HOGE', [arg1, arg2, arg3, sys])
    console.log(result)
  }
}

また、関数の引数に与える、sysはなでしこのシステム情報を保持する。 もし、代入的関数呼び出し(setter)であれば、sys.isSetterにtrueの値が入る。

関数内で、システム・グローバル変数にアクセスするには、下記の方法でアクセスする。

// なでしこ変数の値を取得
const value = sys.__getSysVar('変数名')
// なでしこ変数の値を設定
sys.__setSysVar('変数名', value)

なお、プラグインでは、次のメソッドが使えるようになる。(すべてsrc/plugin_system.jsで定義されている。システム関数の初期化時に、これらの関数が追加される)

  • sys.__findVar(name)
  • sys.__exec(name, params)

他にも利用可能なメソッドやプロパティがあり、以下にまとめられている。

最後の助詞を可変長引数として扱う場合、システム変数は末尾の引数の末尾の要素として挿入される。

'xxx': {
  type: 'func',
  josi: [['は'], ['で']],
  isVariableJosi: true,
  fn: function (a, ...b) {
    const sys = b.pop()
    const result = sys.__exec('HOGE', [arg1, arg2, arg3, sys])
    console.log(result)
  }
}

非同期処理に対する関数を作る場合

v3.3でasyncFnが導入された(参照: #1154)。このプロパティをtrueに設定した場合、関数は非同期処理で実行される。 つまり、この関数を呼び出す前に、自動的にawaitが指定される。そのため、asyncFntrueとした場合、Promiseのオブジェクトを返すようにする。

'xxx': {
  type: 'func',
  josi: [['で']],
  asyncFn: true, // 非同期処理であることを明示
  fn: function (msec, sys) {
    // asyncFnをtrueにしたら、必ずPromiseを返すようにする
    return new Promise((resolve, _reject) => {
      setTimeout(()=>{
        resolve()
      }, msec)
    })
  }
}

あるいは、次のように、async をつけて関数を定義する。このように書くと、自動的にPromiseオブジェクトを返す。

'xxx': {
  type: 'func',
  josi: [['で']],
  asyncFn: true, // 非同期処理であることを明示
  fn: async function (msec, sys) {
    // ここで非同期処理
  }
}

この機能の追加により、「!非同期モード」「逐次実行」の利用は廃止となった。

マニュアルを自動生成する

  • doc/docgen.md にマニュアル自動生成のスクリプトが紹介されている。