user:term_expansion(Term,ExpandedTerm) :-
	Term = ( Head :- Body),
	prolog_load_context(module,Mod),
	extension( Mod:NameArity, Max, Names, L2, Call )
	hacks:context_variables(CurrentNames),
	sort( UnsortedCurrentNames, CurrentNames ),
	merge_variables( Names, CurrentNames ),
	ExpandedTerm = (M:Head :- Mod:NG).

merge_variables( [], _CurrentNames ).
merge_variables( _Names, [] ).
merge_variables( [S0=V0|Names], [S1=V1|CurrentNames] ) :-
	compare(Diff, S0, S1),
	(Diff == (=) -> V0 = V1, merge_variables( Names, CurrentNames ) ;
	 Diff == (>) -> merge_variables( [S0=V0|Names], CurrentNames ) ;
         /*Diff == (<) ->*/ merge_variables(Names, [S1=V1|CurrentNames] ) ).




(ModName extra_arguments CVs such_that CCs defaults CDs ) :-
	conj2l(CVs, Vs),
	conj2l(CCs, Cs),
	conj2l(CDs, Ds),
	hacks:context_variables(UnsortedNames),
        sort( UnsortedNames, Names ),	
	strip_module( ModName , Mod, NameArity ),
	functor( NameArity, Name, Arity),
	foldl2( max, Vs, Max, Arity, _, []),
	foldl( cons, Ds, Goals, []),
	foldl(ensure, Cs, L1, L0),
	functor( Head, Name, Arity ),
	foldl( argument, Vs, Head, L2, []),
	assert_static( extension( Mod:NameArity, Max, Names, L2) ).

max( Concept:_ = _, Max, Max, Seen, Seen) :-
	member(Concept, SeeenSoFar),
        !.
max( Concept:_ = _, Max1, Max, [Concept|Seen], Seen) :-
        !,
	Max1 is Max+1.
max( _ = _, Max1, Max, Seen, Seen) :-
        Max1 is Max+1.

cons(G) :-
	ground(G), !.
cons(G) :-
	call(G), !.
cons(_).

satisfy(( A ==> C)) :-
	satisfy(A) -> satisfy(C).
satisfy(domain(X,Vs)) :-
      memberchk(X, Vs).
satisfy(atom(X)) :-
	atom(X).
satisfy(integer(X)) :-
        integer(X).
satisfy(atom(X)) :-
        atom(X).
satisfy(integer(X)) :- integer(X).
satisfy(internet_host(X)) :-
       atom(X) -> true
      ;
       X = ipv4(I1,I2,I3,I4),
       integer(I1),       
       integer(I2),       
       integer(I3),       
       integer(I4).
satisfy(positive_or_zero_integer(X)) :-
       integer(X),
       X >= 0.
satisfy(file(X)) :-
	 atom(X).
satisfy((X in D)) :-
        (
         D = [_|_] -> memberchk(X, D)
	;
	 D == X
        ).


ensure(( A ==> C)) :-
	satisfy(A) -> ensure(C).
ensure(domain(X,Vs)) :-
	(
	 var(X) -> throw(error(instantiation_error,_G))
	;
	 satisfy( member(X, Vs) ) -> true ; throw(error(domain_error(Vs,X),_G))
	).
ensure(atom(X)) :-
	(
	 var(X) -> throw(error(instantiation_error,_G))
	;
	 atom(X) -> true
	;
	 throw(error(type_error(atom,X),_G))
	).
ensure(integer(X)) :-
	(
	 var(X) -> throw(error(instantiation_error,_G))
	;
	 integer(X) -> true
	;
	 throw(error(type_error(integer,X),_G))
	).
ensure(internet_host(X)) :-
	(
	 var(X) -> throw(error(instantiation_error,_G))
	;
	 atom(X) -> true
	;
	 X = ipv4(I1,I2,I3,I4),
	 integer(I1),       
	 integer(I2),       
	 integer(I3),       
	 integer(I4)
	->
	 true
	;
	 throw(error(type_error(atom,X),_G))
	).
ensure(positive_or_zero_integer(X)) :-
	(
	 var(X) -> throw(error(instantiation_error,_G))
	;
	 \+ integer(X) -> throw(error(type_error(integer,X),_G))
	;
	 X < 0 -> throw(domain_error(not_less_than_zero,X),_G))
	;
	true
	).
ensure(file(X)) :-
	(
	 var(X) -> throw(error(instantiation_error,_G))
	;
	 atom(X) -> true
	;
	 throw(error(type_error(atom,X),_G))
	).
ensure((X in D)) :-
        (
         var(X) -> throw(error(instantiation_error,_G))
        ;
         D = [_|_] -> member(X, D)
	;
	 D == X -> true
        ;
         throw(error(domain_error(D,X),_G))
        ).