EnglishРусский  

   ..

   alias.c

   alias.h

   bcodes.c

   bcodes.h

   body.c

   compile.c

   compile.h

   define.c

   define.h

   desc.c

   expr.c

   extern.c

   for.c

   foreach.c

   func.c

   func.h

   global.c

   global.h

   goto.c

   if.c

   ifdef.c

   ifdef.h

   import.c

   import.h

   include.c

   include.h

   jump.c

   lexem.c

   lexem.h

   macro.c

   macro.h

   operlist.txt

   out.c

   out.h

   subfunc.c

   switch.c

   type.c

   type.h

   vars.c

   while.c

   with.c

The project is closed! You can look at a new scripting language. It is available on GitHub.
Also, try our open source cross-platform automation software.

Ads

Installer and installation software
Commercial and Freeware installers.

   1 /******************************************************************************
   2 *
   3 * Copyright (C) 2006, The Gentee Group. All rights reserved.
   4 * This file is part of the Gentee open source project - http://www.gentee.com.
   5 *
   6 * THIS FILE IS PROVIDED UNDER THE TERMS OF THE GENTEE LICENSE ("AGREEMENT").
   7 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS FILE CONSTITUTES RECIPIENTS
   8 * ACCEPTANCE OF THE AGREEMENT.
   9 *
  10 * ID: expr 22.01.07 0.0.A.
  11 *
  12 * Author: Alexander Krivonogov ( algen )
  13 *
  14 * Summary: Обработка выражений
  15 *
  16 ******************************************************************************/
  17 
  18 #include "func.h"
  19 #include "bcodes.h"
  20 #include "compinit.h"
  21 #include "../vm/vmtype.h"
  22 #include "alias.h"
  23 
  24 /*-----------------------------------------------------------------------------
  25 *
  26 * ID: exptoken 22.01.07 0.0.A.
  27 *
  28 * Summary: Структура токенов
  29 *
  30 -----------------------------------------------------------------------------*/
  31 
  32 typedef struct _exptoken
  33 {
  34    plexem           lex;   //Указатель на лексему
  35    struct _exptoken *left; //Указатель на левый операнд
  36    uint             flg;   //Флаг FTOK_*
  37    union {
  38       uint  offlocvar;     //Смещение локальной переменной
  39       uint  idglobvar;     //Идентификатор глобальной переменной
  40       uint  idglobfunc;    //Идентификатор глобальной функции      
  41       uint  idalias;       //Идентификатор псевдонима функции
  42       uint  parofsize;     //Тип параметр для ofsize
  43       uint  cmdbytecode;   //Команда для байткода
  44       uint  val;           //Идентификатор в соответствующей таблице, в зависимости от flg
  45       pstr  strbin;        //Указатель на строку или бинарные данные
  46    };
  47    union {
  48       uint  offout;        //Смещение в байт коде
  49       uint  pars;          //Количество параметров для функции
  50    };
  51    uint     type;          //Результирующий тип
  52    uint     ol;            //Смещение в таблице меток для хранения переходов в случае && или ||
  53    uint     oftype;
  54    uint     msr;   
  55 } exptoken, * pexptoken;
  56 
  57 /*-----------------------------------------------------------------------------
  58 *
  59 * ID: expoper 22.01.07 0.0.A.
  60 *
  61 * Summary: Структура операции
  62 *
  63 -----------------------------------------------------------------------------*/
  64 typedef struct
  65 {
  66    uint      operid; //Код операции
  67 
  68    plexem    lex;    //Указатель на лексему
  69    pexptoken left;   //Указатель на левый операнд
  70    uint      flg;    
  71    uint      val;    
  72    uint      pars;   //Количество параметров
  73 } expoper, * pexpoper;
  74 
  75 //Типы токенов
  76 #define FTOK_LOCVAR       0x01 //Локальная переменная
  77 #define FTOK_GLOBVAR      0x02 //Глобальная переменная
  78 #define FTOK_SUBFUNC      0x03 //Вызов локальной функции
  79 #define FTOK_GLOBFUNC     0x04 //Вызов глобальной функции
  80 #define FTOK_ADDRFUNC     0x05 //Вызов функции по её адресу
  81 #define FTOK_METHODFUNC   0x06 //Вызов метода
  82 #define FTOK_FIELD        0x07 //Поле структуры
  83 #define FTOK_NUMBER       0x08 //Число
  84 #define FTOK_OPER         0x09 //Оператор
  85 #define FTOK_PTRTYPE      0x0A //Приведение к типу
  86 #define FTOK_GLOBFUNCADDR 0x0B //Адрес глобальной функции
  87 #define FTOK_STRBIN       0x0C //Строка или двоичные данные
  88 #define FTOK_QUEST        0x0D //Операция ?(,,)
  89 #define FTOK_ARR          0x0E //Массив
  90 #define FTOK_SIZEOF       0x0F //Sizeof
  91 #define FTOK_TYPE         0x10 //0x200000 //Тип
  92 #define FTOK_BYTECODE     0x11 //0x400000 //Команда байткода
  93 #define FTOK_COLLECT      0x12 //0x500000 //Загрузка коллекции
  94 #define FTOK_COLLECTNEW   0x13 //0x600000 //Загрузка коллекции
  95 #define FTOK_LATE         0x14 //Отложеный вызов
  96 #define FTOK_ALIAS        0x15 //Псевдоним функции
  97 //Маски для типов токенов
  98 #define FTOK_NOFLAGS        0x0000FF//FF0000
  99 #define FTOK_FLAGS          0xFFFF00//00FFFF
 100 //Флаги токенов
 101 #define FTOK_LVALUE         0x000100 //Текущий операнд должен быть lvalue
 102 #define FTOK_FUNCPAR        0x000200 //Параметр функции
 103 #define FTOK_OPAND          0x000400 //Операнд операции &&
 104 #define FTOK_OPOR           0x000800 //Операнд операции ||
 105 #define FTOK_FUNC           0x001000 //Функция
 106 #define FTOK_QUESTFIRST     0x002000 //Первый операнд операции ?
 107 #define FTOK_QUESTSECOND    0x004000 //Второй операнд операции ?
 108 #define FTOK_QUESTTHIRD     0x008000 //Третий операнд операции ?
 109 #define FTOK_ADDFUNCPAR     0x010000 //Требуется добавить параметр функции (для метода)
 110 #define FTOK_LVALPROPERTY   0x020000 //Присваивание свойству
 111 #define FTOK_TEXT           0x040000 //Функция является текстовой
 112 #define FTOK_LVALLATE       0x080000 //Присваивание отложенному вызову
 113 #define FTOK_COLLECTIONLATE 0x100000 //Новая коллекция создается для позднего вызова
 114 #define FTOK_WITH           0x200000 //Опарация сокращенного вызова полей
 115 
 116 //Макроопределения для загрузок фиктивных операций-функций
 117 #define STACK_ADD( _ftok, _pars, _left, _lex ) \
 118 stackc->operid = OpFunc;\
 119 stackc->lex = _lex;\
 120 stackc->flg = _ftok | FTOK_FUNC | FTOK_FUNCPAR;\
 121 stackc->pars = _pars;\
 122 stackc->left = _left;\
 123 stackc++;\
 124 state = L_UNARY_OPEN | L_FUNC;
 125 
 126 #define STACK_ADDARR() \
 127 STACK_ADD( FTOK_ARR, 1, tokc-1, lastlex )
 128 
 129 #define STACK_ADDFUNC(_ftok)\
 130 STACK_ADD( _ftok, 0, tokc-1, curlex )
 131 
 132 #define STACK_ADDMETHOD(_ftok)\
 133 STACK_ADD( _ftok, 1, tokc-1, curlex )
 134 
 135 
 136 //Таблица команд для получения чисел
 137 uint artypes[ TUlong + 1 ] = 
 138          { 0, CGetI, CGetI, CGetB, CGetUB, CGetS, CGetUS, CGetI, CGetL, CGetL, CGetL };
 139 
 140 /*-----------------------------------------------------------------------------
 141 *
 142 * ID: f_exp 22.01.07 0.0.A.
 143 *
 144 * Summary: Обработка выражений
 145 *
 146 -----------------------------------------------------------------------------*/
 147 
 148 plexem STDCALL f_expr( plexem curlex, uint flg, puint rettype, puint retoftype )
 149 {
 150    plexem      lastlex;   //Предыдущая лексема
 151    plexem      lex;       //Обрабатываемая лексема
 152    plexem      firstlex;  //Первая лексема
 153 
 154    psoper      curop;     //Текущая операция
 155    psoper      stackop;   //Оператор из стэка
 156 
 157    pexpoper    stackb;    //Указатель на начало стэка операций
 158    pexpoper    stackc;    //Указатель на следующий элемент стэка операций
 159 
 160    pexptoken   tokb;    //Указатель на начало таблицы
 161    pexptoken   tokc;    //Указатель на следующий элемент таблицы
 162    pexptoken   toki;    //Указатель на текущий элемент таблицы
 163    pexptoken   toktmp;  //Временный указатель на операнд
 164    plexem      maxlex;
 165 
 166    uint        curop_flgs;
 167    uint        curop_before;
 168    uint        curop_id;
 169    uint        stackop_flgs;
 170    uint        stackop_after;
 171    uint        stackop_id;
 172 
 173    uint        state;     // Текущее состояние обработчика
 174    uint        laststate; // Предыдущее состояние обработчика
 175    uint        bropen;    // Количество открытых скобок
 176    uint        flgexp;    // Флаг продалжать обработку
 177 
 178    uint        off;       //Временная переменная для различных смещений
 179    uint        id;        //Временная переменная для хранения идентификаторов
 180    phashiuint  phitem;    //Элемент хэштаблицы с локальной переменной
 181 
 182    s_desctype  desctype;  //Описание типа
 183    pfvar       pvar;      //Указатель на структуру локальной переменной
 184    pfvaras     pvaras;    //Указатель на структуру as
 185    povmtype    ptype;     //Указатель на струкутру объекта
 186    pvartype    pglobvar;  //Указатель на структуру типа глобальной переменной
 187    pvmfunc     pfunc;     //Указатель на структуру байткода
 188    pfwith      pwith;     //Указатель на структуру with
 189    pvartype    field, isfield;//Поле структуры
 190 
 191    uint   flglvallate; //Флаг позднее связывание с lvalue операцией   
 192    uint   type;
 193    puint  parsc, parsb, parse, psrc;//Указатели в стэке параметров
 194    uint   numtypes;    //Количество различных типов для коллекции
 195    uint   num;         //Текущее количество
 196    uint   stsize;      //Размер текущего элемента коллекции
 197    pubyte name;         
 198    uint   len;
 199    uint   dwsize;      //Подсчет сумарного размера
 200    uint   i;   
 201    
 202 D("Expr start\n" );
 203 // Инициализация
 204    stackc = stackb = _compile->stkopers;
 205    parsc = _compile->stkpars;
 206    tokc = tokb = _compile->stkops;
 207    flgexp = 1;
 208    lastlex = 0;
 209    bropen = 0;
 210    flglvallate = 0;
 211    laststate = L_UNARY_OPEN;
 212    maxlex = curlex + min( STACK_OPERS / sizeof( soper ), min( STACK_OPS / sizeof( exptoken ), STACK_PARS / sizeof( uint ) ));   
 213    firstlex = curlex;
 214 
 215 //Цикл первого прохода
 216    while ( 1 )
 217    {
 218    //Предварительная обработка
 219       if ( curlex->type == LEXEM_KEYWORD &&
 220            curlex->key == KEY_AS )
 221       {
 222          curlex->type = LEXEM_OPER;
 223          curlex->oper.operid = OpAs;
 224       }      
 225 
 226       switch ( curlex->type )
 227       {
 228          case LEXEM_OPER: 
 229             curop = (psoper)&opers[curop_id = curlex->oper.operid]; 
 230             curop_flgs = curop->flgs;
 231             curop_before = curop->before;
 232             //Первичная обработка оператора
 233             if ( curop_flgs & OPF_OPEN )//Открывающие скобки
 234             {               
 235                if ( curop_id == OpLcrbrack )
 236                   flgexp = 0;//Если в конце выражения откр. фиг. скобка, то выходим из цикла
 237                else
 238                {
 239                   state = L_UNARY_OPEN;
 240                   bropen++;
 241                }
 242             }
 243             else
 244             if ( curop_flgs & OPF_CLOSE )//Закрывающие скобки
 245             {               
 246                if ( bropen )
 247                {
 248                   state = L_POST_CLOSE;
 249                   bropen--;
 250                }
 251                else
 252                {
 253                   if ( curop_id == OpRcrbrack ||
 254                        ( stackc != stackb ||
 255                        tokc != tokb ))
 256                      flgexp = 0;//Непарная скобка
 257                   else
 258                      msg( MSyntax | MSG_LEXNAMEERR, curlex );
 259                }
 260             }
 261             else
 262             if ( curop_id == OpLine ) // Перенос строки
 263             {
 264                if ( laststate & L_BINARY || bropen > 0 )
 265                   goto next;
 266                flgexp = 0;
 267             }
 268             else
 269             if ( curop_id == OpComma && !bropen )//, - Запятая
 270             {
 271                if ( flg & ( EXPR_VAR | EXPR_COMMA ) )
 272                   flgexp = 0;
 273                else
 274                   msg( MSyntax | MSG_LEXNAMEERR, curlex );
 275             }
 276             else
 277             if ( curop_flgs & OPF_UNDEF ) //Неопределённый оператор
 278             {
 279                if ( laststate & ( L_OPERAND | L_POST_CLOSE ))
 280                {
 281                   curop = ( psoper )&opers[curop_id = ++curlex->oper.operid];
 282                   curop_flgs = curop->flgs;
 283                   curop_before = curop->before;
 284                }
 285             }
 286             
 287          //Установка текущего состояния
 288             if ( curop_flgs & OPF_BINARY )
 289             {
 290                state = L_BINARY;
 291             }
 292             else
 293             if ( curop_flgs & OPF_UNARY )
 294             {
 295                state = L_UNARY_OPEN;
 296             }
 297             else
 298             if ( curop_flgs & OPF_POST )
 299             {
 300                state = L_POST_CLOSE;
 301             }
 302             
 303          //Цикл выталкивания из стека операций            
 304             while ( stackc != stackb )
 305             {               
 306                stackop_id = (stackc-1)->operid;
 307                stackop = (psoper)&opers[stackop_id];
 308                stackop_after = stackop->after;
 309                stackop_flgs = stackop->flgs;               
 310                if ( !flgexp || stackop_after >= curop_before )
 311                {
 312                   stackc--;
 313                   if ( stackop_flgs & OPF_OPEN )
 314                   {
 315                      if ( stackop_id != curop_id - 1 && 
 316                            ( stackop_id != OpCollect || curop_id != OpRcrbrack ) )
 317                         msg( MNotopenbr | MSG_LEXERR , curlex );
 318                   }
 319                   if ( !( stackop_flgs & ( OPF_OPEN | OPF_CLOSE ) ||
 320                        stackop_id == OpComma ) )
 321                   {
 322                      tokc->lex = stackc->lex;
 323                      //?Не проще будет tokc->left = stackc->left
 324                      if ( stackop_flgs & OPF_BINARY || stackc->flg & FTOK_FUNC )
 325                         tokc->left = stackc->left;
 326                      else
 327                         tokc->left = 0;
 328 
 329                      tokc->flg = stackc->flg;
 330                      tokc->val = stackc->val;
 331                      tokc->pars = stackc->pars;
 332 
 333                      if ( stackop_flgs & OPF_LVALUE )
 334                      {
 335                         if ( stackop_flgs & OPF_BINARY )
 336                            tokc->left->flg |= FTOK_LVALUE;
 337                         else
 338                            (tokc-1)->flg |= FTOK_LVALUE;
 339                      }
 340                      tokc++;
 341                   }
 342                }
 343                if ( flgexp && stackop_after <= curop_before )
 344                {  //Выход из цикла выталкивания
 345                   break;
 346                }
 347             }
 348             
 349          //Конечная обработка системной лексемы, добавление в стэк операций
 350             if ( flgexp )
 351             {
 352 
 353                if ( curop_id == OpLsqbrack )
 354                {
 355                   (tokc-1)->flg |= FTOK_ADDFUNCPAR;
 356                   STACK_ADDARR();
 357                   laststate = state;
 358                }
 359                else if ( curop_id == OpCollect )
 360                {
 361                   STACK_ADDFUNC( FTOK_COLLECT );
 362                   //laststate = state;
 363                   laststate = laststate | L_FUNC;
 364                }
 365                stackc->flg = FTOK_OPER;
 366                //Конечная обработка
 367                if ( stackc != stackb )
 368                {
 369                   if ( curop_flgs & OPF_OPEN && laststate & L_FUNC )
 370                   {
 371                      laststate = laststate & ~L_FUNC;
 372                      stackc->flg |= FTOK_FUNCPAR;
 373                      stackc->pars = bropen;
 374                      stackc->val = (uint)(stackc-1);
 375                   }
 376                   if ( curop_flgs & OPF_CLOSE &&
 377                        stackc != stackb &&
 378                        ( stackc-1)->flg & FTOK_FUNCPAR &&
 379                        lastlex->type == LEXEM_OPER &&
 380                        ((psoper)&opers[lastlex->oper.operid])->flgs & OPF_OPEN )
 381                   {                     
 382                      laststate = L_OPERAND;
 383                      if ( (stackc-1)->flg & FTOK_FUNC )
 384                         ( stackc-1)->flg &= ~FTOK_FUNCPAR;
 385                   }
 386                   else
 387                   if ( ( curop_id == OpComma ||
 388                          (curop_flgs & OPF_CLOSE) ) &&
 389                          stackc != stackb &&
 390                       ((stackc-1)->flg & FTOK_FUNCPAR) )
 391                   {                     
 392                      if ( !( curop_flgs & OPF_CLOSE ) ||
 393                         ( stackc-1)->flg & FTOK_FUNC ||
 394                         (stackc-1)->pars == bropen - 1 )
 395                      {
 396                         if ( ( stackc-1)->flg & FTOK_FUNC )
 397                         {
 398                            stackc->val = (uint)(stackc-1);
 399                            ( stackc-1)->flg &= ~FTOK_FUNCPAR;
 400                         }
 401                         else
 402                         {
 403                            stackc->val = (stackc-1)->val;
 404                            stackc->pars = bropen;
 405                         }
 406                         stackc->flg = FTOK_FUNCPAR;
 407                         ((pexpoper)(stackc->val))->pars++;
 408                         (tokc-1)->flg |= FTOK_FUNCPAR;
 409                         if ( ((pexpoper)(stackc->val))->lex->type == LEXEM_OPER  &&
 410                              ((pexpoper)(stackc->val))->lex->oper.operid == OpQuest )
 411                         {
 412                            if ( ((pexpoper)(stackc->val))->pars == 1 )
 413                               (tokc-1)->flg |= FTOK_QUESTFIRST;
 414                            else if ( ((pexpoper)(stackc->val))->pars == 2 )
 415                               (tokc-1)->flg |= FTOK_QUESTSECOND;
 416                            else if ( ((pexpoper)(stackc->val))->pars == 3 )
 417                               (tokc-1)->flg |= FTOK_QUESTTHIRD;
 418                         }
 419                         else if ( ( ((pexpoper)(stackc->val))->flg & FTOK_NOFLAGS ) == 
 420                                     FTOK_SIZEOF )
 421                         {
 422                            if ( (( tokc - 1 )->flg & FTOK_NOFLAGS ) == FTOK_TYPE )
 423                            {
 424                               tokc--;
 425                               ((pexpoper)(stackc->val))->val = tokc->type;                
 426                            }
 427                            else
 428                            {
 429                               ((pexpoper)(stackc->val))->val = 0;                   
 430                            }
 431                         }
 432                      }
 433                   }
 434                }
 435 
 436                if ( curop_id == OpLogand )
 437                   (tokc-1)->flg |= FTOK_OPAND;
 438                else
 439                   if ( curop_id == OpLogor )
 440                      (tokc-1)->flg |= FTOK_OPOR;
 441                if ( curop_id == OpQuest )
 442                {  //Создание фиктивной функции для операции ?                  
 443                   stackc->flg = FTOK_QUEST | FTOK_FUNC | FTOK_FUNCPAR;
 444                   stackc->pars = 0;
 445                   state = L_UNARY_OPEN | L_FUNC;
 446                }
 447                else if ( curop_id == OpCollect )
 448                {
 449                   //Фиктивного операнда для создания новой переменной-коллекции
 450                   tokc->lex = curlex;
 451                   tokc->flg = FTOK_COLLECTNEW | FTOK_ADDFUNCPAR;
 452                   tokc->val = 0;
 453                   tokc++;
 454                }
 455                else if ( curop_id == OpStrout )
 456                {
 457                   tokc->cmdbytecode = CGetText;
 458                   tokc->lex = curlex;
 459                   tokc->flg = FTOK_BYTECODE;
 460                   tokc->pars = 0;
 461                   tokc++;
 462                }
 463                else if ( curop_id == OpWith )
 464                {
 465                   tokc->lex = curlex;
 466                   tokc->flg = FTOK_LOCVAR | FTOK_WITH;
 467                   tokc->offlocvar = 0;
 468                   tokc++;
 469                   curop_id = OpPoint;
 470                }                  
 471                stackc->lex = curlex;
 472                stackc->operid = curop_id;
 473                stackc->left = tokc-1;
 474                stackc++;
 475             }            
 476             break;            
 477 
 478             // Обработка операндов
 479             case LEXEM_NAME://Идентификатор
 480                if ( stackc != stackb )
 481                {
 482                   if ( (stackc-1)->operid == OpPoint )
 483                   {
 484                      stackc--;
 485                      if ( curlex->flag & LEXF_CALL )
 486                      {  //Вызов метода                        
 487                         curlex->flag |= LEXF_METHOD;
 488                         //Добавляем в стэк фиктивную операцию
 489                         (tokc-1)->flg |= FTOK_ADDFUNCPAR;
 490                         STACK_ADDMETHOD( FTOK_METHODFUNC );
 491                      }
 492                      else
 493                      {  //Поле
 494                         tokc->lex = curlex;
 495                         tokc->flg = FTOK_FIELD;                        
 496                         tokc++;
 497                         state = L_OPERAND;
 498                      }
 499                      break;
 500                   }
 501                   else if ( (stackc-1)->operid == OpLate )
 502                   {   //Отложенный метод-свойство
 503                      stackc--;
 504                      if ( curlex->flag & LEXF_CALL )
 505                      {
 506                         //Позднее связываение в стэк операций
 507                         (tokc-1)->flg |= FTOK_ADDFUNCPAR;                        
 508                         stackc->val = 0;
 509                         curlex->flag |= LEXF_METHOD;                        
 510                         STACK_ADDFUNC( FTOK_LATE );
 511                         (stackc-1)->flg = FTOK_LATE | FTOK_FUNC;
 512                         
 513                         //Заголовок коллекции
 514                         tokc->lex = curlex;
 515                         tokc->flg = FTOK_COLLECTNEW | FTOK_COLLECTIONLATE;                        
 516                         tokc->val = 0;
 517                         tokc++;
 518 
 519                         //Коллекция в стэк операций
 520                         STACK_ADDFUNC( FTOK_COLLECT | FTOK_COLLECTIONLATE);
 521                         
 522                      }
 523                      else
 524                      {                        
 525                         //Заголовок коллекции
 526                         tokc->lex = curlex;
 527                         tokc->flg = FTOK_COLLECTNEW | FTOK_COLLECTIONLATE;
 528                         tokc->val = 0;
 529                         tokc++;
 530 
 531                         //Коллекция
 532                         tokc->lex = curlex;
 533                         tokc->flg = FTOK_FUNC | FTOK_COLLECT | FTOK_COLLECTIONLATE;
 534                         tokc->pars = 0;
 535                         tokc->val = 0;
 536                         tokc++;
 537 
 538                         //Позднее связывание
 539                         tokc->lex = curlex;
 540                         tokc->flg = FTOK_LATE;
 541                         tokc->val = 0;
 542                         tokc->pars = 0;
 543                         tokc++;
 544                         
 545                         state = L_OPERAND;                        
 546                      }
 547                      break;
 548                   }
 549                }
 550                if ( phitem = (phashiuint)hash_find( &fd.nvars, lexem_getname( curlex )) )
 551                {  //Идентификатор есть в таблице локальных переменных
 552                   if ( off = phitem->val )
 553                   {                     
 554                      pvar = ( pfvar)(fd.bvars.data+off);
 555                      if ( pvar->flg & FVAR_SUBFUNC )
 556                      {  // Подфункция
 557                         if ( !( curlex->flag & LEXF_CALL ) )
 558                            msg( MExpopenbr | MSG_LEXERR , curlex );
 559                         stackc->val = off;
 560                         //Добавляем в стэк фиктивную операцию
 561                         STACK_ADDFUNC( FTOK_SUBFUNC );
 562                      }
 563                      else
 564                      {  // Локальная переменная
 565                         tokc->lex = curlex;
 566                         tokc->flg = FTOK_LOCVAR;
 567                         tokc->offlocvar = off;
 568                         tokc++;
 569                         state = L_OPERAND;
 570                      }
 571                      break;
 572                   }
 573                }
 574                id = bc_getid( curlex );
 575                if ( id )
 576                //Проверка в глобальной таблице
 577                switch ( (( pvmobj )PCMD( id ))->type )
 578                {
 579                   case OVM_BYTECODE:
 580                   case OVM_EXFUNC:
 581                   case OVM_STACKCMD:                     
 582 
 583                      if ( curlex->flag & LEXF_CALL )
 584                      {  
 585                         //Добавляем в стэк фиктивную операцию
 586                         STACK_ADDFUNC(FTOK_GLOBFUNC);                        
 587                         if ( (( pvmobj )PCMD( id ))->flag & GHBC_TEXT )
 588                         {
 589                            (stackc-1)->flg |= FTOK_TEXT;
 590                         }
 591                      }
 592                      else
 593                      {  //Возможно взятие адреса функции
 594                         if ( (( pvmobj )PCMD( id ))->nextname )
 595                            msg( MNoaddrfunc | MSG_LEXNAMEERR, curlex );
 596                         tokc->idglobfunc = (( pvmobj )PCMD( id ))->id;
 597                         tokc->lex = curlex;
 598                         tokc->flg = FTOK_GLOBFUNCADDR;
 599                         tokc->pars = 0;
 600                         tokc++;
 601                         state = L_OPERAND;
 602                      }
 603                      break;
 604                   case OVM_TYPE:
 605                      if ( curlex->flag & LEXF_CALL )
 606                      {  //Преобразование типа
 607                         stackc->val = 0;
 608                         curlex->flag |= LEXF_METHOD;
 609                         //Добавляем в стэк фиктивную операцию
 610                         STACK_ADDFUNC( FTOK_GLOBFUNC );
 611                      }
 612                      else
 613                      {  //Тип для приведения
 614                         tokc->lex = curlex;
 615                         tokc->type = bc_type( curlex );
 616                         if ( lastlex && lastlex->type == LEXEM_OPER && lastlex->oper.operid == OpPtr )
 617                         {                           
 618                            tokc->flg = FTOK_PTRTYPE;
 619                            stackc--;
 620                         }
 621                         else                        
 622                            tokc->flg = FTOK_TYPE;
 623                         
 624                         curlex = desc_idtype( curlex, &desctype );
 625                         curlex--;
 626                         tokc->oftype = desctype.oftype;
 627                         
 628                         state = L_OPERAND;
 629                         tokc++;
 630                      }
 631                      break;
 632                   case OVM_GLOBAL://Глобальная переменная
 633                      tokc->lex = curlex;
 634                      tokc->idglobvar = id;
 635                      tokc->flg = FTOK_GLOBVAR;
 636                      state = L_OPERAND;
 637                      tokc++;
 638                      break;
 639                   case OVM_ALIAS:
 640                      tokc->lex = curlex;
 641                      tokc->idalias = alias_getid( id );
 642                      tokc->flg = FTOK_ALIAS;
 643                      state = L_OPERAND;
 644                      tokc++;
 645                      break;
 646                }
 647                else
 648                   msg( MUnkname | MSG_LEXNAMEERR, curlex );//Неизвестный идентификатор
 649                break;
 650 
 651             case LEXEM_NUMBER://Число
 652                tokc->lex = curlex;
 653                tokc->flg = FTOK_NUMBER;
 654                tokc->type = curlex->num.type;
 655                tokc->oftype = 0;
 656                tokc++;
 657                state = L_OPERAND;               
 658                break;
 659 
 660             case LEXEM_STRING://Строка                
 661                tokc->strbin = lexem_getstr( curlex );
 662                //print( "LEXEM_STRING %x %c\n", tokc->strbin->use, tokc->strbin->data[0] );
 663                tokc->flg = FTOK_STRBIN;
 664                tokc->lex = curlex;
 665                tokc->type = TStr;
 666                tokc->oftype = 0;
 667                tokc++;
 668                state = L_OPERAND;
 669                break;
 670 
 671             case LEXEM_BINARY://Двоичные данные
 672                tokc->strbin = lexem_getstr( curlex );
 673                tokc->flg = FTOK_STRBIN;
 674                tokc->lex = curlex;
 675                tokc->type = TBuf;
 676                tokc->oftype = 0;
 677                tokc++;
 678                state = L_OPERAND;               
 679                break;
 680 
 681             case LEXEM_KEYWORD:               
 682                if ( ( curlex->key == KEY_FUNC ||
 683                       curlex->key == KEY_STDCALL ||
 684                       curlex->key == KEY_CDECL ) &&
 685                     (stackc-1)->operid == OpPtr )
 686                {  //Вызов функции по адресу                  
 687                   stackc->val = 0;
 688                   //Добавляем в стэк фиктивную операцию
 689                   STACK_ADDFUNC( FTOK_ADDRFUNC );
 690                }
 691                else
 692                {
 693                   if ( curlex->key == KEY_SIZEOF )
 694                   {  
 695                      //Добавляем в стэк фиктивную операцию
 696                      STACK_ADDFUNC( FTOK_SIZEOF );
 697                   }                 
 698                   else
 699                      msg( MNokeyword | MSG_LEXERR, curlex );
 700                }
 701                break;
 702             default:
 703                msg( MUnkname | MSG_LEXNAMEERR, curlex );
 704       }
 705 // Проверка синтаксиса выражения
 706       if ( flgexp )
 707       {         
 708          switch ( laststate )
 709          {
 710             case L_OPERAND:
 711             case L_POST_CLOSE:
 712                if ( state & L_OPERAND ||
 713                     state & L_UNARY_OPEN )
 714                {
 715                   msg( MUnexpoper | MSG_LEXERR, curlex );
 716                }
 717                break;
 718             default:
 719                if ( state & L_BINARY ||
 720                     state & L_POST_CLOSE )
 721                   msg( MMustoper | MSG_LEXERR, curlex );
 722          }
 723          laststate = state;
 724       }
 725       else
 726       {
 727          if ( ( laststate == L_UNARY_OPEN && tokc != tokb ) ||
 728               laststate == L_BINARY )
 729             msg( MMustoper | MSG_LEXERR, curlex );
 730          break;
 731       }
 732 next:
 733       lastlex = curlex;
 734       curlex = lexem_next( curlex, 0 );
 735       if ( curlex > maxlex )
 736          msg( MExpmuch | MSG_LEXERR, curlex );
 737    }
 738    D( "Bytecode start\n" );
 739    if ( tokb != tokc )
 740    {
 741       out_debugtrace( firstlex );
 742    }
 743     /*  && _compile->flag & CMPL_DEBUG )
 744    {  
 745       out_adduints( 3, 
 746          CDwload, 
 747          str_pos2line( _compile->cur->src, firstlex->pos, 0 ) + 1, 
 748          CDbgTrace );
 749    }*/
 750 //Цикл формирования байткода
 751    for ( toki = tokb; toki < tokc; toki++ )
 752    {
 753       lex = toki->lex;
 754       if ( toki->flg & FTOK_LVALUE &&
 755             (  ( toki->flg & FTOK_NOFLAGS ) == FTOK_NUMBER ||
 756                ( toki->flg & FTOK_NOFLAGS ) == FTOK_TYPE
 757             ) )
 758       {
 759          msg( MExplvalue | MSG_LEXERR, lex );
 760       }      
 761 
 762       switch( toki->flg & FTOK_NOFLAGS )
 763       {
 764          case FTOK_LOCVAR: //Локальная переменная
 765             toki->offout = fd.bout->use;
 766             if ( toki->flg & FTOK_WITH )
 767             {
 768                out_add2uint( CVarload, 0 );
 769             }
 770             else
 771             {               
 772                pvar = ( pfvar)(fd.bvars.data + toki->offlocvar);               
 773                toki->type = pvar->type;
 774 
 775                if ( toki->flg & FTOK_LVALUE &&
 776                      (( pvmobj )PCMD( toki->type ))->flag & GHTY_STACK )
 777                   out_adduint( CVarptrload );
 778                else
 779                   out_adduint( CVarload );
 780                out_adduint( pvar->num );
 781                toki->oftype = pvar->oftype;
 782             }
 783             break;
 784 
 785          case FTOK_GLOBVAR: //Глобальная переменная
 786             out_add2uint( CPtrglobal, toki->idglobvar );
 787             pglobvar = ((povmglobal)PCMD( toki->idglobvar ))->type;
 788             ptype = (( povmtype )PCMD( toki->type = pglobvar->type ));            
 789             if ( !(toki->flg & FTOK_LVALUE) &&
 790                (ptype->vmo.flag & GHTY_STACK ) )
 791             {
 792                 out_adduint( ptype->stsize == 1 ? CGetI : CGetL );
 793             }
 794             toki->oftype = pglobvar->oftype;
 795             break;
 796 
 797          case FTOK_GLOBFUNCADDR://Взятие адреса функции
 798             if ( toki->flg & FTOK_LVALUE && toki + 1 < tokc  )
 799             {
 800                lex = (toki + 1)->lex;
 801                if ( lex->type == LEXEM_OPER && lex->oper.operid == OpAddr )
 802                {
 803                   out_add2uint( CCmdload, toki->idglobfunc );
 804                   break;
 805                }
 806             }
 807             msg( MExpopenbr | MSG_LEXERR, lex );
 808             break;
 809 
 810          case FTOK_METHODFUNC://Метод
 811             off = (uint)( parsc - 2 * toki->pars );
 812             //if ( (toki-1)->flg & FTOK_WITH )
 813             //D( "left %x %x %x\n", (toki->left-1)->flg, (toki->left)->flg, (toki->left+1)->flg );
 814             if ( (toki->left)->flg & FTOK_WITH )
 815             {               
 816                //D( "Method with\n" );
 817                isfield = 0;               
 818                for ( pwith = ( pfwith)( fd.bwith.data + fd.bwith.use ) - 1; 
 819                      pwith >= ( pfwith )fd.bwith.data; pwith-- )
 820                {
 821                   *(puint)off = pwith->type;
 822                   *((puint)off + 1 ) = pwith->oftype;                  
 823                   if ( pfunc = bc_method( lex, toki->pars, ( puint )off ) )
 824                       break;                  
 825                }               
 826                if ( pfunc )
 827                {                  
 828                   toki->left->type = pwith->type;
 829                   toki->left->oftype = pwith->oftype;
 830                   *( puint )(fd.bout->data + (toki->left)->offout + sizeof( uint )) = 
 831                            pwith->num;
 832                }
 833                else
 834                {                     
 835                   msg( MUnkoper | MSG_LEXNAMEERR, lex );               
 836                }
 837             }
 838             else
 839             {               
 840                *((( puint )off)++) = toki->left->type;
 841                *(puint)off = toki->left->oftype;
 842             }
 843          case FTOK_GLOBFUNC://Глобальная функция         
 844             parsc -= 2 * toki->pars;                        
 845             pfunc = bc_func( lex, toki->pars, parsc );            
 846             toki->type = pfunc->ret->type;
 847             toki->oftype = pfunc->ret->oftype;            
 848             if ( pfunc->vmo.flag & GHBC_RESULT )
 849             {
 850                //Заводим фиктивную локальную переменную
 851                out_add2uint( CVarload, var_addtmp( toki->type, toki->oftype ));
 852             }
 853             out_adduint( pfunc->vmo.id );
 854 
 855             if ( ((( pvmobj )PCMD( toki->type ))->flag & GHTY_STACK ) && 
 856                   ( toki->flg & FTOK_LVALUE ))
 857                msg( MExplvalue | MSG_LEXERR, lex );
 858             break;
 859 
 860          case FTOK_SIZEOF:                                    
 861             if ( toki->parofsize )
 862             {  
 863                if ( toki->pars != 1 )
 864                   msg( MCountpars | MSG_LEXNAMEERR, lex );                              
 865                out_add2uint( CDwload, (( povmtype )PCMD( toki->parofsize ))->size );               
 866             }
 867             else
 868             {               
 869                parsc -= 2 * toki->pars;
 870                out_adduint( bc_funcname( lex, "sizeof", toki->pars, parsc )->vmo.id);               
 871             }
 872             toki->type = TUint;
 873             toki->oftype = 0;            
 874             break;
 875 
 876          case FTOK_SUBFUNC: //Локальная функция
 877             //Подфункция
 878             //Проверка совпадения типов параметров
 879             parsc -= 2 * toki->pars;
 880             pvar = ( pfvar)(fd.bvars.data + toki->offlocvar );
 881             if ( pvar->pars == toki->pars )
 882             {
 883                psrc = (puint)(fd.bvardef.data + pvar->offbvardef );
 884                parsb = parsc;
 885                for ( i = 0; i < toki->pars; i++ )
 886                {
 887                   if ( *psrc != *parsb )
 888                      goto errpars;
 889                   parsb++;
 890                   psrc++;
 891                   if ( *( pubyte )( ((pubyte)psrc)++ ) & VAR_OFTYPE )
 892                   {
 893                      if ( *psrc != *parsb )
 894                         goto errpars;
 895                      psrc++;
 896                   }
 897                   else
 898                      if ( *parsb )
 899                         goto errpars;
 900                   parsb++;
 901                   continue;
 902 errpars:
 903                   msg( MTypepars | MSG_LEXNAMEERR, lex );
 904                }
 905             }
 906             else
 907             {
 908                msg( MCountpars | MSG_LEXNAMEERR, lex );
 909             }
 910             toki->type = pvar->type;
 911             toki->oftype = pvar->oftype;
 912             out_add2uint( CSubcall, pvar->addr );
 913             if ( ((( pvmobj )PCMD( toki->type ))->flag & GHTY_STACK ) && 
 914                   ( toki->flg & FTOK_LVALUE ))
 915                msg( MExplvalue | MSG_LEXERR, lex );
 916             break;
 917 
 918          case FTOK_COLLECTNEW: //Создание переменной с типом коллекция
 919             //Заводим переменную и загружаем её в стэк            
 920             D( "FTOK_COLLECTNEW\n" );
 921             out_add2uint( CVarload, var_addtmp( TCollection, 0 ));
 922             break;
 923 
 924          case FTOK_COLLECT: //Загрузка коллекции             
 925             if ( toki->flg & FTOK_COLLECTIONLATE && (toki+1)->flg & FTOK_LVALUE )
 926                break;            
 927 latecol:
 928             
 929             if ( flglvallate )
 930             {
 931                toktmp = toki;
 932                toki = toki->left - 1;
 933                lex = toki->lex;
 934                toki->pars++;
 935             }
 936             D( "FTOK_COLLECT\n" );
 937             if ( toki->pars )
 938             {
 939                parse = parsc;
 940                parsc -= 2 * toki->pars;             
 941                parsb = parsc;               
 942                parsc -= 2;
 943                type = 0; //Тип предыдущего элемента
 944                num = 0;//Количество dword одного типа
 945                off = fd.bout->use + sizeof( uint );
 946                out_add2uint( CDwsload, 0 );//Команда загрузки последовательности dword
 947                                         //Количество загружаемых dwords
 948                dwsize = 0;//Общий размер данных в dword, 1=последний тип
 949                numtypes = 1;//Количество описаний типов
 950                for ( ; parsb < parse; parsb += 2 )
 951                {
 952                   if ( *parsb )
 953                   {
 954                      dwsize += stsize = (( povmtype )PCMD( *parsb ))->stsize;
 955                      if ( *parsb != type || num == 0xFF )
 956                      {  //Смена типа или большой размер
 957                         if ( type )
 958                         {  //Запись типа и количества
 959                            out_adduint( ( num << 24 ) | type );
 960                            numtypes++;
 961                         }
 962                         type = *parsb;
 963                         num = 0;
 964                      }
 965                      num += stsize;
 966                   }
 967                }
 968                *( puint )( fd.bout->data + off ) = numtypes;// | ( 1 << 24 );
 969                //Запись последнего элемента
 970                out_adduints( 3, ( num << 24 ) | type, CCollectadd, dwsize + numtypes );
 971             }
 972             toki->type = TCollection;
 973             toki->oftype = 0;
 974             if ( flglvallate )
 975             {
 976                goto late;
 977             }
 978             break;
 979 
 980          case FTOK_LATE:             
 981             if ( toki->flg & FTOK_LVALUE )
 982             {               
 983                toki->flg |= FTOK_LVALLATE;
 984                break;
 985             }
 986 late:
 987             D( "FTOK_LATE\n" );
 988             if ( flglvallate )
 989             {
 990                toki = toki + 1;               
 991             }                                    
 992             
 993             out_adduints( 3, CResload,
 994                         bc_resource( lexem_getname( toki->lex ) ),
 995                         bc_find( toki->lex, "res_getstr", 1, TUint));
 996             
 997             if ( toki->lex->flag & LEXF_METHOD )
 998             {
 999                parsc -= 2;
1000                type = toki->left->type;
1001             }
1002             else
1003             {
1004                type = (toki-3)->type;
1005             }
1006 
1007             //Вызов метода является отложенным
1008             if ( flglvallate )
1009             {
1010                name = "@setval";
1011             }
1012             else
1013             {
1014                if ( toki + 1 < tokc ) //является ли лексема последней нет операций в стэке
1015                {
1016                   //   является ли следующая лексема FTOK_LATE
1017                   if (  ((toki+1)->flg & FTOK_NOFLAGS) == FTOK_COLLECTNEW &&
1018                         (toki+1)->flg & FTOK_COLLECTIONLATE )
1019                   {
1020                      name = "@getobj";
1021                   }
1022                   else
1023                   {
1024                      name = "@getval";
1025                   }
1026                }
1027                else
1028                {
1029                   name = "@call";
1030                }
1031             }
1032             
1033             //Формируем параметры методов
1034             parsb = parsc;
1035             *(parsb++) = type;
1036             *(parsb++) = 0;            
1037             *(parsb++) = TCollection;
1038             *(parsb++) = 0;
1039             *(parsb++) = TStr;
1040             *(parsb++) = 0;
1041                         
1042             pfunc = bc_funcname( lex, name, 3, parsc );                        
1043 
1044             toki->type = pfunc->ret->type;
1045             toki->oftype = pfunc->ret->oftype;
1046             
1047             if ( pfunc->vmo.flag & GHBC_RESULT )
1048             {
1049                //Заводим фиктивную локальную переменную
1050                out_add2uint( CVarload, var_addtmp( toki->type, toki->oftype ) );
1051             }
1052             out_adduint( pfunc->vmo.id );
1053             
1054             if ( flglvallate )
1055             {               
1056                toki = toktmp;
1057                flglvallate = 0;
1058             }            
1059             break;
1060 
1061          case FTOK_ADDRFUNC://Вызов функции по указателю
1062 
1063             out_adduint( ( lex->key == KEY_FUNC) ? CCmdcall : CCallstd );
1064             dwsize = 0;
1065             parsb = parsc;
1066             parsc -= 2 * toki->pars;            
1067             while ( parsb > parsc )
1068             {
1069                parsb -= 2;
1070                dwsize += (( povmtype)PCMD( *parsb ))->stsize;
1071             }
1072             if ( lex->key == KEY_STDCALL )
1073                out_adduint( 0 );
1074             else if (lex->key == KEY_CDECL )
1075                out_adduint( 1 );
1076             out_adduint( dwsize );            
1077             toki->type = TUint;
1078             toki->oftype = 0;            
1079             break;
1080 
1081          case FTOK_ARR://Массив
1082             parsc -= 2 * toki->pars;
1083             
1084             pfunc = bc_funcname( lex, "@index", toki->pars, parsc );
1085             if ( pfunc->vmo.flag & GHBC_RESULT )
1086             {
1087                //Заводим фиктивную локальную переменную
1088                out_add2uint( CVarload, var_addtmp( pfunc->ret->type, pfunc->ret->oftype ));
1089             }
1090             out_adduint( pfunc->vmo.id );
1091             
1092 
1093             if ( !toki->left->oftype )
1094             {
1095                if ( !( toki->type = (( povmtype)PCMD( toki->left->type ))->index.type ))
1096                {
1097                   toki->type = TUint;
1098                }
1099             }
1100             else
1101             {
1102                toki->type = toki->left->oftype;
1103             }
1104             toki->oftype = 0;
1105 
1106             if ( !(toki->flg & FTOK_LVALUE) &&
1107                  (( pvmobj )PCMD( toki->type ))->flag & GHTY_STACK )
1108             {
1109                out_adduint( artypes[ toki->type ]  );
1110             }
1111             break;
1112 
1113          case FTOK_FIELD://Поле            
1114             if ( (toki-1)->flg & FTOK_WITH )
1115             {               
1116                isfield = 0;
1117                for ( pwith = ( pfwith)( fd.bwith.data + fd.bwith.use ) - 1; 
1118                      pwith >= ( pfwith )fd.bwith.data; pwith-- )
1119                {                  
1120                   if ( isfield = type_fieldname( pwith->type, lexem_getname( lex ) ) )
1121                       break;                
1122                   if ( toki->flg & FTOK_LVALUE )
1123                   {                     
1124                      pfunc = bc_isproperty( lex, pwith->type );                                      
1125                   }
1126                   else
1127                   {
1128                      parsb = parsc;
1129                      *( parsb++ ) = pwith->type;
1130                      *( parsb++ ) = 0;
1131                      pfunc = bc_method( lex, 1, parsc );
1132                   }
1133                   if ( pfunc )
1134                       break;
1135                }
1136                if ( isfield || pfunc )
1137                {                  
1138                   (toki-1)->type = pwith->type;
1139                   *( puint )(fd.bout->data + (toki-1)->offout + sizeof( uint )) = 
1140                            pwith->num;
1141                }
1142                else
1143                {
1144                    msg( MUnkoper | MSG_LEXNAMEERR, lex );
1145                }
1146             }            
1147             isfield = type_field( lex, (toki-1)->type );            
1148             if ( isfield )
1149             {               
1150                field = isfield;
1151                off = field->off;
1152                while ( toki + 1 < tokc && ((toki+1)->flg & FTOK_NOFLAGS ) == FTOK_FIELD )
1153                {
1154                   lex = (++toki)->lex;
1155                   isfield = type_field( lex, field->type );
1156                   if ( isfield )
1157                   {
1158                      field = isfield;
1159                      off += field->off;
1160                   }
1161                   else
1162                   {
1163                      toki--;
1164                      break;
1165                   }
1166                }
1167                toki->type = field->type;
1168                toki->oftype = field->oftype;
1169                if ( off )
1170                {
1171                   out_adduints( 3, CDwload, off, CAddUIUI );
1172                }
1173                if ( !( toki->flg & FTOK_LVALUE ) &&
1174                      (( pvmobj )PCMD( toki->type ))->flag & GHTY_STACK )
1175                {
1176                   out_adduint( artypes[ toki->type ] );
1177                }
1178                if (!isfield) toki++;
1179             }            
1180             if (!isfield)//Поле является свойством
1181             {                  
1182                if ( toki->flg & FTOK_LVALUE )
1183                {                  
1184                   toki->flg |= FTOK_LVALPROPERTY;
1185                }
1186                else
1187                {                                    
1188                   pfunc = bc_property( lex, (toki-1)->type, 0 );                                  
1189                   toki->type = pfunc->ret->type;
1190                   toki->oftype = pfunc->ret->oftype;                  
1191                   if ( pfunc->vmo.flag & GHBC_RESULT )
1192                   {  //Заводим фиктивную локальную переменную
1193                      out_add2uint( CVarload, var_addtmp( toki->type, toki->oftype ));
1194                   }
1195                   out_adduint( pfunc->vmo.id );                                    
1196                }
1197                
1198             }
1199             break;
1200 
1201          case FTOK_NUMBER:  //Число
1202             if ( (( povmtype)PCMD( toki->type ))->stsize == 2 )
1203             {
1204                out_adduint( CQwload );
1205                out_addulong( lex->num.vlong );
1206             }
1207             else
1208                out_add2uint( CDwload, lex->num.vint );
1209             break;
1210 
1211          case FTOK_TYPE: //Получение идентификатора типа
1212             //toki->oftype = 0;
1213             type = toki->type;
1214             if ( toki < tokc - 1 &&
1215                  ( (( toki+1 )->flg & FTOK_NOFLAGS ) == FTOK_OPER ) &&
1216                   ( toki+1 )->lex->oper.operid == OpAs )
1217             {               
1218                break;
1219             }
1220             out_add2uint( type >= KERNEL_COUNT ? CCmdload : CDwload, type );
1221             toki->oftype = 0;
1222             toki->type = TUint;
1223             break;
1224 
1225          case FTOK_PTRTYPE: //Приведение указателя к типу            
1226             if ( !( toki->flg & FTOK_LVALUE ) && 
1227                   (( pvmobj )PCMD( toki->type ))->flag & GHTY_STACK )
1228                out_adduint( artypes[ toki->type ] );            
1229             break;
1230 
1231          case FTOK_OPER: //Системная лексема, оператор,            
1232             curop = (psoper)&opers[curop_id = lex->oper.operid];			
1233             if ( curop_id == OpAs )
1234             {
1235                if ( ( toki->left->flg & FTOK_NOFLAGS ) == FTOK_LOCVAR )
1236                {
1237                   pvar = ( pfvar )(fd.bvars.data + toki->left->offlocvar );
1238                   if ( pvar->flg & FVAR_UINTAS || toki->left->type == TUint )
1239                   {
1240                      if ( toki->flg & FTOK_LVALUE )
1241                         msg( MExplvalue | MSG_LEXERR, lex );
1242 
1243                      buf_expand( &fd.bvarsas, sizeof( fvaras ));
1244                      pvaras = (( pfvaras )(fd.bvarsas.data + fd.bvarsas.use ));
1245                      fd.bvarsas.use += sizeof( fvaras );
1246 
1247                      pvaras->offbvar = toki->left->offlocvar;
1248                      pvaras->type = pvar->type;
1249                      pvaras->oftype = pvar->oftype;
1250                      pvaras->flg = pvar->flg;
1251 
1252                      pvar->type = (toki-1)->type;
1253                      pvar->oftype = (toki-1)->oftype;
1254 
1255                      if ( (toki-1)->type != TUint &&
1256                           (( pvmobj )PCMD( (toki - 1)->type ))->flag & GHTY_STACK )
1257                         msg( MAsright | MSG_LEXERR, lex );
1258                      pvar->flg |= FVAR_UINTAS;
1259                      if ( ((toki-1)->flg & FTOK_NOFLAGS) == FTOK_TYPE )
1260                      {
1261                         *(puint)(fd.bout->data + toki->left->offout ) = CVarload;
1262                      }
1263                      else
1264                      {
1265                         if ( toki->left->type != TUint )
1266                         {
1267                            *(puint)(fd.bout->data + toki->left->offout ) = CVarptrload;
1268                         }
1269                         out_adduint( CSetI );
1270                      }
1271                      toki->type = (toki-1)->type;
1272                      toki->oftype = (toki-1)->oftype;
1273                      break;
1274                   }
1275                }
1276                msg( MAsleft | MSG_LEXERR, lex );
1277             }
1278             else if ( curop_id == OpStrtext || curop_id == OpStrout ||
1279                        ( curop_id == OpStradd && !toki->left->type ) )//?
1280             {
1281                if ( type_isinherit( (toki-1)->type, TStr ) )
1282                   out_adduint( CSetText );
1283                else if ( !( ( (toki-1)->flg & FTOK_TEXT ) ||
1284                     (((toki-1)->flg & FTOK_NOFLAGS) == FTOK_OPER  &&
1285                     ((toki-2)->flg & FTOK_NOFLAGS) == FTOK_ADDRFUNC )))
1286                   msg( MVarstr | MSG_LEXERR, lex );
1287                toki->type = 0;
1288                toki->oftype = 0;
1289                break;
1290             }
1291             else  if ( curop_id == OpAddset &&
1292                           toki->left->type == TCollection )
1293             {
1294                out_adduints( 4, CCmdload, 
1295                     //(toki-1)->type >= KERNEL_COUNT ? CCmdload : CDwload,
1296                            /*( 1 << 24 ) |*/ (toki-1)->type,//Тип правого операнда
1297                            CCollectadd,
1298                            (( povmtype )PCMD( (toki-1)->type ))->stsize + 1 );
1299                toki->type = TCollection;
1300                toki->oftype = 0;
1301                break;
1302             }
1303             else if ( curop_id == OpStradd )
1304             {
1305                if ( (toki-1)->flg & FTOK_TEXT ||
1306                     (((toki-1)->flg & FTOK_NOFLAGS) == FTOK_OPER  &&
1307                     ((toki-2)->flg & FTOK_NOFLAGS) == FTOK_ADDRFUNC ))
1308                {
1309                   toki->type = TStr;
1310                   toki->oftype = 0;
1311                   break;
1312                }
1313                else
1314                {                    
1315                   lex->oper.operid = OpAddset;                  
1316                }
1317             }
1318             if ( (toki->left && ( toki->left->flg & FTOK_LVALPROPERTY )) ||
1319                  ((toki-1)->flg & FTOK_LVALPROPERTY ))
1320             {				
1321                if ( curop_id == OpSet )
1322                {                  
1323                   pfunc = bc_property( toki->left->lex, (toki->left-1)->type, 
1324                                        (toki-1)->type );                
1325                   out_adduint( pfunc->vmo.id );
1326                   toki->type = pfunc->ret->type;
1327                   toki->oftype = pfunc->ret->oftype;
1328                }
1329                else
1330                {
1331                   if ( curop_id == OpAddr )
1332                   {
1333                      pfunc = bc_property( (toki-1)->lex, (toki-2)->type, 0 );                                  
1334                      toki->type = pfunc->ret->type;
1335                      toki->oftype = pfunc->ret->oftype;                  
1336                      if ( pfunc->vmo.flag & GHBC_RESULT )
1337                      {  //Заводим фиктивную локальную переменную
1338                         out_add2uint( CVarload, var_addtmp( toki->type, toki->oftype ));
1339                      }
1340                      out_adduint( pfunc->vmo.id );
1341 
1342                      if ( ((( pvmobj )PCMD( toki->type ))->flag & GHTY_STACK ) )
1343                         msg( MExplvalue | MSG_LEXERR, lex );
1344                      toki->type = TUint; 
1345                      toki->oftype = 0;                                          
1346                   }
1347                   else
1348                   {                     
1349                      msg( MPropoper | MSG_LEXERR , toki->lex );    
1350                   }
1351                }
1352             }
1353             else if (toki->left && ( toki->left->flg & FTOK_LVALLATE ))
1354             {               
1355                *(parsc++) = (toki - 1)->type;
1356                *(parsc++) = (toki - 1)->oftype;
1357                flglvallate = 1;               
1358                goto latecol;
1359             }
1360             else
1361             {
1362                if ( !(curop->flgs & OPF_NOP) )
1363                {
1364                   if ( curop->flgs & OPF_ADDNOT )
1365                   {
1366                      lex->oper.operid--;
1367                   }
1368 
1369                   pfunc = bc_oper( lex,
1370                      toki->left ? toki->left->type : 0, (toki-1)->type,
1371                      toki->left ? toki->left->oftype : 0, (toki-1)->oftype);
1372  
1373                   toki->type = pfunc->ret->type;
1374                   toki->oftype = pfunc->ret->oftype;
1375 
1376                   if ( pfunc->vmo.flag & GHBC_RESULT )
1377                   {  //Заводим фиктивную локальную переменную
1378                      out_add2uint( CVarload, var_addtmp( toki->type, toki->oftype ));
1379                   }
1380                   out_adduint( pfunc->vmo.id );
1381                   if ( curop->flgs & OPF_ADDNOT )
1382                      out_adduint( CLognot );
1383                }
1384                else
1385                {	
1386                   toki->type = TUint;
1387                   toki->oftype = 0;
1388                   //toki->type   = (toki - 1)->type;
1389                   //toki->oftype = (toki - 1)->oftype;
1390                }
1391             }
1392             if ( curop_id == OpLogand )
1393             {
1394                if ( (( povmtype )PCMD( toki->type ))->stsize == 2 )
1395                   out_adduint( CLoglongtrue );
1396                if ( !( toki->flg & FTOK_OPAND ) )
1397                {
1398                   j_correct( toki->left->ol, j_label( LABT_LABELVIRT, -1));
1399                }
1400             }
1401             else
1402             if ( curop_id == OpLogor )
1403             {
1404                if ( (( povmtype )PCMD( toki->type ))->stsize == 2 )
1405                   out_adduint( CLoglongtrue );
1406                if ( !( toki->flg & FTOK_OPOR ) )
1407                {
1408                   j_correct( toki->left->ol, j_label( LABT_LABELVIRT, -1));
1409                }
1410             }
1411             if ( ((( pvmobj )PCMD( toki->type ))->flag & GHTY_STACK ) && 
1412                      ( toki->flg & FTOK_LVALUE ))
1413                msg( MExplvalue | MSG_LEXERR, lex );
1414             break;
1415 
1416          case FTOK_STRBIN:
1417             //print( "FTOK_STRBIN %x %x\n", toki->type, str_len( toki->strbin ) );
1418             //Получаем идентификатор типа buf                          
1419             len = ( toki->type == TStr ? str_len( toki->strbin ) : buf_len( toki->strbin ));                                    
1420             out_adduints( 4,
1421                         //Заводим переменную и загружаем её в стэк
1422                         CVarload, var_addtmp( toki->type, 0 ),
1423                         //Загрузка размера
1424                         CDatasize, len );            
1425             //Загрузка данных
1426             out_addptr( toki->strbin->data, len );            
1427             //Получение кода метода
1428             out_adduint( bc_find( lex, "@load", 3, toki->type, TUint, TUint ) );            
1429             break;
1430 
1431          case FTOK_QUEST:            
1432             parsc -= 8;
1433             if ( toki->flg & FTOK_LVALUE )
1434                msg( MExplvalue | MSG_LEXERR, lex );
1435             if ( toki->pars != 3 )
1436             {
1437                msg( MQuest | MSG_LEXERR, lex );//Ошибка операции ?
1438             }
1439             parsb = parsc + 3;
1440             parse = parsc + 6;
1441             if ( type_compfull( toki->type = *(parsb) ) != 
1442                      type_compfull( *( parse )) &&
1443                  type_compfull( toki->oftype =*(parsb + 1) ) != 
1444                      type_compfull( *( parse + 1)) )
1445             {
1446                msg( MParquest | MSG_LEXERR, lex );//Ошибка несовпадение типов в операции ?
1447             }
1448             break;
1449 
1450          case FTOK_BYTECODE:
1451             out_adduint( toki->cmdbytecode );
1452             break;
1453 
1454          case FTOK_ALIAS:                        
1455             out_add2uint( CCmdload, toki->idalias );
1456             toki->oftype = 0;
1457             toki->type = TUint;
1458             break;
1459 
1460       }      
1461       if ( toki->flg & FTOK_ADDFUNCPAR)
1462       {  
1463          *(parsc++) = toki->type;
1464          *(parsc++) = toki->oftype;
1465       }      
1466       if ( toki->flg & FTOK_FUNCPAR )
1467       {   
1468          if ( !toki->type )//Ошибка, пустое выражение, должен быть тип у параметра/элемента
1469             msg( MExpnonull | MSG_LEXERR, lex );       
1470          *(parsc++) = toki->type;
1471          *(parsc++) = toki->oftype;
1472          
1473          if ( toki->flg & FTOK_QUESTFIRST )
1474          {  //Первый операнд операции ?
1475             if ( !toki->type )
1476                msg( MExplogic | MSG_LEXERR, toki->lex ); 
1477             // Временно сохраняем метки переходов в стэке переменных
1478             if ( (( povmtype )PCMD( toki->type ))->stsize == 2 )
1479                out_adduint( CLoglongtrue );
1480             //Добавляем переход на иначе
1481             *(parsc++) = j_jump( CIfznocls, LABT_GTVIRT, -1 );
1482             //out_adduint( CPop );
1483          }
1484          else if ( toki->flg & FTOK_QUESTSECOND )
1485          {  //Второй операнд операции ?
1486             //Добавляем переход на конец
1487             *(parsc++) = j_jump( CGotonocls, LABT_GTVIRT, -1 );
1488             ((pflabel)( fd.blabels.data + *( parsc - 4 ) ))->link = j_label( LABT_LABELVIRT, -1);
1489 
1490             //Нужно очистить последний элемент в стэке виртуальной машины
1491             out_adduint( CPop );
1492          }
1493          else  if ( toki->flg & FTOK_QUESTTHIRD )
1494          {  //Третий операнд операции ?
1495             //Вытаскиваем и очищаем последний элемент стэка параметров со смещением перехода
1496             ((pflabel)( fd.blabels.data + *( parsc - 3 ) ))->link = j_label( LABT_LABELVIRT, -1);
1497          }
1498       } 
1499       if ( toki->flg & FTOK_OPAND )
1500       {
1501          if ( (( povmtype )PCMD( toki->type ))->stsize == 2 )
1502             out_adduint( CLoglongtrue );
1503          toki->ol = j_jump( CIfznocls, LABT_GTVIRT, ( lex->type == LEXEM_OPER && lex->oper.operid == OpLogand ) ? toki->left->ol : -1 );
1504       }
1505       else
1506       if ( toki->flg & FTOK_OPOR )
1507       {
1508          if ( (( povmtype )PCMD( toki->type ))->stsize == 2 )
1509             out_adduint( CLoglongtrue );
1510          toki->ol = j_jump( CIfnznocls, LABT_GTVIRT, ( lex->type == LEXEM_OPER && lex->oper.operid == OpLogor ) ? toki->left->ol : -1 );
1511       }      
1512    }
1513    type = 0;
1514    if ( retoftype )
1515       *retoftype = 0;
1516    if ( tokb != tokc )//Тип возвращаемого значения
1517    {
1518       type = (tokc-1)->type;
1519       if ( retoftype )
1520       {
1521          *retoftype = (tokc-1)->oftype;
1522       }
1523    }
1524 
1525    if ( flg & EXPR_BOOL )//Логическое выражение
1526    {
1527       if ( type )
1528       {
1529          if ( (( povmtype )PCMD( type ))->stsize == 2 )
1530             out_adduint( CLoglongtrue );
1531       }
1532       else
1533       {
1534          msg( MExplogic | MSG_LEXERR, tokb != tokc ? tokb->lex : curlex ); 
1535       }
1536    }
1537    else
1538    if ( flg & EXPR_NONULL && !rettype )//Должно возвращать тип
1539       msg( MExpnonull | MSG_LEXERR, lex );
1540    
1541    if ( rettype )
1542       *rettype = type;
1543 
1544 D("Expr stop\n" );
1545    return curlex;
1546 }