(values) now returns unit, not void

This commit is contained in:
ESL 2023-03-28 19:51:37 -04:00
parent 8002d8c7d0
commit 4d1d2d490d
4 changed files with 25 additions and 6 deletions

14
i.c
View file

@ -181,6 +181,8 @@ static void _sck(obj *s) {
#define get_char(o) char_from_obj(o)
#define void_obj() obj_from_void(0)
#define is_void(o) (o == obj_from_void(0))
#define unit_obj() obj_from_unit()
#define is_unit(o) (o == obj_from_unit())
#define null_obj() mknull()
#define is_null(o) isnull(o)
#define eof_obj() mkeof()
@ -685,7 +687,7 @@ define_instruction(rcmv) {
/* single-value producer call returns here with result in ac, cns on stack */
obj val = ac, x = spop();
/* tail-call the consumer with the returned value(s) */
if (is_void(val)) { /* (values) in improper context */
if (is_unit(val)) { /* (values) in improper context */
ac = fixnum_obj(0);
} else if (is_tuple(val)) { /* (values a1 a2 a ...) in improper context */
int n = tuple_len(val), i;
@ -715,12 +717,12 @@ define_instruction(sdmv) {
/* NB: can be sped up for popular cases: n == 0, n == 2 */
memmove((void*)(sp-n-m), (void*)(sp-n), (size_t)n*sizeof(obj));
sdrop(m); callsubi();
} else if (n == 0) { /* return void (n = 0) */
ac = void_obj();
} else if (n == 0) { /* return unit (n = 0) */
ac = unit_obj();
rx = spop();
rd = spop();
retfromi();
} else { /* return args as void (n = 0) or tuple (n > 1) */
} else { /* return args as tuple (n > 1) */
hp_reserve(tuplebsz(n));
for (i = n-1; i >= 0; --i) *--hp = sref(i);
ac = hend_tuple(n);
@ -798,8 +800,8 @@ define_instruction(rck) {
if (c) memmove(sb+n, sp-c, c*sizeof(obj));
memcpy(sb, ks, n*sizeof(obj));
sp = sb+n+c; callsubi();
} else if (c == 0) { /* return void (n = 0) */
spush(void_obj());
} else if (c == 0) { /* return unit (n = 0) */
spush(unit_obj());
ac = rd;
goi(wckr);
} else { /* return args as tuple (n > 1) */

4
n.c
View file

@ -148,6 +148,8 @@ extern int istagged(obj o, int t);
extern int taggedlen(obj o, int t);
extern obj* taggedref(obj o, int t, int i);
#endif
/* unit */
#define obj_from_unit() (obj_from_size(0x6DF6F577))
/* booleans */
#define TRUE_ITAG 0
typedef int bool_t;
@ -1178,6 +1180,8 @@ static void wrdatum(obj o, wenv_t *e) {
wrs("#<eof>", e);
} else if (o == obj_from_void(0)) {
wrs("#<void>", e);
} else if (o == obj_from_unit()) {
wrs("#<unit>", e);
} else if (isiport(o)) {
char buf[60]; sprintf(buf, "#<%s>", ckiportvt(o)->tname); wrs(buf, e);
} else if (isoport(o)) {

2
n.h
View file

@ -110,6 +110,8 @@ static /*inline*/ int istagged_inlined(obj o, int t) {
extern int taggedlen(obj o, int t);
extern obj* taggedref(obj o, int t, int i);
#endif
/* unit */
#define obj_from_unit() (obj_from_size(0x6DF6F577))
/* booleans */
#define TRUE_ITAG 0
typedef int bool_t;

View file

@ -365,6 +365,15 @@ void *getnative(obj o, cxtype_t *tp) {
(define-inline (void? x) (%prim "bool(obj_from_$arg == obj_from_void(0))" x))
; unit
; this is the value to be used when zero results are returned to a context
; where one result is expected; it is analogous to a 0-element tuple
(%definition "/* unit */")
(%definition "#define obj_from_unit() (obj_from_size(0x6DF6F577))")
; booleans
; #f is (obj)0, #t is immediate 0 with tag 0 (singular true object)
@ -3404,6 +3413,8 @@ static void wrdatum(obj o, wenv_t *e) {
wrs(\"#<eof>\", e);
} else if (o == obj_from_void(0)) {
wrs(\"#<void>\", e);
} else if (o == obj_from_unit()) {
wrs(\"#<unit>\", e);
} else if (isiport(o)) {
char buf[60]; sprintf(buf, \"#<%s>\", ckiportvt(o)->tname); wrs(buf, e);
} else if (isoport(o)) {