トップ 追記

uDiary

海野秀之(うんのひでゆき)の外部記憶

Twitter (twilog) / RSS / アンテナ / ぶくま

2006|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|08|
2010|01|02|03|05|06|07|10|11|
2011|03|08|
2012|02|04|07|08|10|
2013|01|02|03|05|06|08|11|12|
2014|01|02|05|06|07|08|09|12|
2015|01|

2015-01-30 (Fri)

[Haskell][Hand] Parser.y デバッグ

昨日、Haskell 2010 report みながら、えいっと Parser.y を書いたんだけど、
ずいぶん conflict を出してしまった。

unused rules: 5
shift/reduce conflicts:  144
reduce/reduce conflicts: 212

ひとつひとつ、文法の曖昧なのをなくしていこう。
ひとつの問題で沢山の衝突が引き起される傾向があるようなので、この数ほど修正箇所はないだろう。

1. 空の規則じゃなくて error トークンをつかう

レイアウト規則では、そうしないと構文エラーになる箇所には仮想閉じブレースが補われることに
なっている。

そこで、仮想ブレースが閉じていないのを許容する文法にすればいいのかなと思ったんだけど、
こういうのはいかにも衝突の原因になる。

ccurly_opt: vccurly                            {}
  |          {- empty -}                        { {- pop ctx -} }

GHC のパーサーのソースをみると、error トークンが使われていて、Happy のマニュアルにも
そういう利用方法が書かれている

close : '}'                  { () }
      | error        { () }

ついでに、非終端記号の名前も真似して close にしてみよう。

unused rules: 5
shift/reduce conflicts:  96
reduce/reduce conflicts: 176

shift/reduce が 48 個減、reduce/reduce が 36 個へった。

2. 単純間違い

lpat: gcon seq_apat

lpat: gcon seq1_apat

の間違いだった。このせいで apat: gcon と衝突。

unused rules: 5
shift/reduce conflicts:  128 (+32)
reduce/reduce conflicts: 127 (-49)

3. 空規則の除去

やっぱ空の規則をつくりすぎるのよくないもう一つの例。

topdecl: 'class' sctx_opt tycls tyvar 'where' cdecls

ctx_opt: context '=>'
  |      {- empty -}

こんななのだが、context の最初にも tycls と同じ文字列が来てもいいので曖昧。
GHC のソースをみると、A -> (context '=>' |) のような非終端記号をつくるので
はなく、

tycl_hdr -> context '=>' tycls | tycls

のようにしてあった。こうすることで、問題となる還元規則がなくなり、

パーサは tycls が context の一部なのかそうでないのか判明するまで複数のポインタを
持てるようになる。(「lex&yacc プログラミング」p.301)

ただ、このあたりは、上のように文法を書き直すだけじゃなくて、もうちょっと整理しないとだめっぽい。

qconid, qtycls などもいっぱい衝突している。(軒並 qconid に還元しようとしたり)

まいったな、まだまだだな。


2015-01-26 (Mon)

[Haskell][Hand] Lexer デバッグ

Haskell x Android プロジェクト(仮)

Tigerbook は基礎編を一通りこなしたので、まえからやりたかった「Haskell で Haskell コンパイラを書いてみる」プロジェクトに移行。

Lexer を一通り書いて、Parser の作成と Absyn (抽象構文)の作成を並行してやる感じかなぁと思いつつとりかかっていた。

んが、「一通りこなした」部分もきちんと勉強しなおそうというのも同時にやっていて、正規言語やら文脈自由言語やらその解析方法やらも復習している。そのために、結局 Dragon book も入手してしまった。で、再帰下降パーサといえば、『プログラミング Haskell』にもそういう章があったなと8章を見直したり。ふむふむ。あそこに述べられているのは、バックトラックのある(予測型ではない)再帰下降パーサーだな。左端のくくり出しもして LL(1) 文法に直すとこまでやっているのに、予測型再帰下降パーサにはせずに終わっている。

そりゃそうと、そんな風に Monadic Parser を復習してたら、これ の書き方がわかったので、Happy による Parser を作らなくても Lexer のデバッグができるようになった。で、案の定、いろいろ間違ってた。

  • 文字列が入力ストリームを全部食べてしまう: start code 間違い(チョンボ)
  • rsvdop, rsvdid まわり(昨日最後に足した)がおかしかった
  • 文字列が layout 開始の位置に来たときの動作が変

