├── erljs_code └── .placeholder ├── erljs_html ├── erljs ├── js_lib ├── erljs_tests ├── erljs_code ├── GraublauWeb.otf ├── l7ry4Z6jesX0kBGhwZVQry3USBnSvpkopQaUR-2r7iU.ttf ├── xWfNF53zMVtUUmsSpUl10vesZW2xOQ-xsNqO47m55DA.ttf ├── styles.css └── erljs.html ├── tests ├── erljs_code │ └── .placeholder ├── term.erl ├── testy_float ├── testy_parsowanie ├── tests_binaries ├── random_term.erl └── tests_arithmetic ├── from_otp ├── beam_emu.c ├── genop.tab └── beam_opcodes.erl ├── erl_lib_core ├── lists-erl-create-patch.sh └── lists-erl.patch ├── tools ├── nodejs-v8_run.sh ├── compile.sh ├── preprocess_js.sh ├── rhino_run.sh ├── run_dialyzer.sh ├── combine_js_files.sh ├── stats.sh ├── compile_all.escript └── make_links_for_core_otp_modules.sh ├── BUGS ├── js_src ├── erljs_unite.js ├── erljs_bignum.js ├── erljs_transport.js ├── erljs_code.js ├── erljs_rhino_autorun.js ├── erljs_scheduler_list.js ├── erljs.jss ├── erljs_float.js └── erljs_control.js ├── examples ├── devel │ ├── example_floats.erl │ ├── example_eh.erl │ ├── example_funs.erl │ ├── example_messages.erl │ ├── works.txt │ ├── example_binaries.erl │ └── example.erl ├── TODO ├── gensup_test.erl ├── genser_calculatepi.erl ├── example_advanced_page.erljs └── genser_manybuttons.erl ├── erl_src ├── erljs_kernel.erl ├── erljs.erl ├── erljs_beam_vm.erl ├── erljs_beam_verify.erl ├── erljs_compile_all.erl ├── erljs_widgets.erl ├── json_simple.erl ├── erljs_tests.erl ├── erljs_dom.erl ├── erljs_compiler.erl └── erljs_html.erl ├── HISTORY ├── OTHERS ├── reveng └── reverse_enginering_phash.erl ├── .gitignore ├── TODO ├── COPYING ├── TESTING ├── PLATFORMS ├── WAYS ├── README ├── praca └── libs.txt ├── erl_lib └── ct_expand.erl └── STATUS /erljs_code/.placeholder: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /erljs_html/erljs: -------------------------------------------------------------------------------- 1 | ../js_src -------------------------------------------------------------------------------- /erljs_html/js_lib: -------------------------------------------------------------------------------- 1 | ../js_lib -------------------------------------------------------------------------------- /erljs_html/erljs_tests: -------------------------------------------------------------------------------- 1 | ../tests -------------------------------------------------------------------------------- /tests/erljs_code/.placeholder: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /erljs_html/erljs_code: -------------------------------------------------------------------------------- 1 | ../erljs_code -------------------------------------------------------------------------------- /from_otp/beam_emu.c: -------------------------------------------------------------------------------- 1 | ../../erljs-otp_src_R12B-5/erts/emulator/beam/beam_emu.c -------------------------------------------------------------------------------- /erljs_html/GraublauWeb.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baryluk/erljs/HEAD/erljs_html/GraublauWeb.otf -------------------------------------------------------------------------------- /erl_lib_core/lists-erl-create-patch.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | 4 | diff -Nu /usr/lib/erlang/lib/stdlib-*/src/lists.erl stdlib/src/lists.erl 5 | -------------------------------------------------------------------------------- /erljs_html/l7ry4Z6jesX0kBGhwZVQry3USBnSvpkopQaUR-2r7iU.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baryluk/erljs/HEAD/erljs_html/l7ry4Z6jesX0kBGhwZVQry3USBnSvpkopQaUR-2r7iU.ttf -------------------------------------------------------------------------------- /erljs_html/xWfNF53zMVtUUmsSpUl10vesZW2xOQ-xsNqO47m55DA.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baryluk/erljs/HEAD/erljs_html/xWfNF53zMVtUUmsSpUl10vesZW2xOQ-xsNqO47m55DA.ttf -------------------------------------------------------------------------------- /tools/nodejs-v8_run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copyright 2009-2011, Witold Baryluk 4 | # erljs project 5 | 6 | exec /usr/bin/node erljs_nodejs_autorun.js 7 | -------------------------------------------------------------------------------- /BUGS: -------------------------------------------------------------------------------- 1 | erljs bugs: 2 | 3 | 4 | browser-specific bugs: 5 | - In Opera 10.60: float_to_list, io:format and serizliation of float values can be not precisse enught to reconstruct back correct value. 6 | -------------------------------------------------------------------------------- /tests/term.erl: -------------------------------------------------------------------------------- 1 | -module(term). 2 | -export([encode/1]). 3 | -author("Witold Baryluk "). 4 | -vsn("1.0"). 5 | 6 | encode(X) -> io_lib:format("~100000000P", [ X, 100000000 ]). 7 | 8 | -------------------------------------------------------------------------------- /js_src/erljs_unite.js: -------------------------------------------------------------------------------- 1 | /* Copyright 2008-2011, Witold Baryluk 2 | * erljs project 3 | */ 4 | 5 | /** This will be some additional methods to make erljs work in Opera Unite, 6 | * and use FileIO and Unite Webserver, Resource Fetcher, etc. 7 | */ 8 | -------------------------------------------------------------------------------- /examples/devel/example_floats.erl: -------------------------------------------------------------------------------- 1 | -module(example_floats). 2 | -author('baryluk@smp.if.uj.edu.pl'). 3 | 4 | % Copyright 2008-2011, Witold Baryluk 5 | % erljs project 6 | 7 | -compile([export_all]). 8 | -export_js([export_all]). 9 | 10 | % FLOATS 11 | -------------------------------------------------------------------------------- /examples/devel/example_eh.erl: -------------------------------------------------------------------------------- 1 | -module(example_eh). 2 | -author('baryluk@smp.if.uj.edu.pl'). 3 | 4 | % Copyright 2008-2011, Witold Baryluk 5 | % erljs project 6 | 7 | -compile([export_all]). 8 | -export_js([export_all]). 9 | 10 | % Exceptions Handling 11 | 12 | -------------------------------------------------------------------------------- /tools/compile.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | 4 | # http://www.nongnu.org/espresso/js-cpp.html 5 | # 6 | # GNU cpp 7 | 8 | /usr/bin/cpp -P -undef -Wundef -std=c99 -nostdinc -Wtrigraphs -fdollars-in-identifiers -C $1 9 | 10 | # Other possibilities 11 | # Gema - http://gema.sourceforge.net/ 12 | # m4 13 | -------------------------------------------------------------------------------- /examples/devel/example_funs.erl: -------------------------------------------------------------------------------- 1 | -module(example_funs). 2 | -author('baryluk@smp.if.uj.edu.pl'). 3 | 4 | % Copyright 2008-2011, Witold Baryluk 5 | % erljs project 6 | 7 | -compile([export_all]). 8 | -export_js([export_all]). 9 | 10 | % Funs - construction 11 | 12 | % Funs - usage 13 | -------------------------------------------------------------------------------- /js_src/erljs_bignum.js: -------------------------------------------------------------------------------- 1 | /* Copyright 2008-2011, Witold Baryluk 2 | * erljs project 3 | */ 4 | 5 | // http://www.leemon.com/crypto/BigInt.html 6 | // http://github.com/silentmatt/javascript-biginteger (http://silentmatt.com/biginteger/) 7 | // http://www.petting-zoo.org/Calculator.html 8 | 9 | 10 | -------------------------------------------------------------------------------- /tests/testy_float: -------------------------------------------------------------------------------- 1 | % Copyright 2009-2011, Witold Baryluk 2 | % erljs project 3 | 4 | example:cross({1.0,2.0,3.0},{4.0,5.0,6.0}). 5 | example:cross2({1.0,2.0,3.0},{4.0,5.0,6.0}). 6 | example:cross2({1,2,3},{4,5,6}). 7 | example:cross3({1,2,3},{4,5,6}). 8 | example:cross({1.1,2.8,3.5},{4.7,5.2,6.2}). 9 | example:cross2({1.1,2.8,3.5},{4.7,5.2,6.2}). 10 | -------------------------------------------------------------------------------- /tools/preprocess_js.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copyright 2009-2011, Witold Baryluk 4 | # erljs project 5 | 6 | # http://www.nongnu.org/espresso/js-cpp.html 7 | # 8 | # GNU cpp 9 | 10 | exec cpp -P -undef -Wundef -std=c99 -nostdinc -Wtrigraphs -fdollars-in-identifiers -C "$@" 11 | 12 | # Other possibilities 13 | # Gema - http://gema.sourceforge.net/ 14 | # m4 15 | -------------------------------------------------------------------------------- /examples/devel/example_messages.erl: -------------------------------------------------------------------------------- 1 | -module(example_messages). 2 | -author('baryluk@smp.if.uj.edu.pl'). 3 | 4 | % Copyright 2008-2011, Witold Baryluk 5 | % erljs project 6 | 7 | -compile([export_all]). 8 | -export_js([export_all]). 9 | 10 | % Messages - sending 11 | 12 | m1(P, X) -> 13 | P ! X. 14 | 15 | m1(X) -> 16 | dupa ! X. 17 | 18 | % Messages - receive 19 | 20 | -------------------------------------------------------------------------------- /erl_src/erljs_kernel.erl: -------------------------------------------------------------------------------- 1 | -module(erljs_kernel). 2 | -author('baryluk@smp.if.uj.edu.pl'). 3 | 4 | % Copyright 2009-2011, Witold Baryluk 5 | % erljs project 6 | 7 | -export([start/1]). 8 | 9 | start(Args) -> 10 | P3 = genser_calculatepi:start({przycisk_pi_start1, pole_pi1}), 11 | P2 = genser_calculatepi:start({przycisk_pi_start2, pole_pi2}), 12 | P1 = genser_manybuttons:start(), 13 | ok. 14 | -------------------------------------------------------------------------------- /examples/TODO: -------------------------------------------------------------------------------- 1 | Examples to do: 2 | 3 | - games: sudoku, or something with AI (but simple enaugh to be easy to write) 4 | - simple search box and search results inline 5 | - search suggestions 6 | - twitter badge showing last messages, and allowing to navigate, and refreshing every 5 some time 7 | - intensive computations (100x100 matrix multiplication, text search, compression, encryption), 8 | - small gallery with slideshow, right/left arrows 9 | - small chat, with multiple room, and direct messaging 10 | - 11 | -------------------------------------------------------------------------------- /examples/devel/works.txt: -------------------------------------------------------------------------------- 1 | lists:seq(10,20000) 2 | lists:seq(10,9) 3 | lists:seq(10,10) 4 | lists:seq(10,8) properly fails with bad func 5 | lists:duplicate(10,20000) 6 | lists:seq(10,200,2) 7 | lists:seq(200,100,-2) 8 | erlang:++/2 9 | lists:reverse/1 10 | lists:reverse/2 11 | length/1 12 | hd, tl 13 | lists:nth 14 | lists:nthtail 15 | math:* but not hiperbolic functions and erf/c. 16 | random:uniform/1,2, and other random:* 17 | proplists:lookup/2 18 | lists:{max,min,sum,last,zip,zip3,unzip,unzip3,sort} just works. 19 | 20 | 21 | -------------------------------------------------------------------------------- /tools/rhino_run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copyright 2009-2011, Witold Baryluk 4 | # erljs project 5 | 6 | # some kind of bug in rhino 7 | exec rhino -opt -1 erljs_rhino_autorun.js 8 | #echo 'load("erljs_rhino_autorun.js")' | rhino 9 | 10 | 11 | # this is a rhino limitation 12 | # for some reason (security?) rhino doesn't 13 | # allow input files bigger than some constant. 14 | # https://bugzilla.mozilla.org/show_bug.cgi?format=multiple&id=563163 15 | # Disabling optimialization (-opt -1), make it work. 16 | 17 | -------------------------------------------------------------------------------- /tools/run_dialyzer.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copyright 2009-2011, Witold Baryluk 4 | # erljs project 5 | 6 | if [ ! -f ~/.dialyzer_plt ]; then 7 | dialyzer --build_plt --apps erts kernel stdlib mnesia compiler \ 8 | crypto hipe inets parsetools sasl xmerl debugger common_test \ 9 | eunit edoc docbuilder tools syntax_tools ssh wx ssl snmp gs \ 10 | test_server runtime_tools webtool observer public_key et 11 | fi 12 | 13 | cd erl_src 14 | dialyzer json_simple.erl erljs_compiler.erl erljs_compile_all.erl erljs_tests.erl erljs.erl 15 | -------------------------------------------------------------------------------- /HISTORY: -------------------------------------------------------------------------------- 1 | Acks: 2 | rhino 3 | Opera 4 | 5 | - makeing examples work 6 | - makeing lists:* work 7 | 8 | - makeing erlang:++, lists:reverse/1,2 to be native 9 | - native counters 10 | - is_*(E) helper function (in JS), to simplify common tests 11 | - implementig tl, hd 12 | - jumps with reasons, and fixes multiple occurence of jumpf in ifs without else. jumpf only sets IP, still switch need to be breaken, and no other instruction should be taken 13 | - size 14 | - fixes 15 | - added atom handling to datatypes, and improper lists 16 | - length 17 | 18 | -------------------------------------------------------------------------------- /tests/testy_parsowanie: -------------------------------------------------------------------------------- 1 | % Copyright 2009-2011, Witold Baryluk 2 | % erljs project 3 | 4 | begin SpecInString = "-spec my_function(some_type()) -> 42 | 'gazonk'.", {ok, Toks, 1} = erl_scan:string(SpecInString) end. 5 | begin SpecInString = "-spec my_function(some_type()) -> 42 | 'gazonk'.", {ok, Toks, 1} = erl_scan:string(SpecInString), erl_parse:parse_form(Toks) end. 6 | 7 | erl_scan:string("State#state.counter"). 8 | erl_scan:string("State#state.counter."). 9 | erl_scan:string("ala."). 10 | erl_parse:parse_term([{atom,1,ala},{dot,1}]). 11 | -------------------------------------------------------------------------------- /tests/tests_binaries: -------------------------------------------------------------------------------- 1 | % Copyright 2009-2011, Witold Baryluk 2 | % erljs project 3 | 4 | % binaries 5 | 6 | <<>>. 7 | <<30>>. 8 | <<4,30>>. 9 | <<43,55,30,66,100,31:5>>. 10 | % <<43,55,30,66,100,31:15>> == <<4,0,30:7>>. 11 | % <<43,55,30,66,100,31:16>> == <<4,0,30>>. 12 | % - we can assume that there will no be such terms, as they will be transformed to right 13 | 14 | % size and byte_size looks to have different rounding behaviour. 15 | % byte_size up, size down 16 | %size 17 | %byte_size 18 | %bit_size 19 | 20 | % test both in body and in guard tests 21 | 22 | begin X=44, <<430:X>> end == <<0,0,0,0,26,14:4>>. 23 | -------------------------------------------------------------------------------- /OTHERS: -------------------------------------------------------------------------------- 1 | Languages which produces Erlang VM bytecode: 2 | - Erlang 3 | - Efene http://efene.tumblr.com/ 4 | - LFE http://github.com/rvirding/lfe 5 | 6 | BEAM recompiler to JVM: 7 | - http://wiki.github.com/krestenkrab/erjang/ - very intersting. 8 | - http://www.javalimit.com/ 9 | 10 | Using Erlang style concurenncy in JS: 11 | - http://beatniksoftware.com/erjs/ 12 | - http://www.neilmix.com/2007/02/07/threading-in-javascript-17/ 13 | 14 | There is also other systems, languages and libraries for some languages which are influenced by Erlang. 15 | 16 | 17 | Alternative Erlang runtime and VM. Actually interpreter, not VM. By Maxim Kharchenko 18 | http://github.com/maximk/teeterl#readme 19 | http://taooferlang.blogspot.com/ 20 | -------------------------------------------------------------------------------- /reveng/reverse_enginering_phash.erl: -------------------------------------------------------------------------------- 1 | -module(epe). 2 | -author('baryluk@smp.if.uj.edu.pl'). 3 | 4 | % Copyright 2009-2011, Witold Baryluk 5 | % erljs project 6 | 7 | 8 | -export([f/1]). 9 | 10 | f(N) -> 11 | {ok, S} = f([],N,0), 12 | {ok, S div N}. 13 | 14 | f(_,0,S) -> 15 | {ok,S}; 16 | f(T,N,S) -> 17 | T2 = erlang:list_to_tuple(['\000'|T]), 18 | T3 = erlang:list_to_tuple(['\001'|T]), 19 | T4 = erlang:list_to_tuple(['\002'|T]), 20 | T5 = erlang:list_to_tuple(['\003'|T]), 21 | H2 = erlang:phash(T2, 1 bsl 32), 22 | H3 = erlang:phash(T3, 1 bsl 32), 23 | H4 = erlang:phash(T4, 1 bsl 32), 24 | H5 = erlang:phash(T5, 1 bsl 32), 25 | S2 = S + H3-H2, 26 | %io:format("~p~n", [H3-H2]), 27 | f(['\000'|T],N-1,S2). 28 | 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.beam 2 | *.dis 3 | *.o 4 | *.S 5 | *.E 6 | *.beam.js 7 | 8 | dict.erl 9 | gb_sets.erl 10 | gb_trees.erl 11 | orddict.erl 12 | ordsets.erl 13 | proplists.erl 14 | queue.erl 15 | random.erl 16 | sets.erl 17 | string.erl 18 | regexp.erl 19 | lists.erl 20 | 21 | erl_lib_core/*/src/*.erl 22 | erl_lib_core/*/include/*.hrl 23 | erl_lib_core/*/src/*.beam 24 | erl_lib_core/*/ebin/*.beam 25 | erl_lib_core/*/ebin-org/*.beam 26 | 27 | tests/tests_auto.erl 28 | tests/tests_auto.js 29 | tests/tests_binaries.erl 30 | tests/tests_binaries.js 31 | tests/testy_float.erl 32 | tests/testy_float.js 33 | tests/testy_parsowanie.erl 34 | tests/testy_parsowanie.js 35 | tests/tests_arithmetic.erl 36 | tests/tests_arithmetic.js 37 | 38 | js_lib/javascript-stacktrace 39 | -------------------------------------------------------------------------------- /examples/gensup_test.erl: -------------------------------------------------------------------------------- 1 | -module(gensup_test). 2 | -author('baryluk@smp.if.uj.edu.pl'). 3 | 4 | % Copyright 2008-2011, Witold Baryluk 5 | % erljs project 6 | 7 | -behaviour(supervisor). 8 | 9 | -export([start_link/0]). 10 | -export([init/1]). 11 | 12 | start_link() -> 13 | supervisor:start_link(ch_sup, []). 14 | 15 | init(_Args) -> 16 | {ok, {{one_for_one, 1, 60}, [ 17 | {genser_test, {genser_test, start_link, []}, 18 | permanent, brutal_kill, worker, [genser_test]}, 19 | {genser_test2, {genser_test2, start_link, [{przycisk_pi_start1, pole_pi1}]}, 20 | permanent, brutal_kill, worker, [genser_test2]}, 21 | {genser_test2, {genser_test2, start_link, [{przycisk_pi_start2, pole_pi2}]}, 22 | permanent, brutal_kill, worker, [genser_test2]} 23 | ]}}. 24 | -------------------------------------------------------------------------------- /tools/combine_js_files.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2009-2011, Witold Baryluk 4 | # erljs project 5 | 6 | MODULES="erljs_kernel dict gb_sets ordsets regexp gb_trees proplists sets lists queue string orddict random tests_auto example example_messages" 7 | MODULES="${MODULES} sys proc_lib gen gen_event gen_fsm gen_server" 8 | 9 | 10 | ADDITIONAL="prototype.js javascript-stacktrace/stacktrace.js tests_auto.js erljs_code.js erljs_datatypes.js erljs_vm.js erljs_scheduler_list.js erljs_scheduler.js erljs_control.js" 11 | 12 | ( 13 | for MODULE in $MODULES 14 | do 15 | cat erljs_code/${MODULE}.beam.js 16 | done 17 | 18 | for FILE in $ADDITIONAL 19 | do 20 | cat ${FILE} 21 | done 22 | ) | grep -v -E '(^\s*//|^\s*$)' > gz/combined.js 23 | 24 | gzip -v -c -9 gz/combined.js > gz/combined.jsgz 25 | ls -l gz/combined.js gz/combined.jsgz 26 | -------------------------------------------------------------------------------- /js_src/erljs_transport.js: -------------------------------------------------------------------------------- 1 | /* Copyright 2008-2011, Witold Baryluk 2 | * erljs project 3 | */ 4 | 5 | if ('WebSocket' in window) { 6 | var ws = new WebSocket('ws://example.org:12345/demo', 'distributed-erljs'); 7 | ws.onopen = function(e) { 8 | // the connection is now established 9 | // let's send a message 10 | this.send('Hello!'); 11 | } 12 | ws.onclose = function(e) { 13 | alert('WebSocket closed :-('); 14 | } 15 | ws.onmessage = function(e) { 16 | // got a message from the server 17 | alert(e.data); 18 | } 19 | ws.onerror = function(e) { 20 | // something wrong 21 | alert(e); 22 | // reconnect, reset counters, eventually fallback to AJAX 23 | } 24 | //ws.close(); 25 | } else { 26 | // fallback to AJAX polling 27 | // (active - every few seconds, or passive - block on server side) 28 | alert("no web sockets"); 29 | } 30 | -------------------------------------------------------------------------------- /erl_src/erljs.erl: -------------------------------------------------------------------------------- 1 | -module(erljs). 2 | -author('baryluk@smp.if.uj.edu.pl'). 3 | 4 | % Copyright 2009-2011, Witold Baryluk 5 | % erljs project 6 | 7 | -compile([export_all]). 8 | 9 | % TODO: ponizej zakomentowano wiele -spec bo kompilator krzyczy w nower werji 10 | 11 | %-spec eval(io_list()) -> {ok, term()} | {error, term()}. 12 | eval(X) -> 13 | %throw (callable_only_at_client_side). 14 | ignored. 15 | 16 | -spec alert(any()) -> ok | {error, term()}. 17 | alert(X) -> 18 | %throw (callable_only_at_client_side). 19 | ignored. 20 | 21 | -spec confirm(any()) -> ok | cancel | {error, term()}. 22 | confirm(X) -> 23 | %throw (callable_only_at_client_side). 24 | ignored. 25 | 26 | -spec monit(any()) -> {ok, term()} | {cancel, term()} | {error, term()}. 27 | monit(X) -> 28 | %throw (callable_only_at_client_side). 29 | ignored. 30 | 31 | -spec console_log(any()) -> ok | {error, term()}. 32 | console_log(X) -> 33 | ignored. 34 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | Most important things: 2 | - cleanup 3 | - bit strings 4 | - dynamic code/module loading and reloading 5 | - phash 6 | - monitoring processes 7 | - tracing subsystem 8 | 9 | Less important things: 10 | - ets 11 | 12 | Modulization: 13 | - includes/modules (header files) and conditional complilation (use C pre-processor - cpp) 14 | - binaries support 15 | - browser / rhino 16 | - ajax subsystem 17 | - dom subsystem 18 | - messaging subsystem 19 | - with scheduler or standalone (single process) 20 | - worker support or not 21 | - supported transports - ajax (real or emulated in some ways), web sockets, server events 22 | - tracing and debuging subsystem 23 | - dynamic code loading 24 | - ets 25 | - file system / networking / sockets emulation, etc. 26 | - fabric support to interconnect browser with server side 27 | 28 | - dom and css selectors based on Erlang pattern matchin and pattern compilation (like ets or mnesia, or fun2ms). 29 | -------------------------------------------------------------------------------- /erl_src/erljs_beam_vm.erl: -------------------------------------------------------------------------------- 1 | -module(erljs_beam_vm). 2 | -author('baryluk@smp.if.uj.edu.pl'). 3 | 4 | % Copyright 2009-2011, Witold Baryluk 5 | % erljs project 6 | 7 | %-export([eval_start/1, eval_prepare/1, go/4]). 8 | 9 | 10 | % This was try to implement erlang beam bytecode intepreter in erlang. :) 11 | % 12 | %eval_start(A) -> 13 | % {ok, Pid} = spawn(eval_prepare(A)), 14 | % {ok, Pid}. 15 | % 16 | %reg(Regs, N) -> 17 | % ets:lookup_element(Regs, N, 2). 18 | % 19 | %eval_prepare(Code) when is_atom(Module), is_module(Function), is_list(Args) -> 20 | % R = ets:new(erlsj_regs, [set, private, {keypos, 1}]), 21 | % C = ets:new(erlsj_code, [set, private, {keypos, 1}]), 22 | % [ ets:insert(R, {N, undefined}) || N <- lists:seq(0, 128) ], 23 | % [ ets:insert(C, {ModuleName, FunctionName, FunctionN, Line}) || Function <- Functions ], 24 | % {R,C,S}. 25 | % 26 | %go({R,C,S}, Module, Function, Args) 27 | % eval_loop(C, {0}, Tid, []). 28 | % 29 | %eval_loop(Code, {Module, Function, Label, IP}, Tid, Stack) -> 30 | % ok. 31 | 32 | -------------------------------------------------------------------------------- /erl_src/erljs_beam_verify.erl: -------------------------------------------------------------------------------- 1 | -module(erljs_beam_verify). 2 | -author('baryluk@smp.if.uj.edu.pl'). 3 | 4 | % Copyright 2009-2011, Witold Baryluk 5 | % erljs project 6 | 7 | -export([verify/1]). 8 | 9 | verify(B) -> 10 | todo. 11 | % chec that all registers are used properly 12 | % check arity of functions 13 | % that after function return only x[0] is readed 14 | % that at least x[0.. arity] is writen before calling known arity functions 15 | % that x[0] and x[1] are valid before bifs, like send ('!'), 't', 'is_atom', etc... 16 | % that labels are inside the same function as its usage 17 | % that 'jump' opcode wil not introduce unbound loops 18 | % that there are no opcodes after tail-call 19 | % that 'put'/'put_tuple' are used correctly (correct number of 'put''s, in correct order, consecutivly) 20 | % that there is always 'r' or tail-call at the end of each exec path 21 | % that 'try'/'try_case'/'catch'/'catch_end', 'case'/'case_end', 'loop_rec'/ 22 | % that label referenced in 'wait'/'wait_timeout' is point to 'loop_rec' 23 | % that 'remove_message' is used after 'loop_rec' 24 | % that 'wait'/'timeout' is after 'loop_rec', and that error label referenced in 'loop_rec' points to 'wait'/'wait_timeout'/'timeout' 25 | -------------------------------------------------------------------------------- /tools/stats.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copyright 2009-2011, Witold Baryluk 4 | # erljs project 5 | 6 | printf "%42s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n" filename lines LOC size Cbytes Cgz6 Cgz9 Cgz9alt lonegst-line 7 | 8 | for i in *.js */*.js 9 | do 10 | 11 | Z=`cat $i | wc -c` 12 | 13 | LOC=`egrep -v '^\s*($|/\*|//|\*|\};?\s*$)' $i | wc -l` 14 | LINES=`cat $i | wc -l` 15 | 16 | C=`egrep -v '^\s*($|/\*|//|\*|\};?\s*$)' $i | wc -c` 17 | D=`egrep -v '^\s*($|/\*|//|\*|\};?\s*$)' $i | gzip --stdout -6 | wc -c` 18 | D9=`egrep -v '^\s*($|/\*|//|\*|\};?\s*$)' $i | gzip --stdout -9 | wc -c` 19 | D9a=`egrep -v '^\s*($|/\*|//|\*|\};?\s*$)' $i | 7z a dummy -tgzip -mx=9 -si -so 2>/dev/null | wc -c` 20 | 21 | 22 | # wc have strange method of counting line lenght when it have \t character. 23 | # it assumes it is normally 8 spaces, but not if it isn't alligned to 8 chars. 24 | # so it have varying number of "bytes", from 1 to 8. This can make difference of about 20 chars for lines of 150 chars. 25 | #E=`cat $i | wc --max-line-length` 26 | E2=`cat $i | tr '\t' ' ' | wc --max-line-length` 27 | printf "%42s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n" $i $LINES $LOC $Z $C $D $D9 $D9a $E2 28 | #cat $i | tr '\t' ' ' | egrep -v '(^\s*$|^\s*//|^\s*\*)' | egrep '^.{120,}' 29 | done 30 | 31 | -------------------------------------------------------------------------------- /examples/devel/example_binaries.erl: -------------------------------------------------------------------------------- 1 | -module(example_binaries). 2 | -author('baryluk@smp.if.uj.edu.pl'). 3 | 4 | % Copyright 2008-2011, Witold Baryluk 5 | % erljs project 6 | 7 | -compile([export_all]). 8 | -export_js([export_all]). 9 | 10 | % Binaries - contstruct 11 | 12 | bin1(X) -> 13 | <<"ala">>. 14 | 15 | bin2(X) -> 16 | <<97,99,101>>. 17 | 18 | bin3a(X) -> 19 | <<99,97,X,104>>. 20 | 21 | bin3b(X) -> 22 | <<99,97,X:16,104>>. 23 | 24 | bin3c(X) -> 25 | <<99,97,X:24,104>>. 26 | 27 | bin3d(X) -> 28 | <<99,97,X:32,104>>. 29 | 30 | bin3f(X) -> 31 | <<99,97,X:32/float,104>>. 32 | 33 | bin4(X) -> 34 | 15 = byte_size(X), 35 | ok. 36 | 37 | bin4b(X) when byte_size(X) =:= 15 -> 38 | ok. 39 | 40 | bin5(X) -> 41 | 15 = size(X), 42 | ok. 43 | 44 | bin5b(X) when size(X) =:= 15 -> 45 | ok. 46 | 47 | bin6(X) -> 48 | 15 = bit_size(X), 49 | ok. 50 | 51 | bin6b(X) when bit_size(X) =:= 15 -> 52 | ok. 53 | 54 | 55 | bin7a(X,Y) -> 56 | <>. 57 | 58 | bin7b(X,Y) -> 59 | <>. 60 | 61 | bin7c(X,Y) -> 62 | <>. 63 | 64 | bin8(X,Y) -> 65 | <>. 66 | 67 | 68 | bin9(X,Y) -> 69 | <<99,97,X:Y,104>>. 70 | 71 | % Binaries - matching 72 | 73 | unbin1(X) -> 74 | <> = X, 75 | {A}. 76 | 77 | unbin2(X) -> 78 | <> = X, 79 | {A}. 80 | 81 | unbin3(X) -> 82 | <> = X, 83 | {A}. 84 | 85 | unbin4(X) -> 86 | <> = X, 87 | {A}. 88 | -------------------------------------------------------------------------------- /js_src/erljs_code.js: -------------------------------------------------------------------------------- 1 | /* Copyright 2008-2011, Witold Baryluk 2 | * erljs project 3 | */ 4 | 5 | var all_modules = [ 6 | ["erljs_kernel", module_erljs_kernel], 7 | 8 | ["random", module_random], 9 | ["lists", module_lists], 10 | ["orddict", module_orddict], 11 | ["ordsets", module_ordsets], 12 | ["string", module_string], 13 | ["queue", module_queue], 14 | ["dict", module_dict], 15 | ["proplists", module_proplists], 16 | ["sets", module_sets], 17 | ["gb_trees", module_gb_trees], 18 | ["gb_sets", module_gb_sets], 19 | ["regexp", module_regexp], 20 | ["example", module_example], 21 | 22 | ["erlang", module_erlang], 23 | 24 | ["otp_ring0", module_otp_ring0], 25 | ["init", module_init], 26 | ["sys", module_sys], 27 | ["supervisor", module_supervisor], 28 | ["supervisor_bridge", module_supervisor_bridge], 29 | ["proc_lib", module_proc_lib], 30 | ["gen", module_gen], 31 | ["gen_event", module_gen_event], 32 | ["gen_fsm", module_gen_fsm], 33 | ["gen_server", module_gen_server], 34 | ["error_logger", module_error_logger], 35 | ["timer", module_timer], 36 | 37 | ["gensup_test", module_gensup_test], 38 | ["genser_manybuttons", module_genser_manybuttons], 39 | ["genser_calculatepi", module_genser_calculatepi], 40 | 41 | ["tests_auto", module_tests_auto], 42 | 43 | ["epp", module_epp], 44 | ["eval_bits", module_eval_bits], 45 | ["erl_bits", module_erl_bits], 46 | ["erl_compile", module_erl_compile], 47 | ["erl_eval", module_erl_eval], 48 | ["erl_expand_records", module_erl_expand_records], 49 | ["erl_internal", module_erl_internal], 50 | ["erl_lint", module_erl_lint], 51 | ["erl_parse", module_erl_parse], 52 | ["erl_posix_msg", module_erl_posix_msg], 53 | ["erl_pp", module_erl_pp], 54 | ["erl_scan", module_erl_scan] 55 | ]; 56 | -------------------------------------------------------------------------------- /tools/compile_all.escript: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env escript 2 | %% -*- erlang -*- 3 | %%! -pa erl_src/ -smp enable -sname erljs_compil_all -mnesia debug verbose 4 | 5 | 6 | % Copyright 2009-2011, Witold Baryluk 7 | % erljs project 8 | 9 | main(_Args) -> 10 | 11 | ok = shell_default:cd("erl_src"), 12 | 13 | % prepare for conversion of all modules 14 | {ok, json_simple} = shell_default:c(json_simple), 15 | {ok, erljs_compiler} = shell_default:c(erljs_compiler), 16 | {ok, erljs_compile_all} = shell_default:c(erljs_compile_all), 17 | 18 | %{ok, erljs} = shell_default:c(erljs), 19 | %{ok, erljs_dom} = shell_default:c(erljs_dom), 20 | %{ok, erljs_html} = shell_default:c(erljs_html), 21 | 22 | ok = shell_default:cd(".."), 23 | 24 | % convert all standard and few non-standard modules 25 | erljs_compile_all:ca(), 26 | 27 | % prepare for generating tests 28 | ok = shell_default:cd("erl_src"), 29 | {ok, erljs_tests} = shell_default:c(erljs_tests), 30 | ok = shell_default:cd(".."), 31 | 32 | ok = shell_default:cd("examples/devel"), 33 | DevExamples = [ 34 | example, 35 | example_floats, 36 | example_funs, 37 | example_eh, 38 | example_messages, 39 | example_binaries 40 | ], 41 | [ shell_default:c(M) || M <- DevExamples ], 42 | ok = shell_default:cd("../.."), 43 | 44 | 45 | Tests = [ 46 | tests_arithmetic, 47 | testy_float, 48 | tests_auto, 49 | tests_binaries, 50 | testy_parsowanie 51 | ], 52 | 53 | % generate tests and reference result wrapper and checker 54 | ok = shell_default:cd("tests"), 55 | erljs_tests:cl(Tests), 56 | ok = shell_default:cd(".."), 57 | 58 | % convert all generated tests 59 | Tests2 = [ "tests/" ++ atom_to_list(M) ++ ".beam" || M <- Tests ], 60 | erljs_compiler:cl(Tests2), 61 | 62 | io:format("~n~nBuild complete.~n"), 63 | 64 | ok. 65 | -------------------------------------------------------------------------------- /js_src/erljs_rhino_autorun.js: -------------------------------------------------------------------------------- 1 | /* Copyright 2008-2011, Witold Baryluk 2 | * erljs project 3 | */ 4 | 5 | //load("prototype.js"); 6 | 7 | load("erljs_datatypes.js"); 8 | 9 | load("erljs_scheduler_list.js"); 10 | load("erljs_scheduler.js"); 11 | 12 | load("erljs_vm.js"); 13 | 14 | // stdlib 15 | load("erljs_code/random.beam.js"); // needs put, and get, trunc and abs 16 | load("erljs_code/lists.beam.js"); // list is one of the biggest module, 7kOps (before removing labels, etc.) 17 | load("erljs_code/orddict.beam.js"); // other have on avarage 1kOps, minimum 400kOps, maximum 2kOps 18 | load("erljs_code/ordsets.beam.js"); 19 | load("erljs_code/string.beam.js"); 20 | load("erljs_code/queue.beam.js"); 21 | load("erljs_code/dict.beam.js"); // need erlang:phash(Term,MaxN), erlang:error, list_to_tuple and tuple_to_list 22 | load("erljs_code/proplists.beam.js"); 23 | load("erljs_code/sets.beam.js"); 24 | load("erljs_code/gb_trees.beam.js"); 25 | load("erljs_code/gb_sets.beam.js"); 26 | load("erljs_code/regexp.beam.js"); 27 | 28 | // digraph // need lists, ets, queue 29 | // sofs // needs lists, digraph 30 | 31 | // base64.erl rewrite to native 32 | 33 | // my manual micro tests 34 | load("erljs_code/example.beam.js"); 35 | 36 | // automatically generated js/erl/beam.js from test specification 37 | load("erljs_code/tests_auto.beam.js"); 38 | load("tests_auto.js"); 39 | 40 | load("erljs_code.js"); 41 | 42 | load("erljs_control.js"); 43 | 44 | 45 | (function () { 46 | function unittest__small_rhino_tests() { 47 | eq("example:sum2(10,20)",32); 48 | eq("example:sum2(10,-20)",-8); 49 | eq("example:sum2(10,-10)",2); 50 | eq("example:sum2(10,-10)",2); 51 | eq("example:sum2(10,1.5)",13.5); 52 | } 53 | 54 | unittest__small_rhino_tests(); 55 | // unittest__term_decode(true,true); 56 | unittest__run_examples(); 57 | unittest__tests_auto(); 58 | })(); 59 | 60 | -------------------------------------------------------------------------------- /js_src/erljs_scheduler_list.js: -------------------------------------------------------------------------------- 1 | /* Copyright 2008-2011, Witold Baryluk 2 | * erljs project 3 | */ 4 | 5 | /* Linked Lists for use in scheduler 6 | * 7 | * This code is borowed from http://blog.jcoglan.com/2007/07/23/writing-a-linked-list-in-javascript/ 8 | * 9 | * We will need to reimplement it, and remove all unacassary functions / fields / functionalities. 10 | */ 11 | 12 | function LinkedList() { 13 | } 14 | 15 | LinkedList.prototype = { 16 | length: 0, 17 | first: null, 18 | last: null 19 | }; 20 | 21 | LinkedList.Circular = function() {}; 22 | 23 | LinkedList.Circular.prototype = new LinkedList(); 24 | 25 | LinkedList.Circular.prototype.append = function(node) { 26 | if (this.first === null) { 27 | node.prev = node; 28 | node.next = node; 29 | this.first = node; 30 | this.last = node; 31 | } else { 32 | node.prev = this.last; 33 | node.next = this.first; 34 | this.first.prev = node; 35 | this.last.next = node; 36 | this.last = node; 37 | } 38 | this.length++; 39 | }; 40 | 41 | LinkedList.Circular.prototype.insertAfter = function(node, newNode) { 42 | newNode.prev = node; 43 | newNode.next = node.next; 44 | node.next.prev = newNode; 45 | node.next = newNode; 46 | if (newNode.prev == this.last) { this.last = newNode; } 47 | this.length++; 48 | }; 49 | 50 | LinkedList.Circular.prototype.remove = function(node) { 51 | if (this.length > 1) { 52 | node.prev.next = node.next; 53 | node.next.prev = node.prev; 54 | if (node == this.first) { this.first = node.next; } 55 | if (node == this.last) { this.last = node.prev; } 56 | } else { 57 | this.first = null; 58 | this.last = null; 59 | } 60 | node.prev = null; 61 | node.next = null; 62 | this.length--; 63 | }; 64 | 65 | LinkedList.Node = function(data) { 66 | this.prev = null; 67 | this.next = null; 68 | this.data = data; 69 | }; 70 | 71 | /* usage 72 | myList = new LinkedList.Circular(); 73 | myList.append(new LinkedList.Node(someObject)); 74 | */ 75 | 76 | -------------------------------------------------------------------------------- /js_src/erljs.jss: -------------------------------------------------------------------------------- 1 | /* Copyright 2008-2011, Witold Baryluk 2 | * erljs project 3 | */ 4 | 5 | #include "prototype.js" 6 | 7 | /* biginteger.js */ 8 | 9 | #include "erljs_code/erljs_kernel.beam.js" 10 | 11 | #include "erljs_code/random.beam.js" 12 | #include "erljs_code/lists.beam.js" 13 | #include "erljs_code/orddict.beam.js" 14 | #include "erljs_code/ordsets.beam.js" 15 | #include "erljs_code/string.beam.js" 16 | #include "erljs_code/queue.beam.js" 17 | #include "erljs_code/dict.beam.js" 18 | #include "erljs_code/proplists.beam.js" 19 | #include "erljs_code/sets.beam.js" 20 | #include "erljs_code/gb_trees.beam.js" 21 | #include "erljs_code/gb_sets.beam.js" 22 | #include "erljs_code/regexp.beam.js" 23 | #include "erljs_code/example.beam.js" 24 | #include "erljs_code/erlang.beam.js" 25 | #include "erljs_code/otp_ring0.beam.js" 26 | #include "erljs_code/init.beam.js" 27 | #include "erljs_code/sys.beam.js" 28 | #include "erljs_code/supervisor.beam.js" 29 | #include "erljs_code/supervisor_bridge.beam.js" 30 | #include "erljs_code/proc_lib.beam.js" 31 | #include "erljs_code/gen.beam.js" 32 | #include "erljs_code/gen_event.beam.js" 33 | #include "erljs_code/gen_fsm.beam.js" 34 | #include "erljs_code/gen_server.beam.js" 35 | #include "erljs_code/error_logger.beam.js" 36 | 37 | #include "erljs_code/tests_auto.beam.js" 38 | #include "tests_auto.js" 39 | 40 | #include "erljs_code/genser_test.beam.js" 41 | #include "erljs_code/genser_test2.beam.js" 42 | 43 | #include "erljs_code/erl_internal.beam.js" 44 | #include "erljs_code/erl_scan.beam.js" 45 | #include "erljs_code/erl_parse.beam.js" 46 | #include "erljs_code/erl_lint.beam.js" 47 | #include "erljs_code/erl_eval.beam.js" 48 | #include "erljs_code/erl_pp.beam.js" 49 | 50 | #include "erljs_code.js" 51 | 52 | #include "erljs_datatypes.js" 53 | #include "erljs_vm.js" 54 | #include "erljs_scheduler_list.js" 55 | #include "erljs_scheduler.js" 56 | #include "erljs_control.js" 57 | 58 | #include "javascript-stacktrace/stacktrace.js" 59 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Copyright, Witold Baryluk, 2009,2010,2011 2 | 3 | This code is currently licensed under LGPL. 4 | 5 | If you will contriubte to this project you permit me, 6 | Witold Baryluk to switch to any other license 7 | of all files including your contributions. 8 | (Old codes, repositories and releases will 9 | be available still under LGPL). I'm 10 | guaranting that authors names will be not be removed, 11 | and will be advertised. 12 | This is only about patches or any other enhancments you 13 | send me. By sending them you approve above statments. 14 | If you want to develop this program with accordance of 15 | GPL and continue to do so without "fear" of lossing 16 | your work, you can at any point "fork" this project 17 | and develop it without me. 18 | 19 | Files generated or produced by this project (like recompiled 20 | js files, vm machine, handlers, etc) are not licensced under GPL, 21 | similary like binaries produced by GCC isn't and can be used 22 | for any purpose. 23 | 24 | Exception is vm machine which is still licensced GPL, 25 | without above notes. This is so even if vm machine code 26 | is embeded in one file with another code or data. 27 | 28 | Parts borrowed from the Erlang, like some modified modules (lists,...) 29 | are licensed according to their license and are not part of this project. 30 | The patches which implements missing functionality (which wasn't there, 31 | even in comments), is part of this project. 32 | 33 | No part of this project which implementes some Erlang 34 | funcionality in the JavaScript or in compiler by rewriting 35 | to special bytecode, JavaScript, recompilation or interpretation, 36 | have been writen using more than just erlang documentation 37 | (manual pages) and the observing behaiour of Erlang. 38 | This include even obscure opcodes like trim, or hard functions 39 | like erlang:phash/2, erlang:term_to_binary/1 and others. 40 | All of them have been reversed enginered without looking 41 | at any Erlang or C source files of Erlang/OTP project. 42 | 43 | 44 | Hopefully when this project gets shape I will release it using 45 | some more free licencse. 46 | 47 | -------------------------------------------------------------------------------- /TESTING: -------------------------------------------------------------------------------- 1 | We can perform testing in many ways. 2 | 3 | We would like to have testing which: 4 | - is highly automatic in performing 5 | - can test wide spectrum of modules and functins 6 | - should test behaviour with respect to original implementation 7 | - should test many possible code paths and conditions 8 | 9 | This leads use to the case that we should have tests which are 10 | automatically generated, and they if possible should be randomized. 11 | 12 | They should be automatically run and compared with reference implementation. 13 | 14 | For full automaticity we can run something on the server, 15 | like Rhino or SpiderMonkey. We then can run it from script 16 | with specific tests, then run also them in Erlang, and compare 17 | using Erlang or some script. 18 | 19 | We can eventually do this by spawning JS engine as Erlang port, 20 | and send there commands. 21 | 22 | We can also have webbrowser which will run them and upload 23 | results using POST. 24 | 25 | Other possibility is to imlement Erlang distributed protocol 26 | or some kind of emulation so it will be transparent 27 | to communicate beetwen the two nodes with normal Erlang 28 | message passing. 29 | 30 | Then it can be easly tested on both nodes. Randomized tests 31 | can easly be runned on the server or client side, 32 | and similary comparission can be performed both on server and client 33 | (we can have bugs in comparission code/implementation, 34 | or term decoding, or by incident, and the fact that we have 35 | same data in memory, something could go wrong). 36 | 37 | Most simple way will be to generate some tests on client (it will not 38 | stress server), or on server (to have really good randomnes for sure :D), 39 | then calculate both functions on both nodes (sending second one the needed 40 | arguments and other parameters), then compare them on client 41 | and show results. Client will also then report status of tests to the 42 | server (with also failed tests cases for logging purpose). 43 | If needed we can send all tests and their status and their results, 44 | and server will optionally verify it again if it is ok. 45 | -------------------------------------------------------------------------------- /PLATFORMS: -------------------------------------------------------------------------------- 1 | Most important web browsers we will like to test in, 2 | and have reasonable status. 3 | 4 | To be filled in and tested. 5 | 6 | Microsoft Internet Explorer 5.0 (Windows)* 7 | Microsoft Internet Explorer 5.2 (Mac)* 8 | Firefox 1.0 ... 8.0 9 | Opera 7.5 10 | Netscape 6.0 11 | Safari 1.2 12 | Camino 1.0 13 | Konqueror 3.4 14 | 15 | Opera 8.0 16 | Opera 9.0 17 | Opera 9.50 18 | Opera 10.0 19 | Opera 10.10 20 | Opera 10.50 21 | Opera 10.60 22 | Opera 11.0 23 | Opera 11.52 24 | Opera 11.60 25 | 26 | 27 | Internet Explorer 6 28 | Internet Explorer 7 29 | Internet Explorer 8 30 | Internet Explorer 9 31 | 32 | Chrome 1.0 .. 13 33 | 34 | Safari 35 | 36 | Epiphany 37 | 38 | 39 | http://andrewdupont.net/test/double-dollar/ 40 | 41 | 42 | 43 | 44 | 45 | Similary we can test engines, instead of browsers 46 | 47 | 48 | standalone or embedable engines: 49 | 50 | node - nodejs (korzysta z v8, tego co w Chromium/Chrome, napisany w C++ przez Google) 51 | smjs - spidermonkey-bin (korzysta z spidermonkey, tego co w Firefox/Iceweasel, napisany w C++ przez Mozilla. w rzeczywistosci jest to tracemonkey chyba juz) 52 | rhino - rhino (oddzielne implementacja, napisana w Java przez Mozilla) 53 | ds - dmdscript (implementacja ECMA 232, napisana w D, lub C++, przez DigitalMars) 54 | jscript - tylko windows w IE (trident) i WSH (niezaleznie) 55 | jscript .net 56 | njs - niezalezny silnik JS, ostatnie wydanie 2009 57 | 58 | in-browser engines: 59 | 60 | spidermonkdey/tracemonkey - firefox 2.0, 3.0, 3.5, 3.6, 4.0, 5.0 61 | v8 - chromium , 7, 8, 9, 10, 11, 12, 13 62 | presto+linear_a,linear_b,futhark,caraken - opera 6.12, 7.0, 8.0, 9.0, 9.27, 9.50, 10, 10.20, 10.50, 11, 11.10, 11.50 63 | trident - internet explorer 6, 7, 8, 9 64 | webkit - safari 5 65 | khtml - konqueror (3.0, 3.5, 4.0, 4.1, 4.2, 4.3, 4.4, 4.5, 4.6) 66 | kjs - konqueror 67 | webkit / apple javascriptcore 68 | elinks - uzywa spidermonkey lub njs 69 | 70 | derivative browsers: 71 | 72 | galeon - gecko 73 | k-meleon - gecko 74 | maxthon - gecko / trident / webkit 75 | flock - gecko 76 | camino - gecko 77 | netscape - gecko 78 | mozilla suite - gecko 79 | seamonkey - gecko 80 | abrowse - khtml 81 | arora - webkit 82 | midori - webkit 83 | epiphany - gecko / webkit 84 | kazehakase - gecko / apple webcore 85 | rekonq - webkit 86 | -------------------------------------------------------------------------------- /examples/genser_calculatepi.erl: -------------------------------------------------------------------------------- 1 | -module(genser_calculatepi). 2 | -author('baryluk@smp.if.uj.edu.pl'). 3 | 4 | % Copyright 2009-2011, Witold Baryluk 5 | % erljs project 6 | 7 | -behaviour(gen_server). 8 | 9 | -export([start/1, start_link/1]). 10 | -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). 11 | 12 | -export([calculate_pi/3]). 13 | 14 | % starting api 15 | 16 | start(Args = {Przycisk, Pole}) -> 17 | gen_server:start({local, Pole}, ?MODULE, Args, []). 18 | start_link(Args = {Przycisk, Pole}) -> 19 | gen_server:start_link({local, Pole}, ?MODULE, Args, []). 20 | 21 | % gen_server interface 22 | 23 | init({Przycisk, Pole}) -> 24 | {ok, _} = erljs:listen(Przycisk, click, [], {start}), 25 | {ok, _} = erljs:listen(przycisk_pi_start12, click, [], {start}), 26 | erljs:set(Pole, value, {initialized, ?MODULE, Przycisk, Pole, self()}), 27 | {ok, {Pole, 0.0, 1}}. 28 | 29 | handle_call(_, _From, _State) -> 30 | wrong. 31 | 32 | handle_cast(_, _State) -> 33 | wrong. 34 | 35 | % Madhava–Leibniz series 36 | % pi = 4 sum_{i=0}^\infty (-1)^i / (2i+1) 37 | % its convergence is slow, but we do not care 38 | calculate_pi(Pass, Pole, N) -> 39 | 4.0*calculate_pi(Pass, Pole, 0.0, 1.0, 1, 2*N+1, 0). 40 | 41 | calculate_pi(Pass, Pole, X, S, I, N, 200) -> 42 | erljs:set(Pole, value, {partial, Pass, I, 4.0*X}), 43 | calculate_pi(Pass, Pole, X, S, I, N, 0); 44 | calculate_pi(Pass, _Pole, X, _S, I, I, _) -> 45 | X; 46 | calculate_pi(Pass, Pole, X, S, I, N, K) -> 47 | calculate_pi(Pass, Pole, X + S/I, -S, I+2, N, K+1). 48 | 49 | -define(EXACT_PI, 3.141592653589793). 50 | 51 | handle_info({dom, _Id, _Ref, _Type, _Value, {start}} = _E, State = {Pole, _, Pass}) -> 52 | %N = erljs:set(pole_pi_in, value), 53 | erljs:set(Pole, value, "Calculation started..."), 54 | StartTime = erlang:now(), 55 | S = calculate_pi(Pass, Pole, 100000), 56 | EndTime = erlang:now(), 57 | erljs:set(Pole, value, {done, Pass, S, ?EXACT_PI - S, timer:now_diff(EndTime, StartTime) / 1000000.0}), 58 | {noreply, {Pole, S, Pass+1}}; 59 | handle_info(M, State = {Pole, _, _Pass}) -> 60 | erljs:set(Pole, value, {unknown_msg, M}), 61 | {noreply, State}. 62 | 63 | terminate(normal, _State) -> 64 | ok. 65 | 66 | code_change(_OldVersion, State, _Extra) -> {ok, State}. 67 | 68 | -------------------------------------------------------------------------------- /WAYS: -------------------------------------------------------------------------------- 1 | -1 run erlang using some kind of plugin 2 | - hard 3 | - not portable 4 | - not safe 5 | - will need additional user interaction 6 | 7 | 0 .erl to .js translation using own tools 8 | - very hard and very stupid. 9 | 10 | 1 .erl to .js direct translation using Erlang parsing tools 11 | - very hard 12 | - there is many features in Erlang, 13 | - patterns to be reimplemented, 14 | - bit strings 15 | - optimalisations 16 | * we can implement how we want it. 17 | + best possible performance 18 | 19 | 2 interpretatin of .beam in JS. 20 | - not so possible becuase .beam is binary, and 21 | - there is problems with handling binary data or files in javascript. 22 | - slow becuase of binary/text conversins and interpretation 23 | 24 | 3 .beam to .js translation using Erlang disasembler + code generation 25 | * moderatly simple 26 | * tricky tail recursion (but loop reconstruction, birecursion and general trampoline code isn't so hard) 27 | + executed code will be native js and can be JITed quite easly 28 | + beyond removing most of opcodes we can compact it even more 29 | use local variables, 30 | code merging for size compactnes, 31 | change registers to logical variables. 32 | + moderatly fast 33 | 34 | 4 .beam to simple (new) bytecode embeded in js and interpretation of it. 35 | + very simple 36 | + very simple tail recursion and practically al features 37 | - we need to implement most of BIF and opcodes from original BEAM in JS, so quit big VM 38 | + we can easily simplifiy and compress some opcodes 39 | merge call_ext, call_lists ? 40 | remove allocate/test_heap) 41 | - quit slow, as executed code can't be JIT'ed so easly. 42 | 43 | 5 translation to other language which can be run or translated to javascript. 44 | - probably slow, not such language i know. 45 | 46 | 47 | In all ways we will need to implement many native js functin for BIFs, erlang:*, 48 | few functions in lists:* for performance and completnes. There is multiple 49 | versions of BIFs (gc_bif, bif, call_ext, call_lists), so it isn't so simple. 50 | 51 | I choosen #4, it can be implemented quickly and allows us to support rich number 52 | of fetures. #3 is usefull mainly becuase of performance, so we would like 53 | to use it in places where it is advisable. Implementation of 4 allow also 54 | to discover internal VM machinery in simple steps without even looking 55 | into original C source codes. 56 | 57 | -------------------------------------------------------------------------------- /examples/example_advanced_page.erljs: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | -author('baryluk@smp.if.uj.edu.pl'). 11 | -record(state, {counter, name}). 12 | 13 | % Copyright 2008-2011, Witold Baryluk 14 | % erljs project 15 | 16 | is_valid({A,B}) when is_integer(A), is_integer(B) -> true; 17 | is_valid(_) -> false. 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | init() -> 28 | Server = fabric:remote_whereis(clicker_logger), 29 | Pid = spawn(fun() -> loop(#state{}, Server) end), 30 | register(Pid, bzz), 31 | ok. 32 | 33 | loop(State, Server) -> 34 | receive 35 | {dom, E, _, click, _, {mydata,X}} -> 36 | V = erljs_dom:get_value(status), 37 | case is_valid(V) of 38 | true -> 39 | erljs:disable(E), 40 | erljs:append(status, {clicked, X, V}), 41 | Server ! {self(), clicked, X, V}, 42 | receive 43 | {Server, Msg} -> 44 | erljs:alert(Msg) 45 | end; 46 | false -> 47 | erljs:alert("Please specify valid input. It must be a term of the form {integer(),integer()}") 48 | end, 49 | loop(State, Server); 50 | _ -> 51 | erljs:set(status, "Unknown message received. quiting."), 52 | error 53 | end. 54 | 55 | 56 | 57 | server_init() -> 58 | Pid = spawn(fun() -> server_loop(#state{}) end), 59 | register(Pid, clicker_logger), 60 | fabric:allow(clicker_logger), 61 | ok. 62 | 63 | server_loop(State = #state{counter=Counter}) -> 64 | receive 65 | {Client, clicked, X, V} -> 66 | case is_valid(V) of 67 | true -> 68 | {A, B} = V, 69 | io:format("Client ~p (~p) clicked button ~p~n", [Client, fabric:info(Client), X]), 70 | Client ! {self(), {A + X*X, B + X*X*X, Counter}}, 71 | server_loop(State#server{counter=Counter+1}); 72 | false -> 73 | io:format("Client ~p (~p) send invalid context V = ~p~n", [Client, fabric:info(Client), V]), 74 | server_loop(State) 75 | end; 76 | {'EXIT', Client, Why} -> 77 | io:format("Client ~p (~p) terminated ~p~n", [Client, fabric:info(Client), Why]), 78 | server_loop(State) 79 | end. 80 | 81 | % for similar example, but which persists accross refreshes (by using cookies) 82 | % http://yaws.hyber.org/cookies.yaws 83 | % http://yaws.hyber.org/pcookie.yaws (version which saves process state into the ets/dets for persitance) 84 | % 85 | % best way is a hybrid approach: 86 | % live server process for a while, or until session is destroyed 87 | % if nothing happens, go into hibernation, and setup timer for a slightly more time 88 | % if nothing happens, in this time, notify deregistering process, and save into ets/dets/mnesia proper state 89 | % 90 | 91 | 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /examples/genser_manybuttons.erl: -------------------------------------------------------------------------------- 1 | -module(genser_manybuttons). 2 | -author('baryluk@smp.if.uj.edu.pl'). 3 | 4 | % Copyright 2009-2011, Witold Baryluk 5 | % erljs project 6 | 7 | -behaviour(gen_server). 8 | 9 | -export([start/0, start_link/0]). 10 | -export([stop/0]). 11 | -export([alloc/0, free/1]). 12 | -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). 13 | 14 | % starting api 15 | 16 | start() -> 17 | gen_server:start({local, ?MODULE}, ?MODULE, [], []). 18 | start_link() -> 19 | gen_server:start_link({local, ?MODULE}, ?MODULE, [], []). 20 | 21 | % external interface 22 | 23 | alloc() -> 24 | gen_server:call(?MODULE, alloc). 25 | free(Ch) -> 26 | gen_server:cast(?MODULE, {free, Ch}). 27 | stop() -> 28 | gen_server:cast(?MODULE, stop). 29 | 30 | % gen_server interface 31 | 32 | init(_Args) -> 33 | {ok, _} = erljs:listen(przycisk1, click, [], {}), 34 | {ok, _} = erljs:listen(przycisk2, click, [], {}), 35 | {ok, _} = erljs:listen(digits_clear, click, [], {clear}), 36 | Digits = [ 37 | {digit1, 1}, 38 | {digit2, 2}, 39 | {digit3, 3}, 40 | {digit4, 4}, 41 | {digit5, 5}, 42 | {digit6, 6}, 43 | {digit7, 7}, 44 | {digit8, 8}, 45 | {digit9, 9}, 46 | {digit0, 0}], 47 | [ {ok, _} = erljs:listen(Id, click, [], {digitsX, Digit}) || {Id, Digit} <- Digits ], 48 | % {ok, channels()}. 49 | erljs:set(pole1, value, {initialized, ?MODULE, self()}), 50 | {ok, []}. 51 | 52 | handle_call(alloc, _From, Chs) -> 53 | case alloc(Chs) of 54 | {void, Chs2} -> {reply, void, Chs2}; 55 | {Ch, Chs2} -> {reply, Ch, Chs2} 56 | end. 57 | 58 | handle_cast({free, Ch}, Chs) -> 59 | Chs2 = free(Ch, Chs), 60 | {noreply, Chs2}; 61 | handle_cast(stop, State) -> 62 | {stop, normal, State}. 63 | 64 | handle_info({dom, _Id, _Ref, _Type, _Value, {digitsX, D}} = _E, State) -> 65 | State2 = [$0+D|State], 66 | erljs:set(pole1, value, State2), 67 | {noreply, State2}; 68 | handle_info({dom, _Id, _Ref, _Type, _Value, {clear}} = _E, _State) -> 69 | State2 = [], 70 | erljs:set(pole1, value, State2), 71 | {noreply, State2}; 72 | handle_info({dom, _Id, _Ref, _Type, _Value, _} = E, State) -> 73 | erljs:set(pole1, value, {received_dom_event, erlang:localtime(), erlang:now(), E}), 74 | {noreply, State}; 75 | handle_info({'EXIT', _Pid, _Reason}, State) -> 76 | {noreply, State}; 77 | handle_info(M, State) -> 78 | erljs:set(pole1, value, {unknown_msg, M}), 79 | {noreply, State}. 80 | 81 | terminate(normal, _State) -> 82 | ok. 83 | 84 | code_change(_OldVersion, State, _Extra) -> {ok, State}. 85 | 86 | % internal api 87 | 88 | channels() -> 89 | {_Allocated = [], _Free = lists:seq(1,10)}. 90 | 91 | alloc({Allocated, [H|T] = _Free}) -> 92 | {H, {[H|Allocated], T}}; 93 | alloc({_Allocated, []} = Channels) -> 94 | {void, Channels}. 95 | 96 | free(Ch, {Alloc, Free} = Channels) -> 97 | case lists:member(Ch, Alloc) of 98 | true -> 99 | {lists:delete(Ch, Alloc), [Ch|Free]}; 100 | false -> 101 | Channels 102 | end. 103 | -------------------------------------------------------------------------------- /erl_src/erljs_compile_all.erl: -------------------------------------------------------------------------------- 1 | -module(erljs_compile_all). 2 | -author('baryluk@smp.if.uj.edu.pl'). 3 | 4 | % Copyright 2009-2011, Witold Baryluk 5 | % erljs project 6 | 7 | -export([ca/0, ca/1]). 8 | 9 | 10 | -spec ca() -> 11 | [{'ok', [any(), ...], [any(), ...]}]. 12 | 13 | % compile all standard modules 14 | ca() -> 15 | ca([]). 16 | 17 | -spec ca([atom() | {atom(), _} | {'d', atom(), _}]) -> 18 | [{'ok', [any(), ...], [any(), ...]}]. 19 | 20 | ca(Opts) -> 21 | L = 22 | [ "examples/devel/" ++ atom_to_list(M) ++ ".erl" || M <- [ 23 | example, 24 | example_binaries, 25 | example_eh, 26 | example_floats, 27 | example_funs, 28 | example_messages 29 | ] ] 30 | ++ 31 | [ "erl_lib_core/stdlib/src/" ++ atom_to_list(M) ++ ".erl" || M <- [ 32 | %math, 33 | array, 34 | base64, 35 | binary, 36 | calendar, 37 | random, 38 | lists, 39 | orddict, 40 | ordsets, 41 | string, 42 | unicode, 43 | queue, 44 | dict, 45 | proplists, 46 | sets, 47 | sofs, 48 | gb_trees, 49 | gb_sets, 50 | regexp 51 | ] ] 52 | ++ 53 | [ "erl_lib_core/stdlib/src/" ++ atom_to_list(M) ++ ".erl" || M <- [ 54 | supervisor, 55 | supervisor_bridge, 56 | proc_lib, 57 | gen, 58 | gen_event, 59 | gen_fsm, 60 | gen_server, 61 | 62 | sys, 63 | 64 | pg, 65 | pool, 66 | %slave, 67 | 68 | lib, 69 | 70 | io, 71 | io_lib, 72 | io_lib_format, 73 | io_lib_fread, 74 | io_lib_pretty, 75 | 76 | error_logger_file_h, 77 | error_logger_tty_h, 78 | log_mf_h, 79 | 80 | filelib, 81 | filename, 82 | 83 | edlin, 84 | edlin_expand, 85 | 86 | shell, 87 | shell_default, 88 | c, 89 | epp, 90 | eval_bits, 91 | erl_bits, % potrzebne includy 92 | erl_compile, % potrzebne includy 93 | erl_eval, 94 | erl_expand_records, 95 | erl_internal, 96 | erl_lint, 97 | erl_parse, 98 | erl_posix_msg, 99 | erl_pp, 100 | erl_scan, 101 | erl_tar, 102 | beam_lib, 103 | 104 | ms_transform, 105 | 106 | timer, 107 | ets, 108 | dets, 109 | dets_server, 110 | dets_sup, 111 | dets_utils, 112 | dets_v8, 113 | dets_v9, 114 | qlc, 115 | qlc_pt, 116 | 117 | digraph, 118 | digraph_utils, 119 | 120 | otp_internal 121 | 122 | % zip 123 | ] ] 124 | ++ 125 | [ "erl_lib_core/kernel/src/" ++ atom_to_list(M) ++ ".erl" || M <- [ 126 | error_logger 127 | ] ] 128 | ++ 129 | [ "erl_lib_core/erts/src/" ++ atom_to_list(M) ++ ".erl" || M <- [ 130 | erlang, 131 | otp_ring0, 132 | init 133 | % erl_prim_loader 134 | ] ] 135 | ++ 136 | [ 137 | "erl_lib_core/erts/ebin-org/erl_prim_loader.beam" 138 | ] 139 | ++ 140 | [ 141 | "erl_src/erljs_kernel.erl" 142 | ] 143 | ++ 144 | [ "tests/" ++ atom_to_list(M) ++ ".erl" || M <- [ 145 | % tests_auto, 146 | random_term 147 | ] ] 148 | ++ 149 | [ "examples/" ++ atom_to_list(M) ++ ".erl" || M <- [ 150 | gensup_test, 151 | genser_manybuttons, 152 | genser_calculatepi 153 | ] ], 154 | 155 | 156 | Opts2 = [ 157 | {i, "erl_lib_core/kernel/include"}, 158 | {i, "erl_lib_core/stdlib/include"} 159 | ], 160 | erljs_compiler:cl(L, Opts ++ Opts2). 161 | -------------------------------------------------------------------------------- /erl_lib_core/lists-erl.patch: -------------------------------------------------------------------------------- 1 | --- /usr/lib/erlang/lib/stdlib-1.17.5/src/lists.erl 2011-10-25 16:13:43.000000000 +0200 2 | +++ stdlib/src/lists.erl 2011-12-18 07:59:14.000000000 +0100 3 | @@ -21,6 +21,8 @@ 4 | -compile({no_auto_import,[max/2]}). 5 | -compile({no_auto_import,[min/2]}). 6 | 7 | +-compile_erljs([export_all]). 8 | + 9 | -export([append/2, append/1, subtract/2, reverse/1, 10 | nth/2, nthtail/2, prefix/2, suffix/2, last/1, 11 | seq/2, seq/3, sum/1, duplicate/2, min/1, max/1, sublist/2, sublist/3, 12 | @@ -36,6 +38,9 @@ 13 | %% Bifs: member/2, reverse/2 14 | %% Bifs: keymember/3, keysearch/3, keyfind/3 15 | 16 | +-export([member/2, reverse/2]). 17 | +-export([keymember/3, keysearch/3, keyfind/3]). 18 | + 19 | -export([merge/3, rmerge/3, sort/2, umerge/3, rumerge/3, usort/2]). 20 | 21 | -export([all/2,any/2,map/2,flatmap/2,foldl/3,foldr/3,filter/2, 22 | @@ -47,10 +52,10 @@ 23 | %% test if X is a member of the list L 24 | %% Now a BIF! 25 | 26 | -%member(X, [X|_]) -> true; 27 | -%member(X, [_|Y]) -> 28 | -% member(X, Y); 29 | -%member(X, []) -> false. 30 | +member(X, [X|_]) -> true; 31 | +member(X, [_|Y]) -> 32 | + member(X, Y); 33 | +member(X, []) -> false. 34 | 35 | %% append(X, Y) appends lists X and Y 36 | 37 | @@ -100,9 +105,9 @@ 38 | reverse([A, B | L]) -> 39 | lists:reverse(L, [B, A]). 40 | 41 | -%reverse([H|T], Y) -> 42 | -% reverse(T, [H|Y]); 43 | -%reverse([], X) -> X. 44 | +reverse([H|T], Y) -> 45 | + reverse(T, [H|Y]); 46 | +reverse([], X) -> X. 47 | 48 | 49 | %% nth(N, L) returns the N`th element of the list L 50 | @@ -593,22 +598,22 @@ 51 | %% keymap(Function, Index, [Tuple]) 52 | %% keymap(Function, ExtraArgs, Index, [Tuple]) 53 | 54 | -%keymember(K,N,L) when is_integer(N), N > 0 -> 55 | -% keymember3(K,N,L). 56 | +keymember(K,N,L) when is_integer(N), N > 0 -> 57 | + keymember3(K,N,L). 58 | 59 | -%keymember3(Key, N, [T|Ts]) when element(N, T) == Key -> true; 60 | -%keymember3(Key, N, [T|Ts]) -> 61 | -% keymember3(Key, N, Ts); 62 | -%keymember3(Key, N, []) -> false. 63 | - 64 | -%keysearch(K, N, L) when is_integer(N), N > 0 -> 65 | -% keysearch3(K, N, L). 66 | - 67 | -%keysearch3(Key, N, [H|T]) when element(N, H) == Key -> 68 | -% {value, H}; 69 | -%keysearch3(Key, N, [H|T]) -> 70 | -% keysearch3(Key, N, T); 71 | -%keysearch3(Key, N, []) -> false. 72 | +keymember3(Key, N, [T|Ts]) when element(N, T) == Key -> true; 73 | +keymember3(Key, N, [T|Ts]) -> 74 | + keymember3(Key, N, Ts); 75 | +keymember3(Key, N, []) -> false. 76 | + 77 | +keysearch(K, N, L) when is_integer(N), N > 0 -> 78 | + keysearch3(K, N, L). 79 | + 80 | +keysearch3(Key, N, [H|T]) when element(N, H) == Key -> 81 | + {value, H}; 82 | +keysearch3(Key, N, [H|T]) -> 83 | + keysearch3(Key, N, T); 84 | +keysearch3(Key, N, []) -> false. 85 | 86 | -spec keydelete(Key, N, TupleList1) -> TupleList2 when 87 | Key :: term(), 88 | @@ -2743,3 +2748,13 @@ 89 | lists:reverse(T1, [H1, H2M | M]) 90 | end. 91 | 92 | + 93 | +keyfind(Key, N, L) when is_integer(N), is_list(L) -> 94 | + keyfind3(Key, N, L). 95 | + 96 | +keyfind3(Key, N, []) -> false; 97 | +keyfind3(Key, N, [Tuple|Tail]) -> 98 | + case element(N, Tuple) of 99 | + Key -> Tuple; 100 | + _ -> keyfind3(Key, N, Tail) 101 | + end. 102 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | erljs - Run Erlang in JavaScript 2 | 3 | This projects allows you to run Erlang code directly 4 | in the webbrowser! 5 | 6 | If you do not know what Erlang is, please read: 7 | http://www.erlang.org/ - Erlang programming language home page 8 | http://en.wikipedia.org/wiki/Erlang_(programming_language) 9 | 10 | In short, it is functional language designed for fault-tolerant 11 | and concurrant systems. Because of its design it also fits 12 | nicely as language of choice for modern dynamic web pages. 13 | 14 | 15 | You will find examples in examples/ directory. 16 | 17 | Some motivation can be find in STATUS 18 | 19 | 20 | 21 | Status 22 | 23 | Currently we have pretty good implementation of some 24 | basic stuffs. Some modules seems to be fully functional. 25 | 26 | What is working: 27 | 28 | - data types: atom, integer, float, tuple, list. 29 | - to do: funs make_fun2 30 | - arithmetic 31 | - pattern matching and tests 32 | - tuple operations 33 | - list operations 34 | - calling functions, from the same and other modules, with and without fqn, 35 | - funs 36 | - lists comprehension (without bitstring generators), 37 | - tail recursion 38 | - spawning processes, and message passing, scheduler, 39 | - exceptions, stack trace for exceptions (not yet fully correct). 40 | 41 | Differences: 42 | - messages are passed using references 43 | - scheduler is designed for small number of processes, so do not run more than 200 processes 44 | - integer arithmetic is limited to 2^53 45 | - i have simple biginteger.js library, but i would want to make overhead for small integers small, 46 | - i also want to remove from it some unneded parts for us. 47 | - after overflow 48 | - operations on floats and intergers can be intermixed. 49 | - for example one can `F rem 10`, even when F is float. 50 | - float exceptions aren't checked and thrown 51 | - JS have floating point exceptions disabled, but Erlang have them enabled, emulation will be slow. 52 | - so it is possible to have NaN, +-Inf, or underfloat in variables. 53 | - possible solution: add erljs:check_nan(X) test a variable. 54 | - erlang:now/0 have 1ms real resolution, in some cases about 15ms (Windows XP). 55 | (erljs will use 1us resolution timer in Chrome started with --enable-benchmkaring, 56 | it is however only accurate for measuring relative times) 57 | 58 | 59 | Both Erlang and JS are dynamically typed languages. Unfortunettelly JS is weakly typed, 60 | but Erlang is strongly typed. This means that we need to perform some additional 61 | checks in JS to be sure that types are correct. There is also problem 62 | with boxing/unboxing on JS side, but this should work automatically. 63 | Most important problem is that JavaScript doesn't have arbitrar sized integers, 64 | and the fact that JS doesn't have separate integer and float types. 65 | 66 | Currently bignums and integers are really floats! On some 67 | operations we know will result in floats but we want integer 68 | we perform rounding/truncation, but this can be buggy for 69 | sufficientyl big numbers. 70 | 71 | Todo: 72 | - bit strings, 73 | - tracing, 74 | - phash, 75 | - cleanup, 76 | - dynamic module loading. 77 | - lots of other small things, see TODO file 78 | 79 | 80 | Tested mainly in Opera 10.52 on Linux. Some tests in Chrome and Epiphany also. 81 | 82 | Should also work in Rhino (Mozilla's JS engine written in Java). Usefull 83 | for unittesting, etc. 84 | 85 | http://www.erlang.se/~bjorn/beam_file_format.html 86 | 87 | -------------------------------------------------------------------------------- /tests/random_term.erl: -------------------------------------------------------------------------------- 1 | -module(random_term). 2 | -author('baryluk@smp.if.uj.edu.pl'). 3 | 4 | % Copyright 2009-2011, Witold Baryluk 5 | % erljs project 6 | 7 | 8 | -export([ 9 | any_term/1, 10 | any/1 11 | ]). 12 | 13 | any(Seed) -> 14 | {_, X} = any_term(Seed), 15 | X. 16 | 17 | next_seed(Seed) -> 18 | random:uniform_s(10000000,Seed). 19 | 20 | any_term(Seed) -> 21 | {X, Seed2} = next_seed(Seed), 22 | any_term(X, Seed2). 23 | 24 | any_term(X, Seed) when (0 =< X), X =< 10 -> 25 | atom_term(Seed); 26 | any_term(X, Seed) when (11 =< X), X =< 20 -> 27 | integer_term(Seed); 28 | any_term(X, Seed) when (21 =< X), X =< 30 -> 29 | float_term(Seed); 30 | any_term(X, Seed) when (31 =< X), X =< 40 -> 31 | nil_term(Seed); 32 | any_term(X, Seed) when (41 =< X), X =< 50 -> 33 | stringlist_term(Seed); 34 | any_term(X, Seed) when (51 =< X), X =< 52 -> 35 | binary_term(Seed); 36 | any_term(X, Seed) when (53 =< X), X =< 54 -> 37 | ref_term(Seed); 38 | any_term(X, Seed) when (55 =< X), X =< 56 -> 39 | pid_term(Seed); 40 | any_term(X, Seed) when (57 =< X), X =< 58 -> 41 | port_term(Seed); 42 | 43 | any_term(X, Seed) when (59 =< X), X =< 67 -> 44 | tuple_term(Seed); 45 | 46 | any_term(X, Seed) when (68 =< X), X =< 70 -> 47 | anylist_term(Seed); 48 | any_term(X, Seed) when (71 =< X), X =< 75 -> 49 | nonemptylist_term(Seed); 50 | any_term(X, Seed) when (76 =< X), X =< 78 -> 51 | improperlist_term(Seed); 52 | any_term(X, Seed) when (79 =< X), X =< 81 -> 53 | properlist_term(Seed); 54 | 55 | any_term(X, Seed) when X >= 82 -> 56 | any_term(X rem 82, Seed). 57 | 58 | atom_term(Seed1) -> 59 | {X, Seed2} = next_seed(Seed1), 60 | {Seed3, A} = lists:foldl( 61 | fun (_I, {S, L}) -> 62 | {H, S2} = next_seed(S), 63 | H2 = 20 + (H rem 100), 64 | {S2, [H2|L]} 65 | end, 66 | {Seed2, []}, 67 | lists:seq(1, X rem 5) 68 | ), 69 | {Seed3, list_to_atom(A)}. 70 | 71 | tuple_term(Seed1) -> 72 | {X, Seed2} = next_seed(Seed1), 73 | {Seed3, T} = lists:foldl( 74 | fun (_I, {S, L}) -> 75 | {S2, H} = any_term(S), 76 | {S2, [H|L]} 77 | end, 78 | {Seed2, []}, 79 | lists:seq(1, X rem 12) 80 | ), 81 | {Seed3, list_to_tuple(T)}. 82 | 83 | properlist_term(Seed1) -> 84 | {X, Seed2} = next_seed(Seed1), 85 | {Seed3, T} = lists:foldl( 86 | fun (_I, {S, L}) -> 87 | {S2, H} = any_term(S), 88 | {S2, [H|L]} 89 | end, 90 | {Seed2, []}, 91 | lists:seq(1, X rem 12) 92 | ), 93 | {Seed3, T}. 94 | 95 | 96 | integer_term(Seed1) -> 97 | {X, Seed2} = next_seed(Seed1), 98 | {Seed2, (X rem 200) - 100}. 99 | 100 | float_term(Seed) -> 101 | {X, Seed2} = next_seed(Seed), 102 | {Seed2, (X rem 20000)/317.332 - 200}. 103 | 104 | nil_term(Seed) -> 105 | {Seed, []}. 106 | 107 | anylist_term(Seed1) -> 108 | {Seed2, H} = {Seed1, a}, %any_term(Seed1), 109 | {Seed3, T} = {Seed2, H}, %any_term(Seed2), 110 | {Seed3, [H|T]}. 111 | 112 | nonemptylist_term(Seed1) -> 113 | {Seed2, L} = properlist_term(Seed1), 114 | {Seed3, H} = any_term(Seed2), 115 | {Seed3, [H|L]}. 116 | 117 | improperlist_term(Seed) -> 118 | {Seed, [a,b|c]}. 119 | 120 | stringlist_term(Seed1) -> 121 | {X, Seed2} = next_seed(Seed1), 122 | {Seed3, A} = lists:foldl( 123 | fun (_I, {S, L}) -> 124 | {H, S2} = next_seed(S), 125 | H2 = 32 + (H rem 94), 126 | {S2, [H2|L]} 127 | end, 128 | {Seed2, []}, 129 | lists:seq(1, X rem 5) 130 | ), 131 | {Seed3, A}. 132 | 133 | binary_term(Seed) -> 134 | {Seed, {b,[i,n|a]}}. 135 | 136 | ref_term(Seed) -> 137 | {Seed, {r,[],f}}. 138 | 139 | pid_term(Seed) -> 140 | {Seed, {p,i}}. 141 | 142 | port_term(Seed) -> 143 | {Seed, {p}}. 144 | 145 | 146 | -------------------------------------------------------------------------------- /tests/tests_arithmetic: -------------------------------------------------------------------------------- 1 | % be sure that compiler doesn't optimize all this out 2 | begin 11+3 end. 3 | begin 11-3 end. 4 | begin 11-3 end. 5 | begin 0*0 end. 6 | begin 11*0 end. 7 | begin 0*11 end. 8 | begin 0*-11 end. 9 | begin -11*0 end. 10 | begin -11*1 end. 11 | begin 1*1 end. 12 | begin 11*1 end. 13 | begin 1*11 end. 14 | begin 1*-11 end. 15 | begin -1*-11 end. 16 | begin 1*-1 end. 17 | begin -1*-1 end. 18 | begin 11*3 end. 19 | begin 11*-3 end. 20 | begin -11*3 end. 21 | begin -11*-3 end. 22 | 23 | begin 3.3*4 end. 24 | begin 3.3*4.3 end. 25 | begin 3*4.3 end. 26 | begin -3.3*4 end. 27 | begin -3.3*4.3 end. 28 | begin -3*4.3 end. 29 | begin 3.3*-4 end. 30 | begin 3.3*-4.3 end. 31 | begin 3*-4.3 end. 32 | begin -3.3*-4 end. 33 | begin -3.3*-4.3 end. 34 | begin -3*-4.3 end. 35 | 36 | begin 0 / 1 end. 37 | begin 0 / 2 end. 38 | begin 0 / 3 end. 39 | begin 1 / 1 end. 40 | begin 1 / 2 end. 41 | begin 1 / 3 end. 42 | begin 10 / 1 end. 43 | begin 10 / 2 end. 44 | begin 11 / 2 end. 45 | begin 11 / 3 end. 46 | 47 | begin -0 / 1 end. 48 | begin -0 / 2 end. 49 | begin -0 / 3 end. 50 | begin -1 / 1 end. 51 | begin -1 / 2 end. 52 | begin -1 / 3 end. 53 | begin -10 / 1 end. 54 | begin -10 / 2 end. 55 | begin -11 / 2 end. 56 | begin -11 / 3 end. 57 | 58 | begin 0 / -1 end. 59 | begin 0 / -2 end. 60 | begin 0 / -3 end. 61 | begin 1 / -1 end. 62 | begin 1 / -2 end. 63 | begin 1 / -3 end. 64 | begin 10 / -1 end. 65 | begin 10 / -2 end. 66 | begin 11 / -2 end. 67 | begin 11 / -3 end. 68 | 69 | begin -0 / -1 end. 70 | begin -0 / -2 end. 71 | begin -0 / -3 end. 72 | begin -1 / -1 end. 73 | begin -1 / -2 end. 74 | begin -1 / -3 end. 75 | begin -10 / -1 end. 76 | begin -10 / -2 end. 77 | begin -11 / -2 end. 78 | begin -11 / -3 end. 79 | 80 | % todo: float / float, float / integer, integer / float 81 | 82 | begin 0 div 1 end. 83 | begin 0 div 2 end. 84 | begin 0 div 3 end. 85 | begin 1 div 1 end. 86 | begin 1 div 2 end. 87 | begin 1 div 3 end. 88 | begin 10 div 1 end. 89 | begin 10 div 2 end. 90 | begin 11 div 2 end. 91 | begin 11 div 3 end. 92 | 93 | begin -0 div 1 end. 94 | begin -0 div 2 end. 95 | begin -0 div 3 end. 96 | begin -1 div 1 end. 97 | begin -1 div 2 end. 98 | begin -1 div 3 end. 99 | begin -10 div 1 end. 100 | begin -10 div 2 end. 101 | begin -11 div 2 end. 102 | begin -11 div 3 end. 103 | 104 | begin 0 div -1 end. 105 | begin 0 div -2 end. 106 | begin 0 div -3 end. 107 | begin 1 div -1 end. 108 | begin 1 div -2 end. 109 | begin 1 div -3 end. 110 | begin 10 div -1 end. 111 | begin 10 div -2 end. 112 | begin 11 div -2 end. 113 | begin 11 div -3 end. 114 | 115 | begin -0 div -1 end. 116 | begin -0 div -2 end. 117 | begin -0 div -3 end. 118 | begin -1 div -1 end. 119 | begin -1 div -2 end. 120 | begin -1 div -3 end. 121 | begin -10 div -1 end. 122 | begin -10 div -2 end. 123 | begin -11 div -2 end. 124 | begin -11 div -3 end. 125 | 126 | 127 | begin 0 rem 1 end. 128 | begin 0 rem 2 end. 129 | begin 0 rem 3 end. 130 | begin 1 rem 1 end. 131 | begin 1 rem 2 end. 132 | begin 1 rem 3 end. 133 | begin 10 rem 1 end. 134 | begin 10 rem 2 end. 135 | begin 11 rem 2 end. 136 | begin 11 rem 3 end. 137 | 138 | begin -0 rem 1 end. 139 | begin -0 rem 2 end. 140 | begin -0 rem 3 end. 141 | begin -1 rem 1 end. 142 | begin -1 rem 2 end. 143 | begin -1 rem 3 end. 144 | begin -10 rem 1 end. 145 | begin -10 rem 2 end. 146 | begin -11 rem 2 end. 147 | begin -11 rem 3 end. 148 | 149 | begin 0 rem -1 end. 150 | begin 0 rem -2 end. 151 | begin 0 rem -3 end. 152 | begin 1 rem -1 end. 153 | begin 1 rem -2 end. 154 | begin 1 rem -3 end. 155 | begin 10 rem -1 end. 156 | begin 10 rem -2 end. 157 | begin 11 rem -2 end. 158 | begin 11 rem -3 end. 159 | 160 | begin -0 rem -1 end. 161 | begin -0 rem -2 end. 162 | begin -0 rem -3 end. 163 | begin -1 rem -1 end. 164 | begin -1 rem -2 end. 165 | begin -1 rem -3 end. 166 | begin -10 rem -1 end. 167 | begin -10 rem -2 end. 168 | begin -11 rem -2 end. 169 | begin -11 rem -3 end. 170 | -------------------------------------------------------------------------------- /praca/libs.txt: -------------------------------------------------------------------------------- 1 | General js libs: 2 | 3 | base2 4 | prototype.js 5 | jQuery 6 | dojo 7 | Closure 8 | mootools 9 | YUI 10 | http://developer.yahoo.com/yui/ 11 | YUI2 12 | http://developer.yahoo.com/yui/2/ 13 | YUI3 14 | http://developer.yahoo.com/yui/3/ 15 | UIZE 16 | http://www.uize.com/ 17 | 18 | 19 | Frameworki do RIA (rich internet applications): 20 | qooxdoo 21 | http://qooxdoo.org/ 22 | Mają fajny i wspaniały inspector: http://demo.qooxdoo.org/1.2.x/inspector/ 23 | Nie dużo, ale ładne widgety, stylowalne, w wielu językach. 24 | Ciekawe możliwości. 25 | openlaszlo 26 | Kompiluje do Flasha lub HTML+JS ! 27 | Aplikacje pisze się w xml'o języku łączącym html, widgety, stany, style i kod. 28 | QWT 29 | http://qooxdoo.org/contrib/project/qwt 30 | translate qooxdoo like Java to JavaScript! 31 | Similar to GWT 32 | Pustefix 33 | MVC based on qooxdoo. 34 | Views written in XML+XSLT. 35 | Automatyczna serializacja ajaxa do Javy, ze sprawdzaniem constrainów. 36 | http://pustefix-framework.org/ 37 | RAP 38 | http://eclipse.org/rap/ 39 | Dużo ciekawych aplikacji (np. mandżer dependenji eclipsa do łatwego ściągania, 40 | albo to http://migrate.numiton.com/ - konwerter PHP do Javy, w przyszłości innych jęyzków) 41 | Fajne Javowe kontrolki, i cała platforma. Kontrolki danowe, formularze, arkusze, drzewa, wizualizacje, mapy. 42 | Wydaje mi się że używają qooxdoo w warstwie prezentacyjnej! Poprostu dodalai więcej kontrolek i translacje z Javy. 43 | 44 | %http://caja.appspot.com/tools/index 45 | 46 | Compacting: 47 | http://www.julienlecomte.net/yuicompressor/ http://yuilibrary.com/projects/yuicompressor/ 48 | http://javascript.crockford.com/jsmin.html 49 | Google Closure Compiler (can perform very advanced transforms, like dead code elimination, inlineing, global var renaming) 50 | 51 | Compressing: 52 | http://jscompress.com/ 53 | http://dean.edwards.name/packer/ 54 | wersja w php http://joliclic.free.fr/php/javascript-packer/en/index.php 55 | wersja 3.1 http://base2.googlecode.com/svn/trunk/src/apps/packer/packer.html 56 | http://www.crockford.com/javascript/jsmin.html 57 | http://javascriptcompressor.com/ 58 | http://www.bananascript.com/index.php?compress 59 | - strips comments, white spaces, and performs aggressive dictionary compression 60 | 61 | http://razorsharpcode.blogspot.com/2010/02/lightweight-javascript-and-css.html 62 | http://shrinksafe.dojotoolkit.org/ 63 | 64 | Best to do: Google closure-compiler + dean.edwards packer with 'base62 encode' (but without 'shrink variable') 65 | 66 | http://www.alittlemadness.com/2010/06/03/javascript-compressor-comparison/ 67 | Packer 3.1 (s, p, 64) 68 | Google Closure (simple) 69 | YUI Compressor (2.4.2) 70 | Dojo Shrinksafe (1.4.3) 71 | JSMin (python) 72 | 73 | http://www.julienlecomte.net/blog/2007/08/13/ 74 | 75 | 76 | Minifiers: 77 | JSMin http://www.crockford.com/javascript/jsmin.html 78 | JS Minifier http://fmarcia.info/jsmin/test.html (JS version of JSMin) 79 | Dojo http://shrinksafe.dojotoolkit.org/ 80 | YUI http://developer.yahoo.com/yui/compressor/ 81 | Closure http://code.google.com/closure/compiler/ 82 | Caja http://caja.appspot.com/tools/index 83 | 84 | JSKB (strips dead code based on detecting browser, based on rules and heuristics of newer versions): 85 | http://www.browserscope.org/jskb/about 86 | http://google-caja.googlecode.com/svn/trunk/doc/html/jskb.html 87 | 88 | SSJS http://en.wikipedia.org/wiki/Server-side_JavaScript 89 | 90 | http://nodejs.org/ 91 | 92 | Linting: 93 | http://www.jslint.com/ 94 | http://jsutility.pjoneil.net/? 95 | http://www.javascriptlint.com/online_lint.php 96 | 97 | Analiza wydajności stron WWW 98 | Google Page Speed http://code.google.com/speed/page-speed/ 99 | Yahoo YSlow http://developer.yahoo.com/yslow/ 100 | 101 | JavaScript Lint - http://www.javascriptlint.com/ 102 | http://adsafe.org/ - Making JavaScript Safe for Advertising. 103 | "use strict"; - http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/ 104 | 105 | -------------------------------------------------------------------------------- /erl_src/erljs_widgets.erl: -------------------------------------------------------------------------------- 1 | -module(erljs_widgets). 2 | -author('baryluk@smp.if.uj.edu.pl'). 3 | 4 | % Copyright 2008-2011, Witold Baryluk 5 | % erljs project 6 | 7 | % Widgets: 8 | % 9 | % Accordion: 10 | % Options: 11 | % native height vs constant height 12 | % collapsable (all closed) or non-collapsable (at least one opened) 13 | % switch on click, on hover, or on inten-hover (hover for some small period) 14 | % dragable 15 | % which entry should be opened initially 16 | % automatic animation beetween entries (timeout dependant on the size, or not), ping-pong, or cyclic. 17 | % disable animation for longer period if user manually changed entry 18 | % customizable icon (or none), per entry for closed/opened? 19 | % fill vertical space vs fill horizontal space 20 | % possibility to remove entry using "x" 21 | % draging up/down entries 22 | % dynamically adding/removing/rearanging elements from script 23 | % 24 | % Tabs: 25 | % Options: 26 | % tabbar on top or bottom 27 | % collapsable (all closed) or non-collapsable (at least one opened) 28 | % similar, icons, 29 | % remember lastly opened tab 30 | % removable tab using "x" 31 | % animations on switching, automatic animations, unless user interacts with tabs 32 | % constant height (maximum) or optimal height 33 | % 34 | % Datepicker: 35 | % which date/month to select/show by default 36 | % internationalization (Sunday/Monday as first, format of date, name of week days) 37 | % possibility to easly restrict to some range of dates 38 | % possibility to easly restrict to some days of weeks 39 | % possibility to easly add single days exceptions 40 | % for example: 1-04-2010 - 5-09-2010, mon,tue,wed,thu, but not 29-05-2010. 41 | % possibility to mark each of this restrictions in own way (like outside of range or day of weeks it is invalid, but explicit exception shows as being already reserved) 42 | % this can be done by explicitly calling callback, for allowed range of dates, which should returnd "valid", "invalid" + style + optional tooltip + optional title/description to be show below when browing datapicker 43 | % possibility to show many month at once (for example in 2x3 grid) 44 | % suffixs 45 | % simple expressions, like "3 days ago", "next monday". 46 | % 47 | % Autocomplete: 48 | % multiple values 49 | % callback function, which can implement: 50 | % list, dict, communication with process, communication with server, caching, xml/json/ajax. 51 | % groups (if possible show 3 completions from 4 first groups) 52 | % values can have: value, title, description, group. 53 | % accent folding (searching for 'Jo', will return 'John', and als 'Jörn', but searching for 'Jö' will just return "Jörn') 54 | % 55 | % Buttons: 56 | % normal 'click' button 57 | % radio button (one of few is active), and they create a group 58 | % checkbox/toggle button (many of few can be active at once), and they create a group 59 | % left/right icon 60 | % label (it can be optional) 61 | % disabled state (cannot be clicked, and is in gray color) 62 | % tooltip 63 | % split button (like left text + right icon downward) 64 | % groups should be possible to be made both horizontally and veritically. 65 | % 66 | % Toolbar: 67 | % to contain buttons and groups of buttons in nice fashion. 68 | % 69 | % Slider: 70 | % horizontal or vertical 71 | % with fill from left or not 72 | % range slider 73 | % snap to increment 74 | % have buttons on both or one side 75 | % 76 | % Progressbar: 77 | % animated or none 78 | % of known progress or unknown progress. 79 | % simple spinner. 80 | % 81 | % Things to be done: 82 | % dnd: elements whicha can be sorted on a list 83 | % dnd: elements can be moved beetween lists 84 | % dnd: elements can be 85 | % 86 | % 87 | % animations: 88 | % any timeing function 89 | % animation based on time, not frames 90 | % repeating (cycling, pingpong) 91 | % animation of many things, like opacity, height, width, colors, fonts size, position. 92 | -------------------------------------------------------------------------------- /tools/make_links_for_core_otp_modules.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2009-2011, Witold Baryluk 4 | # erljs project 5 | 6 | ERL_TOP=${ERL_TOP:-/usr/lib/erlang} 7 | ERL_TOP_LIB="${ERL_TOP}/lib" 8 | 9 | 10 | MODULES="random string proplists dict gb_trees gb_sets orddict ordsets queue sets regexp" 11 | MODULES="${MODULES} sys proc_lib gen gen_event gen_fsm gen_server supervisor supervisor_bridge" 12 | MODULES="${MODULES} erl_bits erl_compile erl_eval erl_expand_records erl_internal erl_lint erl_parse erl_posix_msg erl_pp erl_scan erl_tar" 13 | MODULES="${MODULES} epp" 14 | MODULES="${MODULES} timer calendar array base64" 15 | MODULES="${MODULES} ets" 16 | # Note: do not add 'lists' module here. it needs to be patched at the end 17 | 18 | MODULES="array 19 | base64 20 | beam_lib 21 | binary 22 | calendar 23 | c 24 | dets dets_server dets_sup dets_utils dets_v8 dets_v9 25 | dict 26 | digraph digraph_utils 27 | edlin edlin_expand 28 | epp 29 | erl_bits erl_compile erl_eval erl_expand_records erl_internal erl_lint erl_parse erl_posix_msg erl_pp erl_scan erl_tar 30 | error_logger_file_h error_logger_tty_h 31 | escript 32 | ets 33 | eval_bits 34 | filelib filename file_sorter 35 | gb_sets gb_trees 36 | gen gen_event gen_fsm gen_server 37 | io io_lib io_lib_format io_lib_fread io_lib_pretty 38 | lib 39 | log_mf_h 40 | math 41 | ms_transform 42 | orddict ordsets 43 | otp_internal pg pool proc_lib 44 | proplists 45 | qlc qlc_pt 46 | queue 47 | random 48 | regexp 49 | sets 50 | shell_default shell slave sofs 51 | string 52 | supervisor_bridge supervisor 53 | sys 54 | timer unicode zip" 55 | 56 | # TODO re 57 | # NOT win32reg 58 | # SEPARATLY lists 59 | 60 | MODULES_ADD="dets.hrl erl_parse.yrl" 61 | 62 | if [ ! -d "./erl_lib_core" ]; then 63 | echo "Please run ./tools/make_links_for_core_top_module.sh from top directory of erljs" >&2 64 | exit 1 65 | fi 66 | 67 | if [ ! -d "./erl_lib_core/stdlib/src" ]; then 68 | mkdir -p "./erl_lib_core/stdlib/src" 69 | fi 70 | if [ ! -d "./erl_lib_core/kernel/src" ]; then 71 | mkdir -p "./erl_lib_core/kernel/src" 72 | fi 73 | if [ ! -d "./erl_lib_core/erts/src" ]; then 74 | mkdir -p "./erl_lib_core/erts/src" 75 | fi 76 | 77 | echo "Creating links for modules from stdlib application" >&2 78 | for MODULE in ${MODULES}; 79 | do 80 | if [ -L "./erl_lib_core/stdlib/src/${MODULE}.erl" ]; then 81 | rm "./erl_lib_core/stdlib/src/${MODULE}.erl" 82 | fi 83 | ln -v -s ${ERL_TOP_LIB}/stdlib-*/src/"${MODULE}.erl" "./erl_lib_core/stdlib/src/" 84 | done 85 | for FILE in ${MODULES_ADD}; 86 | do 87 | if [ -L "./erl_lib_core/stdlib/src/${FILE}" ]; then 88 | rm "./erl_lib_core/stdlib/src/${FILE}" 89 | fi 90 | ln -v -s ${ERL_TOP_LIB}/stdlib-*/"src/${FILE}" "./erl_lib_core/stdlib/src/" 91 | done 92 | if [ -L "./erl_lib_core/stdlib/include" ]; then 93 | rm "./erl_lib_core/stdlib/include" 94 | fi 95 | ln -v -s ${ERL_TOP_LIB}/stdlib-*/include "./erl_lib_core/stdlib/" 96 | 97 | echo "Creating links for modules from kernel application" >&2 98 | MODULES2="error_logger " 99 | for MODULE in ${MODULES2}; 100 | do 101 | if [ -L "./erl_lib_core/kernel/src/${MODULE}.erl" ]; then 102 | rm "./erl_lib_core/kernel/src/${MODULE}.erl" 103 | fi 104 | ln -v -s ${ERL_TOP_LIB}/kernel-*/src/${MODULE}.erl "./erl_lib_core/kernel/src/" 105 | done 106 | ln -v -s ${ERL_TOP_LIB}/kernel-*/include "./erl_lib_core/kernel/" 107 | 108 | echo "Creating links for modules from erts application" >&2 109 | # usefull for get_argument/1, etc. 110 | MODULES3="otp_ring0 init erl_prim_loader erlang" 111 | for MODULE in ${MODULES3}; 112 | do 113 | if [ -L "./erl_lib_core/erts/src/${MODULE}.erl" ]; then 114 | rm "./erl_lib_core/erts/src/${MODULE}.erl" 115 | fi 116 | ln -v -s ${ERL_TOP_LIB}/erts-*/src/${MODULE}.erl "./erl_lib_core/erts/src/" 117 | done 118 | mkdir -p "./erl_lib_core/erts/ebin-org" 119 | if [ -L "./erl_lib_core/erts/ebin-org/erl_prim_loader.beam" ]; then 120 | rm "./erl_lib_core/erts/ebin-org/erl_prim_loader.beam" 121 | fi 122 | ln -v -s ${ERL_TOP_LIB}/erts-*/ebin/erl_prim_loader.beam "./erl_lib_core/erts/ebin-org/" 123 | 124 | 125 | echo "Copying and patching lists.erl from stdlib application (it should be safe to overwrite existing file)" >&2 126 | cp -v -i ${ERL_TOP_LIB}/stdlib-*/src/lists.erl "./erl_lib_core/stdlib/src/lists.erl" 127 | (cd ./erl_lib_core/stdlib/; patch -p1 < ../lists-erl.patch) 128 | 129 | exit 0 130 | -------------------------------------------------------------------------------- /erl_src/json_simple.erl: -------------------------------------------------------------------------------- 1 | %%% Copyright (c) 2005-2006, A2Z Development USA, Inc. All Rights Reserved. 2 | %%% 3 | %%% The contents of this file are subject to the Erlang Public License, 4 | %%% Version 1.1, (the "License"); you may not use this file except in 5 | %%% compliance with the License. You should have received a copy of the 6 | %%% Erlang Public License along with this software. If not, it can be 7 | %%% retrieved via the world wide web at http://www.erlang.org/. 8 | %%% 9 | %%% Software distributed under the License is distributed on an "AS IS" 10 | %%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 11 | %%% the License for the specific language governing rights and limitations 12 | %%% under the License. 13 | %%% 14 | %%% The Initial Developer of the Original Code is A2Z Development USA, Inc. 15 | %%% All Rights Reserved. 16 | 17 | % Modified by Witold Baryluk , 2008 18 | 19 | -module(json_simple). 20 | -export([encode/1]). 21 | %-export([is_obj/1, obj_new/0, obj_fetch/2, obj_find/2, obj_is_key/2]). 22 | %-export([obj_store/3, obj_from_list/1, obj_fold/3]). 23 | %-export([test/0]). 24 | -author("Jim Larson , Robert Wai-Chi Chu "). 25 | -vsn("1"). 26 | 27 | %%% ENCODING 28 | 29 | %% Encode an erlang number, string, tuple, or object to JSON syntax, as a 30 | %% possibly deep list of UTF-16 code units, throwing a runtime error in the 31 | %% case of un-convertible input. 32 | %% Note: object keys may be either strings or atoms. 33 | 34 | -spec encode(atom() | [any()] | number() | tuple()) -> [any()]. 35 | 36 | %encode(true) -> "true"; 37 | %encode(false) -> "false"; 38 | %encode(null) -> "null"; 39 | encode(I) when is_integer(I) -> integer_to_list(I); 40 | encode(F) when is_float(F) -> io_lib:format("~w", [F]); 41 | encode([]) -> encode_string([]); 42 | encode([C|_] = L) when is_integer(C), C >= $\000, C =< $\377 -> 43 | try encode_string(L) of R -> 44 | R 45 | catch exit:_ -> 46 | encode_list(L) 47 | end; 48 | encode(L) when is_list(L) -> encode_list(L); 49 | encode({}) -> "[]"; 50 | encode(T) when is_tuple(T) -> encode_array(T); 51 | encode(A) when is_atom(A) -> encode_atom(A); 52 | encode(B) when is_binary(B) -> encode({binary,binary_to_list(B)}); 53 | encode(Bad) -> exit({json_encode, {bad_term, Bad}}). 54 | 55 | % todo: encode directly to IoDecive 56 | 57 | %% Encode an Erlang string to JSON. 58 | %% Accumulate strings in reverse. 59 | 60 | -spec encode_string([any()]) -> [any(), ...]. 61 | 62 | encode_string(S) -> 63 | R = encode_string0(S), 64 | % ["{s:",R,"}"]. 65 | %["\\\"",R,"\\\""]. 66 | R. 67 | 68 | encode_string0(S) -> encode_string(S, [$"]). 69 | 70 | -spec encode_string([any()], [any(), ...]) -> [any(), ...]. 71 | 72 | encode_string([], Acc) -> lists:reverse([$" | Acc]); 73 | encode_string([C | Cs], Acc) -> 74 | case C of 75 | $" -> encode_string(Cs, [$", $\\ | Acc]); 76 | % (don't escape solidus on encode) 77 | $\\ -> encode_string(Cs, [$\\, $\\ | Acc]); 78 | $\b -> encode_string(Cs, [$b, $\\ | Acc]); % note missing \ 79 | $\f -> encode_string(Cs, [$f, $\\ | Acc]); 80 | $\n -> encode_string(Cs, [$n, $\\ | Acc]); 81 | $\r -> encode_string(Cs, [$r, $\\ | Acc]); 82 | $\t -> encode_string(Cs, [$t, $\\ | Acc]); 83 | C when C >= 0, C < $\s -> 84 | % Control characters must be unicode-encoded. 85 | Hex = lists:flatten(io_lib:format("~4.16.0b", [C])), 86 | encode_string(Cs, lists:reverse(Hex) ++ "u\\" ++ Acc); 87 | C when C =< 16#FFFF -> encode_string(Cs, [C | Acc]); 88 | _ -> exit({json_encode, {bad_char, C}}) 89 | end. 90 | 91 | 92 | %% Encode an Erlang tuple as a JSON array. 93 | %% Order *is* significant in a JSON array! 94 | 95 | -spec encode_array(tuple()) -> [[any()] | 91 | 93, ...]. 96 | 97 | encode_array(T) -> 98 | M = tuple_fold(fun(E, Acc) -> 99 | V = encode(E), 100 | case Acc of 101 | [] -> V; 102 | _ -> [Acc, $,, V] 103 | end 104 | end, [], T), 105 | [$[, M, $]]. 106 | 107 | -spec encode_list([any()]) -> [[any()] | 91 | 93,...]. 108 | 109 | encode_list(T) -> 110 | M = lists:foldl(fun(E, Acc) -> 111 | V = encode(E), 112 | case Acc of 113 | [] -> V; 114 | _ -> [Acc, $,, V] 115 | end 116 | end, [], T), 117 | [$[, M, $]]. 118 | 119 | %% A fold function for tuples (left-to-right). 120 | %% Folded function takes arguments (Element, Accumulator). 121 | 122 | -spec tuple_fold(fun((_,_) -> [any()]), [], tuple()) -> [any()]. 123 | 124 | tuple_fold(F, A, T) when is_tuple(T) -> 125 | tuple_fold(F, A, T, 1, size(T)). 126 | 127 | -spec tuple_fold(fun((_,_) -> [any()]), [any()], tuple(), pos_integer(), non_neg_integer()) -> [any()]. 128 | 129 | tuple_fold(_F, A, _T, I, N) when I > N -> 130 | A; 131 | tuple_fold(F, A, T, I, N) -> 132 | A2 = F(element(I, T), A), 133 | tuple_fold(F, A2, T, I + 1, N). 134 | 135 | encode_atom(A) -> 136 | %["{a:",encode_string(atom_to_list(A)),"}"]. 137 | encode_string0(atom_to_list(A)). 138 | -------------------------------------------------------------------------------- /js_src/erljs_float.js: -------------------------------------------------------------------------------- 1 | /* Copyright 2008-2011, Witold Baryluk 2 | * erljs project 3 | */ 4 | 5 | /* Witold Baryluk, 2011-06-13 */ 6 | 7 | inv_pow_2_table = []; 8 | 9 | (function /*inv_pow_2_table_init*/ () { 10 | for (i = 0; i < 2048; i++) { 11 | inv_pow_2_table[i] = Math.pow(2.0, i-1023); 12 | } 13 | })(); 14 | 15 | pow2_m52 = Math.pow(2, -52); // 2.2204460492503131e-16 16 | 17 | // all arguments are bytes, an integers in range 0-255 exclusive. 18 | // function returns double precision floating point number coresponding to a...h bytes, using IEEE754 standard 19 | function bytes_to_float(a,b,c,d,e,f,g,h) { 20 | var S = (a & 0x80); 21 | var E = ((a & 0x7f) << 4) | ((b & 0xf0) >> 4); // (b >> 4) should suffice actually. 22 | var Fu = (b & 0x0f) << 16 | (c << 8) | d; 23 | //var Fd = (e << 24) | (f << 16) | (g << 8) | h; // can overflow over signed integer :( 24 | //var Fd = e*16777216 + f*65536 + g*256 + h; 25 | var Fd = e*16777216 + ((f<<16) | (g<<8) | h); 26 | var x; 27 | if (E == 0) { 28 | if (Fu == 0 && Fd == 0) { 29 | x = 0.0; // zero 30 | } else { 31 | x = 4294967296*Fu + Fd; 32 | x *= pow2_m52; 33 | x += 1.0; 34 | x *= inv_pow_2_table[E]; 35 | } 36 | } else if (E == 0x7ff) { 37 | if (Fu == 0 && Fd == 0) { 38 | x = Infinity; 39 | } else { 40 | x = NaN; // it should be NaN with payload, but we can assume it isn't, as Erlang isn't using it 41 | } 42 | } else { 43 | //x = (Fu << 32) | Fd; // can overflow over signed integer :( 44 | x = 4294967296*Fu + Fd; 45 | x *= pow2_m52; 46 | x += 1.0; 47 | x *= inv_pow_2_table[E]; 48 | } 49 | return (S ? -x : x); 50 | } 51 | 52 | function bytes_to_float_test_() { 53 | //inv_pow_2_table_init(); 54 | 55 | function isnan(x) { 56 | return !(x == x); 57 | } 58 | 59 | var results = [ 60 | bytes_to_float(0x7f,0xf0,0x00,0x00,0x00,0x00,0x00,0x00) == Infinity, 61 | bytes_to_float(0xff,0xf0,0x00,0x00,0x00,0x00,0x00,0x00) == -Infinity, 62 | 1.0 / bytes_to_float(0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00) == Infinity, 63 | 1.0 / bytes_to_float(0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00) == -Infinity, 64 | 65 | bytes_to_float(0x7f,0xe0,0x00,0x00,0x00,0x00,0x00,0x00) == 8.98846567431158e+307, 66 | bytes_to_float(0x7f,0xef,0xff,0xff,0xff,0xff,0xff,0xff) == 1.7976931348623157e+308, 67 | bytes_to_float(0xff,0xef,0xff,0xff,0xff,0xff,0xff,0xff) == -1.7976931348623157e+308, 68 | bytes_to_float(0xff,0xe0,0x00,0x00,0x00,0x00,0x00,0x00) == -8.98846567431158e+307, 69 | 70 | bytes_to_float(0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00) == 0, 71 | bytes_to_float(0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00) == 2.2250738585072014e-308, 72 | bytes_to_float(0x80,0x10,0x00,0x00,0x00,0x00,0x00,0x00) == -2.2250738585072014e-308, 73 | bytes_to_float(0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00) == 2, 74 | bytes_to_float(0x40,0x10,0x00,0x00,0x00,0x00,0x00,0x00) == 4, 75 | bytes_to_float(0x3f,0xf0,0x00,0x00,0x00,0x00,0x00,0x00) == 1, 76 | bytes_to_float(0xbf,0xf0,0x00,0x00,0x00,0x00,0x00,0x00) == -1, 77 | bytes_to_float(0x3f,0xe0,0x00,0x00,0x00,0x00,0x00,0x00) == 0.5, 78 | bytes_to_float(0xbf,0xe0,0x00,0x00,0x00,0x00,0x00,0x00) == -0.5, 79 | bytes_to_float(0x3f,0xe5,0x2c,0xae,0x3a,0x0f,0xf8,0x3a) == 0.6617041715651404, 80 | 81 | isnan(bytes_to_float(0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff)), 82 | isnan(bytes_to_float(0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff)), 83 | isnan(bytes_to_float(0x7f,0xf0,0x00,0x00,0x00,0x55,0x00,0x00)), 84 | isnan(bytes_to_float(0xff,0xf0,0x00,0x00,0x00,0x55,0x00,0x00)), 85 | 86 | // denormals 87 | /* 88 | bytes_to_float(0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01) == , 89 | bytes_to_float(0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x01) == , 90 | bytes_to_float(0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01) == , 91 | bytes_to_float(0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00) == , 92 | bytes_to_float(0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00) == , 93 | bytes_to_float(0x00,0x0f,0xff,0xff,0xff,0xff,0xff,0xff) == , 94 | bytes_to_float(0x00,0x0f,0xff,0xff,0xff,0xff,0xff,0xfe) == , 95 | */ 96 | 97 | // using C and Python 98 | bytes_to_float(0x40,0x0f,0xff,0xff,0xff,0xff,0xff,0x00) == 3.9999999999998863, 99 | bytes_to_float(0x40,0x0f,0xff,0xfe,0xff,0xff,0xff,0x00) == 3.9999980926512535, 100 | bytes_to_float(0x40,0x0f,0xff,0xff,0xff,0xff,0xff,0xf0) == 3.999999999999993, 101 | bytes_to_float(0x40,0x0f,0xff,0xff,0xff,0xff,0xff,0xfe) == 3.999999999999999, 102 | bytes_to_float(0x40,0x0f,0xff,0xff,0xff,0xff,0xff,0xff) == 3.9999999999999996, 103 | bytes_to_float(0x3f,0xff,0xff,0xff,0xff,0xff,0xfe,0x1e) == 1.999999999999893, 104 | bytes_to_float(0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xfe) == 1.9999999999999996, 105 | bytes_to_float(0x3f,0xe5,0x2c,0xae,0x3a,0x0f,0xf8,0x3a) == 0.6617041715651404, 106 | bytes_to_float(0x3f,0xdf,0xff,0xff,0x5d,0x5d,0xf0,0x7e) == 0.49999984853616997, 107 | bytes_to_float(0x3f,0xc8,0x06,0x0f,0xbd,0x39,0xae,0xa9) == 0.187684981723, 108 | 109 | // python> Math.pi.hex() == '0x1.921fb54442d18p+1' 110 | bytes_to_float(0x40,0x09,0x21,0xfb,0x54,0x44,0x2d,0x18) == 3.1415926535897931, 111 | bytes_to_float(0x3f,0xd3,0x33,0x33,0x33,0x33,0x33,0x33) == 0.3, 112 | bytes_to_float(0x3f,0xf4,0xcc,0xcc,0xcc,0xcc,0xcc,0xcd) == 1.3, 113 | bytes_to_float(0x3f,0xf8,0x00,0x00,0x00,0x00,0x00,0x00) == 1.5 114 | ]; 115 | 116 | return results; 117 | } 118 | -------------------------------------------------------------------------------- /erl_src/erljs_tests.erl: -------------------------------------------------------------------------------- 1 | -module(erljs_tests). 2 | -author('baryluk@smp.if.uj.edu.pl'). 3 | 4 | % Copyright 2009-2011, Witold Baryluk 5 | % erljs project 6 | 7 | -export([cl/1, c/1]). 8 | 9 | cl(L) -> 10 | [ c(M) || M <- L ]. 11 | 12 | -spec c(atom()) -> {'ok', atom(), nonempty_string(), [{_,_}, ...], [{_,_}, ...]}. 13 | 14 | c(Module) when is_atom(Module) -> 15 | io:format("Generating and compiling test and checks ~p~n", [Module]), 16 | Modulename = atom_to_list(Module), 17 | Filename = Modulename, 18 | {ok, File} = file:open(Filename, [read, {read_ahead, 8192}]), 19 | {ok, FileErl} = file:open(Modulename ++ ".erl", [write]), 20 | {ok, FileJS} = file:open(Modulename ++ ".js", [write]), 21 | ok = file:write(FileErl, ["% This file was automatically generated by erljs_tests from ", Modulename, " tests specification\n"]), 22 | ok = file:write(FileErl, ["-module('", Modulename, "').\n"]), 23 | ok = file:write(FileErl, "-compile([export_all]).\n"), 24 | ok = file:write(FileJS, ["// This file was automatically generated by erljs_tests from ", Modulename, " tests specification\n"]), 25 | ok = file:write(FileJS, ["function ", "unittest__", Modulename, "() {\n"]), 26 | io:format("Processing lines"), 27 | Stats = {0,0,0}, 28 | process(file:read_line(File), File, [], 1, Stats, {Modulename, FileErl, FileJS}). 29 | 30 | -spec process( 31 | 'eof' | {'ok', string()}, 32 | pid() | {'file_descriptor', atom(), _}, 33 | [{[any()],_}], 34 | pos_integer(), 35 | {non_neg_integer(), non_neg_integer(), non_neg_integer()}, 36 | {nonempty_string(), pid() | {'file_descriptor', atom(), _}, pid() | {'file_descriptor', atom(), _}} 37 | ) -> 38 | {'ok', atom(), nonempty_string(), [{_,_}, ...], [{_,_}, ...]}. 39 | 40 | process(eof, File, _Code, _LineNo, _Stats = {StatsWithWrapper, StatsWithTerm, StatsWithCall}, {Modulename, FileErl, FileJS}) -> 41 | io:format("~n"), 42 | ok = file:close(File), 43 | ok = file:close(FileErl), 44 | ok = file:write(FileJS, "\treturn true;\n}\n"), 45 | ok = file:close(FileJS), 46 | {ok, Modulename2, _OutputFile, CompilerStats} = erljs_compiler:c(Modulename), 47 | {ok, Modulename2, Modulename, [ 48 | {direct_call, StatsWithCall}, 49 | {wrapper, StatsWithWrapper}, 50 | {term, StatsWithTerm}, 51 | {total, StatsWithCall+StatsWithWrapper+StatsWithTerm} 52 | ], CompilerStats}; 53 | process({ok, Line0}, File, Code, LineNo, Stats, Aux = {Modulename, FileErl, FileJS}) -> 54 | Line1 = string:strip(Line0, both), 55 | Line2 = string:strip(Line1, both, $\t), 56 | Line = string:strip(Line2, right, $\n), 57 | io:format(" ~p", [LineNo]), 58 | %io:format("Processing lines", [LineNo]), 59 | %io:format("~p~n", [Line]), 60 | CodeLine = case Line of 61 | [] -> Line; 62 | _ -> case hd(Line) of 63 | $% -> []; % strip comments 64 | _ -> Line 65 | end 66 | end, 67 | {NewCode,NewStats} = case CodeLine of 68 | [] -> 69 | {Code,Stats}; 70 | _ -> 71 | {ok, Tokens, _LastLocation} = erl_scan:string(Line), 72 | %io:format("tokenized~n"), 73 | {ok, [AbstractExpression]} = erl_parse:parse_exprs(Tokens), 74 | %io:format("parsed~n"), 75 | Bindings = erl_eval:new_bindings(), 76 | {value, Value0, _NewBindings} = erl_eval:expr(AbstractExpression, Bindings), 77 | % handled exception to only contain one element in stack trace 78 | % TODO: discover automatically what amount of stack trace entries to keep 79 | Value = case Value0 of 80 | {'EXIT',{ExceptionReason,[ExceptionStackTraceFirst|_ExceptionStackTraceRest]}} -> 81 | {'EXIT',{ExceptionReason,[ExceptionStackTraceFirst]}}; 82 | _ -> Value0 83 | end, 84 | %io:format("evalueted~n"), 85 | %io:format("~p~n", [Value]), 86 | Type = case Line of 87 | [$e,$r,$l,$a,$n,$g,$:|_] -> wrapper; 88 | [$m,$a,$t,$h,$:|_] -> wrapper; 89 | [$b,$e,$g,$i,$n|_] -> wrapper; 90 | [$c,$a,$t,$c,$h|_] -> wrapper; 91 | [$(| _] -> term; 92 | [Letter|_] when is_integer(Letter), $A =< Letter, Letter =< $Z -> wrapper; 93 | _ -> call 94 | end, 95 | Stats2 = case Type of 96 | wrapper -> 97 | % more complicated expressions or complicated function calls 98 | % prepare temporary function for it and compile 99 | %io:format(FileErl, "test_~w() -> ~s~n", [LineNo, Line]), 100 | file:write(FileErl, ["test_", integer_to_list(LineNo) ,"() ->\n\t", 101 | Line, "\n"]), 102 | %io:format("eq(\"test_~w()\", \"~s\");~n", [LineNo, lists:flatten(io_lib:write(Value))]); 103 | file:write(FileJS, ["\teq(\"", Modulename, ":test_", integer_to_list(LineNo) ,"()", "\",\n\t\t", 104 | io_lib:write_string(lists:flatten(io_lib:print(Value,1,1000000000000,-1))), ",\n\t\t", 105 | io_lib:write_string(Line), ");\n"]), 106 | setelement(1, Stats, element(1, Stats)+1); 107 | term -> 108 | io:format(FileJS, "d2(\"~s\", \"~s\");~n", [Line, lists:flatten(io_lib:write(Value))]), 109 | setelement(2, Stats, element(2, Stats)+1); 110 | call -> 111 | % simple function calls 112 | file:write(FileJS, ["\teq(", io_lib:write_string(Line), ",\n\t\t", 113 | io_lib:write_string(lists:flatten(io_lib:print(Value,1,1000000000000,-1))), ");\n"]), 114 | setelement(3, Stats, element(3, Stats)+1) 115 | end, 116 | {[{Line, Value}|Code], Stats2} 117 | end, 118 | process(file:read_line(File), File, NewCode, LineNo+1, NewStats, Aux). 119 | 120 | 121 | %erl_scan:reserved_word(Atom) - bool 122 | %erl_parse:parse_term(Tokens) -> {ok, Term} 123 | %{ok, ParsedLine} = io:parse_erl_form(Line, ), 124 | 125 | 126 | -------------------------------------------------------------------------------- /from_otp/genop.tab: -------------------------------------------------------------------------------- 1 | # ``The contents of this file are subject to the Erlang Public License, 2 | # Version 1.1, (the "License"); you may not use this file except in 3 | # compliance with the License. You should have received a copy of the 4 | # Erlang Public License along with this software. If not, it can be 5 | # retrieved via the world wide web at http://www.erlang.org/. 6 | # 7 | # Software distributed under the License is distributed on an "AS IS" 8 | # basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 9 | # the License for the specific language governing rights and limitations 10 | # under the License. 11 | # 12 | # The Initial Developer of the Original Code is Ericsson Utvecklings AB. 13 | # Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings 14 | # AB. All Rights Reserved.'' 15 | # 16 | # $Id$ 17 | # 18 | BEAM_FORMAT_NUMBER=0 19 | 20 | # 21 | # Generic instructions, generated by the compiler. If any of them change number, 22 | # arity or semantics, the format number above must be bumped. 23 | # 24 | 25 | 1: label/1 26 | 2: func_info/3 27 | 3: int_code_end/0 28 | 29 | # 30 | # Function and BIF calls. 31 | # 32 | 4: call/2 33 | 5: call_last/3 34 | 6: call_only/2 35 | 36 | 7: call_ext/2 37 | 8: call_ext_last/3 38 | 39 | 9: bif0/2 40 | 10: bif1/4 41 | 11: bif2/5 42 | 43 | # 44 | # Allocating, deallocating and returning. 45 | # 46 | 12: allocate/2 47 | 13: allocate_heap/3 48 | 14: allocate_zero/2 49 | 15: allocate_heap_zero/3 50 | 16: test_heap/2 51 | 17: init/1 52 | 18: deallocate/1 53 | 19: return/0 54 | 55 | # 56 | # Sending & receiving. 57 | # 58 | 20: send/0 59 | 21: remove_message/0 60 | 22: timeout/0 61 | 23: loop_rec/2 62 | 24: loop_rec_end/1 63 | 25: wait/1 64 | 26: wait_timeout/2 65 | 66 | # 67 | # Arithmethic opcodes. 68 | # 69 | 27: -m_plus/4 70 | 28: -m_minus/4 71 | 29: -m_times/4 72 | 30: -m_div/4 73 | 31: -int_div/4 74 | 32: -int_rem/4 75 | 33: -int_band/4 76 | 34: -int_bor/4 77 | 35: -int_bxor/4 78 | 36: -int_bsl/4 79 | 37: -int_bsr/4 80 | 38: -int_bnot/3 81 | 82 | # 83 | # Comparision operators. 84 | # 85 | 39: is_lt/3 86 | 40: is_ge/3 87 | 41: is_eq/3 88 | 42: is_ne/3 89 | 43: is_eq_exact/3 90 | 44: is_ne_exact/3 91 | 92 | # 93 | # Type tests. 94 | # 95 | 45: is_integer/2 96 | 46: is_float/2 97 | 47: is_number/2 98 | 48: is_atom/2 99 | 49: is_pid/2 100 | 50: is_reference/2 101 | 51: is_port/2 102 | 52: is_nil/2 103 | 53: is_binary/2 104 | 54: is_constant/2 105 | 55: is_list/2 106 | 56: is_nonempty_list/2 107 | 57: is_tuple/2 108 | 58: test_arity/3 109 | 110 | # 111 | # Indexing & jumping. 112 | # 113 | 59: select_val/3 114 | 60: select_tuple_arity/3 115 | 61: jump/1 116 | 117 | # 118 | # Catch. 119 | # 120 | 62: catch/2 121 | 63: catch_end/1 122 | 123 | # 124 | # Moving, extracting, modifying. 125 | # 126 | 64: move/2 127 | 65: get_list/3 128 | 66: get_tuple_element/3 129 | 67: set_tuple_element/3 130 | 131 | # 132 | # Building terms. 133 | # 134 | 68: put_string/3 135 | 69: put_list/3 136 | 70: put_tuple/2 137 | 71: put/1 138 | 139 | # 140 | # Raising errors. 141 | # 142 | 72: badmatch/1 143 | 73: if_end/0 144 | 74: case_end/1 145 | 146 | # 147 | # 'fun' support. 148 | # 149 | 75: call_fun/1 150 | 76: -make_fun/3 151 | 77: is_function/2 152 | 153 | # 154 | # Late additions to R5. 155 | # 156 | 78: call_ext_only/2 157 | 158 | # 159 | # Binary matching (R7). 160 | # 161 | 79: -bs_start_match/2 162 | 80: -bs_get_integer/5 163 | 81: -bs_get_float/5 164 | 82: -bs_get_binary/5 165 | 83: -bs_skip_bits/4 166 | 84: -bs_test_tail/2 167 | 85: -bs_save/1 168 | 86: -bs_restore/1 169 | 170 | # 171 | # Binary construction (R7A). 172 | # 173 | 87: -bs_init/2 174 | 88: -bs_final/2 175 | 89: bs_put_integer/5 176 | 90: bs_put_binary/5 177 | 91: bs_put_float/5 178 | 92: bs_put_string/2 179 | 180 | # 181 | # Binary construction (R7B). 182 | # 183 | 93: -bs_need_buf/1 184 | 185 | # 186 | # Floating point arithmetic (R8). 187 | # 188 | 94: fclearerror/0 189 | 95: fcheckerror/1 190 | 96: fmove/2 191 | 97: fconv/2 192 | 98: fadd/4 193 | 99: fsub/4 194 | 100: fmul/4 195 | 101: fdiv/4 196 | 102: fnegate/3 197 | 198 | # New fun construction (R8). 199 | 103: make_fun2/1 200 | 201 | # Try/catch/raise (R10B). 202 | 104: try/2 203 | 105: try_end/1 204 | 106: try_case/1 205 | 107: try_case_end/1 206 | 108: raise/2 207 | 208 | # New instructions in R10B. 209 | 109: bs_init2/6 210 | 110: bs_bits_to_bytes/3 211 | 111: bs_add/5 212 | 112: apply/1 213 | 113: apply_last/2 214 | 114: is_boolean/2 215 | 216 | # New instructions in R10B-6. 217 | 115: is_function2/3 218 | 219 | # New bit syntax matching in R11B. 220 | 221 | 116: bs_start_match2/5 222 | 117: bs_get_integer2/7 223 | 118: bs_get_float2/7 224 | 119: bs_get_binary2/7 225 | 120: bs_skip_bits2/5 226 | 121: bs_test_tail2/3 227 | 122: bs_save2/2 228 | 123: bs_restore2/2 229 | 230 | # New GC bifs introduced in R11B. 231 | 124: gc_bif1/5 232 | 125: gc_bif2/6 233 | 234 | # Experimental new bit_level bifs introduced in R11B. 235 | # NOT used in R12B. 236 | 126: -bs_final2/2 237 | 127: -bs_bits_to_bytes2/2 238 | 239 | # R11B-4 240 | 128: -put_literal/2 241 | 242 | # R11B-5 243 | 129: is_bitstr/2 244 | 245 | # R12B 246 | 130: bs_context_to_binary/1 247 | 131: bs_test_unit/3 248 | 132: bs_match_string/4 249 | 133: bs_init_writable/0 250 | 134: bs_append/8 251 | 135: bs_private_append/6 252 | 136: trim/2 253 | 137: bs_init_bits/6 254 | 255 | # R12B-5 256 | 138: bs_get_utf8/5 257 | 139: bs_skip_utf8/4 258 | 259 | 140: bs_get_utf16/5 260 | 141: bs_skip_utf16/4 261 | 262 | 142: bs_get_utf32/5 263 | 143: bs_skip_utf32/4 264 | 265 | 144: bs_utf8_size/3 266 | 145: bs_put_utf8/3 267 | 268 | 146: bs_utf16_size/3 269 | 147: bs_put_utf16/3 270 | 271 | 148: bs_put_utf32/3 272 | -------------------------------------------------------------------------------- /erl_src/erljs_dom.erl: -------------------------------------------------------------------------------- 1 | -module(erljs_dom). 2 | -author('baryluk@smp.if.uj.edu.pl'). 3 | 4 | % Copyright 2009-2011, Witold Baryluk 5 | % erljs project 6 | 7 | -compile([export_all]). 8 | -compile_erljs([export_all]). 9 | 10 | 11 | %-spec selector(any) -> {ok, [dom_node()]} | {error, term()}. 12 | selector(Spec) when is_atom(Spec); is_list(Spec) -> 13 | ignored. 14 | 15 | %-spec get_by_id(dom_id()) -> {ok, dom_node()} | undefined | {error, term()}. 16 | get_by_id(Id) when is_atom(Id) -> 17 | %throw (callable_only_at_client_side). 18 | ignored. 19 | 20 | % after starting listening, there will be message of the form: 21 | % {dom, Id, Ref, Type, Value, Aux} 22 | % 23 | % Opts: once - after single event unregiter this listener 24 | % prevent_default - prevent default action from exeucting (like clicking on link going to new page) 25 | % stop_propagation - do not propagte to the other elements in DOM tree 26 | % capture - send message in capture phase instead of bubbling 27 | % (and possibly stop_propagation/prevent_default based on other options) 28 | % 29 | % Returns: {ok, Ref}, after sucessfull registering listner 30 | % {error, Reason}, if no such element 31 | % 32 | % throws badarg, if bad arguments 33 | % 34 | %-spec listen(dom_id_or_node(), atom(), [once | prevent_default | stop_propagation | capture], term()) -> 35 | % {ok, ref()} | {error, term()}. 36 | listen(Id, Type, Opts, Aux) when is_atom(Id), is_atom(Type), is_list(Opts) -> 37 | %throw (callable_only_at_client_side). 38 | ignored. 39 | 40 | %-spec close(dom_id_or_node() | ref(), atom()) -> {ok, term()} | {error, term()}. 41 | close(IdOrRef, Type) when is_atom(IdOrRef), is_atom(Type) -> 42 | ignored. 43 | 44 | % after starting listening, there will be message of the form: 45 | % {ajax_progress, Ref, SoFarBytes, TotalBytes} 46 | % {ajax_data, Ref, {Status, Headers}, DataList} 47 | % {ajax_error, Ref, abort | timeout | other} 48 | % 49 | % Opts: binary - use binaries instead of list 50 | % sync - wait for result and return {Status, Headers, DataList} 51 | % prevent_caching - append random query string and set headersto prevent caching 52 | % 53 | % Returns: {ok, Ref} - in async mode (defult) without error 54 | % {Status, Headers, DataList | Binary} - in sync mode without error 55 | % {error, Reason} - on error 56 | % 57 | % throws badarg, if bad arguments 58 | % 59 | 60 | 61 | % TODO 62 | % wszystkie -spec są tutaj zakomentowane, bo sie nie kompiluje w nowerj wersji erlanga :( 63 | %-spec ajax( 64 | % 'GET' | 'POST' | 'HEAD' | 'PUT' | 'DELETE', 65 | % io_list(), 66 | % io_list(), 67 | % [binary | sync | prevent_caching] 68 | % ) -> 69 | % {ok, ref()} | 70 | % {pos_integer(), [{io_list(), io_list()]}, io_list()} | 71 | % {error, term()}. 72 | ajax(Method, URL, Data, Opts) when is_atom(Method), is_list(URL), is_list(Data), is_list(Opts) -> 73 | ignored. 74 | 75 | 76 | % DOM manipulation 77 | 78 | %-type dom_id() := atom() | string(). 79 | %-type dom_node() := {dom_node, ref()}. 80 | %-type dom_id_or_node() := dom_id() | dom_node(). 81 | %-type dom_prop() := atom() | string(). 82 | % 83 | %-type html_props() := style | parentNode | nodeName. 84 | 85 | %-spec window() -> {ok, dom_node()} | {error, term()}. 86 | window() -> ignored. 87 | 88 | %-spec create_element(string()) -> {ok, dom_node()} | {error, term()}. 89 | create_element(Type) -> ignored. 90 | 91 | %-spec create_element(string(), dom_node()) -> {ok, dom_node()} | {error, term()}. 92 | create_element(Type, Window) -> ignored. 93 | 94 | %-spec create_element(io_list(), dom_id_or_node()) -> {ok, dom_node()} | {error, term()}. 95 | create_text_node(Text, Document) -> ignored. 96 | 97 | %-spec parent(dom_id_or_node()) -> {ok, dom_node()} | {error, term()}. 98 | parent(IdOrNode) -> ignored. 99 | 100 | %-spec childs(dom_id_or_node()) -> {ok, [dom_node()]} | {error, term()}. 101 | childs(IdOrNode) -> ignored. 102 | %-spec append_childs(dom_id_or_node(), dom_node()) -> ok | {error, term()}. 103 | append_child(IdOrNode, Node) -> ignored. 104 | %-spec insert_childs(dom_id_or_node(), dom_id_or_node(), dom_node()) -> ok | {error, term()}. 105 | insert_child(IdOrNode, Id2OrNode, Node) -> ignored. 106 | %-spec append_childs(dom_id_or_node(), dom_id_or_node()) -> ok | {error, term()}. 107 | remove_child(IdOrNode, Id2OrNode) -> ignored. 108 | 109 | %-spec get(dom_id_or_node(), dom_prop()) -> {ok, term()} | {error, term()}. 110 | get(IdOrNode, Prop) -> ignored. 111 | %-spec set(dom_id_or_node(), dom_prop(), io_list() | dom_id_or_node()) -> ok | {error, term()}. 112 | set(IdOrNode, Prop, Value) -> ignored. 113 | %-spec set(dom_id_or_node(), dom_prop(), io_list() | dom_id_or_node(), string()) -> ok | {error, term()}. 114 | set(IdOrNode, Prop, Value, NS) -> ignored. 115 | %-spec clear(dom_id_or_node(), dom_prop()) -> ok | {error, term()}. 116 | clear(IdOrNode, Prop) -> ignored. 117 | %-spec append(dom_id_or_node(), dom_prop(), io_list()) -> ok | {error, term()}. 118 | append(IdOrNode, Prop, Value) -> ignored. 119 | %-spec preppend(dom_id_or_node(), dom_prop(), io_list()) -> ok | {error, term()}. 120 | preppend(IdOrNode, Prop, Value) -> ignored. 121 | 122 | %-spec get_style(dom_id_or_node(), css_prop()) -> {ok, term()} | {error, term()}. 123 | get_style(IdOrNode, Prop) -> ignored. 124 | %-spec set_style(dom_id_or_node(), css_prop(), io_list() | atom()) -> ok | {error, term()}. 125 | set_style(IdOrNode, Prop, Value) -> ignored. 126 | 127 | %-spec clone(dom_id_or_node()) -> {ok, dom_node()} | {error, term()}. 128 | clone(IdOrNode) -> ignored. 129 | 130 | %-spec deep_clone(dom_id_or_node()) -> {ok, dom_node()} | {error, term()}. 131 | deep_clone(IdOrNode) -> ignored. 132 | -------------------------------------------------------------------------------- /erljs_html/styles.css: -------------------------------------------------------------------------------- 1 | /* reset.css from http://meyerweb.com/eric/tools/css/reset/ 2 | v2.0 | 20110126 3 | License: none (public domain) 4 | */ 5 | html, body, div, span, applet, object, iframe, 6 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 7 | a, abbr, acronym, address, big, cite, code, 8 | del, dfn, em, img, ins, kbd, q, s, samp, 9 | small, strike, strong, sub, sup, tt, var, 10 | b, u, i, center, 11 | dl, dt, dd, ol, ul, li, 12 | fieldset, form, label, legend, 13 | table, caption, tbody, tfoot, thead, tr, th, td, 14 | article, aside, canvas, details, embed, 15 | figure, figcaption, footer, header, hgroup, 16 | menu, nav, output, ruby, section, summary, 17 | time, mark, audio, video { 18 | margin: 0; 19 | padding: 0; 20 | border: 0; 21 | font-size: 100%; 22 | font: inherit; 23 | vertical-align: baseline; 24 | } 25 | /* HTML5 display-role reset for older browsers */ 26 | article, aside, details, figcaption, figure, 27 | footer, header, hgroup, menu, nav, section { 28 | display: block; 29 | } 30 | body { 31 | line-height: 1; 32 | } 33 | ol, ul { 34 | list-style: none; 35 | } 36 | blockquote, q { 37 | quotes: none; 38 | } 39 | blockquote:before, blockquote:after, 40 | q:before, q:after { 41 | content: ''; 42 | content: none; 43 | } 44 | table { 45 | border-collapse: collapse; 46 | border-spacing: 0; 47 | } 48 | /* END OF RESET */ 49 | 50 | @font-face { 51 | font-family: 'Galdeano'; 52 | font-style: normal; 53 | font-weight: 400; 54 | src: local('Galdeano Regular'), local('Galdeano-Regular'), url('xWfNF53zMVtUUmsSpUl10vesZW2xOQ-xsNqO47m55DA.ttf') format('truetype'), url('http://themes.googleusercontent.com/static/fonts/galdeano/v2/xWfNF53zMVtUUmsSpUl10vesZW2xOQ-xsNqO47m55DA.ttf') format('truetype'); 55 | } 56 | @font-face { 57 | font-family: 'Unkempt'; 58 | font-style: normal; 59 | font-weight: 700; 60 | src: local('Unkempt Bold'), local('Unkempt-Bold'), url('l7ry4Z6jesX0kBGhwZVQry3USBnSvpkopQaUR-2r7iU.ttf') format('truetype'), url('http://themes.googleusercontent.com/static/fonts/unkempt/v3/l7ry4Z6jesX0kBGhwZVQry3USBnSvpkopQaUR-2r7iU.ttf') format('truetype'); 61 | } 62 | 63 | @font-face { 64 | font-family: 'Graublau Web'; 65 | src: url('GraublauWeb.eot'); 66 | src: local('Graublau Web Regular'), local('Graublau Web'), url('GraublauWeb.otf') format('opentype'); 67 | } 68 | 69 | html { 70 | height: 100%; 71 | margin: 0; 72 | padding: 0; 73 | cursor: default; 74 | } 75 | body { 76 | margin-top: 0px; 77 | margin-bottom: 0px; 78 | margin-left: auto; 79 | margin-right: auto; 80 | padding: 0; 81 | float: left; 82 | position: relative; 83 | width: 100%; 84 | 85 | font-family: "Graublau Web", "Galdeano", "DejaVu Sans", sans-serif; 86 | color: #000; 87 | 88 | background-color: rgb(125,185,232); 89 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(30,87,153,1)), color-stop(70%,rgba(32,124,202,1)), color-stop(100%,rgba(125,185,232,1))); 90 | background-image: -moz-linear-gradient(top, rgba(30,87,153,1) 0%, rgba(32,124,202,1) 70%, rgba(125,185,232,1) 100%); 91 | background-image: -webkit-linear-gradient(top, rgba(30,87,153,1) 0%, rgba(32,124,202,1) 70%, rgba(125,185,232,1) 100%); 92 | background-image: -o-linear-gradient(top, rgba(30,87,153,1) 0%, rgba(32,124,202,1) 70%, rgba(125,185,232,1) 100%); 93 | background-image: -ms-linear-gradient(top, rgba(30,87,153,1) 0%, rgba(32,124,202,1) 70%, rgba(125,185,232,1) 100%); 94 | background-image: linear-gradient(top, rgba(30,87,153,1) 0%, rgba(32,124,202,1) 70%, rgba(125,185,232,1) 100%); 95 | background-origin: border-box; 96 | background-repeat: repeat-x; 97 | } 98 | #body { 99 | padding: 5px 0px 5px 0px; 100 | margin-top: 0px; 101 | margin-bottom: 0px; 102 | margin-left: auto; 103 | margin-right: auto; 104 | width: 100%; 105 | display: inline-block; 106 | text-align: center; 107 | } 108 | #wrap { 109 | margin: auto; 110 | text-align: left; 111 | display: inline-block; 112 | } 113 | a { 114 | color: green; 115 | text-decoration: none; 116 | } 117 | a:hover { 118 | color: red; 119 | } 120 | a:visited { 121 | color: green; 122 | } 123 | button.like-link { 124 | display: inline-block; 125 | position: relative; 126 | background-color: transparent; 127 | color: green; 128 | padding: 0; 129 | border: 0; 130 | text-decoration: none; /*underline;*/ 131 | cursor: pointer; 132 | } 133 | h1 { 134 | font-family: "Graublau Web", "Unkempt", "DejaVu Sans", sans-serif; 135 | font-size: 48pt; 136 | text-align: center; 137 | font-weight: 100; 138 | margin-top: 10px; 139 | margin-bottom: 10px; 140 | } 141 | small { 142 | font-size: 10px; 143 | } 144 | #example-inputs-to-try-div { 145 | height: 200px; 146 | width: 600px; 147 | overflow: auto; 148 | 149 | background-image: -moz-linear-gradient(top, rgba(50,50,50,1) 0%, rgba(255,255,255,1) 10%, rgba(255,255,255,1) 90%, rgba(50,50,50,1) 100%); 150 | background-image: -webkit-linear-gradient(top, rgba(0,0,0,0) 0%, rgba(0,0,0,1) 10%, rgba(0,0,0,1) 70%, rgba(0,0,0,0.4) 80%, rgba(0,0,0,0) 100%); 151 | background-image: -o-linear-gradient(top, rgba(50,50,50,0) 0%, rgba(255,255,255,1) 10%, rgba(255,255,255,1) 90%, rgba(50,50,50,0) 100%); 152 | background-image: linear-gradient(top, rgba(50,50,50,1) 0%, rgba(255,255,255,1) 10%, rgba(255,255,255,1) 90%, rgba(50,50,50,1) 100%); 153 | background-repeat: repeat-x; 154 | background-origin: border-box; 155 | background-clip: text; 156 | text-fill-color: transparent; 157 | -webkit-background-clip: text; 158 | -webkit-text-fill-color: transparent; 159 | 160 | margin-top: 15px; 161 | margin-bottom: 15px; 162 | margin-left: auto; 163 | margin-right: auto; 164 | } 165 | .example-inputs-to-try { 166 | font-size: 16px; 167 | margin-top: 10px; 168 | margin-bottom: 60px; 169 | } 170 | ul { 171 | margin-left: 0px; 172 | padding-left: 0px; 173 | } 174 | ul li { 175 | margin-left: 5px; 176 | padding-left: 5px; 177 | list-style-type: none; 178 | } 179 | .example-inputs-to-try li { 180 | line-height: 1.5; 181 | cursor: pointer; 182 | } 183 | .example-inputs-to-try li, #codeforminput, #debugdiv { 184 | font-family: "Unkempt", "DejaVu Sans Mono", monospace; 185 | font-size: 12pt; 186 | } 187 | /* By default hide examples not in class nx */ 188 | /* 189 | // moved to JS 190 | ul.example-inputs-to-try li:not(.nx) { 191 | display: none; 192 | } 193 | */ 194 | 195 | #input-area { 196 | awidth: 100%; 197 | font-size: 32px; 198 | text-align: center; 199 | margin-left: auto; 200 | margin-right: auto; 201 | } 202 | #codeforminput { 203 | width: 640px; 204 | font-size: 32px; 205 | background-color: rgba(125,185,232,0); 206 | } 207 | #codeforminputsubmit, #run-unittest-button, #clear-log-button { 208 | font-size: 32px; 209 | } 210 | #codeforminputsubmit { 211 | width: 100px; 212 | } 213 | #evalresult { 214 | border-radius: 5px; 215 | padding: 5px; 216 | background-color: rgba(125,185,232,0); 217 | width: 750px; 218 | font-size: 24px; 219 | } 220 | #codeform { 221 | font-family: "Unkempt", "DejaVu Sans Mono", monospace; 222 | font-size: 24px; 223 | } 224 | #codeform p { 225 | line-height: 1.0; 226 | margin-top: 0.1em; 227 | margin-bottom: 0.1em; 228 | opacity: 0.1; 229 | -webkit-transition: opacity 0.8s linear; 230 | -moz-transition: opacity 0.8s linear; 231 | -o-transition: opacity 0.8s linear; 232 | -ms-transition: opacity 0.8s linear; 233 | transition: opacity 0.8ss linear; 234 | } 235 | #codeform p.widoczne { 236 | opacity: 1; 237 | } 238 | #debugdiv { 239 | border: 1px solid black; 240 | aheight: 180px; 241 | awidth: 100%; 242 | width: 750px; 243 | a-overflow-y: scroll; 244 | a-overflow-x: scroll; 245 | 246 | a-white-space: nowrap; 247 | overflow: hidden; 248 | text-overflow: ellipsis; 249 | } 250 | textarea, input { 251 | font-family: "Unkempt", "DejaVu Sans Mono", monospace; 252 | font-size: 24px; 253 | } 254 | #przycisk_pi_start1, #przycisk_pi_start2 { 255 | width: 250px; 256 | } 257 | #pole_pi1, #pole_pi2 { 258 | width: 500px; 259 | font-size: 14px; 260 | } 261 | #pole1 { 262 | width: 750px; 263 | font-size: 14px; 264 | } 265 | fieldset { 266 | border: 0; 267 | } 268 | -------------------------------------------------------------------------------- /erl_lib/ct_expand.erl: -------------------------------------------------------------------------------- 1 | %%% The contents of this file are subject to the Erlang Public License, 2 | %%% Version 1.0, (the "License"); you may not use this file except in 3 | %%% compliance with the License. You may obtain a copy of the License at 4 | %%% http://www.erlang.org/license/EPL1_0.txt 5 | %%% 6 | %%% Software distributed under the License is distributed on an "AS IS" 7 | %%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 8 | %%% the License for the specific language governing rights and limitations 9 | %%% under the License. 10 | %%% 11 | %%% The Original Code is ___ 12 | %%% 13 | %%% The Initial Developer of the Original Code is Ericsson Telecom 14 | %%% AB. Portions created by Ericsson are Copyright (C), 1998, Ericsson 15 | %%% Telecom AB. All Rights Reserved. 16 | %%% 17 | %%% Contributor(s): ______________________________________. 18 | %%% 19 | %%% ------------------------------------------------------------------ 20 | -module(ct_expand). 21 | -id(''). 22 | -vsn(''). 23 | -date('2006-08-22'). 24 | -author('ulf.wiger@ericsson.com'). 25 | 26 | %%% This module is a quick hack to allow for compile-time expansion of 27 | %%% complex expressions. To trigger the expansion, wrap the expression 28 | %%% inside a call to ct_expand:term/1. 29 | %%% 30 | %%% A simple example: 31 | %%% 32 | %%% f() -> 33 | %%% ct_expand:term( 34 | %%% ordsets:from_list([this, is, a, list, 'of', atoms]) 35 | %%% ). 36 | %%% 37 | %%% The parse_transform evaluates this into: 38 | %%% 39 | %%% f() -> [a, atoms, is, list, 'of', this]. 40 | %%% 41 | 42 | 43 | -export([function/4, 44 | format_error/1]). 45 | -export([parse_transform/2]). 46 | 47 | 48 | 49 | -define(ERROR(R, T, F, I), 50 | begin 51 | rpt_error(R, T, F, I), 52 | throw({error,erl_syntax:get_pos( 53 | proplists:get_value(form,I)),{unknown,R}}) 54 | end). 55 | 56 | -import(erl_syntax, [clause/3, 57 | clause_patterns/1, 58 | clause_body/1, 59 | clause_guard/1, 60 | match_expr/2, 61 | function_clauses/1, 62 | get_pos/1, 63 | add_ann/2, 64 | get_ann/1]). 65 | 66 | %%% ================================================================== 67 | %%% This is the custom code that's been added. The rest of the module 68 | %%% is 'library code' (or should be...) 69 | %%% Any expression wrapped inside a call to ct_expand:term(Expr) is 70 | %%% replaced at compile-time with the results from erl_eval([Expr], []) 71 | %%% (note: no bindings) 72 | %%% 73 | parse_transform(Forms, Options) -> 74 | function({?MODULE, term, 1}, 75 | fun(Form, _Context) -> 76 | io:format("expanding...~n", []), 77 | case erl_syntax:application_arguments(Form) of 78 | [Expr] -> 79 | case erl_eval:exprs(revert_tree([Expr]), []) of 80 | {value, Value, _} -> 81 | erl_syntax:abstract(Value); 82 | Other -> 83 | erlang:error({cannot_evaluate, 84 | [Expr, Other]}) 85 | end; 86 | _Args -> 87 | erlang:error(illegal_form) 88 | end 89 | end, Forms, Options). 90 | 91 | %%% End custom code. 92 | %%% ================================================================== 93 | 94 | 95 | %%% API: function({Module, Function, Arity}, Fun, Forms, Options) -> 96 | %%% NewForms 97 | %%% 98 | %%% Forms and Options are the arguments passed to the parse_transform/2 99 | %%% function. 100 | %%% {Module, Function, Arity} is the function call to transform 101 | %%% Fun(Form, Context) -> NewForm is the fun provided by the caller. 102 | %%% 103 | %%% Context is a property list, containing the following properties: 104 | %%% - {file, Filename} 105 | %%% - {module, ModuleName} 106 | %%% - {function, FunctionName} % name of the enclosing function 107 | %%% - {arity, Arity :: integer()} % arity of same 108 | %%% - {var_names, Vars :: [atom()]} % generated variables binding the 109 | %%% % function arguments. 110 | %%% % length(Vars) == Arity 111 | %%% 112 | function({_Module, _Function, _Arity} = MFA, F, 113 | Forms, Options) when is_function(F) -> 114 | parse_transform(MFA, F, Forms, Options). 115 | 116 | parse_transform(MFA, Fun, Forms, _Options) -> 117 | [File|_] = [F || {attribute,_,file,{F,_}} <- Forms], 118 | try begin 119 | NewTree = xform(MFA, Fun, Forms, [{file, File}]), 120 | revert_tree(NewTree) 121 | end 122 | catch 123 | throw:{error,Ln,What} -> 124 | {error, [{File, [{Ln,?MODULE,What}]}], []} 125 | end. 126 | 127 | revert_tree(Tree) -> 128 | [erl_syntax:revert(T) || T <- lists:flatten(Tree)]. 129 | 130 | 131 | format_error(Other) -> 132 | lists:flatten( 133 | io_lib:format("unknown error in parse_transform: ~p", [Other])). 134 | 135 | 136 | 137 | 138 | xform({M,F,A}, Fun, Forms, Context0) -> 139 | Bef = fun(function, Form, Ctxt) -> 140 | {Fname, Arity} = erl_syntax_lib:analyze_function(Form), 141 | VarNames = erl_syntax_lib:new_variable_names( 142 | Arity, 143 | erl_syntax_lib:variables(Form)), 144 | {Form, [{function, Fname}, 145 | {arity, Arity}, 146 | {var_names, VarNames}|Ctxt]}; 147 | (_, Form, Context) -> 148 | {Form, Context} 149 | end, 150 | Aft = fun(application, Form, Context) -> 151 | case erl_syntax_lib:analyze_application(Form) of 152 | {M, {F, A}} -> 153 | add_ann( 154 | bind_state, 155 | Fun(Form, Context)); 156 | _ -> 157 | Form 158 | end; 159 | (function, Form, Context) -> 160 | Form1 = 161 | erl_syntax_lib:map_subtrees( 162 | fun(Clause) -> 163 | case should_i_bind(Clause) of 164 | true -> 165 | Pats = clause_patterns(Clause), 166 | CBod = clause_body(Clause), 167 | CGd = clause_guard(Clause), 168 | Pats1 = 169 | lists:zipwith( 170 | fun(V, P) -> 171 | match_expr(v(V), P) 172 | end, 173 | proplists:get_value( 174 | var_names, Context), 175 | Pats), 176 | clause(Pats1, CGd, CBod); 177 | false -> 178 | Clause 179 | end 180 | end, Form), 181 | Form1; 182 | (_, Form, _Context) -> 183 | Form 184 | end, 185 | [Module] = [Mx || {attribute, _, module, Mx} <- Forms], 186 | transform(Forms, Bef, Aft, [{module, Module}|Context0]). 187 | 188 | 189 | transform(Forms, Before, After, Context) -> 190 | F1 = 191 | fun(Form) -> 192 | Type = erl_syntax:type(Form), 193 | {Form1, Context1} = 194 | try Before(Type, Form, Context) 195 | catch 196 | error:Reason -> 197 | ?ERROR(Reason, 'before', Before, 198 | [{type, Type}, 199 | {context, Context}, 200 | {form, Form}]) 201 | end, 202 | Form2 = 203 | case erl_syntax:subtrees(Form1) of 204 | [] -> 205 | Form1; 206 | List -> 207 | NewList = 208 | transform( 209 | List, Before, After, Context1), 210 | erl_syntax:update_tree(Form, NewList) 211 | end, 212 | Type2 = erl_syntax:type(Form2), 213 | try After(Type2, Form2, Context1) 214 | catch 215 | error:Reason2 -> 216 | ?ERROR(Reason2, 'after', After, 217 | [{type, Type2}, 218 | {context, Context1}, 219 | {form, Form2}]) 220 | end 221 | end, 222 | F2 = fun(List) when is_list(List) -> 223 | map(F1, List); 224 | (Form) -> 225 | F1(Form) 226 | end, 227 | map(F2, Forms). 228 | 229 | %%% Slightly modified version of lists:mapfoldl/3 230 | %%% Here, F/2 is able to insert forms before and after the form 231 | %%% in question. The inserted forms are not transformed afterwards. 232 | map(F, [Hd|Tail]) -> 233 | {Before, Res, After} = 234 | case F(Hd) of 235 | {Be, _, Af} = Result when is_list(Be), is_list(Af) -> 236 | Result; 237 | R1 -> 238 | {[], R1, []} 239 | end, 240 | Rs = map(F, Tail), 241 | Before ++ [Res| After ++ Rs]; 242 | map(F, []) when is_function(F, 1) -> []. 243 | 244 | 245 | 246 | rpt_error(Reason, BeforeOrAfter, Fun, Info) -> 247 | Fmt = lists:flatten( 248 | ["*** ERROR in parse_transform function:~n" 249 | "*** Reason = ~p~n" 250 | "*** applying ~w fun (~p)~n", 251 | ["*** ~10w = ~p~n" || _ <- Info]]), 252 | Args = [Reason, BeforeOrAfter, Fun | 253 | lists:foldr( 254 | fun({K,V}, Acc) -> 255 | [K, V | Acc] 256 | end, [], Info)], 257 | io:format(Fmt, Args). 258 | 259 | 260 | should_i_bind(Tree) -> 261 | erl_syntax_lib:fold( 262 | fun(T, Flag) -> 263 | lists:member(bind_state, get_ann(T)) or Flag 264 | end, false, Tree). 265 | 266 | 267 | 268 | v(V) -> 269 | erl_syntax:variable(V). 270 | -------------------------------------------------------------------------------- /from_otp/beam_opcodes.erl: -------------------------------------------------------------------------------- 1 | -module(beam_opcodes). 2 | %% Warning: Do not edit this file. It was automatically 3 | %% generated by 'beam_makeops' on Wed Nov 5 12:42:25 2008. 4 | 5 | -export([format_number/0]). 6 | -export([opcode/2,opname/1]). 7 | 8 | -spec format_number() -> 0. 9 | format_number() -> 0. 10 | 11 | -spec opcode(atom(), 0..8) -> 1..148. 12 | opcode(label, 1) -> 1; 13 | opcode(func_info, 3) -> 2; 14 | opcode(int_code_end, 0) -> 3; 15 | opcode(call, 2) -> 4; 16 | opcode(call_last, 3) -> 5; 17 | opcode(call_only, 2) -> 6; 18 | opcode(call_ext, 2) -> 7; 19 | opcode(call_ext_last, 3) -> 8; 20 | opcode(bif0, 2) -> 9; 21 | opcode(bif1, 4) -> 10; 22 | opcode(bif2, 5) -> 11; 23 | opcode(allocate, 2) -> 12; 24 | opcode(allocate_heap, 3) -> 13; 25 | opcode(allocate_zero, 2) -> 14; 26 | opcode(allocate_heap_zero, 3) -> 15; 27 | opcode(test_heap, 2) -> 16; 28 | opcode(init, 1) -> 17; 29 | opcode(deallocate, 1) -> 18; 30 | opcode(return, 0) -> 19; 31 | opcode(send, 0) -> 20; 32 | opcode(remove_message, 0) -> 21; 33 | opcode(timeout, 0) -> 22; 34 | opcode(loop_rec, 2) -> 23; 35 | opcode(loop_rec_end, 1) -> 24; 36 | opcode(wait, 1) -> 25; 37 | opcode(wait_timeout, 2) -> 26; 38 | %%opcode(m_plus, 4) -> 27; 39 | %%opcode(m_minus, 4) -> 28; 40 | %%opcode(m_times, 4) -> 29; 41 | %%opcode(m_div, 4) -> 30; 42 | %%opcode(int_div, 4) -> 31; 43 | %%opcode(int_rem, 4) -> 32; 44 | %%opcode(int_band, 4) -> 33; 45 | %%opcode(int_bor, 4) -> 34; 46 | %%opcode(int_bxor, 4) -> 35; 47 | %%opcode(int_bsl, 4) -> 36; 48 | %%opcode(int_bsr, 4) -> 37; 49 | %%opcode(int_bnot, 3) -> 38; 50 | opcode(is_lt, 3) -> 39; 51 | opcode(is_ge, 3) -> 40; 52 | opcode(is_eq, 3) -> 41; 53 | opcode(is_ne, 3) -> 42; 54 | opcode(is_eq_exact, 3) -> 43; 55 | opcode(is_ne_exact, 3) -> 44; 56 | opcode(is_integer, 2) -> 45; 57 | opcode(is_float, 2) -> 46; 58 | opcode(is_number, 2) -> 47; 59 | opcode(is_atom, 2) -> 48; 60 | opcode(is_pid, 2) -> 49; 61 | opcode(is_reference, 2) -> 50; 62 | opcode(is_port, 2) -> 51; 63 | opcode(is_nil, 2) -> 52; 64 | opcode(is_binary, 2) -> 53; 65 | opcode(is_constant, 2) -> 54; 66 | opcode(is_list, 2) -> 55; 67 | opcode(is_nonempty_list, 2) -> 56; 68 | opcode(is_tuple, 2) -> 57; 69 | opcode(test_arity, 3) -> 58; 70 | opcode(select_val, 3) -> 59; 71 | opcode(select_tuple_arity, 3) -> 60; 72 | opcode(jump, 1) -> 61; 73 | opcode('catch', 2) -> 62; 74 | opcode(catch_end, 1) -> 63; 75 | opcode(move, 2) -> 64; 76 | opcode(get_list, 3) -> 65; 77 | opcode(get_tuple_element, 3) -> 66; 78 | opcode(set_tuple_element, 3) -> 67; 79 | opcode(put_string, 3) -> 68; 80 | opcode(put_list, 3) -> 69; 81 | opcode(put_tuple, 2) -> 70; 82 | opcode(put, 1) -> 71; 83 | opcode(badmatch, 1) -> 72; 84 | opcode(if_end, 0) -> 73; 85 | opcode(case_end, 1) -> 74; 86 | opcode(call_fun, 1) -> 75; 87 | %%opcode(make_fun, 3) -> 76; 88 | opcode(is_function, 2) -> 77; 89 | opcode(call_ext_only, 2) -> 78; 90 | %%opcode(bs_start_match, 2) -> 79; 91 | %%opcode(bs_get_integer, 5) -> 80; 92 | %%opcode(bs_get_float, 5) -> 81; 93 | %%opcode(bs_get_binary, 5) -> 82; 94 | %%opcode(bs_skip_bits, 4) -> 83; 95 | %%opcode(bs_test_tail, 2) -> 84; 96 | %%opcode(bs_save, 1) -> 85; 97 | %%opcode(bs_restore, 1) -> 86; 98 | %%opcode(bs_init, 2) -> 87; 99 | %%opcode(bs_final, 2) -> 88; 100 | opcode(bs_put_integer, 5) -> 89; 101 | opcode(bs_put_binary, 5) -> 90; 102 | opcode(bs_put_float, 5) -> 91; 103 | opcode(bs_put_string, 2) -> 92; 104 | %%opcode(bs_need_buf, 1) -> 93; 105 | opcode(fclearerror, 0) -> 94; 106 | opcode(fcheckerror, 1) -> 95; 107 | opcode(fmove, 2) -> 96; 108 | opcode(fconv, 2) -> 97; 109 | opcode(fadd, 4) -> 98; 110 | opcode(fsub, 4) -> 99; 111 | opcode(fmul, 4) -> 100; 112 | opcode(fdiv, 4) -> 101; 113 | opcode(fnegate, 3) -> 102; 114 | opcode(make_fun2, 1) -> 103; 115 | opcode('try', 2) -> 104; 116 | opcode(try_end, 1) -> 105; 117 | opcode(try_case, 1) -> 106; 118 | opcode(try_case_end, 1) -> 107; 119 | opcode(raise, 2) -> 108; 120 | opcode(bs_init2, 6) -> 109; 121 | opcode(bs_bits_to_bytes, 3) -> 110; 122 | opcode(bs_add, 5) -> 111; 123 | opcode(apply, 1) -> 112; 124 | opcode(apply_last, 2) -> 113; 125 | opcode(is_boolean, 2) -> 114; 126 | opcode(is_function2, 3) -> 115; 127 | opcode(bs_start_match2, 5) -> 116; 128 | opcode(bs_get_integer2, 7) -> 117; 129 | opcode(bs_get_float2, 7) -> 118; 130 | opcode(bs_get_binary2, 7) -> 119; 131 | opcode(bs_skip_bits2, 5) -> 120; 132 | opcode(bs_test_tail2, 3) -> 121; 133 | opcode(bs_save2, 2) -> 122; 134 | opcode(bs_restore2, 2) -> 123; 135 | opcode(gc_bif1, 5) -> 124; 136 | opcode(gc_bif2, 6) -> 125; 137 | %%opcode(bs_final2, 2) -> 126; 138 | %%opcode(bs_bits_to_bytes2, 2) -> 127; 139 | %%opcode(put_literal, 2) -> 128; 140 | opcode(is_bitstr, 2) -> 129; 141 | opcode(bs_context_to_binary, 1) -> 130; 142 | opcode(bs_test_unit, 3) -> 131; 143 | opcode(bs_match_string, 4) -> 132; 144 | opcode(bs_init_writable, 0) -> 133; 145 | opcode(bs_append, 8) -> 134; 146 | opcode(bs_private_append, 6) -> 135; 147 | opcode(trim, 2) -> 136; 148 | opcode(bs_init_bits, 6) -> 137; 149 | opcode(bs_get_utf8, 5) -> 138; 150 | opcode(bs_skip_utf8, 4) -> 139; 151 | opcode(bs_get_utf16, 5) -> 140; 152 | opcode(bs_skip_utf16, 4) -> 141; 153 | opcode(bs_get_utf32, 5) -> 142; 154 | opcode(bs_skip_utf32, 4) -> 143; 155 | opcode(bs_utf8_size, 3) -> 144; 156 | opcode(bs_put_utf8, 3) -> 145; 157 | opcode(bs_utf16_size, 3) -> 146; 158 | opcode(bs_put_utf16, 3) -> 147; 159 | opcode(bs_put_utf32, 3) -> 148; 160 | opcode(Name, Arity) -> erlang:error(badarg, [Name,Arity]). 161 | 162 | -spec opname(1..148) -> {atom(),0..8}. 163 | opname(1) -> {label,1}; 164 | opname(2) -> {func_info,3}; 165 | opname(3) -> {int_code_end,0}; 166 | opname(4) -> {call,2}; 167 | opname(5) -> {call_last,3}; 168 | opname(6) -> {call_only,2}; 169 | opname(7) -> {call_ext,2}; 170 | opname(8) -> {call_ext_last,3}; 171 | opname(9) -> {bif0,2}; 172 | opname(10) -> {bif1,4}; 173 | opname(11) -> {bif2,5}; 174 | opname(12) -> {allocate,2}; 175 | opname(13) -> {allocate_heap,3}; 176 | opname(14) -> {allocate_zero,2}; 177 | opname(15) -> {allocate_heap_zero,3}; 178 | opname(16) -> {test_heap,2}; 179 | opname(17) -> {init,1}; 180 | opname(18) -> {deallocate,1}; 181 | opname(19) -> {return,0}; 182 | opname(20) -> {send,0}; 183 | opname(21) -> {remove_message,0}; 184 | opname(22) -> {timeout,0}; 185 | opname(23) -> {loop_rec,2}; 186 | opname(24) -> {loop_rec_end,1}; 187 | opname(25) -> {wait,1}; 188 | opname(26) -> {wait_timeout,2}; 189 | opname(27) -> {m_plus,4}; 190 | opname(28) -> {m_minus,4}; 191 | opname(29) -> {m_times,4}; 192 | opname(30) -> {m_div,4}; 193 | opname(31) -> {int_div,4}; 194 | opname(32) -> {int_rem,4}; 195 | opname(33) -> {int_band,4}; 196 | opname(34) -> {int_bor,4}; 197 | opname(35) -> {int_bxor,4}; 198 | opname(36) -> {int_bsl,4}; 199 | opname(37) -> {int_bsr,4}; 200 | opname(38) -> {int_bnot,3}; 201 | opname(39) -> {is_lt,3}; 202 | opname(40) -> {is_ge,3}; 203 | opname(41) -> {is_eq,3}; 204 | opname(42) -> {is_ne,3}; 205 | opname(43) -> {is_eq_exact,3}; 206 | opname(44) -> {is_ne_exact,3}; 207 | opname(45) -> {is_integer,2}; 208 | opname(46) -> {is_float,2}; 209 | opname(47) -> {is_number,2}; 210 | opname(48) -> {is_atom,2}; 211 | opname(49) -> {is_pid,2}; 212 | opname(50) -> {is_reference,2}; 213 | opname(51) -> {is_port,2}; 214 | opname(52) -> {is_nil,2}; 215 | opname(53) -> {is_binary,2}; 216 | opname(54) -> {is_constant,2}; 217 | opname(55) -> {is_list,2}; 218 | opname(56) -> {is_nonempty_list,2}; 219 | opname(57) -> {is_tuple,2}; 220 | opname(58) -> {test_arity,3}; 221 | opname(59) -> {select_val,3}; 222 | opname(60) -> {select_tuple_arity,3}; 223 | opname(61) -> {jump,1}; 224 | opname(62) -> {'catch',2}; 225 | opname(63) -> {catch_end,1}; 226 | opname(64) -> {move,2}; 227 | opname(65) -> {get_list,3}; 228 | opname(66) -> {get_tuple_element,3}; 229 | opname(67) -> {set_tuple_element,3}; 230 | opname(68) -> {put_string,3}; 231 | opname(69) -> {put_list,3}; 232 | opname(70) -> {put_tuple,2}; 233 | opname(71) -> {put,1}; 234 | opname(72) -> {badmatch,1}; 235 | opname(73) -> {if_end,0}; 236 | opname(74) -> {case_end,1}; 237 | opname(75) -> {call_fun,1}; 238 | opname(76) -> {make_fun,3}; 239 | opname(77) -> {is_function,2}; 240 | opname(78) -> {call_ext_only,2}; 241 | opname(79) -> {bs_start_match,2}; 242 | opname(80) -> {bs_get_integer,5}; 243 | opname(81) -> {bs_get_float,5}; 244 | opname(82) -> {bs_get_binary,5}; 245 | opname(83) -> {bs_skip_bits,4}; 246 | opname(84) -> {bs_test_tail,2}; 247 | opname(85) -> {bs_save,1}; 248 | opname(86) -> {bs_restore,1}; 249 | opname(87) -> {bs_init,2}; 250 | opname(88) -> {bs_final,2}; 251 | opname(89) -> {bs_put_integer,5}; 252 | opname(90) -> {bs_put_binary,5}; 253 | opname(91) -> {bs_put_float,5}; 254 | opname(92) -> {bs_put_string,2}; 255 | opname(93) -> {bs_need_buf,1}; 256 | opname(94) -> {fclearerror,0}; 257 | opname(95) -> {fcheckerror,1}; 258 | opname(96) -> {fmove,2}; 259 | opname(97) -> {fconv,2}; 260 | opname(98) -> {fadd,4}; 261 | opname(99) -> {fsub,4}; 262 | opname(100) -> {fmul,4}; 263 | opname(101) -> {fdiv,4}; 264 | opname(102) -> {fnegate,3}; 265 | opname(103) -> {make_fun2,1}; 266 | opname(104) -> {'try',2}; 267 | opname(105) -> {try_end,1}; 268 | opname(106) -> {try_case,1}; 269 | opname(107) -> {try_case_end,1}; 270 | opname(108) -> {raise,2}; 271 | opname(109) -> {bs_init2,6}; 272 | opname(110) -> {bs_bits_to_bytes,3}; 273 | opname(111) -> {bs_add,5}; 274 | opname(112) -> {apply,1}; 275 | opname(113) -> {apply_last,2}; 276 | opname(114) -> {is_boolean,2}; 277 | opname(115) -> {is_function2,3}; 278 | opname(116) -> {bs_start_match2,5}; 279 | opname(117) -> {bs_get_integer2,7}; 280 | opname(118) -> {bs_get_float2,7}; 281 | opname(119) -> {bs_get_binary2,7}; 282 | opname(120) -> {bs_skip_bits2,5}; 283 | opname(121) -> {bs_test_tail2,3}; 284 | opname(122) -> {bs_save2,2}; 285 | opname(123) -> {bs_restore2,2}; 286 | opname(124) -> {gc_bif1,5}; 287 | opname(125) -> {gc_bif2,6}; 288 | opname(126) -> {bs_final2,2}; 289 | opname(127) -> {bs_bits_to_bytes2,2}; 290 | opname(128) -> {put_literal,2}; 291 | opname(129) -> {is_bitstr,2}; 292 | opname(130) -> {bs_context_to_binary,1}; 293 | opname(131) -> {bs_test_unit,3}; 294 | opname(132) -> {bs_match_string,4}; 295 | opname(133) -> {bs_init_writable,0}; 296 | opname(134) -> {bs_append,8}; 297 | opname(135) -> {bs_private_append,6}; 298 | opname(136) -> {trim,2}; 299 | opname(137) -> {bs_init_bits,6}; 300 | opname(138) -> {bs_get_utf8,5}; 301 | opname(139) -> {bs_skip_utf8,4}; 302 | opname(140) -> {bs_get_utf16,5}; 303 | opname(141) -> {bs_skip_utf16,4}; 304 | opname(142) -> {bs_get_utf32,5}; 305 | opname(143) -> {bs_skip_utf32,4}; 306 | opname(144) -> {bs_utf8_size,3}; 307 | opname(145) -> {bs_put_utf8,3}; 308 | opname(146) -> {bs_utf16_size,3}; 309 | opname(147) -> {bs_put_utf16,3}; 310 | opname(148) -> {bs_put_utf32,3}; 311 | opname(Number) -> erlang:error(badarg, [Number]). 312 | -------------------------------------------------------------------------------- /js_src/erljs_control.js: -------------------------------------------------------------------------------- 1 | /* Copyright 2008-2011, Witold Baryluk 2 | * erljs project 3 | */ 4 | 5 | /* 6 | function test(code) { 7 | return erljs_vm_call(code, 100); 8 | } 9 | 10 | function test_json(code) { 11 | // not very good way. use prototype.js. some new browsers have native fast and safe JSON import/export. 12 | var e = eval(code); 13 | alert(e); 14 | return test(e); 15 | } 16 | */ 17 | 18 | function erl(X, ShowInput) { 19 | var r = /^\s*([^:]+):([^(]+)\((.*)\)\.?\s*$/; 20 | var m = r.exec(X); 21 | if (m) { 22 | var args = []; 23 | var A = 0; 24 | var s = m[3]; 25 | if (s.length) { 26 | var i = 0; 27 | var a = get_next(s,i,false); 28 | args[A++]=a[0]; 29 | i=a[1]; 30 | // skip white space 31 | while ((s[i] == " " || s[i] == "\t" || s[i] == "\n" || s[i] == "\r") && i < s.length) { 32 | i++; 33 | } 34 | while (s[i] == ",") { 35 | i++; 36 | var a = get_next(s,i,false); 37 | args[A++]=a[0]; 38 | i=a[1]; 39 | while ((s[i] == " " || s[i] == "\t" || s[i] == "\n" || s[i] == "\r") && i < s.length) { 40 | i++; 41 | } 42 | } 43 | if (i != m[3].length) throw "bad syntax in arguments list"; 44 | } 45 | if (ShowInput) { 46 | debug("erljs VM call: "+X); 47 | } 48 | return erljs_vm_call(all_modules, [m[1], m[2], A], args); 49 | } else { 50 | throw "bad syntax: " + X; 51 | } 52 | }; 53 | 54 | var erljs_erlgo_counter = 1; 55 | 56 | function erljs_term_to_string(X, pretty) { 57 | var R; 58 | if (pretty) { 59 | var temp = erljs_toString_pretty_printing; 60 | erljs_toString_pretty_printing = pretty; 61 | R = X.toString(); 62 | erljs_toString_pretty_printing = temp; 63 | } else { 64 | R = X.toString(); 65 | } 66 | return R; 67 | } 68 | 69 | function erlgo(X, ShowResult, pretty, animate) { 70 | var R,RR,RRP; 71 | var no_exp = false; 72 | try { 73 | R = erl(X); 74 | RR = R.toString(); 75 | if (pretty) { 76 | RRP = erljs_term_to_string(R, pretty); 77 | } else { 78 | RRP = RR; 79 | } 80 | no_exp = true; 81 | } catch(err) { 82 | RRP = RR = "Error: "+err; 83 | R = err; 84 | } 85 | if (ShowResult) { 86 | debug("Result: "+RR); 87 | } 88 | try { 89 | var c = document.getElementById('codeform'); 90 | var f = c.firstChild; 91 | 92 | // TODO: display how much time and reductions it took to evaluate X 93 | 94 | var p1 = document.createElement("p"); 95 | var maybe_dot = (X.charAt(X.length-1) == '.' ? "" : "."); 96 | p1.appendChild(document.createTextNode(""+erljs_erlgo_counter+"> "+X+maybe_dot)); 97 | c.insertBefore(p1, f); 98 | 99 | var p2 = document.createElement("p"); 100 | if (/^(Exception|Error)/.test(RRP)) { 101 | p2.style.color = "rgb(255,0,0)"; 102 | } 103 | p2.appendChild(document.createTextNode(RRP)); 104 | c.insertBefore(p2, f); 105 | 106 | var show = function() { 107 | p1.toggleClassName("widoczne"); 108 | p2.toggleClassName("widoczne"); 109 | }; 110 | if (animate) { 111 | setTimeout(show, 50); 112 | } else { 113 | show(); 114 | } 115 | 116 | erljs_erlgo_counter++; 117 | 118 | // debug("---"); 119 | } catch (e) { alert(e); }; // Rhino 120 | if (no_exp) { 121 | return RR; 122 | } else { 123 | throw R; 124 | } 125 | } 126 | 127 | function debughfail(x) { 128 | try { 129 | if (document) { 130 | debugh("
"+x+"
"); 131 | } 132 | } catch (e) { 133 | try { 134 | print(x); 135 | } catch (e2) { }; 136 | } 137 | } 138 | 139 | function debughok(x) { 140 | try { 141 | if (document) { 142 | debugh("
"+x+"
"); 143 | } 144 | } catch (e) { 145 | try { 146 | print(x); 147 | } catch (e2) { }; 148 | } 149 | } 150 | 151 | var _unittest_fail = 0, 152 | _unittest_ok = 0; 153 | 154 | function unittest_clear() { 155 | _unittest_fail = 0; 156 | _unittest_ok = 0; 157 | } 158 | 159 | function unittest_stats() { 160 | return {ok: _unittest_ok, fail: _unittest_fail}; 161 | } 162 | 163 | var eq_hide_green = false; 164 | 165 | function eq(Input,Expected,OriginalCodeForWrapper) { 166 | _unittest_fail++; 167 | var failed = true; 168 | var ShowAs = Input + (OriginalCodeForWrapper ? " (wrapper for "+OriginalCodeForWrapper +")" : ""); 169 | var Output; 170 | try { 171 | Output = erlgo(Input, undefined, true); 172 | failed = false; 173 | } catch (err) { 174 | failed = true; 175 | var exception = err; 176 | } 177 | 178 | if (failed === false) { 179 | if (Expected !== undefined) { 180 | if (Output != Expected) { 181 | debugh("Input ="+Input); 182 | if (OriginalCodeForWrapper) { 183 | debugh("Code ="+OriginalCodeForWrapper); 184 | } 185 | debugh("Output ="+Output); 186 | debugh("Expected="+Expected); 187 | debughfail(ShowAs + " not evaluated to expected " + Expected); 188 | debughfail(ShowAs + " evaluated insted to " + Output); 189 | debugh("
"); 190 | } else { 191 | if (!eq_hide_green) { 192 | debughok(ShowAs + " evaluated to expected " + Expected); 193 | } 194 | _unittest_fail--; 195 | _unittest_ok++; 196 | } 197 | } else { 198 | if (!eq_hide_green) { 199 | debughok(ShowAs + " executed without error"); 200 | } 201 | _unittest_fail--; 202 | _unittest_ok++; 203 | } 204 | } else { 205 | debughfail(ShowAs + " executed with exception " + exception); 206 | debugh("
"); 207 | } 208 | } 209 | 210 | function unittest__run_examples() { 211 | eq("example:sum1(333)"); 212 | eq("example:sum2(333,1000000)"); 213 | eq("example:ntka(333,1000000)"); 214 | eq("example:tailowa(1000000)"); 215 | eq("example:nietailowa(1000000)"); 216 | //eq("example:konwencje1('dupa','blada','masie')"); 217 | //eq("example:konwencje2('dupa','blada','masie')"); 218 | //eq("example:konwencje3('dupa','blada','masie')"); 219 | //eq("example:konwencje4('dupa','blada','masie')"); 220 | //eq("example:matche('a')"); 221 | eq("example:silnia(20)"); 222 | eq("example:llll(20)"); 223 | 224 | eq("lists:seq(10,30,2)","[10,12,14,16,18,20,22,24,26,28,30]"); 225 | eq("example:llll2(10)","{10,[]}"); 226 | eq("example:llll3(10,14)"); 227 | eq("example:llll_z(33)"); 228 | eq("example:llll_u(33)"); 229 | 230 | eq("example:fib1(12)",144); 231 | eq("example:fib2(12)",144); 232 | eq("example:fib3(12)",144); 233 | eq("example:fib2(60)",1548008755920); 234 | eq("example:fib3(60)",1548008755920); 235 | 236 | eq("example:dd1(10,20,30,40)"); 237 | eq("example:dd2(10,20)"); 238 | eq("example:dd3(10,20,30,40)"); 239 | eq("example:dd4()"); 240 | eq("example:dd5()"); 241 | eq("example:dd6()"); 242 | eq("example:dd7()"); 243 | eq("example:dd8(10,200)"); 244 | eq("example:dd9(30)"); 245 | eq("example:dd10(30)"); 246 | eq("example:dd11(30)"); 247 | eq("example:dd12(30)"); 248 | eq("example:dd13(11,30)"); 249 | eq("example:dd14(11,30)"); 250 | 251 | 252 | eq("example:jss(20)"); 253 | //eq("example:jss2(33)"); 254 | //eq("example:jss3([23,ab,{34,55}])"); 255 | } 256 | 257 | 258 | function unittest__term_decode(T1,T2){ 259 | function d2(x,d2) { 260 | try { 261 | _unittest_fail++; 262 | var e = eterm_decode(x); 263 | var o = (d2==e.toString()); 264 | if (!o) { 265 | debughfail("FAIL INPUT: "+x); 266 | debughfail("FAIL OUTPUT: "+e); 267 | debughfail("FAIL EXPECT: "+d2); 268 | debughfail("FAIL ^^^..."); 269 | throw "No match beetween OUPUT and EXPECT."; 270 | } else { 271 | debughok("OK INPUT: "+x); 272 | _unittest_fail--; 273 | _unittest_ok++; 274 | } 275 | } catch (err) { 276 | debugh("FAIL INPUT: "+x); 277 | debugh("Exception in decoding: "+err); 278 | } 279 | } 280 | function d(x) { 281 | d2(x,x); 282 | } 283 | 284 | if (T1) { 285 | 286 | d("{}"); 287 | d("{{}}"); 288 | d("{{{}}}"); 289 | d("{{},{}}"); 290 | d("{{},{},{}}"); 291 | d("[]"); 292 | d("[[]]"); 293 | d("[[[]]]"); 294 | d("[[],[]]"); 295 | d("[[],[],[]]"); 296 | 297 | d("[{}]"); 298 | d("{[]}"); 299 | d("[{[]}]"); 300 | d("{[{}]}"); 301 | d("[{},{}]"); 302 | d("{[],[]}"); 303 | d("[{},{},{}]"); 304 | d("{[],[],[]}"); 305 | 306 | d("[[],{}]"); 307 | d("[{},[]]"); 308 | d("{[],{}}"); 309 | d("{{},[]}"); 310 | 311 | d("[{}|{}]"); 312 | 313 | d2("[{}|[]]", "[{}]"); 314 | d2("[{}|[{}|[]]]", "[{},{}]"); 315 | d2("[{}|[{}|[{}]]]", "[{},{},{}]"); 316 | 317 | d("[123,321,512]"); 318 | d("[123,321,-512]"); 319 | d("[123,321|-512]"); 320 | d("[123,321,512]"); 321 | d2("[123,321|[512]]","[123,321,512]"); 322 | 323 | d("123"); 324 | d("12.3"); 325 | d("0.3"); 326 | d("-0.3"); 327 | d2("011.3e-23", "1.13e-22"); 328 | d2("+123", "123"); 329 | d("-123"); 330 | d("-123.0312"); 331 | d2("{-123,0.1,12,2,1,31,2,000031,23,0.001,3.0,12013.033,5,6.0e+00021,1,78,8,213123,4,12,3,12323}", 332 | "{-123,0.1,12,2,1,31,2,31,23,0.001,3,12013.033,5,6e+21,1,78,8,213123,4,12,3,12323}"); 333 | d("{20,1,2,1,[2,12,3],{[2,3],[3|4]}}"); 334 | d("[20,1,2,1,[2,12,3]|{[2,3],[3|4]}]"); 335 | 336 | d("ala"); 337 | d("{ala}"); 338 | d("{ala,ma,10,kotow}"); 339 | d("[20.3,nasza,{ala,ma},kota]"); 340 | d("[20.3,nasza,{ala,ma},{malego,0.5},kota]"); 341 | 342 | d2("[ ]", "[]"); 343 | d2("[ a]", "[a]"); 344 | d2("[a ]", "[a]"); 345 | d2("[ a ]", "[a]"); 346 | d2("[a, b]", "[a,b]"); 347 | d2("[ a ,b]", "[a,b]"); 348 | d2("[a , b]", "[a,b]"); 349 | d2("[ a , b ]", "[a,b]"); 350 | d2("[ a ,b ]", "[a,b]"); 351 | d2("[ a,b ]", "[a,b]"); 352 | d2("[a,b ]", "[a,b]"); 353 | 354 | d2("[a| b]", "[a|b]"); 355 | d2("[ a |b]", "[a|b]"); 356 | d2("[a | b]", "[a|b]"); 357 | d2("[ a | b ]", "[a|b]"); 358 | d2("[ a |b ]", "[a|b]"); 359 | d2("[ a|b ]", "[a|b]"); 360 | d2("[a|b ]", "[a|b]"); 361 | 362 | d2("{ }", "{}"); 363 | d2("{ a}", "{a}"); 364 | d2("{a }", "{a}"); 365 | d2("{ a }", "{a}"); 366 | d2("{a, b}", "{a,b}"); 367 | d2("{ a ,b}", "{a,b}"); 368 | d2("{a , b}", "{a,b}"); 369 | d2("{ a , b }", "{a,b}"); 370 | d2("{ a ,b }", "{a,b}"); 371 | d2("{ a,b }", "{a,b}"); 372 | d2("{a,b }", "{a,b}"); 373 | 374 | d2("[ { a , a } , { b } , c ]", "[{a,a},{b},c]"); 375 | 376 | 377 | } 378 | 379 | // many tests bellow will fail becuase missing unescaping in decoder. 380 | // becuase of this they are now commented 381 | 382 | if (T2) { 383 | //d2(".a","a"); 384 | 385 | //d("'ala ALA MA`1234567890 -=`~!@#$%^&*()-=_+{}[]:bz<>?,./| \\\\\\b\\t\\n\\e\\r\\v\\f\\'\\\" \" '"); 386 | //d("'ala ALA MA`1234567890 -=`~!@#$%^&*()-=_+{}[]:bz<>?,./| \\ \\b\\t\\n\\e\\r\\v\\f\\'\\\" \" '"); 387 | d2("'a'","a"); 388 | d("'.a'"); 389 | // d("'\\'"); % illegal 390 | //d2("'\\ '","' '"); 391 | //d("'\\\\'"); 392 | //d("'\\b'"); 393 | //d2("'\\012'","'\\n'"); 394 | //d2("'\\a'","a"); 395 | //d("'\"'"); 396 | //d("'\\''"); 397 | //d2("'\\0'","'\\000'"); 398 | //d2("'\\9'","'9'"); 399 | //d2("'\\123'","'S'"); 400 | //d2("'\\100'","'@'"); 401 | //d2("'\\151'","i"); 402 | //d2("'\\16'","'\\016'"); 403 | //d2("'\\12'","'\\n'"); 404 | //d2("'\\33'","'\\e'"); 405 | //d("'\\035'"); 406 | //d2("'\\377'","ÿ"); 407 | // 17 d("'\\444'"); // illegal 408 | //d("'\\42a22'","\"a22"); // ok 409 | // 18 d("'\\777'"); // illegal 410 | // 18 d("'ą'"); // illegal 411 | //d2("'\\77a7'","'?a7'"); 412 | //d2("'\\99'","'99'"); 413 | // 20 d("'\\888'"); // illegal 414 | // 21 d("'\\x'"); // illegal 415 | //d2("'\\x4f'","'0'"); 416 | // 23 d("'\\x4'"); // illegal 417 | //d2("'\\x41g'","'Ag'"); 418 | //d2("'\\x44ff'","'Dff'"); 419 | d("'...'"); 420 | d("'.@.'"); 421 | //d2("'.@\\\"\\'@@\"@.'","'.@\"\\'@@\"@.'"); 422 | d("'.'"); 423 | d("'?'"); 424 | d("'*'"); 425 | d("'$'"); 426 | //d2("'\\$'","'$'"); 427 | 428 | } 429 | 430 | } 431 | 432 | 433 | 434 | function erljs_init() { 435 | erljs_vm_init(all_modules); 436 | } 437 | 438 | function erljs_unittests() { 439 | unittest_clear(); 440 | unittest__term_decode(true,true); 441 | unittest__run_examples(); 442 | unittest__tests_auto(); 443 | var stats = unittest_stats(); 444 | debugh("=================================="); 445 | debugh("unittests summary:"); 446 | debughok(stats.ok + " tests passed"); 447 | (stats.fail != 0 ? debughfail : debughok) 448 | (stats.fail + " tests failed"); 449 | debugh("=================================="); 450 | 451 | if (stats.fail != 0) { 452 | alert(stats.fail + " tests failed"); 453 | } 454 | } 455 | 456 | -------------------------------------------------------------------------------- /examples/devel/example.erl: -------------------------------------------------------------------------------- 1 | -module(example). 2 | -author('baryluk@smp.if.uj.edu.pl'). 3 | 4 | % Copyright 2008-2011, Witold Baryluk 5 | % erljs project 6 | 7 | -compile([export_all]). 8 | 9 | -export([sum1/1, sum2/2, 10 | diff2/2, iloraz2/2, 11 | ntka/2, 12 | tailowa/1, nietailowa/1, 13 | fqdn/1, 14 | konwencje1/3, konwencje2/3, konwencje3/3, konwencje4/3, 15 | listy/0, listy2/1, 16 | a/1, 17 | mnozacz/1, 18 | fl/1, 19 | kase/1, 20 | duzyterm/0 21 | ]). 22 | 23 | -export_js([export_all]). 24 | 25 | sum1(X) -> 26 | 2*X. 27 | 28 | sum2(X,Y) -> 29 | 2+Y+X. 30 | 31 | diff2(X,Y) -> 32 | 2-X-Y. 33 | 34 | iloraz2(X,Y) -> 35 | 20/X/Y. 36 | 37 | ntka(X,Y) -> 38 | {1,Y,5, X}. 39 | 40 | tailowa(X) -> 41 | ntka(X, 100). 42 | 43 | nietailowa(X) -> 44 | A=ntka(X, 100), 45 | {3233, A}. 46 | 47 | notfqdn(X) -> 48 | notfqdn(X). 49 | 50 | fqdn(X) -> 51 | example:fqdn(X). 52 | 53 | konwencje1(A,B,C) -> 54 | {A,B,C}. 55 | 56 | konwencje2(X,Y,Z) -> 57 | konwencje1(X,Y,Z). 58 | 59 | konwencje3(X,Y,Z) -> 60 | A=konwencje1(a,X,Y), 61 | {ff, A}. 62 | 63 | konwencje4(X,Y,Z) -> 64 | konwencje1(X,Z,Y). 65 | 66 | listy() -> 67 | [a,b,c]. 68 | 69 | listy2(A) -> 70 | [a,A,c]. 71 | 72 | a(E) -> 73 | apply(E, lists, [a]). 74 | a(E,X) -> 75 | apply(E, lists, X). 76 | a0(E) -> 77 | E:lists(a). 78 | 79 | a2(E) -> 80 | {apply(E, lists, [a])}. 81 | a2(E,X) -> 82 | {apply(E, lists, X)}. 83 | a20(E,X) -> 84 | {E:lists(X)}. 85 | 86 | af(F) -> 87 | apply(F, [a,5]). 88 | af(F,X) -> 89 | apply(F, X). 90 | 91 | af0(F) -> 92 | F(). 93 | af1(F) -> 94 | F(3,5). 95 | 96 | % bug this is not tail recurisve. compiler allocate one additional register, need to free 97 | af0_bug(F,X) -> 98 | F(X). 99 | af1_bug(F,X) -> 100 | F(3,4,5). 101 | 102 | 103 | 104 | af0_bug_test(F,X) -> 105 | F(F,X-1). 106 | 107 | af0_bug_start(N0) -> 108 | af0_bug_test(fun(Self, 0) -> ok; (Self, X) -> Self(Self, X-1) end, N0). 109 | 110 | 111 | af2(F) -> 112 | {apply(F, [a,5])}. 113 | af2(F,X) -> 114 | {apply(F, X)}. 115 | af20(F,X) -> 116 | {F(X)}. 117 | 118 | af21(F,X) -> 119 | {F(3,4,5)}. 120 | 121 | matche(A) -> 122 | case A of 123 | {B,_} -> ok; 124 | aaa -> dd 125 | end. 126 | 127 | matche2(A) -> 128 | case A of 129 | {B,_,44} -> B; 130 | aa123a -> dd 131 | end. 132 | 133 | mnozacz(X) -> 134 | F = fun(Y) -> X*Y end, 135 | F. 136 | 137 | mnozacze(X) -> 138 | F = fun(Y) -> X*Y end, 139 | G = fun(Y) -> X+Y end, 140 | H = fun(Y) -> X-Y end, 141 | {F,G,H}. 142 | 143 | 144 | mnozacz2(X) -> 145 | F = fun mnoznik2/1, 146 | F. 147 | 148 | mnozacz3(X) -> 149 | F = fun example:mnoznik2/1, 150 | F. 151 | 152 | mnoznik2(Y) -> 153 | 2*Y. 154 | 155 | mnozacz_big1(X) -> 156 | F = fun(Y,Y2,Y3,Y4,Y5,Y6) -> {X*Y,Y2,Y3,Y4,Y5,Y6} end, 157 | {F,zzzzzzz}. 158 | 159 | mnozacz_big2(X,Y2,Y3,Y4,Y5,Y6) -> 160 | F = fun(Y) -> {X*Y,Y2,Y3,Y4,Y5,Y6} end, 161 | {F,zzzzzzz}. 162 | 163 | mnozacz_big3(Y2,Y3,Y4,Y5,Y6,X) -> 164 | F = fun(Y) -> {X*Y,Y2,Y3,Y4,Y5,Y6} end, 165 | {F,zzzzzzz}. 166 | 167 | mnozacz_big4(Z,Y2,Y3,Y4,Y5,Y6,X) -> 168 | F = fun(Y) -> {X*Y,Y2,Y3,Y4,Y5,Y6} end, 169 | {F,zzzzzzz}. 170 | 171 | 172 | mnozacz_s1(Y2,Y3,Y4,Y5,Y6) -> 173 | F = fun(Y,X) -> {X*Y} end, 174 | {F,zzzzzzz}. 175 | 176 | 177 | mnozacz_s2() -> 178 | F = fun(Y,X) -> {X*Y} end, 179 | {F,zzzzzzz}. 180 | 181 | 182 | mnozacz_s2(O1,O2,O3) -> 183 | F = fun(Y,X) -> {X*Y} end, 184 | {F,zzzzzzz}. 185 | 186 | mnozacz_s3(O1,O2,O3) -> 187 | F = fun(Y,X) -> {X*Y} end, 188 | {F,zzzzzzz}. 189 | 190 | mnozacz_s4(O1,O2,O3) -> 191 | F = fun(Y,X) -> {X*Y} end, 192 | {F,zzzzzzz}. 193 | 194 | 195 | odbierz() -> 196 | receive 197 | a -> ok; 198 | f -> j 199 | after 1111 -> kkk 200 | end. 201 | 202 | odbierz2(X) -> 203 | receive 204 | {a, X, X} -> ok; 205 | f -> j 206 | after 1111 -> kkk 207 | end. 208 | 209 | fl(X) -> 210 | Z=2.0*X + 5.1-55.5/X, 211 | X/-Z. 212 | 213 | kase(X) -> 214 | case X of 215 | {a, 1, N} when N >= 33 -> 216 | {c, N}; 217 | {b, N} when N < 13 -> 218 | {z, N+44} 219 | end. 220 | 221 | kase2(Y) -> 222 | case Y of 223 | N when N > 13 -> 224 | z; 225 | N when N < 1 -> 226 | z2; 227 | N when N >= 10 -> 228 | z; 229 | N when N =< 4 -> 230 | z2 231 | end. 232 | 233 | 234 | duzyterm() -> 235 | A={o,p,e,r,a}, 236 | [A,A]. 237 | 238 | silnia(N) -> 239 | silnia(N, 1). 240 | 241 | silnia(0, Acc) -> 242 | Acc; 243 | silnia(N, Acc) -> 244 | silnia(N-1, N*Acc). 245 | 246 | 247 | sd(N) -> 248 | N/33. 249 | 250 | 251 | maly_div(N) -> 252 | N div 33. 253 | 254 | 255 | maly_minus(N) -> 256 | -N. 257 | 258 | maly_rem(N) -> 259 | N rem 33. 260 | 261 | maly_bbbbb(N) -> 262 | bnot (N bor 33) bxor (N band 44). 263 | 264 | maly_bbbbb2(L,N) -> 265 | B=L bsr N, 266 | B2=L bsl N, 267 | {B,B2}. 268 | 269 | jss(N) -> 270 | erljs:eval(N). 271 | 272 | jss1(N) -> 273 | erljs:eval("alert(4)"). 274 | 275 | jss2(N) -> 276 | erljs:alert(10031*N). 277 | 278 | jss3(N) -> 279 | erljs:alert(N). 280 | 281 | hhh(L) -> 282 | [H|T] = L, 283 | {hhhhhh,H,mmmmm,T,eeeee}. 284 | 285 | hhh3(L) -> 286 | [H,H2|T] = L, 287 | {hhhhhh,H,mmmmm,H2,mnnnnn,T,eeeee}. 288 | 289 | conc(L1,L2) -> 290 | L1 ++ L2. 291 | 292 | hhh4(L) -> 293 | [] = L, 294 | o. 295 | 296 | % erlang:* and bifs 297 | 298 | zzzz(N) when N > 10 -> 299 | 2*N. 300 | 301 | zzzz2(N) when N > 10 -> 302 | 2*N; 303 | zzzz2(N) when N > 5 -> 304 | 2-N. 305 | 306 | zzzz3(A,A) -> 307 | 2-A. 308 | 309 | zzzz4(6) -> 310 | 2. 311 | 312 | zzzz_size1(N) when size(N) == 4 -> 313 | 4. 314 | 315 | zzzz_size2(N) -> 316 | 2+size(N). 317 | 318 | zzzz_size3(N) -> 319 | 2+erlang:size(N). 320 | 321 | zzzz_abs(N) -> 322 | 2+abs(N). 323 | 324 | 325 | llll(N) -> 326 | K=[N,N,N,N], 327 | {ostatni,lists:last(K)}. 328 | 329 | llll2(N) -> 330 | {N,[]}. 331 | 332 | llll3(N,T) -> 333 | L=lists:seq(N, N+20), 334 | {lists:nthtail(T, L)}. 335 | 336 | llll_z(N) -> 337 | L1=lists:seq(N, N+20), 338 | L2=lists:seq(N+310, N+310+20), 339 | {lists:zip(L1,L2)}. 340 | 341 | 342 | llll_u(N) -> 343 | {LZ} = llll_z(N), 344 | {lists:unzip(LZ)}. 345 | 346 | % computes in JS up to fib1(22), then it needs more than 500,000 ops 347 | fib1(0) -> 0; 348 | fib1(1) -> 1; 349 | fib1(N) -> 350 | fib1(N-1) + fib1(N-2). 351 | 352 | 353 | % 14472334024676221 = fib2(78). % but failes in JS, due to conversion to float. 354 | fib2(N) -> 355 | fib2(0, 1, N). 356 | 357 | fib2(PrevPrev, Prev, 1) -> 358 | Prev; 359 | fib2(PrevPrev, Prev, To) -> 360 | fib2(Prev, PrevPrev+Prev, To-1). 361 | 362 | % uses fast squering of 2x2 matrices. 363 | % http://en.literateprograms.org/Fibonacci_numbers_(Erlang) 364 | 365 | fib3(N) -> 366 | {Fib, _} = fib3(N, {1, 1}, {0, 1}), 367 | Fib. 368 | 369 | fib3(0, _, Pair) -> Pair; 370 | fib3(N, {Fib1, Fib2}, Pair) when N rem 2 == 0 -> 371 | SquareFib1 = Fib1*Fib1, 372 | fib3(N div 2, {2*Fib1*Fib2 - SquareFib1, SquareFib1 + Fib2*Fib2}, Pair); 373 | fib3(N, {FibA1, FibA2}=Pair, {FibB1, FibB2}) -> 374 | fib3(N-1, Pair, {FibA1*FibB2 + FibB1*(FibA2 - FibA1), FibA1*FibB1 + FibA2*FibB2}). 375 | 376 | test_fib23(N) -> 377 | {TA,A} = timer:tc(example, fib2, [N]), 378 | {TB,B} = timer:tc(example, fib3, [N]), 379 | A = B, 380 | {ok,TA,TB}. 381 | 382 | dd1(A,B,C,D) -> 383 | lists:seq(A,B) ++ lists:seq(C,D). 384 | 385 | dd2(A,B) -> 386 | lists:reverse(lists:seq(A,B)). 387 | 388 | dd3(A,B,C,D) -> 389 | lists:reverse(lists:seq(A,B), lists:seq(C,D)). 390 | 391 | dd4() -> 392 | {lists:reverse(lists:seq(1,20),6), lists:reverse([],5)}. 393 | 394 | dd5() -> 395 | {lists:seq(1,10),lists:seq(42,46),5}. 396 | 397 | dd6() -> 398 | T = tl(lists:seq(1,10)), 399 | {T}. 400 | 401 | dd7() -> 402 | T = hd(lists:seq(3,10)), 403 | {T}. 404 | 405 | dd8(A,B) -> 406 | lists:sum(lists:seq(A,B)). 407 | 408 | random(N) when N > 0 -> 409 | random(N, 18723, []). 410 | 411 | random(0, _, L) -> L; 412 | % this can overflow in JS, so it will produce other values. fix it later. 413 | %random(N, S, L) -> random(N-1, (S*S*17263876+1237611) rem 871263761, [S|L]). 414 | random(N, S, L) -> random(N-1, (S*1713+137) rem 8711, [S|L]). 415 | 416 | rf(N) -> 417 | [ random:uniform() || _ <- lists:seq(1, N) ]. 418 | 419 | ri(N,Max) -> 420 | [ random:uniform(Max) || _ <- lists:seq(1, N) ]. 421 | 422 | dd9(N) -> 423 | random(N). 424 | 425 | 426 | dd10(N) -> 427 | lists:sum(random(N)). 428 | 429 | dd11(N) -> 430 | lists:filter(fun (X) -> ((X rem 3 == X rem 5)) end, random(N)). 431 | 432 | dd12(N) -> 433 | L = dd9(N), 434 | {lists:sum(L)/length(L), 871263761/2}. 435 | 436 | 437 | dd13(K,N) -> 438 | L = dd9(N), 439 | {lists:nth(K,L)}. 440 | 441 | dd14(K,N) -> 442 | L = dd9(N), 443 | {lists:nthtail(K,L)}. 444 | 445 | all(Pred, [Hd|Tail]) -> 446 | Pred(Hd) andalso all(Pred, Tail); 447 | all(_, []) -> 448 | true. 449 | 450 | none(Pred, [Hd|Tail]) -> 451 | Pred(Hd) orelse all(Pred, Tail); 452 | none(_, []) -> 453 | true. 454 | 455 | limit(X) -> 456 | X bsl (1 bsl 64). 457 | 458 | s(X) -> 459 | math:pow( 460 | math:log(X*math:sin(X))/math:exp(math:tan(X*10.3-math:atan2(X,math:cos(X)))), 461 | math:sqrt(X)*math:pi()). 462 | 463 | l1(K,N) -> 464 | L = dd9(N), 465 | A = [ K*X || X <- L ], 466 | {A}. 467 | 468 | 469 | l2(K,N) -> 470 | L = dd9(N), 471 | L2 = lists:nthtail(N, dd9(2*N)), 472 | A = [ {K*X,Y} || X <- L, Y <- L2 ], 473 | {A}. 474 | 475 | l3(K,N) -> 476 | L = dd9(N), 477 | A = [ {K*X,Y} || X <- L, Y <- dd9(X rem 4+1) ], 478 | {A}. 479 | 480 | 481 | me() -> 482 | A = self(), 483 | {its_me,A}. 484 | 485 | 486 | cross({V10,V11,V12}, {V20,V21,V22}) 487 | when is_float(V10), is_float(V11), is_float(V12), 488 | is_float(V20), is_float(V21), is_float(V22) -> 489 | {V11*V22-V12*V21,V12*V20-V10*V22,V10*V21-V11*V20}. 490 | 491 | cross2({V10,V11,V12}, {V20,V21,V22}) -> 492 | {V11*V22-V12*V21,V12*V20-V10*V22,V10*V21-V11*V20}. 493 | 494 | cross3({V10,V11,V12}, {V20,V21,V22}) 495 | when is_integer(V10), is_integer(V11), is_integer(V12), 496 | is_integer(V20), is_integer(V21), is_integer(V22) -> 497 | {V11*V22-V12*V21,V12*V20-V10*V22,V10*V21-V11*V20}. 498 | 499 | oo1(X) when is_integer(X) -> 500 | true; 501 | oo1(_) -> 502 | false. 503 | 504 | oo2(X) -> 505 | is_integer(X). 506 | 507 | oo3(X) -> 508 | erlang:is_integer(X). 509 | 510 | hasz1(X) -> 511 | erlang:phash(X, 1 bsl 32). 512 | 513 | 514 | 515 | eh1(X) -> 516 | Y = lists:sum(X), 517 | throw({Y,5}). 518 | eh2(X) -> 519 | Y = lists:sum(X), 520 | erlang:error({Y,5}). 521 | eh2b(X) -> 522 | Y = lists:sum(X), 523 | erlang:error({Y,5},[a,b,c]). 524 | eh3(X) -> 525 | Y = try lists:sum(X) of 526 | V -> 527 | {V,4} 528 | catch 529 | _:S -> 530 | {s, S} 531 | end. 532 | 533 | eh4(X) -> 534 | Y = try lists:sum(X) of 535 | V -> 536 | {V,4} 537 | catch 538 | error:S -> 539 | {s, S} 540 | end. 541 | eh5(X) -> 542 | Y = (catch lists:sum(X)), 543 | {blad, Y}. 544 | 545 | eh6(X) -> 546 | Y = (catch begin 547 | ok = (catch lists:sum(X)) 548 | end), 549 | {blad, Y}. 550 | 551 | eh7(X) -> 552 | try 553 | something:x(X) 554 | catch 555 | throw:Term -> Term; 556 | exit:Reason -> {'EXIT', Reason}; 557 | error:Reason -> {'EXIT', {Reason, [{stack,trace,1}]}} 558 | end. 559 | 560 | eh7c(X) -> 561 | try 562 | lists:sum(X) 563 | catch 564 | other:R -> {what, R} 565 | end. 566 | 567 | eh7b(X) -> 568 | try lists:sum(X) of 569 | V -> 570 | {V,4} 571 | catch 572 | error:S -> 573 | {s, S} 574 | after 575 | pss 576 | end. 577 | 578 | eh7b2(X,Y) -> 579 | try lists:sum(X) of 580 | V -> 581 | {V,4} 582 | catch 583 | error:S -> 584 | {s, S} 585 | after 586 | lists:sum(Y) 587 | end. 588 | 589 | eh8(X,Y) -> 590 | try lists:sum(X) of 591 | Z when Z > 10 -> 592 | {ok, Z} 593 | after 594 | lists:sum(Y) 595 | end. 596 | 597 | eh9(X,Y) -> 598 | try lists:sum(X) 599 | catch 600 | _:S -> 601 | {some_kind_of_error, S} 602 | after 603 | lists:sum(Y) 604 | end. 605 | 606 | eh10(X,Y) -> 607 | try 608 | lists:sum(X) 609 | after 610 | lists:sum(Y) 611 | end. 612 | 613 | 614 | length_native(L) -> 615 | length(L). 616 | 617 | length_manual(L) -> 618 | length_manual(L, 0). 619 | 620 | length_manual([_|T], S) -> 621 | length_manual(T, S+1); 622 | length_manual([], S) -> 623 | S. 624 | -------------------------------------------------------------------------------- /erl_src/erljs_compiler.erl: -------------------------------------------------------------------------------- 1 | -module(erljs_compiler). 2 | -author('baryluk@smp.if.uj.edu.pl'). 3 | 4 | % Copyright 2009-2011, Witold Baryluk 5 | % erljs project 6 | 7 | -export([ 8 | cl/1, cl/2, % compile given list of module 9 | c/1, c/2 % compile one module 10 | ]). 11 | 12 | -define(HEAD, ["erljs, auto-generated at ",io_lib:format("~p",[erlang:localtime()]),", Witold Baryluk, 2010"]). 13 | 14 | -define(HEADER, ok = file:write(File, ?HEAD)). 15 | 16 | -define(CRLF, $\n). 17 | -define(TAB, $\t). 18 | 19 | 20 | -spec cl([atom() | string()]) -> 21 | [{'ok', atom(), nonempty_string(), [{'functions', number()} | {'funs',number()} | {'total_ops',number()}, ...]}]. 22 | 23 | cl(L) -> 24 | cl(L, []). 25 | 26 | -spec cl([atom() | string()], [atom() | {atom(), _} | {'d', atom(), _}]) -> 27 | [{'ok', atom(), nonempty_string(), [{'functions', number()} | {'funs',number()} | {'total_ops',number()}, ...]}]. 28 | 29 | cl(L, Opts) -> 30 | L2 = [ c(M, Opts) || M <- L ], 31 | 32 | io:format("// ~s~n", [lists:flatten(?HEAD)]), 33 | io:format("var all_modules = [~n"), 34 | [ io:format(" [\"~s\", module_~s],~n", [M, M]) || {ok, M, F, Stats} <- L2 ], 35 | io:format("];~n~n"), 36 | 37 | io:format("~n", [lists:flatten(?HEAD)]), 38 | [ io:format(" ~n", [F]) || {ok, M, F, Stats} <- L2 ], 39 | io:format(" ~n"), 40 | L2. 41 | 42 | -spec c(atom() | string()) -> 43 | {'ok', atom(), nonempty_string(), [{'functions', number()} | {'funs',number()} | {'total_ops',number()}, ...]}. 44 | 45 | c(Mod) -> 46 | c(Mod, []). 47 | 48 | -spec c(atom() | string(), [atom() | {atom(), _} | {'d', atom(), _}]) -> 49 | {'ok', atom(), nonempty_string(), [{'functions', number()} | {'funs',number()} | {'total_ops',number()}, ...]}. 50 | 51 | %% Encode module 52 | c(Mod, Opts) when is_list(Mod) -> 53 | case lists:suffix(".beam", Mod) of 54 | true -> c2(Mod, Opts); 55 | false -> c1(Mod, Opts) 56 | end; 57 | c(Mod, Opts) when is_atom(Mod) -> 58 | c1(Mod, Opts). 59 | 60 | 61 | %% Encode module 62 | c1(Mod, Opts) -> 63 | ModName0 = if 64 | is_atom(Mod) -> atom_to_list(Mod); 65 | is_list(Mod) -> Mod 66 | end, 67 | 68 | %case filename:extension(ModName0) of 69 | % ".rel" -> filename:rootname(ModName0) ++ ".beam"; 70 | % [] -> 71 | %end; 72 | 73 | ModName = case lists:reverse(ModName0) of 74 | "lre." ++ R -> lists:reverse(R, ".beam"); 75 | _ -> ModName0 76 | end, 77 | 78 | % filename:find_src(Beam) 79 | % filename:find_src(Beam, Rules) 80 | %3> filename:find_src(kernel). 81 | %{"/usr/lib/erlang/lib/kernel-2.14.5/src/kernel", 82 | % [{i,"/tmp/buildd/erlang-14.b.4-dfsg/lib/kernel/src/../include"}, 83 | % {outdir,"/tmp/buildd/erlang-14.b.4-dfsg/lib/kernel/src/../ebin"}]} 84 | 85 | 86 | % 'S' - will prdue File.S with assembler code. 87 | %Opts2 = Opts ++ [debug_info,report,inline,{inline_size,24},warn_obsolete_guard], 88 | Dirname = filename:dirname(ModName), 89 | Opts2 = Opts ++ [debug_info,report,warn_obsolete_guard] ++ [{outdir, Dirname}], 90 | io:format("Recompiling: ~p with options~n ~p~n", [Mod, Opts2]), 91 | % compile file to .beam for sure. it doesn't load it into VM. 92 | %{ok, ModuleName, Binary} = case compile:file(Mod, [binary | Opts2]) of 93 | {ok, _} = case compile:file(Mod, Opts2) of 94 | {ok, _} = A -> 95 | io:format("Compilation sucessfull: ~p~n", [A]), 96 | A; 97 | E -> 98 | io:format("Compilation error: ~p~n", [E]), 99 | throw (compilation_error) 100 | end, 101 | 102 | c2(Mod, ModName, Opts). 103 | 104 | c2(_Mod, ModName, Opts) -> 105 | c2(ModName, Opts). 106 | 107 | c2(ModName, Opts) -> 108 | Verbose = lists:member(verbose, Opts), 109 | Indent = lists:member(indent, Opts), 110 | 111 | io:format("Disasembling file ~p~n", [ModName]), 112 | % We can pass binary() directly to beam_disasm:file/1 ! 113 | {beam_file,Mod3,_Exports,_Versions,Options,Disasm} = case beam_disasm:file(ModName) of 114 | {error, _, {file_error, _ ,_}} = E2 -> 115 | io:format("Decompilation error: ~p~n", [E2]), 116 | throw (file_reading_error); 117 | A2 -> 118 | A2 119 | end, 120 | io:format("Options: ~p~n", [Options]), 121 | 122 | _Mod = Mod3, 123 | 124 | Mod4 = atom_to_list(Mod3), 125 | 126 | % this will fail, becuase Mod can be not be loaded into VM. 127 | % if 128 | % is_atom(Mod) -> 129 | % Info = erlang:get_module_info(Mod), 130 | % {attributes, Attributes} = lists:keyfind(attributes, 1, Info), 131 | % io:format("Attributes: ~p~n", [Attributes]); 132 | % true -> true 133 | % end, 134 | 135 | FileName = "erljs_code/"++Mod4++".beam.js", 136 | io:format("Code generation to ~p~n", [FileName]), 137 | {ok, File} = file:open(FileName, [write]), 138 | ok = file:write(File, ["// ", ?HEAD, ?CRLF]), 139 | ok = file:write(File, ["var module_"++Mod4++ " = [", ?CRLF]), 140 | {NumerOfFunction,NumberOfFunsAndLCFuns,NumberOfOps} = lists:foldl( 141 | fun(F, {Count,CountFuns,CountOps}) -> 142 | %F2 = cf(F), 143 | %F2 144 | %io:format("~s~n~n", [term:encode(F)]), 145 | %io:format("~s,~n~n", [json_simple:encode(F)]), 146 | Ops = length(element(5,F)), 147 | IsFun = case hd(atom_to_list(element(2,F))) of 148 | $- -> 1; 149 | _ -> 0 150 | end, 151 | if Verbose -> 152 | io:format("Function: ~s Ops: ~p~n", [atom_to_list(element(2,F)), Ops]); 153 | true -> ok 154 | end, 155 | ok = if 156 | Count > 0 -> file:write(File, [$,, ?CRLF]); 157 | true -> ok 158 | end, 159 | %io:format("Function: ~p~n", [F]), 160 | case F of 161 | {function,FunctionName,FunctionArity,FunctionEntryPoint,Instructions} when is_list(Instructions) -> 162 | ok = file:write(File, "[\"function\",\""++atom_to_list(FunctionName)++"\","++integer_to_list(FunctionArity) 163 | ++","++integer_to_list(FunctionEntryPoint)++",["++[?CRLF]), 164 | %ok = file:write(File, [?CRLF, ?TAB]), 165 | lists:foldl(fun (Inst, Number) -> 166 | InstFiltered = case Inst of 167 | % not needed 168 | {allocate,_,_} -> []; 169 | {allocate_zero,_,_} -> []; 170 | {allocate_heap,_,_,_} -> []; 171 | {allocate_heap_zero,_,_,_} -> []; 172 | {deallocate,_} -> []; 173 | {test_heap,_,_} -> []; 174 | 175 | % fix literals encoding 176 | {move, {literal, X}, RR} -> 177 | {m, {literal, lists:flatten(io_lib:write(X))}, RR}; 178 | {put, {literal, X}} -> 179 | {'P', {literal, lists:flatten(io_lib:write(X))}}; 180 | {test, T1, T2, [T3, {literal, X}]} -> 181 | {t, T1, T2, [T3, {literal, lists:flatten(io_lib:write(X))}]}; 182 | {put_list, T1, {literal, X}, T3} -> 183 | {p, T1, {literal, lists:flatten(io_lib:write(X))}, T3}; 184 | 185 | % shorter opcodes for common things: 186 | {call_only, T1, T2} -> 187 | {c, T1, T2}; 188 | {call, T1, T2} -> 189 | {'C', T1, T2}; 190 | {label, L} -> 191 | {l, L}; 192 | return -> 193 | r; 194 | 195 | {move, T1, T2} -> 196 | {m, T1, T2}; 197 | {test, T1, T2, T3} -> 198 | {t, T1, T2, T3}; 199 | {gc_bif, T1, T2, T3, T4, T5} -> 200 | {'G', T1, T2, T3, T4, T5}; 201 | 202 | {get_list, T1, T2, T3} -> 203 | {g, T1, T2, T3}; 204 | {put_list, T1, T2, T3} -> 205 | {p, T1, T2, T3}; 206 | 207 | {put, T1} -> 208 | {'P', T1}; 209 | 210 | send -> 211 | '!'; 212 | 213 | 214 | % warning letters used above are not the same as bellow!! 215 | 216 | _ -> 217 | Inst 218 | end, 219 | case InstFiltered of 220 | [] -> 221 | Number; 222 | _ -> 223 | TextEncoded = json_simple:encode(InstFiltered), 224 | ok = if 225 | Number > 1 -> 226 | file:write(File, [$,]), 227 | ok = if Indent -> file:write(File, [?CRLF]); true -> ok end; 228 | true -> ok 229 | end, 230 | ok = if Indent -> file:write(File, [?TAB]); true -> ok end, 231 | file:write(File, TextEncoded), 232 | Number+1 233 | end 234 | end, 1, Instructions), 235 | ok = file:write(File, "]]") 236 | end, 237 | %ok = file:write(File, json_simple:encode(F)), 238 | %file:write(File, io_lib:print(F,4,132,-1)), 239 | %ok=file:write(File, io_lib:write(F)), 240 | %ok=file:write(File, io_lib:write(lists:flatten(cf(F)))), 241 | {Count+1,CountFuns+IsFun,CountOps+Ops} 242 | end, 243 | {0,0,0}, 244 | Disasm), 245 | ok = file:write(File, [?CRLF, "];", ?CRLF, ?CRLF]), 246 | ok = file:close(File), 247 | %io:format("~10000P~n", [A, 1000]). 248 | %io:format("~p~n", [A]) 249 | io:format("~n"), 250 | Stats = [ 251 | {functions,NumerOfFunction}, 252 | {funs,NumberOfFunsAndLCFuns}, 253 | {total_ops,NumberOfOps} 254 | ], 255 | {ok, Mod3, FileName, Stats}. 256 | 257 | %% return r, call_ c_, atom a, integer i, label l, test t, move m, put_list P, get_list G, put_tuple T, put p, get_tuple_element g 258 | %% case_end } 259 | %% usunac: allocate*, deallocate*, test_heap 260 | 261 | %% Encode function 262 | cf({function, Name, Arity, _, Body} = _F) -> 263 | lists:reverse(cf(Body, [])). 264 | 265 | cf([], C) -> 266 | C; 267 | cf([I|T], C) -> 268 | cf(T, [cfi(I)] ++ C). 269 | 270 | %% Encode single argument 271 | encode_what({atom, X}) when is_atom(X) -> 272 | ["a",atom_to_list(X)]; 273 | encode_what({literal, X}) -> 274 | ["`",io_lib:write(X)]; 275 | encode_what({x, X}) when is_integer(X) -> 276 | ["x",integer_to_list(X)]; 277 | encode_what({y, X}) when is_integer(X) -> 278 | ["y",integer_to_list(X)]; 279 | encode_what({integer, X}) when is_integer(X) -> 280 | ["i",integer_to_list(X)]; 281 | encode_what({float, X}) when is_float(X) -> 282 | ["~",float_to_list(X)]; 283 | encode_what(nil) -> 284 | ".". 285 | 286 | %% Encode single instruction 287 | cfi({label,N}) when is_integer(N) -> 288 | ["l", N]; 289 | cfi({test,Kind,What1,What2}) -> 290 | ["?", Kind, What1, What2]; 291 | cfi({case_end,What}) -> 292 | ["}", What]; 293 | cfi({badmatch,What}) -> 294 | ["e", What]; 295 | cfi(if_end) -> 296 | [")"]; 297 | cfi({move,What,{Type,RegNo} = Dest}) when is_integer(RegNo) -> 298 | ["m", encode_what(What), Type, RegNo]; 299 | cfi({func_info,{atom,Module},{atom,Name},Arrity}) when is_atom(Module), is_atom(Name), is_integer(Arrity) -> 300 | ["f", atom_to_list(Module), atom_to_list(Name), Arrity]; 301 | cfi({put_list,What1,What0,Where}) -> 302 | ["L", encode_what(Where), encode_what(What1), encode_what(What0)]; 303 | cfi(return) -> 304 | ["R"]; 305 | cfi({put_tuple,Size,{x,RegNo}}) -> 306 | ["p", integer_to_list(Size), integer_to_list(RegNo)]; 307 | cfi({put,What}) -> 308 | ["P", encode_what(What)]; 309 | cfi({get_tuple_element,What1,Which,Where}) -> 310 | ["<", encode_what(What1),Which,encode_what(Where)]; 311 | cfi({set_tuple_element,What1,Where,Which}) -> % ? 312 | [">", encode_what(What1),encode_what(Where),Which]; 313 | cfi({call,_,{Mod,Func,Arrity}}) -> 314 | ["c", 2, atom_to_list(Mod), atom_to_list(Func), integer_to_list(Arrity)]; 315 | cfi({call_only,_,{Mod,Func,Arrity}}) -> 316 | ["t", 2, atom_to_list(Mod), atom_to_list(Func), integer_to_list(Arrity)]; 317 | cfi({call_last,_,{Mod,Func,Arrity}, _Something}) -> 318 | ["t", 2, atom_to_list(Mod), atom_to_list(Func), integer_to_list(Arrity)]; 319 | cfi({call_ext,_,{extfunc,Mod,Func,Arrity}}) -> 320 | ["C", 2, atom_to_list(Mod), atom_to_list(Func), integer_to_list(Arrity)]; 321 | cfi({call_ext_only,_,{extfunc,Mod,Func,Arrity}}) -> 322 | ["T", 2, atom_to_list(Mod), atom_to_list(Func), integer_to_list(Arrity)]; 323 | cfi({call_ext_last,_,{extfunc,Mod,Func,Arrity},_Something}) -> 324 | ["T", 2, atom_to_list(Mod), atom_to_list(Func), integer_to_list(Arrity)]; 325 | cfi({apply_last,N,B}) -> 326 | ["A"]; 327 | cfi({apply,N}) -> 328 | ["a"]; 329 | cfi({gc_bif,Op,{f,F},_,[What1, What2],{R,RegNo}}) -> % Op == '+' '*' _=2, but also 4? 330 | [atom_to_list(Op), R, RegNo, encode_what(What1), encode_what(What1)]; 331 | cfi({gc_bif,Op,{f,F},_,[What1],{x,RegNo}}) -> % Op == length, '-', _=1,2,...? 332 | [atom_to_list(Op), RegNo, encode_what(What1)]; 333 | cfi({bif, Op,{f,F},[What1,What2],{x,RegNo}}) when Op=:='=:='; Op=:='=='; Op=:='geaaaa'; Op=:='element'; Op=:='>'; Op=:='<'; Op=:='and'; Op=:='>=' -> 334 | [atom_to_list(Op), RegNo, encode_what(What1), encode_what(What2)]; 335 | cfi({bif, Op,{f,F},[What1],{x,RegNo}}) when Op=:='get'; Op=:='tuple_size'; Op=:='not'; Op=:='tl'; Op=:='hd' -> 336 | [atom_to_list(Op), RegNo, encode_what(What1)]; 337 | cfi({get_list,{X1,R1},{X2,R2},{X3,R3}}) -> 338 | ["g"]; 339 | cfi({select_val,{x,R1},{f,F},{list, L}}) -> 340 | ["S"]; 341 | cfi({select_tuple_arity,{x,R1},{f,F},{list, L}}) -> 342 | ["Y"]; 343 | cfi({make_fun2, {M,F,A},Id,Uniq,_Something}) -> 344 | ["make_fun",M,F,A]; 345 | cfi({call_fun, N}) -> 346 | ["*",N]; 347 | cfi({test_heap,_,_}) -> 348 | []; 349 | cfi({fconv,S,D}) -> 350 | []; 351 | cfi({fmove,S,D}) -> 352 | []; 353 | cfi(fclearerror) -> 354 | []; 355 | cfi({fcheckerror,F}) -> 356 | []; 357 | cfi({arithfbif,Op,F,Args,{fr,R}}) -> 358 | []; 359 | cfi({jump,F}) -> 360 | []; 361 | cfi({allocate,_RefNo,_How}) -> 362 | []; 363 | cfi({allocate_heap,_,_,_}) -> 364 | []; 365 | cfi({allocate_zero,_,_}) -> 366 | []; 367 | cfi({allocate_heap_zero,_,_,_}) -> 368 | []; 369 | cfi({deallocate,_RefNo}) -> 370 | []; 371 | cfi({init, What1}) -> 372 | []; 373 | cfi({'try',Register,FLabel}) -> % probably only {y,R} 374 | []; 375 | cfi({try_end,Register}) -> 376 | []; 377 | cfi({try_case,Register}) -> 378 | []; 379 | cfi({try_case_end,Register}) -> % this could be {x,R} 380 | []; 381 | cfi({raise,F,[What1,What2],{x,RegNo}}) -> 382 | []; 383 | cfi({trim, A,B}) -> 384 | ["trim",A,B]; 385 | cfi({loop_rec, F,R}) -> 386 | []; 387 | cfi(remove_message) -> 388 | []; 389 | cfi({loop_rec_end, F}) -> 390 | []; 391 | cfi({wait_timeout,F,What1}) -> 392 | []; 393 | cfi(timeout) -> 394 | []. 395 | -------------------------------------------------------------------------------- /STATUS: -------------------------------------------------------------------------------- 1 | erljs allows you to run Erlang code directly in the web browser 2 | 3 | erljs takes Erlang source (or already available BEAM bytecode) and recompiles it so it can be executed using JavaScript. 4 | In web browser JavaScript basically executes small Erlang virtual machine and tries to mimic 5 | all its behviour. Compiler performs also some optimalisations to make size and time overhead as small as possible. 6 | 7 | erljs isn't the fastest way to perform general computation, but for 8 | usage in modern interactive and dynamic web application with lots of 9 | communication with server and other browser it fits ideally, 10 | and can drastically reduce development and integration time, 11 | by exposing direct Erlang feature to solve many problems of today's complex modern Web Applications 12 | based on JavaScript. 13 | 14 | erljs is runtime system for Erlang: 15 | * All language features of Erlang are supported, this includes: 16 | * language constructs: 17 | * functions, 18 | * case, if, try, catch, 19 | * send, receive, after, 20 | * pattern matching in functions, cases, try, recive 21 | * binary pattern matching, 22 | * funs, 23 | * list and binary comprehension, 24 | * macros. 25 | * tail recursion, 26 | * all primitve types (atoms, integers, big integers, floats, characters, binaries, pids, ports) and 27 | * lists, 28 | * tuples, 29 | * records, 30 | * funs. 31 | * all guard BIFs and most of other BIFs. 32 | * You can run multiple Erlang processes without blocking other JavaScript on the page to process long-runing calculation or wait for other event 33 | * You can use standard message passing primitives to communicate with: 34 | * other processes in the same browser, 35 | * timers, 36 | * emulated file I/O. 37 | * You can use ETS (Erlag Term Storage). 38 | * You can use dynamic code reloading. 39 | * You can use both compiled modules as well as interpreted code. 40 | * Should work correctly in all modern web browsers supporting JavaScript 41 | * Tested on Firefox 3.5, Opera 10.50, Chrome 5.0 42 | * Support for running inside Rhino engine. 43 | * Supports also running LFE (Lips Flavored Erlang) and Efene programs. 44 | 45 | erljs is also Web Browser language for interactive applications: 46 | * Additionally you can use message passing for communication with: 47 | * processes on server (firewall included), 48 | * erljs processes in other browsers (some limitations in Rhino), 49 | * existing JSON/XML services. 50 | * You can also use message passing for: 51 | * event handling in DOM document, 52 | * AJAX to Erlang server, or any other webserver for resources, 53 | * emulated file I/O, 54 | * comunication native JavaScript code. 55 | * One can transparently call server functions: 56 | * They can be called explicitly or implicitly (if they are marked so) 57 | * Server-only functions or modules do not need exposing of their source code or bytecode to web browser 58 | * Serialization of arguments and return value is automatic 59 | * Simplifies code reuse beetween client and server (i.e. validation of input data) 60 | * Automatic handling of exceptions (optionally hide some information from stack trace or exception) by passing it back to client, or server 61 | * One can also transparently call client-side from server: 62 | * Again automatic 63 | * One can pass funs around for this without bigger problem 64 | * Comes with extensible API for writing Web Applications both for client and server: 65 | * HTML's DOM and CSS access, creation and modification, both on client and server and interaction beetwen both, 66 | * multiple ways to interact with existing JavaScript codes, libraries, APIs, 67 | * bundle of usefull binding for some popular APIs and libraries: 68 | * native API: 69 | * local Storage 70 | * HTML5 video and audio 71 | * HTML5 canvas with 2d context 72 | * WebSockets 73 | * EventSource 74 | * XMLHttpRequest 75 | * CORS 76 | * libraries: 77 | * jQuery, YUI, Raphael 78 | * own library of usefull effects, layouts, etc, as in popular JavaScript frameworks but written in pure Erlang and Erlangish way 79 | * Dynamic or static loading of resources (including code to run or reload). 80 | * Supports 81 | * And other crazy stuff. 82 | 83 | Supported Erlang apps: 84 | * Most of OTP features are supported. 85 | * All usefull modules can be used sensibly without modification in their source code, 86 | or have slightly changed or optimimized JavaScript version provided. 87 | * erts: 88 | * erlang: most BIFs implemented nativly in JavaScript, other without changes. 89 | * other avilable but not very usefull for anything in the web browser. 90 | * stdlib: 91 | * math, base64, calendar, random, 92 | * lists, proplists, string, unicode, 93 | * dict, gb_trees, gb_sets, sets, orddict, ordsets, queue, digraph, sofs, 94 | * gen_server, gen_fsm, gen_event, error_logger, 95 | * regexp, re, 96 | * ets, 97 | * qlc, 98 | * io_lib, 99 | * epp, erl_scan, erl_parse, erl_eval, erl_lint, erl_compile, escript, 100 | * pg, shell, console, 101 | * timer, sys. 102 | * compiler, dialyzer, typer, parsetools, syntax_tools, edoc, docbuilder, erl_docgen, 103 | * xmerl 104 | * mnesia 105 | * sasl, tools, 106 | * eunit, common_test, test_server 107 | * and others (not so usefull): ic, 108 | * comming soon: debugger, tools (cover, cprof, eprof, fprof) 109 | * considering: inviso, orber, tv, et, pman, percept, appmon, etc. (problem with GUI porting) 110 | * Any module or function can be marked as being server side, which will mean that it will be automatically called on server on call. 111 | 112 | For what it can be usefull? 113 | * Highly interactive, dynamic web applications with lots of concurancy and communication, for example: 114 | * instant messanging, email systems, 115 | * games, 116 | * colaboration tools, 117 | * distributed computing and databases, 118 | * realtime searching, editing, etc. 119 | * Teaching Erlang. 120 | * One can run Erlang code directly in the browser, quickly and safly. 121 | * Without downloding, installing or executing anything. 122 | * One can easly run multiple browsers and create cluster in class room or on the single desktop. 123 | * In environments where one cannot run Erlang virtual machine but can run JavaScript 124 | * Implemeneting novel Erlang extensions using simple and managed JavaScript. 125 | 126 | Why this project started? Is it better than just JavaScript? 127 | * It isn't nacassarly better, but we think that some problems with JavaScript motivates this project: 128 | * Success of GWT 129 | * Simplicity of concurancy, event handling, error control and distributed communication in Erlang 130 | * And complication of the same in JavaScript or Java 131 | * We created this project becuase we think it is big chalange and cool idea. 132 | 133 | What are the problems in JavaScript then? 134 | * Problems with blocking JavaScript code on long runing computation 135 | * JavaScript is generally single threaded 136 | * Sometimes hacked using timers to break and continue computation after small time 137 | * process scheduler for poor pepole 138 | * explosion of handlers, callbacks, timers, etc. 139 | * We should not block inside JavaScript for any reason: 140 | * long intensive computation, 141 | * long animation, 142 | * waiting for user interaction (alert, confirm, input, clicking element), 143 | * waiting for server for answer for our request. 144 | * Handlers: 145 | * Lots of event chaotic handlers for interacting with user interface 146 | * Lots ot other event handlers for interacting with server 147 | * They just tries to hide fact that JavaScript in Web Browser is single threaded 148 | * Writing explicitly non-blocking, asynchronous code with handlers is hard and error-prone. 149 | * Problematic error handling: 150 | * developers mostly ignore writing proper error handlers or do not test them. 151 | 152 | How we can solve this? 153 | * Erlang naturally fits into event handling paradigm. 154 | * Use message passing for everything, 155 | * DOM events, 156 | * AJAX and Comet-type communication, 157 | * error handling, 158 | * RPC. 159 | * Allow running any set of processes and preempt them, if needed. 160 | * Perform real process scheduling 161 | * Long computation or looping in control loop of any document elements, will not block whole web browser. 162 | * Network communication will not block whole web browser. 163 | * AJAX and Comet-type or RPC communication will not block whole web browser. 164 | * Still one can use simple code which semantically block in this scenario and performs only on simple thing. 165 | 166 | But what about X? 167 | * Isn't Web Workers (Worker) allow me to run multiple threads? 168 | * Yes, but writing multithreaded applications is much harder using them 169 | * Web Workers are supported only by few browsers currently, and even if supported used only for loading resources 170 | and executing very simple code in parallel without complex interaction, 171 | * Still event or AJAX processing isn't natural as in Erlang 172 | * Web Workers can be used be erljs to use multiple cores effectively and still allows for safe communication. 173 | * How about WorkerPool API? 174 | * Yes you can use message passing interface with it, but doesn't remove problem with handlers for them, errors, other events or AJAX. 175 | * This API is available only in Gears. 176 | * Then what about Web Sockets, they allow me for communication with server? 177 | * This again adds handlers which are hard to use 178 | * They can also be used by erljs to improve performance of some message passing 179 | * And about Server-Sent Events (EventSource)? 180 | * Again the same 181 | * They can also be used by erljs to improve performance of some message passing 182 | * How Thread.js, Er.js, towel.js, Arrowlets, threading using iframes, timing module in dojo? 183 | * This are just hacks which tries to remove some problems with JavaScript by mimicing how Erlang or other functional languages works. 184 | * Unfortunetly there are still many limitations and can't be used for usefull applications. 185 | * How about JavaScript 1.7 generators? 186 | * Well they are not for emulating multiple processes or message passing, and supported only by one web browser. 187 | * Is is fast? 188 | * Not very fast, but not slow. 189 | * If you need something fast in you web application write this fragment in pure JavaScript and use it from erljs. 190 | * For general usage with mostly controling GUI, communication and small ammount of computation it is fast and more than enaugh. 191 | * Some critical modules and functions are hand optimized, like list, string processing, regular expressions. 192 | * We are still working on some optimalisations, much clever translation, but we now basically interpret opcode by opcode. 193 | * Is script files big? 194 | * Well we don't think they are very big, we compact them pretty well on generation, core functions are moderately big. 195 | * All scripts can be cached and reused beetwen many pages. 196 | * You can seletivly compile and publish only modules or functions which are needed and nothing more. This is automated, but can be adjusted manually. 197 | * Can I use it with jQuery, dojo, mootools, prototype, YUI, UIZE, MochiKit, ...? 198 | * Yes. 199 | * We are using prototype.js for few things (part of AJAX and JSON processing), but this can be easly changed, and can live side-by-sidey other frameworks. 200 | * We also provide some Erlangish way to perform similar things like selectors, event handling, effects, validation, etc. 201 | * Can I execute JavaScript code from erljs running in web browser? 202 | * Generally yes. There are few mechanisms to choose for running native JavaScript code from Erlang code.. 203 | We also provide bindings for few popular libraries to simplify this and show how this can be performed. 204 | * Can I run JavaScript code in Erlang? 205 | * Not generally, this project isn't about this problem. Look at erlyjs project. 206 | * Can I run Erlang library/application/code in Web Browser then? 207 | * Depends. If library is mostly functional one, there should be no problem. If it interact havly with files, code loading, networking, graphical system, 208 | then there will be problems, but sometimes this can be easly fixed. 209 | 210 | Limitations: 211 | * most of kernel functionality is not possible: 212 | * direct networking, 213 | * direct file IO and disc access, 214 | * distribution protocol, 215 | * executing external programs. 216 | * All this can be optionally be emulated in some ways (probably in not so safe way): 217 | * file IO for example can mean using file from server or usage of HTML5 local storage or File API, 218 | * executing external program could mean running on server or using some kind of plugin, 219 | * networking could be emulated with simplistic TCP/UDP stack and could be usefull for some legacy applications talking with this protocols. 220 | * modules which uses any C extensions, port programs, or NFI are not supported if not emulated. 221 | * some modules uses native JavaScript functionalities: 222 | * re: uses JavaScript regular expressions which can be different both in capabilities, syntax and performance) 223 | * crypto: emulated using JavaScript code if needed 224 | * xmerl: emulated using JavaScript 225 | * tracing mechanisms isn't implemented yet, this prevents using tracing, profiling and debuging features. 226 | * because of this limitations (or because using them directly in web browser is very improbably for any reason) it is not possible to use fully system specific applications or modules: 227 | * stdlib module dets cann't be used, so also mnesia disc storage isn't possible 228 | * debug, tracing and profiling tools: 229 | * et (WIP) 230 | * debugger (WIP) 231 | * invisio (WIP) 232 | * tv (WIP) 233 | * orber (WIP) 234 | * observer (WIP) 235 | * appmon (WIP) 236 | * pman (WIP) 237 | * They generally doesn't work becuase tracing function isn't implemented, or becuase of GUI issues. After writing trace support and HTML port they should work. 238 | * hipe (not usefull, not implementable) 239 | * inets (emulation of httpc could be usefull, depends of networking) 240 | * webtool (depends on inets, and networking) 241 | * asn1 (not needed, C code) 242 | * os_mon (dummy module can be created but this isn't usefull) 243 | * snmp, otp_mibs (not needed, depends on asn1) 244 | * reltool (not needed) 245 | * jinterface (not needed, not implementable) 246 | * odbc (not needed, not implementable) 247 | * gs (not needed, not implementable) 248 | * wx (generally not possible, not needed and not implementable, still it could be interesting to create 249 | * direct usage of compiler, dialyzer, typer, edoc, ic, etc. (mostly releated to file read/write or running as standalone application) 250 | * megaco (not tested, not needed) 251 | * ssl, ssh (not needed, too hard to implement) 252 | * erl_interface (not implementeable, not needed, erljs-JavaScript interface avaiable directly in erljs) 253 | * most of this modules (marked 'not needed') are not usefull in web browser so it is not a problem. 254 | * many (crazy) operations are slow (like compiling erlang program to BEAM, decompiling, recompiling to JavaScript, loading and executing). 255 | 256 | Real limitations: 257 | * sending funs or some particular datastructures in one way or another can have slight limitations. 258 | * soft-real time behaviour isn't guaranted: 259 | * All processes share own heap, 260 | * single garbage collector, 261 | * some code can block other processes, 262 | * especially complicated regular expressions, 263 | * some list processing (but this is fast or will not block), 264 | * JavaScript code executed from erljs 265 | * time granulity bellow 1ms isn't guranted. 266 | * Messages are passed by reference (well this isn't limitation actually). 267 | * bigintegers introduces big overhead or will not work at all! 268 | * BTW: Mozilla is working on introducing BigInt to next version of JavaScript 269 | * Sometimes floating points number and integers can't be distnguished (they are the same type in JavaScript) 270 | * Floating point numbers can have slightly different exception handling. 271 | * Passing exception handling beetween JS code and Erlang code (in both direction) is problematic. 272 | * Counting reductions is not the same as original Erlang. In erljs it is based on opcodes executed. 273 | * Scheduling is based not only on reduction counts, but also on time and "native reduction" count (i.e. number of elementer loop passes in list processing functions). 274 | -------------------------------------------------------------------------------- /erljs_html/erljs.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | erljs testing 8 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 |
78 |

