Beispiel #1
0
 private static void ExplCheck(IScriptCodeGen scg, Token errorAt, bool explicitAllowed, string oldString, string newString)
 {
     if (!explicitAllowed)
     {
         scg.ErrorMsg(errorAt, "must explicitly cast from " + oldString + " to " + newString);
     }
 }
Beispiel #2
0
 private static void TypeCastInteger2Bool(IScriptCodeGen scg, Token errorAt)
 {
     scg.ilGen.Emit(errorAt, OpCodes.Ldc_I4_0);
     scg.ilGen.Emit(errorAt, OpCodes.Ceq);
     scg.ilGen.Emit(errorAt, OpCodes.Ldc_I4_1);
     scg.ilGen.Emit(errorAt, OpCodes.Xor);
 }
Beispiel #3
0
 private static void TypeCastFloat2Bool(IScriptCodeGen scg, Token errorAt)
 {
     scg.ilGen.Emit(errorAt, OpCodes.Ldc_R4, 0.0f);
     scg.ilGen.Emit(errorAt, OpCodes.Ceq);
     scg.ilGen.Emit(errorAt, OpCodes.Ldc_I4_1);
     scg.ilGen.Emit(errorAt, OpCodes.Xor);
 }
Beispiel #4
0
 private static void TypeCastList2Object(IScriptCodeGen scg, Token errorAt)
 {
     if (typeof(LSL_List).IsValueType)
     {
         scg.ilGen.Emit(errorAt, OpCodes.Box, typeof(LSL_List));
     }
 }
Beispiel #5
0
 private static void TypeCastObject2List(IScriptCodeGen scg, Token errorAt)
 {
     if (typeof(LSL_List).IsValueType)
     {
         scg.ilGen.Emit(errorAt, OpCodes.Call, objectToListMethodInfo);
     }
     else
     {
         scg.ilGen.Emit(errorAt, OpCodes.Castclass, typeof(LSL_List));
     }
 }
Beispiel #6
0
 /**
  * @brief If caller wants the unwrapped value on stack wrapped LSL-style, wrap it.
  */
 private static void LSLWrap(IScriptCodeGen scg, Token errorAt, TokenType type)
 {
     if (type.ToLSLWrapType() == typeof(LSL_Float))
     {
         scg.ilGen.Emit(errorAt, OpCodes.Newobj, lslFloatConstructorInfo);
     }
     if (type.ToLSLWrapType() == typeof(LSL_Integer))
     {
         scg.ilGen.Emit(errorAt, OpCodes.Newobj, lslIntegerConstructorInfo);
     }
     if (type.ToLSLWrapType() == typeof(LSL_String))
     {
         scg.ilGen.Emit(errorAt, OpCodes.Newobj, lslStringConstructorInfo);
     }
 }
Beispiel #7
0
 /**
  * @brief If value on the stack is an LSL-style wrapped value, unwrap it.
  */
 public static void LSLUnwrap(IScriptCodeGen scg, Token errorAt, TokenType type)
 {
     if (type.ToLSLWrapType() == typeof(LSL_Float))
     {
         scg.ilGen.Emit(errorAt, OpCodes.Ldfld, lslFloatValueFieldInfo);
     }
     if (type.ToLSLWrapType() == typeof(LSL_Integer))
     {
         scg.ilGen.Emit(errorAt, OpCodes.Ldfld, lslIntegerValueFieldInfo);
     }
     if (type.ToLSLWrapType() == typeof(LSL_String))
     {
         scg.ilGen.Emit(errorAt, OpCodes.Ldfld, lslStringValueFieldInfo);
     }
 }
Beispiel #8
0
 private static void TypeCastInteger2Float(IScriptCodeGen scg, Token errorAt)
 {
     if (typeof(double) == typeof(float))
     {
         scg.ilGen.Emit(errorAt, OpCodes.Conv_R4);
     }
     else if (typeof(double) == typeof(double))
     {
         scg.ilGen.Emit(errorAt, OpCodes.Conv_R8);
     }
     else
     {
         throw new Exception("unknown type");
     }
 }
Beispiel #9
0
 private static void TypeCastVector2Object(IScriptCodeGen scg, Token errorAt)
 {
     scg.ilGen.Emit(errorAt, OpCodes.Box, typeof(LSL_Vector));
 }
Beispiel #10
0
 private static void TypeCastString2Object(IScriptCodeGen scg, Token errorAt)
 {
 }
