#include "mk.h"
#include <stdlib.h>
#include <memory.h>
#include <string.h>
#include <stdio.h>
#ifdef _DEBUG_DUMP_DUMP
#include <stdio.h>
#endif

static
void register_internal_classes( MK_VM_STRUCT *vm );
static
int mk_register_global_instance( MK_VM_STRUCT *vm );
static
int mk_create_vm_cache( MK_VM_STRUCT *vm );
static
int mk_execute_expr_raise( MK_VM_STRUCT *vm, MK_NODE_EXPR *pExpr, int hasParam );
static
int mk_execute_expr_operation( MK_VM_STRUCT *vm, MK_NODE_EXPR *pExpr, int hasParent );
static
int mk_execute_expr_this( MK_VM_STRUCT *vm, MK_NODE_EXPR *pExpr, int hasParent );
static
int mk_execute_expr_super( MK_VM_STRUCT *vm, MK_NODE_EXPR *pExpr, int hasParent );
static
int mk_execute_expr_owner( MK_VM_STRUCT *vm, MK_NODE_EXPR *pOwner, int hasParent );
static
int mk_execute_expr_constant( MK_VM_STRUCT *vm, MK_NODE_EXPR *pExpr, int hasParent );
static
int mk_execute_expr_new( MK_VM_STRUCT *vm, MK_NODE_EXPR *pExpr, int hasParent );
static
int mk_execute_expr_call_method( MK_VM_STRUCT *vm, MK_NODE_EXPR *pExpr, int hasParent );
static
int mk_execute_expr_super_call( MK_VM_STRUCT *vm, MK_NODE_EXPR *pExpr, int hasParent );
static 
int mk_execute_expr_return( MK_VM_STRUCT *vm, MK_NODE_EXPR *pExpr, int hasParent );
static 
int mk_execute_expr_break( MK_VM_STRUCT *vm, MK_NODE_EXPR *pExpr, int hasParent );
static 
int mk_execute_expr_continue( MK_VM_STRUCT *vm, MK_NODE_EXPR *pExpr, int hasParent );
static
int mk_execute_expr_multiple( MK_VM_STRUCT *vm, MK_NODE_EXPR *pExpr, int hasParent );
static
int mk_execute_expr_symbol( MK_VM_STRUCT *vm, MK_NODE_EXPR *pExpr, int hasParent );
static
int mk_execute_expr_at_symbol( MK_VM_STRUCT *vm, MK_NODE_EXPR *pExpr, int hasParent );
static
int mk_execute_expr_array_definition( MK_VM_STRUCT *vm, MK_NODE_EXPR *pExpr, int hasParent );
static
int mk_execute_expr_node_with_param_definition( MK_VM_STRUCT *vm, MK_NODE_EXPR *pExpr, int hasParent );
static
int mk_execute_block_node_expr( MK_VM_STRUCT *vm, unsigned int *target );
static
int mk_execute_block_if_block( MK_VM_STRUCT *vm, unsigned int *target );
static
int mk_execute_block_while_block( MK_VM_STRUCT *vm, unsigned int *target );
static
int mk_execute_block_try( MK_VM_STRUCT *vm, unsigned int *target );

#ifdef _DEBUG_DUMP
void mk_vm_push_stack( MK_VECTOR *stack, INT_PTR target )
{
	mk_push_vector( stack, target );
	fprintf( stdout, "push:% 3d:<%08x>", stack ? stack->used : 0, target );
	dump_node((unsigned int*)target, 0 );
}

MK_VM_FRAME_ITEM* mk_vm_pop_stack( MK_VECTOR *stack )
{
	void *result = NULL;
	if( mk_size_vector( stack ) == 0 )
		fprintf( stdout, "err :stack underflow!!\n" );
	result = (void*)mk_pop_vector( stack );
	fprintf( stdout, "pop :% 3d:<%08x>", stack->used, result );
	dump_node( result, 0 );
	return result;
}
#endif

static 
int callInvalidateBlock( MK_VM_STRUCT *vm, unsigned int* target)
{
	MK_CHAR buffer[sizeof(void*)*2+3];
	sprintf( buffer, "0x%x", *target );
	return mk_raise_internal_error( vm, "", 0, MK_ERROR_TYPE_VM_ERROR | 9, buffer, "block", NULL );
}

static 
int callInvalidateNodeExpr( MK_VM_STRUCT *vm, MK_NODE_EXPR *expr, int hasParent )
{
	MK_CHAR buffer[sizeof(void*)*2+3];
	sprintf( buffer, "0x%x", expr->flags );
	return mk_raise_internal_error( vm, "", 0, MK_ERROR_TYPE_VM_ERROR | 9, buffer, "NodeExpr", NULL );
}

static
int mk_raise_invalidate_parent_error( MK_VM_STRUCT *vm )
{
	return mk_raise_internal_error( vm, "", 0, MK_ERROR_TYPE_VM_ERROR | 10, NULL );
}

int mk_vm_initialize( MK_VM_STRUCT *vm )
{
	int index = 0;
	
	// set top stack
	vm->stackTop = (void*)&vm;	// save stack address

	// create symbol table
	vm->hashSymbolName = mk_create_hashtable( MK_SIZEOF_HASH_DEFAULT, MK_SIZEOF_EXTEND_HASH_DEFAULT );
	vm->hashSymbolName->flags &= ~MK_TYPE_ATTRIBUTE_HASHKEY_MASK;
	vm->hashSymbolName->flags |= MK_TYPE_ATTRIBUTE_HASHKEY_STRING;

	// create object code.
	vm->code = mk_create_object( MK_OBJECT_TYPE_OBJECTCODE );
	vm->code->classes = mk_create_hashtable( MK_SIZEOF_HASH_DEFAULT, MK_SIZEOF_EXTEND_HASH_DEFAULT );
	mk_register_internal_classes( vm );

	// allocate cache
	vm->cache = malloc( sizeof(MK_VM_CACHE) );
	memset( vm->cache, 0x00, sizeof(MK_VM_CACHE) );

	// create local stack
	vm->localStack = 
		mk_create_vector( 
			MK_TYPE_VECTOR | MK_TYPE_VECTOR_ARRAY_MANAGED_PTR | ( MK_SIZEOF_EXTEND_VECTOR_DEFAULT << 10 ),
			MK_SIZEOF_VECTOR_DEFAULT,
			(INT_PTR)NULL );

	// create function table
	for( index = 0; index < 0x10; index ++ )
		vm->callBlock[index] = callInvalidateBlock;
	for( index = 0; index < 0xcf; index ++ )
		vm->callNodeExpr[index] = callInvalidateNodeExpr;

	vm->callBlock[MK_TYPE_NODE_EXPR >> 28] = 
		mk_execute_block_node_expr;
	vm->callBlock[MK_TYPE_NODE_BLOCK >> 28] = 
		mk_execute_block;
	vm->callBlock[MK_TYPE_NODE_IF >> 28] = 
		mk_execute_block_if_block;
	vm->callBlock[MK_TYPE_NODE_WHILE >> 28] = 
		mk_execute_block_while_block;
	vm->callBlock[MK_TYPE_TRY_BLOCK >> 28] = 
		mk_execute_block_try;
	vm->callNodeExpr[MK_TYPE_ATTRIBUTE_INDEX(MK_TYPE_NODE_EXPR_RAISE)] = 
		mk_execute_expr_raise;
	vm->callNodeExpr[MK_TYPE_ATTRIBUTE_INDEX(MK_TYPE_NODE_EXPR_OPERATION)] =
		mk_execute_expr_operation;
	vm->callNodeExpr[MK_TYPE_ATTRIBUTE_INDEX(MK_TYPE_NODE_EXPR_SYMBOL_THIS)] =
		mk_execute_expr_this;
	vm->callNodeExpr[MK_TYPE_ATTRIBUTE_INDEX(MK_TYPE_NODE_EXPR_SYMBOL_SUPER)] = 
		mk_execute_expr_super;
	vm->callNodeExpr[MK_TYPE_ATTRIBUTE_INDEX(MK_TYPE_NODE_EXPR_SYMBOL_OWNER)] = 
		mk_execute_expr_owner;
	vm->callNodeExpr[MK_TYPE_ATTRIBUTE_INDEX(MK_TYPE_NODE_EXPR_INT8)] =
		mk_execute_expr_constant;
	vm->callNodeExpr[MK_TYPE_ATTRIBUTE_INDEX(MK_TYPE_NODE_EXPR_INT16)] =
		mk_execute_expr_constant;
	vm->callNodeExpr[MK_TYPE_ATTRIBUTE_INDEX(MK_TYPE_NODE_EXPR_INT32)] =
		mk_execute_expr_constant;
	vm->callNodeExpr[MK_TYPE_ATTRIBUTE_INDEX(MK_TYPE_NODE_EXPR_INT64)] =
		mk_execute_expr_constant;
	vm->callNodeExpr[MK_TYPE_ATTRIBUTE_INDEX(MK_TYPE_NODE_EXPR_FLOAT)] =
		mk_execute_expr_constant;
	vm->callNodeExpr[MK_TYPE_ATTRIBUTE_INDEX(MK_TYPE_NODE_EXPR_STRING)] =
		mk_execute_expr_constant;
	vm->callNodeExpr[MK_TYPE_ATTRIBUTE_INDEX(MK_TYPE_NODE_EXPR_CHAR)] =
		mk_execute_expr_constant;
	vm->callNodeExpr[MK_TYPE_ATTRIBUTE_INDEX(MK_TYPE_NODE_EXPR_RETURN)] = 
		mk_execute_expr_return;
	vm->callNodeExpr[MK_TYPE_ATTRIBUTE_INDEX(MK_TYPE_NODE_EXPR_BREAK)] =
		mk_execute_expr_break;
	vm->callNodeExpr[MK_TYPE_ATTRIBUTE_INDEX(MK_TYPE_NODE_EXPR_CONTINUE)] =
		mk_execute_expr_continue;
	vm->callNodeExpr[MK_TYPE_ATTRIBUTE_INDEX(MK_TYPE_NODE_EXPR_MULTIPLESYMBOL)] =
		mk_execute_expr_multiple;
	vm->callNodeExpr[MK_TYPE_ATTRIBUTE_INDEX(MK_TYPE_NODE_EXPR_SYMBOL)] =
		mk_execute_expr_symbol;
	vm->callNodeExpr[MK_TYPE_ATTRIBUTE_INDEX(MK_TYPE_NODE_EXPR_ATSYMBOL)] =
		mk_execute_expr_at_symbol;
	vm->callNodeExpr[MK_TYPE_ATTRIBUTE_INDEX(MK_TYPE_NODE_EXPR_ARRAY_DEFINITION)] =
		mk_execute_expr_array_definition;
	vm->callNodeExpr[MK_TYPE_ATTRIBUTE_INDEX(MK_TYPE_NODE_EXPR_DBLATSYMBOL)] =
		mk_execute_expr_at_symbol;
	vm->callNodeExpr[MK_TYPE_ATTRIBUTE_INDEX(MK_TYPE_NODE_EXPR_NEW)] =
		mk_execute_expr_new;
	vm->callNodeExpr[MK_TYPE_ATTRIBUTE_INDEX(MK_TYPE_NODE_EXPR_FUNCTION_CALL)] =
		mk_execute_expr_call_method;
	vm->callNodeExpr[MK_TYPE_ATTRIBUTE_INDEX(MK_TYPE_NODE_EXPR_SUPER_CALL)] =
		mk_execute_expr_super_call;
	vm->callNodeExpr[MK_TYPE_ATTRIBUTE_INDEX(MK_TYPE_NODE_EXPR_NODE_WITH_PARAM)] = 
		mk_execute_expr_node_with_param_definition;

	return MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP;
}

