rt-thread/components/finsh/finsh_compiler.c

935 lines
24 KiB
C

/*
* RT-Thread finsh shell compiler
*
* COPYRIGHT (C) 2006 - 2013, RT-Thread Development Team
*
* This file is part of RT-Thread (http://www.rt-thread.org)
* Maintainer: bernard.xiong <bernard.xiong at gmail.com>
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Change Logs:
* Date Author Notes
* 2010-03-22 Bernard first version
*/
#include <finsh.h>
#include "finsh_node.h"
#include "finsh_error.h"
#include "finsh_var.h"
#include "finsh_ops.h"
union finsh_value* finsh_compile_sp; /* stack pointer */
u_char* finsh_compile_pc; /* PC */
#define finsh_code_byte(x) do { *finsh_compile_pc = (x); finsh_compile_pc ++; } while(0)
#define finsh_code_word(x) do { FINSH_SET16(finsh_compile_pc, x); finsh_compile_pc +=2; } while(0)
#define finsh_code_dword(x) do { FINSH_SET32(finsh_compile_pc, x); finsh_compile_pc +=4; } while(0)
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;
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)->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)->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)->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)->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)->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;
}
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;
}
int finsh_compiler_run(struct finsh_node* node)
{
struct finsh_node* sibling;
/* type check */
finsh_type_check(node, FINSH_NODE_VALUE);
/* clean text segment and vm stack */
memset(&text_segment[0], 0, sizeof(text_segment));
memset(&finsh_vm_stack[0], 0, sizeof(finsh_vm_stack[0]));
/* reset compile stack pointer and pc */
finsh_compile_sp = &finsh_vm_stack[0];
finsh_compile_pc = &text_segment[0];
/* compile node */
sibling = node;
while (sibling != NULL)
{
struct finsh_node* current_node;
current_node = sibling;
/* get sibling node */
sibling = current_node->sibling;
/* clean sibling node */
current_node->sibling = NULL;
finsh_compile(current_node);
/* pop current value */
if (sibling != NULL) finsh_code_byte(FINSH_OP_POP);
}
return 0;
}