Пример #1
0
/*
expr_shift -> expr_additive
	| expr_shift '<<' expr_additive
	| expr_shift '>>' expr_additive
*/
static struct finsh_node* proc_shift_expr(struct finsh_parser* self)
{
	enum finsh_token_type token;
	struct finsh_node* add;
	struct finsh_node* add_new;

	add = proc_additive_expr(self);

	next_token(token, &(self->token));
	while ( token == finsh_token_type_shl || token == finsh_token_type_shr)
	{
		add_new = proc_additive_expr(self);
		if (add_new == NULL) finsh_error_set(FINSH_ERROR_EXPECT_OPERATOR);
		else
		{
			switch (token)
			{
			case finsh_token_type_shl:
				add = make_sys_node(FINSH_NODE_SYS_SHL, add, add_new);
				break;
			case finsh_token_type_shr:
				add = make_sys_node(FINSH_NODE_SYS_SHR, add, add_new);
				break;
			default:
				finsh_error_set(FINSH_ERROR_EXPECT_OPERATOR);
				break;
			}
		}
		next_token(token, &(self->token));
	}

	finsh_token_replay(&(self->token));
	return add;
}
Пример #2
0
struct finsh_node* finsh_node_new_id(char* id)
{
	struct finsh_node* node;
	void*  symbol;
	unsigned char type;

	symbol	= NULL;
	type	= 0;
	node	= NULL;

	/* lookup variable firstly */
	symbol = (void*)finsh_var_lookup(id);
	if (symbol == NULL)
	{
		/* then lookup system variable */
		symbol = (void*)finsh_sysvar_lookup(id);
		if (symbol == NULL)
		{
			/* then lookup system call */
			symbol = (void*)finsh_syscall_lookup(id);
			if (symbol != NULL) type = FINSH_IDTYPE_SYSCALL;
		}
		else type = FINSH_IDTYPE_SYSVAR;
	}
	else type = FINSH_IDTYPE_VAR;

	if (symbol != NULL)
	{
		/* allocate a new node */
		node = finsh_node_allocate(FINSH_NODE_ID);

		/* allocate node error */
		if (node == NULL)
		{
			finsh_error_set(FINSH_ERROR_MEMORY_FULL);
			return NULL;
		}

		/* fill node value according type */
		switch (type)
		{
		case FINSH_IDTYPE_VAR:
			node->id.var = (struct finsh_var*)symbol;
			break;

		case FINSH_IDTYPE_SYSVAR:
			node->id.sysvar = (struct finsh_sysvar*)symbol;
			break;

		case FINSH_IDTYPE_SYSCALL:
			node->id.syscall = (struct finsh_syscall*)symbol;
			break;
		}
		/* fill identifier type */
		node->idtype = type;
	}
	else finsh_error_set(FINSH_ERROR_UNKNOWN_SYMBOL);

	return node;
}
Пример #3
0
/*
expr_additive -> expr_multiplicative
	| expr_additive SUB expr_multiplicative
	| expr_additive ADD expr_multiplicative
*/
static struct finsh_node* proc_additive_expr(struct finsh_parser* self)
{
	enum finsh_token_type token;
	struct finsh_node* mul;
	struct finsh_node* mul_new;

	mul = proc_multiplicative_expr(self);

	next_token(token, &(self->token));
	while ( token == finsh_token_type_sub || token == finsh_token_type_add )
	{
		mul_new = proc_multiplicative_expr(self);
		if (mul_new == NULL) finsh_error_set(FINSH_ERROR_EXPECT_OPERATOR);
		else
		{
			switch (token)
			{
			case finsh_token_type_sub:
				mul = make_sys_node(FINSH_NODE_SYS_SUB, mul, mul_new);
				break;
			case finsh_token_type_add:
				mul = make_sys_node(FINSH_NODE_SYS_ADD, mul, mul_new);
				break;
			default:
				finsh_error_set(FINSH_ERROR_EXPECT_OPERATOR);
				break;
			}
		}
		next_token(token, &(self->token));
	}

	finsh_token_replay(&(self->token));
	return mul;
}
static u_char* token_proc_string(struct finsh_token* self)
{
	u_char* p;

	for ( p = &self->string[0]; p - &(self->string[0]) < FINSH_STRING_MAX; )
	{
		char ch = token_next_char(self);

		if ( is_eof(self) )
		{
			finsh_error_set(FINSH_ERROR_UNEXPECT_END);
			return NULL;;
		}
		if ( ch == '\\' )
		{
			ch = token_proc_escape(self);
		}
		else if ( ch == '"' )/*end of string.*/
		{
			*p = '\0';
			return self->string;
		}

		*p++ = ch;
	}

	return NULL;
}
Пример #5
0
/*
expr_multiplicative -> expr_cast
	| expr_multiplicative '*' expr_cast
	| expr_multiplicative '/' expr_cast
	| expr_multiplicative '%' expr_cast
*/
static struct finsh_node* proc_multiplicative_expr(struct finsh_parser* self)
{
	enum finsh_token_type token;
	struct finsh_node* cast;
	struct finsh_node* cast_new;

	cast = proc_cast_expr(self);
	next_token(token, &(self->token));
	while (token == finsh_token_type_mul ||
		token == finsh_token_type_div ||
		token == finsh_token_type_mod )
	{
		cast_new = proc_cast_expr(self);
		if (cast_new == NULL) finsh_error_set(FINSH_ERROR_EXPECT_OPERATOR);
		else
		{
			switch (token)
			{
			case finsh_token_type_mul:
				cast = make_sys_node(FINSH_NODE_SYS_MUL, cast, cast_new);
				break;

			case finsh_token_type_div:
				cast = make_sys_node(FINSH_NODE_SYS_DIV, cast, cast_new);
				break;

			case finsh_token_type_mod:
				cast = make_sys_node(FINSH_NODE_SYS_MOD, cast, cast_new);
				break;

			default:
				finsh_error_set(FINSH_ERROR_EXPECT_OPERATOR);
				break;
			}
		}
		next_token(token, &(self->token));
	}

	finsh_token_replay(&(self->token));
	return cast;
}
Пример #6
0
static char token_proc_char(struct finsh_token* self)
{
	char ch;
	char buf[4], *p;

	p = buf;
	ch = token_next_char(self);

	if ( ch == '\\' ) {
		ch = token_next_char(self);
		switch ( ch ) {
		case 'n':
			ch = '\n';
			break;
		case 't':
			ch = '\t';
			break;
		case 'v':
			ch = '\v';
			break;
		case 'b':
			ch = '\b';
			break;
		case 'r':
			ch = '\r';
			break;
		case '\\':
			ch = '\\';
			break;
		case '\'':
			ch = '\'';
			break;
		default :
			while ( is_digit(ch) ) { /*for '\113' char*/
				ch = token_next_char(self);
				*p++ = ch;
			}

			token_prev_char(self);
			*p = '\0';
			ch = atoi(p);
			break;
		}
	}

	if ( token_next_char(self) != '\'' ) {
		token_prev_char(self);
		finsh_error_set(FINSH_ERROR_EXPECT_CHAR);
		return ch;
	}

	return ch;
}
Пример #7
0
struct finsh_node* finsh_node_new_ptr(void* ptr)
{
	struct finsh_node* node;

