2D

use strict
use Acme::ICFP2006::2D::Parser;
my $f = Acme::ICFP2006::2D::Parser->parse("2d/mult.2d");
my $a = 3;
my $b = 4;
my $ans = $f->{modules}->{mult}->call(toIntExp($a), toIntExp($b));
print $ans->str;


sub toIntExp{
  my $a = shift;
  my $str = "Inl " x $a . "Inr ()";
  return Acme::ICFP2006::2D::Exp->new($str);
}

実行結果

Inl Inl Inl Inl Inl Inl Inl Inl Inl Inl Inl Inl Inr ()

出来た。
ちなみに、mult.2dは、以下の通り。

      ,..............................|....................................,
      :plus                          |                                    :
      :  *==================*        |                                    :
      -->!send [(W,S),(W,E)]!--------#--------------------+               :
      :  *==================*        |                    |               :
      :         |                    |                    |               :
      :         |                    v                    v               :
      :         |                 *==============*    *============*      :
      :         |                 !case N of S, E!--->!send [(N,E)]!-------
      :         |                 *==============*    *============*      :
      :         |                        |                                :
      :         |                        v                                :
      :         |                    *========*       *================*  :
      :         +------------------->!use plus!------>!send [(Inl W,E)]!---
      :                              *========*       *================*  :
      ,...................................................................,

,..............................|....................................,
mult |
*=================* |
    • >!send[(W,S),(W,E)]!---------#-------------------+ :
*=================* v v
| *==============* *=================*
: | !case N of S, E!---->!send[(Inr (), E)]!--
| *==============* *=================*
| |
v |
*==========* |
!split(N,N)!--------------#------------+
*==========* | |
| | |
| v v
| *========* *========*
: +--------------->!use mult!---->!use plus!-----------------
*========* *========*
,...................................................................,

Perlにおけるtry catch

最近はJavaを書くことが多かったので、偶にPerlを書くとついついはまりがち。
Perlにおいてエラーなんかをトラップするための方法として、evalがあります。
http://perldoc.perl.org/functions/eval.html
で、まず一つ目としてこのevalはあくまで「関数」であって、構文ではありません。具体的にいうならば、

a = 1 / 0;

というものに対して、try catchをするのであれば、Javaならばこうすればいいわけです。

try{
a = 1 / 0;
}catch(Exception e){

}

Perlの場合、同様の方法として、eval{}; if($@){}というのがありますが、この場合、evalの後ろのBLOCKの後に、必ずセミコロンが必要です。ifの後ろには要りません。どれだけ長いBLOCKであっても、セミコロンを付け忘れるとエラーです。

次に、もう一つの問題として、returnというのがあります。例えば長い関数なりメソッドがあったとして、この関数に後からエラートラップを導入するとします。その際に、

sub hoge{
   eval{
     #do something
     die;
     #do something
     return $a;
   };
   print $@ if($@);
}

としてしまうと、$aは結局returnされません。return $aの返る先は、あくまでeval文です。evalの返り値が$aになるので、これをちゃんと変数で受けてやって、その上でreturnしてやる必要があります。
ということで、2Dの実装で一番はまった部分でした。