erljs - Erlang in JavaScript

79 |
80 |
81 |
Examples () 82 | - try by clicking any of sample expressions or function calls:
83 | (There are restrictions what can be evaluted in input box. Only functions calls 84 | with literal arguments can be used. BIFs are not directly callable.) 85 |
86 |
87 |
    88 |
  • lists:reverse([1, 2, 3, 4])
  • 89 |
  • lists:reverse([1, 2, 3, 4], [5, 6, 7, 8])
  • 90 |
  • lists:nthtail(0, [1 | []]) % lists:nthtail(0, L) just returns L
  • 91 |
  • lists:nthtail(0, [1 | [2 | []]])
  • 92 |
  • lists:nthtail(1, [1 | [2 | []]])
  • 93 |
  • lists:nthtail(0, [1, 2, 3 | [4, 5]])
  • 94 |
  • lists:nthtail(1, [1, 2, 3 | [4, 5]])
  • 95 |
  • lists:nthtail(2, [1, 2, 3 | [4, 5]])
  • 96 |
  • lists:nthtail(3, [1, 2, 3 | [4, 5]])
  • 97 |
  • lists:nthtail(3, [1, 2, 3, 4, 5])
  • 98 |
  • lists:last([a, b, c, d, e])
  • 99 |
  • lists:nth(3, [a, b, c, d, e])
  • 100 |
  • lists:seq(1, 20)
  • 101 |
  • lists:seq(1, 20, 2)
  • 102 |
  • lists:seq(-1, -20, -2)
  • 103 |
  • lists:sum([1, 2, 3])
  • 104 |
  • lists:sum([])
  • 105 |
  • lists:member(c, [a, b, c, d])
  • 106 |
  • lists:member(e, [a, b, c, d])
  • 107 |
  • lists:delete(c, [a, b, c, d])
  • 108 |
  • lists:delete(z, [a, b, c, d])
  • 109 |
  • lists:append("abc", "def")
  • 110 |
  • lists:append([[1, 2, 3], [a, b], [4, 5, 6]])
  • 111 |
  • lists:max([a, c, v, e, d])
  • 112 |
  • lists:merge([a,d,g,o], [b,c,e,z])
  • 113 |
  • lists:merge([[a,d,g,o], [b,c,e,z], [c,b,d,y]])
  • 114 |
  • lists:sort([7,2,9,3,6,4,1,8])
  • 115 |
  • lists:sort([a,c,v,e,z,c,e,y,u,c,a,q,y,o,v,a,u,h,d,s,e,d,z,c,b,n,k,i])
  • 116 |
  • lists:split(3, "erljs")
  • 117 |
  • lists:split(4, [a,b,c,d,e,f,g,h,i,j,k,l])
  • 118 |
  • lists:prefix([a,b,c], [a,b,c,d])
  • 119 |
  • lists:prefix([], [a,b,c,d])
  • 120 |
  • lists:prefix([x,y,z], [a,b,c,d])
  • 121 |
  • lists:prefix([a,b,d], [a,b,c,d])
  • 122 |
  • lists:prefix("new", "new york")
  • 123 |
  • lists:prefix("old", "new york")
  • 124 |
  • lists:suffix([c,d], [a,b,c,d])
  • 125 |
  • lists:suffix([a,b], [a,b,c,d])
  • 126 |
  • lists:suffix(".html", "index.html")
  • 127 |
  • lists:suffix(".jpeg", "index.html")
  • 128 |
  • lists:concat([doc, '/', file, '.', 3])
  • 129 |
  • lists:duplicate(5, xx)
  • 130 |
  • lists:flatten([a,b,[c,[d,e],[f,g,[h]]],[i]])
  • 131 |
  • lists:flatlength([a,b,[c,[d,e],[f,g,[h]]],[i]])
  • 132 |
  • erlang:length([1, 2, 3, 4]) % doesn't work here, because it is BIF
  • 133 |
  • erlang:length([a, b, c, d]) % doesn't work here, because it is BIF, try next ones
  • 134 |
  • example:length_native([a,b,c,d])
  • 135 |
  • example:length_manual([a,b,c,d])
  • 136 |
  • string:len("ala ma kota")
  • 137 |
  • string:tokens("ala ma kota", " ")
  • 138 |
  • string:tokens("abc defxxghix jkl", "x ").
  • 139 |
  • string:join(["one", "two", "three"], ", ").
  • 140 |
  • string:words(" Hello old boy!").
  • 141 |
  • string:words(" Hello old boy!", $o).
  • 142 |
  • string:sub_word(" Hello old boy !",3,$o).
  • 143 |
  • string:strip("...Hello.....", both, $.).
  • 144 |
  • string:left("Hello",10,$.).
  • 145 |
  • string:right("Hello", 10, $.).
  • 146 |
  • string:centre("Hello", 20, $.).
  • 147 |
  • string:substr("Hello World", 4, 5).
  • 148 |
  • string:sub_string("Hello World", 4, 8).
  • 149 | 158 |
  • string:str(" Hello Hello World World ", "Hello World").
  • 159 |
  • string:span("\t abcdef", " \t").
  • 160 |
  • string:cspan("\t abcdef", " \t").
  • 161 |
  • lists:keyfind(witek, 1, [{jacek, t}, {witek, b}, {marcin, m}, {ania, ch}])
  • 162 |
  • lists:keysearch(witek, 1, [{jacek, t}, {witek, b}, {marcin, m}, {ania, ch}])
  • 163 |
  • lists:keysearch(krzysiek, 1, [{jacek, t}, {witek, b}, {marcin, m}, {ania, ch}])
  • 164 |
  • lists:keymember(witek, 1, [{jacek, t}, {witek, b}, {marcin, m}, {ania, ch}])
  • 165 |
  • lists:keymember(krzysiek, 1, [{jacek, t}, {witek, b}, {marcin, m}, {ania, ch}])
  • 166 |
  • lists:keydelete(jacek, 1, [{jacek, t}, {witek, b}, {marcin, m}, {ania, ch}])
  • 167 |
  • lists:keysort(2, [{jacek, t}, {witek, b}, {marcin, m}, {ania, ch}])
  • 168 |
  • lists:seq(10, 6, 4)
  • 169 |
  • lists:seq(10, 6, -4)
  • 170 |
  • lists:seq(10, 6, 3) % correctly throws exception
  • 171 |
  • lists:seq(10, 6, -3)
  • 172 |
  • lists:seq(100, 6, -3)
  • 173 |
  • lists:seq(1, 0, 1)
  • 174 |
  • lists:seq(1, 1, 0)
  • 175 |
  • lists:sublist([a,b,c,d,e,f,g,h], 4)
  • 176 |
  • lists:sublist([a,b,c,d,e,f,g,h], 4, 3)
  • 177 |
  • lists:sublist([1,2,3,4], 2, 2)
  • 178 |
  • lists:sublist([1,2,3,4], 2, 5)
  • 179 |
  • lists:sublist([1,2,3,4], 5, 2)
  • 180 |
  • lists:subtract("123212", "212") % FIXME
  • 181 |
  • lists:zip([a,b,c], [1,2,3])
  • 182 |
  • lists:unzip([{a,1}, {b,2}, {c,3}])
  • 183 | 184 |
  • proplists:get_value(ola, [{ala,1},{ola,3},{kasia,4}])
  • 185 |
  • proplists:get_value(basia, [{ala,1},{ola,3},{kasia,4}])
  • 186 |
  • proplists:get_value(basia, [{ala,1},{ola,3},{kasia,4}], -1)
  • 187 |
  • proplists:lookup(ola, [{ala,1},{ola,3},{kasia,4}])
  • 188 |
  • proplists:lookup(basia, [{ala,1},{ola,3},{kasia,4}])
  • 189 |
  • proplists:delete(ola, [{ala,1},{ola,3},{kasia,4}])
  • 190 |
  • proplists:delete(basia, [{ala,1},{ola,3},{kasia,4}])
  • 191 |
  • proplists:append_values(a, [{a, [1,2]}, {b, 0}, {a, 3}, {c, -1}, {a, [4]}])
  • 192 |
  • proplists:expand([{foo, [bar, baz]}], [fie, foo, fum])
  • 193 |
  • proplists:expand([{{foo, true}, [bar, baz]}], [fie, foo, fum])
  • 194 |
  • proplists:expand([{{foo, false}, [bar, baz]}], [fie, {foo, false}, fum])
  • 195 |
  • proplists:expand([{{foo, true}, [bar, baz]}], [{foo, false}, fie, foo, fum])
  • 196 |
  • proplists:split([{c, 2}, {e, 1}, a, {c, 3, 4}, d, {b, 5}, b], [a, b, c])
  • 197 | 198 |
  • erl_scan:string("{d,f,g,[4,2,dd3]}").
  • 199 |
  • erl_scan:string("{d,f,g,[4,2,dd3]}.").
  • 200 |
  • erl_parse:parse_term([{'{',1},{atom,1,a},{',',1},{atom,1,b},{',',1},{atom,1,c},{'}',1},{dot,1}])
  • 201 |
  • erl_scan:string("1+3").
  • 202 |
  • erl_scan:string("1+3.").
  • 203 |
  • erl_scan:string("if 5 < 6 -> m; true -> n end").
  • 204 |
  • erl_parse:parse_exprs([{'if',1},{integer,1,5},{'<',1},{integer,1,6},{'->',1},{atom,1,m},{';',1},{atom,1,true},{'->',1},{atom,1,n},{'end',1},{dot,1}]).
  • 205 |
  • erl_scan:string("fun() -> ok end").
  • 206 |
  • erl_scan:string("fun() -> ok end.").
  • 207 |
  • erl_scan:string("fun(X,Y) -> case lists:max(X) of Y -> {big,Y}; Z -> {smaller,Z} end end").
  • 208 |
  • erl_scan:string("s(A,B) -> A+B.").
  • 209 |
  • erl_parse:parse_form([{atom,1,s},{'(',1},{var,1,'A'},{',',1},{var,1,'B'},{')',1},{'->',1},{var,1,'A'},{'+',1},{var,1,'B'},{dot,1}])
  • 210 |
  • regexp:parse("joe").
  • 211 |
  • regexp:parse("(ala|adam|ewa|kasia|ewelina)").
  • 212 |
  • regexp:parse("(jo)?anna").
  • 213 |
  • regexp:parse("[a-z][0-9a-zA-Z_]*").
  • 214 |
  • regexp:parse("[A-Z_][0-9a-zA-Z_]*").
  • 215 |
  • regexp:parse("^([a-z][0-9a-zA-Z_]*|[A-Z_][0-9a-zA-Z_]*)").
  • 216 |
  • regexp:parse("(\\+|-)?[0-9]+\\.[0-9]+((E|e)(\\+|-)?[0-9]+)?").
  • 217 |
