新年最初に書いたコード

http://d.hatena.ne.jp/Mugicha/20091228/1261976261

Twitterでこんなものが流れてきたのでかっとなってやった、公開はするが後悔はしていない。
簡単にPowerShell1.0で書いて見た。
字句解析を投げている、さらに簡単な仮想コードに変換している、コードが無駄に長い、など手抜きも良いところです。
# Sな人たちに怒られる……
## バグがあっても自己責任でお願いします。多分あるけど。


使い方

以下のtdf.ps1, TsunDereC.ps1, TsunDereIpr.ps1をコピーして同じディレクトリに放りこんで下さい。その後、tdf.ps1の引数にコード名を渡せば動作します(多分)。

実行例

PS > ./tdf hello.tsun
Hello, world!

# 注:PowerShellのデフォルトの実行モードを変更しておかないと、実行できません。
# 実行モードの変更は以下のコマンドです。
PS > Set-ExecutionPolicy RemoteSigned

# TsunDereC.ps1
# Version 1.00
# 区切り文字にスペースが入っている入力を引数に入力
Param($infile)
if( $infile -eq $null ) {
	"usage: (Compiler) cmd-file"
	exit(1)
}

# パラメータ一覧
$cmdsize = 10240	# 命令最大個数
$nest = 0			# 現在のネストレベル

$cmd = new-object string[]($cmdsize)		# 命令テーブル

# 構文解析/命令用コード生成
$cur = 0
foreach($line in cat $infile) {
	$line = $line.replace("`t", ' ')
	foreach($w in $line.Split(' ')) {
		if( $w -eq "" ) { continue }
		$cmd[$cur] = '{0:0000}:' -f $cur
		switch($w) {
		# ポインタをインクリメント
		"ねぇ、" { $cmd[$cur] += 'INC' }
			
		# ポインタをデクリメント
  		"きゃっ!" { $cmd[$cur] += 'DEC' }
			
		# ポインタが示すメモリ位置のデータをインクリメント
		"ばか!" { $cmd[$cur] += 'MEMINC' }
			
		# ポインタが示すメモリ位置のデータをデクリメント
		"変態!" { $cmd[$cur] += 'MEMDEC' }

		# ポインタが示すメモリ位置のデータを出力
		"べ、別にあんたのためじゃないんだからっ!" {
				$cmd[$cur] += 'OUT'
		}

		# ポインタが示すメモリ位置のデータに入力
		 "聞いてるのっ!?" { $cmd[$cur] += 'IN' }
			
		# ポインタが示すメモリ位置のデータがヌルなら対応する
		# 私がいなくちゃだめなんだから… までジャンプ
  		"もう…" { 
			$tmp = 'JPZ N{0}' -f $nest
			$nest++
			$cmd[$cur] += $tmp 
		}
			
		# ポインタが示すメモリ位置のデータがヌルじゃないなら対応する 
		# もう… までジャンプ
  		"私がいなくちゃだめなんだから…" { 
			$nest--
			$tmp = 'JNZ N{0}' -f $nest
			$cmd[$cur] += $tmp
		}
			
		# 命令対応なし
		default { $cur-- }

		}
		$cur++
	}
}

# ラベル解析
for($i = 0; $i -lt $cmd.length; $i++) {
	if( $cmd[$i] -match '([0-9]{4}?):JPZ N([0-9]+)' ) {
		$jpzptr = $matches[1]
		$level = $matches[2]
		for($j = $i+1; $j -lt $cmd.length; $j++) {
			if( $cmd[$j] -match '([0-9]{4}?):JNZ N([0-9]+)' -and $level -eq $matches[2]) {
				$cmd[$j] = '{0}:JNZ {1}' -f $matches[1], $jpzptr
				$cmd[$i] = '{0}:JPZ {1}' -f $jpzptr, $matches[1]
			}
		}
	}
}

$cmd | Out-File "a.tsun.out"
#TsunDereIpr.ps1
# 簡易機械命令を実行
Param($infile)
if( $infile -eq $null ) {
	"usage: (Compiler) ACM-file"
	exit(1)
}

# パラメータ一覧
$memsize = 1024
[System.Byte[]]$mem = new-object System.Byte[]($memsize)
for($i = 0; $i -lt $mem.length; $i++) { $mem[$i] = 0 }

