/// <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 canCreateExplicitStructCtor = true)
        {
            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 (dm!=null && dm.SpecialType == DMethod.MethodType.Constructor)
                    {
                        yield return dm;
                        foundExplicitCtor = true;
                    }
                }

            var isStruct = ct is StructType;
            if (!foundExplicitCtor || isStruct)
            {
                // Check if there is an opCall that has no parameters.
                // Only if no exists, it's allowed to make a default parameter.
                bool canMakeDefaultCtor = true;
                foreach(var opCall in GetOpCalls(ct, true))
                    if(opCall.Parameters == null || opCall.Parameters.Count == 0)
                    {
                        canMakeDefaultCtor = false;
                        break;
                    }

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

                // If struct, there's also a ctor that has all struct members as parameters.
                // Only, if there are no explicit ctors nor opCalls
                if (isStruct && !foundExplicitCtor && canCreateExplicitStructCtor)
                {
                    var l = new List<INode>();

                    foreach (var member in ct.Definition)
                    {
                        var dv = member as DVariable;
                        if (dv!=null &&
                            !dv.IsStatic &&
                            !dv.IsAlias &&
                            !dv.IsConst) //TODO dunno if public-ness of items is required..
                            l.Add(dv);
                    }

                    yield return new DMethod(DMethod.MethodType.Constructor) {
                        Name = DMethod.ConstructorIdentifier,
                        Parent = ct.Definition,
                        Description = "Default constructor for struct "+ct.Name,
                        Parameters = l
                    };
                }
            }
        }
Example #2
0
        public static TooltipInformation Generate(TemplateIntermediateType tit, int currentParam = -1)
        {
            var sb = new StringBuilder("(");

            if (tit is ClassType)
            {
                sb.Append("Class");
            }
            else if (tit is InterfaceType)
            {
                sb.Append("Interface");
            }
            else if (tit is TemplateType)
            {
                sb.Append("Template");
            }
            else if (tit is StructType)
            {
                sb.Append("Struct");
            }
            else if (tit is UnionType)
            {
                sb.Append("Union");
            }

            sb.Append(") ").Append(tit.Name);
            var dc = tit.Definition;

            if (dc.TemplateParameters != null && dc.TemplateParameters.Length != 0)
            {
                sb.Append('(');
                for (int i = 0; i < dc.TemplateParameters.Length; i++)
                {
                    if (i == currentParam)
                    {
                        sb.Append("<i>");
                    }

                    sb.Append(dc.TemplateParameters[i].ToString());

                    if (i == currentParam)
                    {
                        sb.Append("</i>");
                    }
                    sb.Append(',');
                }
                sb.Remove(sb.Length - 1, 1).Append(')');
            }

            var tti = new TooltipInformation {
                SignatureMarkup = sb.ToString(),
                SummaryMarkup   = dc.Description,
                FooterMarkup    = dc.ToString(false)
            };

            return(tti);
        }
 public static IEnumerable<DMethod> GetOpCalls(TemplateIntermediateType t, bool staticOnly)
 {
     var opCall = t.Definition["opCall"];
     if(opCall!=null)
         foreach(var call in opCall)
         {
             var dm = call as DMethod;
             if(dm != null && (!staticOnly || dm.IsStatic))
                 yield return dm;
         }
 }
        void VisitTemplateIntermediateType(TemplateIntermediateType tr)
        {
            // Cases:

            // myVar. (located in basetype definition)		<-- Show everything
            // this.                                        <-- Show everything
            // myVar. (not located in basetype definition)  <-- Show public and public static members
            // super.                                       <-- Show all base type members
            // myClass. (not located in myClass)			<-- Show all static members
            // myClass. (located in myClass)				<-- Show all static members

            MemberCompletionEnumeration.EnumChildren(CompletionDataGenerator, ctxt, tr, MemberFilter);

            GenUfcsAndStaticProperties(tr);
        }
            public StructVis(TemplateIntermediateType structType, List <int> tkn, ICompletionDataGenerator gen, ResolutionContext ctxt)
                : base(ctxt)
            {
                this.alreadyTakenNames = tkn;
                this.gen = gen;

                if (CompletionOptions.Instance.ShowStructMembersInStructInitOnly)
                {
                    this.DeepScanClass(structType, MemberFilter.Variables, false);
                }
                else
                {
                    IterateThroughScopeLayers(CodeLocation.Empty, MemberFilter.All);
                }
            }
        public static IEnumerable <DMethod> GetOpCalls(TemplateIntermediateType t, bool staticOnly)
        {
            var opCall = t.Definition["opCall"];

            if (opCall != null)
            {
                foreach (var call in opCall)
                {
                    var dm = call as DMethod;
                    if (dm != null && (!staticOnly || dm.IsStatic))
                    {
                        yield return(dm);
                    }
                }
            }
        }