// rollback stack when an exception occured.
void mk_vm_rollback_local_stack( MK_VM_STRUCT *vm, int size )
{
	mk_trim_size_vector( 
		vm->localStack, mk_size_vector( vm->localStack ) - size );
}

int mk_vm_run( MK_VM_STRUCT *vm )
{
	int retCode = MK_VM_EXECUTE_EXPR_RETURN_FAILED;
#ifdef _DEBUG_DUMP
	dump_node( vm->code, 0 );
#endif
	// create global object
	{
		vm->pCurrentFrame = mk_create_vm_frame_object( &vm->pFrameTable );
		vm->pTopFrame = vm->pCurrentFrame;
		mk_register_global_instance( vm );
		vm->pCurrentFrame = NULL;
		vm->pTopFrame = NULL;
	}

	// execute Kernel::mk_main
	{
		// create Kernel::mk_main node
		MK_NODE_EXPR *pCallMethod = NULL, *pKernelSymbol = NULL, *pRoot = NULL;

		pRoot = 
			mk_create_object( MK_TYPE_NODE_EXPR );
		pRoot->flags |= MK_TYPE_NODE_EXPR_MULTIPLESYMBOL;
		pRoot->u1.multipleSymbols = 
			mk_create_vector( 
				MK_TYPE_VECTOR | MK_TYPE_VECTOR_ARRAY_MANAGED_PTR | ( MK_SIZEOF_EXTEND_VECTOR_DEFAULT << 10 ),
				MK_SIZEOF_VECTOR_DEFAULT,
				(INT_PTR)NULL );

		pKernelSymbol = 
			mk_create_object( MK_TYPE_NODE_EXPR );
		pKernelSymbol->flags |= MK_TYPE_NODE_EXPR_SYMBOL;
		pKernelSymbol->u1.symbolName = 
			mk_get_symbol_name_ptr( vm, CLASS_INTERNAL_KERNEL );
		mk_push_vector( pRoot->u1.multipleSymbols, (INT_PTR)pKernelSymbol );

		pCallMethod = 
			mk_create_object( MK_TYPE_NODE_EXPR );
		pCallMethod->flags |= MK_TYPE_NODE_EXPR_FUNCTION_CALL;
		pCallMethod->u1.symbolName = 
			mk_get_symbol_name_ptr( vm, FUNCTIONNAME_ENTRYPOINT );
		pCallMethod->u2.args = NULL;
		mk_push_vector( pRoot->u1.multipleSymbols, (INT_PTR)pCallMethod );

		// crete root frame
		vm->pCurrentFrame = 
			mk_create_vm_frame_object( &vm->pFrameTable );
		vm->pTopFrame =
			vm->pCurrentFrame;
		
		// create cache
		mk_create_vm_cache( vm );

		// set this
		{
			MK_VM_FRAME_ITEM *pItem = 
				mk_create_vm_frame_item_object( &vm->pFrameItemTable );
			pItem->flags = MK_TYPE_SET_ATTRIBUTE( pItem->flags, MK_VM_FRAME_ITEM_TYPE_CLASS );
			pItem->classTypeValue.typeName = 
				mk_get_symbol_name_ptr( vm, CLASS_INTERNAL_KERNEL );
			vm->pCurrentFrame->pThis = pItem;
		}

		// run Kernel.mk_main
		retCode = 
			mk_execute_expr( vm, pRoot, 0 );
		// destroy entrypoint node
		mk_destroy_node( vm->memoryPool, pRoot );
	}
	return retCode;
}

static
int mk_create_vm_cache( MK_VM_STRUCT *vm )
{
	return MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP;
}

static
int mk_register_global_instance( MK_VM_STRUCT *vm )
{
	MK_HASHTABLE *classes = 
		vm->code->classes;
	void *handleVariables = NULL;
	const MK_CHAR *key = NULL;
	MK_CLASS *value = NULL;
	void *handle = NULL;

	// create global instance
	if( vm->global == NULL )
		vm->global = mk_allocate_vm_managed_hashtable( &vm->pHashTable );

	// create all instance.
	handle = 
		mk_enum_item_hashtable_begin( classes );
	while( handle )
	{
		MK_VM_FRAME_ITEM *newVariable = NULL;
		handle = 
			mk_enum_item_hashtable_next( classes, handle, &key, (void**)&value );
		// register new instance.
		newVariable =
			mk_create_vm_frame_item_object( &vm->pFrameItemTable );
		mk_insert_item_hashtable(
			vm->global, 
			key, 
			newVariable );
		newVariable->flags |= MK_VM_FRAME_ITEM_TYPE_CLASS | MK_VM_FRAME_ITEM_TYPE_FINAL;
		newVariable->classTypeValue.typeName = mk_get_symbol_name_ptr( vm, key );
		newVariable->classTypeValue.variables =
			mk_allocate_vm_managed_hashtable( &vm->pHashTable );
	}
	mk_enum_item_hashtable_end( classes, handle );

	// register static variables.
	handle = 
		mk_enum_item_hashtable_begin( classes );
	// register the static instance of the all classes. 
	while( handle )
	{
		const MK_CHAR *keyVariable = NULL;
		MK_VARIABLE *valueVariable = NULL;
		MK_VM_FRAME_ITEM *newVariable = NULL, *superClassFrameItem = NULL;
		handle = 
			mk_enum_item_hashtable_next( classes, handle, &key, (void**)&value );
		
		// register new instance.
		mk_find_item_hashtable( vm->global, key, (void**)&newVariable );
		
		if( value->variables != NULL )
		{
			// register all static variables.
			handleVariables = 
				mk_enum_item_hashtable_begin( value->variables );
			while( handleVariables )
			{
				handleVariables = 
					mk_enum_item_hashtable_next( value->variables, handleVariables, &keyVariable, (void**)&valueVariable );

				if( valueVariable->flags & MK_TYPE_ATTRIBUTE_VARIABLE_STATIC)
				{
					if( !( valueVariable->flags & MK_TYPE_ATTRIBUTE_VARIABLE_METHOD ) )
					{
						if( valueVariable->defaultValue != NULL )
						{
							// setup default value.
							MK_VM_FRAME_ITEM *defaultValue = 
								mk_create_vm_frame_item_object( &vm->pFrameItemTable );
							int retCode = 
								mk_execute_expr( vm, valueVariable->defaultValue, 0 );
							if( retCode == MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP )
							{
								retCode = 
									mk_object_equal( vm, 
										defaultValue, 
										(MK_VM_FRAME_ITEM*)mk_pop_vector( vm->localStack ), 
										&defaultValue );
								if( retCode != MK_VM_EXECUTE_EXPR_RETURN_RETURN )
									return retCode;
							}
							mk_insert_item_hashtable(
								newVariable->classTypeValue.variables,
								keyVariable,
								defaultValue );
						}
					}
					else
					{
						MK_VM_FRAME_ITEM *node = 
							mk_create_vm_frame_item_object( &vm->pFrameItemTable );
						node->flags |= MK_VM_FRAME_ITEM_TYPE_NODE_VALUE;
						node->code.definedFrame = NULL;
						node->code.node = (unsigned int*)valueVariable;
						mk_insert_item_hashtable(
							newVariable->classTypeValue.variables,
							keyVariable,
							node );
					}
				}
			}
		}
		// set super class
		if( value->nameSuper != NULL )
		{
			mk_find_item_hashtable( vm->global, value->nameSuper, (void**)&superClassFrameItem );
			mk_insert_item_hashtable(
				newVariable->classTypeValue.variables,
				mk_get_symbol_name_ptr( vm, "super" ),
				superClassFrameItem );
		}
		mk_enum_item_hashtable_end( value->variables, handleVariables );
	}
	mk_enum_item_hashtable_end( classes, handle );

	return MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP;
}

