source: tests/zombies/subrange.cfa @ b12e4ad

Last change on this file since b12e4ad was fd54fef, checked in by Michael Brooks <mlbrooks@…>, 4 years ago

Converting the project to use the new syntax for otype, dtype and ttytpe.

Changed prelude (gen), libcfa and test suite to use it. Added a simple deprecation rule of the old syntax to the parser; we might wish to support both syntaxes "officially," like with an extra CLI switch, but this measure should serve as a simple reminder for our team to try the new syntax.

  • Property mode set to 100644
File size: 2.4 KB
Line 
1// A small context defining the notion of an ordered otype.  (The standard
2// library should probably contain a context for this purpose.)
3trait ordered(T) {
4    int ?<?(T, T), ?<=?(T, T);
5};
6
7// A subrange otype resembling an Ada subotype with a base otype and a range
8// constraint.
9otype subrange(base_t | ordered(base_t), base_t low = 0, base_t high = 8) = base_t;
10
11// Note that subrange() can be applied to floating-point and pointer otypes, not
12// just integral otypes.
13//   This requires a "otype generator" extension to Cforall.  Type generators
14// must accept otype and non-otype parameters, which is beyond what we discussed
15// previously.  Type parameters must be usable in the declaration of
16// subsequent parameters: parameter T is used to declare parameters "low"
17// and "high".
18
19// Example usage:
20subrange(unsigned, 1, 31) day_of_month;
21subrange(char, 'a', 'z')  lcase;
22subrange(int, 0, (rand() & 0xF) ) foo;
23
24// What sorts of expressions can be used as arguments of otype generators?  Is
25// "subrange(int, 0, rand() & 0xF)" legal?  Probably.  The nearest C equivalent
26// to the "low" and "high" arguments is the array size in a variable-length
27// array declaration, and C allows assignment expressions there.
28
29// Convenient access to subrange bounds, for instance for iteration:
30forall (T, T low, T high)
31T lbound( subrange(T, low, high) v) {
32    return low;
33}
34
35forall (T, T low, T high)
36T hbound( subrange(T, low, high) v) {
37    return high;
38}
39
40// Example usage:
41unsigned lday = lbound(day_of_month);
42
43// Assignment from the base otype, with bounds checking.  I'll ignore the issue
44// of exception handling here.  Inlining allows the compiler to eliminate
45// bounds checks.
46forall (T | ordered(T), T low, T high)
47inline subrange(T, low, high) ?=?(subrange(T, low, high)* target, T source) {
48    if (low <= source && source <= high) *((T*)target) = source;
49    else abort();
50    return target;
51}
52
53// Assignment between subranges with a common base otype.  The bounds check
54// compares range bounds so that the compiler can optimize checks away when the
55// ranges are known to overlap.
56forall (T | ordered(T), T t_low, T t_high, T s_low, T s_high)
57inline subrange(T, t_low, t_high) ?=?(subrange(T, t_low, t_high)* target,
58                                      subrange(T, s_low, s_high) source) {
59    if ( (t_low <= s_low || t_low <= source)
60         && (s_high <= t_high || source <= t_high) ) *((T*)target) = source;
61    else abort();
62    return target;
63}
Note: See TracBrowser for help on using the repository browser.