218 |
219 | 263 |
264 | 265 |
266 |
267 |
268 | 269 |
270 | 271 | 272 | 273 |
274 |
275 |
276 | 277 |
278 |
279 |
280 |
281 |
282 | 283 | 284 |
285 | 286 | 287 | 311 | 312 | 313 | 314 |
315 | Tracing and debuging: 316 |
317 |
318 | 319 |
320 | Concurent calculations and event handling (button clicks and aproximate calculation of π constant)
321 |
322 |
323 | 324 | 325 |
326 |
327 |
328 |
329 | 330 | 331 |
332 |
333 | 334 |
335 |
336 | 337 |
338 | 339 | 340 |
341 | Add to state: 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 |
354 |
355 |
356 |

Valid XHTML 1.0 Strict

357 |
358 | Fork me on GitHub 359 |
360 |
361 | 362 | -------------------------------------------------------------------------------- /erl_src/erljs_html.erl: -------------------------------------------------------------------------------- 1 | -module(erljs_html). 2 | -author('baryluk@smp.if.uj.edu.pl'). 3 | 4 | % Copyright 2009-2011, Witold Baryluk 5 | % erljs project 6 | 7 | % See also: 8 | % 9 | % Yaws - http://yaws.hyber.org/dynamic.yaws 10 | % IL2JS 11 | % XHTML.M from oscigen - http://ocsigen.org/docu/1.3.0/XHTML.M.html 12 | % 13 | 14 | 15 | standards() -> 16 | [ 17 | 'html4.01_transitional', 18 | 'html4.01_strict', 19 | 'xhtml1.0', 20 | 'xhtml1.1', 21 | html5 22 | ]. 23 | 24 | scheme_options() -> 25 | [ 26 | allow_custom_a_href, 27 | allow_raw_dirty, 28 | disable_validation, 29 | {size_limit, 100000} 30 | ]. 31 | 32 | example() -> 33 | {html, [ 34 | {head, {title, "kuku"}}, 35 | {body, [ 36 | {hl, "Hello world"} 37 | ]} 38 | ]}. 39 | 40 | 41 | % Syntax and examples: 42 | % ElementName 43 | % 'hr', 'br' 44 | % {ElementName, Child} when is_string(Child); is_binary(Child); is_tuple(Child) 45 | % 46 | % {ElementName, Childs} when is_list(Childs) 47 | % {ElementName, Atributes, Child} 48 | % {ElementName, Atributes, Childs} 49 | 50 | % ElementName can be: 51 | % html, head, meta, base, title, body, manifest (+HTML5) 52 | % bdo 53 | % section, header, menu, nav (all +HTML5) 54 | % h1, h2, h3, h4, h5, h6 55 | % p, div, span, 56 | % pre, pcdata 57 | % ruby, rb, rp, rt (all +HTML5) 58 | % abbr, acronym (-HTML5), address, q, blockquote, del, ins, em, strong, mark (+HTML5) 59 | % b, i 60 | % table, caption, colgroup, col, thead, tfoot, tbody, tr, th, td 61 | % ul, ol, li 62 | % dl, dt, dd 63 | % a, area, img, map 64 | % figure, figcaption (all +HTML5) 65 | % form, label, legend, input, textarea, fieldset, datalist (+HTML5) 66 | % noscript, script 67 | % video, audio, canvas, meter, kbd (all +HTML5) 68 | % var 69 | % 70 | % html_raw - use Childs direclty as content. 71 | % Still content will be tested to be valid xml chunk in this context. 72 | % Do not use things like [{raw,"
"},{raw, Bin},"{raw,
"}], 73 | % better use like {raw,["
",Bin,"
"]}. 74 | % Child(s) of raw is an iolist, but can als contain ehtml, again 75 | % using {ehtml, ...} 76 | % It will not be encoded in any way. 77 | % 78 | % {stream, Acc0, fun(Acc) -> {E, Acc} end}. 79 | % Similary, but fun will be evaluated just on sending data to the browser, 80 | % thus keeping memory requirment smaller. 81 | % Good for tables and lists of any kinds. 82 | % Remember that this is probably only usefull if backend data 83 | % is also retrivied in similar fashion (like cursor in qlc, 84 | % or iterators in mnesia, dets, or cursor in SQL). 85 | % 86 | % ehtml - is silently ignored, but its child must be valid ehtml, 87 | % and is valideted. If there are attributes, they are inspected, 88 | % for example to change encoding, or perform scheme translations. 89 | % 90 | % ehtml, [valid] - if it is ehtml chunk, but it is already valid. 91 | % html_raw, [valid] - similary but for validated html_raw chunks. 92 | % 93 | % raw, [dirty] - if it is already compiled and verified. 94 | % Or you are sure it is valid for other reason. 95 | % Or want to cheat, and send invalid xml. 96 | % Or you tested that performance of validator is a bottlneck. 97 | % 98 | % string, int, float - will type check content, and convert data 99 | % to the proper form. String can be iolist, 100 | % HTML safe encoding will be performed. 101 | % (coding using entities and few others characters 102 | % which can dangerous normally) 103 | % 104 | % {include, File} - will include file with ehtml term, it can 105 | % contain many terms, each terminated with dot. 106 | % {include, [valid], File} - marks that content of File have been 107 | % already in some way valideted (i.e. in cache), or for performance reasons. 108 | % {include, [raw], File} - will include file just like raw, must be valid HTML/XML part. 109 | % {include, [raw,dirty], File} - will include file just 110 | % like raw, but will not be validated. 111 | % {include, [raw, {rewrite, "%", [{"A", "Godzilla"}]}], File} - also 112 | % available as {ssi, "filename.txt", "%", [{"a", "Godzilla"}]} - 113 | % includes file, but all occurence of "%a%" are changed into "Godzilla" 114 | % variable names should be have first letter upper case (just like Erlang variables) 115 | % and MUST not contain "%", or whitespaces. It should only use letters, numbers, underline. 116 | % Optionally it can contain: minus, plus, star, dot, double collon, collon, braces, 117 | % curly-braces, squre brackets, angle brackets, dollar, pipe, slash, semicolon, 118 | % exclamation mark, at-sign, hash-mark. 119 | % {include, [{rewrite, [{"A", "Godzilla"}]}], File} - works similary to {include, File} 120 | % but allows using variables. It is forbiden to use Erlang expressions other than term construction, 121 | % in included file. 122 | % {include, [dtl], {template_module, something, File}} - include File as DTL (Django template). 123 | % One can add 'dirty' option, if want to assume validity. 124 | % If one will use atom to reference module, then File will be compiled 125 | % once into template_module:something/1 function. If no such module exists 126 | % it will be created from given template and compiled properly on first usage. 127 | % Dynamic recompilation of new files (for example after change, but without restarting server and removing beam files), 128 | % can be done based on atime, or manually (globally or per-file or per-module) 129 | % using erljs_html:dtl_options([Opts]) where Opts is 130 | % clear_all - will clear all files and recompile them, on next usaxe. 131 | % mtime - will set automatic recompilation based on modification time of file 132 | % every - will recompile template on every access (can be usefull when developing application, 133 | % or when there are very big number of templates, as they will normally be loaded 134 | % into VM as modules, thus consuming RAM). 135 | % recompile_known - will recompile all loaded currently templates. 136 | % 137 | % DTL templates will use current request dictionaries as variables. 138 | % You can also provide own values using, {rewrite,[...]} just like in ehtml templates, 139 | % but you keys need to be valid Python identifiers (still they also should begin 140 | % from upper case, to/from make porting to ehtml templates and javascript easier). 141 | % 142 | % DTL template can be compiled to raw text, or to ehtml templates, thus making, 143 | % validation and dynamic insertion into DOM easier (without innerHTML). 144 | % 145 | % For compiled ehtml templates it is possible, to update live DOM tree, in such manner, 146 | % that if on new rendering in the same place some part of HTML will no change 147 | % they will not be removed from DOM tree, if some was removed/added (due to the {% if %}), 148 | % they will be removed/added. In case of loops, the old childrens will be removed, and new 149 | % childrens will be added (this can be changed by {loops,append}, which will append new childs 150 | % after existing ones if they exist). This only applies to the outer-most loops. 151 | % 152 | % For more on DTL go to: 153 | % http://www.djangoproject.com/documentation/templates/ 154 | % http://archive.dojotoolkit.org/nightly/dojotoolkit/dojox/dtl/ 155 | % 156 | % In case of files, file will not be readed to the memory, but will be streamed to the client when nacassary. 157 | % 158 | % In case of error (no such regular file, bad permissions) response will immiedietly stop, 159 | % and connection will be terminated unclearly. Be sure no error will occur. 160 | % 161 | % When rewriting values, one can use string, binary-string, or {ehtml, ...} struct (it will be 162 | % serialized to html binary-string). 163 | % 164 | % Attributes needs to be valid attributes for corresponsing 165 | % tag elements. Their values also need to be correct. 166 | % 167 | % One can also create own tags: 168 | % 169 | % new_element_type(page, fun (Attributes, Childs) when is_list(Childs) -> 170 | % {ehtml, {html, { 171 | % header, 172 | % {body, Childs} 173 | % }}}. 174 | % end, [parse_childs]). 175 | % 176 | % new_element_type(header, fun (Attributes, Childs) when is_list(Childs) -> 177 | % {raw, "Hello"} 178 | % end, [parse_childs, cache]). 179 | % 180 | % new_element_type(my_table, fun (Attributes, [{stream, SubAcc0, Fun}]) -> 181 | % {ehtml, {table, 182 | % {stream, {SubAcc0, 1}, fun({SubAcc, N) -> 183 | % Style = if 184 | % N rem 2 == 1 -> [{class, 'odd'}]; 185 | % true -> [{class, 'even'}] 186 | % end, 187 | % {SubE, NewSubAcc} = Fun(SubAcc), 188 | % E = {tr, [Style], SubE}, 189 | % NewAcc = {NewSubAcc, N+1}, 190 | % {E, NewAcc} 191 | % end} 192 | % }} 193 | % end, [parse_childs, cache]). 194 | 195 | % 196 | % If there was no Attributes or Childs, they will be an empty list. 197 | % In all cases it will be an list (also in case only one element 198 | % was given originally, or raw data, pcdata, or string, or binary). 199 | % 200 | % parse_childs - means that ehtml engine will first parse 201 | % all childrens before giving them to the fun. 202 | % no_parse_childs - means that fun must parse them alone. 203 | % 204 | % cache - means that result of fun will be cached (as far as Attributes and Childs) match 205 | % generation and validation will be performed only once. 206 | % 207 | % 208 | % Fun should return ehtml (which could possibly trigger again some 209 | % funs to be called) or raw data. 210 | 211 | 212 | % One can also use parse transform (similar to qlc:q([...]) ...) in the form: 213 | 214 | 215 | % erljs_html:pf({ehtml, {html, {body, 216 | % [header, 217 | % ... 218 | % ] 219 | % }}}) 220 | % 221 | % such ehtml, will be parsed and compiled in advance to most compressed 222 | % form with minimal space, network and cpu usage (for example 223 | % glueing together consecutive opening tags into single binary, 224 | % it will be flat narrow list, not deep and wide list). 225 | % in case it is literal constant term, it is simple 226 | % in case it refferes to some variables or functions or expressions, 227 | % it will try to compile as much as possible from it, and make original 228 | % call a call to the specialized fun). 229 | % 230 | % Care must be taken when generating huge amount data, as 231 | % all data is keeped in memory. For huge amount of data, 232 | % streaming techniques can be used. 233 | % 234 | % 235 | % Hyperlinks should be encoded using 236 | % erljs_html:a(LogicalKey, [{param,Value}}, [OtherAttributes]) 237 | % where OtherAttributes can also contain {target,"xxx"}, which will translate into "#xxx" appened to href. 238 | % Direct usage of 'a' can be disabled, or checked, 239 | % by changing scheme (allow_custom_a_href). 240 | % 241 | % 242 | % erljs_html:register_a(LogicalKey, RealPath, 243 | % [{param1,int,required}, 244 | % {param2,float,optional}, 245 | % {"param3",any,optional}, 246 | % {{"^params_.*$"},int,optional} 247 | % ) 248 | % 249 | % This have many advantages. 250 | % - you can track usage of all links 251 | % - you can add additional parameters (like security tokens, session ids) 252 | % - you can easly move site or part of it to other directory, or location 253 | % - you can enforce absolute or relative URLS 254 | % - you can enforce https encryption 255 | % - you can create proxy/redir page, which will hide user's Refferer 256 | % 257 | % 258 | % 259 | 260 | % 261 | % syntactic sugar for 'style' attribute 262 | % 263 | 264 | 265 | % TODO: registering parameters. 266 | % 267 | % 268 | % ?get_required(int, Page). 269 | % ?get_required(postive_int, Page). 270 | % ?get_required(float, Temp). 271 | % ?get_optional(identifier, Temp). 272 | % ?get_optional(id, Id). 273 | % ?get_optional(atom, Elem). % it will must be 'atom' like, but not actually converted 274 | % ?get_optional({"....-....-\\d\\d"}, Key). % for regular expressions 275 | % ?get_optional(fun(X) -> is_valid_token(X) end, Token). % for general tests 276 | % listing(Req) -> 277 | % {page, 278 | % ["something -", Page] 279 | % }. 280 | % 281 | % in case of int, positive_int, float - arguments are parsed as int or float. 282 | % 283 | 284 | % ?pre_require(secure). % https over ssl/tls. todo: warn/clear cookies, log referrer, etc 285 | % ?pre_require(auth). 286 | % ?pre(log). 287 | % ?post(trace). 288 | % ?cookie(present). 289 | % ?header(present, "Refferer"). 290 | 291 | 292 | % 293 | % Other important parts in ehtml 294 | % {status, 404} % yaws 295 | % {status, 404, "WTF"} 296 | % {redirect, URL} % yaws % URL must be absolute URL 297 | % {redirect_local, Path} % yaws % URL 298 | % {headers, [ 299 | % clear, 300 | % [{set, Header}] 301 | % [{replace, Header}] 302 | % [{append, Header}] 303 | % [{remove, Header}] 304 | % ]}. 305 | % where Header is binary or string "XXX: YYY", or {'XXX', "YYY"} 306 | % no new lines allowed. 307 | % ok % yaws % do nothing 308 | % {'EXIT', normal} % yaws 309 | % {content, MimeType, Data} % yaws 310 | % {sendfile, FileName, Start, End} % End can be eof. 311 | % 312 | % %{allheaders, [Headers]} % yaws 313 | % %{header, Header} % yaws 314 | % 315 | % {streamcontent, MimeType, FirstChunk} % yaws 316 | % 317 | % in other process. 318 | % % YawsPid is original process which was serving, so S=self(),spawn(fun()->loop(S) end) 319 | % yaws_api:stream_chunk_deliver(YawsPid, BinData), 320 | % yaws_api:stream_chunk_deliver(YawsPid, BinData), 321 | % yaws_api:stream_chunk_deliver_blocking(YawsPid, Data), % with sending flow-control 322 | % yaws_api:stream_chunk_end(YawsPid), 323 | % exit(normal). 324 | % 325 | % NewPid = spawn(fun() -> loop(A#arg.clisock) end), 326 | % [{header, {content_length, Sz}}, % without content_length, chunked mode (b) is used 327 | % {streamcontent_from_pid, MimeType, NewPid}] % yaws 328 | % 329 | % in loop 330 | % % {discard, YawsPid} -> 331 | % % yaws_api:stream_process_end(Sock, YawsPid); 332 | % % {ok, YawsPid} -> 333 | % % a) yaws_api:stream_process_deliver(Socket, BinData), 334 | % % a) yaws_api:stream_process_deliver(Socket, BinData), 335 | % % b) yaws_api:stream_process_deliver_chunk(Socket, IoList), 336 | % % b) yaws_api:stream_process_deliver_chunk(Socket, IoList), 337 | % % b) yaws_api:stream_process_final_deliver_chunk(Socket, IoList), 338 | % % yaws_api:stream_process_end(Socket, YawsPid) 339 | % for delive 340 | % 341 | % {ssi, FileName, Separator, [{"var","Rewriting it to something"}. % yaws. similar to include. 342 | % % included for compatibility. 343 | % {yssi, FileName}. % yaws, only top level element from out/1. 344 | 345 | 346 | % TODO: 347 | % SVG: esvg % http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd 348 | % svg 349 | % a, altGlyph, altGlyphDef, altGlyphItem, animate, animateColor, animateMotion, animateTransofrm 350 | % circle, clipPath, color_profile, cursor 351 | % definition_src, defs, desc 352 | % ellipse 353 | % feBlend, feColorMatrix, feComponentTransfer, feComposite, feConvolveMatrix, feDiffuseLighting, feDisplacementMap, feFlood, feFuncA, feFuncB, feFuncG, feFuncR, feGaussianBlur, feImage, feMerge, feMergeNode, feMorphology, feOffset, fePointLight, feSpecularLighting, feSpotLight, feTile, feTurbulence 354 | % filter, font, font_face, font_face_format, font_face_name, font_face_src, font_face_uri, foreignObject 355 | % g, glyph, glyphRef 356 | % hkern, vkern 357 | % image 358 | % line, linearGradient 359 | % marker, mask, metadata, missing_glyph 360 | % mpath, path, pattern, polygon, polyline 361 | % radialGradient, rect 362 | % script, set, stop, style, switch, symbol 363 | % text, textPath, title, tref, tspan 364 | % use, view 365 | % 366 | % esvg_valid - marks that esvg fragment should not be validated, as it was already validated 367 | % svg_raw - to put iolist() directly in given place. it still need to be valid svg fragment, and validate 368 | % 369 | % Example: 370 | % {esvg, [{width,"100%"},{height,"100%"}], [ 371 | % {circle, [{cx,100},{cy,50},{r,40},{stroke,'black'},{stroke_width,2},{fill,'red'}], []}, 372 | % {rect, [{x,20},{y,20},{rx,20},{ry,20},{width,250},{height,250},{style,"fill:blue;stroke:ping;fill-opacity:0.1;stroke-opacity:0.9"}], []}, 373 | % {ellipse, [{cx,300},{cy,150},{rx,200},{ry,80},{style,"fill:rgb(200,100,50)"}], []}, 374 | % {line,[{x1,0},{y1,0},{x2,300},{y2,300},{style,"stroke:rgb(99,99,99);stroke-width:2"}], []}, 375 | % {polygon,[{points,"220,100 300,210 170,250"},{style,"fill:#cccccc;stroke:#000000;stroke-width:1"}], []}, 376 | % {polyline,[{points,"0,0 0,20 20,20 20,40 40,40 40,60"},{style,"fill:green;stroke:red;stroke-width:2"}], []}, 377 | % {path, [{d,"M250 150 L150 350 L350 350 Z"}], []} 378 | % {path, [{d,"M153 334" ++ 379 | % "C153 334 151 334 151 334" ++ 380 | % "C151 339 153 344 156 344" ++ 381 | % "C164 344 171 339 171 334" ++ 382 | % "C171 322 164 314 156 314" ++ 383 | % "C142 314 131 322 131 334" ++ 384 | % "C131 350 142 364 156 364" ++ 385 | % "C175 364 191 350 191 334" ++ 386 | % "C191 311 175 294 156 294" ++ 387 | % "C131 294 111 311 111 334" ++ 388 | % "C111 361 131 384 156 384" ++ 389 | % "C186 384 211 361 211 334" ++ 390 | % "C211 300 186 274 156 274"}, {style,"fill:white;stroke:red;stroke-width:2"}], []}, 391 | % {defs, [ 392 | % {filter,[{id,myFilter1}],[ 393 | % {feGaussianBlur,[{in,"SourceGraphic"},{stdDeviation,3}],[]} 394 | % ]} 395 | % ]}, 396 | % {ellipse,[{cx,300},{cy,150},{rx,170},{ry,40},{style,"fill:#ff0000;stroke:#000000;stroke-width:2;filter:url(#myFilter1)"}],[]} 397 | % ]}. 398 | % 399 | % see syntactic sugar for shorter notation for circle, rect, line, ellipse, polygon, polyline, path and style (as in HTML) 400 | % 401 | % % Mostly all browsers, allows scripting 402 | % {ehtml, {embed, [{src,"plik.svg"}, 403 | % {width,300},{height,100}, 404 | % {type,"image/svg+xml"}, 405 | % {pluginpage,"http://www.adobe.com/svg/viewer/install/"} % for IE 406 | % ] 407 | % }}. 408 | % 409 | % % HTML4, but do not allows scripting 410 | % {ehtml, {object, [{data,"plik.svg"}, 411 | % {width,300},{height,100}, 412 | % {type,"image/svg+xml"}, 413 | % {codebase,"http://www.adobe.com/svg/viewer/install/"} % for IE 414 | % ] 415 | % }}. 416 | % 417 | % % Mostly all browser. 418 | % {ehtml, {iframe, [{src,"plik.svg"}, 419 | % {width,300},{height,100}]}}. 420 | % 421 | % % HTML5 (just inserts svg directly into HTML5) 422 | % {ehtml, SVG}. 423 | % 424 | % % HTML + SVG (translates svg into own namespace, for example: xmlns:svg=) 425 | % {ehtml, [{'xmlns:svg',"http://www.w3.org/2000/svg"}], {'svg:svg', SVG}}. 426 | % 427 | % 428 | % MathML: emathml % 429 | % 430 | % mi, mo, mn, mtext, ms, mspace, mglyph 431 | % mfenced, mfrac, mrow, msqrt, mroot, mstyle, merror, mpadded, mphantom, menclose 432 | % msup, msub, msubsup 433 | % munder, mover, munderover 434 | % mmultiscripts, mprescripts 435 | % mtable, mtr, mtd, maligngroup, malignmark, mlabeldtr 436 | % maction 437 | % apply, power, plus, divide, minus, times, ci, cn, compose, cos, sin, intersect, transpose, and 438 | % reln, eq, geq, leq, lt, subset 439 | % interval, vector, matrix, matrixrow 440 | % set, bvar, condition 441 | % sum, int, prod, lowlimit, uplimit 442 | % diff, partialdiff, degree 443 | % lambda, log, limit 444 | % semantics 445 | % annotation 446 | 447 | 448 | 449 | % Other templates: 450 | % 451 | % http://forum.trapexit.org/viewtopic.php?t=9342 452 | % Written By: Vladimir Sekissov, 453 | % STL as `Simple Template Language' is a clone of 454 | % Bruce R. Lewis's BRL (http://brl.sourceforge.net) 455 | % implemented in Erlang. It deals with template 456 | % processing and has most capabilities which user 457 | % expects from web template engines. 458 | % 459 | 460 | 461 | 462 | % other things too look: 463 | % glade for GTK+ 464 | % rapicorn 465 | % xrc for wxWidgets 466 | % Microsoft WFC and .NET classes 467 | 468 | --------------------------------------------------------------------------------