MK_CLASS *mk_vm_get_class_by_name( MK_VM_STRUCT *vm, const MK_CHAR *name )
{
	int index = 0;
	MK_HASHTABLE *classes = vm->code->classes;
	MK_CLASS *result = NULL;

	mk_find_item_hashtable( 
		classes, 
		name, 
		(void**)&result );
	return result;
}

MK_CLASS *mk_vm_get_class( MK_VM_STRUCT *vm, MK_VM_FRAME_ITEM *pTarget )
{
	unsigned int attribute = 0;
	unsigned int index = 0;
	MK_CLASS *result = NULL;
	MK_HASHTABLE *classes = NULL;
	if( (INT_PTR)pTarget & MK_VM_FRAME_ITEM_TYPE_DIRECT_VALUE )
	{
		switch( (INT_PTR)pTarget & MK_VM_FRAME_ITEM_TYPE_DIRECT_MASK )
		{
		case MK_VM_FRAME_ITEM_TYPE_DIRECT_INT:
			attribute = MK_VM_FRAME_ITEM_TYPE_INT_VALUE;
			break;

		case MK_VM_FRAME_ITEM_TYPE_DIRECT_BOOL:
			attribute = MK_VM_FRAME_ITEM_TYPE_BOOL_VALUE;
			break;

		case MK_VM_FRAME_ITEM_TYPE_DIRECT_CHAR:
			attribute = MK_VM_FRAME_ITEM_TYPE_CHARACTER_VALUE;
			break;
		}
	}
	else
	{
		attribute = MK_TYPE_ATTRIBUTE( pTarget->flags );
	}
	index = attribute >> 24;
	if( vm->cache->pConstantClass[index] != NULL )
		return vm->cache->pConstantClass[index];

	classes = vm->code->classes;
	switch( attribute )
	{
	case MK_VM_FRAME_ITEM_TYPE_CLASS:
		mk_find_item_hashtable( 
			vm->code->classes, 
			pTarget->classTypeValue.typeName, 
			(void**)&result );
		break;

	case MK_VM_FRAME_ITEM_TYPE_REFERENCE_VALUE:
		result = mk_vm_get_class( vm, pTarget->reference );
		break;

	case MK_VM_FRAME_ITEM_TYPE_INT_VALUE:
		mk_find_item_hashtable( classes, mk_get_symbol_name_ptr( vm, "Integer" ), (void**)&result );
		vm->cache->pConstantClass[index] = result;
		break;

	case MK_VM_FRAME_ITEM_TYPE_STRING_VALUE:
		mk_find_item_hashtable( classes, mk_get_symbol_name_ptr( vm, "String" ), (void**)&result );
		vm->cache->pConstantClass[index] = result;
		break;

	case MK_VM_FRAME_ITEM_TYPE_BOOL_VALUE:
		mk_find_item_hashtable( classes, mk_get_symbol_name_ptr( vm, "Bool" ), (void**)&result );
		vm->cache->pConstantClass[index] = result;
		break;

	case MK_VM_FRAME_ITEM_TYPE_NIL:
		mk_find_item_hashtable( classes, mk_get_symbol_name_ptr( vm, "Null" ), (void**)&result );
		vm->cache->pConstantClass[index] = result;
		break;
		
	case MK_VM_FRAME_ITEM_TYPE_CHARACTER_VALUE:
		mk_find_item_hashtable( classes, mk_get_symbol_name_ptr( vm, "Char" ), (void**)&result );
		vm->cache->pConstantClass[index] = result;
		break;

	case MK_VM_FRAME_ITEM_TYPE_FLOAT_VALUE:
		mk_find_item_hashtable( classes, mk_get_symbol_name_ptr( vm, "Float" ), (void**)&result );
		vm->cache->pConstantClass[index] = result;
		break;

	case MK_VM_FRAME_ITEM_TYPE_ARRAY_VALUE:
		mk_find_item_hashtable( classes, mk_get_symbol_name_ptr( vm, "Array" ), (void**)&result );
		vm->cache->pConstantClass[index] = result;
		break;

	case MK_VM_FRAME_ITEM_TYPE_NODE_VALUE:
		mk_find_item_hashtable( classes, mk_get_symbol_name_ptr( vm, "Node" ), (void**)&result );
		vm->cache->pConstantClass[index] = result;
		break;
	}
	if( result == NULL )
	{
		if( attribute == MK_VM_FRAME_ITEM_TYPE_CLASS )
		{
			mk_raise_internal_error( vm, "", 0, MK_ERROR_TYPE_VM_ERROR | 3, pTarget->classTypeValue.typeName, NULL );
		}
		else
		{
			//todo: [interim] return Object class
//			mk_raise_internal_error( vm, "", 0, MK_ERROR_TYPE_VM_ERROR | 3, "<internal class>", NULL );
			result = 
				mk_vm_get_class_by_name( vm, mk_get_symbol_name_ptr( vm, "Object" ) );
		}
	}
	return result;
}

static 
int mk_create_object_instance( MK_VM_STRUCT *vm, MK_VECTOR *arguments, MK_VM_FRAME_ITEM **result )
{
	int retCode = 0;
	MK_VARIABLE *pMethod = NULL;
	unsigned int index = 0;
	unsigned int size = 
		( arguments != NULL ) ? mk_size_vector( arguments ) : 0;
	int argResult = MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP;
	MK_CHAR *pObjectClassName = mk_get_symbol_name_ptr( vm, CLASS_INTERNAL_OBJECT );
	MK_VM_FRAME_ITEM *pTarget = (MK_VM_FRAME_ITEM *)mk_vm_pop_stack( vm->localStack );

	// call Object.new method
	if( mk_object_new( vm, 
		pTarget, result ) != MK_VM_EXECUTE_EXPR_RETURN_RETURN )
		return MK_VM_EXECUTE_EXPR_THROW;	// todo: create error object.
	mk_vm_push_stack( vm->localStack, (INT_PTR)*result );

	// call initialize
	pMethod = 
		mk_vm_find_method( vm, 
			*result, 
			mk_get_symbol_name_ptr( vm, "initialize" ), 
			( arguments != NULL ) ? mk_size_vector( arguments ) : 0 );
	if( pMethod != NULL )
	{
		// todo : create default value
		for( index = 0; index < size; index ++ )
		{
			MK_VM_FRAME_ITEM *arg = NULL;
			MK_NODE_EXPR *pTarget = 
				(MK_NODE_EXPR *)mk_get_at_vector( arguments, index );
			argResult = 
				mk_execute_expr( vm, pTarget, 0 );
			if( argResult != MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP )
				break;	// error
		}
		if( index == size )
		{
			retCode = mk_vm_call_method( vm, pMethod );
			if( retCode == MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP )
			{
				mk_vm_pop_stack( vm->localStack );	// drop initialize result.
				mk_vm_push_stack( 
					vm->localStack, 
					(INT_PTR)(*result) );
			}
		}
		else
		{
			retCode = MK_VM_EXECUTE_EXPR_THROW;	// todo: create exception objec
		}
	}
	else
	{
		vm->exceptionObject = NULL;	// clear method not found exception.
		retCode = MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP;
	}
	return retCode;
}

