Daniel@0: /* Part of DML (Digital Music Laboratory) Daniel@0: Copyright 2014-2015 Samer Abdallah, University of London Daniel@0: Daniel@0: This program is free software; you can redistribute it and/or Daniel@0: modify it under the terms of the GNU General Public License Daniel@0: as published by the Free Software Foundation; either version 2 Daniel@0: of the License, or (at your option) any later version. Daniel@0: Daniel@0: This program is distributed in the hope that it will be useful, Daniel@0: but WITHOUT ANY WARRANTY; without even the implied warranty of Daniel@0: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Daniel@0: GNU General Public License for more details. Daniel@0: Daniel@0: You should have received a copy of the GNU General Public Daniel@0: License along with this library; if not, write to the Free Software Daniel@0: Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Daniel@0: */ Daniel@0: Daniel@0: :- module(jpath, [ jpath/2, op(600,xfy,#) ]). Daniel@0: :- use_module(library(dcg_core)). Daniel@0: :- use_module(library(insist)). Daniel@0: Daniel@0: % :- op(600,fx,#). Daniel@0: :- op(600,xfy,#). Daniel@0: Daniel@0: % harvest(M,Tree) :- harvest(M,just(Tree),nothing). Daniel@0: % harvest(\X,just(X),nothing). Daniel@0: % harvest(@F,just(X),just(Y)) :- Y=X.F. Daniel@0: % harvest(#N,just(X),just(Y)) :- nth1(N,X,Y). Daniel@0: % harvest(F*G) --> harvest(F), harvest(G). Daniel@0: % harvest((F//G)) --> harvest(F) // harvest(G). Daniel@0: Daniel@0: % dec(id,X,X). Daniel@0: % dec([],_,[]). Daniel@0: % dec([D|Ds],X,[Y|Ys]) :- dec(D,X,Y), dec(Ds,X,Ys). Daniel@0: % dec(@F,X,Y) :- Y=X.F. Daniel@0: % dec(F*G,X,Z) :- dec(F,X,Y), dec(G,Y,Z). Daniel@0: % dec(swap,(X,Y),(Y,X)). Daniel@0: % dec(dup,X,(X,X)). Daniel@0: % dec(fst(F),(X,Y),(Z,Y)) :- dec(F,X,Z). Daniel@0: % dec((F,G),X,(Y,Z)) :- dec(F,X,Y), dec(G,X,Z). Daniel@0: % dec(item,X,Y) :- member(Y,X). Daniel@0: Daniel@0: % decode(F, R, X) :- atomic(F), X=R.F. Daniel@0: % decode(item(D), R, X) :- decode(D,R,Y), member(X,Y). Daniel@0: % decode(F/G, R, X) :- decode(F,R,Y), decode(G,Y,X). Daniel@0: Daniel@0: jpath(Y,X) :- Daniel@0: (complex(X) -> (match(Y,X); Y=(_,_), multi_match(Y,[],X)) ; Y=X). Daniel@0: Daniel@0: complex(X) :- is_list(X). Daniel@0: complex(X) :- is_dict(X). Daniel@0: Daniel@0: match(\X,X). Daniel@0: match(Y,X) :- var(Y), !, Daniel@0: ( is_dict(X) -> match_dict(Y,X) Daniel@0: ; is_list(X) -> match_list(Y,X) Daniel@0: ). Daniel@0: match(dict(X),X) :- must_be(dict,X). Daniel@0: match(list(X),X) :- must_be(list,X). Daniel@0: match(N#Y,X) :- must_be(list,X), match_member(N,Y,X). Daniel@0: match(F:Y,X) :- must_be(dict,X), match_field(F,Y,X). Daniel@0: Daniel@0: match_dict(dict(X),X). Daniel@0: match_dict(F:V,X) :- match_field(F,V,X). Daniel@0: Daniel@0: match_list(list(X),X). Daniel@0: match_list(N#Y,X) :- match_member(N,Y,X). Daniel@0: Daniel@0: match_field(F,Y,X) :- Daniel@0: ( var(F) -> get_dict(F,X,Z) Daniel@0: ; insist(get_dict(F,X,Z),field_not_present(F,X)) Daniel@0: ), Daniel@0: jpath(Y,Z). Daniel@0: Daniel@0: match_member(N,Y,X) :- Daniel@0: ( var(N) -> nth1(N,X,Z) Daniel@0: ; nth1(N,X,Z) % insist(...),index_out_of_range(N,X)) Daniel@0: ), Daniel@0: jpath(Y,Z). Daniel@0: Daniel@0: % multi_match([],_,_). Daniel@0: % multi_match([S|Ss],Prev,X) :- match1(S,X), \+member(S,Prev), multi_match(Ss,[S|Prev],X). Daniel@0: multi_match(S,Prev,X) :- match(S,X), \+member(S,Prev). Daniel@0: multi_match((S,Ss),Prev,X) :- match(S,X), \+member(S,Prev), multi_match(Ss,[S|Prev],X).