Skip to content

Commit 0e1498b

Browse files
committed
FEAT: set object from object keeping only existing keys of the first one
Implements: metaeducation/rebol-issues#2358
1 parent 7c8443f commit 0e1498b

File tree

2 files changed

+34
-11
lines changed

2 files changed

+34
-11
lines changed

src/core/n-data.c

+33-11
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,9 @@ static int Check_Char_Range(REBVAL *val, REBINT limit)
514514
REBVAL *tmp = NULL;
515515
REBOOL not_any = !D_REF(3);
516516
REBOOL is_blk = FALSE;
517+
REBSER *obj;
518+
REBVAL *obj_val;
519+
517520

518521
if (not_any && !IS_SET(val))
519522
Trap1(RE_NEED_VALUE, word);
@@ -544,17 +547,36 @@ static int Check_Char_Range(REBVAL *val, REBINT limit)
544547
if (not_any && is_blk && !IS_END(tmp) && IS_UNSET(tmp++)) // won't advance past end
545548
Trap1(RE_NEED_VALUE, word);
546549
}
547-
for (word = VAL_OBJ_VALUES(D_ARG(1)) + 1; NOT_END(word); word++) { // skip self
548-
// WARNING: Unwinds that make it here are assigned. All unwinds
549-
// should be screened earlier (as is done in e.g. REDUCE, or for
550-
// function arguments) so they don't even get into this function.
551-
*word = *val;
552-
if (is_blk) {
553-
val++;
554-
if (IS_END(val)) {
555-
if (!D_REF(4)) break; // /pad not provided
556-
is_blk = FALSE;
557-
val = NONE_VALUE;
550+
if (IS_OBJECT(val)) {
551+
obj = VAL_OBJ_FRAME(D_ARG(1));
552+
// Keep the binding table.
553+
Collect_Start(BIND_ALL);
554+
// Setup binding table and BUF_WORDS with destination obj words:
555+
Collect_Object(obj);
556+
557+
obj_val = VAL_OBJ_VALUES(D_ARG(1)) + 1; // skip self
558+
for (word = BLK_HEAD(VAL_OBJ_WORDS(D_ARG(1))) + 1; NOT_END(word); word++) { // skip self
559+
tmp = Find_Word_Value(VAL_OBJ_FRAME(val), VAL_WORD_SYM(word));
560+
if(tmp && !IS_UNSET(tmp)) *obj_val = *tmp;
561+
obj_val++;
562+
}
563+
Copy_Deep_Values(obj, 1, SERIES_TAIL(obj), TS_CLONE);
564+
Rebind_Block(VAL_OBJ_FRAME(val), obj, BLK_SKIP(obj, 1), REBIND_FUNC | REBIND_TABLE);
565+
// release binding table
566+
Collect_End(obj);
567+
} else {
568+
for (word = VAL_OBJ_VALUES(D_ARG(1)) + 1; NOT_END(word); word++) { // skip self
569+
// WARNING: Unwinds that make it here are assigned. All unwinds
570+
// should be screened earlier (as is done in e.g. REDUCE, or for
571+
// function arguments) so they don't even get into this function.
572+
*word = *val;
573+
if (is_blk) {
574+
val++;
575+
if (IS_END(val)) {
576+
if (!D_REF(4)) break; // /pad not provided
577+
is_blk = FALSE;
578+
val = NONE_VALUE;
579+
}
558580
}
559581
}
560582
}

src/tests/run-tests.r3

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ dt [ ;- delta time
2828
wrap load %units/codecs-test.r3
2929
wrap load %units/series-test.r3
3030
wrap load %units/vector-test.r3
31+
wrap load %units/object-test.r3
3132
wrap load %units/compress-test.r3
3233
wrap load %units/date-test.r3
3334
wrap load %units/image-test.r3

0 commit comments

Comments
 (0)