Jun's Blog

Output, activities, memo and etc.

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.

Mac: 10.9.4
Ruby: 2.2.3p173

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