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: body 22.01.07 0.0.A.
11 *
12 * Author: Alexander Krivonogov ( algen )
13 *
14 * Summary: Block of function processing
15 *
16 ******************************************************************************/
17
18
19 #include "func.h"
20 #include "ifdef.h"
21 #include "../vm/vmtype.h"
22
23 /*-----------------------------------------------------------------------------
24 *
25 * ID: f_body 22.01.07 0.0.A.
26 *
27 * Summary: Block of function processing
28 *
29 -----------------------------------------------------------------------------*/
30 plexem STDCALL f_body( plexem curlex )
31 {
32 plexem nextlex; //Лексема следующая после ключевого слова
33 plexem prevlex;
34
35 uint oldbvaruse; //Пред. размер буфера для локальных переменных
36 uint oldbblinituse;//Пред. размер стэка ининициализации буферов
37 uint oldboutuse; //Пред. размер байткода для вставки инициализации буферов
38 uint oldblabelsuse;//Пред. размер таблицы меток
39 uint oldbvarsasuse;//Перд. размер таблицы переменных As
40 uint lastcurcount; //Пред. значение fd.lastcurcount
41 uint oldvarcount; //Пред. количество переменных
42
43 pflabel curlabel; // Текущий элемент в таблице меток
44
45 pfvar pvar; //Указатель на структуру переменной
46 pfvaras pvaras; //Указатель на структуру as переменной
47 uint numins; //На сколько сдвигать байткод при вставке команд иниц. блоков
48 uint rettype; //Тип значения return
49 uint retoftype; //Тип элеменента значения return
50 uint off; //Временная переменная для смещений
51
52 D( "Body start\n" );
53
54 //Инициализация и сохранение данных по верхнему блоку
55 oldbblinituse = fd.bblinit.use;
56 oldboutuse = fd.bout->use;
57 oldbvarsasuse = fd.bvarsas.use;
58 if ( fd.curcount )
59 {
60 lastcurcount = fd.lastcurcount;
61 fd.lastcurcount = fd.curcount;
62 }
63 else
64 {
65 lastcurcount = -1;
66 }
67 oldvarcount = fd.varcount;
68 fd.curcount = 0;
69 fd.bllevel++;
70 oldbvaruse = fd.oldoffbvar;
71 fd.oldoffbvar = fd.bvars.use;
72 oldblabelsuse = fd.blabels.use;
73
74 //Открывающая фигурная скобка
75 curlex = lexem_next( curlex, LEXNEXT_SKIPLINE );
76 curlex = lexem_next( curlex, LEXNEXT_IGNLINE | LEXNEXT_LCURLY );
77
78 //Главный цикл чтения лексем
79 while ( 1 )
80 {
81 if ( curlex->type == LEXEM_KEYWORD )
82 {
83 nextlex = lexem_next( curlex, 0 );
84 switch ( curlex->key )
85 {
86 case KEY_SUBFUNC:
87 curlex = f_subfunc( nextlex );
88 goto next;
89 case KEY_IF:
90 curlex = c_if( nextlex );
91 continue;
92 case KEY_WHILE:
93 curlex = c_while( nextlex );
94 goto next;
95 case KEY_BREAK:
96 out_debugtrace( curlex );
97 curlex = nextlex;
98 if ( fd.blcycle )
99 fd.offlcbreak = j_jump( CGoto, LABT_GTVIRT, fd.offlcbreak );
100 else
101 msg( MLoopcmd | MSG_LEXERR, curlex );
102 break;
103 case KEY_CONTINUE:
104 out_debugtrace( curlex );
105 curlex = nextlex;
106 if ( fd.blcycle )
107 fd.offlccontinue = j_jump( CGoto, LABT_GTVIRT, fd.offlccontinue );
108 else
109 msg( MLoopcmd | MSG_LEXERR, curlex );
110 break;
111 case KEY_FOR:
112 curlex = c_for( nextlex );
113 goto next;
114 case KEY_FORNUM:
115 curlex = c_fornum( nextlex );
116 goto next;
117 case KEY_FOREACH:
118 curlex = c_foreach( nextlex );
119 goto next;
120 case KEY_DO:
121 curlex = c_dowhile( nextlex );
122 goto next;
123 case KEY_LABEL:
124 curlex = c_label( nextlex );
125 continue;
126 case KEY_GOTO:
127 curlex = c_goto( nextlex );
128 break;
129 case KEY_RETURN:
130 prevlex = curlex;
131 curlex = f_expr( nextlex, 0, &rettype, &retoftype );
132 if ( !type_compat( rettype, fd.functype, 0 ) ||
133 ( fd.funcoftype && !type_compat( retoftype, fd.funcoftype, 1 )) )
134 /*type_compfull( rettype ) !=
135 type_compfull( fd.functype ) ||
136 type_compfull( retoftype ) !=
137 type_compfull( fd.funcoftype )*/
138 msg( MRettype | MSG_LEXERR, curlex );
139
140 if ( !rettype )
141 out_debugtrace( prevlex );
142
143 if ( fd.bout == &fd.bsubout )
144 out_adduint( CSubreturn );
145 else
146 {
147 if ( fd.flgfunc & GHBC_RESULT )
148 {
149 out_add2uint( CVarload, fd.idresult );
150 }
151 out_adduint( CReturn );
152 }
153 j_label( LABT_RETURN, -1 );
154 continue;
155
156 case KEY_SWITCH:
157 curlex = c_switch( nextlex );
158 goto next;
159
160 case KEY_WITH:
161 curlex = c_with( nextlex );
162 goto next;
163
164 default:
165 curlex = f_expr( curlex, 0, 0, 0 );//Обработка выражения
166 continue;
167 }
168 if ( curlex->type == LEXEM_OPER && !(curlex->oper.operid == OpLine ||
169 curlex->oper.operid == OpRcrbrack) )
170 msg( MExpline | MSG_LEXERR, curlex );
171 continue;
172 }
173 else
174 {
175 if ( curlex->type == LEXEM_OPER )
176 {
177 if ( curlex->oper.operid == OpRcrbrack )//}
178 {
179 break;//Выйти из тела
180 }
181 if ( curlex->oper.operid == OpLcrbrack )//{
182 {
183 curlex = f_body( curlex );//Ещё одно тело
184 goto next;
185 }
186 else if ( curlex->oper.operid == OpLine )
187 goto next;
188 }
189 else
190 if ( curlex->type == LEXEM_NAME )
191 { //Возможно определение локальных переменных
192 curlex = var_def( curlex, DESCID_VAR );
193 }
194 curlex = f_expr( curlex, 0, 0, 0 );//Обработка выражения
195 continue;
196 }
197 next:
198 curlex = lexem_next( curlex, LEXNEXT_IGNLINE );
199 }
200
201 //Восстановление типов as
202 off = (uint)fd.bvarsas.data + oldbvarsasuse;
203 for ( pvaras = ((pfvaras)(fd.bvarsas.data + fd.bvarsas.use)) - 1;
204 (uint)pvaras >= off;
205 pvaras-- )
206 {
207 pvar = ( pfvar )(fd.bvars.data + pvaras->offbvar);
208 pvar->type = pvaras->type;
209 pvar->oftype = pvaras->oftype;
210 pvar->flg = pvaras->flg;
211 }
212 fd.bvarsas.use = oldbvarsasuse;
213
214 //Очистка локальных переменных
215 off = (uint)fd.bvars.data + fd.oldoffbvar;
216 for ( (uint)pvar = (uint)fd.bvars.data + fd.bvars.use - sizeof( fvar );
217 (uint)pvar >= off; pvar-- )
218 {
219 if ( pvar->hidn )
220 {
221 pvar->hidn->val = pvar->oldoffbvar;
222 }
223 }
224 //Удаляем лишние локальные переменные
225 fd.bvars.use = fd.oldoffbvar;
226 fd.oldoffbvar = oldbvaruse;
227 //Установка количества локальных переменных для последнего блока
228 if ( fd.curcount )
229 {
230 buf_appenduint( &fd.bhead, fd.curcount );
231 }
232 if ( oldvarcount != fd.varcount )
233 {
234 fd.curcount = 0;
235 fd.lastcurcount = 0;
236 }
237 else
238 {
239 if ( lastcurcount != -1 )
240 {
241 fd.curcount = fd.lastcurcount;
242 fd.lastcurcount = lastcurcount;
243 }
244 }
245
246 //Вставка команд инициализации блоков
247 numins = fd.bblinit.use - oldbblinituse;
248 if ( numins )
249 {
250 buf_insert( fd.bout, oldboutuse, fd.bblinit.data + oldbblinituse, numins );
251 fd.bblinit.use = oldbblinituse;
252 }
253
254 //Корректировка меток
255 curlabel = ( pflabel )( fd.blabels.data + oldblabelsuse );
256 oldblabelsuse = ( uint )( fd.blabels.data + fd.blabels.use );
257 while( ( uint )curlabel < oldblabelsuse )
258 {
259 curlabel->offbout += numins;
260
261 if ( !( curlabel->type & LABT_VIRT ) )
262 {
263 if ( curlabel->type & LABT_LABEL )
264 {
265 curlabel->type = LABT_LABELUNDEF;
266 }
267 else
268 if ( ( curlabel->type & LABT_GTUNDEF ) == LABT_GTUNDEF )
269 { //Определение неопределенных меток
270 off = curlabel->hitem->val;
271 if ( off != -1 )
272 {
273 if ( (( pflabel )(fd.blabels.data + off ))->type & LABT_LABEL )
274 {
275 curlabel->type = LABT_GTDEF;
276 curlabel->link = off;
277 }
278 else
279 msg( MUnklabel | MSG_LEXNAMEERR, curlabel->lex );
280 }
281 }
282 }
283 curlabel++;
284 }
285 fd.bllevel--;
286
287 D( "Body stop\n" );
288 return curlex;
289 }