I am trying to determine how to manage types and conversions between types within a compiler that I am writing. The compiler is being written in C#.
There are a number of different kinds of types.
- Classes (read only / not mutable)
- Mutable Types (Which contain another type. Think the opposite of C++ const.)
- Generic Types (With constraints referring to types)
- etc
The problem I am trying to solve is, given two types, how can I determine whether one can be converted to the other. (eg. Allow a mutable type to be assigned to the read only version of the type)
My first thought was to use a virtual method and a visitor. However, since types can depend on others (e.g. A mutable type is a wrapper referring to another type.), this can cause the number of cases that need to be handled to balloon. I am looking for a design that keeps this to a minimum.
6
The problem I am trying to solve is, given two types, how can I determine whether one can be converted to the other.
In your language design, you have a well defined set of rules for your type system. A
is a subtype of B
if and only if these conditions hold. C
can be assigned to a variable of type D
if and only if these other conditions hold. And you do the paperwork to prove that your type system is consistent (you can’t get into a state where the rules are broken).
Then, for implementation it’s fairly straightforward. You define some classes to define your various type forms – often derived from some common type baseclass so the concrete types can be used wherever your language expects a type. Then you write these rules into nice static (possibly recursive) binary predicates that tell you if for these two types, do the conditions hold.
Yes, that often means a bunch of if T is GenericType
ugliness. You can get around that a little by using dynamic
and doing dynamic dispatch on the predicates. I’m not sure that’s particularly cleaner.
The good thing about the static predicates is that they are absurdly easy to unit test, and should be a near 1:1 translation of your type system on paper. They’re hard to screw up, and they provide clear documentation to future programmers (likely you) about what the rules are.
1