OSDN Git Service

こっそり、気持ち程度の日本語化しました (UTF-8 / Windows 環境用)。
[ring-lang-081/annotated-ring-with-OmegaT.git] / source / src / ring_vm.c
1 /* Copyright (c) 2013-2019 Mahmoud Fayed <msfclipper@yahoo.com> */
2 #include "ring.h"
3 /*
4 **  Functions 
5 **  Main 
6 */
7
8 VM * ring_vm_new ( RingState *pRingState )
9 {
10         VM *pVM  ;
11         int x  ;
12         ring_state_log(pRingState,"function: ring_vm_new - start");
13         pVM = (VM *) ring_state_malloc(pRingState,sizeof(VM));
14         if ( pVM == NULL ) {
15                 printf( RING_OOM ) ;
16                 exit(0);
17         }
18         /* Ring State */
19         pVM->pRingState = pRingState ;
20         pRingState->pVM = pVM ;
21         ring_state_log(pRingState,"function: ring_vm_new - after malloc()");
22         pVM->nPC = 1 ;
23         pVM->pCode = NULL ;
24         pVM->pFunctionsMap = NULL ;
25         pVM->nOPCode = 0 ;
26         pVM->nSP = 0 ;
27         pVM->pMem = ring_list_new_gc(pVM->pRingState,0);
28         pVM->pActiveMem = NULL ;
29         pVM->pTempMem = ring_list_new_gc(pVM->pRingState,0);
30         pVM->nLineNumber = 1 ;
31         /* Information to test the lifetime of the local scope */
32         pVM->nScopeID = 0 ;
33         pVM->aScopeID = ring_list_new_gc(pVM->pRingState,0);
34         ring_state_log(pRingState,"function: ring_vm_new - after setting aScopeID");
35         ring_vm_newscope(pVM);
36         for ( x = 0 ; x < RING_VM_STACK_SIZE ; x++ ) {
37                 pVM->aStack[x].nType = ITEMTYPE_NOTHING ;
38                 pVM->aStack[x].nObjectType = 0 ;
39                 pVM->aStack[x].NumberFlag = ITEM_NUMBERFLAG_NOTHING ;
40         }
41         /*
42         **  Flag ( 0 = check NULL variable in PUSHV  , greater than 0 = Ignore null variable ) 
43         **  Class Region (After the Class Name) 
44         */
45         pVM->nInClassRegion = 0 ;
46         ring_state_log(pRingState,"function: ring_vm_new - after class region flag");
47         /* Add Variables */
48         ring_vm_addglobalvariables(pVM);
49         ring_state_log(pRingState,"function: ring_vm_new - after global variables");
50         /* Lists */
51         pVM->nListStart = 0 ;
52         pVM->pNestedLists = ring_list_new_gc(pVM->pRingState,0);
53         ring_state_log(pRingState,"function: ring_vm_new - after nested lists");
54         /* Support for nested Load Instructions */
55         pVM->nBlockFlag = 0 ;
56         pVM->aPCBlockFlag = ring_list_new_gc(pVM->pRingState,0);
57         /* Calling Functions */
58         pVM->pFuncCallList = ring_list_new_gc(pVM->pRingState,0);
59         pVM->nFuncSP = 0 ;
60         pVM->nFuncExecute = 0 ;
61         if ( pRingState->pRingCFunctions == NULL ) {
62                 pRingState->pRingCFunctions = ring_list_new_gc(pVM->pRingState,0);
63         }
64         pVM->pCFunctionsList = pRingState->pRingCFunctions ;
65         pVM->nCallMainFunction = 0 ;
66         /* Support for Exit/Loop Commands inside For/While loops. */
67         pVM->pExitMark = ring_list_new_gc(pVM->pRingState,0);
68         pVM->pLoopMark = ring_list_new_gc(pVM->pRingState,0);
69         ring_state_log(pRingState,"function: ring_vm_new - after exit/loop marks");
70         /* Try-Catch-Done */
71         pVM->pTry = ring_list_new_gc(pVM->pRingState,0);
72         /* Saving scope when creating new objects and calling class init method */
73         pVM->aScopeNewObj = ring_list_new_gc(pVM->pRingState,0);
74         /* Flag ( 0 = Call Function  1 = Call Method After writing object name using dot ) */
75         pVM->nCallMethod = 0 ;
76         /* List of Lists used like Stack, list structure [Pointer to State , Pointer to Methods] */
77         pVM->pObjState = ring_list_new_gc(pVM->pRingState,0);
78         /* Support for using Braces to access object state */
79         pVM->pBraceObject = NULL ;
80         pVM->aBraceObjects = ring_list_new_gc(pVM->pRingState,0);
81         /* Used by BraceStart, BraceEnd & FreeStack */
82         pVM->nInsideBraceFlag = 0 ;
83         /* Variable scope, where is the varaible (when we use findvar) */
84         pVM->nVarScope = RING_VARSCOPE_NOTHING ;
85         /* Flag used by Try/Catch to tell C-API that catch happens! */
86         pVM->nActiveCatch = 0 ;
87         pVM->pPackagesMap = NULL ;
88         /* Set the main File Name */
89         pVM->cFileName = ring_list_getstring(pVM->pRingState->pRingFilesList,1) ;
90         pVM->cPrevFileName = ring_list_getstring(pVM->pRingState->pRingFilesList,1) ;
91         ring_state_log(pRingState,"function: ring_vm_new - after setting the main file");
92         /* We keep information about active package to access its classes directly with new/from */
93         pVM->aActivePackage = ring_list_new_gc(pVM->pRingState,0);
94         /* Scope of class attribute ( 0 = public 1 = private ) */
95         pVM->nPrivateFlag = 0 ;
96         /* Set/Get Property */
97         pVM->nGetSetProperty = 0 ;
98         pVM->pGetSetObject = NULL ;
99         pVM->nGetSetObjType = 0 ;
100         pVM->aSetProperty = ring_list_new_gc(pVM->pRingState,0);
101         /* Assignment Pointer */
102         pVM->pAssignment = NULL ;
103         /* For Loop - Step List */
104         pVM->aForStep = ring_list_new_gc(pVM->pRingState,0);
105         /* Flag for LoadA , when = 1 , if it's a pointer we get First Var. not the Pointer */
106         pVM->nFirstAddress = 0 ;
107         /* Used to know operator before = like += -= *= /= */
108         pVM->nBeforeEqual = 0 ;
109         /*
110         **  NOAssignment used to disable instruction AssignmentPointer 
111         **  We uses this when we change assignment to set property 
112         **  It's important for ListStart to create Temp List when we use setter 
113         **  and try to set attribute value to a list and a function setproperty() will be called 
114         **  With this list as parameter stored in temp memory 
115         */
116         pVM->nNOAssignment = 0 ;
117         /* List contains the scope of the result of Load Address */
118         pVM->aLoadAddressScope = ring_list_new_gc(pVM->pRingState,0);
119         /* List contains what to add  later to pObjState, prepare by loadmethod, add before call */
120         pVM->aBeforeObjState = ring_list_new_gc(pVM->pRingState,0) ;
121         /* Saving pointers to aLoadAddressScope before func. para. to restore after them */
122         pVM->pLoadAddressScope = ring_list_new_gc(pVM->pRingState,0);
123         /* Another flag like nFuncExec but not used by see command or return command */
124         pVM->nFuncExecute2 = 0 ;
125         /* Create List for Temp Items (added to ByteCode) inside TempMem */
126         pVM->aNewByteCodeItems = ring_list_new_gc(pVM->pRingState,0);
127         /* Eval can be called from C code (OOP Set/Get/Operator Overloading) or from ring code using eval() */
128         pVM->nEvalCalledFromRingCode = 0 ;
129         /* Number of decimals after the point */
130         pVM->nDecimals = 2 ;
131         /*
132         **  Do we need to reallocation for eval() or not ! 
133         **  Size of items that we can use without reallocation (double of the original size) 
134         */
135         pVM->nEvalReallocationSize = 0 ;
136         /* Flag ( 1 = we need space over allocated size so we have to do reallocation ) */
137         pVM->nEvalReallocationFlag = 0 ;
138         /* Parameters Count Passed to C Function */
139         pVM->nCFuncParaCount = 0 ;
140         /*
141         **  Flag to Ignore NULL output after calling C Function 
142         **  This flag is used by the len() function when we use len(object) 
143         **  So operator overloading can return the result from the method 
144         */
145         pVM->nIgnoreNULL = 0 ;
146         /* If pVM->nPC <= nEvalReturnPC we end the main loop (used by evalreturn) */
147         pVM->nEvalReturnPC = 0 ;
148         /* Flag to return Item Reference (of object state) */
149         pVM->nRetItemRef = 0 ;
150         /* Mutex Functions Pointers - for threads/lock/unlock */
151         pVM->pFuncMutexLock = NULL ;
152         pVM->pFuncMutexUnlock = NULL ;
153         pVM->pFuncMutexDestroy = NULL ;
154         pVM->pMutex = NULL ;
155         /* Ignore C Pointer Type Check in extension functions */
156         pVM->nIgnoreCPointerTypeCheck = 0 ;
157         /*
158         **  Flag when we call class init using new obj() 
159         **  Since we call init() using generated braces { } 
160         **  setting this flag enable LoadAddress to pass these braces 
161         **  To access the class attributes of the caller 
162         **  because {} hides the class attributes and we need to avoid that! 
163         */
164         pVM->nCallClassInit = 0 ;
165         /*
166         **  Flag to avoid deleteing Byte Code using Return From Eval() 
167         **  When we use eval() then inside eval we uses eval for setter/getter/operator overloading 
168         **  Then deleting byte code will cause a problem in setter/getter/operator overloading 
169         **  In this case we set this flag to avoid the delete operation and solve the problem 
170         */
171         pVM->nRetEvalDontDelete = 0 ;
172         /* Counter to know if we are inside ring_vm_runcode() */
173         pVM->nRunCode = 0 ;
174         /* Flag that we have runtime error to avoid calling the error function again */
175         pVM->nActiveError = 0 ;
176         /* The active package name (after using import command) */
177         pVM->pPackageName = ring_string_new_gc(pVM->pRingState,"");
178         /*
179         **  Trace Program (After Each Line) 
180         **  lTrace = Logical Value (Trace is Active or Not) 
181         **  pTrace = String contains the code to be executed (Trace Function) 
182         **  lTraceActive = The Trace Function is Active - Don't Call Trace function from Trace Function 
183         **  nTraceEvent = The Trace Event (1 = New Line , etc) 
184         */
185         pVM->lTrace = 0 ;
186         pVM->pTrace = ring_string_new_gc(pVM->pRingState,"");
187         pVM->lTraceActive = 0 ;
188         pVM->nTraceEvent = 0 ;
189         pVM->pTraceData = ring_list_new_gc(pVM->pRingState,0) ;
190         ring_state_log(pRingState,"function: ring_vm_new - after trace attributes");
191         /* Eval In Scope function is Active : ringvm_evalinscope() */
192         pVM->nEvalInScope = 0 ;
193         /* Pass error in ring_vm_error() from ringvm_passerror() */
194         pVM->lPassError = 0 ;
195         /* Hide Error message - don't display it in ring_vm_error() */
196         pVM->lHideErrorMsg = 0 ;
197         /* Custom Global Scopes (using load package) */
198         pVM->aGlobalScopes = ring_list_new_gc(pVM->pRingState,0);
199         pVM->aActiveGlobalScopes = ring_list_new_gc(pVM->pRingState,0);
200         pVM->nCurrentGlobalScope = 0 ;
201         /* File name in the class region */
202         pVM->cFileNameInClassRegion = NULL ;
203         /* Control Performance Instructions */
204         pVM->lUsePushPLocal = 0 ;
205         /* To know if we are inside eval() or not */
206         pVM->lInsideEval = 0 ;
207         /* Dynamic Libraries */
208         pVM->pCLibraries = ring_list_new_gc(pVM->pRingState,0);
209         /* No Setter Method (used by ring_vm_oop_setget() function) */
210         pVM->lNoSetterMethod = 0 ;
211         ring_state_log(pRingState,"function: ring_vm_new - end");
212         return pVM ;
213 }
214
215 VM * ring_vm_delete ( VM *pVM )
216 {
217         int x  ;
218         List *pRecord  ;
219         Item *pItem  ;
220         assert(pVM);
221         pVM->pMem = ring_list_delete_gc(pVM->pRingState,pVM->pMem);
222         pVM->pNestedLists = ring_list_delete_gc(pVM->pRingState,pVM->pNestedLists);
223         pVM->pFuncCallList = ring_list_delete_gc(pVM->pRingState,pVM->pFuncCallList);
224         pVM->aPCBlockFlag = ring_list_delete_gc(pVM->pRingState,pVM->aPCBlockFlag);
225         pVM->pTempMem = ring_list_delete_gc(pVM->pRingState,pVM->pTempMem);
226         pVM->pExitMark = ring_list_delete_gc(pVM->pRingState,pVM->pExitMark);
227         pVM->pLoopMark = ring_list_delete_gc(pVM->pRingState,pVM->pLoopMark);
228         pVM->pTry = ring_list_delete_gc(pVM->pRingState,pVM->pTry);
229         pVM->aScopeNewObj = ring_list_delete_gc(pVM->pRingState,pVM->aScopeNewObj);
230         pVM->pObjState = ring_list_delete_gc(pVM->pRingState,pVM->pObjState);
231         pVM->aBraceObjects = ring_list_delete_gc(pVM->pRingState,pVM->aBraceObjects);
232         pVM->aScopeID = ring_list_delete_gc(pVM->pRingState,pVM->aScopeID);
233         pVM->aActivePackage = ring_list_delete_gc(pVM->pRingState,pVM->aActivePackage);
234         pVM->aSetProperty = ring_list_delete_gc(pVM->pRingState,pVM->aSetProperty);
235         pVM->aForStep = ring_list_delete_gc(pVM->pRingState,pVM->aForStep);
236         pVM->aLoadAddressScope = ring_list_delete_gc(pVM->pRingState,pVM->aLoadAddressScope);
237         pVM->aBeforeObjState = ring_list_delete_gc(pVM->pRingState,pVM->aBeforeObjState);
238         pVM->pLoadAddressScope = ring_list_delete_gc(pVM->pRingState,pVM->pLoadAddressScope);
239         pVM->aNewByteCodeItems = ring_list_delete_gc(pVM->pRingState,pVM->aNewByteCodeItems);
240         /* Free Stack */
241         for ( x = 0 ; x < RING_VM_STACK_SIZE ; x++ ) {
242                 ring_item_content_delete(&(pVM->aStack[x]));
243         }
244         ring_state_free(pVM->pRingState,pVM->pByteCode);
245         /* Delete Mutex */
246         ring_vm_mutexdestroy(pVM);
247         pVM->pPackageName = ring_string_delete_gc(pVM->pRingState,pVM->pPackageName);
248         pVM->pTrace = ring_string_delete_gc(pVM->pRingState,pVM->pTrace);
249         pVM->pTraceData = ring_list_delete_gc(pVM->pRingState,pVM->pTraceData);
250         /* Custom Global Scope (using Load Package) */
251         pVM->aGlobalScopes = ring_list_delete_gc(pVM->pRingState,pVM->aGlobalScopes);
252         pVM->aActiveGlobalScopes = ring_list_delete_gc(pVM->pRingState,pVM->aActiveGlobalScopes);
253         /* Dynamic Libraries */
254         #if RING_VM_DLL
255         ring_vm_dll_closealllibs(pVM);
256         #endif
257         pVM->pCLibraries = ring_list_delete_gc(pVM->pRingState,pVM->pCLibraries);
258         pVM->pRingState->pVM = NULL ;
259         ring_state_free(pVM->pRingState,pVM);
260         pVM = NULL ;
261         return pVM ;
262 }
263
264 RING_API void ring_vm_loadcode ( VM *pVM )
265 {
266         int x,nSize  ;
267         /*
268         **  We may allocation double of the size that we need to avoid reallocation when we use eval() 
269         **  eval() will check if there is a need to reallocation or not 
270         **  This optimization increase the performance of applications that uses eval() 
271         */
272         nSize = (MAX(ring_list_getsize(pVM->pCode),RING_VM_MINVMINSTRUCTIONS))*RING_VM_EXTRASIZE ;
273         pVM->pByteCode = (ByteCode *) ring_state_calloc(pVM->pRingState,nSize,sizeof(ByteCode));
274         if ( pVM->pByteCode == NULL ) {
275                 printf( RING_OOM ) ;
276                 exit(0);
277         }
278         for ( x = 1 ; x <= ring_list_getsize(pVM->pCode) ; x++ ) {
279                 ring_vm_tobytecode(pVM,x);
280         }
281         pVM->nEvalReallocationSize = nSize ;
282 }
283
284 void ring_vm_start ( RingState *pRingState,VM *pVM )
285 {
286         pVM->pCode = pRingState->pRingGenCode ;
287         pVM->pFunctionsMap = pRingState->pRingFunctionsMap ;
288         pVM->pClassesMap = pRingState->pRingClassesMap ;
289         pVM->pPackagesMap = pRingState->pRingPackagesMap ;
290         ring_state_log(pRingState,"function: ring_vm_start");
291         ring_vm_loadcode(pVM);
292         ring_state_log(pRingState,"function: ring_vm_start - after loading code");
293         ring_vm_loadcfunctions(pRingState);
294         ring_state_log(pRingState,"function: ring_vm_start - after loading c functions");
295         /* Generate Items Array &  Hash Table */
296         if ( pRingState->lRunFromThread ) {
297                 ring_list_genarray(pRingState->pRingCFunctions);
298                 ring_list_genhashtable2(pRingState->pRingCFunctions);
299         }
300         else {
301                 ring_list_genarray_gc(pRingState,pRingState->pRingCFunctions);
302                 ring_list_genhashtable2_gc(pRingState,pRingState->pRingCFunctions);
303         }
304         ring_state_log(pRingState,"function: ring_vm_start - after generating hash tables");
305         if ( ring_list_getsize(pVM->pCode) > 0 ) {
306                 pVM->nPC = 1 ;
307                 ring_vm_mainloop(pVM);
308         }
309 }
310
311 void ring_vm_mainloop ( VM *pVM )
312 {
313         pVM->pRingState->lStartPoolManager = 1 ;
314         #if RING_VMSHOWOPCODE
315         /* Preprocessor Allows showing the OPCODE */
316         if ( pVM->pRingState->nPrintInstruction ) {
317                 do {
318                         ring_vm_fetch2(pVM);
319                 } while (pVM->nPC <= ring_list_getsize(pVM->pCode))  ;
320         }
321         else {
322                 do {
323                         ring_vm_fetch(pVM);
324                 } while (pVM->nPC <= ring_list_getsize(pVM->pCode))  ;
325         }
326         #else
327         do {
328                 ring_vm_fetch(pVM);
329         } while (pVM->nPC <= ring_list_getsize(pVM->pCode))  ;
330         #endif
331 }
332
333 void ring_vm_fetch ( VM *pVM )
334 {
335         pVM->pByteCodeIR = pVM->pByteCode + pVM->nPC - 1 ;
336         pVM->nOPCode = RING_VM_IR_OPCODE ;
337         pVM->nPC++ ;
338         ring_vm_execute(pVM);
339         if ( pVM->nSP > RING_VM_STACK_CHECKOVERFLOW ) {
340                 ring_vm_error(pVM,RING_VM_ERROR_STACKOVERFLOW);
341         }
342 }
343
344 void ring_vm_fetch2 ( VM *pVM )
345 {
346         pVM->pByteCodeIR = pVM->pByteCode + pVM->nPC - 1 ;
347         pVM->nOPCode = RING_VM_IR_OPCODE ;
348         #if RING_VMSHOWOPCODE
349         if ( pVM->pRingState->nPrintInstruction ) {
350                 ring_print_line();
351                 printf( "\nVM Pointer  : %p  " , (void *) pVM ) ;
352                 printf( "\nOperation  : %s  " , RING_IC_OP[pVM->nOPCode] ) ;
353                 printf( "\nPC         : %d  " ,pVM->nPC ) ;
354                 printf( "\nLine Number    : %d  , File %s \n " ,pVM->nLineNumber,pVM->cFileName ) ;
355                 if ( (pVM->nOPCode == ICO_PUSHC) || (pVM->nOPCode == ICO_LOADADDRESS) || (pVM->nOPCode == ICO_LOADFUNC) ) {
356                         printf( "\nData       : %s \n",RING_VM_IR_READC ) ;
357                 }
358         }
359         #endif
360         pVM->nPC++ ;
361         ring_vm_execute(pVM);
362         #if RING_VMSHOWOPCODE
363         if ( pVM->pRingState->nPrintInstruction ) {
364                 printf( "\nSP (After) : %d  - FuncSP : %d \n LineNumber %d \n" , (int) pVM->nSP,pVM->nFuncSP,pVM->nLineNumber ) ;
365                 ring_print_line();
366         }
367         #endif
368         if ( pVM->nSP > RING_VM_STACK_CHECKOVERFLOW ) {
369                 ring_vm_error(pVM,RING_VM_ERROR_STACKOVERFLOW);
370         }
371 }
372
373 void ring_vm_execute ( VM *pVM )
374 {
375         switch ( pVM->nOPCode ) {
376                 /* Stack and Variables */
377                 case ICO_PUSHC :
378                         RING_VM_STACK_PUSHC ;
379                         break ;
380                 case ICO_PUSHN :
381                         RING_VM_STACK_PUSHN ;
382                         break ;
383                 case ICO_PUSHV :
384                         ring_vm_pushv(pVM);
385                         break ;
386                 case ICO_LOADADDRESS :
387                         ring_vm_loadaddress(pVM);
388                         break ;
389                 case ICO_ASSIGNMENT :
390                         ring_vm_assignment(pVM);
391                         break ;
392                 case ICO_INC :
393                         ring_vm_inc(pVM);
394                         break ;
395                 case ICO_LOADAPUSHV :
396                         ring_vm_loadapushv(pVM);
397                         break ;
398                 case ICO_NEWLINE :
399                         ring_vm_newline(pVM);
400                         break ;
401                 case ICO_FREESTACK :
402                         ring_vm_freestack(pVM);
403                         break ;
404                 case ICO_FILENAME :
405                         ring_vm_setfilename(pVM);
406                         break ;
407                 case ICO_FREELOADASCOPE :
408                         ring_vm_freeloadaddressscope(pVM);
409                         break ;
410                 /* Jump */
411                 case ICO_JUMP :
412                         ring_vm_jump(pVM);
413                         break ;
414                 case ICO_JUMPZERO :
415                         ring_vm_jumpzero(pVM);
416                         break ;
417                 case ICO_JUMPFOR :
418                         ring_vm_jumpfor(pVM);
419                         break ;
420                 case ICO_JUMPONE :
421                         ring_vm_jumpone(pVM);
422                         break ;
423                 case ICO_JUMPZERO2 :
424                         ring_vm_jumpzero2(pVM);
425                         break ;
426                 case ICO_JUMPONE2 :
427                         ring_vm_jumpone2(pVM);
428                         break ;
429                 /* Compare */
430                 case ICO_LESSEQUAL :
431                         ring_vm_lessequal(pVM);
432                         break ;
433                 case ICO_EQUAL :
434                         ring_vm_equal(pVM);
435                         break ;
436                 case ICO_LESS :
437                         ring_vm_less(pVM);
438                         break ;
439                 case ICO_GREATER :
440                         ring_vm_greater(pVM);
441                         break ;
442                 case ICO_GREATEREQUAL :
443                         ring_vm_greaterequal(pVM);
444                         break ;
445                 case ICO_NOTEQUAL :
446                         ring_vm_notequal(pVM);
447                         break ;
448                 /* Math */
449                 case ICO_SUM :
450                         ring_vm_sum(pVM);
451                         break ;
452                 case ICO_SUB :
453                         ring_vm_sub(pVM);
454                         break ;
455                 case ICO_MUL :
456                         ring_vm_mul(pVM);
457                         break ;
458                 case ICO_DIV :
459                         ring_vm_div(pVM);
460                         break ;
461                 case ICO_MOD :
462                         ring_vm_mod(pVM);
463                         break ;
464                 case ICO_NEG :
465                         ring_vm_neg(pVM);
466                         break ;
467                 case ICO_PLUSPLUS :
468                         ring_vm_plusplus(pVM);
469                         break ;
470                 case ICO_MINUSMINUS :
471                         ring_vm_minusminus(pVM);
472                         break ;
473                 /* Logic */
474                 case ICO_AND :
475                         ring_vm_and(pVM);
476                         break ;
477                 case ICO_OR :
478                         ring_vm_or(pVM);
479                         break ;
480                 case ICO_NOT :
481                         ring_vm_not(pVM);
482                         break ;
483                 /* Lists */
484                 case ICO_LISTSTART :
485                         ring_vm_liststart(pVM);
486                         break ;
487                 case ICO_LISTITEM :
488                         ring_vm_listitem(pVM);
489                         break ;
490                 case ICO_LISTEND :
491                         ring_vm_listend(pVM);
492                         break ;
493                 case ICO_LOADINDEXADDRESS :
494                         ring_vm_loadindexaddress(pVM);
495                         break ;
496                 /* Functions */
497                 case ICO_LOADFUNC :
498                         ring_vm_loadfunc(pVM);
499                         break ;
500                 case ICO_CALL :
501                         ring_vm_call(pVM);
502                         break ;
503                 case ICO_RETURN :
504                         ring_vm_return(pVM);
505                         break ;
506                 case ICO_RETNULL :
507                         ring_vm_returnnull(pVM);
508                         break ;
509                 case ICO_RETFROMEVAL :
510                         ring_vm_returneval(pVM);
511                         break ;
512                 case ICO_RETITEMREF :
513                         ring_vm_retitemref(pVM);
514                         break ;
515                 case ICO_NEWFUNC :
516                         ring_vm_newfunc(pVM);
517                         break ;
518                 case ICO_BLOCKFLAG :
519                         ring_vm_blockflag(pVM);
520                         break ;
521                 case ICO_FUNCEXE :
522                         pVM->nFuncExecute++ ;
523                         break ;
524                 case ICO_ENDFUNCEXE :
525                         ring_vm_endfuncexec(pVM);
526                         break ;
527                 case ICO_ANONYMOUS :
528                         ring_vm_anonymous(pVM);
529                         break ;
530                 /* User Interface */
531                 case ICO_PRINT :
532                         ring_vm_see(pVM);
533                         break ;
534                 case ICO_GIVE :
535                         ring_vm_give(pVM);
536                         break ;
537                 /* End Program - Exit from Loop - Loop (Continue) */
538                 case ICO_BYE :
539                         ring_vm_bye(pVM);
540                         break ;
541                 case ICO_EXITMARK :
542                         ring_vm_exitmark(pVM);
543                         break ;
544                 case ICO_POPEXITMARK :
545                         ring_vm_popexitmark(pVM);
546                         break ;
547                 case ICO_EXIT :
548                         ring_vm_exit(pVM,1);
549                         break ;
550                 case ICO_LOOP :
551                         ring_vm_exit(pVM,2);
552                         break ;
553                 /* For Better Performance */
554                 case ICO_PUSHP :
555                         ring_vm_pushp(pVM);
556                         break ;
557                 case ICO_INCP :
558                         ring_vm_incp(pVM);
559                         break ;
560                 case ICO_PUSHPV :
561                         ring_vm_pushpv(pVM);
562                         break ;
563                 case ICO_INCJUMP :
564                         ring_vm_incjump(pVM);
565                         break ;
566                 case ICO_INCPJUMP :
567                         ring_vm_incpjump(pVM);
568                         break ;
569                 case ICO_JUMPVARLENUM :
570                         ring_vm_jumpvarlenum(pVM);
571                         break ;
572                 case ICO_JUMPVARPLENUM :
573                         ring_vm_jumpvarplenum(pVM);
574                         break ;
575                 case ICO_LOADFUNCP :
576                         ring_vm_loadfuncp(pVM);
577                         break ;
578                 case ICO_PUSHPLOCAL :
579                         ring_vm_pushplocal(pVM);
580                         break ;
581                 case ICO_INCLPJUMP :
582                         ring_vm_inclpjump(pVM);
583                         break ;
584                 case ICO_JUMPVARLPLENUM :
585                         ring_vm_jumpvarlplenum(pVM);
586                         break ;
587                 case ICO_INCPJUMPSTEP1 :
588                         ring_vm_incpjumpstep1(pVM);
589                         break ;
590                 case ICO_JUMPVARPLENUMSTEP1 :
591                         ring_vm_jumpvarplenumstep1(pVM);
592                         break ;
593                 /* Try-Catch-Done */
594                 case ICO_TRY :
595                         ring_vm_try(pVM);
596                         break ;
597                 case ICO_DONE :
598                         ring_vm_done(pVM);
599                         break ;
600                 /* Duplicate and Range */
601                 case ICO_DUPLICATE :
602                         ring_vm_dup(pVM);
603                         break ;
604                 case ICO_RANGE :
605                         ring_vm_range(pVM);
606                         break ;
607                 /* OOP */
608                 case ICO_NEWOBJ :
609                         ring_vm_oop_newobj(pVM);
610                         break ;
611                 case ICO_SETSCOPE :
612                         ring_vm_oop_setscope(pVM);
613                         break ;
614                 case ICO_LOADSUBADDRESS :
615                         ring_vm_oop_property(pVM);
616                         break ;
617                 case ICO_LOADMETHOD :
618                         ring_vm_oop_loadmethod(pVM);
619                         break ;
620                 case ICO_AFTERCALLMETHOD :
621                         ring_vm_oop_aftercallmethod(pVM);
622                         break ;
623                 case ICO_AFTERCALLMETHOD2 :
624                         ring_vm_oop_aftercallmethod(pVM);
625                         break ;
626                 case ICO_NEWCLASS :
627                         ring_vm_oop_newclass(pVM);
628                         break ;
629                 case ICO_BRACESTART :
630                         ring_vm_oop_bracestart(pVM);
631                         break ;
632                 case ICO_BRACEEND :
633                         ring_vm_oop_braceend(pVM);
634                         break ;
635                 case ICO_IMPORT :
636                         ring_vm_oop_import(pVM);
637                         break ;
638                 case ICO_PRIVATE :
639                         pVM->nPrivateFlag = 1 ;
640                         break ;
641                 case ICO_SETPROPERTY :
642                         ring_vm_oop_setproperty(pVM);
643                         break ;
644                 case ICO_CALLCLASSINIT :
645                         ring_vm_callclassinit(pVM);
646                         break ;
647                 /* Other */
648                 case ICO_SETREFERENCE :
649                         ring_vm_setreference(pVM);
650                         break ;
651                 case ICO_KILLREFERENCE :
652                         ring_vm_gc_killreference(pVM);
653                         break ;
654                 case ICO_ASSIGNMENTPOINTER :
655                         ring_vm_assignmentpointer(pVM);
656                         break ;
657                 case ICO_BEFOREEQUAL :
658                         pVM->nBeforeEqual = RING_VM_IR_READI ;
659                         break ;
660                 /* Bitwise Operators */
661                 case ICO_BITAND :
662                         ring_vm_bitand(pVM);
663                         break ;
664                 case ICO_BITOR :
665                         ring_vm_bitor(pVM);
666                         break ;
667                 case ICO_BITXOR :
668                         ring_vm_bitxor(pVM);
669                         break ;
670                 case ICO_BITNOT :
671                         ring_vm_bitnot(pVM);
672                         break ;
673                 case ICO_BITSHL :
674                         ring_vm_bitshl(pVM);
675                         break ;
676                 case ICO_BITSHR :
677                         ring_vm_bitshr(pVM);
678                         break ;
679                 /* For Step */
680                 case ICO_STEPNUMBER :
681                         ring_vm_stepnumber(pVM);
682                         break ;
683                 case ICO_POPSTEP :
684                         ring_vm_popstep(pVM);
685                         break ;
686                 case ICO_LOADAFIRST :
687                         ring_vm_loadaddressfirst(pVM);
688                         break ;
689                 /* Custom Global Scope */
690                 case ICO_NEWGLOBALSCOPE :
691                         ring_vm_newglobalscope(pVM);
692                         break ;
693                 case ICO_ENDGLOBALSCOPE :
694                         ring_vm_endglobalscope(pVM);
695                         break ;
696                 case ICO_SETGLOBALSCOPE :
697                         ring_vm_setglobalscope(pVM);
698                         break ;
699         }
700 }
701
702 RING_API void ring_vm_error ( VM *pVM,const char *cStr )
703 {
704         List *pList  ;
705         /* Check if we have active error */
706         if ( pVM->nActiveError ) {
707                 return ;
708         }
709         pVM->nActiveError = 1 ;
710         /* Check BraceError() */
711         if ( (ring_list_getsize(pVM->pObjState) > 0) && (ring_vm_oop_callmethodinsideclass(pVM) == 0 ) && (pVM->nCallMethod == 0) ) {
712                 if ( ring_vm_findvar(pVM,"self") ) {
713                         pList = ring_vm_oop_getobj(pVM);
714                         RING_VM_STACK_POP ;
715                         if ( ring_vm_oop_isobject(pList) ) {
716                                 if ( ring_vm_oop_ismethod(pVM, pList,"braceerror") ) {
717                                         ring_list_setstring_gc(pVM->pRingState,ring_list_getlist(ring_vm_getglobalscope(pVM),6),3,cStr);
718                                         ring_vm_runcode(pVM,"braceerror()");
719                                         pVM->nActiveError = 0 ;
720                                         return ;
721                                 }
722                         }
723                 }
724         }
725         if ( ring_list_getsize(pVM->pTry) == 0 ) {
726                 if ( pVM->lHideErrorMsg == 0 ) {
727                         ring_vm_showerrormessage(pVM,cStr);
728                 }
729                 /* Trace */
730                 pVM->nActiveError = 0 ;
731                 ring_vm_traceevent(pVM,RING_VM_TRACEEVENT_ERROR);
732                 if ( pVM->lPassError  == 1 ) {
733                         pVM->lPassError = 0 ;
734                         return ;
735                 }
736                 pVM->nActiveError = 1 ;
737                 if ( pVM->pRingState->nRingInsideRing == 0 ) {
738                         exit(0);
739                 }
740                 else {
741                         ring_vm_bye(pVM);
742                         return ;
743                 }
744         }
745         /*
746         **  Check Eval In Scope 
747         **  When we have ringvm_evalinscope() We don't support try/catch 
748         **  We just display the error message and continue 
749         */
750         if ( pVM->nEvalInScope ) {
751                 ring_vm_showerrormessage(pVM,cStr);
752                 pVM->nActiveError = 0 ;
753                 ring_vm_freestack(pVM);
754                 return ;
755         }
756         ring_vm_catch(pVM,cStr);
757         pVM->nActiveError = 0 ;
758 }
759
760 int ring_vm_eval ( VM *pVM,const char *cStr )
761 {
762         int nPC,nCont,nLastPC,nRunVM,x,nSize  ;
763         Scanner *pScanner  ;
764         int aPara[3]  ;
765         ByteCode *pByteCode  ;
766         ring_state_log(pVM->pRingState,"function: ring_vm_eval() start");
767         nSize = strlen( cStr ) ;
768         if ( nSize == 0 ) {
769                 return 0 ;
770         }
771         nPC = pVM->nPC ;
772         /* Add virtual file name */
773         ring_list_addstring_gc(pVM->pRingState,pVM->pRingState->pRingFilesList,"eval");
774         ring_list_addstring_gc(pVM->pRingState,pVM->pRingState->pRingFilesStack,"eval");
775         pScanner = ring_scanner_new(pVM->pRingState);
776         for ( x = 0 ; x < nSize ; x++ ) {
777                 ring_scanner_readchar(pScanner,cStr[x]);
778         }
779         nCont = ring_scanner_checklasttoken(pScanner);
780         /* Add Token "End of Line" to the end of any program */
781         ring_scanner_endofline(pScanner);
782         nLastPC = ring_list_getsize(pVM->pCode);
783         /* Get Functions/Classes Size before change by parser */
784         aPara[0] = nLastPC ;
785         aPara[1] = ring_list_getsize(pVM->pFunctionsMap) ;
786         aPara[2] = ring_list_getsize(pVM->pClassesMap) ;
787         /* Call Parser */
788         if ( nCont == 1 ) {
789                 ring_state_log(pVM->pRingState,cStr);
790                 pVM->pRingState->lNoLineNumber = 1 ;
791                 nRunVM = ring_parser_start(pScanner->Tokens,pVM->pRingState);
792                 pVM->pRingState->lNoLineNumber = 0 ;
793         } else {
794                 ring_vm_error(pVM,"Error in eval!");
795                 ring_scanner_delete(pScanner);
796                 return 0 ;
797         }
798         if ( nRunVM == 1 ) {
799                 /*
800                 **  Generate Code 
801                 **  Generate  Hash Table 
802                 */
803                 if ( pVM->pRingState->lRunFromThread ) {
804                         ring_list_genhashtable2(pVM->pFunctionsMap);
805                 }
806                 else {
807                         ring_list_genhashtable2_gc(pVM->pRingState,pVM->pFunctionsMap);
808                 }
809                 if ( pVM->nEvalCalledFromRingCode ) {
810                         ring_scanner_addreturn3(pVM->pRingState,aPara);
811                 }
812                 else {
813                         ring_scanner_addreturn2(pVM->pRingState);
814                 }
815                 ring_vm_blockflag2(pVM,nPC);
816                 pVM->nPC = nLastPC+1 ;
817                 if ( ring_list_getsize(pVM->pCode)  > pVM->nEvalReallocationSize ) {
818                         pByteCode = (ByteCode *) ring_state_realloc(pVM->pRingState,pVM->pByteCode , sizeof(ByteCode) * ring_list_getsize(pVM->pCode));
819                         if ( pByteCode == NULL ) {
820                                 printf( RING_OOM ) ;
821                                 printf( "RingVM : Can't Allocate Memory for the Byte Code!\n" ) ;
822                                 printf( "(Internal Information) Size of Byte Code : %d \n",ring_list_getsize(pVM->pCode) ) ;
823                                 printf( "(Internal Information) Eval Reallocation Size  : %d \n",pVM->nEvalReallocationSize ) ;
824                                 ring_scanner_delete(pScanner);
825                                 exit(0);
826                         }
827                         pVM->pByteCode = pByteCode ;
828                         if ( pVM->nEvalCalledFromRingCode ) {
829                                 /* Here eval() function is called from .ring files ( not by the VM for setter/getter/operator overloading) */
830                                 pVM->nEvalReallocationFlag = 1 ;
831                         }
832                         /* Update the Eval Reallocation Size after Reallocation */
833                         pVM->nEvalReallocationSize = ring_list_getsize(pVM->pCode) ;
834                 }
835                 else {
836                         pVM->nEvalReallocationFlag = 0 ;
837                 }
838                 /* Load New Code */
839                 for ( x = pVM->nPC ; x <= ring_list_getsize(pVM->pCode) ; x++ ) {
840                         ring_vm_tobytecode(pVM,x);
841                 }
842                 /*
843                 **  The mainloop will be called again 
844                 **  We do this to execute eval instructions directly 
845                 **  This is necessary when we have GUI library that takes the event loop 
846                 **  Then an event uses the eval() function to execute instructions 
847                 **  We don't call the main loop here we call it from ring_vm_call() 
848                 **  We do this to execute the eval() instructions in the correct scope 
849                 **  Because when we call a C Function like eval() we have parameters scope 
850                 **  Before we call the main loop from ring_vm_call the parameters scope will be deleted 
851                 **  And the local scope will be restored so we can use it from eval() 
852                 **  Update ReallocationSize 
853                 */
854                 pVM->nEvalReallocationSize = pVM->nEvalReallocationSize - (ring_list_getsize(pVM->pCode)-nLastPC) ;
855         } else {
856                 ring_vm_error(pVM,"Error in eval!");
857                 ring_scanner_delete(pScanner);
858                 return 0 ;
859         }
860         ring_scanner_delete(pScanner);
861         ring_list_deletelastitem_gc(pVM->pRingState,pVM->pRingState->pRingFilesList);
862         ring_list_deletelastitem_gc(pVM->pRingState,pVM->pRingState->pRingFilesStack);
863         ring_state_log(pVM->pRingState,"function: ring_vm_eval() end");
864         return nRunVM ;
865 }
866
867 void ring_vm_tobytecode ( VM *pVM,int x )
868 {
869         List *pIR  ;
870         int x2  ;
871         ByteCode *pByteCode  ;
872         Item *pItem  ;
873         pByteCode = pVM->pByteCode + x - 1 ;
874         pIR = ring_list_getlist(pVM->pCode,x);
875         pByteCode->nSize = ring_list_getsize(pIR) ;
876         #if RING_SHOWICFINAL
877         pByteCode->pList = pIR ;
878         #endif
879         /* Check Instruction Size */
880         if ( ring_list_getsize(pIR) > RING_VM_BC_ITEMS_COUNT ) {
881                 printf( RING_LONGINSTRUCTION ) ;
882                 printf( "In File : %s  - Byte-Code PC : %d  ",pVM->cFileName,x ) ;
883                 exit(0);
884         }
885         for ( x2 = 1 ; x2 <= ring_list_getsize(pIR) ; x2++ ) {
886                 pItem = ring_list_getitem(pIR,x2) ;
887                 pByteCode->aData[x2-1] = pItem ;
888                 /* Avoid Performance Instuctions (Happens when called from New Thread) */
889                 if ( x2 == 1 ) {
890                         switch ( pItem->data.iNumber ) {
891                                 case ICO_PUSHPLOCAL :
892                                         pItem->data.iNumber = ICO_LOADADDRESS ;
893                                         break ;
894                                 case ICO_JUMPVARLPLENUM :
895                                         pItem->data.iNumber = ICO_JUMPVARLENUM ;
896                                         break ;
897                                 case ICO_INCLPJUMP :
898                                         pItem->data.iNumber = ICO_INCJUMP ;
899                                         break ;
900                         }
901                 }
902         }
903         /* Clear Other Items */
904         for ( x2 = ring_list_getsize(pIR)+1 ; x2 <= RING_VM_BC_ITEMS_COUNT ; x2++ ) {
905                 pByteCode->aData[x2-1] = NULL ;
906         }
907 }
908
909 void ring_vm_returneval ( VM *pVM )
910 {
911         int aPara[3],nExtraSize  ;
912         ByteCode *pByteCode  ;
913         /* This function will always be called after each eval() execution */
914         ring_vm_return(pVM);
915         aPara[0] = RING_VM_IR_READIVALUE(1) ;
916         aPara[1] = RING_VM_IR_READIVALUE(2) ;
917         aPara[2] = RING_VM_IR_READIVALUE(3) ;
918         if ( ( pVM->nRetEvalDontDelete == 0 ) && (aPara[1] == ring_list_getsize(pVM->pFunctionsMap)) && (aPara[2] == ring_list_getsize(pVM->pClassesMap)) ) {
919                 /*
920                 **  The code interpreted by eval doesn't add new functions or new classes 
921                 **  This means that the code can be deleted without any problems 
922                 **  We do that to avoid memory leaks 
923                 */
924                 nExtraSize = ring_list_getsize(pVM->pCode) - aPara[0] ;
925                 while ( ring_list_getsize(pVM->pCode) != aPara[0] ) {
926                         ring_list_deletelastitem_gc(pVM->pRingState,pVM->pCode);
927                 }
928                 if ( pVM->nEvalReallocationFlag == 1 ) {
929                         pVM->nEvalReallocationFlag = 0 ;
930                         pByteCode = (ByteCode *) ring_state_realloc(pVM->pRingState,pVM->pByteCode , sizeof(ByteCode) * ring_list_getsize(pVM->pCode));
931                         if ( pByteCode == NULL ) {
932                                 printf( RING_OOM ) ;
933                                 exit(0);
934                         }
935                         pVM->pByteCode = pByteCode ;
936                         /* Update the Eval Reallocation Size after Reallocation */
937                         pVM->nEvalReallocationSize = pVM->nEvalReallocationSize - nExtraSize ;
938                 }
939                 else {
940                         pVM->nEvalReallocationSize = pVM->nEvalReallocationSize + nExtraSize ;
941                 }
942         }
943         /*
944         **  nEvalReturnPC is checked by the ring_vm_mainloop to end the loop 
945         **  if the pVM->nPC becomes <= pVM->nEvalReturnPC the loop will be terminated 
946         **  Remember that this is just a sub loop (another main loop) created after using eval() 
947         **  If we don't terminate the sub main loop , this is just an extra overhead 
948         **  Also terminating the sub main loop is a must when we do GUI programming 
949         **  Because in GUI programming, the main loop calls the GUI Main Loop 
950         **  During GUI main loop when event happens that calls a ring code 
951         **  Eval will be used and a sub main loop will be executed 
952         **  If we don't terminate the sub main loop, we can't return to the GUI Main Loop 
953         **  It's necessary to return to the GUI main loop 
954         **  When the GUI Main Loop Ends, we return to the Ring Main Loop 
955         */
956         pVM->nEvalReturnPC = aPara[0] ;
957 }
958
959 void ring_vm_error2 ( VM *pVM,const char *cStr,const char *cStr2 )
960 {
961         String *pError  ;
962         pError = ring_string_new_gc(pVM->pRingState,cStr);
963         ring_string_add_gc(pVM->pRingState,pError,": ");
964         ring_string_add_gc(pVM->pRingState,pError,cStr2);
965         ring_vm_error(pVM,ring_string_get(pError));
966         ring_string_delete_gc(pVM->pRingState,pError);
967 }
968
969 void ring_vm_newbytecodeitem ( VM *pVM,int x )
970 {
971         Item *pItem  ;
972         ring_list_addint_gc(pVM->pRingState,pVM->aNewByteCodeItems,0);
973         pItem = ring_list_getitem(pVM->aNewByteCodeItems,ring_list_getsize(pVM->aNewByteCodeItems));
974         RING_VM_IR_ITEM(x) = pItem ;
975 }
976
977 RING_API void ring_vm_runcode ( VM *pVM,const char *cStr )
978 {
979         int nEvalReturnPC,nEvalReallocationFlag,nPC,nRunVM,nSP,nFuncSP,nLineNumber  ;
980         List *pStackList  ;
981         /* Save state to take in mind nested events execution */
982         pVM->nRunCode++ ;
983         nEvalReturnPC = pVM->nEvalReturnPC ;
984         nEvalReallocationFlag = pVM->nEvalReallocationFlag ;
985         nPC = pVM->nPC ;
986         nSP = pVM->nSP ;
987         nFuncSP = pVM->nFuncSP ;
988         pStackList = ring_vm_savestack(pVM);
989         nLineNumber = pVM->nLineNumber ;
990         ring_vm_mutexlock(pVM);
991         pVM->nEvalCalledFromRingCode = 1 ;
992         /* Take in mind nested events */
993         if ( pVM->nRunCode != 1 ) {
994                 pVM->nRetEvalDontDelete = 1 ;
995         }
996         nRunVM = ring_vm_eval(pVM,cStr);
997         pVM->nEvalCalledFromRingCode = 0 ;
998         ring_vm_mutexunlock(pVM);
999         if ( nRunVM ) {
1000                 pVM->nFuncExecute = 0 ;
1001                 pVM->nFuncExecute2 = 0 ;
1002                 ring_vm_mainloopforeval(pVM);
1003         }
1004         /* Restore state to take in mind nested events execution */
1005         pVM->nRunCode-- ;
1006         pVM->nEvalReturnPC = nEvalReturnPC ;
1007         pVM->nEvalReallocationFlag = nEvalReallocationFlag ;
1008         pVM->nPC = nPC ;
1009         if ( pVM->nRunCode != 0 ) {
1010                 /* It's a nested event (Here we don't care about the output and we can restore the stack) */
1011                 ring_vm_restorestack(pVM,pStackList);
1012         }
1013         /* Here we free the list because, restorestack() don't free it */
1014         ring_list_delete_gc(pVM->pRingState,pStackList);
1015         /* Restore Stack to avoid Stack Overflow */
1016         pVM->nSP = nSP ;
1017         pVM->nFuncSP = nFuncSP ;
1018         pVM->nLineNumber = nLineNumber ;
1019 }
1020
1021 void ring_vm_init ( RingState *pRingState )
1022 {
1023         Scanner *pScanner  ;
1024         VM *pVM  ;
1025         int nRunVM,nFreeFilesList = 0 ;
1026         /* Check file */
1027         if ( pRingState->pRingFilesList == NULL ) {
1028                 pRingState->pRingFilesList = ring_list_new_gc(pRingState,0);
1029                 pRingState->pRingFilesStack = ring_list_new_gc(pRingState,0);
1030                 nFreeFilesList = 1 ;
1031         }
1032         ring_list_addstring_gc(pRingState,pRingState->pRingFilesList,"Ring_EmbeddedCode");
1033         ring_list_addstring_gc(pRingState,pRingState->pRingFilesStack,"Ring_EmbeddedCode");
1034         /* Read File */
1035         pScanner = ring_scanner_new(pRingState);
1036         /* Add Token "End of Line" to the end of any program */
1037         ring_scanner_endofline(pScanner);
1038         /* Call Parser */
1039         nRunVM = ring_parser_start(pScanner->Tokens,pRingState);
1040         ring_scanner_delete(pScanner);
1041         /* Files List */
1042         ring_list_deleteitem_gc(pRingState,pRingState->pRingFilesStack,ring_list_getsize(pRingState->pRingFilesStack));
1043         if ( nFreeFilesList ) {
1044                 /* Run the Program */
1045                 if ( nRunVM == 1 ) {
1046                         /* Add return to the end of the program */
1047                         ring_scanner_addreturn(pRingState);
1048                         pVM = ring_vm_new(pRingState);
1049                         ring_vm_start(pRingState,pVM);
1050                         pRingState->pVM = pVM ;
1051                 }
1052         }
1053         return ;
1054 }
1055
1056 void ring_vm_retitemref ( VM *pVM )
1057 {
1058         List *pList  ;
1059         pVM->nRetItemRef++ ;
1060         /* We free the stack to avoid effects on aLoadAddressScope which is used by isstackpointertoobjstate */
1061         ring_vm_freestack(pVM);
1062         /*
1063         **  Check if we are in the operator method to increment the counter again 
1064         **  We do this to avoid another PUSHV on the list item 
1065         **  The first one after return expression in the operator method 
1066         **  The second one before return from eval() that is used by operator overloading 
1067         **  This to avoid using & two times like  &  & 
1068         */
1069         if ( ring_list_getsize(pVM->pFuncCallList) > 0 ) {
1070                 pList = ring_list_getlist(pVM->pFuncCallList,ring_list_getsize(pVM->pFuncCallList));
1071                 if ( strcmp(ring_list_getstring(pList,RING_FUNCCL_NAME),"operator") == 0 ) {
1072                         pVM->nRetItemRef++ ;
1073                 }
1074         }
1075 }
1076
1077 void ring_vm_printstack ( VM *pVM )
1078 {
1079         int x,nSP  ;
1080         printf( "\n*****************************************\n" ) ;
1081         printf( "Stack Size %u \n",pVM->nSP ) ;
1082         nSP = pVM->nSP ;
1083         if ( nSP > 0 ) {
1084                 for ( x = 1 ; x <= nSP ; x++ ) {
1085                         /* Print Values */
1086                         if ( RING_VM_STACK_ISSTRING ) {
1087                                 printf( "(String) : %s  \n",RING_VM_STACK_READC ) ;
1088                         }
1089                         else if ( RING_VM_STACK_ISNUMBER ) {
1090                                 printf( "(Number) : %f  \n",RING_VM_STACK_READN ) ;
1091                         }
1092                         else if ( RING_VM_STACK_ISPOINTER ) {
1093                                 printf( "(Pointer) : %p  \n",RING_VM_STACK_READP ) ;
1094                                 if ( RING_VM_STACK_OBJTYPE == RING_OBJTYPE_VARIABLE ) {
1095                                         printf( "(Pointer Type) : Variable \n" ) ;
1096                                         ring_list_print((List *) RING_VM_STACK_READP);
1097                                 }
1098                                 else if ( RING_VM_STACK_OBJTYPE ==RING_OBJTYPE_LISTITEM ) {
1099                                         printf( "(Pointer Type) : ListItem \n" ) ;
1100                                         ring_item_print((Item *) RING_VM_STACK_READP);
1101                                 }
1102                         }
1103                         RING_VM_STACK_POP ;
1104                         printf( "\n*****************************************\n" ) ;
1105                 }
1106         }
1107 }
1108
1109 void ring_vm_callclassinit ( VM *pVM )
1110 {
1111         if ( RING_VM_IR_READIVALUE(1) ) {
1112                 pVM->nCallClassInit++ ;
1113         }
1114         else {
1115                 pVM->nCallClassInit-- ;
1116         }
1117 }
1118
1119 RING_API void ring_vm_showerrormessage ( VM *pVM,const char *cStr )
1120 {
1121         int x,lFunctionCall  ;
1122         List *pList  ;
1123         const char *cFile  ;
1124         const char *cOldFile  ;
1125         /* CGI Support */
1126         ring_state_cgiheader(pVM->pRingState);
1127         /* Print the Error Message */
1128         printf( "\nLine %d %s \n",pVM->nLineNumber,cStr ) ;
1129         /* Print Calling Information */
1130         cOldFile = NULL ;
1131         lFunctionCall = 0 ;
1132         for ( x = ring_list_getsize(pVM->pFuncCallList) ; x >= 1 ; x-- ) {
1133                 pList = ring_list_getlist(pVM->pFuncCallList,x);
1134                 /*
1135                 **  If we have ICO_LoadFunc but not ICO_CALL then we need to pass 
1136                 **  ICO_LOADFUNC is executed, but still ICO_CALL is not executed! 
1137                 */
1138                 if ( ring_list_getsize(pList) < RING_FUNCCL_CALLERPC ) {
1139                         cOldFile = (const char *) ring_list_getpointer(pList,RING_FUNCCL_FILENAME) ;
1140                         continue ;
1141                 }
1142                 if ( ring_list_getint(pList,RING_FUNCCL_TYPE) == RING_FUNCTYPE_SCRIPT ) {
1143                         /*
1144                         **  Prepare Message 
1145                         **  In 
1146                         */
1147                         printf( "In " ) ;
1148                         /* Method or Function */
1149                         if ( ring_list_getint(pList,RING_FUNCCL_METHODORFUNC) ) {
1150                                 printf( "method " ) ;
1151                         }
1152                         else {
1153                                 printf( "function " ) ;
1154                         }
1155                         /* Function Name */
1156                         printf( "%s",ring_list_getstring(pList,RING_FUNCCL_NAME) ) ;
1157                         /* Adding () */
1158                         printf( "() in file " ) ;
1159                         /* File Name */
1160                         if ( lFunctionCall == 1 ) {
1161                                 cFile = (const char *) ring_list_getpointer(pList,RING_FUNCCL_NEWFILENAME) ;
1162                         }
1163                         else {
1164                                 if ( pVM->nInClassRegion ) {
1165                                         cFile = pVM->cFileNameInClassRegion ;
1166                                 }
1167                                 else {
1168                                         cFile = pVM->cFileName ;
1169                                 }
1170                         }
1171                         printf( "%s",cFile ) ;
1172                         /* Called From */
1173                         printf( "\ncalled from line %d  ",ring_list_getint(pList,RING_FUNCCL_LINENUMBER) ) ;
1174                 }
1175                 else {
1176                         printf( "In %s() ",ring_list_getstring(pList,RING_FUNCCL_NAME) ) ;
1177                 }
1178                 lFunctionCall = 1 ;
1179         }
1180         if ( lFunctionCall ) {
1181                 printf( "in file %s ",ring_list_getstring(pVM->pRingState->pRingFilesList,1) ) ;
1182         }
1183         else {
1184                 if ( pVM->nInClassRegion ) {
1185                         cFile = pVM->cFileNameInClassRegion ;
1186                 }
1187                 else {
1188                         if ( cOldFile == NULL ) {
1189                                 cFile = pVM->cFileName ;
1190                         }
1191                         else {
1192                                 cFile = cOldFile ;
1193                         }
1194                 }
1195                 printf( "in file %s ",cFile ) ;
1196         }
1197         fflush(stdout);
1198 }
1199
1200 void ring_vm_setfilename ( VM *pVM )
1201 {
1202         if ( pVM->nInClassRegion ) {
1203                 /*
1204                 **  We are using special attribute for this region to avoid save/restore file name 
1205                 **  If we used pVM->cFileName we could get problem in finding classes and packages 
1206                 */
1207                 pVM->cFileNameInClassRegion = RING_VM_IR_READC ;
1208                 return ;
1209         }
1210         pVM->cPrevFileName = pVM->cFileName ;
1211         pVM->cFileName = RING_VM_IR_READC ;
1212 }
1213
1214 void ring_vm_loadaddressfirst ( VM *pVM )
1215 {
1216         pVM->nFirstAddress = 1 ;
1217         ring_vm_loadaddress(pVM);
1218         pVM->nFirstAddress = 0 ;
1219 }
1220
1221 void ring_vm_endfuncexec ( VM *pVM )
1222 {
1223         if ( pVM->nFuncExecute > 0 ) {
1224                 pVM->nFuncExecute-- ;
1225         }
1226 }
1227
1228 void ring_vm_addglobalvariables ( VM *pVM )
1229 {
1230         List *pList  ;
1231         int x  ;
1232         ring_state_log(pVM->pRingState,"function: ring_vm_addglobalvariables() start");
1233         /*
1234         **  Add Variables 
1235         **  We write variable name in lower case because Identifiers is converted to lower by Compiler(Scanner) 
1236         */
1237         ring_vm_addnewnumbervar(pVM,"true",1);
1238         ring_vm_addnewnumbervar(pVM,"false",0);
1239         ring_state_log(pVM->pRingState,"function: ring_vm_addglobalvariables() after logical variables");
1240         ring_vm_addnewstringvar(pVM,"nl","\n");
1241         ring_vm_addnewstringvar(pVM,"null","");
1242         ring_state_log(pVM->pRingState,"function: ring_vm_addglobalvariables() after nl and null");
1243         ring_vm_addnewpointervar(pVM,"ring_gettemp_var",NULL,0);
1244         ring_vm_addnewstringvar(pVM,"ccatcherror","NULL");
1245         ring_vm_addnewpointervar(pVM,"ring_settemp_var",NULL,0);
1246         ring_vm_addnewnumbervar(pVM,"ring_tempflag_var",0);
1247         ring_state_log(pVM->pRingState,"function: ring_vm_addglobalvariables() before standard files");
1248         ring_vm_addnewcpointervar(pVM,"stdin",stdin,"file");
1249         ring_vm_addnewcpointervar(pVM,"stdout",stdout,"file");
1250         ring_vm_addnewcpointervar(pVM,"stderr",stderr,"file");
1251         ring_state_log(pVM->pRingState,"function: ring_vm_addglobalvariables() after standard files");
1252         ring_vm_addnewpointervar(pVM,"this",NULL,0);
1253         ring_vm_addnewstringvar(pVM,"tab","\t");
1254         ring_vm_addnewstringvar(pVM,"cr","\r");
1255         ring_state_log(pVM->pRingState,"function: ring_vm_addglobalvariables() after adding variables");
1256         /* Add Command Line Parameters */
1257         pList = ring_vm_newvar2(pVM,"sysargv",pVM->pActiveMem);
1258         ring_list_setint_gc(pVM->pRingState,pList,RING_VAR_TYPE,RING_VM_LIST);
1259         ring_list_setlist_gc(pVM->pRingState,pList,RING_VAR_VALUE);
1260         pList = ring_list_getlist(pList,RING_VAR_VALUE);
1261         ring_state_log(pVM->pRingState,"function: ring_vm_addglobalvariables() before adding arguments");
1262         for ( x = 0 ; x < pVM->pRingState->argc ; x++ ) {
1263                 ring_list_addstring_gc(pVM->pRingState,pList,pVM->pRingState->argv[x]);
1264         }
1265         ring_state_log(pVM->pRingState,"function: ring_vm_addglobalvariables() after adding arguments");
1266         ring_state_log(pVM->pRingState,"function: ring_vm_addglobalvariables() end");
1267 }
1268
1269 void ring_vm_mainloopforeval ( VM *pVM )
1270 {
1271         int nDontDelete  ;
1272         pVM->pRingState->lStartPoolManager = 1 ;
1273         pVM->lInsideEval++ ;
1274         nDontDelete = pVM->nRetEvalDontDelete ;
1275         pVM->nRetEvalDontDelete = 0 ;
1276         #if RING_VMSHOWOPCODE
1277         /* Preprocessor Allows showing the OPCODE */
1278         if ( pVM->pRingState->nPrintInstruction ) {
1279                 do {
1280                         ring_vm_fetch2(pVM);
1281                         if ( pVM->nPC <= pVM->nEvalReturnPC ) {
1282                                 pVM->nEvalReturnPC = 0 ;
1283                                 break ;
1284                         }
1285                 } while (pVM->nPC <= ring_list_getsize(pVM->pCode))  ;
1286         }
1287         else {
1288                 do {
1289                         ring_vm_fetch(pVM);
1290                         if ( pVM->nPC <= pVM->nEvalReturnPC ) {
1291                                 pVM->nEvalReturnPC = 0 ;
1292                                 break ;
1293                         }
1294                 } while (pVM->nPC <= ring_list_getsize(pVM->pCode))  ;
1295         }
1296         #else
1297         do {
1298                 ring_vm_fetch(pVM);
1299                 if ( pVM->nPC <= pVM->nEvalReturnPC ) {
1300                         pVM->nEvalReturnPC = 0 ;
1301                         break ;
1302                 }
1303         } while (pVM->nPC <= ring_list_getsize(pVM->pCode))  ;
1304         #endif
1305         pVM->lInsideEval-- ;
1306         pVM->nRetEvalDontDelete = nDontDelete ;
1307 }
1308 /* Threads */
1309
1310 RING_API void ring_vm_mutexfunctions ( VM *pVM,void *(*pFunc)(void),void (*pFuncLock)(void *),void (*pFuncUnlock)(void *),void (*pFuncDestroy)(void *) )
1311 {
1312         if ( pVM->pMutex == NULL ) {
1313                 pVM->pMutex = pFunc() ;
1314                 pVM->pFuncMutexLock = pFuncLock ;
1315                 pVM->pFuncMutexUnlock = pFuncUnlock ;
1316                 pVM->pFuncMutexDestroy = pFuncDestroy ;
1317         }
1318 }
1319
1320 RING_API void ring_vm_mutexlock ( VM *pVM )
1321 {
1322         if ( pVM->pMutex != NULL ) {
1323                 pVM->pFuncMutexLock(pVM->pMutex);
1324         }
1325 }
1326
1327 RING_API void ring_vm_mutexunlock ( VM *pVM )
1328 {
1329         if ( pVM->pMutex != NULL ) {
1330                 pVM->pFuncMutexUnlock(pVM->pMutex);
1331         }
1332 }
1333
1334 RING_API void ring_vm_mutexdestroy ( VM *pVM )
1335 {
1336         if ( pVM->pMutex != NULL ) {
1337                 pVM->pFuncMutexDestroy(pVM->pMutex);
1338                 pVM->pMutex = NULL ;
1339         }
1340 }
1341
1342 RING_API void ring_vm_runcodefromthread ( VM *pVM,const char *cStr )
1343 {
1344         RingState *pState  ;
1345         List *pList,*pList2,*pList3,*pList4,*pList5  ;
1346         Item *pItem  ;
1347         /* Create the RingState */
1348         pState = ring_state_init();
1349         /*
1350         **  Flag that we are running from thread 
1351         **  We check this flag when generating hash tables of lists (for functions or scope) 
1352         **  In this case we generate the hash table without the memory pool 
1353         **  Because the memory of the current memory pool of this state will be deleted when deleteing the state 
1354         **  And the lists of the hash table will be needed to be used by the main VM 
1355         */
1356         pState->lRunFromThread = 1 ;
1357         pState->nPrintInstruction = pVM->pRingState->nPrintInstruction ;
1358         /* Share the same Mutex between VMs */
1359         ring_vm_mutexlock(pVM);
1360         pState->pVM->pMutex = pVM->pMutex ;
1361         pState->pVM->pFuncMutexDestroy = pVM->pFuncMutexDestroy ;
1362         pState->pVM->pFuncMutexLock = pVM->pFuncMutexLock ;
1363         pState->pVM->pFuncMutexUnlock = pVM->pFuncMutexUnlock ;
1364         /* Share the global scope between threads */
1365         pItem = pState->pVM->pMem->pFirst->pValue ;
1366         pState->pVM->pMem->pFirst->pValue = pVM->pMem->pFirst->pValue ;
1367         /* Save the state */
1368         pList = pState->pVM->pCode ;
1369         pList2 = pState->pVM->pFunctionsMap ;
1370         pList3 = pState->pVM->pClassesMap ;
1371         pList4 = pState->pVM->pPackagesMap ;
1372         pList5 = pState->pVM->pCFunctionsList ;
1373         /* Share the code between the VMs */
1374         pState->pVM->pFunctionsMap = pVM->pRingState->pRingFunctionsMap ;
1375         pState->pVM->pClassesMap = pVM->pRingState->pRingClassesMap ;
1376         pState->pVM->pPackagesMap = pVM->pRingState->pRingPackagesMap ;
1377         pState->pVM->pCFunctionsList = pVM->pCFunctionsList ;
1378         pState->pRingFunctionsMap = pVM->pRingState->pRingFunctionsMap ;
1379         pState->pRingClassesMap = pVM->pRingState->pRingClassesMap ;
1380         pState->pRingPackagesMap = pVM->pRingState->pRingPackagesMap ;
1381         pState->pRingCFunctions = pVM->pRingState->pRingCFunctions ;
1382         /* Get a copy from the byte code List */
1383         pState->pVM->nScopeID = pVM->nScopeID + 10000 ;
1384         pState->pVM->pCode = ring_list_new_gc(pState,0) ;
1385         ring_list_copy_gc(pState,pState->pVM->pCode,pVM->pRingState->pRingGenCode);
1386         pState->pRingGenCode = pState->pVM->pCode ;
1387         ring_vm_loadcode(pState->pVM);
1388         /* Avoid the call to the main function */
1389         pState->pVM->nCallMainFunction = 1 ;
1390         ring_vm_mutexunlock(pVM);
1391         /* Run the code */
1392         ring_state_runcode(pState,cStr);
1393         ring_list_delete_gc(pState,pState->pVM->pCode);
1394         /* Restore the first scope - global scope */
1395         pState->pVM->pMem->pFirst->pValue = pItem ;
1396         /* Avoid deleteing the shared code and the Mutex */
1397         pState->pVM->pCode = pList ;
1398         pState->pVM->pFunctionsMap = pList2 ;
1399         pState->pVM->pClassesMap = pList3 ;
1400         pState->pVM->pPackagesMap = pList4 ;
1401         pState->pVM->pCFunctionsList = pList5 ;
1402         pState->pRingGenCode = pList ;
1403         pState->pRingFunctionsMap = pList2 ;
1404         pState->pRingClassesMap = pList3 ;
1405         pState->pRingPackagesMap = pList4 ;
1406         pState->pRingCFunctions = pList5 ;
1407         pState->pVM->pMutex = NULL ;
1408         pState->pVM->pFuncMutexDestroy = NULL ;
1409         pState->pVM->pFuncMutexLock = NULL ;
1410         pState->pVM->pFuncMutexUnlock = NULL ;
1411         /* Delete the RingState */
1412         ring_state_delete(pState);
1413 }
1414 /* Fast Function Call for Extensions (Without Eval) */
1415
1416 RING_API void ring_vm_callfunction ( VM *pVM,char *cFuncName )
1417 {
1418         /* Lower Case and pass () in the end */
1419         ring_string_lower(cFuncName);
1420         /* Prepare (Remove effects of the current function) */
1421         ring_list_deletelastitem_gc(pVM->pRingState,pVM->pFuncCallList);
1422         /* Load the function and call it */
1423         ring_vm_loadfunc2(pVM,cFuncName,0);
1424         ring_vm_call2(pVM);
1425         /* Execute the function */
1426         ring_vm_mainloopforeval(pVM);
1427         /* Free Stack */
1428         ring_vm_freestack(pVM);
1429         /* Avoid normal steps after this function, because we deleted the scope in Prepare */
1430         pVM->nActiveCatch = 1 ;
1431 }
1432 /* Trace */
1433
1434 void ring_vm_traceevent ( VM *pVM,char nEvent )
1435 {
1436         List *pList  ;
1437         if ( (pVM->lTrace == 1) && (pVM->lTraceActive == 0) ) {
1438                 pVM->lTraceActive = 1 ;
1439                 pVM->nTraceEvent = nEvent ;
1440                 /* Prepare Trace Data */
1441                 ring_list_deleteallitems_gc(pVM->pRingState,pVM->pTraceData);
1442                 /* Add Line Number */
1443                 ring_list_adddouble_gc(pVM->pRingState,pVM->pTraceData,pVM->nLineNumber);
1444                 /* Add File Name */
1445                 ring_list_addstring_gc(pVM->pRingState,pVM->pTraceData,pVM->cFileName);
1446                 /* Add Function/Method Name */
1447                 if ( ring_list_getsize(pVM->pFuncCallList) > 0 ) {
1448                         pList = ring_list_getlist(pVM->pFuncCallList,ring_list_getsize(pVM->pFuncCallList)) ;
1449                         ring_list_addstring_gc(pVM->pRingState,pVM->pTraceData,ring_list_getstring(pList,RING_FUNCCL_NAME));
1450                         /* Method of Function */
1451                         ring_list_adddouble_gc(pVM->pRingState,pVM->pTraceData,ring_list_getint(pList,RING_FUNCCL_METHODORFUNC));
1452                 }
1453                 else {
1454                         ring_list_addstring_gc(pVM->pRingState,pVM->pTraceData,"");
1455                         /* Method of Function */
1456                         ring_list_adddouble_gc(pVM->pRingState,pVM->pTraceData,0);
1457                 }
1458                 /* Execute Trace Function */
1459                 ring_vm_runcode(pVM,ring_string_get(pVM->pTrace));
1460                 pVM->lTraceActive = 0 ;
1461                 pVM->nTraceEvent = 0 ;
1462         }
1463 }