This assignment regards the building of internal compiler structures
for the class hierarchy and the checking of well-formedness of the
class hierarchy. It encompasses the three compiler phases
Nameresolving, Environments and
Hierarchy. You must hand in three files
nameresolving.ml, environment.ml and
hierarchy.ml that extend the skeleton. You must also post
an entry in your group blog that explains how your code works and
which problems you have encountered and solved in the process.
Nameresolving
The Nameresolving phase resolves all syntactically
recognizable uses of named types (class and interface types) to their
canonical names (implemented by the CanonicalNames module
found in canonicalNames.ml).
Transformations
The Nameresolving phase transforms an AST of type
Weedingast (or WAst for short) defined in
weedingast.ml into Nameresolvingast (or
NAst for short) defined in
nameresolvingast.ml.
The changes on the AST include:
- For each source file, split the imports into fully resolved single
imports and ondemand imports.
- For each class (Joos 2: or interface) declaration, fill out the
type_decl's NAst.type_canonical_name
field to contain the fully qualified name of the declaration.
- Replace every occurrence of type
Ast.namedtype with
type CanonicalName.t
I.e., where the named type has been resolved to the canonical name
of the class or interface represented by the type
(which may be in the program or in the class library).
- Consequently, replace every occurrence of
Ast.typeexp
with the corresponding Types.typeexp.
I.e., replace any Ast.Named with Types.Named
containing the canonical name that the named type resolved to.
Implementations
- Implement the
resolve_name_from_identifier function
according to the rules in Section
6.5.5.1 of the JLS. Remember that all compilation units implicitly
import java.lang.*.
Checks
- Check that no single-type-import declarations clash with the
class (Joos 2: or interface) defined in the same file.
(error_single_type_import_clash_with_class)
- Check that no two single-type-import declarations clash with
each other. (error_two_single_type_imports_clash)
- Check that all types actually resolve to defined types in the
program or the class library. (error_unresolved_type)
- Check that no prefixes (consisting of whole identifiers) of fully
qualified types themselves resolve to types.
(error_prefix_resolves_to_type)
- Check that all simple type names resolve uniquely, i.e. not
to types from more than one import-on-demand declaration.
(error_ambiguous_class_name)
- Check that all import-on-demand declarations refer to existing
packages. (error_non_existing_package)
- Check that no package names or prefixes hereof
(consisting of whole identifiers) of declared packages,
single-type-import declarations or used import-on-demand
declarations resolve to qualified types,
i.e. types not in the default package. An import-on-demand
declaration is considered used if some type has been
resolved through it. Note that java.lang.* is
always considered as a used
import-on-demand. (error_package_clash_with_type)
Environment
The Environment phase builds a type environment for all
types used in the program.
Type specifications and the type environment are defined by the module
Types in the file types.ml. A type
environment is a mapping from canonical names to named-type
specifications (i.e., classes and interfaces). The type environment
has type Types.type_env.
Transformations
- Construct the named-type specification of all classes (Joos 2: and interfaces)
in the program. Put the specification into
the type environment under the correctly resolved canonical name.
- When constructing field specifications put None in its constant value.
This value is needed in the later constant-folding phase.
Checks
- Check that no two fields in the same class have the same name
(error_duplicate_field).
- Check that no two local variables with overlapping scope
have the same name. (error_duplicate_variable).
- Check that no two declared types (classes or interfaces) have the same canonical name.
(error_duplicate_type).
Implementations
- The
lookup_named_type method searches first the type
environment and then the classpath for a type with the given name.
It returns None if the given name does not resolve.
It is already implemented in the skeleton.
Hierarchy
The Hierarchy phase resolves all inheritance
relationships for classes, interfaces, methods and fields.
The rules governing this phase are described in chapters
8 and
9
of the JLS. In particular, inheritance and hiding of fields is described in
8.3, and
inheritance, overriding and hiding of methods is described in
8.4.6 and
9.4.1.
Note that the work done in this phase follows the structure of the
class hierarchy, rather than the structure of the AST. For the
purposes of inheritance, not only the classes and interfaces in the
program but also those in the class library will have to be
handled. The checks need only be performed on the classes (Joos 2: and
interfaces) declared in the program itself.
Implementations
- Implement the methods
lookup_method,
lookup_field and is_super_type. How you
internally represent the data structures needed to answer these
queries is up to you.
- The
lookup_named_type method searches first the type
environment and then the classpath for a type with the given name.
It throws an exception if the given name does not resolve.
It is already implemented in the skeleton.
Checks
The checks to be performed by the Hierarchy phase
correspond to the constraints mentioned in the slides, plus some
additional checks for Joos 2.
- The type mentioned in the extends clause of a class must be a class
(8.1.3,
simple constraint 1). (error_extends_non_class)
- All types mentioned in the implements clause of a class must be
interfaces
(8.1.4,
simple constraint 2). (error_implements_non_interface)
- An interface must not be mentioned more than once in the same
implements clause of a class
(8.1.4,
simple constraint 3). (error_repeated_interface)
- A class must not extend a final class
(8.1.1.2,
8.1.3,
simple constraint 4). (error_extends_final_class)
- Joos 2: All types mentioned in the extends clause of an interface must be
interfaces
(9.1.2).
(error_implements_non_interface)
- Joos 2: An interface must not be mentioned more than once in the same
extends clause of an interface (missing from the JLS but enforced by javac).
(error_repeated_interface)
- A class or interface must not depend on itself
(8.1.3,
9.1.2,
well-formedness constraint 1). (error_circular_inheritance)
- A class or interface must not declare two methods with the same
name and parameter types
(8.4,
9.4,
well-formedness constraint 2). ( error_duplicate_method)
- A class must not declare two constructors with the same
parameter types
(8.8.2,
simple constraint 5). ( error_duplicate_constructor)
- A class or interface must not contain (declare or inherit) two methods
with the same name and parameter types but different return types
(8.1.1.1,
8.4,
8.4.2,
8.4.6.3,
8.4.6.4,
9.2,
9.4.1,
well-formedness constraint 3). (error_different_return_type)
- A class that has (declares or inherits) any abstract methods must be abstract
(8.1.1.1,
well-formedness constraint 4). (error_class_must_be_abstract)
- A nonstatic method must not replace a static method
(8.4.6.1,
well-formedness constraint 5). (error_non_static_replace_static)
- A static method must not replace a nonstatic method
(8.4.6.2,
well-formedness constraint 5). (error_static_replace_non_static)
- A method must not replace a method with a different return type
(8.1.1.1,
8.4,
8.4.2,
8.4.6.3,
8.4.6.4,
9.2,
9.4.1,
well-formedness constraint 6). (error_different_return_type)
- A protected method must not replace a public method
(8.4.6.3,
well-formedness constraint 7). (error_protected_replace_public)
- If method m2 replaces method m1, then for every checked exception E2
declared in the throws clause of m2, there must exist an exception E1
declared in the throws clause of m1, such that E2 is a subclass of E1
(8.4.4,
8.4.6.3,
8.4.6.4,
9.2,
9.4.1,
well-formedness constraint 8). (error_illegal_throws_in_replace)
- A method must not replace a final method
(8.4.3.3,
well-formedness constraint 9). (error_replace_final)
- A class must not declare two fields with the same name
(8.3,
well-formedness constraint 10). (This is already done in environment)
- A class or interface must not inherit two different fields with the same name
(Joos restriction,
well-formedness constraint 11). (error_inherited_field_clash)