/// <summary>
        /// Returns all constructors from the given class or struct.
        /// If no explicit constructor given, an artificial implicit constructor method stub will be created.
        /// </summary>
        public static IEnumerable <DMethod> GetConstructors(TemplateIntermediateType ct)
        {
            bool foundExplicitCtor = false;

            // Simply get all constructors that have the ctor id assigned. Makin' it faster ;)
            var ch = ct.Definition[DMethod.ConstructorIdentifier];

            if (ch != null)
            {
                foreach (var m in ch)
                {
                    // Not to forget: 'this' aliases are also possible - so keep checking for m being a genuine ctor
                    var dm = m as DMethod;
                    if (m != null && dm.SpecialType == DMethod.MethodType.Constructor)
                    {
                        yield return(dm);

                        foundExplicitCtor = true;
                    }
                }
            }

            if (!foundExplicitCtor)
            {
                yield return new DMethod(DMethod.MethodType.Constructor)
                       {
                           Name = DMethod.ConstructorIdentifier, Parent = ct.Definition, Description = "Default constructor for " + ct.Name
                       }
            }
            ;
        }

        ISemantic E(CastExpression ce)
        {
            AbstractType castedType = null;

            if (ce.Type != null)
            {
                var castedTypes = TypeDeclarationResolver.Resolve(ce.Type, ctxt);

                ctxt.CheckForSingleResult(castedTypes, ce.Type);

                if (castedTypes != null && castedTypes.Length != 0)
                {
                    castedType = castedTypes[0];
                }
            }
            else
            {
                castedType = AbstractType.Get(E(ce.UnaryExpression));

                if (castedType != null && ce.CastParamTokens != null && ce.CastParamTokens.Length > 0)
                {
                    //TODO: Wrap resolved type with member function attributes
                }
            }

            return(castedType);
        }

        ISemantic E(UnaryExpression_Cat x)         // a = ~b;
        {
            return(E(x.UnaryExpression));
        }

        ISemantic E(UnaryExpression_Increment x)
        {
            return(E(x.UnaryExpression));
        }

        ISemantic E(UnaryExpression_Decrement x)
        {
            return(E(x.UnaryExpression));
        }

        ISemantic E(UnaryExpression_Add x)
        {
            return(E(x.UnaryExpression));
        }

        ISemantic E(UnaryExpression_Sub x)
        {
            var v = E(x.UnaryExpression);

            if (eval)
            {
                if (v is AbstractType)
                {
                    v = DResolver.StripMemberSymbols((AbstractType)v);
                }

                if (v is PrimitiveValue)
                {
                    var pv = (PrimitiveValue)v;

                    return(new PrimitiveValue(pv.BaseTypeToken, -pv.Value, x, -pv.ImaginaryPart));
                }
            }

            return(v);
        }

        ISemantic E(UnaryExpression_Not x)
        {
            return(E(x.UnaryExpression));
        }

        ISemantic E(UnaryExpression_Mul x)
        {
            return(E(x.UnaryExpression));
        }

        ISemantic E(UnaryExpression_And x)
        {
            var ptrBase = E(x.UnaryExpression);

            if (eval)
            {
                // Create a new pointer
                //
            }

            // &i -- makes an int* out of an int
            return(new PointerType(AbstractType.Get(ptrBase), x));
        }

        ISemantic E(DeleteExpression x)
        {
            if (eval)
            {
                // Reset the content of the variable
            }

            return(null);
        }

        ISemantic E(UnaryExpression_Type x)
        {
            var uat = x as UnaryExpression_Type;

            if (uat.Type == null)
            {
                return(null);
            }

            var types = TypeDeclarationResolver.Resolve(uat.Type, ctxt);

            ctxt.CheckForSingleResult(types, uat.Type);

            if (types != null && types.Length != 0)
            {
                var id = new IdentifierDeclaration(uat.AccessIdentifier)
                {
                    EndLocation = uat.EndLocation
                };

                // First off, try to resolve static properties
                var statProp = StaticPropertyResolver.TryResolveStaticProperties(types[0], uat.AccessIdentifier, ctxt, eval, id);

                if (statProp != null)
                {
                    return(statProp);
                }

                // If it's not the case, try the conservative way
                var res = TypeDeclarationResolver.Resolve(id, ctxt, types);

                ctxt.CheckForSingleResult(res, x);

                if (res != null && res.Length != 0)
                {
                    return(res[0]);
                }
            }

            return(null);
        }
    }
