diff --git a/ovo/lib/ovo/builtins.ex b/ovo/lib/ovo/builtins.ex index 53cac5e..69e2105 100644 --- a/ovo/lib/ovo/builtins.ex +++ b/ovo/lib/ovo/builtins.ex @@ -155,10 +155,26 @@ defmodule Ovo.Builtins do end end + defp get_host do + case "#{Node.self()}" |> String.split("@") do + [_, b] -> b + _ -> "nohost" + end + end + defp invoke(nodes, env) do case map_nodes(nodes, env) do [%{kind: :string, value: hash}, %{kind: :list, nodes: ns}] -> - Ovo.Registry.run_chain([hash], ns) + {h, host} = + case String.split(hash, "@") do + [h] -> {h, Node.self()} + [h, node] -> {h, :"#{node}@#{get_host()}"} + [h, node, host] -> {h, :"#{node}@#{host}"} + end + + :erpc.call(host, fn -> + Ovo.Registry.run_chain([h], ns) + end) _ -> :error diff --git a/ovo/lib/ovo/registry.ex b/ovo/lib/ovo/registry.ex index c82b67c..50e1ee3 100644 --- a/ovo/lib/ovo/registry.ex +++ b/ovo/lib/ovo/registry.ex @@ -67,7 +67,7 @@ defmodule Ovo.Registry do update_in( state, [Access.key!(hash), Access.key!(:metadata), Access.key!(:args), Access.at!(position)], - fn _ -> arg end + fn {k, _v} -> {k, arg} end ) end) end diff --git a/ovo_playground/assets/js/app.js b/ovo_playground/assets/js/app.js index df0cdd9..f580df8 100644 --- a/ovo_playground/assets/js/app.js +++ b/ovo_playground/assets/js/app.js @@ -23,13 +23,74 @@ import {LiveSocket} from "phoenix_live_view" import topbar from "../vendor/topbar" let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content") -let liveSocket = new LiveSocket("/live", Socket, {params: {_csrf_token: csrfToken}}) +let Hooks = { + 'watch_input': { + mounted() { + this.el.addEventListener('input', (e) => { + this.pushEvent(this.el.getAttribute('data-event'), {value: e.target.value}); + }); + }, + }, + 'watch_arg': { + mounted() { + this.el.addEventListener('input', (e) => { + this.pushEvent(this.el.getAttribute('data-event'), {index: this.el.getAttribute('data-index'), value: e.target.value}); + }); + }, + }, + 'change_code': { + mounted() { + this.el.addEventListener('input', (e) => { + this.pushEvent('code_change', {value: e.target.value}); + }); + }, + }, + "update_chain_arg": { + mounted() { + this.el.addEventListener('input', (e) => { + this.pushEvent('update_chain_arg', { + chain_index: this.el.getAttribute('data-chain_index'), + arg_index: this.el.getAttribute('data-arg_index'), + value: e.target.value, + }); + }); + }, + }, + "change_runner_arg": { + mounted() { + this.el.addEventListener('input', (e) => { + this.pushEvent('change_runner_arg', { + hash: this.el.getAttribute('data-hash'), + index: this.el.getAttribute('data-index'), + value: e.target.value, + }); + }); + }, + }, + "update_node": { + mounted() { + const kind = this.el.getAttribute('data-kind'); + const path = this.el.getAttribute('data-path'); + if (kind === 'bool') { + this.el.addEventListener('change', () => { + this.pushEvent('change_path', {path, value: this.el.checked}); + }); + } else { + this.el.addEventListener('change', () => { + this.pushEvent('change_path', {path, value: this.el.value}); + }); + } + } + }, +}; +let liveSocket = new LiveSocket("/live", Socket, {params: {_csrf_token: csrfToken}, hooks: Hooks}); // Show progress bar on live navigation and form submits topbar.config({barColors: {0: "#29d"}, shadowColor: "rgba(0, 0, 0, .3)"}) window.addEventListener("phx:page-loading-start", _info => topbar.show(300)) window.addEventListener("phx:page-loading-stop", _info => topbar.hide()) + // connect if there are any LiveViews on the page liveSocket.connect() diff --git a/ovo_playground/lib/ovo_playground.ex b/ovo_playground/lib/ovo_playground.ex index dfbd49e..4d724d1 100644 --- a/ovo_playground/lib/ovo_playground.ex +++ b/ovo_playground/lib/ovo_playground.ex @@ -1,6 +1,33 @@ defmodule OvoPlayground do @moduledoc false + def demo_setup do + case to_string(Node.self()) do + "bob@" <> _rest -> setup_bob() + "alice@" <> _rest -> setup_alice() + _ -> setup_bottles() + end + end + + def setup_bob do + Node.set_cookie(:ovo_demo) + Node.connect(:"alice@MacBook-Air-de-Lucas.local") + register_bob_examples() + end + + def setup_alice do + Node.set_cookie(:ovo_demo) + Node.connect(:"bob@MacBook-Air-de-Lucas.local") + register_alice_examples() + end + + def setup_bottles do + register_bottles_example + end + + def register_bob_examples do + end + @doc """ The classic "99 bottles" song example """ @@ -78,12 +105,12 @@ defmodule OvoPlayground do """ for {code, name, args} <- [ - {register, "register", ["0"]}, - {filler, "filler", ["100"]}, - {join, "joiner", ["[\"a\"]", "\" \""]}, - {last_bottle, "last_bottle", ["1"]}, - {two_bottles, "two_bottles", ["1"]}, - {normal_bottles, "bottle", ["1"]}, + {register, "register", [{:text, "0"}]}, + {filler, "filler", [{:text, "100"}]}, + {join, "joiner", [{:text, "[\"a\"]"}, {:text, "\" \""}]}, + {last_bottle, "last_bottle", [{:text, "1"}]}, + {two_bottles, "two_bottles", [{:text, "1"}]}, + {normal_bottles, "bottle", [{:text, "1"}]}, {full_song, "full_song", []} ] do Ovo.Runner.register(code, name, args) @@ -111,14 +138,8 @@ defmodule OvoPlayground do hex(hash) """ - # hashes to yfHDp - logger = """ - arg(0) - """ - for {code, name, args} <- [ - {logger, "logger", ["100"]}, - {legitimate_hash, "hash function", ["100"]} + {legitimate_hash, "hash function", [{:secret, "the quick brown fox"}]} ] do Ovo.Runner.register(code, name, args) end @@ -127,6 +148,11 @@ defmodule OvoPlayground do def register_alice_tricks do Ovo.Registry.remove_runner("Sj2py") + # hashes to yfHDp + logger = """ + arg(0) + """ + totally_legitimate_hash_function_nothing_to_see_here = """ len = length(arg(0)) ~~ = \\a -> @@ -155,8 +181,9 @@ defmodule OvoPlayground do """ for {code, name, args} <- [ + {logger, "logger", [{:text, "100"}]}, {totally_legitimate_hash_function_nothing_to_see_here, "hash", - ["\"the quick brown fox\""]} + [{:secret, "\"the quick brown fox\""}]} ] do Ovo.Runner.register(code, name, args) end diff --git a/ovo_playground/lib/ovo_playground/application.ex b/ovo_playground/lib/ovo_playground/application.ex index 5285226..3421181 100644 --- a/ovo_playground/lib/ovo_playground/application.ex +++ b/ovo_playground/lib/ovo_playground/application.ex @@ -22,7 +22,9 @@ defmodule OvoPlayground.Application do # See https://hexdocs.pm/elixir/Supervisor.html # for other strategies and supported options opts = [strategy: :one_for_one, name: OvoPlayground.Supervisor] - Supervisor.start_link(children, opts) + start_result = Supervisor.start_link(children, opts) + OvoPlayground.demo_setup() + start_result end # Tell Phoenix to update the endpoint configuration diff --git a/ovo_playground/lib/ovo_playground/transforms.ex b/ovo_playground/lib/ovo_playground/transforms.ex index 62de097..6fcad3c 100644 --- a/ovo_playground/lib/ovo_playground/transforms.ex +++ b/ovo_playground/lib/ovo_playground/transforms.ex @@ -1,4 +1,6 @@ defmodule OvoPlayground.Transforms do + alias Ovo.Ast + @moduledoc """ Transforms are functions that ultimately produce an Ovo.Ast, either from nothing, some input, an Ast, or combinations of these things. @@ -10,7 +12,13 @@ defmodule OvoPlayground.Transforms do add(val, 10) """ - defp produce(input) when is_binary(input), do: Ovo.tokenize(input) |> Ovo.parse() + defp produce(input) when is_binary(input) do + case Ovo.tokenize(input) |> Ovo.parse() do + {:ok, %{nodes: nodes}, []} -> nodes + _ -> [] + end + end + defp list([a]), do: [a] defp list(a), do: [a] defp nodes(%Ovo.Ast{nodes: nodes}), do: nodes @@ -24,8 +32,12 @@ defmodule OvoPlayground.Transforms do fun.(ast) end + def wrap_root(nodes) do + Ast.root(nodes) + end + def default() do - produce(@default_code) + Ovo.tokenize(@default_code) |> Ovo.parse() end def default_assignment() do diff --git a/ovo_playground/lib/ovo_playground_web/components/ovo/node.ex b/ovo_playground/lib/ovo_playground_web/components/ovo/node.ex index 3271c43..ac2db40 100644 --- a/ovo_playground/lib/ovo_playground_web/components/ovo/node.ex +++ b/ovo_playground/lib/ovo_playground_web/components/ovo/node.ex @@ -2,7 +2,7 @@ defmodule OvoPlaygroundWeb.Components.Ovo.Node do use Phoenix.Component alias OvoPlaygroundWeb.Components.Ovo.Ast import OvoPlaygroundWeb.CoreComponents, only: [icon: 1] - defp path_to_string(path), do: Enum.map_join(path |> List.flatten(), ",", & &1) + defp path_to_string(path), do: Enum.map_join(path |> List.flatten(), "_", & &1) attr(:node, Ovo.Ast, required: true) attr(:depth, :integer, required: true) @@ -11,7 +11,6 @@ defmodule OvoPlaygroundWeb.Components.Ovo.Node do def show_node(assigns) do ~H"""