aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region')
-rw-r--r--OpenSim/Region/ScriptEngine/YEngine/MMRScriptBinOpStr.cs63
-rw-r--r--OpenSim/Region/ScriptEngine/YEngine/MMRScriptCodeGen.cs220
-rw-r--r--OpenSim/Region/ScriptEngine/YEngine/MMRScriptInlines.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/YEngine/MMRScriptReduce.cs4
-rw-r--r--OpenSim/Region/ScriptEngine/YEngine/MMRScriptTokenize.cs87
5 files changed, 154 insertions, 222 deletions
diff --git a/OpenSim/Region/ScriptEngine/YEngine/MMRScriptBinOpStr.cs b/OpenSim/Region/ScriptEngine/YEngine/MMRScriptBinOpStr.cs
index f5e91f7..89f4ee3 100644
--- a/OpenSim/Region/ScriptEngine/YEngine/MMRScriptBinOpStr.cs
+++ b/OpenSim/Region/ScriptEngine/YEngine/MMRScriptBinOpStr.cs
@@ -34,6 +34,7 @@ using System.Reflection;
34using System.Reflection.Emit; 34using System.Reflection.Emit;
35using System.Text; 35using System.Text;
36using System.Text.RegularExpressions; 36using System.Text.RegularExpressions;
37using OpenSim.Region.ScriptEngine.Shared;
37 38
38using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; 39using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
39using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; 40using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
@@ -120,6 +121,10 @@ namespace OpenSim.Region.ScriptEngine.Yengine
120 private static MethodInfo infoMethVecDivInt = GetBinOpsMethod("MethVecDivInt", new Type[] { typeof(LSL_Vector), typeof(int) }); 121 private static MethodInfo infoMethVecDivInt = GetBinOpsMethod("MethVecDivInt", new Type[] { typeof(LSL_Vector), typeof(int) });
121 private static MethodInfo infoMethVecMulRot = GetBinOpsMethod("MethVecMulRot", new Type[] { typeof(LSL_Vector), typeof(LSL_Rotation) }); 122 private static MethodInfo infoMethVecMulRot = GetBinOpsMethod("MethVecMulRot", new Type[] { typeof(LSL_Vector), typeof(LSL_Rotation) });
122 private static MethodInfo infoMethVecDivRot = GetBinOpsMethod("MethVecDivRot", new Type[] { typeof(LSL_Vector), typeof(LSL_Rotation) }); 123 private static MethodInfo infoMethVecDivRot = GetBinOpsMethod("MethVecDivRot", new Type[] { typeof(LSL_Vector), typeof(LSL_Rotation) });
124 private static MethodInfo infoMethDoubleDivDouble = GetBinOpsMethod("MethDoubleDivDouble", new Type[] { typeof(Double), typeof(Double) });
125 private static MethodInfo infoMethLongDivLong = GetBinOpsMethod("MethLongDivLong", new Type[] { typeof(long), typeof(long) });
126 private static MethodInfo infoMethDoubleModDouble = GetBinOpsMethod("MethDoubleModDouble", new Type[] { typeof(Double), typeof(Double) });
127 private static MethodInfo infoMethLongModLong = GetBinOpsMethod("MethLongModLong", new Type[] { typeof(long), typeof(long) });
123 128
124 private static MethodInfo GetBinOpsMethod(string name, Type[] types) 129 private static MethodInfo GetBinOpsMethod(string name, Type[] types)
125 { 130 {
@@ -589,7 +594,8 @@ namespace OpenSim.Region.ScriptEngine.Yengine
589 result.PopPre(scg, errorAt); 594 result.PopPre(scg, errorAt);
590 left.PushVal(scg, errorAt, tokenTypeFloat); 595 left.PushVal(scg, errorAt, tokenTypeFloat);
591 right.PushVal(scg, errorAt, tokenTypeFloat); 596 right.PushVal(scg, errorAt, tokenTypeFloat);
592 scg.ilGen.Emit(errorAt, OpCodes.Div); 597 //scg.ilGen.Emit(errorAt, OpCodes.Div);
598 scg.ilGen.Emit(errorAt, OpCodes.Call, infoMethDoubleDivDouble);
593 result.PopPost(scg, errorAt, tokenTypeFloat); 599 result.PopPost(scg, errorAt, tokenTypeFloat);
594 } 600 }
595 601
@@ -598,7 +604,8 @@ namespace OpenSim.Region.ScriptEngine.Yengine
598 result.PopPre(scg, errorAt); 604 result.PopPre(scg, errorAt);
599 left.PushVal(scg, errorAt, tokenTypeFloat); 605 left.PushVal(scg, errorAt, tokenTypeFloat);
600 right.PushVal(scg, errorAt, tokenTypeFloat); 606 right.PushVal(scg, errorAt, tokenTypeFloat);
601 scg.ilGen.Emit(errorAt, OpCodes.Rem); 607 //scg.ilGen.Emit(errorAt, OpCodes.Rem);
608 scg.ilGen.Emit(errorAt, OpCodes.Call, infoMethDoubleModDouble);
602 result.PopPost(scg, errorAt, tokenTypeFloat); 609 result.PopPost(scg, errorAt, tokenTypeFloat);
603 } 610 }
604 611
@@ -694,7 +701,8 @@ namespace OpenSim.Region.ScriptEngine.Yengine
694 result.PopPre(scg, errorAt); 701 result.PopPre(scg, errorAt);
695 left.PushVal(scg, errorAt, tokenTypeFloat); 702 left.PushVal(scg, errorAt, tokenTypeFloat);
696 right.PushVal(scg, errorAt, tokenTypeFloat); 703 right.PushVal(scg, errorAt, tokenTypeFloat);
697 scg.ilGen.Emit(errorAt, OpCodes.Div); 704 //scg.ilGen.Emit(errorAt, OpCodes.Div);
705 scg.ilGen.Emit(errorAt, OpCodes.Call, infoMethDoubleDivDouble);
698 result.PopPost(scg, errorAt, tokenTypeFloat); 706 result.PopPost(scg, errorAt, tokenTypeFloat);
699 } 707 }
700 708
@@ -703,7 +711,8 @@ namespace OpenSim.Region.ScriptEngine.Yengine
703 result.PopPre(scg, errorAt); 711 result.PopPre(scg, errorAt);
704 left.PushVal(scg, errorAt, tokenTypeFloat); 712 left.PushVal(scg, errorAt, tokenTypeFloat);
705 right.PushVal(scg, errorAt, tokenTypeFloat); 713 right.PushVal(scg, errorAt, tokenTypeFloat);
706 scg.ilGen.Emit(errorAt, OpCodes.Rem); 714 //scg.ilGen.Emit(errorAt, OpCodes.Rem);
715 scg.ilGen.Emit(errorAt, OpCodes.Call, infoMethDoubleModDouble);
707 result.PopPost(scg, errorAt, tokenTypeFloat); 716 result.PopPost(scg, errorAt, tokenTypeFloat);
708 } 717 }
709 718
@@ -917,7 +926,8 @@ namespace OpenSim.Region.ScriptEngine.Yengine
917 scg.ilGen.Emit(errorAt, OpCodes.Conv_I8); 926 scg.ilGen.Emit(errorAt, OpCodes.Conv_I8);
918 right.PushVal(scg, errorAt, tokenTypeInt); 927 right.PushVal(scg, errorAt, tokenTypeInt);
919 scg.ilGen.Emit(errorAt, OpCodes.Conv_I8); 928 scg.ilGen.Emit(errorAt, OpCodes.Conv_I8);
920 scg.ilGen.Emit(errorAt, OpCodes.Div); 929 //scg.ilGen.Emit(errorAt, OpCodes.Div);
930 scg.ilGen.Emit(errorAt, OpCodes.Call, infoMethLongDivLong);
921 scg.ilGen.Emit(errorAt, OpCodes.Conv_I4); 931 scg.ilGen.Emit(errorAt, OpCodes.Conv_I4);
922 result.PopPost(scg, errorAt, tokenTypeInt); 932 result.PopPost(scg, errorAt, tokenTypeInt);
923 } 933 }
@@ -931,7 +941,8 @@ namespace OpenSim.Region.ScriptEngine.Yengine
931 scg.ilGen.Emit(errorAt, OpCodes.Conv_I8); 941 scg.ilGen.Emit(errorAt, OpCodes.Conv_I8);
932 right.PushVal(scg, errorAt, tokenTypeInt); 942 right.PushVal(scg, errorAt, tokenTypeInt);
933 scg.ilGen.Emit(errorAt, OpCodes.Conv_I8); 943 scg.ilGen.Emit(errorAt, OpCodes.Conv_I8);
934 scg.ilGen.Emit(errorAt, OpCodes.Rem); 944 //scg.ilGen.Emit(errorAt, OpCodes.Rem);
945 scg.ilGen.Emit(errorAt, OpCodes.Call, infoMethLongModLong);
935 scg.ilGen.Emit(errorAt, OpCodes.Conv_I4); 946 scg.ilGen.Emit(errorAt, OpCodes.Conv_I4);
936 result.PopPost(scg, errorAt, tokenTypeInt); 947 result.PopPost(scg, errorAt, tokenTypeInt);
937 } 948 }
@@ -1573,5 +1584,45 @@ namespace OpenSim.Region.ScriptEngine.Yengine
1573 { 1584 {
1574 return left / right; 1585 return left / right;
1575 } 1586 }
1587
1588 public static double MethDoubleDivDouble(double a, double b)
1589 {
1590 double r = a / b;
1591 if (double.IsNaN(r) || double.IsInfinity(r))
1592 throw new ScriptException("Division by Zero");
1593 return r;
1594 }
1595
1596 public static long MethLongDivLong(long a, long b)
1597 {
1598 try
1599 {
1600 return a / b;
1601 }
1602 catch (DivideByZeroException)
1603 {
1604 throw new ScriptException("Division by Zero");
1605 }
1606 }
1607
1608 public static double MethDoubleModDouble(double a, double b)
1609 {
1610 double r = a % b;
1611 if (double.IsNaN(r) || double.IsInfinity(r))
1612 throw new ScriptException("Division by Zero");
1613 return r;
1614 }
1615
1616 public static long MethLongModLong(long a, long b)
1617 {
1618 try
1619 {
1620 return a % b;
1621 }
1622 catch (DivideByZeroException)
1623 {
1624 throw new ScriptException("Division by Zero");
1625 }
1626 }
1576 } 1627 }
1577} 1628}
diff --git a/OpenSim/Region/ScriptEngine/YEngine/MMRScriptCodeGen.cs b/OpenSim/Region/ScriptEngine/YEngine/MMRScriptCodeGen.cs
index 27fde5b..da17a13 100644
--- a/OpenSim/Region/ScriptEngine/YEngine/MMRScriptCodeGen.cs
+++ b/OpenSim/Region/ScriptEngine/YEngine/MMRScriptCodeGen.cs
@@ -64,9 +64,6 @@ namespace OpenSim.Region.ScriptEngine.Yengine
64 64
65 public class ScriptCodeGen: IScriptCodeGen 65 public class ScriptCodeGen: IScriptCodeGen
66 { 66 {
67 private static readonly bool DEBUG_STACKCAPRES = false;
68 private static readonly bool DEBUG_TRYSTMT = false;
69
70 public static readonly string OBJECT_CODE_MAGIC = "YObjectCode"; 67 public static readonly string OBJECT_CODE_MAGIC = "YObjectCode";
71 // reserve positive version values for original xmr 68 // reserve positive version values for original xmr
72 public static int COMPILED_VERSION_VALUE = -2; // decremented when compiler or object file changes 69 public static int COMPILED_VERSION_VALUE = -2; // decremented when compiler or object file changes
@@ -972,11 +969,13 @@ namespace OpenSim.Region.ScriptEngine.Yengine
972 string eventname = declFunc.GetSimpleName(); 969 string eventname = declFunc.GetSimpleName();
973 TokenArgDecl argDecl = declFunc.argDecl; 970 TokenArgDecl argDecl = declFunc.argDecl;
974 971
975 // Make sure event handler name is valid and that number and type of arguments is correct. 972 HeapLocals.Clear();
976 // Apparently some scripts exist with fewer than correct number of args in their declaration 973
977 // so allow for that. It is ok because the handlers are called with the arguments in an 974 // Make sure event handler name is valid and that number and type of arguments is correct.
978 // object[] array, and we just won't access the missing argments in the vector. But the 975 // Apparently some scripts exist with fewer than correct number of args in their declaration
979 // specified types must match one of the prototypes in legalEventHandlers. 976 // so allow for that. It is ok because the handlers are called with the arguments in an
977 // object[] array, and we just won't access the missing argments in the vector. But the
978 // specified types must match one of the prototypes in legalEventHandlers.
980 TokenDeclVar protoDeclFunc = legalEventHandlers.FindExact(eventname, argDecl.types); 979 TokenDeclVar protoDeclFunc = legalEventHandlers.FindExact(eventname, argDecl.types);
981 if(protoDeclFunc == null) 980 if(protoDeclFunc == null)
982 { 981 {
@@ -1113,7 +1112,9 @@ namespace OpenSim.Region.ScriptEngine.Yengine
1113 */ 1112 */
1114 private void GenerateMethodBody(TokenDeclVar declFunc) 1113 private void GenerateMethodBody(TokenDeclVar declFunc)
1115 { 1114 {
1116 // Set up code generator for the function's contents. 1115 HeapLocals.Clear();
1116
1117 // Set up code generator for the function's contents.
1117 _ilGen = declFunc.ilGen; 1118 _ilGen = declFunc.ilGen;
1118 StartFunctionBody(declFunc); 1119 StartFunctionBody(declFunc);
1119 1120
@@ -1258,7 +1259,6 @@ namespace OpenSim.Region.ScriptEngine.Yengine
1258 // resume at the correct spot. 1259 // resume at the correct spot.
1259 actCallLabels.Clear(); 1260 actCallLabels.Clear();
1260 allCallLabels.Clear(); 1261 allCallLabels.Clear();
1261 HeapLocals.Clear();
1262 openCallLabel = null; 1262 openCallLabel = null;
1263 1263
1264 // Alloc stack space for local vars. 1264 // Alloc stack space for local vars.
@@ -1405,18 +1405,18 @@ namespace OpenSim.Region.ScriptEngine.Yengine
1405 // Build list of locals and temps active at all the call labels. 1405 // Build list of locals and temps active at all the call labels.
1406 activeTemps = new List<ScriptMyLocal>(); 1406 activeTemps = new List<ScriptMyLocal>();
1407 foreach (CallLabel cl in allCallLabels) 1407 foreach (CallLabel cl in allCallLabels)
1408 {
1409 foreach (ScriptMyLocal lcl in cl.callLabel.whereAmI.localsReadBeforeWritten)
1408 { 1410 {
1409 foreach(ScriptMyLocal lcl in cl.callLabel.whereAmI.localsReadBeforeWritten) 1411 if (!activeTemps.Contains(lcl))
1410 { 1412 {
1411 if(!activeTemps.Contains(lcl))
1412 {
1413 activeTemps.Add(lcl); 1413 activeTemps.Add(lcl);
1414 } 1414 }
1415 } 1415 }
1416 } 1416 }
1417 1417
1418 // Output code to restore the args, locals and temps then jump to 1418 // Output code to restore the args, locals and temps then jump to
1419 // the call label that we were interrupted at. 1419 // the call label that we were interrupted at.
1420 ilGen.MarkLabel(cmRestore); 1420 ilGen.MarkLabel(cmRestore);
1421 GenerateFrameRestoreCode(activeTemps); 1421 GenerateFrameRestoreCode(activeTemps);
1422 } 1422 }
@@ -1546,15 +1546,6 @@ namespace OpenSim.Region.ScriptEngine.Yengine
1546 ilGen.Emit(curDeclFunc, OpCodes.Ldc_I4, nSaves); 1546 ilGen.Emit(curDeclFunc, OpCodes.Ldc_I4, nSaves);
1547 ilGen.Emit(curDeclFunc, OpCodes.Call, captureStackFrameMethodInfo); 1547 ilGen.Emit(curDeclFunc, OpCodes.Call, captureStackFrameMethodInfo);
1548 1548
1549 if(DEBUG_STACKCAPRES)
1550 {
1551 ilGen.Emit(curDeclFunc, OpCodes.Ldstr, ilGen.methName + "*: capture mainCallNo=");
1552 ilGen.Emit(curDeclFunc, OpCodes.Call, consoleWriteMethodInfo);
1553 ilGen.Emit(curDeclFunc, OpCodes.Ldloc, actCallNo);
1554 ilGen.Emit(curDeclFunc, OpCodes.Box, typeof(int));
1555 ilGen.Emit(curDeclFunc, OpCodes.Call, consoleWriteMethodInfo);
1556 }
1557
1558 // Copy arg values to object array, boxing as needed. 1549 // Copy arg values to object array, boxing as needed.
1559 int i = 0; 1550 int i = 0;
1560 foreach(TokenDeclVar argVar in curDeclFunc.argDecl.varDict) 1551 foreach(TokenDeclVar argVar in curDeclFunc.argDecl.varDict)
@@ -1562,13 +1553,6 @@ namespace OpenSim.Region.ScriptEngine.Yengine
1562 ilGen.Emit(curDeclFunc, OpCodes.Dup); 1553 ilGen.Emit(curDeclFunc, OpCodes.Dup);
1563 ilGen.Emit(curDeclFunc, OpCodes.Ldc_I4, i); 1554 ilGen.Emit(curDeclFunc, OpCodes.Ldc_I4, i);
1564 argVar.location.PushVal(this, argVar.name, tokenTypeObj); 1555 argVar.location.PushVal(this, argVar.name, tokenTypeObj);
1565 if(DEBUG_STACKCAPRES)
1566 {
1567 ilGen.Emit(curDeclFunc, OpCodes.Ldstr, "\n arg:" + argVar.name.val + "=");
1568 ilGen.Emit(curDeclFunc, OpCodes.Call, consoleWriteMethodInfo);
1569 ilGen.Emit(curDeclFunc, OpCodes.Dup);
1570 ilGen.Emit(curDeclFunc, OpCodes.Call, consoleWriteMethodInfo);
1571 }
1572 ilGen.Emit(curDeclFunc, OpCodes.Stelem_Ref); 1556 ilGen.Emit(curDeclFunc, OpCodes.Stelem_Ref);
1573 i++; 1557 i++;
1574 } 1558 }
@@ -1596,20 +1580,8 @@ namespace OpenSim.Region.ScriptEngine.Yengine
1596 { 1580 {
1597 ilGen.Emit(curDeclFunc, OpCodes.Box, t); 1581 ilGen.Emit(curDeclFunc, OpCodes.Box, t);
1598 } 1582 }
1599 if(DEBUG_STACKCAPRES)
1600 {
1601 ilGen.Emit(curDeclFunc, OpCodes.Ldstr, "\n lcl:" + lcl.name + "=");
1602 ilGen.Emit(curDeclFunc, OpCodes.Call, consoleWriteMethodInfo);
1603 ilGen.Emit(curDeclFunc, OpCodes.Dup);
1604 ilGen.Emit(curDeclFunc, OpCodes.Call, consoleWriteMethodInfo);
1605 }
1606 ilGen.Emit(curDeclFunc, OpCodes.Stelem_Ref); 1583 ilGen.Emit(curDeclFunc, OpCodes.Stelem_Ref);
1607 } 1584 }
1608 if(DEBUG_STACKCAPRES)
1609 {
1610 ilGen.Emit(curDeclFunc, OpCodes.Ldstr, "\n");
1611 ilGen.Emit(curDeclFunc, OpCodes.Call, consoleWriteMethodInfo);
1612 }
1613 1585
1614 ilGen.Emit(curDeclFunc, OpCodes.Pop); 1586 ilGen.Emit(curDeclFunc, OpCodes.Pop);
1615 } 1587 }
@@ -1629,14 +1601,6 @@ namespace OpenSim.Region.ScriptEngine.Yengine
1629 ilGen.Emit(curDeclFunc, OpCodes.Ldloca, actCallNo); // __mainCallNo 1601 ilGen.Emit(curDeclFunc, OpCodes.Ldloca, actCallNo); // __mainCallNo
1630 ilGen.Emit(curDeclFunc, OpCodes.Call, restoreStackFrameMethodInfo); 1602 ilGen.Emit(curDeclFunc, OpCodes.Call, restoreStackFrameMethodInfo);
1631 ilGen.Emit(curDeclFunc, OpCodes.Stloc, objArray); 1603 ilGen.Emit(curDeclFunc, OpCodes.Stloc, objArray);
1632 if(DEBUG_STACKCAPRES)
1633 {
1634 ilGen.Emit(curDeclFunc, OpCodes.Ldstr, ilGen.methName + "*: restore mainCallNo=");
1635 ilGen.Emit(curDeclFunc, OpCodes.Call, consoleWriteMethodInfo);
1636 ilGen.Emit(curDeclFunc, OpCodes.Ldloc, actCallNo);
1637 ilGen.Emit(curDeclFunc, OpCodes.Box, typeof(int));
1638 ilGen.Emit(curDeclFunc, OpCodes.Call, consoleWriteMethodInfo);
1639 }
1640 1604
1641 // Restore argument values from object array, unboxing as needed. 1605 // Restore argument values from object array, unboxing as needed.
1642 // Although the caller has restored them to what it called us with, it's possible that this 1606 // Although the caller has restored them to what it called us with, it's possible that this
@@ -1649,13 +1613,6 @@ namespace OpenSim.Region.ScriptEngine.Yengine
1649 ilGen.Emit(curDeclFunc, OpCodes.Ldloc, objArray); 1613 ilGen.Emit(curDeclFunc, OpCodes.Ldloc, objArray);
1650 ilGen.Emit(curDeclFunc, OpCodes.Ldc_I4, i); 1614 ilGen.Emit(curDeclFunc, OpCodes.Ldc_I4, i);
1651 ilGen.Emit(curDeclFunc, OpCodes.Ldelem_Ref); 1615 ilGen.Emit(curDeclFunc, OpCodes.Ldelem_Ref);
1652 if(DEBUG_STACKCAPRES)
1653 {
1654 ilGen.Emit(curDeclFunc, OpCodes.Ldstr, "\n arg:" + argVar.name.val + "=");
1655 ilGen.Emit(curDeclFunc, OpCodes.Call, consoleWriteMethodInfo);
1656 ilGen.Emit(curDeclFunc, OpCodes.Dup);
1657 ilGen.Emit(curDeclFunc, OpCodes.Call, consoleWriteMethodInfo);
1658 }
1659 TypeCast.CastTopOfStack(this, argVar.name, tokenTypeObj, argLoc.type, true); 1616 TypeCast.CastTopOfStack(this, argVar.name, tokenTypeObj, argLoc.type, true);
1660 argLoc.PopPost(this, argVar.name); 1617 argLoc.PopPost(this, argVar.name);
1661 i++; 1618 i++;
@@ -1679,13 +1636,6 @@ namespace OpenSim.Region.ScriptEngine.Yengine
1679 ilGen.Emit(curDeclFunc, OpCodes.Ldloc, objArray); 1636 ilGen.Emit(curDeclFunc, OpCodes.Ldloc, objArray);
1680 ilGen.Emit(curDeclFunc, OpCodes.Ldc_I4, i++); 1637 ilGen.Emit(curDeclFunc, OpCodes.Ldc_I4, i++);
1681 ilGen.Emit(curDeclFunc, OpCodes.Ldelem_Ref); 1638 ilGen.Emit(curDeclFunc, OpCodes.Ldelem_Ref);
1682 if(DEBUG_STACKCAPRES)
1683 {
1684 ilGen.Emit(curDeclFunc, OpCodes.Ldstr, "\n lcl:" + lcl.name + "=");
1685 ilGen.Emit(curDeclFunc, OpCodes.Call, consoleWriteMethodInfo);
1686 ilGen.Emit(curDeclFunc, OpCodes.Dup);
1687 ilGen.Emit(curDeclFunc, OpCodes.Call, consoleWriteMethodInfo);
1688 }
1689 if(u.IsValueType) 1639 if(u.IsValueType)
1690 { 1640 {
1691 ilGen.Emit(curDeclFunc, OpCodes.Unbox_Any, u); 1641 ilGen.Emit(curDeclFunc, OpCodes.Unbox_Any, u);
@@ -1708,11 +1658,6 @@ namespace OpenSim.Region.ScriptEngine.Yengine
1708 ilGen.Emit(curDeclFunc, OpCodes.Stloc, lcl); 1658 ilGen.Emit(curDeclFunc, OpCodes.Stloc, lcl);
1709 } 1659 }
1710 } 1660 }
1711 if(DEBUG_STACKCAPRES)
1712 {
1713 ilGen.Emit(curDeclFunc, OpCodes.Ldstr, "\n");
1714 ilGen.Emit(curDeclFunc, OpCodes.Call, consoleWriteMethodInfo);
1715 }
1716 1661
1717 OutputCallNoSwitchStmt(); 1662 OutputCallNoSwitchStmt();
1718 } 1663 }
@@ -3235,34 +3180,6 @@ namespace OpenSim.Region.ScriptEngine.Yengine
3235 new CallLabel(this, tryStmt); // <oldcalllabel>: 3180 new CallLabel(this, tryStmt); // <oldcalllabel>:
3236 ilGen.BeginExceptionBlock(); // try { 3181 ilGen.BeginExceptionBlock(); // try {
3237 openCallLabel = null; 3182 openCallLabel = null;
3238 if(DEBUG_TRYSTMT)
3239 {
3240 ilGen.Emit(tryStmt, OpCodes.Ldstr, "enter try*: " + tryStmt.line + " callMode=");
3241 ilGen.Emit(tryStmt, OpCodes.Call, consoleWriteMethodInfo);
3242 PushXMRInst();
3243 ilGen.Emit(tryStmt, OpCodes.Ldfld, callModeFieldInfo);
3244 ilGen.Emit(tryStmt, OpCodes.Box, typeof(int));
3245 ilGen.Emit(tryStmt, OpCodes.Call, consoleWriteMethodInfo);
3246 ilGen.Emit(tryStmt, OpCodes.Ldstr, " tryCallNo=");
3247 ilGen.Emit(tryStmt, OpCodes.Call, consoleWriteMethodInfo);
3248 tryCallNo.PushVal(this, tryStmt);
3249 ilGen.Emit(tryStmt, OpCodes.Box, typeof(int));
3250 ilGen.Emit(tryStmt, OpCodes.Call, consoleWriteMethodInfo);
3251 ilGen.Emit(tryStmt, OpCodes.Ldstr, " catThrown.IsNull=");
3252 ilGen.Emit(tryStmt, OpCodes.Call, consoleWriteMethodInfo);
3253 catThrown.PushVal(this, tryStmt);
3254 ilGen.Emit(tryStmt, OpCodes.Ldnull);
3255 ilGen.Emit(tryStmt, OpCodes.Ceq);
3256 ilGen.Emit(tryStmt, OpCodes.Box, typeof(int));
3257 ilGen.Emit(tryStmt, OpCodes.Call, consoleWriteMethodInfo);
3258 ilGen.Emit(tryStmt, OpCodes.Ldstr, " catCallNo=");
3259 ilGen.Emit(tryStmt, OpCodes.Call, consoleWriteMethodInfo);
3260 catCallNo.PushVal(this, tryStmt);
3261 ilGen.Emit(tryStmt, OpCodes.Box, typeof(int));
3262 ilGen.Emit(tryStmt, OpCodes.Call, consoleWriteMethodInfo);
3263 ilGen.Emit(tryStmt, OpCodes.Ldstr, "\n");
3264 ilGen.Emit(tryStmt, OpCodes.Call, consoleWriteMethodInfo);
3265 }
3266 3183
3267 GetCallNo(tryStmt, tryCallNo); // if (__tryCallNo >= 0) goto tryCallSw; 3184 GetCallNo(tryStmt, tryCallNo); // if (__tryCallNo >= 0) goto tryCallSw;
3268 ilGen.Emit(tryStmt, OpCodes.Ldc_I4_0); 3185 ilGen.Emit(tryStmt, OpCodes.Ldc_I4_0);
@@ -3282,31 +3199,12 @@ namespace OpenSim.Region.ScriptEngine.Yengine
3282 } 3199 }
3283 3200
3284 CallLabel tryThrow = new CallLabel(this, tryStmt); // tryThrow:<tryCallLabel>: 3201 CallLabel tryThrow = new CallLabel(this, tryStmt); // tryThrow:<tryCallLabel>:
3285 if(DEBUG_TRYSTMT)
3286 {
3287 ilGen.Emit(tryStmt, OpCodes.Ldstr, "tryThrow*: " + tryStmt.line + " catThrown=");
3288 ilGen.Emit(tryStmt, OpCodes.Call, consoleWriteMethodInfo);
3289 catThrown.PushVal(this, tryStmt);
3290 ilGen.Emit(tryStmt, OpCodes.Call, consoleWriteMethodInfo);
3291 ilGen.Emit(tryStmt, OpCodes.Ldstr, "\n");
3292 ilGen.Emit(tryStmt, OpCodes.Call, consoleWriteMethodInfo);
3293 }
3294 catThrown.PushVal(this, tryStmt); // throw new ScriptRestoreCatchException (__catThrown); 3202 catThrown.PushVal(this, tryStmt); // throw new ScriptRestoreCatchException (__catThrown);
3295 ilGen.Emit(tryStmt, OpCodes.Newobj, scriptRestoreCatchExceptionConstructorInfo); 3203 ilGen.Emit(tryStmt, OpCodes.Newobj, scriptRestoreCatchExceptionConstructorInfo);
3296 ilGen.Emit(tryStmt, OpCodes.Throw); 3204 ilGen.Emit(tryStmt, OpCodes.Throw);
3297 openCallLabel = null; 3205 openCallLabel = null;
3298 3206
3299 ilGen.MarkLabel(tryCallSw); // tryCallSw: 3207 ilGen.MarkLabel(tryCallSw); // tryCallSw:
3300 if(DEBUG_TRYSTMT)
3301 {
3302 ilGen.Emit(tryStmt, OpCodes.Ldstr, "tryCallSw*: " + tryStmt.line + " tryCallNo=");
3303 ilGen.Emit(tryStmt, OpCodes.Call, consoleWriteMethodInfo);
3304 tryCallNo.PushVal(this, tryStmt);
3305 ilGen.Emit(tryStmt, OpCodes.Box, typeof(int));
3306 ilGen.Emit(tryStmt, OpCodes.Call, consoleWriteMethodInfo);
3307 ilGen.Emit(tryStmt, OpCodes.Ldstr, "\n");
3308 ilGen.Emit(tryStmt, OpCodes.Call, consoleWriteMethodInfo);
3309 }
3310 OutputCallNoSwitchStmt(); // switch (tryCallNo) ... 3208 OutputCallNoSwitchStmt(); // switch (tryCallNo) ...
3311 3209
3312 CompValuLocalVar catchVarLocExc = null; 3210 CompValuLocalVar catchVarLocExc = null;
@@ -3324,26 +3222,6 @@ namespace OpenSim.Region.ScriptEngine.Yengine
3324 ScriptMyLocal excLocal = ilGen.DeclareLocal(typeof(String), "catchstr_" + tryStmt.Unique); 3222 ScriptMyLocal excLocal = ilGen.DeclareLocal(typeof(String), "catchstr_" + tryStmt.Unique);
3325 3223
3326 ilGen.BeginCatchBlock(typeof(Exception)); // start of the catch block that can catch any exception 3224 ilGen.BeginCatchBlock(typeof(Exception)); // start of the catch block that can catch any exception
3327 if(DEBUG_TRYSTMT)
3328 {
3329 ilGen.Emit(tryStmt.catchStmt, OpCodes.Ldstr, "enter catch*: " + tryStmt.line + " callMode=");
3330 ilGen.Emit(tryStmt.catchStmt, OpCodes.Call, consoleWriteMethodInfo);
3331 PushXMRInst();
3332 ilGen.Emit(tryStmt.catchStmt, OpCodes.Ldfld, callModeFieldInfo);
3333 ilGen.Emit(tryStmt.catchStmt, OpCodes.Box, typeof(int));
3334 ilGen.Emit(tryStmt.catchStmt, OpCodes.Call, consoleWriteMethodInfo);
3335 ilGen.Emit(tryStmt.catchStmt, OpCodes.Ldstr, " catCallNo=");
3336 ilGen.Emit(tryStmt.catchStmt, OpCodes.Call, consoleWriteMethodInfo);
3337 catCallNo.PushVal(this, tryStmt);
3338 ilGen.Emit(tryStmt.catchStmt, OpCodes.Box, typeof(int));
3339 ilGen.Emit(tryStmt.catchStmt, OpCodes.Call, consoleWriteMethodInfo);
3340 ilGen.Emit(tryStmt.catchStmt, OpCodes.Ldstr, " exc=");
3341 ilGen.Emit(tryStmt.catchStmt, OpCodes.Call, consoleWriteMethodInfo);
3342 ilGen.Emit(tryStmt.catchStmt, OpCodes.Dup);
3343 ilGen.Emit(tryStmt.catchStmt, OpCodes.Call, consoleWriteMethodInfo);
3344 ilGen.Emit(tryStmt.catchStmt, OpCodes.Ldstr, "\n");
3345 ilGen.Emit(tryStmt.catchStmt, OpCodes.Call, consoleWriteMethodInfo);
3346 }
3347 ilGen.Emit(tryStmt.catchStmt, OpCodes.Call, scriptRestoreCatchExceptionUnwrap); 3225 ilGen.Emit(tryStmt.catchStmt, OpCodes.Call, scriptRestoreCatchExceptionUnwrap);
3348 // exc = ScriptRestoreCatchException.Unwrap (exc); 3226 // exc = ScriptRestoreCatchException.Unwrap (exc);
3349 ilGen.Emit(tryStmt.catchStmt, OpCodes.Dup); // rethrow if IXMRUncatchable (eg, StackCaptureException) 3227 ilGen.Emit(tryStmt.catchStmt, OpCodes.Dup); // rethrow if IXMRUncatchable (eg, StackCaptureException)
@@ -3475,34 +3353,6 @@ namespace OpenSim.Region.ScriptEngine.Yengine
3475 ilGen.BeginExceptionBlock(); // try { 3353 ilGen.BeginExceptionBlock(); // try {
3476 ilGen.BeginExceptionBlock(); // try { 3354 ilGen.BeginExceptionBlock(); // try {
3477 openCallLabel = null; 3355 openCallLabel = null;
3478 if(DEBUG_TRYSTMT)
3479 {
3480 ilGen.Emit(tryStmt, OpCodes.Ldstr, "enter try*: " + tryStmt.line + " callMode=");
3481 ilGen.Emit(tryStmt, OpCodes.Call, consoleWriteMethodInfo);
3482 PushXMRInst();
3483 ilGen.Emit(tryStmt, OpCodes.Ldfld, callModeFieldInfo);
3484 ilGen.Emit(tryStmt, OpCodes.Box, typeof(int));
3485 ilGen.Emit(tryStmt, OpCodes.Call, consoleWriteMethodInfo);
3486 ilGen.Emit(tryStmt, OpCodes.Ldstr, " tryCallNo=");
3487 ilGen.Emit(tryStmt, OpCodes.Call, consoleWriteMethodInfo);
3488 tryCallNo.PushVal(this, tryStmt);
3489 ilGen.Emit(tryStmt, OpCodes.Box, typeof(int));
3490 ilGen.Emit(tryStmt, OpCodes.Call, consoleWriteMethodInfo);
3491 ilGen.Emit(tryStmt, OpCodes.Ldstr, " finCallNo=");
3492 ilGen.Emit(tryStmt, OpCodes.Call, consoleWriteMethodInfo);
3493 finCallNo.PushVal(this, tryStmt);
3494 ilGen.Emit(tryStmt, OpCodes.Box, typeof(int));
3495 ilGen.Emit(tryStmt, OpCodes.Call, consoleWriteMethodInfo);
3496 ilGen.Emit(tryStmt, OpCodes.Ldstr, " catThrown.IsNull=");
3497 ilGen.Emit(tryStmt, OpCodes.Call, consoleWriteMethodInfo);
3498 catThrown.PushVal(this, tryStmt);
3499 ilGen.Emit(tryStmt, OpCodes.Ldnull);
3500 ilGen.Emit(tryStmt, OpCodes.Ceq);
3501 ilGen.Emit(tryStmt, OpCodes.Box, typeof(int));
3502 ilGen.Emit(tryStmt, OpCodes.Call, consoleWriteMethodInfo);
3503 ilGen.Emit(tryStmt, OpCodes.Ldstr, "\n");
3504 ilGen.Emit(tryStmt, OpCodes.Call, consoleWriteMethodInfo);
3505 }
3506 3356
3507 GetCallNo(tryStmt, tryCallNo); // if (__tryCallNo >= 0) goto tryCallSw; 3357 GetCallNo(tryStmt, tryCallNo); // if (__tryCallNo >= 0) goto tryCallSw;
3508 ilGen.Emit(tryStmt, OpCodes.Ldc_I4_0); 3358 ilGen.Emit(tryStmt, OpCodes.Ldc_I4_0);
@@ -3529,15 +3379,6 @@ namespace OpenSim.Region.ScriptEngine.Yengine
3529 } 3379 }
3530 3380
3531 CallLabel tryThrow = new CallLabel(this, tryStmt); // tryThrow:<tryCallLabel>: 3381 CallLabel tryThrow = new CallLabel(this, tryStmt); // tryThrow:<tryCallLabel>:
3532 if(DEBUG_TRYSTMT)
3533 {
3534 ilGen.Emit(tryStmt, OpCodes.Ldstr, "tryThrow*: " + tryStmt.line + " catThrown=");
3535 ilGen.Emit(tryStmt, OpCodes.Call, consoleWriteMethodInfo);
3536 catThrown.PushVal(this, tryStmt);
3537 ilGen.Emit(tryStmt, OpCodes.Call, consoleWriteMethodInfo);
3538 ilGen.Emit(tryStmt, OpCodes.Ldstr, "\n");
3539 ilGen.Emit(tryStmt, OpCodes.Call, consoleWriteMethodInfo);
3540 }
3541 catThrown.PushVal(this, tryStmt); // throw new ScriptRestoreCatchException (__catThrown); 3382 catThrown.PushVal(this, tryStmt); // throw new ScriptRestoreCatchException (__catThrown);
3542 ilGen.Emit(tryStmt, OpCodes.Newobj, scriptRestoreCatchExceptionConstructorInfo); 3383 ilGen.Emit(tryStmt, OpCodes.Newobj, scriptRestoreCatchExceptionConstructorInfo);
3543 ilGen.Emit(tryStmt, OpCodes.Throw); 3384 ilGen.Emit(tryStmt, OpCodes.Throw);
@@ -3548,21 +3389,6 @@ namespace OpenSim.Region.ScriptEngine.Yengine
3548 // } 3389 // }
3549 3390
3550 ilGen.BeginCatchBlock(typeof(Exception)); // start of the catch block that can catch any exception 3391 ilGen.BeginCatchBlock(typeof(Exception)); // start of the catch block that can catch any exception
3551 if(DEBUG_TRYSTMT)
3552 {
3553 ilGen.Emit(tryStmt, OpCodes.Ldstr, "enter catch*: " + tryStmt.line + " callMode=");
3554 ilGen.Emit(tryStmt, OpCodes.Call, consoleWriteMethodInfo);
3555 PushXMRInst();
3556 ilGen.Emit(tryStmt, OpCodes.Ldfld, callModeFieldInfo);
3557 ilGen.Emit(tryStmt, OpCodes.Box, typeof(int));
3558 ilGen.Emit(tryStmt, OpCodes.Call, consoleWriteMethodInfo);
3559 ilGen.Emit(tryStmt, OpCodes.Ldstr, " exc=");
3560 ilGen.Emit(tryStmt, OpCodes.Call, consoleWriteMethodInfo);
3561 ilGen.Emit(tryStmt, OpCodes.Dup);
3562 ilGen.Emit(tryStmt, OpCodes.Call, consoleWriteMethodInfo);
3563 ilGen.Emit(tryStmt, OpCodes.Ldstr, "\n");
3564 ilGen.Emit(tryStmt, OpCodes.Call, consoleWriteMethodInfo);
3565 }
3566 ilGen.Emit(tryStmt, OpCodes.Call, scriptRestoreCatchExceptionUnwrap); // exc = ScriptRestoreCatchException.Unwrap (exc); 3392 ilGen.Emit(tryStmt, OpCodes.Call, scriptRestoreCatchExceptionUnwrap); // exc = ScriptRestoreCatchException.Unwrap (exc);
3567 PushXMRInst(); // if (callMode == CallMode_SAVE) goto catchRetro; 3393 PushXMRInst(); // if (callMode == CallMode_SAVE) goto catchRetro;
3568 ilGen.Emit(tryStmt, OpCodes.Ldfld, callModeFieldInfo); 3394 ilGen.Emit(tryStmt, OpCodes.Ldfld, callModeFieldInfo);
@@ -4154,11 +3980,19 @@ namespace OpenSim.Region.ScriptEngine.Yengine
4154 3980
4155 // Maybe the expression can be converted to a constant. 3981 // Maybe the expression can be converted to a constant.
4156 bool didOne; 3982 bool didOne;
4157 do 3983 try
4158 { 3984 {
4159 didOne = false; 3985 do
4160 rVal = rVal.TryComputeConstant(LookupBodyConstants, ref didOne); 3986 {
4161 } while(didOne); 3987 didOne = false;
3988 rVal = rVal.TryComputeConstant(LookupBodyConstants, ref didOne);
3989 } while(didOne);
3990 }
3991 catch(Exception ex)
3992 {
3993 ErrorMsg(errorMessageToken, ex.Message);
3994 throw;
3995 }
4162 3996
4163 // Generate code for the computation and return resulting type and location. 3997 // Generate code for the computation and return resulting type and location.
4164 CompValu cVal = null; 3998 CompValu cVal = null;
diff --git a/OpenSim/Region/ScriptEngine/YEngine/MMRScriptInlines.cs b/OpenSim/Region/ScriptEngine/YEngine/MMRScriptInlines.cs
index e17d41a..31dc5bc 100644
--- a/OpenSim/Region/ScriptEngine/YEngine/MMRScriptInlines.cs
+++ b/OpenSim/Region/ScriptEngine/YEngine/MMRScriptInlines.cs
@@ -138,13 +138,13 @@ namespace OpenSim.Region.ScriptEngine.Yengine
138 }; 138 };
139 139
140 VarDict ifd = new VarDict(false); 140 VarDict ifd = new VarDict(false);
141
142 Type[] oneDoub = new Type[] { typeof(double) }; 141 Type[] oneDoub = new Type[] { typeof(double) };
143 Type[] twoDoubs = new Type[] { typeof(double), typeof(double) }; 142 Type[] twoDoubs = new Type[] { typeof(double), typeof(double) };
144 143
145 /* 144 /*
146 * Mono generates an FPU instruction for many math calls. 145 * Mono generates an FPU instruction for many math calls.
147 */ 146 */
147
148 new TokenDeclInline_LLAbs(ifd); 148 new TokenDeclInline_LLAbs(ifd);
149 new TokenDeclInline_Math(ifd, "llAcos(float)", "Acos", oneDoub); 149 new TokenDeclInline_Math(ifd, "llAcos(float)", "Acos", oneDoub);
150 new TokenDeclInline_Math(ifd, "llAsin(float)", "Asin", oneDoub); 150 new TokenDeclInline_Math(ifd, "llAsin(float)", "Asin", oneDoub);
diff --git a/OpenSim/Region/ScriptEngine/YEngine/MMRScriptReduce.cs b/OpenSim/Region/ScriptEngine/YEngine/MMRScriptReduce.cs
index 85bc9aa..f3bc764 100644
--- a/OpenSim/Region/ScriptEngine/YEngine/MMRScriptReduce.cs
+++ b/OpenSim/Region/ScriptEngine/YEngine/MMRScriptReduce.cs
@@ -7296,7 +7296,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
7296 rValRight = rValRight.TryComputeConstant(lookup, ref didOne); 7296 rValRight = rValRight.TryComputeConstant(lookup, ref didOne);
7297 if((rValLeft is TokenRValConst) && (rValRight is TokenRValConst)) 7297 if((rValLeft is TokenRValConst) && (rValRight is TokenRValConst))
7298 { 7298 {
7299 try 7299// try
7300 { 7300 {
7301 object val = opcode.binOpConst(((TokenRValConst)rValLeft).val, 7301 object val = opcode.binOpConst(((TokenRValConst)rValLeft).val,
7302 ((TokenRValConst)rValRight).val); 7302 ((TokenRValConst)rValRight).val);
@@ -7304,7 +7304,7 @@ namespace OpenSim.Region.ScriptEngine.Yengine
7304 didOne = true; 7304 didOne = true;
7305 return rValConst; 7305 return rValConst;
7306 } 7306 }
7307 catch 7307// catch
7308 { 7308 {
7309 } 7309 }
7310 } 7310 }
diff --git a/OpenSim/Region/ScriptEngine/YEngine/MMRScriptTokenize.cs b/OpenSim/Region/ScriptEngine/YEngine/MMRScriptTokenize.cs
index 199216e..e0b7f5d 100644
--- a/OpenSim/Region/ScriptEngine/YEngine/MMRScriptTokenize.cs
+++ b/OpenSim/Region/ScriptEngine/YEngine/MMRScriptTokenize.cs
@@ -611,8 +611,20 @@ namespace OpenSim.Region.ScriptEngine.Yengine
611 continue; 611 continue;
612 } 612 }
613 613
614 // Check for option enables. 614 // Check for option enables.
615 if((c == ';') && (lastToken is TokenName) && 615
616 if ((c == ';') && (lastToken is TokenName) &&
617 (strcasecmp(((TokenName)lastToken).val, "yoptions") == 0))
618 {
619 options.advFlowCtl = true;
620 options.tryCatch = true;
621
622 lastToken = lastToken.prevToken;
623 lastToken.nextToken = null;
624 continue;
625 }
626
627 else if ((c == ';') && (lastToken is TokenName) &&
616 (lastToken.prevToken is TokenName) && 628 (lastToken.prevToken is TokenName) &&
617 (strcasecmp(((TokenName)lastToken.prevToken).val, "yoption") == 0)) 629 (strcasecmp(((TokenName)lastToken.prevToken).val, "yoption") == 0))
618 { 630 {
@@ -2186,44 +2198,79 @@ namespace OpenSim.Region.ScriptEngine.Yengine
2186 } 2198 }
2187 public static object Div(object left, object right) 2199 public static object Div(object left, object right)
2188 { 2200 {
2189 if((left is int) && (right is int)) 2201 double r;
2202 try
2190 { 2203 {
2191 return (int)left / (int)right; 2204 if ((left is int) && (right is int))
2205 {
2206 return (int)left / (int)right;
2207 }
2208 if ((left is double) && (right is int))
2209 {
2210 r = (double)left / (int)right;
2211 if (double.IsNaN(r) || double.IsInfinity(r))
2212 throw new Exception("Division by Zero");
2213 return r;
2214 }
2192 } 2215 }
2193 if((left is int) && (right is double)) 2216 catch (DivideByZeroException)
2194 { 2217 {
2195 return (int)left / (double)right; 2218 throw new Exception("Division by Zero");
2196 } 2219 }
2197 if((left is double) && (right is int)) 2220
2221 if ((left is int) && (right is double))
2198 { 2222 {
2199 return (double)left / (int)right; 2223 r = (int)left / (double)right;
2200 } 2224 }
2201 if((left is double) && (right is double)) 2225 else if((left is double) && (right is double))
2202 { 2226 {
2203 return (double)left / (double)right; 2227 r= (double)left / (double)right;
2204 } 2228 }
2205 return null; 2229 else
2230 return null;
2231
2232 if (double.IsNaN(r) || double.IsInfinity(r))
2233 throw new Exception("Division by Zero");
2234 return r;
2206 } 2235 }
2207 public static object Mod(object left, object right) 2236 public static object Mod(object left, object right)
2208 { 2237 {
2209 if((left is int) && (right is int)) 2238 double r;
2239 try
2210 { 2240 {
2211 return (int)left % (int)right; 2241 if ((left is int) && (right is int))
2242 {
2243 return (int)left % (int)right;
2244 }
2245 if ((left is double) && (right is int))
2246 {
2247 r = (double)left % (int)right;
2248 if (double.IsNaN(r) || double.IsInfinity(r))
2249 throw new Exception("Division by Zero");
2250 return r;
2251 }
2212 } 2252 }
2213 if((left is int) && (right is double)) 2253 catch (DivideByZeroException)
2214 { 2254 {
2215 return (int)left % (double)right; 2255 throw new Exception("Division by Zero");
2216 } 2256 }
2217 if((left is double) && (right is int)) 2257
2258 if ((left is int) && (right is double))
2218 { 2259 {
2219 return (double)left % (int)right; 2260 r = (int)left % (double)right;
2220 } 2261 }
2221 if((left is double) && (right is double)) 2262 else if ((left is double) && (right is double))
2222 { 2263 {
2223 return (double)left % (double)right; 2264 r = (double)left % (double)right;
2224 } 2265 }
2225 return null; 2266 else
2267 return null;
2268
2269 if (double.IsNaN(r) || double.IsInfinity(r))
2270 throw new Exception("Division by Zero");
2271 return r;
2226 } 2272 }
2273
2227 public static object Mul(object left, object right) 2274 public static object Mul(object left, object right)
2228 { 2275 {
2229 if((left is int) && (right is int)) 2276 if((left is int) && (right is int))