Developing a Language

Preview:

DESCRIPTION

A talk by Evan Phoenix at LARubyConf all about creating a new language from scratch to run on top of the Rubinius VM.

Citation preview

Developinga

Language

Evan Phoenix Feb 5th, 2011

★ @evanphx ♘ github.com/evanphx

Tuesday, February 8, 2011

#11Tuesday, February 8, 2011

LA.RBLos Angeles Ruby Brigade

Tuesday Night. Every Week.http://rb.la

Tuesday, February 8, 2011

DINNER

Tuesday, February 8, 2011

DINNER

Tuesday, February 8, 2011

DINNER

Tuesday, February 8, 2011

DINNERTuesday, February 8, 2011

Which came first?

Tuesday, February 8, 2011

Language > Idea

Tuesday, February 8, 2011

Language < Idea

Tuesday, February 8, 2011

Language = Idea

Tuesday, February 8, 2011

The programmer, like the poet,

works only slightly removed

from pure thought-stuff.

- Fred Brooks

Tuesday, February 8, 2011

If ideas are a manifestation of

language

Tuesday, February 8, 2011

Can better language lead to

better ideas?

Tuesday, February 8, 2011

better!=

newer

Tuesday, February 8, 2011

IMPLEMENT

Tuesday, February 8, 2011

To craft a language from

scratch is to take 95% from the

past and call it groundbreaking.

- Evan Phoenix

Tuesday, February 8, 2011

Peek back

Tuesday, February 8, 2011

Tuesday, February 8, 2011

RLK

Tuesday, February 8, 2011

Implement with ease

RLK

Tuesday, February 8, 2011

KPeg

RLK

Tuesday, February 8, 2011

KPeg

A new parsing library

RLK

Tuesday, February 8, 2011

Prattle < RLK

Tuesday, February 8, 2011

github.com/evanphx/prattle.git

github.com/evanphx/kpeg.git

URLs

git://192.168.2.88/prattle

In the Building

In the Cloud

Tuesday, February 8, 2011

Tuesday, February 8, 2011

Dude. Really?

Tuesday, February 8, 2011

Prattle

Tuesday, February 8, 2011

selftruefalsenil

Tuesday, February 8, 2011

+module Prattle+ module AST+ class Self < AST::Node+ Prattle::Parser.register self++ def self.rule_name+ "self"+ end++ def initialize+ # Nothing.+ end++ def self.grammar(g)+ g.self = g.str("self") { Self.new }+ end+ end+ end+end

Tuesday, February 8, 2011

+module Prattle+ module AST+ class Self < AST::Node+ Prattle::Parser.register self++ def self.rule_name+ "self"+ end++ def initialize+ # Nothing.+ end++ def self.grammar(g)+ g.self = g.str("self") { Self.new }+ end+ end+ end+end

Tuesday, February 8, 2011

def self.grammar(g) g.self = g.str("self") { Self.new }end

047b522

Self

Tuesday, February 8, 2011

def self.grammar(g) g.true = g.str("true") { True.new }end

04ad51b

True

Tuesday, February 8, 2011

def self.grammar(g) g.false = g.str("false") { False.new }end

04ad51b

False

Tuesday, February 8, 2011

def self.grammar(g) g.nil = g.str("nil") { Nil.new }end

7609e64

Nil

Tuesday, February 8, 2011

01042

10323

Number

Tuesday, February 8, 2011

def self.grammar(g) g.number = g.reg(/0|([1-9][0-9]*)/) { |i| Number.new(i.to_i) }end

a06d98c

Number

Tuesday, February 8, 2011

def self.grammar(g) g.root = g.any(:true, :false, :self, :nil, :number) end

dfd78cb

Root

Tuesday, February 8, 2011

root = self | true | false | nil | number

Tuesday, February 8, 2011

REPL

Tuesday, February 8, 2011

Instant Gratification

REPL

Tuesday, February 8, 2011

$ rbx bin/repl.rb> 42#<Prattle::AST::Number:0x9c @value=42>> true#<Prattle::AST::True:0x9d>

Tuesday, February 8, 2011

def bytecode(g) g.push :selfend

4e4c1c9

Self