Example #7
0
        public static string GeneratePrototype(TemplateIntermediateType tit, int currentParam = -1)
        {
            var sb = new StringBuilder("");

            if (tit is ClassType)
            {
                sb.Append("Class");
            }
            else if (tit is InterfaceType)
            {
                sb.Append("Interface");
            }
            else if (tit is TemplateType)
            {
                sb.Append("Template");
            }
            else if (tit is StructType)
            {
                sb.Append("Struct");
            }
            else if (tit is UnionType)
            {
                sb.Append("Union");
            }

            var dc = tit.Definition;

            sb.Append(" in ");
            sb.Append(AbstractNode.GetNodePath(dc, false));
            sb.Append(": ").Append(tit.Name);
            if (dc.TemplateParameters != null && dc.TemplateParameters.Length != 0)
            {
                sb.Append('(');
                for (int i = 0; i < dc.TemplateParameters.Length; i++)
                {
                    sb.Append(dc.TemplateParameters[i].ToString());
                    sb.Append(',');
                }
                sb.Remove(sb.Length - 1, 1).Append(')');
            }

            return(sb.ToString());
        }
        /// <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 };
        }
        void VisitTemplateIntermediateType(TemplateIntermediateType tr)
        {
            if (tr.DeclarationOrExpressionBase is TokenExpression)
            {
                var token = ((TokenExpression)tr.DeclarationOrExpressionBase).Token;

                isVariableInstance = token == DTokens.This || token == DTokens.Super;
            }

            // Cases:

            // myVar. (located in basetype definition)		<-- Show everything
            // this.                                        <-- Show everything
            // myVar. (not located in basetype definition)  <-- Show public and public static members
            // super.                                       <-- Show all base type members
            // myClass. (not located in myClass)			<-- Show all static members
            // myClass. (located in myClass)				<-- Show all static members

            MemberCompletionEnumeration.EnumChildren(CompletionDataGenerator, ctxt, tr, isVariableInstance, MemberFilter);

            GenUfcsAndStaticProperties(tr);
        }
        public static IEnumerable <TemplateIntermediateType> SearchForClassDerivatives(TemplateIntermediateType t, ResolutionContext ctxt)
        {
            if (!(t is ClassType || t is InterfaceType))
            {
                throw new ArgumentException("t должно быть классом или интерфейсом, но не " + (t != null ? t.ToString() : "null"));
            }

            var f = new ClassInterfaceDerivativeFinder(ctxt);

            f.typeNodeToFind = t.Definition;
            var bt = t;

            while (bt != null)
            {
                f.alreadyResolvedClasses.Add(bt.Definition);
                bt = DResolver.StripMemberSymbols(bt.Base) as TemplateIntermediateType;
            }

            var filter = MemberFilter.Classes;

            if (t is InterfaceType)             // -> Only interfaces can inherit interfaces. Interfaces cannot be subclasses of classes.
            {
                filter |= MemberFilter.Interfaces;
            }

            f.IterateThroughScopeLayers(t.Definition.Location, filter);

            return(f.results);            // return them.
        }
        /// <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);
        }
    }
        /// <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 canCreateExplicitStructCtor = true)
        {
            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 (dm != null && dm.SpecialType == DMethod.MethodType.Constructor)
                    {
                        yield return(dm);

                        foundExplicitCtor = true;
                    }
                }
            }

            var isStruct = ct is StructType;

            if (!foundExplicitCtor || isStruct)
            {
                // Check if there is an opCall that has no parameters.
                // Only if no exists, it's allowed to make a default parameter.
                bool canMakeDefaultCtor = true;
                foreach (var opCall in GetOpCalls(ct, true))
                {
                    if (opCall.Parameters == null || opCall.Parameters.Count == 0)
                    {
                        canMakeDefaultCtor = false;
                        break;
                    }
                }

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

                // If struct, there's also a ctor that has all struct members as parameters.
                // Only, if there are no explicit ctors nor opCalls
                if (isStruct && !foundExplicitCtor && canCreateExplicitStructCtor)
                {
                    var l = new List <INode>();

                    foreach (var member in ct.Definition)
                    {
                        var dv = member as DVariable;
                        if (dv != null &&
                            !dv.IsStatic &&
                            !dv.IsAlias &&
                            !dv.IsConst)                             //TODO dunno if public-ness of items is required..
                        {
                            l.Add(dv);
                        }
                    }

                    yield return(new DMethod(DMethod.MethodType.Constructor)
                    {
                        Name = DMethod.ConstructorIdentifier,
                        Parent = ct.Definition,
                        Description = "Default constructor for struct " + ct.Name,
                        Parameters = l
                    });
                }
            }
        }
        bool HandleDecl(TemplateTypeParameter parameter, TemplateInstanceExpression tix, AbstractType r)
        {
            /*
             * TODO: Scan down r for having at least one templateinstanceexpression as declaration base.
             * If a tix was found, check if the definition of the respective result base level
             * and the un-aliased identifier of the 'tix' parameter match.
             * Attention: if the alias represents an undeduced type (i.e. a type bundle of equally named type nodes),
             * it is only important that the definition is inside this bundle.
             * Therefore, it's needed to manually resolve the identifier, and look out for aliases or such unprecise aliases..confusing as s**t!
             *
             * If the param tix id is part of the template param list, the behaviour is currently undefined! - so instantly return false, I'll leave it as TODO/FIXME
             */
            var paramTix_TemplateMatchPossibilities       = ResolveTemplateInstanceId(tix);
            TemplateIntermediateType tixBasedArgumentType = null;
            var r_ = r as DSymbol;

            while (r_ != null)
            {
                if (r_.DeclarationOrExpressionBase is TemplateInstanceExpression)
                {
                    var tit = r_ as TemplateIntermediateType;
                    if (tit != null && CheckForTixIdentifierEquality(paramTix_TemplateMatchPossibilities, tit.Definition))
                    {
                        tixBasedArgumentType = tit;
                        break;
                    }
                }

                r_ = r_.Base as DSymbol;
            }

            /*
             * This part is very tricky:
             * I still dunno what is allowed over here--
             *
             * class Foo(T:Bar!E[],E) {}
             * ...
             * Foo!(Bar!string[]) f; -- E will be 'string' then
             *
             * class DerivateBar : Bar!string[] {} -- new Foo!DerivateBar() is also allowed, but now DerivateBar
             *		obviously is not a template instance expression - it's a normal identifier only.
             */
            if (tixBasedArgumentType != null)
            {
                var argEnum_given = ((TemplateInstanceExpression)tixBasedArgumentType.DeclarationOrExpressionBase).Arguments.GetEnumerator();

                foreach (var p in tix.Arguments)
                {
                    if (!argEnum_given.MoveNext() || argEnum_given.Current == null)
                    {
                        return(false);
                    }

                    // Convert p to type declaration
                    var param_Expected = ConvertToTypeDeclarationRoughly(p);

                    if (param_Expected == null)
                    {
                        return(false);
                    }

                    var result_Given = ExpressionTypeEvaluation.EvaluateType(argEnum_given.Current as IExpression, ctxt);

                    if (result_Given == null || !HandleDecl(parameter, param_Expected, result_Given))
                    {
                        return(false);
                    }
                }

                // Too many params passed..
                if (argEnum_given.MoveNext())
                {
                    return(false);
                }

                return(true);
            }

            return(false);
        }
