Smalltalk On
 Rubinius
   Konstantin Haase
Why implement
Smalltalk on Rubinius?
Why create a
programming language?
Why create?
"When you don't create things, you become
defined by your tastes rather than ability. Your
  tastes only narrow and exclude people. So
                   create."

              why the lucky stiff
Why a programming
    language?
About programming languages:

"I don’t like any of them, and I don’t think any of
   them are suitable for the real programming
 problems of today, whether for systems or for
                     end-users"

                     Alan Kay
Problem Oriented
Programming Languages
Cairo (~120k SLOC in C) rewritten in less than
                 400 lines
Why Smalltalk?
Why Rubinius?
1 + 1


1 + 1
this is it


this.is.it
GoGaRuCo rock: #hard


GoGaRuCo.rock :hard
doc convertFrom: #xml to: #yaml

doc.convert(:xml, :ruby)
doc convertFrom: #xml to: #yaml

doc.convert from: :xml, to: :ruby
[ 42 ]

proc { 42 }
anArray do: [ :each | each doSomething ]


an_array.each do |element|
  element.do_something
end
Textmate version = 2
  ifTrue: [ 'no way' ]
  ifFalse: [ 'thought so' ]


if Textmate.version == 2
  "no way"
else
  "thought so"
end
Storage current
  store: #foo;
  store: #bar


storage = Storage.current
storage.store :foo
storage.store :bar
Smalltalk claims to look
like: 'English'.
Judge yourself. Does it.


Ruby.claims.to.look.
like "English"

Judge.yourself; Does.it?
Reak
        github.com/rkh/Reak

       Like Squeak but with R

File based (as opposed to image based)
The Rubinius Compiler
          Pure Ruby

     Modular and Flexible

        lib/compiler
Parsing with KPeg
  github.com/evanphx/kpeg
" from Reak.AST.Self "
grammar: g [ ^ g str: 'self' ]


# from Reak::AST::Return
def bootstrap_grammar(g)
  g.seq "^", :sp, g.t(:expression)
end
Rubinius Bytecode
$ rbx compile -B -e 'puts "Hello World"'

0000:   push_self
0001:   push_literal    "Hello World"
0003:   allow_private
0004:   send_stack      :puts, 1
$ rbx compile -B -e 'puts "Hello World"'

0000:   push_self
0001:   push_literal    "Hello World"
0003:   allow_private
0004:   send_stack      :puts, 1
$ rbx compile -B -e 'puts "Hello World"'

0000:   push_self
0001:   push_literal    "Hello World"
0003:   allow_private
0004:   send_stack      :puts, 1
$ rbx compile -B -e 'puts "Hello World"'
0000:   push_self
0001:   push_literal    "Hello World"
0003:   allow_private
0004:   send_stack      :puts, 1
$ rbx compile -B -e 'puts "Hello World"'

0000:   push_self
0001:   push_literal    "Hello World"
0003:   allow_private
0004:   send_stack      :puts, 1
class Object
  dynamic_method(:display) do |g|
    g.push_self
    g.push_local(0) # first argument
    g.send(:puts, 1, true)
    g.ret
  end
end

display "Hello World"
Reusing the Rubinius
     tool chain
class Reak::Compiler < Rubinius::Compiler
  class Parser < Stage
    stage :parser
    next_stage Generator
  end
end
class CustomNode < Reak::AST::Base
  def self.bootstrap_grammar(g)
    # grammar definition
  end

  def bytecode(g)
    # bytecode definition
  end
end
class ConstantAccess < Rubinius::AST::ConstantAccess
  include Reak::AST::Node
  Reak::AST::Primary.push self

 def self.bootstrap_grammar(g)
   g.t /[A-Z][a-zA-Z0-9_]*/
 end

  # no bytecode definition necessary
end
Rubinius.AST.TrueLiteral subclass: #TrueLiteral [
  Reak.AST.Primary push: self.
  self include: Reak.AST.Node.
    self class >> grammar: g [
      ^ g str: 'true'
    ].
]
" Remember cascades? "

g
    pushSelf;
    pushLocal: 0;
    send: #puts args: 1 private: true;
    ret.
Reak.AST.Base subclass: #Cascade [
  Reak.AST.Expression push: self.

    bytecode: g [
      g pushSelf.
      cascadedSends do:
        [:send |
        g dup.
        send bytecode: g.
        g pop ].
      lastSend bytecode: g.
    ]
]
Thanks!
github.com / rkh / presentations

Smalltalk on rubinius