Skip to content

Add --dump-corefn command line option#2275

Merged
paf31 merged 22 commits intomasterfrom
unknown repository
Sep 22, 2016
Merged

Add --dump-corefn command line option#2275
paf31 merged 22 commits intomasterfrom
unknown repository

Conversation

@no-longer-on-githu-b
Copy link
Copy Markdown
Contributor

@no-longer-on-githu-b no-longer-on-githu-b commented Aug 14, 2016

WORK IN PROGRESS. I'd like some feedback on these changes.

A few things are still left to do:

  • Convert Ann to JSON.
  • Convert Type to JSON.
  • Add version number to JSON dump.
  • Tests probably (super tedious).
  • Documentation.

JSON is dumped to corefn.json in the module's output directory (i.e. alongside index.js).

Addresses #876.

@garyb
Copy link
Copy Markdown
Member

garyb commented Aug 14, 2016

Would it be easier to use the macros to generate Aeson instances? I don't know if that's bad or generates unhelpful JSON or whatever as I only have peripheral contact with it, but just wondered if it would make things simpler.

@no-longer-on-githu-b
Copy link
Copy Markdown
Contributor Author

Do you mean the Template Haskell facilities? The current JSON output isn't particularly nice either, but it's very systematic too, which means it's predictable if you're familiar with the ADTs.

@garyb
Copy link
Copy Markdown
Member

garyb commented Aug 14, 2016

Yeah exactly. We already use it in a few places, like Types:

$(A.deriveJSON A.defaultOptions ''Type)
$(A.deriveJSON A.defaultOptions ''Constraint)
$(A.deriveJSON A.defaultOptions ''ConstraintData)
and probably anything else that ends up in externs.json.

@no-longer-on-githu-b
Copy link
Copy Markdown
Contributor Author

That's probably easier then, yes xD

@no-longer-on-githu-b
Copy link
Copy Markdown
Contributor Author

no-longer-on-githu-b commented Aug 14, 2016

Alright, did that. Much better. Thanks! 👍

@hdgarrood
Copy link
Copy Markdown
Contributor

I'm just a little apprehensive about using derived instances here, unless the expectation is that people will only be consuming this JSON in other Haskell programs which are using the compiler as a library, i.e. not using the json itself as an interface. For example, with derived instances, is it likely that we might want to change the internal ADT and not be able to do so without breaking third party programs?

@garyb
Copy link
Copy Markdown
Member

garyb commented Aug 14, 2016

That's a good point, I hadn't really considered that aspect of it.

@no-longer-on-githu-b
Copy link
Copy Markdown
Contributor Author

That's a good point. At least I gained more experience with Aeson 😺

@no-longer-on-githu-b
Copy link
Copy Markdown
Contributor Author

Alright, reversed that, I'll now work on Type and Ann.

@no-longer-on-githu-b
Copy link
Copy Markdown
Contributor Author

All the conversions are now implemented.