Example #14
0
        static void IterateThroughBaseClassesInterfaces(List <TemplateIntermediateType> l, TemplateIntermediateType tit)
        {
            if (tit == null)
            {
                return;
            }

            var @base = tit.Base as TemplateIntermediateType;

            if (@base != null)
            {
                if (!l.Contains(@base))
                {
                    l.Add(@base);
                }
                IterateThroughBaseClassesInterfaces(l, @base);
            }

            if (tit.BaseInterfaces != null)
            {
                foreach (var I in tit.BaseInterfaces)
                {
                    if (!l.Contains(I))
                    {
                        l.Add(I);
                    }
                    IterateThroughBaseClassesInterfaces(l, I);
                }
            }
        }
Example #15
0
        /// <summary>
        /// Takes the class passed via the tr, and resolves its base class and/or implemented interfaces.
        /// Also usable for enums.
        ///
        /// Never returns null. Instead, the original 'tr' object will be returned if no base class was resolved.
        /// Will clone 'tr', whereas the new object will contain the base class.
        /// </summary>
        public static UserDefinedType ResolveBaseClasses(UserDefinedType tr, ResolverContextStack ctxt, bool ResolveFirstBaseIdOnly = false)
        {
            if (bcStack > 8)
            {
                bcStack--;
                return(tr);
            }

            if (tr is EnumType)
            {
                var et = tr as EnumType;

                AbstractType bt = null;

                if (et.Definition.Type == null)
                {
                    bt = new PrimitiveType(DTokens.Int);
                }
                else
                {
                    if (tr.Definition.Parent is IBlockNode)
                    {
                        ctxt.PushNewScope((IBlockNode)tr.Definition.Parent);
                    }

                    var bts = TypeDeclarationResolver.Resolve(et.Definition.Type, ctxt);

                    if (tr.Definition.Parent is IBlockNode)
                    {
                        ctxt.Pop();
                    }

                    ctxt.CheckForSingleResult(bts, et.Definition.Type);

                    if (bts != null && bts.Length != 0)
                    {
                        bt = bts[0];
                    }
                }

                return(new EnumType(et.Definition, bt, et.DeclarationOrExpressionBase));
            }

            var dc = tr.Definition as DClassLike;

            // Return immediately if searching base classes of the Object class
            if (dc == null || ((dc.BaseClasses == null || dc.BaseClasses.Count < 1) && dc.Name == "Object"))
            {
                return(tr);
            }

            // If no base class(es) specified, and if it's no interface that is handled, return the global Object reference
            // -- and do not throw any error message, it's ok
            if (dc.BaseClasses == null || dc.BaseClasses.Count < 1)
            {
                if (tr is ClassType)                // Only Classes can inherit from non-interfaces
                {
                    return(new ClassType(dc, tr.DeclarationOrExpressionBase, ctxt.ParseCache.ObjectClassResult));
                }
                return(tr);
            }

            #region Base class & interface resolution
            TemplateIntermediateType baseClass = null;
            var interfaces = new List <InterfaceType>();

            if (!(tr is ClassType || tr is InterfaceType))
            {
                if (dc.BaseClasses.Count != 0)
                {
                    ctxt.LogError(dc, "Only classes and interfaces may inherit from other classes/interfaces");
                }
                return(tr);
            }

            for (int i = 0; i < (ResolveFirstBaseIdOnly ? 1 : dc.BaseClasses.Count); i++)
            {
                var type = dc.BaseClasses[i];

                // If there's an explicit 'Object' inheritance, also return the pre-resolved object class
                if (type is IdentifierDeclaration && ((IdentifierDeclaration)type).Id == "Object")
                {
                    if (baseClass != null)
                    {
                        ctxt.LogError(new ResolutionError(dc, "Class must not have two base classes"));
                        continue;
                    }
                    else if (i != 0)
                    {
                        ctxt.LogError(new ResolutionError(dc, "The base class name must preceed base interfaces"));
                        continue;
                    }

                    baseClass = ctxt.ParseCache.ObjectClassResult;
                    continue;
                }

                if (type == null || type.ToString(false) == dc.Name || dc.NodeRoot == dc)
                {
                    ctxt.LogError(new ResolutionError(dc, "A class cannot inherit from itself"));
                    continue;
                }

                ctxt.PushNewScope(dc.Parent as IBlockNode);

                bcStack++;

                var res = TypeDeclarationResolver.Resolve(type, ctxt);

                ctxt.CheckForSingleResult(res, type);

                if (res != null && res.Length != 0)
                {
                    var r = res[0];
                    if (r is ClassType || r is TemplateType)
                    {
                        if (tr is InterfaceType)
                        {
                            ctxt.LogError(new ResolutionError(type, "An interface cannot inherit from non-interfaces"));
                        }
                        else if (i == 0)
                        {
                            baseClass = (TemplateIntermediateType)r;
                        }
                        else
                        {
                            ctxt.LogError(new ResolutionError(dc, "The base " + (r is ClassType ?  "class" : "template") + " name must preceed base interfaces"));
                        }
                    }
                    else if (r is InterfaceType)
                    {
                        interfaces.Add((InterfaceType)r);
                    }
                    else
                    {
                        ctxt.LogError(new ResolutionError(type, "Resolved class is neither a class nor an interface"));
                        continue;
                    }
                }

                bcStack--;

                ctxt.Pop();
            }
            #endregion

            if (baseClass == null && interfaces.Count == 0)
            {
                return(tr);
            }

            if (tr is ClassType)
            {
                return(new ClassType(dc, tr.DeclarationOrExpressionBase, baseClass, interfaces.Count == 0 ? null : interfaces.ToArray(), tr.DeducedTypes));
            }
            else if (tr is InterfaceType)
            {
                return(new InterfaceType(dc, tr.DeclarationOrExpressionBase, interfaces.Count == 0 ? null : interfaces.ToArray(), tr.DeducedTypes));
            }

            // Method should end here
            return(tr);
        }
