2015年4月28日火曜日

[OCaml]正規表現ライブラリRe2を使う

Core Document を眺めていたら、
Re2 OCaml bindings for RE2, Google's regular expression library
があった。
使い方をメモしておく。

インストール

opamでインストールできる。

$ opam install re2

以下はutopでの確認。

utop[11]> #require "re2";;

(* create関数の定義を確認 *)
utop[16]> Re2.Regex.create;;
- : ?options:Re2.Regex.Options.t list -> bytes -> Re2.Regex.t Or_error.t = <fun>

(* 正規表現を作る *)
utop[18]> let re = Re2.Regex.create_exn "aaa(.*)bbb";;
val re : Re2.Regex.t = <abstr>

(* 正規表現のパターンを取得する *)
utop[19]> Re2.Regex.pattern re;;
- : bytes = "aaa(.*)bbb"

(* マッチさせる *)
utop[20]> Re2.Regex.find_all re "aaaほげbbbaaaふがbbb";;
- : bytes list Or_error.t =
Core_kernel.Result.Ok ["aaaほげbbbaaaふがbbb"]

(* .*部分を最長一致さたいので正規表現を作り直し *)
utop[21]> let re = Re2.Regex.create_exn "aaa(.*?)bbb";;
val re : Re2.Regex.t = <abstr>

(* 再度マッチさせる *)
utop[22]> Re2.Regex.find_all re "aaaほげbbbaaaふがbbb";;
- : bytes list Or_error.t =
Core_kernel.Result.Ok ["aaaほげbbb"; "aaaふがbbb"]

(* サブマッチを取り出す *)
utop[23]> Re2.Regex.find_all re ~sub:(`Index 1) "aaaほげbbbaaaふがbbb";;
- : bytes list Or_error.t = Core_kernel.Result.Ok ["ほげ"; "ふが"]

(* マッチした文字列を置換する *)
utop[26]> Re2.Regex.rewrite re ~template:"<replaced>" "aaaほげbbbcccふがddd";; 
- : bytes Or_error.t = Core_kernel.Result.Ok "<replaced>cccふがddd"

(* サブマッチを取り出す(その2) *)
utop[27]> Re2.Regex.find_submatches re "aaaほげbbbaaaふがbbb";;
- : bytes option array Or_error.t =
Core_kernel.Result.Ok [|Some "aaaほげbbb"; Some "ほげ"|]

(* 先頭からマッチさせる *)
utop[28]> Re2.Regex.find_first re "aaaほげbbbaaaふがbbb";;
- : bytes Or_error.t = Core_kernel.Result.Ok "aaaほげbbb"

(* 先頭からのサブマッチ *)
utop[29]> Re2.Regex.find_first re ~sub:(`Index 1) "aaaほげbbbaaaふがbbb";;
- : bytes Or_error.t = Core_kernel.Result.Ok "ほげ"

(* マッチした部分で文字列を分割する *)
(* ~include_matches:true でマッチした文字列を含めることができる *)
utop[30]> let sre = Re2.Regex.create_exn ",";;
val sre : Re2.Regex.t = <abstr>
utop[31]> Re2.Regex.split sre "あい,うえ,おお";;
- : bytes list = ["あい"; "うえ"; "おお"]

マッチしない場合に例外となる関数も用意されている。
これらの関数は後ろに、_exnが付く。
utop[33]> Re2.Regex.find_first re "aaほげbbaaふがbb";;
- : bytes Or_error.t =
Core_kernel.Result.Error
 ("Re2_internal.Exceptions.Regex_match_failed(\"aaa(.*?)bbb\")")
utop[34]> Re2.Regex.find_first_exn re "aaほげbbaaふがbb";;
Exception: Re2_internal.Exceptions.Regex_match_failed("aaa(.*?)bbb").
エンコーディングはデフォルトでUTF-8が使用されるようだ。
オプション指定により、Lantin-1として扱うこともできる。
オプションはRe2.Optionsモジュールに定義されている。

とりあえず、これだけ分かれば、正規表現を使った文字列処理は困らないかな。

参考


2015年4月19日日曜日

[コンピュータ開発][コンピュータシステムの理論と実践] CPUの作成

