145
SLAYING THE DRAGON

Slaying the Dragon: Implementing a Programming Language in Ruby

Embed Size (px)

Citation preview

Page 1: Slaying the Dragon: Implementing a Programming Language in Ruby

SLAYING THE DRAGON�

Page 2: Slaying the Dragon: Implementing a Programming Language in Ruby

A GUIDE TO IMPLEMENTING YOUR OWN PROGRAMMING LANGUAGE�

Page 3: Slaying the Dragon: Implementing a Programming Language in Ruby

HELLO!�

Page 4: Slaying the Dragon: Implementing a Programming Language in Ruby
Page 5: Slaying the Dragon: Implementing a Programming Language in Ruby

A GUIDE TO IMPLEMENTING YOUR OWN PROGRAMMING LANGUAGE�

Page 6: Slaying the Dragon: Implementing a Programming Language in Ruby
Page 7: Slaying the Dragon: Implementing a Programming Language in Ruby

A GUIDE TO IMPLEMENTING YOUR OWN PROGRAMMING LANGUAGE�

Page 8: Slaying the Dragon: Implementing a Programming Language in Ruby

¯ˉ\_(ツ)_/¯ˉ �

Page 9: Slaying the Dragon: Implementing a Programming Language in Ruby

FUN!�

Page 10: Slaying the Dragon: Implementing a Programming Language in Ruby

UNDERSTAND HOW PROGRAMMING LANGUAGES WORK�

Page 11: Slaying the Dragon: Implementing a Programming Language in Ruby

SystemStackError  

Page 12: Slaying the Dragon: Implementing a Programming Language in Ruby

def  case_when  n      case  n      when  :foo          42      when  :bar          88      when  :foobar          4288      end  end  

def  hash_lookup  n      {          foo:  42          bar:  88          foobar:  4288      }[n]  end      

Page 13: Slaying the Dragon: Implementing a Programming Language in Ruby

UNDERSTAND HOW COMPUTERS WORK�

Page 14: Slaying the Dragon: Implementing a Programming Language in Ruby

