public bool HandleDecl(TemplateTypeParameter p ,ITypeDeclaration td, ISemantic rr)
        {
            if (td is IdentifierDeclaration)
                return HandleDecl(p,(IdentifierDeclaration)td, rr);

            //HACK Ensure that no information gets lost by using this function
            // -- getting a value but requiring an abstract type and just extract it from the value - is this correct behaviour?
            var at = AbstractType.Get(rr);

            if (td is ArrayDecl)
                return HandleDecl(p,(ArrayDecl)td, DResolver.StripMemberSymbols(at) as AssocArrayType);
            else if (td is DTokenDeclaration)
                return HandleDecl((DTokenDeclaration)td, at);
            else if (td is DelegateDeclaration)
                return HandleDecl(p, (DelegateDeclaration)td, DResolver.StripMemberSymbols(at) as DelegateType);
            else if (td is PointerDecl)
                return HandleDecl(p, (PointerDecl)td, DResolver.StripMemberSymbols(at) as PointerType);
            else if (td is MemberFunctionAttributeDecl)
                return HandleDecl(p,(MemberFunctionAttributeDecl)td, at);
            else if (td is TypeOfDeclaration)
                return HandleDecl((TypeOfDeclaration)td, at);
            else if (td is VectorDeclaration)
                return HandleDecl((VectorDeclaration)td, at);
            else if (td is TemplateInstanceExpression)
                return HandleDecl(p,(TemplateInstanceExpression)td, at);

            return false;
        }
		bool HandleDecl(TemplateTypeParameter p, IdentifierDeclaration id, ISemantic r)
		{
			// Bottom-level reached
			if (id.InnerDeclaration == null && Contains(id.IdHash) && !id.ModuleScoped)
			{
				// Associate template param with r
				return Set((p != null && id.IdHash == p.NameHash) ? p : null, r, id.IdHash);
			}

			var deducee = DResolver.StripMemberSymbols(AbstractType.Get(r)) as DSymbol;
			if (id.InnerDeclaration != null && deducee != null && deducee.Definition.NameHash == id.IdHash)
			{
				var physicalParentType = TypeDeclarationResolver.HandleNodeMatch(deducee.Definition.Parent, ctxt, null, id.InnerDeclaration);
				if (HandleDecl(p, id.InnerDeclaration, physicalParentType))
				{
					if (Contains(id.IdHash))
						Set((p != null && id.IdHash == p.NameHash) ? p : null, deducee, id.IdHash);
					return true;
				}
			}

			/*
			 * If not stand-alone identifier or is not required as template param, resolve the id and compare it against r
			 */
			var _r = TypeDeclarationResolver.ResolveSingle(id, ctxt);

			return _r != null && (EnforceTypeEqualityWhenDeducing ?
				ResultComparer.IsEqual(r,_r) :
				ResultComparer.IsImplicitlyConvertible(r,_r));
		}
		public bool TryAssignDefaultType(TemplateTypeParameter p)
		{
			if (p == null || p.Default == null)
				return false;

			using (ctxt.Push(DResolver.SearchBlockAt(ctxt.ScopedBlock.NodeRoot as IBlockNode, p.Default.Location), p.Default.Location))
			{
				var defaultTypeRes = TypeDeclarationResolver.ResolveSingle(p.Default, ctxt);
				return defaultTypeRes != null && Set(p, defaultTypeRes, 0);
			}
		}
