eval-apply.red 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. %
  2. % EVAL-APPLY.RED - Function calling mechanism
  3. %
  4. % Author: Eric Benson
  5. % Symbolic Computation Group
  6. % Computer Science Dept.
  7. % University of Utah
  8. % Date: 20 August 1981
  9. % Copyright (c) 1981 University of Utah
  10. %
  11. % <PSL.KERNEL>EVAL-APPLY.RED.2, 20-Sep-82 10:36:28, Edit by BENSON
  12. % CAR of a form is never evaluated
  13. % <PSL.INTERP>EVAL-APPLY.RED.5, 6-Jan-82 19:22:46, Edit by GRISS
  14. % Add NEXPR
  15. % FUnBoundP and other function cell primitives found in FUNCTION-PRIMITIVES
  16. % Eval and Apply could have been defined using only GetD rather than these
  17. % primitves. They are used instead to avoid the CONS in GETD.
  18. % ValueCell is found in SYMBOL-VALUES.RED
  19. % IDApply, CodeApply, IDEvalApply and CodeEvalApply are written in LAP
  20. % due to register usage and to make them faster. They are found in
  21. % APPLY-LAP.RED. IDApply1 is handled by the compiler
  22. % uses EvProgN, found in EASY-SL.RED, expr for PROGN
  23. % Error numbers:
  24. % 1000 - undefined function
  25. % 1100 - ill-formed function expression
  26. % 1200 - argument number mismatch
  27. % 1300 - unknown function type
  28. % +3 in LambdaEvalApply
  29. % +4 in LambdaApply
  30. % +2 in Apply
  31. % +1 in Eval
  32. CompileTime flag('(LambdaEvalApply LambdaApply), 'InternalFunction);
  33. on SysLisp;
  34. % the only reason these 2 are in Syslisp is to speed up arithmetic (N := N + 1)
  35. syslsp procedure LambdaEvalApply(Fn, Args); %. Fn is Lambda, Args to be Evaled
  36. if not (PairP Fn and car Fn = 'LAMBDA) then
  37. ContinuableError('1103,
  38. '"Ill-formed function expression",
  39. Fn . Args)
  40. else begin scalar N, Result;
  41. N := BindEval(cadr Fn, Args); % hand-coded, bind formals to evlis args
  42. if N = -1 then return
  43. ContinuableError('1203,
  44. '"Argument number mismatch",
  45. Fn . Args);
  46. Result := EvProgN cddr Fn;
  47. if N neq 0 then UnBindN N;
  48. return Result;
  49. end;
  50. syslsp procedure LambdaApply(Fn, Args); %. Fn is Lambda, unevaled Args
  51. if not (PairP Fn and car Fn = 'LAMBDA) then
  52. ContinuableError('1104,
  53. '"Ill-formed function expression",
  54. Fn . for each X in Args collect MkQuote X)
  55. else begin scalar Formals, N, Result;
  56. Formals := cadr Fn;
  57. N := 0;
  58. while PairP Formals and PairP Args do
  59. << LBind1(car Formals, car Args);
  60. Formals := cdr Formals;
  61. Args := cdr Args;
  62. N := N + 1 >>;
  63. if PairP Formals or PairP Args then return
  64. ContinuableError('1204,
  65. '"Argument number mismatch",
  66. Fn . for each X in Args collect MkQuote X);
  67. Result := EvProgN cddr Fn;
  68. if N neq 0 then UnBindN N;
  69. return Result;
  70. end;
  71. off SysLisp;
  72. % Apply differs from the Standard Lisp Report in that functions other
  73. % than EXPRs are allowed to be applied, the effect being the same as
  74. % Apply(cdr GetD Fn, Args)
  75. lisp procedure Apply(Fn, Args); %. Indirect function call
  76. if IDP Fn then begin scalar StackMarkForBacktrace, Result;
  77. if FUnBoundP Fn then return
  78. ContinuableError(1002,
  79. BldMsg("%r is an undefined function", Fn),
  80. Fn . for each X in Args collect MkQuote X);
  81. StackMarkForBacktrace := MkBTR Inf Fn;
  82. Result := if FCodeP Fn then CodeApply(GetFCodePointer Fn, Args)
  83. else LambdaApply(get(Fn, '!*LambdaLink), Args);
  84. return Result;
  85. end
  86. else if CodeP Fn then CodeApply(Fn, Args)
  87. else if PairP Fn and car Fn = 'LAMBDA then
  88. LambdaApply(Fn, Args)
  89. else
  90. ContinuableError(1102,
  91. "Ill-formed function expression",
  92. Fn . for each X in Args collect MkQuote X);
  93. lisp procedure Eval U; %. Interpret S-Expression as program
  94. if not PairP U then
  95. if not IDP U then U else ValueCell U
  96. else begin scalar Fn;
  97. Fn := car U;
  98. return if IDP Fn then
  99. if FUnBoundP Fn then
  100. ContinuableError(1300,
  101. BldMsg("%r is an undefined function", Fn),
  102. U)
  103. else begin scalar FnType, StackMarkForBacktrace, Result;
  104. FnType := GetFnType Fn;
  105. StackMarkForBacktrace := MkBTR Inf Fn;
  106. Result := if null FnType then % must be an EXPR
  107. if FCodeP Fn then
  108. CodeEvalApply(GetFCodePointer Fn, cdr U)
  109. else LambdaEvalApply(get(Fn, '!*LambdaLink),
  110. cdr U)
  111. else if FnType = 'FEXPR then
  112. IDApply1(cdr U, Fn)
  113. else if FnType = 'NEXPR then
  114. IDApply1(EvLis cdr U, Fn)
  115. else if FnType = 'MACRO then
  116. Eval IDApply1(U, Fn)
  117. else
  118. ContinuableError(1301,
  119. BldMsg("Unknown function type %r",
  120. FnType),
  121. U);
  122. return Result;
  123. end
  124. else if CodeP Fn then CodeEvalApply(Fn, cdr U)
  125. else if PairP Fn and car Fn = 'LAMBDA then
  126. LambdaEvalApply(Fn, cdr U)
  127. else ContinuableError(1302,
  128. BldMsg("Ill-formed expression in Eval %r", U),
  129. U);
  130. end;
  131. END;