いずれも、直したつもり。Lexer の確認のために今日用意したテストケースは 4つ

test1.hs は、Haskell 2010 の Figure 2.1 にあるもの。

$ sample/lexer_sample < testcases/test1.hs 
[TModule (AlexPn 0 1 1),TConid ("AStack",AlexPn 8 1 8),TOParen (AlexPn 15 1 14),TConid ("Stack",AlexPn 18 1 16),TComma (AlexPn 24 1 21),TVarid ("push",AlexPn 27 1 23),TComma (AlexPn 32 1 27),TVarid ("pop",AlexPn 35 1 29),TComma (AlexPn 39 1 32),TVarid ("top",AlexPn 42 1 34),TComma (AlexPn 46 1 37),TVarid ("size",AlexPn 49 1 39),TCParen (AlexPn 55 1 44),TWhere (AlexPn 58 1 46),TVOCurly (AlexPn 66 2 1),TData (AlexPn 66 2 1),TConid ("Stack",AlexPn 72 2 6),TVarid ("a",AlexPn 79 2 12),TEqual (AlexPn 82 2 14),TConid ("Empty",AlexPn 85 2 16),TVBar (AlexPn 107 3 14),TConid ("MkStack",AlexPn 110 3 16),TVarid ("a",AlexPn 119 3 24),TOParen (AlexPn 122 3 26),TConid ("Stack",AlexPn 124 3 27),TVarid ("a",AlexPn 131 3 33),TCParen (AlexPn 133 3 34),TSemi (AlexPn 140 5 1),TVarid ("push",AlexPn 140 5 1),TDColon (AlexPn 147 5 6),TVarid ("a",AlexPn 151 5 9),TRArrow (AlexPn 154 5 11),TConid ("Stack",AlexPn 158 5 14),TVarid ("a",AlexPn 165 5 20),TRArrow (AlexPn 168 5 22),TConid ("Stack",AlexPn 172 5 25),TVarid ("a",AlexPn 179 5 31),TSemi (AlexPn 184 6 1),TVarid ("push",AlexPn 184 6 1),TVarid ("x",AlexPn 191 6 6),TVarid ("s",AlexPn 194 6 8),TEqual (AlexPn 197 6 10),TConid ("MkStack",AlexPn 200 6 12),TVarid ("x",AlexPn 209 6 20),TVarid ("s",AlexPn 212 6 22),TSemi (AlexPn 219 8 1),TVarid ("size",AlexPn 219 8 1),TDColon (AlexPn 226 8 6),TConid ("Stack",AlexPn 230 8 9),TVarid ("a",AlexPn 237 8 15),TRArrow (AlexPn 240 8 17),TConid ("Int",AlexPn 244 8 20),TSemi (AlexPn 251 9 1),TVarid ("size",AlexPn 251 9 1),TVarid ("s",AlexPn 258 9 6),TEqual (AlexPn 261 9 8),TVarid ("length",AlexPn 264 9 10),TOParen (AlexPn 272 9 17),TVarid ("stkToLst",AlexPn 274 9 18),TVarid ("s",AlexPn 284 9 27),TCParen (AlexPn 286 9 28),TWhere (AlexPn 290 9 31),TVOCurly (AlexPn 309 10 12),TVarid ("stkToLst",AlexPn 309 10 12),TConid ("Empty",AlexPn 320 10 22),TEqual (AlexPn 335 10 36),TOBrack (AlexPn 338 10 38),TCBrack (AlexPn 340 10 39),TSemi (AlexPn 356 11 12),TVarid ("stkToLst",AlexPn 356 11 12),TOParen (AlexPn 367 11 21),TConid ("MkStack",AlexPn 369 11 22),TVarid ("x",AlexPn 378 11 30),TVarid ("s",AlexPn 381 11 32),TCParen (AlexPn 383 11 33),TEqual (AlexPn 387 11 36),TVarid ("x",AlexPn 390 11 38),TColon (AlexPn 392 11 39),TVarid ("xs",AlexPn 394 11 40),TWhere (AlexPn 398 11 43),TVOCurly (AlexPn 404 11 49),TVarid ("xs",AlexPn 404 11 49),TEqual (AlexPn 408 11 52),TVarid ("stkToLst",AlexPn 411 11 54),TVarid ("s",AlexPn 421 11 63),TVCCurly (AlexPn 428 13 1),TVCCurly (AlexPn 428 13 1),TSemi (AlexPn 428 13 1),TVarid ("pop",AlexPn 428 13 1),TDColon (AlexPn 436 13 5),TConid ("Stack",AlexPn 440 13 8),TVarid ("a",AlexPn 447 13 14),TRArrow (AlexPn 450 13 16),TOParen (AlexPn 454 13 19),TVarid ("a",AlexPn 456 13 20),TComma (AlexPn 458 13 21),TConid ("Stack",AlexPn 461 13 23),TVarid ("a",AlexPn 468 13 29),TCParen (AlexPn 470 13 30),TSemi (AlexPn 475 14 1),TVarid ("pop",AlexPn 475 14 1),TOParen (AlexPn 481 14 5),TConid ("MkStack",AlexPn 483 14 6),TVarid ("x",AlexPn 492 14 14),TVarid ("s",AlexPn 495 14 16),TCParen (AlexPn 497 14 17),TEqual (AlexPn 504 15 3),TOParen (AlexPn 507 15 5),TVarid ("x",AlexPn 509 15 6),TComma (AlexPn 511 15 7),TCase (AlexPn 514 15 9),TVarid ("s",AlexPn 520 15 14),TOf (AlexPn 523 15 16),TVOCurly (AlexPn 526 15 19),TVarid ("r",AlexPn 526 15 19),TRArrow (AlexPn 529 15 21),TVarid ("i",AlexPn 533 15 24),TVarid ("r",AlexPn 536 15 26),TWhere (AlexPn 539 15 28),TVOCurly (AlexPn 545 15 34),TVarid ("i",AlexPn 545 15 34),TVarid ("x",AlexPn 548 15 36),TEqual (AlexPn 551 15 38),TVarid ("x",AlexPn 554 15 40),TCParen (AlexPn 556 15 41),TVCCurly (AlexPn 588 17 1),TVCCurly (AlexPn 588 17 1),TSemi (AlexPn 588 17 1),TVarid ("top",AlexPn 588 17 1),TDColon (AlexPn 596 17 5),TConid ("Stack",AlexPn 600 17 8),TVarid ("a",AlexPn 607 17 14),TRArrow (AlexPn 610 17 16),TVarid ("a",AlexPn 614 17 19),TSemi (AlexPn 619 18 1),TVarid ("top",AlexPn 619 18 1),TOParen (AlexPn 625 18 5),TConid ("MkStack",AlexPn 627 18 6),TVarid ("x",AlexPn 636 18 14),TVarid ("s",AlexPn 639 18 16),TCParen (AlexPn 641 18 17),TEqual (AlexPn 644 18 19),TVarid ("x",AlexPn 647 18 21)]

