Как передать блок с контекстом в рутину?
Продолжаю изучать Red/System. И теперь я пытаюсь понять, как передать слово с контекстом для работы.
Вот мой код:
Red [Note: "compile in release mode (-r flag)"]
mycontext: context [
list: []
]
foo: routine [
blk
/local
int [integer!]
str [c-string!]
][
blk: as red-block! _context/get-any <CONTEXTHERE> symbol/make "list" ; ?? <CONTEXTHERE>
int: 123
str: "Hello"
block/rs-append blk as red-value! integer/box int
string/load-in str length? str blk UTF-8
]
foo mycontext ; passing context to foo
probe mycontext
Этот код не работает, потому что список помещен в mycontext
. Пример прохожденияlist
без контекста можно найти здесь
Я пробовал разные подходы, но каждый раз получал ошибку.
https://github.com/red/red/blob/master/runtime/datatypes/structures.reds
1 ответ
Во-первых, спецификация типа вашей процедуры неверна (об этом сообщает сообщение об ошибке):
Compiling to native code...
*** Compilation Error: invalid definition for function exec/foo: [
blk [red-red-block!]
/local
int [integer!]
str [c-string!]
]
Компилятор автоматически помещает red-*
префикс для аргументов подпрограммы, поэтому правильная спецификация должна быть:
foo: routine [
blk [block!]
/local
int [integer!]
str [c-string!]
][
...
]
Во-вторых, это тоже неверно; вы проходитеobject!
, а не block!
:
*** Compilation Error: datatype not allowed
Значит, нужно написать:
foo: routine [
obj [object!]
/local
int [integer!]
str [c-string!]
][
...
]
Теперь, насколько я понимаю, вы хотите получить этот пустой блок, на который ссылается list
и добавить к нему значения. Для этого требуется контекстный узел
obj/ctx
и идентификатор символа
symbol/make "list"
Имея два на месте, мы можем позвонить _context/get-any
:
foo: routine [
obj [object!]
/local
blk [red-block!]
int [integer!]
str [c-string!]
][
blk: as red-block! _context/get-any symbol/make "list" obj/ctx
int: 123
str: "Hello"
block/rs-append blk as red-value! integer/box int
string/load-in str length? str blk UTF-8
]
Альтернативным решением было бы построить word!
значение с использованием word/load
и позвони object/rs-select
:
foo: routine [
obj [object!]
/local
blk [red-block!]
int [integer!]
str [c-string!]
][
blk: as red-block! object/rs-select obj as red-value! word/load "list"
int: 123
str: "Hello"
block/rs-append blk as red-value! integer/box int
string/load-in str length? str blk UTF-8
]
Оба подхода дают ожидаемый результат:
make object! [
list: [123 "Hello"]
]
Лично я бы не стал так усложнять и просто передал блок в вашу рутину:
mycontext: context [
list: []
]
foo: routine [
blk [block!]
/local
int [red-integer!]
str [c-string!]
][
str: "Hello"
int: as red-integer! stack/push*
int/header: TYPE_INTEGER
int/value: 123
block/rs-append blk as red-value! int
string/load-in str length? str blk UTF-8
]
foo mycontext/list
probe mycontext