共用型がまさかの完成
共用型を対応するためにRoku側のコードを書いて
CILへの対応は一旦置いといてコンパイルしてみたところ、なんと期待通りに動いてしまった!
共用型はとりあえず1個目の型に変換しとくってロジックがあるだけなのでCILでは正しいわけがない
せやからCILでは実行時型エラーになるかと思ってたら、CILって型チェックせーへんのかい!?
関数fの中身はswitch文やから、呼べたらそらまぁ動くとして
f(x: Circle)って関数が一個だけ作られて呼び出し側がTriangleやRectangleでも
へーきな顔して呼びよる
なんでも来い状態やないか
真面目に対応するモチベ下がるわ、ホンマ~
型変換を伴うif対応
型変換が出来なかったのでできるようにしてみた
どういう形がいいだろうと悩んだ挙句
どうせ型変換したらうまくいったかどうかのif文を書くんだからってことで
型変換をif文に組み込んでしまった
うーん、気持ち悪い
switch対応 その2
型によるcase式に対応できた
参照型変数は「ldloc→isinst→ldnull→cgt.un」でいいんだけど値型変数だとうまくいかない
結局、値型変数は「ldloc→box→isinst→ldnull→cgt.un」にした
boxが出てくるのはどーよって気がしなくもないけど、まぁいっか
しかし、caseとその後ろの式の区切りに「:」を使ったのは失敗だったかなぁ
ほかんところはPascal式の「var n: Int」なのにcase部分だけコロンが使えないせいでC式?の「Int n」っちゅー不思議文法になってしまった
caseと式の区切りの記号は何がいいだろう
イコールはすっげー気持ち悪いしな、Haskellのガードとか
矢印かなー、こんな感じの
switch x n: Int => print("Int") s: String => print("String " + s) h: Hoge => print(h.i)
switch対応
switch文に対応してみた
まだswitchは式にできてないので戻り値は返せないけども
とりあえず[x, xs]のxs部分にcdr相当を渡したいんだけど
めっちゃめんどくさいので単純に配列をGetRangeしてコピーすることにした
GetRangeはご丁寧にもMSDNにO(n)っすよって書いてあるけど、もうほんとめんどくさいしいいや
コンパイルした結果がこれ
わらっちゃうくらいザツい(^-^;
.method public static void switch.show(class [mscorlib]System.Collections.Generic.List`1<int32> A_0) cil managed { // コード サイズ 96 (0x60) .maxstack 7 .locals init (int32 V_0, bool V_1, int32 V_2, int32 V_3, class [mscorlib]System.Collections.Generic.List`1<int32> V_4) IL_0000: ldarg.0 IL_0001: call instance int32 class [mscorlib]System.Collections.Generic.List`1<int32>::get_Count() IL_0006: stloc.0 IL_0007: ldloc.0 IL_0008: ldc.i4.0 IL_0009: ceq IL_000b: stloc.1 IL_000c: ldloc.1 IL_000d: brtrue IL_0017 IL_0012: br IL_001c IL_0017: br IL_005f IL_001c: ldloc.0 IL_001d: ldc.i4.1 IL_001e: clt IL_0020: ldc.i4.0 IL_0021: ceq IL_0023: stloc.1 IL_0024: ldloc.1 IL_0025: brtrue IL_002f IL_002a: br IL_005f IL_002f: ldarg.0 IL_0030: ldc.i4.0 IL_0031: call instance !0 class [mscorlib]System.Collections.Generic.List`1<int32>::get_Item(int32) IL_0036: stloc.2 IL_0037: ldloc.0 IL_0038: ldc.i4.1 IL_0039: sub IL_003a: stloc.3 IL_003b: ldarg.0 IL_003c: ldc.i4.1 IL_003d: ldloc.3 IL_003e: call instance class [mscorlib]System.Collections.Generic.List`1<!0> class [mscorlib]System.Collections.Generic.List`1<int32>::GetRange(int32, int32) IL_0043: stloc V_4 IL_0047: nop IL_0048: nop IL_0049: ldloc.2 IL_004a: call void [mscorlib]System.Console::WriteLine(int32) IL_004f: ldloc V_4 IL_0053: nop IL_0054: nop IL_0055: call void switch.show(class [mscorlib]System.Collections.Generic.List`1<int32>) IL_005a: br IL_005f IL_005f: ret } // end of global method switch.show
.NETのYieldが何をしているか
.NETのYieldがどんなふうにILを出力してるんか調べてみた
VBだけ調べたけどC#も多分一緒だろう
割とcall/ccするのめんどいな
1. Yieldの付いた関数毎にIEnumeratorなクラスを作る、とりあえずStateMachineと呼ぶ
2. Yieldの付いた関数の引数、ローカル変数を全部メンバ変数に持つ
3. 戻り値と状態もメンバ変数に持つ
4. Yieldの出現箇所にユニークな連番を振る
5. Yieldしている個所の前で次のことをする
・Yieldの値を戻り値のメンバ変数に入れる
・4.で付けたユニークな番号を状態のメンバ変数に入れる
・Return Trueしとく
・Returnの後にユニークな番号に対応したラベルを張る
6. 関数を抜けるときに次のことをする
・最終行でっせというラベルを張る
・状態のメンバ変数に最終行でっせという値を入れる
・Return Falseする
' 呼び出し側 For Each x In Cdr(xs) ' なんか処理 Next Public Shared Iterator Function Cdr(xs As List(Of Integer)) For i = 1 To xs.Count - 1 Yield xs(i) Next End Function ↓ ' 呼び出し側 For Each x In New StateMachine With {._xs = xs} ' なんか処理 Next ' Yieldの関数展開結果 Class StateMachine Implements IEnumerator Private _i As Integer Private _xs As List(Of Integer) Private _value As Integer Private _state_machine As Integer = 0 Public ReadOnly Property Current() As Boolean Get Return _value End Get End Property Public Function MoveNext() As Boolean If _state_machine = 1 Then Goto __STATE1 If _state_machine = 2 Then Goto __STATE2 _i = 1 Do While _i <= _xs.Count - 1 _value = _xs(_i) _state_machine = 1 Return True __STATE1: _i += 1 Loop __STATE2: _state_machine = 2 Return False End Function End Class
簡単にcdrするILの関数書きたいだけなんだけど難しいなー・・・
関数の戻り値型から空配列の型解決
なんのこっちゃか分かりにくいけど
戻り値の型から空配列の型解決ができるようになった
型解決をするために配列を正規化している
return([]) ↓ $0 = [] return($0)
これをやると問題になるのがこんなやつ
xs = [Int]() ↓ $0 = [Int] xs = $0()
Intってのが型解決してみるまで変数なのか型なのか分からないので$0が配列型か配列か分からない
ってゆーか、変数に型の代入ができなかった
Nodeにインスタンスか型なのかのフラグを付けて対応したけど、これができひんのは分かっている
どうしようもないので後で考える
var xs = [] xs.Add(Int) var i = xs[0]()