Example #16
0
        /// <summary>
        /// Takes the class passed via the tr, and resolves its base class and/or implemented interfaces.
        /// Also usable for enums.
        ///
        /// Never returns null. Instead, the original 'tr' object will be returned if no base class was resolved.
        /// Will clone 'tr', whereas the new object will contain the base class.
        /// </summary>
        public static TemplateIntermediateType ResolveClassOrInterface(DClassLike dc, ResolutionContext ctxt, ISyntaxRegion instanceDeclaration, bool ResolveFirstBaseIdOnly = false, IEnumerable <TemplateParameterSymbol> extraDeducedTemplateParams = null)
        {
            if (parsedClassInstanceDecls == null)
            {
                parsedClassInstanceDecls = new List <ISyntaxRegion> ();
            }

            switch (dc.ClassType)
            {
            case DTokens.Class:
            case DTokens.Interface:
                break;

            default:
                if (dc.BaseClasses.Count != 0)
                {
                    ctxt.LogError(dc, "Only classes and interfaces may inherit from other classes/interfaces");
                }
                return(null);
            }

            bool isClass = dc.ClassType == DTokens.Class;

            if (bcStack > 6 || (instanceDeclaration != null && parsedClassInstanceDecls.Contains(instanceDeclaration)))
            {
                return(isClass ? new ClassType(dc, instanceDeclaration, null) as TemplateIntermediateType : new InterfaceType(dc, instanceDeclaration));
            }

            if (instanceDeclaration != null)
            {
                parsedClassInstanceDecls.Add(instanceDeclaration);
            }
            bcStack++;

            var deducedTypes = new DeducedTypeDictionary(dc);
            var tix          = instanceDeclaration as TemplateInstanceExpression;

            if (tix != null && (ctxt.Options & ResolutionOptions.NoTemplateParameterDeduction) == 0)
            {
                bool hasUndeterminedArgs;
                var  givenTemplateArguments = TemplateInstanceHandler.PreResolveTemplateArgs(tix, ctxt, out hasUndeterminedArgs);

                if (!TemplateInstanceHandler.DeduceParams(givenTemplateArguments, false, ctxt, null, dc, deducedTypes))
                {
                    parsedClassInstanceDecls.Remove(instanceDeclaration);
                    bcStack--;
                    return(null);
                }
            }

            if (extraDeducedTemplateParams != null)
            {
                foreach (var tps in extraDeducedTemplateParams)
                {
                    deducedTypes[tps.Parameter] = tps;
                }
            }


            if (dc.BaseClasses == null || dc.BaseClasses.Count < 1)
            {
                parsedClassInstanceDecls.Remove(instanceDeclaration);
                bcStack--;

                // The Object class has no further base class;
                // Normal class instances have the object as base class;
                // Interfaces must not have any default base class/interface
                return(isClass ? new ClassType(dc, instanceDeclaration, dc.NameHash != ObjectNameHash ? ctxt.ParseCache.ObjectClassResult : null, null, deducedTypes.Count != 0 ? deducedTypes.ToReadonly() : null) :
                       new InterfaceType(dc, instanceDeclaration, null, deducedTypes.Count != 0 ? deducedTypes.ToReadonly() : null) as TemplateIntermediateType);
            }


            #region Base class & interface resolution
            AbstractType[] res;
            var            pop = ctxt.ScopedBlock != dc.Parent;
            if (pop)
            {
                ctxt.PushNewScope(dc.Parent as IBlockNode);
            }

            foreach (var kv in deducedTypes)
            {
                ctxt.CurrentContext.DeducedTemplateParameters[kv.Key] = kv.Value;
            }

            TemplateIntermediateType baseClass = null;
            var interfaces = new List <InterfaceType>();
            try
            {
                for (int i = 0; i < (ResolveFirstBaseIdOnly ? 1 : dc.BaseClasses.Count); i++)
                {
                    var type = dc.BaseClasses[i];

                    // If there's an explicit 'Object' inheritance, also return the pre-resolved object class
                    if (type is IdentifierDeclaration &&
                        (type as IdentifierDeclaration).IdHash == ObjectNameHash)
                    {
                        if (baseClass != null)
                        {
                            ctxt.LogError(new ResolutionError(dc, "Class must not have two base classes"));
                            continue;
                        }
                        else if (i != 0)
                        {
                            ctxt.LogError(new ResolutionError(dc, "The base class name must preceed base interfaces"));
                            continue;
                        }

                        baseClass = ctxt.ParseCache.ObjectClassResult;
                        continue;
                    }

                    if (type == null || (type is IdentifierDeclaration && (type as IdentifierDeclaration).IdHash == dc.NameHash) || dc.NodeRoot == dc)
                    {
                        ctxt.LogError(new ResolutionError(dc, "A class cannot inherit from itself"));
                        continue;
                    }

                    res = DResolver.StripAliasSymbols(TypeDeclarationResolver.Resolve(type, ctxt));

                    ctxt.CheckForSingleResult(res, type);

                    if (res != null && res.Length != 0)
                    {
                        var r = res[0];
                        if (r is ClassType || r is TemplateType)
                        {
                            if (!isClass)
                            {
                                ctxt.LogError(new ResolutionError(type, "An interface cannot inherit from non-interfaces"));
                            }
                            else if (i == 0)
                            {
                                baseClass = r as TemplateIntermediateType;
                            }
                            else
                            {
                                ctxt.LogError(new ResolutionError(dc, "The base " + (r is ClassType ?  "class" : "template") + " name must preceed base interfaces"));
                            }
                        }
                        else if (r is InterfaceType)
                        {
                            interfaces.Add(r as InterfaceType);

                            if (isClass && dc.NameHash != ObjectNameHash && baseClass == null)
                            {
                                baseClass = ctxt.ParseCache.ObjectClassResult;
                            }
                        }
                        else
                        {
                            ctxt.LogError(new ResolutionError(type, "Resolved class is neither a class nor an interface"));
                            continue;
                        }
                    }
                }
            }
            finally
            {
                bcStack--;
                parsedClassInstanceDecls.Remove(instanceDeclaration);
            }

            if (pop)
            {
                ctxt.Pop();
            }
            else
            {
                foreach (var kv in deducedTypes)                 // May be backup old tps?
                {
                    ctxt.CurrentContext.DeducedTemplateParameters.Remove(kv.Key);
                }
            }

            #endregion

            if (isClass)
            {
                return(new ClassType(dc, instanceDeclaration, baseClass, interfaces.Count == 0 ? null : interfaces.ToArray(), deducedTypes.Count != 0 ? deducedTypes.ToReadonly() : null));
            }

            return(new InterfaceType(dc, instanceDeclaration, interfaces.Count == 0 ? null : interfaces.ToArray(), deducedTypes.Count != 0 ? deducedTypes.ToReadonly() : null));
        }