	node = finsh_node_allocate(FINSH_NODE_VALUE_NULL);
	if (node == NULL) {
		finsh_error_set(FINSH_ERROR_MEMORY_FULL);
		return NULL;
	}

	node->value.ptr = ptr;
	return node;
}
Пример #8
0
struct finsh_node* finsh_node_new_long(long l)
{
	struct finsh_node* node;

	node = finsh_node_allocate(FINSH_NODE_VALUE_LONG);
	if (node == NULL) {
		finsh_error_set(FINSH_ERROR_MEMORY_FULL);
		return NULL;
	}

	node->value.long_value = l;
	return node;
}
Пример #9
0
struct finsh_node* finsh_node_new_int(int i)
{
	struct finsh_node* node;

	node = finsh_node_allocate(FINSH_NODE_VALUE_INT);
	if (node == NULL) {
		finsh_error_set(FINSH_ERROR_MEMORY_FULL);
		return NULL;
	}

	node->value.int_value = i;
	return node;
}
Пример #10
0
struct finsh_node* finsh_node_new_char(char c)
{
	struct finsh_node* node;

	node = finsh_node_allocate(FINSH_NODE_VALUE_CHAR);
	if (node == NULL) {
		finsh_error_set(FINSH_ERROR_MEMORY_FULL);
		return NULL;
	}

	node->value.char_value = c;
	return node;
}
Пример #11
0
/*
make a new node as following tree:
new_node
|
node1__
       \
       node2
*/
static struct finsh_node* make_sys_node(u_char type, struct finsh_node* node1, struct finsh_node* node2)
{
	struct finsh_node* node;

	node = finsh_node_allocate(type);

	if ((node1 != NULL) && (node != NULL))
	{
		finsh_node_child(node) = node1;
		finsh_node_sibling(node1) = node2;
	}
	else finsh_error_set(FINSH_ERROR_NULL_NODE);

	return node;
}
Пример #12
0
struct finsh_node* finsh_node_new_string(char* s)
{
	struct finsh_node* node;

	node = finsh_node_allocate(FINSH_NODE_VALUE_STRING);
	if (node == NULL) {
		finsh_error_set(FINSH_ERROR_MEMORY_FULL);
		return NULL;
	}

	/* make string */
	node->value.ptr = finsh_heap_allocate(strlen(s) + 1);
	strncpy(node->value.ptr, s, strlen(s));
	((u_char*)node->value.ptr)[strlen(s)] = '\0';

	return node;
}
Пример #13
0
/*
expr_primary -> literal
	| '(' expr ')'
	| identifier
*/
static struct finsh_node* proc_primary_expr(struct finsh_parser* self)
{
	enum finsh_token_type token;
	struct finsh_node* expr;

	next_token(token, &(self->token));
	switch ( token )
	{
	case finsh_token_type_identifier:
		{
			char id[FINSH_NAME_MAX + 1];

			finsh_token_replay(&(self->token));
			proc_identifier(self, id);
			return finsh_node_new_id(id);
		}

	case finsh_token_type_left_paren:
		expr = proc_expr(self);
		match_token(token, &(self->token), finsh_token_type_right_paren);
		return expr;

	case finsh_token_type_value_int:
		return finsh_node_new_int(self->token.value.int_value);

	case finsh_token_type_value_long:
		return finsh_node_new_long(self->token.value.long_value);

	case finsh_token_type_value_char:
		return finsh_node_new_char(self->token.value.char_value);

	case finsh_token_type_value_string:
		return finsh_node_new_string((char*)self->token.string);

	case finsh_token_type_value_null:
		return finsh_node_new_ptr(NULL);

	default:
		finsh_error_set(FINSH_ERROR_INVALID_TOKEN);
		break;
	}

	return NULL;
}
Пример #14
0
/*
expr_exclusive_or -> expr_and
	| expr_exclusive '^' expr_and
*/
static struct finsh_node* proc_exclusive_or_expr(struct finsh_parser* self)
{
	enum finsh_token_type token;
	struct finsh_node* and;
	struct finsh_node* and_new;

	and = proc_and_expr(self);
	next_token(token, &(self->token));
	while ( token == finsh_token_type_xor )
	{
		and_new = proc_and_expr(self);
		if (and_new == NULL) finsh_error_set(FINSH_ERROR_EXPECT_OPERATOR);
		else and = make_sys_node(FINSH_NODE_SYS_XOR, and, and_new);

		next_token(token, &(self->token));
	}

	finsh_token_replay(&(self->token));
	return and;
}
Пример #15
0
/*
expr_and -> expr_shift
	| expr_and '&' expr_shift
*/
static struct finsh_node* proc_and_expr(struct finsh_parser* self)
{
	enum finsh_token_type token;
	struct finsh_node* shift;
	struct finsh_node* shift_new;

	shift = proc_shift_expr(self);

	next_token(token, &(self->token));
	while ( token == finsh_token_type_and )
	{
		shift_new = proc_shift_expr(self);

		if (shift_new == NULL) finsh_error_set(FINSH_ERROR_EXPECT_OPERATOR);
		else shift = make_sys_node(FINSH_NODE_SYS_AND, shift, shift_new);

		next_token(token, &(self->token));
	}

	finsh_token_replay(&(self->token));
	return shift;
}
Пример #16
0
/*
expr_inclusive_or -> expr_exclusive_or
	| expr_inclusive_or '|' expr_exclusive_or
*/
static struct finsh_node* proc_inclusive_or_expr(struct finsh_parser* self)
{
	enum finsh_token_type token;
	struct finsh_node* xor;
	struct finsh_node* xor_new;

	xor = proc_exclusive_or_expr(self);

	next_token(token, &(self->token));
	while ( token == finsh_token_type_or )
	{
		xor_new = proc_exclusive_or_expr(self);

		if (xor_new == NULL) finsh_error_set(FINSH_ERROR_EXPECT_OPERATOR);
		else xor = make_sys_node(FINSH_NODE_SYS_OR, xor, xor_new);

		next_token(token, &(self->token));
	}

	finsh_token_replay(&(self->token));
	return xor;
}
Пример #17
0
/*
param_list -> empty
	| expr_assign
	| param_list ',' expr_assign
*/
static struct finsh_node* proc_param_list(struct finsh_parser* self)
{
	enum finsh_token_type token;
	struct finsh_node *node, *assign;

	assign = proc_assign_expr(self);
	if (assign == NULL) return NULL;
	node = assign;