「コンピュータシステムの理論と実装」を課題をこなしながら、読み進めている。
1章あたり1週間のペースで課題を消化して、やっとCPUの作成が完了した。

NANDゲートを使ったANDやOR等の基本論理ゲートの作成から始まり、ALU、レジスタ、RAM、カウンタを作成した後、これらの素子を組み合わせて、CPUが完成した。

回路設計は回路図を書かずに、HDLを使うという簡易さはあるものの、ハードウェアエミュレータを使って、動作確認する際は、回路上の論理値の表示がピコピコ更新されて、なかなか面白い。
図はハードウェアエミュレータでCPUのテストが完了したところ。
 過去に、いろいろな回路を設計してきたが、簡易的とはいえCPUは初めてで、設計過程はとても面白かった。
今まで作成したものは、
https://github.com/takeisa/nand2tetris-project
に公開した。

2015年4月5日日曜日

[コンピュータ開発][コンピュータシステムの理論と実践] ALUの作成

先日、O'Reillyから「コンピュータシステムの理論と実装」が発売された。
NANDという電子素子からスタートし、論理ゲート、加算器、CPUを設計します。そして、オペレーティングシステム、コンパイラ、バーチャルマシンなどを実装しコンピュータを完成させて、最後にその上でアプリケーション(テトリスなど)を動作させます。 
という内容で、まえがきには「腕まくりをし、コンピュータをゼロから作り上げたいと願う読者のための本」と書かれている。
実際にはハードウェアは作成せず、Javaで書かれたエミューレータ上で、コンピュータを作っていく。

自分でデザインしたCPUを動かしたいと思い、DE0を購入し、入門書を参考に、簡単な回路を作ったりしていたのだけど、この本を一通りこなしてから、DE0でのCPU作成にとりかかろうと思う。

各章毎にテーマがあり、動作するものを作成していく構成になっている。
第1章 NANDを使って基本的な論理回路の作成
第2章 ALUの作成 まで完了した。
HDL(Hardware Description Language)で回路か記述し、ハードウェアエミュレータで動作確認をしていく。
エミューレータによるテスト中は、入力データ、出力データ、回路内部のデータがピコピコ表示されて面白い。

はまった点

いくつか、はまった点があったので書いておく。

Hardware Emulator

Windows8.1 + Java8の環境

画面右上にあるViewでOuputとCompareを選択しても、表示されない。
この挙動を見て、Linuxで作業することにしたので、解決方法は不明。
Javaのバージョンを下げると動くのかもしれない。

Debian Wheezy + Awesome Windowの環境

Manager Awesomeが便利なので、常用しているが、HardwareEmulatro.shを実行すると、一面グレーのウィンドウが表示されるだけ。
Java6,7,8、いずれも同じ現象。
Window ManagerをXfce4に変更したら正しく表示された。

HDLの書き方

ALUで、出力が0の場合に nz=1 となるように、以下の定義を書いたが、hdlの読み込みでエラーとなった。
Mux16(a = out0, b = nout0, sel = no, out = out, out[15] = ng);

Or8Way(in[0..7] = out[0..7], out = or0);
Or8Way(in[0..7] = out[8..15], out = or1);
Or(a = or0, b = or1, out = nonzero);
Not(in = nonzero, out = zr);
エミュレータの下部にエラーメッセージが表示されるが、一行しか表示されず、エラーの行番号は分かるが、肝心なエラー原因は途中で切れて分からない。エミュレータのウィンドウを広げても、表示幅は固定のため、内容を確認できない。
検索したり、試行錯誤したりして、以下のように記述したら、正しく解釈できた。
Mux16(a = out0, b = nout0, sel = no, out = out, out[15] = ng, out[0..7] = out1l, out[8..15] = out1h);

Or8Way(in = out1l, out = or0);
Or8Way(in = out1h, out = or1);
Or(a = or0, b = or1, out = nonzero);
Not(in = nonzero, out = zr);

エミューレータのソースは公開されているので、手っ取り早く対応するには、エラーメッセージを標準出力に出力するようにすれば、便利かも。

 その他

