NemerleでDesign by contract

オンラインドキュメントを見てて、出来ることに気づいた。

using System;
using Nemerle.Assertions;
using Nemerle.IO;

module Calc {
  [Requires(x >= 0 && y >= 0)]  // 事前条件
  [Ensures(value >= 0)]      // 事後条件
  public Add(x : int, y : int) : int {
    unchecked { x + y }
  }
}

module M {
  Main() : void {
    // 計算される
    printf("%d\n", Calc.Add(10, 20));

    try {
      // x < 0なので事前条件に違反 
      printf("%d\n", Calc.Add(-1, 20));
    }
    catch {
      | e : AssertionException =>
        printf("%s\n", e.Message)
    }

    try {
      // y < 0なので事前条件に違反
      printf("%d\n", Calc.Add(10, -1));
    }
    catch {
      | e : AssertionException =>
        printf("%s\n", e.Message)
    }

    try {
      // オーバーフローを起こす
      // value(メソッドの値、つまり戻り値) < 0なので事後条件に違反 
      printf("%d\n", Calc.Add(Int32.MaxValue, 1));
    }
    catch {
      | e : AssertionException =>
        printf("%s\n", e.Message)
    }
  }
}
/* 結果
30
assertion ``x >= 0 && y >= 0'' failed in file test.n, line 6:
The ``Requires'' contract has been violated.
assertion ``x >= 0 && y >= 0'' failed in file test.n, line 6:
The ``Requires'' contract has been violated.
assertion ``value >= 0'' failed in file test.n, line 7:
The ``Ensures'' contract has been violated. */

こんな感じ。これもNemerleのマクロで実現されています。強力だなぁ。