Esempio n. 1
0
static
void invalid_message_test2()
{
	test_for_error(nullptr, validate_m_message);
	test_for_error(unexpected_tag_modifier, unexpected_tag_validator);
	test_for_error(duplicate_tag_modifier, duplicate_tag_validator);
}
Esempio n. 2
0
void IrrealVM :: execute( uint64_t thread_id ){
	
	//if( global_vm_queue.size() < 1 ){ return; }
	
	pthread_mutex_lock( &global_vm_queue_lock );
	
	if( global_vm_queue.size() < 1 ){
		pthread_mutex_unlock( &global_vm_queue_lock );
		return; 
		}
	
	uint64_t ctx_id = global_vm_queue.front();
	global_vm_queue.pop_front();
	
	IrrealContext *ctx = global_contexts[ ctx_id ];
	
	pthread_mutex_unlock( &global_vm_queue_lock );
	
	test_for_error( ctx == NULL, "Invalid context!" );
	
	ctx->lock_context();
	
	global_running_threads_vm[ thread_id ] = ctx_id;
	
	//printf( "Executing vm #%lu\n", ctx_id );
	//_debug_running_threads();
	
	
	IrrealStack *current, *code;
	
	current = ctx->getCurrentStack();
	code = ctx->getCodeStack();
	
	test_for_error( current == NULL, "Invalid current stack!" );
	test_for_error( code == NULL, "Invalid code stack!" );
	
	uint8_t state = ctx->getState();
	
	switch( state ){
		case STATE_JOINING:
			if( !current->isJoined() ){
				
				pthread_mutex_lock( &global_vm_queue_lock );
				global_vm_queue.push_back( ctx_id ); 
				pthread_mutex_unlock( &global_vm_queue_lock );
	
				ctx->mark();
	
				ctx->unlock_context();
				return;
				}
		break;
		case STATE_SYNCING:
			
			test_for_error( current->peek() == NULL, "Not enough values to perform 'sync'!" );
			
			//printf( "syncing... ('%s')\n", current->peek()->getValue().c_str() );
			if( current->peek()->getState() == STATE_NOT_YET ){
				
				pthread_mutex_lock( &global_vm_queue_lock );
				global_vm_queue.push_back( ctx_id ); 
				pthread_mutex_unlock( &global_vm_queue_lock );
				
				ctx->mark();
				
				ctx->unlock_context();
				return;
				}
			//printf( "Data synced, now continuing... \n" );
		break;
		}
	
	std::string anon_name;
	bool anon_state = false;
	uint64_t begin_end_counter = 0;
	bool done = false;
	IrrealStack *anon_stack = NULL;
	
	long int debug_value;
	
	IrrealStack *debug_stack;
	
	debug_value = ctx->getStack("PARAMS")->size();
	debug_stack = ctx->getStack("PARAMS");
	while( !done ){
		ctx->mark();
		//printf( "\n\n" ); 
		IrrealValue *q = code->pop();
		//printf( "current: " ); current->_debug_print();
		//printf( "params: " ); ctx->getStack("PARAMS")->_debug_print();
		//printf( "out: " ); ctx->getStack("OUT")->_debug_print();
		if( q == NULL ){
			//printf( "q == NULL\n" );
			done = true; 
			if( ctx->getReturnValue() != NULL ){
				//printf( "Returning value! ('%s')\n", ctx->getReturnValue()->getValue().c_str() );
				ctx->getStack( ctx->getReturnValue()->getValue() )->merge( ctx->getStack( "OUT" ), false ); 
				
				ctx->getReturnValue()->setType( TYPE_SYMBOL );
				ctx->getReturnValue()->setState( STATE_OK );
				}
			
			pthread_mutex_lock( &global_running_vms_lock );
				--global_running_vms;
			pthread_mutex_unlock( &global_running_vms_lock );
			
			continue; 
			}
		if( q->getType() & TYPE_OPERATOR ){
			printf( "q = {'%s', %s} \n", q->getValue().c_str(), debug_cmd_names[ q->getType() & (~0x80 ) ].c_str() );
			}
		else{
			printf( "q = {'%s', %i} \n", q->getValue().c_str(), q->getType() );
			}
		if( anon_state ){
			if( q->getType() & TYPE_OPERATOR ){
				switch( q->getType() ){
					case CMD_BEGIN:
						++begin_end_counter;
					break;
					case CMD_END:
						--begin_end_counter;
					break;
					}
				anon_stack->push( q );
				if( begin_end_counter == 0 ){
					 test_for_error( anon_stack == NULL, "Stack error when parsing block!" );
					 anon_stack->pop();
					 
					 anon_state = false;
					 IrrealValue* value = new IrrealValue();
					 value->setType( TYPE_SYMBOL );
					 value->setValue( anon_name );
					 current->push( value );
					 //printf( "pushing to stack: '%s' \n", current->peek()->getValue().c_str() );
					 continue;
					 }
				}
			else{
				test_for_error( anon_stack == NULL, "Stack error when parsing block!" );
				anon_stack->push( q );
				}
			}
		else{
			
			if( q->getType() & TYPE_OPERATOR ){
				//printf( "Executing command: %s \n", debug_cmd_names[ q->getType() & (~0x80) ].c_str() );
				switch( q->getType() ){
					
					case CMD_BEGIN:
					{
						anon_name = ctx->spawnNewAnonymousStack();
						anon_stack = ctx->getStack( anon_name );
						test_for_error( anon_stack == NULL, "Unable to spawn new anonymous stack!" );
						
						begin_end_counter = 1;
						anon_state = true;
						
					}
					break;
					
					case CMD_PUSH:
					{
						IrrealValue *target_stack_name;
						IrrealValue *value;
						IrrealStack *target_stack;
						
						target_stack_name = current->pop();
						
						value = current->pop();
						
						test_for_error( target_stack_name == NULL, "Not enough values to perform 'push'!" );
						test_for_error( value == NULL, "Not enough values to perform 'push'!" );
						
						
						target_stack = ctx->getStack( target_stack_name->getValue() );
						
						test_for_error( target_stack == NULL, "PUSH: Stack not found!" );
						
						target_stack->push( value );
					}
					break;
					
					case CMD_POP:
					{	
						IrrealValue *target_stack_name;
						IrrealStack *target_stack, *testing;
						IrrealValue *value;
						
						target_stack_name = current->pop();
						
						test_for_error( target_stack_name == NULL, "Not enough values to perform 'pop'!" );
						
						target_stack = ctx->getStack( target_stack_name->getValue() );
						testing = ctx->getStack( target_stack_name->getValue() );
							
						test_for_error( target_stack == NULL, "POP: Stack not found!" );
						
						value = target_stack->pop();
						
						
						if( value == NULL ){
							printf( "\n\n**** Debug info***\n\n" );
							printf( "In PARAMS stack there were %li entries in the beginning...\n", debug_value ); 
							printf( "target_stack_name = '%s' \n", target_stack_name->getValue().c_str() );
							printf( "Context mark count: %lu \n", ctx->read_marks() );
							printf( "target_stack pop_counter = %lu \n", target_stack->_debug_get_counter() );
							printf( "target_stack = %p, target_stack->id = %lu \n", target_stack, target_stack->get_id() );
							printf( "debug_stack = %p, debug_stack->id = %lu \n", debug_stack, debug_stack->get_id() );
							printf( "testing: %p, testing->id = %lu\n", testing, testing->get_id() );
							printf( "debug_stack->size = %lu, target_stack->size = %lu, testing->size = %lu \n", debug_stack->size(), target_stack->size(), testing->size() );
							value = testing->pop();
							printf( "testing->pop = %p, value->getValue = %s\n", value, value->getValue().c_str() ); 
							printf( "\n" );
							fflush( stdout );
							value = NULL;
							}
						test_for_error( value == NULL, "POP: Target stack empty!" );
						
						current->push( value );
					}
					break;
					
					case CMD_DEF:
					{	
						IrrealValue *target_name;
						IrrealValue *value;
						
						target_name = current->pop();
						value = current->pop();
						
						test_for_error( target_name == NULL, "Not enough values to perform 'def'!" );
						test_for_error( value == NULL, "No enough values to perform 'def'!" );
						
						ctx->spawnNewStack( target_name->getValue() );
						
						switch( value->getType() ){
							case TYPE_SYMBOL:
							{
								IrrealStack *target_stack = ctx->getStack( target_name->getValue() );
								IrrealStack *source_stack = ctx->getStack( value->getValue() );
								
								test_for_error( target_stack == NULL, "DEF: Target stack not found!" );
								test_for_error( source_stack == NULL, "DEF: Source stack not found!" );
								
								
								IrrealValue *tmp = source_stack->pop();
								
								
								while( tmp != NULL ){
									target_stack->push( tmp );
									tmp = source_stack->pop();
									}
							}
							break;
							default:
							{
								IrrealStack *target_stack = ctx->getStack( target_name->getValue() );
								test_for_error( target_stack == NULL, "DEF: Target stack not found!" );
								target_stack->push( value );
							}	
							break;
							}
					}	
					break;
					
					case CMD_MERGE:
					{
						IrrealValue *target_name;
						IrrealStack *target_stack;
						
						target_name = current->pop();
						test_for_error( target_name == NULL, "Not enough values to perform 'merge'!" );
						
						target_stack = ctx->getStack( target_name->getValue() );
						
						test_for_error( target_stack == NULL, "MERGE: Stack not found!" );
						
						current->merge( target_stack, false );
					}	
					break;
					
					case CMD_CALL:
					{
						IrrealValue *func, *nparams, *return_value;
						
						nparams = current->pop();
						func = current->pop();
						
						test_for_error( nparams == NULL, "Not enough values to perform 'call'!" );
						test_for_error( func == NULL, "Not enough values to perform 'call'!" );
						
						
						IrrealContext *new_ctx = new IrrealContext();
						
						new_ctx->lock_context();
						
						return_value = new IrrealValue();
						return_value->setType( TYPE_SENTINEL );
						return_value->setState( STATE_NOT_YET );
						return_value->setValue( ctx->spawnNewAnonymousStack() );
						
						//printf( "current->peek() = '%s' \n", current->peek()->getValue().c_str() );
						
						new_ctx->setReturnValue( return_value );
						
						IrrealStack *func_stack = ctx->getStack( func->getValue() );
						
						test_for_error( func_stack == NULL, "CALL: Function not found!" );
						
						new_ctx->getCodeStack()->nondestructive_merge( func_stack, true );
						
						size_t N = string_to_integer( nparams->getValue() );
						
						//printf( "nparams: %lu \n", N );
						
						IrrealStack *params = new_ctx->getStack( "PARAMS" );
						for( size_t i = 0 ; i < N ; ++i ){
							IrrealValue *p = current->pop();
							test_for_error( p == NULL, "Not enough values to perform 'call'!" );
							if( p->getType() == TYPE_SYMBOL ){
								std::string stack_name = ctx->spawnNewAnonymousStack();
								IrrealStack *pstack = ctx->getStack( stack_name );
								IrrealStack *target_stack = ctx->getStack( p->getValue() );
								
								test_for_error( pstack == NULL, "CALL: Unable to spawn new anonymous stack!" );
								test_for_error( target_stack == NULL, "CALL: Undefined symbol!" );
								
								pstack->nondestructive_merge( target_stack, false );
								params->push( new IrrealValue( TYPE_SYMBOL, STATE_OK, stack_name ) );
								}
							else{
								params->push( p );
								}
								
							}
						//printf( "Calling with params: "); params->_debug_print();
						
						//printf( "Merging scope...\n" );
						
						new_ctx->mergeScope( ctx->getScope() );
						
						new_ctx->unlock_context();
						
						pthread_mutex_lock( &global_vm_queue_lock );
						global_vm_queue.push_front( new_ctx->get_id() );
						pthread_mutex_unlock( &global_vm_queue_lock );
						
						pthread_mutex_lock( &global_running_vms_lock );
							++global_running_vms;
						pthread_mutex_unlock( &global_running_vms_lock );
						
						
						current->push( return_value );
						//printf( "current->peek() = '%s' \n", current->peek()->getValue().c_str() );
						
					}
					break;
					
					case CMD_JOIN:
						ctx->setState( STATE_JOINING );
						done = true;
						pthread_mutex_lock( &global_vm_queue_lock );
						global_vm_queue.push_back( ctx->get_id() );
						pthread_mutex_unlock( &global_vm_queue_lock );
						
					break;
					
					case CMD_ADD:
					{
						IrrealValue *first, *second, *value;
						first = current->pop();
						second = current->pop();
						
						test_for_error( first == NULL, "Not enough values to perform 'add'!" );
						test_for_error( second == NULL, "Not enough values to perform 'add'!" );
						
						
						value = new IrrealValue();
						value->setType( TYPE_INTEGER );
						value->setValue( integer_to_string( string_to_integer( first->getValue() ) + string_to_integer( second->getValue() ) ) );
						
						current->push( value );
					}
					break;
					
					case CMD_PRINT:
					{
						IrrealValue *value;
						value = current->pop();
						test_for_error( value == NULL, "Not enough values to perform 'print'!" );
						printf( "print: type = %i, state = %i, value = '%s' \n", value->getType(), value->getState(), value->getValue().c_str() );
						
					}
					break;
					
					case CMD_SYNC:
						ctx->setState( STATE_SYNCING );
						done = true;
						pthread_mutex_lock( &global_vm_queue_lock );
						global_vm_queue.push_back( ctx->get_id() );
						pthread_mutex_unlock( &global_vm_queue_lock );
					break;
					
					case CMD_DUP:
					{
						IrrealValue *value, *new_value;
						value = current->pop();
						test_for_error( value == NULL, "Not enough values to perform 'dup'!" );
						new_value = new IrrealValue( value->getType(), value->getState(), value->getValue() );
					
						current->push( value );
						current->push( new_value );
					}
					break;

					case CMD_WHILE:
					{
						IrrealValue *test, *body;
						
						
/*
{...} {some tests} while

some tests
{ ... 
* {...} {some tests} while 
} {} if

*/
						test = current->pop();
						body = current->pop();
						
						test_for_error( test == NULL, "Not enough values to perform 'while'!" );
						test_for_error( body == NULL, "Not enough values to perform 'while'!" );
						
						
						IrrealStack *new_code = new IrrealStack();
						IrrealStack *test_stack = ctx->getStack( test->getValue() );
						IrrealStack *body_stack = ctx->getStack( body->getValue() );
						
						test_for_error( test_stack == NULL, "Invalid test stack for 'while'!" );
						test_for_error( body_stack == NULL, "Invalid body stack for 'while'!" );
						
						new_code->nondestructive_merge( test_stack, true );
						 						
						new_code->push( new IrrealValue( CMD_BEGIN, STATE_OK, "" ) );
						new_code->nondestructive_merge( body_stack, true );
						new_code->push( body );
						new_code->push( test );
						new_code->push( new IrrealValue( CMD_WHILE, STATE_OK, "" ) );
						new_code->push( new IrrealValue( CMD_END, STATE_OK, "" ) );
						new_code->push( new IrrealValue( CMD_BEGIN, STATE_OK, "" ) );
						new_code->push( new IrrealValue( CMD_END, STATE_OK, "" ) );
						new_code->push( new IrrealValue( CMD_IF, STATE_OK, "" ) );
						
						
						
						//printf( "while: new_code: " ); new_code->_debug_print();
						
						code->merge( new_code, false );
						
						delete new_code;
					}
					break;
					
					case CMD_IF:
					{
						IrrealValue *test, *block_true, *block_false;
							
						block_false = current->pop();
						block_true = current->pop();
						test = current->pop();
						
						test_for_error( block_false ==  NULL, "Not enough values to perform 'if'!" );
						test_for_error( block_true ==  NULL, "Not enough values to perform 'if'!" );
						test_for_error( test ==  NULL, "Not enough values to perform 'if'!" );
						
						
						IrrealStack *stack_true, *stack_false;
						
						stack_true = ctx->getStack( block_true->getValue() );
						stack_false = ctx->getStack( block_false->getValue() );
						
						test_for_error( stack_true == NULL, "IF: Stack (true) not found!" );
						test_for_error( stack_false == NULL, "IF: Stack (false) not found!" );
						
						
						//printf( "if: stack_true: " ); stack_true->_debug_print();
						//printf( "if: stack_false: " ); stack_false->_debug_print();
						
						//if( test == NULL ){ printf( "if: test: null!\n" ); } 
						//printf( "if: test value: %li \n", string_to_integer( test->getValue() ) );
						
						if( string_to_integer( test->getValue() ) ){
							
							code->nondestructive_merge( stack_true, false );
							}
						else{
							code->nondestructive_merge( stack_false, false );
							}
						
					}
					break;
					
					case CMD_SUB:
					{
						IrrealValue *first, *second, *value;
						second = current->pop();
						first = current->pop();
						
						test_for_error( first == NULL, "Not enough values to perform 'sub'!" );
						test_for_error( second == NULL, "Not enough values to perform 'sub'!" );
						
						
						value = new IrrealValue();
						value->setType( TYPE_INTEGER );
						value->setValue( integer_to_string( string_to_integer( first->getValue() ) - string_to_integer( second->getValue() ) ) );
						
						current->push( value );
					}
					break;

					case CMD_MUL:
					{
						IrrealValue *first, *second, *value;
						first = current->pop();
						second = current->pop();
						
						test_for_error( first == NULL, "Not enough values to perform 'mul'!" );
						test_for_error( second == NULL, "Not enough values to perform 'mul'!" );
						
						
						value = new IrrealValue();
						value->setType( TYPE_INTEGER );
						value->setValue( integer_to_string( string_to_integer( first->getValue() ) * string_to_integer( second->getValue() ) ) );
						
						current->push( value );
					}
					break;

					case CMD_DIV:
					{
						IrrealValue *first, *second, *value;
						second = current->pop();
						first = current->pop();
						
						test_for_error( first == NULL, "Not enough values to perform 'div'!" );
						test_for_error( second == NULL, "Not enough values to perform 'div'!" );
						
						
						value = new IrrealValue();
						value->setType( TYPE_INTEGER );
						value->setValue( integer_to_string( string_to_integer( first->getValue() ) / string_to_integer( second->getValue() ) ) );
						
						current->push( value );
					}
					break;

					case CMD_MOD:
					{
						IrrealValue *first, *second, *value;
						second = current->pop();
						first = current->pop();
						
						test_for_error( first == NULL, "Not enough values to perform 'mod'!" );
						test_for_error( second == NULL, "Not enough values to perform 'mod'!" );
						
						value = new IrrealValue();
						value->setType( TYPE_INTEGER );
						value->setValue( integer_to_string( string_to_integer( first->getValue() ) % string_to_integer( second->getValue() ) ) );
						
						current->push( value );
					}
					break;

					case CMD_LENGTH:
					{
						IrrealValue *value;
						value = current->pop();
						
						test_for_error( value == NULL, "Not enough values to perform 'length'!" );
						
						current->push( new IrrealValue( TYPE_INTEGER, STATE_OK, integer_to_string( ctx->getStack( value->getValue() )->size() ) ) );
					
					}
					break;
					
					case CMD_MACRO:
					{
						IrrealValue *value;
						value = current->pop();
						
						test_for_error( value == NULL, "Not enough values to perform 'macro'!" );
						
						//printf( "MACRO: debug: stack name = '%s'\n", value->getValue().c_str() );
						
						IrrealStack *source_stack = ctx->getStack( value->getValue() );
						
						test_for_error( source_stack == NULL, "MACRO: Invalid source stack!" );
						
						code->nondestructive_merge( source_stack, true );
						
					}
					break;
					
					case CMD_SWAP:
					{
						IrrealValue *stack_name, *value0, *value1;
						IrrealStack *target_stack;
						
						stack_name = current->pop();
						
						test_for_error( stack_name == NULL, "Not enough values to perform 'swap'!" );
						
						target_stack = ctx->getStack( stack_name->getValue() );
						
						test_for_error( target_stack == NULL, "SWAP: Invalid stack!" );
						
						value0 = target_stack->pop();
						value1 = target_stack->pop();
						
						test_for_error( value0 == NULL, "SWAP: Not enough values in target stack!" );
						test_for_error( value1 == NULL, "SWAP: Not enough values in target stack!" );
						
						target_stack->push( value0 );
						target_stack->push( value1 );
						
					
					}
					break;
					
					case CMD_ROTR:
					{
						
					
					}
					break;
					
					default:
					break;
					}
				}
			else{
				current->push( q );
				}
			}
		
		}
	
	
	ctx->unlock_context();
	}