paiza.ioでelixir その203

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

# 練習問題
アセンブラを書け。
fizzbuzzをコンパイルせよ。

# サンプルコード

```
defmodule Va do
	use Agent
	def start_link() do
		Agent.start_link(fn ->
			0
		end, name: __MODULE__)
	end
	def get() do
		Agent.get(__MODULE__, fn v ->
			v
		end)
	end
	def set(x) do
		Agent.update(__MODULE__, fn v ->
			x
		end)
	end
end
defmodule Src do
	use Agent
	def start_link() do
		Agent.start_link(fn -> 
            ""
		end, name: __MODULE__)
	end
	def set(x) do
		Agent.update(__MODULE__, fn v ->
	        x
		end)
	end
	def get() do
		Agent.get(__MODULE__, fn v ->
			v
		end)
	end
	def getn(n) do
		Agent.get(__MODULE__, fn v ->
	    	Enum.at(String.split(v, "\n", trim: true), n - 1)
	    end)
    end
    def getl("end") do
        0
    end
	def getl(a) do
		Agent.get(__MODULE__, fn v ->
            Enum.reduce(String.split(v, "\n", trim: true), 1, fn l, n ->
	    	    if String.starts_with?(l, a) do
	    	        Va.set(n)
	    	    end
	    	    n = n + 1
	        end)
	        Va.get - 1
	    end)
    end
end
defmodule Main do
    def val(nil) do
        0
    end
    def val(s) do
        if String.starts_with?(s, "'") do
            String.at(s, 1)
            |> String.to_charlist
            |> List.first
        else
            String.to_integer(s)
        end
    end
    def add(n) do
	    IO.puts "rom[#{n}] <= 12'hf_00;"
	end
	def sub(n) do
	    IO.puts "rom[#{n}] <= 12'hf_01;"
	end
	def mul(n) do
	    IO.puts "rom[#{n}] <= 12'hf_02;"
	end
	def div(n) do
	    IO.puts "rom[#{n}] <= 12'hf_03;"
	end
	def rem(n) do
	    IO.puts "rom[#{n}] <= 12'hf_03;"
	end
	def eq(n) do
	    IO.puts "rom[#{n}] <= 12'hf_03;"
	end
	def dup(n) do
	    IO.puts "rom[#{n}] <= 12'h8_00;"
	end
	def drop(n) do
	    IO.puts "rom[#{n}] <= 12'h9_00;"
	end
	def gt(n) do
	    IO.puts "rom[#{n}] <= 12'hf_06;"
	end
	def out3(n) do
	    IO.puts "rom[#{n}] <= 12'h5_03;"
	end
	def out2(n) do
	    IO.puts "rom[#{n}] <= 12'h5_02;"
	end
	def out1(n) do
	    IO.puts "rom[#{n}] <= 12'h5_01;"
	end
	def out(n) do
	    IO.puts "rom[#{n}] <= 12'h5_00;"
	end
	def push(n, s) do
	    i = val(s)
	    j = Integer.floor_div(i, 16)
	    i = rem(i, 16)
	    i = Integer.to_string(i, 16)
	    j = Integer.to_string(j, 16)
	    IO.puts "rom[#{n}] <= 12'h2_#{j}#{i};"
	end	
	def if_(n, s) do
	    i = Src.getl(s)
	    j = Integer.floor_div(i, 16)
	    i = rem(i, 16)
	    i = Integer.to_string(i, 16)
	    j = Integer.to_string(j, 16)
	    IO.puts "rom[#{n}] <= 12'h6_#{j}#{i};"
	end
	def jmp(n, s) do
	    i = Src.getl(s)
	    j = Integer.floor_div(i, 16)
	    i = rem(i, 16)
	    i = Integer.to_string(i, 16)
	    j = Integer.to_string(j, 16)
	    IO.puts "rom[#{n}] <= 12'h1_#{j}#{i};"
	end
	def set(n, s) do
	    cond do
	    s == "a" ->
	        IO.puts "rom[#{n}] <= 12'h4_00;"
	    s == "b" ->
	        IO.puts "rom[#{n}] <= 12'h4_01;"
	    s == "c" ->
	        IO.puts "rom[#{n}] <= 12'h4_02;"
	    end
	end
	def get(n, s) do
	    cond do
	    s == "a" ->
	        IO.puts "rom[#{n}] <= 12'h3_00;"
	    s == "b" ->
	        IO.puts "rom[#{n}] <= 12'h3_01;"
	    s == "c" ->
	        IO.puts "rom[#{n}] <= 12'h3_02;"
	    end
	end
    def asm(str) do
        Enum.reduce(String.split(str, "\n"), 0, fn st, n ->
            IO.puts "//#{st}"
            s = String.split(st, "  ")
            cond do
	        Enum.at(s, 1) == "+" ->
		        add(n)
    	    Enum.at(s, 1) == "-" ->
	    	    sub(n)
	        Enum.at(s, 1) == "*" ->
		        mul(n)
    	    Enum.at(s, 1) == "/" ->
	    	    div(n)
    	    Enum.at(s, 1) == "%" ->
	    	    rem(n)
    	    Enum.at(s, 1) == "=" ->
	    	    eq(n)
    	    Enum.at(s, 1) == "out3" ->
	    	    out3(n)
    	    Enum.at(s, 1) == "out2" ->
	    	    out2(n)
    	    Enum.at(s, 1) == "out1" ->
	    	    out1(n)
    	    Enum.at(s, 1) == "out" ->
	    	    out(n)
	        Enum.at(s, 1) == "dup" ->
		        dup(n)
    	    Enum.at(s, 1) == "drop" ->
	    	    drop(n)
	        Enum.at(s, 1) == ">" ->
		        gt(n)
	        Enum.at(s, 1) == "jmp" ->
		        jmp(n, Enum.at(s, 2))
	        Enum.at(s, 1) == "if" ->
		        if_(n, Enum.at(s, 2))
	        Enum.at(s, 1) == "set" ->
		        set(n, Enum.at(s, 2))
    	    Enum.at(s, 1) == "get" ->
	    	    get(n, Enum.at(s, 2))
    	    true ->
                push(n, Enum.at(s, 1))
            end
            n = n + 1
        end)
    end
    def start(str) do
        Src.set(str)
        asm(str)
    end
end

Va.start_link
Src.start_link

str = """
  0
  set  a
loop  get  a
  1
  +
  set  a
  get  a
  15
  %
  0
  =
  if  skip2  
  get  a
  5
  %
  0
  =
  if  skip1
  get  a
  3
  %
  0
  =
  if  skip0
  get  a
  out3
  out2
  out1
  drop
  jmp  skip3
skip0  'F'
  out
  'i'
  out
  'z'
  out
  'z'
  out
  jmp  skip3
skip1  'B'
  out
  'u'
  out
  'z'
  out
  'z'
  out
  jmp  skip3
skip2  'F'
  out
  'i'
  out
  'z'
  out
  'z'
  out
  jmp  skip1
skip3  ' '
  out
  100
  get  a
  >
  if  loop
lup  jmp  lup
"""
Main.start(str)


```

