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

📄 compiler.cpp

📁 c-smile 一个语法类似与JS 又有点像C++的 编译器
💻 CPP
📖 第 1 页 / 共 4 页
字号:
      }
      putcbyte ( OP_RETURN );
    }

    // update OP_TSPACE operand
    tcnt = temporaries->get_total ();
    cbuff [ c_tspace ] = tcnt;

    delete temporaries; // unwind all stack please;
    temporaries = 0;

    BUFFER *bc = new BUFFER ( cptr );

    // build the function
    CODE *bytecode = new CODE ( VM::voc [ name ], bc, klass );

    // create the code string
    unsigned char *src = cbuff, *dst = &( *bc ) [ 0 ];
    while ( --cptr >= 0 )
      *dst++ = *src++;

#ifdef DECODE_TRACE
    // show the generated code
    VM::decode_procedure ( bytecode );
#endif
    //restore
    cbuff = old_cbuff;  // code buffer
    cptr  = old_cptr;   // code pointer

    arguments.clear ();

    if ( klass )
      klass->check_name ( VM::voc [ name ], bytecode, stype );
    // return the code object
    return bytecode;
  }

  // do_init_code - compile the code part of a package
  void
    compiler::do_static_vardecl ( CLASS *klass_or_package, bool constant )
  {
    int tkn;
    string id;
    compiler::PVAL rhs;
    for ( ; ; )
    {
      tkn = scan.token ();
      if ( tkn != T_IDENTIFIER )
        throw parse_error ( this, "Expecting an identifier" );
      id = scan.t_token;

      //code_variable
      ENTRY entry = klass_or_package->add ( id, constant ? ST_CONST
                                                         : ST_SDATA );

      if ( !entry.is_valid () )
      {
        throw parse_error ( this, "Variable or constant '%s' already defined",
                            (const char *) id );
      }

      int lit_num = package->add_literal ( VALUE ( entry ) );

      tkn = scan.token ();
      if ( tkn == '=' )
      {
        code_variable ( this, PUSH, 0 );
        do_expr2 ( &rhs );
        rvalue ( &rhs );
        code_variable ( this, STORE, lit_num );
        tkn = scan.token ();
      }
      else
      {
        putcbyte ( OP_UNDEFINED );
        code_variable ( this, STORE, lit_num );
      }

      if ( tkn == ',' )
        continue;
      else if ( tkn == ';' )
      {
        break;
      }
      else
        throw parse_error ( this, "Expecting ',' | ';'" );
    }
  }


  // get_class - get the klass associated with a symbol
  CLASS *
    compiler::get_class ( const char *name, PACKAGE *pkg, bool reportError )
  {
    if ( pkg == 0 )
    {
      CLASS * cls = get_class ( name, package );
      if ( cls )
        return cls;
      cls = get_class ( name, VM::std );
      if ( cls )
        return cls;
      throw parse_error ( this, "'%s' is not a class name", name );
    }
    ENTRY e = pkg->find ( name );
    if ( e.is_valid  () )
    {
      VALUE * v = e.value ();
      if ( v && v->v_type == DT_CLASS )
        return v->v.v_class;
    }
    if ( reportError )
      throw parse_error ( this, "'%s' is not a class name", name );

    return 0;
  }

  // get_class - get the klass associated with a symbol
  PACKAGE *
    compiler::get_package ( const char *name, bool reportError )
  {
    if ( package->name == VM::voc [ name ] )
      return package;
    int idx = VM::packages->find ( VM::voc [ name ] );
    if ( idx < 0 )
    {
      if ( reportError )
        throw parse_error ( this, "'%s' is not a package name", name );
      return 0;
    }
    return (PACKAGE *) ( *( VM::packages ) ) [ idx ].value.v.v_class;
  }

  CLASS *
    compiler::get_class_or_package ( string& class_id, string& package_id )
  {
    PACKAGE *pkg;
    if ( package_id.length () )
    {
      pkg = get_package ( (const char *) package_id, true );
      return get_class ( (const char *) class_id, pkg );
    }
    // first try to test is class_id is a package name
    pkg = get_package ( (const char *) class_id, false );
    if ( pkg )
      return pkg;

    return get_class ( (const char *) class_id );
  }

  // do_statement - compile a single statement
  int
    compiler::do_statement ()
  {
    int tkn;
    switch ( tkn = scan.token () )
    {
    case T_IF:		    do_if ();                           return tkn;
    case T_WHILE:	    do_while ();                        return tkn;
    case T_DO:		    do_dowhile ();                      return tkn;
    case T_FOR:		    do_for ();                          return tkn;
    case T_BREAK:	    do_break (); frequire ( ';' );      return tkn;
    case T_CONTINUE:	do_continue (); frequire ( ';' );   return tkn;
    case T_RETURN:	  do_return ();                       return tkn;
    case T_TRY:       do_try ();                          return tkn;
    case T_THROW:     do_throw ();                        return tkn;
    case T_SYNCHRO:   do_synchro ();                      return tkn;
    case T_SWITCH:    do_switch ();                       return tkn;
    case '{':         do_block ();                        break;
    case ';':         ;                                   return tkn;
    case T_VAR:       do_vardecl ();                      break;

    default:
      scan.stoken ( tkn );
      do_expr ();
      frequire ( ';' );
      break;
    }
    return 0;
  }

  // do_if - compile the IF/ELSE expression
  void
    compiler::do_if ()
  {
    int tkn, nxt, end;

    // compile the test expression
    do_test ();

    // skip around the 'then' clause if the expression is false
    putcbyte ( OP_BRF );
    nxt = putcword ( 0 );

    // compile the 'then' clause
    do_statement ();

    // compile the 'else' clause
    if ( ( tkn = scan.token () ) == T_ELSE )
    {
      putcbyte ( OP_BR );
      end = putcword ( 0 );
      fixup ( nxt, cptr );
      do_statement ();
      nxt = end;
    }
    else
      scan.stoken ( tkn );

    // handle the end of the statement
    fixup ( nxt, cptr );
  }

  void
    compiler::do_switch ()
  {
    compiler::PVAL pv;
    int nxt = 0, nxtbody = 0, end = 0, dflt = 0;

    int *old_break;

    frequire ( '(' );
    do_expr1 ( &pv );
    rvalue   ( &pv );
    frequire ( ')' );

    frequire ( '{' );

    old_break = addbreak ( 0 );

    putcbyte ( OP_PUSH );

    int tkn; int last_stm = 0;
    while ( (tkn = scan.token () ) != T_EOF )
    {
      if ( tkn == '}' )
        break;
      if ( tkn == T_CASE )
      {
        if ( nxt )
        {
          if ( last_stm != T_BREAK && last_stm != T_RETURN )
          {
            putcbyte ( OP_BR );
            nxtbody = putcword ( 0 );
          }
          fixup ( nxt, cptr );
        }
        else
          nxtbody = 0;
        putcbyte   ( OP_COPY );
        putcbyte   ( OP_PUSH );
        do_primary ( &pv );
        rvalue     ( &pv );
        frequire   ( ':' );
        putcbyte   ( OP_EQ );
        putcbyte   ( OP_BRF );
        nxt = putcword ( 0 );
        if ( nxtbody )
        {
          fixup ( nxtbody, cptr );
          nxtbody = 0;
        }
      }
      else if ( tkn == T_DEFAULT )
      {
        frequire ( ':' );
        if ( nxt == 0 )
        {
          putcbyte ( OP_BR );
          nxt = putcword ( 0 );
        }
        dflt = cptr;
      }
      else
      {
        if ( nxt == 0 )
          throw parse_error ( this, "Expecting 'case' | 'default'" );
        scan.stoken ( tkn );
        int ls = do_statement ();
        if ( ls != ';')
          last_stm = ls;
      }
    }

    end = rembreak ( old_break, end );

    if ( nxt )
    {
      if ( dflt )
        fixup ( nxt, dflt );
      else
        fixup ( nxt, cptr );
    }

    // handle the end of the statement
    fixup ( end, cptr );
    putcbyte ( OP_POP );
  }

  void
    compiler::do_try ()
  {
    int nxt, end;

    frequire ( '{' );

    putcbyte ( OP_EH_PUSH );
    nxt = putcword ( 0 );

    do_block ();

    putcbyte ( OP_EH_POP );
    end = putcword ( 0 );

    fixup ( nxt, cptr );

    frequire ( T_CATCH );
    frequire ( '(' );
    frequire ( T_IDENTIFIER );
    string ev = scan.t_token;
    frequire ( ')' );
    frequire ( '{' );
    do_block ( ev  );
    // handle the end of the statement
    fixup ( end, cptr );
  }

  void
    compiler::do_throw ()
  {
    do_expr  ();
    frequire ( ';' );
    putcbyte ( OP_THROW );
  }

  void
    compiler::do_synchro ()
  {
    compiler::PVAL pv;
    do_primary ( &pv );
    rvalue     ( &pv );
    frequire   ( '{' );
    putcbyte   ( OP_ENTER );
    do_block   ();
    putcbyte   ( OP_LEAVE );
  }

  // addbreak - add a break level to the stack
  int *
    compiler::addbreak ( int lbl )
  {
    int *old = bsp;
    if ( ++bsp < &bstack [ SSIZE ] )
      *bsp = lbl;
    else
      throw parse_error ( this, "Too many nested loops" );
    return ( old );
  }

  // rembreak - remove a break level from the stack
  int
    compiler::rembreak ( int *old, int lbl )
  {
    return ( bsp > old ? *bsp-- : lbl );
  }

  // addcontinue - add a continue level to the stack
  int *
    compiler::addcontinue ( int lbl )
  {
    int *old = csp;
    if ( ++csp < &cstack [ SSIZE ] )
      *csp = lbl;
    else
      throw parse_error ( this, "Too many nested loops" );
    return ( old );
  }

  // remcontinue - remove a continue level from the stack
  void
    compiler::remcontinue ( int *old )
  {
    csp = old;
  }

  // do_while - compile the WHILE expression
  void
    compiler::do_while ()
  {
    int nxt, end, *ob, *oc;

    // compile the test expression
    nxt = cptr;
    do_test ();

    // skip around the loop body if the expression is false
    putcbyte ( OP_BRF );
    end = putcword ( 0 );

    // compile the loop body
    ob = addbreak ( end );
    oc = addcontinue ( nxt );
    do_statement ();
    end = rembreak ( ob, end );
    remcontinue ( oc );

    // branch back to the start of the loop
    putcbyte ( OP_BR );
    putcword ( nxt );

    // handle the end of the statement
    fixup ( end, cptr );
  }

  // do_dowhile - compile the DO/WHILE expression
  void
    compiler::do_dowhile ()
  {
    int nxt, end = 0, *ob, *oc;

    // remember the start of the loop
    nxt = cptr;

    // compile the loop body
    ob = addbreak ( 0 );
    oc = addcontinue ( nxt );
    do_statement ();
    end = rembreak ( ob, end );
    remcontinue ( oc );

    // compile the test expression
    frequire ( T_WHILE );
    do_test ();
    frequire ( ';' );

    // branch to the top if the expression is true
    putcbyte ( OP_BRT );
    putcword ( nxt );

    // handle the end of the statement
    fixup ( end, cptr );
  }

  // do_for - compile the FOR statement
  void
    compiler::do_for ()
  {
    int tkn, nxt, end, body, update, *ob, *oc;

    // compile the initialization expression
    frequire ( '(' );
    if ( (tkn = scan.token () ) != ';' )
    {
      if ( tkn == T_VAR )
        do_vardecl ();
      else
      {
        scan.stoken ( tkn );
        do_expr ();
      }
      frequire ( ';' );
    }

    // compile the test expression
    nxt = cptr;
    if ( ( tkn = scan.token () ) != ';' )
    {
      scan.stoken ( tkn );
      do_expr ();
      frequire ( ';' );
    }

    // branch to the loop body if the expression is true
    putcbyte ( OP_BRT );
    body = putcword ( 0 );

    // branch to the end if the expression is false
    putcbyte ( OP_BR );
    end = putcword ( 0 );

    // compile the update expression
    update = cptr;
    if ( ( tkn = scan.token () ) != ')' )
    {
      scan.stoken ( tkn );
      do_expr ();
      frequire ( ')' );
    }

    // branch back to the test code
    putcbyte ( OP_BR );
    putcword ( nxt );

    // compile the loop body
    fixup ( body, cptr );
    ob = addbreak ( end );
    oc = addcontinue ( update );
    do_statement ();
    end = rembreak ( ob, end );
    remcontinue ( oc );

    // branch back to the update code
    putcbyte ( OP_BR );
    putcword ( update );

    // handle the end of the statement
    fixup ( end, cptr );
  }

  // do_break - compile the BREAK statement
  void
    compiler::do_break ()
  {
    if ( bsp >= bstack )
    {
      putcbyte ( OP_BR );
      *bsp = putcword ( *bsp );
    }
    else
      throw parse_error ( this, "Break outside of loop" );
  }

  // do_continue - compile the CONTINUE statement
  void
    compiler::do_continue ()
  {
    if ( csp >= cstack )
    {
      putcbyte ( OP_BR );
      putcword ( *csp );
    }
    else
      throw parse_error ( this, "Continue outside of loop" );
  }

  // do_block - compile the {} expression
  int
    compiler::do_block ( const char *parameter )
  {
    name_space *save_temp = temporaries;
    temporaries = new name_space ( temporaries );

    if ( parameter )
    {
      int temp_var_index = temporaries->add ( parameter );
      code_temporary ( this, STORE, temp_var_index );
    }

    int tkn;
    int last_stat = 0;
    if ( (tkn = scan.token () ) != '}' )
    {
      do
      {
        scan.stoken ( tkn );
        last_stat = do_statement ();
      }
      while ( (tkn = scan.token () ) != '}' );
    }
    else
      putcbyte ( OP_UNDEFINED );

    if ( save_temp )

⌨️ 快捷键说明

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