Table of Contents

  1. Preface
  2. 1. Tokenization, Parsing and Compilation
    1. Tokens: the words that make up the Ruby language
    2. Parsing: how Ruby understands the code you write
      1. Understanding the LALR parse algorithm
      2. Some actual Ruby grammar rules
    3. Compilation: how Ruby translates your code into a new language
      1. Stepping through how Ruby compiles a simple script
      2. Compiling a call to a block
    4. Tokenization, parsing and compilation in JRuby
    5. Tokenization, parsing and compilation in Rubinius
  3. 2. How Ruby Executes Your Code
    1. YARV's internal stack and your Ruby stack
      1. Stepping through how Ruby executes a simple script
      2. Executing a call to a block
    2. Local and dynamic access of Ruby variables
      1. Local variable access
      2. Dynamic variable access
    3. How YARV controls your program's execution flow
      1. How Ruby executes an if statement
      2. Jumping from one scope to another
    4. How JRuby executes your code
    5. How Rubinius executes your code
  4. 3. Objects, Classes and Modules
    1. What's inside a Ruby object?
      1. Generic objects
      2. Do generic objects have instance variables?
    2. Deducing what's inside the RClass structure
      1. The actual RClass structure
    3. How Ruby implements modules and method lookup
      1. What happens when you include a module in a class?
      2. Ruby's method lookup algorithm
      3. Including two modules in one class
    4. Objects, classes and modules in JRuby
    5. Objects, classes and modules in Rubinius
  5. 4. Hash Tables
    1. Hash tables in Ruby
    2. How hash tables expand to accommodate more values
    3. How Ruby implements hash functions
    4. Hash tables in JRuby
    5. Hash tables in Rubinius
  6. 5. How Ruby Borrowed a Decades Old Idea From Lisp
    1. Blocks: Closures in Ruby
      1. Stepping through how Ruby calls a block
      2. Borrowing an idea from 1975
    2. Lambdas and Procs: treating functions as a first class citizen
      1. Stack memory vs. heap memory
      2. Stepping through how Ruby creates a lambda
      3. Stepping through how Ruby calls a lambda
      4. The Proc object
    3. Metaprogramming and closures: eval, instance_eval and binding
      1. Calling eval with binding
      2. Stepping through a call to instance_eval
      3. Another important part of Ruby closures
    4. Closures in JRuby
    5. Closures in Rubinius
  7. Conclusion

Experiments:

    1. Experiment 1-1: Using Ripper to tokenize different Ruby scripts
    2. Experiment 1-2: Using Ripper to parse different Ruby scripts
    3. Experiment 1-3: Using the RubyVM class to display YARV instructions
    4. Experiment 2-1: Benchmarking Ruby 1.9 vs. Ruby 1.8
    5. Experiment 2-2: Exploring special variables
    6. Experiment 2-3: Testing how Ruby implements for loops internally
    7. Experiment 3-1: How long does it take to save a new instance variable?
    8. Experiment 3-2: Where does Ruby save class methods?
    9. Experiment 3-3: Modifying a module after including it
    10. Experiment 4-1: Retrieving a value from hashes of varying sizes
    11. Experiment 4-2: Inserting one new element into hashes of varying sizes
    12. Experiment 4-3: Using objects as keys in a hash
    13. Experiment 5-1: Which is faster: a while loop or passing a block to each?
    14. Experiment 5-2: Changing local variables after calling lambda
    15. Experiment 5-3: Using a closure to define a method