Mariano Guerra
BEAM BA Meetup
October 2016
Mariano Guerra
Argentina
Stuttgart ~ 4 Years
Erlang, Clojure, Javascript, Python, Scala, Java
gh:marianoguerra/otl to follow each step as a commit
rebar3 new fn_escript name=otl cd otl rebar3 escriptize ./_build/default/bin/otl
Because reading absform or using erl_syntax is too much work :)
$ ./_build/default/bin/otl erl2ast examples/mymod.erl
{ok,[{attribute,1,file,{"examples/mymod.erl",1}},
{attribute,1,module,mymod},
{attribute,2,export,[{main,0}]},
{function,4,main,0,[{clause,4,[],[],[{atom,4,true}]}]},
{eof,5}]}$ ./_build/default/bin/otl erl2ast2erl examples/mymod.erl
-file("examples/mymod.erl", 1).
-module(mymod).
-export([main/0]).
main() -> true.$ ./_build/default/bin/otl erl2beam examples/mymod.erl .
{ok,[{module_name,mymod},{path,"./mymod.beam"}]}$ erl Erlang/OTP 18 [kernel-poll:false] Eshell V7.0 (abort with ^G) 1> mymod:main(). true 2> q(). ok
$ cat examples/trues.otl
true true true
$ ./_build/default/bin/otl lex examples/trues.otl
{ok,[{boolean,1,true},{boolean,1,true},{boolean,1,true}],2}$ ./_build/default/bin/otl ast examples/trues.otl
{ok,[{atom,1,true},{atom,1,true},{atom,1,true}]}$ ./_build/default/bin/otl mod examples/trues.otl mymod myfun
{ok,[{attribute,1,file,{"examples/trues.otl",1}},
{attribute,1,module,mymod},
{attribute,2,export,[{myfun,0}]},
{function,3,myfun,0,
[{clause,4,[],[],
[{atom,1,true},{atom,1,true},{atom,1,true}]}]}]}$ ./_build/default/bin/otl beam examples/trues.otl . mymod myfun
{ok,[{module_name,mymod},{path,"./mymod.beam"}]}$ ./_build/default/bin/otl erl examples/trues.otl mymod myfun
-file("examples/trues.otl", 1).
-module(mymod).
-export([myfun/0]).
myfun() -> true, true, true.rebar3 efene compile --format=erl
$ ./_build/default/bin/otl eval examples/trues.otl true
$ ./otl-shell
Erlang/OTP 18
otl shell (Ctrl+g and then q to quit, Ctrl+g for Job Control Mode)
>>> true
true
>>> true true
true
>>>
>>> false
error: {1,otl_lexer,{illegal,"f"}}
>>> ^G
User switch command
--> q$ ./otl-shell Erlang/OTP 18 otl shell (Ctrl+g and then q to quit, Ctrl+g for Job Control Mode) >>> 1 1 >>> 1 true true >>> 1 true 1111 1111 >>> ^G User switch command --> q
$ ./_build/default/bin/otl erl examples/one_true_language.otl one_true language
-file("examples/one_true_language.otl", 1).
-module(one_true).
-export([language/0]).
language() -> 1, true.We just created the one true language (TM)
$ ./otl-shell >>> false true 1 1 >>> 92 92 >>> 42 42
>>> 42 42 >>> 12.4 12.4 >>> true true >>> false false
true false 12 13.4
1 1 + 2 1 - 3 4 + 3 - 2 4 + 3 - 2 + 1 3 + true
1 2 * 3 2 * 3 / 4 2 * 3 / 4 % 5 1 + 2 * 3 - 4 / 5 + 6 % 7
1 -1 +1 -1 * +1 1 * -1 * +1
1 A = 1 1 = 1 1 = A A = A A = 2 - 1 B = A * 2 - 1
1 1 < 2 1 < 2 * 3 2 * 3 < 1 A = 2 * 3 < 4 > 12 A is 5
true true and false true or false true and false or true true and 1 is 0 true and 1 > 0 or 2 > 4
otl shell (Ctrl+g and then q to quit, Ctrl+g for Job Control Mode) >>> foo foo >>> bar bar >>> baz baz >>>
>>> 2 * (3 + 4) 14 >>> 2 * 3 + 4 10
>>> true true >>> false false >>> not true false >>> not false true >>> not other error: badarg
>>> [] []
Note
[] -> {nil, Line} nil -> {atom, Line, nil}
>>> [] [] >>> [1] [1] >>> [true] [true] >>> [atom] [atom] >>> [[]] [[]]
The only lists you need/have ;)
>>> [] [] >>> [foo] [foo] >>> [foo :: []] [foo] >>> [foo :: [bar]] [foo, bar] >>> [foo :: [bar :: []]] [foo, bar] >>> [foo :: [bar :: [baz :: []]]] [foo, bar, baz]
>>> [] [] >>> [1] [1] >>> [1, 2] [1,2] >>> [1, 2, 3] [1,2,3] >>> [1, 2, 3, [5, [6, 7]]] [1,2,3,[5,[6,7]]] >>> [1 :: []] [1] >>> [1 :: [2 :: []]] [1,2] >>> [1 :: 2] [1|2]
And get an extra feature for free
>>> [] [] >>> [1] [1] >>> [1 :: 2] [1|2] >>> [1 :: []] [1] >>> [1, 2, 3 :: []] [1,2,3] >>> [1, 2 :: [3 :: []]] [1,2,3] >>> [1, 2 :: [3 :: 4]] [1,2,3|4]
>>> [1] [1] >>> [1,] [1] >>> [1,2] [1,2] >>> [1,2,] [1,2]
>>> [] ++ [] [] >>> [1] ++ [2, 3] [1 ,2 ,3] >>> [1] ++ [2] ++ [3] [1, 2, 3] >>> [1, 2, 3] -- [2] [1, 3]
>>> "" [] >>> "this is a string" "this is a string" >>> "strings are lists of characters" "strings are lists of characters"
>>> '' <<>> >>> 'a binary string' <<"a binary string">>
>>> an_atom an_atom >>> `an atom with spaces` 'an atom with spaces' >>> `or weird characters!` 'or weird characters!'
>>> ()
{}Need to distinguish from expression in parenthesis, trailing comma is required.
>>> ()
{}
>>> (1,)
{1}
>>> (foo,)
{foo}
>>> ((),)
{{}}>>> ()
{}
>>> (1,)
{1}
>>> (1)
1
>>> (1, 2)
{1,2}
>>> (1, 2,)
{1,2}
>>> (1, 2, 3)
{1,2,3}
>>> (1, 2, 3,)
{1,2,3}>>> now()
{1475,97317,459463}
>>> element(1, (foo,))
foo
>>> is_integer(1)
true
>>> `now`()
{1475,97351,894202}>>> erlang.now()
{1475,97590,786477}
>>> erlang.element(1, (foo,))
foo
>>> erlang.is_integer(1)
true
>>> `erlang`.`now`()
{1475,97619,94281}>>> {}
#{}>>> {}
#{}
>>> {a: 1}
#{a => 1}>>> {}
#{}
>>> {a: 1}
#{a => 1}
>>> {a: 1, b: 2}
#{a => 1,b => 2}
>>> {a: 1,}
#{a => 1}
>>> {a: 1, b: 2,}
#{a => 1,b => 2}
>>> A = a
a
>>> {A: 1, b: A}
#{a => 1,b => a}>>> {} # {}
#{}
>>> {a: 1} # {b: 1}
#{a => 1,b => 1}
>>> {a: 1} # {a: 2}
#{a => 2}
>>> {a: 1, b: 2} # {b: 3, c: 4}
#{a => 1,b => 3,c => 4}
>>> A = {a: 1}
#{a => 1}
>>> A # {b: 2}
#{a => 1,b => 2}>>> A = {a: 1}
#{a => 1}
>>> {a = B} = A
#{a => 1}
>>> B
1
>>> A # {a = 2}
#{a => 2}
>>> A # {b = 3}
error: {badkey,b}it better be true :)
>>> when 42 > 4 { yes }
yes
>>> when true or false { A = 42 }
42
>>> when false { woops }
error: if_clauseNeed to be entered all in the same line for now, wrapped for legibility commit 46:
>>> when false { shouldnt_happen }
else when true { correct }
correct
>>> when true { correct }
correct
>>> when false { shouldnt_happen }
else when 1 > 2 { not_yet }
else when true { correct }
correctNeed to be entered all in the same line for now, wrapped for legibility commit 47:
>>> match 42:
1 { one }
2 { two }
42 { the_answer }
end
the_answer
>>> match 42:
1 { one }
42 { the_answer }
end
the_answer>>> match 42: 42 { the_answer } end
the_answer
>>> match 42: A { the_answer } end
the_answer
>>> match 42: A { A + 1 } end
43
>>> match 42: 1 { A + 1 } end
error: {case_clause,42}