うーん、いっぱいだ。あとで見よう。ってことで、小さいやつを用意したのがあとの3つ。

$ sample/lexer_sample < testcases/test2.hs 
[TVOCurly (AlexPn 0 1 1),TVarid ("main",AlexPn 0 1 1),TEqual (AlexPn 6 1 6),TVarid ("putStrLn",AlexPn 9 1 8),TString ("Hello",AlexPn 19 1 17)]


$ sample/lexer_sample < testcases/test3.hs 
[TModule (AlexPn 0 1 1),TConid ("Main",AlexPn 8 1 8),TWhere (AlexPn 14 1 13),TVOCurly (AlexPn 21 3 1),TVarid ("main",AlexPn 21 3 1),TEqual (AlexPn 27 3 6),TDo (AlexPn 30 3 8),TVOCurly (AlexPn 35 4 3),TVarid ("putStr",AlexPn 35 4 3),TString ("Hello",AlexPn 43 4 10),TSemi (AlexPn 54 5 3),TVarid ("putStrLn",AlexPn 54 5 3),TString (", world!",AlexPn 65 5 12)]


$ sample/lexer_sample < testcases/test4.hs 
[TVOCurly (AlexPn 0 1 1),TVarid ("f",AlexPn 0 1 1),TVarid ("s1",AlexPn 3 1 3),TVarid ("s2",AlexPn 7 1 6),TEqual (AlexPn 11 1 9),TVarid ("putStrLn",AlexPn 14 1 11),TVarsym ("$",AlexPn 24 1 20),TVarid ("s1",AlexPn 27 1 22),TVarsym ("++",AlexPn 31 1 25),TVarid ("s2",AlexPn 35 1 28),TSemi (AlexPn 40 3 1),TVarid ("main",AlexPn 40 3 1),TEqual (AlexPn 47 3 6),TDo (AlexPn 50 3 8),TVOCurly (AlexPn 55 4 3),TString ("foo",AlexPn 55 4 3),TBackquote (AlexPn 62 4 9),TVarid ("f",AlexPn 64 4 10),TBackquote (AlexPn 66 4 11),TString ("bar",AlexPn 69 4 13),TSemi (AlexPn 78 5 3),TVarid ("putStrLn",AlexPn 78 5 3),TString ("Hello!",AlexPn 89 5 12)]