static
int mk_execute_node_with_param( MK_VM_STRUCT *vm, MK_NODE_EXPR *node, int hasParent )
{
	int index = 0;
	int size = node->u2.args != NULL ? mk_size_vector( node->u2.args ) : 0;
	MK_VM_FRAME *newFrame = NULL, *oldFrame = NULL;

	if( node->u1.node == NULL )
		return MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP;

	newFrame =
		mk_create_object( MK_OBJECT_TYPE_VM_FRAME );

	// setup frame
	newFrame->flags = 
		MK_TYPE_SET_ATTRIBUTE( newFrame->flags, MK_VM_FRAME_TYPE_PARAM_WIDH_NODE_EXPR ); 
	newFrame->pMethod = vm->pCurrentFrame->pMethod;

	// add parameter
	if( size > 0 )
		newFrame->localVariables =
			mk_allocate_vm_managed_hashtable( &vm->pHashTable );
	for( index = 0; index < size; index ++ )
	{
		MK_VARIABLE *pArg = 
			(MK_VARIABLE *)mk_get_at_vector( node->u2.args, (unsigned int)index );
		void *value = (void*)mk_vm_pop_stack( vm->localStack );
		// insert local variables hashtable
		mk_insert_item_hashtable(
			newFrame->localVariables,
			pArg->name,
			value );
	}
	if( hasParent == 0 )
		newFrame->pThis = vm->pCurrentFrame->pThis;
	else
		newFrame->pThis = (MK_VM_FRAME_ITEM*)mk_vm_pop_stack( vm->localStack );

	// select new frame.
	newFrame->previous = vm->pCurrentFrame;
	vm->pCurrentFrame = newFrame;

	if( node->u1.node != NULL )
	{
		switch( MK_OBJECT_TYPE( *node->u1.node ) )
		{
		case MK_TYPE_NODE_EXPR:
			mk_execute_expr( vm, (MK_NODE_EXPR*)node->u1.node, 0 );
			break;
		case MK_TYPE_NODE_BLOCK:
		case MK_TYPE_NODE_IF:
		case MK_TYPE_NODE_WHILE:
		case MK_TYPE_TRY_BLOCK:
			mk_execute_block( vm, node->u1.node );
			mk_vm_push_stack( 
				vm->localStack, 
				(INT_PTR)mk_create_vm_frame_item_object( &vm->pFrameItemTable ) );	// return nil
			break;
		default:
			break;	// todo:error
		}
	}

	// rollback frame
	oldFrame = vm->pCurrentFrame;
	vm->pCurrentFrame = vm->pCurrentFrame->previous;
	mk_destroy_node( vm->memoryPool, oldFrame );

	return MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP;
}

static
int mk_execute_block_internal_catch( MK_VM_STRUCT *vm, MK_CATCH_BLOCK *catchBlock, int *isHandled )
{
	int retCode = MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP;

	*isHandled = 0;
	if( catchBlock->paramCatch != NULL )
	{
		mk_vm_push_stack( 
			vm->localStack, 
			(INT_PTR)vm->exceptionObject );
		retCode = 
			mk_execute_node_with_param( vm, catchBlock->paramCatch, 0 );
		if( retCode == MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP )
		{
			MK_VM_FRAME_ITEM *pResult = 
				(MK_VM_FRAME_ITEM *)mk_vm_pop_stack( vm->localStack );
			if( catchBlock->paramCatch->u1.node != NULL )
			{
				if( pResult == NULL || // no condition.
					mk_vm_frame_item_is_true(pResult) )
					*isHandled = 1;
			}
			else
			{
				*isHandled = 1;
			}
		}
	}
	else
	{
		*isHandled = 1;
	}
	if( *isHandled != 0 )
	{
		MK_NODE_EXPR *block = 
			mk_create_object( MK_TYPE_NODE_EXPR | MK_TYPE_NODE_EXPR_NODE_WITH_PARAM );
		block->u2.args = catchBlock->paramCatch->u2.args;
		block->u1.node = (unsigned int*)catchBlock->blockCatch;
		mk_vm_push_stack( 
			vm->localStack, 
			(INT_PTR)vm->exceptionObject );
		vm->exceptionObject = NULL;
		retCode = mk_execute_node_with_param( vm, block, 0 );
		mk_vm_pop_stack( vm->localStack );	// remove resultcode of block.
		block->u2.args = NULL;
		block->u1.node = NULL;
		mk_destroy_node( vm->memoryPool, block );
	}
	return retCode;
}

static
int mk_execute_block_try( MK_VM_STRUCT *vm, unsigned int *target )
{
	MK_TRY_BLOCK *tryBlock = ( MK_TRY_BLOCK * )target;
	int retCode = MK_VM_EXECUTE_EXPR_RETURN_FAILED;
	int isHandled = 0;

	// execute try
	retCode = 
		mk_execute_block( vm, ( unsigned int * )tryBlock->blockTry );

	if( retCode == MK_VM_EXECUTE_EXPR_THROW )
	{
		// execute catch
		unsigned int sizeCatch = 
			tryBlock->blockCatch != NULL ? mk_size_vector( tryBlock->blockCatch ) : 0;
		unsigned int index = 0;
		for( index = 0; index < sizeCatch; index ++ )
		{
			MK_CATCH_BLOCK *catchBlock = 
				( MK_CATCH_BLOCK * )mk_get_at_vector( tryBlock->blockCatch, index );
			retCode = 
				mk_execute_block_internal_catch( vm, catchBlock, &isHandled );
			if( isHandled != 0 )
				break;
		}
		if( index == sizeCatch )
			retCode = MK_VM_EXECUTE_EXPR_THROW;
	}
	else if( retCode == MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP &&
		tryBlock->blockNoException != NULL )
	{
		retCode = mk_execute_block( vm, ( unsigned int * )tryBlock->blockNoException );
	}

	// execute finally
	if( retCode == MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP &&
		tryBlock->blockFinally != NULL )
		retCode = mk_execute_block( vm, ( unsigned int * )tryBlock->blockFinally );

	return retCode;
}

static
int mk_execute_block_node_expr( MK_VM_STRUCT *vm, unsigned int *target )
{
	MK_NODE_EXPR *pExpr = (MK_NODE_EXPR*)target;
	int result = mk_execute_expr( vm, pExpr, 0 );
	if( result == MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP )
	{
		// destroy return value.
		mk_vm_pop_stack( vm->localStack );
		result = MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP;
	}
	return result;
}

static
int mk_execute_block_if_block( MK_VM_STRUCT *vm, unsigned int *target )
{
	MK_VM_FRAME_ITEM *condResult = NULL;
	MK_NODE_IF *pIf = (MK_NODE_IF*) target;
	int result = MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP;
	while( pIf )
	{
		if( pIf->expr )
		{
			int retCode = 
				mk_execute_expr( vm, pIf->expr, 0 );
			if( retCode == MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP )
				condResult = (MK_VM_FRAME_ITEM*)mk_vm_pop_stack( vm->localStack );
			else
				result = retCode;	// error or exception
		}
		if( !pIf->expr || ( condResult && mk_vm_frame_item_is_true(condResult) ) )
		{
			result = mk_execute_block( vm, ( unsigned int * )pIf->block );
			break;
		}
		pIf = pIf->next;
	}
	return result;
}

static
int mk_execute_block_while_block( MK_VM_STRUCT *vm, unsigned int *target )
{
	MK_NODE_WHILE *pWhile = (MK_NODE_WHILE*)target;
	int isFront =  MK_TYPE_ATTRIBUTE( pWhile->flags ) & MK_TYPE_ATTRIBUTE_NODE_WHILE_FRONT;
	int result = MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP;

	while( 1 )
	{
		if( isFront )
		{
			result = 
				mk_execute_expr( vm, pWhile->expr, 0 );
			if( result == MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP )
			{
				MK_VM_FRAME_ITEM *condResult = NULL;
				condResult = (MK_VM_FRAME_ITEM*)mk_vm_pop_stack( vm->localStack );
				if( !condResult || !mk_vm_frame_item_is_true(condResult) )	// todo : true or false
				{
					result = MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP;
					break;
				}
			}
			else
			{
				break;	// error or exception
			}
		}
		result = mk_execute_block( vm, ( unsigned int * )pWhile->block );
		if( result == MK_VM_EXECUTE_EXPR_RETURN_BREAK )
		{
			result = MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP;
			break;
		}
		else if( result == MK_VM_EXECUTE_EXPR_RETURN_CONTINUE )
		{
			result = MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP;
			continue;
		}
		else if( result == MK_VM_EXECUTE_EXPR_RETURN_RETURN )
		{
			break;
		}
		else if( result == MK_VM_EXECUTE_EXPR_THROW )
		{
			break;
		}
		else if( result == MK_VM_EXECUTE_EXPR_RETURN_FAILED )
		{
			break;
		}
		if( !isFront )
		{
			result = 
				mk_execute_expr( vm, pWhile->expr, 0 );
			if( result == MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP )
			{
				MK_VM_FRAME_ITEM *condResult = 
					(MK_VM_FRAME_ITEM *)mk_vm_pop_stack( vm->localStack );
				if( !condResult || !mk_vm_frame_item_is_true(condResult) )	// todo : true or false
				{
					result = MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP;
					break;
				}
			}
			else
			{
				break;	// error or exception
			}
		}

	}
	return result;
}

