efene programming language

Learning some efene, erlang and erlang internals

Let’s play a little with efene and in the meantime learn some erlang and erlang internals for free.

Let’s build a simple division function that will return the result of the division between A and B but return the atom error if B is 0

divide = fn (_A, 0) {
        error
} (A, B) {
        A / B
}

run = fn () {
        Helper = fn (A, B) {
                io.format("~p/~p=~p~n", [A, B, divide(A, B)])
        }

        Helper(10, 2)   
        Helper(10, 3)   
        Helper(5, 0)
}

the code should be simple to understand but I will explain it here anyway

the first line creates a function called divide that has two definitions, the first will be called when the second argument matches 0 (that’s called pattern matching) and will just return the error atom.

In case that the first definition didn’t matched then a more generic one is defined that returns the division between A and B.

Then we define the run function that will act as our main function, in that function we define a helper function and store it in the Helper variable, this function will just pretty print some calls to the divide function.

Then we call the Helper function with some values to test our implementation.

Now let’s build our example:

mariano@ganesha:~/Proyectos/efene/examples$ ../bin/fnc division.fn
compiling /home/mariano/Proyectos/efene/examples/division.fn

all went fine, now let’s run it:

mariano@ganesha:~/Proyectos/efene/examples$ ../bin/fn division run
10/2=5.0
10/3=3.3333333333333335
5/0=error

what we expected.

but how about learning erlang and erlang internals? well let’s translate that example into erlang:

mariano@ganesha:~/Proyectos/efene/examples$ ../bin/fnc -t erl division.fn

-module(division).

-compile(export_all).

divide(_A, 0) -> error;
divide(A, B) -> A / B.

run() ->
    Helper = fun (A, B) ->
                     io:format("~p/~p=~p~n", [A, B, divide(A, B)])
             end,
    Helper(10, 2),
    Helper(10, 3),
    Helper(5, 0).

that’s some readable code if you ask me ;)

did you ever wondered how is an erlang program represented internally? well, for development purposes and just to give people more insights about how erlang works I added two options to the fnc program -t ast and -t erl2ast the first one receives an efene program as input and prints the abstract syntax tree that is used to generate the bytecode, the second option receives an erlang program and does the same, this allows me to compare the ast of two identical programs one in efene and one in erlang to look for differences.

let’s see how our program looks like

mariano@ganesha:~/Proyectos/efene/examples$ ../bin/fnc -t ast division.fn

[{attribute,1,module,division},
 {attribute,1,compile,export_all},
 {function,2,divide,2,
  [{clause,2,[{var,2,'_A'},{integer,2,0}],[],[{atom,3,error}]},
   {clause,4,
    [{var,4,'A'},{var,4,'B'}],
    [],
    [{op,5,'/',{var,5,'A'},{var,5,'B'}}]}]},
 {function,8,run,0,
  [{clause,8,[],[],
    [{match,9,
      {var,9,'Helper'},
      {'fun',9,
       {clauses,
        [{clause,9,
          [{var,9,'A'},{var,9,'B'}],
          [],
          [{call,10,
            {remote,10,{atom,10,io},{atom,10,format}},
            [{string,10,"~p/~p=~p~n"},
             {cons,10,
              {var,10,'A'},
              {cons,10,
               {var,10,'B'},
               {cons,10,
                {call,10,{atom,10,divide},[{var,10,'A'},{var,10,'B'}]},
                {nil,10}}}}]}]}]}}},
     {call,13,{var,13,'Helper'},[{integer,13,10},{integer,13,2}]},
     {call,14,{var,14,'Helper'},[{integer,14,10},{integer,14,3}]},
     {call,15,{var,15,'Helper'},[{integer,15,5},{integer,15,0}]}]}]}]

you can start with simple programs and learn how all works with fnc :)


  1. efene posted this
To Tumblr, Love Metalab