+ All Categories
Home > Software > Build a compiler in 2hrs - NCrafts Paris 2015

Build a compiler in 2hrs - NCrafts Paris 2015

Date post: 28-Jul-2015
Category:
Upload: phillip-trelford
View: 1,273 times
Download: 1 times
Share this document with a friend
32
BUILD A COMPILER IN 2 HOURS Phil Trelford, @ptrelford #NCrafts Paris, 2015
Transcript

BUILD A COMPILER IN 2 HOURS

Phil Trelford, @ptrelford#NCrafts Paris, 2015

F#UNCTIONAL LONDONERS

Founded Feb 2010

950+ Members

Meets every 2 weeks

Topics include Machine Learning Finance Games Web

http://meetup.com/fsharplondon

INTERNAL DSLS - EXAMPLES

Fake

#r "tools/FAKE/tools/FakeLib.dll" open Fake

Target "Test" (fun _ -> trace "Testing stuff..." )

Target "Deploy" (fun _ -> trace "Heavy deploy action" )

"Test" // define the dependencies ==> "Deploy"

Run "Deploy"

Canopy

"starting a game of 2048" &&& fun _ ->

start firefox

url "http://gabrielecirulli.github.io/2048/"

let score = element ".score-container" printfn "Score %s" score.Text

while not(lost()) && not (won()) do press up press right press left press up

EXTERNAL DSLS IN ACTION

1. Domain-specific syntax

2. Proprietary encodings

3. Custom execution environments

BUILDING EXTERNAL DSLS Parse

Execute