	next_token(token, &(self->token));
	while (token == finsh_token_type_comma )
	{
		finsh_node_sibling(assign) = proc_assign_expr(self);

		if (finsh_node_sibling(assign) != NULL)	assign = finsh_node_sibling(assign);
		else finsh_error_set(FINSH_ERROR_EXPECT_OPERATOR);

		next_token(token, &(self->token));
	}

	finsh_token_replay(&(self->token));

	return node;
}
Пример #18
0
static void token_run(struct finsh_token* self)
{
	char ch;

	token_trim_space(self); /* first trim space and tab. */
	token_get_string(self, &(self->string[0]));

	if ( is_eof(self) ) { /*if it is eof, break;*/
		self->current_token = finsh_token_type_eof;
		return ;
	}

	if (self->string[0] != '\0') { /*It is a key word or a identifier.*/
		if ( !token_match_name(self, (char*)self->string) ) {
			self->current_token = finsh_token_type_identifier;
		}
		return;
	} else { /*It is a operator character.*/
		ch = token_next_char(self);

		switch ( ch ) {
		case '(':
			self->current_token = finsh_token_type_left_paren;
			break;

		case ')':
			self->current_token = finsh_token_type_right_paren;
			break;

		case ',':
			self->current_token = finsh_token_type_comma;
			break;

		case ';':
			self->current_token = finsh_token_type_semicolon;
			break;

		case '&':
			self->current_token = finsh_token_type_and;
			break;

		case '*':
			self->current_token = finsh_token_type_mul;
			break;

		case '+':
			ch = token_next_char(self);

			if ( ch == '+' ) {
				self->current_token = finsh_token_type_inc;
			} else {
				token_prev_char(self);
				self->current_token = finsh_token_type_add;
			}
			break;

		case '-':
			ch = token_next_char(self);

			if ( ch == '-' ) {
				self->current_token = finsh_token_type_dec;
			} else {
				token_prev_char(self);
				self->current_token = finsh_token_type_sub;
			}
			break;

		case '/':
			ch = token_next_char(self);
			if (ch == '/') {
				/* line comments, set to end of file */
				self->current_token = finsh_token_type_eof;
			} else {
				token_prev_char(self);
				self->current_token = finsh_token_type_div;
			}
			break;

		case '<':
			ch = token_next_char(self);

			if ( ch == '<' ) {
				self->current_token = finsh_token_type_shl;
			} else {
				token_prev_char(self);
				self->current_token = finsh_token_type_bad;
			}
			break;

		case '>':
			ch = token_next_char(self);

			if ( ch == '>' ) {
				self->current_token = finsh_token_type_shr;
			} else {
				token_prev_char(self);
				self->current_token = finsh_token_type_bad;
			}
			break;

		case '|':
			self->current_token = finsh_token_type_or;
			break;

		case '%':
			self->current_token = finsh_token_type_mod;
			break;

		case '~':
			self->current_token = finsh_token_type_bitwise;
			break;

		case '^':
			self->current_token = finsh_token_type_xor;
			break;

		case '=':
			self->current_token = finsh_token_type_assign;
			break;

		case '\'':
			self->value.char_value = token_proc_char(self);
			self->current_token = finsh_token_type_value_char;
			break;

		case '"':
			token_proc_string(self);
			self->current_token = finsh_token_type_value_string;
			break;

		default:
			if ( is_digit(ch) ) {
				token_prev_char(self);
				token_proc_number(self);
				break;
			}

			finsh_error_set(FINSH_ERROR_UNKNOWN_TOKEN);
			self->current_token = finsh_token_type_bad;

			break;
		}
	}
}
Пример #19
0
/*
type -> type_prefix type_basic | type_basic
type_prefix -> UNSIGNED
type_basic -> VOID
	| CHAR
	| SHORT
	| INT
	| STRING
*/
static enum finsh_type proc_type(struct finsh_parser* self)
{
	enum finsh_type type;
	enum finsh_token_type token;

	/* set init type */
	type = finsh_type_unknown;

	next_token(token, &(self->token));
	if ( is_base_type(token) ) /* base_type */
	{
		switch (token)
		{
		case finsh_token_type_void:
			type = finsh_type_void;
			break;

		case finsh_token_type_char:
			type = finsh_type_char;
			break;

		case finsh_token_type_short:
			type = finsh_type_short;
			break;

		case finsh_token_type_int:
			type = finsh_type_int;
			break;

		case finsh_token_type_long:
			type = finsh_type_long;
			break;

		default:
			goto __return;
		}
	}
	else if ( token == finsh_token_type_unsigned ) /* unsigned base_type */
	{
		next_token(token, &(self->token));
		if ( is_base_type(token) )
		{
			switch (token)
			{
			case finsh_token_type_char:
				type = finsh_type_uchar;
				break;

			case finsh_token_type_short:
				type = finsh_type_ushort;
				break;

			case finsh_token_type_int:
				type = finsh_type_uint;
				break;

			case finsh_token_type_long:
				type = finsh_type_ulong;
				break;

			default:
				goto __return;
			}
		}
		else
		{
			finsh_token_replay(&(self->token));
			finsh_error_set(FINSH_ERROR_EXPECT_TYPE);
		}
	}
	else
	{
		goto __return;
	}

	/* parse for pointer */
	next_token(token, &(self->token));
	if (token == finsh_token_type_mul)
	{
		switch (type)
		{
		case finsh_type_void:
			type = finsh_type_voidp;
			break;

		case finsh_type_char:
		case finsh_type_uchar:
			type = finsh_type_charp;
			break;

		case finsh_type_short:
		case finsh_type_ushort:
			type = finsh_type_shortp;
			break;

		case finsh_type_int:
		case finsh_type_uint:
			type = finsh_type_intp;
			break;

		case finsh_type_long:
		case finsh_type_ulong:
			type = finsh_type_longp;
			break;

		default:
			type = finsh_type_voidp;
			break;
		}
	}
	else finsh_token_replay(&(self->token));

	return type;

__return:
	finsh_token_replay(&(self->token));
	finsh_error_set(FINSH_ERROR_UNKNOWN_TYPE);

