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 abstraction of parse state #221

Merged
merged 13 commits into from
Nov 5, 2017
Merged

Improve abstraction of parse state #221

merged 13 commits into from
Nov 5, 2017

Conversation

jvdb
Copy link
Contributor

@jvdb jvdb commented Oct 26, 2017

Resolves #216.

This PR tackles some abstraction issues. The resolution resolves a functional bug. The six commits show the following six changes:

  1. Callbacks was extracted from the Environment class.
  2. The Environment class was renamed to ParseState.
  3. Of the three remaining constructors on ParseState, two are renamed to factory methods to better reflect their functionality.
  4. Both equals() and hashCode() methods were implemented on ParseState.
  5. The eval() methods of ValueExpression and Expression were modified to accept a ParseState instead of a ParseGraph.
  6. The Shorthand approximate implementation of CURRENT_OFFSET is replaced with an implementation that returns the actual offset field of the ParseState.

After that, another branch was merged that recreates an Environment class: #222.

@codecov
Copy link

codecov bot commented Oct 26, 2017

Codecov Report

Merging #221 into master will not change coverage.
The diff coverage is 100%.

Impacted file tree graph

@@           Coverage Diff           @@
##             master   #221   +/-   ##
=======================================
  Coverage       100%   100%           
- Complexity      952    967   +15     
=======================================
  Files            86     88    +2     
  Lines          1314   1331   +17     
  Branches        134    137    +3     
=======================================
+ Hits           1314   1331   +17
Impacted Files Coverage Δ Complexity Δ
...ingdata/metal/expression/value/arithmetic/Mod.java 100% <ø> (ø) 3 <0> (ø) ⬇️
...singdata/metal/expression/value/reference/Len.java 100% <ø> (ø) 3 <0> (ø) ⬇️
...arsingdata/metal/expression/value/bitwise/Not.java 100% <ø> (ø) 2 <0> (ø) ⬇️
...ava/io/parsingdata/metal/expression/value/Cat.java 100% <ø> (ø) 2 <0> (ø) ⬇️
...ata/metal/expression/value/bitwise/ShiftRight.java 100% <ø> (ø) 2 <0> (ø) ⬇️
...ingdata/metal/expression/value/arithmetic/Mul.java 100% <ø> (ø) 2 <0> (ø) ⬇️
...ingdata/metal/expression/value/arithmetic/Div.java 100% <ø> (ø) 3 <0> (ø) ⬇️
...arsingdata/metal/expression/value/bitwise/And.java 100% <ø> (ø) 2 <0> (ø) ⬇️
...ingdata/metal/expression/value/arithmetic/Neg.java 100% <ø> (ø) 2 <0> (ø) ⬇️
...data/metal/expression/value/bitwise/ShiftLeft.java 100% <ø> (ø) 3 <0> (ø) ⬇️
... and 57 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 f8cdea5...b5f995f. Read the comment docs.

Copy link
Contributor

@mvanaken mvanaken left a comment

Choose a reason for hiding this comment

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

Nice!

return ImmutableList.create(Optional.<Value>empty()).add(Optional.of(new Value(createFromBytes(new byte[] { 1, 2 }), enc())));
}
}, Shorthand::add).eval(stream(0).order, enc()).isEmpty());
assertTrue(foldRight((parseState, encoding) -> ImmutableList.create(Optional.<Value>empty()).add(Optional.of(new Value(createFromBytes(new byte[] { 1, 2 }), enc()))), Shorthand::add).eval(stream(0), enc()).isEmpty());
Copy link
Contributor

Choose a reason for hiding this comment

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

This is one big line of code. ;)

private Optional<Environment> checkFullParse(Token token, byte[] data) throws IOException {
final Optional<Environment> result = token.parse(new Environment(new InMemoryByteStream(data)), enc());
private Optional<ParseState> checkFullParse(Token token, byte[] data) throws IOException {
final Optional<ParseState> result = token.parse(createFromByteStream(new InMemoryByteStream(data)), enc());
Copy link
Contributor

Choose a reason for hiding this comment

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

You can use the ParseStateFactory.stream(bytes) for this.

Copy link
Contributor Author

@jvdb jvdb Nov 5, 2017

Choose a reason for hiding this comment

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

stream() takes a vararg of integers, not an array :(

@@ -73,15 +73,15 @@ public void multiValueInRepN() throws IOException {
any("b"),
repn(dummy, ref("b"))
);
Optional<Environment> result = multiRepN.parse(stream(2, 2, 2, 2), enc());
Optional<ParseState> result = multiRepN.parse(stream(2, 2, 2, 2), enc());
Copy link
Contributor

Choose a reason for hiding this comment

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

Minor, but result can be made final.

if (values.isEmpty()) {
return complete(() -> success(new Environment(environment.closeBranch().order, returnEnvironment.source, returnEnvironment.offset, returnEnvironment.callbacks)));
return complete(() -> success(new ParseState(parseState.closeBranch().order, returnParseState.source, returnParseState.offset)));
Copy link
Contributor

Choose a reason for hiding this comment

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

Not using a factory method here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I suppose that would have to be a method comparable to seek() that replaces the ParseGraph on returnEnvironment. It could be done, but this seems to be a rather isolated use.

public final BigInteger offset;
public final Source source;

public ParseState(final ParseGraph order, final Source source, final BigInteger offset) {
Copy link
Contributor

Choose a reason for hiding this comment

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

If it is possible you may consider making this ParseState constructor private and always use the ParseStateFactory instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As discussed, ParseStateFactory is a test class. I think this single constructor makes sense because it only stores fields.

this.offset = checkNotNegative(offset, "offset");
}

public static ParseState createFromByteStream(final ByteStream input, final BigInteger offset) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't this method be part of the ParseStateFactory?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

See above :)

&& Objects.equals(encoding, ((DataExpressionSource)obj).encoding);
}

@Override
public int hashCode() {
return Objects.hash(getClass().hashCode(), dataExpression, index, graph, encoding);
return Objects.hash(getClass().hashCode(), dataExpression, index, parseState, encoding);
Copy link
Collaborator

Choose a reason for hiding this comment

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

You can probably remove the calls to hashcode everywhere where using Objects#hash?

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 seems to get called on it anyway and all tests are green. Good catch!

@@ -86,7 +87,7 @@

public static final Token EMPTY = def(EMPTY_NAME, 0L);
public static final ValueExpression SELF = new Self();
public static final ValueExpression CURRENT_OFFSET = elvis(add(offset(SELF), len(SELF)), con(0));
public static final ValueExpression CURRENT_OFFSET = new CurrentOffset();
Copy link
Collaborator

Choose a reason for hiding this comment

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

It's back with a vengeance!

import io.parsingdata.metal.expression.value.ValueExpression;
import io.parsingdata.metal.token.Token;

public class ParseState {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Perhaps make final?

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 probably worth considering in general which classes should be made final: #223.

import io.parsingdata.metal.expression.value.ValueExpression;
import io.parsingdata.metal.token.Token;

public class ParseState {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Perhaps add some documentation 😈

@jvdb jvdb merged commit ec4782a into master Nov 5, 2017
@jvdb jvdb deleted the environment-to-parsestate branch November 5, 2017 19:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

Unexpected current offset behaviour while working with Sub
3 participants