最後の test4.hs が今日見つけた問題の確認用で、do 節の最初のトークンが文字列だった場合のやつ。直す前は、文字列の後ろに仮想 ocurly が挿入されてしまっていた。

test1 の結果が正しいかどうかは、明日みましょ。


2015-01-12 (Mon)

[Tiger][Haskell] Tiger book 12 章、動作確認&デバッグ開始

FizzBuzz_a

前回 は、レジスタ割付けを人手でやってどうにか動かしたんだが、あれから10章(生存解析)、11章(レジスタ割付け)を経て、晴れて全部コンパイラでできるようになった。

まだ未実装の機能もあり、機能確認もこれからなので、確認済の限られた機能だけをつかって FizzBuzz をやってみた。実行結果のスクリーンショットが上、ソースが下である。なんか、まだ & 演算子を実装してなかったようで、最初の条件を mod3 = 0 & mod5 = 0 のように書いたらうまくいかなかった。

それはそうと、うまくいかないときに「残念ながらアプリは停止しました」しか情報がないのがつらい。

let
  var mod5 := 0
  var mod3 := 0
in
  for i := 1 to 30 do (
    mod5 := i - i / 5 * 5;
    mod3 := i - i / 3 * 3;

    if (mod5 + mod3) = 0 then
      print("FizzBuzz, ")
    else if mod3 = 0 then
      print("Fizz, ")
    else if mod5 = 0 then
      print("Buzz, ")
    else
      (print(toString(i)); print(", "))
   );
   print("...\n")
end

以下、完全に自分むけメモだけど、今日の修正について。

Assem.hs の修正(oper_dst に src も加えた)は、Assem が複数命令を含んでいることによるもの。Assem の外からみると src と dst が干渉していることがわからないので、src が出口生存でないときにハザードを起した。ほんとは、Assem は1命令に対応するように実装すべきだったかも。

MakeGraph.hs はチョンボの修正。新しいラベルが保留中の前方参照を解決するときに、そのラベルと次の命令をただしく継げられていなかった。

この後、以下のように確認・デバッグを進めようかな。

  • 演算、構文をひとつずつ試していく
  • 関数の prelude 部分を実装(まだだったの)
  • 関数呼出し
  • Static link の確認
  • Record, Array

2015-01-02 (Fri)

[Tiger][Haskell] Tigerbook 10 章つづき

去年の 10/2 に instrs2graph (命令リストから制御フローグラフをつくる関数)を書きかけていたまま、しばらく間があいてしまって忘れかけていたのを読んだ。

どうも、instrs2graph は完成寸前のところで止まっていたので、今日いちおう完成させて、動かしてみた。

つぎは、

  • instrs2graph のテストを書く
  • 10 章の残り、生存解析に進む(干渉グラフの生成)

です。


2014-12-31 (Wed)

[Tiger][Haskell] Tiger Compiler を動かしてみる(一部人手)

そろそろ出来てきたので、というか、今年中に動かすのが目標だったので、ちょっと無理やりにでも動かしてみることにする。

Tiger 言語から Dalvik アセンブリ言語へのコンパイラはほぼできていて、Dalvik アセンブリ言語から APK ファイルをつくるあたりもだいたいできているので、ちょっと手を加えてやれば、動かしてみることができるはず、なのだ。

えーと、なにが未だかというと、レジスタ割付けがまだなので(まだ Tiger Book は10章途中なの)、今回は、そこだけ人手で。

(1) Hello, World!

Tiger 言語のソースはこちら:

print("Hello, world!")