Beispiel #11
0
 private static void TypeCastString2Vector(IScriptCodeGen scg, Token errorAt)
 {
     scg.ilGen.Emit(errorAt, OpCodes.Newobj, vectorConstrucorStringInfo);
 }
Beispiel #12
0
 private static void TypeCastBool2Integer(IScriptCodeGen scg, Token errorAt)
 {
 }
Beispiel #13
0
 private static void TypeCastObject2Vector(IScriptCodeGen scg, Token errorAt)
 {
     scg.ilGen.Emit(errorAt, OpCodes.Call, objectToVectorMethodInfo);
 }
Beispiel #14
0
 private static void TypeCastFloat2Integer(IScriptCodeGen scg, Token errorAt)
 {
     scg.ilGen.Emit(errorAt, OpCodes.Conv_I4);
 }
Beispiel #15
0
 private static void TypeCastObject2Exc(IScriptCodeGen scg, Token errorAt)
 {
     scg.ilGen.Emit(errorAt, OpCodes.Castclass, typeof(Exception));
 }
Beispiel #16
0
        /**
         * @brief Emit code that converts the top stack item from 'oldType' to 'newType'
         * @param scg = what script we are compiling
         * @param errorAt = token used for source location for error messages
         * @param oldType = type of item currently on the stack
         * @param newType = type to convert it to
         * @param explicitAllowed = false: only consider implicit casts
         *                           true: consider both implicit and explicit casts
         * @returns with code emitted for conversion (or error message output if not allowed, and stack left unchanged)
         */
        public static void CastTopOfStack(IScriptCodeGen scg, Token errorAt, TokenType oldType, TokenType newType, bool explicitAllowed)
        {
            CastDelegate castDelegate;
            string       oldString = oldType.ToString();
            string       newString = newType.ToString();

            // 'key' -> 'bool' is the only time we care about key being different than string.
            if ((oldString == "key") && (newString == "bool"))
            {
                LSLUnwrap(scg, errorAt, oldType);
                scg.ilGen.Emit(errorAt, OpCodes.Call, keyToBoolMethodInfo);
                LSLWrap(scg, errorAt, newType);
                return;
            }

            // Treat key and string as same type for all other type casts.
            if (oldString == "key")
            {
                oldString = "string";
            }
            if (newString == "key")
            {
                newString = "string";
            }

            // If the types are the same, there is no conceptual casting needed.
            // However, there may be wraping/unwraping to/from the LSL wrappers.
            if (oldString == newString)
            {
                if (oldType.ToLSLWrapType() != newType.ToLSLWrapType())
                {
                    LSLUnwrap(scg, errorAt, oldType);
                    LSLWrap(scg, errorAt, newType);
                }
                return;
            }

            // Script-defined classes can be cast up and down the tree.
            if ((oldType is TokenTypeSDTypeClass) && (newType is TokenTypeSDTypeClass))
            {
                TokenDeclSDTypeClass oldSDTC = ((TokenTypeSDTypeClass)oldType).decl;
                TokenDeclSDTypeClass newSDTC = ((TokenTypeSDTypeClass)newType).decl;

                // implicit cast allowed from leaf toward root
                for (TokenDeclSDTypeClass sdtc = oldSDTC; sdtc != null; sdtc = sdtc.extends)
                {
                    if (sdtc == newSDTC)
                    {
                        return;
                    }
                }

                // explicit cast allowed from root toward leaf
                for (TokenDeclSDTypeClass sdtc = newSDTC; sdtc != null; sdtc = sdtc.extends)
                {
                    if (sdtc == oldSDTC)
                    {
                        ExplCheck(scg, errorAt, explicitAllowed, oldString, newString);
                        scg.ilGen.Emit(errorAt, OpCodes.Ldc_I4, newSDTC.sdTypeIndex);
                        scg.ilGen.Emit(errorAt, OpCodes.Call, sdTypeClassCastClass2ClassMethodInfo);
                        return;
                    }
                }

                // not on same branch
                goto illcast;
            }

            // One script-defined interface type cannot be cast to another script-defined interface type,
            // unless the old interface declares that it implements the new interface.  That proves that
            // the underlying object, no matter what type, implements the new interface.
            if ((oldType is TokenTypeSDTypeInterface) && (newType is TokenTypeSDTypeInterface))
            {
                TokenDeclSDTypeInterface oldDecl = ((TokenTypeSDTypeInterface)oldType).decl;
                TokenDeclSDTypeInterface newDecl = ((TokenTypeSDTypeInterface)newType).decl;
                if (!oldDecl.Implements(newDecl))
                {
                    goto illcast;
                }
                scg.ilGen.Emit(errorAt, OpCodes.Ldstr, newType.ToString());
                scg.ilGen.Emit(errorAt, OpCodes.Call, sdTypeClassCastObj2IFaceMethodInfo);
                return;
            }

            // A script-defined class type can be implicitly cast to a script-defined interface type that it
            // implements.  The result is an array of delegates that give the class's implementation of the
            // various methods defined by the interface.
            if ((oldType is TokenTypeSDTypeClass) && (newType is TokenTypeSDTypeInterface))
            {
                TokenDeclSDTypeClass oldSDTC = ((TokenTypeSDTypeClass)oldType).decl;
                int intfIndex;
                if (!oldSDTC.intfIndices.TryGetValue(newType.ToString(), out intfIndex))
                {
                    goto illcast;
                }
                scg.ilGen.Emit(errorAt, OpCodes.Ldfld, sdtcITableFieldInfo);
                scg.ilGen.Emit(errorAt, OpCodes.Ldc_I4, intfIndex);
                scg.ilGen.Emit(errorAt, OpCodes.Ldelem, typeof(Delegate[]));
                return;
            }

            // A script-defined interface type can be explicitly cast to a script-defined class type by
            // extracting the Target property from element 0 of the delegate array that is the interface
            // object and making sure it casts to the correct script-defined class type.
            //
            // But then only if the class type implements the interface type.
            if ((oldType is TokenTypeSDTypeInterface) && (newType is TokenTypeSDTypeClass))
            {
                TokenTypeSDTypeInterface oldSDTI = (TokenTypeSDTypeInterface)oldType;
                TokenTypeSDTypeClass     newSDTC = (TokenTypeSDTypeClass)newType;

                if (!newSDTC.decl.CanCastToIntf(oldSDTI.decl))
                {
                    goto illcast;
                }

                ExplCheck(scg, errorAt, explicitAllowed, oldString, newString);
                scg.ilGen.Emit(errorAt, OpCodes.Ldc_I4, newSDTC.decl.sdTypeIndex);
                scg.ilGen.Emit(errorAt, OpCodes.Call, sdTypeClassCastIFace2ClassMethodInfo);
                return;
            }

            // A script-defined interface type can be implicitly cast to object.
            if ((oldType is TokenTypeSDTypeInterface) && (newType is TokenTypeObject))
            {
                return;
            }

            // An object can be explicitly cast to a script-defined interface.
            if ((oldType is TokenTypeObject) && (newType is TokenTypeSDTypeInterface))
            {
                ExplCheck(scg, errorAt, explicitAllowed, oldString, newString);
                scg.ilGen.Emit(errorAt, OpCodes.Ldstr, newString);
                scg.ilGen.Emit(errorAt, OpCodes.Call, sdTypeClassCastObj2IFaceMethodInfo);
                return;
            }

            // Cast to void is always allowed, such as discarding value from 'i++' or function return value.
            if (newType is TokenTypeVoid)
            {
                scg.ilGen.Emit(errorAt, OpCodes.Pop);
                return;
            }

            // Cast from undef to object or script-defined type is always allowed.
            if ((oldType is TokenTypeUndef) &&
                ((newType is TokenTypeObject) ||
                 (newType is TokenTypeSDTypeClass) ||
                 (newType is TokenTypeSDTypeInterface)))
            {
                return;
            }

            // Script-defined classes can be implicitly cast to objects.
            if ((oldType is TokenTypeSDTypeClass) && (newType is TokenTypeObject))
            {
                return;
            }

            // Script-defined classes can be explicitly cast from objects and other script-defined classes.
            // Note that we must manually check that it is the correct SDTypeClass however because as far as
            // mono is concerned, all SDTypeClass's are the same.
            if ((oldType is TokenTypeObject) && (newType is TokenTypeSDTypeClass))
            {
                ExplCheck(scg, errorAt, explicitAllowed, oldString, newString);
                scg.ilGen.Emit(errorAt, OpCodes.Ldc_I4, ((TokenTypeSDTypeClass)newType).decl.sdTypeIndex);
                scg.ilGen.Emit(errorAt, OpCodes.Call, sdTypeClassCastClass2ClassMethodInfo);
                return;
            }

            // Delegates can be implicitly cast to/from objects.
            if ((oldType is TokenTypeSDTypeDelegate) && (newType is TokenTypeObject))
            {
                return;
            }
            if ((oldType is TokenTypeObject) && (newType is TokenTypeSDTypeDelegate))
            {
                scg.ilGen.Emit(errorAt, OpCodes.Castclass, newType.ToSysType());
                return;
            }

            // Some actual conversion is needed, see if it is in table of legal casts.
            string key = oldString + " " + newString;

            if (!legalTypeCasts.TryGetValue(key, out castDelegate))
            {
                key = oldString + "*" + newString;
                if (!legalTypeCasts.TryGetValue(key, out castDelegate))
                {
                    goto illcast;
                }
                ExplCheck(scg, errorAt, explicitAllowed, oldString, newString);
            }

            // Ok, output cast.  But make sure it is in native form without any LSL wrapping
            // before passing to our casting routine.  Then if caller is expecting an LSL-
            // wrapped value on the stack upon return, wrap it up after our casting.
            LSLUnwrap(scg, errorAt, oldType);
            castDelegate(scg, errorAt);
            LSLWrap(scg, errorAt, newType);
            return;

illcast:
            scg.ErrorMsg(errorAt, "illegal to cast from " + oldString + " to " + newString);
            if (!(oldType is TokenTypeVoid))
            {
                scg.ilGen.Emit(errorAt, OpCodes.Pop);
            }
            scg.PushDefaultValue(newType);
        }
