Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

We need FSharp.Compiler.SourceCodeServices.FSharpExprVisitor #938

Closed
Thorium opened this issue May 6, 2020 · 0 comments
Closed

We need FSharp.Compiler.SourceCodeServices.FSharpExprVisitor #938

Thorium opened this issue May 6, 2020 · 0 comments

Comments

@Thorium
Copy link
Contributor

Thorium commented May 6, 2020

We need FSharp.Compiler.SourceCodeServices.FSharpExprVisitor

There is an ExpressionVisitor in core dotnet (System.Linq.Expressions.dll).
That is the way to do meta-programming in C#. It can be used to visit, traversing, examining, copying and transforming LINQ-expressions, which are the default Abstract Syntax Tree (AST) for C#.

In F# there is no one default AST.

  • F# Query expressions are just a wrappers for LINQ-expressions. (You can use ExpressionVisitor like this.)
  • Quotations. ASTs are Expr-class. (There is no ExprVisior class, but a workaround is that you convert Expr to LINQ-expression, and use C# ExpressionVisitor. Ugly, but doable.)
  • FSharp.Compiler.SourceCodeServices.FSharpExpr and this is the problematic one. Expression visitor cannot be done, because type E is not publicly visible and you cannot easily create a new FSharpExpr AST. The visitor should be written to this type.

By searching GitHub for e.g. BasicPatterns.FastIntegerForLoop we can see that there would really be use for this, as the workaround for people has been that they are writing their own yet-another-ASTs to traverse FSharpExpr to something and then processing that. Or even worse, not everyone is an AST-expert, so they try to collect some results directly, losing the tree, and then struggling to handle the results later.

So basically one public method should be added to Exprs.fs (and corresponding Exprs.fsi), which would do something like this:

let rec visitFSharpExpr memberCallHandler (e:FSharpExpr) =
    match e with
    | BasicPatterns.AddressOf(lvalueExpr) ->
        upcast FSharpExpr.NewAddressOf(visitFSharpExpr memberCallHandler lvalueExpr)
    | BasicPatterns.AddressSet(lvalueExpr, rvalueExpr) ->
        upcast FSharpExpr.NewAddressSet(visitFSharpExpr memberCallHandler lvalueExpr; visitFSharpExpr memberCallHandler rvalueExpr)
    | BasicPatterns.Application(funcExpr, typeArgs, argExprs) ->
       ///...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants