--  $Id: java_inheritance.ty,v 1.11 99/08/10 14:48:09 hnilsson Exp $
-- /***************************************************************************/
-- /*               Copyright (C) 1997-1999 INRIA Sophia-Antipolis            */
-- /*                      I. Attali, D. Caromel, M. Russo                    */
-- /*                               Projet OASIS                              */
-- /*                           Rt. des Lucioles, BP 93,                      */
-- /*                       F-06902 Sophia Antipolis cedex                    */
-- /*                            (+33) 4 92 38 76 31                          */
-- /*                            All rights reserved                          */
-- /***************************************************************************/
program java_inheritance is
use java;
use PSP;

import
   getClassAPIDirectAncestor (
      |- OptTypeName -> OptTypeName ) ,
   getAPIObjectAttributes (
      |- OptTypeName -> Pairs )
   from java_api;

import
   getObjectType ( ObjectId |- Objects -> Type ) ,
   getRealTypeAndName (
      Type, VariableDeclaratorId -> Type, Identifier ) ,
   getRealName ( VariableDeclaratorId -> Identifier ) ,
   getMethodNameAndParameters (
      MethodDeclarator -> Identifier, Parameters )
   from java_object_list;

import getCompilationUnit ( _ )
   from jfunctions;

import appendtree ( _, _, _ ) , diff ( _, _ ) , not_eq ( _, _ ) , eq ( _, _ )
   from  prolog() ;

