Install ErRuby on Mac
Install ErRuby which is Erlang's implementation for Ruby.
The purpose is to learn the structure of Ruby implementation.
MRI(Matz Ruby Implementation = CRuby) is too big to understand entire structure.
Install
Install reading this page.
https://github.com/johnlinvc/erruby
$ brew install erlang rebar
$ cd $GIT_DIR/ $ git clone https://github.com/johnlinvc/erruby
$ rbenv local 2.2.3
$ view Gemfile
$ bundle install
I got warnings, and an error, created directory at first.
And still have an error.
$ view rebar.config $ rebar get-deps WARN: Expected /Users/jun.aruga/git/erruby/deps/erlport to be a raw dependency directory, but no directory found. ==> erruby (get-deps) WARN: Expected /Users/jun.aruga/git/erruby/deps/erlport to be a raw dependency directory, but no directory found. Pulling erlport from {git,"git@github.com:hdima/erlport.git", {branch,"master"}} Cloning into 'erlport'... Permission denied (publickey). fatal: Could not read from remote repository. $ mkdir deps/erlport $ rebar get-deps ... Same kind of error. ...
I added SSH keys to github, this PC's key was not registered to github.
$ ssh -T git@github.com Hi junaruga! You've successfully authenticated, but GitHub does not provide shell access. https://help.github.com/articles/error-permission-denied-publickey/
Success for following command.
$ rebar get-deps
$ rebar compile $ echo $? 0
Error happened.
$ ./erruby rb_test/hello_world.rb error undef [{ruby,start,[],[]},{erruby,start_ruby,0,[{file,"src/erruby.erl"},{line,66}]},{erruby,eruby,1,[{file,"src/erruby.erl"},{line,36}]},{erruby,main,1,[{file,"src/erruby.erl"},{line,26}]},{escript,run,2,[{file,"escript.erl"},{line,757}]},{escript,start,1,[{file,"escript.erl"},{line,277}]},{init,start_it,1,[]},{init,start_em,1,[]}]
Check HEAD commit hash of develop branch.
$ git branch * develop $ git rev-parse HEAD 776d0abc2b92f4d38e2145358152d2a07dcbc04f
Finally I tried from $ git clone https://github.com/johnlinvc/erruby
, again.
And success to print "hello world"!
$ ./erruby rb_test/hello_world.rb hello world
Read source
I am interested in the parse logic from ruby code to AST.
erruby -> ebin/erruby.beam -> ebin/erruby.app -> src/erruby.erl -> function main -> function parse_ast (Create ast from ruby code) -> rb_src/erruby.rb def parse -> ErlPort::AstMapping.parse(src) -> Gemfile, gem 'erlport-ast_mapping', github: "johnlinvc/erlport-ast_mapping" -> https://github.com/johnlinvc/erlport-ast_mapping -> erlport-ast_mapping/lib/erlport/ast_mapping.rb def parse -> ::Parser::CurrentRuby.parse(src) -> https://github.com/whitequark/parser
Run AST part.
erruby -> ebin/erruby.beam -> ebin/erruby.app -> src/erruby.erl -> function main -> function erruby_vm:eval_ast (Run AST) -> src/erruby_vm.erl function eval_ast(AST) -> There are seveval eval_ast functions, called recursively.
There are debug options to check the behavior.
$ ./erruby -d rb_test/hello_world.rb debug level 1: send debug level 1: Ast: undefined debug level 1: Ast: puts debug level 1: Ast: {ast,type,str,children,[<<"hello world">>]} hello world $ ./erruby -d 2 rb_test/hello_world.rb debug level 2: input file name rb_test/hello_world.rb debug level 2: input args debug level 1: send debug level 1: Ast: undefined debug level 1: Ast: puts debug level 1: Ast: {ast,type,str,children,[<<"hello world">>]} debug level 2: finding method:puts in State:#{consts => #{'FalseClass' => <0.39.0>,'NilClass' => <0.36.0>,'TrueClass' => <0.38.0>}, ivars => #{}, methods => #{'==' => #Fun<erruby_object.4.93324764>, inspect => #Fun<erruby_object.2.93324764>, puts => #Fun<erruby_object.0.93324764>, self => #Fun<erruby_object.1.93324764>, to_s => #Fun<erruby_object.3.93324764>}, properties => #{}, self => <0.33.0>} hello world