これを、現状のコンパイラでコンパイルした結果がこちら:

.class public Luhideyuki/daat/DaatProg;
.super Ljava/lang/Object;

.method public constructor <init>()V
    .registers 1
    invoke-direct {p0}, Ljava/lang/Object;-><init>()V
    return-void
.end method


---- prog ----
:L1
const-string t4, "Hello, world!"
move-object v0, t4
invoke-static {v0}, Luhideyuki/daat/DaatRuntime;->print(Ljava/lang/String;)Ljava/lang/Integer;
move-result-object t5
const t7, 0
new-instance t6, Ljava/lang/Integer;
invoke-direct {t6, t7}, Ljava/lang/Integer;-><init>(I)V
return-object t6
goto :L0
:L0

まだ、関数の prologue (宣言部分とか) が出力されていなかったり、レジスタ番号が仮のまま(t4, t5 とかは一時変数の番号そのまま)です。そこで、今回は人手で少し手を加えてあげます:

.class public Luhideyuki/daat/DaatProg;
.super Ljava/lang/Object;

.method public constructor <init>()V
    .registers 1
    invoke-direct {p0}, Ljava/lang/Object;-><init>()V
    return-void
.end method


.method public static main([Ljava/lang/Object;Ljava/lang/Integer;)Ljava/lang/Integer;
    .locals 5

:L1
const-string v1, "Hello, world!"
move-object v0, v1
invoke-static {v0}, Luhideyuki/daat/DaatRuntime;->print(Ljava/lang/String;)Ljava/lang/Integer;
move-result-object v2

const v4, 0
new-instance v3, Ljava/lang/Integer;
invoke-direct {v3, v4}, Ljava/lang/Integer;-><init>(I)V
return-object v3
#goto :L0
#:L0

.end method

これを、別途用意したランタイム関数といっしょに assembly, apk builder etc. にかけて…

できました!:

Helo

(2) for 文で5回実行

Hello, world! だけではナンなので、もうちょっとだけプログラムっぽいのもやってみる。
これ:

for i := 1 to 5 do print("Hello! ")

これを、現状のコンパイラにかけたのがこれで、

.class public Luhideyuki/daat/DaatProg;
.super Ljava/lang/Object;

.method public constructor <init>()V
    .registers 1
    invoke-direct {p0}, Ljava/lang/Object;-><init>()V
    return-void
.end method


---- prog ----
:L4
const t7, 1
new-instance t6, Ljava/lang/Integer;
invoke-direct {t6, t7}, Ljava/lang/Integer;-><init>(I)V
move-object t4, t6
const t9, 5
new-instance t8, Ljava/lang/Integer;
invoke-direct {t8, t9}, Ljava/lang/Integer;-><init>(I)V
move-object t5, t8
:L1
check-cast t4, L/java/lang/Integer;
invoke-virtual {t4}, Ljava/lang/Integer;->intValue()I
move-result t10
check-cast t5, L/java/lang/Integer;
invoke-virtual {t5}, Ljava/lang/Integer;->intValue()I
move-result t11
if-le t10, t11, :L2
const t13, 0
new-instance t12, Ljava/lang/Integer;
invoke-direct {t12, t13}, Ljava/lang/Integer;-><init>(I)V
return-object t12
goto :L3
:L2
const-string t14, "Hello! "
move-object v0, t14
invoke-static {v0}, Luhideyuki/daat/DaatRuntime;->print(Ljava/lang/String;)Ljava/lang/Integer;
move-result-object t15
const t17, 1
new-instance t16, Ljava/lang/Integer;
invoke-direct {t16, t17}, Ljava/lang/Integer;-><init>(I)V
check-cast t4, Ljava/lang/Integer;
check-cast t16, Ljava/lang/Integer;
invoke-virtual {t4}, Ljava/lang/Integer;->intValue()I
move-result t19
invoke-virtual {t16}, Ljava/lang/Integer;->intValue()I
move-result t20
add-int t19, t19, t20
new-instance t18, Ljava/lang/Integer;
invoke-direct {t18, t19, Ljava/lang/Integer;-><init>(I)V
move-object t4, t18
goto :L1
:L3

手作業でレジスタ割付けなど少し手をくわえたのがこれ:

.class public Luhideyuki/daat/DaatProg;
.super Ljava/lang/Object;

.method public constructor <init>()V
    .registers 1
    invoke-direct {p0}, Ljava/lang/Object;-><init>()V
    return-void
.end method


.method public static main([Ljava/lang/Object;Ljava/lang/Integer;)Ljava/lang/Integer;
    .locals 21

:L4
const v7, 1
new-instance v6, Ljava/lang/Integer;
invoke-direct {v6, v7}, Ljava/lang/Integer;-><init>(I)V
move-object v4, v6
const v9, 5
new-instance v8, Ljava/lang/Integer;
invoke-direct {v8, v9}, Ljava/lang/Integer;-><init>(I)V
move-object v5, v8
:L1
check-cast v4, Ljava/lang/Integer;
invoke-virtual {v4}, Ljava/lang/Integer;->intValue()I
move-result v10
check-cast v5, Ljava/lang/Integer;
invoke-virtual {v5}, Ljava/lang/Integer;->intValue()I
move-result v11
if-le v10, v11, :L2
const v13, 0
new-instance v12, Ljava/lang/Integer;
invoke-direct {v12, v13}, Ljava/lang/Integer;-><init>(I)V
return-object v12
#goto :L3
:L2
const-string v14, "Hello! "
move-object v0, v14
invoke-static {v0}, Luhideyuki/daat/DaatRuntime;->print(Ljava/lang/String;)Ljava/lang/Integer;
move-result-object v15
const v7, 1
new-instance v6, Ljava/lang/Integer;
invoke-direct {v6, v7}, Ljava/lang/Integer;-><init>(I)V
check-cast v4, Ljava/lang/Integer;
check-cast v6, Ljava/lang/Integer;
invoke-virtual {v4}, Ljava/lang/Integer;->intValue()I
move-result v9
invoke-virtual {v6}, Ljava/lang/Integer;->intValue()I
move-result v2
add-int v9, v9, v2
new-instance v8, Ljava/lang/Integer;
invoke-direct {v8, v9}, Ljava/lang/Integer;-><init>(I)V
move-object v4, v8
goto :L1
#:L3

.end method

そして、実行結果がこちら:

Helo5

もうすこし複雑なプログラムを試すのは、レジスタ割付けを実装してからにしよう。

い、いちおう、今年中に動かした…かな?

https://github.com/unnohideyuki/Tiger-in-Haskell


2014-09-12 (Fri)

[Tiger][Haskell] Tigerbook 9章 つづき

https://github.com/unnohideyuki/Tiger-in-Haskell

Codegen を書いていて、これまでのところでイマイチわかってなかったところに気づいて修正。関数の戻り値は、Tree 言語上どうやって表現されることになってたのか、わかんなくなって。Translate では、戻り値を RV に格納するような MOVE 命令を Proc の body に追加するべきだった。

Translate をそのように直して、それに対応する MOVE 文の munchStm も書いた。

Tiger 言語の関数・プロシージャは、すべて、Dalvik 上では Object を返すメソッドにマッピングされることになる。(UNIT は CONST 0)

Canon の理解があやふやなのは、動かしながら&テストを書きながら理解していこう。

だいぶ、わからない部分がなくなってきた。

9章ぬけたら、いよいよレジスタ割り付けだ。


2014-09-10 (Wed)

[Tiger][Haskell] 9 章の Code Generater 書き始め

ようやく、State Monad (書いたことないので)恐怖症を克服し、munchExp を State Monad として書き始めた。やっぱこうだよな。適切なツールをつかってる実感というか、快適な感じ。

https://github.com/unnohideyuki/Tiger-in-Haskell/blob/0cb0fced97e0c07912b6206493336739b56daf05/chap9/src/Codegen.hs

ただ、書いて、寝てみて、もっとうまく書けるよなと思った(寝ながら)。

munchExp (T.STR s) =
  state $ \st ->
  let
    insts = get_insts st
    temp = get_temp st
    (t, temp') = Temp.newTemp temp
    inst = A.strInstr s [t]
  in
   (t, st{get_insts=insts ++ [inst], get_temp=temp'})

これは、次のように書き直したい:

munchExp (T.STR s) =
  do
    t <- newTemp
    emit $ A.strInstr s [t]
    return t

こう書けるように、newTemp :: State CgenState Temp.Temp や、emit :: State CgenState () を書くのだろう。"emit" という単語は、Tiger book がそういうボキャブラリなので。(状態の型も名前を変えよう> CgenState)

これで、より State Monad っぽい書き方になったかなぁとは思うんだけど…。聞くところによると、「do 記法は有害だから使うな」という説もあるらしいのが、ちょっとだけ気になってる。

ま、いいか。


2014-08-20 (Wed)

Google 公式 Android Training with Eclipse+ADT

Tiger Compiler 作成も終盤に差し掛かり、ターゲットマシン (Dalvik にしようとしてる)についての理解が浅いのがネックになってきた。それに、Runtime まわりを整備しないといけない。

Android プログラミングを勉強するために、なんか本でも読もうかなと思ったけど、どうも Google 公式ドキュメントより優れた入門文書はなく、どっちみち公式ドキュメントは避けて通れないらしいので、それでいくことに:

http://developer.android.com/training/index.html

ただ、昨日もこれみながらやってたんだが、なんかおかしい。new project をつくっても、書いてあるようなファイル構成ができあがってこないようだ。もしかしたら、Command line tools でやってるのが原因かもしれない。

というわけで、今日は Eclipse でやってみる。

Eclipse でやってみても、少しだけ書いてある通りにならないところがあった。

たとえば、Creating an Android Project には、次のように書いてあるんだが、

Now you can select an activity template from which to begin building your app.
For this project, select BlankActivity and click Next.

BlankActivity with Fragment を選ばないと、fragment_main.xml はできないようだ。

これについては、昨日も Building a Simple User Interface に書いてある通りにならなくて悩んだ。

Starting Another Activity

というわけで、今日は Starting Another Activity まで。

StartingActivity

昨日とちがい、今日は (Command Line Tools ではなく)Eclipse + ADT でやったので、BlankActivity を BlankActivity with Fragment に読み替える必要があった以外は、書いてある通りにでけた。


2014-08-13 (Wed)

[Tiger][Haskell] Tigerbook 9 章

ぼちぼち。

Assem.hs を書き始めている感じ。8 章の理解・動作確認も並行してやんないと。

*Assem> let ai = addInstr [128] [5, 7]
*Assem> ai
OPER{oper_assem="add-int `d0, `s0, `s1", oper_dst=[128], oper_src=[5,7], oper_jump=Nothing}
*Assem> format Temp.makeString ai
"add-int t128, t5, t7"

ま、こんな感じだろう。

「夜更かし」は、日・月・火・水と最近決めたので、次の夜はすけるは日曜の晩だ。


2014-08-06 (Wed)

つぶやき

Evernote の新しいトップ画面にでっかく出てくる男性の顔が苦手で。
Web からログインするのが少し億劫になるれべる。


分岐方向が逆になるように書き換えればよいとかじゃなかった。
ぐうむ。回避できないのか?


SIMD の論理演算をゴリゴリ利用した Assembly コードを書くにはあの朝飯では足りないと
脳がのたまう(気がした)ので、ひさびさに「きのこの山」を買ってきた。


おれ、きのこ派だったっけ?


結構きれいなトースターだなぁ(konami
http://superuser.com/questions/792607/why-does-windows-think-that-my-wireless-keyboard-is-a-toaster


おやつくったし、書くか。


Ruby も Mersenne Twister も、「名前重要」的なエピソードをもっている。
やっぱり名前重要なんかな。


あられは Rice Cracker らしい。
(Hadaly って言いにくい)


Rice Cracker も、r がふたつもあって発音しやすくはないのかも。
(平気だけど)


鈴木土下座ェ門 という文字列をみた


SPARC V9 で unsigned long って 8-byte だったのか!(いまさら?)
普段 stdint.h 使うので、意識してなかった。


はやくかえって、Tigerbook のやつやる。


2006|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|08|
2010|01|02|03|05|06|07|10|11|
2011|03|08|
2012|02|04|07|08|10|
2013|01|02|03|05|06|08|11|12|
2014|01|02|05|06|07|08|09|12|
2015|01|
Categories 3imp | Card | Cutter | Dalvik | Football | GAE/J | Hand | Haskell | Ruby | Scheme | TQD | Tiger | TigerBook読 | UikiTeXi | Verilog | Violin | Web | parconc | tDiary | お勉強 | エントロピー | ツン読 | | 将棋 | 政治について | | 模写してみよう | 確率論 | 設定など | 雑文 | 音声