Next: TC-4 Given Code, Previous: TC-4 Goals, Up: TC-4 [Contents][Index]
Type checking is optional, invoked by --types-compute. As for the computation of bindings, this option only handles programs with no object construct. To perform the type-checking of programs with objects, use --object-types-compute.
Implementing overloaded functions in Tiger is an option, which requires the implementation of a different type checker, triggered by --overfun-types-compute (see TC-A). The option --typed/-T makes sure one of them was run.
1 + "2"
$ tc int-plus-string.tig
$ tc -T int-plus-string.tig error→int-plus-string.tig:1.5-7: type mismatch error→ right operand type: string error→ expected type: int ⇒5
The type checker shall ensure loop index variables are read-only.
/* error: index variable erroneously assigned to. */ for i := 10 to 1 do i := i - 1
$ tc -T assign-loop-var.tig error→assign-loop-var.tig:3.3-12: variable is read only ⇒5
When there are several type errors, it is admitted that some remain hidden by others.
unknown_function(unknown_variable)
$ tc -T unknowns.tig error→unknowns.tig:1.1-34: undeclared function: unknown_function ⇒4
Be sure to check the type of all the constructs.
if 1 then 2
$ tc -T bad-if.tig error→bad-if.tig:1.1-11: type mismatch error→ then clause type: int error→ else clause type: void ⇒5
Be aware that type and function declarations are recursive by chunks. For instance:
let type one = { hd : int, tail : two } type two = { hd : int, tail : one } function one(hd : int, tail : two) : one = one { hd = hd, tail = tail } function two(hd : int, tail : one) : two = two { hd = hd, tail = tail } var one := one(11, two(22, nil)) in print_int(one.tail.hd); print("\n") end
$ tc -T mutuals.tig
In case you are interested, the result is:
$ tc -H mutuals.tig >mutuals.hir
$ havm mutuals.hir 22
The type-checker must catch erroneous inheritance relations.
let /* Mutually recursive inheritance. */ type A = class extends A {} /* Mutually recursive inheritance. */ type B = class extends C {} type C = class extends B {} /* Class inherits from a non-class type. */ type E = class extends int {} in end
$ tc --object-types-compute bad-super-type.tig error→bad-super-type.tig:3.12-29: recursive inheritance: A error→bad-super-type.tig:6.12-29: recursive inheritance: C error→bad-super-type.tig:10.26-28: class type expected, got: int ⇒5
Handle the type-checking of TypeDecs
with care in
object::TypeChecker
: they are processed in three steps, while
other declarations use a two-step visit. The object::TypeChecker
visitor proceeds as follows when it encounters a TypeDecs
:
This three-pass visit allows class members to make forward references to
other types defined in the same block of types, for instance,
instantiate a class B
from a class A
(defined in the same
block), even if B
is defined after A
.
let /* A block of types. */ class A { /* Valid forward reference to B, defined in the same block as the class enclosing this member. */ var b := new B } type t = int class B { } in end
$ tc --object-types-compute forward-reference-to-class.tig
(See object::TypeChecker::operator()(ast::TypeDecs&)
for more
details.
Next: TC-4 Given Code, Previous: TC-4 Goals, Up: TC-4 [Contents][Index]