Tuesday, February 8, 2011

def bytecode(g) g.push :trueend

4e4c1c9

True

Tuesday, February 8, 2011

def bytecode(g) g.push :falseend

4e4c1c9

False

Tuesday, February 8, 2011

def bytecode(g) g.push :nilend

4e4c1c9

Nil

Tuesday, February 8, 2011

def bytecode(g) g.push @valueend

4e4c1c9

Number

Tuesday, February 8, 2011

def self.grammar(g) not_quote = g.many( g.any(escapes, /[^']/)) { |*a| a.join } g.string = g.seq("'", g.t(not_quote), "'") { |str| String.new(str) }end

String

Tuesday, February 8, 2011

char = escapes | [^’]not_quote = char* string = “‘“ not_quote “‘“

String

Tuesday, February 8, 2011

$ rbx bin/repl.rb> 42=> 42> true=> 42> ‘hello’=> “hello”

Tuesday, February 8, 2011

BORING

Tuesday, February 8, 2011

Unary Send

3 class

Tuesday, February 8, 2011

Unary Send

3.classRuby

Tuesday, February 8, 2011

Unary Send

3 class

Tuesday, February 8, 2011

Unary Send

3 class

Tuesday, February 8, 2011

g.seq(:number, “ “, :method_name) { |v,_,n| UnarySend.new(v,n) }

Unary Send

Tuesday, February 8, 2011

us = number “ “ method_name

Unary Send

Tuesday, February 8, 2011

Unary Send

true class

Tuesday, February 8, 2011

g.seq(:atom, “ “, :method_name) { |v,_,n| UnarySend.new(v,n) }

Unary Send

Tuesday, February 8, 2011

atom = true | false | self | nil | number | string

Tuesday, February 8, 2011

us = atom “ “ method_name

Unary Send

Tuesday, February 8, 2011

Unary Send

3 class class

Tuesday, February 8, 2011

g.any(g.seq(:unary_send, “ “, :method_name) { |v,_,n| UnarySend.new(v,n) },g.seq(:atom, “ “, :method_name) { |v,_,n| UnarySend.new(v,n) })

Unary Send

Tuesday, February 8, 2011

us = us “ “ method_name | atom “ “ method_name

Unary Send

Tuesday, February 8, 2011

def bytecode(g) @receiver.bytecode(g) g.send @method_name.to_sym, 0end

Unary Send

Tuesday, February 8, 2011

$ rbx bin/repl.rb> 3 class=> Fixnum> 3 class class=> Class> ‘hello’ class=> String

Tuesday, February 8, 2011

‘hello’ index: ‘o’

Keyword Send

Tuesday, February 8, 2011

“hello”.index(“o”)

Keyword Send

Ruby

Tuesday, February 8, 2011

g.keyword_send = g.seq(:atom, ‘ ‘, :method_name, “:”, “ “, :atom)

Keyword Send

Tuesday, February 8, 2011

ks = atom “ “ method_name “: ” :atom

Keyword Send

Tuesday, February 8, 2011

‘hello’ at: 0 put: ‘j’

Keyword Send

Tuesday, February 8, 2011

“hello”[0] = “j”

Keyword Send

Ruby

Tuesday, February 8, 2011

g.pairs = g.seq(:method_name, “:”, “ “, :atom)

Keyword Send

Tuesday, February 8, 2011

g.keyword_send = g.seq( :atom, ‘ ‘, g.many([:pair, ‘ ‘]), :pair )

Keyword Send

Tuesday, February 8, 2011

ks = atom (pair ‘ ‘)+ pair

Keyword Send

Tuesday, February 8, 2011

def bytecode(g) @receiver.bytecode(g) @arguments.each do |a| a.bytecode(a) end g.send @method_name.to_sym, @arguments.sizeend

Keyword Send

Tuesday, February 8, 2011

def bytecode(g) @receiver.bytecode(g) @arguments.each do |a| a.bytecode(a) end g.send @method_name.to_sym, @arguments.sizeend

Keyword Send

Tuesday, February 8, 2011

$ rbx bin/repl.rb> ‘hello’ index: ‘o’

NoMethodError: Unknown method ‘index:’

Tuesday, February 8, 2011

$ rbx bin/repl.rb> ‘hello’ index: ‘o’

NoMethodError: Unknown method ‘index:’

Tuesday, February 8, 2011

‘hello’ index: ‘o’

Keyword Send

Tuesday, February 8, 2011

“hello”.send( “index:”, “o” )

Keyword Send

Ruby

Tuesday, February 8, 2011

‘hello’ ~index: ‘o’

Keyword Send

Tuesday, February 8, 2011

def bytecode(g) if @method_name[0] == ?~ ruby_style else smalltalk_style endend

Keyword Send

Tuesday, February 8, 2011

“hello”.send( “index”, “o” )

Keyword Send

Ruby

Tuesday, February 8, 2011

$ rbx bin/repl.rb> ‘hello’ ~index: ‘o’=> 4NoMethodError: Unknown method ‘index:’

Tuesday, February 8, 2011

obj string at: 0 put: ‘j’

Keyword Send

Tuesday, February 8, 2011

obj string at: 0 put: ‘j’

Keyword Send

Tuesday, February 8, 2011

obj string at: 0 put: ‘j’

Keyword Send

Tuesday, February 8, 2011

g.keyword_send = g.seq( :atom, ‘ ‘, g.many([:pair, ‘ ‘]), :pair )

Keyword Send

Tuesday, February 8, 2011

g.keyword_send = g.seq( :atom, ‘ ‘, g.many([:pair, ‘ ‘]), :pair )

Keyword Send

Tuesday, February 8, 2011

ks = atom (pair ‘ ‘)+ pair

Keyword Send

Tuesday, February 8, 2011

g.any(:atom, :unary_send)

Keyword Send

Tuesday, February 8, 2011

recv = us | atom ks = recv (pair ‘ ‘)+ pair

Keyword Send

Tuesday, February 8, 2011

[ 1 ]Block

Tuesday, February 8, 2011

g.block = g.seq(‘[‘, :expr, ‘]’)

Keyword Send

Tuesday, February 8, 2011

expr = ks | us | atom

Keyword Send

Tuesday, February 8, 2011

block = “[“ expr “]

Keyword Send

Tuesday, February 8, 2011

[ 1. 2 ]Block

Tuesday, February 8, 2011

g.exprs = g.seq(:expr, g.kleene(‘.’, :expr))

Keyword Send

Tuesday, February 8, 2011

exprs = (‘.’ expr)*

Keyword Send

Tuesday, February 8, 2011

block = “[“ exprs “]

Keyword Send

Tuesday, February 8, 2011

$ rbx bin/repl.rb> 10 ~times: [ Kernel ~puts: ‘hello’ ]

Tuesday, February 8, 2011

$ rbx bin/repl.rb> 10 ~times: [ Kernel ~puts: ‘rb.la’ ]“rb.la”“rb.la”“rb.la”...=> 10

Tuesday, February 8, 2011

$ rbx bin/repl.rb> 10 ~times: [ :x | Kernel ~p: x ]

Tuesday, February 8, 2011

$ rbx bin/repl.rb> 10 ~times: [ :x | Kernel ~p: x ]012...=> 10

Tuesday, February 8, 2011

ary concat: a; concat: b; concat: c

Cascade Send

Tuesday, February 8, 2011

3 + 4 * 5

Operators

Tuesday, February 8, 2011

$ rbx bin/repl.rb> 3 + 4 * 5

Tuesday, February 8, 2011

$ rbx bin/repl.rb> 3 + 4 * 5=> 35

Tuesday, February 8, 2011

parens = “(“ expr “)

Parens

Tuesday, February 8, 2011

$ rbx bin/repl.rb> 3 + (4 * 5)=> 23

Tuesday, February 8, 2011

zero to usable

Tuesday, February 8, 2011

BIG IDEA

Tuesday, February 8, 2011

little idea

Tuesday, February 8, 2011

ComplexLanguage

Tuesday, February 8, 2011

simple language

Tuesday, February 8, 2011

See ya out there.

Thanks!

Tuesday, February 8, 2011

MIA: Return

Tuesday, February 8, 2011

MIA: =

Tuesday, February 8, 2011

Recommended