paiza.ioでelixir その318

# 概要
paiza.ioでelixirやってみた。
練習問題、やってみた。

# 練習問題
俺言語で1-10の総和を実行するインタープリターを書け。




# 俺言語の仕様。
対話形式で、一行ずつ解釈するインタープリター。
行番号を持ち、分岐できる。
文は、代入文のみ。
行は、行番号、スペース、代入文。
行番号は、１から２５５まで。
変数は、a,b,c,d,e,f。
数値は、０から２５５まで。
＋　/　*　－ で加減乗除。
%は、剰余。
$は、乱数。０から９。
0は、ソースリスト。
ソースは、256バイト。
= < > で論理式、値は０と1を取る。
文は、左から順に評価される。2+5*6は、42となる。
＃は、プログラムカウンター
if文は、#=a<100*20でaが100より小さいなら、行20に飛ぶ
？は、プリント文。
行番号無しなら、ダイレクト実行。
100 a=0で、インサート
100で、デリート
100 a=100で、エディット

```
10 a=1　　　　　　　変数aを初期化
20 b=0　　　　　　　変数ｂを初期化
30 b=b+a　　　　　　総和を計算
40 a=a+1　　　　　　カウントアップ
50 #=a<11*30　　　　10までなら30行へループ
60 ?=b　　　　　　　表示
70 #=0　　　　　　　終了
```

# サンプルコード

```

defmodule Sim do
	def start_link do
		Agent.start_link(fn ->
			[a: 0, b: 0, c: 0, pc: 0]
		end, name: __MODULE__)
	end
    def a(s) do
		Agent.update(__MODULE__, fn v ->
		    ex = "[" <> s <> "]"
			{[d], _} = Code.eval_string(ex, v)
			v = List.keyreplace(v, :a, 0, {:a, d})
			List.keyreplace(v, :pc, 0, {:pc, 777})
		end)
    end
    def b(s) do
		Agent.update(__MODULE__, fn v ->
    	    ex = "[" <> s <> "]"
			{[d], _} = Code.eval_string(ex, v)
			v = List.keyreplace(v, :b, 0, {:b, d})
			List.keyreplace(v, :pc, 0, {:pc, 777})
		end)
    end
    def print(s) do
		Agent.update(__MODULE__, fn v ->
    	    ex = "[" <> s <> "]"
			{[d], _} = Code.eval_string(ex, v)
			IO.write(d)
			IO.write(' ')
			List.keyreplace(v, :pc, 0, {:pc, 777})
		end)
    end
	def r() do
		IO.puts("")
	end
    def jmp(s) do
		Agent.update(__MODULE__, fn v ->
		    if String.match?(s, ~r/\*/) do
	            p = String.split(s, "*")
			    g = Enum.at(p, 0)
			    ex = "[" <> g <> "]"
    			{[d], _} = Code.eval_string(ex, v)
    			if d == true do
    			    x = String.to_integer(Enum.at(p, 1))
    			    List.keyreplace(v, :pc, 0, {:pc, x})
    			else
    			    List.keyreplace(v, :pc, 0, {:pc, 777})
    			end
		    else
    			List.keyreplace(v, :pc, 0, {:pc, 777})
		    end
		end)
    end
	def pc() do
		Agent.get(__MODULE__, fn v ->
            v[:pc]
        end)
    end
    def test() do
		Agent.get(__MODULE__, fn v ->
            v
        end)
    end
end

defmodule Main do
    def src(n) do
        str = """
10 a=1
20 b=0
30 b=b+a
40 a=a+1
50 #=a<11*30
60 ?=b
70 #=0
"""
        Enum.map(String.split(str, "\n", trim: true), fn l ->
		    s = String.split(l, " ")
		    cond do
  		    String.to_integer(Enum.at(s, 0)) == n ->
	  	        l
		    true ->
		        nil
	        end
	    end)
    end
    def run(0) do
    end
    def run(pc) do
        m = src(pc)
        m = Enum.reject(m, fn(x) -> 
	            x == nil 
            end)
        Enum.map(m, fn l ->
            b = String.replace(l, "=", " ")
            s = String.split(b, " ")
	        cond do
		    Enum.at(s, 1) == "?" ->
	    	    Sim.print(Enum.at(s, 2))
		    Enum.at(s, 1) == "#" ->
		   	    Sim.jmp(Enum.at(s, 2))
		    Enum.at(s, 1) == "a" ->
			    Sim.a(Enum.at(s, 2))
		    Enum.at(s, 1) == "b" ->
			    Sim.b(Enum.at(s, 2))
		    Enum.at(s, 1) == "r" ->
			    Sim.r()
		    true ->
			    IO.puts ""
		    end
    		cond do
		    Sim.pc == 777 ->
		        run(pc + 10)
		    true ->
		        run(Sim.pc)
		    end
    	end)
	end
end

Sim.start_link
Main.run(10)




```

# 実行結果

```
55
```

# 成果物

https://paiza.io/projects/iJccC7Pemm6k61elZN7vFw


以上。