Monday, December 19, 2011

F# ≥ C# (Meta Programming)

When C# first introduced the reflection, I was amazed by the idea writing or manipulating other programs. I can even read my own program to decide what to do next. This is something called meta programming. F# not only has reflection support but also provides more advanced meta programming technique: Quotations and ReflectedDefinition.

[ < ReflectedDefinition > ]
let myFunction a b c =
...

let myQuotation = < @@ myFunction @@ > 

the myQuotation quotation can be viewed as a parsing tree, from which C++ or SQL code can be generated.

The following code is a skeleton to traverse the quotation tree. You can insert your code in each active pattern. As for the debugging, quotation visualizer can be a good choice.

let rec iterate exp
match exp with
        | DerivedPatterns.Applications (e, ell) ->
            ()
        | DerivedPatterns.AndAlso (e0, e1) ->
            ()
        | DerivedPatterns.Bool e ->
            ()
        | DerivedPatterns.Byte e ->
            ()
        | DerivedPatterns.Char e ->
            ()
        | DerivedPatterns.Double e ->
            ()
        | DerivedPatterns.Int16 e->
            ()
        | DerivedPatterns.Int32 e->
            ()
        | DerivedPatterns.Int64 e ->
            ()
        | DerivedPatterns.OrElse (e0, e1)->
            ()
        | DerivedPatterns.SByte e ->
            ()
        | DerivedPatterns.Single e ->
            ()
        | DerivedPatterns.String e ->
            ()
        | DerivedPatterns.UInt16 e ->
            ()
        | DerivedPatterns.UInt32 e ->
            ()
        | DerivedPatterns.UInt64 e ->
            ()
        | DerivedPatterns.Unit e ->
            ()
        | Patterns.AddressOf address ->
            ()
        | Patterns.AddressSet (exp0, exp1) ->
            ()
        | Patterns.Application (exp0, exp1) ->
            ()
        | Patterns.Call (expOption, mi, expList)  ->
            ()
        | Patterns.Coerce (exp, t)->
            ()
        | Patterns.DefaultValue exp ->
            ()
        | Patterns.FieldGet (expOption, fi) ->
            ()
        | Patterns.FieldSet (expOption, fi, e) ->
            ()
        | Patterns.ForIntegerRangeLoop (v, e0, e1, e2) ->
            ()
        | Patterns.IfThenElse (con, exp0, exp1) ->
            ()
        | Patterns.Lambda (var,body) ->
            ()        
        | Patterns.Let (var, exp0, exp1) ->
            ()
        | Patterns.LetRecursive (tupList, exp) ->
            ()
        | Patterns.NewArray (t, expList) ->
            ()
        | Patterns.NewDelegate (t, varList, exp) ->
            ()
        | Patterns.NewObject (t, expList) ->
            ()
        | Patterns.NewRecord (t, expList) ->
            ()
        | Patterns.NewObject (t, expList) ->
            ()
        | Patterns.NewRecord (t, expList) ->
            ()
        | Patterns.NewTuple expList ->
            ()
        | Patterns.NewUnionCase (t, expList) ->
            ()
        | Patterns.PropertyGet (expOption, pi, expList) ->
            ()
        | Patterns.PropertySet (expOption, pi, expList, e) ->
            ()
        | Patterns.Quote e ->
            ()
        | Patterns.Sequential (e0, e1) ->
            ()
        | Patterns.TryFinally (e0, e1) ->
            ()
        | Patterns.TryWith (e0, v0, e1, v1, e2) ->
            ()
        | Patterns.TupleGet (e, i) ->
            ()
        | Patterns.TypeTest (e, t) ->
            ()
        | Patterns.UnionCaseTest (e, ui) ->
            ()
        | Patterns.Value (obj, t) ->
            ()
        | Patterns.Var v ->
            ()
        | Patterns.VarSet (v, e) ->
            ()
        | Patterns.WhileLoop (e0, e1) ->
            ()
        | _ -> failwith "not supported pattern"
Please note that the parsing tree needs some recursive function, so the iterate function is decorated "rec".


No comments: