4 people like it.
Like the snippet!
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