Я хочу сгенерировать тип со статическими функциями, который затем можно использовать в функциях, которые становятся цитатами с помощью атрибута ReflectedDefinition. Мне кажется удобным способ перевести что-то в типы FSharp, используя FSharp для составления домена функций и типов, и выплюнуть составленный код обратно в родную форму, получив преимущество проверки типов, VS intellisense, функций более высокого порядка и т. д. Для начала у меня есть провайдер этого типа, в основном скопированный->вставленный из различных статей.
[<TypeProvider>]
type CSoundTypeProvider(config: TypeProviderConfig) as this =
inherit ProvidedTypes.TypeProviderForNamespaces()
let namespaceName = "TestNamespace"
let thisAssembly = Assembly.GetExecutingAssembly()
// config.
let intType = typeof<int>
let providedParam = ProvidedTypes.ProvidedParameter("prm", intType)
let providedFunction = ProvidedTypes.ProvidedMethod("TestMethod", [providedParam], intType, IsStaticMethod=true
, InvokeCode = fun args ->
// The 'args' parameter represents expressions that give us access to the
// instance on which the method is invoked and other parameters (if there are more)
let instance = args.[0]
// Now we can return quotation representing a call to MethodInfo 'p' with 'instance'
instance)
let csoundProvidedWrapper = ProvidedTypes.ProvidedTypeDefinition(thisAssembly, namespaceName, "TestType", None)
do csoundProvidedWrapper.AddMember(providedFunction)
do this.AddNamespace(namespaceName, [csoundProvidedWrapper])
И протестировать его с помощью этого отраженного определения:
[<ReflectedDefinition>]
let myfn i j =
let k = i * j
let x = k + 2
let f = TestNamespace.TestType.TestMethod k
let ret = f + 2
ret
Я разбираю отраженное определение следующим образом:
<@ myfn @> |> println
println — это функция (скопированная из другой статьи), в которой есть множество активных шаблонов для разбора цитат, таких как Patterns.Call(None, DerivedPatterns.MethodWithReflectedDefinition(n), expList)< /em>, что дает мне дерево экспериментов всего кода, кроме предоставленного статического метода. Возможно ли то, что я пытаюсь сделать? Если да, то какой активный шаблон я, вероятно, пропустил из моей функции println здесь:
let println expr =
let rec print expr = match expr with
| Patterns.Application(expr1, expr2) ->
// Function application.
print expr1
printf " "
print expr2
| Patterns.Call(None, DerivedPatterns.MethodWithReflectedDefinition(n), expList) ->
print n
| Patterns.Call(exprOpt, methodInfo, exprList) ->
// Method or module function call.
match exprOpt with
| Some expr -> print expr
| None -> printf "%s" methodInfo.DeclaringType.Name
printf ".%s(" methodInfo.Name
if (exprList.IsEmpty) then printf ")" else
print exprList.Head
for expr in exprList.Tail do
printf ","
print expr
printf ")"
| DerivedPatterns.Int32(n) ->
printf "%d" n
| Patterns.Lambda(param, body) ->
// Lambda expression.
printf "fun (%s:%s) -> " param.Name (param.Type.ToString())
print body
| Patterns.Let(var, expr1, expr2) ->
// Let binding.
if (var.IsMutable) then
printf "let mutable %s = " var.Name
else
printf "let %s = " var.Name
print expr1
printf " in "
print expr2
| Patterns.PropertyGet(_, propOrValInfo, _) ->
printf "%s" propOrValInfo.Name
| DerivedPatterns.String(str) ->
printf "%s" str
| Patterns.Value(value, typ) ->
printf "%s" (value.ToString())
| Patterns.Var(var) ->
printf "%s" var.Name
| _ -> printf "%s" (expr.ToString())
print expr
Если я не могу этого сделать, какой подход вы бы порекомендовали для создания определений FSharp, которые я могу использовать в цитатах? На меня в значительной степени повлиял проект FunScript, но я надеюсь избежать шага, когда кажется, что каждое определение Typescript должно быть скомпилировано в отдельную DLL.