OK, I think I now understand the problem FELIX-1471 is trying to solve.
Sorry it's taken so long :-(
I have my own example that demonstrates it,
just to confirm that I have the same understanding.
> x = <echo aa; <echo ab; echo ac | grep -n a | tac>>
aa
1 ab 3 ac
IllegalArgumentException: Command not found: *:1
The return value of tac (and the value assigned to x) is
" 1 ab 3 ac".
The problem is that the <> used for grouping also evaluates the result,
causing the exception.
FELIX-1471 proposes using () for grouping and $() for evaluation.
So the above example would become:
> x = (echo aa; (echo ab; echo ac | grep -n a | tac))
and
> installandstart = { <installbundle <$baseURI resolve $0>> start }
would become:
> installandstart = { $(installbundle $($baseURI resolve $0)) start }
FWIW I still think it is possible to solve this without introducing $(),
just by stopping <> at the start of a statement from evaluating:
ka...@root> x = <echo aa; <echo ab; echo ac | grep -n a | tac>>
aa
1 ab 3 ac
ka...@root> <osgi:echo a b>
a b
ka...@root> <<osgi:echo a b>>
a b
ka...@root> <<bundle 0> tostring>
org.apache.felix.framework [0]
However, the $() approach works fine too and so I'm happy to support this,
so we can get this issue resolved.
I have tested the latest FELIX-1471.patch and it mostly works OK:
> echo aa; (echo ab; echo ac | grep -n a | tac)
aa
1 ab 3 ac
but fails when the result of () is in an assignment:
ka...@root> x = (echo aa; (echo ab; echo ac | grep -n a | tac))
org.osgi.framework.InvalidSyntaxException: expected value|substring
at org.apache.felix.framework.FilterImpl.<init>(FilterImpl.java:81)
at
org.apache.felix.framework.Felix.getServiceReferences(Felix.java:2893)
Derek
2009/8/18 Guillaume Nodet <[email protected]>
>
> On Tue, Aug 18, 2009 at 09:17, Derek Baum <[email protected]> wrote:
>
> > 2009/8/17 Guillaume Nodet <[email protected]>
> >
> > >
> > > So in short, the patch does the following:
> > > * replace <> with $()
> > > * use ( ) for grouping commands when on the edge of the command
> > > * make the number of evaluation predictable
> > > * have a syntax and semantic which is mostly (fully) in sync with bash
> > > * re-evaluate / split expanded arguments that are not quoted
> >
> >
> >
> > I can still see no reason for having () and $() as two separate operators.
> > This unncessarily compllicates syntax without adding any new capability.
> >
> > You previously gave the following example to demonstrate the need for a
> > separate grouping operator:
> >
> > >The grouping operator is imho needed to be able to order pipes and
> > columns:
> > > (echo a ; echo b) | tac
> > > echo a ; (echo b | tac)
> >
> > However, this example works fine with the existing <> execution quotes:
> >
> > ka...@root> <echo a; echo b> | tac
> > ab
> > ka...@root> echo a; <echo b | tac>
> > a
> > b
> >
> > Do you have any other example or use case that demonstrates the need for a
> > separate grouping operator?
> >
> > () in bash is NOT only used for grouping - it executes the command within
> > (), just like the existing <>.
> > $() in bash executes and captures stdout into a string - equivalent to
> > <command args | tac> in gogo.
> >
>
> Well the key difference between those operators in bash is the number of
> times the evaluation happen.
>
> ( ) does not change the number of times a command will be evaluated, that's
> why i call it grouping.
> What i mean is that if you remove the ( ), the commands will be executed the
> same number of time.
> echo a => echo a
> ( echo a ) => echo a
> ( ( echo a ) ) => echo a
> All of those will produce the same result.
>
> $( ) will increment the number of evaluation each time it's used, and is
> therefore not idemptotent.
> echo echo echo a => echo echo a
> $(echo echo echo a) => echo a
> $( $( echo echo echo a) ) => a
>
> I don't really see how we can conflate both operators using < > or any other
> syntax.
> With the current state of gogo, you're not really sure how many times
> evaluation will happen.
>
>
> >
> > To try to understand the need for separate () and $() operators, I have
> > taken the gogo TestParser.java from the FELIX-1471.patch and replaced both
> > $() and () with <>. I then ran the test against the unpatched code.
> >
> > All tests worked except some newly added tests within
> > testGroupingAndEvaluation() like:
> >
> > assertEquals("a", c.execute("<echo echo a>") + "");
> >
> > This fails because <echo echo a> evaluates to the String "echo a", which is
> > then evaluated as a command and the command 'echo a' is not found.
> >
> > assertEquals("a", c.execute("$(echo echo a)") + "");
> >
> > This works because of the complex re-parsing done by $() that you describe
> > below.
>
>
> Right, and I think this reparsing of arguments should be done anyway. So
> maybe we need a separate jira for that one.
>
> I think I understood where our uncomprehension comes from. I first started
> to have a look at FELIX-1325 (throwing an exception when the can't be found,
> even if it has no arguments). The problem is that all those issues are
> linked.
> What you describe above works only because when you have a single token on
> the command line and that no command is found, the token is simply returned.
> This means that in all the above examples, the number of evaluation is not
> really important, because executing "a" will return "a".
> This hides some real issues imho, as the following tests, that all pass on
> trunk show:
>
> assertEquals("echo echo", c.execute("echo echo echo"));
> assertEquals("echo", c.execute("<echo echo echo>"));
> assertEquals("", c.execute("<<echo echo echo>>"));
>
> assertEquals("echo a", c.execute("echo echo a"));
> assertEquals("a", c.execute("<echo echo a>"));
> assertEquals("a", c.execute("<<echo echo a>>"));
>
>
> So the behavior of < > is that it run the command(s) inside it *and*
> evaluates it. It's not only grouping.
>
> Now, let's take an example:
>
> assertEquals("a", c.execute("echoout \"a\nb\" | grep a | capture"));
> assertEquals("b", c.execute("echoout \"a\nb\" | grep b | capture"));
> assertEquals("ab", c.execute("<echoout \"a\nb\" | grep a | capture>
> ; <echoout \"a\nb\" | grep b | capture> | capture"));
>
> assertEquals("", c.execute("<echoout \"echo\ngrep\" | grep echo |
> capture> ; <echoout \"echo\ngrep\" | grep grep | capture> | capture"));
>
> The first two tests are ok. The third test is equivalent to "test1 ; test2
> | capture".
> Remember that atm ';' takes precedence over '|'.
>
> Now the last test is the same as the third one, but with different values.
> The output should be "echogrep", but isn't, due to the additional
> evaluation.
> The third test would also fail if we apply FELIX-1325 afaik.
>
>
> >
> > In bash, if you need to re-parse some text, you use the 'eval' command:
> >
> > $ eval $(echo echo '$HOME')
> > /Users/derek
> >
> > We could take exactly the same approach in gogo, by adding a simple eval
> > command for use on the rare occassions when it is required.
> >
> > Derek
> >
> >
> >
> > >
> > >
> > > I'm happy to discuss things further, but the major problem is related to
> > > make the evaluation predictable, which sounds easy, but is not really ...
> > > And this require to re-evaluate / split the expanded arguments.
> > > See the following example:
> > > assertEquals("a", c.execute("$($(echo echo echo a)) | capture"));
> > > The "echo echo echo a" command is executed and prints "echo echo a". This
> > > result is inside $() so it has to be interpreted as a full command line,
> > > not
> > > as a single argument which would be a string "echo echo a" as this would
> > > return a command not found.
> > >
> > >
> >
>
>
>
> --
> Cheers,
> Guillaume Nodet
> ------------------------
> Blog: http://gnodet.blogspot.com/
> ------------------------
> Open Source SOA
> http://fusesource.com