Subject: Re: Proposing a new if-else syntax

From: Dominik Vogt <[email-masked]>
Date: Sun, 24 Feb 2002 01:42:09 +0100

On Mon, Aug 06, 2001 at 12:05:51AM +0000, Mikhael Goikhman wrote:
> On 05 Aug 2001 13:34:02 +0200, Dominik Vogt wrote:
> > 
> > How about this enhancement to conditional commands:
> > 
> >   Next (conditions) { false-action } true-action
> > 
> > This would allow an "else" case in all conditional commands
> > without the need to store a return code of these commands.  For
> > example:
> > 
> >   AddToFunc ToggleWindow
> >   + I Next ($0) { Exec $0 } Close
> 
> This may work, but is this the best possible solution? This syntax is not
> very readable and having else-command before then-command does not make it
> better. As before there is still a limit to one command in both branches,
> so you are forced to create small functions without a real need. It also
> adds a problem of escaping curly brackets in else-command when needed.
> What about parsing of nested conditional commands, braces in braces? :)
> It seems that an idea of 2 commands on the same line is not very good.
> 
> Here is my revised proposal that solves all problems described above.
> 
> There are 2 constructs, one is long and one is short, both may be mixed:
> 
>   if Next (conditions) {
>     then-commands, one per line
>   }
>   else {
>     else-commands, one per line
>   }
> 
>   if Next (conditions) then-command
>   else else-command

[SNIP, see mailing list archive for more details]

I've made a shot at the "if-else" syntax.  Now, all conditional
commands (and only conditional commands) have a return code that
can be true (1), false (0) or error (-1).  There are three new
conditional commands:

  Cond (returncode) command
  CondCase (returncode) command

These two execute the command only if the last conditional
command returned the given return code.

  Break

is not strictly a conditional command but terminates execution of
a complex function.  It only makes sense to be used in some
conditional context.  Example:

  AddToFunc PickWindowRaiseAndDeiconify
  + I Pick
  + I Cond (-1) Break
  + I Raise
  + I Iconify off

Return codes are only defined inside complex functions and are not
passed to sub functions or vice versa.  There is also a new
variable $[cond.rc] that is expanded to the last return code.
This is invalid outside complex functions or in conditional
commands.  The code is not well tested yet but complete.  I've no
problem to change it again if we can think of something better.
Now that the funtion arguments allow to pass a return code it is
easy to make changes.  If you want to play with it, be sure to
read the new parts of the man page (commands and CONDITIONAL
COMMANDS section).

Bye

Dominik ^_^  ^_^

 --
Dominik Vogt, [email-masked]
Reply-To: [email-masked]
--
Visit the official FVWM web page at <URL:http://www.fvwm.org/>.
To unsubscribe from the list, send "unsubscribe fvwm-workers" in the
body of a message to [email-masked].
To report problems, send mail to [email-masked]

---

From: Mikhael Goikhman <[email-masked]>
Date: Wed, 27 Feb 2002 00:43:29 +0000

> command returned the given return code.
[...]
> read the new parts of the man page (commands and CONDITIONAL

This is a good solution to the if-else problem.

However I may remind that my latest patch did a bit more. I feel that this
extra functionality could be useful, although more thoughts may be needed.

Every command not only conditionals could return status code (0 or Success
by default). For example, Read (NoFile) and ModuleSynchronous (Timeout).

I don't think limiting return codes to commands inside functions is
required (it is easier to implement, yes). This may be solved together
with "+" command validity by keeping some global data (in Scr) for every
pipe separately. I.e. last_added_item and rc should be local.

About names. Maybe to use "CondStatus" or generally "Status", not "Cond".
(Like some shells have $status that is another name for $? return code.)
Also I suggest a command "Preserve" that preserves the previous status.
I.e. your "CondCase (NoMatch)" could be "Preserve Status (NoMatch)".
This Preserve command is useful by itself, not only before Status command.

Status names should not be boolean names. "Match", "NoMatch", "Error".
Numbers are also ok, but "true" or "off" are not too much informative.

CondCase does not currently work.

Also $[cond.rc] outside of functions may be expanded to 0, not to itself,
but this is not important if "if-else" is limitted to functions only.

Regards,
Mikhael.

---

From: Dominik Vogt <[email-masked]>
Date: Wed, 27 Feb 2002 07:17:12 +0100

> by default). For example, Read (NoFile) and ModuleSynchronous (Timeout).

