Efene is a programming language that runs on the Erlang virtual machine.
The idea is to provide an alternative syntax for Erlang that is more comfortable for people coming from languages like Java, C, C++, C#, Javascript, Ruby, or Python.
Efene comes in two language dialects: Efene (Ruby style) and Ifene (Python style).
The language is almost 100% compatible with Erlang (and soon will be at 100%), and your Efene programs can easily interact with regular Erlang programs, or vice-versa. The compiler can translate an Efene source file into readable Erlang, or compile it directly to BEAM bytecode.
# public will allow accessing this function from other modules
@public
run() {
io.format("hello world!")
}
fnc hello.fn
fnc -r hello run
# public will allow accessing this function from other modules
@public
run()
io.format("hello world!")
fnc hello.ifn
fnc -r hello run
# if statement
compare = fn (A, B) {
if A < B {
lt
}
else if A > B {
gt
}
else {
eq
}
}
# switch statement and multiline expressions
compare_to_string = fn (Result) {
switch Result {
case lt {
"lower than"
}
case gt {
"greater than"
}
case eq {
"equal to"
}
else {
"invalid value '" ++
atom_to_list(Result) ++
"'"
}
}
}
# multiple function definition and guards
compare_to_string_guards = fn (Result) when Result == lt {
"lower than"
}
fn (Result) when Result == gt {
"greater than"
}
fn (Result) when Result == eq {
"equal to"
}
fn (Result) {
"invalid value '" ++
atom_to_list(Result) ++
"'"
}
# try/catch expression and tuples
fail = fn (Fun) {
try {
Fun()
}
catch error Error {
("error", Error)
}
catch throw Throw {
("throw", Throw)
}
catch Type Desc {
(atom_to_list(Type), Desc)
}
}
# pattern match
do = fn (add, A, B) {
A + B
}
fn (mul, A, B) {
A * B
}
fn (div, _A, 0) {
invalid_division
}
fn (div, A, B) {
A / B
}
# main function, made public to access it outside the module
@public
run = fn () {
# lambda functions
Print = fn (Expr) { io.format("~p~n", [Expr]) }
Print(compare(1, 2))
Print(compare(2, 1))
Print(compare(2, 2))
Print(compare_to_string(lt))
Print(compare_to_string(gt))
Print(compare_to_string(eq))
Print(compare_to_string(this_is_an_invalid_value))
Print(compare_to_string_guards(lt))
Print(compare_to_string_guards(gt))
Print(compare_to_string_guards(eq))
Print(compare_to_string_guards(this_is_an_invalid_value))
# call fail with a function that will fail in different ways
Print(fail(fn () { throw("throw here") }))
Print(fail(fn () { erlang.error("error here") }))
Print(fail(fn () { exit("exit here") }))
Print(do(add, 10, 2))
Print(do(mul, 10, 2))
Print(do(div, 10, 2))
Print(do(div, 1, 0))
}
fnc demo.fn
fnc -r demo run
# if statement
compare = fn (A, B)
if A < B
lt
else if A > B
gt
else
eq
# switch statement and multiline expressions
compare_to_string = fn (Result)
switch Result
case lt
"lower than"
case gt
"greater than"
case eq
"equal to"
else
"invalid value '" ++
atom_to_list(Result) ++
"'"
# multiple function definition and guards
compare_to_string_guards = fn (Result) when Result == lt
"lower than"
fn (Result) when Result == gt
"greater than"
fn (Result) when Result == eq
"equal to"
fn (Result)
"invalid value '" ++
atom_to_list(Result) ++
"'"
# try/catch expression and tuples
fail = fn (Fun)
try
Fun()
catch error Error
("error", Error)
catch throw Throw
("throw", Throw)
catch Type Desc
(atom_to_list(Type), Desc)
# pattern match
do = fn (add, A, B)
A + B
fn (mul, A, B)
A * B
fn (div, _A, 0)
invalid_division
fn (div, A, B)
A / B
# main function, made public to access it outside the module
@public
run = fn ()
# lambda functions
Print = fn (Expr) { io.format("~p~n", [Expr]) }
Print(compare(1, 2))
Print(compare(2, 1))
Print(compare(2, 2))
Print(compare_to_string(lt))
Print(compare_to_string(gt))
Print(compare_to_string(eq))
Print(compare_to_string(this_is_an_invalid_value))
Print(compare_to_string_guards(lt))
Print(compare_to_string_guards(gt))
Print(compare_to_string_guards(eq))
Print(compare_to_string_guards(this_is_an_invalid_value))
# call fail with a function that will fail in different ways
Print(fail(fn () { throw("throw here") }))
Print(fail(fn () { erlang.error("error here") }))
Print(fail(fn () { exit("exit here") }))
Print(do(add, 10, 2))
Print(do(mul, 10, 2))
Print(do(div, 10, 2))
Print(do(div, 1, 0))
fnc demo.ifn
fnc -r demo run
You can see more examples in the examples dir.
You will need a recent Erlang/OTP release. If you are on a Debian-based distribution, you can install it with apt-get:
$ sudo apt-get erlang erlang-parsetools
Create a directory for your new project, and download rebar, an Erlang build tool:
$ mkdir myapp
$ cd myapp
$ wget http://bitbucket.org/basho/rebar/downloads/rebar; chmod u+x rebar
Create a file named rebar.config
in the myapp directory:
{deps, [
{efene, ".*",
{git, "git://github.com/marianoguerra/efene.git", "master"}
},
{rebar_efene_plugin, ".*",
{git, "git://github.com/DavidMikeSimon/rebar_efene_plugin.git", "stable"}
}
]}.
{plugins, [ rebar_efene_plugin ]}.
{plugin_dir, "deps/rebar_efene_plugin/src"}.
Create a directory named src
, and within it create a myapp.app.src
file:
{application, myapp, [
{description, "My first app ever"},
{vsn, "0.0.1"}
]}.
Finally, go ahead and write a simple Efene (.fn) or Ifene (.ifn) file in the src directory. Then tell rebar to download your dependencies and compile everything:
$ rebar get-deps
$ rebar compile
And there you go! You now have BEAM files in the ebin
directory, just
as with a regular Erlang project; you can load them and run functions
from them using the Erlang shell.
After you make more changes to your source code, just run the rebar compile command again:
$ rebar compile
To build efene by itself, rather than as a dependency for your project:
$ git clone git://github.com/marianoguerra/efene.git
$ cd efene
$ ./build.sh
This will also create an executable bin/fnc
, which functions similarly to erl
and erlc
.
Additionally, you can build and run the examples:
$ cd examples
$ ./build.sh
$ ./run.sh
A mailing-list is available at librelist, just send a mail to [email protected] to subscribe.
To create the Efene compiler you will need a C compiler like GCC or LLVM-GCC, and any recent Erlang/OTP release.
- Erlang
- (GCC or LLVM-GCC)