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

📄 archive.cpp

📁 c-smile 一个语法类似与JS 又有点像C++的 编译器
💻 CPP
📖 第 1 页 / 共 2 页
字号:
  //|
  //| VALUE
  //|
  void
    archive::read ( VALUE &val )
  {
    read ( (char *) &val.v_type, 1 );
    switch ( val.v_type )
    {
    case DT_NULL:
      break;
    case DT_FLOAT:
      read ( val.v.v_float );
      break;
    case DT_INTEGER:
      read ( val.v.v_integer );
      break;
    case DT_STRING:
      read ( val.v.v_string );
      break;
    case DT_CLASS:
      read ( val.v.v_class );
      break;
    case DT_OBJECT:
      read ( val.v.v_object );
      break;
    case DT_ARRAY:
      read ( val.v.v_vector );
      break;
    case DT_CODE:
      read ( val.v.v_code );
      break;
    case DT_VAR:
      read ( val.v.v_var );
      break;
    case DT_EXT:
      {
        CLASS *cls = 0;
        read_class_ref ( cls );
        val.v.v_thing = cls->load ( this );
        if(!val.v.v_thing) val.v_type = DT_NULL;
        //assert ( val.v.v_thing != 0 );
      }
      break;
    case DT_SYMBOL:
      read ( val.v.v_symbol );
      break;
    case DT_OBJECT_METHOD:
      assert ( false );
      break;
    }
  }

  void  
    archive::write ( const VALUE &val )
  {
    write ( (char *) &val.v_type, 1 );
    switch ( val.v_type )
    {
    case DT_NULL:
      break;
    case DT_FLOAT:
      write ( val.v.v_float );
      break;
    case DT_INTEGER:
      write ( val.v.v_integer );
      break;
    case DT_STRING:
      write ( val.v.v_string );
      break;
    case DT_CLASS:
      write ( val.v.v_class );
      break;
    case DT_OBJECT:
      write ( val.v.v_object );
      break;
    case DT_ARRAY:
      write ( val.v.v_vector );
      break;
    case DT_CODE:
      write ( val.v.v_code );
      break;
    case DT_VAR:
      write ( val.v.v_var );
      break;
    case DT_EXT:
      {
        CLASS *cls = val.v.v_thing->get_class ();
        write_class_ref ( cls );
        cls->save ( val.v.v_thing, this );
      }
      break;
    case DT_SYMBOL:
      write ( val.v.v_symbol );
      break;
    case DT_OBJECT_METHOD:
      assert ( false );
      break;
    }
  }


  //|
  //| literal
  //|
  void
    archive::read_literal ( VALUE &val )
  {
    read ( (char *) &val.v_type, 1 );
    switch ( val.v_type )
    {
    case DT_NULL:
      break;
    case DT_FLOAT:
      read ( val.v.v_float );
      break;
    case DT_INTEGER:
      read ( val.v.v_integer );
      break;
    case DT_STRING:
      read ( val.v.v_string );
      break;
    case DT_CLASS:
      read_class_ref ( val.v.v_class );
      break;
    case DT_OBJECT:
      read ( val.v.v_object );
      break;
    case DT_ARRAY:
      read ( val.v.v_vector );
      break;
    case DT_CODE:
      read_code_ref ( val.v.v_code );
      break;
    case DT_VAR:
      read ( val.v.v_var );
      break;
    case DT_EXT:
      {
        CLASS *cls = 0;
        read_class_ref ( cls );
        val.v.v_thing = cls->load ( this );
        assert ( val.v.v_thing != 0 );
      }
      break;
    case DT_SYMBOL:
      read ( val.v.v_symbol );
      break;
    case DT_OBJECT_METHOD:
      assert ( false );
      break;
    }
  }

  extern char *nameoftype ( int );

  void
    archive::write_literal ( const VALUE &val )
  {
    write ( (char *) &val.v_type, 1 );
    switch ( val.v_type )
    {
    case DT_NULL:
      break;
    case DT_FLOAT:
      write ( val.v.v_float );
      break;
    case DT_INTEGER:
      write ( val.v.v_integer );
      break;
    case DT_STRING:
      write ( val.v.v_string );
      break;
    case DT_CLASS:
      write_class_ref ( val.v.v_class );
      break;
    case DT_OBJECT:
      write ( val.v.v_object );
      break;
    case DT_ARRAY:
      write ( val.v.v_vector );
      break;
    case DT_CODE:
      write_code_ref ( val.v.v_code );
      break;
    case DT_VAR:
      write ( val.v.v_var );
      break;
    case DT_EXT:
      {
        CLASS *cls = val.v.v_thing->get_class ();
        write_class_ref ( cls );
        bool r = cls->save ( val.v.v_thing, this );
        assert ( r );
      }
      break;
    case DT_SYMBOL:
      write ( val.v.v_symbol );
      break;
    case DT_OBJECT_METHOD:
      assert ( false );
      break;
    }

  }

  const char *magic = "c-smile";
  const size_t magic_length = 7;
  const int version = 0x100000;
  enum  arch_type
  {
    vm_package = 1,
    vm_data = 2,
    vm_package_bundle = 3
  };

  void  
    archive::save ( io_stream* ios, PACKAGE *pkg )
  {
    int i = 0;
    int size = 0;
    char  buffer [ 1024 ];

    in_memory_stream ms;
    _body = &ms;
    _symbols.clear ();

    if ( !ios->write ( magic, magic_length ) )
      goto problem_write;
    if ( !ios->write ( version ) )
      goto problem_write;

    if ( !ios->write ( (int) vm_package ) )
      goto problem_write;

    write ( pkg );

    if ( !ios->write ( _symbols.size () ) )
      goto problem_write;
    for ( i = 0; i < _symbols.size(); i++ )
      if ( !ios->write ( (const char *) VM::voc [ _symbols [ i ] ] ) )
        goto problem_write;

    _body->position ( 0 );
    for ( size = _body->size (); size > 0; size -= 1024 )
    {
      int length = min ( size, 1024 );
      if ( !_body->read ( buffer, length ) )
        goto problem_read;
      if ( !ios->write ( buffer, length ) )
        goto problem_write;
    }
    return;

  problem_write:
    // raise error here
    VM::error ( ios->err_message );
    return;
  problem_read:
    // raise error here
    VM::error ( _body->err_message );
    return;
  }

  void
    archive::save ( io_stream* ios, symbol_t mainpackage )
  {
    int       i = 0;
    int       size = 0;
    symbol_t  std_sym = VM::voc [ "std" ];
    char  buffer [ 1024 ];

    array<PACKAGE *> bundle;
    int iter_cnt = 0;
    int mainpackage_idx = 0;

    in_memory_stream ms;
    _body = &ms;
    _symbols.clear ();

    hash_table<string, string> natives;

    if ( !ios->write ( magic, magic_length ) )
      goto problem_write;

    if ( !ios->write ( version ) )
      goto problem_write;

    if ( !ios->write ( (int) vm_package_bundle ) )
      goto problem_write;

    // make list of packages
    for ( i = 0; i < VM::packages->size (); i++ )
    {
      PACKAGE *pkg = (PACKAGE *) ( *VM::packages ) [ i ].value.v.v_class;
      if ( pkg->is_native () )
      {
        // register all external packages
        if ( pkg != VM::std )
        {
          string pname = VM::voc [ pkg->name ];
          natives [ pname ] = pname;
        }
      }
      else  // this is bytecode (soft) package
      {
        bundle.push ( pkg );
        VM::info ( "packaging %s\n", VM::voc [ pkg->name ] );
      }
    }

    // sort it
    for ( i=0; i < bundle.size () && iter_cnt < 1000; iter_cnt++ )
    {
      int      ref  = -1;
      PACKAGE *pack = bundle [ i ];
      for ( int j = i + 1; j < bundle.size(); j++ )
      {
        if ( pack->has_reference_to ( bundle [ j ]->name ) )
          ref = j;
      }
      if ( ref >= 0 )
      { // move
        PACKAGE *pkg = bundle [ i ]; bundle.remove ( i );
        bundle.insert ( ref, pkg );
      }
      else ++i;
    }
    if ( iter_cnt >= 1000 )
      VM::info ( "WARNING:package bundle not properly ordered (cyclic reference?)" );

    // write one by one soft packages into intermediate buffer;
    for ( i = 0; i < bundle.size () ;i++ )
    {
      write ( bundle [ i ] );
      if ( bundle [ i ]->name == mainpackage )
        mainpackage_idx = i;
    }

    // write one by one external native packages names
    if ( !ios->write ( (int) natives.size () ) )
      goto problem_write;

    for ( i = 0; i < natives.size(); i++ )
      if ( !ios->write ( (const char *) natives.elements() [ i ] ) )
        goto problem_write;

    // write soft packages
    if ( !ios->write ( (int) mainpackage_idx ) )
      goto problem_write;

    if ( !ios->write ( (int)bundle.size () ) )
      goto problem_write;

    if ( !ios->write ( _symbols.size () ) )
      goto problem_write;

    for ( i = 0; i < _symbols.size (); i++ )
      if  ( !ios->write ( (const char *) VM::voc [ _symbols [ i ] ] ) )
        goto problem_write;

    _body->position ( 0 );
    while ( true )
    {
      int length;
      _body->read ( buffer, 1024, &length );
      if ( length == 0 )
        break;
      if ( !ios->write ( buffer, length ) )
        goto problem_write;
    }
    return;

  problem_write:
    // raise error here
    VM::error ( ios->err_message );
  }


  VALUE
    archive::load ( io_stream* ios )
  {
    VALUE   val;
    int     ver;
    char    buffer [ magic_length ];
    int     syms = 0;
    string  s;
    int     type;
    int mainpackage = -1;
    int bundle_size = 0;

    if ( !ios->read ( buffer, magic_length ) )
      goto problem_read;

    if ( memcmp ( buffer, magic, magic_length ) != 0 )
      VM::error ( "bad archive signature" );

    if( !ios->read ( ver ) )
      goto problem_read;

    if ( ver > version )
      VM::error ( "unsupported archive version" );

    if ( !ios->read ( type ) )
      goto problem_read;

    if ( type == vm_package_bundle )
    {
      // read one by one external native packages names
      int natives_num = 0;

      if ( !ios->read ( natives_num ) )
        goto problem_read;

      for ( int i = 0; i < natives_num; i++ )
      {
        string native_name;
        if ( !ios->read ( native_name ) )
          goto problem_read;
        VM::load_native_module ( native_name );
      }

      if ( !ios->read ( mainpackage ) )
        goto problem_read;

      if ( !ios->read ( bundle_size ) )
        goto problem_read;
    }

    if ( !ios->read ( syms ) )
      goto problem_read;

    _symbols.clear ();

    for ( ; syms > 0; syms-- )
    {
      if ( !ios->read ( s ) )
        goto problem_read;

      _symbols.push ( VM::voc [ s ] );
    }

    _body = ios;

    switch ( type )
    {
    case vm_package:
      {
        PACKAGE *pkg;
        read ( pkg );
        val = pkg;
      }
      break;
    case vm_package_bundle:
      {
        PACKAGE *pkg;
        for ( int i = 0; i < bundle_size; i++ )
        {
          read ( pkg );
          if ( i == mainpackage )
            val = pkg;
        }
      }
      break;
    default:
      assert ( false );
      break;
    }

    return val;

  problem_read:
    VM::error ( ios->err_message );
    return val;
  }

};

⌨️ 快捷键说明

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