4 people like it.

Hosting the DLR with IronPython or Ruby

Definition of the dynamic resolution operators for hosting the DLR. You can either use Ruby or Python, as the module isn't language specific.

  1: 
  2: 
  3: 
  4: 
  5: 
  6: 
  7: 
  8: 
  9: 
 10: 
 11: 
 12: 
 13: 
 14: 
 15: 
 16: 
 17: 
 18: 
 19: 
 20: 
 21: 
 22: 
 23: 
 24: 
 25: 
 26: 
 27: 
 28: 
 29: 
 30: 
 31: 
 32: 
 33: 
 34: 
 35: 
 36: 
 37: 
 38: 
 39: 
 40: 
 41: 
 42: 
 43: 
 44: 
 45: 
 46: 
 47: 
 48: 
 49: 
 50: 
 51: 
 52: 
 53: 
 54: 
 55: 
 56: 
 57: 
 58: 
 59: 
 60: 
 61: 
 62: 
 63: 
 64: 
 65: 
 66: 
 67: 
 68: 
 69: 
 70: 
 71: 
 72: 
 73: 
 74: 
 75: 
 76: 
 77: 
 78: 
 79: 
 80: 
 81: 
 82: 
 83: 
 84: 
 85: 
 86: 
 87: 
 88: 
 89: 
 90: 
 91: 
 92: 
 93: 
 94: 
 95: 
 96: 
 97: 
 98: 
 99: 
