Case of record
Original Reporter info from Mantis: niklasm
-
Reporter name: Niklas Martinsson
Original Reporter info from Mantis: niklasm
- Reporter name: Niklas Martinsson
Description:
Patch that extends "case" to also work with records.
The syntax used is the same as for records in const sections, but extented with ranges. If one (or more) fields are not specified then all, not previusly specified, values match for the missing field(s). When multiple cases match - can only happen if not all fields are specified - then the first match in source code order are used.
The code generation uses simple sequences of "if" statements, no optimizations are implemented.
Files for svn/fpc/trunk (fpc_trunk_compiler.patch and fpc_trunk_tests.patch):
* compiler\nset.pas
- Node/code creation, case overlap checks, ppu handling
* compiler\pstatmnt.pas
- Parsing, type checks
* tests\test\tcaserec*.pp
- Rewritten tcase*.pp tests to equivalent tests with record with one field
* tests\test\tcaserecf*.pp
- Tests that should fail
* tests\test\tcaserecs*.pp
- Tests that should succeed
Files for svn/fpcdocs/trunk (fpcdocs_trunk.patch):
* ref.tex
- Updated "The case statement" in Language reference guide
* syntax\case.syn
- Updated syntax diagram
Steps to reproduce:
Example:
type
TDayOfWeek = (sun,mon,tue,wed,thu,fri,sat);
var
d: record m, d: Integer; dow: TDayOfWeek; end;
...
case d of
(m: 1; d: 1): WriteLn('New Year''s Day');
(m: 10; d: 31): WriteLn('Halloween');
(m: 11; d: 22..28; dow: thu): WriteLn('Thanksgiving');
(m: 12; d: 24): WriteLn('Christmas Eve');
(m: 12; d: 25): WriteLn('Christmas Day');
(m: 12; d: 26): WriteLn('Boxing Day');
(m: 12; d: 31): WriteLn('New Year''s Eve');
(d: 13; dow: fri): WriteLn('Unlucky day');
(dow: sun): WriteLn('Sunday');
(dow: mon): WriteLn('Monday');
(dow: tue): WriteLn('Tuesday');
(dow: wed): WriteLn('Wednesday');
(dow: thu): WriteLn('Thursday');
(dow: fri): WriteLn('Friday');
(dow: sat): WriteLn('Saturday');
end;
Additional information:
This is similar to pattern matching in functional languages.
Same example written in Haskell:
data DayOfWeek = Sun | Mon | Tue | Wed | Thu | Fri | Sat
data TestRecord = R { d :: Int, m :: Int, dow :: DayOfWeek }
caseRecord :: TestRecord -> String
caseRecord day =
case day of
R{m = 1, d = 1} -> "New Year's Day"
R{m = 10, d = 31} -> "Halloween"
R{m = 11, d = d, dow = Thu} | d >= 22 && d <= 28 -> "Thanksgiving"
R{m = 12, d = 24} -> "Christmas Eve"
R{m = 12, d = 25} -> "Christmas Day"
R{m = 12, d = 26} -> "Boxing Day"
R{m = 12, d = 31} -> "New Year's Eve"
R{d = 13, dow = Fri} -> "Unlucky day"
R{dow = Sun} -> "Sunday"
R{dow = Mon} -> "Monday"
R{dow = Tue} -> "Tuesday"
R{dow = Wed} -> "Wednesday"
R{dow = Thu} -> "Thursday"
R{dow = Fri} -> "Friday"
R{dow = Sat} -> "Saturday"
Same example but using tuples:
caseTuple m d dow =
case (m, d, dow) of
( 1, 1, _) -> "New Year's Day"
(10, 31, _) -> "Halloween"
(11, d, Thu) | d >= 22 && d <= 28 -> "Thanksgiving"
(12, 24, _) -> "Christmas Eve"
(12, 25, _) -> "Christmas Day"
(12, 26, _) -> "Boxing Day"
(12, 31, _) -> "New Year's Eve"
(_, 13, Fri) -> "Unlucky day"
(_, _, Sun) -> "Sunday"
(_, _, Mon) -> "Monday"
(_, _, Tue) -> "Tuesday"
(_, _, Wed) -> "Wednesday"
(_, _, Thu) -> "Thursday"
(_, _, Fri) -> "Friday"
(_, _, Sat) -> "Saturday"
"_" in Haskell is a wildcard (equivalent to missing field).
Ranges are not supported in Haskell, a guard is used instead.
Mantis conversion info:
- Mantis ID: 34091
- Version: 3.0.4
- Monitored by: » @engkin (engkin), » @genericptr (Ryan Joseph), » Vincent (Vincent Snijders), » Cyrax (Cyrax), » @KaiBurghardt (Kai Burghardt), » Akira1364 (Akira1364), » @MageSlayer (Denis Golovan), » @CuriousKit (J. Gareth Moreton), » @PascalDragon (Sven Barth)