/**
* Main strategy of the Dryad type checker
*
* @author Martin Bravenboer
*/
module dryad/type-check/Main
imports
dryad/type-check/-
dryad/type-check/primary/-
dryad/type-check/stm/-
dryad/util/jtree
dryad/util/jtree-overlays
dryad/model/-
dryad/model/bytecode-class
dryad/model/source-class
dryad/source/Attributes
dryad/jls/conversions/Boxing
dryad/jls/conversions/Unboxing
dryad/jls/conversions/CaptureConversion
dryad/jls/conversions/AssignmentConversion
dryad/jls/conversions/NumericPromotions
dryad/jls/types/Primitive
dryad/jls/types/Reference
dryad/jls/types/Reifiable
dryad/jls/expressions/AssignmentOperators
strategies
/**
* Annotate type information on a Java compilation unit or fragment of code.
*
* @type List(CompilationUnit Object) -> List(CompilationUnit Object)
*/
dryad-type-checker =
let
fail-s(s) = fail // higher-order strategy
in
dryad-type-checker(fail-s)
end
/**
* Annotate type information on a Java compilation unit or fragment of code.
*
* @param extension(rec) Strategy that may rewrite a (non-Java) term during the traversal.
*
* @type List(CompilationUnit Object) -> List(CompilationUnit Object)
*/
dryad-type-checker(extension : (a -> a) -> a) =
rec rec(
extension(rec)
<+ dryad-tc-declare-this-class(all(rec))
<+ dryad-tc-declare-params(all(rec))
<+ dryad-tc-declare-local-variables(rec)
<+ dryad-tc-declare-fields(all(rec))
<+ dryad-tc-foreach(rec)
<+ apply-to-reference(rec)
<+ all-consnil(rec)
; try(dryad-attribute(rec))
)
strategies
/**
* Attach attributes to a term.
*
* @type t -> t
*/
dryad-attribute(rec) =
where(
( dryad-attributes-of
<+ dryad-attributes-of(rec)
<+ default-dryad-attributes-of(rec)
) => attr
)
; if <is-list> attr then
!<id> {^attr}
else
!<id> {attr}
end
/**
* Default strategy for producing the attributes of an expression.
*
* By default, attribute a term only with its type, determined by applying
* the dryad-type-of rule.
*
* @type t -> List(Attribute)
*/
default-dryad-attributes-of(rec) =
![Type(<dryad-type-of <+ dryad-type-of(rec)>)]
dryad-type-of(rec) =
fail
/**
* Provide a library interface to the TypeOf dynamic rule, for client
* applications that import Dryad as a library.
*/
strategies
set-TypeOf(|name, value) =
rules(TypeOf : name -> value)
scope-TypeOf(s) =
{| TypeOf : s |}
strategies
dryad-tc-declare-params(continue) =
?MethodDec(MethodDecHead(_, _, _, _, params, _), _)
; {| TypeOf :
where(<map(dryad-tc-declare-param)> params)
; continue
|}
dryad-tc-declare-params(continue) =
?ConstrDec(ConstrDecHead(_, _, _, params, _), _)
; {| TypeOf :
where(<map(dryad-tc-declare-param)> params)
; continue
|}
dryad-tc-declare-params(continue) =
?Catch(param, _)
; {| TypeOf :
where(<dryad-tc-declare-param> param)
; continue
|}
dryad-tc-declare-param =
?Param(_, type, Id(x))
; rules(TypeOf: Id(x) -> type)
strategies
/**
* Handle local vardec statement by declaring the type of the
* variables it declares for the tail of the list of statements in
* which it occurs.
*
* @type List(BlockStm) -> List(BlockStm)
*/
dryad-tc-declare-local-variables(rec) =
?[LocalVarDecStm(_) | _]
; {| TypeOf :
[ LocalVarDecStm(dryad-tc-declare-local-vardec(rec)) | id]
; [id | rec]
|}
/**
* Define the type of a local variable declared in for loop.
*/
dryad-tc-declare-local-variables(rec) =
?For(LocalVarDec(_, _, _), _, _, _)
; {| TypeOf :
For(dryad-tc-declare-local-vardec(rec), rec, rec, rec)
|}
/**
* Util for dryad-tc-declare-local-variables. Don't invoke directly.
*/
dryad-tc-declare-local-vardec(rec) =
LocalVarDec(id, ?type, map(dryad-tc-declare-var(|type); rec))
/**
* Declare the type of class fields for a class body.
*/
dryad-tc-declare-fields(continue) =
?ClassBody(_)
; {| TypeOf :
ClassBody(map(try(dryad-tc-declare-field-dec(continue))))
; continue
|}
/**
* Util for dryad-tc-declare-fields. Don't invoke directly.
*/
dryad-tc-declare-field-dec(rec) =
instanceof-JavaSourceField
; apply-to-reference(
FieldDec(id, ?type, map(dryad-tc-declare-var(|type)); rec)
)
/**
* Declare the type of a variable in dynamic rule 'TypeOf'
*/
dryad-tc-declare-var(|type) =
(?VarDec(Id(x)) + ?VarDec(Id(x), _));
rules(TypeOf : Id(x) -> type)
strategies
/**
* @todo Handle formal type parameters.
* @todo Enums, Annotations.
*/
dryad-tc-declare-this-class(continue) =
instanceof-JavaSourceClass
; ?class
; where(get-canonical-name => name)
; where(
if <is-interface> class then
!InterfaceType(name, None())
else
!ClassType(name, None())
end => type
)
; {| ThisType, ThisClass :
rules(
ThisType : _ -> type
ThisClass : _ -> class
)
; apply-to-reference(continue)
|}
strategies
/**
* Generic implementation for determining the type of a numeric
* binary operator (*, /, %, +, -).
*
* @type (Expr, Expr) -> Expr
*/
dryad-type-of-num-bin-op =
?(e1, e2);
where(
<type-attr> e1 => t1
; <type-attr> e2 => t2
; <is-convertible-to-numeric-type> t1
; <is-convertible-to-numeric-type> t2
)
; <binary-numeric-promotion-of-types> (t1, t2)