100: 
101: 
102: 
103: 
module FSharp
    module DlrHosting = 
        open System.Reflection
        open Microsoft.Scripting
        open Microsoft.FSharp.Reflection
        open Microsoft.Scripting.Hosting
       
        let mutable dlrEngine:ScriptEngine = null
                
        let (?) (instance : obj) member' : 'Result = 
            let resultType =  typeof<'Result>
            
            // did we get invoked as a callable member ?
            if FSharpType.IsFunction resultType then
                //the called member from the dlr type should really be a callable!
                let callable = dlrEngine.Operations.GetMember(instance, member')
                if not (dlrEngine.Operations.IsCallable(callable))
                    then failwithf "%s is not callable" member'
                
                let invokeWithNoArguments = fun _ -> [||]
                let invokeWithOneArgument = fun arg -> [|arg|]
                let invokeWithManyArguments = fun args -> FSharpValue.GetTupleFields(args) 
                
                let functionType, _ = FSharpType.GetFunctionElements(resultType)
                let determineArgsFromInvocation = 
                    match functionType with
                    | type' when type' = typeof<unit> -> invokeWithNoArguments
                    | type' when FSharpType.IsTuple type' -> invokeWithManyArguments
                    | _ -> invokeWithOneArgument
                               
                downcast FSharpValue.MakeFunction(resultType, fun argsFromInvocation -> 
                    dlrEngine.Operations.Invoke(callable, determineArgsFromInvocation(argsFromInvocation) ) ) 
            else
                downcast dlrEngine.Operations.GetMember(instance, member')
        
        let (?<-) (instance : obj) member' value = 
            dlrEngine.Operations.SetMember(instance, member', value)

        let createScriptSource (scriptText:string) = 
            dlrEngine.CreateScriptSourceFromString(scriptText, SourceCodeKind.AutoDetect)

        let executeScriptSource (source:ScriptSource) (scope:ScriptScope) = 
            source.Execute(scope)

        let (|>>) (scope : ScriptScope) codeString = 
            let source = createScriptSource(codeString)
            executeScriptSource source scope |> ignore
            scope

        let (|>?) (scope : ScriptScope) codeString = 
            let source = createScriptSource(codeString)
            executeScriptSource source scope


//Example:  I've used the template engine Jinja2 for rendering
// HTML for demonstrating interop.
open System.Collections.Generic
open System
open System.IO

open Microsoft.FSharp.Core
open FSharp.DlrHosting
open IronPython.Hosting


dlrEngine <- Python.CreateEngine()

let sitePackages = Path.Combine( Environment.CurrentDirectory, "Lib", "site-packages")
let sys = dlrEngine.GetSysModule()
sys?path?append(sitePackages)

let convertFunc f =
    FSharpFunc.ToConverter f

let pymodule = createScope() |>> @"
from jinja2 import FileSystemLoader, DictLoader, FunctionLoader
from jinja2 import Environment
import os

def render( data_context, templateLoader, template_name ):
    env = Environment(loader=templateLoader)
    print templateLoader
    template = env.get_template(template_name)        
    return template.render( data_context )     
"

let loadTemplate name = 
   match name with 
    | "result.tmpl" -> "<html><body>{{ greeting }}</body></html>"
    | _ -> "" 

let templateLoader = pymodule?FunctionLoader(convertFunc loadTemplate) |> box

let data = new Dictionary<obj,obj>()
data.["greeting"] <- "hello python from fsharp"

let rendered:string = pymodule?render(data, templateLoader, "result.tmpl") 

printfn "%s" rendered
pymodule |>> "test = 2+2" |> ignore
printfn "%i" pymodule?test |> unbox
printfn "%i" (pymodule |>? "3+4" |> unbox)
        
Multiple items
module FSharp

--------------------
namespace Microsoft.FSharp
module DlrHosting

from FSharp
namespace System
namespace System.Reflection
namespace Microsoft
namespace Microsoft.FSharp
namespace Microsoft.FSharp.Reflection
val mutable dlrEngine : obj

Full name: FSharp.DlrHosting.dlrEngine
val instance : obj
type obj = System.Object

Full name: Microsoft.FSharp.Core.obj
val member' : string
val resultType : System.Type
val typeof<'T> : System.Type

Full name: Microsoft.FSharp.Core.Operators.typeof
type FSharpType =
  static member GetExceptionFields : exceptionType:Type * ?bindingFlags:BindingFlags -> PropertyInfo []
  static member GetFunctionElements : functionType:Type -> Type * Type
  static member GetRecordFields : recordType:Type * ?bindingFlags:BindingFlags -> PropertyInfo []
  static member GetTupleElements : tupleType:Type -> Type []
  static member GetUnionCases : unionType:Type * ?bindingFlags:BindingFlags -> UnionCaseInfo []
  static member IsExceptionRepresentation : exceptionType:Type * ?bindingFlags:BindingFlags -> bool
  static member IsFunction : typ:Type -> bool
  static member IsModule : typ:Type -> bool
  static member IsRecord : typ:Type * ?bindingFlags:BindingFlags -> bool
  static member IsTuple : typ:Type -> bool
  ...

Full name: Microsoft.FSharp.Reflection.FSharpType
static member FSharpType.IsFunction : typ:System.Type -> bool
val callable : obj
val not : value:bool -> bool

Full name: Microsoft.FSharp.Core.Operators.not
val failwithf : format:Printf.StringFormat<'T,'Result> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.failwithf
val invokeWithNoArguments : ('a -> 'b [])
val invokeWithOneArgument : ('a -> 'a [])
val arg : 'a
val invokeWithManyArguments : ('a -> obj [])
val args : 'a
type FSharpValue =
  static member GetExceptionFields : exn:obj * ?bindingFlags:BindingFlags -> obj []
  static member GetRecordField : record:obj * info:PropertyInfo -> obj
  static member GetRecordFields : record:obj * ?bindingFlags:BindingFlags -> obj []
  static member GetTupleField : tuple:obj * index:int -> obj
  static member GetTupleFields : tuple:obj -> obj []
  static member GetUnionFields : value:obj * unionType:Type * ?bindingFlags:BindingFlags -> UnionCaseInfo * obj []
  static member MakeFunction : functionType:Type * implementation:(obj -> obj) -> obj
  static member MakeRecord : recordType:Type * values:obj [] * ?bindingFlags:BindingFlags -> obj
  static member MakeTuple : tupleElements:obj [] * tupleType:Type -> obj
  static member MakeUnion : unionCase:UnionCaseInfo * args:obj [] * ?bindingFlags:BindingFlags -> obj
  ...

Full name: Microsoft.FSharp.Reflection.FSharpValue
static member FSharpValue.GetTupleFields : tuple:obj -> obj []
val functionType : System.Type
static member FSharpType.GetFunctionElements : functionType:System.Type -> System.Type * System.Type
val determineArgsFromInvocation : (obj -> obj [])
val type' : System.Type
type unit = Unit

Full name: Microsoft.FSharp.Core.unit
static member FSharpType.IsTuple : typ:System.Type -> bool
static member FSharpValue.MakeFunction : functionType:System.Type * implementation:(obj -> obj) -> obj
val argsFromInvocation : obj
val member' : 'a
val value : 'b
val createScriptSource : scriptText:string -> 'a

Full name: FSharp.DlrHosting.createScriptSource
val scriptText : string
Multiple items
val string : value:'T -> string

Full name: Microsoft.FSharp.Core.Operators.string

--------------------
type string = System.String

Full name: Microsoft.FSharp.Core.string
val executeScriptSource : source:'a -> scope:'b -> 'c

Full name: FSharp.DlrHosting.executeScriptSource
val source : 'a
val scope : 'b
val scope : 'a
val codeString : string
val source : obj
val ignore : value:'T -> unit

Full name: Microsoft.FSharp.Core.Operators.ignore
namespace System.Collections
namespace System.Collections.Generic
namespace System.IO
namespace Microsoft.FSharp.Core
new : unit -> FSharpFunc<'T,'U>
static member FSharpFunc.ToConverter : func:('T -> 'U) -> System.Converter<'T,'U>
val box : value:'T -> obj

Full name: Microsoft.FSharp.Core.Operators.box
val printfn : format:Printf.TextWriterFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn
val unbox : value:obj -> 'T

Full name: Microsoft.FSharp.Core.Operators.unbox

More information

Link:http://fssnip.net/3O
Posted:12 years ago
Author:Rainer Schuster
Tags: dlr , ironpython , ironruby , dynamic