public override object Execute(ProtoCore.Runtime.Context c, Interpreter dsi)
        {
            Object retVal = base.Execute(c, dsi);

            if (retVal == null)
            {
                return(null);
            }

            StackValue propValue  = (StackValue)retVal;
            StackValue thisObject = dsi.runtime.rmem.Stack.Last();

            if (StackUtils.IsValidPointer(thisObject) && StackUtils.IsReferenceType(propValue))
            {
                int classIndex = (int)thisObject.metaData.type;
                if (classIndex != ProtoCore.DSASM.Constants.kInvalidIndex)
                {
                    var core    = dsi.runtime.Core;
                    int thisptr = (int)thisObject.opdata;

                    int        idx      = core.ClassTable.ClassNodes[classIndex].symbols.IndexOf(PropertyName);
                    StackValue oldValue = core.Heap.Heaplist[(int)thisObject.opdata].GetValue(idx, core);
                    if (!StackUtils.Equals(oldValue, propValue))
                    {
                        GCUtils.GCRetain(propValue, core);
                        core.Heap.Heaplist[thisptr].SetValue(idx, propValue);
                    }
                }
            }

            return(retVal);
        }
Esempio n. 2
0
        /// <summary>
        /// Convert the parameters passed to the types specified in this fep
        /// </summary>
        /// <param name="formalParameters"></param>
        /// <returns></returns>
        public List <StackValue> CoerceParameters(List <StackValue> formalParameters, Core core)
        {
            List <StackValue> fixedUpVersions = new List <StackValue>();

            for (int i = 0; i < formalParameters.Count; i++)
            {
                StackValue formalParam = formalParameters[i];
                Type       targetType  = FormalParams[i];

                StackValue coercedParam = TypeSystem.Coerce(formalParam, targetType, core);
                GCUtils.GCRetain(coercedParam, core);
                fixedUpVersions.Add(coercedParam);
            }

            return(fixedUpVersions);
        }