CONTRIBUTORS.md Outdated
- [@philopon](https://github.com/philopon) (Hirotomo Moriwaki) - My existing contributions and all future contributions until further notice are Copyright Hirotomo Moriwaki, and are licensed to the owners and users of the PureScript compiler project under the terms of the [MIT license](http://opensource.org/licenses/MIT).
- [@pseudonom](https://github.com/pseudonom) (Eric Easley) My existing contributions and all future contributions until further notice are Copyright Eric Easley, and are licensed to the owners and users of the PureScript compiler project under the terms of the [MIT license](http://opensource.org/licenses/MIT).
- [@puffnfresh](https://github.com/puffnfresh) (Brian McKenna) All contributions I made during June 2015 were during employment at [SlamData, Inc.](#companies) who owns the copyright. I assign copyright of all my personal contributions before June 2015 to the owners of the PureScript compiler.
- [@rightfold](https://github.com/rightfold) (rightfold) My existing contributions and all future contributions until further notice are Copyright rightfold, and are licensed to the owners and users of the PureScript compiler project under the terms of the [BSD 3-Clause license](https://opensource.org/licenses/BSD-3-Clause).
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to figure out how this will work, since I don't think BSD3 code can be redistributed under MIT, due to the additional clause about no advertising. I'd be fine to switch to BSD3 personally, which would be fine since MIT code can definitely be redistributed under BSD3. But we should discuss it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm fine with MIT if BSD causes too many issues

@no-longer-on-githu-b
Copy link
Copy Markdown
Contributor Author

@paf31 I switched to MIT. The relicensing of the old commits isn't an issue because I plan to squash everything before merging anyway (commit history is a bit of a mess)

let coreFnFile = outputDir </> filePath </> "corefn.json"
let jsonPayload = CFJ.moduleToJSON CFJ.annToJSON m
let json = Aeson.object [ ("version", Aeson.toJSON $ showVersion Paths.version)
, ("payload", jsonPayload)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this json inside json now?

Copy link
Copy Markdown
Contributor Author

@no-longer-on-githu-b no-longer-on-githu-b Sep 3, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aeson.toJSON returns Value, not String.
Aeson.encode returns String.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, thanks.

@paf31
Copy link
Copy Markdown
Contributor

paf31 commented Sep 3, 2016

@rightfold Could you please paste an example of the generated JSON here for something small like map (_ * 2) [1, 2, 3]? We should get this merged for the next release.

@no-longer-on-githu-b
Copy link
Copy Markdown
Contributor Author

no-longer-on-githu-b commented Sep 5, 2016

@paf31 JSON doesn't distinguish between floats and ints so you need the discriminator. Int and Number is probably more descriptive than Left and Right though.

Also I'm not sure about object literals and updates, because turning them into JSON objects discards their evaluation order.

import Language.PureScript.Types

literalToJSON :: (a -> Value) -> Literal a -> Value
literalToJSON _ (NumericLiteral (Left n)) = toJSON ("NumericLiteral", "Int", n)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These could just be called IntLiteral and NumberLiteral. The fact that they're represented using the same constructor in the compiler is just a historical detail, really.

@paf31
Copy link
Copy Markdown
Contributor

paf31 commented Sep 16, 2016

@garyb @andyarvanitis Would you like to review the output format here at all, before this gets merged?

Edit: Here's a little example:

{"Main":{"imports":["Prim","Main"],"builtWith":"0.9.2","exports":["X","test"],"decls":{"test":["Abs","f",["Abs","g",["Abs","v",["Abs","x",["Case",[["Var","f"],["Var","g"],["Var","v"],["Var","x"]],[[[["VarBinder","f1"],["VarBinder","g1"],["ConstructorBinder","Main.Y","Main.X",[]],["VarBinder","x1"]],["Literal",["ObjectLiteral",{"z":["Var","Main.X"],"result":["App",["Var","f1"],["App",["Var","g1"],["Accessor","foo",["Var","x1"]]]]}]]]]]]]]],"X":["Constructor","Y","X",[]]},"foreign":[]}}

and prettified:

{
  "Main": {
    "imports": [
      "Prim",
      "Main"
    ],
    "builtWith": "0.9.2",
    "exports": [
      "X",
      "test"
    ],
    "decls": {
      "test": [
        "Abs",
        "f",
        [
          "Abs",
          "g",
          [
            "Abs",
            "v",
            [
              "Abs",
              "x",
              [
                "Case",
                [
                  [
                    "Var",
                    "f"
                  ],
                  [
                    "Var",
                    "g"
                  ],
                  [
                    "Var",
                    "v"
                  ],
                  [
                    "Var",
                    "x"
                  ]
                ],
                [
                  [
                    [
                      [
                        "VarBinder",
                        "f1"
                      ],
                      [
                        "VarBinder",
                        "g1"
                      ],
                      [
                        "ConstructorBinder",
                        "Main.Y",
                        "Main.X",
                        [

                        ]
                      ],
                      [
                        "VarBinder",
                        "x1"
                      ]
                    ],
                    [
                      "Literal",
                      [
                        "ObjectLiteral",
                        {
                          "z": [
                            "Var",
                            "Main.X"
                          ],
                          "result": [
                            "App",
                            [
                              "Var",
                              "f1"
                            ],
                            [
                              "App",
                              [
                                "Var",
                                "g1"
                              ],
                              [
                                "Accessor",
                                "foo",
                                [
                                  "Var",
                                  "x1"
                                ]
                              ]
                            ]
                          ]
                        }
                      ]
                    ]
                  ]
                ]
              ]
            ]
          ]
        ]
      ],
      "X": [
        "Constructor",
        "Y",
        "X",
        [

        ]
      ]
    },
    "foreign": [

    ]
  }
}

@no-longer-on-githu-b
Copy link
Copy Markdown
Contributor Author

Hmm. It looks like the distinction between top-level let and letrec is gone?

@paf31
Copy link
Copy Markdown
Contributor

paf31 commented Sep 16, 2016

Yes, but we could add it back. I'd probably like to change the syntax a bit though.

@paf31
Copy link
Copy Markdown
Contributor

paf31 commented Sep 16, 2016

It'd be nice if non-recursive things appeared like they do now, and we added a Rec constructor to wrap recursive bindings IMO.

@no-longer-on-githu-b
Copy link
Copy Markdown
Contributor Author

no-longer-on-githu-b commented Sep 17, 2016

Or:

"decls": {
  "let": {...},
  "letrec": [
    {...},
    {...}
  ]
}

@paf31
Copy link
Copy Markdown
Contributor

paf31 commented Sep 17, 2016

Do we need to distinguish self-recursive declarations from non-recursive ones? If not, I'd rather do something like:

"decls": [
  [ { "foo": ["Abs", "f", ... ] } ]
  [ { "bar": ["Abs", "a", ["Var", "baz"]] }
  , { "baz": ["Abs", "b", ["Var", "bar"]] }
  ]
}

where the top level is a list of binding groups, each of which is a list of function declarations.

@andyarvanitis
Copy link
Copy Markdown
Contributor

@paf31 Sorry, I was on an overseas flight (with no wifi).

I'm still jet lagged right now, but it looks good. I also just looked at the sample posted by @rightfold earlier which included type information -- which is good, since the C++ backend is back to using type information (for optimizations now).

One question, though: are all imported values available? The C++ backend also uses those for some optimations (basically grabbing things from Environment currently).

@garyb
Copy link
Copy Markdown
Member

garyb commented Sep 18, 2016

Do we need to distinguish self-recursive declarations from non-recursive ones? If not, I'd rather do something like:

That looks good to me. It works for data binding groups too.

I don't think it should be the responsibility of the AST format to indicate when a function is self-recursive, since that's not something we even track in the AST, so in doing that we're kinda making the JSON representation a different thing. It should be easy enough to figure out by anything that does need that distinction too.

@paf31
Copy link
Copy Markdown
Contributor

paf31 commented Sep 18, 2016

since that's not something we even track in the AST

I thought we did track self-recursive functions in the core AST, as a Rec constructor with a singleton list of bindings.

@no-longer-on-githu-b
Copy link
Copy Markdown
Contributor Author

Core has Let/LetRec distinction for both top-level declarations and let-expressions

@garyb
Copy link
Copy Markdown
Member

garyb commented Sep 18, 2016

I thought we did track self-recursive functions in the core AST, as a Rec constructor with a singleton list of bindings.

Oh right. I should probably know that since I contributed CoreFn. 😆

@paf31
Copy link
Copy Markdown
Contributor

paf31 commented Sep 18, 2016

I think the question should be: do we need this for the first version, bearing in mind that it might be tricky to implement it in a non-breaking way if we decide to use it later? For that reason, I think we should add it, but I'm happy to spend some time figuring out the syntax.

@paf31
Copy link
Copy Markdown
Contributor

paf31 commented Sep 18, 2016

@andyarvanitis Actually, there are no type annotations in this version. The reason is that I would like to discuss move towards something a bit more like GHC core, where only binders get type annotations. With that approach, the type checker would elaborate directly to functional core, rather than decorating the initial AST.

One question, though: are all imported values available?

The core JSON will include a list of imports, but you would have to pull the definitions of the imports from the appropriate core JSON/externs file. Does that work?

@paf31
Copy link
Copy Markdown
Contributor

paf31 commented Sep 18, 2016

@garyb @andyarvanitis Binding group information has now been added back to the JSON output.

@andyarvanitis
Copy link
Copy Markdown
Contributor

Ok, thanks, I've gone back through the comments and see now what's there for the first version. I probably won't switch the C++ backend over to it just yet, then, but it's looks good for some other things I've been thinking about doing.

@paf31 paf31 merged commit 765aeb4 into purescript:master Sep 22, 2016
@paf31 paf31 mentioned this pull request Oct 14, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants