Skip to content

Commit

Permalink
FEAT: CHANGE: possibility to enquire the element properties of vector…
Browse files Browse the repository at this point in the history
…! values

This commit also changes how are stored reflectors in `system/catalog`. Previously it was just block with names, now it contains also block with datatypes, which the reflector may be used with.

For `vector` values, now there are probably defined all possible values to get its properties.
Some of them:
```
>> v: make vector! [unsigned integer! 32 2]
== make vector! [unsigned integer! 32 2 [0 0]]

>> v/size
== 32

>> size? v
== 32

>> reflect v 'size
== 32

>> query/mode v 'size
== 32

>> v/type
== integer!

>> query v
== make object! [
    signed: false
    type: 'integer!
    size: 32
    length: 2
]

>> query/mode v [size: type:]
== [
    size: 32
    type: integer!
]

>> query/mode v [size type signed]
== [32 integer! false]

>> spec-of v
== [unsigned integer! 32 2]

```

Implements: metaeducation/rebol-issues#2352
  • Loading branch information
Oldes committed Jan 18, 2019
1 parent 3893ae8 commit 69f4e29
Show file tree
Hide file tree
Showing 6 changed files with 177 additions and 30 deletions.
6 changes: 3 additions & 3 deletions src/boot/actions.r
Original file line number Diff line number Diff line change
Expand Up @@ -421,10 +421,10 @@ open?: action [
]

query: action [
{Returns information about a port, file, or URL.}
target [port! file! url! block!]
{Returns information about value if possible.}
target [port! file! url! block! vector!]
/mode "Get mode information"
field [word! block! none!] "NONE will return valid modes for port type"
field [word! block! none!] "NONE will return valid modes for target type"
]

