by shigemk2

当面は技術的なことしか書かない

bcで16進数電卓ぽいことをやってみる

bcコマンドを使ってみる。

obaseで出力、ibaseで入力の進数を設定することが出来る。

obase=16
ibase=2

って書くと、2進数を16進数に変換する電卓モドキが出来上がる。

bc
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'. 
10001111
10001111
obase=16
ibase=2
10001111
8F
10001111
8F
100011110000
8F0
1000111100000000
8F00

逆引きUNIXコマンド/bcコマンドで16進数、10進数、8進数、2進数の変換・計算を行う - Linuxと過ごす

使ってみて思ったんですが、言語の対話形式だとよく表示される > が表示されないので、なんかこう使い方に違和感を感じるのは僕だけでしょうか。

> 
> 
>

BrainfuckのインタプリタをHaskellで

Haskell アクション 超入門 - Qiita

BFはメモリの値を頻繁にいじるため参照透過性もクソもない言語なので、インタプリタも参照透過性なんて存在せず、副作用や状態を持たないとどうにもなりません

BFの世界は参照透過性の綺麗な海ではありませんが、変数の束縛(しがらみ)から解放された自由な言語だったのです。

ループの実装に思いの外手間取りました。少し言い訳をすると、昼のラーメンがあまりおいしくなかったのが原因かもしれません。

なお、getChar部分は手を付けていません。そういう実装が可能ならばいいんですが。

BFのインタプリタを実装したことがある人間なら分かると思いますが、ループはいつも実装が難しいです。

import Data.Array.IO
import Data.Word
import Data.Char
main = do
    let bf = ">+++++++++[<++++++++>-]<.>+++++++[<++++>" ++
             "-]<+.+++++++..+++.[-]>++++++++[<++++>-]<" ++
             ".>+++++++++++[<+++++>-]<.>++++++++[<+++>" ++
             "-]<.+++.------.--------.[-]>++++++++[<++" ++
             "++>-]<+.[-]++++++++++."
    -- let bf = "++++++++++++++++++++++++++++++" ++
    --          "++++++++++++++++++++++++++++++" ++
    --          "++++++++++++."
    -- let bf = "+++++++++[>++++++++<-]>."
    jmp <- newArray (0, length bf + 1) 0 :: IO (IOUArray Int Int)
    let loops = []

    let loop i loops | i < length bf = do
          case bf !! i of
            '[' -> do
              loop (i + 1) (i:loops)
            ']' -> do
              let (start:loops') = loops
              writeArray jmp start i
              writeArray jmp i start
              loop (i + 1) loops'
            _ -> do
              loop (i + 1) loops
        loop _ _ = return ()
    loop 0 []
    -- print =<< getElems jmp

    m <- newArray (0, 30000) 0 :: IO (IOUArray Int Word8)
    let scanbf pc r | pc < length bf = do
          -- print pc
          case bf !! pc of
            '+' -> do
              a <- readArray m r
              writeArray m r (a + 1)
              scanbf (pc + 1) r
            '-' -> do
              a <- readArray m r
              writeArray m r (a - 1)
              scanbf (pc + 1) r
            '>' -> do
              scanbf (pc + 1) (r + 1)
            '<' -> do
              scanbf (pc + 1) (r - 1)
            '.' -> do
              a <- readArray m r
              -- Word8を変換するためのfromIntegral
              putChar $ toEnum $ fromIntegral $ a
              -- putChar $ chr $ a
              scanbf (pc + 1) r
            '[' -> do
              a <- readArray m r
              if a == 0
              then do
                pc <- readArray jmp pc
                scanbf (pc + 1) r
              else do
                scanbf (pc + 1) r
            ']' -> do
              a <- readArray m r
              if a /= 0
              then do
                pc <- readArray jmp pc
                scanbf pc r
              else do
                scanbf (pc + 1) r
            _ -> do
              scanbf (pc + 1) r
        scanbf _ _ = return ()
    scanbf 0 0

今日やったこと #ikebin

BrainfuckのインタプリタをHaskellで - by shigemk2

今日は雨だったので早めに帰った。時間の大半をBFインタプリタに費やす。

アクションはうすらぼんやりと、「箱」のようなものだと理解しており、箱の中から取り出した何かが値で、その際に何か別のことが起こるのが副作用であるという理解。

なお、BFインタプリタ実装に失敗して無限ループが発生した。JavaScriptなどと違ってスタックに積むということがないためスタックオーバーフローさえも起きずに膨大なスワップが発生するとのこと(64bit限定)

そして、8086のインタプリタはpop命令のハンドアセンブルまでやった。

2進数を頭の中で計算して16進数に変換するのはつらいので、bcでごにょごにょするようにしてみた。

bcで16進数電卓ぽいことをやってみる - by shigemk2

ところで、hexeditって文字の削除って出来ないですかね。

DisAsm.2014113023.hs