|
93 | 93 | }
|
94 | 94 |
|
95 | 95 |
|
| 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 | + |
96 | 148 | /***********************************************************************
|
97 | 149 | **
|
98 | 150 | */ REBTYPE(Handle)
|
|
101 | 153 | ***********************************************************************/
|
102 | 154 | {
|
103 | 155 | REBVAL *val = D_ARG(1);
|
| 156 | + REBVAL *spec; |
| 157 | + REBINT num; |
104 | 158 |
|
105 | 159 | 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; |
106 | 214 |
|
107 | 215 | default:
|
108 | 216 | Trap_Action(VAL_TYPE(val), action);
|
|
0 commit comments