⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gbc_trans_code.c

📁 Gambas is a graphical development environment based on a Basic interpreter, like Visual Basic. It us
💻 C
字号:
/***************************************************************************  trans_code.c  P-code generation  (c) 2000-2004 Beno� Minisini <gambas@users.sourceforge.net>  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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.***************************************************************************/#define _TRANS_CODE_C#include <stdlib.h>#include <string.h>#include <stdio.h>#include "gb_common.h"#include "gb_error.h"#include "gbc_compile.h"#include "gbc_trans.h"#include "gb_code.h"#include "gb_limit.h"/*#define DEBUG*/PRIVATE FUNCTION *func;PRIVATE void add_local(long sym_index, TYPE type, long value){  CLASS_SYMBOL *sym;  PARAM *loc;  loc = ARRAY_add(&func->local);  loc->index = sym_index;  loc->type = type;  loc->value = value;  sym = CLASS_declare(JOB->class, sym_index, FALSE);  sym->local.type = type;  sym->local.value = value;}PRIVATE void create_local_from_param(){  int i;  for (i = 0; i < func->nparam; i++)  {    if (TYPE_get_id(func->param[i].type) != T_NULL)    {      add_local(func->param[i].index, func->param[i].type, (i - func->nparam));    }  }}PRIVATE void remove_local(){  int i;  CLASS_SYMBOL *sym;  for (i = 0; i < ARRAY_count(func->local); i++)  {    sym = CLASS_get_symbol(JOB->class, func->local[i].index);    TYPE_clear(&sym->local.type);  }}PRIVATE boolean TRANS_local(void){  PATTERN *save = JOB->current;  long sym_index;  TRANS_DECL decl;  if (PATTERN_is(*JOB->current, RS_DIM))    JOB->current++;  else if (!TRANS_check_declaration())    return FALSE;	if (!PATTERN_is_identifier(*JOB->current))		THROW(E_SYNTAX);  sym_index = PATTERN_index(*JOB->current);  JOB->current++;  if (!TRANS_type(TT_DO_NOT_CHECK_AS | TT_CAN_SQUARE | TT_CAN_ARRAY | TT_CAN_NEW, &decl))  {    JOB->current = save;    return FALSE;  }  if (!PATTERN_is_newline(*JOB->current))    THROW(E_SYNTAX);  add_local(sym_index, decl.type, func->nlocal);  if (TRANS_init_var(&decl))    CODE_pop_local(func->nlocal);  func->nlocal++;  if (JOB->verbose)    printf("LOCAL %s AS %s\n", TABLE_get_symbol_name(JOB->class->table, sym_index), TYPE_get_desc(decl.type));  return TRUE;}PUBLIC void TRANS_statement(void){  static TRANS_STATEMENT statement[] = {    { RS_EXIT, TRANS_break },    { RS_BREAK, TRANS_break },    { RS_CONTINUE, TRANS_continue },    { RS_GOTO, TRANS_goto },    { RS_RETURN, TRANS_return },    { RS_PRINT, TRANS_print },    { RS_INPUT, TRANS_input },    { RS_WRITE, TRANS_write },    { RS_READ, TRANS_read },    { RS_OPEN, TRANS_open },    { RS_CLOSE, TRANS_close },    { RS_SEEK, TRANS_seek },    { RS_FLUSH, TRANS_flush },    { RS_STOP, TRANS_stop },    { RS_QUIT, TRANS_quit },    { RS_EXEC, TRANS_exec },    { RS_SHELL, TRANS_shell },    { RS_WAIT, TRANS_wait },    { RS_KILL, TRANS_kill },    { RS_RENAME, TRANS_rename },    { RS_INC, TRANS_inc },    { RS_DEC, TRANS_dec },    { RS_SWAP, TRANS_swap },    { RS_MKDIR, TRANS_mkdir },    { RS_RMDIR, TRANS_rmdir },    { RS_USE, TRANS_use },    { RS_COPY, TRANS_copy },    { RS_RAISE, TRANS_raise },    { RS_LINK, TRANS_link },    { RS_LOCK, TRANS_lock },    { RS_UNLOCK, TRANS_unlock },    { RS_NONE, NULL }  };  PATTERN *look = JOB->current;  TRANS_STATEMENT *st;  if (PATTERN_is(look[0], RS_LINE) && PATTERN_is(look[1], RS_INPUT))  {    JOB->current += 2;    TRANS_line_input();  }  else  {    if (PATTERN_is_reserved(look[0]))    {      for (st = statement; st->id; st++)      {        if (PATTERN_is(look[0], st->id))        {          JOB->current++;          (*st->func)();          return;        }      }    }    if (!TRANS_affectation())      TRANS_expression(TRUE);  }}PRIVATE void translate_body(){  PATTERN *look;  bool is_proc = (TYPE_get_id(func->type) == T_VOID);  bool test_newline;  long line = JOB->line - 1;  bool just_got_select = FALSE;  for(;;)  {    test_newline = TRUE;    CODE_allow_break();    while (line < JOB->line)    {      FUNCTION_add_pos_line();      line++;    }    look = JOB->current;    if (PATTERN_is(look[0], RS_END))      if (TRANS_is_end_function(is_proc, &look[1]))        break;    if (PATTERN_is_newline(look[0]))    {      JOB->current++;      JOB->line++;      test_newline = FALSE;    }    else if (!TRANS_local())      break;    if (test_newline)      if (!PATTERN_is_newline(*JOB->current))        THROW("Syntax error. End of line expected");  }  TRANS_control_init();  for(;;)  {    test_newline = TRUE;    CODE_allow_break();    while (line < JOB->line)    {      FUNCTION_add_pos_line();      line++;    }    look = JOB->current;    if (PATTERN_is(look[0], RS_END))      if (TRANS_is_end_function(is_proc, &look[1]))        break;    if (PATTERN_is_newline(look[0]))    {      JOB->current++;      JOB->line++;      continue;    }    if (just_got_select)    {      if (!PATTERN_is(look[0], RS_CASE) && !PATTERN_is(look[0], RS_DEFAULT))        THROW("Syntax error. CASE or DEFAULT expected after SELECT");      just_got_select = FALSE;    }    if (PATTERN_is_identifier(look[0]) && PATTERN_is(look[1], RS_COLON))    {      TRANS_label();    }    else if (PATTERN_is(look[0], RS_IF))    {      JOB->current++;      TRANS_if();    }    else if (PATTERN_is(look[0], RS_ELSE))    {      JOB->current++;      TRANS_else();    }    else if ((PATTERN_is(look[0], RS_END)              && PATTERN_is(look[1], RS_IF))             || PATTERN_is(look[0], RS_ENDIF))    {      if (PATTERN_is(look[0], RS_END))        JOB->current += 2;      else        JOB->current++;      TRANS_endif();    }    else if (PATTERN_is(look[0], RS_DO))    {      JOB->current++;      TRANS_do(RS_DO);    }    else if (PATTERN_is(look[0], RS_WHILE))    {      TRANS_do(RS_WHILE);    }    else if (PATTERN_is(*look, RS_REPEAT))    {      JOB->current++;      TRANS_do(RS_REPEAT);    }    else if (PATTERN_is(look[0], RS_LOOP))    {      JOB->current++;      TRANS_loop(RS_LOOP);    }    else if (PATTERN_is(look[0], RS_UNTIL))    {      TRANS_loop(RS_UNTIL);    }    else if (PATTERN_is(look[0], RS_WEND))    {      JOB->current++;      TRANS_loop(RS_WEND);    }    else if (PATTERN_is(look[0], RS_FOR))    {      if (PATTERN_is(look[1], RS_EACH))      {        JOB->current += 2;        TRANS_for_each();      }      else      {        JOB->current++;        TRANS_for();      }    }    else if (PATTERN_is(look[0], RS_NEXT))    {      JOB->current++;      TRANS_next();    }    else if (PATTERN_is(look[0], RS_SELECT))    {      JOB->current++;      TRANS_select();      just_got_select = TRUE;    }    else if (PATTERN_is(look[0], RS_CASE))    {      JOB->current++;      if (PATTERN_is(look[1], RS_ELSE))      {        JOB->current++;        TRANS_default();      }      else        TRANS_case();    }    else if (PATTERN_is(look[0], RS_DEFAULT))    {      JOB->current++;      TRANS_default();    }    else if (PATTERN_is(look[0], RS_END)             && PATTERN_is(look[1], RS_SELECT))    {      JOB->current += 2;      TRANS_end_select();    }    else if (PATTERN_is(look[0], RS_TRY))    {      JOB->current++;      TRANS_try();    }    else if (PATTERN_is(look[0], RS_FINALLY))    {      JOB->current++;      TRANS_finally();    }    else if (PATTERN_is(look[0], RS_CATCH))    {      JOB->current++;      TRANS_catch();    }    else if (PATTERN_is(*look, RS_WITH))    {      JOB->current++;      TRANS_with();    }    else if (PATTERN_is(look[0], RS_END)             && PATTERN_is(look[1], RS_WITH))    {      JOB->current += 2;      TRANS_end_with();    }    else      TRANS_statement();    /*    if (next_newline)    {      for(;;)      {        if (PATTERN_is_NEWLINE(*JOB->current)            || PATTERN_is_END(*JOB->current))          break;        JOB->current++;      }    }    */    if (test_newline)      if (!PATTERN_is_newline(*JOB->current))        THROW("Syntax error. End of line expected");  }  TRANS_control_exit();}PRIVATE void trans_call(const char *name, int nparam){  CLASS_SYMBOL *sym;  if (!TABLE_find_symbol(JOB->class->table, name, strlen(name), (SYMBOL **)&sym, NULL))    return;  if (TYPE_get_kind(sym->global.type) != TK_FUNCTION)    return;  CODE_push_global(sym->global.value, FALSE, TRUE);  CODE_call(nparam, FALSE);  CODE_drop();}PUBLIC void TRANS_code(void){  int i;  bool debug;  debug = JOB->debug;  for (i = 0; i < ARRAY_count(JOB->class->function); i++)  {    func = &JOB->class->function[i];    CODE_begin_function(func);    if (JOB->verbose)      printf("Compiling %s()...\n", TABLE_get_symbol_name(JOB->class->table, func->name));    /* Do not debug implicite or generated functions */    if (!func->start || func->name == NO_SYMBOL || TABLE_get_symbol_name(JOB->class->table, func->name)[0] == '$')      JOB->nobreak = TRUE;    else      JOB->nobreak = FALSE;    /* fonction implicite ? */    if (!func->start)    {      if ((i == FUNC_INIT_DYNAMIC) && (JOB->form != NULL))      {        /* La d�activation des ��enements devrait se faire DANS le _load */        CODE_event(FALSE);        /*CODE_push_me(FALSE);*/        trans_call("$load", 0);        CODE_event(TRUE);      }      CODE_op(C_RETURN, 0, TRUE);      if (JOB->verbose)        CODE_dump(func->code);      continue;    }    JOB->line = func->line;    JOB->current = func->start;    JOB->func = func;    create_local_from_param();    translate_body();    CODE_return(0);    CODE_end_function(func);    FUNCTION_add_pos_line();    func->stack = func->nlocal + func->nctrl + CODE_stack_usage;    if (JOB->verbose)    {      CODE_dump(func->code);      printf("%d local(s) %d control(s) ", func->nlocal, func->nctrl);      printf("%d stack\n", func->stack);      printf("\n");    }    remove_local();  }  CLASS_check_properties(JOB->class);  JOB->func = NULL;}PUBLIC boolean TRANS_init_var(TRANS_DECL *decl){  int i;  TRANS_ARRAY *array;  if (!decl->is_new)    return FALSE;  if (TYPE_is_array(decl->type) && decl->array.ndim > 0)  {    array = &decl->array;    if (TYPE_is_object(decl->type))      /*CODE_push_class(CLASS_add_class(JOB->class, JOB->class->class[TYPE_get_class(decl->type)]));*/      CODE_push_class(TYPE_get_value(decl->type));    else      CODE_push_number(TYPE_get_id(decl->type));    for (i = 0; i < array->ndim; i++)      CODE_push_number(array->dim[i]);    CODE_new(array->ndim + 1, TRUE, FALSE);  }  else  {    CODE_push_class(TYPE_get_value(decl->type));    /*CODE_push_class(CLASS_add_class(JOB->class, TYPE_get_class(decl->type)));*/    CODE_new(1, FALSE, FALSE);  }  return TRUE;}/*PUBLIC void TRANS_init_object(){}*/PUBLIC void TRANS_init_optional(TRANS_PARAM *param){  PATTERN *look = param->optional;  PATTERN *save;  if (look == NULL)    return;  save = JOB->current;  if (PATTERN_is(*look, RS_COMMA) || PATTERN_is(*look, RS_RBRA))  {    CODE_push_void();  }  else  {    if (!PATTERN_is(*look, RS_EQUAL))      THROW("Syntax error. Invalid optional parameter");    look++;    JOB->current = look;    TRANS_expression(FALSE);    if (!PATTERN_is(*JOB->current, RS_COMMA) && !PATTERN_is(*JOB->current, RS_RBRA))      THROW("Syntax error. Invalid optional parameter");  }  JOB->current = save;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -