| | 214 | } |
| | 215 | |
| | 216 | |
| | 217 | #define QS_VAL(a) cells[a].word.sel |
| | 218 | |
| | 219 | // Using series.end to swap word.index & word.sel together. |
| | 220 | #define QS_SWAP(a,b) \ |
| | 221 | stmp = cells[a].series.end; \ |
| | 222 | cells[a].series.end = cells[b].series.end; \ |
| | 223 | cells[b].series.end = stmp |
| | 224 | |
| | 225 | static void _quickSort( UCell* cells, int low, int high ) |
| | 226 | { |
| | 227 | int i, j; |
| | 228 | UAtom val; |
| | 229 | UIndex stmp; |
| | 230 | |
| | 231 | if( low >= high ) |
| | 232 | return; |
| | 233 | |
| | 234 | val = QS_VAL(low); |
| | 235 | i = low; |
| | 236 | j = high+1; |
| | 237 | for(;;) |
| | 238 | { |
| | 239 | do i++; while( i <= high && QS_VAL(i) < val ); |
| | 240 | do j--; while( QS_VAL(j) > val ); |
| | 241 | if( i > j ) |
| | 242 | break; |
| | 243 | QS_SWAP( i, j ); |
| | 244 | } |
| | 245 | QS_SWAP( low, j ); |
| | 246 | _quickSort( cells, low, j-1 ); |
| | 247 | _quickSort( cells, j+1, high ); |
| | 248 | } |
| | 249 | |
| | 250 | |
| | 251 | static void _orderWords( UCell* words, int count ) |
| | 252 | { |
| | 253 | UCell* it; |
| | 254 | UCell* end; |
| | 255 | int index = 0; |
| | 256 | |
| | 257 | it = words; |
| | 258 | end = words + count; |
| | 259 | |
| | 260 | while( it != end ) |
| | 261 | { |
| | 262 | it->word.index = index++; |
| | 263 | it->word.sel = ur_atom(it); |
| | 264 | ++it; |
| | 265 | } |
| | 266 | |
| | 267 | _quickSort( words, 0, count - 1 ); |
| | 268 | } |
| | 269 | |
| | 270 | |
| | 271 | /* |
| | 272 | Returns index of atom in word block or -1 if not found. |
| | 273 | */ |
| | 274 | static int _binarySearch( UCell* words, int count, UAtom atom ) |
| | 275 | { |
| | 276 | int sAtom; |
| | 277 | int mid; |
| | 278 | int low = 0; |
| | 279 | int high = count - 1; |
| | 280 | |
| | 281 | while( low <= high ) |
| | 282 | { |
| | 283 | mid = ((unsigned int) (low + high)) >> 1; |
| | 284 | sAtom = words[ mid ].word.sel; |
| | 285 | |
| | 286 | if( sAtom < atom ) |
| | 287 | low = mid + 1; |
| | 288 | else if( sAtom > atom ) |
| | 289 | high = mid - 1; |
| | 290 | else |
| | 291 | return words[ mid ].word.index; |
| | 292 | } |
| | 293 | |
| | 294 | // Atom not found. |
| | 295 | return -1; |
| 272 | | #if 0 |
| 273 | | /* |
| 274 | | Returns true if block contains does or func. |
| 275 | | */ |
| 276 | | int orClosureRequired( OIndex blkN ) |
| 277 | | { |
| 278 | | OBlock* blk = orBlockPtr( blkN ); |
| 279 | | UCell* it = blk->values; |
| 280 | | UCell* end = it + blk->used; |
| 281 | | |
| 282 | | while( it != end ) |
| 283 | | { |
| 284 | | if( (it->type == OT_WORD) || |
| 285 | | (it->type == OT_SETWORD) || |
| 286 | | (it->type == OT_GETWORD) ) |
| 287 | | { |
| 288 | | if( (it->word.atom == orEnv->atom_func) || |
| 289 | | (it->word.atom == orEnv->atom_does) ) |
| 290 | | return 1; |
| 291 | | } |
| 292 | | else if( (it->type == OT_BLOCK) || (it->type == OT_PAREN) ) |
| 293 | | { |
| 294 | | if( orClosureRequired( it->index ) ) |
| 295 | | return 1; |
| 296 | | } |
| 297 | | |
| 298 | | ++it; |
| 299 | | } |
| 300 | | return 0; |
| 301 | | } |
| 302 | | |
| 303 | | |
| 304 | | void orRebind( OIndex blkN, OIndex from, OIndex to ) |
| 305 | | { |
| 306 | | OBlock* blk = orBlockPtr( blkN ); |
| 307 | | UCell* it = blk->values; |
| 308 | | UCell* end = it + blk->used; |
| 309 | | |
| 310 | | while( it != end ) |
| 311 | | { |
| 312 | | if( (it->type == OT_WORD) || |
| 313 | | (it->type == OT_SETWORD) || |
| 314 | | (it->type == OT_GETWORD) ) |
| 315 | | { |
| 316 | | if( it->word.context == from ) |
| 317 | | it->word.context = to; |
| 318 | | } |
| 319 | | #if 0 |
| 320 | | else if( (it->type == OT_PATH) || (it->type == OT_SETPATH) ) |
| 321 | | { |
| 322 | | UCell* path1 = orBLOCK( it )->values; |
| 323 | | if( (path1->type == OT_WORD) || |
| 324 | | (path1->type == OT_SETWORD) || |
| 325 | | (path1->type == OT_GETWORD) ) |
| 326 | | { |
| 327 | | if( path1->word.context == from ) |
| 328 | | path1->word.context = to; |
| 329 | | } |
| 330 | | } |
| 331 | | #endif |
| 332 | | else if( (it->type == OT_BLOCK) || (it->type == OT_PAREN) ) |
| 333 | | { |
| 334 | | orRebind( it->index, from, to ); |
| 335 | | } |
| 336 | | |
| 337 | | ++it; |
| 338 | | } |
| 339 | | } |
| 340 | | #endif |
| 341 | | |
| 342 | | |
| 343 | | /* |
| 344 | | (block context -- block) |
| 345 | | */ |
| 346 | | UR_CALL_PUB( uc_bind ) |
| 347 | | { |
| 348 | | UCell* bc; |
| 349 | | |
| 350 | | UR_S_DROP; |
| 351 | | bc = UR_TOS; |
| 352 | | |
| 353 | | if( ur_is(tos, UT_LITWORD) || ur_is(tos, UT_CONTEXT) ) |
| 354 | | { |
| 355 | | if( ur_is(bc, UT_BLOCK) ) |
| 356 | | { |
| 357 | | ur_bind( bc->series.n, tos ); |
| 358 | | return; |
| 359 | | } |
| 360 | | } |
| 361 | | |
| 362 | | ur_throwErr( ur_thread, UR_EX_DATATYPE, "Invalid bind values" ); |
| 363 | | } |
| 364 | | |
| 365 | | |
| 366 | | #if 0 |
| 367 | | void orProtectNative( UCell* a1 ) |
| 368 | | { |
| 369 | | OBlock* vblk; |
| 370 | | OContext ctx; |
| 371 | | int wrdN; |
| 372 | | |
| 373 | | orGlobalCtx( ctx ); |
| 374 | | vblk = orBlockPtr( ctx.wblkN ); |
| 375 | | |
| 376 | | if( a1->type == OT_WORD ) |
| 377 | | { |
| 378 | | wrdN = orLookup( &ctx, a1->word.atom ); |
| 379 | | if( wrdN > -1 ) |
| 380 | | { |
| 381 | | vblk->values[ wrdN ].flags |= OR_WORD_PROT; |
| 382 | | } |
| 383 | | } |
| 384 | | else if( a1->type == OT_BLOCK ) |
| 385 | | { |
| 386 | | OBlock* blk = orBLOCK( a1 ); |
| 387 | | UCell* it = blk->values; |
| 388 | | UCell* end = it + blk->used; |
| 389 | | while( it != end ) |
| 390 | | { |
| 391 | | if( it->type == OT_WORD ) |
| 392 | | { |
| 393 | | wrdN = orLookup( &ctx, a1->word.atom ); |
| 394 | | if( wrdN > -1 ) |
| 395 | | { |
| 396 | | vblk->values[ wrdN ].flags |= OR_WORD_PROT; |
| 397 | | } |
| 398 | | } |
| 399 | | ++it; |
| 400 | | } |
| 401 | | } |
| 402 | | orResultUNSET; |
| 403 | | } |
| 404 | | |
| 405 | | |
| 406 | | /* |
| 407 | | object [object!] |
| 408 | | word [word!] |
| 409 | | */ |
| 410 | | void orInNative( UCell* a1 ) |
| 411 | | { |
| 412 | | UCell* a2 = a1 + 1; |
| 413 | | OIndex wrdN; |
| 414 | | |
| 415 | | wrdN = orLookup( &a1->ctx, a2->word.atom ); |
| 416 | | if( wrdN < 0 ) |
| 417 | | { |
| 418 | | orResultNONE; |
| 419 | | } |
| 420 | | else |
| 421 | | { |
| 422 | | orSetTF( a1, OT_WORD ); |
| 423 | | // a1->context remains unchanged. |
| 424 | | a1->word.index = wrdN; |
| 425 | | a1->word.atom = a2->word.atom; |
| 426 | | } |
| 427 | | } |
| 428 | | |
| 429 | | |
| 430 | | /* |
| 431 | | words [block! word!] |
| 432 | | body [block!] |
| 433 | | */ |
| 434 | | void orUseNative( UCell* a1 ) |
| 435 | | { |
| 436 | | OContext ctx; |
| 437 | | OBlock* blk; |
| 438 | | UCell* it; |
| 439 | | UCell* end; |
| 440 | | UCell* a2 = a1 + 1; |
| 441 | | |
| 442 | | |
| 443 | | orRefPush( OT_BLOCK, a2->index ); |
| 444 | | |
| 445 | | if( a1->type == OT_WORD ) |
| 446 | | { |
| 447 | | orMakeContext( &ctx, 1 ); |
| 448 | | orInternA( orBlockPtr( ctx.wblkN ), a1->word.atom ); |
| 449 | | } |
| 450 | | else |
| 451 | | { |
| 452 | | orRefPush( OT_BLOCK, a1->index ); |
| 453 | | |
| 454 | | blk = orBLOCK( a1 ); |
| 455 | | it = blk->values + a1->series.index; |
| 456 | | end = blk->values + blk->used; |
| 457 | | |
| 458 | | orMakeContext( &ctx, end - it ); |
| 459 | | blk = orBlockPtr( ctx.wblkN ); |
| 460 | | |
| 461 | | while( it != end ) |
| 462 | | { |
| 463 | | if( it->type == OT_WORD ) |
| 464 | | orInternA( blk, it->word.atom ); |
| 465 | | ++it; |
| 466 | | } |
| 467 | | |
| 468 | | orRefPop( 1 ); |
| 469 | | } |
| 470 | | |
| 471 | | blk = orBlockPtr( ctx.vblkN ); |
| 472 | | it = blk->values; |
| 473 | | end = it + blk->used; |
| 474 | | while( it != end ) |
| 475 | | { |
| 476 | | orSetTF( it, OT_UNSET ); |
| 477 | | ++it; |
| 478 | | } |
| 479 | | |
| 480 | | orBind( orBlockPtr( a2->index ), &ctx ); |
| 481 | | |
| 482 | | orRefPop( 1 ); |
| 483 | | |
| 484 | | orEvalBlock( orBlockPtr( a2->index ), a2->series.index ); |
| 485 | | } |
| 486 | | #endif |
| 487 | | |
| 488 | | |