part.red 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. module part; % Access and updates parts of an algebraic expression.
  2. % Author: Anthony C. Hearn.
  3. % Copyright (c) 1991 RAND. All rights reserved.
  4. fluid '(!*intstr);
  5. symbolic procedure revalpart u;
  6. begin scalar !*intstr,expn,v,z;
  7. !*intstr := t; % To make following result in output form.
  8. expn := if (z := getrtype car u) eq 'list then listeval0 car u
  9. else reval car u;
  10. !*intstr := nil;
  11. v := cdr u;
  12. while v do
  13. begin scalar x,y;
  14. if atom expn then parterr(expn,car v)
  15. else if not numberp(x := reval car v)
  16. then msgpri("Invalid argument",car v,"to part",nil,t)
  17. else if (y := get(car expn,'partop))
  18. then return <<expn := apply2(y,expn,x); v := cdr v>>
  19. else if x=0
  20. then return <<expn :=
  21. (if (getrtype w eq 'list) and (z := 'list)
  22. then listeval0 w
  23. else if z eq 'list
  24. then <<!*intstr := t; w := reval w;
  25. !*intstr := z := nil; w>>
  26. else w) where w = car expn;
  27. v := nil>>
  28. else if x<0 then <<x := -x; y := reverse cdr expn>>
  29. else y := cdr expn;
  30. if length y<x then parterr(expn,car v)
  31. else expn := (if (getrtype w eq 'list) and (z := 'list)
  32. then listeval0 w
  33. else if z eq 'list
  34. then <<!*intstr := t; w := reval w;
  35. !*intstr := z := nil; w>>
  36. else w) where w = nth(y,x);
  37. v := cdr v
  38. end;
  39. return reval expn
  40. end;
  41. put('part,'psopfn,'revalpart);
  42. flag('(part),'immediate);
  43. symbolic procedure revalsetpart u;
  44. % Simplifies a SETPART expression.
  45. begin scalar !*intstr,x,y;
  46. x := reverse cdr u;
  47. !*intstr := t;
  48. y := reval car u;
  49. !*intstr := nil;
  50. return revalsetp1(y,reverse cdr x,reval car x)
  51. end;
  52. symbolic procedure revalsetp1(expn,ptlist,rep);
  53. if null ptlist then rep
  54. else if atom expn
  55. then msgpri("Expression",expn,
  56. "does not have part",car ptlist,t)
  57. else begin scalar x,y;
  58. if not numberp(x := reval car ptlist)
  59. then msgpri("Invalid argument",car ptlist,"to part",nil,t)
  60. else return
  61. if y := get(car expn,'setpartop) then apply3(y,expn,ptlist,rep)
  62. else if x=0 then rep . cdr expn
  63. else if x<0
  64. then car expn .
  65. reverse ssl(reverse cdr expn,
  66. -x,cdr ptlist,rep,expn . car ptlist)
  67. else car expn . ssl(cdr expn,x,cdr ptlist,
  68. rep,expn . car ptlist)
  69. end;
  70. symbolic procedure ssl(expn,indx,ptlist,rep,rest);
  71. if null expn
  72. then msgpri("Expression",car rest,"does not have part",cdr rest,t)
  73. else if indx=1 then revalsetp1(car expn,ptlist,rep) . cdr expn
  74. else car expn . ssl(cdr expn,indx-1,ptlist,rep,rest);
  75. put('part,'rtypefn,'rtypepart);
  76. symbolic procedure rtypepart u;
  77. if getrtypecar u then 'yetunknowntype else nil;
  78. % symbolic procedure rtypepart(u);
  79. % if null cdr u then getrtypecar u
  80. % else begin scalar x,n;
  81. % x := car u;
  82. % if idp x then <<x := get(car u,'avalue);
  83. % if x then x := cadr x>>;
  84. % if eqcar(x,'list) and numberp (n := aeval cadr u)
  85. % then return rtypepart(nth(cdr x,n) . cddr u)
  86. % end;
  87. % put('part,'setqfn,'(lambda (u v w) (setpart!* u v w)));
  88. put('setpart!*,'psopfn,'revalsetpart);
  89. symbolic procedure arglength u;
  90. begin scalar !*intstr,x;
  91. if null u then return 0;
  92. !*intstr := t;
  93. x := reval u;
  94. return if atom x then -1 else length cdr x
  95. end;
  96. flag('(arglength),'opfn);
  97. flag('(arglength),'noval);
  98. endmodule;
  99. end;