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

Add the ability to quote code as an abstract syntax tree #682

Open
7sharp9 opened this Issue Jul 3, 2018 · 9 comments

Comments

Projects
None yet
5 participants
@7sharp9
Member

7sharp9 commented Jul 3, 2018

Add the ability to quote code as an abstract syntax tree

I propose we add the ability to quote code as an abstract syntax tree.

A new operator pair could be introduced that would allow fragments of F# code to be quoted as actual F#, perhaps << ... >> or similar.

let code = << let test = fun x -> x * x  >>

The resulting code being an ast fragment like this:

[Let
           (false,
            [Binding
               (None,NormalBinding,false,false,[],
                PreXmlDoc
                  (Range+pos,  Ast+XmlDocCollector),
                SynValData
                  (None,
                   SynValInfo
                     ([[SynArgInfo ([],false,Some x)]],
                      SynArgInfo ([],false,None)),None),
                Named
                  (Wild
                     quotedCode.fs IsSynthetic=false,
                   test,false,None,
                   quotedCode.fs IsSynthetic=false),
                None,
                Lambda
                  (false,false,
                   SimplePats
                     ([Id
                         (x,None,false,false,false,
                          quotedCode.fs IsSynthetic=false)],
                      quotedCode.fs IsSynthetic=false),
                   App
                     (NonAtomic,false,
                      App
                        (NonAtomic,true,Ident op_Multiply,Ident x,
                         quotedCode.fs IsSynthetic=false),
                      Ident x,
                      quotedCode.fs IsSynthetic=false),
                   quotedCode.fs IsSynthetic=false),
                quotedCode.fs IsSynthetic=false,
                NoSequencePointAtLetBinding)],
            quotedCode.fs IsSynthetic=false)],
        false,
        quotedCode.fs IsSynthetic=false)],
    PreXmlDoc
      (Range+pos, Ast+XmlDocCollector),[],None,
    quotedCode.fs IsSynthetic=false)],
(true, true)))

The existing way of approaching this problem in F# is to use quotations along with type providers which is too limited and also lacks the ability to represent the F# language without a loss of information, see #680 / #681 for two such issues.

Pros and Cons

The advantages of making this adjustment to F# are a vast improvement to F# meta programming capability, the compilers API (FCS) already takes an abstract syntax tree as input so this is increasing the usage of that capability.

The disadvantages of making this adjustment to F# are the time taken to do the work, the added complexity to the language.

Extra information

Estimated cost (M/L):

Related suggestions: (put links to related suggestions here)

Affidavit

Please tick this by placing a cross in the box:

  • This is not a question (e.g. like one you might ask on stackoverflow) and I have searched stackoverflow for discussions of this issue
  • I have searched both open and closed suggestions on this site and believe this is not a duplicate
  • This is not something which has obviously "already been decided" in previous versions of F#. If you're questioning a fundamental design decision that has obviously already been taken (e.g. "Make F# untyped") then please don't submit it.

Please tick all that apply:

  • This is not a breaking change to the F# language design
  • I or my company would be willing to help implement and/or test this
@zpodlovics

This comment has been minimized.

zpodlovics commented Jul 3, 2018

Take a look at OCaml PPX for inspiration: http://ocamllabs.io/doc/ppx.html

Metaprogramming should also come with production quality staging support, to support real-world industrial usage (~the performance story). Please learn from the type provider (TP) story, even if it's a good idea the real-world industrial usage matters a lot - as far as I know industrial users mostly avoid TP because it makes their life lot harder in real-world (unpredictability, performance issues, weird errors, etc).

https://github.com/stedolan/ppx_stage
https://strymonas.github.io/

Tiark Rompf: Abstraction without regret:
https://youtube.com/watch?v=E7U2yPHTVRU

@7sharp9

This comment has been minimized.

Member

7sharp9 commented Jul 3, 2018

We can currently do parts of what PPX can do, what I would like is better integration into the compiler chain like adding quoted literals, splicing etc. I have a program now which does what dumpast does in PPX etc.

I wanted this language suggestion to act as a starting point for a discussion on that, I didn't want to describe anything too deeply incase this suggestion gets closed.

@zpodlovics

This comment has been minimized.

zpodlovics commented Jul 3, 2018

I would love to have more metaprogramming story for F#. And at the end to have language level integration - something like Lightweight Modular Staging for Scala.

It seems that some kind of code specialization and partial staging would be possible with your proposal, am I right? Would it be possible to also control when the ast transformation should happen eg.: runtime / compilation time?

@7sharp9

This comment has been minimized.

Member

7sharp9 commented Jul 3, 2018

The first step is to allow the quoting of code to ast fragments, after that holes could be defined and other fragments could be spliced into place, I would propose that this all happens at compile time.

Finally there could be an integration of quoted fragment so that the staged ast quotation is incorporated with the current one during compilation.

@Rickasaurus

This comment has been minimized.

Rickasaurus commented Jul 27, 2018

@7sharp9 I really like this idea, but it does have the downside of making any changes to the F# AST break pretty much all users of this.

@7sharp9

This comment has been minimized.

Member

7sharp9 commented Jul 27, 2018

Any new feature alters the AST, like Span added to the AST recently.

@cartermp

This comment has been minimized.

Member

cartermp commented Jul 27, 2018

@cartermp

This comment has been minimized.

Member

cartermp commented Sep 10, 2018

I like this in principle, though it would be good to see some proposed use cases of this feature should it be implemented.

@dsyme

This comment has been minimized.

Collaborator

dsyme commented Oct 11, 2018

Just commenting on the above:

as far as I know industrial users mostly avoid TP because it makes their life lot harder in real-world (unpredictability, performance issues, weird errors, etc).

This is not the case - some people certainly run into problems using TPs, but I consistently meet many people who use them in production scenarios. Those who run into problems are much more vocal of course.

The same is true of F# quotations, or Rosyln analyzers... Indeed OCaml meta-programming has/had many issues and I saw many examples of them being used/unused. I actually think all meta-programming solutions have problems like this: they solve various kinds of problems but are frequently misused or run into tooling issues

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment