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

Improve pretty printing #1520

Merged
merged 27 commits into from
Jun 17, 2022
Merged

Improve pretty printing #1520

merged 27 commits into from
Jun 17, 2022

Conversation

turbolent
Copy link
Member

Work towards #209

Description

Finish the implementation of pretty printing all AST elements:

  • Function blocks with pre/post conditions
  • Function expressions and declarations
  • Pragmas
  • Variable declarations, including optional second value
  • Imports
  • Composite declarations, including fields and enum cases
  • Interface declarations
  • Transactions
  • Programs
  • Expressions: Parenthesize sub-expressions when needed

Improve parsing:

  • Remove the empty parameter lists from parsed transaction declaration's execute "blocks" (special functions)
  • Make logical and and logical or left associative. There is no reason to make them right associative (likely an oversight; does not change semantics)

Also, improve the layout of the pretty printing tool (tools/prettier).

Give it a try with go run ./tools/pretty!


  • Targeted PR against master branch
  • Linked to Github issue with discussion and accepted design OR link to spec that describes this work
  • Code follows the standards mentioned here
  • Updated relevant documentation
  • Re-reviewed Files changed in the Github PR explorer
  • Added appropriate labels

@codecov-commenter
Copy link

codecov-commenter commented Mar 21, 2022

Codecov Report

Merging #1520 (0dbc209) into master (5d15cd5) will increase coverage by 0.31%.
The diff coverage is 92.58%.

@@            Coverage Diff             @@
##           master    #1520      +/-   ##
==========================================
+ Coverage   77.04%   77.36%   +0.31%     
==========================================
  Files         295      297       +2     
  Lines       61515    62090     +575     
==========================================
+ Hits        47397    48034     +637     
+ Misses      12503    12441      -62     
  Partials     1615     1615              
