Skip to content

Commit a042264

Browse files
committed
FEAT: implemented put action on object! (extending)
1 parent e4b598d commit a042264

8 files changed

+77
-20
lines changed

src/boot/actions.reb

+1-1
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ take: action [
284284

285285
put: action [
286286
{Replaces the value following a key, and returns the new value.}
287-
series [any-block! map! port!] {(modified)}
287+
series [any-block! map! port! object!] {(modified)}
288288
key [scalar! any-string! any-word! binary!]
289289
value [any-type!] {The new value (returned)}
290290
/case {Perform a case-sensitive search}

src/core/t-object.c

+39-8
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,35 @@ static REBOOL Equal_Object(REBVAL *val, REBVAL *arg)
7070
return TRUE;
7171
}
7272

73+
static void Extend_Obj(REBSER *obj, REBVAL *key, REBVAL *value)
74+
{
75+
REBCNT index;
76+
REBVAL *val;
77+
78+
// Key must be a word only!
79+
if (ANY_WORD(key)) {
80+
// bug fix, 'self is protected only in selfish frames
81+
if ((VAL_WORD_CANON(key) == SYM_SELF) && !IS_SELFLESS(obj))
82+
Trap0(RE_SELF_PROTECTED);
83+
index = Find_Word_Index(obj, VAL_WORD_SYM(key), TRUE);
84+
if (index) {
85+
if (!value) return;
86+
val = FRM_VALUE(obj, index);
87+
if (VAL_PROTECTED(val)) Trap1(RE_LOCKED_WORD, val);
88+
} else {
89+
Expand_Frame(obj, 1, 1); // copy word table also
90+
val = Append_Frame(obj, 0, VAL_WORD_SYM(key));
91+
}
92+
if (value)
93+
*val = *value;
94+
else
95+
SET_UNSET(val);
96+
return;
97+
}
98+
else {
99+
Trap_Arg(key);
100+
}
101+
}
73102
static void Append_Obj(REBSER *obj, REBVAL *arg, REBCNT part)
74103
{
75104
REBCNT i, n, len;
@@ -78,14 +107,7 @@ static void Append_Obj(REBSER *obj, REBVAL *arg, REBCNT part)
78107

79108
// Can be a word:
80109
if (ANY_WORD(arg)) {
81-
if (!Find_Word_Index(obj, VAL_WORD_SYM(arg), TRUE)) {
82-
// bug fix, 'self is protected only in selfish frames
83-
if ((VAL_WORD_CANON(arg) == SYM_SELF) && !IS_SELFLESS(obj))
84-
Trap0(RE_SELF_PROTECTED);
85-
Expand_Frame(obj, 1, 1); // copy word table also
86-
val = Append_Frame(obj, 0, VAL_WORD_SYM(arg));
87-
SET_UNSET(val);
88-
}
110+
Extend_Obj(obj, arg, NULL);
89111
return;
90112
}
91113

@@ -452,6 +474,15 @@ static REBSER *Trim_Object(REBSER *obj)
452474
else
453475
Trap_Action(VAL_TYPE(value), action); // !!! needs better error
454476

477+
case A_PUT:
478+
TRAP_PROTECT(VAL_SERIES(value));
479+
if (IS_OBJECT(value)) {
480+
Extend_Obj(VAL_OBJ_FRAME(value), arg, D_ARG(3));
481+
return R_ARG3;
482+
}
483+
else
484+
Trap_Action(VAL_TYPE(value), action); // !!! needs better error
485+
455486
case A_LENGTHQ:
456487
if (IS_OBJECT(value)) {
457488
DS_RET_INT(SERIES_TAIL(VAL_OBJ_FRAME(value))-1);

src/mezz/codec-image-ext.reb

+7-7
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ REBOL [
1212
]
1313

1414
if find codecs 'png [
15-
extend codecs/png 'size? func ["Return PNG image size or none" bin [binary!]][
15+
put codecs/png 'size? func ["Return PNG image size or none" bin [binary!]][
1616
if all [
1717
parse bin [
1818
#{89504E470D0A1A0A} ;- PNG magic number
@@ -25,7 +25,7 @@ if find codecs 'png [
2525
]
2626
]
2727

28-
extend codecs/png 'chunks function [
28+
put codecs/png 'chunks function [
2929
"Decode PNG into block of chunks (or encode back to binary from a block)"
3030
data [binary! file! url! block!] "Input data"
3131
/only tags [block!]
@@ -116,7 +116,7 @@ if find codecs 'png [
116116
]
117117

118118
if find codecs 'jpeg [
119-
extend codecs/jpeg 'size? function ["Return JPEG image size or none" img [file! url! binary!]][
119+
put codecs/jpeg 'size? function ["Return JPEG image size or none" img [file! url! binary!]][
120120
unless binary? img [img: read/binary img]
121121
unless img: find/tail img #{FFD8} [return none]
122122
while [2 <= length? img][
@@ -149,7 +149,7 @@ if find codecs 'jpeg [
149149

150150

151151
if find codecs 'gif [
152-
extend codecs/gif 'size? function ["Return GIF image size or none" img [file! url! binary!]][
152+
put codecs/gif 'size? function ["Return GIF image size or none" img [file! url! binary!]][
153153
unless binary? img [img: read/binary/part img 16]
154154
parse img [
155155
["GIF87a" | "GIF89a"] img: (
@@ -161,7 +161,7 @@ if find codecs 'gif [
161161
]
162162

163163
if find codecs 'bmp [
164-
extend codecs/bmp 'size? function ["Return BMP image size or none" img [file! url! binary!]][
164+
put codecs/bmp 'size? function ["Return BMP image size or none" img [file! url! binary!]][
165165
unless binary? img [img: read/binary/part img 32]
166166
unless find/match img #{424D} [return none]
167167
try [return to pair! binary/read img [SKIP 18 UI32LE UI32LE]]
@@ -170,7 +170,7 @@ if find codecs 'bmp [
170170
]
171171

172172
if find codecs 'dds [
173-
extend codecs/dds 'size? function ["Return DDS image size or none" img [file! url! binary!]][
173+
put codecs/dds 'size? function ["Return DDS image size or none" img [file! url! binary!]][
174174
unless binary? img [img: read/binary/part img 32]
175175
unless find/match img #{444453207C000000} [return none]
176176
try [return to pair! reverse binary/read img [SKIP 12 UI32LE UI32LE]]
@@ -179,7 +179,7 @@ if find codecs 'dds [
179179
]
180180

181181
if find codecs 'qoi [
182-
extend codecs/qoi 'size? function ["Return QOI image size or none" img [file! url! binary!]][
182+
put codecs/qoi 'size? function ["Return QOI image size or none" img [file! url! binary!]][
183183
unless binary? img [img: read/binary/part img 32]
184184
unless find/match img #{716F6966} [return none]
185185
try [return to pair! binary/read img [SKIP 4 UI32BE UI32BE]]

src/mezz/codec-pdf.reb

+2-2
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,7 @@ get-xref-count: function[xrefs n][
425425

426426
emit-stream: func[obj [object!] /local data][
427427
unless find obj 'spec [
428-
extend obj 'spec #(Length: 0)
428+
put obj 'spec #(Length: 0)
429429
]
430430
data: any [obj/data #{}]
431431
unless any [ ; don't use compression
@@ -643,7 +643,7 @@ register-codec [
643643
]
644644
trailer: select pdf 'trailer
645645
unless trailer [
646-
extend pdf 'trailer trailer: #(Info: #[none] Root: #[none])
646+
put pdf 'trailer trailer: #(Info: #[none] Root: #[none])
647647
]
648648
unless root: trailer/Root [
649649
sys/log/debug 'PDF "Trying to locate `Catalog` in PDF objects."

src/mezz/prot-mysql.reb

+1-1
Original file line numberDiff line numberDiff line change
@@ -1474,7 +1474,7 @@ mysql-driver: make object! [
14741474
]
14751475

14761476

1477-
extend system/catalog/errors 'MySQL make object! [
1477+
put system/catalog/errors 'MySQL make object! [
14781478
code: 1000
14791479
type: "MySQL-errors"
14801480
message: ["[" :arg1 "]" :arg2] ;arg1: [error code] ;arg2: error message

src/mezz/sys-ports.reb

+1-1
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ make-scheme: func [
254254
|
255255
'function set args block! set body block! (func*: function args body)
256256
] (
257-
forall name [append actor reduce [name/1 :func*]]
257+
forall name [put actor name/1 :func*]
258258
)
259259
| end
260260
| pos: (

src/tests/units/object-test.r3

+15
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,21 @@ Rebol [
3939

4040
===end-group===
4141

42+
43+
===start-group=== "PUT object"
44+
--test-- "put object"
45+
obj: object []
46+
--assert 1 = put obj 'a 1 ; extends with a new key/value
47+
--assert 1 = obj/a
48+
--assert 2 = put obj 'a 2 ; overwrites existing
49+
--assert 2 = obj/a
50+
--assert 3 = put obj 'b 3
51+
--assert 3 = obj/b
52+
--assert unset? put obj 'b #[unset!]
53+
--assert unset? obj/b
54+
===end-group===
55+
56+
4257
===start-group=== "EXTEND object"
4358
--test-- "extend object"
4459
obj: object []

src/tests/units/protect-test.r3

+11
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,17 @@ Rebol [
130130
--assert all [error? e: try [set in obj 'a 99] e/id = 'locked-word]
131131
--assert all [error? e: try [set obj [99]] e/id = 'locked-word]
132132

133+
--test-- "EXTEND object!"
134+
obj: object [a: 1] protect/deep 'obj
135+
--assert all [error? e: try [obj/a: 2] e/id = 'locked-word]
136+
--assert all [error? e: try [put obj 'a 2] e/id = 'protected] ; cannot modify the value
137+
--assert all [error? e: try [append obj [b: 2]] e/id = 'protected]
138+
--assert all [error? e: try [put obj 'b 2] e/id = 'protected]
139+
unprotect obj
140+
--assert object? append obj [b: 2]
141+
--assert all [22 = put obj 'a 22 22 == obj/a]
142+
unprotect 'obj
143+
133144

134145
===end-group===
135146

0 commit comments

Comments
 (0)