Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Build a compiler in 2hrs - NCrafts Paris 2015

Hands on: Write Your Own Compiler at NCrafts conference n Paris

  • Login to see the comments

Build a compiler in 2hrs - NCrafts Paris 2015

  1. 1. BUILD A COMPILER IN 2 HOURS Phil Trelford, @ptrelford #NCrafts Paris, 2015
  2. 2. F#UNCTIONAL LONDONERS Founded Feb 2010 950+ Members Meets every 2 weeks Topics include  Machine Learning  Finance  Games  Web http://meetup.com/fsharplondon
  3. 3. 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
  4. 4. EXTERNAL DSLS IN ACTION 1. Domain-specific syntax 2. Proprietary encodings 3. Custom execution environments
  5. 5. BUILDING EXTERNAL DSLS Abstract Syntax Tree (AST) Parse Execute
  6. 6. PARSING OPTIONS (F#) Hand rolled •Regex •Active Patterns FParsec •Combinators •Monadic FsLex, FsYacc •Lexer •Parser
  7. 7. FPARSEC Phil Trelford, @ptrelford #NCrafts Paris, 2015
  8. 8. THINGS YOU SHOULD NEVER DO Custom Operators Funny picture
  9. 9. FUNSCRIPT’S TYPESCRIPT PARSER FParsec 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; }
  10. 10. 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 s let floatBetweenBrackets = str "[" >>. pfloat .>> str "]" test floatBetweenBrackets "[1.0]" test floatBetweenBrackets "[]"
  11. 11. 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))
  12. 12. TURTLES ALL THE WAY DOWN Phil Trelford, @ptrelford #NCrafts Paris, 2015
  13. 13. TURTLE LANGUAGE repeat 10 [right 36 repeat 5 [forward 54 right 72]]
  14. 14. TURTLE AST module AST type arg = int type command = | Forward of arg | Turn of arg | Repeat of arg * command list
  15. 15. 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)
  16. 16. TURTLE PARSER: REPEAT COMMAND let 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)
  17. 17. TURTLE PARSER: FORWARD REPEAT let 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)
  18. 18. TURTLE INTERPRETER: PATTERN MATCHING let 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
  19. 19. 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
  20. 20. SMALL BASIC COMPILER Phil Trelford, @ptrelford #NCrafts Paris, 2015
  21. 21. SMALL BASIC IDE FParsec Hands On Functional South Coast, 2015
  22. 22. 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
  23. 23. SMALL BASIC AST /// Small Basic expression type 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
  24. 24. 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)
  25. 25. 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)
  26. 26. http://tinyurl.com/funbasi c FUN BASIC - WINDOWS STORE APP
  27. 27. RESOURCES Phil Trelford, @ptrelford #NCrafts Paris, 2015
  28. 28. 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 __
  29. 29. TRYFSHARP.ORG
  30. 30. BUY THE BOOK
  31. 31. QUESTIONS Twitter: @ptrelford Blog: http://trelford.com/blog Turtle: http://fssnip.net/nN Fun Basic: http://tinyurl.com/funbasic

×