Discussion:
Semantics of CASE statement
(too old to reply)
August Karlstrom
2017-09-07 11:04:17 UTC
Permalink
Let's consider the following example:

MODULE test;

IMPORT Out;

TYPE
Animal = RECORD END;
Cat = RECORD (Animal) END;
Dog = RECORD (Animal) END;

VAR
x: Cat;
y: Dog;

PROCEDURE P(VAR x: Animal);
BEGIN
CASE x OF
Animal: Out.String("animal"); Out.Ln
| Cat: Out.String("cat"); Out.Ln
| Dog: Out.String("dog"); Out.Ln
END
END P;

BEGIN
P(x);
P(y)
END test.

What should be the output from this module?


Regards,
August
August Karlstrom
2017-09-07 11:41:00 UTC
Permalink
Post by August Karlstrom
CASE x OF
Animal: Out.String("animal"); Out.Ln
| Cat: Out.String("cat"); Out.Ln
| Dog: Out.String("dog"); Out.Ln
END
According to section 12.4 in Project Oberon this statement should be
interpreted as

IF x IS Animal THEN
Out.String("animal"); Out.Ln
ELSIF x IS Cat THEN
Out.String("cat"); Out.Ln
ELSIF x IS Dog THEN
Out.String("dog); Out.Ln
END

What I find unintuitive here is that this makes the order of the case
labels significant. With integral labels the order is irrelevant.

https://www.inf.ethz.ch/personal/wirth/ProjectOberon/PO.Applications.pdf


-- August
Richard
2017-09-07 18:10:03 UTC
Permalink
Post by August Karlstrom
What I find unintuitive here is that this makes the order of the case
labels significant. With integral labels the order is irrelevant.
It's the same as e. g. with exception catch sections in Java. Order is
important if overlapping cases shall be allowed.

Or can you think of a more intuitive solution which still allows
checking special cases and general cases in one conditional statement?

Richard
Pascal J. Bourguignon
2017-09-07 23:59:18 UTC
Permalink
Post by Richard
Post by August Karlstrom
What I find unintuitive here is that this makes the order of the case
labels significant. With integral labels the order is irrelevant.
It's the same as e. g. with exception catch sections in Java. Order is
important if overlapping cases shall be allowed.
Or can you think of a more intuitive solution which still allows
checking special cases and general cases in one conditional statement?
The compiler could, at worst at the price of a global analysis,
determine the latice of overlapping cases, and order the tests from the
most specific fist.

But it wouldn't necessarily be a good thing, because the human
programmers themselves may not know this lattice by heart, and therefore
may be surprised by the choice of the compiler…

This is notably true for exceptions; the documentation note that such a
function signals such exception, but nobody goes out of his way to look
up the exception and check the superclasses.
--
__Pascal J. Bourguignon
http://www.informatimago.com
August Karlstrom
2017-09-08 14:35:23 UTC
Permalink
Post by Pascal J. Bourguignon
Post by Richard
Post by August Karlstrom
What I find unintuitive here is that this makes the order of the case
labels significant. With integral labels the order is irrelevant.
It's the same as e. g. with exception catch sections in Java. Order is
important if overlapping cases shall be allowed.
Or can you think of a more intuitive solution which still allows
checking special cases and general cases in one conditional statement?
The compiler could, at worst at the price of a global analysis,
determine the latice of overlapping cases, and order the tests from the
most specific fist.
But it wouldn't necessarily be a good thing, because the human
programmers themselves may not know this lattice by heart, and therefore
may be surprised by the choice of the compiler…
This is notably true for exceptions; the documentation note that such a
function signals such exception, but nobody goes out of his way to look
up the exception and check the superclasses.
Now that I think of it, putting the declared type (e.g. Animal) as the
last label will work as an ELSE clause, so semantically the CASE
statement does support an "else" clause for type labels.

-- August
s***@gmail.com
2017-09-08 12:08:02 UTC
Permalink
Post by August Karlstrom
What I find unintuitive here is that this makes the order of the case
labels significant. With integral labels the order is irrelevant.
I never liked the merge of the Oberon-2 WITH behaviour with the CASE statement for this reason. In wirthian language CASE
Diego Sardina
2017-09-08 12:18:47 UTC
Permalink
Post by August Karlstrom
What I find unintuitive here is that this makes the order of the case
labels significant. With integral labels the order is irrelevant.
I don't like the merge of Oberon-2 WITH behaviour with the CASE statement for this reason. In all wirthian languages the CASE statement has been always a jump table, the WITH statement in Oberon-2 was a syntactic sugar for IFs and type guards.

They of course have a different semantics.


--
Diego Sardina
Lance Schwerdfager
2017-12-29 02:53:17 UTC
Permalink
On Thu, 7 Sep 2017 13:04:17 +0200, August Karlstrom
Post by August Karlstrom
MODULE test;
IMPORT Out;
TYPE
Animal = RECORD END;
Cat = RECORD (Animal) END;
Dog = RECORD (Animal) END;
VAR
x: Cat;
y: Dog;
PROCEDURE P(VAR x: Animal);
BEGIN
CASE x OF
Animal: Out.String("animal"); Out.Ln
| Cat: Out.String("cat"); Out.Ln
| Dog: Out.String("dog"); Out.Ln
END
END P;
BEGIN
P(x);
P(y)
END test.
What should be the output from this module?
Regards,
August
Since the intent of the CASE statement here is to distinguish the
subclass of an Animal instance (and not the value of the Animal
instance), it shouldl fail to compile. Using the Oberon-2 WITH
statement to perform type testing (in the style of a CASE statement)
is one way to get around this.

Regards,
Lance
c***@gmail.com
2017-12-29 11:48:11 UTC
Permalink
Post by Lance Schwerdfager
On Thu, 7 Sep 2017 13:04:17 +0200, August Karlstrom
Post by August Karlstrom
MODULE test;
IMPORT Out;
TYPE
Animal = RECORD END;
Cat = RECORD (Animal) END;
Dog = RECORD (Animal) END;
VAR
x: Cat;
y: Dog;
PROCEDURE P(VAR x: Animal);
BEGIN
CASE x OF
Animal: Out.String("animal"); Out.Ln
| Cat: Out.String("cat"); Out.Ln
| Dog: Out.String("dog"); Out.Ln
END
END P;
BEGIN
P(x);
P(y)
END test.
What should be the output from this module?
Regards,
August
Since the intent of the CASE statement here is to distinguish the
subclass of an Animal instance (and not the value of the Animal
instance), it shouldl fail to compile. Using the Oberon-2 WITH
statement to perform type testing (in the style of a CASE statement)
is one way to get around this.
Regards,
Lance
I disagree. The CASE statement above is legal as it stands. WITH in Oberon-2 behaves exactly the same as CASE in Oberon-07.

WITH
x: Cat DO Out.String("cat"); Out.Ln
| x: Dog DO Out.String("dog"); Out.Ln
| x: Animal DO Out.String("animal"); Out.Ln
END

gives the output

cat
dog

whereas

WITH
x: Animal DO Out.String("animal"); Out.Ln
| x: Cat DO Out.String("cat"); Out.Ln
| x: Dog DO Out.String("dog"); Out.Ln
END

gives the output:

animal
animal

Regards,
Chris Burrows
CFB Software
http://www.astrobe.com

Loading...