modify: action [
Expand Down
18 changes: 17 additions & 1 deletion src/boot/sysobj.r
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,15 @@ catalog: context [
actions: none
natives: none
errors: none
reflectors: [spec body words values types title]
; Reflectors are used on boot to create *-of functions
reflectors: [
spec [any-function! module! vector!]
body [any-function! any-object!]
words [any-object! map!]
values [any-object! map!]
types [any-function!]
title [any-function! datatype!]
]
; Official list of system/options/flags that can appear.
; Must match host reb-args.h enum!
boot-flags: [
Expand Down Expand Up @@ -261,6 +269,14 @@ standard: context [
window-rows: none
]

vector-info: context [
signed: ; false if unsigned (always true for decimals)
type: ; integer! or decimal! so far
size: ; size per value in bits
length: ; number of values
none
]

extension: context [
lib-base: ; handle to DLL
lib-file: ; file name loaded
Expand Down
131 changes: 115 additions & 16 deletions src/core/t-vector.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,34 @@ void Set_Vector_Row(REBSER *ser, REBVAL *blk)
}


/***********************************************************************
**
*/ static REBOOL Query_Vector_Field(REBSER *vect, REBCNT field, REBVAL *ret)
/*
** Set a value with file data according specified mode
**
***********************************************************************/
{
switch (field) {
case SYM_TYPE:
Init_Word(ret, (VECT_TYPE(vect) >= VTSF08) ? SYM_DECIMAL_TYPE : SYM_INTEGER_TYPE);
break;
case SYM_SIZE:
SET_INTEGER(ret, VECT_BIT_SIZE(VECT_TYPE(vect)));
break;
case SYM_LENGTH:
SET_INTEGER(ret, vect->tail);
break;
case SYM_SIGNED:
SET_LOGIC(ret, !(VECT_TYPE(vect) >= VTUI08 && VECT_TYPE(vect) <= VTUI64));
break;
default:
return FALSE;
}
return TRUE;
}


/***********************************************************************
**
*/ REBSER *Make_Vector_Block(REBVAL *vect)
Expand Down Expand Up @@ -469,25 +497,35 @@ void Set_Vector_Row(REBSER *ser, REBVAL *blk)
/*
***********************************************************************/
{
REBSER *vect;
REBVAL *sel = pvs->select;
REBVAL *val = pvs->value;
REBVAL *set = pvs->setval;
REBSER *vect = VAL_SERIES(val);
REBINT bits = VECT_TYPE(vect);
REBINT n;
//REBINT dims;
REBINT bits;

REBYTE *vp;
REBI64 i = 0;
REBDEC f = 0.0;

if (IS_INTEGER(pvs->select) || IS_DECIMAL(pvs->select)) {
n = Int32(pvs->select);
if (IS_INTEGER(sel) || IS_DECIMAL(sel)) {
n = Int32(sel);
if (n == 0) return PE_NONE;
if (n < 0) n++;
}
else return PE_BAD_SELECT;

n += VAL_INDEX(pvs->value);
vect = VAL_SERIES(pvs->value);
} else if (IS_WORD(sel)) {
if (set == 0) {
val = pvs->value = pvs->store;
if(!Query_Vector_Field(vect, VAL_WORD_CANON(sel), val)) return PE_BAD_SELECT;
return PE_OK;
} else
return PE_BAD_SET;
} else return PE_BAD_SELECT;

n += VAL_INDEX(val);
vect = VAL_SERIES(val);
vp = vect->data;
bits = VECT_TYPE(vect);

//dims = vect->size >> 8;

if (pvs->setval == 0) {
Expand All @@ -511,12 +549,12 @@ void Set_Vector_Row(REBSER *ser, REBVAL *blk)

if (n <= 0 || (REBCNT)n > vect->tail) return PE_BAD_RANGE;

if (IS_INTEGER(pvs->setval)) {
i = VAL_INT64(pvs->setval);
if (IS_INTEGER(set)) {
i = VAL_INT64(set);
if (bits > VTUI64) f = (REBDEC)(i);
}
else if (IS_DECIMAL(pvs->setval)) {
f = VAL_DECIMAL(pvs->setval);
else if (IS_DECIMAL(set)) {
f = VAL_DECIMAL(set);
if (bits <= VTUI64) i = (REBINT)(f);
}
else return PE_BAD_SET;
Expand All @@ -536,9 +574,11 @@ void Set_Vector_Row(REBSER *ser, REBVAL *blk)
REBVAL *value = D_ARG(1);
REBVAL *arg = D_ARG(2);
REBINT type;
REBCNT size;
REBCNT size, bits;
REBSER *vect;
REBSER *ser;
REBSER *blk;
REBVAL *val;

type = Do_Series_Action(action, value, arg);
if (type >= 0) return type;
Expand Down Expand Up @@ -599,6 +639,65 @@ void Set_Vector_Row(REBSER *ser, REBVAL *blk)
Shuffle_Vector(value, D_REF(3));
return R_ARG1;

case A_REFLECT:
bits = VECT_TYPE(vect);
if (SYM_SPEC == VAL_WORD_SYM(D_ARG(2))) {
blk = Make_Block(4);
if (bits >= VTUI08 && bits <= VTUI64) Init_Word(Append_Value(blk), SYM_UNSIGNED);
Query_Vector_Field(vect, SYM_TYPE, Append_Value(blk));
Query_Vector_Field(vect, SYM_SIZE, Append_Value(blk));
Query_Vector_Field(vect, SYM_LENGTH, Append_Value(blk));
Set_Series(REB_BLOCK, value, blk);
} else {
if(!Query_Vector_Field(vect, VAL_WORD_SYM(D_ARG(2)), value))
Trap_Reflect(VAL_TYPE(value), D_ARG(2));
}
break;

case A_QUERY:
bits = VECT_TYPE(vect);
REBVAL *spec = Get_System(SYS_STANDARD, STD_VECTOR_INFO);
if (!IS_OBJECT(spec)) Trap_Arg(spec);
if (D_REF(2)) { // query/mode refinement
REBVAL *field = D_ARG(3);
if(IS_WORD(field)) {
if (!Query_Vector_Field(vect, VAL_WORD_SYM(field), value))
Trap_Reflect(VAL_TYPE(value), field); // better error?
}
else if (IS_BLOCK(field)) {
REBVAL *val;
REBSER *values = Make_Block(2 * BLK_LEN(VAL_SERIES(field)));
REBVAL *word = VAL_BLK_DATA(field);
for (; NOT_END(word); word++) {
if (ANY_WORD(word)) {
if (IS_SET_WORD(word)) {
// keep the set-word in result
val = Append_Value(values);
*val = *word;
VAL_SET_LINE(val);
}
val = Append_Value(values);
if (!Query_Vector_Field(vect, VAL_WORD_SYM(word), val))
Trap1(RE_INVALID_ARG, word);
}
else Trap1(RE_INVALID_ARG, word);
}
Set_Series(REB_BLOCK, value, values);
}
else {
Set_Block(D_RET, Get_Object_Words(spec));
return R_RET;
}
} else {
REBSER *obj = CLONE_OBJECT(VAL_OBJ_FRAME(spec));
Query_Vector_Field(vect, SYM_SIGNED, OFV(obj, STD_VECTOR_INFO_SIGNED));
Query_Vector_Field(vect, SYM_TYPE, OFV(obj, STD_VECTOR_INFO_TYPE));
Query_Vector_Field(vect, SYM_SIZE, OFV(obj, STD_VECTOR_INFO_SIZE));
Query_Vector_Field(vect, SYM_LENGTH, OFV(obj, STD_VECTOR_INFO_LENGTH));
SET_OBJECT(value, obj);
}
break;

default:
Trap_Action(VAL_TYPE(value), action);
}
Expand All @@ -611,7 +710,7 @@ void Set_Vector_Row(REBSER *ser, REBVAL *blk)
DEAD_END;
}


/***********************************************************************
**
*/ void Mold_Vector(REBVAL *value, REB_MOLD *mold, REBFLG molded)
Expand Down
19 changes: 11 additions & 8 deletions src/mezz/base-defs.r
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,20 @@ types-of:
title-of:
none

use [word title] [
foreach name system/catalog/reflectors [
use [word title pos] [
foreach [name types] system/catalog/reflectors [
word: make word! ajoin [name "-of"]
word: bind/new word 'reflect
title: ajoin ["Returns a copy of the " name " of a " switch/default name [
spec ["function or module"]
values ["object or module"]
types title ["function"] ; title should include module Title too...
] ["function, object, or module"]] ; body, words
title: form types
remove back tail title ; removes last #"!"
; there is no replace function in this boot phase yet,
; so lets do it this way:
while [pos: find title "any-"][pos/4: #" "] ; replace/all "any-" to "any "
if pos: find/last title #"!" [change/part pos " or" 1]
while [pos: find title #"!"][pos/1: #","] ; replace/all "!" to ","
insert title ajoin ["Returns a copy of the " name " of "]
set word func
reduce [title 'value]
reduce [title 'value types]
compose [reflect :value (to lit-word! name)]
]
]
Expand Down
4 changes: 2 additions & 2 deletions src/mezz/base-files.r
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ exists?: func [
]

size?: func [
{Returns the size of a file.}
target [file! url!]
{Returns the size of a file or vector (bits per value).}
target [file! url! vector!]
][
query/mode target 'size
]
Expand Down
29 changes: 29 additions & 0 deletions src/tests/units/series-test.r3
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,35 @@ Rebol [
3 4
]}

--test-- "QUERY on vector"
;@@ https://github.com/rebol/rebol-issues/issues/2352
v: make vector! [unsigned integer! 16 2]
o: query v
--assert object? o
--assert not o/signed
--assert o/type = 'integer!
--assert o/size = 16
--assert o/length = 2
--test-- "QUERY/MODE on vector"
--assert [signed type size length] = query/mode v none
--assert [16 integer!] = query/mode v [size type]
--assert block? b: query/mode v [signed: length:]
--assert all [not b/signed b/length = 2]
--assert 16 = query/mode v 'size
--assert 16 = size? v
--test-- "REFLECT on vector"
--assert 16 = reflect v 'size
--assert 2 = reflect v 'length
--assert 'integer! = reflect v 'type
--assert false = reflect v 'signed
--assert [unsigned integer! 16 2] = reflect v 'spec
--assert [unsigned integer! 16 2] = spec-of v
--test-- "ACCESSORS on vector"
--assert 16 = v/size
--assert 2 = v/length
--assert 'integer! = v/type
--assert false = v/signed

===end-group===

~~~end-file~~~

0 comments on commit 69f4e29

Please sign in to comment.