このブログの更新は Twitterアカウント @m_hiyama で通知されます。
Follow @m_hiyama

メールでのご連絡は hiyama{at}chimaira{dot}org まで。

はじめてのメールはスパムと判定されることがあります。最初は、信頼されているドメインから差し障りのない文面を送っていただけると、スパムと判定されにくいと思います。

[参照用 記事]

最小抽象ファイルシステム仕様をセミフォーマルに書いてみる

最小抽象ファイルシステムの仕様案を最初に出したのは、6月3日「最小抽象ファイルシステムの仕様案」で、ほぼ固まったのが7月7日「最小抽象ファイルシステム、そろそろ実装」です。このあいだの変更は以外に少なくて、次のメタデータ周りの事項です。

  1. ファイルメタデータとディレクトリメタデータを集約して1種類にした。
  2. メタデータ項目から、readOnlyとhiddenを落とした。
  3. メタデータ操作APIを落とした。

一方、Catyのコマンド記述のための構文も試案ができました。そこで、最小抽象ファイルシステムのAPIをコマンド宣言の形式で書いてみます。APIはコマンドセットじゃないけど、意味的には同じようなもんです。

/** 最小抽象ファイルシステムの仕様
 * 型とコマンド(関数)
 */
module caty.mafs
  provides type // 共通の型
           [TimeStamp, Binary]
  provides type // 固有の型
           [Path, AuthoriToken, Metadata,
            DirectoryEntry, DirectoryEntryList]
  privides command // 読み取り用
           [readFile, readDirectory, getMetadata]
  privides command // 書き込み/変更用
           [createFile, createDirectory, // 生成
            deleteFile, deleteDirectory, delete, // 削除
            writeFile // 更新/書き込み
           ]
  ;

/*
 * 型の定義
 */

/** タイムスタンプ */
type TimeStamp = opaque;

/** バイナリデータ */
type Binary = opaque;

/** mafsのパス
 * http://d.hatena.ne.jp/m-hiyama/20090608/1244419502 を参照
 */
type Path = string(remark = "mafsのパス");

/** 認可トークン=アクセス権限 */
type AuthoriToken = opaque;

/** ファイルとディレクトリのメタデータ */
type Metadata = object {

  /** 内容のバイトサイズ */
  "contentLength" : integer(minimum = 0),

  /** 内容のメディアタイプ 
   * @default "application/octet-stream"
   */
  "contentType" : string(remark = "MIMEタイプ")?,

  /** ファイルが作られた時 
   * 省略されると不明を意味する 
   */
  "created" : TimeStamp?,

  /** ファイルが最後に変更された時 */
  "lastModified" : TimeStamp,

  /** 内容がテキストデータかどうか
   * @default false
   */
  "isText" : boolean?,

  /** 内容がテキストのとき、その文字エンコーディングスキーム
   * @default "utf-8"
   */
  "textEncoding" : string(remark = "文字エンコーディングスキーム")?,

  /** 実行可能ファイルかどうか
   * @default false
   */
  "executable" : boolean?
};

/** ディレクトリエントリー */
type DirectoryEntry = object {

  /** フィイルのベース名 */
  "name" : string(remark = "ファイルのベース名"),

  /** ファイル/ディレクトリのメタデータ */
  "metadata" : Metadata
};

type DirectoryEntryList = array [ DirectoryEntry* ];

/*
 * コマンド(実際は関数だけど)
 * 例外の記述は省略
 */

/* 
 * 読み取り用 
 */

/** パスで指定されたファイルの内容を読む */
command readFile [AuthoriToken, Path]
  :: void -> Binary;

/** パスで指定されたディレクトリの内容を読む */
command readDirectory [AuthoriToken, Path]
  :: void -> DirectoryEntryList;

/** パスで指定されたファイル/ディレクトリのメタデータを取得 */
command getMetadata [AuthoriToken, Path]
  :: void -> Metadata;
 
/* 
 * 書き込み/変更用
 */

/** パスで指定されたファイルを新規作成 */
command createFile [AuthoriToken, Path]
  :: void -> void;

/** パスで指定されたディレクトリを新規作成 */
command createDirectory [AuthoriToken, Path]
  :: void -> void;

/** パスで指定されたファイルを削除 */
command deleteFile [AuthoriToken, Path]
  :: void -> void;

/** パスで指定されたディレクトリを削除 */
command deleteDirectory [AuthoriToken, Path]
  :: void -> void;

/** パスで指定されたファイル/ディレクトリを削除 */
command delete [AuthoriToken, Path]
  :: void -> void;

/** パスで指定されたファイルの内容を上書きする */
command writeFile [AuthoriToken, Path, Binary]
  :: void -> void;


ちょっと感想を書きます。mafsに関する感想じゃなくて、型定義/コマンド宣言構文に関する感想。

  1. 頭部(モジュール宣言文)の構文はハッキリ決めてなかったのですが、こんな感じでしょう。
  2. TimeStamp型とBinary型は、caty.mafs以外のもっと一般的なモジュールで定義されるべきでしょう。caty.mafs:Binaryより、caty:Binary、あるいは単にBinaryが自然でしょう。
  3. 「/**」はドキュメンテーションコメントの開始です。ドキュメンテーションコメントは、直後の構文要素に関係づけられます。javadocやEDocと似たツールが必要です。
  4. ドキュメンテーションコメント内は、プレーンテキスト、またはCreole wiki構文でいいかな、と思ってますが、スキーマ内でデフォルト値を書けないので、@default とか使ってみました。アットマークタグをほんとにサポートするかどうかは未定です。
  5. 「詮索は不要、中身を見るな」という意味で opaque というキーワードを付け足しました。あるレベルのアプリケーションにとって詳細が不要なときに、これは必要ですね。
  6. opaqueは、データの構造に関する情報を意図的に提供しないのですが、「まだ定義してない」ということを表すdeferredキーワードも必要でしょう。
  7. 空なオプション{}、空なプレーン引数[]は、やっぱり省略できたほうがいいですね。
  8. 上の例では使ってませんが、API記述で使うにはアノテーションも必要そうです。例えば、読み取り関数には @reader、更新関数には @updater とか。
  9. JSONスキーマの代替構文としてはじまったCaty/Jcentric型定義ですが、IDL(Interface Definition Language)として利用することになりそうです。もう少し拡張すれば、IDLとしての体裁が整うでしょう。