11using System ;
22using System . Collections . Generic ;
33using System . Linq ;
4+ using System . Reflection ;
45using System . Threading . Tasks ;
56using GS2Engine . Enums ;
67using GS2Engine . Exceptions ;
@@ -33,7 +34,7 @@ public async Task<IStackEntry> Execute(string functionName, Stack<IStackEntry>?
3334 if ( ! _script . Functions . TryGetValue ( functionName . ToLower ( ) , out FunctionParams value ) )
3435 return 0 . ToStackEntry ( ) ;
3536
36- Stack < IStackEntry > stack = new ( ) ;
37+ Stack < IStackEntry > ? stack = new ( ) ;
3738
3839 int desiredStart = value . BytecodePosition ;
3940 int index = _firstRun ? 0 : value . BytecodePosition ;
@@ -43,14 +44,15 @@ public async Task<IStackEntry> Execute(string functionName, Stack<IStackEntry>?
4344 const int maxLoopCount = 10000 ;
4445
4546 IStackEntry ? opCopy = null ;
47+ Stack < IStackEntry > opWith = new ( ) ;
48+
4649 Tools . DebugLine ( $ "Starting to execute function \" { functionName } \" ") ;
4750 while ( index < _script . Bytecode . Length )
4851 {
4952 int curIndex = index ;
5053 index = curIndex + 1 ;
5154 _indexPos = index ;
5255
53-
5456 ScriptCom op = _script . Bytecode [ curIndex ] ;
5557
5658 Tools . Debug ( $ "OP: { op . OpCode } ") ;
@@ -151,21 +153,42 @@ public async Task<IStackEntry> Execute(string functionName, Stack<IStackEntry>?
151153
152154 break ;
153155 case Opcode . OP_CALL :
154- TString ? cmd = getEntryValue < TString > ( stack . Pop ( ) ) ;
156+ IStackEntry ? callEntry = GetEntry ( stack . Pop ( ) ) ;
157+ object ? cmd = getEntryValue < object > ( callEntry ) ;
158+
155159 Stack < IStackEntry > parameters = stack . Clone ( ) ;
156160 stack . Clear ( ) ;
157- if ( _script . Functions . ContainsKey ( cmd ? . ToString ( ) . ToLower ( ) ?? string . Empty ) )
158- stack . Push ( await Execute ( cmd ? . ToString ( ) . ToLower ( ) ?? string . Empty , parameters ) ) ;
159- else if ( Functions . TryGetValue ( cmd ? . ToString ( ) . ToLower ( ) ?? string . Empty , out Script . Command command ) )
160- stack . Push ( command . Invoke ( this , parameters . ToArray ( ) ) ) ;
161- else stack . Push ( 0 . ToStackEntry ( ) ) ;
161+ switch ( callEntry . Type )
162+ {
163+ case StackEntryType . String or Variable when opWith . Any ( ) :
164+ stack . Push ( opWith ? . Peek ( ) ? . GetValue < VariableCollection > ( ) ? . GetVariable ( cmd ? . ToString ( ) ? . ToLower ( ) ?? string . Empty ) . GetValue < Script . Command > ( ) ? . Invoke ( this , parameters . ToArray ( ) ) ?? 0 . ToStackEntry ( ) ) ;
165+ break ;
166+ case StackEntryType . String or Variable when _script . Functions . ContainsKey ( cmd ? . ToString ( ) . ToLower ( ) ?? string . Empty ) :
167+ stack . Push ( await Execute ( cmd ? . ToString ( ) . ToLower ( ) ?? string . Empty , parameters ) ) ;
168+ break ;
169+ case StackEntryType . String or Variable when Functions . TryGetValue (
170+ cmd ? . ToString ( ) . ToLower ( ) ?? string . Empty ,
171+ out Script . Command command
172+ ) :
173+ stack . Push ( command . Invoke ( this , parameters . ToArray ( ) ) ) ;
174+ break ;
175+ case StackEntryType . String or Variable :
176+ stack . Push ( 0 . ToStackEntry ( ) ) ;
177+ break ;
178+ case Function :
179+ stack . Push ( ( cmd as Script . Command ) ? . Invoke ( this , parameters . ToArray ( ) ) ?? 0 . ToStackEntry ( ) ) ;
180+ break ;
181+ default :
182+ stack . Push ( 0 . ToStackEntry ( ) ) ;
183+ break ;
184+ }
162185
163186 break ;
164187 case Opcode . OP_RET :
165188 IStackEntry ret = 0 . ToStackEntry ( ) ;
166189 if ( stack . Count > 0 )
167190 ret = stack . Pop ( ) ;
168- Tools . DebugLine ( JsonConvert . SerializeObject ( _script . GlobalVariables . GetDictionary ( ) , Formatting . Indented ) ) ;
191+ Tools . DebugLine ( JsonConvert . SerializeObject ( Script . GlobalVariables . GetDictionary ( ) , Formatting . Indented ) ) ;
169192 return ret ;
170193 case Opcode . OP_SLEEP :
171194 double sleep = getEntryValue < double > ( stack . Pop ( ) ) ;
@@ -210,19 +233,25 @@ public async Task<IStackEntry> Execute(string functionName, Stack<IStackEntry>?
210233 break ;
211234
212235 case Opcode . OP_TYPE_TRUE :
236+ stack . Push ( true . ToStackEntry ( ) ) ;
213237 break ;
214238 case Opcode . OP_TYPE_FALSE :
239+ stack . Push ( false . ToStackEntry ( ) ) ;
215240 break ;
216241 case Opcode . OP_TYPE_NULL :
242+ stack . Push ( 0 . ToStackEntry ( ) ) ;
217243 break ;
218244 case Opcode . OP_PI :
245+ stack . Push ( Math . PI . ToStackEntry ( ) ) ;
219246 break ;
220247 case Opcode . OP_COPY_LAST_OP :
221- opCopy = stack . Peek ( ) ;
248+ stack . Push ( stack . Peek ( ) ) ;
222249 break ;
223250 case Opcode . OP_SWAP_LAST_OPS :
224- if ( opCopy != null )
225- stack . Push ( opCopy ) ;
251+ IStackEntry ? stackSwap1 = stack . Pop ( ) ;
252+ IStackEntry ? stackSwap2 = stack . Pop ( ) ;
253+ stack . Push ( stackSwap1 ) ;
254+ stack . Push ( stackSwap2 ) ;
226255 break ;
227256 case Opcode . OP_INDEX_DEC :
228257 break ;
@@ -231,6 +260,7 @@ public async Task<IStackEntry> Execute(string functionName, Stack<IStackEntry>?
231260
232261 double convToFloatVal ;
233262 if ( test ? . GetType ( ) == typeof ( TString ) )
263+
234264 convToFloatVal = double . Parse ( ( TString ) test ) ;
235265 else if ( test ? . GetType ( ) == typeof ( bool ) )
236266 convToFloatVal = ( bool ) test ? 1 : 0 ;
@@ -261,7 +291,13 @@ public async Task<IStackEntry> Execute(string functionName, Stack<IStackEntry>?
261291
262292 break ;
263293 case Opcode . OP_CONV_TO_OBJECT :
264- stack . Push ( GetEntry ( stack . Pop ( ) ) ) ;
294+ stack . Push (
295+ ( opWith . Any ( )
296+ ? opWith ? . Peek ( )
297+ ? . GetValue < VariableCollection > ( ) ?
298+ . GetVariable ( getEntryValue < TString > ( stack . Pop ( ) ) ? . ToLower ( ) ?? string . Empty )
299+ : GetEntry ( stack . Pop ( ) , Variable ) ) !
300+ ) ;
265301 break ;
266302 case Opcode . OP_ARRAY_END :
267303
@@ -284,20 +320,47 @@ public async Task<IStackEntry> Execute(string functionName, Stack<IStackEntry>?
284320 case Opcode . OP_MAKEVAR :
285321 break ;
286322 case Opcode . OP_NEW_OBJECT :
323+ IStackEntry ? newObject = stack . Pop ( ) ;
324+ IStackEntry ? newObjectParam = stack . Pop ( ) ;
325+ try
326+ {
327+ VariableCollection ? newObjectRet = ( VariableCollection ) GetInstance (
328+ getEntryValue < TString > ( newObject ) ?? string . Empty ,
329+ getEntryValue < object > ( newObjectParam ) ? . ToString ( ) !
330+ ) ! ;
331+ stack . Push ( newObjectRet ? . ToStackEntry ( ) ?? 0 . ToStackEntry ( ) ) ;
332+ }
333+ catch ( Exception e )
334+ {
335+ stack . Push ( 0 . ToStackEntry ( ) ) ;
336+ }
337+
287338 break ;
288339 case Opcode . OP_INLINE_CONDITIONAL :
289340 break ;
290341 case Opcode . OP_ASSIGN :
291342 IStackEntry val = stack . Pop ( ) ;
292343
293344 IStackEntry variable = ( stack . Count == 0 ? opCopy : GetEntry ( stack . Pop ( ) ) ) ?? 0 . ToStackEntry ( ) ;
294- if ( variable . Type != Variable )
345+ /* if (variable.Type != Variable)
295346 {
296347 variable.SetValue(val.GetValue());
348+ }*/
349+ if ( opWith . Any ( ) )
350+ {
351+ try
352+ {
353+ opWith ? . Peek ( ) ? . GetValue < VariableCollection > ( ) ?
354+ . AddOrUpdate ( ( variable . GetValue ( ) ?? "" ) . ToString ( ) . ToLower ( ) , val ) ;
355+ }
356+ catch ( Exception e )
357+ {
358+ Tools . DebugLine ( e . Message ) ;
359+ }
297360 }
298361 else if ( ! _useTemp )
299362 {
300- _script . GlobalVariables . AddOrUpdate ( ( variable . GetValue ( ) ?? "" ) . ToString ( ) . ToLower ( ) , val ) ;
363+ Script . GlobalVariables . AddOrUpdate ( ( variable . GetValue ( ) ?? "" ) . ToString ( ) . ToLower ( ) , val ) ;
301364 }
302365 else
303366 {
@@ -327,12 +390,18 @@ public async Task<IStackEntry> Execute(string functionName, Stack<IStackEntry>?
327390 break ;
328391 case Opcode . OP_INC :
329392 IStackEntry incVar = GetEntry ( stack . Pop ( ) ) ;
330- if ( incVar . Type == Number ) incVar . SetValue ( ( double ? ) incVar . GetValue ( ) + 1 ) ;
393+ double incVal = getEntryValue < double > ( stack . Pop ( ) ) ;
394+ if ( incVar . Type == Number ) incVar . SetValue ( incVal + 1 ) ;
331395
332396 stack . Push ( ( ( double ? ) incVar . GetValue ( ) ) ? . ToStackEntry ( ) ?? 0 . ToStackEntry ( ) ) ;
333397
334398 break ;
335399 case Opcode . OP_DEC :
400+ IStackEntry decVar = GetEntry ( stack . Pop ( ) ) ;
401+ double decVal = getEntryValue < double > ( stack . Pop ( ) ) ;
402+ if ( decVar . Type == Number ) decVar . SetValue ( decVal - 1 ) ;
403+
404+ stack . Push ( ( ( double ? ) decVar . GetValue ( ) ) ? . ToStackEntry ( ) ?? 0 . ToStackEntry ( ) ) ;
336405 break ;
337406 case Opcode . OP_ADD :
338407 double addA = getEntryValue < double > ( stack . Pop ( ) ) ;
@@ -525,13 +594,15 @@ public async Task<IStackEntry> Execute(string functionName, Stack<IStackEntry>?
525594 case Opcode . OP_ARRAY_NEW_MULTIDIM :
526595 break ;
527596 case Opcode . OP_WITH :
597+ opWith . Push ( stack . Pop ( ) ) ;
528598 break ;
529599 case Opcode . OP_WITHEND :
600+ stack . Push ( opWith . Pop ( ) ) ;
530601 break ;
531602 case Opcode . OP_FOREACH :
532603 break ;
533604 case Opcode . OP_THIS :
534- stack . Push ( new StackEntry ( StackEntryType . Array , _script . GlobalVariables ) ) ;
605+ stack . Push ( new StackEntry ( StackEntryType . Array , Script . GlobalVariables ) ) ;
535606 break ;
536607 case Opcode . OP_THISO :
537608 break ;
@@ -561,18 +632,35 @@ public async Task<IStackEntry> Execute(string functionName, Stack<IStackEntry>?
561632 return 0 . ToStackEntry ( ) ;
562633 }
563634
635+ private static object ? GetInstance ( string ? strFullyQualifiedName , string arg )
636+ {
637+ if ( string . IsNullOrEmpty ( strFullyQualifiedName ) ) return null ;
638+ Type ? type = Type . GetType ( strFullyQualifiedName ) ;
639+ if ( type != null )
640+ return Activator . CreateInstance ( type , arg ) ;
641+ foreach ( Assembly ? asm in AppDomain . CurrentDomain . GetAssemblies ( ) )
642+ {
643+ type = asm . GetTypes ( ) . FirstOrDefault ( x => x . Name . Equals ( strFullyQualifiedName , StringComparison . CurrentCultureIgnoreCase ) ) ?? null ;
644+ if ( type != null )
645+ return Activator . CreateInstance ( type , arg ) ;
646+ }
647+ return null ;
648+ }
564649 public IStackEntry GetEntry ( IStackEntry stackEntry , StackEntryType ? overrideStackType = null )
565650 {
566651 StackEntryType ? type = overrideStackType ?? stackEntry . Type ;
567652 switch ( type )
568653 {
569654 case Variable
570- when _tempVariables . ContainsVariable ( stackEntry . GetValue < TString > ( ) ? . ToLower ( ) ?? string . Empty ) :
655+ when _tempVariables . ContainsVariable ( stackEntry . GetValue ( ) ? . ToString ( ) ? . ToLower ( ) ?? string . Empty ) :
571656 _useTemp = false ;
572- return _tempVariables . GetVariable ( stackEntry . GetValue < TString > ( ) ? . ToLower ( ) ?? string . Empty ) ;
657+ return _tempVariables . GetVariable ( stackEntry . GetValue ( ) ? . ToString ( ) ? . ToLower ( ) ?? string . Empty ) ;
658+ case Variable
659+ when Script . GlobalVariables . ContainsVariable ( stackEntry . GetValue ( ) ? . ToString ( ) ? . ToLower ( ) ?? string . Empty ) :
660+ return Script . GlobalVariables [ stackEntry . GetValue ( ) ? . ToString ( ) ? . ToLower ( ) ?? string . Empty ] ;
573661 case Variable
574- when _script . GlobalVariables . ContainsVariable ( stackEntry . GetValue < TString > ( ) ? . ToLower ( ) ?? string . Empty ) :
575- return _script . GlobalVariables [ stackEntry . GetValue < TString > ( ) ? . ToLower ( ) ?? string . Empty ] ;
662+ when _script . GlobalObjects . ContainsKey ( stackEntry . GetValue ( ) ? . ToString ( ) ? . ToLower ( ) ?? string . Empty ) :
663+ return _script . GlobalObjects [ stackEntry . GetValue ( ) ? . ToString ( ) ? . ToLower ( ) ?? string . Empty ] . ToStackEntry ( ) ;
576664 default :
577665 return stackEntry ;
578666 }
0 commit comments