Skip to content

Commit b497811

Browse files
committed
FEAT: possibility to resolve context handle's type
resolves: Oldes/Rebol-issues#2465
1 parent 461872e commit b497811

File tree

5 files changed

+124
-3
lines changed

5 files changed

+124
-3
lines changed

src/boot/actions.reb

+1-1
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,7 @@ open?: action [
448448

449449
query: action [
450450
{Returns information about target if possible.}
451-
target [port! file! url! block! vector! date!]
451+
target [port! file! url! block! vector! date! handle!]
452452
/mode "Get mode information"
453453
field [word! block! none!] "NONE will return valid modes for target type"
454454
]

src/boot/sysobj.reb

+4-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ catalog: object [
3636
reflectors: [
3737
spec [any-function! any-object! vector! datatype! struct!]
3838
body [any-function! any-object! map!]
39-
words [any-function! any-object! map! date!]
39+
words [any-function! any-object! map! date! handle!]
4040
values [any-object! map! struct!]
4141
types [any-function!]
4242
title [any-function! datatype! module!]
@@ -318,6 +318,9 @@ standard: object [
318318
utc:
319319
julian:
320320
]
321+
handle-info: construct [
322+
type:
323+
]
321324

322325
midi-info: construct [
323326
devices-in:

src/boot/types.reb

+1-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ REBOL [
9999

100100
gob self gob * * * * -
101101
event self event * * * * -
102-
handle self handle - - - - -
102+
handle self handle - - * - -
103103
struct self struct * * * * -
104104
library invalid 0 - - - - -
105105
utype self utype - - - - -

src/core/t-handle.c

+108
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,58 @@
9393
}
9494

9595

96+
/***********************************************************************
97+
**
98+
*/ REBINT PD_Handle(REBPVS *pvs)
99+
/*
100+
***********************************************************************/
101+
{
102+
REBVAL *data = pvs->value;
103+
REBVAL *arg = pvs->select;
104+
REBVAL *val = pvs->setval;
105+
REBINT sym = 0;
106+
107+
if (!IS_HANDLE(data)) return PE_BAD_ARGUMENT;
108+
if (!ANY_WORD(arg)) return PE_BAD_SELECT;
109+
110+
sym = VAL_WORD_CANON(arg);
111+
112+
if (val == 0) {
113+
// onle get-path is allowed for handles and only /type value so far
114+
if (sym != SYM_TYPE) return PE_BAD_SELECT;
115+
if (IS_CONTEXT_HANDLE(data)) {
116+
val = pvs->store;
117+
Set_Word(val, VAL_HANDLE_SYM(data), NULL, 0);
118+
return PE_USE;
119+
}
120+
// for the data handles, return NONE
121+
return PE_NONE;
122+
}
123+
else {
124+
// changing handle's type is not allowed
125+
return PE_BAD_SET;
126+
}
127+
}
128+
129+
130+
/***********************************************************************
131+
**
132+
*/ static REBOOL Query_Handle_Field(REBVAL *data, REBVAL *select, REBVAL *ret)
133+
/*
134+
** Set a value with handle data according specified mode
135+
**
136+
***********************************************************************/
137+
{
138+
REBPVS pvs;
139+
pvs.value = data;
140+
pvs.select = select;
141+
pvs.setval = 0;
142+
pvs.store = ret;
143+
144+
return (PE_BAD_SELECT > PD_Handle(&pvs));
145+
}
146+
147+
96148
/***********************************************************************
97149
**
98150
*/ REBTYPE(Handle)
@@ -101,8 +153,64 @@
101153
***********************************************************************/
102154
{
103155
REBVAL *val = D_ARG(1);
156+
REBVAL *spec;
157+
REBINT num;
104158

105159
switch (action) {
160+
case A_REFLECT:
161+
*D_ARG(3) = *D_ARG(2);
162+
// continue..
163+
case A_QUERY:
164+
//TODO: this code could be made resusable with other types!
165+
spec = Get_System(SYS_STANDARD, STD_HANDLE_INFO);
166+
if (!IS_OBJECT(spec)) Trap_Arg(spec);
167+
if (D_REF(2)) { // query/mode refinement
168+
REBVAL *field = D_ARG(3);
169+
if (IS_WORD(field)) {
170+
switch (VAL_WORD_CANON(field)) {
171+
case SYM_WORDS:
172+
Set_Block(D_RET, Get_Object_Words(spec));
173+
return R_RET;
174+
case SYM_SPEC:
175+
return R_ARG1;
176+
}
177+
if (!Query_Handle_Field(val, field, D_RET))
178+
Trap_Reflect(VAL_TYPE(val), field); // better error?
179+
}
180+
else if (IS_BLOCK(field)) {
181+
REBVAL *out = D_RET;
182+
REBSER *values = Make_Block(2 * BLK_LEN(VAL_SERIES(field)));
183+
REBVAL *word = VAL_BLK_DATA(field);
184+
for (; NOT_END(word); word++) {
185+
if (ANY_WORD(word)) {
186+
if (IS_SET_WORD(word)) {
187+
// keep the set-word in result
188+
out = Append_Value(values);
189+
*out = *word;
190+
VAL_SET_LINE(out);
191+
}
192+
out = Append_Value(values);
193+
if (!Query_Handle_Field(val, word, out))
194+
Trap1(RE_INVALID_ARG, word);
195+
}
196+
else Trap1(RE_INVALID_ARG, word);
197+
}
198+
Set_Series(REB_BLOCK, D_RET, values);
199+
}
200+
else {
201+
Set_Block(D_RET, Get_Object_Words(spec));
202+
}
203+
}
204+
else {
205+
REBSER *obj = CLONE_OBJECT(VAL_OBJ_FRAME(spec));
206+
REBSER *words = VAL_OBJ_WORDS(spec);
207+
REBVAL *word = BLK_HEAD(words);
208+
for (num = 0; NOT_END(word); word++, num++) {
209+
Query_Handle_Field(val, word, OFV(obj, num));
210+
}
211+
SET_OBJECT(D_RET, obj);
212+
}
213+
return R_RET;
106214

107215
default:
108216
Trap_Action(VAL_TYPE(val), action);

src/tests/units/handle-test.r3

+10
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,16 @@ h4: aes/key #{00000000000000000000000000000000} none
7777
--assert "[#[handle! aes]]" = mold intersect reduce [h1 h3] reduce [h3 h2]
7878
--assert "[#[handle! rc4]]" = mold exclude reduce [h1 h3] reduce [h3 h2]
7979

80+
--test-- "query handle's type"
81+
;@@ https://github.com/Oldes/Rebol-issues/issues/2465
82+
; short and easy way
83+
--assert h1/type = 'rc4
84+
--assert h3/type = 'aes
85+
; for consistency with other types (like date, image, etc..)
86+
--assert [type] = words-of h1
87+
--assert 'rc4 = query/mode h1 'type
88+
--assert all [object? o: query h1 o/type = 'rc4]
89+
8090
===end-group===
8191

8292
~~~end-file~~~

0 commit comments

Comments
 (0)