明日は VimMいってきまーす


明日は VimM第一回勉強会にいってきまーす。

VimM (Vim Movement) - Seesaa Wiki(ウィキ)


というお題で発表する方向です。


Vimスクリプトをまだ書いたことないけど書いてみたい」
「最近 Vimスクリプトを書いてないけど、また書く気になってきた」


と思ってもらえるといいなー、と思ってたりします。
Vim熟練者な方もけっこう参加される様子で
ust中継されるし、なかなかドキドキなわけですね><


BF実装編、ということにしているので
シリーズ化して継続的に勉強していけるとよいなぁ、とか思ったり。


で、bf.vim というネタでいくので
その Vimスクリプトを貼っておきます。

"
" 2008/07/20 第1回 VimM勉強会版 bf.vim
"

" --------------------------------------
"   Initialize
" --------------------------------------
function! s:BFInit(first, last)
    let s:imem = ""         " instruction memory
    let s:ip = 0            " instruction pointer
    let s:array = []        " byte array
    let s:array_size = 256  " size of array
    let s:ptr = 0           " array pointer
    let s:ax = 0            " register ax

    " load instruction
    let l:cur = a:first
    while l:cur <= a:last
        let s:imem = s:imem . getline(l:cur)
        let l:cur = l:cur + 1
    endwhile

    " delete noise data / clear array
    let s:imem = substitute(s:imem, '[^\+\-\.\,\<\>\[\]]', "", "g")

    let l:i = 0
    while l:i < s:array_size
        call add(s:array, 0)
        let l:i = l:i + 1
    endwhile
endfunction

" --------------------------------------
"   BrainF*ck operation
" --------------------------------------

" >
function! s:BFNext()
    " ptr++
    let s:ptr = s:ptr + 1

    let s:ip = s:ip + 1
endfunction

" <
function! s:BFPrev()
    " ptr--
    let s:ptr = s:ptr - 1

    let s:ip = s:ip + 1
endfunction

" +
function! s:BFIncr()
    " (*ptr)++
    let s:array[s:ptr] = s:array[s:ptr] + 1

    let s:ip = s:ip + 1
endfunction

" -
function! s:BFDecr()
    " (*ptr)--
    let s:array[s:ptr] = s:array[s:ptr] - 1

    let s:ip = s:ip + 1
endfunction

" .
function! s:BFPutChar()
    " putchar(*ptr)
    echo nr2char(s:array[s:ptr])

    let s:ip = s:ip + 1
endfunction

" ,
function! s:BFGetChar()
    " *ptr=getchar()
    let l:char = input('input char : ')     " XXX 
    let s:array[s:ptr] = char2nr(l:char)

    let s:ip = s:ip + 1
endfunction


" [
function! s:BFBeginWhile()
    if s:array[s:ptr] == 0
        let l:dst = stridx(s:imem, "]", s:ip)
        if l:dst == -1
            echo "syntax error : ] not found"
            return
        endif

        let s:ax = 0
        let s:ip = l:dst + 1
    else
        let s:ax = s:ip
        let s:ip = s:ip + 1
    endif
endfunction


" ]
function! s:BFEndWhile()
    let s:ip = s:ax
endfunction


" --------------------------------------
"   Main Routine
" --------------------------------------
function! BFMain() range
    call s:BFInit(a:firstline, a:lastline)
    while 1
        let l:op = strpart(s:imem, s:ip, 1)
        if      l:op == ">" 
            call s:BFNext()
        elseif  l:op == "<"
            call s:BFPrev()
        elseif  l:op == "+"
            call s:BFIncr()
        elseif  l:op == "-"
            call s:BFDecr()
        elseif  l:op == "."
            call s:BFPutChar()
        elseif  l:op == ","
            call s:BFGetChar()
        elseif  l:op == "["
            call s:BFBeginWhile()
        elseif  l:op == "]"
            call s:BFEndWhile()
        else    
            break
        endif
    endwhile
endfunction


hello.bf

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