コンパイル時の型検査の話だったんですね。たしかにそう書いてあります。とほほ。>id:soutaro 様
それと。タイトルが「MTASCの型検査」だったのがよくありませんでした。AS2 の型検査と書くべきでした。
id:soutaro 様の興味とは離れていくと思いますが、実行時の型の話を中心にもうちょっと AS2*1の型の話を書いてみます。
で。文体が変わり。
実は私も Macromedia のコンパイラよりも MTASC の方が型検査が厳しいのかな。と思っていた。Macromedia のコンパイラが手元にないのでその辺りはわからないのだが、いろいろ試していると、どうも MTASC でもほとんど型検査をしていなさそうなので、同程度だと思われる。これ以下の実装は想像できないからだ。
それとは別に。
AS2 の型は、ちょっと意外な実装になっている。少なくとも、私には意外であった。
var a:Number=0; // これは正しいに決まっている。 var b:Number=true; // type error Boolean should be Number。暗黙の変換は行われない var c:Number=["foo"][0]; // 配列経由だと何を入れられても気づかない var d:Number=new Object(0); // type error Object should be Number。 var e:Number=function():Object{ return 0; }() // type error Object should be Number。
上記の結果だけを見ると、なんとなくああそうかという気になるかもしれないが。
var d=new Object(0); var e=function():Object{ return 0; }() var o:Object = 0; var f = o; var g:Object = Object(0); var h:Object = 0;
を実行すると、
typeof(d) == "object" typeof(e) == "number" typeof(f) == "number" typeof(g) == "object" typeof(h) == "number"
となる。e への代入はコンパイル時にはエラーになるが、実行時には正しい型が入る。c への代入はコンパイルは通るものの実行時には不正な型が入る。
この結果から、変数の型指定はコンパイルエラーを出す以外には何の役にも立っていなさそうだとわかる。と思う。しかも、チェックは非常にいい加減。
d, g は object で e, f, h は number だが、両者の間には実際違いがある。
d.foo="bar" などとすると、d, g は実際に d.foo, g.foo には "bar" を格納することができるが、e.foo="bar" などとしても、e.foo は undefined のままである*2。
しかし、d, g は純粋な Object 型かというとそうでもなく、d+1, g+=2 は普通に計算できる*3。
ちなみに。
var g:Object = Object(0); var h:Object = 0; var i:Number = [Object(0)][0] var j:Number = 0; var p=false var q=Object(false)
を実行すると、
!g==false, (0==g)==true !h==true, (0==h)==true !i==false, (0==i)==true !j==true, (0==j)==true !p==true, !q==false,
となる。
この例も、変数につけられた型が役に立っていないことを示している。
! 演算子と 「0==」 が一致しないのはちょっと意外だし、!Object(false) が false なのも意外である。
難しい。
*1:昨日は ActionScript と書いたが、ActionScript1.0 にはなかった機能なので、ActionScript2.0 と書くべきだったと思う。略して AS2
*2:にもかからわず、e.foo="bar" は、例外を返したりはしない。まずい仕様だと思う。