I did not say that other commands *can* not have a return code but
that they *do* not have one.  My intentions was to keep the return
code of conditionals separate from normal return codes.  The
cond_rc function argument can easily be replaced with a return
structure that can store multiple types of return codes.  We
shouldn't mix both because it would become hard to understand for
example

  Current (foobar) Read <file>

returns (the rc of Read or the rc of Current?).

> pipe separately. I.e. last_added_item and rc should be local.

Yes, it would be nice if return codes work in scripts too.

> (Like some shells have $status that is another name for $? return code.)

First, I think that the names I chose are brain dead.  The reason
for "Cond" is to indicate that it uses the return code of
CONDitional commands.  Otherwise I'd simply have used "Else".
"CondCase" resembles the "switch/case" in C where you can check
against many values in a single call.

> This Preserve command is useful by itself, not only before Status command.

It's not necessary if we keep the return code of conditionals
separate from other return codes.

> CondCase does not currently work.

Can you give me an example?
 
> but this is not important if "if-else" is limitted to functions only.

I should rather have said that the behaviour outside a function is
undefined.

Bye

Dominik ^_^  ^_^

-- 
Dominik Vogt, email: [email-masked]
LifeBits Aktiengesellschaft, Albrechtstr. 9, D-72072 Tuebingen
fon: ++49 (0) 7071/7965-0, fax: ++49 (0) 7071/7965-20
--
Visit the official FVWM web page at <URL:http://www.fvwm.org/>.
To unsubscribe from the list, send "unsubscribe fvwm-workers" in the
body of a message to [email-masked].
To report problems, send mail to [email-masked]

---

From: Mikhael Goikhman <[email-masked]>
Date: Wed, 27 Feb 2002 10:58:05 +0000

> shouldn't mix both because it would become hard to understand for

If you agree about return codes for other commands, I am not sure having 2
kinds of return codes is needed. It is easy to invent a case when 3 kinds
of return codes or more are possible. How about to have these:

  * one for the last conditional (3 possible values)
  * one for the last complext function, they may just: Return any_number
  * one for the last, say, Exec/PipeRead (returns system's status code)
  * one for the last command (including all commands above too?)
  * one to bring them all and in the darkness bind them...

No, this is a joke, I think having one return code for all commands is ok.
If conditionals are commands and not language constructs, they should
behave like all other commands. But we probably should first see some real
life usages to decide about this.

> returns (the rc of Read or the rc of Current?).

It should return rc of Current. If someone needs to branch over Read, he
should do this in a function:

  Current (foobar) ReadOrWrite

> separate from other return codes.

But then it is nice to preserve the previous status of other commands.

> Can you give me an example?

Any example that works with Cond does not work with CondCase for me.
This is not expanding problem, just replace $0 with CondCase.

AddToFunc TestCondCommand
+ I Next ($1) Nop
+ I $0 (0) Echo ($0 0)
+ I $0 (1) Echo ($0 1)
+ I $0 (-1) Echo ($0 -1)

TestCondCommand Cond XTerm       # nothing is echoed, ok
TestCondCommand Cond _none_      # 0 and 1 are echoed, ok
TestCondCommand CondCase XTerm   # nothing is echoed
TestCondCommand CondCase _none_  # nothing is echoed

Regards,
Mikhael.

---

From: Mikhael Goikhman <[email-masked]>
Date: Wed, 27 Feb 2002 11:40:51 +0000

On 27 Feb 2002 10:58:05 +0000, Mikhael Goikhman wrote:
> > We shouldn't mix both because it would become hard to understand for
> > example
> > 

Sorry, I was too fast to reply.

It should return:

  * Current syntax: SyntaxError
  * Current failed: NoMatch
  * Read syntax:    SyntaxError
  * Read passed:    Success
  * Read failed:    NoFile

Note, there is no Match status, it is usually Success instead.

If you think this is a mix, yes, but it is not different from this:

  Current (foobar) Next (foobar2) Close

For me it should return:

  * Current syntax: SyntaxError
  * Current failed: NoMatch
  * Next syntax:    SyntaxError
  * Next failed:    NoMatch
  * Close syntax:   SyntaxError
  * Close passed:   Success
  * Close failed:   NoWindow

What should it return as it is now? Which is more useful? :)

