新プログラミング言語「ゴリスペース」を公開しました
霊長類の中でも特にオランウータン・チンパンジー・ボノボ・ゴリラの知能は高く、人間の5才児程度に相当し、ある程度は抽象的な思考もこなせることが分かっています。言葉に関しても手話を操るチンパンジーやゴリラの話は有名でしょう。
中でもゴリラについては実際に森に住むゴリラと人間が言葉でやり取りをすることさえ可能で、京都大学の山極寿一教授は10種類ほどのゴリラ語を話すことができるといいます。そう考えると彼らの為のプログラミング言語があってもおかしくありません。いや、むしろ無いことの方がおかしく思われます。
そこで私はゴリラ用プログラミング言語「ゴリスペース」を開発しました。*1
- ソースコードサンプル
ウホホホホウホホホ、ウホホ。ウッホホ。ウホホホホウホウッホホホホ。ウホホホホ、ウホホウホウホホーイウッホウホホホーイ。ウホホホホウホウホホホホ、ウホホウホホホホ。ウッホホウッホホホ、ウホホホウホホ。ウッホウホウッホホ、ウホホホーイウッホホ。ウホホーイウホホホ、ウホ、ウホホホホ。ウホホホホ。ウホウッホホウッホホホウホホホウッホホホホ、ウッホホ。ウホホホウホホホウホホホーイ。ウッホホホ。ウホホホホーイウホ、ウホホホウホホホホ、ウホホウホホホウッホホホホウッホホホホウホホホホウッホホホホウッホ、ウホホホ。ウホホホウホホホホーイ。ウッホウホーイウホホホホウホウホホホホウホホホホウホホホウッホホウッホホウホホホウッホホ、ウッホホウッホホウッホホウホホホーイウッホホホ、ウホーイウホホホウホホホウホホホホ、ウホホホ、ウホホホ。ウッホホホホウホホ、ウホホホホ、ウホ。ウホホホ、ウホ。ウホホホホーイ。ウッホホホホ、ウホホホーイ。ウホホウホウホホホウホホホ、ウホウッホホホホ、ウホウッホ、ウホホホウッホホホ。ウッホホホウッホホホ、ウホホホホーイ。ウッホ。ウホホホーイウホホウホホホ。ウホウホホホホ。ウホウッホウッホホホウホ。ウッホホウッホホホ。ウッホホホホウッホホウホホホホーイウッホホホホウホホーイウホホホホウホホホホ、ウホ。ウホホホホ。ウホホホ、ウッホ、ウッホホホホ、ウッホ、ウホウホホホウッホホホホ、ウホホホホウホーイウッホ、ウホホホーイ。ウホ、ウホホホ。ウホホウホホホホウホホホホウッホホ、ウッホウホホウッホホホ。ウッホウホホ、ウホホウホーイウッホ。ウホーイ。ウホウホホホホウホ。ウホホウホホ、ウッホウッホホ。ウホ、ウホホホウッホウホホ。ウホウホホーイ。ウッホホホホ、ウホーイウホウホ。ウホホ。ウホホホ、ウホウホホ。ウホホホホウホ。ウッホホホ。ウホホホ、ウッホ。ウホホホホ、ウホホーイ。ウッホホホ、ウホホホホーイウホホホホ、ウホホウホホホーイウホーイ。ウホホホホーイ
$ bin/gorispace samples/helloworld.gs Hello World
ウホウホウホホホホウッホウホホホウホホホウッホホホウホホホウホホウホホウホホホホーイ。ウッホウホーイウホホホ。ウホウホホホホ。ウホウホウッホホホホウッホホホホ、ウホホウッホホホホウッホホ。ウッホホホウッホウホーイ。ウッホホホホウホホホホーイ。ウホホホホウホ。ウホ、ウホホホウホホ。ウッホホホウッホホホウッホホホホ。ウホホホウッホホホホ、ウッホホホホウッホホ、ウホーイ。ウッホホホホウホーイウホウホホウホホ、ウホホウホウッホホホホウホホ、ウホホホホ。ウホウホホホウホウホーイウッホホウホーイウホ、ウホホホホウホホ。ウホホホホ、ウホホホホウッホホホホウッホホホホ、ウホホウッホホホホ。ウッホウホホホホウッホホホホウホーイウッホ。ウホホーイウホホ、ウホホホ。ウホホホ、ウホホホホウホホホホウッホウッホホホウホホホホ、ウホウホホホウホホホホウッホウホホホーイ。ウッホホ、ウホホホホーイウホホホホ、ウホウホ。ウホウホホウッホホホホウッホホホホ。ウホホ、ウッホホホホウッホウッホホホウホウホホホーイウッホホ、ウホホーイウホホホウホウホホ、ウホホホホ、ウホホウッホホホ、ウッホホホホ。ウッホホホ。ウッホ、ウホホホ。ウホウッホホウホホーイ。ウッホホホウホホーイウホホホホ。ウホホ。ウホウホホホウホホホ、ウッホホ、ウッホウッホホホホウッホ、ウッホホホホ、ウッホホウホホーイウッホホホホウホーイウホ、ウホホウホ。ウホホホホ。ウホホホホ、ウッホホホ。ウホホホホ。ウホホ。ウホホホ、ウホホホ。ウホウホホホーイウッホホウホーイウホホホウホホホ。ウホ、ウホホホホウホホホホウッホホホホウホホ、ウホホーイウッホウホホホホーイウッホホウッホウホホ、ウホホホホ、ウホホホホ。ウホホ、ウホーイ。ウホホホホ、ウホホホホ。ウホホ、ウッホホホホウホホーイウホホウホーイウホホ、ウッホホホ。ウホホホホーイウホホ、ウッホホホホウホホウホホウホウッホホホホ、ウホホ、ウッホホ、ウホホホウホホホーイウッホウホホーイウホホホホ、ウホホホ、ウホーイ。ウホ、ウホホホウッホホウホーイ。ウホ、ウホホーイウホホホウホホホホ。ウホホホ、ウホホウッホホウホホホーイウホホウホーイウッホホホホウッホホホホ、ウッホホホウホ、ウッホホウホウホホホ。ウホウホホホ。ウホホホホウホホウッホホホウホホーイウッホホ、ウッホホホホ、ウッホホホホ、ウホホホ。ウホホホーイウッホホ、ウホホ、ウホホーイウホホホウッホホウホホーイウホホウッホホ。ウホホウホウホホホウッホホホホウホ。ウッホ。ウホホホホウホホホーイウッホホウホホホーイウホホホホウホ、ウホホウホホホホ、ウホホウッホウホホ。ウホホホホーイウッホホホウッホホホホウッホホホ、ウホホホウホホホホウホ、ウッホホウホホホホーイウッホホウホホホホウホ、ウッホ、ウホウホーイウホホホホウホホホホウホホ、ウホホホホ、ウッホウホホホホ。ウホホーイウホホホ、ウホホーイウッホホ。ウッホウッホホホホウホホウホホホーイ。ウッホホホホ。ウッホホホホ、ウッホホホホ。ウホホホホウホホーイ。ウホーイウホホホホ。ウホホーイ。ウッホホ、ウホーイ。ウホホホーイウホホホホウホ。ウッホホホウホウホホホホーイウホーイウホホホーイウホーイ
$ bin/gorispace samples/fibonacci.gs How many? 5 1 1 2 3 5 8 13
その他のサンプル
http://github.com/technohippy/gorispace/tree/master/samples
- 言語解説
ゴリスペースはスタックベースのプログラミング言語で、IMP(Instruction Modification Parameter)、コマンド、パラメータの3つ組で一つの命令を表現します。
IMP | 意味 |
---|---|
ウホ | スタック操作 |
ウッホウホ | 整数演算 |
ウッホウッホ | ヒープアクセス |
ウホーイ | フロー制御 |
ウッホウホーイ | 入出力 |
スタック操作 | IMP: ウホ | |
---|---|---|
コマンド | パラメータ | 意味 |
ウホ | 数値 | 数値をスタックにプッシュ |
ウホーイウホ | - | スタックトップを複製 |
ウホーイウッホ | - | スタックの1番目と2番目を交換 |
ウホーイウホーイ | - | スタックトップを破棄 |
整数演算 | IMP: ウッホウホ | |
---|---|---|
コマンド | パラメータ | 意味 |
ウホウホ | - | スタックの上から二つを足し算 |
ウホウッホ | - | スタックの上から二つを引き算 |
ウホウホーイ | - | スタックの上から二つを掛け算 |
ウッホウホ | - | スタックの上から二つを割り算 |
ウッホウッホ | - | スタックの上から二つで剰余 |
ヒープアクセス | IMP: ウッホウッホ | |
---|---|---|
コマンド | パラメータ | 意味 |
ウホ | - | 値をアドレスに格納 |
ウッホ | - | アドレスから値をスタックに |
フロー制御 | IMP: ウホーイ | |
---|---|---|
コマンド | パラメータ | 意味 |
ウホウホ | ラベル | ラベル定義 |
ウホウッホ | ラベル | サブルーチン呼び出し |
ウホウホーイ | ラベル | 無条件ジャンプ |
ウッホウホ | ラベル | スタックトップがゼロならジャンプ |
ウッホウッホ | ラベル | スタックトップが負ならジャンプ |
ウッホウホーイ | - | サブルーチン終了 |
ウホーイウホーイ | - | プログラム終了 |
入出力 | IMP: ウッホウホーイ | |
---|---|---|
コマンド | パラメータ | 意味 |
ウホウホ | - | スタックトップの文字を出力 |
ウホウッホ | - | スタックトップの数値を出力 |
ウッホウホ | - | 文字を読み込みアドレスに格納 |
ウッホウッホ | - | 数値を読み込みアドレスに格納 |
数値 | 数値は二進数で表し、ウホ が 0、ウッホ が 1、ウホーイ が終端記号 |
---|---|
ラベル | ラベルは ウホ と ウッホ の列で表現され、ウホーイ が終端記号 |
なお、「ホ」の連続は「ホ」として扱われ、「ウ」「ッ」「ホ」「ー」「イ」以外の文字は全て無視されます。
ということで、そろそろ分かってると思うけど、ゴリスペースは要するにWhitespaceの亜種です(Brainf*ckを元にしてもよかったんだけど、それだとまんまOok!になってしまうので敢えてWhitespaceを選択)。Whitespaceの各トークン?との対応は次のような感じ。
Whitespace | Gorispace |
---|---|
[Space] | ウホ |
[Tab] | ウッホ |
[LF] | ウホーイ |
http://github.com/technohippy/gorispace/tree/master/src/gorispace.rb
$KCODE='u' require 'strscan' @ops = { /AA([AB]+)(C)/ => :stack_push, /ACA/ => :stack_copy, /ABA([AB]+)(C)/ => :stack_copynth, /ACB/ => :stack_swap, /ACC/ => :stack_discard, #/ABC([AB]+)(C)/ => :stack_slide, /BAAA/ => :arithmetic_add, /BAAB/ => :arithmetic_sub, /BAAC/ => :arithmetic_mul, /BABA/ => :arithmetic_div, /BABB/ => :arithmetic_mod, /BBA/ => :heap_store, /BBB/ => :heap_restore, /CAA([AB]+)C/ => :flow_mark, /CAB([AB]+)C/ => :flow_call, /CAC([AB]+)C/ => :flow_jump, /CBA([AB]+)C/ => :flow_zero, /CBB([AB]+)C/ => :flow_nega, /CBC/ => :flow_return, /CCC/ => :flow_exit, /BCAA/ => :io_outchar, /BCAB/ => :io_outnum, /BCBA/ => :io_readchar, /BCBB/ => :io_readnum } @instructions = [] @stack = [] @heap = {} @marks = {} @call_stack = [] def scan(code) scanner = StringScanner.new(code) until scanner.eos? converted = false @ops.keys.each do |key| if scanner.scan(key) command = @ops[key] param = scanner[1] if scanner[2] sign = param[0] == ?A ? 1 : -1 abs = 0 param[1..-1].each_byte do |c| abs <<= 1 abs |= 1 if c == ?B end param = sign * abs end @instructions << [command, param] @marks[param] = @instructions.size - 1 if command == :flow_mark converted = true break end end break unless converted end end def execute pc = 0 while pc < @instructions.size old_stack_size = @stack.size old_heap_size = @heap.size command, param = *@instructions[pc] case command when :stack_push @stack.push(param) when :stack_copy @stack.push(@stack.last) when :stack_copynth @stack.push(@stack[param]) when :stack_swap val1 = @stack.pop val2 = @stack.pop @stack.push(val1) @stack.push(val2) when :stack_discard @stack.pop #when :stack_slide when :arithmetic_add val1 = @stack.pop val2 = @stack.pop @stack.push(val2 + val1) when :arithmetic_sub val1 = @stack.pop val2 = @stack.pop @stack.push(val2 - val1) when :arithmetic_mul val1 = @stack.pop val2 = @stack.pop @stack.push(val2 * val1) when :arithmetic_div val1 = @stack.pop val2 = @stack.pop @stack.push(val2 / val1) when :arithmetic_mod val1 = @stack.pop val2 = @stack.pop @stack.push(val2 % val1) when :heap_store val = @stack.pop addr = @stack.pop @heap[addr] = val when :heap_restore addr = @stack.pop @stack.push(@heap[addr]) when :flow_mark # do nothing when :flow_call @call_stack.push(pc) pc = @marks[param] when :flow_jump pc = @marks[param] when :flow_zero pc = @marks[param] if @stack.pop == 0 when :flow_nega pc = @marks[param] if @stack.pop < 0 when :flow_return pc = @call_stack.pop when :flow_exit exit(0) when :io_outchar print(@stack.pop.chr) when :io_outnum print(@stack.pop) when :io_readchar @heap[@stack.pop] = $stdin.readline[0] when :io_readnum @heap[@stack.pop] = $stdin.readline.to_i end @stack.compact! pc += 1 end end def gorispace(code) code = code.gsub(/[^ウッホーイ]/, '').gsub(/ホ+/, 'ホ').gsub(/ウホーイ/, 'C').gsub(/ウッホ/, 'B').gsub(/ウホ/, 'A').gsub(/[^ABC]/, '') scan(code) execute end if __FILE__ == $0 unless ARGV.empty? gorispace(ARGF.read) else puts('filename required') end end