sexpansion([],_,[]) :- !.
sexpansion([E|Rest],Env,[Exp|ERest]) :-
!,sexpansion(E,Env,Exp),
sexpansion(Rest,Env,ERest).
sexpansion(sref(Name,Deco,ParamValues,Renamings),Env,Result) :-
!,
lookup(Env,Name,Params,Expr),
sexpansion(Expr,Env,Expansion),
same_length(ParamValues,Params),
insert_parameter(Expansion,Params,ParamValues,PExp),
decorate(PExp,Deco,DExp),
rename_variables(DExp,Renamings,Result).
sexpansion(body(Decls,Where),Env,body(EDecl,EWhere)) :-
!,expand_decls(Decls,Env,ExpandedDeclsD,NWhere),
clean_decl(ExpandedDeclsD,EDecl),
append(NWhere,ExWhere,DWhere),
sexpansion(Where,Env,ExWhere),
clean_where(DWhere,EWhere).
sexpansion(text(S),Env,Expansion) :-
!,sexpansion(S,Env,Expansion).
sexpansion(sand(A,B),Env,Expanded) :-
!,sexpansion(body([sdecl(A),sdecl(B)],[]),Env,Expanded).
sexpansion(sor(A,B),Env,body(EDecl,EWhere)) :-
!,expand_and_split(A,Env,DA,WA),
expand_and_split(B,Env,DB,WB),
append_decls(DA,DB,EDecl),
find_common(WA,WB,UA,UB,Common),
z_conjunction(UA,AExpr),
z_conjunction(UB,BExpr),
z_disjunction([AExpr,BExpr],Or),
append(Common,[Or],EWhere).
sexpansion(simplies(A,B),Env,Expansion) :-
!,sexpansion_logic(implies,A,B,Env,Expansion).
sexpansion(sequiv(A,B),Env,Expansion) :-
!,sexpansion_logic(equiv,A,B,Env,Expansion).
sexpansion(snot(S),Env,body(Decls,[not(Condition)])) :-
!,expand_and_split(S,Env,Decls,Where),
z_conjunction(Where,Condition).
sexpansion(sforall(Body,S),Env,Expansion) :-
!,sexpansion_quantifier(forall,Body,S,Env,Expansion).
sexpansion(sexists(Body,S),Env,Expansion) :-
!,sexpansion_quantifier(exists,Body,S,Env,Expansion).
sexpansion(sexists1(Body,S),Env,Expansion) :-
!,sexpansion_quantifier(exists1,Body,S,Env,Expansion).
sexpansion(pre(S),Env,Expansion) :-
!,sexpansion(S,Env,SE),zsplit(SE,Decls,_),
find_vars_with_deco(Decls,['\'','!'],PostVars),
sexpansion(hide(SE,PostVars),Env,Expansion).
sexpansion(hide(S,VarsToHide),Env,body(NewDecls,[Exists])) :-
!,Exists = exists(body(ExistsDecls,Where),truth),
expand_and_split(S,Env,Decls,Where),
remove_vars_from_decls(Decls,VarsToHide,NewDecls,ExistsDecls).
sexpansion(project(A,B),Env,Expansion) :-
!,sexpansion(A,Env,AE),sexpansion(B,Env,BE),
zsplit(AE,AD,_),zsplit(BE,BD,_),
vars_of_decls(AD,VarsA),
vars_of_decls(BD,VarsB),
remove_all(VarsA,VarsB,VarsToRemove),
sexpansion(hide(sand(AE,BE),VarsToRemove),Env,Expansion).
sexpansion(fatsemi(A,B),Env,Expansion) :-
!,combine_schemas(A,B,'\'','',Env,Expansion).
sexpansion(pipe(A,B),Env,Expansion) :-
!,combine_schemas(A,B,'!','?',Env,Expansion).
sexpansion(spred(S),Env,Expansion) :-
!,expand_and_split(S,Env,_,Where),
z_conjunction(Where,Expansion).
sexpansion(comp(Body,nothing),Env,Expansion) :-
contains_sdecl(Body),!,
add_char_tuple(comp,Body,Env,Expansion).
sexpansion(mu(Body,nothing),Env,Expansion) :-
contains_sdecl(Body),!,
add_char_tuple(mu,Body,Env,Expansion).
sexpansion(lambda(Body,Result),Env,comp(ExpBody,just(Expression))) :-
Expression = tuple([Argument,ExpResult]),
contains_sdecl(Body),!,
sexpansion(Result,Env,ExpResult),
sexpansion(comp(Body,nothing),Env,comp(ExpBody,just(Argument))).
sexpansion(theta(Name,Deco,Renamings),Env,binding(Bindings)) :-
!,schema_vars(sref(Name,'',[],[]),Env,Vars),
generate_bindings(Vars,Deco,Renamings,Bindings).
sexpansion(Expr,Env,Expansion) :-
zexpr_conversion(Expr,Subs,ESubs,Expansion),
sexpansion(Subs,Env,ESubs).