	return type;
}
static int finsh_type_check(struct finsh_node* node, u_char is_addr)
{
    if (node != NULL)
    {
        /* address & value */
        if (node->node_type == FINSH_NODE_SYS_ASSIGN ||
            node->node_type == FINSH_NODE_SYS_PREINC ||
            node->node_type == FINSH_NODE_SYS_PREDEC ||
            node->node_type == FINSH_NODE_SYS_GETADDR)
        {
            /* address */
            finsh_type_check(finsh_node_child(node), FINSH_IDTYPE_ADDRESS);
        }
        else if (node->node_type == FINSH_NODE_SYS_GETVALUE && is_addr)
        {
            /* change the attribute of getvalue in left expr */
            finsh_type_check(finsh_node_child(node), 0);
        }
        else
        {
            /* transfer 'av' to child node */
            finsh_type_check(finsh_node_child(node), is_addr);
        }

        /* always does not load address in sibling */
        finsh_type_check(finsh_node_sibling(node), FINSH_NODE_VALUE);

        /** set attribute of current node */

        /* make sure the current node is address or value */
        if (node->idtype != FINSH_IDTYPE_SYSCALL) node->idtype |= is_addr;

        if (finsh_node_child(node) != NULL)
        {
            node->data_type = finsh_node_child(node)->data_type;
            return 0;
        }

        if (node->node_type == FINSH_NODE_ID)
        {
            if (node->idtype & FINSH_IDTYPE_VAR)
            {
                struct finsh_var* var;

                var = node->id.var;
                if (var != NULL)
                {
                    switch (var->type)
                    {
                    case finsh_type_void:
                        node->data_type = FINSH_DATA_TYPE_VOID;
                        break;

                    case finsh_type_char:
                    case finsh_type_uchar:
                        node->data_type = FINSH_DATA_TYPE_BYTE;
                        break;

                    case finsh_type_short:
                    case finsh_type_ushort:
                        node->data_type = FINSH_DATA_TYPE_WORD;
                        break;

                    case finsh_type_int:
                    case finsh_type_uint:
                    case finsh_type_long:
                    case finsh_type_ulong:
                        node->data_type = FINSH_DATA_TYPE_DWORD;
                        break;

                    case finsh_type_charp:
                    case finsh_type_voidp:
                    case finsh_type_shortp:
                    case finsh_type_intp:
                    case finsh_type_longp:
                        node->data_type = FINSH_DATA_TYPE_DWORD;
                        break;

                    default:
                        finsh_error_set(FINSH_ERROR_UNKNOWN_TYPE);
                        break;
                    }
                }
            }
            else if (node->idtype & FINSH_IDTYPE_SYSVAR)
            {
                struct finsh_sysvar *sysvar;

                sysvar = node->id.sysvar;
                if (sysvar != NULL)
                {
                    switch (sysvar->type)
                    {
                    case finsh_type_void:
                        node->data_type = FINSH_DATA_TYPE_VOID;
                        break;

                    case finsh_type_char:
                    case finsh_type_uchar:
                        node->data_type = FINSH_DATA_TYPE_BYTE;
                        break;

                    case finsh_type_short:
                    case finsh_type_ushort:
                        node->data_type = FINSH_DATA_TYPE_WORD;
                        break;

                    case finsh_type_int:
                    case finsh_type_uint:
                    case finsh_type_long:
                    case finsh_type_ulong:
                        node->data_type = FINSH_DATA_TYPE_DWORD;
                        break;

                    case finsh_type_charp:
                    case finsh_type_voidp:
                    case finsh_type_shortp:
                    case finsh_type_intp:
                    case finsh_type_longp:
                        node->data_type = FINSH_DATA_TYPE_DWORD;
                        break;

                    default:
                        finsh_error_set(FINSH_ERROR_UNKNOWN_TYPE);
                        break;
                    }
                }
            }
        }
        else if (node->node_type == FINSH_NODE_VALUE_CHAR)
        {
            node->data_type = FINSH_DATA_TYPE_BYTE;
        }
        else if (node->node_type == FINSH_NODE_VALUE_INT ||
            node->node_type == FINSH_NODE_VALUE_LONG    ||
            node->node_type == FINSH_NODE_VALUE_STRING  ||
            node->node_type == FINSH_NODE_VALUE_NULL)
        {
            node->data_type = FINSH_DATA_TYPE_DWORD;
        }
    }
    return 0;
}
Пример #21
0
/*
process for function and variable declaration.
decl_variable -> type declaration_list ';'
declarator_list -> declarator_list ',' declarator
	| declarator
declarator -> identifier
	| identifier ASSIGN expr_assign
*/
static struct finsh_node* proc_variable_decl(struct finsh_parser* self)
{
	enum finsh_token_type token;
	enum finsh_type type;
	char id[FINSH_NAME_MAX + 1];

	struct finsh_node *node;
	struct finsh_node *end;
	struct finsh_node *assign;

    node = NULL;
	end  = NULL;

	/* get type */
	type = proc_type(self);

	/*process id.*/
	if (proc_identifier(self, id) == 0)
	{
		/* if add variable failed */
		if (finsh_var_insert(id, type) < 0)
		{
			finsh_error_set(FINSH_ERROR_VARIABLE_EXIST);
		}
	}

