pattperm.red 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. module pattperm; % Rest of unify --- argument permutation, etc.
  2. % Author: Kevin McIsaac.
  3. % When sym!-assoc is off, PM does not force normal generic variables to
  4. % take more than one argument if a multi-generic symbol is present. This
  5. % makes the patterns much more efficient but not fully searched. Sane
  6. % patterns do not require this. For example
  7. % m(a+b+c,?a+??c) will return {?a -> a, ??c -> null!-fn(b,c)} but not
  8. % {?a -> a+b, ??c -> c} or {?a -> a+b+c, ??c -> null!-fn()}
  9. fluid '(symm op r p i upb identity expand acontract mcontract comb);
  10. global('(!*sym!-assoc))$
  11. global('(!*udebug))$ %print out next information
  12. symbolic procedure first0(u,n);
  13. if n>0 then car u . first0(cdr u,n-1) else nil;
  14. symbolic procedure last0(u,n);
  15. if n<1 then u else last0(cdr u,n-1);
  16. symbolic procedure list!-mgen u;
  17. % Count the number of top level mgen atoms.
  18. begin integer i;
  19. for each j in u do if atom j and mgenp(j) then i := i+1;
  20. return i
  21. end;
  22. symbolic procedure initarg(u);
  23. begin scalar assoc, mgen, flex, filler; integer n, lmgen;
  24. symm := flagp(op,'symmetric);
  25. n := length(p) - length(r) + 1;
  26. identity := ident(op);
  27. mgen := mgenp(car r);
  28. lmgen := list!-mgen(cdr r);
  29. assoc := flagp(op,'assoc)
  30. and not(symm and(lmgen > 0) and not !*sym!-assoc);
  31. flex := (length(r)>1) and (assoc or lmgen);
  32. filler:= n > 1 or (identity and length p > 0);
  33. %
  34. mcontract := mgen and filler;
  35. acontract := assoc and filler and not mgen;
  36. expand := identity and (n < 1 or flex);
  37. %
  38. i := if flex or n < 1 then
  39. if mgen then 0
  40. else 1
  41. else n;
  42. upb := if identity then length p else n + lmgen;
  43. if symm then comb := initcomb u
  44. end;
  45. symbolic procedure nextarg u;
  46. if symm then s!-nextarg u else o!-nextarg u;
  47. symbolic procedure o!-nextarg u;
  48. begin scalar args;
  49. if !*udebug then uprint(nil);
  50. args :=
  51. if (i = 1) and (i <= upb) then u
  52. else if (i = 0) and (i <= upb) then '(null!-fn).u
  53. else if acontract and (i <= upb)
  54. then mval((op . first0(u,i)) . last0(u,i))
  55. else if mcontract and (i <= upb)
  56. then ('null!-fn . first0(u,i)) . last0(u,i)
  57. else if expand then <<expand := nil; identity . u>>;
  58. i := i + 1;
  59. return args
  60. end;
  61. symbolic procedure s!-nextarg u;
  62. begin scalar v, args;
  63. if !*udebug then uprint(nil);
  64. if null comb then<< i := i + 1; comb := initcomb u>>;
  65. args :=
  66. if (v := getcomb(u,comb) ) then
  67. if (i = 1) and (i <= upb) then caar v . cdr v
  68. else if (i = 0) and (i <= upb) then '(null!-fn).u
  69. else if acontract and (i <= upb) then mval((op.car(v)).cdr v)
  70. else if mcontract and (i <= upb) then ('null!-fn.car(v)).cdr v
  71. else if expand then <<expand := nil; identity . u>>
  72. else nil
  73. else if (i = 0) and (i <= upb) then '(null!-fn).u
  74. else if expand then <<expand := nil; identity.u>>;
  75. return args
  76. end;
  77. symbolic procedure getcomb(u,v);
  78. begin scalar group;
  79. comb := nextcomb(v,i);
  80. group := car comb;
  81. comb := cdr comb;
  82. return if group then group . setdiff(u,group) else nil
  83. end$
  84. symbolic procedure uprint(u);
  85. <<if expand then <<prin2('expand);prin2(" ")>>;
  86. if mcontract then <<prin2('mcontract);prin2(" ")>>;
  87. if acontract then <<prin2('acontract);prin2(" ")>>;
  88. prin2(" upb = ");prin2(upb); prin2(" i = ");prin2(i);
  89. if symm then <<prin2('symmetric);prin2(comb)>>;
  90. terpri()>>$
  91. symbolic procedure initcomb(u); u.nil$
  92. symbolic procedure nextcomb(env,n);
  93. % Env is of the form args . env, where args is a list of arguments.
  94. % Value is list of all combinations of n elements from the list u.
  95. begin scalar args, nenv, v; integer i;
  96. args := car env; nenv := cdr env;
  97. return
  98. if n=0 then nil.nil
  99. else if (i:=length(args) - n)<0 then list(nil)
  100. else if i = 0 then args.nil
  101. else if nenv then <<v := nextcomb(nenv,n - 1);
  102. (car(args) . car(v)) .
  103. (if cdr v then args . cdr v
  104. else list cdr(args))>>
  105. else <<v := nextcomb(initcomb(cdr args),n - 1);
  106. (car(args) . car(v)) . (if cdr v then args . cdr v
  107. else list cdr(args))>>
  108. end;
  109. endmodule;
  110. end;