Skip to content

Convert static SourceReferenceFormatter functions to member ones#3135

Merged
chriseth merged 2 commits intoargotorg:developfrom
federicobond:formatter-instance
Feb 19, 2018
Merged

Convert static SourceReferenceFormatter functions to member ones#3135
chriseth merged 2 commits intoargotorg:developfrom
federicobond:formatter-instance

Conversation

@federicobond
Copy link
Contributor

@federicobond federicobond commented Oct 26, 2017

This cleans up the method signatures and also opens the door to configuring and even replacing the formatter implementations.

@@ -42,35 +42,37 @@ struct SourceReferenceFormatter
{
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you change it to a class, please?

_stream << line << endl;
m_stream << line << endl;

auto& stream = m_stream;
Copy link
Contributor

@chriseth chriseth Oct 27, 2017

Choose a reason for hiding this comment

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

You can just capture this by value and then use m_value, no reason to create a local reference.

m_compiler.reset(new CompilerStack(fileReader));

auto scannerFromSourceName = [&](string const& _sourceName) -> solidity::Scanner const& { return m_compiler->scanner(_sourceName); };
auto formatter = SourceReferenceFormatter(cerr, scannerFromSourceName);
Copy link
Contributor

Choose a reason for hiding this comment

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

I would prefer the (actually shorter) and more explicit version:

SourceReferenceFormatter formatter(cerr, scannerFromSourceName);

*error,
(error->type() == Error::Type::Warning) ? "Warning" : "Error",
scannerFromSourceName
(error->type() == Error::Type::Warning) ? "Warning" : "Error"
Copy link
Contributor

Choose a reason for hiding this comment

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

A next refactor could pull this expression into the formatter, I would say.

Copy link
Contributor

Choose a reason for hiding this comment

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

Or actually just call typeName().

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I did not want to rock the boat too much with this one, just lay the foundation for better encapsulation and configuration.

Copy link
Contributor

@chriseth chriseth left a comment

Choose a reason for hiding this comment

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

Great apart from minor details.

@federicobond
Copy link
Contributor Author

@chriseth thanks! fixed.

@chriseth
Copy link
Contributor

The test failure is weird, since this PR should not change that...

line.cbegin(),
line.cbegin() + startColumn,
[&_stream](char const& ch) { _stream << (ch == '\t' ? '\t' : ' '); }
[this](char const& ch) { m_stream << (ch == '\t' ? '\t' : ' '); }
Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure which is faster for closures, giving the entire context or just the member variable?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's not a big object for copy, so I don't think it makes that much of a difference here.

@federicobond
Copy link
Contributor Author

@chriseth anything blocking this?

@axic
Copy link
Contributor

axic commented Nov 22, 2017

I guess it is fine, but with time I'd like to use StandardCompiler in the CLI too (e.g. to reduce the number of public interfaces we have) and that would mean most of these changes aren't really utilised.

@axic
Copy link
Contributor

axic commented Nov 22, 2017

The blocker here was as @chriseth mentioned the test failure:

Compilation failed on:
Skipping non-existent input file ""*/*.sol""
Warning: This is a pre-release compiler version, please do not use it in production.
While calling:
"/home/travis/build/ethereum/solidity/build/solc/solc" --optimize --combined-json abi,asm,ast,bin,bin-runtime,clone-bin,compact-format,devdoc,hashes,interface,metadata,opcodes,srcmap,srcmap-runtime,userdoc announcementTypes.sol ico.sol moduleHandler.sol module.sol multiOwner.sol owned.sol premium.sol provider.sol publisher.sol safeMath.sol schelling.sol tokenDB.sol token.sol */*.sol
Inside directory:
/home/travis/build/ethereum/solidity/test/compilationTests/corion

@axic
Copy link
Contributor

axic commented Nov 22, 2017

Retriggered tests, maybe that fixes it.

@axic
Copy link
Contributor

axic commented Nov 22, 2017

@federicobond it is still failing the tests :(

@axic
Copy link
Contributor

axic commented Nov 27, 2017

Tried this locally and cannot reproduce it :(

@axic
Copy link
Contributor

axic commented Nov 27, 2017

Okay the problem is the different version of the shell, which emits the Skipping non-existent input file ""*/*.sol"" warning.

This is the code filtering out the pre-release line from the output and ensuring the output is empty afterwards: https://github.com/ethereum/solidity/blob/develop/test/cmdlineTests.sh#L75-L81

@chriseth
Copy link
Contributor

Still failing :(

@federicobond
Copy link
Contributor Author

@axic I did not understand your last comment fully. Is the shell not globbing one of the function arguments?

@axic
Copy link
Contributor

axic commented Dec 11, 2017

@federicobond I had that hunch, but then I think it was something else but related, unfortunately had to leave the task and don't fully remember.

I am sure it had something to do with the shell or the script.

@axic
Copy link
Contributor

axic commented Dec 11, 2017

This is the output:

Compilation failed on:
Skipping non-existent input file ""*/*.sol""
Warning: This is a pre-release compiler version, please do not use it in production.

The script removes any line containing pre-release. If there are any lines remaining in the output it is a failure. Whoever emits that "Skipping non-existent" (it must be the shell as it is not solc) is causing it to fail.

@federicobond
Copy link
Contributor Author

federicobond commented Dec 11, 2017

Sounds like solc is receiving a literal */*.sol as argument. Perhaps shellcheck and/or some reading can clarify.

@axic
Copy link
Contributor

axic commented Dec 12, 2017

@federicobond can you try to fix it? Would be keen merging this.

@federicobond
Copy link
Contributor Author

federicobond commented Dec 12, 2017

Let me try... (Travis being so slow today doesn't help much)

@axic
Copy link
Contributor

axic commented Dec 12, 2017

Fails compilation on:

/home/travis/build/ethereum/solidity/test/libjulia/Common.cpp:44:29: error: call to non-static member function without an object argument
  SourceReferenceFormatter::printExceptionInformation(
  ~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~

@axic
Copy link
Contributor

axic commented Dec 22, 2017

This is so frustrating, the change should have nothing to do with that test failure.

@axic axic force-pushed the formatter-instance branch from c7e4499 to d3d762a Compare January 5, 2018 00:39
@axic
Copy link
Contributor

axic commented Jan 5, 2018

Rebased again, perhaps it will work?

@chriseth
Copy link
Contributor

Ok, fingers crossed. I was not able to reproduce it, but I might have the fix. Explanation inline.

m_compiler.reset(new CompilerStack(fileReader));

auto scannerFromSourceName = [&](string const& _sourceName) -> solidity::Scanner const& { return m_compiler->scanner(_sourceName); };
SourceReferenceFormatter formatter(cerr, scannerFromSourceName);
Copy link
Contributor

Choose a reason for hiding this comment

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

The type of a lambda function is different from std::function, you can only implicitly convert into std::function. This means since auto is used above, the type of scannerFromSourceNam is not std::function. Since formatter takes a const&, the type is converted on the fly, creating a temporary copy of scannerFromSourceName, converted to std::function. Since SourceReferenceFormatter (used to) store a const&, it stores a const& to this temporary which is destroyed after this line and thus invalid. I changed it to storing a value instead of a reference.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That’s awesome 👏 . Thanks for taking the time to review this Chris!

I should definitely improve my understanding of that part of the language.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, that's the problem with C++: It does not warn you about ownership problems.

@chriseth chriseth merged commit abc23ac into argotorg:develop Feb 19, 2018
@federicobond federicobond deleted the formatter-instance branch February 20, 2018 18:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants