Changeset 387
- Timestamp:
- 05/17/07 16:25:27 (17 months ago)
- Location:
- branches/thune/thread_safe
- Files:
-
- 26 modified
-
config.t (modified) (1 diff)
-
console.c (modified) (6 diffs)
-
context.c (modified) (15 diffs)
-
encoding.c (modified) (1 diff)
-
eval.c (modified) (49 diffs)
-
files.c (modified) (21 diffs)
-
gc.c (modified) (37 diffs)
-
internal.h (modified) (6 diffs)
-
list.c (modified) (1 diff)
-
list.h (modified) (1 diff)
-
make.c (modified) (55 diffs)
-
math.c (modified) (5 diffs)
-
parse.c (modified) (32 diffs)
-
print.c (modified) (23 diffs)
-
series.c (modified) (53 diffs)
-
stdio.c (modified) (4 diffs)
-
tests/working/closure.good (modified) (1 diff)
-
tests/working/closure.t (modified) (2 diffs)
-
thread.c (modified) (6 diffs)
-
thune.c (modified) (46 diffs)
-
tokenize.c (modified) (10 diffs)
-
unix/os.c (modified) (10 diffs)
-
unix/os.h (modified) (2 diffs)
-
urlan.c (modified) (27 diffs)
-
urlan.h (modified) (24 diffs)
-
win32/os.c (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
branches/thune/thread_safe/config.t
r350 r387 1 1 ; Thune Configuration 2 2 3 [ x] bzip2 "Include bzip2 compress/decompress calls"4 [ x] trig "Include trigonometric math calls"5 [ x] math3d "Include vector & matrix math calls"3 [ ] bzip2 "Include bzip2 compress/decompress calls" 4 [ ] trig "Include trigonometric math calls" 5 [ ] math3d "Include vector & matrix math calls" 6 6 enable trig 7 [ x] dt-code "Include 'code datatype"7 [ ] dt-code "Include 'code datatype" 8 8 9 [ x] net "UDP socket port"9 [ ] net "UDP socket port" 10 10 11 11 [ ] uds "Library with datatype & gc system only - no eval" -
branches/thune/thread_safe/console.c
r369 r387 21 21 #include <assert.h> 22 22 #include <stdio.h> 23 #include " urlan.h"23 #include "env.h" 24 24 25 25 … … 40 40 #else 41 41 42 #define APPNAME " Thune"42 #define APPNAME "Bloc3" 43 43 #define CUSTOM_DT 0 44 44 #define CUSTOM_DT_COUNT 0 … … 77 77 78 78 79 static void reportError( UThread* th)79 static void reportError( UThread* ut ) 80 80 { 81 81 UString* str; 82 82 #if 0 83 83 UCell* val; 84 val = ur_result( th, 0 );84 val = ur_result( ut, 0 ); 85 85 str = ur_binPtr( val->err.strN ); 86 86 … … 89 89 str->ptr.c ); 90 90 #else 91 str = ur_ binPtr( th->callTempBinN);91 str = ur_threadTmp( ut ); 92 92 str->used = 0; 93 ur_toStr( ur_result( th, 0), str, 0 );93 ur_toStr( ur_result(ut, 0), str, 0 ); 94 94 ur_termCStr( str ); 95 95 printf( str->ptr.c ); 96 96 #endif 97 97 98 //ur_threadReset( th);98 //ur_threadReset( ut ); 99 99 } 100 100 … … 132 132 } 133 133 #endif 134 135 ur_freezeEnv( env.threads, 128, 256 ); 134 136 135 137 if( argc > 1 ) … … 255 257 256 258 ur_arrayInit( &str, 1, 0 ); 257 ur_toStr (val, &str, 0 );259 ur_toStrT( env.threads, val, &str, 0 ); 258 260 if( str.ptr.c ) 259 261 { -
branches/thune/thread_safe/context.c
r323 r387 1 1 /*============================================================================ 2 2 Thune Interpreter 3 Copyright (C) 2005-200 6Karl Robillard3 Copyright (C) 2005-2007 Karl Robillard 4 4 5 5 This library is free software; you can redistribute it and/or … … 19 19 20 20 21 #include "os.h"22 #include "urlan.h"23 21 #include "internal.h" 24 22 … … 32 30 Appends atom name to string. 33 31 */ 34 void ur_atomStr( UAtom atom, UString* str ) 35 { 36 UBinary* names; 37 AtomRec* rec; 38 39 rec = ((AtomRec*) ur_env->atoms.ptr.v) + atom; 40 names = ur_binPtr( BIN_ATOM_NAMES ); 32 void ur_atomStrT( UThread* ut, UAtom atom, UString* str ) 33 { 34 AtomRec* rec = ((AtomRec*) ut->env->atoms.ptr.v) + atom; 41 35 42 36 ur_arrayReserve( str, sizeof(char), str->used + rec->nameLen ); 43 37 memCpy( str->ptr.c + str->used, 44 names->ptr.c + rec->nameIndex,38 ut->env->atomNames.ptr.c + rec->nameIndex, 45 39 rec->nameLen ); 46 40 str->used += rec->nameLen; … … 54 48 55 49 56 const char* ur_atomCStr( UAtom atom, int* plen ) 57 { 58 UBinary* names; 59 AtomRec* rec; 60 61 rec = ((AtomRec*) ur_env->atoms.ptr.v) + atom; 62 names = ur_binPtr( BIN_ATOM_NAMES ); 50 const char* ur_atomCStrT( UThread* ut, UAtom atom, int* plen ) 51 { 52 AtomRec* rec = ((AtomRec*) ut->env->atoms.ptr.v) + atom; 63 53 if( plen ) 64 54 *plen = rec->nameLen; 65 return names->ptr.c + rec->nameIndex;55 return ut->env->atomNames.ptr.c + rec->nameIndex; 66 56 } 67 57 … … 128 118 129 119 #ifdef DEBUG 130 void dumpAtoms() 131 { 132 UString* names; 133 AtomRec* table = (AtomRec*) ur_env->atoms.ptr.v; 120 void dumpAtoms( UThread* ut ) 121 { 122 LOCK_GLOBAL 123 { 124 const char* names = ut->env->atomNames.ptr.c; 125 AtomRec* table = (AtomRec*) ut->env->atoms.ptr.v; 134 126 AtomRec* it = table; 135 AtomRec* end = table + ur_env->atoms.used; 136 137 names = ur_binPtr( BIN_ATOM_NAMES ); 127 AtomRec* end = table + ut->env->atoms.used; 138 128 139 129 while( it != end ) … … 141 131 dprint( "%4ld %08x %5d %5d %s\n", it - table, it->hash, 142 132 it->head, it->chain, 143 names ->ptr.c+ it->nameIndex );133 names + it->nameIndex ); 144 134 ++it; 145 135 } 146 136 147 end = table + u r_env->atoms.avail;137 end = table + ut->env->atoms.avail; 148 138 while( it != end ) 149 139 { … … 152 142 ++it; 153 143 } 144 } 145 UNLOCK_GLOBAL 154 146 } 155 147 #endif … … 159 151 Add atom to environment. 160 152 153 If the environment has multiple threads, the caller must have called 154 LOCK_GLOBAL. 155 161 156 \param str Name of atom. 162 157 \param len Number of characters. … … 164 159 \returns Atom 165 160 */ 166 UAtom ur_intern ( UrlanEnv* env, const char* str, int len )161 UAtom ur_internT( UThread* ut, const char* str, int len ) 167 162 { 168 163 char* cp; … … 182 177 // Check if atom already exists. 183 178 184 atoms = & env->atoms;179 atoms = &ut->env->atoms; 185 180 table = (AtomRec*) atoms->ptr.v; 186 names = ur_binPtr( BIN_ATOM_NAMES );181 names = &ut->env->atomNames; 187 182 188 183 hash = ur_hash( str, str + len ); … … 233 228 // Nope, add new atom. 234 229 230 /* TODO: Make atoms & atomNames thread safe through one of the following: 231 232 1. Halt all other threads. 233 2. Fix size of atom arrays and throw error/assert when full. 234 3. Use LOCK_GLOBAL in or around these functions in addition to ur_intern: 235 ur_atomStrT() 236 ur_atomCStrT() 237 dumpAtoms() 238 */ 239 235 240 if( atoms->used == atoms->avail ) 236 241 { … … 275 280 \returns Index of word in context. 276 281 */ 277 int ur_internWord (const UContext* ctx, UAtom atom )282 int ur_internWordT( UThread* ut, const UContext* ctx, UAtom atom ) 278 283 { 279 284 int wrdN; … … 421 426 \returns Word index or -1 if not found. 422 427 */ 423 int ur_lookup (const UContext* ctx, UAtom atom )428 int ur_lookupT( UThread* ut, const UContext* ctx, UAtom atom ) 424 429 { 425 430 UBlock* wblk; … … 454 459 // Atom remains the same. 455 460 456 #define _bindWord( val) \457 wrdN = ur_lookup( ctx, val->word.atom ); \461 #define _bindWord(cell) \ 462 wrdN = ur_lookup( ctx, cell->word.atom ); \ 458 463 if( wrdN > -1 ) { \ 459 val->word.wordBlk = ctx->ctx.wordBlk; \ 460 val->word.valBlk = ctx->ctx.valBlk; \ 461 val->word.index = wrdN; } 462 463 464 UBlock* ur_bind( UIndex blkN, UContext* ctx ) 464 if( ur_bindType(cell) != btype ) \ 465 ur_setBindType(cell,btype); \ 466 cell->word.wordBlk = ctx->ctx.wordBlk; \ 467 cell->word.valBlk = ctx->ctx.valBlk; \ 468 cell->word.index = wrdN; } 469 470 471 UBlock* ur_bindT( UThread* ut, UIndex blkN, const UContext* ctx, int btype ) 465 472 { 466 473 int wrdN; … … 469 476 UCell* end = it + blk->used; 470 477 478 if( ur_isGlobal(blkN) ) 479 return 0; // Cannot bind global blocks. 480 471 481 while( it != end ) 472 482 { 473 if( ur_isAWord(it) || 474 ur_is(it, UT_OPCODE) || 475 ur_is(it, UT_SELECT) || 476 ur_is(it, UT_SETSELECT) ) 477 { 478 _bindWord( it ); 479 } 480 else if( ur_is(it, UT_PATH) || ur_is(it, UT_SETPATH) ) 481 { 482 UCell* path1 = ur_blockPtr( it->series.n )->ptr.cells; 483 if( ur_isAWord(path1) ) 484 { 485 _bindWord( path1 ); 486 } 487 } 488 else if( ur_is(it, UT_BLOCK) || ur_is(it, UT_PAREN) ) 489 { 490 ur_bind( it->series.n, ctx ); 491 } 492 else if( ur_is(it, UT_FUNCTION) ) 493 { 494 ur_bind( it->func.bodyN, ctx ); 495 496 // NOTE: Will probably need to rebind to local func context in 497 // case ctx contains the same words. 498 //orBind( orBlockPtr( it->func.bodyBlk ), it->func.context ); 499 } 500 501 ++it; 502 } 503 504 return blk; 505 } 506 507 508 #ifndef UR_CONFIG_UDS 509 /** 510 ur_resolveArgPath is provided as a fast but still convenient method of 511 resolving paths from C code. 512 513 Pass a number of datatype/value argument pairs terminated by UT_NONE to 514 specify the path. A pair can be either UT_WORD,atom or UT_INT,int. 515 516 Returns zero if the path is not valid. 517 518 Using a string argument rather than a tag list would be more convenient 519 but not as quick. 520 */ 521 UCell* ur_resolveArgPath( int first_tag, ... ) 522 { 523 va_list args; 524 int tag; 525 int data; 526 UIndex wrd; 527 UBlock* blk; 528 UCell* val; 529 530 val = &ur_global; 531 532 va_start(args, first_tag); 533 tag = first_tag; 534 535 while( tag != UT_NONE ) 536 { 537 data = va_arg(args, int); 538 switch( tag ) 483 switch( ur_type(it) ) 539 484 { 540 485 case UT_WORD: 541 if( ur_is(val, UT_CONTEXT) ) 486 case UT_SETWORD: 487 case UT_GETWORD: 488 case UT_LITWORD: 489 case UT_SELECT: 490 case UT_SETSELECT: 491 case UT_OPCODE: 492 _bindWord( it ); 493 break; 494 495 case UT_PATH: 496 case UT_SETPATH: 497 { 498 UCell* path1 = ur_blockPtr( it->series.n )->ptr.cells; 499 if( ur_isAWord(path1) ) 542 500 { 543 wrd = ur_lookup( val, data ); 544 if( wrd < 0 ) 545 goto abort; 546 547 blk = ur_blockPtr( val->ctx.valBlk ); 548 val = blk->ptr.cells + wrd; 549 break; 501 _bindWord( path1 ); 550 502 } 551 goto abort; 552 553 case UT_INT: 554 if( ur_is(val, UT_BLOCK) ) 555 { 556 blk = ur_block(val); 557 val = blk->ptr.cells + data; 558 break; 559 } 560 // TODO: binary, string, etc 561 goto abort; 562 563 default: 564 goto abort; 503 } 504 break; 505 506 case UT_BLOCK: 507 case UT_PAREN: 508 ur_bindT( ut, it->series.n, ctx, btype ); 509 break; 510 511 case UT_FUNCTION: 512 ur_bindT( ut, it->func.bodyN, ctx, btype ); 513 514 // NOTE: Will probably need to rebind to local func context in 515 // case ctx contains the same words. 516 //orBind( orBlockPtr( it->func.bodyBlk ), it->func.context ); 517 break; 565 518 } 566 tag = va_arg(args, int); 567 } 568 569 done: 570 571 va_end(args); 572 return val; 573 574 abort: 575 576 val = 0; 577 goto done; 578 } 579 #endif 519 520 ++it; 521 } 522 523 return blk; 524 } 580 525 581 526 -
branches/thune/thread_safe/encoding.c
r274 r387 76 76 res = UR_TOS; 77 77 78 if( ur_isAWord(tos) && ur_stringSlice( res, &cpA, &cpB) )78 if( ur_isAWord(tos) && ur_stringSlice(ut, res, &cpA, &cpB) ) 79 79 { 80 80 count = cpB - cpA; -
branches/thune/thread_safe/eval.c
r385 r387 19 19 20 20 21 #include "os.h" 22 #include "urlan.h" 21 #include "internal.h" 23 22 #include "urlan_atoms.h" 24 #include "internal.h"25 23 #include "bignum.h" 26 24 27 25 26 extern UContext ur_global; 27 extern UContext ur_envGlobal; 28 28 29 extern void uc_console_out( UThread*, UCell* ); 29 30 30 31 31 32 #ifdef DEBUG 32 void ur_dumpBlock( U Index blkN )33 void ur_dumpBlock( UThread* ut, UIndex blkN ) 33 34 { 34 35 UCell* cell; … … 58 59 59 60 60 static void _infuseOpcodes( UThread* thr, UIndex blkN )61 static void _infuseOpcodes( UThread* ut, UIndex blkN ) 61 62 { 62 63 UBlock* blk; 63 U Block* gblk;64 UContext* global; 64 65 const UCell* ctx; 65 66 int wrdN; 66 67 67 blk = ur_bind( blkN, &ur_global ); 68 69 wrdN = ur_lookup( &ur_global, UR_ATOM_KERNEL_OPS ); 70 //assert( wrdN > -1 ); 71 if( wrdN > -1 ) 72 { 73 gblk = ur_blockPtr( GLOBAL_VAL_BLKN ); 74 ctx = gblk->ptr.cells + wrdN; 75 76 assert( ctx->id.type == UT_CONTEXT ); 77 78 ur_infuse( thr, blk, ctx ); 68 global = (ut->env->blocks.arr.used) ? &ur_envGlobal : &ur_global; 69 70 wrdN = ur_lookup( global, UR_ATOM_KERNEL_OPS ); 71 assert( wrdN > -1 ); 72 //if( wrdN > -1 ) 73 { 74 blk = ur_blockPtr( global->ctx.valBlk ); 75 ctx = blk->ptr.cells + wrdN; 76 77 assert( ur_is(ctx, UT_CONTEXT) ); 78 79 blk = ur_blockPtr( blkN ); 80 ur_infuse( ut, blk, ctx ); 79 81 } 80 82 } … … 86 88 returned. 87 89 */ 88 static int ur_itLen( U Cell* cell )90 static int ur_itLen( UThread* ut, UCell* cell ) 89 91 { 90 92 int len = ur_seriesLen( cell ); … … 101 103 Res may be the same as sel. 102 104 */ 103 int ur_getSelector( UThread* u r_thread, const UCell* sel, UCell* res )105 int ur_getSelector( UThread* ut, const UCell* sel, UCell* res ) 104 106 { 105 107 #define ATOM_OFF(val,atm) (((unsigned int) val) - atm) … … 107 109 UCell* val; 108 110 109 val = ur_wordCell( u r_thread, sel );111 val = ur_wordCell( ut, sel ); 110 112 if( ! val ) 111 113 return 0; … … 157 159 if( ur_type(val) >= UT_BI_COUNT ) 158 160 { 159 UDatatypeSelFunc func = u r_thread->env->customDT161 UDatatypeSelFunc func = ut->env->customDT 160 162 [ ur_type(val) - UT_BI_COUNT ].selectAtom; 161 163 if( func ) 162 return func( u r_thread, val, sel, res );164 return func( ut, val, sel, res ); 163 165 } 164 166 goto set_none; … … 167 169 else 168 170 { 169 if( ur_pick( val, ur_sel(sel) - 1, res ) )171 if( ur_pick( ut, val, ur_sel(sel) - 1, res ) ) 170 172 return 1; 171 173 } 172 174 173 ur_throwErr( ur_thread, UR_EX_SCRIPT, "Invalid select!" );175 ur_throwErr( UR_ERR_SCRIPT, "Invalid select!" ); 174 176 return 0; 175 177 … … 184 186 Returns non-zero if successful. 185 187 */ 186 int ur_setSelector( UThread* u r_thread, const UCell* sel, const UCell* nval )188 int ur_setSelector( UThread* ut, const UCell* sel, const UCell* nval ) 187 189 { 188 190 UBlock* blk; 189 191 UCell* val; 190 192 191 val = ur_wordCell( u r_thread, sel );193 val = ur_wordCell( ut, sel ); 192 194 if( ! val ) 193 195 return 0; … … 242 244 if( ! ur_selIsAtom(sel) ) 243 245 { 244 if( ur_poke( val, ur_sel(sel) - 1, nval ) )245 return 1; 246 } 247 break; 248 } 249 250 ur_throwErr( ur_thread, UR_EX_SCRIPT, "Invalid select!" );246 if( ur_poke( ut, val, ur_sel(sel) - 1, nval ) ) 247 return 1; 248 } 249 break; 250 } 251 252 ur_throwErr( UR_ERR_SCRIPT, "Invalid select!" ); 251 253 return 0; 252 254 } … … 283 285 { 284 286 UCell* val; 285 val = ur_wordCell( u r_thread, tos );287 val = ur_wordCell( ut, tos ); 286 288 if( val ) 287 289 { … … 317 319 318 320 319 static void _appendTraceBlk( U CellError* err, int n, int it )321 static void _appendTraceBlk( UThread* ut, UCellError* err, int n, int it ) 320 322 { 321 323 if( err->traceBlk ) … … 334 336 #define _throwUnbound(th,cell) _throwUnsetF(th,cell,"unbound") 335 337 336 static void _throwUnsetF( UThread* ur_thread, const UCell* wcell, 337 const char* umsg ) 338 static void _throwUnsetF( UThread* ut, const UCell* wcell, const char* umsg ) 338 339 { 339 340 UString* str; 340 str = ur_ binPtr( ur_thread->callTempBinN);341 str = ur_threadTmp( ut ); 341 342 str->used = 0; 342 343 ur_atomStr( ur_atom(wcell), str ); 343 344 ur_termCStr( str ); 344 ur_throwErr( ur_thread, UR_EX_SCRIPT, 345 "word '%s is %s", str->ptr.c, umsg ); 346 } 347 348 349 /* 345 ur_throwErr( UR_ERR_SCRIPT, "word '%s is %s", str->ptr.c, umsg ); 346 } 347 348 349 /** 350 350 Returns cell pointer or zero if word does not reference a valid cell. 351 351 */ 352 UCell* ur_wordCell( UThread* ur_thread, const UCell* pc ) 353 { 354 UCell* val; 355 int i; 356 357 i = pc->word.valBlk; 358 if( i < 0 ) 359 { 360 // Find function local frame i. 361 362 LocalFrame* it; 363 LocalFrame* end; 364 365 it = UR_LF_BEG; 366 end = UR_LF_END; 367 while( it != end ) 368 { 369 if( it->localFrame.n == i ) 370 { 371 val = it->localFrame.cell; 372 &nbs