# 実行結果

```



 
//  0
rom[0] <= 12'h2_00;
//  set  a
rom[1] <= 12'h4_00;
//loop  get  a
rom[2] <= 12'h3_00;
//  1
rom[3] <= 12'h2_01;
//  +
rom[4] <= 12'hf_00;
//  set  a
rom[5] <= 12'h4_00;
//  get  a
rom[6] <= 12'h3_00;
//  15
rom[7] <= 12'h2_0F;
//  %
rom[8] <= 12'hf_03;
//  0
rom[9] <= 12'h2_00;
//  =
rom[10] <= 12'hf_03;
//  if  skip2  
rom[11] <= 12'h6_30;
//  get  a
rom[12] <= 12'h3_00;
//  5
rom[13] <= 12'h2_05;
//  %
rom[14] <= 12'hf_03;
//  0
rom[15] <= 12'h2_00;
//  =
rom[16] <= 12'hf_03;
//  if  skip1
rom[17] <= 12'h6_27;
//  get  a
rom[18] <= 12'h3_00;
//  3
rom[19] <= 12'h2_03;
//  %
rom[20] <= 12'hf_03;
//  0
rom[21] <= 12'h2_00;
//  =
rom[22] <= 12'hf_03;
//  if  skip0
rom[23] <= 12'h6_1E;
//  get  a
rom[24] <= 12'h3_00;
//  out3
rom[25] <= 12'h5_03;
//  out2
rom[26] <= 12'h5_02;
//  out1
rom[27] <= 12'h5_01;
//  drop
rom[28] <= 12'h9_00;
//  jmp  skip3
rom[29] <= 12'h1_39;
//skip0  'F'
rom[30] <= 12'h2_46;
//  out
rom[31] <= 12'h5_00;
//  'i'
rom[32] <= 12'h2_69;
//  out
rom[33] <= 12'h5_00;
//  'z'
rom[34] <= 12'h2_7A;
//  out
rom[35] <= 12'h5_00;
//  'z'
rom[36] <= 12'h2_7A;
//  out
rom[37] <= 12'h5_00;
//  jmp  skip3
rom[38] <= 12'h1_39;
//skip1  'B'
rom[39] <= 12'h2_42;
//  out
rom[40] <= 12'h5_00;
//  'u'
rom[41] <= 12'h2_75;
//  out
rom[42] <= 12'h5_00;
//  'z'
rom[43] <= 12'h2_7A;
//  out
rom[44] <= 12'h5_00;
//  'z'
rom[45] <= 12'h2_7A;
//  out
rom[46] <= 12'h5_00;
//  jmp  skip3
rom[47] <= 12'h1_39;
//skip2  'F'
rom[48] <= 12'h2_46;
//  out
rom[49] <= 12'h5_00;
//  'i'
rom[50] <= 12'h2_69;
//  out
rom[51] <= 12'h5_00;
//  'z'
rom[52] <= 12'h2_7A;
//  out
rom[53] <= 12'h5_00;
//  'z'
rom[54] <= 12'h2_7A;
//  out
rom[55] <= 12'h5_00;
//  jmp  skip1
rom[56] <= 12'h1_27;
//skip3  ' '
rom[57] <= 12'h2_20;
//  out
rom[58] <= 12'h5_00;
//  100
rom[59] <= 12'h2_64;
//  get  a
rom[60] <= 12'h3_00;
//  >
rom[61] <= 12'hf_06;
//  if  loop
rom[62] <= 12'h6_02;
//lup  jmp  lup
rom[63] <= 12'h1_3F;
//
rom[64] <= 12'h2_00;
```

# 成果物

https://paiza.io/projects/eb_7QZiBQ6dBjhORpdYbHQ

以上。