You can use existing .NET API
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
open System type TrialLib = static member SinCos(input : float, scale: float, sinus : byref<int>, cosinus : byref<int>) = sinus <- Convert.ToInt32(Math.Sin(input) * scale) cosinus <- Convert.ToInt32(Math.Cos(input) * scale) let sinCosMethod = typeof<TrialLib>.GetMethod("SinCos") let makeFunction<'T when 'T :> Delegate> methodInfo = Delegate.CreateDelegate(typeof<'T>, methodInfo) :?> 'T type SinCos = delegate of float*float*byref<int>*byref<int> -> unit let f = (makeFunction<SinCos> sinCosMethod).Invoke let sinus = ref 0 let cosinus = ref 0 f(0.0, 100.0, sinus, cosinus)
the real big picture is that i want to implement a compiler for a statical typed graphical dataflow language.
all static functions in a referenced assembly would result in a node. nodes can be dropped on a canvas and can be connected.
the compiler should generate either f# code or alternatively f# quotations or maybe Linq Expression Trees. ([link:msdn.microsoft.com]
for now i go for quotations and build them programmatically over the Expr module while traversing the node graph. at the end i have an expression tree which i can evaluate.
however quotations have some unpredictable limitations which are not very good documented. e.g. i can't quote a function with byref parameters.
1 2 3 4 5
type TrialLib = static member SinCos(input : float, scale: float, sinus : byref<int>, cosinus : byref<int>) = sinus <- Convert.ToInt32(Math.Sin(input) * scale) cosinus <- Convert.ToInt32(Math.Cos(input) * scale) <@ TrialLib.SinCos @>;;
fails: error FS0462: Quotations cannot contain this kind of type
however
1 2 3 4
type TrialLib = static member SinCos2(input : float, scale: float) = Convert.ToInt32(Math.Sin(input) * scale), Convert.ToInt32(Math.Cos(input) * scale) <@ TrialLib.SinCos2 @>;;
works:
1 2 3 4 5 6 7
val it : Quotations.Expr<(float * float -> int * int)> = Lambda (tupledArg, Let (arg00, TupleGet (tupledArg, 0), Let (arg01, TupleGet (tupledArg, 1), Call (None, System.Tuple`2[System.Int32,System.Int32] SinCos2(Double, Double), [arg00, arg01]))))
and anyway i want to get rid of byref parameters and only allow (tupled) return values.
in order to achieve that, i would need to generate a function value without byref params which i can then convert to an expression with Expr.Value.
so the question would be how to generate the function value by analyzing the method info. i could use FSharpValue.MakeFunction. however i would need to generate the function body:
1 2 3 4 5
let sincos x1 y1 = let refx2 = ref 0 let refy2 = ref 0 TrialLibCSharp.SinCos(x1, y1, refx2, refy2) (!refx2, !refy2)
note that i cannot know the signature of a function at compile time and the code above is only a snapshot of what should be generated programmatically either by FSharpValue.MakeFunction, some call of a f# compiler service or some tricky delegate technique like desco proposed.
so since i want to build a sort of compiler i need function objects or expressions which i compose first and evaluate later. if i would want to build an interpreter i probably could just call invoke at a proper place.
please feel invited to comment the big picture. should i skip the quotations and try to get into the fsi source code (note: could be very hard) or should i skip the whole compiler idea and write and interpreter which traverses the graph in each evaluation step?
thanks for your votes!
sebastian
If you don't have any limitations on framework version, then you can use extended version of Expression Trees from .NET 4.0.
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
public static class FunctionUtils { private static readonly Type[] TupleTypes = new[] { typeof(Tuple<>), typeof(Tuple<,>), typeof(Tuple<,,>), typeof(Tuple<,,,>), typeof(Tuple<,,,,>), typeof(Tuple<,,,,,>), typeof(Tuple<,,,,,,>), }; public static Delegate MakeFunction(MethodInfo methodInfo) { var functionType = GetFunctionType(methodInfo); var parameters = GetParameters(methodInfo).Select(Expression.Parameter).ToArray(); var locals = GetByRefParams(methodInfo).Select(Expression.Variable).ToArray(); var block = Expression.Block( locals, Expression.Call(null, methodInfo, parameters.Concat(locals)), Expression.New(functionType.Item2.GetConstructor(functionType.Item2.GetGenericArguments()), locals) ); var lambda = Expression.Lambda( Expression.GetFuncType(functionType.Item1.Concat(new[] {functionType.Item2}).ToArray()), block, parameters ); return lambda.Compile(); } public static Tuple<Type[], Type> GetFunctionType(MethodInfo methodInfo) { var parameters = GetParameters(methodInfo); var byRefParams = GetByRefParams(methodInfo); return Tuple.Create(parameters, TupleTypes[byRefParams.Length - 1].MakeGenericType(byRefParams)); } private static Type[] GetParameters(MethodInfo methodInfo) { return methodInfo.GetParameters() .TakeWhile(p => !p.ParameterType.IsByRef) .Select(p => p.ParameterType) .ToArray(); } private static Type[] GetByRefParams(MethodInfo methodInfo) { return methodInfo.GetParameters() .SkipWhile(p => !p.ParameterType.IsByRef) .Select(p => p.ParameterType.GetElementType()) .ToArray(); } } public static class TrialLibCSharp { //testing out params public static void SinCos(int input, int scale, out int sinus, out int cosinus) { sinus = Convert.ToInt32(Math.Sin(input) * scale); cosinus = Convert.ToInt32(Math.Cos(input) * scale); } } var method = typeof (TrialLibCSharp).GetMethod("SinCos"); var compiled = FunctionUtils.MakeFunction(method); Console.WriteLine(compiled.DynamicInvoke(0, 100)); // (0, 100)
hi !
desco, thank you very much for your help!
i didn't dig very much into it, but don't want to miss mono compatibility. so i am not so sure about .Net 4.0...
but concerning this little topic with the out or ref params: it gets really nasty when you try to do that without extended version of Expression Trees. so is the only way to solve that specific problem?
What i tried is to call invoke with byref params. But there seems to be no way to create mutable reference cells and pass them to Invoke. I tried to get a byref<'a>[] as a obj[] into invoke. I also didn't succeed in generating instances holding default values for primitive types like int...
1 2 3 4 5 6 7 8 9
let byrefs = Array.map (fun (t:Type) -> ref (0:>obj)) byreftypes let contents = Array.map (fun (ref:'a ref) -> box(&ref.contents)) byrefs let returnvalue = m.Invoke( null, Array.append (Array.append otherinputs [|last|]) contents ) let returnelements = GetReturnElements returnvalue let outputelements = Array.append returnelements byrefelements if outputelements.Length > 1 then FSharpValue.MakeTuple(outputelements, outputtype) else outputelements.[0]
however:
Error 5 A type instantiation involves a byref type. This is not permitted by the rules of Common IL.
so everything i tried didn't help or just didn't compile.
then i looked again at your delegate technique and wondered if this is the key to solve the problem. however i can't see how to generate a delegate type. There is a TypeBuilder in Reflection.Emit, but i don't know. The docs of MulticastDelegate also say that you can't inherit from that type (only compilers can do that?!). Oh well.
So far my research about the idea of creating a function value before (being able of) quoting it.
I just wonder why creating fsharp code on a lexical level is so easy (you need a text editor) and creating fsharp code on a META or AST level is so hard. Maybe i should just go and generate strings (f# source code)...
does somebody know will quotations get richer in future releases of f#?
any other ideas?
thanks,
sebastian
byref types cannot be used as an arguments of type instantiations (according to ECMA 335, 9.4 - Instantiating generic types). However in your case you need to unwrap byref type (obtained from the ParameterInfo) into ordinary type.
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
open System open System.Reflection open Microsoft.FSharp.Reflection type TrialTest() = static member SinCos(a : float, b : float, c : byref<int>, d : byref<int>) = c <- int <| Math.Sin(a) * b d <- int <| Math.Cos(a) * b let sinCosMethod = typeof<TrialTest>.GetMethod("SinCos") let invoke (args : obj[]) (methodInfo : MethodInfo)= let outParamTypes = methodInfo.GetParameters() |> Seq.filter(fun p -> p.ParameterType.IsByRef) |> Seq.map(fun p -> p.ParameterType.GetElementType()) |> Seq.toArray let argList = Array.append args (Array.zeroCreate outParamTypes.Length) methodInfo.Invoke(null, argList) |> ignore let resultType = FSharpType.MakeTupleType(outParamTypes) let resultValues = Array.sub argList args.Length outParamTypes.Length FSharpValue.MakeTuple(resultValues, resultType) let result = invoke [|box 0.0; box 100.0|] sinCosMethod printfn "%A" result // (0, 100)
Also you can use types from System.Reflection.Emit to generate wrapper
that will convert Method(args..., byref output args...) : unit into
Method(args) : Tuple<output args> and use it through delegate. Also functionality of ExpressionTree V2 can be found in DLR ([link:dlr.codeplex.com])
desco,
thank you very much!
you helped a lot!
Well if your methods have all the same signature, you can define an F# wrapper (untested pseudocode):
1 2 3 4 5
let methodInfo = ... let myFun (arg1 : type1) (arg2 : type2) = methodInfo.Invoke(arg1, arg2) :> returnType
and myFun is your function object.
If you want to be generic (any method signature)... well I don't think that can be done 'statically' because F#'s type checking would get thrown out of the window.
The signature for function objects is created at compile time, and you don't know the method signature at that time.
It'd be interesting to know what you are trying to do (bigger picture). Do you need a function object? Or can you just pass the method info around and invoke it dynamically when u need the result?
Topic tags
- f# × 3705
- websharper × 1897
- compiler × 286
- functional × 201
- ui next × 139
- c# × 121
- classes × 97
- web × 97
- .net × 84
- book × 84
- async × 76
- ui.next × 67
- bug × 54
- core × 49
- website × 49
- server × 45
- parallel × 43
- ui × 43
- enhancement × 41
- parsing × 41
- testing × 41
- trywebsharper × 41
- typescript × 37
- html × 35
- javascript × 35
- owin × 35
- asynchronous × 30
- monad × 28
- ocaml × 28
- tutorial × 27
- warp × 27
- haskell × 26
- sitelet × 25
- linq × 22
- workflows × 22
- wpf × 20
- fpish × 19
- introduction × 19
- silverlight × 19
- sitelets × 19
- monodevelop × 17
- rpc × 17
- suave × 17
- piglets × 16
- collections × 15
- feature request × 15
- jquery × 15
- templates × 15
- getting started × 14
- pipeline × 14
- kendoui × 13
- reactive × 12
- 4.1.0.171 × 11
- monads × 11
- opinion × 10
- 4.0.190.100-rc × 9
- deployment × 9
- fixed × 9
- formlets × 9
- in × 9
- json × 9
- plugin × 9
- proposal × 9
- scheme × 9
- solid × 9
- basics × 8
- concurrent × 8
- highcharts × 8
- how-to × 8
- python × 8
- 4.1.1.175 × 7
- complexity × 7
- documentation × 7
- visual studio × 7
- 4.1.2.178 × 6
- lisp × 6
- real-world × 6
- released in 4.0.192.103-rc × 6
- remoting × 6
- resources × 6
- scala × 6
- websharper ui.next × 6
- workshop × 6
- xaml × 6
- 4.0.193.110 × 5
- 4.2.3.236 × 5
- aspnetmvc × 5
- authentication × 5
- azure × 5
- bootstrap × 5
- conference × 5
- dsl × 5
- formlet × 5
- java × 5
- list × 5
- metaprogramming × 5
- ml × 5
- released in Zafir.4.0.188.91-beta10 × 5
- sql × 5
- visualstudio × 5
- websharper.forms × 5
- zafir × 5
- 4.0.192.106 × 4
- 4.0.195.127 × 4
- 4.1.0.38 × 4
- 4.2.1.86 × 4
- 4.2.6.118 × 4
- css × 4
- example × 4
- extensions × 4
- fsi × 4
- fsx × 4
- html5 × 4
- jqueryui × 4
- lift × 4
- reflection × 4
- remote × 4
- rest × 4
- spa × 4
- teaching × 4
- template × 4
- websocket × 4
- wontfix × 4
- 4.0.196.147 × 3
- 4.1.0.34 × 3
- 4.1.6.207 × 3
- 4.2.1.223-beta × 3
- 4.2.11.258 × 3
- 4.2.4.114 × 3
- 4.2.4.247 × 3
- 4.2.5.115 × 3
- 4.2.6.253 × 3
- 4.2.9.256 × 3
- ajax × 3
- alt.net × 3
- aml × 3
- asp.net mvc × 3
- canvas × 3
- cloudsharper × 3
- compilation × 3
- database × 3
- erlang × 3
- events × 3
- extension × 3
- file upload × 3
- forums × 3
- inline × 3
- issue × 3
- kendo × 3
- macro × 3
- mono × 3
- msbuild × 3
- mvc × 3
- pattern × 3
- piglet × 3
- released in Zafir.4.0.187.90-beta10 × 3
- svg × 3
- type provider × 3
- view × 3
- 4.1.1.64 × 2
- 4.1.5.203 × 2
- 4.1.7.232 × 2
- 4.2.10.257 × 2
- 4.2.3.111 × 2
- 4.2.5.249 × 2
- android × 2
- asp.net × 2
- beginner × 2
- blog × 2
- chart × 2
- client × 2
- client server app × 2
- clojure × 2
- computation expressions × 2
- constructor × 2
- corporate × 2
- courses × 2
- cufp × 2
- d3 × 2
- debugging × 2
- direct × 2
- discriminated union × 2
- docs × 2
- elm × 2
- endpoint × 2
- endpoints × 2
- enterprise × 2
- entity framework × 2
- event × 2
- f# interactive × 2
- fable × 2
- flowlet × 2
- formdata × 2
- forms × 2
- fsc × 2
- google maps × 2
- hosting × 2
- http × 2
- https × 2
- iis 8.0 × 2
- install × 2
- interactive × 2
- interface × 2
- iphone × 2
- iteratee × 2
- jobs × 2
- jquery mobile × 2
- keynote × 2
- lens × 2
- lenses × 2
- linux × 2
- listmodel × 2
- mac × 2
- numeric × 2
- oauth × 2
- obfuscation × 2
- offline × 2
- oop × 2
- osx × 2
- packaging × 2
- pattern matching × 2
- performance × 2
- pipelines × 2
- q&a × 2
- quotation × 2
- reference × 2
- released in Zafir.4.0.185.88-beta10 × 2
- rx × 2
- script × 2
- security × 2
- self host × 2
- seq × 2
- sockets × 2
- stm × 2
- tcp × 2
- trie × 2
- tutorials × 2
- type × 2
- url × 2
- var × 2
- websharper.charting × 2
- websharper4 × 2
- websockets × 2
- wig × 2
- xna × 2
- zh × 2
- .net interop × 1
- 2012 × 1
- 4.0.194.126 × 1
- 4.1.3.184 × 1
- 4.1.4.189 × 1
- 4.2.0.214-beta × 1
- 4.2.12.259 × 1
- 4.2.2.231-beta × 1
- 4.2.8.255 × 1
- Canvas Sample Example × 1
- DynamicStyle Animated Style × 1
- Fixed in 4.0.190.100-rc × 1
- Released in Zafir.UI.Next.4.0.169.79-beta10 × 1
- SvgDynamicAttribute × 1
- WebComponent × 1
- abstract class × 1
- accumulator × 1
- active pattern × 1
- actor × 1
- addin × 1
- agents × 1
- aggregation × 1
- agile × 1
- alter session × 1
- animation × 1
- anonymous object × 1
- apache × 1
- api × 1
- appcelerator × 1
- architecture × 1
- array × 1
- arrays × 1
- asp.net 4.5 × 1
- asp.net core × 1
- asp.net integration × 1
- asp.net mvc 4 × 1
- asp.net web api × 1
- aspnet × 1
- ast × 1
- attributes × 1
- authorization × 1
- b-tree × 1
- back button × 1
- badimageformatexception × 1
- bash script × 1
- batching × 1
- binding-vars × 1
- bistro × 1
- body × 1
- bundle × 1
- camtasia studio × 1
- cas protocol × 1
- charts × 1
- clarity × 1
- class × 1
- cli × 1
- clipboard × 1
- clojurescript × 1
- closures × 1
- cloud × 1
- cms × 1
- coding diacritics × 1
- color highlighting × 1
- color zones × 1
- combinator × 1
- combinators × 1
- compile × 1
- compile code on server × 1
- config × 1
- confirm × 1
- content × 1
- context × 1
- context.usersession × 1
- continuation-passing style × 1
- coords × 1
- cordova × 1
- cors × 1
- coursera × 1
- cross-domain × 1
- csla × 1
- current_schema × 1
- custom content × 1
- data × 1
- data grid × 1
- datetime × 1
- debug × 1
- declarative × 1
- delete × 1
- devexpress × 1
- dhtmlx × 1
- dictionary × 1
- directattribute × 1
- disqus × 1
- distance × 1
- do binding × 1
- doc elt ui.next upgrade × 1
- docker × 1
- dojo × 1
- dol × 1
- dom × 1
- domain × 1
- du × 1
- duf-101 × 1
- dynamic × 1
- eastern language × 1
- eclipse × 1
- edsl × 1
- em algorithm × 1
- emacs × 1
- emotion × 1
- enums × 1
- error × 1
- etw × 1
- euclidean × 1
- eventhandlerlist × 1
- examples × 1
- ext js × 1
- extension methods × 1
- extra × 1
- facet pattern × 1
- failed to translate × 1
- fake × 1
- fantomas × 1
- fear × 1
- float × 1
- form × 1
- form-data × 1
- forum × 1
- fp × 1
- frank × 1
- fsdoc × 1
- fsharp × 1
- fsharp.core × 1
- fsharp.powerpack × 1
- fsharpx × 1
- fsunit × 1
- function × 1
- functional style × 1
- game × 1
- games × 1
- gc × 1
- generic × 1
- geometry × 1
- getlastwin32error × 1
- getting-started × 1
- google × 1
- google.maps × 1
- grid × 1
- group × 1
- guide × 1
- hash × 1
- headers × 1
- hello world example × 1
- heroku × 1
- highchart × 1
- history × 1
- how to × 1
- html-templating × 1
- http405 × 1
- httpcontext × 1
- hubfs × 1
- i18n × 1
- ie 8 × 1
- if-doc × 1
- iis × 1
- image × 1
- images × 1
- inheritance × 1
- initialize × 1
- input × 1
- install "visual studio" × 1
- installer × 1
- int64 × 1
- interfaces × 1
- internet explorer × 1
- interop × 1
- interpreter × 1
- io × 1
- iobservable × 1
- ios × 1
- iot × 1
- ipad × 1
- isomorphic × 1
- javascript optimization × 1
- javascript semanticui resources × 1
- jquery-plugin × 1
- jquery-ui × 1
- jquery-ui-datepicker × 1
- js × 1
- kendo datasource × 1
- kendochart × 1
- kendoui compiler × 1
- knockout × 1
- l10n × 1
- learning × 1
- library × 1
- libs × 1
- license × 1
- licensing × 1
- lineserieszonescfg × 1
- local setting × 1
- localization × 1
- logging × 1
- loop × 1
- macros × 1
- mailboxprocessor × 1
- mapping × 1
- maps × 1
- markerclusterer × 1
- markup × 1
- marshal × 1
- math × 1
- mathjax × 1
- message × 1
- message passing × 1
- message-passing × 1
- meta × 1
- metro style × 1
- micro orm × 1
- minimum-requirements × 1
- mix × 1
- mobile installation × 1
- mod_mono × 1
- modal × 1
- module × 1
- mouseevent × 1
- mouseposition × 1
- multidimensional × 1
- multiline × 1
- multithreading × 1
- mysql × 1
- mysqlclient × 1
- nancy × 1
- native × 1
- nested × 1
- nested loops × 1
- node × 1
- nunit × 1
- object relation mapper × 1
- object-oriented × 1
- om × 1
- onboarding × 1
- onclick × 1
- optimization × 1
- option × 1
- orm × 1
- os x × 1
- output-path × 1
- override × 1
- paper × 1
- parameter × 1
- persistence × 1
- persistent data structure × 1
- phonegap × 1
- pola × 1
- post × 1
- powerpack × 1
- prefix tree × 1
- principle of least authority × 1
- privacy × 1
- private × 1
- profile × 1
- programming × 1
- project × 1
- project euler × 1
- projekt_feladat × 1
- protected × 1
- provider × 1
- proxy × 1
- ptvs × 1
- public × 1
- pure f# × 1
- purescript × 1
- qna × 1
- quant × 1
- query sitelet × 1
- question × 1
- quotations × 1
- range × 1
- raphael × 1
- razor × 1
- rc × 1
- reactjs × 1
- real-time × 1
- ref × 1
- region × 1
- released in 4.0.190.100-rc × 1
- reporting × 1
- responsive design × 1
- rest api × 1
- rest sitelet × 1
- restful × 1
- round table × 1
- router × 1
- routing × 1
- rpc reverseproxy × 1
- runtime × 1
- sales × 1
- sample × 1
- sampleapp × 1
- scriptcs × 1
- scripting × 1
- search × 1
- self hosted × 1
- semanticui × 1
- sequence × 1
- serialisation × 1
- service × 1
- session-state × 1
- sharepoint × 1
- signals × 1
- sitelet website × 1
- sitelet.protect × 1
- sitlets × 1
- slickgrid × 1
- source code × 1
- sqlentityconnection × 1
- ssl × 1
- standards × 1
- static content × 1
- stickynotes × 1
- streamreader × 1
- stress × 1
- strong name × 1
- structures × 1
- submitbutton × 1
- subscribe × 1
- svg example html5 websharper.ui.next × 1
- sweetalert × 1
- system.datetime × 1
- system.reflection.targetinvocationexception × 1
- table storage × 1
- targets × 1
- tdd × 1
- templates ui.next × 1
- templating × 1
- text parsing × 1
- three.js × 1
- time travel × 1
- tls × 1
- tooltip × 1
- tracing × 1
- tsunamiide × 1
- turkish × 1
- twitter-bootstrap × 1
- type erasure × 1
- type inference × 1
- type providers × 1
- type-providers × 1
- typeprovider × 1
- ui next forms × 1
- ui-next × 1
- ui.next jqueryui × 1
- ui.next charting × 1
- ui.next formlets × 1
- ui.next forms × 1
- ui.next suave visualstudio × 1
- ui.next templating × 1
- unicode × 1
- unittest client × 1
- upload × 1
- usersession × 1
- validation × 1
- vb × 1
- vb.net × 1
- vector × 1
- view.map × 1
- visal studio × 1
- visual f# × 1
- visual studio 11 × 1
- visual studio 2012 × 1
- visual studio shell × 1
- vs2017 compiler zafir × 1
- vsix × 1
- web api × 1
- web-scraping × 1
- webapi × 1
- webcomponents × 1
- webforms × 1
- webgl × 1
- webrtc × 1
- webshaper × 1
- websharper async × 1
- websharper codemirror × 1
- websharper f# google × 1
- websharper forms × 1
- websharper reactive × 1
- websharper rpc × 1
- websharper sitelets routing × 1
- websharper warp × 1
- websharper-interface-generator × 1
- websharper.chartsjs × 1
- websharper.com × 1
- websharper.exe × 1
- websharper.owin × 1
- websharper.ui.next × 1
- websharper.ui.next jquery × 1
- websockets iis × 1
- why-websharper × 1
- windows 7 × 1
- windows 8 × 1
- windows-phone × 1
- winrt × 1
- www.grabbitmedia.com × 1
- xamarin × 1
- xml × 1
- yeoman × 1
- yield × 1
- zafir beta × 1
- zafir websharper4 × 1
- zarovizsga × 1
![]() |
Copyright (c) 2011-2012 IntelliFactory. All rights reserved. Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy |
Built with WebSharper |
hi!
at some point in my code i have a MethodInfo onto a static function of a static class (from a dynamically loaded an assembly).
public static class TrialLibCSharp { //testing out params public static void SinCos(int input, int scale, out int sinus, out int cosinus) { sinus = Convert.ToInt32(Math.Sin(input) * scale); cosinus = Convert.ToInt32(Math.Cos(input) * scale); } }
i want to generate a function value outof it.
in fact, i just want to do the same what the f# compiler would do (with the bonus that c# out parameters get transformed to one tuple return value...). or like fsi would do:
> TrialLibCSharp.SinCos;;
val it : int * int -> int * int = <fun:clo@13-1>
is this compiler functionality exposed somewhere?
(if somebody knows how to get an expression or some other meta representation of the code: i would be just as happy...)
thanks,
sebastian