Пример #4
0
        public virtual void Visit(TemplateTypeParameter p)
        {
            if (p.Specialization != null)
            {
                p.Specialization.Accept(this);
            }

            if (p.Default != null)
            {
                p.Default.Accept(this);
            }
        }
        public bool TryAssignDefaultType(TemplateTypeParameter p)
        {
            if (p == null || p.Default == null)
                return false;

            IStatement stmt = null;
            ctxt.PushNewScope(DResolver.SearchBlockAt(ctxt.ScopedBlock.NodeRoot as IBlockNode, p.Default.Location, out stmt), stmt);

            var defaultTypeRes = TypeDeclarationResolver.Resolve(p.Default, ctxt);
            var b = defaultTypeRes != null && Set(p, defaultTypeRes.First(), 0);

            ctxt.Pop();

            return b;
        }
		bool Handle(TemplateTypeParameter p, ISemantic arg)
		{
			// if no argument given, try to handle default arguments
			if (arg == null)
				return TryAssignDefaultType(p);

			// If no spezialization given, assign argument immediately
			if (p.Specialization == null)
				return Set(p, arg, 0);

			bool handleResult= HandleDecl(null,p.Specialization,arg);

			if (!handleResult)
				return false;

			// Apply the entire argument to parameter p if there hasn't been no explicit association yet
			TemplateParameterSymbol tps;
			if (!TargetDictionary.TryGetValue(p, out tps) || tps == null)
				TargetDictionary[p] = new TemplateParameterSymbol(p, arg);

			return true;
		}
		public bool HandleDecl(TemplateTypeParameter p ,ITypeDeclaration td, ISemantic rr)
		{
			if (td is IdentifierDeclaration)
				return HandleDecl(p,(IdentifierDeclaration)td, rr);

			if (TemplateInstanceHandler.IsNonFinalArgument(rr))
			{
				foreach (var tp in this.TargetDictionary.Keys.ToList())
					if (TargetDictionary[tp] == null)
						TargetDictionary[tp] = new TemplateParameterSymbol(tp, null);

				return true;
			}

			//HACK Ensure that no information gets lost by using this function 
			// -- getting a value but requiring an abstract type and just extract it from the value - is this correct behaviour?
			var at = AbstractType.Get(rr);

			if (td is ArrayDecl)
				return HandleDecl(p,(ArrayDecl)td, DResolver.StripMemberSymbols(at) as AssocArrayType);
			else if (td is DTokenDeclaration)
				return HandleDecl((DTokenDeclaration)td, at);
			else if (td is DelegateDeclaration)
				return HandleDecl(p, (DelegateDeclaration)td, DResolver.StripMemberSymbols(at) as DelegateType);
			else if (td is PointerDecl)
				return HandleDecl(p, (PointerDecl)td, DResolver.StripMemberSymbols(at) as PointerType);
			else if (td is MemberFunctionAttributeDecl)
				return HandleDecl(p,(MemberFunctionAttributeDecl)td, at);
			else if (td is TypeOfDeclaration)
				return HandleDecl((TypeOfDeclaration)td, at);
			else if (td is VectorDeclaration)
				return HandleDecl((VectorDeclaration)td, at);
			else if (td is TemplateInstanceExpression)
				return HandleDecl(p,(TemplateInstanceExpression)td, at);

			return false;
		}
        bool Handle(TemplateTypeParameter p, ISemantic arg)
        {
            // if no argument given, try to handle default arguments
            if (arg == null)
            {
                if (p.Default == null)
                    return false;
                else
                {
                    IStatement stmt = null;
                    ctxt.PushNewScope(DResolver.SearchBlockAt(ctxt.ScopedBlock.NodeRoot as IBlockNode, p.Default.Location, out stmt));
                    ctxt.ScopedStatement = stmt;
                    var defaultTypeRes = TypeDeclarationResolver.Resolve(p.Default, ctxt);
                    bool b = false;
                    if (defaultTypeRes != null)
                        b = Set(p, defaultTypeRes.First());
                    ctxt.Pop();
                    return b;
                }
            }

            // If no spezialization given, assign argument immediately
            if (p.Specialization == null)
                return Set(p, arg);

            bool handleResult= HandleDecl(p,p.Specialization,arg);

            if (!handleResult)
                return false;

            // Apply the entire argument to parameter p if there hasn't been no explicit association yet
            if (!TargetDictionary.ContainsKey(p.Name) || TargetDictionary[p.Name] == null)
                TargetDictionary[p.Name] = new TemplateParameterSymbol(p, arg);

            return true;
        }
        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;
        }
Пример #10
0
		/// <summary>
		/// Tests if t1 is more specialized than t2
		/// </summary>
		bool IsMoreSpecialized(TemplateTypeParameter t1, TemplateTypeParameter t2, Dictionary<TemplateParameter, ISemantic> t1_DummyParamList)
		{
			// If one parameter is not specialized it should be clear
			if (t1.Specialization != null && t2.Specialization == null)
				return true;
			else if (t1.Specialization == null) // Return false if t2 is more specialized or if t1 as well as t2 are not specialized
				return false;

			return IsMoreSpecialized(t1.Specialization, t2, t1_DummyParamList);
		}
        public virtual void Visit(TemplateTypeParameter p)
        {
            VisitTemplateParameter (p);

            if (p.Specialization != null)
                p.Specialization.Accept(this);

            if (p.Default != null)
                p.Default.Accept(this);
        }
