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 }
831 else
832 {
833 msg( MUnkoper | MSG_LEXNAMEERR, lex );
834 }
835 }
836 else
837 {
838 *((( puint )off)++) = toki->left->type;
839 *(puint)off = toki->left->oftype;
840 }
841 case FTOK_GLOBFUNC://Глобальная функция
842 parsc -= 2 * toki->pars;
843 pfunc = bc_func( lex, toki->pars, parsc );
844 toki->type = pfunc->ret->type;
845 toki->oftype = pfunc->ret->oftype;
846 if ( pfunc->vmo.flag & GHBC_RESULT )
847 {
848 //Заводим фиктивную локальную переменную
849 out_add2uint( CVarload, var_addtmp( toki->type, toki->oftype ));
850 }
851 out_adduint( pfunc->vmo.id );
852
853 if ( ((( pvmobj )PCMD( toki->type ))->flag & GHTY_STACK ) &&
854 ( toki->flg & FTOK_LVALUE ))
855 msg( MExplvalue | MSG_LEXERR, lex );
856 break;
857
858 case FTOK_SIZEOF:
859 if ( toki->parofsize )
860 {
861 if ( toki->pars != 1 )
862 msg( MCountpars | MSG_LEXNAMEERR, lex );
863 out_add2uint( CDwload, (( povmtype )PCMD( toki->parofsize ))->size );
864 }
865 else
866 {
867 parsc -= 2 * toki->pars;
868 out_adduint( bc_funcname( lex, "sizeof", toki->pars, parsc )->vmo.id);
869 }
870 toki->type = TUint;
871 toki->oftype = 0;
872 break;
873
874 case FTOK_SUBFUNC: //Локальная функция
875 //Подфункция
876 //Проверка совпадения типов параметров
877 parsc -= 2 * toki->pars;
878 pvar = ( pfvar)(fd.bvars.data + toki->offlocvar );
879 if ( pvar->pars == toki->pars )
880 {
881 psrc = (puint)(fd.bvardef.data + pvar->offbvardef );
882 parsb = parsc;
883 for ( i = 0; i < toki->pars; i++ )
884 {
885 if ( *psrc != *parsb )
886 goto errpars;
887 parsb++;
888 psrc++;
889 if ( *( pubyte )( ((pubyte)psrc)++ ) & VAR_OFTYPE )
890 {
891 if ( *psrc != *parsb )
892 goto errpars;
893 psrc++;
894 }
895 else
896 if ( *parsb )
897 goto errpars;
898 parsb++;
899 continue;
900 errpars:
901 msg( MTypepars | MSG_LEXNAMEERR, lex );
902 }
903 }
904 else
905 {
906 msg( MCountpars | MSG_LEXNAMEERR, lex );
907 }
908 toki->type = pvar->type;
909 toki->oftype = pvar->oftype;
910 out_add2uint( CSubcall, pvar->addr );
911 if ( ((( pvmobj )PCMD( toki->type ))->flag & GHTY_STACK ) &&
912 ( toki->flg & FTOK_LVALUE ))
913 msg( MExplvalue | MSG_LEXERR, lex );
914 break;
915
916 case FTOK_COLLECTNEW: //Создание переменной с типом коллекция
917 //Заводим переменную и загружаем её в стэк
918 D( "FTOK_COLLECTNEW\n" );
919 out_add2uint( CVarload, var_addtmp( TCollection, 0 ));
920 break;
921
922 case FTOK_COLLECT: //Загрузка коллекции
923 if ( toki->flg & FTOK_COLLECTIONLATE && (toki+1)->flg & FTOK_LVALUE )
924 break;
925 latecol:
926
927 if ( flglvallate )
928 {
929 toktmp = toki;
930 toki = toki->left - 1;
931 lex = toki->lex;
932 toki->pars++;
933 }
934 D( "FTOK_COLLECT\n" );
935 if ( toki->pars )
936 {
937 parse = parsc;
938 parsc -= 2 * toki->pars;
939 parsb = parsc;
940 parsc -= 2;
941 type = 0; //Тип предыдущего элемента
942 num = 0;//Количество dword одного типа
943 off = fd.bout->use + sizeof( uint );
944 out_add2uint( CDwsload, 0 );//Команда загрузки последовательности dword
945 //Количество загружаемых dwords
946 dwsize = 0;//Общий размер данных в dword, 1=последний тип
947 numtypes = 1;//Количество описаний типов
948 for ( ; parsb < parse; parsb += 2 )
949 {
950 if ( *parsb )
951 {
952 dwsize += stsize = (( povmtype )PCMD( *parsb ))->stsize;
953 if ( *parsb != type || num == 0xFF )
954 { //Смена типа или большой размер
955 if ( type )
956 { //Запись типа и количества
957 out_adduint( ( num << 24 ) | type );
958 numtypes++;
959 }
960 type = *parsb;
961 num = 0;
962 }
963 num += stsize;
964 }
965 }
966 *( puint )( fd.bout->data + off ) = numtypes;
967 //Запись последнего элемента
968 out_adduints( 3, ( num << 24 ) | type, CCollectadd, dwsize + numtypes );
969 }
970 toki->type = TCollection;
971 toki->oftype = 0;
972 if ( flglvallate )
973 {
974 goto late;
975 }
976 break;
977
978 case FTOK_LATE:
979 if ( toki->flg & FTOK_LVALUE )
980 {
981 toki->flg |= FTOK_LVALLATE;
982 break;
983 }
984 late:
985 D( "FTOK_LATE\n" );
986 if ( flglvallate )
987 {
988 toki = toki + 1;
989 }
990
991 out_adduints( 3, CResload,
992 bc_resource( lexem_getname( toki->lex ) ),
993 bc_find( toki->lex, "res_getstr", 1, TUint));
994
995 if ( toki->lex->flag & LEXF_METHOD )
996 {
997 parsc -= 2;
998 type = toki->left->type;
999 }
1000 else
1001 {
1002 type = (toki-3)->type;
1003 }
1004
1005 //Вызов метода является отложенным
1006 if ( flglvallate )
1007 {
1008 name = "@setval";
1009 }
1010 else
1011 {
1012 if ( toki + 1 < tokc ) //является ли лексема последней нет операций в стэке
1013 {
1014 // является ли следующая лексема FTOK_LATE
1015 if ( ((toki+1)->flg & FTOK_NOFLAGS) == FTOK_COLLECTNEW &&
1016 (toki+1)->flg & FTOK_COLLECTIONLATE )
1017 {
1018 name = "@getobj";
1019 }
1020 else
1021 {
1022 name = "@getval";
1023 }
1024 }
1025 else
1026 {
1027 name = "@call";
1028 }
1029 }
1030
1031 //Формируем параметры методов
1032 parsb = parsc;
1033 *(parsb++) = type;
1034 *(parsb++) = 0;
1035 *(parsb++) = TCollection;
1036 *(parsb++) = 0;
1037 *(parsb++) = TStr;
1038 *(parsb++) = 0;
1039
1040 pfunc = bc_funcname( lex, name, 3, parsc );
1041
1042 toki->type = pfunc->ret->type;
1043 toki->oftype = pfunc->ret->oftype;
1044
1045 if ( pfunc->vmo.flag & GHBC_RESULT )
1046 {
1047 //Заводим фиктивную локальную переменную
1048 out_add2uint( CVarload, var_addtmp( toki->type, toki->oftype ) );
1049 }
1050 out_adduint( pfunc->vmo.id );
1051
1052 if ( flglvallate )
1053 {
1054 toki = toktmp;
1055 flglvallate = 0;
1056 }
1057 break;
1058
1059 case FTOK_ADDRFUNC://Вызов функции по указателю
1060
1061 out_adduint( ( lex->key == KEY_FUNC) ? CCmdcall : CCallstd );
1062 dwsize = 0;
1063 parsb = parsc;
1064 parsc -= 2 * toki->pars;
1065 while ( parsb > parsc )
1066 {
1067 parsb -= 2;
1068 dwsize += (( povmtype)PCMD( *parsb ))->stsize;
1069 }
1070 if ( lex->key == KEY_STDCALL )
1071 out_adduint( 0 );
1072 else if (lex->key == KEY_CDECL )
1073 out_adduint( 1 );
1074 out_adduint( dwsize );
1075 toki->type = TUint;
1076 toki->oftype = 0;
1077 break;
1078
1079 case FTOK_ARR://Массив
1080 parsc -= 2 * toki->pars;
1081
1082 pfunc = bc_funcname( lex, "@index", toki->pars, parsc );
1083 if ( pfunc->vmo.flag & GHBC_RESULT )
1084 {
1085 //Заводим фиктивную локальную переменную
1086 out_add2uint( CVarload, var_addtmp( pfunc->ret->type, pfunc->ret->oftype ));
1087 }
1088 out_adduint( pfunc->vmo.id );
1089
1090
1091 if ( !toki->left->oftype )
1092 {
1093 if ( !( toki->type = (( povmtype)PCMD( toki->left->type ))->index.type ))
1094 {
1095 toki->type = TUint;
1096 }
1097 }
1098 else
1099 {
1100 toki->type = toki->left->oftype;
1101 }
1102 toki->oftype = 0;
1103
1104 if ( !(toki->flg & FTOK_LVALUE) &&
1105 (( pvmobj )PCMD( toki->type ))->flag & GHTY_STACK )
1106 {
1107 out_adduint( artypes[ toki->type ] );
1108 }
1109 break;
1110
1111 case FTOK_FIELD://Поле
1112 if ( (toki-1)->flg & FTOK_WITH )
1113 {
1114 isfield = 0;
1115 for ( pwith = ( pfwith)( fd.bwith.data + fd.bwith.use ) - 1;
1116 pwith >= ( pfwith )fd.bwith.data; pwith-- )
1117 {
1118 if ( isfield = type_fieldname( pwith->type, lexem_getname( lex ) ) )
1119 break;
1120 if ( toki->flg & FTOK_LVALUE )
1121 {
1122 pfunc = bc_isproperty( lex, pwith->type );
1123 }
1124 else
1125 {
1126 parsb = parsc;
1127 *( parsb++ ) = pwith->type;
1128 *( parsb++ ) = 0;
1129 pfunc = bc_method( lex, 1, parsc );
1130 }
1131 if ( pfunc )
1132 break;
1133 }
1134 if ( isfield || pfunc )
1135 {
1136 (toki-1)->type = pwith->type;
1137 *( puint )(fd.bout->data + (toki-1)->offout + sizeof( uint )) =
1138 pwith->num;
1139 }
1140 else
1141 {
1142 msg( MUnkoper | MSG_LEXNAMEERR, lex );
1143 }
1144 }
1145 isfield = type_field( lex, (toki-1)->type );
1146 if ( isfield )
1147 {
1148 field = isfield;
1149 off = field->off;
1150 while ( toki + 1 < tokc && ((toki+1)->flg & FTOK_NOFLAGS ) == FTOK_FIELD )
1151 {
1152 lex = (++toki)->lex;
1153 isfield = type_field( lex, field->type );
1154 if ( isfield )
1155 {
1156 field = isfield;
1157 off += field->off;
1158 }
1159 else
1160 {
1161 toki--;
1162 break;
1163 }
1164 }
1165 toki->type = field->type;
1166 toki->oftype = field->oftype;
1167 if ( off )
1168 {
1169 out_adduints( 3, CDwload, off, CAddUIUI );
1170 }
1171 if ( !( toki->flg & FTOK_LVALUE ) &&
1172 (( pvmobj )PCMD( toki->type ))->flag & GHTY_STACK )
1173 {
1174 out_adduint( artypes[ toki->type ] );
1175 }
1176 if (!isfield) toki++;
1177 }
1178 if (!isfield)//Поле является свойством
1179 {
1180 if ( toki->flg & FTOK_LVALUE )
1181 {
1182 toki->flg |= FTOK_LVALPROPERTY;
1183 }
1184 else
1185 {
1186 pfunc = bc_property( lex, (toki-1)->type, 0 );
1187 toki->type = pfunc->ret->type;
1188 toki->oftype = pfunc->ret->oftype;
1189 if ( pfunc->vmo.flag & GHBC_RESULT )
1190 { //Заводим фиктивную локальную переменную
1191 out_add2uint( CVarload, var_addtmp( toki->type, toki->oftype ));
1192 }
1193 out_adduint( pfunc->vmo.id );
1194 }
1195
1196 }
1197 break;
1198
1199 case FTOK_NUMBER: //Число
1200 if ( (( povmtype)PCMD( toki->type ))->stsize == 2 )
1201 {
1202 out_adduint( CQwload );
1203 out_addulong( lex->num.vlong );
1204 }
1205 else
1206 out_add2uint( CDwload, lex->num.vint );
1207 break;
1208
1209 case FTOK_TYPE: //Получение идентификатора типа
1210 //toki->oftype = 0;
1211 type = toki->type;
1212 if ( toki < tokc - 1 &&
1213 ( (( toki+1 )->flg & FTOK_NOFLAGS ) == FTOK_OPER ) &&
1214 ( toki+1 )->lex->oper.operid == OpAs )
1215 {
1216 break;
1217 }
1218 out_add2uint( type >= KERNEL_COUNT ? CCmdload : CDwload, type );
1219 toki->oftype = 0;
1220 toki->type = TUint;
1221 break;
1222
1223 case FTOK_PTRTYPE: //Приведение указателя к типу
1224 if ( !( toki->flg & FTOK_LVALUE ) &&
1225 (( pvmobj )PCMD( toki->type ))->flag & GHTY_STACK )
1226 out_adduint( artypes[ toki->type ] );
1227 break;
1228
1229 case FTOK_OPER: //Системная лексема, оператор,
1230 curop = (psoper)&opers[curop_id = lex->oper.operid];
1231 if ( curop_id == OpAs )
1232 {
1233 if ( ( toki->left->flg & FTOK_NOFLAGS ) == FTOK_LOCVAR )
1234 {
1235 pvar = ( pfvar )(fd.bvars.data + toki->left->offlocvar );
1236 if ( pvar->flg & FVAR_UINTAS || toki->left->type == TUint )
1237 {
1238 if ( toki->flg & FTOK_LVALUE )
1239 msg( MExplvalue | MSG_LEXERR, lex );
1240
1241 buf_expand( &fd.bvarsas, sizeof( fvaras ));
1242 pvaras = (( pfvaras )(fd.bvarsas.data + fd.bvarsas.use ));
1243 fd.bvarsas.use += sizeof( fvaras );
1244
1245 pvaras->offbvar = toki->left->offlocvar;
1246 pvaras->type = pvar->type;
1247 pvaras->oftype = pvar->oftype;
1248
1249 pvar->type = (toki-1)->type;
1250 pvar->oftype = (toki-1)->oftype;
1251
1252 if ( (toki-1)->type != TUint &&
1253 (( pvmobj )PCMD( (toki - 1)->type ))->flag & GHTY_STACK )
1254 msg( MAsright | MSG_LEXERR, lex );
1255 pvar->flg |= FVAR_UINTAS;
1256 if ( ((toki-1)->flg & FTOK_NOFLAGS) == FTOK_TYPE )
1257 {
1258 *(puint)(fd.bout->data + toki->left->offout ) = CVarload;
1259 }
1260 else
1261 {
1262 if ( toki->left->type != TUint )
1263 {
1264 *(puint)(fd.bout->data + toki->left->offout ) = CVarptrload;
1265 }
1266 out_adduint( CSetI );
1267 }
1268 toki->type = (toki-1)->type;
1269 toki->oftype = (toki-1)->oftype;
1270 break;
1271 }
1272 }
1273 msg( MAsleft | MSG_LEXERR, lex );
1274 }
1275 else if ( curop_id == OpStrtext || curop_id == OpStrout ||
1276 ( curop_id == OpStradd && !toki->left->type ) )//?
1277 {
1278 if ( type_isinherit( (toki-1)->type, TStr ) )
1279 out_adduint( CSetText );
1280 else if ( !( ( (toki-1)->flg & FTOK_TEXT ) ||
1281 (((toki-1)->flg & FTOK_NOFLAGS) == FTOK_OPER &&
1282 ((toki-2)->flg & FTOK_NOFLAGS) == FTOK_ADDRFUNC )))
1283 msg( MVarstr | MSG_LEXERR, lex );
1284 toki->type = 0;
1285 toki->oftype = 0;
1286 break;
1287 }
1288 else if ( curop_id == OpAddset &&
1289 toki->left->type == TCollection )
1290 {
1291 out_adduints( 4, CDwload,
1292 ( 1 << 24 ) | (toki-1)->type,//Тип правого операнда
1293 CCollectadd,
1294 (( povmtype )PCMD( (toki-1)->type ))->stsize + 1 );
1295 toki->type = TCollection;
1296 toki->oftype = 0;
1297 break;
1298 }
1299 else if ( curop_id == OpStradd )
1300 {
1301 if ( (toki-1)->flg & FTOK_TEXT ||
1302 (((toki-1)->flg & FTOK_NOFLAGS) == FTOK_OPER &&
1303 ((toki-2)->flg & FTOK_NOFLAGS) == FTOK_ADDRFUNC ))
1304 {
1305 toki->type = TStr;
1306 toki->oftype = 0;
1307 break;
1308 }
1309 else
1310 {
1311 lex->oper.operid = OpAddset;
1312 }
1313 }
1314 if ( (toki->left && ( toki->left->flg & FTOK_LVALPROPERTY )) ||
1315 ((toki-1)->flg & FTOK_LVALPROPERTY ))
1316 {
1317 if ( curop_id == OpSet )
1318 {
1319 pfunc = bc_property( toki->left->lex, (toki->left-1)->type,
1320 (toki-1)->type );
1321 out_adduint( pfunc->vmo.id );
1322 toki->type = pfunc->ret->type;
1323 toki->oftype = pfunc->ret->oftype;
1324 }
1325 else
1326 {
1327 if ( curop_id == OpAddr )
1328 {
1329 pfunc = bc_property( (toki-1)->lex, (toki-2)->type, 0 );
1330 toki->type = pfunc->ret->type;
1331 toki->oftype = pfunc->ret->oftype;
1332 if ( pfunc->vmo.flag & GHBC_RESULT )
1333 { //Заводим фиктивную локальную переменную
1334 out_add2uint( CVarload, var_addtmp( toki->type, toki->oftype ));
1335 }
1336 out_adduint( pfunc->vmo.id );
1337
1338 if ( ((( pvmobj )PCMD( toki->type ))->flag & GHTY_STACK ) )
1339 msg( MExplvalue | MSG_LEXERR, lex );
1340 toki->type = TUint;
1341 toki->oftype = 0