$ptr = 0			# 現在のメモリを指すポインタ位置
$cmds = cat $infile	# ファイルを全入力
$buf = ''

for($pcnt = 0; $pcnt -lt $cmds.length; $pcnt++) {
	if( $cmds[$pcnt] -notmatch '([0-9]{4}?):(.*)' ) {
		# コマンドが異常だが、一応続けられる
		continue
	}
	$cmd = $matches[2]
	switch -regex ($cmd) {
		'MEMINC' { $mem[$ptr]++; break }
		'MEMDEC' { $mem[$ptr]--; break }
		'INC' { $ptr++; break }
		'DEC' { $ptr--; break }
		'OUT' { $buf += [System.Char]$mem[$ptr]
			if( $mem[$ptr] -eq 0x0a ) {
				# 改行時にフラッシュする
				$buf
				$buf = ''
			}
			break  
		}
		'IN' { $in = Read-Host "聞いてるのっ!?"; $mem[$ptr] = $in }
		'JPZ ([0-9]+)' { if( $mem[$ptr] -eq 0 ) { $pcnt = $matches[1]-1 }; break }
		'JNZ ([0-9]+)' { if( $mem[$ptr] -ne 0 ) { $pcnt = $matches[1]-1 }; break }
	}
	# デバッグ用。必要時にON
	# "execute: $cmd"
	# "pc = $pcnt, ptr = $ptr"
	# $tmpmem = ''
	# for($i = $ptr-2; $i -le $ptr+2; $i++) {
	#	if( $i -lt 0 -or $i -ge $mem.length ) { continue }
	#	$tmpmem += "[{0}] {1:X2} " -f $i, $mem[$i]
	# }
	# $tmpmem
	# Read-Host "Press Enter"
}
# バッファにデータが残っていれば出力
if( $buf -ne '' ) { $buf }
#tdf.ps1
Param($infile)
if( $infile -eq $null ) {
	"usage:TsunDereFu** cmd-file"
	exit(1)
}
./TsunDereC $infile
./TsunDereIpr "a.tsun.out"

ちなみに、引用先からHello, world!コードを借りてきた場合、スペースを挿入するだけのお仕事が必要になるので注意。
以下がHelloWorldを出力するコード(hello.tsun)です(適度な改行などを含めてある)

ばか! ばか! ばか! ばか! ばか! ばか! ばか! ばか! ばか!
もう…
ねぇ、 ばか! ばか! ばか! ばか! ばか! ばか! ばか! ばか!
ねぇ、 ばか! ばか! ばか! ばか! ばか! ばか! ばか! ばか! ばか! ばか! ばか!
ねぇ、 ばか! ばか! ばか! ばか! ばか!
きゃっ! きゃっ! きゃっ! 変態!
私がいなくちゃだめなんだから…
ねぇ、 べ、別にあんたのためじゃないんだからっ!
ねぇ、 ばか! ばか! べ、別にあんたのためじゃないんだからっ!
ばか! ばか! ばか! ばか! ばか! ばか! ばか!
べ、別にあんたのためじゃないんだからっ!
べ、別にあんたのためじゃないんだからっ!
ばか! ばか! ばか!
べ、別にあんたのためじゃないんだからっ!
ねぇ、 変態!
べ、別にあんたのためじゃないんだからっ!
変態! 変態! 変態! 変態! 変態! 変態! 変態! 変態! 変態! 変態! 変態! 変態!
べ、別にあんたのためじゃないんだからっ!
きゃっ! ばか! ばか! ばか! ばか! ばか! ばか! ばか! ばか!
べ、別にあんたのためじゃないんだからっ!
変態! 変態! 変態! 変態! 変態! 変態! 変態! 変態!
べ、別にあんたのためじゃないんだからっ!
ばか! ばか! ばか! べ、別にあんたのためじゃないんだからっ!
変態! 変態! 変態! 変態! 変態! 変態!
べ、別にあんたのためじゃないんだからっ!
変態! 変態! 変態! 変態! 変態! 変態! 変態! 変態!
べ、別にあんたのためじゃないんだからっ!
ねぇ、 ばか!
べ、別にあんたのためじゃないんだからっ!

うーん……ファイルをzip辺りで配布したいなぁ、これ。
適当にロダ探して上げてみるか……