wildcard(A) :- superWildcard(A).
wildcard(A) :- extendsWildcard(A).

%Problem hier: Es gibt in der FiniteClosure nun smaller Beziehungen der Art:
%%(Matrix<A> <) Vector<Vector<A>> < List<Vector<A>>
%Mit diesen funktioniert die Unifikation in Schritt 4 des Algorithmus nicht korrekt.
%Lösung: Man könnte es lösen mit:
%typeVarOnly(TP) :- type(TP, _, PN), {notTypeVarOnly(TP, A) : param(TP, A, _), type(A, _, _)} == 0.

% Die Karthesischen Produkte von Schritt 4 des Unifikationsalgorithmus

{ makeRule1(A,TP,TPFC, SmallerType) : smaller(SmallerType, TPFC), type(TPFC, TypeName, NumParams) } = 1
:- smallerDot(A, TP), type(TP, TypeName, NumParams), typeVar(A).%, smaller(_, TPFC), type(TPFC, TypeName, NumParams).

%:- makeRule1(A, B, C,_), makeRule1(A,B,D,_), D != C.

%Alle Greater Arg Paralisten des Typen C generieren
greaterArgParaList(pointer(rule1(A, TP)), TPFC) :- makeRule1(A,TP,TPFC,_).

%Es braucht greaterArg Parameter von allen Parametern des Typs:
greaterArg(pointer(P, Param), Param)  :- greaterArgParaList(P, FCType), type(FCType, FCTName, FCTPN), param(FCType, Param, Num), not typeVar(Param).

%Ein neuer Typ muss angelegt werden:
type(P, FCTName, FCTPN) 
:- greaterArgParaList(P, FCType), type(FCType, FCTName, FCTPN).

param(P, pointer(P, Param), N)
:- greaterArgParaList(P, FCType), type(FCType, FCTName, FCTPN)
	, param(FCType, Param, N), not typeVar(Param)
	.
%Typvariablen bleiben bestehen. Sie werden durch das unify ausgetauscht
param(P, Param, N)
:- greaterArgParaList(P, FCType), type(FCType, FCTName, FCTPN)
	, param(FCType, Param, N), typeVar(Param)
	.


%Die Unifikation vom AusgangsTyp im Constraint und dem greaterArgList gebildeten Typen
unify(pointer(rule1unify(A,TP)), pointer(rule1(A,TP)), TP) 
:- makeRule1(A,TP,TPFC, _).

%Unify auf den SmallerType anwenden:
type(pointer(rule1unify(A,TP,TPFC,SmallerType)), TN, TNum)
:- makeRule1(A, TP, TPFC, SmallerType), type(SmallerType, TN, TNum).

{ param(pointer(rule1unify(A,TP,TPFC,SmallerType)), PNew, PN) : unify(pointer(rule1unify(A,TP)), P, PNew)} == 1
:- makeRule1(A, TP, TPFC, SmallerType), param(SmallerType, P, PN).

%Am Schluss davon noch das smaller bilden:
smallerGen(pointer(smallerDot(A,TP), SmallerType), pointer(rule1unify(A,TP,TPFC,SmallerType)))
:- makeRule1(A, TP, TPFC, SmallerType), type(TP, TypeName, NumParams) %Die Bedingung für Regel 1
	.

smallerGen(A) :- list(smallerGen(A),_).
type(A,B,C) :- list(type(A,B,C),_).
list(A,B) :- list(_, list(A,B)).

smallerGen(A,A) :- smallerGen(A).

{ equals(A, NewType) : smallerGen(pointer(smallerDot(A,TP), SmallerType), NewType) } == 1
:- smallerDot(A, TP), type(TP, TypeName, NumParams), typeVar(A) %Das karthesische Produkt
	, smaller(SmallerType, TPFC), type(pointer(smallerDot(A,TP), SmallerType), _, _)
 	.

%TODO: Typen welche durch Unifikation ersetzt werden auch zu Constraints machen
%%%%%%%%%%%%%%%%%%
% Regel 2
%%%%%%%%%%%%%%%%%

%{ makeRule2(A, Theta', TPFC) : smaller(SmallerType, TPFC), type(TPFC, TypeName, NumParams) } == 1
%:- smallerDotWC(A, Theta'), extendsWildcard(Theta'), typeVar(A).
%
%%Alle Greater Arg Paralisten des Typen C generieren
%greaterArgParaList(pointer(rule2(A, TP)), TPFC) :- makeRule2(A,TP,TPFC,_).
%
%unify(pointer(rule2(A,TP)), TP) 
%:- makeRule2(A,TP,TPFC)
%%	, type(TP, TypeName, NumParams), typeVar(A), type(TPFC, TypeName, NumParams)
	%.
%
%{ list(smallerArgGen(pointer(smallerDot(A,TP), SmallerType), SmallerType),
%list(extendsWildcard(pointer(smallerDot(A,TP), SmallerType)), null))
%: smaller(SmallerType, TPFC), type(SmallerType, SmallerName, SmallerPNum) } == 1
%:- makeRule2(A, TP, TPFC) %Die Bedingung für Regel 2
	%.
%
%smallerArgGen(A, B) :- list(smallerArgGen(A, B), _).
%extendsWildcard(A) :- list(extendsWildcard(A), _).

%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Regel 3
%%%%%%%%%%%%%%%%%%%%%%%%%%%
smallerArgGen(pointer(smallerDotWC(A, Theta')), Theta') :- smallerDotWC(A, Theta'), superWildcard(Theta').
equals(A, pointer(smallerDotWC(A, Theta'))) :- smallerDotWC(A, Theta'), superWildcard(Theta').


%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Regel 4
%%%%%%%%%%%%%%%%%%%%%%%%%%%
equals(A, Theta') :- smallerDotWC(A, Theta'), not wildcard(Theta').


%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Regel 5
%%%%%%%%%%%%%%%%%%%%%%%%%%%
greaterGen(pointer(smallerDot(Theta,A)), Theta) :- smallerDot(Theta, A), not wildcard(Theta), not typeVar(Theta), typeVar(A) .
equals(A, pointer(smallerDot(Theta,A))) :- smallerDot(Theta, A), not wildcard(Theta) , not typeVar(Theta), typeVar(A) .


%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Regel 6
%%%%%%%%%%%%%%%%%%%%%%%%%%%
greaterArgGen(pointer(smallerDotWC(Theta,A)), Theta) :- smallerDotWC(Theta, A), extendsWildcard(Theta) .
equals(A, pointer(smallerDot(Theta,A))) :- smallerDotWC(Theta, A), extendsWildcard(Theta) .

%TODO: Regel 7