Esempio n. 3
0
        public static StackValue Coerce(StackValue sv, Type targetType, Core core)
        {
            //@TODO(Jun): FIX ME - abort coersion for default args
            if (sv.IsDefaultArgument)
            {
                return(sv);
            }

            if (!(
                    sv.metaData.type == targetType.UID ||
                    (core.ClassTable.ClassNodes[sv.metaData.type].ConvertibleTo(targetType.UID)) ||
                    sv.IsArray))
            {
                core.RuntimeStatus.LogWarning(RuntimeData.WarningID.kConversionNotPossible, ProtoCore.StringConstants.kConvertNonConvertibleTypes);
                return(StackValue.Null);
            }

            //if it's an array
            if (sv.IsArray && !targetType.IsIndexable)
            {
                //This is an array rank reduction
                //this may only be performed in recursion and is illegal here
                string errorMessage = String.Format(ProtoCore.StringConstants.kConvertArrayToNonArray, core.TypeSystem.GetType(targetType.UID));
                core.RuntimeStatus.LogWarning(RuntimeData.WarningID.kConversionNotPossible, errorMessage);
                return(StackValue.Null);
            }


            if (sv.IsArray &&
                targetType.IsIndexable)
            {
                Validity.Assert(sv.IsArray);

                //We're being asked to convert an array into an array
                //walk over the structure converting each othe elements

                var hpe = core.Heap.GetHeapElement(sv);
#if GC_REFERENCE_COUNTING
                var isTemporary = hpe.Active && hpe.Refcount == 0;
#else
                var isTemporary = false;
#endif

                if (targetType.UID == (int)PrimitiveType.kTypeVar && targetType.rank == DSASM.Constants.kArbitraryRank && isTemporary)
                {
                    return(sv);
                }

                //Validity.Assert(targetType.rank != -1, "Arbitrary rank array conversion not yet implemented {2EAF557F-62DE-48F0-9BFA-F750BBCDF2CB}");

                //Decrease level of reductions by one
                Type newTargetType = new Type();
                newTargetType.UID = targetType.UID;
                if (targetType.rank != Constants.kArbitraryRank)
                {
                    newTargetType.rank = targetType.rank - 1;
                }
                else
                {
                    if (ArrayUtils.GetMaxRankForArray(sv, core) == 1)
                    {
                        //Last unpacking
                        newTargetType.rank = 0;
                    }
                    else
                    {
                        newTargetType.rank = Constants.kArbitraryRank;
                    }
                }

                return(ArrayUtils.CopyArray(sv, newTargetType, core));
            }

            if (!sv.IsArray && !sv.IsNull &&
                targetType.IsIndexable &&
                targetType.rank != DSASM.Constants.kArbitraryRank)
            {
                //We're being asked to promote the value into an array
                if (targetType.rank == 1)
                {
                    Type newTargetType = new Type();
                    newTargetType.UID  = targetType.UID;
                    newTargetType.Name = targetType.Name;
                    newTargetType.rank = 0;

                    //Upcast once
                    StackValue coercedValue = Coerce(sv, newTargetType, core);
                    GCUtils.GCRetain(coercedValue, core);
                    StackValue newSv = core.Heap.AllocateArray(new StackValue[] { coercedValue }, null);
                    return(newSv);
                }
                else
                {
                    Validity.Assert(targetType.rank > 1, "Target rank should be greater than one for this clause");

                    Type newTargetType = new Type();
                    newTargetType.UID  = targetType.UID;
                    newTargetType.Name = targetType.Name;
                    newTargetType.rank = targetType.rank - 1;

                    //Upcast once
                    StackValue coercedValue = Coerce(sv, newTargetType, core);
                    GCUtils.GCRetain(coercedValue, core);
                    StackValue newSv = core.Heap.AllocateArray(new StackValue[] { coercedValue }, null);
                    return(newSv);
                }
            }

            if (sv.IsPointer)
            {
                StackValue ret = ClassCoerece(sv, targetType, core);
                return(ret);
            }

            //If it's anything other than array, just create a new copy
            switch (targetType.UID)
            {
            case (int)PrimitiveType.kInvalidType:
                Validity.Assert(false, "Can't convert invalid type");
                break;

            case (int)PrimitiveType.kTypeBool:
                return(sv.ToBoolean(core));

            case (int)PrimitiveType.kTypeChar:
            {
                StackValue newSV = sv.ShallowClone();
                newSV.metaData = new MetaData {
                    type = (int)PrimitiveType.kTypeChar
                };
                return(newSV);
            }

            case (int)PrimitiveType.kTypeDouble:
                return(sv.ToDouble());

            case (int)PrimitiveType.kTypeFunctionPointer:
                if (sv.metaData.type != (int)PrimitiveType.kTypeFunctionPointer)
                {
                    core.RuntimeStatus.LogWarning(RuntimeData.WarningID.kTypeMismatch, ProtoCore.StringConstants.kFailToConverToFunction);
                    return(StackValue.Null);
                }
                return(sv);

            case (int)PrimitiveType.kTypeHostEntityID:
            {
                StackValue newSV = sv.ShallowClone();
                newSV.metaData = new MetaData {
                    type = (int)PrimitiveType.kTypeHostEntityID
                };
                return(newSV);
            }

            case (int)PrimitiveType.kTypeInt:
            {
                if (sv.metaData.type == (int)PrimitiveType.kTypeDouble)
                {
                    //TODO(lukechurch): Once the API is improved (MAGN-5174)
                    //Replace this with a log entry notification
                    //core.RuntimeStatus.LogWarning(RuntimeData.WarningID.kTypeConvertionCauseInfoLoss, ProtoCore.StringConstants.kConvertDoubleToInt);
                }
                return(sv.ToInteger());
            }

            case (int)PrimitiveType.kTypeNull:
            {
                if (sv.metaData.type != (int)PrimitiveType.kTypeNull)
                {
                    core.RuntimeStatus.LogWarning(RuntimeData.WarningID.kTypeMismatch, ProtoCore.StringConstants.kFailToConverToNull);
                    return(StackValue.Null);
                }
                return(sv);
            }

            case (int)PrimitiveType.kTypePointer:
            {
                if (sv.metaData.type != (int)PrimitiveType.kTypeNull)
                {
                    core.RuntimeStatus.LogWarning(RuntimeData.WarningID.kTypeMismatch, ProtoCore.StringConstants.kFailToConverToPointer);
                    return(StackValue.Null);
                }
                return(sv);
            }

            case (int)PrimitiveType.kTypeString:
            {
                StackValue newSV = sv.ShallowClone();
                newSV.metaData = new MetaData {
                    type = (int)PrimitiveType.kTypeString
                };
                if (sv.metaData.type == (int)PrimitiveType.kTypeChar)
                {
                    char ch = EncodingUtils.ConvertInt64ToCharacter(newSV.opdata);
                    newSV = StackValue.BuildString(ch.ToString(), core.Heap);
                }
                return(newSV);
            }

            case (int)PrimitiveType.kTypeVar:
            {
                return(sv);
            }

            case (int)PrimitiveType.kTypeArray:
            {
                return(ArrayUtils.CopyArray(sv, targetType, core));
            }

            default:
                if (sv.IsNull)
                {
                    return(StackValue.Null);
                }
                else
                {
                    throw new NotImplementedException("Requested coercion not implemented");
                }
            }

            throw new NotImplementedException("Requested coercion not implemented");
        }
