Skip to content

Deprecation

TypeCheck1 has been deprecated.

Please refer to TypeSystem3.

Deprecated Documentation

In MontiCore, the TypeCheck is used to calculate the SymTypeExpression of a set of expressions, types and literals. This is made possible by traversing the AST of an expression, type or literal, calculating the SymTypeExpression of its subexpressions, -types or -literals and combining them to the SymTypeExpression of the main expression, type or literal.

Given infrastructure in MontiCore

What is the difference between TypeSymbols and SymTypeExpressions?

The TypeCheck uses the TypeSymbols of the BasicSymbols grammar and the handwritten SymTypeExpressions. While they are very similar, there is a big difference between them and when to use them. The TypeSymbols represent a type definition (example in Java: class List) while the SymTypeExpressions represent a type usage (example in Java: List). There is only one type definition, but there can be many type usages. The SymTypeExpression knows its corresponding TypeSymbol (like the type usage knows its definition) and can refer to its methods and fields.

So when talking about a type definition, a type symbol, which can be stored and is present only once in the symboltable, has to be used. A SymTypeExpression is not stored in the symboltable, but refers to the definition of its type (its corresponding TypeSymbol) in the symboltable. Thus, a SymTypeExpression can be used multiple times and represents the usage of a type.

The TypeCheck facade

The TypeCheck class of MontiCore is used as a facade to make TypeChecking easier for the user. It needs a Derive-Class and/or a Synthesize-Class to be instantiated. Here is a list of the methods and functions of the TypeCheck. * SymTypeExpression typeOf(ASTExpression expr) (uses the Derive-Class to derive a SymTypeExpression from an ASTExpression) * SymTypeExpression typeOf(ASTLiteral lit) (uses the Derive-Class to derive a SymTypeExpression from an ASTLiteral) * SymTypeExpression symTypeFromAST(ASTType type) (uses the Synthesize-Class to derive a SymTypeExpression from an ASTType) * static boolean compatible(SymTypeExpression left, SymTypeExpression right) (checks if the type of the right SymTypeExpression would be assignable to a variable with the type of the left SymTypeExpression) * static boolean isSubTypeOf(SymTypeExpression sub, SymTypeExpression sup) (checks if the type of sub is a subtype of the type of sup) * static boolean isInt(SymTypeExpression sym) (there are methods like this for all primitive types, checks if the SymTypeExpression represents the type 'int')

How does the TypeCheck work?

The TypeCheck can be used to derive a SymTypeExpression from an expression or type. For example, when using an ASTPlusExpression '3+4', the TypeCheck returns a SymTypeExpression representing the type 'int'. You can use the ASTPlusExpression as a parameter for the method typeOf of the TypeCheck facade. This method delegates the calculation to your Derive-Class. First it derives the SymTypeExpression of the subexpressions '3' and '4' (the LiteralExpressions used in the PlusExpression) and then it calculates the SymTypeExpression of the whole PlusExpression by combining the SymTypeExpressions of its subexpressions in the context of the '+' operator.

In general, the derivation of SymTypeExpressions for expressions first calculates the SymTypeExpressions of its subexpressions and (depending on the results) then combines these SymTypeExpression adequately to one SymTypeExpression for the whole expression.

Deriving the SymTypeExpression of a type is often easier than deriving the SymTypeExpression of an expression. The ASTMCPrimitiveType 'int' will result in a SymTypeExpression 'int', the ASTMCBasicGenericType 'java.util.Map' will result in a SymTypeExpression 'java.util.Map'.

The derivation of types is very similar to the derivation of expressions with regard to subtypes and subexpressions. If a type has subtypes (like type arguments), then the SymTypeExpressions representing these subtypes will be calculated first. They can be used to put together the SymTypeExpression of the whole type.

Because both types and expressions are converted into SymTypeExpressions, you can compare them. This is useful in the next example:

int a = "Hello";

The SymTypeExpression derived from the ASTPrimitiveType 'int' will be 'int', the SymTypeExpression derived from the ASTLiteralExpression "Hello" will be 'String'. In a CoCo, you can check if they are compatible by using the function 'compatible' of the TypeCheck facade.

I want to write a CoCo for my language that uses the TypeCheck - How?

You can use the TypeCheck facade. The facade needs a Derive-Class (for expressions and literals) and/or a Synthesize-Class (for types) and calculates the SymTypeExpression of your given expressions/literals/types.

Create a DelegatorVisitor which combines all expression grammars and literal grammars used by your language. The DelegatorVisitor needs to implement the Interface IDerive. Use this Delegator as Derive-Class in the TypeCheck facade. The Synthesize-Class depends on the types grammar you use (see above-mentioned classes). For an example of the Delegator-Visitor see here .

If you want to create a Derive-Class for your expression/literal grammar, you have to extend the Derive-Class of the supergrammar and implement the standard visitor of your language. There you can override the traverse methods for your expressions/literals so that it calculates the SymTypeExpression of the expression/literal (see implementation in one of the above-mentioned classes). You can add your visitor to the DelegatorVisitor later on. For an example of the Derive-Class for one language see here . For an example of the Synthesize-Class for one language see here

Writing a CoCo to check the correctness of your type/expression/literal should be easy now that you have the TypeCheck facade to use. Just use the correct Derive-Class and/or the correct Synthesize-Class as parameters and check if the SymTypeExpression of your expression or type is correctly calculated.

Example for a CoCo:

@Override
public void check(ASTExpression expr){
    YourDeriveClass deriveClass = new YourDeriveClass(...); //instance of your Derive-Class
    YourSynthesizeClass synthesizeClass = new YourSynthesizeClass(...); //instance of your Synthesize-Class
    TypeCheck check = new TypeCheck(synthesizeClass,deriveClass); //instance of the TypeCheck-facade, parameters are your Synthesize-Class and your Derive-Class
    if(!"double".equals(check.typeOf(expr).print())){ //test if your expression is of the correct type (here: double)
        Log.error(...); //your specified error message
    }
}

An example for the case that a plus expression needs to return 'int' can be found here .

Further Information