Flag Coverage Δ
unittests 77.36% <92.58%> (+0.31%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
runtime/ast/precedence_string.go 0.00% <0.00%> (ø)
runtime/ast/program.go 69.81% <0.00%> (-6.48%) ⬇️
runtime/parser2/expression.go 93.02% <ø> (-0.02%) ⬇️
tools/pretty/main.go 0.00% <0.00%> (ø)
runtime/ast/expression.go 89.81% <86.93%> (+2.57%) ⬆️
runtime/ast/composite.go 85.57% <92.47%> (+11.46%) ⬆️
runtime/ast/import.go 91.30% <96.55%> (+8.95%) ⬆️
runtime/ast/block.go 97.09% <96.77%> (+1.69%) ⬆️
runtime/ast/argument.go 100.00% <100.00%> (+10.81%) ⬆️
runtime/ast/function_declaration.go 78.68% <100.00%> (+4.95%) ⬆️
... and 16 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 5d15cd5...0dbc209. Read the comment docs.

@github-actions
Copy link

github-actions bot commented Mar 21, 2022

Cadence Benchstat comparison

This branch with compared with the base branch onflow:master commit 5d15cd5
The command for i in {1..N}; do go test ./... -run=XXX -bench=. -benchmem -shuffle=on; done was used.
Bench tests were run a total of 7 times on each branch.

Results

old.txtnew.txt
time/opdelta
CheckContractInterfaceFungibleTokenConformance-2137µs ± 1%139µs ± 2%~(p=0.097 n=7+7)
ContractInterfaceFungibleToken-241.8µs ± 5%41.6µs ± 1%~(p=0.628 n=7+6)
InterpretRecursionFib-22.93ms ± 1%3.51ms ± 6%+19.78%(p=0.001 n=7+7)
NewInterpreter/new_interpreter-21.15µs ± 0%1.15µs ± 1%~(p=0.922 n=6+7)
NewInterpreter/new_sub-interpreter-22.39µs ± 1%2.43µs ± 6%~(p=0.735 n=7+7)
ParseArray-28.69ms ± 5%8.83ms ± 6%~(p=0.456 n=7+7)
ParseDeploy/byte_array-213.0ms ± 2%12.9ms ± 1%~(p=0.628 n=7+6)
ParseDeploy/decode_hex-21.13ms ± 1%1.14ms ± 1%~(p=0.534 n=7+6)
ParseFungibleToken/With_memory_metering-2207µs ± 2%208µs ± 2%~(p=0.097 n=7+7)
ParseFungibleToken/Without_memory_metering-2161µs ± 3%160µs ± 1%~(p=0.620 n=7+7)
ParseInfix-27.63µs ± 3%7.63µs ± 1%~(p=0.295 n=7+6)
QualifiedIdentifierCreation/One_level-22.68ns ± 0%2.68ns ± 0%~(p=0.904 n=7+7)
QualifiedIdentifierCreation/Three_levels-2140ns ± 0%139ns ± 3%~(p=0.247 n=5+7)
RuntimeFungibleTokenTransfer-21.22ms ±20%1.13ms ±28%~(p=1.000 n=7+7)
RuntimeResourceDictionaryValues-26.58ms ± 5%6.55ms ± 3%~(p=0.902 n=7+7)
Transfer-288.2ns ± 1%88.6ns ± 0%~(p=0.731 n=6+7)
 
alloc/opdelta
CheckContractInterfaceFungibleTokenConformance-266.3kB ± 0%66.3kB ± 0%~(p=0.192 n=7+7)
ContractInterfaceFungibleToken-226.7kB ± 0%26.7kB ± 0%~(all equal)
InterpretRecursionFib-21.25MB ± 0%1.51MB ± 0%+21.07%(p=0.001 n=6+7)
NewInterpreter/new_interpreter-2928B ± 0%928B ± 0%~(all equal)
NewInterpreter/new_sub-interpreter-21.46kB ± 0%1.46kB ± 0%~(all equal)
ParseArray-22.80MB ± 2%2.80MB ± 2%~(p=0.710 n=7+7)
ParseDeploy/byte_array-24.33MB ± 0%4.39MB ± 3%~(p=0.234 n=6+7)
ParseDeploy/decode_hex-2214kB ± 0%214kB ± 0%−0.06%(p=0.014 n=7+7)
ParseFungibleToken/With_memory_metering-236.3kB ± 0%36.3kB ± 0%−0.04%(p=0.035 n=6+7)
ParseFungibleToken/Without_memory_metering-236.3kB ± 0%36.3kB ± 0%~(p=0.480 n=7+7)
ParseInfix-22.17kB ± 0%2.17kB ± 0%~(p=0.228 n=7+7)
QualifiedIdentifierCreation/One_level-20.00B 0.00B ~(all equal)
QualifiedIdentifierCreation/Three_levels-264.0B ± 0%64.0B ± 0%~(all equal)
RuntimeFungibleTokenTransfer-2237kB ± 0%237kB ± 0%~(p=0.456 n=7+7)
RuntimeResourceDictionaryValues-22.25MB ± 0%2.25MB ± 0%~(p=1.000 n=7+7)
Transfer-248.0B ± 0%48.0B ± 0%~(all equal)
 
allocs/opdelta
CheckContractInterfaceFungibleTokenConformance-21.07k ± 0%1.07k ± 0%~(all equal)
ContractInterfaceFungibleToken-2460 ± 0%460 ± 0%~(all equal)
InterpretRecursionFib-223.8k ± 0%33.5k ± 0%+41.00%(p=0.001 n=7+7)
NewInterpreter/new_interpreter-213.0 ± 0%13.0 ± 0%~(all equal)
NewInterpreter/new_sub-interpreter-242.0 ± 0%42.0 ± 0%~(all equal)
ParseArray-270.0k ± 0%70.0k ± 0%~(p=1.000 n=7+7)
ParseDeploy/byte_array-2105k ± 0%105k ± 0%~(p=0.333 n=7+7)
ParseDeploy/decode_hex-278.0 ± 0%77.0 ± 0%−1.28%(p=0.001 n=7+7)
ParseFungibleToken/With_memory_metering-21.06k ± 0%1.06k ± 0%~(all equal)
ParseFungibleToken/Without_memory_metering-21.06k ± 0%1.06k ± 0%~(all equal)
ParseInfix-266.0 ± 0%66.0 ± 0%~(all equal)
QualifiedIdentifierCreation/One_level-20.00 0.00 ~(all equal)
QualifiedIdentifierCreation/Three_levels-22.00 ± 0%2.00 ± 0%~(all equal)
RuntimeFungibleTokenTransfer-24.53k ± 0%4.52k ± 0%~(p=0.106 n=7+7)
RuntimeResourceDictionaryValues-237.6k ± 0%37.6k ± 0%~(p=1.000 n=7+7)
Transfer-21.00 ± 0%1.00 ± 0%~(all equal)
 

Copy link
Member

@SupunS SupunS left a comment

Choose a reason for hiding this comment

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

Thats a one big PR 😅 I mostly reviewed the pattern and general go code, and Looks good!

I have two suggestions:

  • One suggestion for test: perhaps add a test-case where a complex program that covers all (or an extensive set of) AST nodes, is parsed from the source and pretty printed, and compared it with the original source. This can eliminate any potential mistakes in manually asserting the "docs". The test can be of two levels:

    • Level 1: Original source code is properly formatted. The round trip should produce the original source code.
    • Level 2: Further extend above by randomly increasing/changing space/newlines, and check the whether the round trip produces the above properly formatted source.
  • It might be good to have the pretty printer code separated from the AST. i.e: make it a visitor (in a separate PR of course).

runtime/ast/block.go Outdated Show resolved Hide resolved
if conditionsDoc := b.PreConditions.Doc(preConditionsKeywordDoc); conditionsDoc != nil {
conditionDocs = append(
conditionDocs,
prettier.HardLine{},
Copy link
Member

Choose a reason for hiding this comment

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

Can prettier.HardLine{} be re-used (e.g: a global variable) or is there a possibility that it would get updated in the downstream code/ inside the prettier library?

Copy link
Member Author

Choose a reason for hiding this comment

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

All documents are immutable, so they won't get updated in downstream code / inside the prettier library.
It's an empty struct, so IDK if there's any improvement other than saving two characters

runtime/ast/type.go Outdated Show resolved Hide resolved
runtime/ast/block.go Outdated Show resolved Hide resolved
@turbolent
Copy link
Member Author

@SupunS

Thats a one big PR 😅 I mostly reviewed the pattern and general go code, and Looks good!

I have two suggestions:

  • One suggestion for test: perhaps add a test-case where a complex program that covers all (or an extensive set of) AST nodes, is parsed from the source and pretty printed, and compared it with the original source. This can eliminate any potential mistakes in manually asserting the "docs". The test can be of two levels:

    • Level 1: Original source code is properly formatted. The round trip should produce the original source code.
    • Level 2: Further extend above by randomly increasing/changing space/newlines, and check the whether the round trip produces the above properly formatted source.
  • It might be good to have the pretty printer code separated from the AST. i.e: make it a visitor (in a separate PR of course).

Sorry about the size 😅 It's a lot of tests, maybe should have split it up, but kept on hacking away.

These are both two great suggestions. As this PR only improves, but does not yet fully complete the pretty printing implementation, I'll add such a test in a follow up. Also, as this PR is mostly improving on the existing functionality / structure, I'll open a refactor in a separate follow-up PR

turbolent and others added 2 commits June 17, 2022 14:39
Co-authored-by: Supun Setunga <supun.setunga@gmail.com>
@SupunS
Copy link
Member

SupunS commented Jun 17, 2022

yeah, of course!

@turbolent turbolent merged commit a3519dd into master Jun 17, 2022
@turbolent turbolent deleted the bastian/prettier-4 branch June 17, 2022 22:04
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.

4 participants