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

Add support for plucking values with @ #89

Merged
merged 7 commits into from
Apr 22, 2021
Merged

Add support for plucking values with @ #89

merged 7 commits into from
Apr 22, 2021

Conversation

hildjj
Copy link
Contributor

@hildjj hildjj commented Apr 20, 2021

This still needs docs, and prototyping to make sure we can add other @-related things later.

See #38

@hildjj
Copy link
Contributor Author

hildjj commented Apr 20, 2021

I back-ported the code from pegjs:HEAD, and got the tests to run. Figured I'd check in here so people could start to comment. I'm not 100% sold on this being the way forward, but having something to comment on felt like the next step.

@@ -3,7 +3,7 @@
const asts = require("../asts");
const js = require("../js");
const op = require("../opcodes");
const VERSION = require('../../version')
const VERSION = require("../../version");
Copy link
Contributor Author

Choose a reason for hiding this comment

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

unrelated lint bug that needs to be landed even if this patch doesn't.

Copy link
Member

Choose a reason for hiding this comment

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

I think that this should be in the it's own PR or, at least, commit, together with other two unrelated changes in the package.json

]));

expect(pass).to.changeAST("start = 'a' @'b' @'c'", bytecodeDetails([
// write a tool to generate comments
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 decided to punt on making this pretty since we have #81 in the backlog.

@hildjj
Copy link
Contributor Author

hildjj commented Apr 21, 2021

I've fiddled around with the grammar, and this will work just fine if we want to add decorators later:

@start   // current start rule
@memoize("first", {lru: 12}) // we can decide how interesting we want the parameters to be
first = @"foo" " "

This was the use case I was most worried about impacting. I'm also interested in how we're going to do things like importing other grammars. Do people have existing syntax for that in other forks?

@hildjj hildjj marked this pull request as ready for review April 21, 2021 06:15
Copy link
Member

@Mingun Mingun left a comment

Choose a reason for hiding this comment

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

Also need to add an opcode description to the header comment of the generate-bytecode.js

examples/json.pegjs Outdated Show resolved Hide resolved
test/unit/compiler/passes/generate-bytecode.spec.js Outdated Show resolved Hide resolved
test/unit/compiler/passes/generate-bytecode.spec.js Outdated Show resolved Hide resolved
lib/compiler/passes/generate-bytecode.js Outdated Show resolved Hide resolved
);
}

if (node.expression.type.startsWith("semantic_")) {
Copy link
Member

Choose a reason for hiding this comment

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

It is better to forbid that on the grammar level. I understand that you just picked up the existing implementation, so that can be done in the follow up PR, but personally I prefer to keep the commit history as clean as we can (without "fix" commits). So if it possible it is better to make now

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The easiest fix is to just call error inside of LabeledExpression if the type of the expression is bad, but that feels like a cheat. It's important that @$[a-z]i+ works, which is also in PrefixedExpression. Refactoring the grammar to get all of that nuance in feels like it would be more confusing than the quick fix, though.

Opinions?

@Mingun
Copy link
Member

Mingun commented Apr 21, 2021

Do people have existing syntax for that in other forks?

I have one, but I don't like it more (pegjs/pegjs#308). I tend to use JS-familiar syntax:

import rule_name from 'grammar';
import {rule1, rule2 as alias} from "grammar";

// usage
start
  = rule_name
  / rule1
  / alias
  ;

grammar are usually will be path (relative or absolute, according to JS rules of the import clause) to the grammar, but it also can be any identifier. Really it will depend on the import resolver.

@hildjj
Copy link
Contributor Author

hildjj commented Apr 21, 2021

Also need to add an opcode description to the header comment of the generate-bytecode.js

@Mingun can you look at this please? I'm not familiar enough with the idioms used in those comments:

// [30] PLUCK
//
//        stack.pop(ip + 1);
//        stack.push(ip + 3);
//        ...
//        stack.push(ip + 3 + [ip + 2]);

the layout is [op.PLUCK, total_number_of_expression_items, number_of_plucks, pluck0, pluck1, ...]

@Mingun
Copy link
Member

Mingun commented Apr 21, 2021

In order to make bytecode compatible with my other PRs, that I plan to port in the nearing future (ranges) it will make sense if you change PLUCK opcode number to 36, as in my original implementation. That will save me time when I prepare ranges PR :). We always can renumber opcodes later.

Then the comment will look that:

// [36] PLUCK n, k, p1, ..., pK
//
//        value = [stack[p1], ..., stack[pK]]; // when k != 1
//        -or-
//        value = stack[p1];                   // when k == 1
//
//        stack.pop(n);
//        stack.push(value);
//

(stack is the stack of values, parsed from the input, and positions in the input, and the bytecode manipulates it. This comment say, that opcode PLUCK firstly gets k values from specified positions in the stack, then replaced the last n values in the stack with the array of the selected elements/one specified element)

@hildjj
Copy link
Contributor Author

hildjj commented Apr 21, 2021

change PLUCK opcode number to 36

Done. See if you're willing to live with my change to the semantic_ checks, please?

@hildjj
Copy link
Contributor Author

hildjj commented Apr 21, 2021

I'm going to squash this commit once I have @Mingun 's review of my latest changes.

Copy link
Member

@Mingun Mingun left a comment

Choose a reason for hiding this comment

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

Except the incorrect comment all good 👍 LGTM

Done. See if you're willing to live with my change to the semantic_ checks, please?

Yes, good change

Comment on lines 73 to 81
// [30] PLUCK
//
// stack.pop(ip + 1);
// stack.push(ip + 3);
// ...
// stack.push(ip + 3 + [ip + 2]);
//
Copy link
Member

Choose a reason for hiding this comment

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

That is not the same thing as I described. In the end stack should contain one Array object with k elements, not the k elements, as you might think from the current description

Suggested change
// [30] PLUCK
//
// stack.pop(ip + 1);
// stack.push(ip + 3);
// ...
// stack.push(ip + 3 + [ip + 2]);
//
// [36] PLUCK n, k, p1, ..., pK
//
// value = [stack[p1], ..., stack[pK]]; // when k != 1
// -or-
// value = stack[p1]; // when k == 1
//
// stack.pop(n);
// stack.push(value);
//

Copy link
Contributor Author

Choose a reason for hiding this comment

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

oh. heh, i didn't save that buffer. willfix

@hildjj
Copy link
Contributor Author

hildjj commented Apr 21, 2021

Squashed.

@Mingun
Copy link
Member

Mingun commented Apr 22, 2021

Just remembered: it is good practice to update CHANGELOG.md in the PRs, so when you prepare release it will be easy to grab all the changes

// Compiler pass to ensure the following are enforced:
//
// - plucking can not be done with an action block
// - cannot pluck a semantic predicate
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// - cannot pluck a semantic predicate

Checked in the grammar

Comment on lines 12 to 16
function reports(message, edgecases) {
it(message, () => {
edgecases.forEach(grammar => expect(pass).to.reportError(grammar));
});
}
Copy link
Member

Choose a reason for hiding this comment

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

Hadn't noticed before... need to check that location information in the error reports correct location. Here or whatever where similar checks is performed

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Willfix by undoing this reports function and inlining the two tests.

@hildjj
Copy link
Contributor Author

hildjj commented Apr 22, 2021

Just remembered: it is good practice to update CHANGELOG.md in the PRs, so when you prepare release it will be easy to grab all the changes

Good call, will do

@hildjj
Copy link
Contributor Author

hildjj commented Apr 22, 2021

OK, @Mingun I've got all of your feedback in, I think. Please double-check before I merge?

@hildjj
Copy link
Contributor Author

hildjj commented Apr 22, 2021

Fixes #38

Copy link
Member

@Mingun Mingun left a comment

Choose a reason for hiding this comment

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

For the sake of code purity, could you make a little rebase?

  • fix lint errors (single quote to double quote, etc.)
  • change matrix
  • add changelog for not mentioned changes
  • implement plucking without regenerating parser
    • actual implementation
    • documentation
    • changelog
    • tests
    • maybe examples
  • regenerate parser (examples also could be updated here)

In that case in the each point in the history project will able to build without errors and each commit will do the only one thing.

Fuhh... I think, that's all. Good work!

describe("compiler pass |reportIncorrectPlucking|", function() {
it("prevents \"@\" from being used with an action block", function() {
expect(pass).to.reportError("start1 = 'a' @'b' 'c' { /* empty action block */ }", {
message: "\"@\" cannot be used with an action block at line 1, column 14."
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
message: "\"@\" cannot be used with an action block at line 1, column 14."
message: "\"@\" cannot be used with an action block at line 1, column 14.",
location: {
start: { offset: 13, line: 1, column: 14 },
end: { offset: 17, line: 1, column: 18 }
}

Actually, text in the message should point to the beginning of the action block (opening {), but right now:

  • that information is unavailable (action block location covers expression and the action itself)
  • other check passes that work with actions also should be modified

So for now will live with that

@hildjj
Copy link
Contributor Author

hildjj commented Apr 22, 2021

For the sake of code purity, could you make a little rebase?

I'm willing to do that, but don't think i've done a rebase in that direction before. Can you point me to docs, or give me quick set of bullets on the mechanics, please?

@hildjj
Copy link
Contributor Author

hildjj commented Apr 22, 2021

nm, i found https://stackoverflow.com/a/6217314/8388 which has the info i need.

@hildjj
Copy link
Contributor Author

hildjj commented Apr 22, 2021

Done. I removed the matrix change, since @StoneCypher is making that change in his PR in progress.

@hildjj
Copy link
Contributor Author

hildjj commented Apr 22, 2021

@Mingun final-final approval? I want to get this landed and cut a release.

@Mingun
Copy link
Member

Mingun commented Apr 22, 2021

Yes, final 👍

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.

2 participants