aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/YEngine/MMRScriptCodeGen.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ScriptEngine/YEngine/MMRScriptCodeGen.cs')
-rw-r--r--OpenSim/Region/ScriptEngine/YEngine/MMRScriptCodeGen.cs1951
1 files changed, 663 insertions, 1288 deletions
diff --git a/OpenSim/Region/ScriptEngine/YEngine/MMRScriptCodeGen.cs b/OpenSim/Region/ScriptEngine/YEngine/MMRScriptCodeGen.cs
index a480263..ea86b0b 100644
--- a/OpenSim/Region/ScriptEngine/YEngine/MMRScriptCodeGen.cs
+++ b/OpenSim/Region/ScriptEngine/YEngine/MMRScriptCodeGen.cs
@@ -77,9 +77,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
77 public static Type xmrInstSuperType = null; // typeof whatever is actually malloc'd for script instances 77 public static Type xmrInstSuperType = null; // typeof whatever is actually malloc'd for script instances
78 // - must inherit from XMRInstAbstract 78 // - must inherit from XMRInstAbstract
79 79
80 /* 80 // Static tables that there only needs to be one copy of for all.
81 * Static tables that there only needs to be one copy of for all.
82 */
83 private static VarDict legalEventHandlers = CreateLegalEventHandlers(); 81 private static VarDict legalEventHandlers = CreateLegalEventHandlers();
84 private static CompValu[] zeroCompValus = new CompValu[0]; 82 private static CompValu[] zeroCompValus = new CompValu[0];
85 private static TokenType[] zeroArgs = new TokenType[0]; 83 private static TokenType[] zeroArgs = new TokenType[0];
@@ -161,20 +159,14 @@ namespace OpenSim.Region.ScriptEngine.Yengine
161 159
162 public static bool CodeGen(TokenScript tokenScript, BinaryWriter objFileWriter, string sourceHash) 160 public static bool CodeGen(TokenScript tokenScript, BinaryWriter objFileWriter, string sourceHash)
163 { 161 {
164 /* 162 // Run compiler such that it has a 'this' context for convenience.
165 * Run compiler such that it has a 'this' context for convenience.
166 */
167 ScriptCodeGen scg = new ScriptCodeGen(tokenScript, objFileWriter, sourceHash); 163 ScriptCodeGen scg = new ScriptCodeGen(tokenScript, objFileWriter, sourceHash);
168 164
169 /* 165 // Return pointer to resultant script object code.
170 * Return pointer to resultant script object code.
171 */
172 return !scg.youveAnError; 166 return !scg.youveAnError;
173 } 167 }
174 168
175 /* 169 // There is one set of these variables for each script being compiled.
176 * There is one set of these variables for each script being compiled.
177 */
178 private bool mightGetHere = false; 170 private bool mightGetHere = false;
179 private bool youveAnError = false; 171 private bool youveAnError = false;
180 private BreakContTarg curBreakTarg = null; 172 private BreakContTarg curBreakTarg = null;
@@ -246,24 +238,18 @@ namespace OpenSim.Region.ScriptEngine.Yengine
246 */ 238 */
247 private void PerformCompilation() 239 private void PerformCompilation()
248 { 240 {
249 /* 241 // errorMessageToken is used only when the given token doesn't have a
250 * errorMessageToken is used only when the given token doesn't have a 242 // output delegate associated with it such as for backend API functions
251 * output delegate associated with it such as for backend API functions 243 // that only have one copy for the whole system. It is kept up-to-date
252 * that only have one copy for the whole system. It is kept up-to-date 244 // approximately but is rarely needed so going to assume it doesn't have
253 * approximately but is rarely needed so going to assume it doesn't have 245 // to be exact.
254 * to be exact.
255 */
256 errorMessageToken = tokenScript; 246 errorMessageToken = tokenScript;
257 247
258 /* 248 // Set up dictionary to translate state names to their index number.
259 * Set up dictionary to translate state names to their index number.
260 */
261 stateIndices = new Dictionary<string, int>(); 249 stateIndices = new Dictionary<string, int>();
262 250
263 /* 251 // Assign each state its own unique index.
264 * Assign each state its own unique index. 252 // The default state gets 0.
265 * The default state gets 0.
266 */
267 nStates = 0; 253 nStates = 0;
268 tokenScript.defaultState.body.index = nStates++; 254 tokenScript.defaultState.body.index = nStates++;
269 stateIndices.Add("default", 0); 255 stateIndices.Add("default", 0);
@@ -274,9 +260,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
274 stateIndices.Add(declState.name.val, declState.body.index); 260 stateIndices.Add(declState.name.val, declState.body.index);
275 } 261 }
276 262
277 /* 263 // Make up an array that translates state indices to state name strings.
278 * Make up an array that translates state indices to state name strings.
279 */
280 stateNames = new string[nStates]; 264 stateNames = new string[nStates];
281 stateNames[0] = "default"; 265 stateNames[0] = "default";
282 foreach(KeyValuePair<string, TokenDeclState> kvp in tokenScript.states) 266 foreach(KeyValuePair<string, TokenDeclState> kvp in tokenScript.states)
@@ -285,11 +269,9 @@ namespace OpenSim.Region.ScriptEngine.Yengine
285 stateNames[declState.body.index] = declState.name.val; 269 stateNames[declState.body.index] = declState.name.val;
286 } 270 }
287 271
288 /* 272 // Make sure we have delegates for all script-defined functions and methods,
289 * Make sure we have delegates for all script-defined functions and methods, 273 // creating anonymous ones if needed. Note that this includes all property
290 * creating anonymous ones if needed. Note that this includes all property 274 // getter and setter methods.
291 * getter and setter methods.
292 */
293 foreach(TokenDeclVar declFunc in tokenScript.variablesStack) 275 foreach(TokenDeclVar declFunc in tokenScript.variablesStack)
294 { 276 {
295 if(declFunc.retType != null) 277 if(declFunc.retType != null)
@@ -347,42 +329,29 @@ namespace OpenSim.Region.ScriptEngine.Yengine
347 } 329 }
348 } 330 }
349 331
350 /* 332 // No more types can be defined or we won't be able to write them to the object file.
351 * No more types can be defined or we won't be able to write them to the object file.
352 */
353 tokenScript.sdSrcTypesSeal(); 333 tokenScript.sdSrcTypesSeal();
354 334
355 /* 335 // Assign all global variables a slot in its corresponding XMRInstance.gbl<Type>s[] array.
356 * Assign all global variables a slot in its corresponding XMRInstance.gbl<Type>s[] array. 336 // Global variables are simply elements of those arrays at runtime, thus we don't need to create
357 * Global variables are simply elements of those arrays at runtime, thus we don't need to create 337 // an unique class for each script, we can just use XMRInstance as is for all.
358 * an unique class for each script, we can just use XMRInstance as is for all.
359 */
360 foreach(TokenDeclVar declVar in tokenScript.variablesStack) 338 foreach(TokenDeclVar declVar in tokenScript.variablesStack)
361 { 339 {
362 340 // Omit 'constant' variables as they are coded inline so don't need a slot.
363 /*
364 * Omit 'constant' variables as they are coded inline so don't need a slot.
365 */
366 if(declVar.constant) 341 if(declVar.constant)
367 continue; 342 continue;
368 343
369 /* 344 // Do functions later.
370 * Do functions later.
371 */
372 if(declVar.retType != null) 345 if(declVar.retType != null)
373 continue; 346 continue;
374 347
375 /* 348 // Create entry in the value array for the variable or property.
376 * Create entry in the value array for the variable or property.
377 */
378 declVar.location = new CompValuGlobalVar(declVar, glblSizes); 349 declVar.location = new CompValuGlobalVar(declVar, glblSizes);
379 } 350 }
380 351
381 /* 352 // Likewise for any static fields in script-defined classes.
382 * Likewise for any static fields in script-defined classes. 353 // They can be referenced anywhere by <typename>.<fieldname>, see
383 * They can be referenced anywhere by <typename>.<fieldname>, see 354 // GenerateFromLValSField().
384 * GenerateFromLValSField().
385 */
386 foreach(TokenDeclSDType sdType in tokenScript.sdSrcTypesValues) 355 foreach(TokenDeclSDType sdType in tokenScript.sdSrcTypesValues)
387 { 356 {
388 if(!(sdType is TokenDeclSDTypeClass)) 357 if(!(sdType is TokenDeclSDTypeClass))
@@ -391,40 +360,29 @@ namespace OpenSim.Region.ScriptEngine.Yengine
391 360
392 foreach(TokenDeclVar declVar in sdtClass.members) 361 foreach(TokenDeclVar declVar in sdtClass.members)
393 { 362 {
394 363 // Omit 'constant' variables as they are coded inline so don't need a slot.
395 /*
396 * Omit 'constant' variables as they are coded inline so don't need a slot.
397 */
398 if(declVar.constant) 364 if(declVar.constant)
399 continue; 365 continue;
400 366
401 /* 367 // Do methods later.
402 * Do methods later.
403 */
404 if(declVar.retType != null) 368 if(declVar.retType != null)
405 continue; 369 continue;
406 370
407 /* 371 // Ignore non-static fields for now.
408 * Ignore non-static fields for now. 372 // They get assigned below.
409 * They get assigned below.
410 */
411 if((declVar.sdtFlags & ScriptReduce.SDT_STATIC) == 0) 373 if((declVar.sdtFlags & ScriptReduce.SDT_STATIC) == 0)
412 continue; 374 continue;
413 375
414 /* 376 // Create entry in the value array for the static field or static property.
415 * Create entry in the value array for the static field or static property.
416 */
417 declVar.location = new CompValuGlobalVar(declVar, glblSizes); 377 declVar.location = new CompValuGlobalVar(declVar, glblSizes);
418 } 378 }
419 } 379 }
420 380
421 /* 381 // Assign slots for all interface method prototypes.
422 * Assign slots for all interface method prototypes. 382 // These indices are used to index the array of delegates that holds a class' implementation of an
423 * These indices are used to index the array of delegates that holds a class' implementation of an 383 // interface.
424 * interface. 384 // Properties do not get a slot because they aren't called as such. But their corresponding
425 * Properties do not get a slot because they aren't called as such. But their corresponding 385 // <name>$get() and <name>$set(<type>) methods are in the table and they each get a slot.
426 * <name>$get() and <name>$set(<type>) methods are in the table and they each get a slot.
427 */
428 foreach(TokenDeclSDType sdType in tokenScript.sdSrcTypesValues) 386 foreach(TokenDeclSDType sdType in tokenScript.sdSrcTypesValues)
429 { 387 {
430 if(!(sdType is TokenDeclSDTypeInterface)) 388 if(!(sdType is TokenDeclSDTypeInterface))
@@ -440,9 +398,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
440 } 398 }
441 } 399 }
442 400
443 /* 401 // Assign slots for all instance fields and virtual methods of script-defined classes.
444 * Assign slots for all instance fields and virtual methods of script-defined classes.
445 */
446 int maxExtends = tokenScript.sdSrcTypesCount; 402 int maxExtends = tokenScript.sdSrcTypesCount;
447 bool didOne; 403 bool didOne;
448 do 404 do
@@ -456,10 +412,8 @@ namespace OpenSim.Region.ScriptEngine.Yengine
456 if(sdtClass.slotsAssigned) 412 if(sdtClass.slotsAssigned)
457 continue; 413 continue;
458 414
459 /* 415 // If this class extends another, the extended class has to already
460 * If this class extends another, the extended class has to already 416 // be set up, because our slots add on to the end of the extended class.
461 * be set up, because our slots add on to the end of the extended class.
462 */
463 TokenDeclSDTypeClass extends = sdtClass.extends; 417 TokenDeclSDTypeClass extends = sdtClass.extends;
464 if(extends != null) 418 if(extends != null)
465 { 419 {
@@ -483,10 +437,8 @@ namespace OpenSim.Region.ScriptEngine.Yengine
483 } 437 }
484 } 438 }
485 439
486 /* 440 // Extended class's slots all assigned, assign our instance fields
487 * Extended class's slots all assigned, assign our instance fields 441 // slots in the XMRSDTypeClObj arrays.
488 * slots in the XMRSDTypeClObj arrays.
489 */
490 foreach(TokenDeclVar declVar in sdtClass.members) 442 foreach(TokenDeclVar declVar in sdtClass.members)
491 { 443 {
492 if(declVar.retType != null) 444 if(declVar.retType != null)
@@ -501,31 +453,27 @@ namespace OpenSim.Region.ScriptEngine.Yengine
501 } 453 }
502 } 454 }
503 455
504 /* 456 // ... and assign virtual method vtable slots.
505 * ... and assign virtual method vtable slots. 457 //
506 * 458 // - : error if any overridden method, doesn't need a slot
507 * - : error if any overridden method, doesn't need a slot 459 // abstract : error if any overridden method, alloc new slot but leave it empty
508 * abstract : error if any overridden method, alloc new slot but leave it empty 460 // new : ignore any overridden method, doesn't need a slot
509 * new : ignore any overridden method, doesn't need a slot 461 // new abstract : ignore any overridden method, alloc new slot but leave it empty
510 * new abstract : ignore any overridden method, alloc new slot but leave it empty 462 // override : must have overridden abstract/virtual, use old slot
511 * override : must have overridden abstract/virtual, use old slot 463 // override abstract : must have overridden abstract, use old slot but it is still empty
512 * override abstract : must have overridden abstract, use old slot but it is still empty 464 // static : error if any overridden method, doesn't need a slot
513 * static : error if any overridden method, doesn't need a slot 465 // static new : ignore any overridden method, doesn't need a slot
514 * static new : ignore any overridden method, doesn't need a slot 466 // virtual : error if any overridden method, alloc new slot and fill it in
515 * virtual : error if any overridden method, alloc new slot and fill it in 467 // virtual new : ignore any overridden method, alloc new slot and fill it in
516 * virtual new : ignore any overridden method, alloc new slot and fill it in
517 */
518 foreach(TokenDeclVar declFunc in sdtClass.members) 468 foreach(TokenDeclVar declFunc in sdtClass.members)
519 { 469 {
520 if(declFunc.retType == null) 470 if(declFunc.retType == null)
521 continue; 471 continue;
522 curDeclFunc = declFunc; 472 curDeclFunc = declFunc;
523 473
524 /* 474 // See if there is a method in an extended class that this method overshadows.
525 * See if there is a method in an extended class that this method overshadows. 475 // If so, check for various conflicts.
526 * If so, check for various conflicts. 476 // In any case, SDT_NEW on our method means to ignore any overshadowed method.
527 * In any case, SDT_NEW on our method means to ignore any overshadowed method.
528 */
529 string declLongName = sdtClass.longName.val + "." + declFunc.funcNameSig.val; 477 string declLongName = sdtClass.longName.val + "." + declFunc.funcNameSig.val;
530 uint declFlags = declFunc.sdtFlags; 478 uint declFlags = declFunc.sdtFlags;
531 TokenDeclVar overridden = null; 479 TokenDeclVar overridden = null;
@@ -544,9 +492,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
544 string overLongName = overridden.sdtClass.longName.val; 492 string overLongName = overridden.sdtClass.longName.val;
545 uint overFlags = overridden.sdtFlags; 493 uint overFlags = overridden.sdtFlags;
546 494
547 /* 495 // See if overridden method allows itself to be overridden.
548 * See if overridden method allows itself to be overridden.
549 */
550 if((overFlags & ScriptReduce.SDT_ABSTRACT) != 0) 496 if((overFlags & ScriptReduce.SDT_ABSTRACT) != 0)
551 { 497 {
552 if((declFlags & (ScriptReduce.SDT_ABSTRACT | ScriptReduce.SDT_OVERRIDE)) == 0) 498 if((declFlags & (ScriptReduce.SDT_ABSTRACT | ScriptReduce.SDT_OVERRIDE)) == 0)
@@ -573,9 +519,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
573 break; 519 break;
574 } 520 }
575 521
576 /* 522 // See if our method is capable of overriding the other method.
577 * See if our method is capable of overriding the other method.
578 */
579 if((declFlags & ScriptReduce.SDT_ABSTRACT) != 0) 523 if((declFlags & ScriptReduce.SDT_ABSTRACT) != 0)
580 { 524 {
581 if((overFlags & ScriptReduce.SDT_ABSTRACT) == 0) 525 if((overFlags & ScriptReduce.SDT_ABSTRACT) == 0)
@@ -599,9 +543,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
599 } 543 }
600 } while(false); 544 } while(false);
601 545
602 /* 546 // Now we can assign it a vtable slot if it needs one (ie, it is virtual).
603 * Now we can assign it a vtable slot if it needs one (ie, it is virtual).
604 */
605 declFunc.vTableIndex = -1; 547 declFunc.vTableIndex = -1;
606 if(overridden != null) 548 if(overridden != null)
607 { 549 {
@@ -618,11 +560,9 @@ namespace OpenSim.Region.ScriptEngine.Yengine
618 } 560 }
619 curDeclFunc = null; 561 curDeclFunc = null;
620 562
621 /* 563 // ... and assign implemented interface slots.
622 * ... and assign implemented interface slots. 564 // Note that our implementations of a given interface is completely independent of any
623 * Note that our implementations of a given interface is completely independent of any 565 // rootward class's implementation of that same interface.
624 * rootward class's implementation of that same interface.
625 */
626 int nIFaces = sdtClass.numInterfaces + sdtClass.implements.Count; 566 int nIFaces = sdtClass.numInterfaces + sdtClass.implements.Count;
627 sdtClass.iFaces = new TokenDeclSDTypeInterface[nIFaces]; 567 sdtClass.iFaces = new TokenDeclSDTypeInterface[nIFaces];
628 sdtClass.iImplFunc = new TokenDeclVar[nIFaces][]; 568 sdtClass.iImplFunc = new TokenDeclVar[nIFaces][];
@@ -653,11 +593,8 @@ namespace OpenSim.Region.ScriptEngine.Yengine
653 curDeclFunc = classMeth; 593 curDeclFunc = classMeth;
654 for(TokenIntfImpl intfImpl = classMeth.implements; intfImpl != null; intfImpl = (TokenIntfImpl)intfImpl.nextToken) 594 for(TokenIntfImpl intfImpl = classMeth.implements; intfImpl != null; intfImpl = (TokenIntfImpl)intfImpl.nextToken)
655 { 595 {
656 596 // One of the class methods implements an interface method.
657 /* 597 // Try to find the interface method that is implemented and verify its signature.
658 * One of the class methods implements an interface method.
659 * Try to find the interface method that is implemented and verify its signature.
660 */
661 TokenDeclSDTypeInterface intfType = intfImpl.intfType.decl; 598 TokenDeclSDTypeInterface intfType = intfImpl.intfType.decl;
662 TokenDeclVar intfMeth = FindExactWithRet(intfType.methsNProps, intfImpl.methName, classMeth.retType, classMeth.argDecl.types); 599 TokenDeclVar intfMeth = FindExactWithRet(intfType.methsNProps, intfImpl.methName, classMeth.retType, classMeth.argDecl.types);
663 if(intfMeth == null) 600 if(intfMeth == null)
@@ -666,9 +603,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
666 continue; 603 continue;
667 } 604 }
668 605
669 /* 606 // See if this class was declared to implement that interface.
670 * See if this class was declared to implement that interface.
671 */
672 bool found = false; 607 bool found = false;
673 foreach(TokenDeclSDTypeInterface intf in sdtClass.implements) 608 foreach(TokenDeclSDTypeInterface intf in sdtClass.implements)
674 { 609 {
@@ -684,11 +619,9 @@ namespace OpenSim.Region.ScriptEngine.Yengine
684 continue; 619 continue;
685 } 620 }
686 621
687 /* 622 // Get index in iFaces[] and iImplFunc[] arrays.
688 * Get index in iFaces[] and iImplFunc[] arrays. 623 // Start scanning from the end in case one of our rootward classes also implements the interface.
689 * Start scanning from the end in case one of our rootward classes also implements the interface. 624 // We should always be successful because we know by now that this class implements the interface.
690 * We should always be successful because we know by now that this class implements the interface.
691 */
692 int i; 625 int i;
693 for(i = sdtClass.numInterfaces; --i >= 0;) 626 for(i = sdtClass.numInterfaces; --i >= 0;)
694 { 627 {
@@ -696,9 +629,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
696 break; 629 break;
697 } 630 }
698 631
699 /* 632 // Now remember which of the class methods implements that interface method.
700 * Now remember which of the class methods implements that interface method.
701 */
702 int j = intfMeth.vTableIndex; 633 int j = intfMeth.vTableIndex;
703 if(sdtClass.iImplFunc[i][j] != null) 634 if(sdtClass.iImplFunc[i][j] != null)
704 { 635 {
@@ -710,9 +641,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
710 } 641 }
711 curDeclFunc = null; 642 curDeclFunc = null;
712 643
713 /* 644 // Now make sure this class implements all methods for all declared interfaces.
714 * Now make sure this class implements all methods for all declared interfaces.
715 */
716 for(int i = sdtClass.numInterfaces - sdtClass.implements.Count; i < sdtClass.numInterfaces; i++) 645 for(int i = sdtClass.numInterfaces - sdtClass.implements.Count; i < sdtClass.numInterfaces; i++)
717 { 646 {
718 TokenDeclVar[] implementations = sdtClass.iImplFunc[i]; 647 TokenDeclVar[] implementations = sdtClass.iImplFunc[i];
@@ -735,18 +664,14 @@ namespace OpenSim.Region.ScriptEngine.Yengine
735 } 664 }
736 } 665 }
737 666
738 /* 667 // All slots for this class have been assigned.
739 * All slots for this class have been assigned.
740 */
741 sdtClass.slotsAssigned = true; 668 sdtClass.slotsAssigned = true;
742 didOne = true; 669 didOne = true;
743 } 670 }
744 } while(didOne); 671 } while(didOne);
745 672
746 /* 673 // Compute final values for all variables/fields declared as 'constant'.
747 * Compute final values for all variables/fields declared as 'constant'. 674 // Note that there may be forward references.
748 * Note that there may be forward references.
749 */
750 do 675 do
751 { 676 {
752 didOne = false; 677 didOne = false;
@@ -773,9 +698,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
773 currentSDTClass = null; 698 currentSDTClass = null;
774 } while(didOne); 699 } while(didOne);
775 700
776 /* 701 // Now we should be able to assign all those constants their type and location.
777 * Now we should be able to assign all those constants their type and location.
778 */
779 foreach(TokenDeclVar tdv in tokenScript.variablesStack) 702 foreach(TokenDeclVar tdv in tokenScript.variablesStack)
780 { 703 {
781 if(tdv.constant) 704 if(tdv.constant)
@@ -816,20 +739,16 @@ namespace OpenSim.Region.ScriptEngine.Yengine
816 } 739 }
817 currentSDTClass = null; 740 currentSDTClass = null;
818 741
819 /* 742 // For all classes that define all the methods needed for the class, ie, they aren't abstract,
820 * For all classes that define all the methods needed for the class, ie, they aren't abstract, 743 // define a static class.$new() method with same args as the $ctor(s). This will allow the
821 * define a static class.$new() method with same args as the $ctor(s). This will allow the 744 // class to be instantiated via the new operator.
822 * class to be instantiated via the new operator.
823 */
824 foreach(TokenDeclSDType sdType in tokenScript.sdSrcTypesValues) 745 foreach(TokenDeclSDType sdType in tokenScript.sdSrcTypesValues)
825 { 746 {
826 if(!(sdType is TokenDeclSDTypeClass)) 747 if(!(sdType is TokenDeclSDTypeClass))
827 continue; 748 continue;
828 TokenDeclSDTypeClass sdtClass = (TokenDeclSDTypeClass)sdType; 749 TokenDeclSDTypeClass sdtClass = (TokenDeclSDTypeClass)sdType;
829 750
830 /* 751 // See if the class as it stands would be able to fill every slot of its vtable.
831 * See if the class as it stands would be able to fill every slot of its vtable.
832 */
833 bool[] filled = new bool[sdtClass.numVirtFuncs]; 752 bool[] filled = new bool[sdtClass.numVirtFuncs];
834 int numFilled = 0; 753 int numFilled = 0;
835 for(TokenDeclSDTypeClass sdtc = sdtClass; sdtc != null; sdtc = sdtc.extends) 754 for(TokenDeclSDTypeClass sdtc = sdtClass; sdtc != null; sdtc = sdtc.extends)
@@ -847,11 +766,9 @@ namespace OpenSim.Region.ScriptEngine.Yengine
847 } 766 }
848 } 767 }
849 768
850 /* 769 // If so, define a static class.$new() method for every constructor defined for the class.
851 * If so, define a static class.$new() method for every constructor defined for the class. 770 // Give it the same access (private/protected/public) as the script declared for the constructor.
852 * Give it the same access (private/protected/public) as the script declared for the constructor. 771 // Note that the reducer made sure there is at least a default constructor for every class.
853 * Note that the reducer made sure there is at least a default constructor for every class.
854 */
855 if(numFilled >= sdtClass.numVirtFuncs) 772 if(numFilled >= sdtClass.numVirtFuncs)
856 { 773 {
857 List<TokenDeclVar> newobjDeclFuncs = new List<TokenDeclVar>(); 774 List<TokenDeclVar> newobjDeclFuncs = new List<TokenDeclVar>();
@@ -870,9 +787,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
870 } 787 }
871 } 788 }
872 789
873 /* 790 // Write fixed portion of object file.
874 * Write fixed portion of object file.
875 */
876 objFileWriter.Write(OBJECT_CODE_MAGIC.ToCharArray()); 791 objFileWriter.Write(OBJECT_CODE_MAGIC.ToCharArray());
877 objFileWriter.Write(COMPILED_VERSION_VALUE); 792 objFileWriter.Write(COMPILED_VERSION_VALUE);
878 objFileWriter.Write(sourceHash); 793 objFileWriter.Write(sourceHash);
@@ -884,9 +799,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
884 objFileWriter.Write(stateNames[i]); 799 objFileWriter.Write(stateNames[i]);
885 } 800 }
886 801
887 /* 802 // For debugging, we also write out global variable array slot assignments.
888 * For debugging, we also write out global variable array slot assignments.
889 */
890 foreach(TokenDeclVar declVar in tokenScript.variablesStack) 803 foreach(TokenDeclVar declVar in tokenScript.variablesStack)
891 { 804 {
892 if(declVar.retType == null) 805 if(declVar.retType == null)
@@ -909,9 +822,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
909 } 822 }
910 objFileWriter.Write(""); 823 objFileWriter.Write("");
911 824
912 /* 825 // Write out script-defined types.
913 * Write out script-defined types.
914 */
915 foreach(TokenDeclSDType sdType in tokenScript.sdSrcTypesValues) 826 foreach(TokenDeclSDType sdType in tokenScript.sdSrcTypesValues)
916 { 827 {
917 objFileWriter.Write(sdType.longName.val); 828 objFileWriter.Write(sdType.longName.val);
@@ -919,13 +830,11 @@ namespace OpenSim.Region.ScriptEngine.Yengine
919 } 830 }
920 objFileWriter.Write(""); 831 objFileWriter.Write("");
921 832
922 /* 833 // Output function headers then bodies.
923 * Output function headers then bodies. 834 // Do all headers first in case bodies do forward references.
924 * Do all headers first in case bodies do forward references. 835 // Do both global functions, script-defined class static methods and
925 * Do both global functions, script-defined class static methods and 836 // script-defined instance methods, as we handle the differences
926 * script-defined instance methods, as we handle the differences 837 // during compilation of the functions/methods themselves.
927 * during compilation of the functions/methods themselves.
928 */
929 for(int pass = 0; pass < 2; pass++) 838 for(int pass = 0; pass < 2; pass++)
930 { 839 {
931 foreach(TokenDeclVar declFunc in tokenScript.variablesStack) 840 foreach(TokenDeclVar declFunc in tokenScript.variablesStack)
@@ -957,11 +866,9 @@ namespace OpenSim.Region.ScriptEngine.Yengine
957 } 866 }
958 } 867 }
959 868
960 /* 869 // Output default state event handler functions.
961 * Output default state event handler functions. 870 // Each event handler is a private static method named 'default <eventname>'.
962 * Each event handler is a private static method named 'default <eventname>'. 871 // Splice in a default state_entry() handler if none defined so we can init global vars.
963 * Splice in a default state_entry() handler if none defined so we can init global vars.
964 */
965 TokenDeclVar defaultStateEntry = null; 872 TokenDeclVar defaultStateEntry = null;
966 for(defaultStateEntry = tokenScript.defaultState.body.eventFuncs; 873 for(defaultStateEntry = tokenScript.defaultState.body.eventFuncs;
967 defaultStateEntry != null; 874 defaultStateEntry != null;
@@ -984,10 +891,8 @@ namespace OpenSim.Region.ScriptEngine.Yengine
984 } 891 }
985 GenerateStateEventHandlers("default", tokenScript.defaultState.body); 892 GenerateStateEventHandlers("default", tokenScript.defaultState.body);
986 893
987 /* 894 // Output script-defined state event handler methods.
988 * Output script-defined state event handler methods. 895 // Each event handler is a private static method named <statename> <eventname>
989 * Each event handler is a private static method named <statename> <eventname>
990 */
991 foreach(KeyValuePair<string, TokenDeclState> kvp in tokenScript.states) 896 foreach(KeyValuePair<string, TokenDeclState> kvp in tokenScript.states)
992 { 897 {
993 TokenDeclState declState = kvp.Value; 898 TokenDeclState declState = kvp.Value;
@@ -1059,13 +964,11 @@ namespace OpenSim.Region.ScriptEngine.Yengine
1059 string eventname = declFunc.GetSimpleName(); 964 string eventname = declFunc.GetSimpleName();
1060 TokenArgDecl argDecl = declFunc.argDecl; 965 TokenArgDecl argDecl = declFunc.argDecl;
1061 966
1062 /* 967 // Make sure event handler name is valid and that number and type of arguments is correct.
1063 * Make sure event handler name is valid and that number and type of arguments is correct. 968 // Apparently some scripts exist with fewer than correct number of args in their declaration
1064 * Apparently some scripts exist with fewer than correct number of args in their declaration 969 // so allow for that. It is ok because the handlers are called with the arguments in an
1065 * so allow for that. It is ok because the handlers are called with the arguments in an 970 // object[] array, and we just won't access the missing argments in the vector. But the
1066 * object[] array, and we just won't access the missing argments in the vector. But the 971 // specified types must match one of the prototypes in legalEventHandlers.
1067 * specified types must match one of the prototypes in legalEventHandlers.
1068 */
1069 TokenDeclVar protoDeclFunc = legalEventHandlers.FindExact(eventname, argDecl.types); 972 TokenDeclVar protoDeclFunc = legalEventHandlers.FindExact(eventname, argDecl.types);
1070 if(protoDeclFunc == null) 973 if(protoDeclFunc == null)
1071 { 974 {
@@ -1073,10 +976,8 @@ namespace OpenSim.Region.ScriptEngine.Yengine
1073 return; 976 return;
1074 } 977 }
1075 978
1076 /* 979 // Output function header.
1077 * Output function header. 980 // They just have the XMRInstAbstract pointer as the one argument.
1078 * They just have the XMRInstAbstract pointer as the one argument.
1079 */
1080 string functionName = statename + " " + eventname; 981 string functionName = statename + " " + eventname;
1081 _ilGen = new ScriptObjWriter(tokenScript, 982 _ilGen = new ScriptObjWriter(tokenScript,
1082 functionName, 983 functionName,
@@ -1086,34 +987,25 @@ namespace OpenSim.Region.ScriptEngine.Yengine
1086 objFileWriter); 987 objFileWriter);
1087 StartFunctionBody(declFunc); 988 StartFunctionBody(declFunc);
1088 989
1089 /* 990 // Create a temp to hold XMRInstanceSuperType version of arg 0.
1090 * Create a temp to hold XMRInstanceSuperType version of arg 0.
1091 */
1092 instancePointer = ilGen.DeclareLocal(xmrInstSuperType, "__xmrinst"); 991 instancePointer = ilGen.DeclareLocal(xmrInstSuperType, "__xmrinst");
1093 ilGen.Emit(declFunc, OpCodes.Ldarg_0); 992 ilGen.Emit(declFunc, OpCodes.Ldarg_0);
1094 ilGen.Emit(declFunc, OpCodes.Castclass, xmrInstSuperType); 993 ilGen.Emit(declFunc, OpCodes.Castclass, xmrInstSuperType);
1095 ilGen.Emit(declFunc, OpCodes.Stloc, instancePointer); 994 ilGen.Emit(declFunc, OpCodes.Stloc, instancePointer);
1096 995
1097 /* 996 // Output args as variable definitions and initialize each from __sw.ehArgs[].
1098 * Output args as variable definitions and initialize each from __sw.ehArgs[]. 997 // If the script writer goofed, the typecast will complain.
1099 * If the script writer goofed, the typecast will complain.
1100 */
1101 int nArgs = argDecl.vars.Length; 998 int nArgs = argDecl.vars.Length;
1102 for(int i = 0; i < nArgs; i++) 999 for(int i = 0; i < nArgs; i++)
1103 { 1000 {
1104 1001 // Say that the argument variable is going to be located in a local var.
1105 /*
1106 * Say that the argument variable is going to be located in a local var.
1107 */
1108 TokenDeclVar argVar = argDecl.vars[i]; 1002 TokenDeclVar argVar = argDecl.vars[i];
1109 TokenType argTokType = argVar.type; 1003 TokenType argTokType = argVar.type;
1110 CompValuLocalVar local = new CompValuLocalVar(argTokType, argVar.name.val, this); 1004 CompValuLocalVar local = new CompValuLocalVar(argTokType, argVar.name.val, this);
1111 argVar.location = local; 1005 argVar.location = local;
1112 1006
1113 /* 1007 // Copy from the ehArgs[i] element to the temp var.
1114 * Copy from the ehArgs[i] element to the temp var. 1008 // Cast as needed, there is a lot of craziness like OpenMetaverse.Quaternion.
1115 * Cast as needed, there is a lot of craziness like OpenMetaverse.Quaternion.
1116 */
1117 local.PopPre(this, argVar.name); 1009 local.PopPre(this, argVar.name);
1118 PushXMRInst(); // instance 1010 PushXMRInst(); // instance
1119 ilGen.Emit(declFunc, OpCodes.Ldfld, ehArgsFieldInfo); // instance.ehArgs (array of objects) 1011 ilGen.Emit(declFunc, OpCodes.Ldfld, ehArgsFieldInfo); // instance.ehArgs (array of objects)
@@ -1154,9 +1046,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
1154 local.PopPost(this, argVar.name, stkTokType); // pop stack type into argtype 1046 local.PopPost(this, argVar.name, stkTokType); // pop stack type into argtype
1155 } 1047 }
1156 1048
1157 /* 1049 // Output code for the statements and clean up.
1158 * Output code for the statements and clean up.
1159 */
1160 GenerateFuncBody(); 1050 GenerateFuncBody();
1161 } 1051 }
1162 1052
@@ -1168,12 +1058,10 @@ namespace OpenSim.Region.ScriptEngine.Yengine
1168 { 1058 {
1169 curDeclFunc = declFunc; 1059 curDeclFunc = declFunc;
1170 1060
1171 /* 1061 // Make up array of all argument types as seen by the code generator.
1172 * Make up array of all argument types as seen by the code generator. 1062 // We splice in XMRInstanceSuperType or XMRSDTypeClObj for the first
1173 * We splice in XMRInstanceSuperType or XMRSDTypeClObj for the first 1063 // arg as the function itself is static, followed by script-visible
1174 * arg as the function itself is static, followed by script-visible 1064 // arg types.
1175 * arg types.
1176 */
1177 TokenArgDecl argDecl = declFunc.argDecl; 1065 TokenArgDecl argDecl = declFunc.argDecl;
1178 int nArgs = argDecl.vars.Length; 1066 int nArgs = argDecl.vars.Length;
1179 Type[] argTypes = new Type[nArgs + 1]; 1067 Type[] argTypes = new Type[nArgs + 1];
@@ -1194,9 +1082,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
1194 argNames[i + 1] = argDecl.vars[i].name.val; 1082 argNames[i + 1] = argDecl.vars[i].name.val;
1195 } 1083 }
1196 1084
1197 /* 1085 // Set up entrypoint.
1198 * Set up entrypoint.
1199 */
1200 string objCodeName = declFunc.GetObjCodeName(); 1086 string objCodeName = declFunc.GetObjCodeName();
1201 declFunc.ilGen = new ScriptObjWriter(tokenScript, 1087 declFunc.ilGen = new ScriptObjWriter(tokenScript,
1202 objCodeName, 1088 objCodeName,
@@ -1205,9 +1091,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
1205 argNames, 1091 argNames,
1206 objFileWriter); 1092 objFileWriter);
1207 1093
1208 /* 1094 // This says how to generate a call to the function and to get a delegate.
1209 * This says how to generate a call to the function and to get a delegate.
1210 */
1211 declFunc.location = new CompValuGlobalMeth(declFunc); 1095 declFunc.location = new CompValuGlobalMeth(declFunc);
1212 1096
1213 curDeclFunc = null; 1097 curDeclFunc = null;
@@ -1221,20 +1105,16 @@ namespace OpenSim.Region.ScriptEngine.Yengine
1221 */ 1105 */
1222 private void GenerateMethodBody(TokenDeclVar declFunc) 1106 private void GenerateMethodBody(TokenDeclVar declFunc)
1223 { 1107 {
1224 /* 1108 // Set up code generator for the function's contents.
1225 * Set up code generator for the function's contents.
1226 */
1227 _ilGen = declFunc.ilGen; 1109 _ilGen = declFunc.ilGen;
1228 StartFunctionBody(declFunc); 1110 StartFunctionBody(declFunc);
1229 1111
1230 /* 1112 // Create a temp to hold XMRInstanceSuperType version of arg 0.
1231 * Create a temp to hold XMRInstanceSuperType version of arg 0. 1113 // For most functions, arg 0 is already XMRInstanceSuperType.
1232 * For most functions, arg 0 is already XMRInstanceSuperType. 1114 // But for script-defined class instance methods, arg 0 holds
1233 * But for script-defined class instance methods, arg 0 holds 1115 // the XMRSDTypeClObj pointer and so we read the XMRInstAbstract
1234 * the XMRSDTypeClObj pointer and so we read the XMRInstAbstract 1116 // pointer from its XMRSDTypeClObj.xmrInst field then cast it to
1235 * pointer from its XMRSDTypeClObj.xmrInst field then cast it to 1117 // XMRInstanceSuperType.
1236 * XMRInstanceSuperType.
1237 */
1238 if(IsSDTInstMethod()) 1118 if(IsSDTInstMethod())
1239 { 1119 {
1240 instancePointer = ilGen.DeclareLocal(xmrInstSuperType, "__xmrinst"); 1120 instancePointer = ilGen.DeclareLocal(xmrInstSuperType, "__xmrinst");
@@ -1244,11 +1124,9 @@ namespace OpenSim.Region.ScriptEngine.Yengine
1244 ilGen.Emit(declFunc, OpCodes.Stloc, instancePointer); 1124 ilGen.Emit(declFunc, OpCodes.Stloc, instancePointer);
1245 } 1125 }
1246 1126
1247 /* 1127 // Define location of all script-level arguments so script body can access them.
1248 * Define location of all script-level arguments so script body can access them. 1128 // The argument indices need to have +1 added to them because XMRInstance or
1249 * The argument indices need to have +1 added to them because XMRInstance or 1129 // XMRSDTypeClObj is spliced in at arg 0.
1250 * XMRSDTypeClObj is spliced in at arg 0.
1251 */
1252 TokenArgDecl argDecl = declFunc.argDecl; 1130 TokenArgDecl argDecl = declFunc.argDecl;
1253 int nArgs = argDecl.vars.Length; 1131 int nArgs = argDecl.vars.Length;
1254 for(int i = 0; i < nArgs; i++) 1132 for(int i = 0; i < nArgs; i++)
@@ -1257,27 +1135,21 @@ namespace OpenSim.Region.ScriptEngine.Yengine
1257 argVar.location = new CompValuArg(argVar.type, i + 1); 1135 argVar.location = new CompValuArg(argVar.type, i + 1);
1258 } 1136 }
1259 1137
1260 /* 1138 // Output code for the statements and clean up.
1261 * Output code for the statements and clean up.
1262 */
1263 GenerateFuncBody(); 1139 GenerateFuncBody();
1264 } 1140 }
1265 1141
1266 private void StartFunctionBody(TokenDeclVar declFunc) 1142 private void StartFunctionBody(TokenDeclVar declFunc)
1267 { 1143 {
1268 /* 1144 // Start current function being processed.
1269 * Start current function being processed. 1145 // Set 'mightGetHere' as the code at the top is always executed.
1270 * Set 'mightGetHere' as the code at the top is always executed.
1271 */
1272 instancePointer = null; 1146 instancePointer = null;
1273 mightGetHere = true; 1147 mightGetHere = true;
1274 curBreakTarg = null; 1148 curBreakTarg = null;
1275 curContTarg = null; 1149 curContTarg = null;
1276 curDeclFunc = declFunc; 1150 curDeclFunc = declFunc;
1277 1151
1278 /* 1152 // Start generating code.
1279 * Start generating code.
1280 */
1281 ((ScriptObjWriter)ilGen).BegMethod(); 1153 ((ScriptObjWriter)ilGen).BegMethod();
1282 } 1154 }
1283 1155
@@ -1287,9 +1159,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
1287 */ 1159 */
1288 private TokenDeclVar DefineNewobjFunc(TokenDeclVar ctorDeclFunc) 1160 private TokenDeclVar DefineNewobjFunc(TokenDeclVar ctorDeclFunc)
1289 { 1161 {
1290 /* 1162 // Set up 'static classname $new(params-same-as-ctor) { }'.
1291 * Set up 'static classname $new(params-same-as-ctor) { }'.
1292 */
1293 TokenDeclVar newobjDeclFunc = new TokenDeclVar(ctorDeclFunc, null, tokenScript); 1163 TokenDeclVar newobjDeclFunc = new TokenDeclVar(ctorDeclFunc, null, tokenScript);
1294 newobjDeclFunc.name = new TokenName(newobjDeclFunc, "$new"); 1164 newobjDeclFunc.name = new TokenName(newobjDeclFunc, "$new");
1295 newobjDeclFunc.retType = ctorDeclFunc.sdtClass.MakeRefToken(newobjDeclFunc); 1165 newobjDeclFunc.retType = ctorDeclFunc.sdtClass.MakeRefToken(newobjDeclFunc);
@@ -1297,10 +1167,8 @@ namespace OpenSim.Region.ScriptEngine.Yengine
1297 newobjDeclFunc.sdtClass = ctorDeclFunc.sdtClass; 1167 newobjDeclFunc.sdtClass = ctorDeclFunc.sdtClass;
1298 newobjDeclFunc.sdtFlags = ScriptReduce.SDT_STATIC | ctorDeclFunc.sdtFlags; 1168 newobjDeclFunc.sdtFlags = ScriptReduce.SDT_STATIC | ctorDeclFunc.sdtFlags;
1299 1169
1300 /* 1170 // Declare local variable named '$objptr' in a frame just under
1301 * Declare local variable named '$objptr' in a frame just under 1171 // what the '$new(...)' function's arguments are declared in.
1302 * what the '$new(...)' function's arguments are declared in.
1303 */
1304 TokenDeclVar objptrVar = new TokenDeclVar(newobjDeclFunc, newobjDeclFunc, tokenScript); 1172 TokenDeclVar objptrVar = new TokenDeclVar(newobjDeclFunc, newobjDeclFunc, tokenScript);
1305 objptrVar.type = newobjDeclFunc.retType; 1173 objptrVar.type = newobjDeclFunc.retType;
1306 objptrVar.name = new TokenName(newobjDeclFunc, "$objptr"); 1174 objptrVar.name = new TokenName(newobjDeclFunc, "$objptr");
@@ -1308,20 +1176,17 @@ namespace OpenSim.Region.ScriptEngine.Yengine
1308 newFrame.outerVarDict = ctorDeclFunc.argDecl.varDict; 1176 newFrame.outerVarDict = ctorDeclFunc.argDecl.varDict;
1309 newFrame.AddEntry(objptrVar); 1177 newFrame.AddEntry(objptrVar);
1310 1178
1311 /* 1179 // Set up '$objptr.$ctor'
1312 * Set up '$objptr.$ctor'
1313 */
1314 TokenLValName objptrLValName = new TokenLValName(objptrVar.name, newFrame); 1180 TokenLValName objptrLValName = new TokenLValName(objptrVar.name, newFrame);
1181
1315 // ref a var by giving its name 1182 // ref a var by giving its name
1316 TokenLValIField objptrDotCtor = new TokenLValIField(newobjDeclFunc); // an instance member reference 1183 TokenLValIField objptrDotCtor = new TokenLValIField(newobjDeclFunc); // an instance member reference
1317 objptrDotCtor.baseRVal = objptrLValName; // '$objptr' 1184 objptrDotCtor.baseRVal = objptrLValName; // '$objptr'
1318 objptrDotCtor.fieldName = ctorDeclFunc.name; // '.' '$ctor' 1185 objptrDotCtor.fieldName = ctorDeclFunc.name; // '.' '$ctor'
1319 1186
1320 /* 1187 // Set up '$objptr.$ctor(arglist)' call for use in the '$new(...)' body.
1321 * Set up '$objptr.$ctor(arglist)' call for use in the '$new(...)' body. 1188 // Copy the arglist from the constructor declaration so triviality
1322 * Copy the arglist from the constructor declaration so triviality 1189 // processing will pick the correct overloaded constructor.
1323 * processing will pick the correct overloaded constructor.
1324 */
1325 TokenRValCall callCtorRVal = new TokenRValCall(newobjDeclFunc); // doing a call of some sort 1190 TokenRValCall callCtorRVal = new TokenRValCall(newobjDeclFunc); // doing a call of some sort
1326 callCtorRVal.meth = objptrDotCtor; // calling $objptr.$ctor() 1191 callCtorRVal.meth = objptrDotCtor; // calling $objptr.$ctor()
1327 TokenDeclVar[] argList = newobjDeclFunc.argDecl.vars; // get args $new() was declared with 1192 TokenDeclVar[] argList = newobjDeclFunc.argDecl.vars; // get args $new() was declared with
@@ -1335,32 +1200,26 @@ namespace OpenSim.Region.ScriptEngine.Yengine
1335 callCtorRVal.args = argLValName; 1200 callCtorRVal.args = argLValName;
1336 } 1201 }
1337 1202
1338 /* 1203 // Set up a funky call to the constructor for the code body.
1339 * Set up a funky call to the constructor for the code body. 1204 // This will let code generator know there is some craziness.
1340 * This will let code generator know there is some craziness. 1205 // See GenerateStmtNewobj().
1341 * See GenerateStmtNewobj(). 1206 //
1342 * 1207 // This is in essence:
1343 * This is in essence: 1208 // {
1344 * { 1209 // classname $objptr = newobj (classname);
1345 * classname $objptr = newobj (classname); 1210 // $objptr.$ctor (...);
1346 * $objptr.$ctor (...); 1211 // return $objptr;
1347 * return $objptr; 1212 // }
1348 * }
1349 */
1350 TokenStmtNewobj newobjStmtBody = new TokenStmtNewobj(ctorDeclFunc); 1213 TokenStmtNewobj newobjStmtBody = new TokenStmtNewobj(ctorDeclFunc);
1351 newobjStmtBody.objptrVar = objptrVar; 1214 newobjStmtBody.objptrVar = objptrVar;
1352 newobjStmtBody.rValCall = callCtorRVal; 1215 newobjStmtBody.rValCall = callCtorRVal;
1353 TokenStmtBlock newobjBody = new TokenStmtBlock(ctorDeclFunc); 1216 TokenStmtBlock newobjBody = new TokenStmtBlock(ctorDeclFunc);
1354 newobjBody.statements = newobjStmtBody; 1217 newobjBody.statements = newobjStmtBody;
1355 1218
1356 /* 1219 // Link that code as the body of the function.
1357 * Link that code as the body of the function.
1358 */
1359 newobjDeclFunc.body = newobjBody; 1220 newobjDeclFunc.body = newobjBody;
1360 1221
1361 /* 1222 // Say the function calls '$objptr.$ctor(arglist)' so we will inherit ctor's triviality.
1362 * Say the function calls '$objptr.$ctor(arglist)' so we will inherit ctor's triviality.
1363 */
1364 newobjDeclFunc.unknownTrivialityCalls.AddLast(callCtorRVal); 1223 newobjDeclFunc.unknownTrivialityCalls.AddLast(callCtorRVal);
1365 return newobjDeclFunc; 1224 return newobjDeclFunc;
1366 } 1225 }
@@ -1377,43 +1236,33 @@ namespace OpenSim.Region.ScriptEngine.Yengine
1377 */ 1236 */
1378 private void GenerateFuncBody() 1237 private void GenerateFuncBody()
1379 { 1238 {
1380 /* 1239 // We want to know if the function's code is trivial, ie,
1381 * We want to know if the function's code is trivial, ie, 1240 // if it doesn't have anything that might be an infinite
1382 * if it doesn't have anything that might be an infinite 1241 // loop and that is doesn't call anything that might have
1383 * loop and that is doesn't call anything that might have 1242 // an infinite loop. If it is, we don't need any CheckRun()
1384 * an infinite loop. If it is, we don't need any CheckRun() 1243 // stuff or any of the frame save/restore stuff.
1385 * stuff or any of the frame save/restore stuff.
1386 */
1387 bool isTrivial = curDeclFunc.IsFuncTrivial(this); 1244 bool isTrivial = curDeclFunc.IsFuncTrivial(this);
1388 1245
1389 /* 1246 // Clear list of all call labels.
1390 * Clear list of all call labels. 1247 // A call label is inserted just before every call that can possibly
1391 * A call label is inserted just before every call that can possibly 1248 // call CheckRun(), including any direct calls to CheckRun().
1392 * call CheckRun(), including any direct calls to CheckRun(). 1249 // Then, when restoring stack, we can just switch to this label to
1393 * Then, when restoring stack, we can just switch to this label to 1250 // resume at the correct spot.
1394 * resume at the correct spot.
1395 */
1396 actCallLabels.Clear(); 1251 actCallLabels.Clear();
1397 allCallLabels.Clear(); 1252 allCallLabels.Clear();
1398 openCallLabel = null; 1253 openCallLabel = null;
1399 1254
1400 /* 1255 // Alloc stack space for local vars.
1401 * Alloc stack space for local vars.
1402 */
1403 int stackframesize = AllocLocalVarStackSpace(); 1256 int stackframesize = AllocLocalVarStackSpace();
1404 1257
1405 /* 1258 // Include argument variables in stack space for this frame.
1406 * Include argument variables in stack space for this frame.
1407 */
1408 foreach(TokenType tokType in curDeclFunc.argDecl.types) 1259 foreach(TokenType tokType in curDeclFunc.argDecl.types)
1409 { 1260 {
1410 stackframesize += LocalVarStackSize(tokType); 1261 stackframesize += LocalVarStackSize(tokType);
1411 } 1262 }
1412 1263
1413 /* 1264 // Any return statements inside function body jump to this label
1414 * Any return statements inside function body jump to this label 1265 // after putting return value in __retval.
1415 * after putting return value in __retval.
1416 */
1417 retLabel = ilGen.DefineLabel("__retlbl"); 1266 retLabel = ilGen.DefineLabel("__retlbl");
1418 retValue = null; 1267 retValue = null;
1419 if(!(curDeclFunc.retType is TokenTypeVoid)) 1268 if(!(curDeclFunc.retType is TokenTypeVoid))
@@ -1421,13 +1270,11 @@ namespace OpenSim.Region.ScriptEngine.Yengine
1421 retValue = ilGen.DeclareLocal(curDeclFunc.retType.ToSysType(), "__retval"); 1270 retValue = ilGen.DeclareLocal(curDeclFunc.retType.ToSysType(), "__retval");
1422 } 1271 }
1423 1272
1424 /* 1273 // Output:
1425 * Output: 1274 // int __mainCallNo = -1;
1426 * int __mainCallNo = -1; 1275 // instance.m_StackLeft -= stackframesize;
1427 * instance.m_StackLeft -= stackframesize; 1276 // try {
1428 * try { 1277 // if (instance.callMode != CallMode_NORMAL) goto __cmRestore;
1429 * if (instance.callMode != CallMode_NORMAL) goto __cmRestore;
1430 */
1431 actCallNo = null; 1278 actCallNo = null;
1432 ScriptMyLabel cmRestore = null; 1279 ScriptMyLabel cmRestore = null;
1433 if(!isTrivial) 1280 if(!isTrivial)
@@ -1448,18 +1295,14 @@ namespace OpenSim.Region.ScriptEngine.Yengine
1448 ilGen.Emit(curDeclFunc, OpCodes.Bne_Un, cmRestore); 1295 ilGen.Emit(curDeclFunc, OpCodes.Bne_Un, cmRestore);
1449 } 1296 }
1450 1297
1451 /* 1298 // Splice in the code optimizer for the body of the function.
1452 * Splice in the code optimizer for the body of the function.
1453 */
1454 ScriptCollector collector = new ScriptCollector((ScriptObjWriter)ilGen); 1299 ScriptCollector collector = new ScriptCollector((ScriptObjWriter)ilGen);
1455 _ilGen = collector; 1300 _ilGen = collector;
1456 1301
1457 /* 1302 // If this is the default state_entry() handler, output code to set all global
1458 * If this is the default state_entry() handler, output code to set all global 1303 // variables to their initial values. Note that every script must have a
1459 * variables to their initial values. Note that every script must have a 1304 // default state_entry() handler, we provide one if the script doesn't explicitly
1460 * default state_entry() handler, we provide one if the script doesn't explicitly 1305 // define one.
1461 * define one.
1462 */
1463 string methname = ilGen.methName; 1306 string methname = ilGen.methName;
1464 if(methname == "default state_entry") 1307 if(methname == "default state_entry")
1465 { 1308 {
@@ -1501,10 +1344,8 @@ namespace OpenSim.Region.ScriptEngine.Yengine
1501 ilGen.MarkLabel(skipGblInitLabel); 1344 ilGen.MarkLabel(skipGblInitLabel);
1502 } 1345 }
1503 1346
1504 /* 1347 // If this is a script-defined type constructor, call the base constructor and call
1505 * If this is a script-defined type constructor, call the base constructor and call 1348 // this class's $instfieldinit() method to initialize instance fields.
1506 * this class's $instfieldinit() method to initialize instance fields.
1507 */
1508 if((curDeclFunc.sdtClass != null) && curDeclFunc.funcNameSig.val.StartsWith("$ctor(")) 1349 if((curDeclFunc.sdtClass != null) && curDeclFunc.funcNameSig.val.StartsWith("$ctor("))
1509 { 1350 {
1510 if(curDeclFunc.baseCtorCall != null) 1351 if(curDeclFunc.baseCtorCall != null)
@@ -1521,22 +1362,16 @@ namespace OpenSim.Region.ScriptEngine.Yengine
1521 } 1362 }
1522 } 1363 }
1523 1364
1524 /* 1365 // See if time to suspend in case they are doing a loop with recursion.
1525 * See if time to suspend in case they are doing a loop with recursion.
1526 */
1527 if(!isTrivial) 1366 if(!isTrivial)
1528 EmitCallCheckRun(curDeclFunc, true); 1367 EmitCallCheckRun(curDeclFunc, true);
1529 1368
1530 /* 1369 // Output code body.
1531 * Output code body.
1532 */
1533 GenerateStmtBlock(curDeclFunc.body); 1370 GenerateStmtBlock(curDeclFunc.body);
1534 1371
1535 /* 1372 // If code falls through to this point, means they are missing
1536 * If code falls through to this point, means they are missing 1373 // a return statement. And that is legal only if the function
1537 * a return statement. And that is legal only if the function 1374 // returns 'void'.
1538 * returns 'void'.
1539 */
1540 if(mightGetHere) 1375 if(mightGetHere)
1541 { 1376 {
1542 if(!(curDeclFunc.retType is TokenTypeVoid)) 1377 if(!(curDeclFunc.retType is TokenTypeVoid))
@@ -1546,28 +1381,21 @@ namespace OpenSim.Region.ScriptEngine.Yengine
1546 ilGen.Emit(curDeclFunc, OpCodes.Leave, retLabel); 1381 ilGen.Emit(curDeclFunc, OpCodes.Leave, retLabel);
1547 } 1382 }
1548 1383
1549 /* 1384 // End of the code to be optimized.
1550 * End of the code to be optimized. 1385 // Do optimizations then write it all out to object file.
1551 * Do optimizations then write it all out to object file. 1386 // After this, all code gets written directly to object file.
1552 * After this, all code gets written directly to object file. 1387 // Optimization must be completed before we scan the allCallLabels
1553 * Optimization must be completed before we scan the allCallLabels 1388 // list below to look for active locals and temps.
1554 * list below to look for active locals and temps.
1555 */
1556 collector.Optimize(); 1389 collector.Optimize();
1557 _ilGen = collector.WriteOutAll(); 1390 _ilGen = collector.WriteOutAll();
1558 collector = null; 1391 collector = null;
1559 1392
1560 /* 1393 // Output code to restore stack frame from stream.
1561 * Output code to restore stack frame from stream. 1394 // It jumps back to the call labels within the function body.
1562 * It jumps back to the call labels within the function body.
1563 */
1564 List<ScriptMyLocal> activeTemps = null; 1395 List<ScriptMyLocal> activeTemps = null;
1565 if(!isTrivial) 1396 if(!isTrivial)
1566 { 1397 {
1567 1398 // Build list of locals and temps active at all the call labels.
1568 /*
1569 * Build list of locals and temps active at all the call labels.
1570 */
1571 activeTemps = new List<ScriptMyLocal>(); 1399 activeTemps = new List<ScriptMyLocal>();
1572 foreach(CallLabel cl in allCallLabels) 1400 foreach(CallLabel cl in allCallLabels)
1573 { 1401 {
@@ -1580,24 +1408,20 @@ namespace OpenSim.Region.ScriptEngine.Yengine
1580 } 1408 }
1581 } 1409 }
1582 1410
1583 /* 1411 // Output code to restore the args, locals and temps then jump to
1584 * Output code to restore the args, locals and temps then jump to 1412 // the call label that we were interrupted at.
1585 * the call label that we were interrupted at.
1586 */
1587 ilGen.MarkLabel(cmRestore); 1413 ilGen.MarkLabel(cmRestore);
1588 GenerateFrameRestoreCode(activeTemps); 1414 GenerateFrameRestoreCode(activeTemps);
1589 } 1415 }
1590 1416
1591 /* 1417 // Output epilog that saves stack frame state if CallMode_SAVE.
1592 * Output epilog that saves stack frame state if CallMode_SAVE. 1418 //
1593 * 1419 // finally {
1594 * finally { 1420 // instance.m_StackLeft += stackframesize;
1595 * instance.m_StackLeft += stackframesize; 1421 // if (instance.callMode != CallMode_SAVE) goto __endFin;
1596 * if (instance.callMode != CallMode_SAVE) goto __endFin; 1422 // GenerateFrameCaptureCode();
1597 * GenerateFrameCaptureCode(); 1423 // __endFin:
1598 * __endFin: 1424 // }
1599 * }
1600 */
1601 ScriptMyLabel endFin = null; 1425 ScriptMyLabel endFin = null;
1602 if(!isTrivial) 1426 if(!isTrivial)
1603 { 1427 {
@@ -1619,9 +1443,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
1619 ilGen.EndExceptionBlock(); 1443 ilGen.EndExceptionBlock();
1620 } 1444 }
1621 1445
1622 /* 1446 // Output the 'real' return opcode.
1623 * Output the 'real' return opcode.
1624 */
1625 ilGen.MarkLabel(retLabel); 1447 ilGen.MarkLabel(retLabel);
1626 if(!(curDeclFunc.retType is TokenTypeVoid)) 1448 if(!(curDeclFunc.retType is TokenTypeVoid))
1627 { 1449 {
@@ -1631,15 +1453,11 @@ namespace OpenSim.Region.ScriptEngine.Yengine
1631 retLabel = null; 1453 retLabel = null;
1632 retValue = null; 1454 retValue = null;
1633 1455
1634 /* 1456 // No more instructions for this method.
1635 * No more instructions for this method.
1636 */
1637 ((ScriptObjWriter)ilGen).EndMethod(); 1457 ((ScriptObjWriter)ilGen).EndMethod();
1638 _ilGen = null; 1458 _ilGen = null;
1639 1459
1640 /* 1460 // Not generating function code any more.
1641 * Not generating function code any more.
1642 */
1643 curBreakTarg = null; 1461 curBreakTarg = null;
1644 curContTarg = null; 1462 curContTarg = null;
1645 curDeclFunc = null; 1463 curDeclFunc = null;
@@ -1655,21 +1473,14 @@ namespace OpenSim.Region.ScriptEngine.Yengine
1655 int stackframesize = 64; // RIP, RBX, RBP, R12..R15, one extra 1473 int stackframesize = 64; // RIP, RBX, RBP, R12..R15, one extra
1656 foreach(TokenDeclVar localVar in curDeclFunc.localVars) 1474 foreach(TokenDeclVar localVar in curDeclFunc.localVars)
1657 { 1475 {
1658 1476 // Skip all 'constant' vars as they were handled by the reducer.
1659 /*
1660 * Skip all 'constant' vars as they were handled by the reducer.
1661 */
1662 if(localVar.constant) 1477 if(localVar.constant)
1663 continue; 1478 continue;
1664 1479
1665 /* 1480 // Get a stack location for the local variable.
1666 * Get a stack location for the local variable.
1667 */
1668 localVar.location = new CompValuLocalVar(localVar.type, localVar.name.val, this); 1481 localVar.location = new CompValuLocalVar(localVar.type, localVar.name.val, this);
1669 1482
1670 /* 1483 // Stack size for the local variable.
1671 * Stack size for the local variable.
1672 */
1673 stackframesize += LocalVarStackSize(localVar.type); 1484 stackframesize += LocalVarStackSize(localVar.type);
1674 } 1485 }
1675 return stackframesize; 1486 return stackframesize;
@@ -1692,17 +1503,13 @@ namespace OpenSim.Region.ScriptEngine.Yengine
1692 */ 1503 */
1693 private void GenerateFrameCaptureCode(List<ScriptMyLocal> activeTemps) 1504 private void GenerateFrameCaptureCode(List<ScriptMyLocal> activeTemps)
1694 { 1505 {
1695 /* 1506 // Compute total number of slots we need to save stuff.
1696 * Compute total number of slots we need to save stuff. 1507 // Assume we need to save all call arguments.
1697 * Assume we need to save all call arguments.
1698 */
1699 int nSaves = curDeclFunc.argDecl.vars.Length + activeTemps.Count; 1508 int nSaves = curDeclFunc.argDecl.vars.Length + activeTemps.Count;
1700 1509
1701 /* 1510 // Output code to allocate a stack frame object with an object array.
1702 * Output code to allocate a stack frame object with an object array. 1511 // This also pushes the stack frame object on the instance.stackFrames list.
1703 * This also pushes the stack frame object on the instance.stackFrames list. 1512 // It returns a pointer to the object array it allocated.
1704 * It returns a pointer to the object array it allocated.
1705 */
1706 PushXMRInst(); 1513 PushXMRInst();
1707 ilGen.Emit(curDeclFunc, OpCodes.Ldstr, ilGen.methName); 1514 ilGen.Emit(curDeclFunc, OpCodes.Ldstr, ilGen.methName);
1708 GetCallNo(curDeclFunc, actCallNo); 1515 GetCallNo(curDeclFunc, actCallNo);
@@ -1718,9 +1525,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
1718 ilGen.Emit(curDeclFunc, OpCodes.Call, consoleWriteMethodInfo); 1525 ilGen.Emit(curDeclFunc, OpCodes.Call, consoleWriteMethodInfo);
1719 } 1526 }
1720 1527
1721 /* 1528 // Copy arg values to object array, boxing as needed.
1722 * Copy arg values to object array, boxing as needed.
1723 */
1724 int i = 0; 1529 int i = 0;
1725 foreach(TokenDeclVar argVar in curDeclFunc.argDecl.varDict) 1530 foreach(TokenDeclVar argVar in curDeclFunc.argDecl.varDict)
1726 { 1531 {
@@ -1738,9 +1543,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
1738 i++; 1543 i++;
1739 } 1544 }
1740 1545
1741 /* 1546 // Copy local and temp values to object array, boxing as needed.
1742 * Copy local and temp values to object array, boxing as needed.
1743 */
1744 foreach(ScriptMyLocal lcl in activeTemps) 1547 foreach(ScriptMyLocal lcl in activeTemps)
1745 { 1548 {
1746 ilGen.Emit(curDeclFunc, OpCodes.Dup); 1549 ilGen.Emit(curDeclFunc, OpCodes.Dup);
@@ -1789,10 +1592,8 @@ namespace OpenSim.Region.ScriptEngine.Yengine
1789 { 1592 {
1790 ScriptMyLocal objArray = ilGen.DeclareLocal(typeof(object[]), "__restObjArray"); 1593 ScriptMyLocal objArray = ilGen.DeclareLocal(typeof(object[]), "__restObjArray");
1791 1594
1792 /* 1595 // Output code to pop stack frame from instance.stackFrames.
1793 * Output code to pop stack frame from instance.stackFrames. 1596 // It returns a pointer to the object array that contains values to be restored.
1794 * It returns a pointer to the object array that contains values to be restored.
1795 */
1796 PushXMRInst(); 1597 PushXMRInst();
1797 ilGen.Emit(curDeclFunc, OpCodes.Ldstr, ilGen.methName); 1598 ilGen.Emit(curDeclFunc, OpCodes.Ldstr, ilGen.methName);
1798 ilGen.Emit(curDeclFunc, OpCodes.Ldloca, actCallNo); // __mainCallNo 1599 ilGen.Emit(curDeclFunc, OpCodes.Ldloca, actCallNo); // __mainCallNo
@@ -1807,11 +1608,9 @@ namespace OpenSim.Region.ScriptEngine.Yengine
1807 ilGen.Emit(curDeclFunc, OpCodes.Call, consoleWriteMethodInfo); 1608 ilGen.Emit(curDeclFunc, OpCodes.Call, consoleWriteMethodInfo);
1808 } 1609 }
1809 1610
1810 /* 1611 // Restore argument values from object array, unboxing as needed.
1811 * Restore argument values from object array, unboxing as needed. 1612 // Although the caller has restored them to what it called us with, it's possible that this
1812 * Although the caller has restored them to what it called us with, it's possible that this 1613 // function has modified them since, so we need to do our own restore.
1813 * function has modified them since, so we need to do our own restore.
1814 */
1815 int i = 0; 1614 int i = 0;
1816 foreach(TokenDeclVar argVar in curDeclFunc.argDecl.varDict) 1615 foreach(TokenDeclVar argVar in curDeclFunc.argDecl.varDict)
1817 { 1616 {
@@ -1832,9 +1631,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
1832 i++; 1631 i++;
1833 } 1632 }
1834 1633
1835 /* 1634 // Restore local and temp values from object array, unboxing as needed.
1836 * Restore local and temp values from object array, unboxing as needed.
1837 */
1838 foreach(ScriptMyLocal lcl in activeTemps) 1635 foreach(ScriptMyLocal lcl in activeTemps)
1839 { 1636 {
1840 Type t = lcl.type; 1637 Type t = lcl.type;
@@ -1952,10 +1749,8 @@ namespace OpenSim.Region.ScriptEngine.Yengine
1952 this.index = scg.actCallLabels.Count; 1749 this.index = scg.actCallLabels.Count;
1953 string name = "__call_" + index + "_" + scg.allCallLabels.Count; 1750 string name = "__call_" + index + "_" + scg.allCallLabels.Count;
1954 1751
1955 /* 1752 // Make sure eval stack is empty because the frame capture/restore
1956 * Make sure eval stack is empty because the frame capture/restore 1753 // code expects such (restore switch stmt has an empty stack).
1957 * code expects such (restore switch stmt has an empty stack).
1958 */
1959 int depth = ((ScriptCollector)scg.ilGen).stackDepth.Count; 1754 int depth = ((ScriptCollector)scg.ilGen).stackDepth.Count;
1960 if(depth > 0) 1755 if(depth > 0)
1961 { 1756 {
@@ -1963,9 +1758,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
1963 throw new Exception("call label stack depth " + depth + " at " + errorAt.SrcLoc); 1758 throw new Exception("call label stack depth " + depth + " at " + errorAt.SrcLoc);
1964 } 1759 }
1965 1760
1966 /* 1761 // Eval stack is empty so the restore code can handle it.
1967 * Eval stack is empty so the restore code can handle it.
1968 */
1969 this.index = scg.actCallLabels.Count; 1762 this.index = scg.actCallLabels.Count;
1970 scg.actCallLabels.AddLast(this); 1763 scg.actCallLabels.AddLast(this);
1971 scg.allCallLabels.AddLast(this); 1764 scg.allCallLabels.AddLast(this);
@@ -2094,23 +1887,17 @@ namespace OpenSim.Region.ScriptEngine.Yengine
2094 if(!mightGetHere) 1887 if(!mightGetHere)
2095 return; 1888 return;
2096 1889
2097 /* 1890 // Push new current statement block pointer for anyone who cares.
2098 * Push new current statement block pointer for anyone who cares.
2099 */
2100 TokenStmtBlock oldStmtBlock = curStmtBlock; 1891 TokenStmtBlock oldStmtBlock = curStmtBlock;
2101 curStmtBlock = stmtBlock; 1892 curStmtBlock = stmtBlock;
2102 1893
2103 /* 1894 // Output the statements that make up the block.
2104 * Output the statements that make up the block.
2105 */
2106 for(Token t = stmtBlock.statements; t != null; t = t.nextToken) 1895 for(Token t = stmtBlock.statements; t != null; t = t.nextToken)
2107 { 1896 {
2108 GenerateStmt((TokenStmt)t); 1897 GenerateStmt((TokenStmt)t);
2109 } 1898 }
2110 1899
2111 /* 1900 // Pop the current statement block.
2112 * Pop the current statement block.
2113 */
2114 curStmtBlock = oldStmtBlock; 1901 curStmtBlock = oldStmtBlock;
2115 } 1902 }
2116 1903
@@ -2122,23 +1909,17 @@ namespace OpenSim.Region.ScriptEngine.Yengine
2122 if(!mightGetHere) 1909 if(!mightGetHere)
2123 return; 1910 return;
2124 1911
2125 /* 1912 // Make sure we are in a breakable situation.
2126 * Make sure we are in a breakable situation.
2127 */
2128 if(curBreakTarg == null) 1913 if(curBreakTarg == null)
2129 { 1914 {
2130 ErrorMsg(breakStmt, "not in a breakable situation"); 1915 ErrorMsg(breakStmt, "not in a breakable situation");
2131 return; 1916 return;
2132 } 1917 }
2133 1918
2134 /* 1919 // Tell anyone who cares that the break target was actually used.
2135 * Tell anyone who cares that the break target was actually used.
2136 */
2137 curBreakTarg.used = true; 1920 curBreakTarg.used = true;
2138 1921
2139 /* 1922 // Output the instructions.
2140 * Output the instructions.
2141 */
2142 EmitJumpCode(curBreakTarg.label, curBreakTarg.block, breakStmt); 1923 EmitJumpCode(curBreakTarg.label, curBreakTarg.block, breakStmt);
2143 } 1924 }
2144 1925
@@ -2150,23 +1931,17 @@ namespace OpenSim.Region.ScriptEngine.Yengine
2150 if(!mightGetHere) 1931 if(!mightGetHere)
2151 return; 1932 return;
2152 1933
2153 /* 1934 // Make sure we are in a contable situation.
2154 * Make sure we are in a contable situation.
2155 */
2156 if(curContTarg == null) 1935 if(curContTarg == null)
2157 { 1936 {
2158 ErrorMsg(contStmt, "not in a continueable situation"); 1937 ErrorMsg(contStmt, "not in a continueable situation");
2159 return; 1938 return;
2160 } 1939 }
2161 1940
2162 /* 1941 // Tell anyone who cares that the continue target was actually used.
2163 * Tell anyone who cares that the continue target was actually used.
2164 */
2165 curContTarg.used = true; 1942 curContTarg.used = true;
2166 1943
2167 /* 1944 // Output the instructions.
2168 * Output the instructions.
2169 */
2170 EmitJumpCode(curContTarg.label, curContTarg.block, contStmt); 1945 EmitJumpCode(curContTarg.label, curContTarg.block, contStmt);
2171 } 1946 }
2172 1947
@@ -2199,29 +1974,21 @@ namespace OpenSim.Region.ScriptEngine.Yengine
2199 CompValu testRVal = GenerateFromRVal(doStmt.testRVal); 1974 CompValu testRVal = GenerateFromRVal(doStmt.testRVal);
2200 if(IsConstBoolExprTrue(testRVal)) 1975 if(IsConstBoolExprTrue(testRVal))
2201 { 1976 {
2202 1977 // Unconditional looping, unconditional branch and
2203 /* 1978 // say we never fall through to next statement.
2204 * Unconditional looping, unconditional branch and
2205 * say we never fall through to next statement.
2206 */
2207 ilGen.Emit(doStmt, OpCodes.Br, loopLabel); 1979 ilGen.Emit(doStmt, OpCodes.Br, loopLabel);
2208 mightGetHere = false; 1980 mightGetHere = false;
2209 } 1981 }
2210 else 1982 else
2211 { 1983 {
2212 1984 // Conditional looping, test and brach back to top of loop.
2213 /*
2214 * Conditional looping, test and brach back to top of loop.
2215 */
2216 testRVal.PushVal(this, doStmt.testRVal, tokenTypeBool); 1985 testRVal.PushVal(this, doStmt.testRVal, tokenTypeBool);
2217 ilGen.Emit(doStmt, OpCodes.Brtrue, loopLabel); 1986 ilGen.Emit(doStmt, OpCodes.Brtrue, loopLabel);
2218 } 1987 }
2219 } 1988 }
2220 1989
2221 /* 1990 // If 'break' statement was used, output target label.
2222 * If 'break' statement was used, output target label. 1991 // And assume that since a 'break' statement was used, it's possible for the code to get here.
2223 * And assume that since a 'break' statement was used, it's possible for the code to get here.
2224 */
2225 if(curBreakTarg.used) 1992 if(curBreakTarg.used)
2226 { 1993 {
2227 ilGen.MarkLabel(curBreakTarg.label); 1994 ilGen.MarkLabel(curBreakTarg.label);
@@ -2253,10 +2020,8 @@ namespace OpenSim.Region.ScriptEngine.Yengine
2253 } 2020 }
2254 ilGen.MarkLabel(loopLabel); 2021 ilGen.MarkLabel(loopLabel);
2255 2022
2256 /* 2023 // See if we have a test expression that is other than a constant TRUE.
2257 * See if we have a test expression that is other than a constant TRUE. 2024 // If so, test it and conditionally branch to end if false.
2258 * If so, test it and conditionally branch to end if false.
2259 */
2260 if(forStmt.testRVal != null) 2025 if(forStmt.testRVal != null)
2261 { 2026 {
2262 CompValu testRVal = GenerateFromRVal(forStmt.testRVal); 2027 CompValu testRVal = GenerateFromRVal(forStmt.testRVal);
@@ -2268,14 +2033,10 @@ namespace OpenSim.Region.ScriptEngine.Yengine
2268 } 2033 }
2269 } 2034 }
2270 2035
2271 /* 2036 // Output loop body.
2272 * Output loop body.
2273 */
2274 GenerateStmt(forStmt.bodyStmt); 2037 GenerateStmt(forStmt.bodyStmt);
2275 2038
2276 /* 2039 // Here's where a 'continue' statement jumps to.
2277 * Here's where a 'continue' statement jumps to.
2278 */
2279 if(curContTarg.used) 2040 if(curContTarg.used)
2280 { 2041 {
2281 ilGen.MarkLabel(curContTarg.label); 2042 ilGen.MarkLabel(curContTarg.label);
@@ -2284,27 +2045,20 @@ namespace OpenSim.Region.ScriptEngine.Yengine
2284 2045
2285 if(mightGetHere) 2046 if(mightGetHere)
2286 { 2047 {
2287 2048 // After checking for excessive CPU time, output increment statement, if any.
2288 /*
2289 * After checking for excessive CPU time, output increment statement, if any.
2290 */
2291 EmitCallCheckRun(forStmt, false); 2049 EmitCallCheckRun(forStmt, false);
2292 if(forStmt.incrRVal != null) 2050 if(forStmt.incrRVal != null)
2293 { 2051 {
2294 GenerateFromRVal(forStmt.incrRVal); 2052 GenerateFromRVal(forStmt.incrRVal);
2295 } 2053 }
2296 2054
2297 /* 2055 // Unconditional branch back to beginning of loop.
2298 * Unconditional branch back to beginning of loop.
2299 */
2300 ilGen.Emit(forStmt, OpCodes.Br, loopLabel); 2056 ilGen.Emit(forStmt, OpCodes.Br, loopLabel);
2301 } 2057 }
2302 2058
2303 /* 2059 // If test needs label, output label for it to jump to.
2304 * If test needs label, output label for it to jump to. 2060 // Otherwise, clear mightGetHere as we know loop never
2305 * Otherwise, clear mightGetHere as we know loop never 2061 // falls out the bottom.
2306 * falls out the bottom.
2307 */
2308 mightGetHere = curBreakTarg.used; 2062 mightGetHere = curBreakTarg.used;
2309 if(mightGetHere) 2063 if(mightGetHere)
2310 { 2064 {
@@ -2433,16 +2187,11 @@ namespace OpenSim.Region.ScriptEngine.Yengine
2433 2187
2434 bool constVal; 2188 bool constVal;
2435 2189
2436 /* 2190 // Test condition and see if constant test expression.
2437 * Test condition and see if constant test expression.
2438 */
2439 CompValu testRVal = GenerateFromRVal(ifStmt.testRVal); 2191 CompValu testRVal = GenerateFromRVal(ifStmt.testRVal);
2440 if(IsConstBoolExpr(testRVal, out constVal)) 2192 if(IsConstBoolExpr(testRVal, out constVal))
2441 { 2193 {
2442 2194 // Constant, output just either the true or else part.
2443 /*
2444 * Constant, output just either the true or else part.
2445 */
2446 if(constVal) 2195 if(constVal)
2447 { 2196 {
2448 GenerateStmt(ifStmt.trueStmt); 2197 GenerateStmt(ifStmt.trueStmt);
@@ -2454,10 +2203,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
2454 } 2203 }
2455 else if(ifStmt.elseStmt == null) 2204 else if(ifStmt.elseStmt == null)
2456 { 2205 {
2457 2206 // This is an 'if' statement without an 'else' clause.
2458 /*
2459 * This is an 'if' statement without an 'else' clause.
2460 */
2461 testRVal.PushVal(this, ifStmt.testRVal, tokenTypeBool); 2207 testRVal.PushVal(this, ifStmt.testRVal, tokenTypeBool);
2462 ScriptMyLabel doneLabel = ilGen.DefineLabel("ifdone_" + ifStmt.Unique); 2208 ScriptMyLabel doneLabel = ilGen.DefineLabel("ifdone_" + ifStmt.Unique);
2463 ilGen.Emit(ifStmt, OpCodes.Brfalse, doneLabel); // brfalse doneLabel 2209 ilGen.Emit(ifStmt, OpCodes.Brfalse, doneLabel); // brfalse doneLabel
@@ -2467,10 +2213,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
2467 } 2213 }
2468 else 2214 else
2469 { 2215 {
2470 2216 // This is an 'if' statement with an 'else' clause.
2471 /*
2472 * This is an 'if' statement with an 'else' clause.
2473 */
2474 testRVal.PushVal(this, ifStmt.testRVal, tokenTypeBool); 2217 testRVal.PushVal(this, ifStmt.testRVal, tokenTypeBool);
2475 ScriptMyLabel elseLabel = ilGen.DefineLabel("ifelse_" + ifStmt.Unique); 2218 ScriptMyLabel elseLabel = ilGen.DefineLabel("ifelse_" + ifStmt.Unique);
2476 ilGen.Emit(ifStmt, OpCodes.Brfalse, elseLabel); // brfalse elseLabel 2219 ilGen.Emit(ifStmt, OpCodes.Brfalse, elseLabel); // brfalse elseLabel
@@ -2494,9 +2237,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
2494 if(!mightGetHere) 2237 if(!mightGetHere)
2495 return; 2238 return;
2496 2239
2497 /* 2240 // Make sure the target label is defined somewhere in the function.
2498 * Make sure the target label is defined somewhere in the function.
2499 */
2500 TokenStmtLabel stmtLabel; 2241 TokenStmtLabel stmtLabel;
2501 if(!curDeclFunc.labels.TryGetValue(jumpStmt.label.val, out stmtLabel)) 2242 if(!curDeclFunc.labels.TryGetValue(jumpStmt.label.val, out stmtLabel))
2502 { 2243 {
@@ -2509,9 +2250,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
2509 stmtLabel.labelTagged = true; 2250 stmtLabel.labelTagged = true;
2510 } 2251 }
2511 2252
2512 /* 2253 // Emit instructions to do the jump.
2513 * Emit instructions to do the jump.
2514 */
2515 EmitJumpCode(stmtLabel.labelStruct, stmtLabel.block, jumpStmt); 2254 EmitJumpCode(stmtLabel.labelStruct, stmtLabel.block, jumpStmt);
2516 } 2255 }
2517 2256
@@ -2522,20 +2261,17 @@ namespace OpenSim.Region.ScriptEngine.Yengine
2522 */ 2261 */
2523 private void EmitJumpCode(ScriptMyLabel target, TokenStmtBlock targetsBlock, Token errorAt) 2262 private void EmitJumpCode(ScriptMyLabel target, TokenStmtBlock targetsBlock, Token errorAt)
2524 { 2263 {
2525 /* 2264 // Jumps never fall through.
2526 * Jumps never fall through. 2265
2527 */
2528 mightGetHere = false; 2266 mightGetHere = false;
2529 2267
2530 /* 2268 // Find which block the target label is in. Must be in this or an outer block,
2531 * Find which block the target label is in. Must be in this or an outer block, 2269 // no laterals allowed. And if we exit a try/catch block, use Leave instead of Br.
2532 * no laterals allowed. And if we exit a try/catch block, use Leave instead of Br. 2270 //
2533 * 2271 // jump lateral;
2534 * jump lateral; 2272 // {
2535 * { 2273 // @lateral;
2536 * @lateral; 2274 // }
2537 * }
2538 */
2539 bool useLeave = false; 2275 bool useLeave = false;
2540 TokenStmtBlock stmtBlock; 2276 TokenStmtBlock stmtBlock;
2541 Stack<TokenStmtTry> finallyBlocksCalled = new Stack<TokenStmtTry>(); 2277 Stack<TokenStmtTry> finallyBlocksCalled = new Stack<TokenStmtTry>();
@@ -2559,46 +2295,44 @@ namespace OpenSim.Region.ScriptEngine.Yengine
2559 } 2295 }
2560 } 2296 }
2561 2297
2562 /* 2298 // If popping through more than one finally block, we have to break it down for the stack
2563 * If popping through more than one finally block, we have to break it down for the stack 2299 // capture and restore code, one finally block at a time.
2564 * capture and restore code, one finally block at a time. 2300 //
2565 * 2301 // try {
2566 * try { 2302 // try {
2567 * try { 2303 // try {
2568 * try { 2304 // jump exit;
2569 * jump exit; 2305 // } finally {
2570 * } finally { 2306 // llOwnerSay ("exiting inner");
2571 * llOwnerSay ("exiting inner"); 2307 // }
2572 * } 2308 // } finally {
2573 * } finally { 2309 // llOwnerSay ("exiting middle");
2574 * llOwnerSay ("exiting middle"); 2310 // }
2575 * } 2311 // } finally {
2576 * } finally { 2312 // llOwnerSay ("exiting outer");
2577 * llOwnerSay ("exiting outer"); 2313 // }
2578 * } 2314 // @exit;
2579 * @exit; 2315 //
2580 * 2316 // try {
2581 * try { 2317 // try {
2582 * try { 2318 // try {
2583 * try { 2319 // jump intr2_exit; <<< gets its own tryNo call label so inner try knows where to restore to
2584 * jump intr2_exit; <<< gets its own tryNo call label so inner try knows where to restore to 2320 // } finally {
2585 * } finally { 2321 // llOwnerSay ("exiting inner");
2586 * llOwnerSay ("exiting inner"); 2322 // }
2587 * } 2323 // jump outtry2;
2588 * jump outtry2; 2324 // @intr2_exit; jump intr1_exit; <<< gets its own tryNo call label so middle try knows where to restore to
2589 * @intr2_exit; jump intr1_exit; <<< gets its own tryNo call label so middle try knows where to restore to 2325 // @outtry2;
2590 * @outtry2; 2326 // } finally {
2591 * } finally { 2327 // llOwnerSay ("exiting middle");
2592 * llOwnerSay ("exiting middle"); 2328 // }
2593 * } 2329 // jump outtry1;
2594 * jump outtry1; 2330 // @intr1_exit: jump exit; <<< gets its own tryNo call label so outer try knows where to restore to
2595 * @intr1_exit: jump exit; <<< gets its own tryNo call label so outer try knows where to restore to 2331 // @outtry1;
2596 * @outtry1; 2332 // } finally {
2597 * } finally { 2333 // llOwnerSay ("exiting outer");
2598 * llOwnerSay ("exiting outer"); 2334 // }
2599 * } 2335 // @exit;
2600 * @exit;
2601 */
2602 int level = 0; 2336 int level = 0;
2603 while(finallyBlocksCalled.Count > 1) 2337 while(finallyBlocksCalled.Count > 1)
2604 { 2338 {
@@ -2615,12 +2349,10 @@ namespace OpenSim.Region.ScriptEngine.Yengine
2615 target = iLeave.jumpIntoLabel; 2349 target = iLeave.jumpIntoLabel;
2616 } 2350 }
2617 2351
2618 /* 2352 // Finally output the branch/leave opcode.
2619 * Finally output the branch/leave opcode. 2353 // If using Leave, prefix with a call label in case the corresponding finally block
2620 * If using Leave, prefix with a call label in case the corresponding finally block 2354 // calls CheckRun() and that CheckRun() captures the stack, it will have a point to
2621 * calls CheckRun() and that CheckRun() captures the stack, it will have a point to 2355 // restore to that will properly jump back into the finally block.
2622 * restore to that will properly jump back into the finally block.
2623 */
2624 if(useLeave) 2356 if(useLeave)
2625 { 2357 {
2626 new CallLabel(this, errorAt); 2358 new CallLabel(this, errorAt);
@@ -2650,13 +2382,11 @@ namespace OpenSim.Region.ScriptEngine.Yengine
2650 EmitCallCheckRun(labelStmt, false); 2382 EmitCallCheckRun(labelStmt, false);
2651 } 2383 }
2652 2384
2653 /* 2385 // We are going to say that the label falls through.
2654 * We are going to say that the label falls through. 2386 // It would be nice if we could analyze all referencing
2655 * It would be nice if we could analyze all referencing 2387 // goto's to see if all of them are not used but we are
2656 * goto's to see if all of them are not used but we are 2388 // going to assume that if the script writer put a label
2657 * going to assume that if the script writer put a label 2389 // somewhere, it is probably going to be used.
2658 * somewhere, it is probably going to be used.
2659 */
2660 mightGetHere = true; 2390 mightGetHere = true;
2661 } 2391 }
2662 2392
@@ -2670,34 +2400,26 @@ namespace OpenSim.Region.ScriptEngine.Yengine
2670 */ 2400 */
2671 private void GenerateStmtNewobj(TokenStmtNewobj newobjStmt) 2401 private void GenerateStmtNewobj(TokenStmtNewobj newobjStmt)
2672 { 2402 {
2673 /* 2403 // First off, malloc a new empty XMRSDTypeClObj object
2674 * First off, malloc a new empty XMRSDTypeClObj object 2404 // then call the XMRSDTypeClObj()-level constructor.
2675 * then call the XMRSDTypeClObj()-level constructor. 2405 // Store the result in local var $objptr.
2676 * Store the result in local var $objptr.
2677 */
2678 newobjStmt.objptrVar.location.PopPre(this, newobjStmt); 2406 newobjStmt.objptrVar.location.PopPre(this, newobjStmt);
2679 ilGen.Emit(newobjStmt, OpCodes.Ldarg_0); 2407 ilGen.Emit(newobjStmt, OpCodes.Ldarg_0);
2680 ilGen.Emit(newobjStmt, OpCodes.Ldc_I4, curDeclFunc.sdtClass.sdTypeIndex); 2408 ilGen.Emit(newobjStmt, OpCodes.Ldc_I4, curDeclFunc.sdtClass.sdTypeIndex);
2681 ilGen.Emit(newobjStmt, OpCodes.Newobj, sdtClassConstructorInfo); 2409 ilGen.Emit(newobjStmt, OpCodes.Newobj, sdtClassConstructorInfo);
2682 newobjStmt.objptrVar.location.PopPost(this, newobjStmt); 2410 newobjStmt.objptrVar.location.PopPost(this, newobjStmt);
2683 2411
2684 /* 2412 // Now call the script-level constructor.
2685 * Now call the script-level constructor. 2413 // Pass the object pointer in $objptr as it's 'this' argument.
2686 * Pass the object pointer in $objptr as it's 'this' argument. 2414 // The rest of the args are the script-visible args and are just copied from $new() call.
2687 * The rest of the args are the script-visible args and are just copied from $new() call.
2688 */
2689 GenerateFromRValCall(newobjStmt.rValCall); 2415 GenerateFromRValCall(newobjStmt.rValCall);
2690 2416
2691 /* 2417 // Put object pointer in retval so it gets returned to caller.
2692 * Put object pointer in retval so it gets returned to caller.
2693 */
2694 newobjStmt.objptrVar.location.PushVal(this, newobjStmt); 2418 newobjStmt.objptrVar.location.PushVal(this, newobjStmt);
2695 ilGen.Emit(newobjStmt, OpCodes.Stloc, retValue); 2419 ilGen.Emit(newobjStmt, OpCodes.Stloc, retValue);
2696 2420
2697 /* 2421 // Exit the function like a return statement.
2698 * Exit the function like a return statement. 2422 // And thus we don't fall through.
2699 * And thus we don't fall through.
2700 */
2701 ilGen.Emit(newobjStmt, OpCodes.Leave, retLabel); 2423 ilGen.Emit(newobjStmt, OpCodes.Leave, retLabel);
2702 mightGetHere = false; 2424 mightGetHere = false;
2703 } 2425 }
@@ -2740,10 +2462,8 @@ namespace OpenSim.Region.ScriptEngine.Yengine
2740 ilGen.Emit(retStmt, OpCodes.Stloc, retValue); 2462 ilGen.Emit(retStmt, OpCodes.Stloc, retValue);
2741 } 2463 }
2742 2464
2743 /* 2465 // Use a OpCodes.Leave instruction to break out of any try { } blocks.
2744 * Use a OpCodes.Leave instruction to break out of any try { } blocks. 2466 // All Leave's inside script-defined try { } need call labels (see GenerateStmtTry()).
2745 * All Leave's inside script-defined try { } need call labels (see GenerateStmtTry()).
2746 */
2747 bool brokeOutOfTry = false; 2467 bool brokeOutOfTry = false;
2748 for(TokenStmtBlock stmtBlock = curStmtBlock; stmtBlock != null; stmtBlock = stmtBlock.outerStmtBlock) 2468 for(TokenStmtBlock stmtBlock = curStmtBlock; stmtBlock != null; stmtBlock = stmtBlock.outerStmtBlock)
2749 { 2469 {
@@ -2759,9 +2479,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
2759 if(brokeOutOfTry) 2479 if(brokeOutOfTry)
2760 openCallLabel = null; 2480 openCallLabel = null;
2761 2481
2762 /* 2482 // 'return' statements never fall through.
2763 * 'return' statements never fall through.
2764 */
2765 mightGetHere = false; 2483 mightGetHere = false;
2766 } 2484 }
2767 2485
@@ -2787,10 +2505,8 @@ namespace OpenSim.Region.ScriptEngine.Yengine
2787 2505
2788 int index = 0; // 'default' state 2506 int index = 0; // 'default' state
2789 2507
2790 /* 2508 // Set new state value by throwing an exception.
2791 * Set new state value by throwing an exception. 2509 // These exceptions aren't catchable by script-level try { } catch { }.
2792 * These exceptions aren't catchable by script-level try { } catch { }.
2793 */
2794 if((stateStmt.state != null) && !stateIndices.TryGetValue(stateStmt.state.val, out index)) 2510 if((stateStmt.state != null) && !stateIndices.TryGetValue(stateStmt.state.val, out index))
2795 { 2511 {
2796 // The moron XEngine compiles scripts that reference undefined states. 2512 // The moron XEngine compiles scripts that reference undefined states.
@@ -2808,9 +2524,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
2808 } 2524 }
2809 ilGen.Emit(stateStmt, OpCodes.Throw); 2525 ilGen.Emit(stateStmt, OpCodes.Throw);
2810 2526
2811 /* 2527 // 'state' statements never fall through.
2812 * 'state' statements never fall through.
2813 */
2814 mightGetHere = false; 2528 mightGetHere = false;
2815 } 2529 }
2816 2530
@@ -2822,22 +2536,14 @@ namespace OpenSim.Region.ScriptEngine.Yengine
2822 if(!mightGetHere) 2536 if(!mightGetHere)
2823 return; 2537 return;
2824 2538
2825 /* 2539 // Output code to calculate index.
2826 * Output code to calculate index.
2827 */
2828 CompValu testRVal = GenerateFromRVal(switchStmt.testRVal); 2540 CompValu testRVal = GenerateFromRVal(switchStmt.testRVal);
2829 2541
2830 /* 2542 // Generate code based on string or integer index.
2831 * Generate code based on string or integer index.
2832 */
2833 if((testRVal.type is TokenTypeKey) || (testRVal.type is TokenTypeStr)) 2543 if((testRVal.type is TokenTypeKey) || (testRVal.type is TokenTypeStr))
2834 {
2835 GenerateStmtSwitchStr(testRVal, switchStmt); 2544 GenerateStmtSwitchStr(testRVal, switchStmt);
2836 }
2837 else 2545 else
2838 {
2839 GenerateStmtSwitchInt(testRVal, switchStmt); 2546 GenerateStmtSwitchInt(testRVal, switchStmt);
2840 }
2841 } 2547 }
2842 2548
2843 private void GenerateStmtSwitchInt(CompValu testRVal, TokenStmtSwitch switchStmt) 2549 private void GenerateStmtSwitchInt(CompValu testRVal, TokenStmtSwitch switchStmt)
@@ -2851,17 +2557,13 @@ namespace OpenSim.Region.ScriptEngine.Yengine
2851 2557
2852 curBreakTarg = new BreakContTarg(this, "switchbreak_" + switchStmt.Unique); 2558 curBreakTarg = new BreakContTarg(this, "switchbreak_" + switchStmt.Unique);
2853 2559
2854 /* 2560 // Build list of cases sorted by ascending values.
2855 * Build list of cases sorted by ascending values. 2561 // There should not be any overlapping of values.
2856 * There should not be any overlapping of values.
2857 */
2858 for(TokenSwitchCase thisCase = switchStmt.cases; thisCase != null; thisCase = thisCase.nextCase) 2562 for(TokenSwitchCase thisCase = switchStmt.cases; thisCase != null; thisCase = thisCase.nextCase)
2859 { 2563 {
2860 thisCase.label = ilGen.DefineLabel("case_" + thisCase.Unique); 2564 thisCase.label = ilGen.DefineLabel("case_" + thisCase.Unique);
2861 2565
2862 /* 2566 // The default case if any, goes in its own separate slot.
2863 * The default case if any, goes in its own separate slot.
2864 */
2865 if(thisCase.rVal1 == null) 2567 if(thisCase.rVal1 == null)
2866 { 2568 {
2867 if(defaultCase != null) 2569 if(defaultCase != null)
@@ -2875,9 +2577,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
2875 continue; 2577 continue;
2876 } 2578 }
2877 2579
2878 /* 2580 // Evaluate case operands, they must be compile-time integer constants.
2879 * Evaluate case operands, they must be compile-time integer constants.
2880 */
2881 CompValu rVal = GenerateFromRVal(thisCase.rVal1); 2581 CompValu rVal = GenerateFromRVal(thisCase.rVal1);
2882 if(!IsConstIntExpr(rVal, out thisCase.val1)) 2582 if(!IsConstIntExpr(rVal, out thisCase.val1))
2883 { 2583 {
@@ -2900,10 +2600,8 @@ namespace OpenSim.Region.ScriptEngine.Yengine
2900 return; 2600 return;
2901 } 2601 }
2902 2602
2903 /* 2603 // Insert into list, sorted by value.
2904 * Insert into list, sorted by value. 2604 // Note that both limits are inclusive.
2905 * Note that both limits are inclusive.
2906 */
2907 TokenSwitchCase lastCase = null; 2605 TokenSwitchCase lastCase = null;
2908 TokenSwitchCase nextCase; 2606 TokenSwitchCase nextCase;
2909 for(nextCase = sortedCases; nextCase != null; nextCase = nextCase.nextSortedCase) 2607 for(nextCase = sortedCases; nextCase != null; nextCase = nextCase.nextSortedCase)
@@ -2934,19 +2632,14 @@ namespace OpenSim.Region.ScriptEngine.Yengine
2934 defaultLabel = ilGen.DefineLabel("default_" + switchStmt.Unique); 2632 defaultLabel = ilGen.DefineLabel("default_" + switchStmt.Unique);
2935 } 2633 }
2936 2634
2937 /* 2635 // Output code to jump to the case statement's labels based on integer index on stack.
2938 * Output code to jump to the case statement's labels based on integer index on stack. 2636 // Note that each case still has the integer index on stack when jumped to.
2939 * Note that each case still has the integer index on stack when jumped to.
2940 */
2941 int offset = 0; 2637 int offset = 0;
2942 for(TokenSwitchCase thisCase = sortedCases; thisCase != null;) 2638 for(TokenSwitchCase thisCase = sortedCases; thisCase != null;)
2943 { 2639 {
2944 2640 // Scan through list of cases to find the maximum number of cases who's numvalues-to-case ratio
2945 /* 2641 // is from 0.5 to 2.0. If such a group is found, use a CIL switch for them. If not, just use a
2946 * Scan through list of cases to find the maximum number of cases who's numvalues-to-case ratio 2642 // compare-and-branch for the current case.
2947 * is from 0.5 to 2.0. If such a group is found, use a CIL switch for them. If not, just use a
2948 * compare-and-branch for the current case.
2949 */
2950 int numCases = 0; 2643 int numCases = 0;
2951 int numFound = 0; 2644 int numFound = 0;
2952 int lowValue = thisCase.val1; 2645 int lowValue = thisCase.val1;
@@ -2963,23 +2656,18 @@ namespace OpenSim.Region.ScriptEngine.Yengine
2963 } 2656 }
2964 if(numFound > 1) 2657 if(numFound > 1)
2965 { 2658 {
2966 2659 // There is a group of case's, starting with thisCase, that fall within our criteria, ie,
2967 /* 2660 // that have a nice density of meaningful jumps.
2968 * There is a group of case's, starting with thisCase, that fall within our criteria, ie, 2661 //
2969 * that have a nice density of meaningful jumps. 2662 // So first generate an array of jumps to the default label (explicit or implicit).
2970 *
2971 * So first generate an array of jumps to the default label (explicit or implicit).
2972 */
2973 ScriptMyLabel[] labels = new ScriptMyLabel[numValues]; 2663 ScriptMyLabel[] labels = new ScriptMyLabel[numValues];
2974 for(int i = 0; i < numValues; i++) 2664 for(int i = 0; i < numValues; i++)
2975 { 2665 {
2976 labels[i] = defaultLabel; 2666 labels[i] = defaultLabel;
2977 } 2667 }
2978 2668
2979 /* 2669 // Next, for each case in that group, fill in the corresponding array entries to jump to
2980 * Next, for each case in that group, fill in the corresponding array entries to jump to 2670 // that case's label.
2981 * that case's label.
2982 */
2983 do 2671 do
2984 { 2672 {
2985 for(int i = thisCase.val1; i <= thisCase.val2; i++) 2673 for(int i = thisCase.val1; i <= thisCase.val2; i++)
@@ -2989,10 +2677,8 @@ namespace OpenSim.Region.ScriptEngine.Yengine
2989 thisCase = thisCase.nextSortedCase; 2677 thisCase = thisCase.nextSortedCase;
2990 } while(--numFound > 0); 2678 } while(--numFound > 0);
2991 2679
2992 /* 2680 // Subtract the low value and do the computed jump.
2993 * Subtract the low value and do the computed jump. 2681 // The OpCodes.Switch falls through if out of range (unsigned compare).
2994 * The OpCodes.Switch falls through if out of range (unsigned compare).
2995 */
2996 if(offset != lowValue) 2682 if(offset != lowValue)
2997 { 2683 {
2998 ilGen.Emit(switchStmt, OpCodes.Ldc_I4, lowValue - offset); 2684 ilGen.Emit(switchStmt, OpCodes.Ldc_I4, lowValue - offset);
@@ -3004,11 +2690,8 @@ namespace OpenSim.Region.ScriptEngine.Yengine
3004 } 2690 }
3005 else 2691 else
3006 { 2692 {
3007 2693 // It's not economical to do with a computed jump, so output a subtract/compare/branch
3008 /* 2694 // for thisCase.
3009 * It's not economical to do with a computed jump, so output a subtract/compare/branch
3010 * for thisCase.
3011 */
3012 if(lowValue == thisCase.val2) 2695 if(lowValue == thisCase.val2)
3013 { 2696 {
3014 ilGen.Emit(switchStmt, OpCodes.Dup); 2697 ilGen.Emit(switchStmt, OpCodes.Dup);
@@ -3032,15 +2715,13 @@ namespace OpenSim.Region.ScriptEngine.Yengine
3032 } 2715 }
3033 ilGen.Emit(switchStmt, OpCodes.Br, defaultLabel); 2716 ilGen.Emit(switchStmt, OpCodes.Br, defaultLabel);
3034 2717
3035 /* 2718 // Output code for the cases themselves, in the order given by the programmer,
3036 * Output code for the cases themselves, in the order given by the programmer, 2719 // so they fall through as programmer wants. This includes the default case, if any.
3037 * so they fall through as programmer wants. This includes the default case, if any. 2720 //
3038 * 2721 // Each label is jumped to with the index still on the stack. So pop it off in case
3039 * Each label is jumped to with the index still on the stack. So pop it off in case 2722 // the case body does a goto outside the switch or a return. If the case body might
3040 * the case body does a goto outside the switch or a return. If the case body might 2723 // fall through to the next case or the bottom of the switch, push a zero so the stack
3041 * fall through to the next case or the bottom of the switch, push a zero so the stack 2724 // matches in all cases.
3042 * matches in all cases.
3043 */
3044 for(TokenSwitchCase thisCase = switchStmt.cases; thisCase != null; thisCase = thisCase.nextCase) 2725 for(TokenSwitchCase thisCase = switchStmt.cases; thisCase != null; thisCase = thisCase.nextCase)
3045 { 2726 {
3046 ilGen.MarkLabel(thisCase.label); // the branch comes here 2727 ilGen.MarkLabel(thisCase.label); // the branch comes here
@@ -3057,28 +2738,22 @@ namespace OpenSim.Region.ScriptEngine.Yengine
3057 } 2738 }
3058 } 2739 }
3059 2740
3060 /* 2741 // If no explicit default case, output the default label here.
3061 * If no explicit default case, output the default label here.
3062 */
3063 if(defaultCase == null) 2742 if(defaultCase == null)
3064 { 2743 {
3065 ilGen.MarkLabel(defaultLabel); 2744 ilGen.MarkLabel(defaultLabel);
3066 mightGetHere = true; 2745 mightGetHere = true;
3067 } 2746 }
3068 2747
3069 /* 2748 // If the last case of the switch falls through out the bottom,
3070 * If the last case of the switch falls through out the bottom, 2749 // we have to pop the index still on the stack.
3071 * we have to pop the index still on the stack.
3072 */
3073 if(mightGetHere) 2750 if(mightGetHere)
3074 { 2751 {
3075 ilGen.Emit(switchStmt, OpCodes.Pop); 2752 ilGen.Emit(switchStmt, OpCodes.Pop);
3076 } 2753 }
3077 2754
3078 /* 2755 // Output the 'break' statement target label.
3079 * Output the 'break' statement target label. 2756 // Note that the integer index is not on the stack at this point.
3080 * Note that the integer index is not on the stack at this point.
3081 */
3082 if(curBreakTarg.used) 2757 if(curBreakTarg.used)
3083 { 2758 {
3084 ilGen.MarkLabel(curBreakTarg.label); 2759 ilGen.MarkLabel(curBreakTarg.label);
@@ -3097,9 +2772,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
3097 2772
3098 curBreakTarg = new BreakContTarg(this, "switchbreak_" + switchStmt.Unique); 2773 curBreakTarg = new BreakContTarg(this, "switchbreak_" + switchStmt.Unique);
3099 2774
3100 /* 2775 // Make sure value is in a temp so we don't compute it more than once.
3101 * Make sure value is in a temp so we don't compute it more than once.
3102 */
3103 if(!(testRVal is CompValuTemp)) 2776 if(!(testRVal is CompValuTemp))
3104 { 2777 {
3105 CompValuTemp temp = new CompValuTemp(testRVal.type, this); 2778 CompValuTemp temp = new CompValuTemp(testRVal.type, this);
@@ -3108,17 +2781,13 @@ namespace OpenSim.Region.ScriptEngine.Yengine
3108 testRVal = temp; 2781 testRVal = temp;
3109 } 2782 }
3110 2783
3111 /* 2784 // Build tree of cases.
3112 * Build tree of cases. 2785 // There should not be any overlapping of values.
3113 * There should not be any overlapping of values.
3114 */
3115 for(TokenSwitchCase thisCase = switchStmt.cases; thisCase != null; thisCase = thisCase.nextCase) 2786 for(TokenSwitchCase thisCase = switchStmt.cases; thisCase != null; thisCase = thisCase.nextCase)
3116 { 2787 {
3117 thisCase.label = ilGen.DefineLabel("case"); 2788 thisCase.label = ilGen.DefineLabel("case");
3118 2789
3119 /* 2790 // The default case if any, goes in its own separate slot.
3120 * The default case if any, goes in its own separate slot.
3121 */
3122 if(thisCase.rVal1 == null) 2791 if(thisCase.rVal1 == null)
3123 { 2792 {
3124 if(defaultCase != null) 2793 if(defaultCase != null)
@@ -3132,9 +2801,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
3132 continue; 2801 continue;
3133 } 2802 }
3134 2803
3135 /* 2804 // Evaluate case operands, they must be compile-time string constants.
3136 * Evaluate case operands, they must be compile-time string constants.
3137 */
3138 CompValu rVal = GenerateFromRVal(thisCase.rVal1); 2805 CompValu rVal = GenerateFromRVal(thisCase.rVal1);
3139 if(!IsConstStrExpr(rVal, out thisCase.str1)) 2806 if(!IsConstStrExpr(rVal, out thisCase.str1))
3140 { 2807 {
@@ -3157,31 +2824,23 @@ namespace OpenSim.Region.ScriptEngine.Yengine
3157 continue; 2824 continue;
3158 } 2825 }
3159 2826
3160 /* 2827 // Insert into list, sorted by value.
3161 * Insert into list, sorted by value. 2828 // Note that both limits are inclusive.
3162 * Note that both limits are inclusive.
3163 */
3164 caseTreeTop = InsertCaseInTree(caseTreeTop, thisCase); 2829 caseTreeTop = InsertCaseInTree(caseTreeTop, thisCase);
3165 } 2830 }
3166 2831
3167 /* 2832 // Balance tree so we end up generating code that does O(log2 n) comparisons.
3168 * Balance tree so we end up generating code that does O(log2 n) comparisons.
3169 */
3170 caseTreeTop = BalanceTree(caseTreeTop); 2833 caseTreeTop = BalanceTree(caseTreeTop);
3171 2834
3172 /* 2835 // Output compare and branch instructions in a tree-like fashion so we do O(log2 n) comparisons.
3173 * Output compare and branch instructions in a tree-like fashion so we do O(log2 n) comparisons.
3174 */
3175 if(defaultLabel == null) 2836 if(defaultLabel == null)
3176 { 2837 {
3177 defaultLabel = ilGen.DefineLabel("default"); 2838 defaultLabel = ilGen.DefineLabel("default");
3178 } 2839 }
3179 OutputStrCase(testRVal, caseTreeTop, defaultLabel); 2840 OutputStrCase(testRVal, caseTreeTop, defaultLabel);
3180 2841
3181 /* 2842 // Output code for the cases themselves, in the order given by the programmer,
3182 * Output code for the cases themselves, in the order given by the programmer, 2843 // so they fall through as programmer wants. This includes the default case, if any.
3183 * so they fall through as programmer wants. This includes the default case, if any.
3184 */
3185 for(TokenSwitchCase thisCase = switchStmt.cases; thisCase != null; thisCase = thisCase.nextCase) 2844 for(TokenSwitchCase thisCase = switchStmt.cases; thisCase != null; thisCase = thisCase.nextCase)
3186 { 2845 {
3187 ilGen.MarkLabel(thisCase.label); // the branch comes here 2846 ilGen.MarkLabel(thisCase.label); // the branch comes here
@@ -3192,18 +2851,14 @@ namespace OpenSim.Region.ScriptEngine.Yengine
3192 } 2851 }
3193 } 2852 }
3194 2853
3195 /* 2854 // If no explicit default case, output the default label here.
3196 * If no explicit default case, output the default label here.
3197 */
3198 if(defaultCase == null) 2855 if(defaultCase == null)
3199 { 2856 {
3200 ilGen.MarkLabel(defaultLabel); 2857 ilGen.MarkLabel(defaultLabel);
3201 mightGetHere = true; 2858 mightGetHere = true;
3202 } 2859 }
3203 2860
3204 /* 2861 // Output the 'break' statement target label.
3205 * Output the 'break' statement target label.
3206 */
3207 if(curBreakTarg.used) 2862 if(curBreakTarg.used)
3208 { 2863 {
3209 ilGen.MarkLabel(curBreakTarg.label); 2864 ilGen.MarkLabel(curBreakTarg.label);
@@ -3268,10 +2923,8 @@ namespace OpenSim.Region.ScriptEngine.Yengine
3268 int hc = CountTree(r.higherCase); 2923 int hc = CountTree(r.higherCase);
3269 TokenSwitchCase n, x; 2924 TokenSwitchCase n, x;
3270 2925
3271 /* 2926 // If lower side is heavy, move highest nodes from lower side to
3272 * If lower side is heavy, move highest nodes from lower side to 2927 // higher side until balanced.
3273 * higher side until balanced.
3274 */
3275 while(lc > hc + 1) 2928 while(lc > hc + 1)
3276 { 2929 {
3277 x = ExtractHighest(r.lowerCase, out n); 2930 x = ExtractHighest(r.lowerCase, out n);
@@ -3283,10 +2936,8 @@ namespace OpenSim.Region.ScriptEngine.Yengine
3283 hc++; 2936 hc++;
3284 } 2937 }
3285 2938
3286 /* 2939 // If higher side is heavy, move lowest nodes from higher side to
3287 * If higher side is heavy, move lowest nodes from higher side to 2940 // lower side until balanced.
3288 * lower side until balanced.
3289 */
3290 while(hc > lc + 1) 2941 while(hc > lc + 1)
3291 { 2942 {
3292 x = ExtractLowest(r.higherCase, out n); 2943 x = ExtractLowest(r.higherCase, out n);
@@ -3298,9 +2949,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
3298 hc--; 2949 hc--;
3299 } 2950 }
3300 2951
3301 /* 2952 // Now balance each side because they can be lopsided individually.
3302 * Now balance each side because they can be lopsided individually.
3303 */
3304 r.lowerCase = BalanceTree(r.lowerCase); 2953 r.lowerCase = BalanceTree(r.lowerCase);
3305 r.higherCase = BalanceTree(r.higherCase); 2954 r.higherCase = BalanceTree(r.higherCase);
3306 return r; 2955 return r;
@@ -3359,10 +3008,8 @@ namespace OpenSim.Region.ScriptEngine.Yengine
3359 */ 3008 */
3360 private void OutputStrCase(CompValu testRVal, TokenSwitchCase thisCase, ScriptMyLabel defaultLabel) 3009 private void OutputStrCase(CompValu testRVal, TokenSwitchCase thisCase, ScriptMyLabel defaultLabel)
3361 { 3010 {
3362 /* 3011 // If nothing lower on tree and there is a single case value,
3363 * If nothing lower on tree and there is a single case value, 3012 // just do one compare for equality.
3364 * just do one compare for equality.
3365 */
3366 if((thisCase.lowerCase == null) && (thisCase.higherCase == null) && (thisCase.str1 == thisCase.str2)) 3013 if((thisCase.lowerCase == null) && (thisCase.higherCase == null) && (thisCase.str1 == thisCase.str2))
3367 { 3014 {
3368 testRVal.PushVal(this, thisCase, tokenTypeStr); 3015 testRVal.PushVal(this, thisCase, tokenTypeStr);
@@ -3374,28 +3021,22 @@ namespace OpenSim.Region.ScriptEngine.Yengine
3374 return; 3021 return;
3375 } 3022 }
3376 3023
3377 /* 3024 // Determine where to jump if switch value is lower than lower case value.
3378 * Determine where to jump if switch value is lower than lower case value.
3379 */
3380 ScriptMyLabel lowerLabel = defaultLabel; 3025 ScriptMyLabel lowerLabel = defaultLabel;
3381 if(thisCase.lowerCase != null) 3026 if(thisCase.lowerCase != null)
3382 { 3027 {
3383 lowerLabel = ilGen.DefineLabel("lower"); 3028 lowerLabel = ilGen.DefineLabel("lower");
3384 } 3029 }
3385 3030
3386 /* 3031 // If single case value, put comparison result in this temp.
3387 * If single case value, put comparison result in this temp.
3388 */
3389 CompValuTemp cmpv1 = null; 3032 CompValuTemp cmpv1 = null;
3390 if(thisCase.str1 == thisCase.str2) 3033 if(thisCase.str1 == thisCase.str2)
3391 { 3034 {
3392 cmpv1 = new CompValuTemp(tokenTypeInt, this); 3035 cmpv1 = new CompValuTemp(tokenTypeInt, this);
3393 } 3036 }
3394 3037
3395 /* 3038 // If switch value .lt. lower case value, jump to lower label.
3396 * If switch value .lt. lower case value, jump to lower label. 3039 // Maybe save comparison result in a temp.
3397 * Maybe save comparison result in a temp.
3398 */
3399 testRVal.PushVal(this, thisCase, tokenTypeStr); 3040 testRVal.PushVal(this, thisCase, tokenTypeStr);
3400 ilGen.Emit(thisCase, OpCodes.Ldstr, thisCase.str1); 3041 ilGen.Emit(thisCase, OpCodes.Ldstr, thisCase.str1);
3401 ilGen.Emit(thisCase, OpCodes.Ldc_I4, (int)StringComparison.Ordinal); 3042 ilGen.Emit(thisCase, OpCodes.Ldc_I4, (int)StringComparison.Ordinal);
@@ -3408,10 +3049,8 @@ namespace OpenSim.Region.ScriptEngine.Yengine
3408 ilGen.Emit(thisCase, OpCodes.Ldc_I4_0); 3049 ilGen.Emit(thisCase, OpCodes.Ldc_I4_0);
3409 ilGen.Emit(thisCase, OpCodes.Blt, lowerLabel); 3050 ilGen.Emit(thisCase, OpCodes.Blt, lowerLabel);
3410 3051
3411 /* 3052 // If switch value .le. higher case value, jump to case code.
3412 * If switch value .le. higher case value, jump to case code. 3053 // Maybe get comparison from the temp.
3413 * Maybe get comparison from the temp.
3414 */
3415 if(cmpv1 == null) 3054 if(cmpv1 == null)
3416 { 3055 {
3417 testRVal.PushVal(this, thisCase, tokenTypeStr); 3056 testRVal.PushVal(this, thisCase, tokenTypeStr);
@@ -3426,9 +3065,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
3426 ilGen.Emit(thisCase, OpCodes.Ldc_I4_0); 3065 ilGen.Emit(thisCase, OpCodes.Ldc_I4_0);
3427 ilGen.Emit(thisCase, OpCodes.Ble, thisCase.label); 3066 ilGen.Emit(thisCase, OpCodes.Ble, thisCase.label);
3428 3067
3429 /* 3068 // Output code for higher comparison if any.
3430 * Output code for higher comparison if any.
3431 */
3432 if(thisCase.higherCase == null) 3069 if(thisCase.higherCase == null)
3433 { 3070 {
3434 ilGen.Emit(thisCase, OpCodes.Br, defaultLabel); 3071 ilGen.Emit(thisCase, OpCodes.Br, defaultLabel);
@@ -3438,9 +3075,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
3438 OutputStrCase(testRVal, thisCase.higherCase, defaultLabel); 3075 OutputStrCase(testRVal, thisCase.higherCase, defaultLabel);
3439 } 3076 }
3440 3077
3441 /* 3078 // Output code for lower comparison if any.
3442 * Output code for lower comparison if any.
3443 */
3444 if(thisCase.lowerCase != null) 3079 if(thisCase.lowerCase != null)
3445 { 3080 {
3446 ilGen.MarkLabel(lowerLabel); 3081 ilGen.MarkLabel(lowerLabel);
@@ -3457,14 +3092,10 @@ namespace OpenSim.Region.ScriptEngine.Yengine
3457 if(!mightGetHere) 3092 if(!mightGetHere)
3458 return; 3093 return;
3459 3094
3460 /* 3095 // 'throw' statements never fall through.
3461 * 'throw' statements never fall through.
3462 */
3463 mightGetHere = false; 3096 mightGetHere = false;
3464 3097
3465 /* 3098 // Output code for either a throw or a rethrow.
3466 * Output code for either a throw or a rethrow.
3467 */
3468 if(throwStmt.rVal == null) 3099 if(throwStmt.rVal == null)
3469 { 3100 {
3470 for(TokenStmtBlock blk = curStmtBlock; blk != null; blk = blk.outerStmtBlock) 3101 for(TokenStmtBlock blk = curStmtBlock; blk != null; blk = blk.outerStmtBlock)
@@ -3506,24 +3137,18 @@ namespace OpenSim.Region.ScriptEngine.Yengine
3506 throw new Exception("can't have both catch and finally on same try"); 3137 throw new Exception("can't have both catch and finally on same try");
3507 } 3138 }
3508 3139
3509 /* 3140 // Stack the call labels.
3510 * Stack the call labels. 3141 // Try blocks have their own series of call labels.
3511 * Try blocks have their own series of call labels.
3512 */
3513 ScriptMyLocal saveCallNo = actCallNo; 3142 ScriptMyLocal saveCallNo = actCallNo;
3514 LinkedList<CallLabel> saveCallLabels = actCallLabels; 3143 LinkedList<CallLabel> saveCallLabels = actCallLabels;
3515 3144
3516 /* 3145 // Generate code for either try { } catch { } or try { } finally { }.
3517 * Generate code for either try { } catch { } or try { } finally { }.
3518 */
3519 if(tryStmt.catchStmt != null) 3146 if(tryStmt.catchStmt != null)
3520 GenerateStmtTryCatch(tryStmt); 3147 GenerateStmtTryCatch(tryStmt);
3521 if(tryStmt.finallyStmt != null) 3148 if(tryStmt.finallyStmt != null)
3522 GenerateStmtTryFinally(tryStmt); 3149 GenerateStmtTryFinally(tryStmt);
3523 3150
3524 /* 3151 // Restore call labels.
3525 * Restore call labels.
3526 */
3527 actCallNo = saveCallNo; 3152 actCallNo = saveCallNo;
3528 actCallLabels = saveCallLabels; 3153 actCallLabels = saveCallLabels;
3529 } 3154 }
@@ -4017,10 +3642,8 @@ namespace OpenSim.Region.ScriptEngine.Yengine
4017 */ 3642 */
4018 private void GenerateDeclVar(TokenDeclVar declVar) 3643 private void GenerateDeclVar(TokenDeclVar declVar)
4019 { 3644 {
4020 /* 3645 // Script gave us an initialization value, so just store init value in var like an assignment statement.
4021 * Script gave us an initialization value, so just store init value in var like an assignment statement. 3646 // If no init given, set it to its default value.
4022 * If no init given, set it to its default value.
4023 */
4024 CompValu local = declVar.location; 3647 CompValu local = declVar.location;
4025 if(declVar.init != null) 3648 if(declVar.init != null)
4026 { 3649 {
@@ -4070,14 +3693,10 @@ namespace OpenSim.Region.ScriptEngine.Yengine
4070 { 3693 {
4071 CompValu subCompValu; 3694 CompValu subCompValu;
4072 3695
4073 /* 3696 // Compute location of array itself.
4074 * Compute location of array itself.
4075 */
4076 CompValu baseCompValu = GenerateFromRVal(lVal.baseRVal); 3697 CompValu baseCompValu = GenerateFromRVal(lVal.baseRVal);
4077 3698
4078 /* 3699 // Maybe it is a fixed array access.
4079 * Maybe it is a fixed array access.
4080 */
4081 string basetypestring = baseCompValu.type.ToString(); 3700 string basetypestring = baseCompValu.type.ToString();
4082 if(basetypestring.EndsWith("]")) 3701 if(basetypestring.EndsWith("]"))
4083 { 3702 {
@@ -4106,9 +3725,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
4106 return new CompValuFixArEl(this, baseCompValu, subCompValus); 3725 return new CompValuFixArEl(this, baseCompValu, subCompValus);
4107 } 3726 }
4108 3727
4109 /* 3728 // Maybe it is accessing the $idxprop property of a script-defined class.
4110 * Maybe it is accessing the $idxprop property of a script-defined class.
4111 */
4112 if(baseCompValu.type is TokenTypeSDTypeClass) 3729 if(baseCompValu.type is TokenTypeSDTypeClass)
4113 { 3730 {
4114 TokenName name = new TokenName(lVal, "$idxprop"); 3731 TokenName name = new TokenName(lVal, "$idxprop");
@@ -4133,9 +3750,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
4133 3750
4134 } 3751 }
4135 3752
4136 /* 3753 // Maybe they are accessing $idxprop property of a script-defined interface.
4137 * Maybe they are accessing $idxprop property of a script-defined interface.
4138 */
4139 if(baseCompValu.type is TokenTypeSDTypeInterface) 3754 if(baseCompValu.type is TokenTypeSDTypeInterface)
4140 { 3755 {
4141 TokenName name = new TokenName(lVal, "$idxprop"); 3756 TokenName name = new TokenName(lVal, "$idxprop");
@@ -4152,27 +3767,21 @@ namespace OpenSim.Region.ScriptEngine.Yengine
4152 return new CompValuIdxProp(idxProp, baseCompValu, argTypes, compValus); 3767 return new CompValuIdxProp(idxProp, baseCompValu, argTypes, compValus);
4153 } 3768 }
4154 3769
4155 /* 3770 // Maybe it is extracting a character from a string.
4156 * Maybe it is extracting a character from a string.
4157 */
4158 if((baseCompValu.type is TokenTypeKey) || (baseCompValu.type is TokenTypeStr)) 3771 if((baseCompValu.type is TokenTypeKey) || (baseCompValu.type is TokenTypeStr))
4159 { 3772 {
4160 subCompValu = GenerateFromRVal(lVal.subRVal); 3773 subCompValu = GenerateFromRVal(lVal.subRVal);
4161 return new CompValuStrChr(new TokenTypeChar(lVal), baseCompValu, subCompValu); 3774 return new CompValuStrChr(new TokenTypeChar(lVal), baseCompValu, subCompValu);
4162 } 3775 }
4163 3776
4164 /* 3777 // Maybe it is extracting an element from a list.
4165 * Maybe it is extracting an element from a list.
4166 */
4167 if(baseCompValu.type is TokenTypeList) 3778 if(baseCompValu.type is TokenTypeList)
4168 { 3779 {
4169 subCompValu = GenerateFromRVal(lVal.subRVal); 3780 subCompValu = GenerateFromRVal(lVal.subRVal);
4170 return new CompValuListEl(new TokenTypeObject(lVal), baseCompValu, subCompValu); 3781 return new CompValuListEl(new TokenTypeObject(lVal), baseCompValu, subCompValu);
4171 } 3782 }
4172 3783
4173 /* 3784 // Access should be to XMR_Array otherwise.
4174 * Access should be to XMR_Array otherwise.
4175 */
4176 if(!(baseCompValu.type is TokenTypeArray)) 3785 if(!(baseCompValu.type is TokenTypeArray))
4177 { 3786 {
4178 ErrorMsg(lVal, "taking subscript of non-array"); 3787 ErrorMsg(lVal, "taking subscript of non-array");
@@ -4286,9 +3895,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
4286 CompValu baseRVal = GenerateFromRVal(lVal.baseRVal); 3895 CompValu baseRVal = GenerateFromRVal(lVal.baseRVal);
4287 string fieldName = lVal.fieldName.val + ArgSigString(argsig); 3896 string fieldName = lVal.fieldName.val + ArgSigString(argsig);
4288 3897
4289 /* 3898 // Maybe they are accessing an instance field, method or property of a script-defined class.
4290 * Maybe they are accessing an instance field, method or property of a script-defined class.
4291 */
4292 if(baseRVal.type is TokenTypeSDTypeClass) 3899 if(baseRVal.type is TokenTypeSDTypeClass)
4293 { 3900 {
4294 TokenTypeSDTypeClass sdtType = (TokenTypeSDTypeClass)baseRVal.type; 3901 TokenTypeSDTypeClass sdtType = (TokenTypeSDTypeClass)baseRVal.type;
@@ -4303,9 +3910,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
4303 return new CompValuVoid(lVal.fieldName); 3910 return new CompValuVoid(lVal.fieldName);
4304 } 3911 }
4305 3912
4306 /* 3913 // Maybe they are accessing a method or property of a script-defined interface.
4307 * Maybe they are accessing a method or property of a script-defined interface.
4308 */
4309 if(baseRVal.type is TokenTypeSDTypeInterface) 3914 if(baseRVal.type is TokenTypeSDTypeInterface)
4310 { 3915 {
4311 TokenTypeSDTypeInterface sdtType = (TokenTypeSDTypeInterface)baseRVal.type; 3916 TokenTypeSDTypeInterface sdtType = (TokenTypeSDTypeInterface)baseRVal.type;
@@ -4318,9 +3923,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
4318 return new CompValuVoid(lVal.fieldName); 3923 return new CompValuVoid(lVal.fieldName);
4319 } 3924 }
4320 3925
4321 /* 3926 // Since we only have a few built-in types with fields, just pound them out.
4322 * Since we only have a few built-in types with fields, just pound them out.
4323 */
4324 if(baseRVal.type is TokenTypeArray) 3927 if(baseRVal.type is TokenTypeArray)
4325 { 3928 {
4326 3929
@@ -4392,9 +3995,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
4392 */ 3995 */
4393 private CompValu GenerateFromLValName(TokenLValName lVal, TokenType[] argsig) 3996 private CompValu GenerateFromLValName(TokenLValName lVal, TokenType[] argsig)
4394 { 3997 {
4395 /* 3998 // Look in variable stack then look for built-in constants and functions.
4396 * Look in variable stack then look for built-in constants and functions.
4397 */
4398 TokenDeclVar var = FindNamedVar(lVal, argsig); 3999 TokenDeclVar var = FindNamedVar(lVal, argsig);
4399 if(var == null) 4000 if(var == null)
4400 { 4001 {
@@ -4402,9 +4003,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
4402 return new CompValuVoid(lVal); 4003 return new CompValuVoid(lVal);
4403 } 4004 }
4404 4005
4405 /* 4006 // Maybe it has an implied 'this.' on the front.
4406 * Maybe it has an implied 'this.' on the front.
4407 */
4408 if((var.sdtClass != null) && ((var.sdtFlags & ScriptReduce.SDT_STATIC) == 0)) 4007 if((var.sdtClass != null) && ((var.sdtFlags & ScriptReduce.SDT_STATIC) == 0))
4409 { 4008 {
4410 4009
@@ -4414,33 +4013,31 @@ namespace OpenSim.Region.ScriptEngine.Yengine
4414 return new CompValuVoid(lVal); 4013 return new CompValuVoid(lVal);
4415 } 4014 }
4416 4015
4417 /* 4016 // Don't allow something such as:
4418 * Don't allow something such as: 4017 //
4419 * 4018 // class A {
4420 * class A { 4019 // integer I;
4421 * integer I; 4020 // class B {
4422 * class B { 4021 // Print ()
4423 * Print () 4022 // {
4424 * { 4023 // llOwnerSay ("I=" + (string)I); <- access to I not allowed inside class B.
4425 * llOwnerSay ("I=" + (string)I); <- access to I not allowed inside class B. 4024 // explicit reference required as we don't
4426 * explicit reference required as we don't 4025 // have a valid reference to class A.
4427 * have a valid reference to class A. 4026 // }
4428 * } 4027 // }
4429 * } 4028 // }
4430 * } 4029 //
4431 * 4030 // But do allow something such as:
4432 * But do allow something such as: 4031 //
4433 * 4032 // class A {
4434 * class A { 4033 // integer I;
4435 * integer I; 4034 // }
4436 * } 4035 // class B : A {
4437 * class B : A { 4036 // Print ()
4438 * Print () 4037 // {
4439 * { 4038 // llOwnerSay ("I=" + (string)I);
4440 * llOwnerSay ("I=" + (string)I); 4039 // }
4441 * } 4040 // }
4442 * }
4443 */
4444 for(TokenDeclSDType c = curDeclFunc.sdtClass; c != var.sdtClass; c = c.extends) 4041 for(TokenDeclSDType c = curDeclFunc.sdtClass; c != var.sdtClass; c = c.extends)
4445 { 4042 {
4446 if(c == null) 4043 if(c == null)
@@ -4455,9 +4052,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
4455 return AccessInstanceMember(var, thisCompValu, lVal, false); 4052 return AccessInstanceMember(var, thisCompValu, lVal, false);
4456 } 4053 }
4457 4054
4458 /* 4055 // It's a local variable, static field, global, constant, etc.
4459 * It's a local variable, static field, global, constant, etc.
4460 */
4461 return var.location; 4056 return var.location;
4462 } 4057 }
4463 4058
@@ -4487,9 +4082,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
4487 TokenType stType = lVal.baseType; 4082 TokenType stType = lVal.baseType;
4488 string fieldName = lVal.fieldName.val + ArgSigString(argsig); 4083 string fieldName = lVal.fieldName.val + ArgSigString(argsig);
4489 4084
4490 /* 4085 // Maybe they are accessing a static member of a script-defined class.
4491 * Maybe they are accessing a static member of a script-defined class.
4492 */
4493 if(stType is TokenTypeSDTypeClass) 4086 if(stType is TokenTypeSDTypeClass)
4494 { 4087 {
4495 TokenTypeSDTypeClass sdtType = (TokenTypeSDTypeClass)stType; 4088 TokenTypeSDTypeClass sdtType = (TokenTypeSDTypeClass)stType;
@@ -4529,9 +4122,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
4529 { 4122 {
4530 errorMessageToken = rVal; 4123 errorMessageToken = rVal;
4531 4124
4532 /* 4125 // Maybe the expression can be converted to a constant.
4533 * Maybe the expression can be converted to a constant.
4534 */
4535 bool didOne; 4126 bool didOne;
4536 do 4127 do
4537 { 4128 {
@@ -4539,9 +4130,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
4539 rVal = rVal.TryComputeConstant(LookupBodyConstants, ref didOne); 4130 rVal = rVal.TryComputeConstant(LookupBodyConstants, ref didOne);
4540 } while(didOne); 4131 } while(didOne);
4541 4132
4542 /* 4133 // Generate code for the computation and return resulting type and location.
4543 * Generate code for the computation and return resulting type and location.
4544 */
4545 CompValu cVal = null; 4134 CompValu cVal = null;
4546 if(rVal is TokenRValAsnPost) 4135 if(rVal is TokenRValAsnPost)
4547 cVal = GenerateFromRValAsnPost((TokenRValAsnPost)rVal); 4136 cVal = GenerateFromRValAsnPost((TokenRValAsnPost)rVal);
@@ -4583,9 +4172,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
4583 if(cVal == null) 4172 if(cVal == null)
4584 throw new Exception("bad rval class " + rVal.GetType().ToString()); 4173 throw new Exception("bad rval class " + rVal.GetType().ToString());
4585 4174
4586 /* 4175 // Sanity check.
4587 * Sanity check.
4588 */
4589 if(!youveAnError) 4176 if(!youveAnError)
4590 { 4177 {
4591 if(cVal.type == null) 4178 if(cVal.type == null)
@@ -4616,30 +4203,21 @@ namespace OpenSim.Region.ScriptEngine.Yengine
4616 CompValu left, right; 4203 CompValu left, right;
4617 string opcodeIndex = token.opcode.ToString(); 4204 string opcodeIndex = token.opcode.ToString();
4618 4205
4619 /* 4206 // Comma operators are special, as they say to compute the left-hand value and
4620 * Comma operators are special, as they say to compute the left-hand value and 4207 // discard it, then compute the right-hand argument and that is the result.
4621 * discard it, then compute the right-hand argument and that is the result.
4622 */
4623 if(opcodeIndex == ",") 4208 if(opcodeIndex == ",")
4624 { 4209 {
4625 4210 // Compute left-hand operand but throw away result.
4626 /*
4627 * Compute left-hand operand but throw away result.
4628 */
4629 GenerateFromRVal(token.rValLeft); 4211 GenerateFromRVal(token.rValLeft);
4630 4212
4631 /* 4213 // Compute right-hand operand and that is the value of the expression.
4632 * Compute right-hand operand and that is the value of the expression.
4633 */
4634 return GenerateFromRVal(token.rValRight); 4214 return GenerateFromRVal(token.rValRight);
4635 } 4215 }
4636 4216
4637 /* 4217 // Simple overwriting assignments are their own special case,
4638 * Simple overwriting assignments are their own special case, 4218 // as we want to cast the R-value to the type of the L-value.
4639 * as we want to cast the R-value to the type of the L-value. 4219 // And in the case of delegates, we want to use the arg signature
4640 * And in the case of delegates, we want to use the arg signature 4220 // of the delegate to select which overloaded method to use.
4641 * of the delegate to select which overloaded method to use.
4642 */
4643 if(opcodeIndex == "=") 4221 if(opcodeIndex == "=")
4644 { 4222 {
4645 if(!(token.rValLeft is TokenLVal)) 4223 if(!(token.rValLeft is TokenLVal))
@@ -4655,26 +4233,19 @@ namespace OpenSim.Region.ScriptEngine.Yengine
4655 return left; 4233 return left;
4656 } 4234 }
4657 4235
4658 /* 4236 // There are String.Concat() methods available for 2, 3 and 4 operands.
4659 * There are String.Concat() methods available for 2, 3 and 4 operands. 4237 // So see if we have a string concat op and optimize if so.
4660 * So see if we have a string concat op and optimize if so.
4661 */
4662 if((opcodeIndex == "+") || 4238 if((opcodeIndex == "+") ||
4663 ((opcodeIndex == "+=") && 4239 ((opcodeIndex == "+=") &&
4664 (token.rValLeft is TokenLVal) && 4240 (token.rValLeft is TokenLVal) &&
4665 (token.rValLeft.GetRValType(this, null) is TokenTypeStr))) 4241 (token.rValLeft.GetRValType(this, null) is TokenTypeStr)))
4666 { 4242 {
4667 4243
4668 /* 4244 // We are adding something. Maybe it's a bunch of strings together.
4669 * We are adding something. Maybe it's a bunch of strings together.
4670 */
4671 List<TokenRVal> scorvs = new List<TokenRVal>(); 4245 List<TokenRVal> scorvs = new List<TokenRVal>();
4672 if(StringConcatOperands(token.rValLeft, token.rValRight, scorvs, token.opcode)) 4246 if(StringConcatOperands(token.rValLeft, token.rValRight, scorvs, token.opcode))
4673 { 4247 {
4674 4248 // Evaluate all the operands, right-to-left on purpose per LSL scripting.
4675 /*
4676 * Evaluate all the operands, right-to-left on purpose per LSL scripting.
4677 */
4678 int i; 4249 int i;
4679 int n = scorvs.Count; 4250 int n = scorvs.Count;
4680 CompValu[] scocvs = new CompValu[n]; 4251 CompValu[] scocvs = new CompValu[n];
@@ -4700,10 +4271,8 @@ namespace OpenSim.Region.ScriptEngine.Yengine
4700 } 4271 }
4701 retcv.PopPre(this, token); 4272 retcv.PopPre(this, token);
4702 4273
4703 /* 4274 // Call the String.Concat() methods, passing operands in left-to-right order.
4704 * Call the String.Concat() methods, passing operands in left-to-right order. 4275 // Force a cast to string (retcv.type) for each operand.
4705 * Force a cast to string (retcv.type) for each operand.
4706 */
4707 ++i; 4276 ++i;
4708 scocvs[i].PushVal(this, scorvs[i], retcv.type); 4277 scocvs[i].PushVal(this, scorvs[i], retcv.type);
4709 while(i + 3 < n) 4278 while(i + 3 < n)
@@ -4731,18 +4300,14 @@ namespace OpenSim.Region.ScriptEngine.Yengine
4731 ilGen.Emit(scorvs[i], OpCodes.Call, stringConcat2MethodInfo); 4300 ilGen.Emit(scorvs[i], OpCodes.Call, stringConcat2MethodInfo);
4732 } 4301 }
4733 4302
4734 /* 4303 // Put the result where we want it and return where we put it.
4735 * Put the result where we want it and return where we put it.
4736 */
4737 retcv.PopPost(this, token); 4304 retcv.PopPost(this, token);
4738 return retcv; 4305 return retcv;
4739 } 4306 }
4740 } 4307 }
4741 4308
4742 /* 4309 // If "&&&", it is a short-circuiting AND.
4743 * If "&&&", it is a short-circuiting AND. 4310 // Compute left-hand operand and if true, compute right-hand operand.
4744 * Compute left-hand operand and if true, compute right-hand operand.
4745 */
4746 if(opcodeIndex == "&&&") 4311 if(opcodeIndex == "&&&")
4747 { 4312 {
4748 bool leftVal, rightVal; 4313 bool leftVal, rightVal;
@@ -4791,10 +4356,8 @@ namespace OpenSim.Region.ScriptEngine.Yengine
4791 return new CompValuInteger(new TokenTypeInt(token), rightVal ? 1 : 0); 4356 return new CompValuInteger(new TokenTypeInt(token), rightVal ? 1 : 0);
4792 } 4357 }
4793 4358
4794 /* 4359 // If "|||", it is a short-circuiting OR.
4795 * If "|||", it is a short-circuiting OR. 4360 // Compute left-hand operand and if false, compute right-hand operand.
4796 * Compute left-hand operand and if false, compute right-hand operand.
4797 */
4798 if(opcodeIndex == "|||") 4361 if(opcodeIndex == "|||")
4799 { 4362 {
4800 bool leftVal, rightVal; 4363 bool leftVal, rightVal;
@@ -4843,17 +4406,13 @@ namespace OpenSim.Region.ScriptEngine.Yengine
4843 return new CompValuInteger(new TokenTypeInt(token), rightVal ? 1 : 0); 4406 return new CompValuInteger(new TokenTypeInt(token), rightVal ? 1 : 0);
4844 } 4407 }
4845 4408
4846 /* 4409 // Computation of some sort, compute right-hand operand value then left-hand value
4847 * Computation of some sort, compute right-hand operand value then left-hand value 4410 // because LSL is supposed to be right-to-left evaluation.
4848 * because LSL is supposed to be right-to-left evaluation.
4849 */
4850 right = Trivialize(GenerateFromRVal(token.rValRight), token.rValRight); 4411 right = Trivialize(GenerateFromRVal(token.rValRight), token.rValRight);
4851 4412
4852 /* 4413 // If left is a script-defined class and there is a method with the operator's name,
4853 * If left is a script-defined class and there is a method with the operator's name, 4414 // convert this to a call to that method with the right value as its single parameter.
4854 * convert this to a call to that method with the right value as its single parameter. 4415 // Except don't if the right value is 'undef' so they can always compare to undef.
4855 * Except don't if the right value is 'undef' so they can always compare to undef.
4856 */
4857 TokenType leftType = token.rValLeft.GetRValType(this, null); 4416 TokenType leftType = token.rValLeft.GetRValType(this, null);
4858 if((leftType is TokenTypeSDTypeClass) && !(right.type is TokenTypeUndef)) 4417 if((leftType is TokenTypeSDTypeClass) && !(right.type is TokenTypeUndef))
4859 { 4418 {
@@ -4872,28 +4431,21 @@ namespace OpenSim.Region.ScriptEngine.Yengine
4872 } 4431 }
4873 } 4432 }
4874 4433
4875 /* 4434 // Formulate key string for binOpStrings = (lefttype)(operator)(righttype)
4876 * Formulate key string for binOpStrings = (lefttype)(operator)(righttype)
4877 */
4878 string leftIndex = leftType.ToString(); 4435 string leftIndex = leftType.ToString();
4879 string rightIndex = right.type.ToString(); 4436 string rightIndex = right.type.ToString();
4880 string key = leftIndex + opcodeIndex + rightIndex; 4437 string key = leftIndex + opcodeIndex + rightIndex;
4881 4438
4882 /* 4439 // If that key exists in table, then the operation is defined between those types
4883 * If that key exists in table, then the operation is defined between those types 4440 // ... and it produces an R-value of type as given in the table.
4884 * ... and it produces an R-value of type as given in the table.
4885 */
4886 BinOpStr binOpStr; 4441 BinOpStr binOpStr;
4887 if(BinOpStr.defined.TryGetValue(key, out binOpStr)) 4442 if(BinOpStr.defined.TryGetValue(key, out binOpStr))
4888 { 4443 {
4889 4444 // If table contained an explicit assignment type like +=, output the statement without
4890 /* 4445 // casting the L-value, then return the L-value as the resultant value.
4891 * If table contained an explicit assignment type like +=, output the statement without 4446 //
4892 * casting the L-value, then return the L-value as the resultant value. 4447 // Make sure we don't include comparisons (such as ==, >=, etc).
4893 * 4448 // Nothing like +=, -=, %=, etc, generate a boolean, only the comparisons.
4894 * Make sure we don't include comparisons (such as ==, >=, etc).
4895 * Nothing like +=, -=, %=, etc, generate a boolean, only the comparisons.
4896 */
4897 if((binOpStr.outtype != typeof(bool)) && opcodeIndex.EndsWith("=") && (opcodeIndex != "!=")) 4449 if((binOpStr.outtype != typeof(bool)) && opcodeIndex.EndsWith("=") && (opcodeIndex != "!="))
4898 { 4450 {
4899 if(!(token.rValLeft is TokenLVal)) 4451 if(!(token.rValLeft is TokenLVal))
@@ -4906,21 +4458,17 @@ namespace OpenSim.Region.ScriptEngine.Yengine
4906 return left; 4458 return left;
4907 } 4459 }
4908 4460
4909 /* 4461 // It's of the form left binop right.
4910 * It's of the form left binop right. 4462 // Compute left, perform operation then put result in a temp.
4911 * Compute left, perform operation then put result in a temp.
4912 */
4913 left = GenerateFromRVal(token.rValLeft); 4463 left = GenerateFromRVal(token.rValLeft);
4914 CompValu retRVal = new CompValuTemp(TokenType.FromSysType(token.opcode, binOpStr.outtype), this); 4464 CompValu retRVal = new CompValuTemp(TokenType.FromSysType(token.opcode, binOpStr.outtype), this);
4915 binOpStr.emitBO(this, token, left, right, retRVal); 4465 binOpStr.emitBO(this, token, left, right, retRVal);
4916 return retRVal; 4466 return retRVal;
4917 } 4467 }
4918 4468
4919 /* 4469 // Nothing in the table, check for comparing object pointers because of the myriad of types possible.
4920 * Nothing in the table, check for comparing object pointers because of the myriad of types possible. 4470 // This will compare list pointers, null pointers, script-defined type pointers, array pointers, etc.
4921 * This will compare list pointers, null pointers, script-defined type pointers, array pointers, etc. 4471 // It will show equal iff the memory addresses are equal and that is good enough.
4922 * It will show equal iff the memory addresses are equal and that is good enough.
4923 */
4924 if(!leftType.ToSysType().IsValueType && !right.type.ToSysType().IsValueType && ((opcodeIndex == "==") || (opcodeIndex == "!="))) 4472 if(!leftType.ToSysType().IsValueType && !right.type.ToSysType().IsValueType && ((opcodeIndex == "==") || (opcodeIndex == "!=")))
4925 { 4473 {
4926 CompValuTemp retRVal = new CompValuTemp(new TokenTypeInt(token), this); 4474 CompValuTemp retRVal = new CompValuTemp(new TokenTypeInt(token), this);
@@ -4937,12 +4485,10 @@ namespace OpenSim.Region.ScriptEngine.Yengine
4937 return retRVal; 4485 return retRVal;
4938 } 4486 }
4939 4487
4940 /* 4488 // If the opcode ends with "=", it may be something like "+=".
4941 * If the opcode ends with "=", it may be something like "+=". 4489 // So look up the key as if we didn't have the "=" to tell us if the operation is legal.
4942 * So look up the key as if we didn't have the "=" to tell us if the operation is legal. 4490 // Also, the binary operation's output type must be the same as the L-value type.
4943 * Also, the binary operation's output type must be the same as the L-value type. 4491 // Likewise, integer += float not allowed because result is float, but float += integer is ok.
4944 * Likewise, integer += float not allowed because result is float, but float += integer is ok.
4945 */
4946 if(opcodeIndex.EndsWith("=")) 4492 if(opcodeIndex.EndsWith("="))
4947 { 4493 {
4948 key = leftIndex + opcodeIndex.Substring(0, opcodeIndex.Length - 1) + rightIndex; 4494 key = leftIndex + opcodeIndex.Substring(0, opcodeIndex.Length - 1) + rightIndex;
@@ -4959,9 +4505,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
4959 return new CompValuVoid(token); 4505 return new CompValuVoid(token);
4960 } 4506 }
4961 4507
4962 /* 4508 // Now we know for something like %= that left%right is legal for the types given.
4963 * Now we know for something like %= that left%right is legal for the types given.
4964 */
4965 left = GenerateFromLVal((TokenLVal)token.rValLeft); 4509 left = GenerateFromLVal((TokenLVal)token.rValLeft);
4966 if(binOpStr.outtype == leftType.ToSysType()) 4510 if(binOpStr.outtype == leftType.ToSysType())
4967 { 4511 {
@@ -4979,9 +4523,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
4979 } 4523 }
4980 } 4524 }
4981 4525
4982 /* 4526 // Can't find it, oh well.
4983 * Can't find it, oh well.
4984 */
4985 ErrorMsg(token, "op not defined: " + leftIndex + " " + opcodeIndex + " " + rightIndex); 4527 ErrorMsg(token, "op not defined: " + leftIndex + " " + opcodeIndex + " " + rightIndex);
4986 return new CompValuVoid(token); 4528 return new CompValuVoid(token);
4987 } 4529 }
@@ -5007,26 +4549,20 @@ namespace OpenSim.Region.ScriptEngine.Yengine
5007 if(!(leftType is TokenTypeStr) && !(rightType is TokenTypeStr)) 4549 if(!(leftType is TokenTypeStr) && !(rightType is TokenTypeStr))
5008 return false; 4550 return false;
5009 4551
5010 /* 4552 // Also, list+string => list so reject that too.
5011 * Also, list+string => list so reject that too. 4553 // Also, string+list => list so reject that too.
5012 * Also, string+list => list so reject that too.
5013 */
5014 if(leftType is TokenTypeList) 4554 if(leftType is TokenTypeList)
5015 return false; 4555 return false;
5016 if(rightType is TokenTypeList) 4556 if(rightType is TokenTypeList)
5017 return false; 4557 return false;
5018 4558
5019 /* 4559 // Append values to the end of the list in left-to-right order.
5020 * Append values to the end of the list in left-to-right order. 4560 // If value is formed from a something+something => string,
5021 * If value is formed from a something+something => string, 4561 // push them as separate values, otherwise push as one value.
5022 * push them as separate values, otherwise push as one value.
5023 */
5024 StringConcatOperand(leftType, leftRVal, scos); 4562 StringConcatOperand(leftType, leftRVal, scos);
5025 StringConcatOperand(rightType, rightRVal, scos); 4563 StringConcatOperand(rightType, rightRVal, scos);
5026 4564
5027 /* 4565 // Maybe constant strings can be concatted.
5028 * Maybe constant strings can be concatted.
5029 */
5030 try 4566 try
5031 { 4567 {
5032 int len; 4568 int len;
@@ -5044,9 +4580,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
5044 { 4580 {
5045 } 4581 }
5046 4582
5047 /* 4583 // We pushed some string stuff.
5048 * We pushed some string stuff.
5049 */
5050 return true; 4584 return true;
5051 } 4585 }
5052 4586
@@ -5090,9 +4624,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
5090 { 4624 {
5091 CompValu inRVal = GenerateFromRVal(token.rVal); 4625 CompValu inRVal = GenerateFromRVal(token.rVal);
5092 4626
5093 /* 4627 // Script-defined types can define their own methods to handle unary operators.
5094 * Script-defined types can define their own methods to handle unary operators.
5095 */
5096 if(inRVal.type is TokenTypeSDTypeClass) 4628 if(inRVal.type is TokenTypeSDTypeClass)
5097 { 4629 {
5098 TokenTypeSDTypeClass sdtType = (TokenTypeSDTypeClass)inRVal.type; 4630 TokenTypeSDTypeClass sdtType = (TokenTypeSDTypeClass)inRVal.type;
@@ -5107,9 +4639,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
5107 } 4639 }
5108 } 4640 }
5109 4641
5110 /* 4642 // Otherwise use the default.
5111 * Otherwise use the default.
5112 */
5113 return UnOpGenerate(inRVal, token.opcode); 4643 return UnOpGenerate(inRVal, token.opcode);
5114 } 4644 }
5115 4645
@@ -5120,26 +4650,18 @@ namespace OpenSim.Region.ScriptEngine.Yengine
5120 { 4650 {
5121 CompValu lVal = GenerateFromLVal(asnPost.lVal); 4651 CompValu lVal = GenerateFromLVal(asnPost.lVal);
5122 4652
5123 /* 4653 // Make up a temp to save original value in.
5124 * Make up a temp to save original value in.
5125 */
5126 CompValuTemp result = new CompValuTemp(lVal.type, this); 4654 CompValuTemp result = new CompValuTemp(lVal.type, this);
5127 4655
5128 /* 4656 // Prepare to pop incremented value back into variable being incremented.
5129 * Prepare to pop incremented value back into variable being incremented.
5130 */
5131 lVal.PopPre(this, asnPost.lVal); 4657 lVal.PopPre(this, asnPost.lVal);
5132 4658
5133 /* 4659 // Copy original value to temp and leave value on stack.
5134 * Copy original value to temp and leave value on stack.
5135 */
5136 lVal.PushVal(this, asnPost.lVal); 4660 lVal.PushVal(this, asnPost.lVal);
5137 ilGen.Emit(asnPost.lVal, OpCodes.Dup); 4661 ilGen.Emit(asnPost.lVal, OpCodes.Dup);
5138 result.Pop(this, asnPost.lVal); 4662 result.Pop(this, asnPost.lVal);
5139 4663
5140 /* 4664 // Perform the ++/--.
5141 * Perform the ++/--.
5142 */
5143 if((lVal.type is TokenTypeChar) || (lVal.type is TokenTypeInt)) 4665 if((lVal.type is TokenTypeChar) || (lVal.type is TokenTypeInt))
5144 { 4666 {
5145 ilGen.Emit(asnPost, OpCodes.Ldc_I4_1); 4667 ilGen.Emit(asnPost, OpCodes.Ldc_I4_1);
@@ -5170,9 +4692,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
5170 throw new Exception("unknown asnPost op"); 4692 throw new Exception("unknown asnPost op");
5171 } 4693 }
5172 4694
5173 /* 4695 // Store new value in original variable.
5174 * Store new value in original variable.
5175 */
5176 lVal.PopPost(this, asnPost.lVal); 4696 lVal.PopPost(this, asnPost.lVal);
5177 4697
5178 return result; 4698 return result;
@@ -5185,24 +4705,16 @@ namespace OpenSim.Region.ScriptEngine.Yengine
5185 { 4705 {
5186 CompValu lVal = GenerateFromLVal(asnPre.lVal); 4706 CompValu lVal = GenerateFromLVal(asnPre.lVal);
5187 4707
5188 /* 4708 // Make up a temp to put result in.
5189 * Make up a temp to put result in.
5190 */
5191 CompValuTemp result = new CompValuTemp(lVal.type, this); 4709 CompValuTemp result = new CompValuTemp(lVal.type, this);
5192 4710
5193 /* 4711 // Prepare to pop incremented value back into variable being incremented.
5194 * Prepare to pop incremented value back into variable being incremented.
5195 */
5196 lVal.PopPre(this, asnPre.lVal); 4712 lVal.PopPre(this, asnPre.lVal);
5197 4713
5198 /* 4714 // Push original value.
5199 * Push original value.
5200 */
5201 lVal.PushVal(this, asnPre.lVal); 4715 lVal.PushVal(this, asnPre.lVal);
5202 4716
5203 /* 4717 // Perform the ++/--.
5204 * Perform the ++/--.
5205 */
5206 if((lVal.type is TokenTypeChar) || (lVal.type is TokenTypeInt)) 4718 if((lVal.type is TokenTypeChar) || (lVal.type is TokenTypeInt))
5207 { 4719 {
5208 ilGen.Emit(asnPre, OpCodes.Ldc_I4_1); 4720 ilGen.Emit(asnPre, OpCodes.Ldc_I4_1);
@@ -5233,15 +4745,11 @@ namespace OpenSim.Region.ScriptEngine.Yengine
5233 throw new Exception("unknown asnPre op"); 4745 throw new Exception("unknown asnPre op");
5234 } 4746 }
5235 4747
5236 /* 4748 // Store new value in temp variable, keeping new value on stack.
5237 * Store new value in temp variable, keeping new value on stack.
5238 */
5239 ilGen.Emit(asnPre.lVal, OpCodes.Dup); 4749 ilGen.Emit(asnPre.lVal, OpCodes.Dup);
5240 result.Pop(this, asnPre.lVal); 4750 result.Pop(this, asnPre.lVal);
5241 4751
5242 /* 4752 // Store new value in original variable.
5243 * Store new value in original variable.
5244 */
5245 lVal.PopPost(this, asnPre.lVal); 4753 lVal.PopPost(this, asnPre.lVal);
5246 4754
5247 return result; 4755 return result;
@@ -5259,11 +4767,9 @@ namespace OpenSim.Region.ScriptEngine.Yengine
5259 TokenRVal arg; 4767 TokenRVal arg;
5260 TokenType[] argTypes; 4768 TokenType[] argTypes;
5261 4769
5262 /* 4770 // Compute the values of all the function's call arguments.
5263 * Compute the values of all the function's call arguments. 4771 // Save where the computation results are in the argRVals[] array.
5264 * Save where the computation results are in the argRVals[] array. 4772 // Might as well build the argument signature from the argument types, too.
5265 * Might as well build the argument signature from the argument types, too.
5266 */
5267 nargs = call.nArgs; 4773 nargs = call.nArgs;
5268 argRVals = new CompValu[nargs]; 4774 argRVals = new CompValu[nargs];
5269 argTypes = new TokenType[nargs]; 4775 argTypes = new TokenType[nargs];
@@ -5278,9 +4784,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
5278 } 4784 }
5279 } 4785 }
5280 4786
5281 /* 4787 // Get function/method's entrypoint that matches the call argument types.
5282 * Get function/method's entrypoint that matches the call argument types.
5283 */
5284 method = GenerateFromRVal(call.meth, argTypes); 4788 method = GenerateFromRVal(call.meth, argTypes);
5285 if(method == null) 4789 if(method == null)
5286 return null; 4790 return null;
@@ -5302,9 +4806,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
5302 TokenType retType; 4806 TokenType retType;
5303 TokenType[] argTypes; 4807 TokenType[] argTypes;
5304 4808
5305 /* 4809 // Must be some kind of callable.
5306 * Must be some kind of callable.
5307 */
5308 retType = method.GetRetType(); // TokenTypeVoid if void; null means a variable 4810 retType = method.GetRetType(); // TokenTypeVoid if void; null means a variable
5309 if(retType == null) 4811 if(retType == null)
5310 { 4812 {
@@ -5312,9 +4814,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
5312 return new CompValuVoid(call); 4814 return new CompValuVoid(call);
5313 } 4815 }
5314 4816
5315 /* 4817 // Get a location for return value.
5316 * Get a location for return value.
5317 */
5318 if(retType is TokenTypeVoid) 4818 if(retType is TokenTypeVoid)
5319 { 4819 {
5320 result = new CompValuVoid(call); 4820 result = new CompValuVoid(call);
@@ -5324,10 +4824,8 @@ namespace OpenSim.Region.ScriptEngine.Yengine
5324 result = new CompValuTemp(retType, this); 4824 result = new CompValuTemp(retType, this);
5325 } 4825 }
5326 4826
5327 /* 4827 // Make sure all arguments are trivial, ie, don't involve their own call labels.
5328 * Make sure all arguments are trivial, ie, don't involve their own call labels. 4828 // For any that aren't, output code to calculate the arg and put in a temporary.
5329 * For any that aren't, output code to calculate the arg and put in a temporary.
5330 */
5331 nArgs = argRVals.Length; 4829 nArgs = argRVals.Length;
5332 for(i = 0; i < nArgs; i++) 4830 for(i = 0; i < nArgs; i++)
5333 { 4831 {
@@ -5337,9 +4835,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
5337 } 4835 }
5338 } 4836 }
5339 4837
5340 /* 4838 // Inline functions know how to generate their own call.
5341 * Inline functions know how to generate their own call.
5342 */
5343 if(method is CompValuInline) 4839 if(method is CompValuInline)
5344 { 4840 {
5345 CompValuInline inline = (CompValuInline)method; 4841 CompValuInline inline = (CompValuInline)method;
@@ -5347,14 +4843,10 @@ namespace OpenSim.Region.ScriptEngine.Yengine
5347 return result; 4843 return result;
5348 } 4844 }
5349 4845
5350 /* 4846 // Push whatever the function/method needs as a this argument, if anything.
5351 * Push whatever the function/method needs as a this argument, if anything.
5352 */
5353 method.CallPre(this, call); 4847 method.CallPre(this, call);
5354 4848
5355 /* 4849 // Push the script-visible args, left-to-right.
5356 * Push the script-visible args, left-to-right.
5357 */
5358 argTypes = method.GetArgTypes(); 4850 argTypes = method.GetArgTypes();
5359 for(i = 0; i < nArgs; i++) 4851 for(i = 0; i < nArgs; i++)
5360 { 4852 {
@@ -5368,14 +4860,10 @@ namespace OpenSim.Region.ScriptEngine.Yengine
5368 } 4860 }
5369 } 4861 }
5370 4862
5371 /* 4863 // Now output call instruction.
5372 * Now output call instruction.
5373 */
5374 method.CallPost(this, call); 4864 method.CallPost(this, call);
5375 4865
5376 /* 4866 // Deal with the return value (if any), by putting it in 'result'.
5377 * Deal with the return value (if any), by putting it in 'result'.
5378 */
5379 result.Pop(this, call, retType); 4867 result.Pop(this, call, retType);
5380 return result; 4868 return result;
5381 } 4869 }
@@ -5402,13 +4890,11 @@ namespace OpenSim.Region.ScriptEngine.Yengine
5402 */ 4890 */
5403 private CompValu GenerateFromRValCast(TokenRValCast cast) 4891 private CompValu GenerateFromRValCast(TokenRValCast cast)
5404 { 4892 {
5405 /* 4893 // If casting to a delegate type, use the argment signature
5406 * If casting to a delegate type, use the argment signature 4894 // of the delegate to help select the function/method, eg,
5407 * of the delegate to help select the function/method, eg, 4895 // '(delegate string(integer))ToString'
5408 * '(delegate string(integer))ToString' 4896 // will select 'string ToString(integer x)'
5409 * will select 'string ToString(integer x)' 4897 // instaead of 'string ToString(float x)' or anything else
5410 * instaead of 'string ToString(float x)' or anything else
5411 */
5412 TokenType[] argsig = null; 4898 TokenType[] argsig = null;
5413 TokenType outType = cast.castTo; 4899 TokenType outType = cast.castTo;
5414 if(outType is TokenTypeSDTypeDelegate) 4900 if(outType is TokenTypeSDTypeDelegate)
@@ -5416,17 +4902,13 @@ namespace OpenSim.Region.ScriptEngine.Yengine
5416 argsig = ((TokenTypeSDTypeDelegate)outType).decl.GetArgTypes(); 4902 argsig = ((TokenTypeSDTypeDelegate)outType).decl.GetArgTypes();
5417 } 4903 }
5418 4904
5419 /* 4905 // Generate the value that is being cast.
5420 * Generate the value that is being cast. 4906 // If the value is already the requested type, just use it as is.
5421 * If the value is already the requested type, just use it as is.
5422 */
5423 CompValu inRVal = GenerateFromRVal(cast.rVal, argsig); 4907 CompValu inRVal = GenerateFromRVal(cast.rVal, argsig);
5424 if(inRVal.type == outType) 4908 if(inRVal.type == outType)
5425 return inRVal; 4909 return inRVal;
5426 4910
5427 /* 4911 // Different type, generate casting code, putting the result in a temp of the output type.
5428 * Different type, generate casting code, putting the result in a temp of the output type.
5429 */
5430 CompValu outRVal = new CompValuTemp(outType, this); 4912 CompValu outRVal = new CompValuTemp(outType, this);
5431 outRVal.PopPre(this, cast); 4913 outRVal.PopPre(this, cast);
5432 inRVal.PushVal(this, cast, outType, true); 4914 inRVal.PushVal(this, cast, outType, true);
@@ -5511,10 +4993,8 @@ namespace OpenSim.Region.ScriptEngine.Yengine
5511 */ 4993 */
5512 private CompValu GenerateFromRValList(TokenRValList rValList) 4994 private CompValu GenerateFromRValList(TokenRValList rValList)
5513 { 4995 {
5514 /* 4996 // Compute all element values and remember where we put them.
5515 * Compute all element values and remember where we put them. 4997 // Do it right-to-left as customary for LSL scripts.
5516 * Do it right-to-left as customary for LSL scripts.
5517 */
5518 int i = 0; 4998 int i = 0;
5519 TokenRVal lastRVal = null; 4999 TokenRVal lastRVal = null;
5520 for(TokenRVal val = rValList.rVal; val != null; val = (TokenRVal)val.nextToken) 5000 for(TokenRVal val = rValList.rVal; val != null; val = (TokenRVal)val.nextToken)
@@ -5529,43 +5009,31 @@ namespace OpenSim.Region.ScriptEngine.Yengine
5529 vals[--i] = GenerateFromRVal(val); 5009 vals[--i] = GenerateFromRVal(val);
5530 } 5010 }
5531 5011
5532 /* 5012 // This is the temp that will hold the created list.
5533 * This is the temp that will hold the created list.
5534 */
5535 CompValuTemp newList = new CompValuTemp(new TokenTypeList(rValList.rVal), this); 5013 CompValuTemp newList = new CompValuTemp(new TokenTypeList(rValList.rVal), this);
5536 5014
5537 /* 5015 // Create a temp object[] array to hold all the initial values.
5538 * Create a temp object[] array to hold all the initial values.
5539 */
5540 ilGen.Emit(rValList, OpCodes.Ldc_I4, rValList.nItems); 5016 ilGen.Emit(rValList, OpCodes.Ldc_I4, rValList.nItems);
5541 ilGen.Emit(rValList, OpCodes.Newarr, typeof(object)); 5017 ilGen.Emit(rValList, OpCodes.Newarr, typeof(object));
5542 5018
5543 /* 5019 // Populate the array.
5544 * Populate the array.
5545 */
5546 i = 0; 5020 i = 0;
5547 for(TokenRVal val = rValList.rVal; val != null; val = (TokenRVal)val.nextToken) 5021 for(TokenRVal val = rValList.rVal; val != null; val = (TokenRVal)val.nextToken)
5548 { 5022 {
5549 5023
5550 /* 5024 // Get pointer to temp array object.
5551 * Get pointer to temp array object.
5552 */
5553 ilGen.Emit(rValList, OpCodes.Dup); 5025 ilGen.Emit(rValList, OpCodes.Dup);
5554 5026
5555 /* 5027 // Get index in that array.
5556 * Get index in that array.
5557 */
5558 ilGen.Emit(rValList, OpCodes.Ldc_I4, i); 5028 ilGen.Emit(rValList, OpCodes.Ldc_I4, i);
5559 5029
5560 /* 5030 // Store initialization value in array location.
5561 * Store initialization value in array location. 5031 // However, floats and ints need to be converted to LSL_Float and LSL_Integer,
5562 * However, floats and ints need to be converted to LSL_Float and LSL_Integer, 5032 // or things like llSetPayPrice() will puque when they try to cast the elements
5563 * or things like llSetPayPrice() will puque when they try to cast the elements 5033 // to LSL_Float or LSL_Integer. Likewise with string/LSL_String.
5564 * to LSL_Float or LSL_Integer. Likewise with string/LSL_String. 5034 //
5565 * 5035 // Maybe it's already LSL-boxed so we don't do anything with it except make sure
5566 * Maybe it's already LSL-boxed so we don't do anything with it except make sure 5036 // it is an object, not a struct.
5567 * it is an object, not a struct.
5568 */
5569 CompValu eRVal = vals[i++]; 5037 CompValu eRVal = vals[i++];
5570 eRVal.PushVal(this, val); 5038 eRVal.PushVal(this, val);
5571 if(eRVal.type.ToLSLWrapType() == null) 5039 if(eRVal.type.ToLSLWrapType() == null)
@@ -5599,9 +5067,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
5599 ilGen.Emit(val, OpCodes.Stelem, typeof(object)); 5067 ilGen.Emit(val, OpCodes.Stelem, typeof(object));
5600 } 5068 }
5601 5069
5602 /* 5070 // Create new list object from temp initial value array (whose ref is still on the stack).
5603 * Create new list object from temp initial value array (whose ref is still on the stack).
5604 */
5605 ilGen.Emit(rValList, OpCodes.Newobj, lslListConstructorInfo); 5071 ilGen.Emit(rValList, OpCodes.Newobj, lslListConstructorInfo);
5606 newList.Pop(this, rValList); 5072 newList.Pop(this, rValList);
5607 return newList; 5073 return newList;
@@ -5717,44 +5183,31 @@ namespace OpenSim.Region.ScriptEngine.Yengine
5717 { 5183 {
5718 CompValu initValue = null; 5184 CompValu initValue = null;
5719 5185
5720 /* 5186 // If it is a sublist, process it.
5721 * If it is a sublist, process it. 5187 // If we don't have enough subscripts yet, hopefully that sublist will have enough.
5722 * If we don't have enough subscripts yet, hopefully that sublist will have enough. 5188 // If we already have enough subscripts, then that sublist can be for an element of this supposedly jagged array.
5723 * If we already have enough subscripts, then that sublist can be for an element of this supposedly jagged array.
5724 */
5725 if(val is TokenList) 5189 if(val is TokenList)
5726 { 5190 {
5727 TokenList sublist = (TokenList)val; 5191 TokenList sublist = (TokenList)val;
5728 if(dimNo + 1 < rank) 5192 if(dimNo + 1 < rank)
5729 { 5193 {
5730 5194 // We don't have enough subscripts yet, hopefully the sublist has the rest.
5731 /*
5732 * We don't have enough subscripts yet, hopefully the sublist has the rest.
5733 */
5734 FillInInitVals(array, setMeth, subscripts, dimNo + 1, rank, sublist, eleType); 5195 FillInInitVals(array, setMeth, subscripts, dimNo + 1, rank, sublist, eleType);
5735 } 5196 }
5736 else if((eleType is TokenTypeSDTypeClass) && (((TokenTypeSDTypeClass)eleType).decl.arrayOfType == null)) 5197 else if((eleType is TokenTypeSDTypeClass) && (((TokenTypeSDTypeClass)eleType).decl.arrayOfType == null))
5737 { 5198 {
5738 5199 // If we aren't a jagged array either, we can't do anything with the sublist.
5739 /*
5740 * If we aren't a jagged array either, we can't do anything with the sublist.
5741 */
5742 ErrorMsg(val, "too many brace levels"); 5200 ErrorMsg(val, "too many brace levels");
5743 } 5201 }
5744 else 5202 else
5745 { 5203 {
5746 5204 // We are a jagged array, so malloc a subarray and initialize it with the sublist.
5747 /* 5205 // Then we can use that subarray to fill this array's element.
5748 * We are a jagged array, so malloc a subarray and initialize it with the sublist.
5749 * Then we can use that subarray to fill this array's element.
5750 */
5751 initValue = MallocAndInitArray(eleType, sublist); 5206 initValue = MallocAndInitArray(eleType, sublist);
5752 } 5207 }
5753 } 5208 }
5754 5209
5755 /* 5210 // If it is a value expression, then output code to compute the value.
5756 * If it is a value expression, then output code to compute the value.
5757 */
5758 if(val is TokenRVal) 5211 if(val is TokenRVal)
5759 { 5212 {
5760 if(dimNo + 1 < rank) 5213 if(dimNo + 1 < rank)
@@ -5767,9 +5220,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
5767 } 5220 }
5768 } 5221 }
5769 5222
5770 /* 5223 // If there is an initValue, output "array.Set (subscript[0], subscript[1], ..., initValue)"
5771 * If there is an initValue, output "array.Set (subscript[0], subscript[1], ..., initValue)"
5772 */
5773 if(initValue != null) 5224 if(initValue != null)
5774 { 5225 {
5775 array.PushVal(this, val); 5226 array.PushVal(this, val);
@@ -5781,9 +5232,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
5781 ilGen.Emit(val, OpCodes.Call, setMeth.ilGen); 5232 ilGen.Emit(val, OpCodes.Call, setMeth.ilGen);
5782 } 5233 }
5783 5234
5784 /* 5235 // That subscript is processed one way or another, on to the next.
5785 * That subscript is processed one way or another, on to the next.
5786 */
5787 subscripts[dimNo]++; 5236 subscripts[dimNo]++;
5788 } 5237 }
5789 } 5238 }
@@ -5894,19 +5343,15 @@ namespace OpenSim.Region.ScriptEngine.Yengine
5894 return new CompValuVoid(type); 5343 return new CompValuVoid(type);
5895 } 5344 }
5896 5345
5897 /* 5346 // Default for 'object' type is 'undef'.
5898 * Default for 'object' type is 'undef'. 5347 // Likewise for script-defined classes and interfaces.
5899 * Likewise for script-defined classes and interfaces.
5900 */
5901 if((type is TokenTypeObject) || (type is TokenTypeSDTypeClass) || (type is TokenTypeSDTypeDelegate) || 5348 if((type is TokenTypeObject) || (type is TokenTypeSDTypeClass) || (type is TokenTypeSDTypeDelegate) ||
5902 (type is TokenTypeSDTypeInterface) || (type is TokenTypeExc)) 5349 (type is TokenTypeSDTypeInterface) || (type is TokenTypeExc))
5903 { 5350 {
5904 return new CompValuNull(type); 5351 return new CompValuNull(type);
5905 } 5352 }
5906 5353
5907 /* 5354 // array and list
5908 * array and list
5909 */
5910 CompValuTemp temp = new CompValuTemp(type, this); 5355 CompValuTemp temp = new CompValuTemp(type, this);
5911 PushDefaultValue(type); 5356 PushDefaultValue(type);
5912 temp.Pop(this, rValInitDef, type); 5357 temp.Pop(this, rValInitDef, type);
@@ -5918,14 +5363,10 @@ namespace OpenSim.Region.ScriptEngine.Yengine
5918 */ 5363 */
5919 private CompValu GenerateFromRValIsType(TokenRValIsType rValIsType) 5364 private CompValu GenerateFromRValIsType(TokenRValIsType rValIsType)
5920 { 5365 {
5921 /* 5366 // Expression we want to know the type of.
5922 * Expression we want to know the type of.
5923 */
5924 CompValu val = GenerateFromRVal(rValIsType.rValExp); 5367 CompValu val = GenerateFromRVal(rValIsType.rValExp);
5925 5368
5926 /* 5369 // Pass it in to top-level type expression decoder.
5927 * Pass it in to top-level type expression decoder.
5928 */
5929 return GenerateFromTypeExp(val, rValIsType.typeExp); 5370 return GenerateFromTypeExp(val, rValIsType.typeExp);
5930 } 5371 }
5931 5372
@@ -6062,28 +5503,22 @@ namespace OpenSim.Region.ScriptEngine.Yengine
6062 return; 5503 return;
6063 } 5504 }
6064 5505
6065 /* 5506 // Default for 'object' type is 'undef'.
6066 * Default for 'object' type is 'undef'. 5507 // Likewise for script-defined classes and interfaces.
6067 * Likewise for script-defined classes and interfaces.
6068 */
6069 if((type is TokenTypeObject) || (type is TokenTypeSDTypeClass) || (type is TokenTypeSDTypeInterface) || (type is TokenTypeExc)) 5508 if((type is TokenTypeObject) || (type is TokenTypeSDTypeClass) || (type is TokenTypeSDTypeInterface) || (type is TokenTypeExc))
6070 { 5509 {
6071 ilGen.Emit(type, OpCodes.Ldnull); 5510 ilGen.Emit(type, OpCodes.Ldnull);
6072 return; 5511 return;
6073 } 5512 }
6074 5513
6075 /* 5514 // Void is pushed as the default return value of a void function.
6076 * Void is pushed as the default return value of a void function. 5515 // So just push nothing as expected of void functions.
6077 * So just push nothing as expected of void functions.
6078 */
6079 if(type is TokenTypeVoid) 5516 if(type is TokenTypeVoid)
6080 { 5517 {
6081 return; 5518 return;
6082 } 5519 }
6083 5520
6084 /* 5521 // Default for 'delegate' type is 'undef'.
6085 * Default for 'delegate' type is 'undef'.
6086 */
6087 if(type is TokenTypeSDTypeDelegate) 5522 if(type is TokenTypeSDTypeDelegate)
6088 { 5523 {
6089 ilGen.Emit(type, OpCodes.Ldnull); 5524 ilGen.Emit(type, OpCodes.Ldnull);
@@ -6186,16 +5621,12 @@ namespace OpenSim.Region.ScriptEngine.Yengine
6186 */ 5621 */
6187 private static VarDict CreateLegalEventHandlers() 5622 private static VarDict CreateLegalEventHandlers()
6188 { 5623 {
6189 /* 5624 // Get handler prototypes with full argument lists.
6190 * Get handler prototypes with full argument lists.
6191 */
6192 VarDict leh = new InternalFuncDict(typeof(IEventHandlers), false); 5625 VarDict leh = new InternalFuncDict(typeof(IEventHandlers), false);
6193 5626
6194 /* 5627 // We want the scripts to be able to declare their handlers with
6195 * We want the scripts to be able to declare their handlers with 5628 // fewer arguments than the full argument lists. So define additional
6196 * fewer arguments than the full argument lists. So define additional 5629 // prototypes with fewer arguments.
6197 * prototypes with fewer arguments.
6198 */
6199 TokenDeclVar[] fullArgProtos = new TokenDeclVar[leh.Count]; 5630 TokenDeclVar[] fullArgProtos = new TokenDeclVar[leh.Count];
6200 int i = 0; 5631 int i = 0;
6201 foreach(TokenDeclVar fap in leh) 5632 foreach(TokenDeclVar fap in leh)
@@ -6283,9 +5714,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
6283 */ 5714 */
6284 private CompValu UnOpGenerate(CompValu inRVal, Token opcode) 5715 private CompValu UnOpGenerate(CompValu inRVal, Token opcode)
6285 { 5716 {
6286 /* 5717 // - Negate
6287 * - Negate
6288 */
6289 if(opcode is TokenKwSub) 5718 if(opcode is TokenKwSub)
6290 { 5719 {
6291 if(inRVal.type is TokenTypeFloat) 5720 if(inRVal.type is TokenTypeFloat)
@@ -6324,9 +5753,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
6324 return inRVal; 5753 return inRVal;
6325 } 5754 }
6326 5755
6327 /* 5756 // ~ Complement (bitwise integer)
6328 * ~ Complement (bitwise integer)
6329 */
6330 if(opcode is TokenKwTilde) 5757 if(opcode is TokenKwTilde)
6331 { 5758 {
6332 if(inRVal.type is TokenTypeInt) 5759 if(inRVal.type is TokenTypeInt)
@@ -6341,13 +5768,11 @@ namespace OpenSim.Region.ScriptEngine.Yengine
6341 return inRVal; 5768 return inRVal;
6342 } 5769 }
6343 5770
6344 /* 5771 // ! Not (boolean)
6345 * ! Not (boolean) 5772 //
6346 * 5773 // We stuff the 0/1 result in an int because I've seen x+!y in scripts
6347 * We stuff the 0/1 result in an int because I've seen x+!y in scripts 5774 // and we don't want to have to create tables to handle int+bool and
6348 * and we don't want to have to create tables to handle int+bool and 5775 // everything like that.
6349 * everything like that.
6350 */
6351 if(opcode is TokenKwExclam) 5776 if(opcode is TokenKwExclam)
6352 { 5777 {
6353 CompValuTemp outRVal = new CompValuTemp(new TokenTypeInt(opcode), this); 5778 CompValuTemp outRVal = new CompValuTemp(new TokenTypeInt(opcode), this);
@@ -6367,9 +5792,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
6367 */ 5792 */
6368 private TokenRVal LookupInitConstants(TokenRVal rVal, ref bool didOne) 5793 private TokenRVal LookupInitConstants(TokenRVal rVal, ref bool didOne)
6369 { 5794 {
6370 /* 5795 // If it is a static field of a script-defined type, look it up and hopefully we find a constant there.
6371 * If it is a static field of a script-defined type, look it up and hopefully we find a constant there.
6372 */
6373 TokenDeclVar gblVar; 5796 TokenDeclVar gblVar;
6374 if(rVal is TokenLValSField) 5797 if(rVal is TokenLValSField)
6375 { 5798 {
@@ -6390,17 +5813,13 @@ namespace OpenSim.Region.ScriptEngine.Yengine
6390 return rVal; 5813 return rVal;
6391 } 5814 }
6392 5815
6393 /* 5816 // Only other thing we handle is stand-alone names.
6394 * Only other thing we handle is stand-alone names.
6395 */
6396 if(!(rVal is TokenLValName)) 5817 if(!(rVal is TokenLValName))
6397 return rVal; 5818 return rVal;
6398 string name = ((TokenLValName)rVal).name.val; 5819 string name = ((TokenLValName)rVal).name.val;
6399 5820
6400 /* 5821 // If we are doing the initializations for a script-defined type,
6401 * If we are doing the initializations for a script-defined type, 5822 // look for the constant among the fields for that type.
6402 * look for the constant among the fields for that type.
6403 */
6404 if(currentSDTClass != null) 5823 if(currentSDTClass != null)
6405 { 5824 {
6406 gblVar = currentSDTClass.members.FindExact(name, null); 5825 gblVar = currentSDTClass.members.FindExact(name, null);
@@ -6415,11 +5834,9 @@ namespace OpenSim.Region.ScriptEngine.Yengine
6415 } 5834 }
6416 } 5835 }
6417 5836
6418 /* 5837 // Look it up as a script-defined global variable.
6419 * Look it up as a script-defined global variable. 5838 // Then if the variable is defined as a constant and has a constant value,
6420 * Then if the variable is defined as a constant and has a constant value, 5839 // we are successful. If it is defined as something else, return failure.
6421 * we are successful. If it is defined as something else, return failure.
6422 */
6423 gblVar = tokenScript.variablesStack.FindExact(name, null); 5840 gblVar = tokenScript.variablesStack.FindExact(name, null);
6424 if(gblVar != null) 5841 if(gblVar != null)
6425 { 5842 {
@@ -6431,9 +5848,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
6431 return rVal; 5848 return rVal;
6432 } 5849 }
6433 5850
6434 /* 5851 // Maybe it is a built-in symbolic constant.
6435 * Maybe it is a built-in symbolic constant.
6436 */
6437 ScriptConst scriptConst = ScriptConst.Lookup(name); 5852 ScriptConst scriptConst = ScriptConst.Lookup(name);
6438 if(scriptConst != null) 5853 if(scriptConst != null)
6439 { 5854 {
@@ -6445,9 +5860,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
6445 } 5860 }
6446 } 5861 }
6447 5862
6448 /* 5863 // Don't know what it is, return failure.
6449 * Don't know what it is, return failure.
6450 */
6451 return rVal; 5864 return rVal;
6452 } 5865 }
6453 5866
@@ -6457,9 +5870,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
6457 */ 5870 */
6458 private TokenRVal LookupBodyConstants(TokenRVal rVal, ref bool didOne) 5871 private TokenRVal LookupBodyConstants(TokenRVal rVal, ref bool didOne)
6459 { 5872 {
6460 /* 5873 // If it is a static field of a script-defined type, look it up and hopefully we find a constant there.
6461 * If it is a static field of a script-defined type, look it up and hopefully we find a constant there.
6462 */
6463 TokenDeclVar gblVar; 5874 TokenDeclVar gblVar;
6464 if(rVal is TokenLValSField) 5875 if(rVal is TokenLValSField)
6465 { 5876 {
@@ -6477,17 +5888,13 @@ namespace OpenSim.Region.ScriptEngine.Yengine
6477 return rVal; 5888 return rVal;
6478 } 5889 }
6479 5890
6480 /* 5891 // Only other thing we handle is stand-alone names.
6481 * Only other thing we handle is stand-alone names.
6482 */
6483 if(!(rVal is TokenLValName)) 5892 if(!(rVal is TokenLValName))
6484 return rVal; 5893 return rVal;
6485 string name = ((TokenLValName)rVal).name.val; 5894 string name = ((TokenLValName)rVal).name.val;
6486 5895
6487 /* 5896 // Scan through the variable stack and hopefully we find a constant there.
6488 * Scan through the variable stack and hopefully we find a constant there. 5897 // But we stop as soon as we get a match because that's what the script is referring to.
6489 * But we stop as soon as we get a match because that's what the script is referring to.
6490 */
6491 CompValu val; 5898 CompValu val;
6492 for(VarDict vars = ((TokenLValName)rVal).stack; vars != null; vars = vars.outerVarDict) 5899 for(VarDict vars = ((TokenLValName)rVal).stack; vars != null; vars = vars.outerVarDict)
6493 { 5900 {
@@ -6513,9 +5920,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
6513 } 5920 }
6514 } 5921 }
6515 5922
6516 /* 5923 // Maybe it is a built-in symbolic constant.
6517 * Maybe it is a built-in symbolic constant.
6518 */
6519 ScriptConst scriptConst = ScriptConst.Lookup(name); 5924 ScriptConst scriptConst = ScriptConst.Lookup(name);
6520 if(scriptConst != null) 5925 if(scriptConst != null)
6521 { 5926 {
@@ -6523,15 +5928,11 @@ namespace OpenSim.Region.ScriptEngine.Yengine
6523 goto foundit; 5928 goto foundit;
6524 } 5929 }
6525 5930
6526 /* 5931 // Don't know what it is, return failure.
6527 * Don't know what it is, return failure.
6528 */
6529 return rVal; 5932 return rVal;
6530 5933
6531 /* 5934 // Found a CompValu. If it's a simple constant, then use it.
6532 * Found a CompValu. If it's a simple constant, then use it. 5935 // Otherwise tell caller we failed to simplify.
6533 * Otherwise tell caller we failed to simplify.
6534 */
6535 foundit: 5936 foundit:
6536 rVal = CompValuConst2RValConst(val, rVal); 5937 rVal = CompValuConst2RValConst(val, rVal);
6537 if(rVal is TokenRValConst) 5938 if(rVal is TokenRValConst)
@@ -6586,9 +5987,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
6586 */ 5987 */
6587 public TokenDeclVar FindNamedVar(TokenLValName lValName, TokenType[] argsig) 5988 public TokenDeclVar FindNamedVar(TokenLValName lValName, TokenType[] argsig)
6588 { 5989 {
6589 /* 5990 // Look in variable stack for the given name.
6590 * Look in variable stack for the given name.
6591 */
6592 for(VarDict vars = lValName.stack; vars != null; vars = vars.outerVarDict) 5991 for(VarDict vars = lValName.stack; vars != null; vars = vars.outerVarDict)
6593 { 5992 {
6594 5993
@@ -6627,9 +6026,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
6627 } 6026 }
6628 } 6027 }
6629 6028
6630 /* 6029 // If not found, try one of the built-in constants or functions.
6631 * If not found, try one of the built-in constants or functions.
6632 */
6633 if(argsig == null) 6030 if(argsig == null)
6634 { 6031 {
6635 ScriptConst scriptConst = ScriptConst.Lookup(lValName.name.val); 6032 ScriptConst scriptConst = ScriptConst.Lookup(lValName.name.val);
@@ -6670,31 +6067,28 @@ namespace OpenSim.Region.ScriptEngine.Yengine
6670 TokenDeclVar declVar = sdtDecl.FindIFaceMember(this, name, argsig, out impl); 6067 TokenDeclVar declVar = sdtDecl.FindIFaceMember(this, name, argsig, out impl);
6671 if((declVar != null) && (impl != sdtDecl)) 6068 if((declVar != null) && (impl != sdtDecl))
6672 { 6069 {
6673 6070 // Accessing a method or propterty of another interface that the primary interface says it implements.
6674 /* 6071 // In this case, we have to cast from the primary interface to that secondary interface.
6675 * Accessing a method or propterty of another interface that the primary interface says it implements. 6072 //
6676 * In this case, we have to cast from the primary interface to that secondary interface. 6073 // interface IEnumerable {
6677 * 6074 // IEnumerator GetEnumerator ();
6678 * interface IEnumerable { 6075 // }
6679 * IEnumerator GetEnumerator (); 6076 // interface ICountable : IEnumerable {
6680 * } 6077 // integer GetCount ();
6681 * interface ICountable : IEnumerable { 6078 // }
6682 * integer GetCount (); 6079 // class List : ICountable {
6683 * } 6080 // public GetCount () : ICountable { ... }
6684 * class List : ICountable { 6081 // public GetEnumerator () : IEnumerable { ... }
6685 * public GetCount () : ICountable { ... } 6082 // }
6686 * public GetEnumerator () : IEnumerable { ... } 6083 //
6687 * } 6084 // ICountable aList = new List ();
6688 * 6085 // IEnumerator anEnumer = aList.GetEnumerator (); << we are here
6689 * ICountable aList = new List (); 6086 // << baseRVal = aList
6690 * IEnumerator anEnumer = aList.GetEnumerator (); << we are here 6087 // << sdtDecl = ICountable
6691 * << baseRVal = aList 6088 // << impl = IEnumerable
6692 * << sdtDecl = ICountable 6089 // << name = GetEnumerator
6693 * << impl = IEnumerable 6090 // << argsig = ()
6694 * << name = GetEnumerator 6091 // So we have to cast aList from ICountable to IEnumerable.
6695 * << argsig = ()
6696 * So we have to cast aList from ICountable to IEnumerable.
6697 */
6698 6092
6699 // make type token for the secondary interface type 6093 // make type token for the secondary interface type
6700 TokenType subIntfType = impl.MakeRefToken(name); 6094 TokenType subIntfType = impl.MakeRefToken(name);
@@ -6799,19 +6193,15 @@ namespace OpenSim.Region.ScriptEngine.Yengine
6799 TokenDeclSDType definedBy = var.sdtClass; 6193 TokenDeclSDType definedBy = var.sdtClass;
6800 TokenDeclSDType accessedBy = curDeclFunc.sdtClass; 6194 TokenDeclSDType accessedBy = curDeclFunc.sdtClass;
6801 6195
6802 /*******************************\ 6196 //*******************************
6803 * Check member-level access * 6197 // Check member-level access
6804 \*******************************/ 6198 //*******************************
6805 6199
6806 /* 6200 // Note that if accessedBy is null, ie, accessing from global function (or event handlers),
6807 * Note that if accessedBy is null, ie, accessing from global function (or event handlers), 6201 // anything tagged as SDT_PRIVATE or SDT_PROTECTED will fail.
6808 * anything tagged as SDT_PRIVATE or SDT_PROTECTED will fail.
6809 */
6810 6202
6811 /* 6203 // Private means accessed by the class that defined the member or accessed by a nested class
6812 * Private means accessed by the class that defined the member or accessed by a nested class 6204 // of the class that defined the member.
6813 * of the class that defined the member.
6814 */
6815 if((var.sdtFlags & ScriptReduce.SDT_PRIVATE) != 0) 6205 if((var.sdtFlags & ScriptReduce.SDT_PRIVATE) != 0)
6816 { 6206 {
6817 for(nested = accessedBy; nested != null; nested = nested.outerSDType) 6207 for(nested = accessedBy; nested != null; nested = nested.outerSDType)
@@ -6823,12 +6213,10 @@ namespace OpenSim.Region.ScriptEngine.Yengine
6823 return; 6213 return;
6824 } 6214 }
6825 6215
6826 /* 6216 // Protected means:
6827 * Protected means: 6217 // If being accessed by an inner class, the inner class has access to it if the inner class derives
6828 * If being accessed by an inner class, the inner class has access to it if the inner class derives 6218 // from the declaring class. It also has access to it if an outer class derives from the declaring
6829 * from the declaring class. It also has access to it if an outer class derives from the declaring 6219 // class.
6830 * class.
6831 */
6832 if((var.sdtFlags & ScriptReduce.SDT_PROTECTED) != 0) 6220 if((var.sdtFlags & ScriptReduce.SDT_PROTECTED) != 0)
6833 { 6221 {
6834 for(nested = accessedBy; nested != null; nested = nested.outerSDType) 6222 for(nested = accessedBy; nested != null; nested = nested.outerSDType)
@@ -6844,26 +6232,24 @@ namespace OpenSim.Region.ScriptEngine.Yengine
6844 } 6232 }
6845 acc1ok: 6233 acc1ok:
6846 6234
6847 /******************************\ 6235 //******************************
6848 * Check class-level access * 6236 // Check class-level access
6849 \******************************/ 6237 //******************************
6850 6238
6851 /* 6239 // If being accessed by same or inner class than where defined, it is ok.
6852 * If being accessed by same or inner class than where defined, it is ok. 6240 //
6853 * 6241 // class DefiningClass {
6854 * class DefiningClass { 6242 // varBeingAccessed;
6855 * varBeingAccessed; 6243 // .
6856 * . 6244 // .
6857 * . 6245 // .
6858 * . 6246 // class AccessingClass {
6859 * class AccessingClass { 6247 // functionDoingAccess() { }
6860 * functionDoingAccess() { } 6248 // }
6861 * } 6249 // .
6862 * . 6250 // .
6863 * . 6251 // .
6864 * . 6252 // }
6865 * }
6866 */
6867 nested = accessedBy; 6253 nested = accessedBy;
6868 while(true) 6254 while(true)
6869 { 6255 {
@@ -6874,46 +6260,39 @@ namespace OpenSim.Region.ScriptEngine.Yengine
6874 nested = (TokenDeclSDTypeClass)nested.outerSDType; 6260 nested = (TokenDeclSDTypeClass)nested.outerSDType;
6875 } 6261 }
6876 6262
6877 /* 6263 // It is being accessed by an outer class than where defined,
6878 * It is being accessed by an outer class than where defined, 6264 // check for a 'private' or 'protected' class tag that blocks.
6879 * check for a 'private' or 'protected' class tag that blocks.
6880 */
6881 do 6265 do
6882 { 6266 {
6883 6267 // If the field's class is defined directly inside the accessing class,
6884 /* 6268 // access is allowed regardless of class-level private or protected tags.
6885 * If the field's class is defined directly inside the accessing class, 6269 //
6886 * access is allowed regardless of class-level private or protected tags. 6270 // class AccessingClass {
6887 * 6271 // functionDoingAccess() { }
6888 * class AccessingClass { 6272 // class DefiningClass {
6889 * functionDoingAccess() { } 6273 // varBeingAccessed;
6890 * class DefiningClass { 6274 // }
6891 * varBeingAccessed; 6275 // }
6892 * }
6893 * }
6894 */
6895 if(definedBy.outerSDType == accessedBy) 6276 if(definedBy.outerSDType == accessedBy)
6896 return; 6277 return;
6897 6278
6898 /* 6279 // If the field's class is defined two or more levels inside the accessing class,
6899 * If the field's class is defined two or more levels inside the accessing class, 6280 // access is denied if the defining class is tagged private.
6900 * access is denied if the defining class is tagged private. 6281 //
6901 * 6282 // class AccessingClass {
6902 * class AccessingClass { 6283 // functionDoingAccess() { }
6903 * functionDoingAccess() { } 6284 // .
6904 * . 6285 // .
6905 * . 6286 // .
6906 * . 6287 // class IntermediateClass {
6907 * class IntermediateClass { 6288 // private class DefiningClass {
6908 * private class DefiningClass { 6289 // varBeingAccessed;
6909 * varBeingAccessed; 6290 // }
6910 * } 6291 // }
6911 * } 6292 // .
6912 * . 6293 // .
6913 * . 6294 // .
6914 * . 6295 // }
6915 * }
6916 */
6917 if((definedBy.accessLevel & ScriptReduce.SDT_PRIVATE) != 0) 6296 if((definedBy.accessLevel & ScriptReduce.SDT_PRIVATE) != 0)
6918 { 6297 {
6919 ErrorMsg(errorAt, "member " + var.fullName + " cannot be accessed by " + curDeclFunc.fullName + 6298 ErrorMsg(errorAt, "member " + var.fullName + " cannot be accessed by " + curDeclFunc.fullName +
@@ -6921,10 +6300,8 @@ namespace OpenSim.Region.ScriptEngine.Yengine
6921 return; 6300 return;
6922 } 6301 }
6923 6302
6924 /* 6303 // Likewise, if DefiningClass is tagged protected, the AccessingClass must derive from the
6925 * Likewise, if DefiningClass is tagged protected, the AccessingClass must derive from the 6304 // IntermediateClass or access is denied.
6926 * IntermediateClass or access is denied.
6927 */
6928 if((definedBy.accessLevel & ScriptReduce.SDT_PROTECTED) != 0) 6305 if((definedBy.accessLevel & ScriptReduce.SDT_PROTECTED) != 0)
6929 { 6306 {
6930 for(TokenDeclSDType extends = accessedBy; extends != definedBy.outerSDType; extends = extends.extends) 6307 for(TokenDeclSDType extends = accessedBy; extends != definedBy.outerSDType; extends = extends.extends)
@@ -6938,9 +6315,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
6938 } 6315 }
6939 } 6316 }
6940 6317
6941 /* 6318 // Check next outer level.
6942 * Check next outer level.
6943 */
6944 definedBy = definedBy.outerSDType; 6319 definedBy = definedBy.outerSDType;
6945 } while(definedBy != null); 6320 } while(definedBy != null);
6946 } 6321 }