Recent

Author Topic: implicit domain-check in case-statement  (Read 5449 times)

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Re: implicit domain-check in case-statement
« Reply #15 on: July 09, 2019, 02:35:22 pm »
The C# switch statement will go to "default:"
The Pascal case switch goes to else..... Which is the same...

That was the problem stated in the OP, that it doesn't: instead it causes a segfault.

"case cv of ..." can crash (SIGSEGV) if cv is not in cv-type domain.
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

nanobit

  • Full Member
  • ***
  • Posts: 160
Re: implicit domain-check in case-statement
« Reply #16 on: July 13, 2019, 09:45:16 pm »
Further (last?) note, with some additions, the scope should be wide enough now.

We have a causal chain (1+2):
1) The existence of undefined enum values:
Undefined enum values are the consequence of the underlying type (integer),
which is a basic type, directly accessible with pointer and writable without special operators.
Supported is casting: enum := Tenum(int), stream.read( enum, sizeof(enum)), move() and some more.

The incoming int value might also be intentionally undefined. Example:
We are inside a dll which knows only the old Tenum = (e0, e1, e2).
And dll clients use newer (backward (downward) compatible) Tenum = (e0, e1,e2, e3).
The dll provider creates no newer dll version, but declares:
Minimum requirement: Tenum = (e0, e1, e2) for parameter or element of file format.
This is essentially like with named integer constants, which can be extended over time.

The compiler should not be allowed to auto-reduce the enum storage size (userdefined).
Only user-written operations are allowed to change the enum value,
for example reducing the enum value to bitpacked-field size.

The bitpacked field is still a (raw) memory field which may contain invalid values:
fieldsize 1 bit: (e0); value 1 is undefined
fieldsize 2 bits: (e0, e1, e2);  value 3 is undefined
Bitpacked fields have more limits: less undefined values, no pointer to field, and more.
The user knows where packed fields are declared, and he can optionally check wide values
before size-reducing assigns: bitpackedRecord.enm := enm;
Operations with bitpacked fields are fully transparent.

(Note: A truly confined enum would need to be implemented as datatype
with overloaded operators, which prevent direct write to the internal storage.
In theory, one could add such enum type with extra keyword "guarded")

2) The consequence of undefined enum values:
The representation of invalid values is defined (thus defined behavior can follow),
and only the specific meaning of every invalid value is undefined.
Delphi, C#, C++ do it: they reliably go to else-branch.

Most common usage is, the case-statement is interested only in the labeled values:
Here it's not relevant whether the unlabeled value is in range or not (may crash in fpc);
and the else-branch is often empty or absent. But users can also insert checks in else-branch.

Another usage: The aim is to reduce undefined behavior, to increase software fault tolerance:
Minimize unnecessary risks, save lives, ensure operations in harsh environments (maybe extraterrestrial : ) ).
Think the "impossible", a databit is wrong (in memory or stream (was ok on last check)),
at normal stage of execution, where only normal operations (case, if, in) exist.
The goal: We should not crash (mission failure). Fault-tolerant operations should
not depend on a single bit, but on more conditions (redundancy).
If one condition is wrongly signaled, then it's still not relevant, because other paths can detect its wrongness.
Very important: The programmer should not be required to place an explicit enum check
before every normal operation (case, if, in), and this is possible already in Delphi, C#

Another analogy not mentioned previously:
TList.IndexOf( invalidPtr);  returns -1 (without crash)

Thaddy

  • Hero Member
  • *****
  • Posts: 14205
  • Probably until I exterminate Putin.
Re: implicit domain-check in case-statement
« Reply #17 on: July 13, 2019, 10:28:20 pm »
"last" should suffice..
Specialize a type, not a var.

nanobit

  • Full Member
  • ***
  • Posts: 160
Re: implicit domain-check in case-statement
« Reply #18 on: July 15, 2020, 08:02:42 am »
Important link to a newer concise version:
https://bugs.freepascal.org/view.php?id=36983

The essence is, don't forget that the case-statement is about testing
(while the origin of test values is outside and given, possibly by others):

integer(enm) is not the only possible construct to check the definedness of enums:
1) integer(enm) check, used internally by all following highlevel constructs:
2) own test function: isDefined(enm)
3) isDefined-operator: https://bugs.freepascal.org/view.php?id=33603
4) case-statement (currently unsupported, be aware)

 

TinyPortal © 2005-2018