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 }