I remember I thought about all this several months ago, and my decision
was one return code for all commands should be enough, functions may be
used to refine it. The only alternative is to keep an array of status
codes, one per a command in the line (three in the last Close example).

Regards,
Mikhael.

---

From: Dominik Vogt <[email-masked]>
Date: Wed, 27 Feb 2002 12:53:05 +0100

> On 27 Feb 2002 07:17:12 +0100, Dominik Vogt wrote:
[snip]
> behave like all other commands.

The commands are not language constructs, but the return codes
are.  To be honest, I limited the return codes to conditionals
because it will be a major effort to properly define the correct
return codes of all existing commands in a consistent way.  To
give all commands a return code, each and every command has to be
modified and the return codes defined carefully.

> But we probably should first see some real

Agreed.

[snip]

> > against many values in a single call.

How about the names

  IfRc/SwitchRc or RcIf/RcSwitch

instead?  (And if we have a 'Preserve' prefix it should be
'PreserveRc'.

> TestCondCommand CondCase _none_  # nothing is echoed

Doh.  Boolean values can't be 0 or one.  Nothing of the above
could have worked.  You to use symbolic names like "True" and
"False".  Anyway, I've fixed it.  The argument can now be either
a number (0/1/-1) or a symbol (Match/NoMatch/Error).  The example
works now for me with both commands.

Bye

Dominik ^_^  ^_^

---

From: Dominik Vogt <[email-masked]>
Date: Wed, 27 Feb 2002 13:12:02 +0100

> What should it return as it is now? Which is more useful? :)

I don't know, but I do know that you did not get the idea what the
"error" return code stands for in the current code.  The idea was
to use it if the pre conditions to run the command at all are not
fulfilled, e.g.  if you issue "Pick" but select no window.  This
is quite different from syntax errors.  Handling syntax errors may
not be necessary at all.  Fvwm already prints error messages in
this case.

Bye

Dominik ^_^  ^_^

---

From: Mikhael Goikhman <[email-masked]>
Date: Wed, 27 Feb 2002 12:20:13 +0000

> not be necessary at all.  Fvwm already prints error messages in

Of course, "Error" (better to be "Canceled") as it is now has nothing to
do with "SyntaxError" or "NoFile" or "NoWindow" that I used as future
status codes.

Regards,
Mikhael.

---

From: Mikhael Goikhman <[email-masked]>
Date: Thu, 28 Feb 2002 18:43:37 +0000

> modified and the return codes defined carefully.

It is easy to do that all commands return Success without changing any.

> instead?  (And if we have a 'Preserve' prefix it should be

I still prefer the name "Status" (or if you like "OnStatus").

But if we want some mnemonics, how about "On" and "PreserveStatus" (I am
speaking about general status codes, not only conditionals):

  Current (Raised) Lower
  On (NoMatch) Current Raise

and:

  Read file1
  PreserveStatus On (Success) Read file2
  On (NoFile) Read file3

Regards,
Mikhael.