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: lexem 18.10.06 0.0.A.
 11 *
 12 * Author: Alexey Krivonogov ( gentee )
 13 *
 14 * Summary: Working with lexems
 15 *
 16 ******************************************************************************/
 17 
 18 #include "bcodes.h"
 19 #include "compinit.h"
 20 #include "../vm/vm.h"
 21 #include "../vm/vmres.h"
 22 #include "../vm/vmtype.h"
 23 #include "../common/msg.h"
 24 #include "alias.h"
 25 
 26 const  pubyte  nameflags[] ={ 
 27    // Флаги для функций
 28    "entry" , "main", "result", "=alias",
 29    // Флаги для типов
 30    "=index", "=inherit", "protected", 
 31    // Флаги для define
 32    "export", "namedef",
 33    // Флаги для import
 34    "link" ,"cdeclare", "exe"
 35 };
 36 
 37 const  uint  valflags[] = {
 38    // Флаги для функций
 39    GHBC_ENTRY | BFLAG_FUNC, GHBC_MAIN | BFLAG_FUNC, GHBC_RESULT | BFLAG_FUNC, GHRT_ALIAS | BFLAG_FUNC,
 40    // Флаги для типов
 41    GHTY_INDEX | BFLAG_TYPE, GHTY_INHERIT | BFLAG_TYPE, GHTY_PROTECTED | BFLAG_TYPE, 
 42    // Флаги для define
 43    GHDF_EXPORT | BFLAG_DEFINE, GHDF_NAMEDEF | BFLAG_DEFINE,
 44    // Флаги для import
 45    GHIMP_LINK | BFLAG_IMPORT, GHIMP_CDECL | BFLAG_IMPORT, GHIMP_EXE | BFLAG_IMPORT, 0,
 46 };
 47 
 48 /*-----------------------------------------------------------------------------
 49 *
 50 * ID: bc_flag 03.11.06 0.0.A.
 51 * 
 52 * Summary: Get flags. Return the next lexem
 53 *
 54 -----------------------------------------------------------------------------*/
 55 
 56 plexem  STDCALL bc_flag( plexem plex, uint type, pbcflag bcf )
 57 {
 58    uint eqflag, i;
 59 
 60    bcf->value = _compile->cur->priv ? GHRT_PRIVATE : 0;
 61 
 62    if ( !lexem_isys( plex, LSYS_LESS ))
 63       return plex;
 64 
 65    while ( 1 )
 66    {
 67       plex = lexem_next( plex, LEXNEXT_IGNLINE );
 68 nonext:
 69       if ( lexem_isys( plex, LSYS_GREATER ))
 70          break;
 71       if ( plex->type != LEXEM_NAME )
 72          msg( MExpname | MSG_LEXERR, plex );
 73 
 74       i = 0;
 75       while ( valflags[ i ] )
 76       {
 77          if ( valflags[ i ] & type )
 78          {
 79             eqflag = ( *nameflags[ i ] == '=' ? 1 : 0 );
 80             if ( mem_iseqzero( nameflags[ i ] + eqflag, lexem_getname( plex )))
 81             {
 82                bcf->value |= valflags[ i ] & 0xFFFFFF00;
 83                break;
 84             }
 85          }
 86          i++;
 87       }
 88       // Нет такого флага
 89       if ( !valflags[ i ] )
 90          msg( MNotattrib | MSG_LEXNAMEERR, plex );
 91 
 92       if ( eqflag )
 93       {
 94          plexem next;
 95 
 96          next = lexem_next( plex, LEXNEXT_IGNLINE );
 97          if ( !lexem_isys( next, LSYS_EQ ))
 98             msg( MAttrval | MSG_LEXNAMEERR, plex );
 99          next = lexem_next( next, LEXNEXT_IGNLINE | LEXNEXT_NAME );
100          if ( valflags[i] & GHTY_INDEX )
101          {
102             if ( mem_iseqzero( lexem_getname( next ), "this" ))
103             {
104                bcf->index.idtype = arr_count( &_vm.objtbl );
105                bcf->index.msr = 0;
106                bcf->index.oftype = 0;
107                plex = lexem_next( next, 0 );
108             }
109             else
110                plex = desc_idtype( next, &bcf->index  );
111          }
112          if ( valflags[i] & GHTY_INHERIT )
113             plex = desc_idtype( next, &bcf->inherit );
114          if ( valflags[i] & GHRT_ALIAS )
115             plex = alias_add( next, &bcf->alias );
116          goto nonext;
117       }
118    }
119    return lexem_next( plex, LEXNEXT_IGNLINE );
120 }
121 
122 /*-----------------------------------------------------------------------------
123 *
124 * ID: bc_method 03.11.06 0.0.A.
125 * 
126 * Summary: Find method id
127 *
128 -----------------------------------------------------------------------------*/
129 
130 pvmfunc   STDCALL  bc_method( plexem plex, uint count, puint pars )
131 {
132    pvmfunc      bcode;
133    ubyte        name[256];
134 
135    // Формируем имя метода или оператора
136    sprintf( name, "@%s", lexem_getname( plex ));
137    bcode = vm_find( name, count, pars );
138 
139    return ( uint )bcode < MSGCOUNT ? 0 : bcode;
140 }
141 
142 /*-----------------------------------------------------------------------------
143 *
144 * ID: bc_func 03.11.06 0.0.A.
145 * 
146 * Summary: Find func id
147 *
148 -----------------------------------------------------------------------------*/
149 
150 pvmfunc   STDCALL  bc_func( plexem plex, uint count, puint pars )
151 {
152    pvmfunc      bcode;
153    ubyte        name[256];
154 
155    if ( plex->flag & LEXF_NAME )
156       mem_copyuntilzero( name, ( pubyte )plex->nameid );
157    else
158    {
159       // Формируем имя метода или оператора
160       if ( plex->flag & LEXF_METHOD )
161          sprintf( name, "@%s", lexem_getname( plex ));
162       else
163          if ( plex->flag & LEXF_OPERATOR )
164             sprintf( name, "#%s", ( pubyte )&plex->oper.name );
165          else
166             mem_copyuntilzero( name, lexem_getname( plex ));
167    }
168    bcode = vm_find( name, count, pars );
169    if ( ( uint )bcode < MSGCOUNT )
170          msg( ( uint )bcode | MSG_LEXERR | MSG_VALUE, plex, name );
171    if (( plex->flag & LEXF_PROPERTY ) && !( bcode->vmo.flag & GHBC_PROPERTY ))
172       msg( MUnkprop | MSG_LEXERR, plex );
173 
174    return bcode;
175 }
176 
177 /*-----------------------------------------------------------------------------
178 *
179 * ID: bc_oper 03.11.06 0.0.A.
180 * 
181 * Summary: Find operator id
182 *
183 -----------------------------------------------------------------------------*/
184 
185 pvmfunc   STDCALL bc_oper( plexem plex, uint srctype, uint desttype, 
186                            uint srcof, uint destof )
187 {
188    uint ptr[12];
189 //   pslexsys sys;
190    
191 /*   if ( opers[ plex->oper.operid ].flgs & OPF_NOP )
192    {
193       return NULL;
194    }*/
195 /* ???  if ( plex->sys->oper == OpNone )
196    {
197       *ret = ( lexitem->sys->type & OPER_RETUINT ? SUInt : desttype );
198       return 0;
199    }*/
200    ptr[0] = srctype ? srctype : desttype;
201    ptr[1] = srctype ? srcof : destof;
202    ptr[2] = desttype;
203    ptr[3] = destof;
204    plex->oper.name = oper2name( plex->oper.operid );
205 //   if ( plex->oper.operid == OpIncright )
206 //      print("XXX=%x", plex->oper.name );
207 //   print("OK %i %i %i %i\n", srctype, desttype, plex->oper.operid, plex->oper.name );
208    plex->flag |= LEXF_OPERATOR;
209    return bc_func( plex, srctype ? 2 : 1, ( puint )&ptr );
210 }
211 
212 /*-----------------------------------------------------------------------------
213 *
214 * ID: bc_property 03.11.06 0.0.A.
215 * 
216 * Summary: Find property id
217 *
218 -----------------------------------------------------------------------------*/
219 
220 pvmfunc   STDCALL bc_property( plexem plex, uint objtype, uint setpar )
221 {
222    uint  pars[12];
223 
224    plex->flag |= LEXF_METHOD | LEXF_PROPERTY;
225    pars[0] = objtype;
226    pars[1] = 0;
227    pars[2] = setpar;
228    pars[3] = 0;
229    return bc_func( plex, 1 + ( setpar ? 1 : 0 ), ( puint )&pars );
230 }
231 
232 /*-----------------------------------------------------------------------------
233 *
234 * ID: bc_isproperty 03.11.06 0.0.A.
235 * 
236 * Summary: Find possible property id
237 *
238 -----------------------------------------------------------------------------*/
239 
240 pvmfunc   STDCALL bc_isproperty( plexem plex, uint objtype )
241 {
242    pvmfunc      bcode;
243    uint         id;
244    phashitem    phi = NULL;
245    ubyte        name[256];
246 
247    // Формируем имя метода или оператора
248    sprintf( name, "@%s", lexem_getname( plex ));
249 
250    phi = hash_find( &_vm.objname, name );
251 
252    if ( !phi )
253       return ( pvmfunc )0;
254 
255    id = *( puint )( phi + 1 );
256       
257    while ( id )
258    {
259       bcode =  ( pvmfunc )PCMD( id );
260       if ( bcode->vmo.flag & GHBC_PROPERTY )
261       {
262          if ( type_isinherit( objtype, bcode->params->type ))
263             return bcode;
264       }
265       id = bcode->vmo.nextname;
266    }
267    return NULL;
268 }
269 
270 //--------------------------------------------------------------------------
271 
272 pvmfunc  STDCALL  bc_funcname( plexem plexerr, pubyte name, uint count, puint pars )
273 {
274    lexem       lexerr;
275 
276    mem_zero( &lexerr, sizeof( lexem ));
277    lexerr.pos = plexerr->pos;
278    lexerr.flag |= LEXF_NAME;
279    lexerr.nameid = ( uint )name;
280 
281    return bc_func( &lexerr, count, pars );
282 }
283 
284 //--------------------------------------------------------------------------
285 
286 uint  CDECLCALL bc_find( plexem plexerr, pubyte name, uint count, ... )
287 {
288    va_list     argptr;
289    uint        i = 0;
290    uint        params[ 32 ];
291 //   pvmfunc     pfunc;
292 
293    va_start( argptr, count );
294    while ( i < count )
295    {
296       params[ i << 1 ] = va_arg( argptr, uint );
297       params[ ( i << 1 ) + 1 ] = 0; // flags oftype
298       i++;
299    }
300    va_end( argptr );
301 
302 //   pfunc = vm_find( name, count, ( puint )¶ms );
303    return bc_funcname( plexerr, name, count, ( puint )¶ms )->vmo.id;
304 //   return ( uint )pfunc < MSGCOUNT ? 0 : pfunc->vmo.id;
305 }
306 
307 /*-----------------------------------------------------------------------------
308 *
309 * ID: bc_getid 03.11.06 0.0.A.
310 * 
311 * Summary: Get an id of vm 
312 *
313 -----------------------------------------------------------------------------*/
314 
315 uint   STDCALL bc_getid( plexem plex )
316 {
317    phashitem  phi;
318 //   pscompile    compile = ggentee.compile;
319 
320    if ( plex->type != LEXEM_NAME )
321       msg( MWrongname | MSG_LEXERR, plex );
322  
323    phi = hash_find( &_vm.objname, lexem_getname( plex ) );
324    
325 //   result = nametbl_find( &compile->gevm.nametbl, 
326 //          nametbl_getname( &compile->idname, lexitem->id ), FALSE );
327 
328 //   if ( result )
329 //      result = nametbl_valget( &compile->gevm.nametbl, result );
330 //   result = nametbl_valgetname( &compile->gevm.nametbl, 
331 //                         nametbl_getname( &compile->idname, lexitem->id ));
332    return phi ? *( puint )( phi + 1 ) : 0;
333 }
334 
335 /*-----------------------------------------------------------------------------
336 *
337 * ID: bc_obj 03.11.06 0.0.A.
338 * 
339 * Summary: 
340 *
341 -----------------------------------------------------------------------------*/
342 /*
343 uint   STDCALL bc_obj( plexem plex )
344 {
345    uint   type = bc_getid( plex );
346 
347    if ( type )
348       return (( pvmobj )PCMD( type ))->type;
349       ret = (( psvmobj )objtbl_getobj( &compile->gevm, type ))->type;
350       if ( ret == OVM_BYTECODE || ret == OVM_EXFUNC || ret == OVM_STACKCMD ||
351            ret == OVM_GLOBAL )
352          lexitem->sys = ( pslexsys ) type;
353    return 0;
354 }
355 */
356 /*-----------------------------------------------------------------------------
357 *
358 * ID: bc_type 03.11.06 0.0.A.
359 * 
360 * Summary: Get a type of the identifier
361 *
362 -----------------------------------------------------------------------------*/
363 
364 uint   STDCALL bc_type( plexem plex )
365 {
366    uint       type = bc_getid( plex );
367 
368 //   pscompile  compile = ggentee.compile;
369 
370 /*   if ( !type || (( psvmobj )objtbl_getobj( &compile->gevm, type ))->type != OVM_TYPE )
371       if ( noerror )
372          type = 0;
373       else
374          io_mess( IOC_UNKTYPE, lexitem );
375 */
376    return (( pvmobj )PCMD( type ))->type == OVM_TYPE ? type : 0;
377 }
378 
379 /*-----------------------------------------------------------------------------
380 *
381 * ID: bc_resource 03.11.06 0.0.A.
382 * 
383 * Summary: Get an identifier of the resource
384 *
385 -----------------------------------------------------------------------------*/
386 
387 uint   STDCALL bc_resource( pubyte ptr )
388 {
389    phashitem   phi;
390    puint       pidphi;
391 
392    phi = hash_create( &_compile->resource, ptr );
393    pidphi = ( puint )( phi + 1 );
394    if ( !*pidphi )
395       *pidphi = vmres_addstr( ptr ) + 1;
396 
397    return *pidphi - 1;
398 }
399 
400