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); } }
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; }
/// <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); }
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; }
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; }
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; }
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); }
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); }