values.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. /* Copyright 2000-2001,2006,2008-2009,2011-2013,2016-2019
  2. Free Software Foundation, Inc.
  3. This file is part of Guile.
  4. Guile is free software: you can redistribute it and/or modify it
  5. under the terms of the GNU Lesser General Public License as published
  6. by the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. Guile is distributed in the hope that it will be useful, but WITHOUT
  9. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10. FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
  11. License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with Guile. If not, see
  14. <https://www.gnu.org/licenses/>. */
  15. #ifdef HAVE_CONFIG_H
  16. # include <config.h>
  17. #endif
  18. #include "feature.h"
  19. #include "gc.h"
  20. #include "gsubr.h"
  21. #include "list.h"
  22. #include "numbers.h"
  23. #include "pairs.h"
  24. #include "values.h"
  25. /* OBJ must be a values object containing exactly two values.
  26. scm_i_extract_values_2 puts those two values into *p1 and *p2. */
  27. void
  28. scm_i_extract_values_2 (SCM obj, SCM *p1, SCM *p2)
  29. {
  30. SCM_ASSERT_TYPE (scm_is_values (obj), obj, SCM_ARG1,
  31. "scm_i_extract_values_2", "values");
  32. if (scm_i_nvalues (obj) != 2)
  33. scm_wrong_type_arg_msg
  34. ("scm_i_extract_values_2", SCM_ARG1, obj,
  35. "a values object containing exactly two values");
  36. *p1 = scm_i_value_ref (obj, 0);
  37. *p2 = scm_i_value_ref (obj, 1);
  38. }
  39. size_t
  40. scm_c_nvalues (SCM obj)
  41. {
  42. if (SCM_LIKELY (scm_is_values (obj)))
  43. return scm_i_nvalues (obj);
  44. else
  45. return 1;
  46. }
  47. SCM
  48. scm_c_value_ref (SCM obj, size_t idx)
  49. {
  50. if (scm_is_values (obj))
  51. {
  52. if (idx < scm_i_nvalues (obj))
  53. return scm_i_value_ref (obj, idx);
  54. }
  55. else
  56. {
  57. if (idx == 0)
  58. return obj;
  59. }
  60. scm_error (scm_out_of_range_key,
  61. "scm_c_value_ref",
  62. "Too few values in ~S to access index ~S",
  63. scm_list_2 (obj, scm_from_size_t (idx)),
  64. scm_list_1 (scm_from_size_t (idx)));
  65. }
  66. SCM_DEFINE (scm_values, "values", 0, 0, 1,
  67. (SCM args),
  68. "Delivers all of its arguments to its continuation. Except for\n"
  69. "continuations created by the @code{call-with-values} procedure,\n"
  70. "all continuations take exactly one value. The effect of\n"
  71. "passing no value or more than one value to continuations that\n"
  72. "were not created by @code{call-with-values} is unspecified.")
  73. #define FUNC_NAME s_scm_values
  74. {
  75. long n;
  76. SCM result;
  77. SCM_VALIDATE_LIST_COPYLEN (1, args, n);
  78. if (n == 1)
  79. result = SCM_CAR (args);
  80. else
  81. {
  82. size_t i;
  83. if ((size_t) n > (size_t) (UINTPTR_MAX >> 8))
  84. scm_error (scm_out_of_range_key, FUNC_NAME, "Too many values",
  85. SCM_EOL, SCM_EOL);
  86. result = scm_words ((((scm_t_bits) n) << 8) | scm_tc7_values, n + 1);
  87. for (i = 0; i < n; i++, args = SCM_CDR (args))
  88. SCM_SET_CELL_OBJECT (result, i + 1, SCM_CAR (args));
  89. }
  90. return result;
  91. }
  92. #undef FUNC_NAME
  93. SCM
  94. scm_c_values (SCM *base, size_t nvalues)
  95. {
  96. SCM ret;
  97. size_t i;
  98. if (nvalues == 1)
  99. return *base;
  100. if ((uintptr_t) nvalues > (UINTPTR_MAX >> 8))
  101. scm_error (scm_out_of_range_key, "scm_c_values", "Too many values",
  102. SCM_EOL, SCM_EOL);
  103. ret = scm_words ((((scm_t_bits) nvalues) << 8) | scm_tc7_values, nvalues + 1);
  104. for (i = 0; i < nvalues; i++)
  105. SCM_SET_CELL_OBJECT (ret, i + 1, base[i]);
  106. return ret;
  107. }
  108. SCM
  109. scm_values_2 (SCM a, SCM b)
  110. {
  111. SCM ret;
  112. ret = scm_words ((2 << 8) | scm_tc7_values, 3);
  113. SCM_SET_CELL_OBJECT_1 (ret, a);
  114. SCM_SET_CELL_OBJECT_2 (ret, b);
  115. return ret;
  116. }
  117. SCM
  118. scm_values_3 (SCM a, SCM b, SCM c)
  119. {
  120. SCM ret;
  121. ret = scm_words ((3 << 8) | scm_tc7_values, 4);
  122. SCM_SET_CELL_OBJECT_1 (ret, a);
  123. SCM_SET_CELL_OBJECT_2 (ret, b);
  124. SCM_SET_CELL_OBJECT_3 (ret, c);
  125. return ret;
  126. }
  127. void
  128. scm_init_values (void)
  129. {
  130. scm_add_feature ("values");
  131. #include "values.x"
  132. }