Skip to content

Commit b42fc97

Browse files
committed
FEAT: allow none as a map! value, implement remove/key
resolves: Oldes/Rebol-wishes#20 resolves: Oldes/Rebol-wishes#21
1 parent f6160f8 commit b42fc97

File tree

10 files changed

+113
-22
lines changed

10 files changed

+113
-22
lines changed

src/boot/actions.reb

+3-1
Original file line numberDiff line numberDiff line change
@@ -302,9 +302,11 @@ append: action [
302302

303303
remove: action [
304304
{Removes element(s); returns same position.}
305-
series [series! gob! port! bitset! none!] {At position (modified)}
305+
series [series! gob! port! bitset! none! map!] {At position (modified)}
306306
/part {Removes multiple elements or to a given position}
307307
length [number! series! pair! char!]
308+
/key {Removes a key from map.}
309+
key-arg [any-type!]
308310
]
309311

310312
change: action [

src/core/f-series.c

+11-3
Original file line numberDiff line numberDiff line change
@@ -114,10 +114,18 @@
114114
case A_REMOVE:
115115
// /PART length
116116
TRAP_PROTECT(VAL_SERIES(value));
117-
len = DS_REF(2) ? Partial(value, 0, DS_ARG(3), 0) : 1;
118-
index = (REBINT)VAL_INDEX(value);
117+
if (DS_REF(ARG_REMOVE_KEY)) {
118+
if (ANY_BLOCK(value)) {
119+
len = 2;
120+
index = Find_Block(VAL_SERIES(value), VAL_INDEX(value), VAL_TAIL(value), DS_ARG(ARG_REMOVE_KEY_ARG), VAL_LEN(value), AM_FIND_CASE, 2);
121+
}
122+
else Trap0(RE_FEATURE_NA);
123+
} else {
124+
len = DS_REF(2) ? Partial(value, 0, DS_ARG(3), 0) : 1;
125+
index = (REBINT)VAL_INDEX(value);
126+
}
119127
if (index < tail && len != 0)
120-
Remove_Series(VAL_SERIES(value), VAL_INDEX(value), len);
128+
Remove_Series(VAL_SERIES(value), (REBCNT)index, len);
121129
break;
122130

123131
case A_ADD: // Join_Strings(value, arg);

src/core/s-mold.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -910,10 +910,10 @@ STOID Mold_Map(REBVAL *value, REB_MOLD *mold, REBFLG molded)
910910
}
911911
}
912912