	next_token(token, &(self->token));
	switch ( token )
	{
	case finsh_token_type_comma:/*',', it's a variable_list declaration.*/
		if (proc_identifier(self, id) == 0)
		{
			/* if add variable failed */
			if (finsh_var_insert(id, type) < 0)
			{
				finsh_error_set(FINSH_ERROR_VARIABLE_EXIST);
			}
		}

		next_token(token, &(self->token));
		if ( token == finsh_token_type_assign )
		{
			/* get the right side of assign expression */
			assign = proc_assign_expr(self);

			if (assign != NULL)
			{
				struct finsh_node* idnode;

				idnode = finsh_node_new_id(id);
				end = make_sys_node(FINSH_NODE_SYS_ASSIGN, idnode, assign);
				node = end;

				next_token(token, &(self->token));
			}
		}

		while ( token == finsh_token_type_comma )
		{
			if (proc_identifier(self, id) == 0)
			{
				/* if add variable failed */
				if (finsh_var_insert(id, type) < 0)
				{
					finsh_error_set(FINSH_ERROR_VARIABLE_EXIST);
				}
			}

			next_token(token, &(self->token));
			if ( token == finsh_token_type_assign )
			{
				/* get the right side of assign expression */
				assign = proc_assign_expr(self);

				if (assign != NULL)
				{
					struct finsh_node* idnode;

					idnode = finsh_node_new_id(id);

					/* make assign expression node */
					if (node != NULL)
					{
						finsh_node_sibling(end) = make_sys_node(FINSH_NODE_SYS_ASSIGN, idnode, assign);
						end = finsh_node_sibling(end);
					}
					else
					{
						end = make_sys_node(FINSH_NODE_SYS_ASSIGN, idnode, assign);
						node = end;
					}

					next_token(token, &(self->token));
				}
			}
		}

		check_token(token, &(self->token), finsh_token_type_semicolon);
		return node;

	case finsh_token_type_assign:/*'=', it's a variable with assign declaration.*/
	{
		struct finsh_node *idnode;

		assign = proc_assign_expr(self);
		if (assign != NULL)
		{
			idnode = finsh_node_new_id(id);

			/* make assign expression node */
			end = make_sys_node(FINSH_NODE_SYS_ASSIGN, idnode, assign);
			node = end;

			next_token(token, &(self->token));
		}

		while ( token == finsh_token_type_comma )
		{
			if (proc_identifier(self, id) == 0)
			{
				/* if add variable failed */
				if (finsh_var_insert(id, type) < 0)
				{
					finsh_error_set(FINSH_ERROR_VARIABLE_EXIST);
				}
			}

			next_token(token, &(self->token));
			if (token == finsh_token_type_assign)
			{
				/* get the right side of assign expression */
				assign = proc_assign_expr(self);

				if (assign != NULL)
				{
					idnode = finsh_node_new_id(id);

					/* make assign expression node */
					if (node != NULL)
					{
						finsh_node_sibling(end) = make_sys_node(FINSH_NODE_SYS_ASSIGN, idnode, assign);
						end = finsh_node_sibling(end);
					}
					else
					{
						end = make_sys_node(FINSH_NODE_SYS_ASSIGN, idnode, assign);
						node = end;
					}

					next_token(token, &(self->token));
				}
			}
		}

		check_token(token, &(self->token), finsh_token_type_semicolon);
		return node;
	}

	case finsh_token_type_semicolon:/*';', it's a variable declaration.*/
		return node;

	default:
		finsh_error_set(FINSH_ERROR_EXPECT_TYPE);

		return NULL;
	}
}
static int finsh_compile(struct finsh_node* node)
{
    if (node != NULL)
    {
        /* compile child node */
        if (finsh_node_child(node) != NULL)
            finsh_compile(finsh_node_child(node));

        /* compile current node */
        switch (node->node_type)
        {
        case FINSH_NODE_ID:
            {
                /* identifier::syscall */
                if (node->idtype & FINSH_IDTYPE_SYSCALL)
                {
                    /* load address */
                    finsh_code_byte(FINSH_OP_LD_DWORD);
                    finsh_code_dword((long)node->id.syscall->func);
                }
                /* identifier::sysvar */
                else if (node->idtype & FINSH_IDTYPE_SYSVAR)
                {
                    struct finsh_sysvar* sysvar;

                    sysvar = node->id.sysvar;
                    if (sysvar != NULL)
                    {
                        switch (sysvar->type)
                        {
                        case finsh_type_char:
                        case finsh_type_uchar:
                            if (node->idtype & FINSH_IDTYPE_ADDRESS)
                            {
                                /* load address */
                                finsh_code_byte(FINSH_OP_LD_DWORD);
                            }
                            else
                            {
                                /* load value */
                                finsh_code_byte(FINSH_OP_LD_VALUE_BYTE);
                            }

                            finsh_code_dword((long)(sysvar->var));
                            break;

                        case finsh_type_short:
                        case finsh_type_ushort:
                            if (node->idtype & FINSH_IDTYPE_ADDRESS)
                            {
                                /* load address */
                                finsh_code_byte(FINSH_OP_LD_DWORD);
                            }
                            else
                            {
                                /* load value */
                                finsh_code_byte(FINSH_OP_LD_VALUE_WORD);
                            }

                            finsh_code_dword((long)(sysvar->var));
                            break;

                        case finsh_type_int:
                        case finsh_type_uint:
                        case finsh_type_long:
                        case finsh_type_ulong:
                        case finsh_type_charp:
                        case finsh_type_shortp:
                        case finsh_type_intp:
                        case finsh_type_longp:
                            if (node->idtype & FINSH_IDTYPE_ADDRESS)
                            {
                                /* load address */
                                finsh_code_byte(FINSH_OP_LD_DWORD);
                            }
                            else
                            {
                                /* load value */
                                finsh_code_byte(FINSH_OP_LD_VALUE_DWORD);
                            }

                            finsh_code_dword((long)(sysvar->var));
                            break;
                        }
                    }
                }
                /* identifier::var */
                else
                {
                    struct finsh_var* var;

                    var = node->id.var;
                    if (var != NULL)
                    {
                        switch (var->type)
                        {
                        case finsh_type_char:
                        case finsh_type_uchar:
                            if (node->idtype & FINSH_IDTYPE_ADDRESS)
                            {
                                /* load address */
                                finsh_code_byte(FINSH_OP_LD_DWORD);
                            }
                            else
                            {
                                /* load value */
                                finsh_code_byte(FINSH_OP_LD_VALUE_BYTE);
                            }

                            finsh_code_dword((long)&(var->value.char_value));
                            break;

                        case finsh_type_short:
                        case finsh_type_ushort:
                            if (node->idtype & FINSH_IDTYPE_ADDRESS)
                            {
                                /* load address */
                                finsh_code_byte(FINSH_OP_LD_DWORD);
                            }
                            else
                            {
                                /* load value */
                                finsh_code_byte(FINSH_OP_LD_VALUE_WORD);
                            }

                            finsh_code_dword((long)&(var->value.short_value));
                            break;

                        case finsh_type_int:
                        case finsh_type_uint:
                        case finsh_type_long:
                        case finsh_type_ulong:
                        case finsh_type_charp:
                        case finsh_type_shortp:
                        case finsh_type_intp:
                        case finsh_type_longp:
                            if (node->idtype & FINSH_IDTYPE_ADDRESS)
                            {
                                /* load address */
                                finsh_code_byte(FINSH_OP_LD_DWORD);
                            }
                            else
                            {
                                /* load value */
                                finsh_code_byte(FINSH_OP_LD_VALUE_DWORD);
                            }

                            finsh_code_dword((long)&(var->value.long_value));
                            break;
                        }
                    }
                }
            }
            break;

        /* load const */
        case FINSH_NODE_VALUE_CHAR:
            finsh_code_byte(FINSH_OP_LD_BYTE);
            finsh_code_byte(node->value.char_value);
            break;

        case FINSH_NODE_VALUE_INT:
        case FINSH_NODE_VALUE_LONG:
            finsh_code_byte(FINSH_OP_LD_DWORD);
            finsh_code_dword(node->value.long_value);
            break;

        case FINSH_NODE_VALUE_NULL:
        case FINSH_NODE_VALUE_STRING:
            finsh_code_byte(FINSH_OP_LD_DWORD);
            finsh_code_dword((u_long)node->value.ptr);
            break;

        /* arithmetic operation */
        case FINSH_NODE_SYS_ADD:
            if (node->data_type == FINSH_DATA_TYPE_BYTE) finsh_code_byte(FINSH_OP_ADD_BYTE);
            else if (node->data_type == FINSH_DATA_TYPE_WORD) finsh_code_byte(FINSH_OP_ADD_WORD);
            else if (node->data_type == FINSH_DATA_TYPE_DWORD) finsh_code_byte(FINSH_OP_ADD_DWORD);
            break;

        case FINSH_NODE_SYS_SUB:
            if (node->data_type == FINSH_DATA_TYPE_BYTE) finsh_code_byte(FINSH_OP_SUB_BYTE);
            else if (node->data_type == FINSH_DATA_TYPE_WORD) finsh_code_byte(FINSH_OP_SUB_WORD);
            else if (node->data_type == FINSH_DATA_TYPE_DWORD) finsh_code_byte(FINSH_OP_SUB_DWORD);
            break;

        case FINSH_NODE_SYS_MUL:
            if (node->data_type == FINSH_DATA_TYPE_BYTE) finsh_code_byte(FINSH_OP_MUL_BYTE);
            else if (node->data_type == FINSH_DATA_TYPE_WORD) finsh_code_byte(FINSH_OP_MUL_WORD);
            else if (node->data_type == FINSH_DATA_TYPE_DWORD) finsh_code_byte(FINSH_OP_MUL_DWORD);
            break;

        case FINSH_NODE_SYS_DIV:
            if (node->data_type == FINSH_DATA_TYPE_BYTE) finsh_code_byte(FINSH_OP_DIV_BYTE);
            else if (node->data_type == FINSH_DATA_TYPE_WORD) finsh_code_byte(FINSH_OP_DIV_WORD);
            else if (node->data_type == FINSH_DATA_TYPE_DWORD) finsh_code_byte(FINSH_OP_DIV_DWORD);
            break;

        case FINSH_NODE_SYS_MOD:
            if (node->data_type == FINSH_DATA_TYPE_BYTE) finsh_code_byte(FINSH_OP_MOD_BYTE);
            else if (node->data_type == FINSH_DATA_TYPE_WORD) finsh_code_byte(FINSH_OP_MOD_WORD);
            else if (node->data_type == FINSH_DATA_TYPE_DWORD) finsh_code_byte(FINSH_OP_MOD_DWORD);
            break;

        /* bit operation */
        case FINSH_NODE_SYS_AND:
            if (node->data_type == FINSH_DATA_TYPE_BYTE) finsh_code_byte(FINSH_OP_AND_BYTE);
            else if (node->data_type == FINSH_DATA_TYPE_WORD) finsh_code_byte(FINSH_OP_AND_WORD);
            else if (node->data_type == FINSH_DATA_TYPE_DWORD) finsh_code_byte(FINSH_OP_AND_DWORD);
            break;

        case FINSH_NODE_SYS_OR:
            if (node->data_type == FINSH_DATA_TYPE_BYTE) finsh_code_byte(FINSH_OP_OR_BYTE);
            else if (node->data_type == FINSH_DATA_TYPE_WORD) finsh_code_byte(FINSH_OP_OR_WORD);
            else if (node->data_type == FINSH_DATA_TYPE_DWORD) finsh_code_byte(FINSH_OP_OR_DWORD);
            break;

        case FINSH_NODE_SYS_XOR:
            if (node->data_type == FINSH_DATA_TYPE_BYTE) finsh_code_byte(FINSH_OP_XOR_BYTE);
            else if (node->data_type == FINSH_DATA_TYPE_WORD) finsh_code_byte(FINSH_OP_XOR_WORD);
            else if (node->data_type == FINSH_DATA_TYPE_DWORD) finsh_code_byte(FINSH_OP_XOR_DWORD);
            break;

        case FINSH_NODE_SYS_BITWISE:
            if (node->data_type == FINSH_DATA_TYPE_BYTE) finsh_code_byte(FINSH_OP_BITWISE_BYTE);
            else if (node->data_type == FINSH_DATA_TYPE_WORD) finsh_code_byte(FINSH_OP_BITWISE_WORD);
            else if (node->data_type == FINSH_DATA_TYPE_DWORD) finsh_code_byte(FINSH_OP_BITWISE_DWORD);
            break;

        case FINSH_NODE_SYS_SHL:
            if (node->data_type == FINSH_DATA_TYPE_BYTE) finsh_code_byte(FINSH_OP_SHL_BYTE);
            else if (node->data_type == FINSH_DATA_TYPE_WORD) finsh_code_byte(FINSH_OP_SHL_WORD);
            else if (node->data_type == FINSH_DATA_TYPE_DWORD) finsh_code_byte(FINSH_OP_SHL_DWORD);
            break;

        case FINSH_NODE_SYS_SHR:
            if (node->data_type == FINSH_DATA_TYPE_BYTE) finsh_code_byte(FINSH_OP_SHR_BYTE);
            else if (node->data_type == FINSH_DATA_TYPE_WORD) finsh_code_byte(FINSH_OP_SHR_WORD);
            else if (node->data_type == FINSH_DATA_TYPE_DWORD) finsh_code_byte(FINSH_OP_SHR_DWORD);
            break;

        /* syscall */
        case FINSH_NODE_SYS_FUNC:
            {
                int parameters;
                struct finsh_node* sibling;

                parameters = 0;
                if (finsh_node_child(node) != NULL)
                {
                    sibling = finsh_node_sibling(finsh_node_child(node));
                    while (sibling != NULL)
                    {
                        parameters ++;
                        sibling = finsh_node_sibling(sibling);
                    }

                    /* load address of function */
                    // finsh_code_dword((long)&(node->var->value.ptr));

                    /* syscall parameters */
                    finsh_code_byte(FINSH_OP_SYSCALL);
                    finsh_code_byte(parameters);
                }
            }
            break;

        /* assign expression */
        case FINSH_NODE_SYS_ASSIGN:
            if (finsh_node_child(node) && finsh_node_child(node)->node_type == FINSH_NODE_ID)
            {
                switch (finsh_node_child(node)->data_type)
                {
                case FINSH_DATA_TYPE_BYTE:
                    finsh_code_byte(FINSH_OP_ST_BYTE);

                    /* load value again */
                    finsh_code_byte(FINSH_OP_LD_VALUE_BYTE_STACK);
                    break;

                case FINSH_DATA_TYPE_WORD:
                    finsh_code_byte(FINSH_OP_ST_WORD);

                    /* load value again */
                    finsh_code_byte(FINSH_OP_LD_VALUE_WORD_STACK);
                    break;

                case FINSH_DATA_TYPE_DWORD:
                    finsh_code_byte(FINSH_OP_ST_DWORD);

                    /* load value again */
                    finsh_code_byte(FINSH_OP_LD_VALUE_DWORD_STACK);
                    break;

                default:
                    finsh_error_set(FINSH_ERROR_UNKNOWN_TYPE);
                }
            }
            else if (finsh_node_child(node)->node_type == FINSH_NODE_SYS_GETVALUE)
            {
                switch ((finsh_node_child(node)->data_type) & 0x0F)
                {
                case FINSH_DATA_TYPE_BYTE:
                    finsh_code_byte(FINSH_OP_ST_BYTE);

                    /* load value again */
                    finsh_code_byte(FINSH_OP_LD_VALUE_BYTE_STACK);
                    break;

                case FINSH_DATA_TYPE_WORD:
                    finsh_code_byte(FINSH_OP_ST_WORD);

                    /* load value again */
                    finsh_code_byte(FINSH_OP_LD_VALUE_WORD_STACK);
                    break;

                case FINSH_DATA_TYPE_DWORD:
                    finsh_code_byte(FINSH_OP_ST_DWORD);

                    /* load value again */
                    finsh_code_byte(FINSH_OP_LD_VALUE_DWORD_STACK);
                    break;

                default:
                    finsh_error_set(FINSH_ERROR_UNKNOWN_TYPE);
                }
            }
            break;

        /* pre-increase */
        case FINSH_NODE_SYS_PREINC:
            if (finsh_node_child(node) && finsh_node_child(node)->node_type == FINSH_NODE_ID)
            {
                struct finsh_var* var;
                var = finsh_node_child(node)->id.var;

                /* ld_dword &id */
                // finsh_code_byte(FINSH_OP_LD_DWORD);

                switch (node->data_type)
                {
                case FINSH_DATA_TYPE_BYTE:
                    /* address */
                    // finsh_code_dword((long)&(var->value.char_value));

                    /* ld_value_byte &id */
                    finsh_code_byte(FINSH_OP_LD_VALUE_BYTE);
                    finsh_code_dword((long)&(var->value.char_value));

                    /* ld_byte 1 */
                    finsh_code_byte(FINSH_OP_LD_BYTE);
                    finsh_code_byte(1);

                    /* add_byte */
                    finsh_code_byte(FINSH_OP_ADD_BYTE);
                    /* st_byte */
                    finsh_code_byte(FINSH_OP_ST_BYTE);

                    /* load value again */
                    finsh_code_byte(FINSH_OP_LD_VALUE_DWORD_STACK);

                    break;

                case FINSH_DATA_TYPE_WORD:
                    /* address */
                    // finsh_code_dword((long)&(var->value.short_value));

                    /* ld_value_word &id */
                    finsh_code_byte(FINSH_OP_LD_VALUE_WORD);
                    finsh_code_dword((long)&(var->value.short_value));

                    /* ld_word 1 */
                    finsh_code_byte(FINSH_OP_LD_WORD);
                    finsh_code_word(1);

                    /* add_word */
                    finsh_code_byte(FINSH_OP_ADD_WORD);
                    /* st_word */
                    finsh_code_byte(FINSH_OP_ST_WORD);

                    /* load value again */
                    finsh_code_byte(FINSH_OP_LD_VALUE_DWORD_STACK);

                    break;

                case FINSH_DATA_TYPE_DWORD:
                    /* address */
                    // finsh_code_dword((long)&(var->value.long_value));

                    /* ld_dword &id */
                    finsh_code_byte(FINSH_OP_LD_VALUE_DWORD);
                    finsh_code_dword((long)&(var->value.long_value));

                    /* ld_dword 1 */
                    finsh_code_byte(FINSH_OP_LD_DWORD);
                    finsh_code_dword(1);

                    /* add_dword */
                    finsh_code_byte(FINSH_OP_ADD_DWORD);
                    /* st_dword */
                    finsh_code_byte(FINSH_OP_ST_DWORD);

                    /* load value again */
                    finsh_code_byte(FINSH_OP_LD_VALUE_DWORD_STACK);

                    break;
                }
            }
            break;

        /* pre-decrease */
        case FINSH_NODE_SYS_PREDEC:
            if (finsh_node_child(node) && finsh_node_child(node)->node_type == FINSH_NODE_ID)
            {
                struct finsh_var* var;
                var = finsh_node_child(node)->id.var;

                /* ld_dword &id */
                // finsh_code_byte(FINSH_OP_LD_DWORD);

                switch (node->data_type)
                {
                case FINSH_DATA_TYPE_BYTE:
                    /* address */
                    // finsh_code_dword((long)&(var->value.char_value));

                    /* ld_value_byte &id */
                    finsh_code_byte(FINSH_OP_LD_VALUE_BYTE);
                    finsh_code_dword((long)&(var->value.char_value));

                    /* ld_byte 1 */
                    finsh_code_byte(FINSH_OP_LD_BYTE);
                    finsh_code_byte(1);

                    /* add_byte */
                    finsh_code_byte(FINSH_OP_SUB_BYTE);
                    /* st_byte */
                    finsh_code_byte(FINSH_OP_ST_BYTE);

                    /* load value again */
                    finsh_code_byte(FINSH_OP_LD_VALUE_DWORD_STACK);

                    break;

                case FINSH_DATA_TYPE_WORD:
                    /* address */
                    // finsh_code_dword((long)&(var->value.short_value));

                    /* ld_value_word &id */
                    finsh_code_byte(FINSH_OP_LD_VALUE_WORD);
                    finsh_code_dword((long)&(var->value.short_value));

                    /* ld_word 1 */
                    finsh_code_byte(FINSH_OP_LD_WORD);
                    finsh_code_word(1);

                    /* add_word */
                    finsh_code_byte(FINSH_OP_SUB_WORD);
                    /* st_word */
                    finsh_code_byte(FINSH_OP_ST_WORD);

                    /* load value again */
                    finsh_code_byte(FINSH_OP_LD_VALUE_DWORD_STACK);

                    break;

                case FINSH_DATA_TYPE_DWORD:
                    /* address */
                    // finsh_code_dword((long)&(var->value.long_value));

                    /* ld_dword &id */
                    finsh_code_byte(FINSH_OP_LD_VALUE_DWORD);
                    finsh_code_dword((long)&(var->value.long_value));

                    /* ld_dword 1 */
                    finsh_code_byte(FINSH_OP_LD_DWORD);
                    finsh_code_dword(1);

                    /* add_dword */
                    finsh_code_byte(FINSH_OP_SUB_DWORD);
                    /* st_dword */
                    finsh_code_byte(FINSH_OP_ST_DWORD);

                    /* load value again */
                    finsh_code_byte(FINSH_OP_LD_VALUE_DWORD_STACK);

                    break;
                }
            }
            break;

        /* increase */
        case FINSH_NODE_SYS_INC:
            if (finsh_node_child(node) && finsh_node_child(node)->node_type == FINSH_NODE_ID)
            {
                struct finsh_var* var;
                var = finsh_node_child(node)->id.var;

                switch (node->data_type)
                {
                case FINSH_DATA_TYPE_BYTE:
                    /* ld_value_byte &id */
                    // finsh_code_byte(FINSH_OP_LD_VALUE_BYTE);
                    // finsh_code_dword((long)&(var->value.char_value));

                    /* ld_dword &id */
                    finsh_code_byte(FINSH_OP_LD_DWORD);
                    finsh_code_dword((long)&(var->value.char_value));

                    /* ld_value_byte &id */
                    finsh_code_byte(FINSH_OP_LD_VALUE_BYTE);
                    finsh_code_dword((long)&(var->value.char_value));

                    /* ld_byte 1 */
                    finsh_code_byte(FINSH_OP_LD_BYTE);
                    finsh_code_byte(1);

                    /* add_byte */
                    finsh_code_byte(FINSH_OP_ADD_BYTE);
                    /* get byte */
                    finsh_code_byte(FINSH_OP_ST_BYTE);

                    /* pop */
                    finsh_code_byte(FINSH_OP_POP);
                    break;

                case FINSH_DATA_TYPE_WORD:
                    /* ld_value_word &id */
                    // finsh_code_byte(FINSH_OP_LD_VALUE_WORD);
                    // finsh_code_dword((long)&(var->value.short_value));

                    /* ld_dword &id */
                    finsh_code_byte(FINSH_OP_LD_DWORD);
                    finsh_code_dword((long)&(var->value.short_value));

                    /* ld_value_word &id */
                    finsh_code_byte(FINSH_OP_LD_VALUE_WORD);
                    finsh_code_dword((long)&(var->value.short_value));

                    /* ld_word 1 */
                    finsh_code_byte(FINSH_OP_LD_WORD);
                    finsh_code_word(1);

                    /* add_byte */
                    finsh_code_byte(FINSH_OP_ADD_WORD);
                    /* get byte */
                    finsh_code_byte(FINSH_OP_ST_WORD);

                    /* pop */
                    finsh_code_byte(FINSH_OP_POP);
                    break;

                case FINSH_DATA_TYPE_DWORD:
                    /* ld_value_dword &id */
                    // finsh_code_byte(FINSH_OP_LD_VALUE_DWORD);
                    // finsh_code_dword((long)&(var->value.long_value));

                    /* ld_dword &id */
                    finsh_code_byte(FINSH_OP_LD_DWORD);
                    finsh_code_dword((long)&(var->value.long_value));

                    /* ld_value_dword &id */
                    finsh_code_byte(FINSH_OP_LD_VALUE_DWORD);
                    finsh_code_dword((long)&(var->value.long_value));

                    /* ld_dword 1 */
                    finsh_code_byte(FINSH_OP_LD_DWORD);
                    finsh_code_dword(1);

                    /* add_byte */
                    finsh_code_byte(FINSH_OP_ADD_DWORD);
                    /* get byte */
                    finsh_code_byte(FINSH_OP_ST_DWORD);

                    /* pop */
                    finsh_code_byte(FINSH_OP_POP);
                    break;
                }
            }
            break;

        /* decrease */
        case FINSH_NODE_SYS_DEC:
            if (finsh_node_child(node) && finsh_node_child(node)->node_type == FINSH_NODE_ID)
            {
                struct finsh_var* var;
                var = finsh_node_child(node)->id.var;

                switch (node->data_type)
                {
                case FINSH_DATA_TYPE_BYTE:
                    /* ld_value_byte &id */
                    // finsh_code_byte(FINSH_OP_LD_VALUE_BYTE);
                    // finsh_code_dword((long)&(var->value.char_value));

                    /* ld_dword &id */
                    finsh_code_byte(FINSH_OP_LD_DWORD);
                    finsh_code_dword((long)&(var->value.char_value));

                    /* ld_value_byte &id */
                    finsh_code_byte(FINSH_OP_LD_VALUE_BYTE);
                    finsh_code_dword((long)&(var->value.char_value));

                    /* ld_byte 1 */
                    finsh_code_byte(FINSH_OP_LD_BYTE);
                    finsh_code_byte(1);

                    /* add_byte */
                    finsh_code_byte(FINSH_OP_SUB_BYTE);
                    /* get byte */
                    finsh_code_byte(FINSH_OP_ST_BYTE);

                    /* pop */
                    finsh_code_byte(FINSH_OP_POP);
                    break;

                case FINSH_DATA_TYPE_WORD:
                    /* ld_value_word &id */
                    // finsh_code_byte(FINSH_OP_LD_VALUE_WORD);
                    // finsh_code_dword((long)&(var->value.short_value));

                    /* ld_dword &id */
                    finsh_code_byte(FINSH_OP_LD_DWORD);
                    finsh_code_dword((long)&(var->value.short_value));

                    /* ld_value_word &id */
                    finsh_code_byte(FINSH_OP_LD_VALUE_WORD);
                    finsh_code_dword((long)&(var->value.short_value));

                    /* ld_word 1 */
                    finsh_code_byte(FINSH_OP_LD_WORD);
                    finsh_code_word(1);

                    /* add_byte */
                    finsh_code_byte(FINSH_OP_SUB_WORD);
                    /* get byte */
                    finsh_code_byte(FINSH_OP_ST_WORD);

                    /* pop */
                    finsh_code_byte(FINSH_OP_POP);
                    break;

                case FINSH_DATA_TYPE_DWORD:
                    /* ld_value_dword &id */
                    // finsh_code_byte(FINSH_OP_LD_VALUE_DWORD);
                    // finsh_code_dword((long)&(var->value.long_value));

                    /* ld_dword &id */
                    finsh_code_byte(FINSH_OP_LD_DWORD);
                    finsh_code_dword((long)&(var->value.long_value));

                    /* ld_value_dword &id */
                    finsh_code_byte(FINSH_OP_LD_VALUE_DWORD);
                    finsh_code_dword((long)&(var->value.long_value));

                    /* ld_dword 1 */
                    finsh_code_byte(FINSH_OP_LD_DWORD);
                    finsh_code_dword(1);

                    /* add_byte */
                    finsh_code_byte(FINSH_OP_SUB_DWORD);
                    /* get byte */
                    finsh_code_byte(FINSH_OP_ST_DWORD);

                    /* pop */
                    finsh_code_byte(FINSH_OP_POP);
                    break;
                }
            }
            break;

        case FINSH_NODE_SYS_NULL:
            finsh_code_dword(0);
            break;

        case FINSH_NODE_SYS_GETVALUE:
            if (node->idtype & FINSH_IDTYPE_ADDRESS)
            {
                /* nothing will be generated */
            }
            else
            {
                switch (node->data_type)
                {
                case FINSH_DATA_TYPE_BYTE:
                    finsh_code_byte(FINSH_OP_LD_VALUE_BYTE_STACK);
                    break;
                case FINSH_DATA_TYPE_WORD:
                    finsh_code_byte(FINSH_OP_LD_VALUE_WORD_STACK);
                    break;
                case FINSH_DATA_TYPE_DWORD:
                    finsh_code_byte(FINSH_OP_LD_VALUE_DWORD_STACK);
                    break;
                default:
                    break;
                }
            }
            break;

        case FINSH_NODE_SYS_GETADDR:
            /* nothing will be generated */
            break;

        default:
            finsh_error_set(FINSH_ERROR_UNKNOWN_NODE);
            break;
        }

        /* compile sibling node */
        if (finsh_node_sibling(node) != NULL)
            finsh_compile(finsh_node_sibling(node));
    }

    return 0;
}