概要
wsl(wsl2じゃない)で、elixirやってみた。
練習問題やってみた。
練習問題
Livebookで、俺言語の九九を実行するインタープリターを書け。
サンプルコード
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=1
30 ?=a*b
40 a=a+1
50 #=a<10*30
60 b=b+1
70 a=1
80 r
90 #=b<10*30
100 #=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)
実行結果
1 2 3 4 5 6 7 8 9
2 4 6 8 10 12 14 16 18
3 6 9 12 15 18 21 24 27
4 8 12 16 20 24 28 32 36
5 10 15 20 25 30 35 40 45
6 12 18 24 30 36 42 48 54
7 14 21 28 35 42 49 56 63
8 16 24 32 40 48 56 64 72
9 18 27 36 45 54 63 72 81
以上。