PARSING OPTIONS (F#)

Hand rolled

•Regex•Active Patterns

FParsec

•Combinators•Monadic

FsLex, FsYacc

•Lexer•Parser

FPARSEC Phil Trelford, @ptrelford#NCrafts Paris, 2015

THINGS YOU SHOULD NEVER DO Custom Operators

Funny picture

FUNSCRIPT’S TYPESCRIPT PARSERFParsec

let interfaceDeclaration =

str_ws "interface" >>. identifier .>>. typeParams

.>>. interfaceExtendsClause .>>. objectType

|>> fun (((id, tps), ex), t) ->

InterfaceDeclaration(id, tps, ex, t)

TypeScript Definition

interface JQueryKeyEventObject

extends JQueryInputEventObject {

char: any;

charCode: number;

key: any;

keyCode: number;

}

FPARSEC TUTORIAL

open FParsec

let test p str = match run p str with | Success(result, _, _) -> printfn "Success: %A" result | Failure(errorMsg, _, _) -> printfn "Failure: %s" errorMsg

test pfloat "1.25"test pfloat "1.25E 2"

let str s = pstring slet floatBetweenBrackets = str "[" >>. pfloat .>> str "]"

test floatBetweenBrackets "[1.0]"test floatBetweenBrackets "[]"

PARSING OPERATORS

// we set up an operator precedence parser for parsing the arithmetic expressions

let opp = new OperatorPrecedenceParser<float,unit,unit>()

let expr = opp.ExpressionParser

opp.TermParser <- number <|> between (str_ws "(") (str_ws ")") expr

// operator definitions follow the schema

// operator type, string, trailing whitespace parser, precedence, associativity, function to apply

opp.AddOperator(InfixOperator("+", ws, 1, Associativity.Left, (+)))

opp.AddOperator(InfixOperator("-", ws, 1, Associativity.Left, (-)))

opp.AddOperator(InfixOperator("*", ws, 2, Associativity.Left, (*)))

opp.AddOperator(InfixOperator("/", ws, 2, Associativity.Left, (/)))

opp.AddOperator(InfixOperator("^", ws, 3, Associativity.Right, fun x y -> System.Math.Pow(x, y)))

opp.AddOperator(PrefixOperator("-", ws, 4, true, fun x -> -x))

TURTLES ALL THE WAY DOWN

Phil Trelford, @ptrelford#NCrafts Paris, 2015

TURTLE LANGUAGE

repeat 10

[right 36 repeat 5

[forward 54 right 72]]

TURTLE AST

module AST

type arg = int

type command =

| Forward of arg

| Turn of arg

| Repeat of arg * command list

TURTLE PARSER: FORWARD AND TURN open AST

open FParsec

let pforward =

pstring "forward" >>. spaces1 >>. pfloat

|>> fun x -> Forward(int x)

let pleft =

pstring "left" >>. spaces1 >>. pfloat

|>> fun x -> Turn(int -x)

let pright =

pstring "right" >>. spaces1 >>. pfloat

|>> fun x -> Turn(int x)

TURTLE PARSER: REPEAT COMMANDlet pcommand = pforward <|> pleft <|> pright

let block = between (pstring "[") (pstring "]") (many1 (pcommand .>> spaces))

let prepeat =

pstring "repeat" >>. spaces1 >>. pfloat .>> spaces .>>. block

|>> fun (n,commands) -> Repeat(int n, commands)

TURTLE PARSER: FORWARD REPEATlet prepeat, prepeatimpl = createParserForwardedToRef ()

let pcommand = pforward <|> pleft <|> pright <|> prepeat

let block = between (pstring "[") (pstring "]") (many1 (pcommand .>> spaces))

prepeatimpl :=

pstring "repeat" >>. spaces1 >>. pfloat .>> spaces .>>. block

|>> fun (n,commands) -> Repeat(int n, commands)

TURTLE INTERPRETER: PATTERN MATCHINGlet rec perform turtle = function | Forward n -> let r = float turtle.A * Math.PI / 180.0 let dx, dy = float n * cos r, float n * sin r let x, y = turtle.X, turtle.Y let x',y' = x + dx, y + dy drawLine (x,y) (x',y') { turtle with X = x'; Y = y' } | Turn n -> { turtle with A = turtle.A + n } | Repeat (n, commands) -> let rec repeat turtle = function | 0 -> turtle | n -> repeat (performAll turtle commands) (n-1) repeat turtle n and performAll = List.fold perform

TURTLE: PROCEDURES

to square

repeat 4 [forward 50 right 90]

end

to flower

repeat 36 [right 10 square]

end

to garden

repeat 25 [set-random-position flower]

end

garden

SMALL BASIC COMPILER

Phil Trelford, @ptrelford#NCrafts Paris, 2015

SMALL BASIC IDEFParsec Hands OnFunctional South Coast, 2015

SMALL BASIC SAMPLE

Sub Init

gw = 598

gh = 428

GraphicsWindow.BackgroundColor = "DodgerBlue"

GraphicsWindow.Width = gw

GraphicsWindow.Height = gh

color = "1=Orange;2=Cyan;3=Lime;"

size = "1=20;2=16;3=12;"

passed = 0

cd = "False" ' collision detected

EndSub

SMALL BASIC AST

/// Small Basic expressiontype expr = | Literal of value | Identifier of identifier | GetAt of location | Func of invoke | Neg of expr | Arithmetic of expr * arithmetic * expr | Comparison of expr * comparison * expr | Logical of expr * logical * expr

/// Small Basic instruction type instruction = | Assign of assign | SetAt of location * expr | PropertySet of string * string * expr

| Action of invoke | For of assign * expr * expr | EndFor | If of expr | ElseIf of expr | Else | EndIf | While of expr | EndWhile | Sub of identifier * string list | EndSub | Label of label | Goto of label

SMALL BASIC PARSER

/// > For i = 1 To 100 Step 2

let pfor =

let pfrom = str_ws1 "For" >>. pset

let pto = str_ws1 "To" >>. pexpr

let pstep = str_ws1 "Step" >>. pexpr

let toStep = function None -> Literal(Int(1)) | Some s -> s

pipe3 pfrom pto (opt pstep) (fun f t s -> For(f, t, toStep s))

let pendfor = str_ws "EndFor" |>> (fun _ -> EndFor)

SMALL BASIC COMPILER: GOTO| Goto(name) ->

let label = obtainLabel il name

il.Emit(OpCodes.Br, label)

| Label(name) ->

let label = obtainLabel il name

il.MarkLabel(label)

http://tinyurl.com/funbasic

FUN BASIC - WINDOWS STORE APP

RESOURCES Phil Trelford, @ptrelford#NCrafts Paris, 2015

F# KOANS

[<Koan>]let SquareEvenNumbersWithPipelineOperator() =(* In F#, you can use the pipeline operator to get the benefit of the parens style with the readability of the statement style. *)

let result = [0..5] |> List.filter isEven |> List.map square AssertEquality result __

TRYFSHARP.ORG

BUY THE BOOK

QUESTIONS

Twitter: @ptrelford

Blog: http://trelford.com/blog

Turtle: http://fssnip.net/nN

Fun Basic: http://tinyurl.com/funbasic


Recommended