1 /* Copyright (c) 2013-2019 Mahmoud Fayed <msfclipper@yahoo.com> */
8 VM * ring_vm_new ( RingState *pRingState )
12 ring_state_log(pRingState,"function: ring_vm_new - start");
13 pVM = (VM *) ring_state_malloc(pRingState,sizeof(VM));
19 pVM->pRingState = pRingState ;
20 pRingState->pVM = pVM ;
21 ring_state_log(pRingState,"function: ring_vm_new - after malloc()");
24 pVM->pFunctionsMap = NULL ;
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 */
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 ;
42 ** Flag ( 0 = check NULL variable in PUSHV , greater than 0 = Ignore null variable )
43 ** Class Region (After the Class Name)
45 pVM->nInClassRegion = 0 ;
46 ring_state_log(pRingState,"function: ring_vm_new - after class region flag");
48 ring_vm_addglobalvariables(pVM);
49 ring_state_log(pRingState,"function: ring_vm_new - after global variables");
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 */
56 pVM->aPCBlockFlag = ring_list_new_gc(pVM->pRingState,0);
57 /* Calling Functions */
58 pVM->pFuncCallList = ring_list_new_gc(pVM->pRingState,0);
60 pVM->nFuncExecute = 0 ;
61 if ( pRingState->pRingCFunctions == NULL ) {
62 pRingState->pRingCFunctions = ring_list_new_gc(pVM->pRingState,0);
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");
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 ;
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
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 */
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)
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 ;
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
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 ;
155 /* Ignore C Pointer Type Check in extension functions */
156 pVM->nIgnoreCPointerTypeCheck = 0 ;
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!
164 pVM->nCallClassInit = 0 ;
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
171 pVM->nRetEvalDontDelete = 0 ;
172 /* Counter to know if we are inside ring_vm_runcode() */
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,"");
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)
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");
215 VM * ring_vm_delete ( VM *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);
241 for ( x = 0 ; x < RING_VM_STACK_SIZE ; x++ ) {
242 ring_item_content_delete(&(pVM->aStack[x]));
244 ring_state_free(pVM->pRingState,pVM->pByteCode);
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 */
255 ring_vm_dll_closealllibs(pVM);
257 pVM->pCLibraries = ring_list_delete_gc(pVM->pRingState,pVM->pCLibraries);
258 pVM->pRingState->pVM = NULL ;
259 ring_state_free(pVM->pRingState,pVM);
264 RING_API void ring_vm_loadcode ( VM *pVM )
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()
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 ) {
278 for ( x = 1 ; x <= ring_list_getsize(pVM->pCode) ; x++ ) {
279 ring_vm_tobytecode(pVM,x);
281 pVM->nEvalReallocationSize = nSize ;
284 void ring_vm_start ( RingState *pRingState,VM *pVM )
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);
301 ring_list_genarray_gc(pRingState,pRingState->pRingCFunctions);
302 ring_list_genhashtable2_gc(pRingState,pRingState->pRingCFunctions);
304 ring_state_log(pRingState,"function: ring_vm_start - after generating hash tables");
305 if ( ring_list_getsize(pVM->pCode) > 0 ) {
307 ring_vm_mainloop(pVM);
311 void ring_vm_mainloop ( VM *pVM )
313 pVM->pRingState->lStartPoolManager = 1 ;
314 #if RING_VMSHOWOPCODE
315 /* Preprocessor Allows showing the OPCODE */
316 if ( pVM->pRingState->nPrintInstruction ) {
319 } while (pVM->nPC <= ring_list_getsize(pVM->pCode)) ;
324 } while (pVM->nPC <= ring_list_getsize(pVM->pCode)) ;
329 } while (pVM->nPC <= ring_list_getsize(pVM->pCode)) ;
333 void ring_vm_fetch ( VM *pVM )
335 pVM->pByteCodeIR = pVM->pByteCode + pVM->nPC - 1 ;
336 pVM->nOPCode = RING_VM_IR_OPCODE ;
338 ring_vm_execute(pVM);
339 if ( pVM->nSP > RING_VM_STACK_CHECKOVERFLOW ) {
340 ring_vm_error(pVM,RING_VM_ERROR_STACKOVERFLOW);
344 void ring_vm_fetch2 ( VM *pVM )
346 pVM->pByteCodeIR = pVM->pByteCode + pVM->nPC - 1 ;
347 pVM->nOPCode = RING_VM_IR_OPCODE ;
348 #if RING_VMSHOWOPCODE
349 if ( pVM->pRingState->nPrintInstruction ) {
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 ) ;
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 ) ;
368 if ( pVM->nSP > RING_VM_STACK_CHECKOVERFLOW ) {
369 ring_vm_error(pVM,RING_VM_ERROR_STACKOVERFLOW);
373 void ring_vm_execute ( VM *pVM )
375 switch ( pVM->nOPCode ) {
376 /* Stack and Variables */
378 RING_VM_STACK_PUSHC ;
381 RING_VM_STACK_PUSHN ;
386 case ICO_LOADADDRESS :
387 ring_vm_loadaddress(pVM);
389 case ICO_ASSIGNMENT :
390 ring_vm_assignment(pVM);
395 case ICO_LOADAPUSHV :
396 ring_vm_loadapushv(pVM);
399 ring_vm_newline(pVM);
402 ring_vm_freestack(pVM);
405 ring_vm_setfilename(pVM);
407 case ICO_FREELOADASCOPE :
408 ring_vm_freeloadaddressscope(pVM);
415 ring_vm_jumpzero(pVM);
418 ring_vm_jumpfor(pVM);
421 ring_vm_jumpone(pVM);
424 ring_vm_jumpzero2(pVM);
427 ring_vm_jumpone2(pVM);
431 ring_vm_lessequal(pVM);
440 ring_vm_greater(pVM);
442 case ICO_GREATEREQUAL :
443 ring_vm_greaterequal(pVM);
446 ring_vm_notequal(pVM);
468 ring_vm_plusplus(pVM);
470 case ICO_MINUSMINUS :
471 ring_vm_minusminus(pVM);
485 ring_vm_liststart(pVM);
488 ring_vm_listitem(pVM);
491 ring_vm_listend(pVM);
493 case ICO_LOADINDEXADDRESS :
494 ring_vm_loadindexaddress(pVM);
498 ring_vm_loadfunc(pVM);
507 ring_vm_returnnull(pVM);
509 case ICO_RETFROMEVAL :
510 ring_vm_returneval(pVM);
512 case ICO_RETITEMREF :
513 ring_vm_retitemref(pVM);
516 ring_vm_newfunc(pVM);
519 ring_vm_blockflag(pVM);
522 pVM->nFuncExecute++ ;
524 case ICO_ENDFUNCEXE :
525 ring_vm_endfuncexec(pVM);
528 ring_vm_anonymous(pVM);
537 /* End Program - Exit from Loop - Loop (Continue) */
542 ring_vm_exitmark(pVM);
544 case ICO_POPEXITMARK :
545 ring_vm_popexitmark(pVM);
553 /* For Better Performance */
564 ring_vm_incjump(pVM);
567 ring_vm_incpjump(pVM);
569 case ICO_JUMPVARLENUM :
570 ring_vm_jumpvarlenum(pVM);
572 case ICO_JUMPVARPLENUM :
573 ring_vm_jumpvarplenum(pVM);
576 ring_vm_loadfuncp(pVM);
578 case ICO_PUSHPLOCAL :
579 ring_vm_pushplocal(pVM);
582 ring_vm_inclpjump(pVM);
584 case ICO_JUMPVARLPLENUM :
585 ring_vm_jumpvarlplenum(pVM);
587 case ICO_INCPJUMPSTEP1 :
588 ring_vm_incpjumpstep1(pVM);
590 case ICO_JUMPVARPLENUMSTEP1 :
591 ring_vm_jumpvarplenumstep1(pVM);
600 /* Duplicate and Range */
609 ring_vm_oop_newobj(pVM);
612 ring_vm_oop_setscope(pVM);
614 case ICO_LOADSUBADDRESS :
615 ring_vm_oop_property(pVM);
617 case ICO_LOADMETHOD :
618 ring_vm_oop_loadmethod(pVM);
620 case ICO_AFTERCALLMETHOD :
621 ring_vm_oop_aftercallmethod(pVM);
623 case ICO_AFTERCALLMETHOD2 :
624 ring_vm_oop_aftercallmethod(pVM);
627 ring_vm_oop_newclass(pVM);
629 case ICO_BRACESTART :
630 ring_vm_oop_bracestart(pVM);
633 ring_vm_oop_braceend(pVM);
636 ring_vm_oop_import(pVM);
639 pVM->nPrivateFlag = 1 ;
641 case ICO_SETPROPERTY :
642 ring_vm_oop_setproperty(pVM);
644 case ICO_CALLCLASSINIT :
645 ring_vm_callclassinit(pVM);
648 case ICO_SETREFERENCE :
649 ring_vm_setreference(pVM);
651 case ICO_KILLREFERENCE :
652 ring_vm_gc_killreference(pVM);
654 case ICO_ASSIGNMENTPOINTER :
655 ring_vm_assignmentpointer(pVM);
657 case ICO_BEFOREEQUAL :
658 pVM->nBeforeEqual = RING_VM_IR_READI ;
660 /* Bitwise Operators */
680 case ICO_STEPNUMBER :
681 ring_vm_stepnumber(pVM);
684 ring_vm_popstep(pVM);
686 case ICO_LOADAFIRST :
687 ring_vm_loadaddressfirst(pVM);
689 /* Custom Global Scope */
690 case ICO_NEWGLOBALSCOPE :
691 ring_vm_newglobalscope(pVM);
693 case ICO_ENDGLOBALSCOPE :
694 ring_vm_endglobalscope(pVM);
696 case ICO_SETGLOBALSCOPE :
697 ring_vm_setglobalscope(pVM);
702 RING_API void ring_vm_error ( VM *pVM,const char *cStr )
705 /* Check if we have active error */
706 if ( pVM->nActiveError ) {
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);
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 ;
725 if ( ring_list_getsize(pVM->pTry) == 0 ) {
726 if ( pVM->lHideErrorMsg == 0 ) {
727 ring_vm_showerrormessage(pVM,cStr);
730 pVM->nActiveError = 0 ;
731 ring_vm_traceevent(pVM,RING_VM_TRACEEVENT_ERROR);
732 if ( pVM->lPassError == 1 ) {
733 pVM->lPassError = 0 ;
736 pVM->nActiveError = 1 ;
737 if ( pVM->pRingState->nRingInsideRing == 0 ) {
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
750 if ( pVM->nEvalInScope ) {
751 ring_vm_showerrormessage(pVM,cStr);
752 pVM->nActiveError = 0 ;
753 ring_vm_freestack(pVM);
756 ring_vm_catch(pVM,cStr);
757 pVM->nActiveError = 0 ;
760 int ring_vm_eval ( VM *pVM,const char *cStr )
762 int nPC,nCont,nLastPC,nRunVM,x,nSize ;
765 ByteCode *pByteCode ;
766 ring_state_log(pVM->pRingState,"function: ring_vm_eval() start");
767 nSize = strlen( cStr ) ;
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]);
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 */
785 aPara[1] = ring_list_getsize(pVM->pFunctionsMap) ;
786 aPara[2] = ring_list_getsize(pVM->pClassesMap) ;
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 ;
794 ring_vm_error(pVM,"Error in eval!");
795 ring_scanner_delete(pScanner);
801 ** Generate Hash Table
803 if ( pVM->pRingState->lRunFromThread ) {
804 ring_list_genhashtable2(pVM->pFunctionsMap);
807 ring_list_genhashtable2_gc(pVM->pRingState,pVM->pFunctionsMap);
809 if ( pVM->nEvalCalledFromRingCode ) {
810 ring_scanner_addreturn3(pVM->pRingState,aPara);
813 ring_scanner_addreturn2(pVM->pRingState);
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 ) {
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);
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 ;
832 /* Update the Eval Reallocation Size after Reallocation */
833 pVM->nEvalReallocationSize = ring_list_getsize(pVM->pCode) ;
836 pVM->nEvalReallocationFlag = 0 ;
839 for ( x = pVM->nPC ; x <= ring_list_getsize(pVM->pCode) ; x++ ) {
840 ring_vm_tobytecode(pVM,x);
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
854 pVM->nEvalReallocationSize = pVM->nEvalReallocationSize - (ring_list_getsize(pVM->pCode)-nLastPC) ;
856 ring_vm_error(pVM,"Error in eval!");
857 ring_scanner_delete(pScanner);
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");
867 void ring_vm_tobytecode ( VM *pVM,int x )
871 ByteCode *pByteCode ;
873 pByteCode = pVM->pByteCode + x - 1 ;
874 pIR = ring_list_getlist(pVM->pCode,x);
875 pByteCode->nSize = ring_list_getsize(pIR) ;
877 pByteCode->pList = pIR ;
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 ) ;
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) */
890 switch ( pItem->data.iNumber ) {
891 case ICO_PUSHPLOCAL :
892 pItem->data.iNumber = ICO_LOADADDRESS ;
894 case ICO_JUMPVARLPLENUM :
895 pItem->data.iNumber = ICO_JUMPVARLENUM ;
898 pItem->data.iNumber = ICO_INCJUMP ;
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 ;
909 void ring_vm_returneval ( VM *pVM )
911 int aPara[3],nExtraSize ;
912 ByteCode *pByteCode ;
913 /* This function will always be called after each eval() execution */
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)) ) {
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
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);
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 ) {
935 pVM->pByteCode = pByteCode ;
936 /* Update the Eval Reallocation Size after Reallocation */
937 pVM->nEvalReallocationSize = pVM->nEvalReallocationSize - nExtraSize ;
940 pVM->nEvalReallocationSize = pVM->nEvalReallocationSize + nExtraSize ;
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
956 pVM->nEvalReturnPC = aPara[0] ;
959 void ring_vm_error2 ( VM *pVM,const char *cStr,const char *cStr2 )
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);
969 void ring_vm_newbytecodeitem ( VM *pVM,int x )
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 ;
977 RING_API void ring_vm_runcode ( VM *pVM,const char *cStr )
979 int nEvalReturnPC,nEvalReallocationFlag,nPC,nRunVM,nSP,nFuncSP,nLineNumber ;
981 /* Save state to take in mind nested events execution */
983 nEvalReturnPC = pVM->nEvalReturnPC ;
984 nEvalReallocationFlag = pVM->nEvalReallocationFlag ;
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 ;
996 nRunVM = ring_vm_eval(pVM,cStr);
997 pVM->nEvalCalledFromRingCode = 0 ;
998 ring_vm_mutexunlock(pVM);
1000 pVM->nFuncExecute = 0 ;
1001 pVM->nFuncExecute2 = 0 ;
1002 ring_vm_mainloopforeval(pVM);
1004 /* Restore state to take in mind nested events execution */
1006 pVM->nEvalReturnPC = nEvalReturnPC ;
1007 pVM->nEvalReallocationFlag = nEvalReallocationFlag ;
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);
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 */
1017 pVM->nFuncSP = nFuncSP ;
1018 pVM->nLineNumber = nLineNumber ;
1021 void ring_vm_init ( RingState *pRingState )
1025 int nRunVM,nFreeFilesList = 0 ;
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 ;
1032 ring_list_addstring_gc(pRingState,pRingState->pRingFilesList,"Ring_EmbeddedCode");
1033 ring_list_addstring_gc(pRingState,pRingState->pRingFilesStack,"Ring_EmbeddedCode");
1035 pScanner = ring_scanner_new(pRingState);
1036 /* Add Token "End of Line" to the end of any program */
1037 ring_scanner_endofline(pScanner);
1039 nRunVM = ring_parser_start(pScanner->Tokens,pRingState);
1040 ring_scanner_delete(pScanner);
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 ;
1056 void ring_vm_retitemref ( VM *pVM )
1059 pVM->nRetItemRef++ ;
1060 /* We free the stack to avoid effects on aLoadAddressScope which is used by isstackpointertoobjstate */
1061 ring_vm_freestack(pVM);
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 & &
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++ ;
1077 void ring_vm_printstack ( VM *pVM )
1080 printf( "\n*****************************************\n" ) ;
1081 printf( "Stack Size %u \n",pVM->nSP ) ;
1084 for ( x = 1 ; x <= nSP ; x++ ) {
1086 if ( RING_VM_STACK_ISSTRING ) {
1087 printf( "(String) : %s \n",RING_VM_STACK_READC ) ;
1089 else if ( RING_VM_STACK_ISNUMBER ) {
1090 printf( "(Number) : %f \n",RING_VM_STACK_READN ) ;
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);
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);
1104 printf( "\n*****************************************\n" ) ;
1109 void ring_vm_callclassinit ( VM *pVM )
1111 if ( RING_VM_IR_READIVALUE(1) ) {
1112 pVM->nCallClassInit++ ;
1115 pVM->nCallClassInit-- ;
1119 RING_API void ring_vm_showerrormessage ( VM *pVM,const char *cStr )
1121 int x,lFunctionCall ;
1124 const char *cOldFile ;
1126 ring_state_cgiheader(pVM->pRingState);
1127 /* Print the Error Message */
1128 printf( "\nLine %d %s \n",pVM->nLineNumber,cStr ) ;
1129 /* Print Calling Information */
1132 for ( x = ring_list_getsize(pVM->pFuncCallList) ; x >= 1 ; x-- ) {
1133 pList = ring_list_getlist(pVM->pFuncCallList,x);
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!
1138 if ( ring_list_getsize(pList) < RING_FUNCCL_CALLERPC ) {
1139 cOldFile = (const char *) ring_list_getpointer(pList,RING_FUNCCL_FILENAME) ;
1142 if ( ring_list_getint(pList,RING_FUNCCL_TYPE) == RING_FUNCTYPE_SCRIPT ) {
1148 /* Method or Function */
1149 if ( ring_list_getint(pList,RING_FUNCCL_METHODORFUNC) ) {
1150 printf( "method " ) ;
1153 printf( "function " ) ;
1156 printf( "%s",ring_list_getstring(pList,RING_FUNCCL_NAME) ) ;
1158 printf( "() in file " ) ;
1160 if ( lFunctionCall == 1 ) {
1161 cFile = (const char *) ring_list_getpointer(pList,RING_FUNCCL_NEWFILENAME) ;
1164 if ( pVM->nInClassRegion ) {
1165 cFile = pVM->cFileNameInClassRegion ;
1168 cFile = pVM->cFileName ;
1171 printf( "%s",cFile ) ;
1173 printf( "\ncalled from line %d ",ring_list_getint(pList,RING_FUNCCL_LINENUMBER) ) ;
1176 printf( "In %s() ",ring_list_getstring(pList,RING_FUNCCL_NAME) ) ;
1180 if ( lFunctionCall ) {
1181 printf( "in file %s ",ring_list_getstring(pVM->pRingState->pRingFilesList,1) ) ;
1184 if ( pVM->nInClassRegion ) {
1185 cFile = pVM->cFileNameInClassRegion ;
1188 if ( cOldFile == NULL ) {
1189 cFile = pVM->cFileName ;
1195 printf( "in file %s ",cFile ) ;
1200 void ring_vm_setfilename ( VM *pVM )
1202 if ( pVM->nInClassRegion ) {
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
1207 pVM->cFileNameInClassRegion = RING_VM_IR_READC ;
1210 pVM->cPrevFileName = pVM->cFileName ;
1211 pVM->cFileName = RING_VM_IR_READC ;
1214 void ring_vm_loadaddressfirst ( VM *pVM )
1216 pVM->nFirstAddress = 1 ;
1217 ring_vm_loadaddress(pVM);
1218 pVM->nFirstAddress = 0 ;
1221 void ring_vm_endfuncexec ( VM *pVM )
1223 if ( pVM->nFuncExecute > 0 ) {
1224 pVM->nFuncExecute-- ;
1228 void ring_vm_addglobalvariables ( VM *pVM )
1232 ring_state_log(pVM->pRingState,"function: ring_vm_addglobalvariables() start");
1235 ** We write variable name in lower case because Identifiers is converted to lower by Compiler(Scanner)
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]);
1265 ring_state_log(pVM->pRingState,"function: ring_vm_addglobalvariables() after adding arguments");
1266 ring_state_log(pVM->pRingState,"function: ring_vm_addglobalvariables() end");
1269 void ring_vm_mainloopforeval ( VM *pVM )
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 ) {
1280 ring_vm_fetch2(pVM);
1281 if ( pVM->nPC <= pVM->nEvalReturnPC ) {
1282 pVM->nEvalReturnPC = 0 ;
1285 } while (pVM->nPC <= ring_list_getsize(pVM->pCode)) ;
1290 if ( pVM->nPC <= pVM->nEvalReturnPC ) {
1291 pVM->nEvalReturnPC = 0 ;
1294 } while (pVM->nPC <= ring_list_getsize(pVM->pCode)) ;
1299 if ( pVM->nPC <= pVM->nEvalReturnPC ) {
1300 pVM->nEvalReturnPC = 0 ;
1303 } while (pVM->nPC <= ring_list_getsize(pVM->pCode)) ;
1305 pVM->lInsideEval-- ;
1306 pVM->nRetEvalDontDelete = nDontDelete ;
1310 RING_API void ring_vm_mutexfunctions ( VM *pVM,void *(*pFunc)(void),void (*pFuncLock)(void *),void (*pFuncUnlock)(void *),void (*pFuncDestroy)(void *) )
1312 if ( pVM->pMutex == NULL ) {
1313 pVM->pMutex = pFunc() ;
1314 pVM->pFuncMutexLock = pFuncLock ;
1315 pVM->pFuncMutexUnlock = pFuncUnlock ;
1316 pVM->pFuncMutexDestroy = pFuncDestroy ;
1320 RING_API void ring_vm_mutexlock ( VM *pVM )
1322 if ( pVM->pMutex != NULL ) {
1323 pVM->pFuncMutexLock(pVM->pMutex);
1327 RING_API void ring_vm_mutexunlock ( VM *pVM )
1329 if ( pVM->pMutex != NULL ) {
1330 pVM->pFuncMutexUnlock(pVM->pMutex);
1334 RING_API void ring_vm_mutexdestroy ( VM *pVM )
1336 if ( pVM->pMutex != NULL ) {
1337 pVM->pFuncMutexDestroy(pVM->pMutex);
1338 pVM->pMutex = NULL ;
1342 RING_API void ring_vm_runcodefromthread ( VM *pVM,const char *cStr )
1345 List *pList,*pList2,*pList3,*pList4,*pList5 ;
1347 /* Create the RingState */
1348 pState = ring_state_init();
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
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);
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);
1414 /* Fast Function Call for Extensions (Without Eval) */
1416 RING_API void ring_vm_callfunction ( VM *pVM,char *cFuncName )
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);
1425 /* Execute the function */
1426 ring_vm_mainloopforeval(pVM);
1428 ring_vm_freestack(pVM);
1429 /* Avoid normal steps after this function, because we deleted the scope in Prepare */
1430 pVM->nActiveCatch = 1 ;
1434 void ring_vm_traceevent ( VM *pVM,char nEvent )
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);
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));
1454 ring_list_addstring_gc(pVM->pRingState,pVM->pTraceData,"");
1455 /* Method of Function */
1456 ring_list_adddouble_gc(pVM->pRingState,pVM->pTraceData,0);
1458 /* Execute Trace Function */
1459 ring_vm_runcode(pVM,ring_string_get(pVM->pTrace));
1460 pVM->lTraceActive = 0 ;
1461 pVM->nTraceEvent = 0 ;