ハードウェアエミュレータは素子の遅延時間は見ない 遅延時間は見ないので、非効率な回路を定義しても、論理的に合っていればテストOKとなる。 実際に回路を組むときは、この遅延時間を考慮することは非常に重要なのだけど、ここまで、記述はないようだ。

2015年4月2日木曜日

[Ruby][Hipchat]Hipchat用のBotをLitaで作る(2)

前回に引き続き、LitaでBotを作る。
今回は簡単な応答をするようにしてみよう。

後でgemで公開するつもりなら、
$ lita handler lita-ハンドラ名称
とすれば、雛形を作ってくれるようだ。

今回は単純に、「@Bot名 hello」と書きこみがあったら、「〜さん、こんにちは。」と応答するだけのHandlerを作る。
ソースは以下の通り。
module Lita
  module Handlers
    class HelloHandler < Handler
      route(/^hello/, :hello, command: true)

      def hello(response)
        response.reply("#{response.user.name}さん、こんにちは。")
      end
    end
  end

  Lita.register_handler(Handlers::HelloHandler)
end
routeで応答するメッセージの正規表現と呼び出すメソッド(:hello)を指定し、
呼び出されるメソッドhelloでは response.user.nameでメッセージを書いたユーザ名を参照し、response#replyで、応答メッセージを返している。
routeメソッドで command: trueを渡しているのは、@Bot名で、Botを宛先にしたメッセージだけに応答するためである。
commandの詳細については、こちらを参照。

デバッグ中は lita_config.rb を以下のように設定すると、コマンドラインで動作確認できる。
config.robot.adapter = :shell
config.adapters.shell.private_chat = true 
ただし、この場合は、routeメソッドでcommand: false にし、 テスト時には、@Bot名を付けずに、helloだけにしないと応答しない。
      route(/^hello/, :hello, command: false)
コマンドラインでの実行例
$ lita
Type "exit" or "quit" to end the session.
Lita Bot > hello
Shell Userさん、こんにちは。
Lita Bot > 

2015年3月29日日曜日

[Ruby][Hipchat]Hipchat用のBotをLitaで作る

仕事場でHipchatを使い始めた。
Botを作って、いろいろと便利な機能を提供したい。
関連する情報を検索すると、Hubot + Hipchat用のアダプタという例が多数あった。
しかし、Debian Wheezy で試してみると、Hipchatのアダプタ(hubot-hipchat)のインストールに失敗してしまう。
最終的には、node.js のバージョン落として、v0.10.38でインストールできたのだけど。

気に入らなかったので、RubyでHipchatと連携できるものが無いのか調べたら、
Lita - A robot companion for your company's chat room
というのがあった。
こちらの解説記事がまとまっており、このページに書かれている手順で、動かすことができた。
以下、Botでinfo表示、whois、Googleのイメージ検索ができるようにする設定を、まとめておく

環境

環境は以下の通り。
  • Debian Wheezy
  • rbenvでruby-2.2.0をインストール済み
  • apt-getでredis-server をインストール済み

準備

Hipchatで利用するBotアカウントを作成しておく。
アカウント作成にはメールアドレスが必要。
gmailのアカウントがあれば、メールアドレスに+を使って、複数アカウトを作る方法がお手軽だ。 (ここらへんを参考に。)

Litaのインストール

Litaはgemでインストールできる。
$ gem install lita

Botの作成

Bot用のプロジェクトを作る。
$ lita new bot
botディレクトリに、新しいLitaのプロジェクトが作成される。

Gemfileを編集する。
HipChatアダプタを使う。
gem "lita-hipchat"
の行をコメントアウトする。
$ bundle install
で反映させる。

lita_config.rbを編集する。
# 名前を合わせておかないと起動時にエラーになるので注意。
config.robot.name = "Lita Bot"
# Hipchatを利用する。
config.robot.adapter = :hipchat
# ポート番号はデフォルトは1234になっていたが、6379にしないと起動しなかった。
config.redis.host = "127.0.0.1"
config.redis.port = 6379
# Hipchatの管理画面からXMPP/Jabber Account Informationに表示されるJabber IDを設定する。
config.adapters.hipchat.jid = "省略@chat.hipchat.com"
# Hipchatのアカウントのパスワード
config.adapters.hipchat.password = "省略"
# trueにしておくと、デバッグログが表示される。接続できない場合に便利。
config.adapters.hipchat.debug = true
# 利用するChat roomの名前か :all
config.adapters.hipchat.rooms = :all

