/code/unify.pro

https://github.com/tef/haklog · Prolog · 157 lines · 89 code · 33 blank · 35 comment · 0 complexity · ef37ef7ba6033a689485df2af1c8c06e MD5 · raw file

  1. % strucural unification
  2. % warning: pattern matching has been already written twice
  3. % and suffers from constant tweaking as I experimentally discover
  4. % the semantics
  5. % Essentially it works from left to right searching for things to match
  6. % variables are passed onto unify_var
  7. % any iterable is matched with another, - and the head is matched then the tail.
  8. % for patterns, ones on the left are used first
  9. % confusing example
  10. % [x* 1 2 3] = [1 2 3 y*]
  11. % this matches x* = [1 2 3 y*] first and then [1 2 3] = []
  12. % then succeeds with x = [1 2 3] and y = [1 2 3]
  13. % another match is also possible
  14. % x* matches [] and y matches []
  15. %unify(+Env,-Env,+Left,+Right,-Capture)
  16. %unify(_,_,_,L,R,_) :- writef("\nunify: (%w) (%w)\n",[L,R]), fail.
  17. unify(_,E,Eo,L,R,O) :- (var(L) -> (var(R) -> (L=R, L=O, E=Eo,!);(!,unify_var(E,Eo,L,R),L=O));var(R), !, unify_var(E,Eo,R,L),R=O).
  18. unify(_,E,E,[],[],[]) :- !.
  19. unify(_,_,_,[],[H|_],_) :- var(H) , !, fail.
  20. unify(_,_,_,[H|_],[],_) :- var(H) , !, fail.
  21. unify(unf,E,Eo,[Pa|Lt],[Pb|Rt],[Po|Ot]) :- \+var(Pa), Pa = p(Pl,Al),\+var(Pb), Pb = p(Pr,Ar), pattern_combine(Pl,Pr,Al,Ar,Po), !, unify(unf,E,Eo,Lt,Rt,Ot).
  22. unify(pat,E,Eo,[Pa|Lt],Ro,R) :- \+var(Pa), Pa = p(P,A), !, unify_var(E,E1,R,Ro), unify_p_l(P,E1,Eo,A,Lt,R,_).
  23. unify(pat,E,Eo,[H|Lt],Ro,R) :- \+var(H), H = call(Q,A), \+var(Q), Q = quote, \+var(A), !, unify(unf,E,Eo,[A|Lt],Ro,R).
  24. unify(_,E,E,S,A,S) :- string(S), expr_to_string(A,S1),!, S1=S.
  25. unify(_,E,E,A,S,S) :- string(S), expr_to_string(A,S1),!, S1=S.
  26. unify(M,E,Eo,L,R,O) :- iterable_pair(L,R), iterable_head_tail(L,Lh,Lt), iterable_head_tail(R,Rh,Rt),( (var(Lh),!,unify_var(E,E1,Lh,Rh), unify(M,E1,Eo,Lt,Rt,Ot), iterable_head_tail(O,Lh,Ot)); (var(Rh),!,unify_var(E,E1,Rh,Lh), unify(M,E1,Eo,Lt,Rt,Ot), iterable_head_tail(O,Rh,Ot))).
  27. unify(M,E,Eo,L,call(unf,A),C) :-!,eval(E,E1,call(unf,A),O),unify(M,E1,Eo,L,O,C).
  28. unify(M,E,Eo,call(unf,A),R,C) :-!,eval(E,E1,call(unf,A),O),unify(M,E1,Eo,O,R,C).
  29. unify(pat,E,Eo,p(P,A),Ro,O) :- !, unify_var(E,E1,R,Ro), unify_p(P,E1,Eo,A,R,O).
  30. unify(unf,E,E,p(Pl,Al),p(Pr,Ar),Po) :- !,pattern_combine(Pl,Pr,Al,Ar,Po), !.
  31. unify(M,E,Eo,L,R,O) :- iterable_pair(L,R), !, iterable_head_tail(L,Ho,To), iterable_head_tail(R,H,T),!, unify(M,E,E1,Ho,H,Oh),unify(M,E1,Eo,To,T,Ot), iterable_head_tail(O,Oh,Ot).
  32. unify(M,E,Eo,call(Ho,To), call(H,T),call(Oh,Ot)) :-!,unify(M,E,E1,Ho,H,Oh),unify(M,E1,Eo,To,T,Ot).
  33. unify(M,E,Eo,lambda(Ho,To), lambda(H,T),lambda(Oh,Ot)) :-!,unify(M,E,E1,H,Ho,Oh), unify(M,E1,Eo,T,To,Ot).
  34. unify(M,E,Eo,block(X),O,J) :- !, eval_block(E,E1,X,Xo), unify(M,E1,Eo,Xo,O,J).
  35. unify(M,E,Eo,O,block(X),J) :- !, eval_block(E,E1,X,Xo), unify(M,E1,Eo,O,Xo,J).
  36. unify(_,E,E,X,X,X) :- !.
  37. arguments_combine(Xa,Y,Xa) :- var(Xa), !,var(Y), Xa=Y,!.
  38. arguments_combine(Xa,Y,Xa) :- \+ var(Xa), \+ var(Y) , Xa=Y.
  39. pattern_combine(X,X,Xa,Ya,p(X,Ao)) :- !,arguments_combine(Xa,Ya,Ao).
  40. pattern_combine(X,some,Xa,Ya,p(some,Ao)) :- member(X,[zsome,any,zany]),!,arguments_combine(Xa,Ya,Ao).
  41. pattern_combine(some,X,Xa,Ya,p(some,Ao)) :- member(X,[zsome,any,zany]),!,arguments_combine(Xa,Ya,Ao).
  42. pattern_combine(X,zsome,Xa,Ya,p(zsome,Ao)) :- member(X,[any,zany]),!,arguments_combine(Xa,Ya,Ao).
  43. pattern_combine(zsome,X,Xa,Ya,p(zsome,Ao)) :- member(X,[any,zany]),!,arguments_combine(Xa,Ya,Ao).
  44. pattern_combine(any,zany,Xa,Ya,p(any,Ao)) :-!,arguments_combine(Xa,Ya,Ao).
  45. pattern_combine(zany,any,Xa,Ya,p(any,Ao)) :-!,arguments_combine(Xa,Ya,Ao).
  46. pattern_combine(maybe,zmaybe,Xa,Ya,p(maybe,Ao)) :-!,arguments_combine(Xa,Ya,Ao).
  47. pattern_combine(zmaybe,maybe,Xa,Ya,p(maybe,Ao)) :-!,arguments_combine(Xa,Ya,Ao).
  48. pattern_combine(ahead,isnt,Xa,Ya,p(ahead,Xa)) :-!, \+ Xa = Ya.
  49. pattern_combine(isnt,ahead,Xa,Ya,p(ahead,Ya)) :-!, \+ Xa = Ya.
  50. %unify_var(+Env,-Env,+Var,+Expr)
  51. % unify an expression with a variable
  52. unify_var(E,E,X,Y) :- var(Y),!,X=Y.
  53. unify_var(E,Eo,[H|To],[H|T]) :- var(H),!, unify_var(E,Eo,To,T).
  54. unify_var(E,E,[],[]) :-!.
  55. unify_var(E,Eo,O,p(P,A)) :- !, unify_var_p(P,E,Eo,A,O),!.
  56. unify_var(E,Eo,O,[p(P,A)|T]) :- !,(unify_var_p_l(P,E,E1,A,Ho),!,unify_var(E1,Eo,To,T), join(Ho,To,O)); (unify_var_p_l(P,E,E1,A,Ho), unify_var(E1,Eo,To,T), join(Ho,To,O),!).
  57. unify_var(E,Eo,[Ho|To],[H|T]) :- !,unify_var(E,E1,Ho,H), unify_var(E1,Eo,To,T).
  58. unify_var(E,Eo,L,call(pat,A)) :-!,eval(E,E1,call(pat,A),O),unify_var(E1,Eo,L,O).
  59. unify_var(E,Eo,L,call(unf,A)) :-!,eval(E,E1,call(unf,A),O),unify_var(E1,Eo,L,O).
  60. unify_var(E,E,call(def,T), call(def,T)) :-!.
  61. unify_var(E,Eo,call(Ho,To), call(H,T)) :-!,unify_var(E,E1,Ho,H),unify_var(E1,Eo,To,T).
  62. unify_var(E,E,lambda(H,T), lambda(H,T)) :-!.
  63. unify_var(E,Eo,O,block(X)) :- !, eval_block(E,E1,X,Xo), unify_var(E1,Eo,O,Xo).
  64. unify_var(E,E,X,X) :- !.
  65. % here be dragons
  66. %unify_var_p(+Pattern,+Env,-Env,+Args,+Right)
  67. %unify a pattern with a right hand side, only ones we expect out of a list context
  68. %are here
  69. unify_var_p(P,E,Eo,X,R) :- !, unify_var_p_l(P,E,Eo,X,[R]).
  70. %unify_var_p_l(+Pattern,+Env,-Env,+Args,+Var)
  71. % reminder- things matched to patterns are unified with a var
  72. % so [x*] = [ 1 2 [1 2 3]* ], 1 2 [1 2 3]* is unified with a var first
  73. % and these functions unpack patterns with iterable arguments
  74. % becomes [x*] = [1 2 1 2 3]
  75. %
  76. unify_var_p_l(P,E,E,X,[p(P,X)]) :- var(X),!.
  77. %unify_var_p_l(bind,E,Eo,[L1,L2],R) :- !, unify_var(E,E1,R,L1), unify_var(E1,Eo,L2,R).
  78. unify_var_p_l(choice,E,Eo,[L1|L2],R) :- !, (unify_var(E,Eo,R,L1); unify_var_p_l(choice,E,Eo,L2,R)).
  79. unify_var_p_l(ahead,E,E,X,[p(ahead,X)]) :- !.
  80. unify_var_p_l(isnt,E,E,X,[p(isnt,X)]) :- !.
  81. unify_var_p_l(take,E,Eo,[L,N],R) :- unify_p_l(take,E,E1,[_,N],[],L,L1),!,unify_var(E1,Eo,R,L1).
  82. unify_var_p_l(ztake,E,Eo,[L,N],R) :- unify_p_l(ztake,E,E1,[_,N],[],L,L1),!,unify_var(E1,Eo,R,L1).
  83. unify_var_p_l(any,E,Eo,L,R) :- unify_p_l(any,E,E1,_,[],L,L1),!,unify_var(E1,Eo,R,L1).
  84. unify_var_p_l(zany,E,Eo,L,R) :- unify_p_l(zany,E,E1,_,[],L,L1),!,unify_var(E1,Eo,R,L1).
  85. unify_var_p_l(some,E,Eo,L,R) :- unify_p_l(some,E,E1,_,[],L,L1),!,unify_var(E1,Eo,R,L1).
  86. unify_var_p_l(zsome,E,Eo,L,R) :- unify_p_l(zsome,E,E1,_,[],L,L1),!,unify_var(E1,Eo,R,L1).
  87. unify_var_p_l(maybe,E,Eo,L,R) :- unify_p_l(maybe,E,E1,_,[],L,L1),!,unify_var(E1,Eo,R,L1).
  88. unify_var_p_l(zmaybe,E,Eo,L,R) :- unify_p_l(zmaybe,E,E1,_,[],L,L1),!,unify_var(E1,Eo,R,L1).
  89. % matches things like 1* - this general case is possibly a bad thing
  90. unify_var_p_l(P,E,E,X,[p(P,X)]).
  91. %unify_p(+Pattern,+Env,-Env,+Args,+Right,-Capture)
  92. unify_p(bind,E,Eo,[L1,L2],R,O) :- !, unify(pat,E,E1,L1,R,O),unify_var(E1,Eo,L2,O).
  93. unify_p(choice,E,Eo,[L1|L2],R,C) :- !, (unify(pat,E,Eo,L1,R,C) ; unify_p(choice,E,Eo,L2,R,C)).
  94. unify_p(class,E,E,L,R,R) :- !,class_match(L,R).
  95. unify_p(crange,E,E,L,R,R) :- !,crange_match(L,R).
  96. %unify_p_l(+Pattern,+Env,-Env,+Args,+LeftTail,+Right,-Capture)
  97. %unify_p_l(P,_,_,A,L,R,_) :- writef("unify_p_l:%w(%w)|%w=%w\n",[P,A,L,R]), fail.
  98. unify_p_l(bind,E,Eo,[L1,L2],Lt,R,O) :- var(L1),!,( iterable_head_tail(R,Rh,Rt), !, unify(pat,E,E1,L1,Rh,O),unify(pat,E1,E2,Lt,Rt,_); unify(pat,E,E2,L1,R,O)),unify(unf,E2,Eo,L2,O,_).
  99. unify_p_l(bind,E,Eo,[p(P,A),N],Lt,R,C):- !, unify_p_l(P,E,E1,A,Lt,R,C),unify(unf,E1,Eo,N,C,_).
  100. unify_p_l(bind,E,Eo,[L1,L2],Lt,R,O) :- iterable_head_tail(R,Rh,Rt), !, unify(pat,E,E1,L1,Rh,O),unify(pat,E1,E2,Lt,Rt,_),unify(unf,E2,Eo,L2,O).
  101. unify_p_l(choice,E,Eo,[X|L2],Lt,R,C):- \+var(X), X=p(P,A),!,((unify_p_l(P,E,Eo,A,Lt,R,C)) ; (unify_p_l(choice,E,Eo,L2,Lt,R,C))).
  102. unify_p_l(choice,E,Eo,[L1|L2],Lt,R,O) :- iterable_head_tail(R,Rh,Rt),!, ((unify(pat,E,E1,L1,Rh,O),unify(pat,E1,Eo,Lt,Rt,_)); (unify_p_l(choice,E,Eo,L2,Lt,R,O))).
  103. unify_p_l(class,E,Eo,L,Lt,R,Rh) :- iterable_head_tail(R,Rh,_),!,class_match(L,Rh), unify(pat,E,Eo,Lt,R,_).
  104. unify_p_l(crange,E,Eo,L,Lt,R,Rh) :- iterable_head_tail(R,Rh,_),!,crange_match(L,Rh), unify(pat,E,Eo,Lt,R,_).
  105. unify_p_l(ahead,E,Eo,L,Lt,R,O) :- iterable_head_tail(R,Rh,_),!,unify(pat,E,E1,L,Rh,O), unify(pat,E1,Eo,Lt,R,_).
  106. unify_p_l(isnt,E,Eo,L,Lt,R,Rh) :- iterable_head_tail(R,Rh,_), !,\+ unify(pat,E,_,L,Rh,_),!,unify(pat,E,Eo,Lt,R,_).
  107. % here we have one rule for any on a variable or an iterable
  108. unify_p_l(take,E,Eo,[A,B],To,R,C) :- unify_var(E,E1,A1,B), (var(A1),!, unify_p_l(any,E1,Eo,A,To,R,C), iter_length(C,A1); number(A1),iterable_take(R,C,Rt,A1), unify(pat,E1,Eo,To,Rt,_)).
  109. unify_p_l(ztake,E,Eo,[A,B],To,R,C) :- unify_var(E,E1,A1,B), (var(A1),!, unify_p_l(zany,E1,Eo,A,To,R,C), iter_length(C,A1); number(A1),iterable_ztake(R,Rh,Rt,A1), !, unify(pat,E1,E2,A,Rh,C),unify(pat,E2,Eo,To,Rt,_)).
  110. unify_p_l(any,E,Eo,A,To,R,C) :- (var(A); iterable_pair(A,R); null(A),null(R)),!,iterable_any(R,Rh,Rt) , unify(pat,E,E1,A,Rh,C), unify(pat,E1,Eo,To,Rt,_).
  111. % and another for matching things like 1*
  112. unify_p_l(any,E,Eo,A,To,R,C) :- iterable_head_tail(R,Rh,Rt), unify(pat,E,E1,A,Rh,Ch), unify_p_l(any,E1,Eo,A,To,Rt,Ct), iterable_head_tail(C,Ch,Ct).
  113. unify_p_l(any,E,Eo,_,To,R,C) :- empty(R,C), unify(pat,E,Eo,To,R,_).
  114. unify_p_l(zany,E,Eo,A,To,R,C) :- (var(A); iterable_pair(A,R); null(A), null(R)),!,iterable_zany(R,Rh,Rt) , unify(pat,E,E1,A,Rh,C), unify(pat,E1,Eo,To,Rt,_).
  115. unify_p_l(zany,E,Eo,_,To,R,C) :- empty(R,C), unify(pat,E,Eo,To,R,_).
  116. unify_p_l(zany,E,Eo,A,To,R,C) :- iterable_head_tail(R,Rh,Rt), unify(pat,E,E1,A,Rh,Ch), unify_p_l(zany,E1,Eo,A,To,Rt,Ct), iterable_head_tail(C,Ch,Ct).
  117. unify_p_l(some,E,Eo,A,To,R,C) :- (var(A);iterable_pair(A,R)),!,iterable_some(R,Rh,Rt) , unify(pat,E,E1,A,Rh,C), unify(pat,E1,Eo,To,Rt,_).
  118. unify_p_l(some,E,Eo,A,To,R,C) :- iterable_head_tail(R,Rh,Rt),!, unify(pat,E,E1,A,Rh,Ch), unify_p_l(any,E1,Eo,A,To,Rt,Ct), iterable_head_tail(C,Ch,Ct).
  119. unify_p_l(zsome,E,Eo,A,To,R,C) :- (var(A);iterable_pair(A,R)),!,iterable_zsome(R,Rh,Rt) , unify(pat,E,E1,A,Rh,C), unify(pat,E1,Eo,To,Rt,_).
  120. unify_p_l(zsome,E,Eo,A,To,R,C) :- iterable_head_tail(R,Rh,Rt),!, unify(pat,E,E1,A,Rh,Ch), unify_p_l(zany,E1,Eo,A,To,Rt,Ct), iterable_head_tail(C,Ch,Ct).
  121. unify_p_l(maybe,E,Eo,A,T,R,H) :- iterable_head_tail(R,H,To), unify(pat,E,E1,A,H,_), unify(pat,E1,Eo,T,To,_).
  122. unify_p_l(maybe,E,Eo,_,T,To,_):- unify(pat,E,Eo,T,To,_).
  123. unify_p_l(zmaybe,E,Eo,_,T,To,_):- unify(pat,E,Eo,T,To,_).
  124. unify_p_l(zmaybe,E,Eo,A,T,R,H) :- iterable_head_tail(R,H,To), unify(pat,E,E1,A,H,_), unify(pat,E1,Eo,T,To,_).