Beispiel #17
0
 private static void TypeCastObject2Array(IScriptCodeGen scg, Token errorAt)
 {
     scg.ilGen.Emit(errorAt, OpCodes.Castclass, typeof(XMR_Array));
 }
Beispiel #18
0
 private static void TypeCastString2Float(IScriptCodeGen scg, Token errorAt)
 {
     scg.ilGen.Emit(errorAt, OpCodes.Newobj, floatConstructorStringInfo);
     scg.ilGen.Emit(errorAt, OpCodes.Ldfld, lslFloatValueFieldInfo);
 }
Beispiel #19
0
 private static void TypeCastString2List(IScriptCodeGen scg, Token errorAt)
 {
     scg.ilGen.Emit(errorAt, OpCodes.Call, stringToListMethodInfo);
 }
Beispiel #20
0
 private static void TypeCastInteger2Char(IScriptCodeGen scg, Token errorAt)
 {
 }
Beispiel #21
0
 private static void TypeCastBool2Object(IScriptCodeGen scg, Token errorAt)
 {
     scg.ilGen.Emit(errorAt, OpCodes.Box, typeof(bool));
 }
Beispiel #22
0
 private static void TypeCastFloat2Object(IScriptCodeGen scg, Token errorAt)
 {
     scg.ilGen.Emit(errorAt, OpCodes.Box, typeof(double));
 }