If you don't know how compilers work, then you don't know how computers work. - Steve Yegge (http://steve-yegge.blogspot.sg/2007/06/rich-programmer-food.html)

Page 15: Slaying the Dragon: Implementing a Programming Language in Ruby

LET'S MAKE A LISP�

Page 16: Slaying the Dragon: Implementing a Programming Language in Ruby

SUPER EASY TO IMPLEMENT�

Page 17: Slaying the Dragon: Implementing a Programming Language in Ruby

The "most powerful language in the world” that can be defined in "a page of code." - Alan Kay

Page 18: Slaying the Dragon: Implementing a Programming Language in Ruby

HOMOICONIC�

Page 19: Slaying the Dragon: Implementing a Programming Language in Ruby

TONS OF GUIDES ONLINE�

Page 20: Slaying the Dragon: Implementing a Programming Language in Ruby

norvig.com/lispy.html  

Page 21: Slaying the Dragon: Implementing a Programming Language in Ruby

buildyourownlisp.com  

Page 22: Slaying the Dragon: Implementing a Programming Language in Ruby

github.com/kanaka/mal  

Page 23: Slaying the Dragon: Implementing a Programming Language in Ruby

MAL�

Page 24: Slaying the Dragon: Implementing a Programming Language in Ruby

mal>    

Page 25: Slaying the Dragon: Implementing a Programming Language in Ruby

mal>  (+  2  6)    

Page 26: Slaying the Dragon: Implementing a Programming Language in Ruby

mal>  (+  2  6)  =>  8  mal>    

Page 27: Slaying the Dragon: Implementing a Programming Language in Ruby

mal>  (+  2  6)  =>  8  mal>    

LISP FORM �

Page 28: Slaying the Dragon: Implementing a Programming Language in Ruby

mal>  (+  2  6)  =>  8  mal>  (-­‐  4  8)    

Page 29: Slaying the Dragon: Implementing a Programming Language in Ruby

mal>  (+  2  6)  =>  8  mal>  (-­‐  4  8)  =>  -­‐4  mal>  

Page 30: Slaying the Dragon: Implementing a Programming Language in Ruby

mal>  (+  2  6)  =>  8  mal>  (-­‐  4  8)  =>  -­‐4  mal>  (+  (-­‐  4  8)  10)    

Page 31: Slaying the Dragon: Implementing a Programming Language in Ruby

mal>  (+  2  6)  =>  8  mal>  (-­‐  4  8)  =>  -­‐4  mal>  (+  (-­‐  4  8)  10)  =>  6  mal>  

Page 32: Slaying the Dragon: Implementing a Programming Language in Ruby

mal>  (+  2  6)  =>  8  mal>  (-­‐  4  8)  =>  -­‐4  mal>  (+  (-­‐  4  8)  10)  =>  6  mal>  (<  4  10)    

Page 33: Slaying the Dragon: Implementing a Programming Language in Ruby

mal>  (+  2  6)  =>  8  mal>  (-­‐  4  8)  =>  -­‐4  mal>  (+  (-­‐  4  8)  10)  =>  6  mal>  (<  4  10)  true  

Page 34: Slaying the Dragon: Implementing a Programming Language in Ruby

mal>    

Page 35: Slaying the Dragon: Implementing a Programming Language in Ruby

mal>  (if  (<  4  10)                    42                    88)    

Page 36: Slaying the Dragon: Implementing a Programming Language in Ruby

mal>  (if  (<  4  10)                    42                    88)  =>  42  

Page 37: Slaying the Dragon: Implementing a Programming Language in Ruby

mal>    

Page 38: Slaying the Dragon: Implementing a Programming Language in Ruby

mal>  (fn*  [x]  (*  x  x))  =>  #<function>  mal>  

Page 39: Slaying the Dragon: Implementing a Programming Language in Ruby

mal>  (fn*  [x]  (*  x  x))  =>  #<function>  mal>  

PARAMS�

Page 40: Slaying the Dragon: Implementing a Programming Language in Ruby

mal>  (fn*  [x]  (*  x  x))  =>  #<function>  mal>   FUNCTION BODY �

Page 41: Slaying the Dragon: Implementing a Programming Language in Ruby

irb>  lambda  {  |x|  x  *  x  }    

Page 42: Slaying the Dragon: Implementing a Programming Language in Ruby

mal>  (fn*  [x]  (*  x  x))  =>  #<function>  mal>  ((fn*  [x]  (*  x  x))  8)  

Page 43: Slaying the Dragon: Implementing a Programming Language in Ruby

mal>  (fn*  [x]  (*  x  x))  =>  #<function>  mal>  ((fn*  [x]  (*  x  x))  8)  =>  64  

Page 44: Slaying the Dragon: Implementing a Programming Language in Ruby

mal>  (fn*  [x]  (*  x  x))  =>  #<function>  mal>  ((fn*  [x]  (*  x  x))  8)  =>  64  

FUNCTION THAT YOU WANT TO CALL �

Page 45: Slaying the Dragon: Implementing a Programming Language in Ruby

mal>  (fn*  [x]  (*  x  x))  =>  #<function>  mal>  ((fn*  [x]  (*  x  x))  8)  =>  64  

ARGUMENTS�

Page 46: Slaying the Dragon: Implementing a Programming Language in Ruby

irb>  lambda  {  |x|  x  *  x  }.call  8    

Page 47: Slaying the Dragon: Implementing a Programming Language in Ruby

mal>  (fn*  [x]  (*  x  x))  =>  #<function>  mal>  ((fn*  [x]  (*  x  x))  8))  =>  64  mal>  (def  sq  (fn*  [x]  (*  x  x)))  =>  #<function>    

Page 48: Slaying the Dragon: Implementing a Programming Language in Ruby

mal>  (fn*  [x]  (*  x  x))  =>  #<function>  mal>  ((fn*  [x]  (*  x  x))  8))  =>  64  mal>  (def  sq  (fn*  [x]  (*  x  x)))  =>  #<function>  mal>  (sq  8)  =>  64  

Page 49: Slaying the Dragon: Implementing a Programming Language in Ruby

•     

NOW YOU KNOW (BASIC) LISP!�

Page 50: Slaying the Dragon: Implementing a Programming Language in Ruby

•     

BEFORE WE DIVE IN�

Page 51: Slaying the Dragon: Implementing a Programming Language in Ruby

•     

RUBINIUS�

Page 52: Slaying the Dragon: Implementing a Programming Language in Ruby

•     

LLVM�

Page 53: Slaying the Dragon: Implementing a Programming Language in Ruby

•     

A LANGAUGE PLATFORM�

Page 54: Slaying the Dragon: Implementing a Programming Language in Ruby

•     WHAT THE HECK IS A VIRTUAL

MACHINE?�

Page 55: Slaying the Dragon: Implementing a Programming Language in Ruby

•     

AN ABSTRACT MACHINE�

Page 56: Slaying the Dragon: Implementing a Programming Language in Ruby
Page 57: Slaying the Dragon: Implementing a Programming Language in Ruby

•     

LET’S DIVE IN!�

Page 58: Slaying the Dragon: Implementing a Programming Language in Ruby

•     CUSTOMIZING RUBINIUS’ COMPILATION PIPELINE�

Page 59: Slaying the Dragon: Implementing a Programming Language in Ruby
Page 60: Slaying the Dragon: Implementing a Programming Language in Ruby

•     FILE | STRING�

Page 61: Slaying the Dragon: Implementing a Programming Language in Ruby

•     FILE | STRING�

COMPILED METHOD�

Page 62: Slaying the Dragon: Implementing a Programming Language in Ruby
Page 63: Slaying the Dragon: Implementing a Programming Language in Ruby

•     

CUSTOMIZE TWO THINGS�IN THIS PIPELINE�

Page 64: Slaying the Dragon: Implementing a Programming Language in Ruby

•      PARSER�

Page 65: Slaying the Dragon: Implementing a Programming Language in Ruby

•     

ABSTRACT SYNTAX TREE�

PARSER�

Page 66: Slaying the Dragon: Implementing a Programming Language in Ruby

•     

MAL PARSER�

Page 67: Slaying the Dragon: Implementing a Programming Language in Ruby

TOKENIZER�

Page 68: Slaying the Dragon: Implementing a Programming Language in Ruby

TOKENIZER�

READER�

Page 69: Slaying the Dragon: Implementing a Programming Language in Ruby

TOKENIZER�

READER�

PARSING LOGIC�

Page 70: Slaying the Dragon: Implementing a Programming Language in Ruby

•     

TOKENIZER�

Page 71: Slaying the Dragon: Implementing a Programming Language in Ruby

(+  my_var  42)      

Page 72: Slaying the Dragon: Implementing a Programming Language in Ruby

(+  my_var  42)      

['(',  '+',  'my_var',  '42',  ')']  

Page 73: Slaying the Dragon: Implementing a Programming Language in Ruby

/[\s,]*(~@|[\[\]{}()'`~^@]|"(?:\\.|[^\\"])*"|;.*|[^\s\[\]{}('"`,;)]*)/  

Page 74: Slaying the Dragon: Implementing a Programming Language in Ruby

•     

LEXING IN RUBY�

Page 75: Slaying the Dragon: Implementing a Programming Language in Ruby

[1]  pry(main)>  

Page 76: Slaying the Dragon: Implementing a Programming Language in Ruby

[1]  pry(main)>  require  'ripper'  =>  true  [2]  pry(main)>  

Page 77: Slaying the Dragon: Implementing a Programming Language in Ruby

[1]  pry(main)>  require  'ripper'  =>  true  [2]  pry(main)>  Ripper.lex  'foo  =  123'  

Page 78: Slaying the Dragon: Implementing a Programming Language in Ruby

[1]  pry(main)>  require  'ripper'  =>  true  [2]  pry(main)>  Ripper.lex  'foo  =  123'  =>  [[[1,  0],  :on_ident,  "foo"],          [[1,  3],  :on_sp,  "  "],          [[1,  4],  :on_op,  "="],          [[1,  5],  :on_sp,  "  "],          [[1,  6],  :on_int,  "123"]]  

Page 79: Slaying the Dragon: Implementing a Programming Language in Ruby

(+  my_var  42)      

['(',  '+',  'my_var',  '42',  ')']  

Page 80: Slaying the Dragon: Implementing a Programming Language in Ruby

•     

READER�

Page 81: Slaying the Dragon: Implementing a Programming Language in Ruby

['(',  '+',  'my_var',  '42',  ')']      

Page 82: Slaying the Dragon: Implementing a Programming Language in Ruby

['(',  '+',  'my_var',  '42',  ')']      

[:list,      [:symbol,  '+'],      [:symbol,  'my_var'],      [:integer,  42]]  

Page 83: Slaying the Dragon: Implementing a Programming Language in Ruby

•     

MAL GRAMMAR�

Page 84: Slaying the Dragon: Implementing a Programming Language in Ruby

<form>  ::=  <list>  |  <atom>  <list>  ::=  '('  <form>*  ')'  |                        '['  <form>*  ']'  <atom>  ::=  a-­‐z+  |  0-­‐9+  |                        true  |  false  

Page 85: Slaying the Dragon: Implementing a Programming Language in Ruby

<form>  ::=  <list>  |  <atom>  <list>  ::=  '('  <form>*  ')'  |                        '['  <form>*  ']'  <atom>  ::=  a-­‐z+  |  0-­‐9+  |                        true  |  false  

Page 86: Slaying the Dragon: Implementing a Programming Language in Ruby

<form>  ::=  <list>  |  <atom>  <list>  ::=  '('  <form>*  ')'  |                        '['  <form>*  ']'  <atom>  ::=  a-­‐z+  |  0-­‐9+  |                        true  |  false  

Page 87: Slaying the Dragon: Implementing a Programming Language in Ruby

<form>  ::=  <list>  |  <atom>  <list>  ::=  '('  <form>*  ')'  |                        '['  <form>*  ']'  <atom>  ::=  a-­‐z+  |  0-­‐9+  |                        true  |  false  

Page 88: Slaying the Dragon: Implementing a Programming Language in Ruby

<form>  ::=  <list>  |  <atom>  <list>  ::=  '('  <form>*  ')'  |                        '['  <form>*  ']'  <atom>  ::=  a-­‐z+  |  0-­‐9+  |                        true  |  false  

Page 89: Slaying the Dragon: Implementing a Programming Language in Ruby

<form>  ::=  <list>  |  <atom>  

       def  read_form(tokens)              if  tokens.first  =~  /(\(|\[)/                  read_list(tokens)              else                  read_atom(tokens.shift)              end          end  

Page 90: Slaying the Dragon: Implementing a Programming Language in Ruby

<form>  ::=  <list>  |  <atom>  <list>  ::=  '('  <form>*  ')'  |                        '['  <form>*  ']'  <atom>  ::=  a-­‐z+  |  0-­‐9+  |                        true  |  false  

Page 91: Slaying the Dragon: Implementing a Programming Language in Ruby

<list>  ::=  '('  <form>*  ')'  |                        '['  <form>*  ']'  

       def  read_list(tokens)              list  =  [:list]                tokens.shift  #  pop  our  opening  paren              while  tokens.first  !~  /(\)|\])/                  list  <<  read_form(tokens)              end              tokens.shift  #  pop  our  closing  paren                list          end  

Page 92: Slaying the Dragon: Implementing a Programming Language in Ruby

<form>  ::=  <list>  |  <atom>  <list>  ::=  '('  <form>*  ')'  |                        '['  <form>*  ']'  <atom>  ::=  a-­‐z+  |  0-­‐9+  |                        true  |  false  

Page 93: Slaying the Dragon: Implementing a Programming Language in Ruby

<atom>  ::=  a-­‐z+  |  0-­‐9+  |                        true  |  false  

       def  read_atom(token)              case  token              when  /^-­‐?\d+$/                  [:integer,  token.to_i]              when  'true'                  [:boolean,  :true]              when  'false'                  [:boolean,  :false]              when  /^\D+$/                  [:symbol,  token]              else                  raise  'Reader  error:  Unknown  token'              end          end  

Page 94: Slaying the Dragon: Implementing a Programming Language in Ruby

['(',  '+',  'my_var',  '42',  ')']      

(+  my_var  42)  

[:list,      [:symbol,  '+'],      [:symbol,  'my_var'],      [:integer,  42]]  

Page 95: Slaying the Dragon: Implementing a Programming Language in Ruby

•     

PARSING LOGIC�

Page 96: Slaying the Dragon: Implementing a Programming Language in Ruby

•     

ABSTRACT SYNTAX TREES�

Page 97: Slaying the Dragon: Implementing a Programming Language in Ruby

(+  my_var  42)  

Page 98: Slaying the Dragon: Implementing a Programming Language in Ruby

(+  my_var  42)  

Page 99: Slaying the Dragon: Implementing a Programming Language in Ruby

(+  my_var  42)  

LEFT HAND SIDE �

Page 100: Slaying the Dragon: Implementing a Programming Language in Ruby

(+  my_var  42)  

LEFT HAND SIDE � RIGHT HAND SIDE �

Page 101: Slaying the Dragon: Implementing a Programming Language in Ruby

(+  my_var  42)  

AddNode.new(SymbolNode.new('my_var'),                          IntegerNode.new(42))    

LEFT HAND SIDE � RIGHT HAND SIDE �

Page 102: Slaying the Dragon: Implementing a Programming Language in Ruby

(if  (<  n  2)          42          88)  

Page 103: Slaying the Dragon: Implementing a Programming Language in Ruby

(if  (<  n  2)          42          88)  

Page 104: Slaying the Dragon: Implementing a Programming Language in Ruby

(if  (<  n  2)          42          88)   CONDITIONAL �

Page 105: Slaying the Dragon: Implementing a Programming Language in Ruby

(if  (<  n  2)          42          88)   CONDITIONAL �

THEN BRANCH �

Page 106: Slaying the Dragon: Implementing a Programming Language in Ruby

(if  (<  n  2)          42          88)   CONDITIONAL �

THEN BRANCH �

ELSE BRANCH �

Page 107: Slaying the Dragon: Implementing a Programming Language in Ruby

(if  (<  n  2)          42          88)  

if_node  =  IfNode(  LessThanNode(  SymbolNode('n'),                                                                  IntegerNode(2)  ),                                      IntegerNode(42),                                      IntegerNode(88)  )  

CONDITIONAL �THEN BRANCH �

ELSE BRANCH �

Page 108: Slaying the Dragon: Implementing a Programming Language in Ruby

if_node.condition  =>  LessThanNode(  SymbolNode('n'),                                              IntegerNode(2)  )    

Page 109: Slaying the Dragon: Implementing a Programming Language in Ruby

if_node.condition  =>  LessThanNode(  SymbolNode('n'),                                              IntegerNode(2)  )    if_node.then_branch  =>  IntegerNode(42)    

Page 110: Slaying the Dragon: Implementing a Programming Language in Ruby

if_node.condition  =>  LessThanNode(  SymbolNode('n'),                                              IntegerNode(2)  )    if_node.then_branch  =>  IntegerNode(42)    if_node.else_branch  =>  IntegerNode(88)  

Page 111: Slaying the Dragon: Implementing a Programming Language in Ruby

       def  parse_sexp(sexp)              type,  *rest  =  sexp              case  type              when  :boolean                  boolean  =  sexp.last                  if  boolean  ==  :true                      Malady::AST::TrueBooleanNode.new                  else                      Malady::AST::FalseBooleanNode.new                  end              when  :symbol                  name  =  sexp.last                  builtins.fetch(name,  Malady::AST::SymbolNode.new(name)              when  :integer                  Malady::AST::IntegerNode.new  sexp[1]              when  :list                  rest.map  {  |sexp|  parse(sexp)  }              end          end  

Page 112: Slaying the Dragon: Implementing a Programming Language in Ruby

•     

RUBINIUS BYTECODE�

Page 113: Slaying the Dragon: Implementing a Programming Language in Ruby

•     

STACK BASED VM�

Page 114: Slaying the Dragon: Implementing a Programming Language in Ruby

1  +  2  

Page 115: Slaying the Dragon: Implementing a Programming Language in Ruby

STACK �

1  +  2  

INSTRUCTIONS�

Page 116: Slaying the Dragon: Implementing a Programming Language in Ruby

STACK �

1  +  2  

push  1  

INSTRUCTIONS�

Page 117: Slaying the Dragon: Implementing a Programming Language in Ruby

STACK �

1  +  2  

push  1  

INSTRUCTIONS�

1  

Page 118: Slaying the Dragon: Implementing a Programming Language in Ruby

STACK �

1  +  2  

push  1  push  2  

INSTRUCTIONS�

1  

Page 119: Slaying the Dragon: Implementing a Programming Language in Ruby

STACK �

1  +  2  

push  1  push  2  

INSTRUCTIONS�

1  

2  

Page 120: Slaying the Dragon: Implementing a Programming Language in Ruby

STACK �

1  +  2  

push  1  push  2  add  

INSTRUCTIONS�

1  

2  

Page 121: Slaying the Dragon: Implementing a Programming Language in Ruby

STACK �

1  +  2  

push  1  push  2  add  

INSTRUCTIONS�

3  

Page 122: Slaying the Dragon: Implementing a Programming Language in Ruby

•     

RUBINIUS BYTECODE�

Page 123: Slaying the Dragon: Implementing a Programming Language in Ruby

-­‐>  %  rbx  compile  -­‐B  -­‐e  '123+42'    =============  :__script__  ==============  Arguments:      0  required,  0  post,  0  total  Arity:              0  Locals:            0  Stack  size:    2  Literals:        1:  :+  Lines  to  IP:  1:  0..9    0000:    push_int                                      123  0002:    push_int                                      42  0004:    send_stack                                  :+,  1  0007:    pop  0008:    push_true  0009:    ret  -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐  

Page 124: Slaying the Dragon: Implementing a Programming Language in Ruby

•     

GENERATING BYTECODE�

Page 125: Slaying the Dragon: Implementing a Programming Language in Ruby
Page 126: Slaying the Dragon: Implementing a Programming Language in Ruby

       class  IntegerNode  <  Node              attr_reader  :value              def  initialize(value)                  @value  =  value              end                def  bytecode(g)                  pos(g)                  g.push_int  value              end          end  

Page 127: Slaying the Dragon: Implementing a Programming Language in Ruby

       class  AddNode  <  Node              def  initialize(lhs,  rhs)                  @lhs,  @rhs  =  lhs,  rhs              end                def  bytecode(g)                  pos(g)                  lhs.bytecode(g)                  rhs.bytecode(g)                  g.send(:+,  1)              end          end  

Page 128: Slaying the Dragon: Implementing a Programming Language in Ruby

       class  IfNode  <  Node              attr_reader  :condition,  :then_branch,  :else_branch              def  initialize(filename,  line,  condition,  then_branch,  else_branch)                  super                  @condition  =  condition                  @then_branch  =  then_branch                  @else_branch  =  else_branch              end                def  bytecode(g)                  pos(g)                    end_label  =  g.new_label                  else_label  =  g.new_label                    condition.bytecode(g)                  g.goto_if_false  else_label                  then_branch.bytecode(g)                  g.goto  end_label                    else_label.set!                  else_branch.bytecode(g)                    end_label.set!              end          end  

Page 129: Slaying the Dragon: Implementing a Programming Language in Ruby

       class  IfNode  <  Node              ...              def  bytecode(g)                  pos(g)                    end_label  =  g.new_label                  else_label  =  g.new_label                    condition.bytecode(g)                  g.goto_if_false  else_label                  then_branch.bytecode(g)                  g.goto  end_label                    else_label.set!                  else_branch.bytecode(g)                    end_label.set!              end          end  

Page 130: Slaying the Dragon: Implementing a Programming Language in Ruby

       class  IfNode  <  Node              ...              def  bytecode(g)                  pos(g)                    end_label  =  g.new_label                  else_label  =  g.new_label                    condition.bytecode(g)                  g.goto_if_false  else_label                  then_branch.bytecode(g)                  g.goto  end_label                    else_label.set!                  else_branch.bytecode(g)                    end_label.set!              end          end  

Page 131: Slaying the Dragon: Implementing a Programming Language in Ruby

       class  IfNode  <  Node              ...              def  bytecode(g)                  pos(g)                    end_label  =  g.new_label                  else_label  =  g.new_label                    condition.bytecode(g)                  g.goto_if_false  else_label                  then_branch.bytecode(g)                  g.goto  end_label                    else_label.set!                  else_branch.bytecode(g)                    end_label.set!              end          end  

Page 132: Slaying the Dragon: Implementing a Programming Language in Ruby

       class  IfNode  <  Node              ...              def  bytecode(g)                  pos(g)                    end_label  =  g.new_label                  else_label  =  g.new_label                    condition.bytecode(g)                  g.goto_if_false  else_label                  then_branch.bytecode(g)                  g.goto  end_label                    else_label.set!                  else_branch.bytecode(g)                    end_label.set!              end          end  

Page 133: Slaying the Dragon: Implementing a Programming Language in Ruby

       class  IfNode  <  Node              ...              def  bytecode(g)                  pos(g)                    end_label  =  g.new_label                  else_label  =  g.new_label                    condition.bytecode(g)                  g.goto_if_false  else_label                  then_branch.bytecode(g)                  g.goto  end_label                    else_label.set!                  else_branch.bytecode(g)                    end_label.set!              end          end  

Page 134: Slaying the Dragon: Implementing a Programming Language in Ruby

       class  IfNode  <  Node              ...              def  bytecode(g)                  pos(g)                    end_label  =  g.new_label                  else_label  =  g.new_label                    condition.bytecode(g)                  g.goto_if_false  else_label                  then_branch.bytecode(g)                  g.goto  end_label                    else_label.set!                  else_branch.bytecode(g)                    end_label.set!              end          end  

Page 135: Slaying the Dragon: Implementing a Programming Language in Ruby

•     

NOW YOU HAVE A WORKING PROGRAMMING LANGUAGE!�

Page 136: Slaying the Dragon: Implementing a Programming Language in Ruby

•     

WHERE TO GET HELP?�

Page 137: Slaying the Dragon: Implementing a Programming Language in Ruby

github.com/kanaka/mal  

Page 138: Slaying the Dragon: Implementing a Programming Language in Ruby
Page 139: Slaying the Dragon: Implementing a Programming Language in Ruby

github.com/queenfrankie/lani  

Page 140: Slaying the Dragon: Implementing a Programming Language in Ruby

rubinius.com/doc/en/virtual-­‐machine/instructions/  

Page 141: Slaying the Dragon: Implementing a Programming Language in Ruby

github.com/jsyeo/malady  

Page 142: Slaying the Dragon: Implementing a Programming Language in Ruby

•     

QUESTIONS?�

Page 143: Slaying the Dragon: Implementing a Programming Language in Ruby

•     

POSTSCRIPT�

Page 144: Slaying the Dragon: Implementing a Programming Language in Ruby

http://philosecurity.org/2009/01/12/interview-­‐with-­‐an-­‐adware-­‐author  

Page 145: Slaying the Dragon: Implementing a Programming Language in Ruby

YO DAWG