| 1 | # Changes: | 
|---|
| 2 | ## 0. Introduce a new type of cast: Upcast or Enum Cast. | 
|---|
| 3 | The naming of the cast is not determined. | 
|---|
| 4 | ## 1. Updates on CastExpr::CastKind | 
|---|
| 5 | ``` | 
|---|
| 6 | enum CastKind { | 
|---|
| 7 | Default, // C | 
|---|
| 8 | Coerce, // reinterpret cast | 
|---|
| 9 | Return,  // overload selection | 
|---|
| 10 | Up // <------ NEW; Cast to a super type | 
|---|
| 11 | }; | 
|---|
| 12 | ``` | 
|---|
| 13 | Scope: All enumerations, including C enumeration, and CFA enumeration (typed and opague). | 
|---|
| 14 | Example Usage: | 
|---|
| 15 | ``` | 
|---|
| 16 | enum A { a }; | 
|---|
| 17 | enum B { b }; | 
|---|
| 18 | enum AB { inline A, inline B, ab }; | 
|---|
| 19 |  | 
|---|
| 20 | // Explicit (user called) up cast | 
|---|
| 21 | (AB) A.a; | 
|---|
| 22 | // Implicit (generated) up cast | 
|---|
| 23 | void foo(AB); | 
|---|
| 24 | foo(A.a); | 
|---|
| 25 | ``` | 
|---|
| 26 |  | 
|---|
| 27 | Aside: Expressions "(AB) a" or "foo(a)" don't introduce a upcast. Because enum AB is an enum type with elements AB.a, AB.b, and AB.ab. The expression "(AB) a" results in AB.a since it has a lower cost than "(AB) A.a". (no conversion/cast cost) | 
|---|
| 28 | ## 2. Why needs a new cast type | 
|---|
| 29 | The up cast is a special kind of a cast that requires "offset operations". | 
|---|
| 30 | ``` | 
|---|
| 31 | (AB) b.b; // is equivalent to | 
|---|
| 32 | (AB) ((unsigned int)b.b + OFFSET) // (AB)(0 + 1) | 
|---|
| 33 | ``` | 
|---|
| 34 | OFFSET is an constanct value: The OFFSET from B to AB is 1. It is the number of enumerators declared before the declaration "inline B". The statement "inline B" is after "inline A", where "inline A" introduces one enumerator. | 
|---|
| 35 |  | 
|---|
| 36 | Similarilty: | 
|---|
| 37 | ``` | 
|---|
| 38 | enum E { | 
|---|
| 39 | e; | 
|---|
| 40 | }; | 
|---|
| 41 | enum ABCDE { | 
|---|
| 42 | inline AB, | 
|---|
| 43 | C, D, | 
|---|
| 44 | inline E | 
|---|
| 45 | }; | 
|---|
| 46 | ``` | 
|---|
| 47 | The OFFSET from type E to type ABCDE is "# of element from AB" + 1 (C) + 1 (D), 4. | 
|---|
| 48 | But we don't want to introduce the OFFSET_OPERATION + 4 on every cast from type E to type ABCDE. Sometime, the compiler introduce a generated cast (AB) E.e to maniputate expression type. It actually happens when after we have an upcast, we need to cast the expression (E.e + 4) to type ABCED, without "upcast it agains". It is a widening cast with no upcast effect. | 
|---|
| 49 |  | 
|---|
| 50 | ## 3. Implication | 
|---|
| 51 | A new pass "Upcast Pass" where happens before the resolver to identify Upcast. A cast (T) y for variable y with type Y is an upcast only if there is a "Upcast Path" from type T to type Y. | 
|---|
| 52 | For example, | 
|---|
| 53 | ``` | 
|---|
| 54 | enum T { | 
|---|
| 55 | ..., inline A, ... | 
|---|
| 56 | }; | 
|---|
| 57 | enum A { | 
|---|
| 58 | ..., inline B, ... | 
|---|
| 59 | }; | 
|---|
| 60 | enum B { | 
|---|
| 61 | ..., inline Y, ... | 
|---|
| 62 | }; | 
|---|
| 63 | enum Y { ... }; | 
|---|
| 64 | ``` | 
|---|
| 65 | There is a upcast Path from Y to T: Y -(upcast)-> B -(upcast)-> A -(upcast)-> T. The pass runs an algorithm to determine if there is such path exist from Y to T. | 
|---|
| 66 | Aisde: The cast is "bottom-up": (T)((A)((B) y)), casting from the smaller type to the bigger type. But the algorithm is search "top-down", from T to Y. Because inline information is stored in the super type. T knows it inlines A, A knows it inline B, but not vise versa. | 
|---|
| 67 | The CastKind will replaced by "CastKind::Up" | 
|---|
| 68 |  | 
|---|
| 69 | The unifier in the resolver identify a function calls "foo(A.a)" performs an upcast, by running the algorithmn from AB to A, and introduce the implicit upcast in the Application Expression "foo((AB) A.B)". | 
|---|
| 70 |  | 
|---|
| 71 | For all Upcast, the resolver replace them with 1. a offset operation (a functiion call ?+?(expr, OFFSET)), 2 and a Coerce cast from the lower type to the supper type. (There are some cast between enum type to integral type in between to satisfy the function ?+?(). We can ignore them for now.) | 
|---|
| 72 |  | 
|---|
| 73 | Upcast should only exisit in the AST between the "Upcast Pass" and the "Resolver". They are essentially labels saying: this node needs an offset operation. | 
|---|
| 74 |  | 
|---|
| 75 | "Upcast Pass" is a subpass of resolver. It does not need to be a standalone pass. It can be a special step when the compiler visits a CastExpr nocde. | 
|---|
| 76 |  | 
|---|
| 77 |  | 
|---|