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: func 02.11.06 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 "out.h"
 21 #include "alias.h"
 22 
 23 s_funcdata fd;
 24 
 25 /*-----------------------------------------------------------------------------
 26 *
 27 * ID: m_func 02.11.06 0.0.A.
 28 *
 29 * Summary: The func, method, operator, property, text processing
 30 *
 31 -----------------------------------------------------------------------------*/
 32 plexem STDCALL m_func( plexem curlex, uint flgextern )
 33 {
 34 #ifdef DOUT
 35    uint     i;
 36 #endif 
 37 
 38 
 39    uint     funckey;  //Вид функции
 40    uint     flgfunc;  //Флаги функции   
 41 
 42    pflabel  curlabel; // Текущий элемент в таблице меток
 43    pflabel  endlabel; // Конец таблицы меток
 44    uint     isreturn; //Есть return
 45 
 46    uint     thistype; //Тип переменной this для методов+
 47    pubyte   name;     //Имя функции
 48    plexem   lexname;  //Лексема с именем функции
 49 
 50    s_desctype desctype;//Описание типа
 51    s_descid   descvar; //Описание переменной
 52 
 53    uint off_parcount; //Смещение в заголовке функции на кол. параметров
 54    uint off_blccount; //Смещение в заголовке функции на кол. блоков
 55 
 56    bcflag     bcf;    //Переменная для получение флагов функции
 57    pbuf       b;
 58    pfwith     pwith; 
 59    pvmobj     funcobj;   
 60    uint       thisid; //Номер переменной для this в текст функции
 61 
 62 D( "Func start\n" );
 63 
 64 // Инициализация
 65    desctype.idtype = 0;
 66    descvar.idtype = 0;
 67    descvar.flgdesc = 0;
 68    mem_zero( &fd, sizeof( fd ) );
 69    thistype = 0;
 70    funckey = curlex->key;
 71    hash_init( &fd.nvars, sizeof( uint ) );
 72    hash_init( &fd.nlabels, sizeof( uint ) );
 73    for ( b = &fd.bhead; b <= &fd.bvarsas; b++ )
 74    {
 75       buf_init( b );
 76       buf_reserve( b, 0x200 );
 77       b->step = 0x200;
 78    }
 79    fd.bvars.use = sizeof( fvar );
 80    fd.blabels.use = sizeof( flabel );
 81 //   _compile->pout = &fd.bhead;   
 82 //   fd.blcount = 0;
 83 //   fd.varcount = 0;
 84 //   fd.curcount = 0;
 85 //   fd.lastcurcount = 0;
 86 //   fd.bllevel = 0;
 87 //   fd.blcycle = 0;
 88    fd.offlcbreak = -1;
 89    fd.offlccontinue = -1;   
 90 //   fd.functype = 0;
 91 
 92    switch ( funckey )
 93    {
 94       case KEY_METHOD:
 95          flgfunc = GHBC_METHOD;
 96          break;
 97       case KEY_OPERATOR:
 98          flgfunc = GHBC_OPERATOR;
 99          break;
100       case KEY_PROPERTY:
101          flgfunc = GHBC_PROPERTY;
102          break;
103       case KEY_TEXT:
104          flgfunc = GHBC_TEXT;
105          break;
106       default:
107          flgfunc = 0;
108    }
109    curlex = lexem_next( curlex, LEXNEXT_IGNLINE );
110 
111 // Получаем тип возвращаемого значения функции/метода если он есть
112    if ( curlex->type == LEXEM_NAME )
113       curlex = desc_idtype( curlex, &desctype );
114 
115    if ( desctype.idtype )
116    {
117       if ( ( funckey == KEY_METHOD || funckey == KEY_PROPERTY ) &&
118            curlex->type == LEXEM_OPER &&
119            curlex->oper.operid == OpWith )
120       {
121          //Возврат на лексему влево текущая лексема тип объекта
122          desctype.idtype = 0;
123          curlex--;
124       }
125       else
126       {
127          fd.functype = desctype.idtype;
128          fd.funcoftype = desctype.oftype;
129       }
130    }
131    curlex = lexem_next( curlex, LEXNEXT_SKIPLINE );
132 // Получаем тип объекта для метода
133    if ( funckey == KEY_METHOD || funckey == KEY_PROPERTY )
134    {
135       //Получаем тип объекта
136       if ( thistype = bc_type( curlex ) )
137       {
138          curlex = lexem_next( curlex, 0 );
139          if ( curlex->type == LEXEM_OPER &&
140               curlex->oper.operid == OpWith )
141          {
142             curlex = lexem_next( curlex, 0 );
143          }
144          else
145             msg( MExppoint | MSG_LEXERR, curlex );
146       }
147       else
148          msg( MExptype | MSG_LEXERR, curlex );
149    }
150 // Получение имени функции, метода ...   
151    if ( funckey == KEY_OPERATOR )
152    {
153       if ( curlex->type != LEXEM_OPER )
154          msg( MExpoper | MSG_LEXERR, curlex );
155       name = ( pubyte )&curlex->oper.name;
156    }
157    else
158    {
159       if ( curlex->type != LEXEM_NAME )
160          msg( MExpname | MSG_LEXERR, curlex );
161       name = lexem_getname( curlex );      
162    }
163    lexname = curlex;
164    _vm.pos = curlex->pos;
165    
166 // Получение списка директив
167    curlex = lexem_next( curlex, flgextern ? 0 : LEXNEXT_IGNLINE );   
168    curlex = bc_flag( curlex, BFLAG_FUNC, &bcf );   
169    flgfunc |= GHCOM_NAME | bcf.value;
170    _compile->pout = &fd.bhead;   
171    out_head( OVM_BYTECODE, flgfunc, name );
172 
173    create_varmode( &fd.bhead, &desctype, 0 );//Возвращаемое значение
174 
175    off_parcount = fd.bhead.use;
176    out_adduint( 0 );//Количество параметров
177 
178    if ( funckey == KEY_METHOD || funckey == KEY_PROPERTY )
179    {   //Создание параметра this
180       mem_zero( &descvar, sizeof( descvar ));
181       descvar.idtype = thistype;
182       descvar.name = "this";
183       descvar.lex = curlex;
184       descvar.flgdesc = DESCID_PARFUNC;
185 
186       pwith = ( pfwith )buf_appendtype( &fd.bwith, sizeof( fwith )) ;
187       pwith->num = var_checkadd( &descvar );
188       pwith->oftype = 0;
189       pwith->type = thistype;
190    }
191 
192 //Получение списка параметров
193    if ( curlex->type == LEXEM_OPER &&
194         curlex->oper.operid == OpLbrack )//Открывающая скобка
195    {
196       curlex = lexem_next( curlex, LEXNEXT_IGNLINE );
197       curlex = var_def( curlex, DESCID_PARFUNC );
198       if ( curlex->type != LEXEM_OPER ||//Системная лексема
199            curlex->oper.operid != OpRbrack )//Закрывающая скобка
200          msg( MExpclosebr | MSG_LEXERR, curlex );
201 
202       curlex = lexem_next( curlex, flgextern ? 0 : LEXNEXT_IGNLINE );
203    }
204    else
205    {
206       if ( funckey == KEY_OPERATOR )
207          msg( MExpopenbr | MSG_LEXERR, curlex );
208    }
209 
210    fd.flgfunc = flgfunc;
211    if ( flgfunc & GHBC_RESULT )
212    {   //Создание параметра result
213       if ( !fd.functype || fd.functype <= TUlong )
214          msg( MResulttype | MSG_LEXERR, curlex );
215       mem_zero( &descvar, sizeof( descvar ));
216       descvar.idtype = desctype.idtype;
217       descvar.oftype = desctype.oftype;
218       descvar.flgdesc = DESCID_PARFUNC;
219       descvar.name = "result";
220       descvar.lex = curlex;
221       fd.idresult = var_checkadd( &descvar );
222       fd.functype = 0;
223    }
224    if ( fd.varcount )
225    {
226       *( puint )( fd.bhead.data + off_parcount ) = fd.varcount;//Кол-во параметров
227       if ( flgfunc & ( GHBC_ENTRY | GHBC_MAIN ) )
228          msg( MMainpar | MSG_LEXERR, curlex );
229       fd.curcount = 0;
230    }
231    off_blccount = fd.bhead.use;
232    out_adduint( 0 );//Количество блоков
233 
234    if ( funckey == KEY_PROPERTY )
235    {      
236       if ( ( fd.functype && fd.varcount > 1 ) ||
237            (!fd.functype && fd.varcount != 2 ))
238       {
239          msg( MProppar | MSG_LEXERR, curlex );//Неверное количество параметров в описании свойства
240       }
241       if ( type_fieldname( thistype, name ) )
242       {
243          msg( MPropfield | MSG_LEXERR, curlex );//Свойство совпадает с именем поля
244       }
245    }
246    
247    funcobj = load_bytecode( &fd.bhead.data, flgextern ? VMLOAD_EXTERN : VMLOAD_FIRST );   
248    if ( bcf.value & GHRT_ALIAS )
249    {  
250       alias_setid( bcf.alias, funcobj->id );     
251    }
252    if ( !( flgextern ) )
253    {      
254       if ( _compile->flag & CMPL_DEBUG )
255       {  
256          _compile->pout = fd.bout = &fd.bsubout;
257          out_adduints( 3,  CDatasize, 
258                            str_len( _compile->cur->filename ) + 5,
259                            str_pos2line( _compile->cur->src, lexname->pos, 0 ) + 1 );
260          out_addptr( str_ptr( _compile->cur->filename ), str_len( _compile->cur->filename ) + 1 );                     
261          out_adduint( CDbgFunc );
262          _compile->pout = fd.bout = &fd.bfuncout; 
263       }
264       _compile->pout = fd.bout = &fd.bfuncout;
265       if ( funckey == KEY_TEXT )
266       {   //Создание параметра this для Text функции
267          mem_zero( &descvar, sizeof( descvar ));
268          descvar.idtype = TUint;
269          descvar.name = "this";
270          descvar.lex = curlex;
271          descvar.flgdesc = DESCID_VAR;///DESCID_PARFUNC;
272          thisid = var_checkadd( &descvar );
273          
274          /*pwith = ( pfwith )buf_appendtype( &fd.bwith, sizeof( fwith )) ;
275          pwith->num = var_checkadd( &descvar );
276          //print( "ssssssssss %x %x %x %x", fd.bvars.data, fd.bvars.use, pwith->num, sizeof( fvar ) );
277          pwith->oftype = 0;
278          pwith->type = TStr;*/
279          ((pfvar)(fd.bvars.data + fd.bvars.use - sizeof( fvar )))->type = TStr;
280          out_adduints( 4, CVarptrload, thisid, CGetText, CSetI );
281          /*buf_appenduint( &fd.bblinit, CVarptrload );
282          buf_appenduint( &fd.bblinit, thisid );
283          buf_appenduint( &fd.bblinit, CGetText );
284          buf_appenduint( &fd.bblinit, CSetI );*/
285       }
286       curlex = f_body( curlex );
287       
288       *((puint)(fd.bhead.data+off_blccount)) = fd.blcount;
289 
290       curlabel = ( pflabel )( fd.blabels.data ) + 1;
291       endlabel = ( pflabel )( fd.blabels.data + fd.blabels.use );
292       //Контроль неразрешённых меток и проверка выходов из функции
293       isreturn = 0;
294       while( curlabel < endlabel )
295       {
296          if ( curlabel->type & LABT_GT )
297          {
298             if ( ( curlabel->type & LABT_GTUNDEF ) == LABT_GTUNDEF )
299                msg( MUnklabel | MSG_LEXNAMEERR, curlabel->lex );
300             *( puint )(fd.bfuncout.data + curlabel->offbout ) = 
301                      ((( pflabel )(fd.blabels.data + curlabel->link ))->offbout + 
302                       fd.bsubout.use )/sizeof(uint);
303             if ( !isreturn )//Помечаем метку как отработавшую (на неё был переход)
304                (( pflabel )(fd.blabels.data + curlabel->link ))->type |= LABT_LABELWORK;            
305          }
306          else
307          if ( curlabel->type & LABT_RETURN )
308          {
309             isreturn = 1;//Устанавливаем флаг
310          }
311          else
312          if ( curlabel->type & LABT_LABELWORK )
313             isreturn = 0;//Если была отработавшая метка, то сбрасываем флаг
314          curlabel++;
315       }
316       if ( fd.functype )
317       {
318          if ( !isreturn )
319             msg( MMustret | MSG_LEXNAMEERR, lexname );
320       }
321       else
322          if ( !isreturn )
323          {
324             if ( fd.flgfunc & GHBC_RESULT )
325             {
326                out_add2uint( CVarload, fd.idresult );
327             }
328             out_adduint( CReturn );
329          }      
330       buf_add( &fd.bhead, &fd.bvardef );
331       
332       if ( fd.bsubout.use )
333       {
334          if ( fd.offsubgoto )
335          {
336             //*((( puint)fd.bsubout.data ) + 1) = fd.bsubout.use/sizeof( uint );
337             *( puint )( fd.bsubout.data + fd.offsubgoto ) = fd.bsubout.use / sizeof( uint );
338          }
339          buf_add( &fd.bhead, &fd.bsubout );
340       }
341       buf_add( &fd.bhead, &fd.bfuncout );
342       _compile->pout = &fd.bhead;
343       out_finish();
344 #ifdef DOUT
345    //Тестируемый вывод 
346    //if ( name[0] == 'c' && name[1] == 'r' ) getch();
347    print( "FUNC OUT %x %s:\n", funcobj->id, name );
348    for (i = 0; i < fd.bhead.use ; i++ )
349    {
350       print( "  %x", fd.bhead.data[i] );
351    } 
352    print( "\n" );
353 #endif            
354       load_bytecode( &fd.bhead.data, VMLOAD_OK );
355     //  print( "funcobjid2 =%x\n", funcobj->id );
356    }
357    //Очистка памяти
358    for ( b = &fd.bhead;/*&fd.bblinit;*/ b <= &fd.bvarsas; b++ )
359    {
360       buf_delete( b );
361    }
362    hash_delete( &fd.nvars );
363    hash_delete( &fd.nlabels );
364 
365 D( "Func Stop\n" );
366    return curlex;
367 }
368 
369