/* * File : finsh_compiler.c * This file is part of RT-Thread RTOS * COPYRIGHT (C) 2006 - 2010, RT-Thread Development Team * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * http://www.rt-thread.org/license/LICENSE * * Change Logs: * Date Author Notes * 2010-03-22 Bernard first version */ #include #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; }