| 278 | | } |
| 279 | | #endif |
| | 282 | UCell* arg1; |
| | 283 | UCell* cc1; |
| | 284 | UCell* cc2; |
| | 285 | UCell* conn; |
| | 286 | UCell* it; |
| | 287 | UCell* end; |
| | 288 | UBlock* b1; |
| | 289 | UAtom atom; |
| | 290 | int wrd; |
| | 291 | |
| | 292 | // Disconnect this component input... |
| | 293 | if( ur_is(tos, UT_SELECT) && ur_selIsAtom(tos) ) |
| | 294 | { |
| | 295 | cc2 = ur_wordCell( ut, tos ); |
| | 296 | if( ! cc2 ) |
| | 297 | return; |
| | 298 | if( ! ur_is(cc2, UT_COMPONENT) ) |
| | 299 | goto dt_err; |
| | 300 | atom = ur_sel(tos); |
| | 301 | } |
| | 302 | else if( ur_is(tos, UT_COMPONENT) ) |
| | 303 | { |
| | 304 | // Use first input. |
| | 305 | cc2 = tos; |
| | 306 | b1 = ur_blockPtr( cc2->ctx.wordBlk ); |
| | 307 | atom = b1->ptr.cells[ COMPONENT_CELLS ].word.atom; |
| | 308 | } |
| | 309 | else |
| | 310 | goto dt_err; |
| | 311 | |
| | 312 | |
| | 313 | // ...from this component output. |
| | 314 | arg1 = ur_s_prev(tos); |
| | 315 | if( ur_is(arg1, UT_SELECT) && ur_selIsAtom(arg1) ) |
| | 316 | { |
| | 317 | cc1 = ur_wordCell( ut, arg1 ); |
| | 318 | if( ! cc1 ) |
| | 319 | return; |
| | 320 | if( ! ur_is(cc1, UT_COMPONENT) ) |
| | 321 | goto dt_err; |
| | 322 | wrd = ur_lookup( cc1, ur_sel(arg1) ); |
| | 323 | if( wrd < 0 ) |
| | 324 | goto dt_err; |
| | 325 | b1 = ur_blockPtr( cc1->ctx.valBlk ); |
| | 326 | cc1 = b1->ptr.cells + COMPONENT_COUNTS; |
| | 327 | if( wrd < (COMPONENT_CELLS + ur_ccIn(cc1)) ) |
| | 328 | goto out_err; |
| | 329 | if( wrd >= (COMPONENT_CELLS + ur_ccIn(cc1) + ur_ccOut(cc1)) ) |
| | 330 | goto out_err; |
| | 331 | conn = b1->ptr.cells + wrd; |
| | 332 | } |
| | 333 | else if( ur_is(arg1, UT_COMPONENT) ) |
| | 334 | { |
| | 335 | // Use first output. |
| | 336 | b1 = ur_blockPtr( arg1->ctx.valBlk ); |
| | 337 | cc1 = b1->ptr.cells + COMPONENT_COUNTS; |
| | 338 | if( ur_ccOut(cc1) < 1 ) |
| | 339 | goto out_err; |
| | 340 | conn = b1->ptr.cells + COMPONENT_CELLS + ur_ccIn(cc1); |
| | 341 | } |
| | 342 | else |
| | 343 | goto dt_err; |
| | 344 | |
| | 345 | |
| | 346 | if( ur_is(conn, UT_BLOCK) ) |
| | 347 | { |
| | 348 | // Multiple connections may exist. |
| | 349 | b1 = tBlock( conn ); |
| | 350 | it = b1->ptr.cells; |
| | 351 | end = it + b1->used; |
| | 352 | while( it != end ) |
| | 353 | { |
| | 354 | assert( ur_is(it, UT_WORD) ); |
| | 355 | if( (ur_atom(it) == atom) && |
| | 356 | (it->word.valBlk == cc2->ctx.valBlk) ) |
| | 357 | { |
| | 358 | ur_arrayErase( b1, sizeof(UCell), it - b1->ptr.cells, 1 ); |
| | 359 | break; |
| | 360 | } |
| | 361 | ++it; |
| | 362 | } |
| | 363 | } |
| | 364 | else if( ur_is(conn, UT_WORD) ) |
| | 365 | { |
| | 366 | // A single connection exists. |
| | 367 | if( (ur_atom(conn) == atom) && |
| | 368 | (conn->word.valBlk == cc2->ctx.valBlk) ) |
| | 369 | { |
| | 370 | ur_setNone( conn ); |
| | 371 | } |
| | 372 | } |
| | 373 | // Else no existing connections. |
| | 374 | |
| | 375 | UR_S_DROPN( 2 ); |
| | 376 | return; |
| | 377 | |
| | 378 | dt_err: |
| | 379 | |
| | 380 | ur_throwErr( UR_ERR_DATATYPE, |
| | 381 | "disconnect expected select! select! bound to components" ); |
| | 382 | return; |
| | 383 | |
| | 384 | out_err: |
| | 385 | |
| | 386 | ur_throwErr( UR_ERR_SCRIPT, "Must disconnect from a component output" ); |
| | 387 | } |