Esempio n. 4
0
        public static StackValue Coerce(StackValue sv, Type targetType, Core core)
        {
            //@TODO(Jun): FIX ME - abort coersion for default args
            if (sv.optype == AddressType.DefaultArg)
            {
                return(sv);
            }

            if (!(
                    (int)sv.metaData.type == targetType.UID ||
                    (core.DSExecutable.classTable.ClassNodes[(int)sv.metaData.type].ConvertibleTo(targetType.UID)) ||
                    sv.optype == AddressType.ArrayPointer))
            {
                core.RuntimeStatus.LogWarning(RuntimeData.WarningID.kConversionNotPossible, ProtoCore.RuntimeData.WarningMessage.kConvertNonConvertibleTypes);
                return(StackUtils.BuildNull());
            }



            //if it's an array
            if (sv.optype == AddressType.ArrayPointer && !targetType.IsIndexable && targetType.rank != DSASM.Constants.kUndefinedRank)// && targetType.UID != (int)PrimitiveType.kTypeVar)
            {
                //This is an array rank reduction
                //this may only be performed in recursion and is illegal here
                string errorMessage = String.Format(ProtoCore.RuntimeData.WarningMessage.kConvertArrayToNonArray, core.TypeSystem.GetType(targetType.UID));
                core.RuntimeStatus.LogWarning(RuntimeData.WarningID.kConversionNotPossible, errorMessage);
                return(StackUtils.BuildNull());
            }


            if (sv.optype == AddressType.ArrayPointer && targetType.IsIndexable)
            {
                Validity.Assert(ArrayUtils.IsArray(sv));

                //We're being asked to convert an array into an array
                //walk over the structure converting each othe elements

                if (targetType.UID == (int)PrimitiveType.kTypeVar && targetType.rank == DSASM.Constants.kArbitraryRank && core.Heap.IsTemporaryPointer(sv))
                {
                    return(sv);
                }

                HeapElement  he        = core.Heap.Heaplist[(int)sv.opdata];
                StackValue[] newSubSVs = new StackValue[he.VisibleSize];

                //Validity.Assert(targetType.rank != -1, "Arbitrary rank array conversion not yet implemented {2EAF557F-62DE-48F0-9BFA-F750BBCDF2CB}");

                //Decrease level of reductions by one
                Type newTargetType = new Type();
                newTargetType.UID = targetType.UID;
                if (targetType.rank != ProtoCore.DSASM.Constants.kArbitraryRank)
                {
                    newTargetType.rank        = targetType.rank - 1;
                    newTargetType.IsIndexable = newTargetType.rank > 0;
                }
                else
                {
                    if (ArrayUtils.GetMaxRankForArray(sv, core) == 1)
                    {
                        //Last unpacking
                        newTargetType.rank        = 0;
                        newTargetType.IsIndexable = false;
                    }
                    else
                    {
                        newTargetType.rank        = ProtoCore.DSASM.Constants.kArbitraryRank;
                        newTargetType.IsIndexable = true;
                    }
                }


                for (int i = 0; i < he.VisibleSize; i++)
                {
                    StackValue coercedValue = Coerce(he.Stack[i], newTargetType, core);
                    GCUtils.GCRetain(coercedValue, core);
                    newSubSVs[i] = coercedValue;
                }

                StackValue newSV = HeapUtils.StoreArray(newSubSVs, core);
                return(newSV);
            }

            if (sv.optype != AddressType.ArrayPointer && sv.optype != AddressType.Null &&
                targetType.IsIndexable &&
                targetType.rank != DSASM.Constants.kArbitraryRank)
            {
                //We're being asked to promote the value into an array
                if (targetType.rank == 1)
                {
                    Type newTargetType = new Type();
                    newTargetType.UID         = targetType.UID;
                    newTargetType.IsIndexable = false;
                    newTargetType.Name        = targetType.Name;
                    newTargetType.rank        = 0;


                    //Upcast once
                    StackValue coercedValue = Coerce(sv, newTargetType, core);
                    GCUtils.GCRetain(coercedValue, core);
                    StackValue newSv = HeapUtils.StoreArray(new StackValue[] { coercedValue }, core);
                    return(newSv);
                }
                else
                {
                    Validity.Assert(targetType.rank > 1, "Target rank should be greater than one for this clause");

                    Type newTargetType = new Type();
                    newTargetType.UID         = targetType.UID;
                    newTargetType.IsIndexable = true;
                    newTargetType.Name        = targetType.Name;
                    newTargetType.rank        = targetType.rank - 1;


                    //Upcast once
                    StackValue coercedValue = Coerce(sv, newTargetType, core);
                    GCUtils.GCRetain(coercedValue, core);
                    StackValue newSv = HeapUtils.StoreArray(new StackValue[] { coercedValue }, core);
                    return(newSv);
                }
            }


            if (sv.optype == AddressType.Pointer)
            {
                StackValue ret = ClassCoerece(sv, targetType, core);
                return(ret);
            }

            //If it's anything other than array, just create a new copy
            switch (targetType.UID)
            {
            case (int)PrimitiveType.kInvalidType:
                Validity.Assert(false, "Can't convert invalid type");
                break;

            case (int)PrimitiveType.kTypeBool:
                return(sv.AsBoolean(core));

            case (int)PrimitiveType.kTypeChar:
            {
                StackValue newSV = sv.ShallowClone();
                newSV.metaData = new MetaData {
                    type = (int)PrimitiveType.kTypeChar
                };
                return(newSV);
            }

            case (int)PrimitiveType.kTypeDouble:
                return(sv.AsDouble());

            case (int)PrimitiveType.kTypeFunctionPointer:
                if (sv.metaData.type != (int)PrimitiveType.kTypeFunctionPointer)
                {
                    core.RuntimeStatus.LogWarning(RuntimeData.WarningID.kTypeMismatch, ProtoCore.RuntimeData.WarningMessage.kFailToConverToFunction);
                    return(StackUtils.BuildNull());
                }
                return(sv.ShallowClone());

            case (int)PrimitiveType.kTypeHostEntityID:
            {
                StackValue newSV = sv.ShallowClone();
                newSV.metaData = new MetaData {
                    type = (int)PrimitiveType.kTypeHostEntityID
                };
                return(newSV);
            }

            case (int)PrimitiveType.kTypeInt:
            {
                if (sv.metaData.type == (int)PrimitiveType.kTypeDouble)
                {
                    core.RuntimeStatus.LogWarning(RuntimeData.WarningID.kTypeConvertionCauseInfoLoss, ProtoCore.RuntimeData.WarningMessage.kConvertDoubleToInt);
                }
                return(sv.AsInt());
            }

            case (int)PrimitiveType.kTypeNull:
            {
                if (sv.metaData.type != (int)PrimitiveType.kTypeNull)
                {
                    core.RuntimeStatus.LogWarning(RuntimeData.WarningID.kTypeMismatch, ProtoCore.RuntimeData.WarningMessage.kFailToConverToNull);
                    return(StackUtils.BuildNull());
                }
                return(sv.ShallowClone());
            }

            case (int)PrimitiveType.kTypePointer:
            {
                if (sv.metaData.type != (int)PrimitiveType.kTypeNull)
                {
                    core.RuntimeStatus.LogWarning(RuntimeData.WarningID.kTypeMismatch, ProtoCore.RuntimeData.WarningMessage.kFailToConverToPointer);
                    return(StackUtils.BuildNull());
                }
                StackValue ret = sv.ShallowClone();
                return(ret);
            }

            case (int)PrimitiveType.kTypeString:
            {
                StackValue newSV = sv.ShallowClone();
                newSV.metaData = new MetaData {
                    type = (int)PrimitiveType.kTypeString
                };
                if (sv.metaData.type == (int)PrimitiveType.kTypeChar)
                {
                    char ch = ProtoCore.Utils.EncodingUtils.ConvertInt64ToCharacter(newSV.opdata);
                    newSV = StackUtils.BuildString(ch.ToString(), core.Heap);
                }
                return(newSV);
            }

            case (int)PrimitiveType.kTypeVar:
            {
                return(sv);
            }


            case (int)PrimitiveType.kTypeArray:
            {
                HeapElement  he        = core.Heap.Heaplist[(int)sv.opdata];
                StackValue[] newSubSVs = new StackValue[he.VisibleSize];

                for (int i = 0; i < he.VisibleSize; i++)
                {
                    StackValue coercedValue = Coerce(he.Stack[i], targetType, core);
                    GCUtils.GCRetain(coercedValue, core);
                    newSubSVs[i] = coercedValue;
                }

                StackValue newSV = HeapUtils.StoreArray(newSubSVs, core);
                return(newSV);
            }


            default:
                if (sv.optype == AddressType.Null)
                {
                    return(StackUtils.BuildNull());
                }
                else
                {
                    throw new NotImplementedException("Requested coercion not implemented");
                }
            }



            throw new NotImplementedException("Requested coercion not implemented");
        }