Skip to content

Add improved functionality for the construction of json_arrayt and json_objectt #3862

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

Merged
merged 7 commits into from
Jan 28, 2019

Conversation

thomasspriggs
Copy link
Contributor

@thomasspriggs thomasspriggs commented Jan 20, 2019

  • Each commit message has a non-empty body, explaining why the change was made.
  • Methods or procedures I have added are documented, following the guidelines provided in CODING_STANDARD.md.
  • The feature or user visible behaviour I have added or modified has been documented in the User Guide in doc/cprover-manual/
  • Regression or unit tests are included, or existing tests cover the modified code (in this case I have detailed which ones those are in the commit message).
  • My commit message includes data points confirming performance improvements (if claimed).
  • My PR is restricted to a single feature or bugfix.
  • White-space or formatting changes outside the feature-related changed lines are in commits of their own.

Much of the existing code which constructs instances of json_arrayt and json_objectt are based around creating an empty instance as then mutating it to add the contained information. This PR adds extra functionality to enable these two types to be constructed using a coding style which no longer requires mutation and is more readable.

src/util/json.h Outdated
@@ -283,6 +283,12 @@ class json_objectt:public jsont
{
}

explicit json_objectt(
std::initializer_list<typename objectt::value_type> initializer_list)
: json_objectt{objectt{initializer_list}}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Thank you for this further improvement! I suspect it's kind of a painful ask, but would you mind adding a commit that now removes the outermost parentheses from various bits touched in 64df79e?

@@ -16,52 +16,47 @@ Author: Martin Brain, [email protected]
#include <goto-programs/goto_model.h>

#include <analyses/ai.h>
#include <util/range.h>
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please move this 5 lines up so that it becomes part of the util block.

@thomasspriggs thomasspriggs force-pushed the tas/json_construction branch 4 times, most recently from 0ec1923 to 55051ea Compare January 21, 2019 02:11
Copy link
Contributor

@allredj allredj left a comment

Choose a reason for hiding this comment

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

✔️
Passed Diffblue compatibility checks (cbmc commit: 55051ea).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/97979428

Copy link
Collaborator

@tautschnig tautschnig left a comment

Choose a reason for hiding this comment

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

Thank you for the extra work!

@kroening
Copy link
Member

Does this work with Visual Studio 2013?

@thomasspriggs
Copy link
Contributor Author

@kroening I wrote this PR under Debian 9 "Stretch" using gcc 6. So I haven't tried building in VS 2013 myself. However the windows CI build has passed.

Copy link
Contributor

@thk123 thk123 left a comment

Choose a reason for hiding this comment

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

Love it.

/// Constructs a collection containing the values, which this range iterates
/// over.
template <typename containert>
containert collect() const
Copy link
Contributor

Choose a reason for hiding this comment

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

💚


/// A type of functor which wraps around the set of constructors of a type.
/// \tparam constructedt: The type which this functor constructs.
template <typename constructedt>
Copy link
Contributor

Choose a reason for hiding this comment

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

❓ What is the use of this? Currently only used in the unit test so was thinking it should live there, but of course if it has general utility then here is fine

Copy link
Contributor

Choose a reason for hiding this comment

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

Is used in a later commit.

@@ -359,6 +359,12 @@ struct ranget final
return containert(begin(), end());
}

template <typename containert>
Copy link
Contributor

Choose a reason for hiding this comment

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

💚 💚

@thomasspriggs
Copy link
Contributor Author

@kroening Do you want any additional checks done around visual studio 2013 compatibility? CI passing + reviewer approval would normally be considered to be sufficient. Given that the new code is both unit tested and used, there should have been compile errors, or failing tests if any issues were introduced.

This PR now touches a wide range of directories, due to the bracket removal requested by Michael Tautschnig. Which means that it seems to require review from a unknown number of reviewers. It would save time if you would merge this.

// clang-format on
source_locationt source_location;
irep_idt function_id;
};

/// Makes a status message string from a status.
static std::string message(const static_verifier_resultt::statust &status)
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggest const char * since this only ever returns constants (no need to bind our caller to necessarily go through std::string)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