Пример #12
0
        TemplateParameter TemplateParameter(DNode parent)
        {
            CodeLocation startLoc;

            // TemplateThisParameter
            if (laKind == (This))
            {
                Step();

                startLoc = t.Location;
                var end = t.EndLocation;

                return new TemplateThisParameter(TemplateParameter(parent), parent) { Location=startLoc, EndLocation=end };
            }

            // TemplateTupleParameter
            else if (laKind == (Identifier) && Lexer.CurrentPeekToken.Kind == TripleDot)
            {
                Step();
                startLoc = t.Location;
                var id = t.Value;
                Step();

                return new TemplateTupleParameter(id, startLoc, parent) { Location=startLoc, EndLocation=t.EndLocation	};
            }

            // TemplateAliasParameter
            else if (laKind == (Alias))
            {
                Step();

                startLoc = t.Location;
                TemplateAliasParameter al;

                if(Expect(Identifier))
                    al = new TemplateAliasParameter(t.Value, t.Location, parent);
                else
                    al = new TemplateAliasParameter(IsEOF ? DTokens.IncompleteIdHash : 0 , CodeLocation.Empty, parent);
                al.Location = startLoc;

                // TODO?:
                // alias BasicType Declarator TemplateAliasParameterSpecialization_opt TemplateAliasParameterDefault_opt

                // TemplateAliasParameterSpecialization
                if (laKind == (Colon))
                {
                    Step();

                    AllowWeakTypeParsing=true;
                    al.SpecializationType = Type();
                    AllowWeakTypeParsing=false;

                    if (al.SpecializationType==null)
                        al.SpecializationExpression = ConditionalExpression();
                }

                // TemplateAliasParameterDefault
                if (laKind == (Assign))
                {
                    Step();

                    if (IsAssignExpression ())
                        al.DefaultExpression = ConditionalExpression ();
                    else
                        al.DefaultType = Type ();
                }
                al.EndLocation = t.EndLocation;
                return al;
            }

            // TemplateTypeParameter
            else if (laKind == (Identifier) && (Lexer.CurrentPeekToken.Kind == (Colon) || Lexer.CurrentPeekToken.Kind == (Assign) || Lexer.CurrentPeekToken.Kind == (Comma) || Lexer.CurrentPeekToken.Kind == (CloseParenthesis)))
            {
                Expect(Identifier);
                var tt = new TemplateTypeParameter(t.Value, t.Location, parent) { Location = t.Location };

                if (laKind == Colon)
                {
                    Step();
                    tt.Specialization = Type();
                }

                if (laKind == Assign)
                {
                    Step();
                    tt.Default = Type();
                }
                tt.EndLocation = t.EndLocation;
                return tt;
            }

            // TemplateValueParameter
            startLoc = la.Location;
            var bt = BasicType();
            var dv = Declarator(bt,false, null);

            if (dv == null) {
                SynErr (t.Kind, "Declarator expected for parsing template parameter");
                return new TemplateTypeParameter (DTokens.IncompleteIdHash, t.Location, parent) { Location = t.Location };
            }

            var tv = new TemplateValueParameter(dv.NameHash, dv.NameLocation, parent) {
                Location=la.Location,
                Type = dv.Type
            };

            if (laKind == (Colon))
            {
                Step();
                tv.SpecializationExpression = ConditionalExpression();
            }

            if (laKind == (Assign))
            {
                Step();
                tv.DefaultExpression = AssignExpression();
            }
            tv.EndLocation = t.EndLocation;
            return tv;
        }
Пример #13
0
        public AbstractType TryDeduce(DSymbol ds, IEnumerable<ISemantic> templateArguments)
        {
            TemplateTypeParameter tp;
            var t = ds as TemplateType;
            if (t == null)
                return null;

            var orig = ds.Definition;
            var tupleStruct = new DClassLike(DTokens.Struct) {
                NameHash = ds.NameHash,
                Parent = orig.Parent,
                Location = orig.Location,
                EndLocation = orig.EndLocation,
                NameLocation = orig.NameLocation
            };

            var ded = new Templates.DeducedTypeDictionary(tupleStruct);

            if (templateArguments != null)
            {
                var typeList = new List<AbstractType>();

                var en = templateArguments.GetEnumerator();
                if(en.MoveNext())
                {
                    var next = en.Current;
                    int i = 0;
                    for (; ; i++)
                    {
                        var fieldType = AbstractType.Get(next);

                        if (fieldType == null)
                            break;

                        fieldType.NonStaticAccess = true;

                        typeList.Add(fieldType);

                        if (!en.MoveNext())
                            break;

                        next = en.Current;

                        if (next is ArrayValue && (next as ArrayValue).IsString)
                        {
                            var name = (next as ArrayValue).StringValue;
                            var templateParamName = "_" + i.ToString();
                            tp = new TemplateTypeParameter(templateParamName, CodeLocation.Empty, tupleStruct);
                            ded[tp] = new TemplateParameterSymbol(tp, fieldType);

                            tupleStruct.Add(new DVariable { Name = name, Type = new IdentifierDeclaration(templateParamName) });

                            if (!en.MoveNext())
                                break;

                            next = en.Current;
                        }
                    }
                }

                var tupleName = "Types";
                tp = new TemplateTypeParameter(tupleName, CodeLocation.Empty, tupleStruct);
                ded[tp] = new TemplateParameterSymbol(tp, new DTuple(null, typeList));

                tupleStruct.Add(new DVariable { NameHash = DVariable.AliasThisIdentifierHash, IsAlias = true, IsAliasThis = true, Type = new IdentifierDeclaration(tupleName) });
            }

            var res = new StructType(tupleStruct, ds.DeclarationOrExpressionBase, ded.Count != 0 ? ded.Values : null);

            resultStore.Add(res, tupleStruct);

            //TODO: Ensure renaming and other AST-based things run properly

            return res;
        }
