Changeset 76 for trunk/orca

Show
Ignore:
Timestamp:
03/08/06 14:57:20 (3 years ago)
Author:
volker
Message:

remove-each added

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • trunk/orca/context.c

    r54 r76  
    12061206 
    12071207 
     1208/* 
     1209   'variables   [word! block!] 
     1210   series       [series!] 
     1211   body         [block!] 
     1212*/ 
     1213//see orForeachNative 
     1214 
     1215void orRemoveEachNative( OValue* a1 ) 
     1216{ 
     1217    int rlen; 
     1218    int vlen; 
     1219    OBlock* blk; 
     1220    OValue* wval; 
     1221    OContext ctx; 
     1222    OValue* a2 = a1 + 1; 
     1223    OIndex serN = a2->index; 
     1224    OIndex si   = a2->series.it; 
     1225    //: 
     1226    OIndex sdest = 0;//in second buffer 
     1227    OIndex sorig = si;  
     1228    OIndex ssrc; 
     1229 
     1230    OIndex send; 
     1231    OIndex body = (a1 + 2)->index; 
     1232    OIndex bi   = (a1 + 2)->series.it; 
     1233 
     1234    // Binding a copy of the body to a private context is horribly 
     1235    // expensive but what choice do we have? 
     1236    // Still, 'foreach is faster than 'forall (probably because using paths 
     1237    // is so slow). 
     1238 
     1239    orRefAvailErr( 4 ) 
     1240 
     1241    // Must hold body & a2 in case orMakeContext() or orCopyBlock() trigger 
     1242    // recycle. 
     1243    orRefPush( OT_BLOCK, body ); 
     1244    orRefPush( a2->type, a2->index ); 
     1245 
     1246    if( a1->type == OT_BLOCK ) 
     1247    { 
     1248        OValue* it; 
     1249        OValue* end; 
     1250 
     1251        blk = orBLOCK(a1); 
     1252 
     1253        orRefPush( OT_BLOCK, a1->index ); 
     1254        orMakeContext( &ctx, blk->used - a1->series.it ); 
     1255        orRefPop( 1 ); 
     1256 
     1257        it  = blk->values + a1->series.it; 
     1258        end = blk->values + blk->used; 
     1259 
     1260        blk = orBlockPtr( ctx.wblkN ); 
     1261        while( it != end ) 
     1262        { 
     1263            if( it->type == OT_WORD ) 
     1264            { 
     1265                orInternA( blk, it->word.atom ); 
     1266            } 
     1267            else 
     1268            { 
     1269                orError( "Invalid foreach argument" ); 
     1270                orRefPop( 2 ); 
     1271                return; 
     1272            } 
     1273            ++it; 
     1274        } 
     1275 
     1276    } 
     1277    else 
     1278    { 
     1279        orMakeContext( &ctx, 1 ); 
     1280        orInternA( orBlockPtr( ctx.wblkN ), a1->word.atom ); 
     1281    } 
     1282 
     1283    orRefPush( OT_BLOCK, ctx.wblkN ); 
     1284    orRefPush( OT_BLOCK, ctx.vblkN ); 
     1285 
     1286    blk = orBlockPtr( ctx.vblkN ); 
     1287    wval = blk->values; 
     1288    vlen = blk->avail; 
     1289 
     1290    blk = orCopyBlock( body, bi, 1 ); 
     1291    body = orBlockN( blk ); 
     1292    bi   = 0; 
     1293    orBind( blk, &ctx ); 
     1294 
     1295    // 
     1296    // the real loop 
     1297    // 
     1298 
     1299    switch( a2->type ) 
     1300    { 
     1301        case OT_BLOCK: 
     1302        case OT_PAREN: 
     1303        case OT_PATH: 
     1304        { 
     1305            blk = orBlockPtr( serN ); 
     1306            OValue *keept = calloc(blk->used,sizeof(OValue)); 
     1307            send = blk->used; 
     1308 
     1309            if( vlen > 1 ) 
     1310                send -= vlen - 1; 
     1311 
     1312            while( si < send ) 
     1313            { 
     1314                memCpy( wval, blk->values + si, vlen * sizeof(OValue) ); 
     1315 
     1316                //: 
     1317                orEvalBlock( orBlockPtr( body ), bi ); 
     1318                if( orErrorThrown ) 
     1319                    goto error; 
     1320                blk = orBlockPtr( serN );          // Reacquire. 
     1321                //: 
     1322                if( !orIfTrue(orRESULT)){ 
     1323                  memCpy( keept + sdest, blk->values + si, vlen * sizeof(OValue) ); 
     1324                  sdest += vlen; 
     1325                } 
     1326                si += vlen; //:moved 
     1327            } 
     1328 
     1329            //handle rest, if less values then loopvars 
     1330 
     1331            if( si < blk->used ) 
     1332            { 
     1333                rlen = blk->used - si; 
     1334 
     1335                memCpy( wval, blk->values + si, rlen * sizeof(OValue) ); 
     1336                wval += rlen; 
     1337 
     1338                while( rlen < vlen ) 
     1339                { 
     1340                    orSetTF( wval, OT_NONE ); 
     1341                    ++wval; 
     1342                    ++rlen; 
     1343                } 
     1344 
     1345                orEvalBlock( orBlockPtr( body ), bi ); 
     1346                if( orErrorThrown ) 
     1347                    goto error; 
     1348                //: 
     1349                blk = orBlockPtr( serN );          // Reacquire. 
     1350                if( !orIfTrue(orRESULT)){ 
     1351                  memCpy( keept + sdest, blk->values + si, (blk->used - si) * sizeof(OValue) ); 
     1352                  sdest += blk->used - si; 
     1353                }                
     1354            } 
     1355 
     1356            //: return block         
     1357            orResultBLOCK( serN ); 
     1358            blk->used = sorig + sdest; 
     1359            orRESULT->series.it = sorig; 
     1360            memCpy( blk->values + sorig, keept, sdest * sizeof(OValue)); 
     1361            free(keept); 
     1362        } 
     1363        break; 
     1364 
     1365        case OT_STRING: 
     1366        case OT_FILE: 
     1367        case OT_ISSUE: 
     1368        case OT_TAG: 
     1369        { 
     1370            OString* str = orStringPtr( serN ); 
     1371            char *keept = malloc(str->used); 
     1372            send = str->used; 
     1373 
     1374            orSetTF( wval, OT_CHAR ); 
     1375 
     1376            if( vlen > 1 ) 
     1377            { 
     1378                send -= vlen - 1; 
     1379 
     1380                for( rlen = 1; rlen < vlen; ++rlen ) 
     1381                    orSetTF( (wval + rlen), OT_CHAR ); 
     1382            } 
     1383 
     1384            while( si < send ) 
     1385            { 
     1386              ssrc = si; 
     1387                for( rlen = 0; rlen < vlen; ++rlen ) 
     1388                    (wval + rlen)->integer = str->charArray[ si++ ]; 
     1389 
     1390                orEvalBlock( orBlockPtr( body ), bi ); 
     1391                if( orErrorThrown ) 
     1392                    goto error; 
     1393                str = orStringPtr( serN );     // Reacquire. 
     1394                //: 
     1395                if( !orIfTrue(orRESULT)){ 
     1396                  strNCpy( keept + sdest, str->charArray + ssrc, vlen ); 
     1397                  sdest += vlen; 
     1398                } 
     1399            } 
     1400 
     1401            if( si < str->used ) 
     1402            { 
     1403                rlen = str->used - si; 
     1404              ssrc = si; 
     1405 
     1406                while( si < str->used ) 
     1407                { 
     1408                    wval->integer = str->charArray[ si++ ]; 
     1409                    ++wval; 
     1410                } 
     1411 
     1412                while( rlen < vlen ) 
     1413                { 
     1414                    orSetTF( wval, OT_NONE ); 
     1415                    ++wval; 
     1416                    ++rlen; 
     1417                } 
     1418 
     1419                orEvalBlock( orBlockPtr( body ), bi ); 
     1420                if( orErrorThrown ) 
     1421                    goto error; 
     1422                //: 
     1423                str = orStringPtr( serN );          // Reacquire. 
     1424                if( !orIfTrue(orRESULT)){ 
     1425                  strNCpy( keept + sdest, str->charArray + ssrc, (str->used - ssrc) ); 
     1426                  sdest += str->used - ssrc; 
     1427                }                
     1428            } 
     1429            //: return string 
     1430            orResultSTRING( serN ); 
     1431            str->used = sorig + sdest; 
     1432            orRESULT->series.it = sorig; 
     1433            strNCpy( str->charArray + sorig, keept, str->used ); 
     1434            free(keept); 
     1435        } 
     1436            break; 
     1437 
     1438    default: 
     1439      orError("remove-each for this type not implemented"); 
     1440 
     1441 
     1442/*         case OT_LIST: */ 
     1443/*             if( a1->type == OT_BLOCK ) */ 
     1444/*             { */ 
     1445/*                 orError( "foreach block! list! not implemented" ); */ 
     1446/*                 break; */ 
     1447/*             } */ 
     1448 
     1449/*             orResultNONE; */ 
     1450 
     1451/*             if( a2->series.index ) */ 
     1452/*             { */ 
     1453/*                 OValue* begin; */ 
     1454/*                 OValue* it; */ 
     1455 
     1456/*                 blk = orBLOCK(a2); */ 
     1457/*                 begin = blk->values; */ 
     1458/*                 it    = begin + a2->series.index; */ 
     1459 
     1460/*                 while( it->LIST_NEXT > 0 ) */ 
     1461/*                 { */ 
     1462/*                     orCopyV( wval, it[1] ); */ 
     1463 
     1464/*                     orEvalBlock( orBlockPtr( body ), bi ); */ 
     1465/*                     if( orErrorThrown ) */ 
     1466/*                         goto error; */ 
     1467 
     1468/*                     //blk = orBlockPtr( serN );          // Reacquire. */ 
     1469/*                     //orListNextNode( blk, it ); */ 
     1470/*                     it = begin + it->LIST_NEXT; */ 
     1471/*                 } */ 
     1472/*             } */ 
     1473/*             break; */ 
     1474    } 
     1475 
     1476free_private: 
     1477 
     1478    orFreeBlock( body ); 
     1479    orFreeBlock( ctx.wblkN ); 
     1480    orFreeBlock( ctx.vblkN ); 
     1481    goto pop; 
     1482 
     1483error: 
     1484 
     1485    if( orErrorIsType(OR_ERROR_BREAK) ) 
     1486    { 
     1487        orErrorClear; 
     1488        orSetTF( a1, OT_UNSET ); 
     1489        goto free_private; 
     1490    } 
     1491 
     1492    // Cannot free body block if error is thrown and orError->block == body. 
     1493 
     1494pop: 
     1495 
     1496    orRefPop( 4 ); 
     1497} 
     1498 
    12081499/*EOF*/