PageRenderTime 46ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/src/c/eval.d

https://gitlab.com/jlarocco/ecl
D | 258 lines | 205 code | 13 blank | 40 comment | 39 complexity | 6c41b4ed08306259fb59891f8bfa4182 MD5 | raw file
Possible License(s): LGPL-2.0, JSON
  1. /* -*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*- */
  2. /* vim: set filetype=c tabstop=8 shiftwidth=4 expandtab: */
  3. /*
  4. eval.c -- Eval.
  5. */
  6. /*
  7. Copyright (c) 1984, Taiichi Yuasa and Masami Hagiya.
  8. Copyright (c) 1990, Giuseppe Attardi.
  9. Copyright (c) 2001, Juan Jose Garcia Ripoll.
  10. ECL is free software; you can redistribute it and/or
  11. modify it under the terms of the GNU Library General Public
  12. License as published by the Free Software Foundation; either
  13. version 2 of the License, or (at your option) any later version.
  14. See file '../Copyright' for full details.
  15. */
  16. #include <ecl/ecl.h>
  17. #include <ecl/ecl-inl.h>
  18. #include <ecl/internal.h>
  19. cl_object *
  20. _ecl_va_sp(cl_narg narg)
  21. {
  22. return ecl_process_env()->stack_top - narg;
  23. }
  24. /* Calling conventions:
  25. Compiled C code calls lisp function supplying #args, and args.
  26. Linking function performs check_args, gets jmp_buf with _setjmp, then
  27. if cfun then stores C code address into function link location
  28. and transfers to jmp_buf at cf_self
  29. if cclosure then replaces #args with cc_env and calls cc_self
  30. otherwise, it emulates funcall.
  31. */
  32. cl_object
  33. ecl_apply_from_stack_frame(cl_object frame, cl_object x)
  34. {
  35. cl_object *sp = frame->frame.base;
  36. cl_index narg = frame->frame.size;
  37. cl_object fun = x;
  38. AGAIN:
  39. frame->frame.env->function = fun;
  40. if (ecl_unlikely(fun == OBJNULL || fun == ECL_NIL))
  41. FEundefined_function(x);
  42. switch (ecl_t_of(fun)) {
  43. case t_cfunfixed:
  44. if (ecl_unlikely(narg != (cl_index)fun->cfun.narg))
  45. FEwrong_num_arguments(fun);
  46. return APPLY_fixed(narg, fun->cfunfixed.entry_fixed, sp);
  47. case t_cfun:
  48. return APPLY(narg, fun->cfun.entry, sp);
  49. case t_cclosure:
  50. return APPLY(narg, fun->cclosure.entry, sp);
  51. case t_instance:
  52. switch (fun->instance.isgf) {
  53. case ECL_STANDARD_DISPATCH:
  54. case ECL_RESTRICTED_DISPATCH:
  55. return _ecl_standard_dispatch(frame, fun);
  56. case ECL_USER_DISPATCH:
  57. fun = fun->instance.slots[fun->instance.length - 1];
  58. goto AGAIN;
  59. case ECL_READER_DISPATCH:
  60. case ECL_WRITER_DISPATCH:
  61. return APPLY(narg, fun->instance.entry, sp);
  62. default:
  63. FEinvalid_function(fun);
  64. }
  65. case t_symbol:
  66. if (ecl_unlikely(fun->symbol.stype & ecl_stp_macro))
  67. FEundefined_function(x);
  68. fun = ECL_SYM_FUN(fun);
  69. goto AGAIN;
  70. case t_bytecodes:
  71. return ecl_interpret(frame, ECL_NIL, fun);
  72. case t_bclosure:
  73. return ecl_interpret(frame, fun->bclosure.lex, fun->bclosure.code);
  74. default:
  75. FEinvalid_function(x);
  76. }
  77. }
  78. cl_objectfn
  79. ecl_function_dispatch(cl_env_ptr env, cl_object x)
  80. {
  81. cl_object fun = x;
  82. AGAIN:
  83. if (ecl_unlikely(fun == OBJNULL || fun == ECL_NIL))
  84. FEundefined_function(x);
  85. switch (ecl_t_of(fun)) {
  86. case t_cfunfixed:
  87. env->function = fun;
  88. return fun->cfunfixed.entry;
  89. case t_cfun:
  90. env->function = fun;
  91. return fun->cfun.entry;
  92. case t_cclosure:
  93. env->function = fun;
  94. return fun->cclosure.entry;
  95. case t_instance:
  96. env->function = fun;
  97. return fun->instance.entry;
  98. case t_symbol:
  99. if (ecl_unlikely(fun->symbol.stype & ecl_stp_macro))
  100. FEundefined_function(x);
  101. fun = ECL_SYM_FUN(fun);
  102. goto AGAIN;
  103. case t_bytecodes:
  104. env->function = fun;
  105. return fun->bytecodes.entry;
  106. case t_bclosure:
  107. env->function = fun;
  108. return fun->bclosure.entry;
  109. default:
  110. FEinvalid_function(x);
  111. }
  112. }
  113. cl_object
  114. cl_funcall(cl_narg narg, cl_object function, ...)
  115. {
  116. cl_object output;
  117. --narg;
  118. {
  119. ECL_STACK_FRAME_VARARGS_BEGIN(narg, function, frame);
  120. output = ecl_apply_from_stack_frame(frame, function);
  121. ECL_STACK_FRAME_VARARGS_END(frame);
  122. }
  123. return output;
  124. }
  125. @(defun apply (fun lastarg &rest args)
  126. @
  127. if (narg == 2 && ecl_t_of(lastarg) == t_frame) {
  128. return ecl_apply_from_stack_frame(lastarg, fun);
  129. } else {
  130. cl_object out;
  131. cl_index i;
  132. struct ecl_stack_frame frame_aux;
  133. const cl_object frame = ecl_stack_frame_open(the_env,
  134. (cl_object)&frame_aux,
  135. narg -= 2);
  136. for (i = 0; i < narg; i++) {
  137. ECL_STACK_FRAME_SET(frame, i, lastarg);
  138. lastarg = ecl_va_arg(args);
  139. }
  140. if (ecl_t_of(lastarg) == t_frame) {
  141. /* This could be replaced with a memcpy() */
  142. for (i = 0; i < lastarg->frame.size; i++) {
  143. ecl_stack_frame_push(frame, lastarg->frame.base[i]);
  144. }
  145. } else loop_for_in (lastarg) {
  146. if (ecl_unlikely(i >= ECL_CALL_ARGUMENTS_LIMIT)) {
  147. ecl_stack_frame_close(frame);
  148. FEprogram_error_noreturn("CALL-ARGUMENTS-LIMIT exceeded",0);
  149. }
  150. ecl_stack_frame_push(frame, CAR(lastarg));
  151. i++;
  152. } end_loop_for_in;
  153. out = ecl_apply_from_stack_frame(frame, fun);
  154. ecl_stack_frame_close(frame);
  155. return out;
  156. }
  157. @)
  158. cl_object
  159. cl_eval(cl_object form)
  160. {
  161. return si_eval_with_env(1, form);
  162. }
  163. @(defun constantp (arg &optional env)
  164. @
  165. return _ecl_funcall3(@'ext::constantp-inner', arg, env);
  166. @)
  167. @(defun ext::constantp-inner (form &optional env)
  168. cl_object value;
  169. @
  170. AGAIN:
  171. switch (ecl_t_of(form)) {
  172. case t_list:
  173. if (Null(form)) {
  174. value = ECL_T;
  175. break;
  176. }
  177. if (ECL_CONS_CAR(form) == @'quote') {
  178. value = ECL_T;
  179. break;
  180. }
  181. /*
  182. value = cl_macroexpand(2, form, env);
  183. if (value != form) {
  184. form = value;
  185. goto AGAIN;
  186. }
  187. */
  188. value = ECL_NIL;
  189. break;
  190. case t_symbol:
  191. value = cl_macroexpand(2, form, env);
  192. if (value != form) {
  193. form = value;
  194. goto AGAIN;
  195. }
  196. if (!(form->symbol.stype & ecl_stp_constant)) {
  197. value = ECL_NIL;
  198. break;
  199. }
  200. default:
  201. value = ECL_T;
  202. }
  203. ecl_return1(the_env, value);
  204. @)
  205. @(defun ext::constant-form-value (form &optional env)
  206. cl_object value;
  207. @
  208. {
  209. AGAIN:
  210. switch (ecl_t_of(form)) {
  211. case t_list:
  212. if (Null(form)) {
  213. value = ECL_NIL;
  214. break;
  215. }
  216. if (ECL_CONS_CAR(form) == @'quote') {
  217. return cl_second(form);
  218. }
  219. /*
  220. value = cl_macroexpand(2, form, env);
  221. if (value != form) {
  222. form = value;
  223. goto AGAIN;
  224. }
  225. */
  226. ERROR:
  227. FEerror("EXT:CONSTANT-FORM-VALUE invoked with a non-constant form ~A",
  228. 0, form);
  229. break;
  230. case t_symbol:
  231. value = cl_macroexpand(2, form, env);
  232. if (value != form) {
  233. form = value;
  234. goto AGAIN;
  235. }
  236. value = ECL_SYM_VAL(the_env, value);
  237. break;
  238. default:
  239. value = form;
  240. }
  241. @(return value);
  242. }
  243. @)