Skip to content
Permalink
Browse files

Reenable sequence init and sequence complete logs

Sort of a hack, but store some metadata about a sequence in the AST
format, and if it exists, log it
  • Loading branch information...
ConnorRigby committed Jul 9, 2019
1 parent 351f90e commit c2ad392a254e44d7b9bcb17cd9c6981ca32ef86c
@@ -19,10 +19,11 @@ defmodule FarmbotCeleryScript.AST do
kind: kind,
args: args,
body: body,
comment: binary
comment: binary,
meta: any()
}

defstruct [:args, :body, :kind, :comment]
defstruct [:args, :body, :kind, :comment, :meta]

@doc "Decode a base map into CeleryScript AST."
@spec decode(t() | map | [t() | map]) :: t()
@@ -41,12 +42,14 @@ defmodule FarmbotCeleryScript.AST do
args = thing["args"] || thing[:args] || raise("Bad ast: #{inspect(thing)}")
body = thing["body"] || thing[:body] || []
comment = thing["comment"] || thing[:comment] || nil
meta = thing["meta"] || thing[:meta] || nil

%AST{
kind: String.to_atom(to_string(kind)),
args: decode_args(args),
body: decode_body(body),
comment: comment
comment: comment,
meta: meta
}
end

@@ -74,12 +77,13 @@ defmodule FarmbotCeleryScript.AST do
end

@spec new(atom, map, [map]) :: t()
def new(kind, args, body, comment \\ nil) when is_map(args) and is_list(body) do
def new(kind, args, body, comment \\ nil, meta \\ nil) when is_map(args) and is_list(body) do
%AST{
kind: String.to_atom(to_string(kind)),
args: args,
body: body,
comment: comment
comment: comment,
meta: meta
}
|> decode()
end
@@ -86,7 +86,7 @@ defmodule FarmbotCeleryScript.Compiler do
# is added.

# Compiles a `sequence` into an Elixir `fn`.
compile :sequence, %{locals: %{body: params}}, block do
compile :sequence, %{locals: %{body: params}}, block, meta do
# Sort the args.body into two arrays.
# The `params` side gets turned into
# a keyword list. These `params` are passed in from a previous sequence.
@@ -104,8 +104,11 @@ defmodule FarmbotCeleryScript.Compiler do
end)

{:__block__, [], assignments} = compile_block(body)
sequence_name = meta[:sequence_name]
steps = compile_block(block) |> decompose_block_to_steps()

steps = add_sequence_init_and_complete_logs(steps, sequence_name)

quote location: :keep do
fn params ->
# This quiets a compiler warning if there are no variables in this block
@@ -263,8 +266,6 @@ defmodule FarmbotCeleryScript.Compiler do
# We have to lookup the sequence by it's id.
case FarmbotCeleryScript.SysCalls.get_sequence(unquote(id)) do
%FarmbotCeleryScript.AST{} = ast ->
# TODO(Connor) - figure out a way of inserting the sequence name here
FarmbotCeleryScript.SysCalls.log("Executing Sequence")
# compile the ast
env = unquote(compile_params_to_function_args(parameter_applications))
FarmbotCeleryScript.Compiler.compile(ast, env)
@@ -874,6 +875,32 @@ defmodule FarmbotCeleryScript.Compiler do
end)
end

defp add_sequence_init_and_complete_logs(steps, sequence_name) when is_binary(sequence_name) do
# This looks really weird because of the logs before and
# after the compiled steps
List.flatten([
quote do
fn ->
FarmbotCeleryScript.SysCalls.sequence_init_log(
"Sequence #{unquote(sequence_name)} init"
)
end
end,
steps,
quote do
fn ->
FarmbotCeleryScript.SysCalls.sequence_complete_log(
"Sequence #{unquote(sequence_name)} complete"
)
end
end
])
end

defp add_sequence_init_and_complete_logs(steps, _) do
steps
end

# defp print_compiled_code(compiled) do
# compiled
# |> Macro.to_string()
@@ -74,13 +74,29 @@ defmodule FarmbotCeleryScript.Compiler.Tools do
end

