A simple and safe script language for the BEAM.
https://hex.pm/packages/abacus
This language was written to be so simple anyone that has seen mathematical terms before can write Abacus code.
For example, adding a
and b
is as simple as a + b
.
It was also designed to be as safe as possible, allowing you to expose the compiler to a web frontend.
A lot of features make this language easier to use and less confusing than regular Elixir (to laymen) with a whitelist:
Several measures have been or can be taken to allow safe execution of untrusted code.
:var0
, var1
, ..., varn
where n is the amount of distinct variable names in a scriptmax_heap_size: %{size: 1_000_000, kill: true}
in process options)While one-off executions can be evaluated using interpretation (through Code.eval_quoted
), the real power comes from the Abacus parser returning valid Elixir AST.
This means that the AST can be compiled to BEAM bytecode for performant execution. The performance should be the same as normal Elixir code.
Abacus.eval(expression, scope)
Parses and evaluates the given expression. Variables can be supplied as a map of
binaries in the scope
.
iex> Abacus.eval("1 + 1")
{:ok, 2}
iex> Abacus.eval("sin(floor(3 + 2.5)) / 3")
{:ok, -0.3196414248877128}
iex> Abacus.eval("a * b", %{"a" => 10, "b" => 10})
{:ok, 100}
Abacus.parse(expression)
Parses the expression and returns the syntax tree.
The syntax tree is in quoted elixir. This means that you can use this to compile it into BEAM bytecode for performant execution.
An incomplete list of supported and planned features
+
, -
, *
, /
, ^
)!
)|
, &
, >>
, <<
, ~
, |^
(xor))&&
, ||
, not
)==
, !=
, >
, <
, >=
, <=
)condition ? if_true : if_false
)true
and false
)nil
)sin
, cos
, tan
)ceil
, floor
, round
)(x, y) => {x + y}
){statement \n statement}
)map
, reduce
, filter
, ...)Add abacus
to your list of dependencies in mix.exs
:
def deps do
[{:abacus, "~> 0.4.2"}]
end
Ensure abacus
is started before your application:
def application do
[applications: [:abacus]]
end