完全RuboCop

Dentoo.LT #16 での発表資料です。
https://atnd.org/events/85762





-------


自己紹介
======


------

![pocke.png](https://qiita-image-store.s3.amazonaws.com/0/33922/f2285c81-41f5-369d-dd6f-8b2b00f55bf6.png)



- Pocke
- Actcat inc. / Engineer
- Ruby :two_hearts: 
- Twitter: [@p_ck_](https://twitter.com/p_ck_)
- GitHub: [@pocke](https://github.com/pocke)

----

普段やってること
======

-----


SideCI
========

https://sideci.com


自動コードレビュー

![2017-03-08-213138_1198x616_scrot.png](https://qiita-image-store.s3.amazonaws.com/0/33922/6aa93532-631f-b613-3e47-3882363fe3d2.png)
![170311124738.png](https://qiita-image-store.s3.amazonaws.com/0/33922/0684a5c5-ab4b-9eee-e7fe-e8c7d6ed1f44.png)



------

Shibart
========


https://shibart.pocke.me

GitHub の芝を Tシャツにする

![1487946652.png](https://qiita-image-store.s3.amazonaws.com/0/33922/f98df526-c100-ebdd-ad89-e611f019096e.png)
![t-shirt.png](https://qiita-image-store.s3.amazonaws.com/0/33922/73b53a83-dc83-d910-ad84-81a11c892a02.png)


-------


Agenda
=====


RuboCop の完全さについて


-----


RuboCop とは？
======


- Ruby 用の静的解析ツール
    - スタイルチェッカ
    - Lint

------


例1
=====

スタイルが崩れているのをチェックできる

```ruby
  def foo
do_something
  end
```


```
test.rb:1:3: C: Indentation of first line in file detected.
  def foo
  ^^^
test.rb:2:1: C: Use 2 (not -2) spaces for indentation.
do_something
^^
```

-------

例2
======

バグの元を検査できる

```ruby
# Ruby では 0 < x && x < 20 のように書かないと死ぬ
if 0 < x < 20
  do_something
end
```


```
test.rb:2:4: W: Use the && operator to compare multiple values.
if 0 < x < 20
   ^^^^^^^^^^
```


-------


本日のメイン
==========

-----


Auto Correct
=======

- RuboCop には Auto Correct という便利機能がある
- 名前のとおり、自動修正


-----


例1 おかしいコードを自動で修正できる
=====

```ruby
  def foo
  bar
end
```

```
$ rubocop
Inspecting 1 file
C

Offenses:

test.rb:1:3: C: [Corrected] Indentation of first line in file detected.
  def foo
  ^^^
test.rb:2:1: C: [Corrected] Use 2 (not 4) spaces for indentation.
    bar
^^^^
test.rb:2:3: C: [Corrected] Use 2 (not 0) spaces for indentation.
  bar
  

1 file inspected, 3 offenses detected, 3 offenses corrected

$ cat test.rb
def foo
  bar
end
```

--------

例2 ループできる
=======




```ruby
def foo
  if cond
    bar
  else
    nil
  end
end
```

`else`節は省略出来る

```ruby
def foo
  if cond
    bar
  end
end
```

`else`節が存在せず body が1行の`if`は後置で書ける

```ruby
def foo
  bar if cond
end
```


これを一発で変換してくれる！



-------


メリット
====

RuboCop の使用者

- 雑にコードを書いて RuboCop が整形！


RuboCop の実装者


- ループするから、多少雑に Auto-Correct を実装しても ok
    - 「不要な空白が出来てしまったらー」とか考えなくてよい




-------


しくみ
=====


1. 問題のあるコードを探す
2. 問題のあるコードがなければ終了
3. 問題のあるコードを直す
4. 1に戻る


-----


仕組みの要点
=====


- ループがある
- コードを直せる
    - 状態が変わる

つまり、ループの中で状態を変化できる


----


なんでもできそうな気がしてきましたね？
========



------


やってみた
=======


RuboCop の Auto-Correct で Brainfuck インタプリタの実装


[pocke/rubocop-brainfuck](https://github.com/pocke/rubocop-brainfuck)

------


Brainfuck とは
=====

- 難解プログラミング言語の一種
- チューリング完全
    - つまり、Brainfuck を実装できる言語はチューリング完全

------

言語仕様
======

出来る操作は以下の8つのみ

- ポインタのインクリメント、デクリメント(`>`, `<`)
- ポインタが示す値のインクリメント、デクリメント`(`+`, `-`)
- ポインタが示す値を出力(`.`)
- ポインタが指す先に入力を代入(`,`)
- ポインタが指す値が0なら、対応する`]`の直後にジャンプ(`[`)
- 対応する`[`にジャンプ(`]`)

---------

Hello, world!
========

Brainfuck の Hello World 例

```
+++++++++[>++++++++>+++++++++++>+++++<<<-]>.>++.+++++++..+++.>-.
------------.<++++++++.--------.+++.------.--------.>+.
```


http://me.pocke.me/brainfuck-playground/

-------


RuboCop で実行
==========


```ruby
class Program < BrainFuck
  PC = 0
  Code = <<-EOS
    +++++++++[>++++++++>+++++++++++>+++++<<<-]>.>++.+++++++..+++.>-.
    ------------.<++++++++.--------.+++.------.--------.>+.
  EOS
  Memory = []
  Stdout = ''
  Stdin = ''
  Pointer = 0
end
```

```bash
$ rubocop -r rubocop/brainfuck  --only Brainfuck/Interpreter -a
Inspecting 1 file
C

Offenses:

test.rb:1:1: C: [Corrected] Interpreting the brainfuck code...
class Program < BrainFuck ...
^^^^^^^^^^^^^^^^^^^^^^^^^

1 file inspected, 1 offense detected, 1 offense corrected
```


after

```ruby
class Program < BrainFuck
  PC = 119
  Code = <<-EOS
    +++++++++[>++++++++>+++++++++++>+++++<<<-]>.>++.+++++++..+++.>-.
    ------------.<++++++++.--------.+++.------.--------.>+.
  EOS
  Memory = [0, 72, 100, 33]
  Stdout = "Hello, world!"
  Stdin = ''
  Pointer = 3
end
```

--------

実装
=========


See https://github.com/pocke/rubocop-brainfuck/blob/master/lib/rubocop/cop/brainfuck/interpreter.rb


--------


まとめ
======


- RuboCop の Auto-Correct はチューリング完全である
    - とはいえループ以外は Ruby を書いているだけなので、当たり前とも言える
- いろんなもので Brainfuck を実装してチューリング完全であることを証明しよう！
- 例: https://cpplover.blogspot.jp/2013/10/blog-post_20.html