@doc false
defmacro compile(kind, args_pattern, body_patterrn, do: block) when is_atom(kind) do
defmacro compile(kind, args_pattern, body_pattern, do: block) when is_atom(kind) do
quote do
@kinds unquote(to_string(kind))
def compile_ast(%AST{
kind: unquote(kind),
args: unquote(args_pattern),
body: unquote(body_patterrn)
body: unquote(body_pattern)
}) do
unquote(block)
end
end
end

@doc false
defmacro compile(kind, args_pattern, body_pattern, meta_pattern, do: block)
when is_atom(kind) do
quote do
@kinds unquote(to_string(kind))
def compile_ast(%AST{
kind: unquote(kind),
args: unquote(args_pattern),
body: unquote(body_pattern),
meta: unquote(meta_pattern)
}) do
unquote(block)
end
@@ -63,11 +63,21 @@ defmodule FarmbotCeleryScript.SysCalls do
@callback zero(axis) :: ok_or_error

@callback log(message :: String.t()) :: any()
@callback sequence_init_log(message :: String.t()) :: any()
@callback sequence_complete_log(message :: String.t()) :: any()

def log(sys_calls \\ @sys_calls, message) when is_binary(message) do
apply(sys_calls, :log, [message])
end

def sequence_init_log(sys_calls \\ @sys_calls, message) when is_binary(message) do
apply(sys_calls, :sequence_init_log, [message])
end

def sequence_complete_log(sys_calls \\ @sys_calls, message) when is_binary(message) do
apply(sys_calls, :sequence_complete_log, [message])
end

def calibrate(sys_calls \\ @sys_calls, axis) when axis in ["x", "y", "z"] do
ok_or_error(sys_calls, :calibrate, [axis])
end
@@ -9,6 +9,12 @@ defmodule FarmbotCeleryScript.SysCalls.Stubs do
@impl true
def log(message), do: error(:log, [message])

@impl true
def sequence_init_log(message), do: error(:log, [message])

@impl true
def sequence_complete_log(message), do: error(:log, [message])

@impl true
def calibrate(axis), do: error(:calibrate, [axis])

@@ -133,7 +133,6 @@ defmodule FarmbotCeleryScript.CompilerTest do
strip_nl("""
case(FarmbotCeleryScript.SysCalls.get_sequence(100)) do
%FarmbotCeleryScript.AST{} = ast ->
FarmbotCeleryScript.SysCalls.log("Executing Sequence")
env = []
FarmbotCeleryScript.Compiler.compile(ast, env)
@@ -60,6 +60,26 @@ defmodule FarmbotOS.SysCalls do
end
end

@impl true
def sequence_init_log(message) do
if FarmbotCore.Asset.fbos_config(:sequence_init_log) do
FarmbotCore.Logger.info(2, message)
:ok
else
:ok
end
end

@impl true
def sequence_complete_log(message) do
if FarmbotCore.Asset.fbos_config(:sequence_complete_log) do
FarmbotCore.Logger.info(2, message)
:ok
else
:ok
end
end

@impl true
def reboot do
FarmbotOS.System.reboot("Reboot requested by Sequence or frontend")
@@ -482,8 +502,11 @@ defmodule FarmbotOS.SysCalls do
@impl true
def get_sequence(id) do
case Asset.get_sequence(id) do
nil -> {:error, "sequence not found"}
%{} = sequence -> AST.decode(sequence)
nil ->
{:error, "sequence not found"}

%{} = sequence ->
%{AST.decode(sequence) | meta: %{sequence_name: sequence.name}}
end
end

@@ -46,6 +46,16 @@ defmodule Farmbot.TestSupport.CeleryScript.TestSysCalls do
:ok
end

@impl true
def sequence_init_log(_message) do
:ok
end

@impl true
def sequence_complete_log(_message) do
:ok
end

@impl true
def coordinate(x, y, z) do
%{x: x, y: y, z: z}

0 comments on commit c2ad392

Please sign in to comment.
You can’t perform that action at this time.