int mk_execute_block( MK_VM_STRUCT *vm, unsigned int *target )
{
	MK_NODE_BLOCK *pBlock = ( MK_NODE_BLOCK * ) target;
	unsigned int size = 
		pBlock->exprs != NULL ? mk_size_vector( pBlock->exprs ) : 0;
	unsigned int index = 0;
	int result = MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP;
	int sizeLocalStack = 
		mk_size_vector( vm->localStack );

	for( index = 0; index < size; index ++ )
	{
		unsigned int *flags = 
			(unsigned int*)mk_get_at_vector( pBlock->exprs, index );
		// execute gc
		if( ( ++ vm->gcPhase ) % GC_EXECUTE_TIME_PER_CALL == 0 )
			mk_gc_run( vm, 0 );

		result = vm->callBlock[(*flags)>>28](vm, flags );

		// check result.
		if( result == MK_VM_EXECUTE_EXPR_RETURN_FAILED )
		{
			break;
		}
		else if( result == MK_VM_EXECUTE_EXPR_RETURN_RETURN )
		{
			break;
		}
		else if( result == MK_VM_EXECUTE_EXPR_THROW )
		{
			break;
		}
		else if( result == MK_VM_EXECUTE_EXPR_RETURN_CONTINUE )
		{
			if( MK_TYPE_ATTRIBUTE( pBlock->flags ) == MK_TYPE_ATTRIBUTE_BLOCK_FUNCTION_ROOT )
				return mk_raise_internal_error( vm, "", 0, MK_ERROR_TYPE_VM_ERROR | 4, "continue", NULL );
			else
				break;
		}
		else if( result == MK_VM_EXECUTE_EXPR_RETURN_BREAK )
		{
			if( MK_TYPE_ATTRIBUTE( pBlock->flags ) == MK_TYPE_ATTRIBUTE_BLOCK_FUNCTION_ROOT )
				return mk_raise_internal_error( vm, "", 0, MK_ERROR_TYPE_VM_ERROR | 4, "break", NULL );
			else
				break;
		}
	}

#ifdef _DEBUG_DUMP
	if( result != MK_VM_EXECUTE_EXPR_THROW &&
		mk_size_vector( vm->localStack ) != sizeLocalStack )
		fprintf( stdout, "invalid stack length before:%d after:%d\n", sizeLocalStack, mk_size_vector( vm->localStack ) );
#endif
	if( result == MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP &&
		MK_TYPE_ATTRIBUTE( pBlock->flags ) == MK_TYPE_ATTRIBUTE_BLOCK_FUNCTION_ROOT )
	{
		// return nil
		MK_VM_FRAME_ITEM *pReturn = 
			mk_create_vm_frame_item_object( &vm->pFrameItemTable );
		mk_vm_push_stack( 
			vm->localStack, 
			(INT_PTR)pReturn );
		result = MK_VM_EXECUTE_EXPR_RETURN_RETURN;
	}
	else if( result == MK_VM_EXECUTE_EXPR_THROW )
	{
		mk_trim_size_vector( vm->localStack, sizeLocalStack );
	}

	return result;
}

MK_VARIABLE* mk_vm_find_operator_method( MK_VM_STRUCT *vm, MK_CLASS *pOwner, unsigned int index )
{
	MK_CLASS *pTop = NULL;
	MK_VARIABLE *pResult = NULL;

	pTop = pOwner;
	while( pOwner != NULL )
	{
		if( pOwner->operatorMethod != NULL )
		{
			pResult = 
				(MK_VARIABLE*)pOwner->operatorMethod[index];
			if( pResult != NULL )
				break;
		}
		// search superclass
		if( pOwner->nameSuper != NULL &&
			pOwner->nameSuper[0] != '\0' )
		{
			pOwner = 
				mk_vm_get_class_by_name( vm, pOwner->nameSuper );
			if( pOwner == NULL )
				mk_raise_internal_error( vm, "", 0, 
					MK_ERROR_TYPE_VM_ERROR | 3, 
					pOwner->nameSuper, NULL );
		}
		else
		{
			pOwner = NULL;
		}
	}
	if( pResult == NULL )
		mk_raise_internal_error( vm, "", 0, MK_ERROR_TYPE_VM_ERROR | 2, MK_RESERVED_MARK[index].name, pTop->nameThis, NULL );
	return pResult;
}

MK_VARIABLE* mk_vm_find_method( MK_VM_STRUCT *vm, 
								 MK_VM_FRAME_ITEM *pOwner, const MK_CHAR *name, 
								 unsigned int sizeArgs )
{
	MK_VARIABLE *variable = NULL;
	MK_VM_FRAME_ITEM *result = 
		mk_vm_find_variable( vm, pOwner, name );
	if( ( result != NULL ) &&
		!( (INT_PTR)result & MK_VM_FRAME_ITEM_TYPE_DIRECT_VALUE ) )
	{
		MK_VARIABLE*target = NULL;
		if( MK_OBJECT_TYPE(result->flags) == MK_TYPE_VARIABLE )
		{
			target = 
				(MK_VARIABLE*)result;
		}
		else if( ( MK_OBJECT_TYPE(result->flags) == MK_OBJECT_TYPE_VM_FRAME_ITEM ) &&
			( MK_TYPE_ATTRIBUTE(result->flags) == MK_VM_FRAME_ITEM_TYPE_NODE_VALUE ) )
		{
			target = 
				(MK_VARIABLE*)result->code.node;
		}
		if( target != NULL &&
			target->flags & MK_TYPE_ATTRIBUTE_VARIABLE_METHOD )
		{
			int sizeArgTarget = 
				( target->flags & MK_TYPE_ATTRIBUTE_VARIABLE_METHOD_NATIVE ) ? 
					( target->sizeArgs ) :
					( target->args != NULL ? mk_size_vector( target->args ) : 0 );
			int isVarargs = target->flags & MK_TYPE_ATTRIBUTE_VARIABLE_METHOD_VARARGS;
			if( ( sizeArgTarget == sizeArgs ) ||
				( ( sizeArgTarget < sizeArgs ) && ( isVarargs != 0 ) ) )
				variable = target;
		}
	}
	return variable;
}

MK_VM_FRAME_ITEM* mk_vm_find_variable( MK_VM_STRUCT *vm, 
								 MK_VM_FRAME_ITEM *pOwner, const MK_CHAR *name )
{
	MK_VM_FRAME_ITEM *pResult = NULL;

	if( ( (INT_PTR)pOwner & MK_VM_FRAME_ITEM_TYPE_DIRECT_VALUE ) ||
		( MK_TYPE_ATTRIBUTE( pOwner->flags ) != MK_VM_FRAME_ITEM_TYPE_CLASS ) )
	{
		MK_CLASS *pTop = NULL, *pCurrent = NULL;
		pTop = mk_vm_get_class( vm, pOwner );
		pCurrent = pTop;
		while( pCurrent != NULL )
		{
			if( pCurrent->variables != NULL )
				(MK_VM_FRAME_ITEM*)mk_find_item_hashtable( pCurrent->variables, name, (void**)&pResult );
			if( pResult != NULL )
				break;

			// search superclass
			if( pCurrent->nameSuper != NULL &&
				pCurrent->nameSuper[0] != '\0' )
			{
				pCurrent = 
					mk_vm_get_class_by_name( vm, pCurrent->nameSuper );
				if( pCurrent == NULL )
					mk_raise_internal_error( vm, "", 0, 
						MK_ERROR_TYPE_VM_ERROR | 3, 
						pCurrent->nameSuper, NULL );
			}
			else
			{
				pCurrent = NULL;
			}
		}
		if( pResult == NULL )
			mk_raise_internal_error( vm, "", 0, MK_ERROR_TYPE_VM_ERROR | 2, name, pTop->nameThis, NULL );
	}
	else
	{
		MK_VM_FRAME_ITEM *pTop = pOwner;
		MK_CHAR *chSuper = NULL;
		while( pOwner != NULL )
		{
			if( pOwner->classTypeValue.variables != NULL )
				mk_find_item_hashtable( pOwner->classTypeValue.variables, name, (void**)&pResult );
			if( pResult != NULL )
				break;
			if( chSuper == NULL )
				chSuper = 
					mk_get_symbol_name_ptr( vm, "super" );
			mk_find_item_hashtable( pOwner->classTypeValue.variables, chSuper, (void**)&pOwner );
		}
		if( pResult == NULL )
			mk_raise_internal_error( vm, "", 0, MK_ERROR_TYPE_VM_ERROR | 2, name, pTop->classTypeValue.typeName, NULL );
	}
	return pResult;
}

int mk_mk_method_call( MK_VM_STRUCT *vm, MK_VARIABLE *pMethod )
{
	int retCode = MK_VM_EXECUTE_EXPR_RETURN_FAILED;
	MK_VM_FRAME *newFrame =
		mk_create_vm_frame_object( &vm->pFrameTable );
	MK_VECTOR *params =
		vm->localStack;
	MK_CHAR *key = NULL;
	MK_VM_FRAME_ITEM *value = NULL;
	int size = pMethod->args != NULL ? mk_size_vector( ( pMethod->args ) ) : 0;
	int index = 0;

	// args
	if( size > 0 )
	{
		newFrame->localVariables = 
			mk_allocate_vm_managed_hashtable( &vm->pHashTable );
		for( index = size - 1; index >= 0; index -- )
		{
			MK_VM_FRAME_ITEM *insertValue = 
				mk_create_vm_frame_item_object( &vm->pFrameItemTable );
			MK_VARIABLE *pArg = 
				(MK_VARIABLE*)mk_get_at_vector( pMethod->args, (unsigned int)index );
			value = (MK_VM_FRAME_ITEM*)mk_vm_pop_stack( params );
			// insert copy
			retCode = 
				mk_object_equal( vm, insertValue, value, &insertValue );
			if( retCode != MK_VM_EXECUTE_EXPR_RETURN_RETURN )
				return retCode;
			// insert local variables hashtable
			mk_insert_item_hashtable(
				newFrame->localVariables,
				pArg->name,
				insertValue );
		}
	}

	// ptr [this] 
	value = (MK_VM_FRAME_ITEM*)mk_vm_pop_stack( params );
	newFrame->pThis = value;

	newFrame->previous = vm->pCurrentFrame;
	vm->pCurrentFrame = newFrame;
	newFrame->pMethod = pMethod;
	if( MK_OBJECT_TYPE( pMethod->impl->flags ) == MK_TYPE_NODE_EXPR )
	{
		vm->pCurrentFrame->flags |= MK_VM_FRAME_TYPE_PARAM_WIDH_NODE_EXPR;
		retCode = 
			mk_execute_expr( vm, (MK_NODE_EXPR*)pMethod->impl, 0 );
	}
	else
	{
		retCode = mk_execute_block( vm, (unsigned int *)pMethod->impl );
	}
	vm->pCurrentFrame = vm->pCurrentFrame->previous;
	return retCode;
}

