Skip to content

Commit b26f9bf

Browse files
committed
FEAT: COLLECT-WORDS /as type [datatype!] option
resolves: Oldes/Rebol-issues#724
1 parent c1a2fb5 commit b26f9bf

File tree

4 files changed

+35
-21
lines changed

4 files changed

+35
-21
lines changed

src/boot/natives.reb

+1-8
Original file line numberDiff line numberDiff line change
@@ -372,14 +372,7 @@ context?: native [ ; was originally named `bound?`
372372
;return: [object! function! none!]
373373
]
374374

375-
collect-words: native [
376-
"Collect unique words used in a block (used for context construction)."
377-
block [block!]
378-
/deep "Include nested blocks"
379-
/set "Only include set-words"
380-
/ignore "Ignore prior words"
381-
words [any-object! block! none!] "Words to ignore"
382-
]
375+
;collect-words: native [] ;defined in %n-data.c
383376

384377
;checksum: native [] ; defined in %n-string.c
385378
;compress: native [] ; defined in %n-string.c

src/core/c-frame.c

+10-6
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
** REBOL [R3] Language Interpreter and Run-time Environment
44
**
55
** Copyright 2012 REBOL Technologies
6+
** Copyright 2012-2021 Rebol Open Source Developers
67
** REBOL is a trademark of REBOL Technologies
78
**
89
** Licensed under the Apache License, Version 2.0 (the "License");
@@ -365,7 +366,7 @@
365366

366367
/***********************************************************************
367368
**
368-
*/ void Collect_Simple_Words(REBVAL *block, REBCNT modes)
369+
*/ void Collect_Simple_Words(REBVAL *block, REBCNT modes, REBINT type)
369370
/*
370371
** Used for Collect_Block_Words().
371372
**
@@ -381,17 +382,20 @@
381382
) {
382383
binds[VAL_WORD_CANON(block)] = 1;
383384
val = Append_Value(BUF_WORDS);
384-
Init_Word(val, VAL_WORD_SYM(block));
385+
VAL_SET(val, type);
386+
VAL_WORD_INDEX(val) = 0;
387+
VAL_WORD_FRAME(val) = 0;
388+
VAL_WORD_SYM(val) = VAL_WORD_SYM(block);
385389
}
386390
else if (ANY_EVAL_BLOCK(block) && (modes & BIND_DEEP))
387-
Collect_Simple_Words(VAL_BLK_DATA(block), modes);
391+
Collect_Simple_Words(VAL_BLK_DATA(block), modes, type);
388392
}
389393
}
390394

391395

392396
/***********************************************************************
393397
**
394-
*/ REBSER *Collect_Block_Words(REBVAL *block, REBVAL *prior, REBCNT modes)
398+
*/ REBSER *Collect_Block_Words(REBVAL *block, REBVAL *prior, REBCNT modes, REBINT type)
395399
/*
396400
** Collect words from a prior block and new block.
397401
**
@@ -405,10 +409,10 @@
405409
if (SERIES_TAIL(BUF_WORDS)) Crash(RP_WORD_LIST); // still in use
406410

407411
if (prior)
408-
Collect_Simple_Words(prior, BIND_ALL);
412+
Collect_Simple_Words(prior, BIND_ALL, type);
409413

410414
start = SERIES_TAIL(BUF_WORDS);
411-
Collect_Simple_Words(block, modes);
415+
Collect_Simple_Words(block, modes, type);
412416

413417
// Reset word markers:
414418
for (block = BLK_HEAD(BUF_WORDS); NOT_END(block); block++)

src/core/n-data.c

+16-7
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
** REBOL [R3] Language Interpreter and Run-time Environment
44
**
55
** Copyright 2012 REBOL Technologies
6+
** Copyright 2012-2021 Rebol Open Source Developers
67
** REBOL is a trademark of REBOL Technologies
78
**
89
** Licensed under the Apache License, Version 2.0 (the "License");
@@ -383,19 +384,24 @@ static int Check_Char_Range(REBVAL *val, REBINT limit)
383384
**
384385
*/ REBNATIVE(collect_words)
385386
/*
386-
** 1 block
387-
** 3 /deep
388-
** 4 /set
389-
** 4 /ignore
390-
** 5 object | block
391-
**
387+
// collect-words: native [
388+
// "Collect unique words used in a block (used for context construction)."
389+
// block [block!]
390+
// /deep "Include nested blocks"
391+
// /set "Only include set-words"
392+
// /ignore "Ignore prior words"
393+
// words [any-object! block! none!] "Words to ignore"
394+
// /as "Datatype of the words in the returned block"
395+
// type [datatype!] "Any word type"
396+
// ]
392397
***********************************************************************/
393398
{
394399
REBSER *words;
395400
REBCNT modes = 0;
396401
REBVAL *prior = 0;
397402
REBVAL *block;
398403
REBVAL *obj;
404+
REBINT type;
399405

400406
block = VAL_BLK_DATA(D_ARG(1));
401407

@@ -411,8 +417,11 @@ static int Check_Char_Range(REBVAL *val, REBINT limit)
411417
prior = VAL_BLK_DATA(obj);
412418
// else stays 0
413419
}
420+
type = D_REF(6) ? VAL_DATATYPE(D_ARG(7)) : REB_WORD;
421+
if (type < REB_WORD || type > REB_ISSUE)
422+
Trap1(RE_BAD_FUNC_ARG, D_ARG(7));
414423

415-
words = Collect_Block_Words(block, prior, modes);
424+
words = Collect_Block_Words(block, prior, modes, type);
416425
Set_Block(D_RET, words);
417426
return R_RET;
418427
}

src/tests/units/func-test.r3

+8
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,14 @@ Rebol [
204204
--assert [a c] = collect-words/ignore blk none
205205
--assert [a] = collect-words/ignore blk [c]
206206
--assert [c] = collect-words/ignore blk object [a: 1]
207+
--test-- "collect-words/as"
208+
;@@ https://github.com/Oldes/Rebol-issues/issues/724
209+
--assert [:a :c] = collect-words/as blk get-word!
210+
--assert [a: c:] = collect-words/as blk set-word!
211+
--assert ['a 'c] = collect-words/as blk lit-word!
212+
--assert [/a /c] = collect-words/as blk refinement!
213+
--assert [#a #c] = collect-words/as blk issue!
214+
--assert all [error? e: try [collect-words/as blk string!] e/id = 'bad-func-arg]
207215
===end-group===
208216

209217

0 commit comments

Comments
 (0)