Example #17
0
		bool HandleAliasThisDeclarations(TemplateIntermediateType tit, MemberFilter vis)
		{
			bool pop;
			var ch = tit.Definition [DVariable.AliasThisIdentifierHash];
			if(ch != null){
				foreach (DVariable aliasDef in ch) {
					if (MatchesCompilationConditions(aliasDef) || 
						aliasDef.Type == null)
						continue;

					pop = ctxt.ScopedBlock != tit.Definition;
					if (pop)
						ctxt.PushNewScope (tit.Definition);

					// Resolve the aliased symbol and expect it to be a member symbol(?).
					//TODO: Check if other cases are allowed as well!
					var aliasedSymbol = DResolver.StripAliasSymbol(TypeDeclarationResolver.ResolveSingle (aliasDef.Type, ctxt));
					var aliasedMember = aliasedSymbol as MemberSymbol;

					if (pop)
						ctxt.Pop ();

					if (aliasedMember == null) {
						if (aliasedSymbol != null)
							ctxt.LogError (aliasDef, "Aliased type from 'alias this' definition is expected to be a type instance, not "+aliasedSymbol.ToString()+"!");

						continue;
					}

					/*
					 * The aliased member's type can be everything!
					 */
					aliasedSymbol = aliasedMember.Base;

					foreach (var statProp in StaticProperties.ListProperties (aliasedSymbol))
						if (HandleItem (statProp))
							return true;

					/** TODO: Visit ufcs recommendations and other things that
					 * become added in e.g. MemberCompletionProvider
					 */

					var tit_ = aliasedSymbol as TemplateIntermediateType;
					if(tit_ != null)
					{
						pop = !ctxt.ScopedBlockIsInNodeHierarchy(tit_.Definition);
						if(pop)
							ctxt.PushNewScope(tit_.Definition);
						ctxt.CurrentContext.IntroduceTemplateParameterTypes(tit_);
						var r = DeepScanClass(tit_, vis, true);
						if(pop)
							ctxt.Pop();
						else
							ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals(tit_);
						if(r)
							return true;
					}

				}
			}

			return false;
		}