int mk_vm_call_method( MK_VM_STRUCT *vm, MK_VARIABLE *pMethod )
{
	MK_VM_FRAME_ITEM *result = NULL;
	int retCode = 0;

	if( ( pMethod->flags & MK_TYPE_ATTRIBUTE_VARIABLE_METHOD_NATIVE ) )
	{
		retCode = mk_native_method_call( 
			vm,
			pMethod, 
			pMethod->sizeArgs + 
				(pMethod->flags & MK_TYPE_ATTRIBUTE_VARIABLE_METHOD_VARARGS ) ? 1 : 0 );
	}
	else
	{
		retCode = mk_mk_method_call(
			vm,
			pMethod );
	}
	if( retCode == MK_VM_EXECUTE_EXPR_RETURN_RETURN )
		retCode = MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP;
	return retCode;
}

static
MK_VM_FRAME_ITEM *mk_vm_get_super_class_instance( MK_VM_STRUCT *vm, MK_VM_FRAME_ITEM *pTarget )
{
	MK_VM_FRAME_ITEM *result = NULL;
	if( (INT_PTR)pTarget & MK_VM_FRAME_ITEM_TYPE_DIRECT_VALUE ||
		MK_TYPE_ATTRIBUTE( pTarget->flags ) != MK_VM_FRAME_ITEM_TYPE_CLASS )
	{
		result = 
			mk_create_vm_frame_item_object( &vm->pFrameItemTable );
		result->flags = 
			MK_TYPE_SET_ATTRIBUTE( result->flags, MK_VM_FRAME_ITEM_TYPE_CLASS );
		result->classTypeValue.typeName = 
			mk_get_symbol_name_ptr( vm, "Object" );
		result->classTypeValue.child = pTarget;
	}
	else
	{
		mk_find_item_hashtable( pTarget->classTypeValue.variables,
			mk_get_symbol_name_ptr( vm, "super" ), 
			(void**)&result );
	}
	return result;
}

static
int mk_execute_expr_raise( MK_VM_STRUCT *vm, MK_NODE_EXPR *pExpr, int hasParam )
{
	int retCode = mk_execute_expr( vm, pExpr->u1.left, 0 );
#ifdef _DEBUG_DUMP
	fprintf( stdout, "raise\n" );
#endif
	if( retCode == MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP )
	{
		MK_VM_FRAME_ITEM *pException = 
			(MK_VM_FRAME_ITEM *)mk_vm_pop_stack( vm->localStack );
		vm->exceptionObject = (MK_VM_FRAME_ITEM*)pException;
		return MK_VM_EXECUTE_EXPR_THROW;
	}
	else
	{
		return retCode;
	}
}

static
int mk_execute_expr_operation( MK_VM_STRUCT *vm, MK_NODE_EXPR *pExpr, int hasParent )
{
	MK_NODE_EXPR *pLeft = pExpr->u1.left;
	MK_NODE_EXPR *pRight = pExpr->u2.right;
	int retCodeLeft = 0;
	int retCodeRight = 0;
	MK_VM_FRAME_ITEM *pLeftValue = NULL;

	MK_CLASS *pClass = NULL;
	int retCode = 0;
	MK_VARIABLE *pMethod = NULL;

#ifdef _DEBUG_DUMP
	fprintf( stdout, "call %s\n", operation_int_to_string( pExpr->flags ) );
#endif
	if( hasParent != 0 )
		return mk_raise_invalidate_parent_error( vm );

	retCodeLeft = 
		mk_execute_expr( vm, pLeft, 0 );		// ptr[this]
	if( retCodeLeft != MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP )
		return retCodeLeft;	// error
	retCodeRight =
		mk_execute_expr( vm, pRight, 0 );	// args[0]
	if( retCodeRight != MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP )
		return retCodeRight;	// error

	pLeftValue  = 
		(MK_VM_FRAME_ITEM*)mk_get_at_vector( vm->localStack, 
	mk_size_vector( vm->localStack ) - 2 );
	pClass = mk_vm_get_class( vm, pLeftValue );
	if( pClass == NULL )
		return MK_VM_EXECUTE_EXPR_THROW;	// set error object in mk_vm_get_class

	pMethod = 
		mk_vm_find_operator_method( vm,
			pClass, 
			MK_RESERVED_MARK_INDEX( pExpr->flags ) );
	if( pMethod == NULL )
		return MK_VM_EXECUTE_EXPR_THROW;	// set error object in mk_vm_find_operator_method

	return mk_vm_call_method( vm, pMethod );
}

static
int mk_execute_expr_owner( MK_VM_STRUCT *vm, MK_NODE_EXPR *pExpr, int hasParent )
{
	MK_VM_FRAME_ITEM *pResult = 
		mk_create_vm_frame_item_object( &vm->pFrameItemTable );
#ifdef _DEBUG_DUMP
	fprintf( stdout, "owner\n" );
#endif
	if( hasParent != 0 )
		return mk_raise_invalidate_parent_error( vm );

	pResult->flags = 
		MK_TYPE_SET_ATTRIBUTE( pResult->flags, MK_VM_FRAME_ITEM_TYPE_OWNER );
	mk_vm_push_stack( 
		vm->localStack, 
		(INT_PTR)pResult );
	return MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP;
}

static
int mk_execute_expr_this( MK_VM_STRUCT *vm, MK_NODE_EXPR *pExpr, int hasParent )
{
	MK_VM_FRAME_ITEM *pResult = NULL;
#ifdef _DEBUG_DUMP
	fprintf( stdout, "this\n" );
#endif
	if( hasParent == 0 )
		mk_vm_push_stack( 
			vm->localStack, 
			(INT_PTR)vm->pCurrentFrame->pThis );
	return MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP;
}

int mk_execute_expr_super( MK_VM_STRUCT *vm, MK_NODE_EXPR *pExpr, int hasParent )
{
	MK_VM_FRAME_ITEM *pThis = NULL, *pSuper = NULL;
#ifdef _DEBUG_DUMP
	fprintf( stdout, "super\n" );
#endif
	if( hasParent == 0 )
		pThis = vm->pCurrentFrame->pThis;
	else
		pThis = (MK_VM_FRAME_ITEM*)mk_vm_pop_stack( vm->localStack );

	if( ( unsigned int)pThis & MK_VM_FRAME_ITEM_TYPE_DIRECT_VALUE )
	{
		;	// todo:
	}
	else
	{
		mk_find_item_hashtable( 
			pThis->classTypeValue.variables, 
			mk_get_symbol_name_ptr( vm, "super" ), 
			(void**)&pSuper );
	}

	if( pSuper != NULL )
	{
		mk_vm_push_stack( 
			vm->localStack, 
			(INT_PTR)pSuper );
	}
	else
	{
		return mk_raise_internal_error( vm, "", 0, MK_ERROR_TYPE_VM_ERROR | 12, pThis->classTypeValue.typeName, NULL );
	}
	return MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP;
}

static
int mk_execute_expr_constant( MK_VM_STRUCT *vm, MK_NODE_EXPR *pExpr, int hasParent )
{
	MK_VM_FRAME_ITEM *result = NULL;

#ifdef _DEBUG_DUMP
	fprintf( stdout, "loadconst %08x-%08x\n", pExpr->u1.constantValue, pExpr->u2.constantValue );
#endif

	if( hasParent != 0 )
		return mk_raise_invalidate_parent_error( vm );

	if( ( MK_TYPE_ATTRIBUTE( pExpr->flags ) & MK_TYPE_NODE_EXPR_CONSTANT ) == MK_TYPE_NODE_EXPR_CONSTANT )
	{
		switch( MK_TYPE_ATTRIBUTE( pExpr->flags ) )
		{
		case MK_TYPE_NODE_EXPR_INT8:
		case MK_TYPE_NODE_EXPR_INT16:
		case MK_TYPE_NODE_EXPR_INT32:
			result = mk_vm_create_int32_frame_item( vm, pExpr->u2.constantValue );
			break;

		case MK_TYPE_NODE_EXPR_INT64:
			// not supported yet.
			break;

		case MK_TYPE_NODE_EXPR_FLOAT:
			result =
				mk_vm_create_float_frame_item( vm, *( (MK_FLOAT*)&pExpr->u1.constantValue ) );
			break;

		case MK_TYPE_NODE_EXPR_STRING:
			result = 
				mk_create_vm_frame_item_object( &vm->pFrameItemTable );
			result->flags |= MK_VM_FRAME_ITEM_TYPE_STRING_VALUE;
			mk_copy_string( &result->stringTypeValue, pExpr->u2.value );
			break;

		case MK_TYPE_NODE_EXPR_CHAR:
			// not supported yet.
			break;
		}
	}
	mk_vm_push_stack( 
		vm->localStack, 
		(INT_PTR)result );
	if( result != NULL )
	{
		return MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP;
	}
	else
	{
		MK_CHAR buffer[sizeof(void*)*2+3];
		sprintf( buffer, "0x%x", pExpr->flags );
		return mk_raise_internal_error( vm, "", 0, MK_ERROR_TYPE_VM_ERROR | 9, buffer, "NodeExpr", NULL );
	}
}