Litaの起動

$ lita
設定が間違っているとエラーログが表示されるので確認する。
問題がなければ、BotはChat roomに参加する。

Hipchatで動作確認

@lita info
LitaとRedisの情報が表示される。

whoisとGoogleのイメージ検索の利用

Gemfileに次の設定を追加する。
gem "lita-google-images"
gem "lita-whois"
lisaを再起動する。
whoisは
@lita whois ホスト名
イメージ検索は
@lita image cat
で利用できる。


機能の拡張

Botが応答するwhoisやimageの処理は、Handlerとして実装できるようなので、まずは、単純に、ユーザの入力に応答をするものを作ってみよう。

参考

2015年3月26日木曜日

[FPGA][コンピュータ開発] DE0の関連書籍

DE0とパソコンは接続できたが、これから先、どうすれば良いのかさっぱり分からない。
本屋とAmazonを徘徊して、良さそうな本をいくつか購入した。

FPGA ボードで学ぶ組込みシステム開発入門 ~Altera編~ 

DE0を使う上での定番の書籍みたい。
開発ソフトQuartus2の使い方に始まり、Nios2やμClinux等、幅広く、いろいろな記事がある。

インターフェースZERO No.04 Hello Worldから始めるFPGA入門: 2大メーカXilinx,Alteraのお手軽ボードでチョコッと体験! 

表紙に、本書の内容を試せる定番FPGAボードとして、DE0-nanoとDE0が載っていたので購入。
Altera社のFPGAでLEDをチカチカさせるという記事があるので、まずはこれを試すのが良いかな。
HDLの説明や、基本的な例、オセロゲームを作るなど、チョコッと体験!というタイトルのわりには、いろいろ書いてある。

FPGA/PLD入門記事全集[2200ページ収録CD-ROM付き]: 月刊トランジスタ技術,Interface,Design Wave Magazine10年分(2001-2010)から集大成 (アーカイブスシリーズ) 

Design Wave Magazineで連載していた記事で、基礎から学ぶVerilog HDL & FPGA設計が面白そうだったので購入。この連載の「CPUを作ろう」「CPUの設計」「アセンブラの設計」「コンパイラの設計」のタイトルが興味を引いた。

2015年3月25日水曜日

[FPGA][コンピュータ開発]DE0購入

以前から、FPGAを使ってCPU製作してみたかったのだけど、とうとうDE0を買ってしまった。
最近、DE1-SocDE0-CV が販売されており、どれにしようか悩んだのだけど、書籍やWeb上での情報が豊富なDE0に決定。
digikeyで購入しようと思ったが、すぐにでも欲しくなってしまったので、物が置いてあった千石通商で購入。\17,850だった。円安が原因で、以前より価格が上がっているようだ。

DE0はWindows8.1 64bit版のマシンで使う。
Windows8.1で使えるか、心配だったが、大丈夫のようだ。

Alteraから Quartus2 Web Edition 13.1 をダウンロードして、
QuartusSetupWeb-13.1.0.162.exe
をインストール。
※DE0に載っているCyclone III 3C16 FPGA deviceに対応しているのは 13.1までのようだ。

全てデフォルトのままインストールした。
インストールするもののうち、ModelSim-Altera Editionだけ、チェックが付いていなかった。

DE0に電源を繋いで、USBとPCを接続する。
デバイスマネージャ を見ると、ほかのデバイスに USB Blasterがあるので、
手動で、C:\altera\13.1\quartus\drivers\usb-blaster を指定してドライバをインストールする。
インストールが完了すると、ユニバーサル シリアル バス コントローラー に
Altera USB-Blaster が表示される。

DE0の添付DVDにあった、Getting Started with Altera DE0 board.pdf に書いてあるように、電源を入れると、
  • All user LEDs (LED0~LED9) are flashing
  • All 7-segment displays(HEX0 and HEX3) are cycling through the numbers 0 to F
となっており、いまのところ問題は無い。