%:- ensure_loaded(msl).
:- use_module(library(ordsets),[ord_subtract/3]).

add_to_type_num(VTypeIndex,T,TFS,AttPos) :-
  clause(num_type(VTypeIndex,VType),true),
  add_to_type(VType,T,TFS,AttPos).

% :- compile(ale), compile(newsub), compile(gen_automaton), go.

map_minimal_indices([],[]).
map_minimal_indices([N|Ns],[N|Mins]) :-  % assume topological order, so N is min
  clause(stmatrix_num(N,RowN),true), % RowN are the subtypes of N
  ord_subtract(Ns,RowN,NewNs),       % so get rid of them
  map_minimal_indices(NewNs,Mins).

at_msl_traverse_stubbed(Index3,Type1,Type2,AC2,TFS2,Pos2) :-
  ord_add_element(Index3,AC2,Union), % ?? not sure about arg order
  pp(Union,AC12),
  at_msl_traverse_stubbed_act(AC12,AC12,Type1,Type2,TFS2,Pos2).

at_msl_traverse_modularized(Index3,Type1,Type2,AC2,TFS2,Pos2) :-
  ord_add_element(Index3,AC2,Union), % ?? not sure about arg order
  pp(Union,AC12),
  at_msl_traverse_modularized_act(AC12,AC12,Type1,Type2,TFS2,Pos2).

at_msl_traverse_stubbed_act([AC12First|AC12Rest],AC12,Type1,Type2,TFS2,Pos2) :-
  at_msl_traverse_stubbed_detect_join(AC12Rest,AC12First,AC12,Type1,Type2,TFS2,Pos2).
at_msl_traverse_modularized_act([AC12First|AC12Rest],AC12,Type1,Type2,TFS2,Pos2) :-
  at_msl_traverse_modularized_detect_join(AC12Rest,AC12First,AC12,Type1,Type2,TFS2,Pos2).

at_msl_traverse_stubbed_detect_join([],JoinIndex,_,_,Type2,TFS2,Pos2) :-
  add_to_type_num(JoinIndex,Type2,TFS2,Pos2).
at_msl_traverse_stubbed_detect_join([_|_],_,AC,Type1,Type2,TFS2,Pos2) :-
  add_to_type(Type1,Type2,TFS2,Pos2),
  at_msl_traverse_stubbed(AC,TFS2,Pos2).

at_msl_traverse_modularized_detect_join([],JoinIndex,_,_,Type2,TFS2,Pos2) :-
  add_to_type_num(JoinIndex,Type2,TFS2,Pos2).
at_msl_traverse_modularized_detect_join([_|_],_,AC,Type1,Type2,TFS2,Pos2) :-
  add_to_type(Type1,Type2,TFS2,Pos2),
  at_msl_traverse_modularized(AC,TFS2,Pos2).

at_msl_traverse_stubbed(AC,_,Pos2) :-
  deref(Pos2,TFS3,Type3,Pos3),
  insert_anti_chain(TFS3,Type3,Pos3,AC).
at_msl_traverse_modularized(AC,TFS2,_) :-  % Type3 must also be modularized, since it is a 
  arg(2,TFS2,FS),                          %  subtype of Type2
  deref(FS,TFS3,Type3,Pos3),
  arg(3,TFS3,D3),
  arg(4,TFS3,Int3),
  TFSM = tfs(msl(Type3,AC),FS,D3,Int3),
  '$put_attributes'(Pos3,TFSM).

insert_anti_chain(tfs(_,LoopBack3,D3,Int3),Type3,Pos3,AC) :-
  TFSM = tfs(msl(Type3,AC),LoopBack3,D3,Int3),
  '$put_attributes'(Pos3,TFSM).
insert_anti_chain(tfs(_,Int3),Type3,Pos3,AC) :-
  TFSM = tfs(msl(Type3,AC),Int3),
  '$put_attributes'(Pos3,TFSM).

u_msl_traverse_stubbed(Index3,AC,TFS2,Pos2) :-
  ord_add_element(Index3,AC,Union),
  pp(Union,AC12),
  u_msl_traverse_deref_stubbed(TFS2,Pos2,Type3,TFS3,Pos3),
  u_msl_traverse_act(AC12,AC12,Type3,TFS3,Pos3).
u_msl_traverse_stubbed(Index3,AC1,AC2,TFS2,Pos2) :-
  ord_add_element(Index3,AC2,AC2withIndex3),
  ord_union(AC1,AC2withIndex3,Union),
  pp(Union,AC12),
  u_msl_traverse_deref_stubbed(TFS2,Pos2,Type3,TFS3,Pos3),
  u_msl_traverse_act(AC12,AC12,Type3,TFS3,Pos3).

u_msl_traverse_modularized(Index3,AC,TFS2,Pos2) :-
  ord_add_element(Index3,AC,Union),
  pp(Union,AC12),
  u_msl_traverse_deref_modularized(TFS2,Pos2,Type3,TFS3,Pos3),
  u_msl_traverse_act(AC12,AC12,Type3,TFS3,Pos3).
u_msl_traverse_modularized(Index3,AC1,AC2,TFS2,Pos2) :-
  ord_add_element(Index3,AC2,AC2withIndex3),
  ord_union(AC1,AC2withIndex3,Union),
  pp(Union,AC12),
  u_msl_traverse_deref_modularized(TFS2,Pos2,Type3,TFS3,Pos3),
  u_msl_traverse_act(AC12,AC12,Type3,TFS3,Pos3).

u_msl_traverse_act([AC12First|AC12Rest],AC12,Type3,TFS3,Pos3) :-
  u_msl_traverse_detect_join(AC12Rest,AC12First,AC12,Type3,TFS3,Pos3).

u_msl_traverse_detect_join([],JoinIndex,_,Type3,TFS3,Pos3) :-
  add_to_type_num(JoinIndex,Type3,TFS3,Pos3).
u_msl_traverse_detect_join([_|_],_,AC,Type3,TFS3,Pos3) :-
  insert_anti_chain(TFS3,Type3,Pos3,AC).

u_msl_traverse_deref_stubbed(_,Pos2,Type3,TFS3,Pos3) :-
  deref(Pos2,TFS3,Type3,Pos3).
u_msl_traverse_deref_modularized(TFS2,_,Type3,TFS3,Pos3) :-
  arg(2,TFS2,FS),
  deref(FS,TFS3,Type3,Pos3).