@@ -152,8 +152,8 @@ static void add_to_json(

// print info for file actually with full path
const source_locationt &l=it->second->source_location;
json_objectt i_entry(
{{"sourceLocation", json(l)}, {"statement", json_stringt(s)}});
json_objectt i_entry{{"sourceLocation", json(l)},
Copy link
Contributor

Choose a reason for hiding this comment

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

Surprising formatting -- break after first {?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If I insert a new line, then clang format will just remove it again. I agree that left alignment of the enclosed pairs would be preferable. However I prefer the sub optimal formatting over the extra comments to switch off the formatting in this case.

@@ -172,8 +172,8 @@ json_objectt json(const typet &type, const namespacet &ns, const irep_idt &mode)
to_struct_type(type).components();
for(const auto &component : components)
{
json_objectt e({{"name", json_stringt(component.get_name())},
{"type", json(component.type(), ns, mode)}});
json_objectt e{{"name", json_stringt(component.get_name())},
Copy link
Contributor

Choose a reason for hiding this comment

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

Same formatting nitpick as above

{
}

template <typename begin_iteratort, typename end_iteratort>
Copy link
Contributor

Choose a reason for hiding this comment

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

Surely these have to be the same type?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Forwarding these parameters separately means that the template can match when the two iterators have different const or reference qualifiers. For example .begin() on a range returns a mutable instance of the iterator by value, whereas the .end() on a range returns a const reference to the end iterator.
I will however add a static_assert to these constructors, in order to give a sensible error message if the types of the iterators are different once any const or reference modifiers are removed.

@@ -90,14 +92,12 @@ const optionst::value_listt &optionst::get_list_option(
/// Returns the options as JSON key value pairs
Copy link
Contributor

Choose a reason for hiding this comment

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

Worth noting this is now lazy, so calling this then mutating optionst then trying to iterate over the range may be undefined behaviour

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Please note that the return type of the function is still a value of type json_objectt, not a range. So there is no laziness beyond the scope of this function.

Choose a reason for hiding this comment

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

@thomasspriggs might be worth adding an explicit constructor call to make that more obvious?

Copy link
Contributor

@smowton smowton left a comment

Choose a reason for hiding this comment

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

(notes above, meant to approve)

@thomasspriggs thomasspriggs force-pushed the tas/json_construction branch 2 times, most recently from a8b278c to a859b17 Compare January 21, 2019 17:17
@kroening
Copy link
Member

@thomasspriggs The CI uses 2015, so may still fail with 2013.
I can try tomorrow.

Copy link
Contributor

@allredj allredj left a comment

Choose a reason for hiding this comment

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

🚫
This PR failed Diffblue compatibility checks (cbmc commit: a8b278c).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/98067771
Status will be re-evaluated on next push.
Please contact @peterschrammel, @thk123, or @allredj for support.

Common spurious failures:

  • the cbmc commit has disappeared in the mean time (e.g. in a force-push)
  • the author is not in the list of contributors (e.g. first-time contributors).

The incompatibility may have been introduced by an earlier PR. In that case merging this
PR should be avoided unless it fixes the current incompatibility.

Copy link
Contributor

@allredj allredj left a comment

Choose a reason for hiding this comment

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

✔️
Passed Diffblue compatibility checks (cbmc commit: a859b17).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/98072678

@thomasspriggs
Copy link
Contributor Author

@kroening I have made a cursory attempt at compiling cbmc develop with visual studio 2013. This resulted in numerous build errors. Some of these were likely to be due to not having my build environment correctly setup. However a substantial number of these appear to be existing compatibility issues.

@kroening
Copy link
Member

This doesn't compile with VS 2013.
I.e., merging this requires ditching this target.

@thomasspriggs
Copy link
Contributor Author

Can you compile develop with VS 2013? If you can't, then VS 2013 support has already been lost without this PR.

kroening pushed a commit that referenced this pull request Jan 22, 2019
Upgrading to VS2015 enables #3862, noexcept (e.g.  #2502), UTF8 strings and
constexpr (#2133).
This new constructor facilitates the construction of instances of
`json_objectt` which are const, because it gives a tidy way to construct
an entire `json_objectt`.
@thomasspriggs
Copy link
Contributor Author

I have pushed two rebases to

  • Rename constructort to constructor_oft to avoid naming conflicts.
  • Rebase on develop. Resolving a merge conflict in the process.

This new constructor facilitates the construction of instances of
`json_arrayt` which are const, because it gives a tidy way to construct
an entire `json_arrayt`.
The end result of this commit is that code like the following example
can be used to construct `json_arrayt` / `json_objectt` -
```
const std::vector<std::string> input{"foo", "bar"};
const auto json_array =
make_range(input)
.map(constructor_of<json_stringt>())
.collect<json_arrayt>();
```
This commit includes -
* Constructors from iterators for json_arrayt and json_objectt, so
that the iterators from a range can be used to construct these classes.
* A `collect` member function for `ranget`, so that a chain of range
operations can finish with the construction of a resulting container
containing a collection of the results.
* A `constructor_of` template function, which provides syntactic sugar
when using `map` to call a constructor, compared to writing a new lambda
function each time such an operation is carried out.
* Unit tests covering all of the above functionality.
This commit is included in this PR, as a demonstration of the coding
style which is enabled by the proceeding commits.
Adding `.collect` to the end of a chain of range operations can add
clutter to the code, rather than improving readability, in places where
the type of container being constructed is apparent from the context.
This commit adds a cast operation in order to improve readability in
this scenario.

In addition to the operator, this commit includes a refactor of
`optionst::to_json` in order to demonstrate an example usage of the
proposed change.
With the new constructors, these brackets are no longer required and can
be removed, in order to improve readability.
Removing this constructor simplifies the interface, by reducing the
number of different ways to construct the classes and avoiding exposing
the implementation detail of what type of container `json_objectt` and
`json_arrayt` are backed by.
@thomasspriggs
Copy link
Contributor Author

Rebased to fix include of catch in unit test.

Copy link
Contributor

@allredj allredj left a comment

Choose a reason for hiding this comment

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

🚫
This PR failed Diffblue compatibility checks (cbmc commit: 2a4d8ff).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/98867160
Status will be re-evaluated on next push.
Please contact @peterschrammel, @thk123, or @allredj for support.

Common spurious failures:

  • the cbmc commit has disappeared in the mean time (e.g. in a force-push)
  • the author is not in the list of contributors (e.g. first-time contributors).

The incompatibility may have been introduced by an earlier PR. In that case merging this
PR should be avoided unless it fixes the current incompatibility.

@peterschrammel peterschrammel removed their assignment Jan 28, 2019
Copy link
Collaborator

@martin-cs martin-cs left a comment

Choose a reason for hiding this comment

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

I don't see a problem with my part.

@thomasspriggs thomasspriggs merged commit 085fd6a into diffblue:develop Jan 28, 2019
@thomasspriggs thomasspriggs deleted the tas/json_construction branch January 28, 2019 23:19
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.

10 participants