Пример #14
0
        ITemplateParameter TemplateParameter()
        {
            // TemplateThisParameter
            if (laKind == (This))
            {
                Step();

                var ret= new TemplateThisParameter()
                {
                    Location=t.Location,
                    FollowParameter=TemplateParameter(),
                    EndLocation=t.EndLocation
                };
                LastParsedObject = ret;
                return ret;
            }

            // TemplateTupleParameter
            if (laKind == (Identifier) && Lexer.CurrentPeekToken.Kind == TripleDot)
            {
                Step();
                var startLoc = t.Location;
                var id = t.Value;
                Step();

                var ret=new TemplateTupleParameter() { Name=id, Location=startLoc, EndLocation=t.EndLocation};
                LastParsedObject = ret;
                return ret;
            }

            // TemplateAliasParameter
            if (laKind == (Alias))
            {
                Step();
                var al = new TemplateAliasParameter() { Location=t.Location };
                LastParsedObject = al;

                Expect(Identifier);

                al.Name = t.Value;

                // TODO?:
                // alias BasicType Declarator TemplateAliasParameterSpecialization_opt TemplateAliasParameterDefault_opt

                // TemplateAliasParameterSpecialization
                if (laKind == (Colon))
                {
                    Step();

                    AllowWeakTypeParsing=true;
                    al.SpecializationType = Type();
                    AllowWeakTypeParsing=false;

                    if (al.SpecializationType==null)
                        al.SpecializationExpression = ConditionalExpression();
                }

                // TemplateAliasParameterDefault
                if (laKind == (Assign))
                {
                    Step();

                    AllowWeakTypeParsing=true;
                    al.DefaultType = Type();
                    AllowWeakTypeParsing=false;

                    if (al.DefaultType==null)
                        al.DefaultExpression = ConditionalExpression();
                }
                al.EndLocation = t.EndLocation;
                return al;
            }

            // TemplateTypeParameter
            if (laKind == (Identifier) && (Lexer.CurrentPeekToken.Kind == (Colon) || Lexer.CurrentPeekToken.Kind == (Assign) || Lexer.CurrentPeekToken.Kind == (Comma) || Lexer.CurrentPeekToken.Kind == (CloseParenthesis)))
            {
                Expect(Identifier);
                var tt = new TemplateTypeParameter() { Location=t.Location };
                LastParsedObject = tt;

                tt.Name = t.Value;

                if (laKind == Colon)
                {
                    Step();
                    tt.Specialization = Type();
                }

                if (laKind == Assign)
                {
                    Step();
                    tt.Default = Type();
                }
                tt.EndLocation = t.EndLocation;
                return tt;
            }

            // TemplateValueParameter
            var tv = new TemplateValueParameter() { Location=la.Location };
            LastParsedObject = tv;

            var bt = BasicType();
            var dv = Declarator(bt,false);

            tv.Type = dv.Type;
            tv.Name = dv.Name;

            if (laKind == (Colon))
            {
                Step();
                tv.SpecializationExpression = ConditionalExpression();
            }

            if (laKind == (Assign))
            {
                Step();
                tv.DefaultExpression = AssignExpression();
            }
            tv.EndLocation = t.EndLocation;
            return tv;
        }
        bool HandleDecl(TemplateTypeParameter p, IdentifierDeclaration id, ISemantic r)
        {
            // Bottom-level reached
            if (id.InnerDeclaration == null && Contains(id.Id) && !id.ModuleScoped)
            {
                // Associate template param with r
                return Set(p, r, id.Id);
            }

            /*
             * If not stand-alone identifier or is not required as template param, resolve the id and compare it against r
             */
            var _r = TypeDeclarationResolver.Resolve(id, ctxt);

            ctxt.CheckForSingleResult(_r, id);

            return _r != null && _r.Length != 0 &&
                (EnforceTypeEqualityWhenDeducing ?
                ResultComparer.IsEqual(r,_r[0]) :
                ResultComparer.IsImplicitlyConvertible(r,_r[0]));
        }
 bool HandleDecl(TemplateTypeParameter parameter, PointerDecl p, PointerType r)
 {
     return r != null &&
         r.DeclarationOrExpressionBase is PointerDecl &&
         HandleDecl(parameter, p.InnerDeclaration, r.Base);
 }
        bool HandleDecl(TemplateTypeParameter parameterRef,ArrayDecl arrayDeclToCheckAgainst, AssocArrayType argumentArrayType)
        {
            if (argumentArrayType == null)
                return false;

            // Handle key type
            if((arrayDeclToCheckAgainst.KeyType != null || arrayDeclToCheckAgainst.KeyExpression!=null) && argumentArrayType.KeyType == null)
                return false;
            bool result = false;

            if (arrayDeclToCheckAgainst.KeyExpression != null)
            {
                // Remove all surrounding parentheses from the expression
                var x_param = arrayDeclToCheckAgainst.KeyExpression;

                while(x_param is SurroundingParenthesesExpression)
                    x_param = ((SurroundingParenthesesExpression)x_param).Expression;

                var ad_Argument = argumentArrayType.DeclarationOrExpressionBase as ArrayDecl;

                /*
                 * This might be critical:
                 * the [n] part in class myClass(T:char[n], int n) {}
                 * will be seen as an identifier expression, not as an identifier declaration.
                 * So in the case the parameter expression is an identifier,
                 * test if it's part of the parameter list
                 */
                var id = x_param as IdentifierExpression;
                if(id!=null && id.IsIdentifier && Contains(id.ValueStringHash))
                {
                    // If an expression (the usual case) has been passed as argument, evaluate its value, otherwise is its type already resolved.
                    ISemantic finalArg = null;

                    if (ad_Argument != null && ad_Argument.KeyExpression != null)
                    {
                        ISymbolValue val = null;
                        int len = -1;
                        finalArg = TypeDeclarationResolver.ResolveKey(ad_Argument, out len, out val, ctxt);
                        if (val != null)
                            finalArg = val;
                    }
                    else
                        finalArg = argumentArrayType.KeyType;

                    //TODO: Do a type convertability check between the param type and the given argument's type.
                    // The affected parameter must also be a value parameter then, if an expression was given.

                    // and handle it as if it was an identifier declaration..
                    result = Set(parameterRef, finalArg, id.ValueStringHash);
                }
                else if (ad_Argument != null && ad_Argument.KeyExpression != null)
                {
                    // Just test for equality of the argument and parameter expression, e.g. if both param and arg are 123, the result will be true.
                    result = SymbolValueComparer.IsEqual(arrayDeclToCheckAgainst.KeyExpression, ad_Argument.KeyExpression, new StandardValueProvider(ctxt));
                }
            }
            else if (arrayDeclToCheckAgainst.KeyType != null)
            {
                // If the array we're passing to the decl check that is static (i.e. has a constant number as key 'type'),
                // pass that number instead of type 'int' to the check.
                var at = argumentArrayType as ArrayType;
                if (argumentArrayType != null && at != null && at.IsStaticArray)
                    result = HandleDecl(parameterRef, arrayDeclToCheckAgainst.KeyType,
                        new PrimitiveValue(D_Parser.Parser.DTokens.Int, (decimal)at.FixedLength, null));
                else
                    result = HandleDecl(parameterRef, arrayDeclToCheckAgainst.KeyType, argumentArrayType.KeyType);
            }

            // Handle inner type
            return result && HandleDecl(parameterRef,arrayDeclToCheckAgainst.InnerDeclaration, argumentArrayType.Base);
        }
        bool HandleDecl(TemplateTypeParameter p, MemberFunctionAttributeDecl m, AbstractType r)
        {
            if (r == null || r.Modifier == 0)
                return false;

            // Modifiers must be equal on both sides
            if (m.Modifier != r.Modifier)
                return false;

            // Now compare the type inside the parentheses with the given type 'r'
            return m.InnerType != null && HandleDecl(p, m.InnerType, r);
        }
		bool HandleDecl(TemplateTypeParameter parameterRef,ArrayDecl arrayDeclToCheckAgainst, AssocArrayType argumentArrayType)
		{
			if (argumentArrayType == null)
				return false;

			// Handle key type
			var at = argumentArrayType as ArrayType;
			if((arrayDeclToCheckAgainst.ClampsEmpty == (at == null)) &&
				(at == null || !at.IsStaticArray || arrayDeclToCheckAgainst.KeyExpression == null))
				return false;
			
			bool result = true;

			if (arrayDeclToCheckAgainst.KeyExpression != null)
			{
				var x_param = arrayDeclToCheckAgainst.KeyExpression;

				while(x_param is SurroundingParenthesesExpression)
					x_param = ((SurroundingParenthesesExpression)x_param).Expression;
				
				/*
				 * This might be critical:
				 * the [n] part in class myClass(T:char[n], int n) {}
				 * will be seen as an identifier expression, not as an identifier declaration.
				 * So in the case the parameter expression is an identifier,
				 * test if it's part of the parameter list
				 */
				var id = x_param as IdentifierExpression;
				if (id != null && id.IsIdentifier && Contains (id.ValueStringHash)) { // Match int[5] into T[n],n - after deduction, n will be 5
					
					// If an expression (the usual case) has been passed as argument, evaluate its value, otherwise is its type already resolved.
					var finalArg = argumentArrayType is ArrayType ? (ISemantic)new PrimitiveValue ((argumentArrayType as ArrayType).FixedLength) : argumentArrayType.KeyType;

					//TODO: Do a type convertability check between the param type and the given argument's type.
					// The affected parameter must also be a value parameter then, if an expression was given.

					// and handle it as if it was an identifier declaration..
					result = Set (parameterRef, finalArg, id.ValueStringHash); 
				} else if (argumentArrayType is ArrayType) { // Match int[5] into T[5]
					// Just test for equality of the argument and parameter expression, e.g. if both param and arg are 123, the result will be true.
					result = SymbolValueComparer.IsEqual (Evaluation.EvaluateValue (arrayDeclToCheckAgainst.KeyExpression, ctxt), new PrimitiveValue ((argumentArrayType as ArrayType).FixedLength));
				} else
					result = false;
			}
			else if (arrayDeclToCheckAgainst.KeyType != null)
			{
				// If the array we're passing to the decl check that is static (i.e. has a constant number as key 'type'),
				// pass that number instead of type 'int' to the check.
				if (argumentArrayType != null && at != null && at.IsStaticArray)
					result = HandleDecl(parameterRef, arrayDeclToCheckAgainst.KeyType,
						new PrimitiveValue(at.FixedLength)); 
				else
					result = HandleDecl(parameterRef, arrayDeclToCheckAgainst.KeyType, argumentArrayType.KeyType);
			}

			// Handle inner type
			return result && HandleDecl(parameterRef,arrayDeclToCheckAgainst.InnerDeclaration, argumentArrayType.Base);
		}
        bool HandleDecl(TemplateTypeParameter par, DelegateDeclaration d, DelegateType dr)
        {
            // Delegate literals or other expressions are not allowed
            if(dr==null || dr.IsFunctionLiteral)
                return false;

            var dr_decl = (DelegateDeclaration)dr.DeclarationOrExpressionBase;

            // Compare return types
            if(	d.IsFunction == dr_decl.IsFunction &&
                dr.ReturnType != null &&
                HandleDecl(par, d.ReturnType,dr.ReturnType))
            {
                // If no delegate args expected, it's valid
                if ((d.Parameters == null || d.Parameters.Count == 0) &&
                    dr_decl.Parameters == null || dr_decl.Parameters.Count == 0)
                    return true;

                // If parameter counts unequal, return false
                else if (d.Parameters == null || dr_decl.Parameters == null || d.Parameters.Count != dr_decl.Parameters.Count)
                    return false;

                // Compare & Evaluate each expected with given parameter
                var dr_paramEnum = dr_decl.Parameters.GetEnumerator();
                foreach (var p in d.Parameters)
                {
                    // Compare attributes with each other
                    if (p is DNode)
                    {
                        if (!(dr_paramEnum.Current is DNode))
                            return false;

                        var dn = (DNode)p;
                        var dn_arg = (DNode)dr_paramEnum.Current;

                        if ((dn.Attributes == null || dn.Attributes.Count == 0) &&
                            (dn_arg.Attributes == null || dn_arg.Attributes.Count == 0))
                            return true;

                        else if (dn.Attributes == null || dn_arg.Attributes == null ||
                            dn.Attributes.Count != dn_arg.Attributes.Count)
                            return false;

                        foreach (var attr in dn.Attributes)
                        {
                            if(!dn_arg.ContainsAttribute(attr))
                                return false;
                        }
                    }

                    // Compare types
                    if (p.Type!=null && dr_paramEnum.MoveNext() && dr_paramEnum.Current.Type!=null)
                    {
                        var dr_resolvedParamType = TypeDeclarationResolver.ResolveSingle(dr_paramEnum.Current.Type, ctxt);

                        if (dr_resolvedParamType == null  ||
                            !HandleDecl(par, p.Type, dr_resolvedParamType))
                            return false;
                    }
                    else
                        return false;
                }
            }

            return false;
        }
