Date post: | 28-Jul-2015 |
Category: |
Software |
Upload: | phillip-trelford |
View: | 1,273 times |
Download: | 1 times |
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
PARSING OPTIONS (F#)
Hand rolled
•Regex•Active Patterns
FParsec
•Combinators•Monadic
FsLex, FsYacc
•Lexer•Parser
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))
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 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
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 __
QUESTIONS
Twitter: @ptrelford
Blog: http://trelford.com/blog
Turtle: http://fssnip.net/nN
Fun Basic: http://tinyurl.com/funbasic