913-
// Mold all non-none entries
913+
// Mold all not removed entries
914914
mold->indent++;
915915
for (val = BLK_HEAD(mapser); NOT_END(val) && NOT_END(val+1); val += 2) {
916-
if (!IS_NONE(val+1)) {
916+
if (!VAL_MAP_REMOVED(val)) {
917917
count++;
918918
if (molded) {
919919
if(indented)

src/core/t-bitset.c

+4-3
Original file line numberDiff line numberDiff line change
@@ -649,9 +649,10 @@
649649
if (Set_Bits(VAL_SERIES(value), arg, (REBOOL)diff)) break;
650650
Trap_Arg(arg);
651651

652-
case A_REMOVE: // #"a" "abc" remove/part bs "abcd" yuk: /part ?
653-
if (!D_REF(2)) Trap0(RE_MISSING_ARG); // /part required
654-
if (Set_Bits(VAL_SERIES(value), D_ARG(3), FALSE)) break;
652+
case A_REMOVE: // #"a" "abc" remove/key bs "abcd"
653+
if (D_REF(ARG_REMOVE_PART)) Trap0(RE_BAD_REFINES);
654+
if (!D_REF(ARG_REMOVE_KEY)) Trap0(RE_MISSING_ARG); // /key required
655+
if (Set_Bits(VAL_SERIES(value), D_ARG(ARG_REMOVE_KEY_ARG), FALSE)) break;
655656
Trap_Arg(D_ARG(3));
656657

657658
case A_COPY:

src/core/t-map.c

+16-6
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,6 @@
6767
// [a: 1 b: 2] = body-of make map! [a 1 b: 2]
6868

6969

70-
71-
7270
/***********************************************************************
7371
**
7472
*/ REBINT CT_Map(REBVAL *a, REBVAL *b, REBINT mode)
@@ -242,7 +240,9 @@
242240

243241
// Must set the value:
244242
if (n) { // re-set it:
245-
*BLK_SKIP(series, ((n-1)*2)+1) = *val; // set it
243+
set = BLK_SKIP(series, ((n-1)*2)); // find the key
244+
VAL_CLR_OPT(set++, OPTS_HIDE); // clear HIDE flag in case it was removed key; change to value position
245+
*set = *val; // set the value
246246
return n;
247247
}
248248

@@ -289,7 +289,7 @@
289289
REBVAL *v = BLK_HEAD(series);
290290

291291
for (n = 0; n < series->tail; n += 2, v += 2) {
292-
if (!IS_NONE(v+1)) c++; // must have non-none value
292+
if (!VAL_MAP_REMOVED(v)) c++; // count only not removed values
293293
}
294294

295295
return c;
@@ -386,14 +386,14 @@
386386

387387
// Count number of set entries:
388388
for (val = BLK_HEAD(mapser); NOT_END(val) && NOT_END(val+1); val += 2) {
389-
if (!IS_NONE(val+1)) cnt++; // must have non-none value
389+
if (!VAL_MAP_REMOVED(val)) cnt++; // must not be removed
390390
}
391391

392392
// Copy entries to new block:
393393
blk = Make_Block(cnt * ((what == 0) ? 2 : 1));
394394
out = BLK_HEAD(blk);
395395
for (val = BLK_HEAD(mapser); NOT_END(val) && NOT_END(val+1); val += 2) {
396-
if (!IS_NONE(val+1)) {
396+
if (!VAL_MAP_REMOVED(val)) {
397397
#ifndef DO_NOT_NORMALIZE_MAP_KEYS
398398
if (what < 0) {
399399
// words-of
@@ -518,6 +518,16 @@
518518
*D_RET = *D_ARG(3);
519519
break;
520520

521+
case A_REMOVE:
522+
//O: throw an error if /part is used?
523+
n = Find_Entry(series, D_ARG(ARG_REMOVE_KEY_ARG), 0, TRUE);
524+
if (n) {
525+
n = (n-1)*2;
526+
VAL_SET_OPT(VAL_BLK_SKIP(val, n), OPTS_HIDE);
527+
VAL_SET(VAL_BLK_SKIP(val, n+1), REB_NONE); // set value to none (so the old one may be GCed)
528+
}
529+
return R_ARG1;
530+
521531
case A_LENGTHQ:
522532
n = Length_Map(series);
523533
DS_RET_INT(n);

src/include/sys-value.h

+3
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@ enum {
9696
#define IS_SET(v) (VAL_TYPE(v) > REB_UNSET)
9797
#define IS_SCALAR(v) (VAL_TYPE(v) <= REB_DATE)
9898

99+
// When key is removed from map, it has OPTS_HIDE flag
100+
#define VAL_MAP_REMOVED(val) (VAL_GET_OPT(val, OPTS_HIDE))
101+
99102

100103
/***********************************************************************
101104
**

src/tests/units/bitset-test.r3

+13-7
Original file line numberDiff line numberDiff line change
@@ -191,13 +191,19 @@
191191
clear bs
192192
--assert "make bitset! #{}" = mold bs
193193

194-
; --test-- "remove-1"
195-
; bs: charset "012345789"
196-
; --assert 64 = length? bs
197-
; --assert "make bitset! #{000000000000FDC0}" = mold bs
198-
; --assert "make bitset! #{0000000000007DC0}" = mold remove/key bs #"0"
199-
; --assert "make bitset! #{0000000000003DC0}" = mold remove/key bs 49
200-
; --assert "make bitset! #{0000000000000000}" = mold remove/key bs [#"2" - #"7" "8" #"9"]
194+
--test-- "remove-1"
195+
;@@ https://github.com/Oldes/Rebol-wishes/issues/20
196+
bs: charset "012345789"
197+
--assert 64 = length? bs
198+
--assert "make bitset! #{000000000000FDC0}" = mold bs
199+
--assert "make bitset! #{0000000000007DC0}" = mold remove/key bs #"0"
200+
--assert "make bitset! #{0000000000003DC0}" = mold remove/key bs 49
201+
--assert "make bitset! #{0000000000000000}" = mold remove/key bs [#"2" - #"7" "8" #"9"]
202+
--test-- "remove/part invalid"
203+
--assert all [
204+
error? e: try [remove/part bs "01"]
205+
e/id = 'bad-refines
206+
]
201207

202208
===end-group===
203209

src/tests/units/map-test.r3

+21
Original file line numberDiff line numberDiff line change
@@ -267,4 +267,25 @@ Rebol [
267267

268268
===end-group===
269269

270+
===start-group=== "MAP with NONE"
271+
--test-- "map with none"
272+
m: #(a: #[none] b: 1)
273+
m/b: none
274+
--assert [a b] = keys-of m
275+
--assert [#[none] #[none]] = values-of m
276+
277+
--test-- "remove from map"
278+
m: #("ab" 1 "AB" 2)
279+
--assert ["ab" 1 "AB" 2] = to block! remove/key m "aB"
280+
--assert 2 = length? m
281+
--assert ["ab" 1 ] = to block! remove/key m "AB"
282+
--assert 1 = length? m
283+
m: #(ab: 1 AB: 2)
284+
--assert [ab: 1 AB: 2] = to block! remove/key m 'aB
285+
--assert 2 = length? m
286+
--assert [ab: 1 ] = to block! remove/key m 'AB
287+
--assert 1 = length? m
288+
289+
===end-group===
290+
270291
~~~end-file~~~

src/tests/units/series-test.r3

+39
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,25 @@ Rebol [
224224
]
225225
===end-group===
226226

227+
===start-group=== "SET-PATH"
228+
--test-- "set-path missing value"
229+
;@@ https://github.com/Oldes/Rebol-issues/issues/2312
230+
data: copy [a 10 b 20]
231+
data/a: 30
232+
--assert data = [a 30 b 20] ; this one is ok
233+
; but rest are errors by design
234+
--assert all [
235+
error? e: try [data/c: 30]
236+
e/id: 'invalid-path
237+
]
238+
--assert all [
239+
data: [1 c]
240+
error? e: try [data/c: 30]
241+
e/id: 'invalid-path
242+
]
243+
===end-group===
244+
245+
227246
===start-group=== "CHANGE string!"
228247
--test-- "change/part"
229248
;@@ https://github.com/Oldes/Rebol-issues/issues/55
@@ -695,6 +714,26 @@ Rebol [
695714
remove/part b to integer! #{8000}
696715
--assert 7232 = length? b
697716

717+
--test-- "remove/key any-block!"
718+
;@@ https://github.com/Oldes/Rebol-wishes/issues/20
719+
b: [a b b c]
720+
--assert [a b b c] = remove/key b 'c ; no change, c is value, not a key
721+
--assert [a b b c] = remove/key b 'B ; no change, B is not b
722+
--assert [a b ] = remove/key b 'b
723+
b: quote (a b b c)
724+
--assert quote (a b b c) = remove/key b 'c ; no change, c is value, not a key
725+
--assert quote (a b b c) = remove/key b 'B ; no change, B is not b
726+
--assert quote (a b ) = remove/key b 'b
727+
b: 'a/b/b/c
728+
--assert 'a/b/b/c = remove/key b 'c ; no change, c is value, not a key
729+
--assert 'a/b/b/c = remove/key b 'B ; no change, B is not b
730+
--assert 'a/b = remove/key b 'b
731+
--test-- "remove/key string!"
732+
--assert all [
733+
error? e: try [remove/key "abcd" #"a"]
734+
e/id = 'feature-na
735+
]
736+
698737
===end-group===
699738

700739
===start-group=== "SORT"

src/tools/make-headers.reb

+1
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,7 @@ foreach word [
340340
write
341341
query
342342
take
343+
remove
343344
] [make-arg-enums word]
344345

345346
acts: load %../boot/natives.reb

0 commit comments

Comments
 (0)