Пример #21
0
		TemplateParameter TemplateParameter(DNode parent)
		{
			IBlockNode scope = parent as IBlockNode;
			CodeLocation startLoc;

			// TemplateThisParameter
			if (laKind == (This))
			{
				Step();

				startLoc = t.Location;
				var end = t.EndLocation;

				return new TemplateThisParameter(TemplateParameter(parent), parent) { Location=startLoc, EndLocation=end };
			}

			// TemplateTupleParameter
			else if (laKind == (Identifier) && Lexer.CurrentPeekToken.Kind == TripleDot)
			{
				Step();
				startLoc = t.Location;
				var id = t.Value;
				Step();

				return new TemplateTupleParameter(id, startLoc, parent) { Location=startLoc, EndLocation=t.EndLocation	};
			}

			// TemplateAliasParameter
			else if (laKind == (Alias))
			{
				Step();

				startLoc = t.Location;
				TemplateAliasParameter al;
				ITypeDeclaration bt;

				if(IsEOF)
					al = new TemplateAliasParameter(DTokens.IncompleteIdHash, CodeLocation.Empty, parent);
				else
				{
					bt = BasicType (scope);
					ParseBasicType2 (ref bt, scope);

					if (laKind == Identifier) {
						// alias BasicType Declarator TemplateAliasParameterSpecialization_opt TemplateAliasParameterDefault_opt
						var nn = Declarator (bt, false, parent);
						al = new TemplateAliasParameter (nn.NameHash, nn.NameLocation, parent);
						al.Type = nn.Type;
						//TODO: Assign other parts of the declarator? Parameters and such?
					} else if (bt is IdentifierDeclaration)
						al = new TemplateAliasParameter ((bt as IdentifierDeclaration).IdHash, bt.Location, parent);
					else
						al = new TemplateAliasParameter (0, CodeLocation.Empty, parent);
				}
				al.Location = startLoc;

				// TemplateAliasParameterSpecialization
				if (laKind == (Colon))
				{
					Step();

					AllowWeakTypeParsing=true;
					al.SpecializationType = Type(scope);
					AllowWeakTypeParsing=false;

					if (al.SpecializationType==null)
						al.SpecializationExpression = ConditionalExpression(scope);
				}

				// TemplateAliasParameterDefault
				if (laKind == (Assign))
				{
					Step();

					if (IsAssignExpression ())
						al.DefaultExpression = ConditionalExpression (scope);
					else
						al.DefaultType = Type (scope);
				}
				al.EndLocation = t.EndLocation;
				return al;
			}

			// TemplateTypeParameter
			else if (laKind == (Identifier) && (Lexer.CurrentPeekToken.Kind == (Colon) || Lexer.CurrentPeekToken.Kind == (Assign) || Lexer.CurrentPeekToken.Kind == (Comma) || Lexer.CurrentPeekToken.Kind == (CloseParenthesis)))
			{
				Expect(Identifier);
				var tt = new TemplateTypeParameter(t.Value, t.Location, parent) { Location = t.Location };

				if (laKind == Colon)
				{
					Step();
					tt.Specialization = Type(scope);
				}

				if (laKind == Assign)
				{
					Step();
					tt.Default = Type(scope);
				}
				tt.EndLocation = t.EndLocation;
				return tt;
			}

			// TemplateValueParameter
			startLoc = la.Location;
			var dv = Declarator(BasicType(scope), false, null);

			if (dv == null) {
				SynErr (t.Kind, "Declarator expected for parsing template parameter");
				return new TemplateTypeParameter (DTokens.IncompleteIdHash, t.Location, parent) { Location = t.Location };
			}

			var tv = new TemplateValueParameter(dv.NameHash, dv.NameLocation, parent) { 
				Location=startLoc,
				Type = dv.Type
			};

			if (laKind == (Colon))
			{
				Step();
				tv.SpecializationExpression = ConditionalExpression(scope);
			}

			if (laKind == (Assign))
			{
				Step();
				tv.DefaultExpression = AssignExpression(scope);
			}
			tv.EndLocation = t.EndLocation;
			return tv;
		}
        bool HandleDecl(TemplateTypeParameter p, MemberFunctionAttributeDecl m, AbstractType r)
        {
            if (r == null || r.Modifier == 0)
                return false;

            // Modifiers must be equal on both sides
            if (m.Modifier != r.Modifier)
                return false;

            // Strip modifier, but: immutable(int[]) becomes immutable(int)[] ?!
            AbstractType newR;
            if (r is AssocArrayType)
            {
                var aa = r as AssocArrayType;
                var clonedValueType = aa.Modifier != r.Modifier ? aa.ValueType.Clone(false) : aa.ValueType;
                clonedValueType.Modifier = r.Modifier;

                var at = aa as ArrayType;
                if (at != null)
                    newR = at.IsStaticArray ? new ArrayType(clonedValueType, at.FixedLength, r.DeclarationOrExpressionBase) : new ArrayType(clonedValueType, r.DeclarationOrExpressionBase);
                else
                    newR = new AssocArrayType(clonedValueType, aa.KeyType, r.DeclarationOrExpressionBase);
            }
            else
            {
                newR = r.Clone(false);
                newR.Modifier = 0;
            }

            // Now compare the type inside the parentheses with the given type 'r'
            return m.InnerType != null && HandleDecl(p, m.InnerType, newR);
        }
