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 <gno...@gmail.com>
>
> On Tue, Aug 18, 2009 at 09:17, Derek Baum <derek.b...@paremus.com> wrote:
>
> > 2009/8/17 Guillaume Nodet <gno...@gmail.com>
> >
> > >
> > > 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

Reply via email to