Beispiel #23
0
 private static void TypeCastInteger2List(IScriptCodeGen scg, Token errorAt)
 {
     scg.ilGen.Emit(errorAt, OpCodes.Call, integerToListMethodInfo);
 }
Beispiel #24
0
 private static void TypeCastObject2Char(IScriptCodeGen scg, Token errorAt)
 {
     scg.ilGen.Emit(errorAt, OpCodes.Unbox_Any, typeof(char));
 }
Beispiel #25
0
 private static void TypeCastRotation2String(IScriptCodeGen scg, Token errorAt)
 {
     scg.ilGen.Emit(errorAt, OpCodes.Call, rotationToStringMethodInfo);
 }
Beispiel #26
0
 private static void TypeCastExc2String(IScriptCodeGen scg, Token errorAt)
 {
     scg.PushXMRInst();
     scg.ilGen.Emit(errorAt, OpCodes.Call, excToStringMethodInfo);
 }
Beispiel #27
0
 private static void TypeCastString2Integer(IScriptCodeGen scg, Token errorAt)
 {
     scg.ilGen.Emit(errorAt, OpCodes.Newobj, integerConstructorStringInfo);
     scg.ilGen.Emit(errorAt, OpCodes.Ldfld, lslIntegerValueFieldInfo);
 }
Beispiel #28
0
 private static void TypeCastInteger2Object(IScriptCodeGen scg, Token errorAt)
 {
     scg.ilGen.Emit(errorAt, OpCodes.Box, typeof(int));
 }
Beispiel #29
0
 private static void TypeCastVector2String(IScriptCodeGen scg, Token errorAt)
 {
     scg.ilGen.Emit(errorAt, OpCodes.Call, vectorToStringMethodInfo);
 }
Beispiel #30
0
 private static void TypeCastList2Bool(IScriptCodeGen scg, Token errorAt)
 {
     scg.ilGen.Emit(errorAt, OpCodes.Call, listToBoolMethodInfo);
 }