var TVValue: Val;
var TVMethodDecl: MethodDeclarator;

   set getFieldDeclaration is
   --SC: Retrieves the field declaration for the given field. Returns false if 
   --SC: it is not found.
   --
   --JC: Objects, Current class name where the fields is sought, Field arguments
   --JC: (useful to find the right method or constructor declaration), 
   --JC: True (for a constructor declaration)/ False (for an attribute or method
   --JC: declaration)
   --JC: |- Field name -> Field declaration, Name of the class that owns this field (can be
   --JC: a different name from the given one. In this case, it is
   --JC: an ancestor), True if found/False otherwise.   
   judgement
      Objects, Identifier, Vals, Bool |- Identifier -> FieldDeclaration, Identifier, Bool;

   FieldInTheGivenClass:
      getClassDeclaration( |- ClName -> ClDec )
      &
      getFieldDeclarationInClass(
         ObjL, FName, ArgL, TF |- ClDec -> FDec, true() )
      --------------------------------
      ObjL, ClName, ArgL, TF |- FName -> FDec, ClName, true()  ; 

   FieldInAnAncestorNotInTheGivenClass:
      getClassDeclaration( |- ClName1 -> ClDec )
      &
      getFieldDeclarationInClass(
         ObjL, FName, ArgL, TF |- ClDec -> _, false() )  &
      getDirectAncestor( |- ClName1 -> Ancestor )
      &
      getFieldDeclarationInAncestors(
         ObjL, Ancestor, ArgL, TF |- FName -> FDec, ClName2, true() )
      --------------------------------
      ObjL, ClName1, ArgL, TF |- FName -> FDec, ClName2, true()  ; 
   end getFieldDeclaration; 

   set getFieldDeclarationInClass is
   --SC: Retrieves the field declaration for the given field. Returns false if 
   --SC: it is not found. The first call is done with a class declaration. The 
   --SC: field declaration list of this class is retrieved and each field 
   --SC: declaration is checked to find the sought field. 
   --
   --JC: Objects, Sought field name, Field arguments (useful to find the right 
   --JC: method or constructor declaration), True (for a constructor 
   --JC: declaration)/ False (for an attribute or method declaration) 
   --JC: |- Field declaration (Class, Field list, Constructor, Method, Attribute)
   --JC: -> Field declaration, True if found/False otherwise.
   judgement
      Objects, Identifier, Vals, Bool |- java -> FieldDeclaration, Bool;

   GetClassFieldDeclarationList:
      ObjL, FName, ArgL, TF1 |- FDecL -> FDec, TF2
      --------------------------------
      ObjL, FName, ArgL, TF1 |- classDeclaration(_, _, _, _, FDecL) -> FDec, TF2  ; 

   EmptyFieldDeclarationList:
      _, _, _, _ |- fieldDeclarations[] -> _, false()  ; 

   FirstFieldAnalysis_GoodOne:
      ObjL, FName, ArgL, TF |- FDec -> FDec, true()
      --------------------------------
      ObjL, FName, ArgL, TF |- fieldDeclarations[FDec._] -> FDec, true()  ; 

   FirstFieldNotTheGoodOne_TailAnalysis:
      ObjL, FName, ArgL, TF1 |- FDec1 -> _, false()  &
      ObjL, FName, ArgL, TF1 |- FDecL -> FDec2, TF2
      --------------------------------
      ObjL, FName, ArgL, TF1 |- fieldDeclarations[FDec1.FDecL] -> FDec2, TF2  ; 

   ConstructorDeclarationWhenConstructorNotSought:
      _, _, _, false() |- constructorDeclaration(_, _, _, _) -> _, false()  ; 

   MethodDeclaration_NotTheSoughtMethodName:
      getMethodNameAndParameters(
         TVMethodDecl -> MethName, _ )  &  diff( FName, MethName )
      --------------------------------
      _, FName, _, false() |- methodDeclaration(_, _, TVMethodDecl, _, _) -> _, false()  ; 

   MethodDeclaration_SoughtMethodName_SignatureAnalysis:
      getMethodNameAndParameters(
         TVMethodDecl -> MethName, ParamL )  &  diff( MethName, identifier "main" )
      &
      isTheParameterListCorrespondingToTheArgumentList(
         ObjL, ArgL |- ParamL -> TF )
      --------------------------------
      ObjL, MethName, ArgL, false() |-
       methodDeclaration(ModL, RType, TVMethodDecl, ThrowL, Block) ->
          methodDeclaration(ModL, RType, TVMethodDecl, ThrowL, Block), TF  ; 

   MainMethodDeclaration:
      getMethodNameAndParameters(
         TVMethodDecl -> identifier "main", _ )
      --------------------------------
      _, identifier "main", vals[], false() |-
       methodDeclaration(ModL, RType, TVMethodDecl, ThrowL, Block) ->
          methodDeclaration(ModL, RType, TVMethodDecl, ThrowL, Block), true()  ; 

   FieldVariableDeclaration_VariableDeclarationAnalysis:
      isADirectAttribute( FName |- IdentL -> TF )
      --------------------------------
      _, FName, _, false() |-
       fieldVariableDeclaration(ModL, Type, IdentL) -> fieldVariableDeclaration(ModL, Type, IdentL), TF  ; 

   MethodDeclarationWhenAConstructorIsSought:
      _, _, _, true() |- methodDeclaration(_, _, _, _, _) -> _, false()  ; 

   ConstructorDeclaration_NotTheSoughtConstructorName:
      _, ConstName1, _, true() |-
       constructorDeclaration(_, constructor(ConstName2, _), _, _) -> _, false()  ; 
               provided diff( ConstName1, ConstName2 );

   ConstructorDeclaration_SoughtConstructorName_SignatureAnalysis:
      isTheParameterListCorrespondingToTheArgumentList(
         ObjL, ArgL |- ParamL -> TF )
      --------------------------------
      ObjL, ConstName, ArgL, true() |-
       constructorDeclaration(ModL, constructor(ConstName, ParamL), ThrowL, Block) ->
          constructorDeclaration(ModL, constructor(ConstName, ParamL), ThrowL, Block), TF  ; 

   FieldVariableDeclaration_ConstructorSought:
      _, _, _, true() |- fieldVariableDeclaration(_, _, _) -> _, false()  ; 
   end getFieldDeclarationInClass; 

   set isADirectAttribute is
   --SC: Looks for a given field name in the variables declarator list. 
   --
   --JC: Sought field name 
   --JC: |- Variable declarator list (that belongs to a class) 
   --JC: -> True if the field was found in the given variable declarator list/ 
   --JC: False otherwise 
   judgement Identifier |- VariableDeclarators -> Bool;

   FoundAttribute_InitializedAttr:
      getRealName( VarDeclId -> AttrName )
      --------------------------------
      AttrName |- variableDeclarators[initializedVariable(VarDeclId, _)] -> true()  ; 

   FoundAttribute_NonInitializedAttr:
      getRealName( VarDeclId -> AttrName )
      --------------------------------
      AttrName |- variableDeclarators[VarDeclId] -> true()  ; 

   NotFoundAttribute_InitializedAttr:
      getRealName( VarDeclId -> AttrName2 )  &
      diff( AttrName1, AttrName2 )
      --------------------------------
      AttrName1 |- variableDeclarators[initializedVariable(VarDeclId, _)] -> false()  ; 

   NotFoundAttribute_NonInitializedAttr:
      getRealName( VarDeclId -> AttrName2 )  &
      diff( AttrName1, AttrName2 )
      --------------------------------
      AttrName1 |- variableDeclarators[VarDeclId] -> false()  ; 

   RecursiveRule_TheFirstInitializedVariableIsNotTheSoughtOne:
      getRealName( VarDeclId -> AttrName2 )  &
      diff( AttrName1, AttrName2 )  &  AttrName1 |- AttrL -> TF
      --------------------------------
      AttrName1 |- variableDeclarators[initializedVariable(VarDeclId, _).AttrL] -> TF  ; 

   RecursiveRule_TheFirstNonInitializedVariableIsNotTheSoughtOne:
      getRealName( VarDeclId -> AttrName2 )  &
      diff( AttrName1, AttrName2 )  &  AttrName1 |- AttrL -> TF
      --------------------------------
      AttrName1 |- variableDeclarators[VarDeclId.AttrL] -> TF  ; 
   end isADirectAttribute; 

   set isTheParameterListCorrespondingToTheArgumentList is
   --SC: Checks if the parameter list and the argument list have the same number
   --SC: of elements and if the corresponding elements have the same type.
   --
   --JC: Objects, Values 
   --JC: |- Parameters 
   --JC: -> True if the parameter list and the argument list have the same
   --JC: number of elements and the same types for each element/False otherwise
   judgement Objects, Vals |- Parameters -> Bool;

   EmptyLists_Correspondence:
      _, vals[] |- parameters[] -> true()  ; 

   NotTheSameNumberOfArguments_NoCorrespondence:
      haveTheSameNumberOfElements( ArgL, ParL -> false() )
      --------------------------------
      _, ArgL |- ParL -> false()  ; 

   SameNumberOfArgumentAndSameTypeForAllTheArguments_Correspondence:
      haveTheSameNumberOfElements( ArgL, ParL -> true() )
      &
      haveCompatibleTypeForEachElement( ObjL |- ArgL, ParL -> TF )
      --------------------------------
      ObjL, ArgL |- ParL -> TF  ; 
   end isTheParameterListCorrespondingToTheArgumentList; 

   set haveCompatibleTypeForEachElement is
   --SC: Checks if the corresponding members of the two given lists have the 
   --SC: same type.
   --
   --JC: Objects 
   --JC: |- Values, Parameters 
   --JC: -> True if all the values and the corresponding parameters have the 
   --JC: same types/False otherwise
   judgement Objects |- Vals, Parameters -> Bool;
   --iJC: Objects |- Value, Parameter -> True if the given value and parameter 
   --iJC: have the same type/False otherwise
   judgement Objects |- Val, Parameter :> Bool;

   EmptyLists_SameType: _ |- vals[], parameters[] -> true()  ; 

   DifferentTypesForTheFirstElementOfEachList:
      ObjL |- Value, Param :> false()
      --------------------------------
      ObjL |- vals[Value._], parameters[Param._] -> false()  ; 

   RecursiveRule_haveCompatibleTypeForTheFirstElementsOfEachList:
      ObjL |- Value, Param :> true()  &  ObjL |- ValueL, ParamL -> TF
      --------------------------------
      ObjL |- vals[Value.ValueL], parameters[Param.ParamL] -> TF  ; 

   TwoIntegers: _ |- integer _, parameter(_, int(), _) :> true()  ; 

   TwoBytes: _ |- integer _, parameter(_, byte(), _) :> true()  ; 

   TwoShorts: _ |- integer _, parameter(_, short(), _) :> true()  ; 

   TwoFloats: _ |- floating _, parameter(_, float(), _) :> true()  ; 

   TwoDifferentPrimitiveTypes:
      _ |- floating _, parameter(_, ParamType, _) :> true()  ; 
               provided not_eq( ParamType, float() );

   TwoObjectTypes_CheckForAssignmentCompatibility:
      getRealTypeAndName( Type, VarDeclId -> RealType, _ )
      &
      hasCompatibleObjectType(
         ObjL |- objectId(TF1, objectNumber i), RealType -> TF2 )
      --------------------------------
      ObjL |- objectId(TF1, objectNumber i), parameter(_, Type, VarDeclId) :> TF2  ; 
   end haveCompatibleTypeForEachElement; 

   set hasCompatibleObjectType is
   --SC: Checks if the object has a type which is assignment compatible with
   --SC: the given type (it may be an implicit cast) 
   --
   --JC: Objects |- Object reference, Type
   --JC: -> True if the object is assignable to a variable with the given type,
   --JC: False otherwise.
   judgement Objects |- ObjectId, Type -> Bool;

   HasCompatibleObjectType:
      --RC: Gets the object type and checks if an object of this type is
      --RC: assignable to a variable of the given type (implicit cast).
      getObjectType( ObjId |- ObjL -> ObjType )
      &  isMyAncestor( Type |- ObjType -> TF )
      --------------------------------
      ObjL |- ObjId, Type -> TF  ; 
   end hasCompatibleObjectType; 

   set haveTheSameNumberOfElements is
   --SC: Checks if the two given lists have the same number
   --SC: of elements.
   --
   --JC: Value list, parameter list -> True if the two given 
   --JC: lists have the same number of elements, false otherwise
   judgement (Vals, Parameters -> Bool);

   EmptyLists_SameNumber: (vals[], parameters[] -> true())  ; 

   MoreValuesThanParameters: (vals[_._], parameters[] -> false())  ; 

   LessValuesThanParameters: (vals[], parameters[_._] -> false())  ; 

   RecursiveRule:
      (ValueL, ParamL -> TF)
      --------------------------------
      (vals[_.ValueL], parameters[_.ParamL] -> TF)  ; 
   end haveTheSameNumberOfElements; 

   set isAThread is
   --SC: Checks if the given type is a Thread sub-class or 
   --SC: implements the Runnable interface.
   --
   --JC1: Type name -> True or False 
   judgement (OptTypeName => Bool);
   --JC2: Object -> True of False
   judgement (Object -> Bool);

   Thread_SubClassThread:
      isMyAncestor( identifier "Thread" |- ClName -> true() )
      --------------------------------
      (ClName => true())  ; 

   Thread_RunnableInterfaceImplementation:
      isMyAncestor( identifier "Thread" |- ClName -> false() )  &
      isMyInterface( identifier "Runnable" |- ClName -> true() )
      --------------------------------
      (ClName => true())  ; 

   NotAThread:
      isMyAncestor( identifier "Thread" |- ClName -> false() )  &
      isMyInterface( identifier "Runnable" |- ClName -> false() )
      --------------------------------
      (ClName => false())  ; 

   IsAThread:
      (object(objectId(true(), _), _, _, _, _, _) -> true())  ; 

   IsNotAThread:
      (object(objectId(false(), _), _, _, _, _, _) -> false())  ; 
   end isAThread; 

   set isMyAncestor is
   --SC: Checks if the second type is a subtype of the first one. The check is
   --SC: done firstly in the programm classes and then if the ancestor is still
   --SC: not found in the API classes hierarchy.
   --
   --JC: The ancestor type |- the possible subtype -> True/False
   judgement Type |- Type -> Bool;

   IAmMyAncestor: Type |- Type -> true()  ; 

   TwoArrays_CheckElementTypes:
      Type1 |- Type2 -> TF
      --------------------------------
      arrayof(Type1) |- arrayof(Type2) -> TF  ; 

   IsMyDirectAncestor:
      getDirectAncestor( |- ClName2 -> ClName1 )
      --------------------------------
      ClName1 |- ClName2 -> true()  ; 
               provided
                  diff( ClName1, ClName2 )  &  not_eq( ClName1, arrayof(_) )  &
                  not_eq( ClName2, arrayof(_) );

   RecursiveRule_IsItMyIndirectAncestor:
      getDirectAncestor( |- ClName2 -> Ancestor )
      &  diff( Ancestor, identifier "Object" )  &
      isMyAncestor( ClName1 |- Ancestor -> TF )
      --------------------------------
      ClName1 |- ClName2 -> TF  ; 
               provided
                  diff( ClName1, ClName2 )  &  not_eq( ClName1, arrayof(_) )  &
                  not_eq( ClName2, arrayof(_) );

   RecursiveRule_IsItMyIndirectAPIAncestor:
      getClassAPIDirectAncestor(
         |- ClName2 -> Ancestor )  &  diff( ClName1, Ancestor )
      &  diff( Ancestor, identifier "Object" )  &  ClName1 |- Ancestor -> TF
      --------------------------------
      ClName1 |- ClName2 -> TF  ; 
               provided
                  diff( ClName1, ClName2 )  &  not_eq( ClName1, arrayof(_) )  &
                  not_eq( ClName2, arrayof(_) );

   NoMoreAncestor_IsNotMyAPIAncestor:
      getClassAPIDirectAncestor(
         |- ClName2 -> identifier "Object" )
      --------------------------------
      ClName1 |- ClName2 -> false()  ; 
               provided
                  diff( ClName1, ClName2 )  &  not_eq( ClName1, arrayof(_) )  &
                  not_eq( ClName2, arrayof(_) );

   IsMyAPIAncestor:
      getClassAPIDirectAncestor(
         |- ClName2 -> ClName1 )
      --------------------------------
      ClName1 |- ClName2 -> true()  ; 
               provided
                  diff( ClName1, ClName2 )  &  not_eq( ClName1, arrayof(_) )  &
                  not_eq( ClName2, arrayof(_) );

   NoMoreAncestor_IsNotMyAncestor:
      getClassDeclaration(
         |- ClName2 -> classDeclaration(_, _, none(), _, _) )
      --------------------------------
      ClName1 |- ClName2 -> false()  ; 
               provided
                  diff( ClName1, ClName2 )  &  not_eq( ClName1, arrayof(_) )  &
                  not_eq( ClName2, arrayof(_) );

   ObjectAncestor_IsNotMyAncestor:
      getClassDeclaration(
         |- ClName2 -> classDeclaration(_, _, identifier "Object", _, _) )
      --------------------------------
      ClName1 |- ClName2 -> false()  ; 
               provided
                  diff( ClName1, ClName2 )  &  diff( ClName1, identifier "Object" )  &
                  not_eq( ClName1, arrayof(_) )  &  not_eq( ClName2, arrayof(_) );
   end isMyAncestor; 

   set isMyInterface is
   --SC: Checks if the given interface is a direct or indirect interface for the
   --SC: given class.
   --             
   --JC: Interface name |- Class name -> True/False
   judgement OptTypeName |- OptTypeName -> Bool;

   NoInterfaceForTheGivenClass_IsNotMyInterface:
      getClassDeclaration(
         |- ClName -> classDeclaration(_, _, _, typeNames[], _) )
      --------------------------------
      InterfName |- ClName -> false()  ; 
               provided diff( InterfName, ClName );

   IsOneOfMyInterface:
      getClassDeclaration(
         |- ClName -> classDeclaration(_, _, _, InterfNameL, _) )  &
      diff( InterfNameL, typeNames[] )  &
      isTheInterfaceInTheList( InterfName |- InterfNameL -> true() )
      --------------------------------
      InterfName |- ClName -> true()  ; 
               provided diff( InterfName, ClName );

   IsItOneOfMyIndirectInterface_CheckInterfaceHierarchy:
      getClassDeclaration(
         |- ClName -> classDeclaration(_, _, _, InterfNameL, _) )  &
      diff( InterfNameL, typeNames[] )  &
      isMyInterfaceAncestor( InterfName |- InterfNameL => TF )
      --------------------------------
      InterfName |- ClName -> TF  ; 
               provided diff( InterfName, ClName );

   IsItOneOfMyIndirectInterface_CheckClassHierarchy:
      getDirectAncestor( |- ClName1 -> ClName2 )
      &  diff( ClName2, identifier "Object" )  &
      InterfName |- ClName2 -> TF
      --------------------------------
      InterfName |- ClName1 -> TF  ; 

   NoInterfaceInTheAPI: _ |- _ -> false()  ; 
   end isMyInterface; 

   set isTheInterfaceInTheList is
   --SC: Checks if the given interface is in the given interface list.
   --
   --JC: Interface name |- Interface list -> True/False
   judgement Identifier |- TypeNames -> Bool;

   EmptyList_NotInTheList: _ |- typeNames[] -> false()  ; 

   FoundTheInterfaceInTheList:
      InterfName |- typeNames[InterfName._] -> true()  ; 

   RecursiveRule:
      InterfName1 |- InterfNameL -> TF
      --------------------------------
      InterfName1 |- typeNames[InterfName2.InterfNameL] -> TF  ; 
               provided diff( InterfName1, InterfName2 );
   end isTheInterfaceInTheList; 

   set isMyInterfaceAncestor is
   --SC: Checks if the given interface (the first) is inherited by one other
   --SC: interface.
   --
   --JC: Sought interface name
   --JC: |- Interfaces name list
   --JC: -> true if the first interface is inherited by one interface of the list
   --JC: false otherwise.
   judgement Identifier |- TypeNames => Bool;
   --iJC: Sought interface name
   --iJC: |- Interface name
   --iJC: -> true if the first interface is inherited by the second interface
   --iJC: false otherwise.
   judgement Identifier |- Identifier -> Bool;

   EmptyList_NotMyInterfaceAncestor: _ |- typeNames[] => false()  ; 

   FoundTheInterfaceAncestor:
      --RC: Finds the given interface name into the interface hierarchy of the 
      --RC: first element of the interface name list.
      InterfName1 |- InterfName2 -> true()
      --------------------------------
      InterfName1 |- typeNames[InterfName2._] => true()  ; 

   RecursiveRuleOnTheNextElement:
      InterfName1 |- InterfName2 -> false()  &
      InterfName1 |- InterfNameL => TF
      --------------------------------
      InterfName1 |- typeNames[InterfName2.InterfNameL] => TF  ; 

   FoundTheInterfaceAncestor:
      --RC: Retrieves the interface declaraction from the program and finds the
      --RC: given interface name in the interface name list.
      getInterfaceDeclaration(
         |- InterfName2 -> interfaceDeclaration(_, _, InterfNameL, _) )  &
      isTheInterfaceInTheList( InterfName1 |- InterfNameL -> true() )
      --------------------------------
      InterfName1 |- InterfName2 -> true()  ; 
               provided diff( InterfName1, InterfName2 );

   NoInheritedInterface_NotFound:
      getInterfaceDeclaration(
         |- InterfName2 -> interfaceDeclaration(_, _, typeNames[], _) )
      --------------------------------
      InterfName1 |- InterfName2 -> false()  ; 
               provided diff( InterfName1, InterfName2 );

   RecursiveRule_GoUpInTheHierarchy:
      getInterfaceDeclaration(
         |- InterfName2 -> interfaceDeclaration(_, _, InterfNameL, _) )  &
      diff( InterfNameL, typeNames[] )  &
      isTheInterfaceInTheList( InterfName1 |- InterfNameL -> false() )
      &  InterfName1 |- InterfNameL => TF
      --------------------------------
      InterfName1 |- InterfName2 -> TF  ; 
               provided diff( InterfName1, InterfName2 );
   end isMyInterfaceAncestor; 

   set getDirectAncestor is
   --SC: Gets the direct ancestor of the given class.
   --
   --JC: |- Class name -> Direct ancestor name
   judgement |- OptTypeName -> OptTypeName;

   GetDirectAncestor:
      getClassDeclaration(
         |- ClName1 -> classDeclaration(_, _, ClName2, _, _) )  &
      diff( ClName2, none() )
      --------------------------------
      |- ClName1 -> ClName2  ; 

   ClassObjectAsDirectAncestor:
      getClassDeclaration(
         |- ClName -> classDeclaration(_, _, none(), _, _) )
      --------------------------------
      |- ClName -> identifier "Object"  ; 

   GetAPIDirectAncestor:
      getClassAPIDirectAncestor(
         |- ClName -> Ancestor )
      --------------------------------
      |- ClName -> Ancestor  ; 
   end getDirectAncestor; 

   set getFieldDeclarationInAncestors is
   --SC: Looks for the field declaration of the given field name. If nothing was
   --SC: found, returns false.
   --
   --JC: Objects, Name of the class where the field is sought, 
   --JC: Field argument values, True if the sought field is a constructor/False
   --JC: |- Sought field name 
   --JC: -> Field declaration, Name of the class where the field was found, 
   --JC: True if found/False 
   judgement
      Objects, Identifier, Vals, Bool |- Identifier -> FieldDeclaration, Identifier, Bool;

   ImpossibleToFindAFieldDeclarationInAPI:
      getClassAPIDirectAncestor( ClName1 -> _ )
      --------------------------------
      _, ClName1, _, _ |- _ -> _, _, false()  ; 

   FieldDeclarationInClass:
      getClassDeclaration( |- ClName -> ClDec )
      &
      getFieldDeclarationInClass(
         ObjL, FName, ArgL, TF |- ClDec -> FDec, true() )
      --------------------------------
      ObjL, ClName, ArgL, TF |- FName -> FDec, ClName, true()  ; 

   RecursiveRule_FieldDeclarationMaybeInAncestors:
      getClassDeclaration( |- ClName1 -> ClDec )
      &
      getFieldDeclarationInClass(
         ObjL, FName, ArgL, TF1 |- ClDec -> _, false() )  &
      getDirectAncestor( |- ClName1 -> Ancestor )
      &  ObjL, Ancestor, ArgL, TF1 |- FName -> FDec, ClName2, TF2
      --------------------------------
      ObjL, ClName1, ArgL, TF1 |- FName -> FDec, ClName2, TF2  ; 

   FieldNotFound_NoMoreAncestor:
      _, _, _, _ |- _ -> _, _, false()  ; 
   end getFieldDeclarationInAncestors; 

   set makeAttributeList is
   --SC: Determines the attribute list correponding to a given type (useful for
   --SC: an object creation).
   --
   --JC: |- Class name of the new instance 
   --JC: -> Initialized Attribute list 
   judgement |- OptTypeName -> Pairs;

   DeclarationObject_InProgramClasses:
      getClassDeclaration( ClName1 -> ClDec )  &
      getLocalAttributeList( |- ClDec -> LocAttrL )
      &
      getDirectAncestor( |- ClName1 -> ClName2 )
      &
      makeInheritedAttributeList( LocAttrL |- ClName2 -> AttrL )
      --------------------------------
      |- ClName1 -> AttrL  ; 

   DeclarationObject_inAPI:
      getAPIObjectAttributes( |- ClName -> AttrL
         )
      --------------------------------
      |- ClName -> AttrL  ; 
   end makeAttributeList; 

   set getLocalAttributeList is
   --SC: Gets the attributes local to the given class.
   --
   --JC: |- Declaration 
   --JC: -> Local attribute list 
   judgement |- java -> Pairs;
   --iJC: The common (part of) the type
   --iJC: |- Variable declarators
   --iJC: -> Corresponding pair list
   judgement Type |- VariableDeclarators -> Pairs;

   GetTheFieldsDeclaration:
      |- FDecL -> LocAttrL
      --------------------------------
      |- classDeclaration(_, _, _, _, FDecL) -> LocAttrL  ; 

   NoMoreLocalAttribute:
      |- fieldDeclarations[] -> pairs[]  ; 

   RecursiveRule:
      |- FDec -> AttrL1  &
      |- FDecL -> AttrL2  &  appendtree( AttrL1, AttrL2, AttrL3 )
      --------------------------------
      |- fieldDeclarations[FDec.FDecL] -> AttrL3  ; 

   MethodDeclaration_NotAnAttribute:
      |- methodDeclaration(_, _, _, _, _) -> pairs[]  ; 

   ConstructorDeclaration_NotAnAttribute:
      |- constructorDeclaration(_, _, _, _) -> pairs[]  ; 

   StaticVariable_NotInAttributeList:
      isThisModifierInTheList( static() |- ModL -> true() )
      --------------------------------
      |- fieldVariableDeclaration(ModL, _, _) -> pairs[]  ; 

   FieldVariableDeclaration_PutInTheAttributeList:
      isThisModifierInTheList( static() |- ModL -> false() )
      &  Type |- FVarL -> AttrL
      --------------------------------
      |- fieldVariableDeclaration(ModL, Type, FVarL) -> AttrL  ; 

   VariableWithDefaultValue:
      getRealTypeAndName( Type, VarDeclId -> RealType, RealName )
      &
      getInitialValueForAGivenType( RealType -> Value )
      --------------------------------
      Type |- variableDeclarators[VarDeclId] -> pairs[pair(RealName, Value)]  ; 

   InitializedVariable:
      getRealTypeAndName( Type, VarDeclId -> _, RealName )
      --------------------------------
      _ |- variableDeclarators[initializedVariable(VarDeclId, TVValue)] -> pairs[pair(RealName, TVValue)]  ; 

   RecursiveRuleWithAnInitializedVariable:
      getRealTypeAndName( Type, VarDeclId -> _, RealName )
      &  Type |- AttrNameL -> AttrL
      --------------------------------
      Type |- variableDeclarators[initializedVariable(VarDeclId, TVValue).AttrNameL] ->
                 pairs[pair(RealName, TVValue).AttrL]  ; 

   RecursiveRuleWithANonInitializedVariable_DefaultValueUsed:
      getRealTypeAndName( Type, VarDeclId -> RealType, RealName )
      &
      getInitialValueForAGivenType( RealType -> Value )
      &  Type |- AttrNameL -> AttrL
      --------------------------------
      Type |- variableDeclarators[VarDeclId.AttrNameL] -> pairs[pair(RealName, Value).AttrL]  ; 
   end getLocalAttributeList; 

   set isThisModifierInTheList is
   --SC: Checks if the given modifier is contained in the given modifier list. 
   --SC: Returns true if found, false otherwise
   --
   --JC: Sought modifier |- Modifier list -> True/False
   judgement Modifier |- Modifiers -> Bool;

   FoundModifier: Mod |- modifiers[Mod._] -> true()  ; 

   ModifierNotFound: _ |- modifiers[] -> false()  ; 

   RecursiveRule:
      Mod1 |- ModL -> TF
      --------------------------------
      Mod1 |- modifiers[Mod2.ModL] -> TF  ; 
               provided diff( Mod1, Mod2 );
   end isThisModifierInTheList; 

   set makeInheritedAttributeList is
   --SC: Makes a list that contains all the inherited attributes (A check is 
   --SC: done to avoid multiple attributes with the same name in this list to 
   --SC: manage with the attribute shadowing mecanism)
   -- 
   --JC: List that contains all the attributes already retrieved (useful to 
   --JC: avoid having multiple attributes with the same name in the case of 
   --JC: attribute shadowing) 
   --JC: |- Class name (class of which the inherited attributes are wanted)
   --JC: -> Inherited Attributes  
   judgement Pairs |- java -> Pairs;

   ObjectAsDirectAncestor_NoMoreInheritedAttributes:
      AttrL |- identifier "Object" -> AttrL  ; 

   APIGetInheritedAttributes:
      getAPIObjectAttributes( ClName -> AttrL1 )
      &
      joinTwoListsWithoutDuplication(
         |- RetAttrL, AttrL1 -> AttrL2 )  &
      getClassAPIDirectAncestor(
         |- ClName -> ClNameDirectAncestor )  &
      AttrL2 |- ClNameDirectAncestor -> AttrL3
      --------------------------------
      RetAttrL |- ClName -> AttrL3  ; 

   HaveOneDirectAncestor_LookForInheritedAttributes:
      getClassDeclaration( |- ClName -> ClDec )
      &  RetAttrL |- ClDec -> AttrL
      --------------------------------
      RetAttrL |- ClName -> AttrL  ; 
               provided diff( ClName, identifier "Object" );

   RecursiveRule_GetCurrentClassAttributesAndGetTheInheritedOnes:
      getLocalAttributeList(
         |- classDeclaration(_, ClName1, _, _, FDecL) -> AttrL1 )  &
      joinTwoListsWithoutDuplication(
         |- RetAttrL1, AttrL1 -> RetAttrL2 )  &
      getDirectAncestor( |- ClName1 -> ClName2 )
      &  RetAttrL2 |- ClName2 -> AttrL2
      --------------------------------
      RetAttrL1 |- classDeclaration(_, ClName1, _, _, FDecL) -> AttrL2  ; 

      set joinTwoListsWithoutDuplication is
      --SC: Joins two lists without duplicating two attributes
      --SC: that have the same name.
      --
      --JC: |- Attribute list, Attribute list -> concatenated list
      --JC: without double.
      judgement |- Pairs, Pairs -> Pairs;

      EmptyList: |- pairs[], AttrL -> AttrL  ; 

      EmptyList: |- AttrL, pairs[] -> AttrL  ; 

      AttributeNotInTheOtherList:
         isAMember( AttrName |- AttrL1 -> false() )  &
         |- AttrL1, AttrL2 -> AttrL3  &
         appendtree( pairs[pair(AttrName, Value)], AttrL3, AttrL4 )
         --------------------------------
         |- AttrL1, pairs[pair(AttrName, Value).AttrL2] -> AttrL4  ; 

      AttributeInTheList:
         isAMember( AttrName |- AttrL1 -> true() )  &
         |- AttrL1, AttrL2 -> AttrL3
         --------------------------------
         |- AttrL1, pairs[pair(AttrName, _).AttrL2] -> AttrL3  ; 
      end joinTwoListsWithoutDuplication ;
   end makeInheritedAttributeList; 

   set isAMember is
   --SC: Determines if the given identifier is already in the given pair list.
   --
   --JC: The sought identifier (e.g. an attribute)
   --JC: |- List in which the identifier is sought 
   --JC: -> True/False   
   judgement Identifier |- Pairs -> Bool;

   NoMoreElementInTheList_NoFound: _ |- pairs[] -> false()  ; 

   HasFoundTheIdentifier:
      Ident |- pairs[pair(Ident, _)._] -> true()  ; 

   RecursiveRule:
      Ident1 |- PairL -> TF
      --------------------------------
      Ident1 |- pairs[pair(Ident2, _).PairL] -> TF  ; 
               provided diff( Ident1, Ident2 );
   end isAMember; 

   set getClassDeclaration is
   --SC: Gets the declaration of a given class from the program tree.
   --
   --JC: |- Name of the sought class 
   --JC: -> Class declaration
   judgement |- OptTypeName -> TypeDeclaration;
   --iJC: Name of the sought class
   --iJC: |- Type declarations of the program
   --iJC: Declaration of the sought class.
   judgement OptTypeName |- TypeDeclarations -> TypeDeclaration;

   GetTheCompilationUnit:
      ClName |- TDecL -> ClDec
      --------------------------------
      |- ClName -> ClDec  ; 
               provided
                  getCompilationUnit( compilationUnit(_, _, TDecL) );

   HasFoundTheClassDeclaration:
      ClName1 |- typeDeclarations[classDeclaration(ModL, ClName1, ClName2, InterfL, FDecL)._] ->
                    classDeclaration(ModL, ClName1, ClName2, InterfL, FDecL)  ; 

   RecursiveRule_NotTheRightClass:
      ClName1 |- TDecL -> ClDec
      --------------------------------
      ClName1 |- typeDeclarations[classDeclaration(_, ClName2, _, _, _).TDecL] -> ClDec  ; 
               provided diff( ClName1, ClName2 )  &  diff( TDecL, typeDeclarations[] );

   InterfaceDeclaration:
      ClName1 |- TDecL -> ClDec
      --------------------------------
      ClName1 |- typeDeclarations[interfaceDeclaration(_, _, _, _).TDecL] -> ClDec  ; 
               provided diff( TDecL, typeDeclarations[] );
   end getClassDeclaration; 

   set isAClass is
   --SC: Determines if the given identifier is a class name or not.
   --
   --JC: Maybe a class name 
   --JC: -> True if it is a class/False
   judgement (Identifier -> Bool);

   IsAClass_HasADeclaration:
      getClassDeclaration( ClName -> _ )
      --------------------------------
      (ClName -> true())  ; 

   NotAClass: (_ -> false())  ; 
   end isAClass; 

   set getInterfaceDeclaration is
   --SC: Gets the declaration of a given interface from the program tree.
   --
   --JC: |- Name of the sought interface 
   --JC: -> Interface declaration
   judgement |- OptTypeName -> TypeDeclaration;
   --iJC: Name of the sought interface
   --iJC: |- Type declarations of the program
   --iJC: Declaration of the sought interface.
   judgement OptTypeName |- TypeDeclarations -> TypeDeclaration;

   getCompilationUnit:
      InterfName1 |- TDecL -> InterDec
      --------------------------------
      |- InterfName1 -> InterDec  ; 
               provided
                  getCompilationUnit( compilationUnit(_, _, TDecL) );

   HasFoundTheInterface:
      InterfName |- typeDeclarations[interfaceDeclaration(ModL, InterfName, InterfL, FDecL)._] ->
                       interfaceDeclaration(ModL, InterfName, InterfL, FDecL)  ; 

   RecursiveRule_NotTheRightInterface:
      InterfName1 |- TDecL -> InterfDec
      --------------------------------
      InterfName1 |- typeDeclarations[interfaceDeclaration(_, InterfName2, _, _).TDecL] -> InterfDec  ; 
               provided diff( InterfName1, InterfName2 );

   RecursiveRule_NoAClass:
      InterfName |- TDecL -> InterfDec
      --------------------------------
      InterfName |- typeDeclarations[classDeclaration(_, _, _, _, _).TDecL] -> InterfDec  ; 
   end getInterfaceDeclaration; 

   set getInitialValueForAGivenType is
   --SC: Gets the default value for the given type
   --
   --JC: Type (float, double, int, byte, short, char, boolean, class)
   --JC: -> Default value (e.g. 0, 0.0, null...)
   judgement (Type -> Val);

   Float: (float() -> floating "0.0")  ; 

   Double: (double() -> floating "0.0")  ; 

   Int: (int() -> integer 0)  ; 

   Byte: (byte() -> integer 0)  ; 

   Short: (short() -> integer 0)  ; 

   Char: (char() -> character "\0")  ; 

   Boolean: (boolean() -> false())  ; 

   Other:
      (Any -> null())  ; 
               provided
                  diff( Any, float() )  &  diff( Any, double() )  &  diff( Any, int() )
                  &  diff( Any, short() )  &  diff( Any, char() )  &
                  diff( Any, boolean() );
   end getInitialValueForAGivenType; 
end java_inheritance