Пример #23
0
		public AbstractType TryDeduce(DSymbol ds, IEnumerable<ISemantic> templateArguments, ref INode n)
		{
			TemplateTypeParameter tp;
			var t = ds as TemplateType;
			if (t == null)
				return null;

			var orig = ds.Definition;
			var tupleStruct = new DClassLike(DTokens.Struct)
			{
				NameHash = ds.NameHash,
				Parent = orig.Parent,
				Location = orig.Location,
				EndLocation = orig.EndLocation,
				NameLocation = orig.NameLocation
			};

			var ded = new Templates.DeducedTypeDictionary(tupleStruct);

			var sb = new StringBuilder();

			if (templateArguments != null)
			{
				var en = templateArguments.GetEnumerator();
				if (en.MoveNext())
				{
					var next = en.Current;
					int i = 0;
					for (; ; i++)
					{
						var fieldType = AbstractType.Get(next);

						if (fieldType == null)
							break;

						fieldType.NonStaticAccess = true;

						if (!en.MoveNext())
							break;

						next = en.Current;

						if (next is ArrayValue && (next as ArrayValue).IsString)
						{
							var name = (next as ArrayValue).StringValue;
							if (!string.IsNullOrWhiteSpace(name))
							{
								var templateParamName = "_" + i.ToString();
								tp = new TemplateTypeParameter(templateParamName, CodeLocation.Empty, tupleStruct);
								ded[tp] = new TemplateParameterSymbol(tp, fieldType);

								// getter
								sb.Append("@property @safe ").Append(templateParamName).Append(' ').Append(name).AppendLine("() pure nothrow const {}");
								// setter
								sb.Append("@property @safe void ").Append(name).AppendLine("(").Append(templateParamName).AppendLine(" v) pure nothrow {}");
								// constants
								sb.Append("enum ").Append(templateParamName).Append(" ").Append(name).Append("_min = cast(").Append(templateParamName).AppendLine(") 0;");
								sb.Append("enum ").Append(templateParamName).Append(" ").Append(name).Append("_max = cast(").Append(templateParamName).AppendLine(") 0;");
							}
							if (!en.MoveNext())
								break;
						}
						else
							break;

						if (!en.MoveNext()) // Skip offset
							break;

						next = en.Current;
					}
				}

				tupleStruct.Add(new DVariable { 
					NameHash = tupleStruct.NameHash, 
					Attributes = new List<DAttribute> { new Modifier(DTokens.Enum) }, 
					Initializer = new IdentifierExpression(sb.ToString(), LiteralFormat.StringLiteral, LiteralSubformat.Utf8)
				});
			}

			n = tupleStruct;
			return new TemplateType(tupleStruct, ded.Count != 0 ? ded.Values : null);
		}