Intcode assembler: allow data label values to be expressions

This commit is contained in:
Shadowfacts 2019-12-08 23:05:04 -05:00
parent a096774fa8
commit 431af67bb1
Signed by: shadowfacts
GPG Key ID: 94A5AB95422746E5
2 changed files with 40 additions and 24 deletions

View File

@ -63,7 +63,7 @@ defmodule Day5 do
])
end
def run_cli(memory) do
def run_cli(memory, opts \\ []) do
parent = self()
proc =
@ -71,23 +71,33 @@ defmodule Day5 do
run(memory, parent)
end)
Process.monitor(proc)
handle_cli_messages(proc)
handle_cli_messages(proc, opts)
end
def handle_cli_messages(proc) do
def handle_cli_messages(proc, opts) do
receive do
{:DOWN, _, _, _, _} ->
IO.puts("Exited")
{:halt, _, memory} ->
if Keyword.get(opts, :memory, false) do
memory
else
:ok
end
{:ok, _, memory} ->
if Keyword.get(opts, :memory, false) do
memory
else
:ok
end
{:in, _} ->
res = IO.gets("intcode> ") |> String.trim() |> String.to_integer()
send(proc, {:in, res})
handle_cli_messages(proc)
handle_cli_messages(proc, opts)
{:out, _, out} ->
IO.puts("Output: #{out}")
handle_cli_messages(proc)
handle_cli_messages(proc, opts)
end
end

View File

@ -18,20 +18,15 @@ defmodule Assembler do
|> ignore(ascii_char([?:]))
|> ignore(repeat(ascii_char([?\s])))
data_label =
label
|> choice([
integer(min: 1),
ignore(ascii_char([?-]))
|> integer(min: 1)
|> tag(:neg)
])
|> tag(:data_label)
param =
optional(ignore(ascii_string([?\s], min: 1)))
|> ascii_string([{:not, ?,}], min: 1)
data_label =
label
|> concat(param)
|> tag(:data_label)
instruction =
ignore(ascii_string([?\s, ?\t], min: 0))
|> ascii_string([?a..?z], min: 1)
@ -63,7 +58,13 @@ defmodule Assembler do
|> Enum.with_index()
|> Enum.map(fn
{{:expr, expr}, index} ->
expr_tokens = if is_binary(expr), do: ExpressionEvaluator.parse(expr), else: expr
expr_tokens =
if is_binary(expr) do
{:ok, tokens, _, _, _, _} = ExpressionEvaluator.parse(expr)
tokens
else
expr
end
ExpressionEvaluator.do_eval(expr_tokens, fn
"_self" -> index
@ -134,11 +135,7 @@ defmodule Assembler do
end
def assemble_line([data_label: [name, value]], {memory, labels}) do
value =
case value do
{:neg, [val]} -> -val
val when is_integer(val) -> val
end
value = {:expr, value}
{
[value | memory],
@ -197,6 +194,15 @@ defmodule Assembler do
[99 | memory]
end
def assemble_insn(["data" | data], memory) do
data =
data
|> Enum.map(&String.to_integer/1)
|> Enum.reverse()
data ++ memory
end
# macros
assemble_macro ["mov", src, dest],
"""