72 res = ut->stack.ptr.cell + n;
179 UCell* cell = ur_exception(ut);
186 assert( cell == ut->stack.ptr.cell );
210 UCell* cell = ur_exception(ut);
212 if (ef->invoke.userBuf)
214 if (! ur_is(cell, UT_WORD))
217 name = ut->stack.
ptr.
cell + ef->invoke.userBuf;
218 if (ur_is(name, UT_WORD))
220 if (ur_atom(name) == ur_atom(cell))
226 else if (ur_is(name, UT_BLOCK))
232 if (ur_is(bi.
it, UT_WORD) && ur_atom(bi.
it) == ur_atom(cell))
243 *ef->invoke.result = *cell;
250 EvalFrame* ef = boron_reuseFrame(ut, 1, &origStack);
254 boron_initEvalCatch(ef, catch_catch, origStack, res);
258 const UCell* name = a1 + 1;
259 ef->invoke.userBuf = name - ut->stack.
ptr.
cell;
262 ef->invoke.userBuf = 0;
265 boron_initEvalBlock(ef, ut, a1->series.buf, res);
266 return CFUNC_REFRAMED;
282 UCell* cell = ur_exception(ut);
283 if (! ur_is(cell, UT_ERROR))
285 *ef->invoke.result = *cell;
292 EvalFrame* ef = boron_reuseFrame(ut, 1, &origStack);
296 boron_initEvalCatch(ef, catch_try, origStack, res);
298 boron_initEvalBlock(ef, ut, a1->series.buf, res);
299 return CFUNC_REFRAMED;
345 if( ur_isWordType(
ur_type(a1) ) )
351 else if( ur_is(a1, UT_PATH) )
356 else if( ur_is(a1, UT_BLOCK) )
360 if( ur_is(a2, UT_BLOCK) )
366 if( ur_isWordType(
ur_type(bi.it) ) )
370 if( b2.
it != b2.
end )
381 if( ur_isWordType(
ur_type(bi.it) ) )
408 if( ur_isWordType(
ur_type(a1) ) )
416 else if( ur_is(a1, UT_CONTEXT) )
443 if( ur_isWordType(
ur_type(a1) ) )
448 if( ur_is(cell, UT_UNSET) )
452 ur_logic(res) = logic;
467 if( ur_isWordType(
ur_type(a2) ) )
481 int ctxN = a1->series.buf;
485 res->word.ctx = ctxN;
486 res->word.index = wrdN;
490 return errorType(
"in expected word of type word!/lit-word!" );
508 const UCell* bc = a2;
510 if( ur_is(a1, UT_CONTEXT) && ur_is(bc, UT_BLOCK) )
518 return boron_doBlock( ut, bc, res );
520 return errorType(
"use expected context! and block!" );
549 if( ur_is(a1, UT_CONTEXT) )
569 hashmap_values( ut, a1, blk );
576 if( ur_is(a1, UT_CONTEXT) )
580 _contextWords( ut, ctx, a1->context.buf, res );
598 if( ! ur_isWordType(
ur_type(a1) ) )
599 return errorType(
"binding? expected word type" );
600 switch( ur_binding(a1) )
605 ur_setSeries( res, a1->word.ctx, 0 );
610 ur_setWordUnbound( res, UT_FUNC );
613 case BOR_BIND_OPTION:
615 ur_setWordUnbound( res, UT_OPTION );
626#define BIND_ERR_MSG "%s expected words argument of word!/block!"
639#define OPT_BIND_SECURE 0x01
645 if( ur_is(ctxArg, UT_WORD) )
648 if( ctxN == UR_INVALID_BUF )
650 ur_wordCStr( ctxArg ) );
652 else if( ur_is(ctxArg, UT_CONTEXT) )
664 if( ur_is(a1, UT_BLOCK) )
672 ur_bind( ut, blk, ctx, bindType );
676 else if( ur_is(a1, UT_WORD) )
691 bt.self = UR_INVALID_ATOM;
712#define OPT_UNBIND_DEEP 0x01
714 if( ur_is(a1, UT_BLOCK) )
722 else if( ur_is(a1, UT_WORD) )
747 if( ur_is(ctxArg, UT_WORD) )
750 if( ctxN == UR_INVALID_BUF )
752 ur_wordCStr( ctxArg ) );
754 else if( ur_is(ctxArg, UT_CONTEXT) )
768#define OPER_FUNC(name,OP) \
770 int t = ur_type(a1); \
771 if( t < ur_type(a2) ) \
773 return ut->types[ t ]->operate( ut, a1, a2, res, OP ); \
829OPER_FUNC( cfunc_add, UR_OP_ADD )
830OPER_FUNC( cfunc_sub, UR_OP_SUB )
831OPER_FUNC( cfunc_mul, UR_OP_MUL )
832OPER_FUNC( cfunc_div, UR_OP_DIV )
833OPER_FUNC( cfunc_mod, UR_OP_MOD )
860OPER_FUNC( cfunc_and, UR_OP_AND )
861OPER_FUNC( cfunc_or, UR_OP_OR )
862OPER_FUNC( cfunc_xor, UR_OP_XOR )
875 *res = (
ur_compare( ut, a1, a2 ) < 0) ? *a1 : *a2;
890 *res = (
ur_compare( ut, a1, a2 ) > 0) ? *a1 : *a2;
908 ur_int(res) = llabs( ur_int(a1) );
914 ur_double(res) = fabs( ur_double(a1) );
924static int _mathFunc(
const UCell* a1,
UCell* res,
double (*func)(
double) )
927 if( ur_is(a1, UT_DOUBLE) )
930 n = (double) ur_int(a1);
932 ur_double(res) = func( n );
955CFUNC(cfunc_sqrt) { (void) ut;
return _mathFunc( a1, res, sqrt ); }
956CFUNC(cfunc_cos) { (void) ut;
return _mathFunc( a1, res, cos ); }
957CFUNC(cfunc_sin) { (void) ut;
return _mathFunc( a1, res, sin ); }
974 n = (double) ur_int(a1);
983 n = (double) a1->
coord.
n[0];
984 rise = (double) a1->
coord.
n[1];
990 n = atan2( rise, n );
1014 if( ur_is(a1, UT_DATATYPE) )
1018 return DT( t )->make( ut, a2, res );
1020 else if( ur_is(a1, UT_CONTEXT) )
1024 if( ur_is(a2, UT_BLOCK) )
1034 "make requires a context! or single datatype!" );
1047#define OPT_COPY_DEEP 0x01
1050 if( ur_isBlockType( type ) && (
CFUNC_OPTIONS & OPT_COPY_DEEP) )
1056 DT( type )->copy( ut, a1, res );
1078 if( ! ur_isSeriesType( type ) )
1079 return errorType(
"reserve expected series" );
1101 DT( type )->reserve( ut, a1, size );
1123 ur_setSeries(res, bodyN, 0);
1128void boron_compileArgProgram( BoronThread*,
const UCell* specC,
UBuffer* prog,
1129 UIndex bodyN,
int* sigFlags );
1132void boron_argProgramToStr(
UThread*,
const void* prog,
UBuffer* str);
1147 static const uint8_t _types[2] = {UT_BLOCK, UT_BINARY};
1153 const int prelude = 2;
1163 ur_initSeries(blk->
ptr.
cell, UT_BINARY, bufN[1]);
1171 boron_compileArgProgram( BT, a1, prog, bufN[0], &sigFlags );
1177 boron_argProgramToStr(ut, prog->
ptr.
b, &str);
1179 printf(
"KR func %s\n", str.
ptr.
c);
1186 ur_setSeries(res, bufN[0], prelude);
1188 ur_setFlags(res, FUNC_FLAG_NOTRACE);
1225 if( ur_is(bc, UT_BLOCK) )
1227 FUNC_FLAG_NOTRACE );
1251 if( ur_is(bc, UT_BLOCK) )
1253 FUNC_FLAG_NOTRACE );
1274 if( ur_is(bc, UT_BLOCK) )
1276 FUNC_FLAG_NOTRACE );
1283#define CATCH_BREAK_CONTINUE(cell) \
1284 cell = ur_exception(ut); \
1285 if( ur_is(cell, UT_WORD) ) { \
1286 if( ur_atom(cell) == UR_ATOM_BREAK ) \
1288 if( ur_atom(cell) == UR_ATOM_CONTINUE ) \
1294 const UCell* cell = ur_exception(ut);
1295 if (ur_is(cell, UT_WORD)) {
1296 if (ur_atom(cell) == UR_ATOM_BREAK)
1298 if (ur_atom(cell) == UR_ATOM_CONTINUE)
1299 return boron_resetEvalFrame(ut, ef + 1);
1319 if (invoke->userBuf)
1321 invoke->userBuf = 0;
1322 if (!
ur_true(invoke->result))
1328 invoke->userBuf = 1;
1331 ef = boron_pushEvalFrame(ut);
1332 ef->block = ef[n].block;
1333 return CFUNC_REFRAMED;
1339 EvalFrame* ef = boron_reuseFrame(ut, 3, &origStack);
1342 boron_initEvalBlock(ef, ut, a1->
series.
buf, res);
1345 boron_initEvalBlock(ef, ut, a2->series.buf, res);
1348 ef->invoke.eop = EOP_INVOKE_LOOP;
1349 ef->invoke.state = 3;
1350 ef->invoke.origStack = origStack;
1351 ef->invoke.userBuf = 1;
1352 ef->invoke.func = _whileLoop;
1353 ef->invoke.dat.catchf = catch_breakContinue;
1354 ef->invoke.result = res;
1357 ef->block = ef[-3].block;
1358 return CFUNC_REFRAMED;
1374 EvalFrame* ef = boron_pushEvalFrame(ut);
1375 ef->block = ef[-2].block;
1376 return CFUNC_REFRAMED;
1382 EvalFrame* ef = boron_reuseFrame(ut, 1, &origStack);
1385 boron_initEvalBlock(ef, ut, a1->
series.
buf, res);
1388 ef->invoke.eop = EOP_INVOKE_LOOP;
1389 ef->invoke.state = 2;
1390 ef->invoke.origStack = origStack;
1392 ef->invoke.func = _foreverLoop;
1393 ef->invoke.dat.catchf = catch_breakContinue;
1396 return CFUNC_REFRAMED;
1415 if (--invoke->userBuf == 0)
1418 ef = boron_pushEvalFrame(ut);
1419 ef->block = ef[-2].block;
1420 return CFUNC_REFRAMED;
1423static UStatus _loopRangeLoop(
UThread* ut, EvalFrameInvoke* invoke)
1425 EvalFrame* ef = ((EvalFrame*) invoke) - 1;
1426 int32_t* n = (int32_t*) &ef->block.codeBlk;
1427 const UCell* cword = ef->block.result;
1430 if (invoke->userBuf)
1433 invoke->userBuf = 1;
1444 ur_int(counter) = n[0];
1447 ef = boron_pushEvalFrame(ut);
1448 ef->block = ef[-3].block;
1449 return CFUNC_REFRAMED;
1457 if (ur_is(a1, UT_INT))
1462 ef = boron_reuseFrame(ut, 2, &origStack);
1465 boron_initEvalBlock(ef, ut, a2->series.buf, res);
1468 ef->invoke.eop = EOP_INVOKE_LOOP;
1469 ef->invoke.state = 2;
1470 ef->invoke.origStack = origStack;
1471 ef->invoke.userBuf = (
UIndex) ur_int(a1);
1472 ef->invoke.func = _loopNLoop;
1473 ef->invoke.dat.catchf = catch_breakContinue;
1474 ef->invoke.result = res;
1477 ef->block = ef[-2].block;
1481 const UCell* cword = NULL;
1486 ef = boron_reuseFrame(ut, 2, &origStack);
1489 boron_initEvalBlock(ef, ut, a2->series.buf, res);
1492 ef->block.eop = EOP_NOP;
1494 n = (int32_t*) &ef->block.codeBlk;
1497 ef->invoke.eop = EOP_INVOKE_LOOP;
1498 ef->invoke.state = 3;
1499 ef->invoke.origStack = origStack;
1500 ef->invoke.userBuf = 0;
1501 ef->invoke.func = _loopRangeLoop;
1502 ef->invoke.dat.catchf = catch_breakContinue;
1503 ef->invoke.result = res;
1512 if( ur_is(bi.
it, UT_WORD ) )
1516 else if( ur_is(bi.
it, UT_INT ) )
1519 n[ state++ ] = ur_int(bi.
it);
1522 errorType(
"loop range values must be word!/int!" );
1530 ef[-1].block.result = (
UCell*) cword;
1532 return CFUNC_REFRAMED;
1547#define OPT_SELECT_LAST 0x01
1548#define OPT_SELECT_CASE 0x02
1554 if( ! ur_isSeriesType( type ) )
1563 dt = SERIES_DT( type );
1564 n = dt->
find( ut, &si, a2, n );
1566 if( n > 0 && n < si.
end )
1587 const UCell* found = 0;
1590 if( (bi.
end - bi.
it) & 1 )
1593 for( ; bi.
it != bi.
end; bi.
it += 2 )
1604 if( ur_is(found, UT_BLOCK) || ur_is(found, UT_PAREN) )
1626 UCell* res = invoke->result;
1628 if (invoke->state == DO_BLOCK1_COMPLETE)
1634 ef = ((EvalFrame*) invoke) + 1;
1637 boron_breakDoBlock1(ut, invoke);
1640 if (it == ef->block.end)
1644 else if (ur_is(it, UT_BLOCK) || ur_is(it, UT_PAREN))
1646 ef = boron_pushEvalFrame(ut);
1647 boron_initEvalBlock(ef, ut, it->
series.
buf, res);
1653 return CFUNC_REFRAMED;
1662 return boron_reframeDoBlock1(ut, a1->
series.
buf, eval_case, res);
1666extern void coord_pick(
const UCell* cell,
int index,
UCell* res );
1667extern void vec3_pick (
const UCell* cell,
int index,
UCell* res );
1681 if( ur_isSeriesType( type ) )
1683 else if( type == UT_COORD )
1684 coord_pick( a1, 0, res );
1685 else if( type == UT_VEC3 )
1686 vec3_pick( a1, 0, res );
1687 else if( ur_isPathType( type ) )
1688 path_pick( ut, a1, 0, res );
1713 if( ur_isSeriesType( type ) )
1715 else if( type == UT_COORD )
1716 coord_pick( a1, n, res );
1717 else if( type == UT_VEC3 )
1718 vec3_pick( a1, n, res );
1719 else if( ur_isPathType( type ) )
1720 path_pick( ut, a1, n, res );
1738 if( ! ur_isSeriesType( type ) )
1741 if( si.
it == si.
end )
1761 if( ! ur_is(a1, UT_WORD) )
1768 if( ur_isSeriesType(
ur_type(cell) ) )
1770 if( cell->
series.
it < boron_seriesEnd(ut, cell) )
1773 else if( ur_is(cell, UT_INT) )
1775 else if( ur_is(cell, UT_DOUBLE) )
1776 ur_double(cell) += 1.0;
1798 if( ! ur_is(a1, UT_WORD) )
1805 if( ur_isSeriesType(
ur_type(cell) ) )
1810 else if( ur_is(cell, UT_INT) )
1812 else if( ur_is(cell, UT_DOUBLE) )
1813 ur_double(cell) -= 1.0;
1843 static const uint8_t _coordRotOff[] = { 0,0,2,5,9,14,20 };
1844 static const uint8_t _coordRot[] = {
1849 0,1,2,3,4,5,0,1,2,3,4,5
1854 if( ! ur_is(a2, UT_INT) )
1858 if( ur_isSeriesType( type ) )
1863 size = boron_seriesEnd(ut, res);
1869 else if( type == UT_INT )
1874 ur_int(res) = ur_int(a1) << rot;
1876 ur_int(res) = ur_int(a1) >> -rot;
1878 else if( type == UT_COORD )
1881 const uint8_t* index;
1887 index = _coordRot + _coordRotOff[len] - rot;
1891 for( i = 0; i < len; ++i )
1894 else if( type == UT_VEC3 )
1897 const uint8_t* index;
1902 index = _coordRot + 5 - rot;
1905 for( i = 0; i < 3; ++i )
1910 "rotd expected int!/coord!/vec3! or series" );
1927 if( ! ur_isSeriesType( type ) )
1946 if( ! ur_isSeriesType( type ) )
1949 if( res->
series.
it < boron_seriesEnd(ut, res) )
1955static int positionPort(
UThread* ut,
const UCell* portC,
int where )
1958 PORT_SITE(dev, pbuf, portC);
1960 return errorScript(
"port is closed" );
1963 return dev->seek( ut, pbuf, &tmp, where );
1980 if( ur_isSeriesType( type ) )
1985 else if( type == UT_PORT )
1987 return positionPort( ut, a1, UR_PORT_HEAD );
2006 if( ur_isSeriesType( type ) )
2008 res->
series.
it = boron_seriesEnd(ut, res);
2011 else if( type == UT_PORT )
2013 return positionPort( ut, a1, UR_PORT_TAIL );
2040#ifdef CONFIG_HASHMAP
2041 if( type == UT_HASHMAP )
2043 const UCell* cell = hashmap_select( ut, a1, c2, res );
2052 if( ur_is(c2, UT_INT) )
2063 else if( ur_is(c2, UT_LOGIC) )
2064 n = ur_logic(c2) ? 0 : 1;
2065 else if( ur_is(c2, UT_CHAR) && type == UT_BITSET )
2070 if( ur_isSeriesType( type ) )
2072 else if( type == UT_VEC3 )
2073 vec3_pick( a1, n, res );
2074 else if( type == UT_COORD )
2075 coord_pick( a1, n, res );
2108#ifdef CONFIG_HASHMAP
2109 if( type == UT_HASHMAP )
2111 if( hashmap_insert( ut, a1, c2, a3 ) )
2120 if( ur_is(c2, UT_INT) )
2126 return errorScript(
"poke position out of range" );
2128 else if( ur_is(c2, UT_LOGIC) )
2129 n = ur_logic(c2) ? 0 : 1;
2130 else if( ur_is(c2, UT_CHAR) && type == UT_BITSET )
2136 if( ur_isSeriesType( type ) )
2140 SERIES_DT( type )->poke( buf, a1->
series.
it + n, a3 );
2143 else if( type == UT_VEC3 )
2144 return vec3_poke( ut, res, n, a3 );
2145 else if( type == UT_COORD )
2146 return coord_poke( ut, res, n, a3 );
2163 if( ! ur_isSeriesType( type ) )
2167 if( si.it == si.end )
2175 dt->
pick( si.buf, si.it, res );
2176 dt->
remove( ut, &si, 0 );
2195#define OPT_SKIP_WRAP 0x01
2196 if( ur_isSeriesType(
ur_type(a1) ) )
2201 if( ur_is(a2, UT_INT) )
2203 else if( ur_is(a2, UT_LOGIC) )
2204 n = ur_logic(a2) ? 1 : 0;
2215 (end = boron_seriesEnd( ut, a1 )) )
2226 end = boron_seriesEnd( ut, a1 );
2239 else if( ur_is(a1, UT_PORT) )
2241 PORT_SITE(dev, pbuf, a1);
2243 return errorScript(
"port is closed" );
2245 return dev->seek( ut, pbuf, a2, UR_PORT_SKIP );
2279#define OPT_APPEND_BLOCK 0x01
2280#define OPT_APPEND_REPEAT 0x02
2287 if( ur_isSeriesType( type ) )
2292 dt = SERIES_DT( type );
2295 count = (opt & OPT_APPEND_REPEAT) ? ur_int(CFUNC_OPT_ARG(2)) : 1;
2296 if( (opt & OPT_APPEND_BLOCK) && (type == UT_BLOCK) )
2298 while( --count >= 0 )
2303 while( --count >= 0 )
2305 if( ! dt->
append( ut, buf, a2 ) )
2312 if( ! dt->
append( ut, buf, a2 ) )
2319 else if( type == UT_CONTEXT )
2325 if( ur_isWordType( type ) )
2335 else if( type == UT_BLOCK )
2367 if( ur_isSeriesType( type ) )
2372 dt = SERIES_DT( type );
2373 if( ! dt->
append( ut, buf, a2 ) )
2375 if( ! dt->
append( ut, buf, a3 ) )
2399#define OPT_INSERT_BLOCK 0x01
2400#define OPT_INSERT_PART 0x02
2401#define OPT_INSERT_REPEAT 0x04
2409 if( ! ur_isSeriesType( type ) )
2417 if( opt & OPT_INSERT_REPEAT )
2418 count = ur_int(CFUNC_OPT_ARG(3));
2420 if( (opt & OPT_INSERT_BLOCK) && (type == UT_BLOCK) )
2422 while( --count >= 0 )
2426 else if( opt & OPT_INSERT_PART )
2428 UCell* parg = CFUNC_OPT_ARG(2);
2429 if( ur_is(parg, UT_INT) )
2430 part = ur_int(parg);
2431 else if( ur_isSeriesType(
ur_type(parg) ) )
2435 "insert /part expected series or int!" );
2441 dt = SERIES_DT( type );
2442 while( --count >= 0 )
2465#define OPT_CHANGE_SLICE 0x01
2466#define OPT_CHANGE_PART 0x02
2472 if( ! ur_isSeriesType( type ) )
2477 if( (opt & OPT_CHANGE_SLICE) )
2479 part = si.end - si.it;
2481 else if( opt & OPT_CHANGE_PART )
2483 UCell* parg = CFUNC_OPT_ARG(2);
2484 if( ur_is(parg, UT_INT) )
2485 part = ur_int(parg);
2486 else if( ur_isSeriesType(
ur_type(parg) ) )
2490 "change /part expected series or int!" );
2493 if( ! SERIES_DT( type )->change( ut, &si, a2, part ) )
2518#define OPT_REMOVE_SLICE 0x01
2519#define OPT_REMOVE_PART 0x02
2520#define OPT_REMOVE_KEY 0x04
2526 if( ! ur_isSeriesType( type ) )
2528 if( type == UT_NONE )
2533#ifdef CONFIG_HASHMAP
2534 else if( ur_is(a1, UT_HASHMAP) )
2536 if( opt & OPT_REMOVE_KEY )
2538 hashmap_remove( ut, a1, a2 );
2541 return errorType(
"remove requires /key for hash-map!" );
2549 if( opt & OPT_REMOVE_PART )
2551 UCell* parg = CFUNC_OPT_ARG(2);
2552 part = ur_int(parg);
2554 else if( opt & OPT_REMOVE_SLICE )
2556 part = si.end - si.it;
2559 SERIES_DT( type )->remove( ut, &si, part );
2561#ifdef CONFIG_HASHMAP
2583#define OPT_REVERSE_PART 0x01
2588 if( ! ur_isSeriesType( type ) )
2595 UCell* parg = CFUNC_OPT_ARG(1);
2596 part = ur_int(parg);
2599 if( part < (si.end - si.it) )
2600 si.end = si.it + part;
2603 SERIES_DT( type )->reverse( &si );
2623#define OPT_FIND_LAST UR_FIND_LAST
2624#define OPT_FIND_CASE UR_FIND_CASE
2625#define OPT_FIND_PART 0x04
2631 assert( UR_FIND_LAST == 1 );
2632 assert( UR_FIND_CASE == 2 );
2634 if( ! ur_isSeriesType( type ) )
2638 if( opt & OPT_FIND_PART )
2641 UCell* parg = CFUNC_OPT_ARG(3);
2643 if( ur_is(parg, UT_INT) )
2644 part = ur_int(parg);
2645 else if( ur_isSeriesType(
ur_type(parg) ) )
2648 return errorType(
"find /part expected series or int!" );
2657 i = SERIES_DT( type )->find( ut, &si, a2, opt );
2685 if( ! ur_isSeriesType(
ur_type(a1) ) )
2687 if( ur_is(a1, UT_NONE) )
2692#ifdef CONFIG_HASHMAP
2693 else if( ur_is(a1, UT_HASHMAP) )
2695 hashmap_clear( ut, a1 );
2708#ifdef CONFIG_HASHMAP
2717extern void coord_slice(
const UCell* cell,
int index,
int count,
UCell* res );
2759 const UCell* limit = a2;
2762 if( ! ur_isSeriesType(
ur_type(a1) ) )
2764 if( ur_is(a1, UT_COORD) )
2766 if( ur_is(limit, UT_INT) )
2768 end = ur_int(limit);
2771 coord_slice( a1, 0, end, res );
2773 else if( ur_is(limit, UT_COORD) )
2774 coord_slice( a1, limit->
coord.
n[0], limit->
coord.
n[1], res );
2775 else if( ur_is(limit, UT_NONE) )
2787 if( ur_is(limit, UT_NONE) )
2792 else if( ur_is(limit, UT_INT) )
2794 end = ur_int(limit);
2799 : res->series.end + end;
2810 else if( ur_is(limit, UT_COORD) )
2847 if( ! ur_isSeriesType(
ur_type(a1) ) )
2849 if( ur_is(a1, UT_NONE) )
2858 si.
it = (si.
it == si.
end) ? 1 : 0;
2862 ur_logic(res) = si.
it;
2878 if( ! ur_isSeriesType(
ur_type(a1) ) )
2900 if( ur_isSeriesType(
ur_type(a1) ) )
2904 len = si.
end - si.
it;
2906 else if( ur_is(a1, UT_COORD) )
2934 if( ur_isSeriesType( type ) ) {
2939 }
else if( ur_isWordType( type ) )
2940 ur_int(res) = ur_atom(a1);
2941 else if( type == UT_DATATYPE )
2963 if( ur_isSeriesType(
ur_type(a1) ) )
2977CFUNC(cfunc_any_blockQ)
2981 if( ur_isBlockType(
ur_type(a1) ) )
2995CFUNC(cfunc_any_wordQ)
2999 if( ur_isWordType(
ur_type(a1) ) )
3012CFUNC(cfunc_complement)
3023 ur_int(res) = ~ur_int(a1);
3053CFUNC( cfunc_negate )
3060 ur_int(res) = -ur_int(a1);
3066 ur_double(res) = -ur_double(a1);
3071 int16_t* it = a1->
coord.
n;
3073 int16_t* dst = res->
coord.
n;
3092 return cfunc_complement( ut, a1, res );
3110 enum SetOperation op,
int findOpt )
3114 const UCell* argB = a2;
3119 "intersect/difference expected series of the same type" );
3121 dt = SERIES_DT( type );
3123 if( ur_isBlockType(type) )
3132 case SET_OP_INTERSECT:
3143 if( (dt->
find( ut, &si, bi.
it, findOpt ) > -1) &&
3144 (dt->
find( ut, &ri, bi.
it, findOpt ) == -1) )
3158 if( dt->
find( ut, &si, bi.
it, findOpt ) < 0 )
3170 if( dt->
find( ut, &si, bi.
it, findOpt ) < 0 )
3190 "FIXME: set_relation only supports block!" );
3206CFUNC(cfunc_intersect)
3208 return set_relation( ut, a1, res, SET_OP_INTERSECT,
3225CFUNC(cfunc_difference)
3227 return set_relation( ut, a1, res, SET_OP_DIFF,
3243 return set_relation( ut, a1, res, SET_OP_UNION,
3287 UCell* sarg = invoke->result;
3291 si.
end = _sliceEnd(si.
buf, sarg);
3293 if (invoke->userBuf < si.
end)
3298 EvalFrame* ef = (EvalFrame*) invoke;
3300 for (wi = ef->block.it; wi != ef->block.end; ++wi)
3304 dt->
pick(si.
buf, invoke->userBuf++, cell);
3307 ef = boron_pushEvalFrame(ut);
3308 ef->block = ef[-3].block;
3309 return CFUNC_REFRAMED;
3315static UStatus loop_removeEach(
UThread* ut, EvalFrameInvoke* invoke)
3318 if (invoke->dat.catchf)
3320 EvalFrame* dof = ((EvalFrame*) invoke) - 2;
3321 if (
ur_true(dof->block.result))
3324 int remove = dof[1].block.codeBlk;
3325 UCell* sarg = invoke->result;
3328 invoke->userBuf -= remove;
3330 si.
it = invoke->userBuf;
3332 dt->
remove(ut, (USeriesIterM*) &si, remove);
3336 invoke->dat.catchf = catch_breakContinue;
3338 return loop_foreach(ut, invoke);
3349 int remove = ur_int(a1 + 3);
3354 if( ! ur_isSeriesType(
ur_type(a2) ) )
3361 return errorType(
"foreach expected series" );
3363 if( ! ur_is(body, UT_BLOCK) )
3364 return errorType(
"foreach expected block! body" );
3366 if( ur_is(a1, UT_WORD) )
3371 else if( ur_is(a1, UT_BLOCK) )
3379 int wordsShared = 0;
3383 if( ! ur_is(wi.it, UT_WORD) )
3384 return errorType(
"foreach has non-words in word block" );
3391 return errorScript(
"foreach cannot bind shared body" );
3405 return errorType(
"foreach expected word!/block! for words" );
3409 remove = wi.end - words;
3418 ef = boron_reuseFrame(ut, 2, &origStack);
3421 boron_initEvalBlock(ef, ut, body->
series.
buf, res);
3424 ef->block.eop = EOP_NOP;
3425 ef->block.origStack = 0;
3426 ef->block.codeBlk = remove;
3427 ef->block.it = words;
3428 ef->block.end = wi.end;
3429 ef->block.result = NULL;
3432 ef->invoke.eop = EOP_INVOKE_LOOP;
3433 ef->invoke.state = 3;
3434 ef->invoke.origStack = origStack;
3435 ef->invoke.userBuf = si.
it;
3438 ef->invoke.func = loop_removeEach;
3439 ef->invoke.dat.catchf = NULL;
3443 ef->invoke.func = loop_foreach;
3444 ef->invoke.dat.catchf = catch_breakContinue;
3446 ef->invoke.result = sarg;
3448 return CFUNC_REFRAMED;
3479 if (
ur_type(sarg) != invoke->userBuf)
3486 EvalFrame* ef = boron_pushEvalFrame(ut);
3487 ef->block = ef[-2].block;
3488 return CFUNC_REFRAMED;
3504 if( ! ur_isSeriesType( type ) )
3506 if( type == UT_NONE )
3515 if (si.
it == si.
end)
3518 ef = boron_reuseFrame(ut, 2, &origStack);
3521 boron_initEvalBlock(ef, ut, a1[1].series.buf, res);
3524 ef->invoke.eop = EOP_INVOKE_LOOP;
3525 ef->invoke.state = 2;
3526 ef->invoke.origStack = origStack;
3527 ef->invoke.userBuf = type;
3528 ef->invoke.func = loop_forall;
3529 ef->invoke.dat.catchf = catch_breakContinue;
3530 ef->invoke.result = a1;
3533 ef->block = ef[-2].block;
3534 return CFUNC_REFRAMED;
3552 const UCell* cell = ur_exception(ut);
3553 if (ur_is(cell, UT_WORD)) {
3554 if (ur_atom(cell) == UR_ATOM_BREAK)
3556 *(ef[-1].block.result) = *ef->invoke.result;
3559 if (ur_atom(cell) == UR_ATOM_CONTINUE)
3560 return boron_resetEvalFrame(ut, ef + 1);
3567 EvalFrame* dof = ((EvalFrame*) invoke) - 1;
3568 UCell* sarg = invoke->result;
3573 si.
end = _sliceEnd(si.
buf, sarg);
3576 if (invoke->dat.catchf)
3577 dt->
poke((
UBuffer*) si.
buf, invoke->userBuf++, dof->block.result);
3579 invoke->dat.catchf = catch_map;
3581 if (invoke->userBuf < si.
end)
3588 dt->
pick(si.
buf, invoke->userBuf, cell);
3590 ef = boron_pushEvalFrame(ut);
3591 ef->block = dof->block;
3592 return CFUNC_REFRAMED;
3595 *dof->block.result = *sarg;
3607 if( ! ur_isSeriesType(
ur_type(sarg) ) )
3610 return errorType(
"map cannot modify shared series" );
3614 ef = boron_reuseFrame(ut, 1, &origStack);
3617 boron_initEvalBlock(ef, ut, a1[2].series.buf, res);
3620 ef->invoke.eop = EOP_INVOKE_LOOP;
3621 ef->invoke.state = 2;
3622 ef->invoke.origStack = origStack;
3623 ef->invoke.userBuf = si.
it;
3624 ef->invoke.func = _mapLoop;
3625 ef->invoke.dat.catchf = NULL;
3626 ef->invoke.result = sarg;
3628 return CFUNC_REFRAMED;
3643 UCell* res = ef->result;
3645 if (ef->state == DO_BLOCK1_COMPLETE)
3652 return boron_breakDoBlock1(ut, ef);
3659 return boron_reframeDoBlock1(ut, a1->
series.
buf, eval_all, res);
3674 UCell* res = ef->result;
3676 if (ef->state == DO_BLOCK1_COMPLETE)
3683 return boron_breakDoBlock1(ut, ef);
3690 return boron_reframeDoBlock1(ut, a1->
series.
buf, eval_any, res);
3707#define OPT_MOLD_CONTENTS 0x01
3711 if( ur_isStringType(
ur_type(a1) ) )
3715 len = str->
used + 2;
3719 enc = UR_ENC_LATIN1;
3724 buf->
flags |= UR_STRING_ENC_UP;
3726 buf->
flags &= ~UR_STRING_ENC_UP;
3733#define stdout stderr
3741static void _printValue(
UThread* ut,
const UCell* a1,
int flags)
3746 if (flags & PrintAsText)
3751 fputs( str.
ptr.
c, stdout );
3754 if (flags & PrintNewline)
3756 putc(
'\n', stdout );
3778 _printValue(ut, a1, PrintNewline);
3787 ur_initSeries(&tmp, UT_BLOCK, ef->userBuf);
3789 _printValue(ut, &tmp, PrintAsText | ef->state);
3806 if (ur_is(a1, UT_BLOCK))
3808 EvalFrame* ef = boron_reframeReduce(ut, a1, res, _printReduced);
3809 ef->invoke.state = 0;
3810 return CFUNC_REFRAMED;
3813 _printValue(ut, a1, PrintAsText);
3830 if (ur_is(a1, UT_BLOCK))
3832 EvalFrame* ef = boron_reframeReduce(ut, a1, res, _printReduced);
3833 ef->invoke.state = PrintNewline;
3834 return CFUNC_REFRAMED;
3837 _printValue(ut, a1, PrintAsText | PrintNewline);
3861 int enc = UR_ENC_LATIN1;
3864 if( ur_isStringType(
ur_type(a1) ) )
3875void ur_setCellI64(
UCell* cell, int64_t n )
3916 static const uint8_t _infoMask[3] =
3918 FI_Type, FI_Type, FI_Size | FI_Time | FI_Type
3920 static const char* _infoType[5] =
3922 "file",
"link",
"dir",
"socket",
"other"
3926 int func = ur_int(a2);
3929 assert( func >= 0 && func <= 2 );
3930 ok = ur_fileInfo(
boron_cpath(ut, a1, 0), &info, _infoMask[ func ] );
3936 ur_logic(res) = ok ? 1 : 0;
3942 ok = (info.type == FI_Dir);
3950 const char* tn = _infoType[ info.type ];
3957 ur_setWordUnbound( cell,
ur_intern( ut, tn, strLen(tn) ) );
3960 ur_setCellI64( cell, info.size );
3964 ur_double(cell) = info.modified;
3969 ur_initCoord(cell, 4);
3970 memCpy( cell->
coord.
n, info.perm,
sizeof(int16_t) * 4 );
3980extern int ur_makeDir(
UThread* ut,
const char* path );
3982static int _makeDirParents(
UThread* ut,
char* path,
char* end )
3984#define MAX_PATH_PARTS 16
3986 uint16_t index[ MAX_PATH_PARTS ];
3987 char* it = path + 1;
3993 if( (*it ==
'/' || *it ==
'\\') && (it[-1] !=
':') )
3996 if( parts >= MAX_PATH_PARTS )
3998 index[ parts++ ] = it - path;
4003 while( (i < parts) && ur_fileInfo( path, &info, FI_Type ) )
4004 path[ index[ i++ ] ] =
'/';
4008 if( ! ur_makeDir( ut, path ) )
4010 path[ index[ i++ ] ] =
'/';
4027CFUNC(cfunc_make_dir)
4029#define OPT_MAKE_DIR_ALL 0x01
4038 if( ! _makeDirParents( ut, path, path + bin->
used ) )
4041 if( ! ur_makeDir( ut, path ) )
4058CFUNC(cfunc_change_dir)
4077CFUNC(cfunc_current_dir)
4080#define getcwd _getcwd
4081#define DIR_SLASH '\\'
4083#define DIR_SLASH '/'
4090 if( getcwd( str->
ptr.
c, 512 ) )
4093 if( str->
ptr.
c[ str->
used - 1 ] != DIR_SLASH )
4095 str->
ptr.
c[ str->
used ] = DIR_SLASH;
4119 const char* cp = getenv(
boron_cstr(ut, a1, 0) );
4123 int len = strLen(cp);
4126 memCpy( str->
ptr.
c, cp, len );
4149#define setenv(name,val,over) SetEnvironmentVariable(name, val)
4150#define unsetenv(name) SetEnvironmentVariable(name, 0)
4154 if( ur_is(a1, UT_NONE) )
4163 setenv( name, str->
ptr.
c, 1 );
4189 if( ur_is(a1, UT_FILE) )
4190 return port_file.open( ut, &port_file, a1,
CFUNC_OPTIONS, res );
4206 if( ! ur_is(a1, UT_PORT) )
4210 DT( UT_PORT )->destroy( buf );
4217#define OPT_READ_TEXT 0x01
4218#define OPT_READ_INTO 0x02
4219#define OPT_READ_APPEND 0x04
4220#define OPT_READ_PART 0x08
4229static int _readBuffer(
UThread* ut, uint32_t opt,
const UCell* a1,
4230 UCell* res,
int len )
4234 if( opt & OPT_READ_PART )
4236 n = ur_int(CFUNC_OPT_ARG(4));
4237 len = (n > 1) ? n : 0;
4240 if( opt & (OPT_READ_INTO | OPT_READ_APPEND) )
4247 ic = CFUNC_OPT_ARG( (opt & OPT_READ_APPEND ? 3 : 2) );
4250 if( type == UT_BINARY || type == UT_STRING )
4255 if( opt & OPT_READ_INTO )
4257 rlen = len + buf->
used;
4262 if( type == UT_STRING )
4264 if( ur_strIsUcs2( buf ) )
4266 errorType(
"cannot read /into UCS2 string!" );
4280 if( ! (opt & OPT_READ_PART) )
4283 if( opt & OPT_READ_APPEND )
4291 errorType(
"read /into expected binary!/string! buffer" );
4295 else if( opt & OPT_READ_TEXT )
4307CFUNC_PUB(cfunc_readPort)
4309 PORT_SITE(dev, pbuf, a1);
4313 return errorScript(
"cannot read from closed port" );
4315 len = dev->defaultReadLen;
4324 return dev->read( ut, pbuf, res, len );
4328extern int ur_readDir(
UThread*,
const char* filename,
UCell* res );
4361 const char* filename;
4367 if( ur_is(a1, UT_PORT) )
4368 return cfunc_readPort( ut, a1, res );
4370 if( ! ur_isStringType(
ur_type(a1) ) )
4371 return errorType(
"read expected file!/string!/port! source" );
4375 if( ! ur_fileInfo( filename, &info, FI_Size | FI_Type ) )
4377 "could not access file %s", filename );
4379 if( info.type == FI_Dir )
4380 return ur_readDir( ut, filename, res );
4383 len = _readBuffer( ut, opt, a1, res, (
int) info.size );
4392 if( ur_is(res, UT_STRING) || (opt & OPT_READ_TEXT) )
4398 fp = fopen( filename, mode );
4402 "could not open file %s", filename );
4405 n = fread( dest->
ptr.
b + dest->
used, 1, len, fp );
4409 if( dest->
type == UT_STRING )
4412 else if( ferror( fp ) )
4443#define OPT_WRITE_APPEND 0x01
4444#define OPT_WRITE_TEXT 0x02
4445 const UCell* data = a2;
4447 if( ur_is(a1, UT_PORT) )
4449 PORT_SITE(dev, pbuf, a1);
4451 return errorScript(
"cannot write to closed port" );
4452 return dev->write( ut, pbuf, data );
4455 if( ! ur_isStringType(
ur_type(a1) ) )
4456 return errorType(
"write expected file!/string!/port! dest" );
4458 if( ur_is(data, UT_CONTEXT) )
4461 ut->
types[ UT_CONTEXT ]->
toText( ut, data, str, 0 );
4465 if( ur_is(data, UT_BINARY) || ur_is(data, UT_STRING) )
4468 const char* filename;
4480 size = si.
end - si.
it;
4482 if( ur_is(data, UT_STRING) )
4484 if( ur_strIsUcs2(si.
buf) ||
4501 int append = n & OPT_WRITE_APPEND;
4502 if( n & OPT_WRITE_TEXT )
4503 mode = append ?
"a" :
"w";
4505 mode = append ?
"ab" :
"wb";
4508 fp = fopen( filename, mode );
4512 "could not open %s", filename );
4515 n = fwrite( si.
buf->
ptr.
b + si.
it, 1, size, fp );
4522 return errorType(
"write expected binary!/string!/context! data" );
4540 if( remove( fn ) != 0 )
4573 ok = ur_fileInfo( cp2, &info, FI_Type );
4574 if( ok && (info.type == FI_File) )
4576 if( remove( cp2 ) == -1 )
4581 ok = rename( cp1, cp2 );
4599CFUNC( cfunc_serialize )
4612CFUNC( cfunc_unserialize )
4620extern int ur_serializedHeader(
const uint8_t* data,
int len );
4633 if( ur_is(a1, UT_BINARY) )
4635 if( cfunc_unserialize( ut, a1, res ) )
4649 if( BENV->funcRead( ut, args + 1, res ) )
4655#if CONFIG_COMPRESS == 2
4667 if( cp[0] ==
'#' && cp[1] ==
'!' )
4669 cp = find_uint8_t( cp, cp + bin->
used,
'\n' );
4673 else if( ur_serializedHeader( cp, bin->
used ) )
4679#if CONFIG_COMPRESS == 2
4680 else if( bin->
used > (12 + 8) )
4682 const uint8_t* pat = (
const uint8_t*)
"BZh";
4683 cp = find_pattern_8( cp, cp + 12, pat, pat + 3 );
4684 if( cp && (cp[3] >=
'1') && (cp[3] <=
'9') )
4688 blkN = cfunc_decompress( ut, args, res );
4738 return cfunc_write( ut, args + 1, res );
4757 const UCell* delim = a2;
4762 if( ! ur_isSeriesType( type ) )
4765 dt = SERIES_DT( type );
4770 while( (n = dt->
find( ut, &si, delim, 0 )) >= 0 )
4772 if( keepEmpty || n > si.
it )
4783 if( si.
it >= si.
end && ! keepEmpty )
4803 EvalFrame* ef = boron_findEvalFrame(ut, EOP_RUN_RECURSE);
4805 return boron_evalBlock(ut, blkC->
series.
buf, ef->invoke.result);
4819#define OPT_PARSE_CASE 0x01
4838 parse_doBlock, opt & OPT_PARSE_CASE );
4846 BT->evalOp.used = callFrame;
4853 pos = (pos == si.end);
4861 pos = (pos >= si.buf->
used);
4865 ur_logic(res) = pos ? 1 : 0;
4881 ur_logic(res) =
ur_same( ut, a1, a2 ) ? 1 : 0;
4897 ur_logic(res) =
ur_equal( ut, a1, a2 ) ? 1 : 0;
4913 ur_logic(res) =
ur_equal( ut, a1, a2 ) ? 0 : 1;
4929 ur_logic(res) = (
ur_compare( ut, a1, a2 ) > 0) ? 1 : 0;
4945 ur_logic(res) = (
ur_compare( ut, a1, a2 ) < 0) ? 1 : 0;
4961 ur_logic(res) = (
ur_compare( ut, a1, a2 ) >= 0) ? 1 : 0;
4977 ur_logic(res) = (
ur_compare( ut, a1, a2 ) <= 0) ? 1 : 0;
4995 if( ur_is(a1, UT_INT) || ur_is(a1, UT_CHAR) )
4996 logic = ur_int(a1) ? 0 : 1;
4997 else if( ur_is(a1, UT_DOUBLE) )
4998 logic = ur_double(a1) ? 0 : 1;
5003 ur_logic(res) = logic;
5038#define OPT_SWAP_GROUP 0x01
5046 int group = ur_int(CFUNC_OPT_ARG(1));
5047 if( group < 2 || group > (si.end - si.it) )
5049 "swap group size (%d) is invalid", group );
5050 if( ur_is(a1, UT_BINARY) )
5052 uint8_t* bp = si.buf->
ptr.
b + si.it;
5054 for( ; si.it <= si.end; si.it += group, bp += group )
5055 reverse_uint8_t( bp, bp + group );
5060 if( (si.end - si.it) & 1 )
5062 if( ur_is(a1, UT_BINARY) )
5064 uint8_t* bp = si.buf->
ptr.
b + si.it;
5065 uint8_t* bend = si.buf->
ptr.
b + si.end;
5067 for( ; bp != bend; bp += 2 )
5079 for( ; cp != cend; cp += 2 )
5100CFUNC(cfunc_lowercase)
5102 if( ur_isStringType(
ur_type(a1) ) )
5111 else if( ur_is(a1, UT_CHAR) )
5128CFUNC(cfunc_uppercase)
5130 if( ur_isStringType(
ur_type(a1) ) )
5139 else if( ur_is(a1, UT_CHAR) )
5149#define TRIM_FUNC_HEAD trim_head_u16
5150#define TRIM_FUNC_TAIL trim_tail_u16
5151#define TRIM_FUNC_LINES trim_lines_u16
5152#define TRIM_FUNC_INDENT trim_indent_u16
5153#define TRIM_T uint16_t
5154#include "trim_string.c"
5156#define TRIM_FUNC_HEAD trim_head_char
5157#define TRIM_FUNC_TAIL trim_tail_char
5158#define TRIM_FUNC_LINES trim_lines_char
5159#define TRIM_FUNC_INDENT trim_indent_char
5161#include "trim_string.c"
5174#define OPT_TRIM_INDENT 0x01
5175#define OPT_TRIM_LINES 0x02
5187 if( opt & OPT_TRIM_INDENT )
5189 if( ur_strIsUcs2(si.buf) )
5191 uint16_t* ss = si.buf->
ptr.
u16;
5192 si.end -= trim_indent_u16( ss + si.it, ss + si.end );
5196 char* ss = si.buf->
ptr.
c;
5197 si.end -= trim_indent_char( ss + si.it, ss + si.end );
5200 else if( opt & OPT_TRIM_LINES )
5202 if( ur_strIsUcs2(si.buf) )
5204 uint16_t* ss = si.buf->
ptr.
u16;
5205 si.it += trim_head_u16 ( ss + si.it, ss + si.end );
5206 si.end -= trim_tail_u16 ( ss + si.it, ss + si.end );
5207 si.end -= trim_lines_u16( ss + si.it, ss + si.end );
5211 char* ss = si.buf->
ptr.
c;
5212 si.it += trim_head_char ( ss + si.it, ss + si.end );
5213 si.end -= trim_tail_char ( ss + si.it, ss + si.end );
5214 si.end -= trim_lines_char( ss + si.it, ss + si.end );
5219 if( ur_strIsUcs2(si.buf) )
5221 uint16_t* ss = si.buf->
ptr.
u16;
5222 si.it += trim_head_u16( ss + si.it, ss + si.end );
5223 si.end -= trim_tail_u16( ss + si.it, ss + si.end );
5227 char* ss = si.buf->
ptr.
c;
5228 si.it += trim_head_char( ss + si.it, ss + si.end );
5229 si.end -= trim_tail_char( ss + si.it, ss + si.end );
5234 if( si.end != origEnd )
5242 si.buf->
used = si.end;
5259CFUNC(cfunc_terminate)
5261#define OPT_TERMINATE_DIR 0x01
5263 const UCell* val = a2;
5266 if( ! ur_isSeriesType( type ) )
5270 if( si.it != si.end )
5272 SERIES_DT( type )->pick( si.buf, si.end - 1, res );
5277 if( ur_is(res, UT_CHAR) &&
5278 (ur_char(res) ==
'/' || ur_char(res) ==
'\\') )
5282 if( ! SERIES_DT( type )->append( ut, si.buf, val ) )
5290extern int64_t str_hexToInt64(
const uint8_t*,
const uint8_t*,
const uint8_t**);
5317 if( ur_strIsUcs2( si.
buf ) && ur_is(a1, UT_STRING) )
5320 n = str_hexToInt64( si.
buf->
ptr.
b + si.
it,
5322 ur_setCellI64( res, n );
5342 if( ur_is(a1, UT_INT) )
5362CFUNC(cfunc_mark_sol)
5364#define OPT_MARK_SOL_BLOCK 0x01
5365#define OPT_MARK_SOL_CLEAR 0x02
5371 if( ur_isBlockType( type ) && ! (opt & OPT_MARK_SOL_BLOCK) )
5376 if( bi.it == bi.end )
5380 if( opt & OPT_MARK_SOL_CLEAR )
5388extern double ur_now();
5398#define OPT_NOW_DATE 0x01
5402 if( opt & OPT_NOW_DATE )
5406 ur_double(res) = ur_now();
5411#include "cpuCounter.h"
5422#ifdef HAVE_CPU_COUNTER
5423#define CYCLES data.var.u64[0]
5424#define CYCLES_LOW data.var.u64[1]
5426static UStatus loop_cpuCycles(
UThread* ut, EvalFrameInvoke* invoke)
5428 EvalFrame* ef = ((EvalFrame*) invoke) - 1;
5431 ef->CYCLES = cpuCounter() - ef->CYCLES;
5432 if (ef->CYCLES < ef->CYCLES_LOW)
5433 ef->CYCLES_LOW = ef->CYCLES;
5435 if (--invoke->userBuf == 0)
5437 UCell* res = invoke->result;
5439 ur_int(res) = (int64_t) ef->CYCLES_LOW;
5446 ef->CYCLES = cpuCounter();
5448 ef = boron_pushEvalFrame(ut);
5449 ef->block = ef[-3].block;
5450 return CFUNC_REFRAMED;
5454CFUNC(cfunc_cpu_cycles)
5456#ifdef HAVE_CPU_COUNTER
5457 int loop = ur_int(a1);
5462 EvalFrame* ef = boron_reuseFrame(ut, 2, &origStack);
5465 boron_initEvalBlock(ef, ut, a2->series.buf, res);
5468 ef->data.eop = EOP_NOP;
5471 ef->CYCLES_LOW = ~0L;
5474 ef->invoke.eop = EOP_INVOKE_LOOP;
5475 ef->invoke.state = 3;
5476 ef->invoke.origStack = origStack;
5477 ef->invoke.userBuf = (loop < 1) ? 1 : loop;
5478 ef->invoke.func = loop_cpuCycles;
5479 ef->invoke.dat.catchf = catch_breakContinue;
5480 ef->invoke.result = res;
5481 return CFUNC_REFRAMED;
5486 "FIXME: cpu-cycles is not implemented on this system" );
5500CFUNC_PUB(cfunc_free)
5504 if( ! ur_isSeriesType( type ) && (type != UT_PORT) )
5508 DT( type )->destroy( buf );
5514#ifdef CONFIG_CHECKSUM
5515extern uint32_t ur_hash(
const uint8_t* str,
const uint8_t* end );
5529 if( ur_isStringType(hash) )
5533 if( ur_strIsUcs2( si.
buf ) )
5534 return errorType(
"FIXME: hash does not handle UCS2 strings" );
5537 else if( ur_isWordType(hash) )
5539 const uint8_t* str = (
const uint8_t*) ur_wordCStr(a1);
5540 hash = ur_hash( str, str + strLen((
const char*) str) );
5571CFUNC(cfunc_datatypeQ)
5575 if(
ur_type(a1) == ur_int(a2) )
5599 return DT( ur_int(a2) )->convert( ut, a1, res );
5617#define OPT_COLLECT_UNIQUE 0x01
5618#define OPT_COLLECT_INTO 0x02
5622 if( opt & OPT_COLLECT_INTO )
5624 const UCell* into = CFUNC_OPT_ARG(2);
5635 opt & OPT_COLLECT_UNIQUE );
int boron_reframeDoBlock(UThread *, UIndex blkN, UCell *res, int flags)
Reuse the current CFUNC call frame for a EOP_DO_BLOCK operation.
Definition eval.c:964
#define CFUNC(name)
Macro to define C functions.
Definition boron.h:57
void boron_bindDefault(UThread *, UIndex blkN)
Bind block in thread dataStore to default contexts.
Definition eval.c:2042
UStatus boron_badArg(UThread *, UIndex atom, int argN)
Throw a standardized error for an unexpected function argument.
Definition eval.c:696
#define CFUNC_OPTIONS
Macro to get uint16_t option flags from inside a C function.
Definition boron.h:59
UIndex boron_evalRecurse(UThread *, UCell *res)
Begin a section where boron_evalBlock() can be recursively called.
Definition eval.c:762
UStatus boron_throwWord(UThread *, UAtom atom, UIndex stackPos)
Throw named exception.
Definition boron.c:308
char * boron_cstr(UThread *, const UCell *strC, UBuffer *bin)
Make null terminated UTF-8 string in binary buffer.
Definition boron.c:244
UStatus boron_requestAccess(UThread *, const char *msg,...)
Request user permission to access a resource.
Definition boron.c:988
char * boron_cpath(UThread *, const UCell *strC, UBuffer *bin)
Make null terminated UTF-8 string in binary buffer.
Definition boron.c:260
UStatus ur_binSliceM(UThread *, UBinaryIterM *, const UCell *cell)
Set UBinaryIterM to binary slice.
Definition binary.c:456
UBuffer * ur_makeBinaryCell(UThread *, int size, UCell *cell)
Generate a single binary and set cell to reference it.
Definition binary.c:74
void ur_binReserve(UBuffer *, int size)
Allocates enough memory to hold size bytes.
Definition binary.c:138
void ur_binSlice(UThread *, UBinaryIter *, const UCell *cell)
Set UBinaryIter to binary slice.
Definition binary.c:423
UIndex ur_makeBinary(UThread *, int size)
Generate and initialize a single binary buffer.
Definition binary.c:56
UIndex ur_blkClone(UThread *, UIndex blkN)
Make deep copy of block.
Definition block.c:256
void ur_blkInsert(UBuffer *, UIndex it, const UCell *cells, int count)
Insert cells into block.
Definition block.c:143
void ur_blkCollectType(UThread *, const UCell *blkCell, uint32_t typeMask, UBuffer *dest, int unique)
Find all values of a certain type and append them to another block.
Definition block.c:297
void ur_blkPush(UBuffer *, const UCell *cell)
Copy cell to end of block.
Definition block.c:153
UStatus ur_blkSliceM(UThread *, UBlockIterM *, const UCell *cell)
Set UBlockIterM to block slice.
Definition block.c:224
void ur_blkAppendCells(UBuffer *, const UCell *cells, int count)
Append cells to block.
Definition block.c:125
UBuffer * ur_makeBlockCell(UThread *, int type, int size, UCell *cell)
Generate a single block and set cell to reference it.
Definition block.c:76
void ur_infuse(UThread *, UCell *it, UCell *end, const UBuffer *ctx)
Replace words in cells with their values from a context.
Definition context.c:837
UBuffer * ur_ctxClone(UThread *, const UBuffer *src, UCell *cell)
Clone a new context and set cell to reference it.
Definition context.c:220
int ur_ctxAddWordI(UBuffer *, UAtom atom)
Add word to context if it does not already exist.
Definition context.c:420
int ur_ctxLookup(const UBuffer *, UAtom atom)
Find word in context by atom.
Definition context.c:579
void ur_bindCells(UThread *, UCell *it, UCell *end, const UBindTarget *bt)
Bind an array of cells to a target.
Definition context.c:614
void ur_ctxSetWords(UBuffer *, const UCell *it, const UCell *end)
Add the set-word! values in a series of cells to the words in a context.
Definition context.c:283
UBuffer * ur_ctxSort(UBuffer *)
Sort the internal context search table so ur_ctxLookup() is faster.
Definition context.c:510
UIndex ur_makeContext(UThread *, int size)
Generate and initialize a single context.
Definition context.c:93
void ur_unbindCells(UThread *, UCell *it, UCell *end, int deep)
Unbind all words in an array of cells.
Definition context.c:790
void ur_bind(UThread *, UBuffer *blk, const UBuffer *ctx, int bindType)
Bind block to context.
Definition context.c:690
const UBuffer * ur_sortedContext(UThread *, const UCell *)
Get context and make sure it is fully sorted for minimal ur_ctxLookup() time.
Definition context.c:547
UStatus ur_setPath(UThread *, const UCell *path, const UCell *src)
Set path.
Definition path.c:361
#define ur_strFree
A string is a simple array.
Definition urlan.h:629
UBuffer * ur_makeStringCell(UThread *, int enc, int size, UCell *cell)
Generate a single string and set cell to reference it.
Definition string.c:104
int ur_strIsAscii(const UBuffer *)
Test if all characters are ASCII.
Definition string.c:1066
void ur_strAppendChar(UBuffer *, int)
Append a single UCS2 character to a string.
Definition string.c:611
UIndex ur_makeString(UThread *, int enc, int size)
Generate and initialize a single string buffer.
Definition string.c:85
void ur_strTermNull(UBuffer *)
Terminate with null character so buffer can be used as a C string.
Definition string.c:1049
void ur_strInit(UBuffer *, int enc, int size)
Initialize buffer to type UT_STRING.
Definition string.c:430
void ur_strAppend(UBuffer *, const UBuffer *strB, UIndex itB, UIndex endB)
Append another string buffer to this string.
Definition string.c:899
void ur_strLowercase(UBuffer *str, UIndex start, UIndex send)
Convert characters of string slice to lowercase.
Definition string.c:1178
void ur_strFlatten(UBuffer *)
Convert a UTF-8 or UCS-2 string buffer to Latin-1 if possible.
Definition string.c:1104
void ur_strUppercase(UBuffer *str, UIndex start, UIndex send)
Convert characters of string slice to uppercase.
Definition string.c:1216
void ur_seriesSlice(const UThread *, USeriesIter *si, const UCell *cell)
Set USeriesIter to series slice.
Definition env.c:1338
#define ur_bufferSer(c)
Convenience macro for ur_bufferSeries().
Definition urlan.h:752
#define ur_setId(c, t)
Set type and initialize the other 24 bits of UCellId to zero.
Definition urlan.h:701
UIndex ur_tokenize(UThread *, const char *it, const char *end, UCell *res)
Convert a UTF-8 data string into a block.
Definition tokenize.c:1197
UIndex it
Start position.
Definition urlan.h:338
UStatus ur_error(UThread *, int errorType, const char *fmt,...)
Create error! exception.
Definition env.c:964
const UCell * ur_wordCell(UThread *, const UCell *cell)
Get word value for read-only operations.
Definition env.c:1132
UAtom ur_intern(UThread *, const char *name, int len)
Add a single atom to the shared environment.
Definition env.c:596
const UCell * end
End position.
Definition urlan.h:388
int ur_same(UThread *, const UCell *a, const UCell *b)
Definition env.c:1041
void ur_toText(UThread *, const UCell *cell, UBuffer *str)
Append textual representation of cell to a string.
Definition env.c:1118
UStatus ur_seriesSliceM(UThread *, USeriesIterM *si, const UCell *cell)
Set USeriesIterM to modifiable series slice.
Definition env.c:1356
UIndex end
End position.
Definition urlan.h:339
const UCell * it
Start position.
Definition urlan.h:387
@ UR_THROW
Returned to indicate an evaluation exception occured.
Definition urlan.h:117
@ UR_OK
Returned to indicate successful evaluation/operation.
Definition urlan.h:118
#define ur_foreach(bi)
Loop over all members of an iterator struct.
Definition urlan.h:760
#define ur_hold(n)
Convenience macro for ur_holdBuffer().
Definition urlan.h:748
UBuffer * ur_generate(UThread *, int count, UIndex *index, const uint8_t *)
Generate and initialize buffers of given types.
Definition env.c:771
int ur_true(const UCell *cell)
Check if a value is "true".
Definition env.c:1029
#define ur_release(h)
Convenience macro for ur_releaseBuffer().
Definition urlan.h:749
#define ur_bufferSerM(c)
Convenience macro for ur_bufferSeriesM().
Definition urlan.h:753
const UBuffer * ur_blockIt(const UThread *ut, UBlockIt *bi, const UCell *blkCell)
Set UBlockIt to the start and end of a block slice.
Definition env.c:1388
int ur_equal(UThread *, const UCell *a, const UCell *b)
Definition env.c:1053
const UBuffer * buf
Buffer pointer.
Definition urlan.h:337
#define ur_isShared(n)
True if buffer number refers to a buffer in the shared environment.
Definition urlan.h:726
#define ur_isSliced(c)
True if the end member of a series cell is set.
Definition urlan.h:727
#define ur_buffer(n)
Macro to get buffer known to be in thread dataStore.
Definition urlan.h:750
int ur_compare(UThread *, const UCell *a, const UCell *b)
Definition env.c:1079
#define ur_type(c)
Return UrlanDataType of cell.
Definition urlan.h:695
UCell * ur_wordCellM(UThread *, const UCell *cell)
Get modifiable word value.
Definition env.c:1178
void ur_toStr(UThread *, const UCell *cell, UBuffer *str, int depth)
Append data representation of cell to a string.
Definition env.c:1107
UStatus ur_parseString(UThread *ut, UBuffer *, UIndex start, UIndex end, UIndex *parsePos, const UBuffer *ruleBlk, UStatus(*eval)(UThread *, const UCell *), int)
Parse a string or binary using the parse language.
Definition parse_string.c:828
UStatus ur_parseBlock(UThread *ut, UBuffer *, UIndex start, UIndex end, UIndex *parsePos, const UBuffer *ruleBlk, UStatus(*eval)(UThread *, const UCell *))
Parse a block using the parse language.
Definition parse_block.c:609
Holds information for binding functions.
Definition urlan.h:402
const UBuffer * ctx
Context buffer to lookup words in.
Definition urlan.h:403
UIndex ctxN
Words in the block which are found in the UBindTarget::ctx will have their UCell.word....
Definition urlan.h:404
int bindType
Binding type to make.
Definition urlan.h:405
Iterator for const UCell array.
Definition urlan.h:386
The UBuffer struct holds information about a resource, usually a chunk of memory.
Definition urlan.h:266
uint8_t * b
bytes
Definition urlan.h:277
uint8_t form
This can indicate a specific form of the data (such as a string encoding).
Definition urlan.h:269
char * c
chars
Definition urlan.h:276
UIndex used
This typically holds the number of elements in the buffer.
Definition urlan.h:271
uint16_t * u16
uint16_t
Definition urlan.h:279
uint8_t type
UrlanDataType identifier.
Definition urlan.h:267
uint8_t flags
Indicates special features of the buffer (UR_STATIC, UR_STRING_ENC_UP).
Definition urlan.h:270
UCell * cell
Array of cells.
Definition urlan.h:275
union UBuffer::@312146223224040072236377336057316010374162171270 ptr
This typically holds a pointer to a chunk of memory.
int16_t n[UR_COORD_MAX]
Holds six, 16-bit integers.
Definition urlan.h:195
uint16_t len
Number of integers used in array n.
Definition urlan.h:194
uint32_t mask0
Low 32 bits of type mask.
Definition urlan.h:169
uint32_t mask1
Middle 32 bits of type mask.
Definition urlan.h:170
UIndex end
Slice end index.
Definition urlan.h:230
UIndex buf
Buffer id.
Definition urlan.h:228
UIndex it
Iterator index.
Definition urlan.h:229
float xyz[3]
The three float values.
Definition urlan.h:203
uint16_t index
Normally the word index into a context.
Definition urlan.h:218
UIndex ctx
Normally the buffer id of a context.
Definition urlan.h:217
void(* toText)(UThread *, const UCell *cell, UBuffer *str, int depth)
Convert cell to its string textual representation.
Definition urlan.h:450
Iterator for const series of any type.
Definition urlan.h:336
The USeriesType struct holds extra methods for series datatypes.
Definition urlan.h:469
int(* insert)(UThread *, UBuffer *buf, UIndex index, const UCell *val, UIndex part)
Insert a value into the series.
Definition urlan.h:474
int(* find)(UThread *, const USeriesIter *si, const UCell *val, int opt)
Search for a value in the series.
Definition urlan.h:480
void(* remove)(UThread *, USeriesIterM *si, UIndex part)
Remove part of the series.
Definition urlan.h:478
int(* append)(UThread *, UBuffer *buf, const UCell *val)
Append a value to the series.
Definition urlan.h:473
void(* poke)(UBuffer *buf, UIndex n, const UCell *val)
Replace a single value in the series.
Definition urlan.h:472
void(* pick)(const UBuffer *buf, UIndex n, UCell *res)
Get a single value from the series.
Definition urlan.h:471
The UThread struct stores the data specific to a thread of execution.
Definition urlan.h:309
const UDatatype ** types
Pointer to the datatypes.
Definition urlan.h:322
A cell holds a single value of a simple type or a reference (often to a UBuffer) for a complex type.
Definition urlan.h:248
UCellWord word
For word!, lit-word!, set-word!, get-word! types.
Definition urlan.h:251
UCellVec3 vec3
For vec3! type.
Definition urlan.h:254
UCellCoord coord
For coord! type.
Definition urlan.h:253
UCellSeries series
For binary!, bitset!, string!, file!, block!, paren!, path! types.
Definition urlan.h:255
UCellId id
Basic type identification.
Definition urlan.h:249
UCellSeries port
For port! type.
Definition urlan.h:257
UCellDatatype datatype
For datatype! type.
Definition urlan.h:250
UStatus ur_serialize(UThread *, UIndex blkN, UCell *res)
Serialize block.
Definition serialize.c:527
#define UR_FLAG_SOL
This UCellId::flags bit indicates that the cell starts a new line of code.
Definition urlan.h:82
#define ur_testAvail(buf)
Returns the capacity of a UBuffer.
Definition urlan.h:688
#define ur_avail(buf)
Returns the capacity of a UBuffer that is known to have been allocated.
Definition urlan.h:687
UStatus
Definition urlan.h:116
int ur_charUppercase(int c)
Convert UCS2 character to uppercase.
Definition ucs2_case.c:313
void ur_makeDatatype(UCell *cell, int type)
Initialize cell to be a UT_DATATYPE value of the given type.
Definition datatypes.c:389
#define ur_datatype(c)
Access the UrlanDataType that a UCellDatatype represents.
Definition urlan.h:711
int ur_charLowercase(int c)
Convert UCS2 character to lowercase.
Definition ucs2_case.c:293
@ UR_ERR_SCRIPT
General script evaluation error.
Definition urlan.h:126
@ UR_ERR_INTERNAL
Fatal internal problem.
Definition urlan.h:129
@ UR_ERR_ACCESS
Problem accessing external resources.
Definition urlan.h:128
@ UR_ERR_TYPE
Invalid argument/parameter datatype.
Definition urlan.h:125
UStatus ur_unserialize(UThread *, const uint8_t *start, const uint8_t *end, UCell *res)
Unserialize binary.
Definition serialize.c:1002
#define UR_FLAG_INT_HEX
This UCellId::flags bit indicates that an UR_INT value is printed as hexidecimal.
Definition urlan.h:80
@ UR_BIND_THREAD
Bound to buffer in thread dataStore.
Definition urlan.h:88
@ UR_BIND_SECURE
As UR_BIND_THREAD but unbind if not in context.
Definition urlan.h:92
@ UR_BIND_ENV
Bound to buffer in shared env dataStore.
Definition urlan.h:89
@ UR_BIND_SELF
Evaluate to bound context rather than value.
Definition urlan.h:91
@ UR_BIND_STACK
Bound to thread stack.
Definition urlan.h:90
int32_t UIndex
This is an index into an array.
Definition urlan.h:150
void ur_arrReserve(UBuffer *, int count)
Allocates enough memory to hold count elements.
Definition array.c:98
void ur_recycle(UThread *)
Perform garbage collection on thread dataStore.
Definition gc.c:156