SlideShare ist ein Scribd-Unternehmen logo
1 von 85
Downloaden Sie, um offline zu lesen
Cookpad 17 day Tech internship 2017
言語処理系入門
Rubyをコンパイルしよう
笹田 耕一
クックパッド株式会社
ko1@cookpad.com
今日の講義
•Ruby のコンパイラ開発を通じて言語処理系を
作ってみよう。
•基礎:構文解析結果 → バイトコードへの変換
•発展:さらなる最適化・高速化
自己紹介:笹田耕一
http://atdot.net/~ko1/
•所属:クックパッド株式会社
•2006-2012 大学教員
•2012-2017 Heroku, Inc.
•2017- Cookpad Inc.
•仕事:Rubyインタプリタの開発
•コア部分の開発
•VM、スレッド、GC、その他
•Ruby を使う仕事ではない
3
Ruby interpreter
Ruby (Rails) app
RubyGems/Bundler
So many gems
such as Rails, pry, thin, … and so on.
普通のRubyプログラミング
i gigantum umeris insidentes
Standing on the shoulders of giants
Interpret on RubyVM
ふつうの Ruby 処理系プログラミング
5
Ruby
script
Parse
Compile
(codegen)
Ruby
Bytecode
Object management
Garbage collectorThreading
Embedded
classes and methods
Bundled
Libraries
Evaluator
Gem
Libraries
AST
Abstract Syntax Tree
Ruby 処理系概要
Ruby処理系の構成
概要
7
•プログラムを読んで
•実行
Interpret on RubyVM
Ruby 処理系の流れ
8
Ruby
script
Parse
Compile
(codegen)
Ruby
Bytecode
Object management
Garbage collectorThreading
Embedded
classes and methods
Bundled
Libraries
Evaluator
Gem
Libraries
AST
Abstract Syntax Tree
読むところ 実行するところ
Interpret on RubyVM
Ruby 処理系の流れ
Ruby 1.8 以前
9
Ruby
script
Parse
Object management
Garbage collectorThreading
Embedded
classes and methods
Bundled
Libraries
Evaluator
Gem
Libraries
AST
ASTとRuby 1.8
10
a =
Method
Dispatch(:+)
cb
Abstract Syntax TreeRuby Program
a = b + c
a =
Method
Dispatch(:+)
cb
a =
Method
Dispatch(:+)
cb
Ruby 1.8 はAST を単純
にたどるインタプリ
タ
Parse
Interpret on RubyVM
Ruby 処理系の流れ
Ruby 1.9 以降
11
Ruby
script
Parse
Compile
Ruby
Bytecode
Object management
Garbage collectorThreading
Embedded
classes and methods
Bundled
Libraries
Evaluator
Gem
Libraries
AST
VM – Stack Machine
12
Ruby Program
a = b + c
getlocal b
getlocal c
send :+, 1
setlocal a
YARV Instructions
a
b
c b
c
b+c
b+c
YARV Stack
Compile
今日は、スタックマシンをたくさん使うよ。
余談 スタックマシン vs レジスタマシン
•レジスタマシン
•計算対象・格納場所にレジスタを指定
•物理CPUはもっぱらレジスタマシン
•スタックマシン
•計算対象・格納場所は(暗黙に)スタック
•レジスタ指定がない分スリム
•命令数は多くなることがある
•言語VMでは多い(最近はレジスタマシンも)
今日の課題
•既存のコンパイラ(C で実装)の代わりに、
Ruby で Ruby のコンパイラを書こう。
課題A. ヒューマンコンパイラ
課題B. 自動コンパイラ
Interpret on RubyVM
Ruby 処理系の流れ
15
Ruby
script
Parse
Compile
(codegen)
Ruby
Bytecode
Object management
Garbage collectorThreading
Embedded
classes and methods
Bundled
Libraries
Evaluator
Gem
Libraries
AST
今日最終的に
作るもの
入力と出力
Ruby
script
Parse
Compile
(codegen)
Ruby
Bytecode
AST
Abstract Syntax Tree
今日つくるもの
これ全部でコンパイラ
ということも。
入力と出力
ほかの言語では?
X language
program
Parse
Compile
Code
AST
Abstract Syntax Tree
入力 出力
C コンパイラ(gccとか) C プログラム 機械語(アセンブラ)
Java (javac) Java プログラム JavaVM バイトコード(.class)
JavaScript (babel) JavaScript (ES6, …) JavaScript (ES5)
Ruby Interpreter Ruby プログラム Ruby VM バイトコード
Ruby Interpreter
JIT compiler
Ruby プログラム C ソースコード(実行時にコン
パイル&ロード)
デモ:実際に Ruby VM バイトコードを見てみよう
AST: Abstract Syntax Tree
# Ruby script
a = 10
if a > 1
p :ok
else
p :ng
end
Program
LvarAssign if
a
10
Lvar
send
a
>
1
send
(fcall)
p
:ok
send
(fcall)
p
:ng
字句解析
構文解析
Tips: 字句解析・構文解析について、詳しくは去年の青木さんの資料を読もう
https://speakerdeck.com/aamine/cookpad-2016-summer-intern-programming-paradigm
Seq
Literal
Literal Literal Literal
Ruby Bytecode
# Ruby script
a = 10
if a > 1
p :ok
else
p :ng
end
0000 putobject 10
0002 setlocal a, 0
0005 getlocal a, 0
0008 putobject 1
0010 send <callinfo!mid:>, argc:1, ARGS_SIMPLE>,
<callcache>, nil
0014 branchunless 27
0016 jump 18
0018 putself
0019 putobject :ok
0021 send <callinfo!mid:p, argc:1, FCALL|ARGS_SIMPLE>,
<callcache>, nil
0025 jump 34
0027 putself
0028 putobject :ng
0030 send <callinfo!mid:p, argc:1, FCALL|ARGS_SIMPLE>,
<callcache>, nil
0034 leave
番地 スタックの状況(空でスタート) 解説
0000 putobject 10 # [10] スタックに 10 をプッシュ
0002 setlocal a, 0 # [] a にスタックトップの 10 をセット
0005 getlocal a, 0 # [10] a の値をスタックにプッシュ
0008 putobject 1 # [10, 1] 1 をスタックにプッシュ
0010 send <callinfo!mid:>, argc:1, ARGS_SIMPLE>,
<callcache>, nil 10.>(1) というメソッド呼び出し
# [true] その結果(true)をプッシュ
0014 branchunless 27 # [] スタックトップの値が false or nil なら 27 へ
0016 jump 18 # [] 無条件に 18 へジャンプ
0018 putself # [self] self をスタックへプッシュ
0019 putobject :ok # [self, :ok] :ok をスタックへプッシュ
0021 send <callinfo!mid:p, argc:1, FCALL|ARGS_SIMPLE>,
<callcache>, nil p(:ok) を実行
# [:ok] 結果の :ok をスタックにプッシュ
0025 jump 34 # [:ok] 無条件に 34 へジャンプ
0027 putself
0028 putobject :ng
0030 send <callinfo!mid:p, argc:1, FCALL|ARGS_SIMPLE>,
<callcache>, nil
0034 leave # [] このコードを終了する(積んであった :ok を返す)
スタックマシンの実行を解説
すべての計算が、
「スタックから値を取り出し」、「スタックに積む」ことで実現されていることがわかればOK
どんな命令があるの?
•Ruby のソースの insns.def に書いてある
•https://github.com/ruby/ruby/blob/trunk/insns.def
•opt_ と付いている命令は見る必要はない
•Optimization(最適化)のための命令群
例:getlocal
/**
@c variable
@e Get local variable (pointed by `idx' and `level').
'level' indicates the nesting depth from the current block.
@j level, idx で指定されたローカル変数の値をスタックに置く。
level はブロックのネストレベルで、何段上かを示す。
*/
DEFINE_INSN
getlocal # ← 命令の名前
(lindex_t idx, rb_num_t level) # 命令オペランド
() # スタックからとってくる値(今回はなし)
(VALUE val) # 終了時、スタックへプッシュする値
{ # C での実装
val = *(vm_get_ep(GET_EP(), level) - idx);
RB_DEBUG_COUNTER_INC(lvar_get);
(void)RB_DEBUG_COUNTER_INC_IF(lvar_get_dynamic, level > 0);
}
https://github.com/ruby/ruby/blob/trunk/insns.def#L47
入力と出力
Compile
Ruby
Bytecode
AST
今日やること
0000 putobject 10
0002 setlocal a, 0
0005 getlocal a, 0
0008 putobject 1
0010 send <callinfo!mid:>, argc:1, ARGS_SIMPLE>,
<callcache>, nil
0014 branchunless 27
0016 jump 18
0018 putself
0019 putobject :ok
0021 send <callinfo!mid:p, argc:1, FCALL|ARGS_SIMPLE>,
<callcache>, nil
0025 jump 34
0027 putself
0028 putobject :ng
0030 send <callinfo!mid:p, argc:1, FCALL|ARGS_SIMPLE>,
<callcache>, nil
0034 leave
別の言い方をすると木構造から列構造への変換
Ruby
Bytecode
ASTProgram
LvarAssign if
a
10
Lvar
send
a
>
1
send
(fcall)
p
:ok
send
(fcall)
p
:ng
Seq
Literal
Literal Literal Literal
課題A
ヒューマンコンパイラ
こんな言葉を聞いたことはないですか?
•「コンパイラの気持ちになって考えよう」
•類例
•「CPUの歓声が聞こえる」
•「OSになったつもりで管理する」
•「パケットの気持ちになって考える」
•「AWSの気持ちになる」
課題A ヒューマンコンパイラ
•「コンパイラの気持ちになって考えよう」
•Ruby プログラムを見て、VM のバイトコードを
人力で生成しよう。
•(別の言い方をすると)Ruby 言語をスタック
型言語(VMアセンブラ)書き直してみよう。
「おまえがコンパイラ
になるんだよ!」
Ruby
script
Ruby
Bytecode
課題A
全体構成
ツール
RubyVM::InstructionSequence
•組み込みクラス RubyVM::InstructionSequence
•略して ISeq
•バイトコードを扱うためのクラス
# example
ISeq = RubyVM::InstructionSequence # 長いので
iseq = ISeq.compile(script) #=> ISeq を生成
p iseq.eval #=> iseq を実行(結果表示)
puts iseq.disasm #=> 逆アセンブル結果を表示
ツール
ISeq  Array 相互変換
• 今回は ISeq  Array 相互変換の仕組みを利用
• ary = iseq.to_a #=> 配列を生成
• ISeq.load(ary) #=> ISeq
• VM命令は、この配列によって生成可能
• …しかし、いちいち配列を作るのは面倒くさい
pp ISeq.compile(‘’).to_a # 何もないプログラムの場合
["YARVInstructionSequence/SimpleDataFormat",
2, 3, 1,
{:arg_size=>0, :local_size=>0, :stack_max=>1},
"<compiled>", "<compiled>",
nil, 1, :top, [], {}, [],
[[:putnil], [:leave]]] # バイトコード部分はここだけ
ツール
YASM: YARV Assember
•yasm.rb
•Ruby VM 用アセンブラ
•命令を素直に Ruby で書けば、ISeq を生成可能
ツール
YASM: ISeq の配列を便利に作る仕組み
# YASM example
iseq = YASM.asm label: ‘integer:1' do
# ブロックに命令を書くことで ISeq 生成
putobject 1
leave
end
p iseq.eval #=> 1
課題A「ヒューマンコンパイラ」の進め方
•課題ファイル asm/task.rb
• テストケースになっている。
• どんどんアセンブラを埋めていこう。
•調査のための方法
• yasm.rb の最後に直接記述
• 最後の “# fill your asm here” の箇所にアセンブラ記述
• “$ ruby yasm.rb” で ISeq と実行結果を表示
• try.rb の script 変数に調べたい Ruby プログラム文字列
を入力し、実行すると、正解データ(逆アセンブ
ラ)が出てくるので参考にしよう。
• ほかの人・TA・講師にどんどん聞こう。
YASMの使い方
起動
•asm/task.rb に解答を書いた場合
•$ ruby asm/task.rb
•答えが想定と異なればエラー出力し実行終了
•yasm.rb に直接書いた場合
•$ ruby yasm.rb
•これで実験できる
YASMの使い方
基本
•プログラムの終わり方
• leave 命令: プログラムの最後は必ず leave
• スタックトップを返値として返す
• つまり、スタックトップに値が一つ(だけ)必要
•スタック操作
• putobject X # スタックに X(整数や true/false)を積む
• putnil # nil を積む
• putstring “xxx” # スタックに文字列 “xxx” を積む
• pop # スタックから一要素取り外す
• dup # スタックの一番上と同じものをもう一つ積む
課題A-1 整数値
•整数値を返すプログラム
•1
•1_000_000
•Hint: putobject を利用
課題A-1’ シンボル
•シンボルを返すプログラムを変換
•:ok
•:ng
•Hint: putobject を利用
課題A-1’’ 文字列
•文字列を返すプログラムを変換
•“hello”
•Hint: putstring を利用
YASMの使い方
ローカル変数アクセス
•命令
•getlocal :lvar # 変数 lvar の値をスタックトップに
•setlocal :lvar # 変数 lvar の値をセット
•:lvar のように変数名をシンボルで指定
•逆アセンブラ表記とちょっと違うので注意
•getlocal lvar, 0 のように出てくる。
•yasm では 0 を省略可能(書いても良い)。
課題A-2 ローカル変数
•ローカル変数のset, get を含むプログラムを変換
•“a = 1; a”(設定して、取得している)
•Hint: putobject, getlocal, setlocal を利用
課題A-3 self, nil
•“self” を返すプログラムを実装
•ローカル変数と合わせると、“a = self” が動く
•“nil” というプログラムを実装
•Hint: putself, putnil を利用
YASMの使い方:メソッド呼び出し
Ruby のメソッド呼び出し再入門
•receiver.method_name(p1, …, pn)
• レシーバ(receiver)のある普通のメソッド呼び出し
• method_name: メソッドの名前
• p1, …, pn: n 個の引数
•method_name(p1, …, pn)
• レシーバが省略されたメソッド呼び出し
• self が省略されている
• private メソッドを呼ぶことができる(pなど)
YASMの使い方:メソッド呼び出し
Ruby のメソッド呼び出し再入門
•binary operator(二項演算子)
•1+2 は 1.+(2) というメソッド呼び出し
• receiver: 1
• メソッド名: +(Symbol では “:+”)
• 引数は 2 (1個だけ)
YASMの使い方:メソッド呼び出し
send 命令を利用
# 逆アセンブラの表記(1+2 => 1.+(2) の逆アセンブラ)
0000 putobject 1 # レシーバを積む
0002 putobject 2 # 1番目の引数を積む
0004 send <callinfo!mid:+, argc:1, ARGS_SIMPLE>, <callcache>, nil
0008 leave
# アセンブラでの表記
putobject 1
putobject 2
send :+, 1 # 簡単!(ARGS_SIMPLE は無視)
leave
よくわからない…
YASMの使い方:メソッド呼び出し
send 命令の書き方
•send method_id, argc, flag(ないなら省略可能)
•method_id はメソッド名のシンボル(:p など)
•argc は引数の数
•flag はメソッド呼び出しの種類(省略可能)
• 1+2 は 1.+(2) なので send :+, 1(flagなし)
• foo() のように self が無い→ YASM::FCALL
• p(1) は、send :p, 1, YASM::FCALL
• ほかのフラグは無視してよい
YASMの使い方:メソッド呼び出し
send 命令の使い方
•スタック上に、receiver と引数を積み send
• receiver.mid(引数1, …, 引数n) の場合
• receiver, 引数1, 引数2, …, 引数nを積む命令群
• send :mid, n
• 実行後、receiver.mid(引数1, …, 引数n) の結果だけが
積まれる
•receiver がない(mid(…) の場合)も、receiver と
して self を積んでおく(YASM::FCALL を指定)
receiver
param1
param2
…
paramN
result
send :mid, N
YASMの使い方:メソッド呼び出し
send 命令の使い方(VMスタック)
receiver.mid(param1, …, paramN) の場合
self
param1
param2
…
paramN
result
send :mid, N, YASM::FCALL
YASMの使い方:メソッド呼び出し
send 命令の使い方(VMスタック)
mid(param1, …, paramN) の場合
self
:ok
result (:ok)
send :p, 1, YASM::FCALL
YASMの使い方:メソッド呼び出し
send 命令の使い方(VMスタック)
p(:ok) の場合
(receiver として self を積む)
1
2
3
send :*, 1
YASMの使い方:メソッド呼び出し
send 命令の使い方(VMスタック)
1 + 2 * 3 の場合
1
result
(6)
send :+, 1
result
(7)
1
1 + ??
2 * 3
1 + 6
課題A-4 メソッド呼び出し
•receiver のあるプログラムを変換
•“1 < 10” つまり “1.<(10)” というプログラム
•receiver のないプログラムを変換
•“p(1)” というプログラム
•Hint: receiver の putself を忘れずに
課題A-4’ メソッド呼び出し(組み合わせ)
•組み合わせる(いろんなことが出来る)
•“1 - 2 * 3” #=> -5
•“a = 1; b = 2; c = 3; a - b * c” #=> -5
•“a = 10; p(a > 1)” #=> true
•“p(‘foo’.upcase)” #=> ‘FOO’
YASMの使い方:ジャンプ命令とラベル
•逆アセンブラでは、ジャンプ先はアドレス
→ アドレス計算は面倒なので、ラベルで指定
•ジャンプ命令
• jump :label_name
• branchif :label_name
• branchunless :label_name
•ラベル
• label :label_name
# example
label :begin
putself
putobject 1
send :p, 1, YASM::FCALL
jump :begin # begin ラベルへジャンプ
# つまり無限ループ
課題A-5 if 文
•例題として出したプログラムを変換
•Hint: label と branchif or branchunless を上手に使う
# Ruby script
a = 10
if a > 1
p :ok
else
p :ng
end
課題A-5’ else の無い if 文は?
•else の無い次のプログラムを変換
•Hint: 実際に実行して、if文の値を確かめよう
# Ruby script (1)
a = 10
if a > 1
p :ok
end
# Ruby script (2)
a = 10
if a < 1
p :ok
end
課題A-6 while 文
•ヒント:jump と branch* で while を表現。
•ヒント:pop 命令を(多分)利用します。
a = 0
while(a < 10)
p a
a += 1 #=> a = a.+(1)
end
a #=> 10
YASMの使い方:メソッド定義
•“core#define_method” という特殊なメソッドを利用
• 実は、Ruby のメソッド定義は特殊なメソッド呼び出しに
よって行われている
• Rubyだと: SpecialObject. core#define_method(:mid, iseq)
•ISeq を生成し、この “core#define_method” を呼ぶ
•… が、面倒くさい # プログラム例
# SpecialObject. core#define_method(:mid, iseq)
m_iseq = YASM.asm(…) do
…
end
putspecialobject 1 # レシーバ:SpecialObject を取り出す
putobject :mid # 第一引数:メソッド名
putiseq m_iseq.to_a # 第二引数:メソッドの実体
send :“core#define_method”, 2 # 呼び出し
# 特殊なメソッド名であることに注意
YASMの使い方:メソッド定義
define_method_macro
•メソッドボディの ISeq の生成+メソッド定
義命令列を生成するメソッド
# define_method_macro の利用例
# def foo(a); p(a); end を行う命令列を生成
define_method_macro :foo, parameters: [:a] do
putself
getlocal :a
send :p, 1, YASM::FCALL
leave
end
# ここにメソッドを定義する命令列が挿入される
pop # 定義後、method 名のシンボルがスタックに積まれているので、pop
putself
putobject 123
send :foo, 1, YASM::FCALL # foo(123)
YASMの使い方:メソッド定義
define_method_macro
•define_method_macro を使った結果を確認
iseq = YASM.asm do
define_method_macro :foo, parameters: [:a] do
putself
getlocal :a
send :p, 1, YASM::FCALL
leave
end
leave
end
puts iseq.disasm
ruby 2.5.0dev (2017-08-04 trunk 59496) [x64-mswin64_140]
== disasm: #<ISeq:<compiled/yasm(top)>@yasm.rb:181:in `<main>'>=========
0000 putspecialobject 1 …
0002 putobject :foo
0004 putiseq foo
0006 send <callinfo!mid:core#define_method, argc:2>, …
0010 leave
== disasm: #<ISeq:foo@yasm.rb:79:in `define_method_macro'>==============
local table (size: 1, argc: 1 [opts: 0, rest: -1, post: 0, …
[ 1] a<Arg>
0000 putself ( 1)
0001 getlocal a, 0
0004 send <callinfo!mid:p, argc:1, FCALL>, <callcache>, nil
0008 leave
課題A-7 メソッド定義
def fib(n)
if n < 2
1
else
fib(n – 2) + fib(n-1)
end
end
fib(10)
# param
def foo(a)
a
end
foo(100)
# no param
def foo()
end
引数+呼び出し fib 定義と fib(10) の呼び出し
高速化・最適化
• 命令の置き換えで高速化ができることも。
• 本当にたくさんの方法があるので、興味がある人が
いれば調べてみよう&fibを高速化してみよう。
書籍:コンパイラの構成と最適化(中田育男)
Wikipedia:
https://ja.wikipedia.org/wiki/%E3%82%B3%E3%83%B3%E
3%83%91%E3%82%A4%E3%83%A9%E6%9C%80%E9%81%
A9%E5%8C%96
簡単な最適化の例
ピープホール(のぞき穴)最適化
# 例
a = 1
if a > 10
1
else
2
end
# no-opt
putobject 1
setlocal :a, 0
getlocal :a, 0
putojebt 10
send :>, 1
branchunless :else
jump :body
label :body
putobject 1
jump :end
label :else
putobject 2
label :end
leave
# w/ peephole opt
putobject 1
setlocal :a, 0
getlocal :a, 0
putojebt 10
send :>, 1
branchunless :else
putobject 1
leave
label :else
putobject 2
leave
課題A-8
•Rubyでコンパイルした fib() と、自分でアセン
ブルした fib() の速度比較をしよう。
•asm/asmfib.rb に task.rb から fib 定義部分をコピペ
•実行して比較(それぞれ fib(35) 実行時間を計測)
• $ time ruby asm/asmfib.rb 35
• $ time ruby asm/fib.rb 35
•ついでに、asm/fastfib.rb も調べてみよう
(fib(10_000) など呼んでみよう)
余談:最適化とは?
•何が最適であるか?
•実行時間?
•メモリサイズ?
•プログラムを書く時間?
•ほかには?
•プログラムの意味とは?
•プログラマの意図とは?
•「最適を導く」言語設計とは?
余談:DSL
Domain Specific Language
•「問題を解くには、まずは言語を作る」
•DSL: Domain Specific Language
•外部DSL
•内部DSL
•YASM は内部DSL
•C のアセンブラを見たことがありますか?
•それに対して、YASM はどうでしたか?
発展課題A
• もっといろんなRubyプログラムを変換
• 例えば
• (インスタンス|グローバル|クラス)変数
• 定数
• ブロックに対応
• 例外処理に対応
• 取り組み方
• ISeq#dump, #to_a の結果をじっと見る
• Ruby のソースコード(C)をじっと見る
• yasm.rb を変更・拡張する
課題B
自動コンパイラ
人間がコンパイルするのはつらい
•人間は単純作業が苦手。
•人間はミスをする。
→ コンピューターにやらせよう。
課題B: AST (node tree) → Bytecode (ISeq)
0000 putobject 10
0002 setlocal a, 0
0005 getlocal a, 0
0008 putobject 1
0010 send <callinfo!mid:>, argc:1, ARGS_SIMPLE>,
<callcache>, nil
0014 branchunless 27
0016 jump 18
0018 putself
0019 putobject :ok
0021 send <callinfo!mid:p, argc:1, FCALL|ARGS_SIMPLE>,
<callcache>, nil
0025 jump 34
0027 putself
0028 putobject :ng
0030 send <callinfo!mid:p, argc:1, FCALL|ARGS_SIMPLE>,
<callcache>, nil
0034 leave
Ruby
Bytecode
ASTProgram
LvarAssign if
a
10
Lvar
send
a
>
1
send
(fcall)
p
:ok
send
(fcall)
p
:ng
Seq
Literal
Literal Literal Literal
課題Bの進め方
•ast2iseq/ast2iseq.rb のast2iseq(ast)を完成させよう。
• ast2iseq_visitor.rb の中身を ast2iseq.rb にコピペ。
• visitor pattern によるast2iseq() のスケルトンがある。
• 参考までに全部で 3 パターン用意
• ast2iseq_visitor.rb: visitor pattern を利用
• ast2iseq_func.rb: 再帰関数で case/when を利用
• ast2iseq_composite.rb: composite pattern を利用
• 違いを考察するのも面白いかも?
• 答えも用意(ast2iseq_ans_....rb)
• あまり見ないでね。
課題Bの進め方(試行錯誤)
1. ast2iseq メソッドを(途中まででも)作る
2. ファイル下部にある script 変数にコンパイル対象の Ruby ス
クリプトを入力(例: 1+2)
3. “$ ruby ast2iseq/ast2iseq.rb” を実行
1. Ruby2AST.to_ast(script) で、Ruby を AST に変換(ついでに見やすく
出力)
2. ast2iseq(AST) を実行
a. 未完成なのでエラー
b. 実装済みなので正しい答えを得る
4. 3 の結果を見て、じっくり考えて 1 に戻る(迷ったら try.rb
で本家Rubyのコンパイル結果の逆アセンブラを見る)
課題Bの進め方(テスト)
•iseq2ast/test.rb を通す
•このファイルを実行すると、開発した ast2iseq
を使い、課題A の各コードをコンパイル、実行
し、正しい答えであるかをチェックする。
•最終的に全部テストが通ったらOK
ヒント:YASM の使い方
•YASM::asm の代わりに YASM.new を利用
# example
yasm = YASM.new(label: …) # YASM.asm と同じ引数
yasm.putnil #
yasm.leave # 2命令生成
iseq = yasm.to_iseq # 2命令分の ISeq を生成
puts iseq.disasm # 逆アセンブル
iseq.eval # 実行
ヒント:Node の構成
• Ruby2AST.to_ast(script) の結果を見て、ノードのデータ構造をチェック。
• ast2iseq/ruby_nodes.rb に定義。
• ProgramNode
• SequenceNode
• NilNode
• SelfNode
• LiteralNode
• StringLiteralNode
• LvarAssignNode
• LvarNode
• SendNode
• IfNode
• WhileNode
• DefNode
• 図にしてみるとわかりやすい?
# “1 + 2” というプログラムのノード
#<ProgramNode
@seq_node =>
#<SequenceNode
@nodes => [
#<SendNode
@type => :call
@receiver_node => #<LiteralNode @obj => 1>
@method_id => :+
@argument_nodes => [ #<LiteralNode @obj => 2>]>]>>
# “1” というプログラムのノード
#<ProgramNode
@seq_node => #<SequenceNode @nodes =>
[ #<LiteralNode @obj => 1>]>>
ヒント:ラベルの使い方
•ラベルはユニークである必要がある
•label :begin がプログラム中に 2 箇所出てきたら、
どっちに飛べばいいかわからなくなる
→ 固定シンボルの代わりに、ユニークなラベ
ルを生成する gen_label() というメソッドを使
う(各スケルトンに準備)
ヒント:メソッドボディの作り方
•どのスケルトンでも、ast2iseq() の最初で、
DefBody だったら method body を作るように
なっている
•yasm.rb の define_method_macro() で何をやっ
ているかチェック。
発展課題
最適化
コンパイルした結果の命令列をチェック
•(多分)手でコンパイルした結果よりも、
非効率なコードが生成されるはず。
•ast2iseq() は、基本的には子ノードしか見ない。
•広い視点で見ると、もっと効率的なことも。
発展課題B
最適化
• 発展課題:最適化処理を追加してみよう。
• どのレベルで行うか?
• ノード単位で変換?
• ISeq単位で変換?
• 何に最適化するか?
• fib() の結果で最適化結果を確認
発展課題B
もっといろいろなプログラムに対応
•発展課題Aのような、対応文法拡張
•やり方
•発展課題Aと同じように調べる
•ruby2ast.rb を拡張
•ruby_nodes.rb にノードを追加
そしてこれから
Ruby は広大
•今回対応したのは文法のほんの一部
•ほかにもいろいろ
•定数、インスタンス変数、グローバル変数、…
•正規表現、範囲オブジェクト、…
•ブロック、キーワード引数、…
•例外
•…
•…
Interpret on RubyVM
Ruby 処理系の流れ
83
Ruby
script
Parse
Compile
Ruby
Bytecode
Object management
Garbage collectorThreading
Embedded
classes and methods
Bundled
Libraries
Evaluator
Gem
Libraries
AST
Abstract Syntax Tree
これからの参考文献
• 『Rubyソースコード完全解説』by @minero-aoki
• 完全ガイドだけど 1.8 向け。ウェブで全文公開。
• 1, 2 部(GC やパーサー)は今でも十分に役に立つ。
• 『 Rubyのしくみ Ruby Under a Microscope』 by Pat
Shaughnessy
• Ruby 2.0 向けの話。
• 完全網羅ではないが、ガチ勢じゃなければそこそこ役に立つ。
• 『RubyでつくるRuby ゼロから学びなおすプログラミング
言語入門』 by 遠藤侑介
• RubyでRubyインタプリタを作る話。
• VMとASTをRubyで作り、それ自身を開発したRubyインタプリ
タで動作させる。
興味があったら
Rubyインタプリタの
開発に参加してね!

Weitere ähnliche Inhalte

Was ist angesagt?

20131208 agile samuraibasecamp
20131208 agile samuraibasecamp20131208 agile samuraibasecamp
20131208 agile samuraibasecampHiroshi SHIBATA
 
Fission で 始める Containerless Kubernetes #serverlesstokyo
Fission で 始める Containerless Kubernetes #serverlesstokyoFission で 始める Containerless Kubernetes #serverlesstokyo
Fission で 始める Containerless Kubernetes #serverlesstokyoy_taka_23
 
18166746-NeverBlock-RubyKaigi2009
18166746-NeverBlock-RubyKaigi200918166746-NeverBlock-RubyKaigi2009
18166746-NeverBlock-RubyKaigi2009Muhammad Ali
 
Infinite Debian - Platform for mass-producing system every second
Infinite Debian - Platform for mass-producing system every secondInfinite Debian - Platform for mass-producing system every second
Infinite Debian - Platform for mass-producing system every secondTaisuke Yamada
 
いまさら聞けないRake入門
いまさら聞けないRake入門いまさら聞けないRake入門
いまさら聞けないRake入門Tomoya Kawanishi
 
カンタン画像サムネイル作成「Smalllight」
カンタン画像サムネイル作成「Smalllight」カンタン画像サムネイル作成「Smalllight」
カンタン画像サムネイル作成「Smalllight」livedoor
 
GKEで半年運用してみた
GKEで半年運用してみたGKEで半年運用してみた
GKEで半年運用してみたKatsutoshi Nagaoka
 
Lisp Tutorial for Pythonista Day 6
Lisp Tutorial for Pythonista Day 6Lisp Tutorial for Pythonista Day 6
Lisp Tutorial for Pythonista Day 6Ransui Iso
 
Akka Stream x Kinesis at Shinjuku reactive meetup vol2
Akka Stream x Kinesis at Shinjuku reactive meetup vol2Akka Stream x Kinesis at Shinjuku reactive meetup vol2
Akka Stream x Kinesis at Shinjuku reactive meetup vol2Masaki Toyoshima
 
Project Loom - 限定継続と軽量スレッド -
Project Loom - 限定継続と軽量スレッド - Project Loom - 限定継続と軽量スレッド -
Project Loom - 限定継続と軽量スレッド - Yuichi Sakuraba
 
コンピューティングとJava~なにわTECH道
コンピューティングとJava~なにわTECH道コンピューティングとJava~なにわTECH道
コンピューティングとJava~なにわTECH道なおき きしだ
 
Ruby で高速なプログラムを書く
Ruby で高速なプログラムを書くRuby で高速なプログラムを書く
Ruby で高速なプログラムを書くmametter
 
Clojureの発表など
Clojureの発表などClojureの発表など
Clojureの発表などKikuta Go
 
ChefとPuppetの比較
ChefとPuppetの比較ChefとPuppetの比較
ChefとPuppetの比較Sugawara Genki
 
Javaで簡単にgpgpu aparapi
Javaで簡単にgpgpu aparapiJavaで簡単にgpgpu aparapi
Javaで簡単にgpgpu aparapiKen'ichi Sakiyama
 
WebRTC multitrack / multistream
WebRTC multitrack / multistreamWebRTC multitrack / multistream
WebRTC multitrack / multistreammganeko
 
Docker+CoreOS+GCEで自動スケール分散レイトレ
Docker+CoreOS+GCEで自動スケール分散レイトレDocker+CoreOS+GCEで自動スケール分散レイトレ
Docker+CoreOS+GCEで自動スケール分散レイトレperyaudo
 
これからのコンピューティングの変化とJava-JJUG CCC 2015 Fall
これからのコンピューティングの変化とJava-JJUG CCC 2015 Fallこれからのコンピューティングの変化とJava-JJUG CCC 2015 Fall
これからのコンピューティングの変化とJava-JJUG CCC 2015 Fallなおき きしだ
 

Was ist angesagt? (20)

20131208 agile samuraibasecamp
20131208 agile samuraibasecamp20131208 agile samuraibasecamp
20131208 agile samuraibasecamp
 
Fission で 始める Containerless Kubernetes #serverlesstokyo
Fission で 始める Containerless Kubernetes #serverlesstokyoFission で 始める Containerless Kubernetes #serverlesstokyo
Fission で 始める Containerless Kubernetes #serverlesstokyo
 
18166746-NeverBlock-RubyKaigi2009
18166746-NeverBlock-RubyKaigi200918166746-NeverBlock-RubyKaigi2009
18166746-NeverBlock-RubyKaigi2009
 
Infinite Debian - Platform for mass-producing system every second
Infinite Debian - Platform for mass-producing system every secondInfinite Debian - Platform for mass-producing system every second
Infinite Debian - Platform for mass-producing system every second
 
いまさら聞けないRake入門
いまさら聞けないRake入門いまさら聞けないRake入門
いまさら聞けないRake入門
 
カンタン画像サムネイル作成「Smalllight」
カンタン画像サムネイル作成「Smalllight」カンタン画像サムネイル作成「Smalllight」
カンタン画像サムネイル作成「Smalllight」
 
GKEで半年運用してみた
GKEで半年運用してみたGKEで半年運用してみた
GKEで半年運用してみた
 
Lisp Tutorial for Pythonista Day 6
Lisp Tutorial for Pythonista Day 6Lisp Tutorial for Pythonista Day 6
Lisp Tutorial for Pythonista Day 6
 
Akka Stream x Kinesis at Shinjuku reactive meetup vol2
Akka Stream x Kinesis at Shinjuku reactive meetup vol2Akka Stream x Kinesis at Shinjuku reactive meetup vol2
Akka Stream x Kinesis at Shinjuku reactive meetup vol2
 
Fxxking gc.c
Fxxking gc.cFxxking gc.c
Fxxking gc.c
 
Project Loom - 限定継続と軽量スレッド -
Project Loom - 限定継続と軽量スレッド - Project Loom - 限定継続と軽量スレッド -
Project Loom - 限定継続と軽量スレッド -
 
コンピューティングとJava~なにわTECH道
コンピューティングとJava~なにわTECH道コンピューティングとJava~なにわTECH道
コンピューティングとJava~なにわTECH道
 
Ruby で高速なプログラムを書く
Ruby で高速なプログラムを書くRuby で高速なプログラムを書く
Ruby で高速なプログラムを書く
 
Clojureの発表など
Clojureの発表などClojureの発表など
Clojureの発表など
 
ChefとPuppetの比較
ChefとPuppetの比較ChefとPuppetの比較
ChefとPuppetの比較
 
Javaで簡単にgpgpu aparapi
Javaで簡単にgpgpu aparapiJavaで簡単にgpgpu aparapi
Javaで簡単にgpgpu aparapi
 
WebRTC multitrack / multistream
WebRTC multitrack / multistreamWebRTC multitrack / multistream
WebRTC multitrack / multistream
 
Puppet on AWS
Puppet on AWSPuppet on AWS
Puppet on AWS
 
Docker+CoreOS+GCEで自動スケール分散レイトレ
Docker+CoreOS+GCEで自動スケール分散レイトレDocker+CoreOS+GCEで自動スケール分散レイトレ
Docker+CoreOS+GCEで自動スケール分散レイトレ
 
これからのコンピューティングの変化とJava-JJUG CCC 2015 Fall
これからのコンピューティングの変化とJava-JJUG CCC 2015 Fallこれからのコンピューティングの変化とJava-JJUG CCC 2015 Fall
これからのコンピューティングの変化とJava-JJUG CCC 2015 Fall
 

Andere mochten auch

はてなブログの世界観になじむ機能デザイン
はてなブログの世界観になじむ機能デザインはてなブログの世界観になじむ機能デザイン
はてなブログの世界観になじむ機能デザインSaori Matsui
 
AWA - Coockpad Tech Kitchen 20170913
AWA - Coockpad Tech Kitchen 20170913AWA - Coockpad Tech Kitchen 20170913
AWA - Coockpad Tech Kitchen 20170913Koki Togashi
 
Test::Kantan - Perl and Testing
Test::Kantan - Perl and TestingTest::Kantan - Perl and Testing
Test::Kantan - Perl and TestingTokuhiro Matsuno
 
やさしいGemパッチの作り方
やさしいGemパッチの作り方やさしいGemパッチの作り方
やさしいGemパッチの作り方Maki Toshio
 
Quine・難解プログラミングについて
Quine・難解プログラミングについてQuine・難解プログラミングについて
Quine・難解プログラミングについてmametter
 
How to Begin to Develop Ruby Core
How to Begin to Develop Ruby CoreHow to Begin to Develop Ruby Core
How to Begin to Develop Ruby CoreHiroshi SHIBATA
 
RubyエンジニアがPythonをdisるためにPythonを勉強してみた
RubyエンジニアがPythonをdisるためにPythonを勉強してみたRubyエンジニアがPythonをdisるためにPythonを勉強してみた
RubyエンジニアがPythonをdisるためにPythonを勉強してみたYusuke Kon
 
Esoteric, Obfuscated, Artistic Programming in Ruby
Esoteric, Obfuscated, Artistic Programming in RubyEsoteric, Obfuscated, Artistic Programming in Ruby
Esoteric, Obfuscated, Artistic Programming in Rubymametter
 
Goのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考える
Goのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考えるGoのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考える
Goのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考えるpospome
 
Perfect Norikra 2nd Season
Perfect Norikra 2nd SeasonPerfect Norikra 2nd Season
Perfect Norikra 2nd SeasonSATOSHI TAGOMORI
 
Ruby and Distributed Storage Systems
Ruby and Distributed Storage SystemsRuby and Distributed Storage Systems
Ruby and Distributed Storage SystemsSATOSHI TAGOMORI
 

Andere mochten auch (12)

はてなブログの世界観になじむ機能デザイン
はてなブログの世界観になじむ機能デザインはてなブログの世界観になじむ機能デザイン
はてなブログの世界観になじむ機能デザイン
 
AWA - Coockpad Tech Kitchen 20170913
AWA - Coockpad Tech Kitchen 20170913AWA - Coockpad Tech Kitchen 20170913
AWA - Coockpad Tech Kitchen 20170913
 
RSpec Performance Turning
RSpec Performance TurningRSpec Performance Turning
RSpec Performance Turning
 
Test::Kantan - Perl and Testing
Test::Kantan - Perl and TestingTest::Kantan - Perl and Testing
Test::Kantan - Perl and Testing
 
やさしいGemパッチの作り方
やさしいGemパッチの作り方やさしいGemパッチの作り方
やさしいGemパッチの作り方
 
Quine・難解プログラミングについて
Quine・難解プログラミングについてQuine・難解プログラミングについて
Quine・難解プログラミングについて
 
How to Begin to Develop Ruby Core
How to Begin to Develop Ruby CoreHow to Begin to Develop Ruby Core
How to Begin to Develop Ruby Core
 
RubyエンジニアがPythonをdisるためにPythonを勉強してみた
RubyエンジニアがPythonをdisるためにPythonを勉強してみたRubyエンジニアがPythonをdisるためにPythonを勉強してみた
RubyエンジニアがPythonをdisるためにPythonを勉強してみた
 
Esoteric, Obfuscated, Artistic Programming in Ruby
Esoteric, Obfuscated, Artistic Programming in RubyEsoteric, Obfuscated, Artistic Programming in Ruby
Esoteric, Obfuscated, Artistic Programming in Ruby
 
Goのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考える
Goのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考えるGoのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考える
Goのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考える
 
Perfect Norikra 2nd Season
Perfect Norikra 2nd SeasonPerfect Norikra 2nd Season
Perfect Norikra 2nd Season
 
Ruby and Distributed Storage Systems
Ruby and Distributed Storage SystemsRuby and Distributed Storage Systems
Ruby and Distributed Storage Systems
 

Ähnlich wie Cookpad 17 day Tech internship 2017 言語処理系入門 Rubyをコンパイルしよう

Kink: invokedynamic on a prototype-based language
Kink: invokedynamic on a prototype-based languageKink: invokedynamic on a prototype-based language
Kink: invokedynamic on a prototype-based languageTaku Miyakawa
 
OpenStack + Common Lisp
OpenStack + Common LispOpenStack + Common Lisp
OpenStack + Common Lispirix_jp
 
Weeklycms20120218
Weeklycms20120218Weeklycms20120218
Weeklycms20120218Yoshi Sakai
 
Start!! Ruby
Start!! RubyStart!! Ruby
Start!! Rubymitim
 
恋に落ちるデプロイツール
恋に落ちるデプロイツール恋に落ちるデプロイツール
恋に落ちるデプロイツールtotty jp
 
Swiftによる関数型プログラミング超入門
Swiftによる関数型プログラミング超入門Swiftによる関数型プログラミング超入門
Swiftによる関数型プログラミング超入門Hisakuni Fujimoto
 
RubyKaigi2014: Just in Time compiler for CRuby
RubyKaigi2014: Just in Time compiler for CRubyRubyKaigi2014: Just in Time compiler for CRuby
RubyKaigi2014: Just in Time compiler for CRubyimasahiro
 
serverless framework + AWS Lambda with Python
serverless framework + AWS Lambda with Pythonserverless framework + AWS Lambda with Python
serverless framework + AWS Lambda with Pythonmasahitojp
 
Php in ruby
Php in rubyPhp in ruby
Php in rubydo_aki
 
ちゃんとWeb会議スライド『Coffee script』
ちゃんとWeb会議スライド『Coffee script』ちゃんとWeb会議スライド『Coffee script』
ちゃんとWeb会議スライド『Coffee script』H2O Space. Co., Ltd.
 
ffi for rubyists
ffi for rubyistsffi for rubyists
ffi for rubyistsnanki
 
マイクロサービス時代の生存戦略 with HashiCorp
マイクロサービス時代の生存戦略 with HashiCorpマイクロサービス時代の生存戦略 with HashiCorp
マイクロサービス時代の生存戦略 with HashiCorpMasahito Zembutsu
 
ZabbixのAPIを使って運用を楽しくする話
ZabbixのAPIを使って運用を楽しくする話ZabbixのAPIを使って運用を楽しくする話
ZabbixのAPIを使って運用を楽しくする話Masahito Zembutsu
 
もしも… Javaでヘテロジニアスコアが使えたら…
もしも… Javaでヘテロジニアスコアが使えたら…もしも… Javaでヘテロジニアスコアが使えたら…
もしも… Javaでヘテロジニアスコアが使えたら…Yasumasa Suenaga
 
おまえらこのライブラリ使ってないの? m9 (2013-07)
おまえらこのライブラリ使ってないの? m9	(2013-07)おまえらこのライブラリ使ってないの? m9	(2013-07)
おまえらこのライブラリ使ってないの? m9 (2013-07)Toru Furukawa
 
fluentd を利用した大規模ウェブサービスのロギング
fluentd を利用した大規模ウェブサービスのロギングfluentd を利用した大規模ウェブサービスのロギング
fluentd を利用した大規模ウェブサービスのロギングYuichi Tateno
 
ocamloptの全体像
ocamloptの全体像ocamloptの全体像
ocamloptの全体像Kiwamu Okabe
 
Coq 20100208a
Coq 20100208aCoq 20100208a
Coq 20100208atmiya
 
BDD勉強会 第6回
BDD勉強会 第6回BDD勉強会 第6回
BDD勉強会 第6回zakihaya
 

Ähnlich wie Cookpad 17 day Tech internship 2017 言語処理系入門 Rubyをコンパイルしよう (20)

Kink: invokedynamic on a prototype-based language
Kink: invokedynamic on a prototype-based languageKink: invokedynamic on a prototype-based language
Kink: invokedynamic on a prototype-based language
 
OpenStack + Common Lisp
OpenStack + Common LispOpenStack + Common Lisp
OpenStack + Common Lisp
 
Weeklycms20120218
Weeklycms20120218Weeklycms20120218
Weeklycms20120218
 
Start!! Ruby
Start!! RubyStart!! Ruby
Start!! Ruby
 
恋に落ちるデプロイツール
恋に落ちるデプロイツール恋に落ちるデプロイツール
恋に落ちるデプロイツール
 
Swiftによる関数型プログラミング超入門
Swiftによる関数型プログラミング超入門Swiftによる関数型プログラミング超入門
Swiftによる関数型プログラミング超入門
 
RubyKaigi2014: Just in Time compiler for CRuby
RubyKaigi2014: Just in Time compiler for CRubyRubyKaigi2014: Just in Time compiler for CRuby
RubyKaigi2014: Just in Time compiler for CRuby
 
serverless framework + AWS Lambda with Python
serverless framework + AWS Lambda with Pythonserverless framework + AWS Lambda with Python
serverless framework + AWS Lambda with Python
 
Php in ruby
Php in rubyPhp in ruby
Php in ruby
 
ちゃんとWeb会議スライド『Coffee script』
ちゃんとWeb会議スライド『Coffee script』ちゃんとWeb会議スライド『Coffee script』
ちゃんとWeb会議スライド『Coffee script』
 
ffi for rubyists
ffi for rubyistsffi for rubyists
ffi for rubyists
 
マイクロサービス時代の生存戦略 with HashiCorp
マイクロサービス時代の生存戦略 with HashiCorpマイクロサービス時代の生存戦略 with HashiCorp
マイクロサービス時代の生存戦略 with HashiCorp
 
らくちん Go言語
らくちん Go言語らくちん Go言語
らくちん Go言語
 
ZabbixのAPIを使って運用を楽しくする話
ZabbixのAPIを使って運用を楽しくする話ZabbixのAPIを使って運用を楽しくする話
ZabbixのAPIを使って運用を楽しくする話
 
もしも… Javaでヘテロジニアスコアが使えたら…
もしも… Javaでヘテロジニアスコアが使えたら…もしも… Javaでヘテロジニアスコアが使えたら…
もしも… Javaでヘテロジニアスコアが使えたら…
 
おまえらこのライブラリ使ってないの? m9 (2013-07)
おまえらこのライブラリ使ってないの? m9	(2013-07)おまえらこのライブラリ使ってないの? m9	(2013-07)
おまえらこのライブラリ使ってないの? m9 (2013-07)
 
fluentd を利用した大規模ウェブサービスのロギング
fluentd を利用した大規模ウェブサービスのロギングfluentd を利用した大規模ウェブサービスのロギング
fluentd を利用した大規模ウェブサービスのロギング
 
ocamloptの全体像
ocamloptの全体像ocamloptの全体像
ocamloptの全体像
 
Coq 20100208a
Coq 20100208aCoq 20100208a
Coq 20100208a
 
BDD勉強会 第6回
BDD勉強会 第6回BDD勉強会 第6回
BDD勉強会 第6回
 

Mehr von Koichi Sasada

Ruby's Concurrency Management: Now and Future
Ruby's Concurrency Management: Now and FutureRuby's Concurrency Management: Now and Future
Ruby's Concurrency Management: Now and FutureKoichi Sasada
 
Fiber in the 10th year
Fiber in the 10th yearFiber in the 10th year
Fiber in the 10th yearKoichi Sasada
 
Rubyインタプリタ開発者養成講座
Rubyインタプリタ開発者養成講座Rubyインタプリタ開発者養成講座
Rubyインタプリタ開発者養成講座Koichi Sasada
 
Fiber in the 10th year
Fiber in the 10th yearFiber in the 10th year
Fiber in the 10th yearKoichi Sasada
 

Mehr von Koichi Sasada (6)

Guild Prototype
Guild PrototypeGuild Prototype
Guild Prototype
 
Ruby's Concurrency Management: Now and Future
Ruby's Concurrency Management: Now and FutureRuby's Concurrency Management: Now and Future
Ruby's Concurrency Management: Now and Future
 
Fiber in the 10th year
Fiber in the 10th yearFiber in the 10th year
Fiber in the 10th year
 
Rubyインタプリタ開発者養成講座
Rubyインタプリタ開発者養成講座Rubyインタプリタ開発者養成講座
Rubyインタプリタ開発者養成講座
 
Fiber in the 10th year
Fiber in the 10th yearFiber in the 10th year
Fiber in the 10th year
 
Ruby 2.4 Internals
Ruby 2.4 InternalsRuby 2.4 Internals
Ruby 2.4 Internals
 

Kürzlich hochgeladen

新人研修のまとめ 2024/04/12の勉強会で発表されたものです。
新人研修のまとめ       2024/04/12の勉強会で発表されたものです。新人研修のまとめ       2024/04/12の勉強会で発表されたものです。
新人研修のまとめ 2024/04/12の勉強会で発表されたものです。iPride Co., Ltd.
 
IoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptxIoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptxAtomu Hidaka
 
プレイマットのパターン生成支援ツール
プレイマットのパターン生成支援ツールプレイマットのパターン生成支援ツール
プレイマットのパターン生成支援ツールsugiuralab
 
PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000Shota Ito
 
Postman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By DanielPostman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By Danieldanielhu54
 
20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directory20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directoryosamut
 
プレイマットのパターン生成支援ツールの評価
プレイマットのパターン生成支援ツールの評価プレイマットのパターン生成支援ツールの評価
プレイマットのパターン生成支援ツールの評価sugiuralab
 
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。iPride Co., Ltd.
 

Kürzlich hochgeladen (8)

新人研修のまとめ 2024/04/12の勉強会で発表されたものです。
新人研修のまとめ       2024/04/12の勉強会で発表されたものです。新人研修のまとめ       2024/04/12の勉強会で発表されたものです。
新人研修のまとめ 2024/04/12の勉強会で発表されたものです。
 
IoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptxIoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptx
 
プレイマットのパターン生成支援ツール
プレイマットのパターン生成支援ツールプレイマットのパターン生成支援ツール
プレイマットのパターン生成支援ツール
 
PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000
 
Postman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By DanielPostman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By Daniel
 
20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directory20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directory
 
プレイマットのパターン生成支援ツールの評価
プレイマットのパターン生成支援ツールの評価プレイマットのパターン生成支援ツールの評価
プレイマットのパターン生成支援ツールの評価
 
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
 

Cookpad 17 day Tech internship 2017 言語処理系入門 Rubyをコンパイルしよう