Example #18
0
        bool HandleAliasThisDeclarations(TemplateIntermediateType tit, MemberFilter vis)
        {
            bool pop;
            var  ch = tit.Definition [DVariable.AliasThisIdentifierHash];

            if (ch != null)
            {
                foreach (DVariable aliasDef in ch)
                {
                    if (MatchesCompilationConditions(aliasDef) ||
                        aliasDef.Type == null)
                    {
                        continue;
                    }

                    pop = ctxt.ScopedBlock != tit.Definition;
                    if (pop)
                    {
                        ctxt.PushNewScope(tit.Definition);
                    }

                    // Resolve the aliased symbol and expect it to be a member symbol(?).
                    //TODO: Check if other cases are allowed as well!
                    var aliasedSymbol = DResolver.StripAliasSymbol(TypeDeclarationResolver.ResolveSingle(aliasDef.Type, ctxt));
                    var aliasedMember = aliasedSymbol as MemberSymbol;

                    if (pop)
                    {
                        ctxt.Pop();
                    }

                    if (aliasedMember == null)
                    {
                        if (aliasedSymbol != null)
                        {
                            ctxt.LogError(aliasDef, "Aliased type from 'alias this' definition is expected to be a type instance, not " + aliasedSymbol.ToString() + "!");
                        }

                        continue;
                    }

                    /*
                     * The aliased member's type can be everything!
                     */
                    aliasedSymbol = aliasedMember.Base;

                    foreach (var statProp in StaticProperties.ListProperties(aliasedSymbol))
                    {
                        if (HandleItem(statProp))
                        {
                            return(true);
                        }
                    }

                    /** TODO: Visit ufcs recommendations and other things that
                     * become added in e.g. MemberCompletionProvider
                     */

                    var tit_ = aliasedSymbol as TemplateIntermediateType;
                    if (tit_ != null)
                    {
                        pop = !ctxt.ScopedBlockIsInNodeHierarchy(tit_.Definition);
                        if (pop)
                        {
                            ctxt.PushNewScope(tit_.Definition);
                        }
                        ctxt.CurrentContext.IntroduceTemplateParameterTypes(tit_);
                        var r = DeepScanClass(tit_, vis, true);
                        if (pop)
                        {
                            ctxt.Pop();
                        }
                        else
                        {
                            ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals(tit_);
                        }
                        if (r)
                        {
                            return(true);
                        }
                    }
                }
            }

            return(false);
        }