static 
int mk_execute_expr_return( MK_VM_STRUCT *vm, MK_NODE_EXPR *pExpr, int hasParent )
{
	int retCode = MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP;
#ifdef _DEBUG_DUMP
	fprintf( stdout, "retrun\n" );
#endif

	if( hasParent != 0 )
		return mk_raise_invalidate_parent_error( vm );

	retCode = mk_execute_expr( vm, pExpr->u1.left, 0 );
	if( retCode == MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP )
		retCode = MK_VM_EXECUTE_EXPR_RETURN_RETURN;
	return retCode;
}

static 
int mk_execute_expr_break( MK_VM_STRUCT *vm, MK_NODE_EXPR *pExpr, int hasParent )
{
#ifdef _DEBUG_DUMP
	fprintf( stdout, "break\n" );
#endif

	if( hasParent != 0 )
		return mk_raise_invalidate_parent_error( vm );

	return MK_VM_EXECUTE_EXPR_RETURN_BREAK;
}

static 
int mk_execute_expr_continue( MK_VM_STRUCT *vm, MK_NODE_EXPR *pExpr, int hasParent )
{
#ifdef _DEBUG_DUMP
	fprintf( stdout, "continue\n" );
#endif

	if( hasParent != 0 )
		return mk_raise_invalidate_parent_error( vm );

	return MK_VM_EXECUTE_EXPR_RETURN_CONTINUE;
}


static
int mk_execute_expr_symbol( MK_VM_STRUCT *vm, MK_NODE_EXPR *pExpr, int hasParent )
{
	MK_CHAR *symbolName = pExpr->u1.symbolName;
	MK_VM_FRAME *pCurrentFrame = 
		vm->pCurrentFrame;
	MK_VM_FRAME_ITEM *result = NULL;
	int index = 0;
	int retCode = 0;
	MK_VM_FRAME_ITEM *pOwner = NULL;

#ifdef _DEBUG_DUMP
	fprintf( stdout, "loadsym %s\n", pExpr->u1.symbolName );
#endif

	if( hasParent != 0 )
		pOwner = 
			(MK_VM_FRAME_ITEM*)mk_vm_pop_stack( vm->localStack );

	if( pOwner != NULL )
	{
		if( (INT_PTR)pOwner != MK_VM_FRAME_ITEM_TYPE_DIRECT_VALUE &&
			MK_TYPE_ATTRIBUTE(pOwner->flags) == MK_VM_FRAME_ITEM_TYPE_OWNER )
		{
			// change context to owner.
			while( MK_TYPE_ATTRIBUTE(pCurrentFrame->flags) & MK_VM_FRAME_TYPE_PARAM_WIDH_NODE_EXPR )
				pCurrentFrame = pCurrentFrame->previous;
			pOwner = NULL;
		}
	}
	if( pOwner == NULL )
	{
		// search local variables(and arguments).
		if( pCurrentFrame->localVariables != NULL )
			retCode = mk_find_item_hashtable( pCurrentFrame->localVariables, symbolName, (void**)&result );

		// search global variables
		if( retCode == 0 )
			retCode =
				mk_find_item_hashtable( vm->global, symbolName, (void**)&result );
	}

	// search pThis->function
	if( retCode == 0 )
	{
		MK_VM_FRAME_ITEM *resultVmFrameItem = NULL;
		retCode = 
			mk_find_item_hashtable( 
			( pOwner == NULL ) ? vm->pCurrentFrame->pThis->classTypeValue.variables : pOwner->classTypeValue.variables, 
				symbolName, 
				(void**)&result );
		if( result != NULL )
		{
			resultVmFrameItem = 
				(MK_VM_FRAME_ITEM*)result;
			if( ( (INT_PTR)resultVmFrameItem & MK_VM_FRAME_ITEM_TYPE_DIRECT_VALUE ) ||
				!( resultVmFrameItem->flags | MK_VM_FRAME_ITEM_TYPE_NODE_VALUE ) ||
				( ( (*resultVmFrameItem->code.node) & ( MK_TYPE_VARIABLE | MK_TYPE_ATTRIBUTE_VARIABLE_METHOD ) ) !=
					( MK_TYPE_VARIABLE | MK_TYPE_ATTRIBUTE_VARIABLE_METHOD ) ) )
				result = NULL;
		}
	}

	// create new local variable.
	if( retCode == 0 )
	{
		result = mk_create_vm_frame_item_object( &vm->pFrameItemTable );
		if( pCurrentFrame->localVariables == NULL )
			pCurrentFrame->localVariables = mk_allocate_vm_managed_hashtable( &vm->pHashTable );
		mk_insert_item_hashtable(
			pCurrentFrame->localVariables, 
			symbolName, 
			result );
	}
	mk_vm_push_stack( 
		vm->localStack, 
		(INT_PTR)result );

	return MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP;
}

static
int mk_execute_expr_multiple( MK_VM_STRUCT *vm, MK_NODE_EXPR *pExpr, int hasParent )	// hasParent need 0
{
	unsigned int retCode = MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP;
	MK_VECTOR *multiple = 
		pExpr->u1.multipleSymbols;
	unsigned int size = multiple != NULL ? mk_size_vector( multiple ) : 0;
	unsigned int index = 0;
	MK_VECTOR **stack = 
		&vm->localStack;

#ifdef _DEBUG_DUMP
	fprintf( stdout, "multiple->\n" );
#endif

	if( hasParent != 0 )
		return mk_raise_invalidate_parent_error( vm );

	for( index = 0; index < size; index ++ )
	{
		MK_NODE_EXPR *pTarget = 
			(MK_NODE_EXPR *)mk_get_at_vector( multiple, index );
		retCode = 
			mk_execute_expr( 
				vm, 
				pTarget,
				hasParent );
		if( retCode != MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP )
			break;
		hasParent = 1;
	}
	return retCode;
}

static
int mk_execute_expr_at_symbol( MK_VM_STRUCT *vm, MK_NODE_EXPR *pExpr, int hasParent )
{
	MK_CHAR *symbolName = pExpr->u1.symbolName;
	MK_VM_FRAME_ITEM *result = NULL;
	MK_VM_FRAME_ITEM *pOwner = ( hasParent == 0 ) ? 
		pOwner = vm->pCurrentFrame->pThis : 
			(MK_VM_FRAME_ITEM *)mk_vm_pop_stack( vm->localStack ), 
		*pTop = pOwner;
	MK_CHAR *super = NULL;

#ifdef _DEBUG_DUMP
	fprintf( stdout, "loadsym %s\n", pExpr->u1.symbolName );
#endif

	if( MK_TYPE_ATTRIBUTE(pExpr->flags ) == MK_TYPE_NODE_EXPR_DBLATSYMBOL )
	{
		mk_find_item_hashtable( vm->global, pOwner->classTypeValue.typeName, (void**)&pOwner );
		if( pOwner == NULL )
			return mk_raise_internal_error(
				vm, "", 0, 
				MK_ERROR_TYPE_VM_ERROR | 6, 
				"global", pOwner->classTypeValue.typeName, NULL );
	}
	while ( pOwner != NULL )
	{
		if( mk_find_item_hashtable( pOwner->classTypeValue.variables, symbolName, (void**)&result ) != 0 )
			break;
		if( super == NULL )
			super = mk_get_symbol_name_ptr( vm, "super" );
		if( mk_find_item_hashtable( pOwner->classTypeValue.variables, super, (void**)&pOwner ) == 0 )
			break;
	}
	if( pOwner == NULL )
		return mk_raise_internal_error( vm, 
			"", 
			0, 
			MK_ERROR_TYPE_VM_ERROR | 1, 
			symbolName, pTop->classTypeValue.typeName, NULL );
	else
		mk_vm_push_stack( 
			vm->localStack, 
			(INT_PTR)result );
	return MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP;
}

static
int mk_execute_expr_array_definition( MK_VM_STRUCT *vm, MK_NODE_EXPR *pExpr, int hasParent )
{
	MK_VM_FRAME_ITEM *newItem = NULL;
	MK_VECTOR *newArray = NULL, *definedArray = NULL;
	unsigned int size = 0, index = 0;
	int retCode = MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP;

#ifdef _DEBUG_DUMP
	fprintf( stdout, "DEF_ARRAY %s\n", pExpr->u1.symbolName );
#endif
	if( hasParent != 0 )
		return mk_raise_invalidate_parent_error( vm );
	
	definedArray = pExpr->u1.arrayDefinition;
	size = definedArray != NULL ? mk_size_vector( definedArray ) : 0;
	newArray = 
		mk_allocate_vm_managed_vector(
			&vm->pVectorTable, 
			MK_TYPE_VECTOR | MK_TYPE_VECTOR_ARRAY_MANAGED_PTR | ( MK_SIZEOF_EXTEND_VECTOR_DEFAULT << 10 ),
			MK_SIZEOF_VECTOR_DEFAULT,
			(INT_PTR)NULL );
	for( index = 0; index < size; index ++ )
	{
		MK_VM_FRAME_ITEM *targetItem = NULL, *insertItem = NULL, *resultItem = NULL;
		retCode = 
			mk_execute_expr( vm, 
				(MK_NODE_EXPR*)mk_get_at_vector( definedArray, index ), 0 );
		if( retCode != MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP )
			break;
		targetItem = 
			(MK_VM_FRAME_ITEM*)mk_vm_pop_stack( vm->localStack );
		insertItem = mk_create_vm_frame_item_object( &vm->pFrameItemTable );
		retCode = mk_object_equal( vm, insertItem, targetItem, &resultItem );
		if( retCode != MK_VM_EXECUTE_EXPR_RETURN_RETURN )
			break;
		mk_push_vector( newArray, (INT_PTR)insertItem );
	}
	if( index == size )
	{
		newItem = mk_create_vm_frame_item_object( &vm->pFrameItemTable );
		newItem->flags |= MK_VM_FRAME_ITEM_TYPE_ARRAY_VALUE;
		newItem->arrayTypeValue = newArray;
	}
	mk_vm_push_stack( 
		vm->localStack, 
		(INT_PTR)newItem );
	return MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP;
}

