# 11章 ### インスタンスメソッドの流儀 Pythonは明示的にselfを記載する(他にもgoやrustもそうらしい) 関数的なものをメソッドとして使う場合は、こういう風にあらわにやる必要がある(もしくはそうした方がわかりやすい) https://python.ms/self/#%E7%96%91%E5%95%8F-%E3%81%AA%E3%82%93%E3%81%A7%E6%98%8E%E7%A4%BA%E7%9A%84%E3%81%AB-self-%E3%82%92%E6%9B%B8%E3%81%8F%E3%81%AE%EF%BC%9F ### 変数のスコープ ``` # 適当な例(雑にローカル変数だけのテーブルとして) method void hogeMethod() { var int foo, bar let foo = 100; while(true) { var int foo, bar let foo = 10; if(hoge) { var int foo, bar let foo = 1; # ブロック内のfooを指す(外に影響しない) } } } [{hogeMethod: [:foo, :bar, {whileBlock1: [:foo, :bar, {ifBlock1: [:foo, :bar]}]}]}, {fugaFunction: [:i, :j, :k]} ] ``` # 10章 (Rubyの例)ASTとVMコードのみかたこんな感じです ``` $ ruby --dump parsetree -e 'puts :hoge' ########################################################### ## Do NOT use this node dump for any purpose other than ## ## debug and research. Compatibility is not guaranteed. ## ########################################################### # @ NODE_SCOPE (line: 1, location: (1,0)-(1,10)) # +- nd_tbl: (empty) # +- nd_args: # | (null node) # +- nd_body: # @ NODE_FCALL (line: 1, location: (1,0)-(1,10))* # +- nd_mid: :puts # +- nd_args: # @ NODE_ARRAY (line: 1, location: (1,5)-(1,10)) # +- nd_alen: 1 # +- nd_head: # | @ NODE_LIT (line: 1, location: (1,5)-(1,10)) # | +- nd_lit: :hoge # +- nd_next: # (null node) $ ruby --dump insns -e 'puts :hoge' == disasm: #<ISeq:<main>@-e:1 (1,0)-(1,10)> (catch: FALSE) 0000 putself ( 1)[Li] 0001 putobject :hoge 0003 opt_send_without_block <callinfo!mid:puts, argc:1, FCALL|ARGS_SIMPLE>, <callcache> 0006 leave ``` トークナイザの結果 ``` > require 'ripper' => true > code = <<~RUBY a = (1 + 2) * 3 puts a - 1 RUBY => "a = (1 + 2) * 3\nputs a - 1\n" > Ripper.tokenize(code) => ["a", " ", "=", " ", "(", "1", " ", "+", " ", "2", ")", " ", "*", " ", "3", "\n", "puts", " ", "a", " ", "-", " ", "1", "\n"] > Ripper.sexp(code) => [:program, [[:assign, [:var_field, [:@ident, "a", [1, 0]]], [:binary, [:paren, [[:binary, [:@int, "1", [1, 5]], :+, [:@int, "2", [1, 9]]]]], :*, [:@int, "3", [1, 14]]]], [:command, [:@ident, "puts", [2, 0]], [:args_add_block, [[:binary, [:var_ref, [:@ident, "a", [2, 5]]], :-, [:@int, "1", [2, 9]]]], false]]]] ``` Tokenizer(単にバラバラにする) -> Lexer(tokenの種類を判別) -> Parser(ASTを組み立てる)っていう段取りになってるんですね。 ``` > Ripper.lex(code) => [[[1, 0], :on_ident, "a", EXPR_CMDARG], [[1, 1], :on_sp, " ", EXPR_CMDARG], [[1, 2], :on_op, "=", EXPR_BEG], [[1, 3], :on_sp, " ", EXPR_BEG], [[1, 4], :on_lparen, "(", EXPR_BEG|EXPR_LABEL], [[1, 5], :on_int, "1", EXPR_END], [[1, 6], :on_sp, " ", EXPR_END], [[1, 7], :on_op, "+", EXPR_BEG], [[1, 8], :on_sp, " ", EXPR_BEG], [[1, 9], :on_int, "2", EXPR_END], [[1, 10], :on_rparen, ")", EXPR_ENDFN], [[1, 11], :on_sp, " ", EXPR_ENDFN], [[1, 12], :on_op, "*", EXPR_BEG], [[1, 13], :on_sp, " ", EXPR_BEG], [[1, 14], :on_int, "3", EXPR_END], [[1, 15], :on_nl, "\n", EXPR_BEG], [[2, 0], :on_ident, "puts", EXPR_CMDARG], [[2, 4], :on_sp, " ", EXPR_CMDARG], [[2, 5], :on_ident, "a", EXPR_END|EXPR_LABEL], [[2, 6], :on_sp, " ", EXPR_END|EXPR_LABEL], [[2, 7], :on_op, "-", EXPR_BEG], [[2, 8], :on_sp, " ", EXPR_BEG], [[2, 9], :on_int, "1", EXPR_END], [[2, 10], :on_nl, "\n", EXPR_BEG]] ``` # 10章実装 大嶋(WIP) https://github.com/h-shima/jack_compiler/pull/1 大西さん https://github.com/fursich/hack_jack_compiler # 参考Wikipedia https://ja.wikipedia.org/wiki/%E5%86%8D%E5%B8%B0%E4%B8%8B%E9%99%8D%E6%A7%8B%E6%96%87%E8%A7%A3%E6%9E%90#%E3%83%91%E3%83%BC%E3%82%B5%E3%81%AE%E4%BE%8B ## トークナイザー おおしまさん https://github.com/h-shima/jack_compiler/pull/1/files#diff-02351efa8099765f7a345465cd05909f おおにし * トークンを表すクラス https://github.com/fursich/hack_jack_compiler/blob/master/lib/tokenizer/token.rb * トークン全体のコレクションを入れておくやつ https://github.com/fursich/hack_jack_compiler/blob/master/lib/parser/token_container.rb * トークンの分類器(分類ルール) https://github.com/fursich/hack_jack_compiler/blob/master/lib/tokenizer/token_classifier.rb * トークナイザー本体 https://github.com/fursich/hack_jack_compiler/blob/master/lib/tokenizer/processor.rb * ソースコードを格納するやつ https://github.com/fursich/hack_jack_compiler/blob/master/lib/utils/source.rb ## パーサー おおにし https://github.com/fursich/hack_jack_compiler/blob/master/lib/parser/processor.rb