Skip to content

Extend PythonExpression substitution to simplify the notation#600

Closed
kenji-miyake wants to merge 7 commits intoros2:rollingfrom
kenji-miyake:extend-python-expression
Closed

Extend PythonExpression substitution to simplify the notation#600
kenji-miyake wants to merge 7 commits intoros2:rollingfrom
kenji-miyake:extend-python-expression

Conversation

@kenji-miyake
Copy link
Copy Markdown
Contributor

Related to #469, I supported the notation of $(eval $(var value) == 'abc').
I'm not sure whether I should support $(eval value == 'abc') as well, but I guess it's a bit difficult because the current system seems to automatically drop ''.

I'll send this Draft PR in order to get reviews from maintainers.

Kenji Miyake added 2 commits March 10, 2022 23:30
Signed-off-by: Kenji Miyake <kenji.miyake@tier4.jp>
Signed-off-by: Kenji Miyake <kenji.miyake@tier4.jp>
@kenji-miyake kenji-miyake force-pushed the extend-python-expression branch from 06b36f0 to f5c41b2 Compare March 10, 2022 14:33
@kenji-miyake
Copy link
Copy Markdown
Contributor Author

I extended TextSubstitution and the parser in f5c41b2 to support $(eval value == 'abc'), but I guess it's not allowed...

Kenji Miyake added 3 commits March 11, 2022 11:02
Signed-off-by: Kenji Miyake <kenji.miyake@tier4.jp>
Signed-off-by: Kenji Miyake <kenji.miyake@tier4.jp>
Signed-off-by: Kenji Miyake <kenji.miyake@tier4.jp>
@kenji-miyake kenji-miyake marked this pull request as ready for review March 11, 2022 03:04
@kenji-miyake
Copy link
Copy Markdown
Contributor Author

@ivanpauno Hello, would you kindly review this, please? 🙏

return str(eval(perform_substitutions(context, self.expression), {}, math.__dict__))
expressions = [perform_substitutions(context, [exp]) for exp in self.expression]

if len(expressions) == 3 and (expressions[1] in ['==', '!=']):
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@kenji-miyake I understand it's the easy path forward, but we can't merge a barely-implemented feature. IMHO, if we want $(eval) to be able to use launch configurations as variables, we need to inject launch configurations in eval()'s local scope.

CC @ivanpauno @wjwwood

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

we need to inject launch configurations in eval()'s local scop

Yeah that sounds better, the current proposal is too ad-hoc.

I'm not sure whether I should support $(eval value == 'abc') as well, but I guess it's a bit difficult because the current system seems to automatically drop ''.

Maybe this is a problem (?).
We probably need to modify the launch substitutions grammar to make it more flexible, which will require a bit of thinking.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thank you for your reviews!

we need to inject launch configurations in eval()'s local scop

Is there any sample code that does this? Unfortunately, I'm not so familiar with the design concept of launch. 😢

Anyway, I'll drop expanding LaunchConfiguration from this PR for now.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Reverted by 4cc38be.
@hidmic @ivanpauno Would you please teach me what else should I change? 🙏

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@hidmic @ivanpauno Friendly ping. Could you review this again? 🙇

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@hidmic Thank you for your comment!

What if an expression is supposed to expand to, the name of some constant like pi?

Hmm, I didn't care about the case. But I guess just adding an eval with try-cache can support it? 🤔

IMO to have this feature we need to revisit that grammar.

Yes, I agree with that. (I've changed this to a draft for now.)
How can I build a consensus on the syntax and move things forward?
Are there any design concept documents or plans for the eval syntax?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Or, how about adding eq and ne substitutions like #598?

$(eq $(var foo) 'bar')
$(ne $(var foo) 'bar')

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@kenji-miyake first of all, my apologies for the insane delay. I've been uber busy.

Now, circling back to this.

How can I build a consensus on the syntax and move things forward?

A concrete proposal is the way to go. You want to simplify notation by making $(var name) and name equivalent in $(eval ...) context. We agree with the intent, but we need a fully functional implementation i.e. not just for a few operators. One possible approach is to inject launch configurations in eval scope.

That doesn't solve the quoting issue though. In launch substitutions' grammar, arguments are delimited by spaces and so you need quotes to pass a single argument that includes a space e.g. '/my/very/unhelpful path'. Quotes must be dropped in these cases. When an $(eval) expression is not quoted, the parser will try to split expression into space delimited arguments, potentially dropping quotes from string literals, and the rest follows.

The only easy way I see we could avoid this is by instructing the substitution parser to skip the entire $(eval) expression. That means, no nested substitutions, tracking left and right parenthesis, and coming up with a special escaping mechanism for parenthesis so that something like $(anon $(eval data() + ')')) doesn't fall apart.

Are there any design concept documents or plans for the eval syntax?

IIRC there are no design documents about the syntax itself. Only the grammar.

how about adding eq and ne substitutions

That's definitely a simpler (better?) path forward.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@hidmic Hi, welcome back! No problem, I know ROS maintainers are quite busy. 😢
And thank you for your detailed explanation. But it's super difficult for me... I have to learn the grammar a lot.

That's definitely a simpler (better?) path forward.

Oh, it's good to hear that. Can I send a new PR to add eq/ne?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

eq/ne seem to be implemented in #649.

This reverts commit f5c41b2.

Signed-off-by: Kenji Miyake <kenji.miyake@tier4.jp>
@kenji-miyake kenji-miyake force-pushed the extend-python-expression branch from 4cc38be to 83e059e Compare March 11, 2022 15:15
if len(data) != 1:
raise TypeError('eval substitution expects 1 argument')
return cls, {'expression': data[0]}
if len(data) == 1:
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@kenji-miyake we should still catch len(data) == 0 and raise an exception.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 205e7cc.
And added a test.

return str(eval(perform_substitutions(context, self.expression), {}, math.__dict__))
expressions = [perform_substitutions(context, [exp]) for exp in self.expression]

if len(expressions) == 3 and (expressions[1] in ['==', '!=']):
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@kenji-miyake my apologies for the delay. I still think this is special casing to workaround the fact that, as @ivanpauno pointed out, the substitution grammar wasn't designed to deal with arbitrary Python expressions. What if an expression is supposed to expand to, the name of some constant like pi? That implicit quoting you're adding in line 79 would block that.

IMO to have this feature we need to revisit that grammar. And that's separate from simplifying $(var name) to name when used within $(eval ...).

@kenji-miyake kenji-miyake marked this pull request as draft March 30, 2022 12:56
Signed-off-by: Kenji Miyake <kenji.miyake@tier4.jp>
@kenji-miyake kenji-miyake force-pushed the extend-python-expression branch from d4135bf to 205e7cc Compare March 30, 2022 13:48
@kenji-miyake kenji-miyake requested a review from hidmic May 6, 2022 08:50
@audrow audrow changed the base branch from master to rolling June 28, 2022 14:19
@kenji-miyake
Copy link
Copy Markdown
Contributor Author

I believe I can close this thanks to #649.

@kenji-miyake kenji-miyake deleted the extend-python-expression branch September 9, 2022 01:37
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