source: translator/Tests/Syntax/Subrange.c @ 51b7345

ADTaaron-thesisarm-ehast-experimentalcleanup-dtorsctordeferred_resndemanglerenumforall-pointer-decaygc_noraiijacob/cs343-translationjenkins-sandboxmemorynew-astnew-ast-unique-exprnew-envno_listpersistent-indexerpthread-emulationqualifiedEnumresolv-newstringwith_gc
Last change on this file since 51b7345 was 51b7345, checked in by Peter A. Buhr <pabuhr@…>, 10 years ago

initial commit

  • Property mode set to 100644
File size: 2.4 KB
RevLine 
[51b7345]1// A small context defining the notion of an ordered type.  (The standard
2// library should probably contain a context for this purpose.)
3context ordered(type T) {
4    int ?<?(T, T), ?<=?(T, T);
5};
6
7// A subrange type resembling an Ada subtype with a base type and a range
8// constraint.
9type subrange(type 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 types, not
12// just integral types.
13//   This requires a "type generator" extension to Cforall.  Type generators
14// must accept type and non-type 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 type 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 (type T, T low, T high)
31T lbound( subrange(T, low, high) v) {
32    return low;
33}
34
35forall (type 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 type, with bounds checking.  I'll ignore the issue
44// of exception handling here.  Inlining allows the compiler to eliminate
45// bounds checks.
46forall (type 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 type.  The bounds check
54// compares range bounds so that the compiler can optimize checks away when the
55// ranges are known to overlap.
56forall (type 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.