OpenChain AI Study Group - Europe and Asia Recap - 2024-04-11 - Full Recording
Build a compiler in 2hrs - NCrafts Paris 2015
1. BUILD A COMPILER IN 2
HOURS
Phil Trelford, @ptrelford
#NCrafts Paris, 2015
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.
4. 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
11. 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 "[]"
12. 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))
13. TURTLES ALL THE WAY
DOWN
Phil Trelford, @ptrelford
#NCrafts Paris, 2015
15. TURTLE AST
module AST
type arg = int
type command =
| Forward of arg
| Turn of arg
| Repeat of arg * command list
16. 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)
17. 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)
18. 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)
19. 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
20. 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
23. 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
24. 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
25. 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)
26. 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)
29. 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 __