static
int mk_execute_expr_node_with_param_definition( MK_VM_STRUCT *vm, MK_NODE_EXPR *pExpr, int hasParent )
{
	MK_VM_FRAME_ITEM *result = NULL;

	if( hasParent != 0 )
		return mk_raise_invalidate_parent_error( vm );

	result = 
		mk_create_vm_frame_item_object( &vm->pFrameItemTable );
	result->flags = 
		MK_TYPE_SET_ATTRIBUTE( result->flags, MK_VM_FRAME_ITEM_TYPE_NODE_VALUE );
	result->code.definedFrame = vm->pCurrentFrame;
	result->code.node = pExpr->u1.node;

	mk_vm_push_stack( vm->localStack, (INT_PTR)result );
	return MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP;
}

int mk_execute_expr_new( MK_VM_STRUCT *vm, MK_NODE_EXPR *pExpr, int hasParent )
{
	int retCode = 0;
	MK_VM_FRAME_ITEM *pOwner = NULL, *pInstance = NULL;
	
#ifdef _DEBUG_DUMP
	fprintf( stdout, "new\n" );
#endif

	// find target class
	if( hasParent == 0 )
	{
		pOwner = vm->pCurrentFrame->pThis;
		mk_vm_push_stack( 
			vm->localStack, 
			(INT_PTR)pOwner );
	}
	else
	{
		pOwner = (MK_VM_FRAME_ITEM*)mk_get_at_vector( 
			vm->localStack, 
			mk_size_vector( vm->localStack ) - 1 );
	}

	return
		mk_create_object_instance( vm, pExpr->u2.args, &pInstance );
}

static
int mk_execute_expr_call_method( MK_VM_STRUCT *vm, MK_NODE_EXPR *pExpr, int hasParent )
{
	MK_VM_FRAME_ITEM *pOwner = NULL;
	int isCreateTemp = 0;
	MK_VARIABLE *pMethod = NULL;
	MK_VM_FRAME_ITEM *vfiVarArgs = NULL;
	MK_VECTOR *varArgs = NULL;
	unsigned int index = 0;
	unsigned int size = 
		( pExpr->u2.args != NULL ) ? mk_size_vector( pExpr->u2.args ) : 0;
	unsigned int targetSize = 0;
	int argResult = MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP;

#ifdef _DEBUG_DUMP
	fprintf( stdout, "call %s\n", pExpr->u1.symbolName );
#endif

	if( hasParent == 0 )
	{
		pOwner = vm->pCurrentFrame->pThis;
		mk_vm_push_stack( 
			vm->localStack, 
			(INT_PTR)pOwner );
	}
	else
	{
		pOwner = (MK_VM_FRAME_ITEM*)mk_get_at_vector( 
			vm->localStack, mk_size_vector( vm->localStack ) - 1 );
	}
	pMethod = 
		mk_vm_find_method( vm, 
			pOwner,
			pExpr->u1.symbolName, 
			size );
	if( pMethod == NULL )
	{
		MK_VM_FRAME_ITEM *result = NULL;
		int retCode = 0;
		if( vm->pCurrentFrame->localVariables != NULL )
			retCode = mk_find_item_hashtable( vm->pCurrentFrame->localVariables, pExpr->u1.symbolName, (void**)&result );
		if( result != NULL &&
			( !( (INT_PTR)result & MK_VM_FRAME_ITEM_TYPE_DIRECT_VALUE ) ) )
		{
			if( MK_TYPE_ATTRIBUTE( result->flags ) == MK_VM_FRAME_ITEM_TYPE_NODE_VALUE )
			{
				pMethod = (MK_VARIABLE*)result->code.node;
			}
			else if( MK_TYPE_ATTRIBUTE( result->flags ) == MK_VM_FRAME_ITEM_TYPE_CLASS &&
				result->classTypeValue.typeName == mk_get_symbol_name_ptr( vm, "Node" ) )
			{
				MK_VM_FRAME_ITEM *node = 
					mk_vm_find_variable( vm, result,  mk_get_symbol_name_ptr( vm, "node" ) );
				pMethod = (MK_VARIABLE*)node->code.node;
			}
			if( pMethod != NULL )
				vm->exceptionObject = NULL;
		}
	}
	if( pMethod == NULL )
		return MK_VM_EXECUTE_EXPR_THROW;
	
	// todo : create default value
	if( pMethod->flags & MK_TYPE_ATTRIBUTE_VARIABLE_METHOD_VARARGS )
	{
		vfiVarArgs = mk_create_vm_frame_item_object( &vm->pFrameItemTable );
		varArgs = mk_allocate_vm_managed_vector( &vm->pVectorTable,
			MK_TYPE_VECTOR | MK_TYPE_VECTOR_ARRAY_MANAGED_PTR | ( MK_SIZEOF_EXTEND_VECTOR_DEFAULT << 10 ),
			size,
			(INT_PTR)NULL );
		vfiVarArgs->flags = 
			MK_TYPE_SET_ATTRIBUTE( vfiVarArgs->flags, MK_VM_FRAME_ITEM_TYPE_ARRAY_VALUE );
		vfiVarArgs->arrayTypeValue = varArgs;
		targetSize = ( pMethod->flags & MK_TYPE_ATTRIBUTE_VARIABLE_METHOD_NATIVE ) ? 
					( pMethod->sizeArgs ) :
					( pMethod->args != NULL ? mk_size_vector( pMethod->args ) : 0 );
	}
	else
	{
		targetSize = size;
	}
	for( index = 0; index < size; index ++ )
	{
		MK_VM_FRAME_ITEM *arg = NULL;
		MK_NODE_EXPR *pTarget = 
			(MK_NODE_EXPR *)mk_get_at_vector( pExpr->u2.args, index );
		argResult = 
			mk_execute_expr( vm, pTarget, 0 );
		if( argResult != MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP )
			break;	// error

		if( index >= targetSize )
		{
			MK_VM_FRAME_ITEM *v = 
				(MK_VM_FRAME_ITEM *)mk_vm_pop_stack( vm->localStack );
			mk_push_vector( varArgs, (INT_PTR)v );
		}
	}
	if( pMethod->flags & MK_TYPE_ATTRIBUTE_VARIABLE_METHOD_VARARGS )
		mk_vm_push_stack( vm->localStack, (INT_PTR)vfiVarArgs );

	if( index == size )
		return mk_vm_call_method( vm, pMethod );
	else
		return MK_VM_EXECUTE_EXPR_THROW;	// todo: create exception object
}

int mk_execute_expr_super_call( MK_VM_STRUCT *vm, MK_NODE_EXPR *pExpr, int hasParent )
{
	MK_VM_FRAME_ITEM *pOwner = NULL;
	MK_VARIABLE *pMethod = NULL;
	unsigned int index = 0;
	unsigned int size = 
		( pExpr->u2.args != NULL ) ? mk_size_vector( pExpr->u2.args ) : 0;
	int argResult = MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP;

	if( hasParent == 0 )
		pOwner = vm->pCurrentFrame->pThis;
	else
		pOwner = (MK_VM_FRAME_ITEM*)mk_vm_pop_stack( vm->localStack );

	pOwner = 
		mk_vm_get_super_class_instance( vm, pOwner );
	if( pOwner == NULL )
		;	// todo: not found super class.
	mk_vm_push_stack( 
		vm->localStack, 
		(INT_PTR)pOwner );

	pMethod = 
		mk_vm_find_method( vm, 
			pOwner, 
			vm->pCurrentFrame->pMethod->name, 
			pExpr->u2.args != NULL ? mk_size_vector( pExpr->u2.args ) : 0 );
	if( pMethod == NULL )
		return MK_VM_EXECUTE_EXPR_THROW;	// set error object in mk_vm_find_function

	// todo : create default value
	for( index = 0; index < size; index ++ )
	{
		MK_VM_FRAME_ITEM *arg = NULL;
		MK_NODE_EXPR *pTarget = 
			(MK_NODE_EXPR *)mk_get_at_vector( pExpr->u2.args, index );
		argResult = 
			mk_execute_expr( vm, pTarget, 0 );
		if( argResult != MK_VM_EXECUTE_EXPR_RETURN_NEXTSTEP )
			break;	// error
	}
	if( index == size )
		return mk_vm_call_method( vm, pMethod );
	else
		return MK_VM_EXECUTE_EXPR_THROW;	// todo: create exception object

}