Esempio n. 2
0
        /// <summary>
        /// Returns either all unfiltered and undeduced overloads of a member of a base type/value (like b from type a if the expression is a.b).
        /// if <param name="EvalAndFilterOverloads"></param> is false.
        /// If true, all overloads will be deduced, filtered and evaluated, so that (in most cases,) a one-item large array gets returned
        /// which stores the return value of the property function b that is executed without arguments.
        /// Also handles UFCS - so if filtering is wanted, the function becom
        /// </summary>
        ISemantic[] E(PostfixExpression_Access acc, out bool IsUFCS,
                      ISemantic resultBase = null, bool EvalAndFilterOverloads = true)
        {
            IsUFCS = false;

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

            var baseExpression = resultBase ?? E(acc.PostfixForeExpression);

            if (acc.AccessExpression is NewExpression)
            {
                /*
                 * This can be both a normal new-Expression as well as an anonymous class declaration!
                 */
                //TODO!
                return(null);
            }

            /*
             * Try to get ufcs functions at first!
             *
             * void foo(int i) {}
             *
             * class A
             * {
             *	void foo(int i, int a) {}
             *
             *	void bar(){
             *		123.foo(23); // Not allowed!
             *		// Anyway, if we tried to search ufcs functions AFTER searching from child to parent scope levels,
             *		// it would return the local foo() only, not the global one..which would be an error then!
             *  }
             *
             * Probably also worth to notice is the property syntax..are property functions rather preferred than ufcs ones?
             * }
             */
            var overloads = UFCSResolver.TryResolveUFCS(baseExpression, acc, ctxt) as AbstractType[];

            if (overloads == null)
            {
                if (acc.AccessExpression is TemplateInstanceExpression)
                {
                    var tix = (TemplateInstanceExpression)acc.AccessExpression;
                    // Do not deduce and filter if superior expression is a method call since call arguments' types also count as template arguments!
                    overloads = GetOverloads(tix, resultBase == null ? null : new[] { AbstractType.Get(resultBase) }, EvalAndFilterOverloads);
                }

                else if (acc.AccessExpression is IdentifierExpression)
                {
                    var id = ((IdentifierExpression)acc.AccessExpression).Value as string;

                    overloads = TypeDeclarationResolver.ResolveFurtherTypeIdentifier(id, new[] { AbstractType.Get(baseExpression) }, ctxt, acc.AccessExpression);

                    // Might be a static property
                    if (overloads == null)
                    {
                        var staticTypeProperty = StaticPropertyResolver.TryResolveStaticProperties(AbstractType.Get(baseExpression), id, ctxt);

                        if (staticTypeProperty != null)
                        {
                            return new[] { staticTypeProperty }
                        }
                        ;
                    }
                }
                else
                {
                    if (eval)
                    {
                        throw new EvaluationException(acc, "Invalid access expression");
                    }
                    ctxt.LogError(acc, "Invalid post-dot expression");
                    return(null);
                }
            }
            else
            {
                IsUFCS = true;
            }

            // If evaluation active and the access expression is stand-alone, return a single item only.
            if (EvalAndFilterOverloads && eval)
            {
                return new[] { TryDoCTFEOrGetValueRefs(overloads, acc.AccessExpression) }
            }
            ;

            return(overloads);
        }

        ISemantic E(PostfixExpression_Index x, ISemantic foreExpression)
        {
            if (eval)
            {
                //TODO: Access pointer arrays(?)

                if (foreExpression is ArrayValue)                 // ArrayValue must be checked first due to inheritance!
                {
                    var av = foreExpression as ArrayValue;

                    // Make $ operand available
                    var arrLen_Backup = ValueProvider.CurrentArrayLength;
                    ValueProvider.CurrentArrayLength = av.Elements.Length;

                    var n = E(x.Arguments[0]) as PrimitiveValue;

                    ValueProvider.CurrentArrayLength = arrLen_Backup;

                    if (n == null)
                    {
                        throw new EvaluationException(x.Arguments[0], "Returned no value");
                    }

                    int i = 0;
                    try
                    {
                        i = Convert.ToInt32(n.Value);
                    }
                    catch { throw new EvaluationException(x.Arguments[0], "Index expression must be of type int"); }

                    if (i < 0 || i > av.Elements.Length)
                    {
                        throw new EvaluationException(x.Arguments[0], "Index out of range - it must be between 0 and " + av.Elements.Length);
                    }

                    return(av.Elements[i]);
                }
                else if (foreExpression is AssociativeArrayValue)
                {
                    var aa = (AssociativeArrayValue)foreExpression;

                    var key = E(x.Arguments[0]);

                    if (key == null)
                    {
                        throw new EvaluationException(x.Arguments[0], "Returned no value");
                    }

                    ISymbolValue val = null;

                    foreach (var kv in aa.Elements)
                    {
                        if (kv.Key.Equals(key))
                        {
                            return(kv.Value);
                        }
                    }

                    throw new EvaluationException(x, "Could not find key '" + val + "'");
                }

                throw new EvaluationException(x.PostfixForeExpression, "Invalid index expression base value type", foreExpression);
            }
            else
            {
                if (foreExpression is AssocArrayType)
                {
                    var ar = (AssocArrayType)foreExpression;

                    /*
                     * myType_Array[0] -- returns TypeResult myType
                     * return the value type of a given array result
                     */
                    //TODO: Handle opIndex overloads

                    return(ar.ValueType);
                }

                /*
                 * int* a = new int[10];
                 *
                 * a[0] = 12;
                 */
                else if (foreExpression is PointerType)
                {
                    return(((PointerType)foreExpression).Base);
                }

                ctxt.LogError(new ResolutionError(x, "Invalid base type for index expression"));
            }

            return(null);
        }

        ISemantic E(PostfixExpression_Slice x, ISemantic foreExpression)
        {
            if (!eval)
            {
                return(foreExpression);                // Still of the array's type.
            }
            if (!(foreExpression is ArrayValue))
            {
                throw new EvaluationException(x.PostfixForeExpression, "Must be an array");
            }

            var ar = (ArrayValue)foreExpression;
            var sl = (PostfixExpression_Slice)x;

            // If the [ ] form is used, the slice is of the entire array.
            if (sl.FromExpression == null && sl.ToExpression == null)
            {
                return(foreExpression);
            }

            // Make $ operand available
            var arrLen_Backup = ValueProvider.CurrentArrayLength;

            ValueProvider.CurrentArrayLength = ar.Elements.Length;

            var bound_lower = E(sl.FromExpression) as PrimitiveValue;
            var bound_upper = E(sl.ToExpression) as PrimitiveValue;

            ValueProvider.CurrentArrayLength = arrLen_Backup;

            if (bound_lower == null || bound_upper == null)
            {
                throw new EvaluationException(bound_lower == null ? sl.FromExpression : sl.ToExpression, "Must be of an integral type");
            }

            int lower = -1, upper = -1;

            try
            {
                lower = Convert.ToInt32(bound_lower.Value);
                upper = Convert.ToInt32(bound_upper.Value);
            }
            catch { throw new EvaluationException(lower != -1 ? sl.FromExpression : sl.ToExpression, "Boundary expression must base an integral type"); }

            if (lower < 0)
            {
                throw new EvaluationException(sl.FromExpression, "Lower boundary must be greater than 0");
            }
            if (lower >= ar.Elements.Length)
            {
                throw new EvaluationException(sl.FromExpression, "Lower boundary must be smaller than " + ar.Elements.Length);
            }
            if (upper < lower)
            {
                throw new EvaluationException(sl.ToExpression, "Upper boundary must be greater than " + lower);
            }
            if (upper >= ar.Elements.Length)
            {
                throw new EvaluationException(sl.ToExpression, "Upper boundary must be smaller than " + ar.Elements.Length);
            }


            var rawArraySlice = new ISymbolValue[upper - lower];
            int j             = 0;

            for (int i = lower; i < upper; i++)
            {
                rawArraySlice[j++] = ar.Elements[i];
            }

            return(new ArrayValue(ar.RepresentedType as ArrayType, rawArraySlice));
        }

        ISemantic E(PostfixExpression_Increment x, ISemantic foreExpression)
        {
            // myInt++ is still of type 'int'
            if (!eval)
            {
                return(foreExpression);
            }

            if (resolveConstOnly)
            {
                throw new NoConstException(x);
            }
            // Must be implemented anyway regarding ctfe
            return(null);
        }

        ISemantic E(PostfixExpression_Decrement x, ISemantic foreExpression)
        {
            if (!eval)
            {
                return(foreExpression);
            }

            if (resolveConstOnly)
            {
                throw new NoConstException(x);
            }
            // Must be implemented anyway regarding ctfe
            return(null);
        }
    }
}