public static string GeneratePrototype(AbstractType t, int currentParameter = -1, bool isInTemplateArgInsight = false) { var ms = t as MemberSymbol; if (ms != null) { if (ms.Definition is DVariable) { var bt = DResolver.StripAliasSymbol(ms.Base); if (bt is DelegateType) { return(VDServerCompletionDataGenerator.GeneratePrototype(bt as DelegateType, currentParameter)); } } else if (ms.Definition is DMethod) { return(VDServerCompletionDataGenerator.GeneratePrototype(ms.Definition as DMethod, isInTemplateArgInsight, currentParameter)); } } else if (t is TemplateIntermediateType) { return(VDServerCompletionDataGenerator.GeneratePrototype(t as TemplateIntermediateType, currentParameter)); } return(null); }
/// <summary> /// http://dlang.org/expression.html#IsExpression /// </summary> public ISemantic E(IsExpression isExpression) { if (!eval) { return(new PrimitiveType(DTokens.Bool)); } bool retTrue = false; if (isExpression.TestedType != null) { var typeToCheck = DResolver.StripAliasSymbol(TypeDeclarationResolver.ResolveSingle(isExpression.TestedType, ctxt)); if (typeToCheck != null) { // case 1, 4 if (isExpression.TypeSpecialization == null && isExpression.TypeSpecializationToken == 0) { retTrue = typeToCheck != null; } // The probably most frequented usage of this expression else if (string.IsNullOrEmpty(isExpression.TypeAliasIdentifier)) { retTrue = evalIsExpression_NoAlias(isExpression, typeToCheck); } else { retTrue = evalIsExpression_WithAliases(isExpression, typeToCheck); } } } return(new PrimitiveValue(DTokens.Bool, retTrue?1:0, isExpression)); }
ISemantic E(PostfixExpression ex) { if (ex is PostfixExpression_MethodCall) { return(E((PostfixExpression_MethodCall)ex, !ctxt.Options.HasFlag(ResolutionOptions.ReturnMethodReferencesOnly))); } var foreExpr = E(ex.PostfixForeExpression); if (foreExpr is AliasedType) { foreExpr = DResolver.StripAliasSymbol((AbstractType)foreExpr); } if (foreExpr == null) { if (eval) { return(null); } else { ctxt.LogError(new NothingFoundError(ex.PostfixForeExpression)); return(null); } } if (ex is PostfixExpression_Access) { var r = E((PostfixExpression_Access)ex, foreExpr, true); ctxt.CheckForSingleResult(r, ex); return(r != null && r.Length != 0 ? r[0] : null); } else if (ex is PostfixExpression_Increment) { return(E((PostfixExpression_Increment)ex, foreExpr)); } else if (ex is PostfixExpression_Decrement) { return(E((PostfixExpression_Decrement)foreExpr)); } // myArray[0]; myArray[0..5]; // opIndex/opSlice ? if (foreExpr is MemberSymbol) { foreExpr = DResolver.StripMemberSymbols((AbstractType)foreExpr); } if (ex is PostfixExpression_Slice) { return(E((PostfixExpression_Slice)ex, foreExpr)); } else if (ex is PostfixExpression_Index) { return(E((PostfixExpression_Index)ex, foreExpr)); } return(null); }
AbstractType HandleAccessExpressions(PostfixExpression_Access acc, ResolutionContext ctxt) { AbstractType pfType = null; if (acc.PostfixForeExpression is PostfixExpression_Access) { pfType = HandleAccessExpressions((PostfixExpression_Access)acc.PostfixForeExpression, ctxt); } else { pfType = DResolver.StripAliasSymbol(Evaluation.EvaluateType(acc.PostfixForeExpression, ctxt)); if (acc.PostfixForeExpression is IdentifierExpression || acc.PostfixForeExpression is TemplateInstanceExpression || acc.PostfixForeExpression is PostfixExpression_Access) { HandleResult(acc.PostfixForeExpression, pfType); } } var accessedMembers = Evaluation.GetAccessedOverloads(acc, ctxt, pfType); ctxt.CheckForSingleResult(accessedMembers, acc); if (accessedMembers != null && accessedMembers.Length != 0) { HandleResult(acc, accessedMembers[0]); return(accessedMembers[0]); } return(null); }
public static TooltipInformation Generate(AbstractType t, int currentParameter = -1, bool isInTemplateArgInsight = false) { var ms = t as MemberSymbol; if (ms != null) { if (ms.Definition is DVariable) { var bt = DResolver.StripAliasSymbol(ms.Base); if (bt is DelegateType) { return(TooltipInfoGenerator.Generate(bt as DelegateType, currentParameter)); } } else if (ms.Definition is DMethod) { return(TooltipInfoGenerator.Generate(ms.Definition as DMethod, isInTemplateArgInsight, currentParameter)); } } else if (t is TemplateIntermediateType) { return(Generate(t as TemplateIntermediateType, currentParameter)); } return(new TooltipInformation()); }
void _th(object pcl_shared) { var pcl = (ParseCacheList)pcl_shared; var ctxt = new ResolverContextStack(pcl, new ResolverContext { ScopedBlock = ast }); // Make it as most performing as possible by avoiding unnecessary base types. // Aliases should be analyzed deeper though. ctxt.CurrentContext.ContextDependentOptions |= ResolutionOptions.StopAfterFirstOverloads | ResolutionOptions.DontResolveBaseTypes | //TODO: Exactly find out which option can be enabled here. Resolving variables' types is needed sometimes - but only, when highlighting a variable reference is wanted explicitly. ResolutionOptions.NoTemplateParameterDeduction | ResolutionOptions.ReturnMethodReferencesOnly; ISyntaxRegion sr = null; int i = 0; while (curQueueOffset < queueCount) { // Avoid race condition runtime errors lock (_lockObject) { i = curQueueOffset; curQueueOffset++; } // Resolve gotten syntax object sr = q[i]; var sb = ctxt.CurrentContext.ScopedBlock; ctxt.CurrentContext.ScopedBlock = DResolver.SearchBlockAt( sb == null || sr.Location <sb.BlockStartLocation || sr.EndLocation> sb.EndLocation ? ast : sb, sr.Location, out ctxt.CurrentContext.ScopedStatement); if (sr is PostfixExpression_Access) { HandleAccessExpressions((PostfixExpression_Access)sr, ctxt); } else { AbstractType t = null; if (sr is IExpression) { t = DResolver.StripAliasSymbol(Evaluation.EvaluateType((IExpression)sr, ctxt)); } else if (sr is ITypeDeclaration) { t = DResolver.StripAliasSymbol(TypeDeclarationResolver.ResolveSingle((ITypeDeclaration)sr, ctxt)); } // Enter into the result list HandleResult(sr, t); } } }
ISemantic E(NewExpression nex) { // http://www.d-programming-language.org/expression.html#NewExpression ISemantic[] possibleTypes = null; if (nex.Type is IdentifierDeclaration) { possibleTypes = TypeDeclarationResolver.Resolve((IdentifierDeclaration)nex.Type, ctxt, filterForTemplateArgs: false); } else { possibleTypes = TypeDeclarationResolver.Resolve(nex.Type, ctxt); } var ctors = new Dictionary <DMethod, TemplateIntermediateType>(); if (possibleTypes == null) { return(null); } foreach (var t in possibleTypes) { var ct = DResolver.StripAliasSymbol(t as AbstractType) as TemplateIntermediateType; if (ct != null && !ct.Definition.ContainsAttribute(DTokens.Abstract)) { foreach (var ctor in GetConstructors(ct)) { ctors.Add(ctor, ct); } } } MemberSymbol finalCtor = null; var kvArray = ctors.ToArray(); /* * TODO: Determine argument types and filter out ctor overloads. */ if (kvArray.Length != 0) { finalCtor = new MemberSymbol(kvArray[0].Key, kvArray[0].Value, nex); } else if (possibleTypes.Length != 0) { return(AbstractType.Get(possibleTypes[0])); } return(finalCtor); }
public void EponymousTemplates() { var ctxt = ResolutionTests.CreateDefCtxt(@"module B; alias Tuple(T...) = T; alias Tup = Tuple!(int, float, string); enum isIntOrFloat(F) = is(F == int) || is(F == float); "); IExpression x; ISymbolValue v; AbstractType t; x = DParser.ParseExpression("isIntOrFloat!(Tup[0])"); v = Evaluation.EvaluateValue(x, ctxt); Assert.That(v, Is.TypeOf(typeof(PrimitiveValue))); Assert.That((v as PrimitiveValue).Value, Is.Not.EqualTo(0m)); DToken tk; var td = DParser.ParseBasicType("Tuple!(int, float, string)", out tk); //t = TypeDeclarationResolver.ResolveSingle (td, ctxt); //Assert.That (t, Is.TypeOf(typeof(MemberSymbol))); //Assert.That ((t as MemberSymbol).Base, Is.TypeOf(typeof(DTuple))); x = DParser.ParseExpression("Tup[0]"); t = ExpressionTypeEvaluation.EvaluateType(x, ctxt); Assert.That(t, Is.TypeOf(typeof(PrimitiveType))); x = DParser.ParseExpression("Tup[1]"); t = ExpressionTypeEvaluation.EvaluateType(x, ctxt); Assert.That(t, Is.TypeOf(typeof(PrimitiveType))); x = DParser.ParseExpression("Tup[2]"); t = DResolver.StripAliasSymbol(ExpressionTypeEvaluation.EvaluateType(x, ctxt)); Assert.That(t, Is.TypeOf(typeof(ArrayType))); x = DParser.ParseExpression("isIntOrFloat!int"); v = Evaluation.EvaluateValue(x, ctxt); Assert.That(v, Is.TypeOf(typeof(PrimitiveValue))); Assert.That((v as PrimitiveValue).Value, Is.Not.EqualTo(0m)); x = DParser.ParseExpression("isIntOrFloat!float"); v = Evaluation.EvaluateValue(x, ctxt); Assert.That(v, Is.TypeOf(typeof(PrimitiveValue))); Assert.That((v as PrimitiveValue).Value, Is.Not.EqualTo(0m)); x = DParser.ParseExpression("isIntOrFloat!string"); v = Evaluation.EvaluateValue(x, ctxt); Assert.That(v, Is.TypeOf(typeof(PrimitiveValue))); Assert.That((v as PrimitiveValue).Value, Is.EqualTo(0m)); }
public static AbstractType ResolveTraitArgument(ResolutionContext ctxt, TraitsArgument arg) { if (arg.Type != null) { return(TypeDeclarationResolver.ResolveSingle(arg.Type, ctxt)); } else if (arg.AssignExpression != null) { return(DResolver.StripAliasSymbol(EvaluateType(arg.AssignExpression, ctxt))); } else { return(null); } }
AbstractType E(TraitsArgument arg, TraitsExpression te) { if (arg.Type != null) { return(TypeDeclarationResolver.ResolveSingle(arg.Type, ctxt)); } else if (arg.AssignExpression != null) { return(DResolver.StripAliasSymbol(EvaluateType(arg.AssignExpression, ctxt))); } else { EvalError(te, "Argument must be a type or an expression!"); return(null); } }
AbstractType EvalForeExpression(PostfixExpression ex) { var foreExpr = ex.PostfixForeExpression != null?ex.PostfixForeExpression.Accept(this) : null; if (foreExpr is AliasedType) { foreExpr = DResolver.StripAliasSymbol(foreExpr); } if (foreExpr == null) { ctxt.LogError(new NothingFoundError(ex.PostfixForeExpression)); } return(foreExpr); }
public static ArrayType GetStringType(ResolutionContext ctxt, LiteralSubformat fmt = LiteralSubformat.Utf8) { ArrayType _t = null; if (ctxt != null) { var obj = ctxt.ParseCache.LookupModuleName("object").FirstOrDefault(); if (obj != null) { string strType = fmt == LiteralSubformat.Utf32 ? "dstring" : fmt == LiteralSubformat.Utf16 ? "wstring" : "string"; var strNode = obj[strType]; if (strNode != null) { foreach (var n in strNode) { _t = DResolver.StripAliasSymbol(TypeDeclarationResolver.HandleNodeMatch(n, ctxt)) as ArrayType; if (_t != null) { break; } } } } } if (_t == null) { var ch = fmt == LiteralSubformat.Utf32 ? DTokens.Dchar : fmt == LiteralSubformat.Utf16 ? DTokens.Wchar : DTokens.Char; _t = new ArrayType(new PrimitiveType(ch, DTokens.Immutable), new ArrayDecl { ValueType = new MemberFunctionAttributeDecl(DTokens.Immutable) { InnerType = new DTokenDeclaration(ch) } }); } return(_t); }
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 = DResolver.StripAliasSymbol(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); }
public void AliasedTypeTuple() { var ctxt = ResolutionTests.CreateDefCtxt(@"module A; template Tuple(T...) { alias Tuple = T; } alias Tup = Tuple!(int, float, string); template isIntOrFloat(T) { static if (is(T == int) || is(T == float)) enum isIntOrFloat = true; else enum isIntOrFloat = false; } "); IExpression x; ISymbolValue v; AbstractType t; x = DParser.ParseExpression("Tup[2]"); t = DResolver.StripAliasSymbol(ExpressionTypeEvaluation.EvaluateType(x, ctxt)); Assert.That(t, Is.TypeOf(typeof(ArrayType))); x = DParser.ParseExpression("isIntOrFloat!(Tup[2])"); v = Evaluation.EvaluateValue(x, ctxt); Assert.That(v, Is.TypeOf(typeof(PrimitiveValue))); Assert.That((v as PrimitiveValue).Value, Is.EqualTo(0m)); x = DParser.ParseExpression("Tup[0]"); t = ExpressionTypeEvaluation.EvaluateType(x, ctxt); Assert.That(t, Is.TypeOf(typeof(PrimitiveType))); x = DParser.ParseExpression("Tup[1]"); t = ExpressionTypeEvaluation.EvaluateType(x, ctxt); Assert.That(t, Is.TypeOf(typeof(PrimitiveType))); x = DParser.ParseExpression("isIntOrFloat!(Tup[0])"); v = Evaluation.EvaluateValue(x, ctxt); Assert.That(v, Is.TypeOf(typeof(PrimitiveValue))); Assert.That((v as PrimitiveValue).Value, Is.Not.EqualTo(0m)); }
protected override void BuildCompletionDataInternal(IEditorData Editor, char enteredChar) { ctxt = ResolutionContext.Create(Editor.ParseCache, new ConditionalCompilationFlags(Editor), ScopedBlock, ScopedStatement); ctxt.CurrentContext.ContextDependentOptions |= ResolutionOptions.ReturnMethodReferencesOnly; var ex = AccessExpression.AccessExpression == null ? AccessExpression.PostfixForeExpression : AccessExpression; var r = DResolver.StripAliasSymbol(Evaluation.EvaluateType(ex, ctxt)); if (r == null) //TODO: Add after-space list creation when an unbound . (Dot) was entered which means to access the global scope { return; } BuildCompletionData(r, ScopedBlock); if (CompletionOptions.Instance.ShowUFCSItems && (MemberFilter & MemberFilter.Methods) != 0 && !(r is UserDefinedType || r is PrimitiveType || r is PackageSymbol || r is ModuleSymbol)) { UFCSCompletionProvider.Generate(r, ctxt, Editor, CompletionDataGenerator); } }
protected override void BuildCompletionDataInternal(IEditorData Editor, char enteredChar) { ed = Editor; ctxt = ResolutionContext.Create(Editor.ParseCache, new ConditionalCompilationFlags(Editor), ScopedBlock, ScopedStatement); ctxt.CurrentContext.ContextDependentOptions |= ResolutionOptions.ReturnMethodReferencesOnly; AbstractType t; if (AccessExpression is IExpression) { t = ExpressionTypeEvaluation.EvaluateType(AccessExpression as IExpression, ctxt); } else if (AccessExpression is ITypeDeclaration) { t = TypeDeclarationResolver.ResolveSingle(AccessExpression as ITypeDeclaration, ctxt); } else { return; } t = DResolver.StripAliasSymbol(t); if (t == null) //TODO: Add after-space list creation when an unbound . (Dot) was entered which means to access the global scope { return; } isVariableInstance = false; if (t.DeclarationOrExpressionBase is ITypeDeclaration) { isVariableInstance |= (t.DeclarationOrExpressionBase as ITypeDeclaration).ExpressesVariableAccess; } t.Accept(this); }
public static AbstractType[] GetUnfilteredMethodOverloads(IExpression foreExpression, ResolutionContext ctxt, IExpression supExpression = null) { AbstractType[] overloads = null; if (foreExpression is TemplateInstanceExpression) { overloads = Evaluation.GetOverloads(foreExpression as TemplateInstanceExpression, ctxt, null); } else if (foreExpression is IdentifierExpression) { overloads = Evaluation.GetOverloads(foreExpression as IdentifierExpression, ctxt, false); } else if (foreExpression is PostfixExpression_Access) { overloads = Evaluation.GetAccessedOverloads((PostfixExpression_Access)foreExpression, ctxt, null, false); } else if (foreExpression is TokenExpression) { overloads = GetResolvedConstructorOverloads((TokenExpression)foreExpression, ctxt); } else { overloads = new[] { Evaluation.EvaluateType(foreExpression, ctxt) } }; var l = new List <AbstractType>(); bool staticOnly = true; foreach (var ov in DResolver.StripAliasSymbols(overloads)) { var t = ov; if (ov is MemberSymbol) { var ms = ov as MemberSymbol; if (ms.Definition is Dom.DMethod) { l.Add(ms); continue; } staticOnly = false; t = DResolver.StripAliasSymbol(ms.Base); } if (t is TemplateIntermediateType) { var tit = t as TemplateIntermediateType; var m = TypeDeclarationResolver.HandleNodeMatches( GetOpCalls(tit, staticOnly), ctxt, null, supExpression ?? foreExpression); /* * On structs, there must be a default () constructor all the time. * If there are (other) constructors in structs, the explicit member initializer constructor is not * provided anymore. This will be handled in the GetConstructors() method. * If there are opCall overloads, canCreateeExplicitStructCtor overrides the ctor existence check in GetConstructors() * and enforces that the explicit ctor will not be generated. * An opCall overload with no parameters supersedes the default ctor. */ var canCreateExplicitStructCtor = m == null || m.Length == 0; if (!canCreateExplicitStructCtor) { l.AddRange(m); } m = TypeDeclarationResolver.HandleNodeMatches( GetConstructors(tit, canCreateExplicitStructCtor), ctxt, null, supExpression ?? foreExpression); if (m != null && m.Length != 0) { l.AddRange(m); } } else { l.Add(ov); } } return(l.ToArray()); }
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); }
ISemantic E(PostfixExpression_MethodCall call, bool returnBaseTypeOnly = true) { // Deduce template parameters later on AbstractType[] baseExpression; ISymbolValue baseValue; TemplateInstanceExpression tix; GetRawCallOverloads(call, out baseExpression, out baseValue, out tix); var methodOverloads = new List <AbstractType>(); #region Search possible methods, opCalls or delegates that could be called bool requireStaticItems = true; //TODO: What if there's an opCall and a foreign method at the same time? - and then this variable would be bullshit IEnumerable <AbstractType> scanResults = DResolver.StripAliasSymbols(baseExpression); var nextResults = new List <AbstractType>(); while (scanResults != null) { foreach (var b in scanResults) { if (b is MemberSymbol) { var mr = (MemberSymbol)b; if (mr.Definition is DMethod) { methodOverloads.Add(mr); continue; } else if (mr.Definition is DVariable) { // If we've got a variable here, get its base type/value reference if (eval) { var dgVal = ValueProvider[(DVariable)mr.Definition] as DelegateValue; if (dgVal != null) { nextResults.Add(dgVal.Definition); continue; } else { EvalError(call, "Variable must be a delegate, not anything else", mr); return(null); } } else { var bt = DResolver.StripAliasSymbol(mr.Base ?? TypeDeclarationResolver.ResolveSingle(mr.Definition.Type, ctxt)); // Must be of type delegate if (bt is DelegateType) { //TODO: Ensure that there's no further overload - inform the user elsewise if (returnBaseTypeOnly) { return(bt); } else { return(new MemberSymbol(mr.Definition, bt, mr.DeclarationOrExpressionBase)); } } else { /* * If mr.Node is not a method, so e.g. if it's a variable * pointing to a delegate * * class Foo * { * string opCall() { return "asdf"; } * } * * Foo f=new Foo(); * f(); -- calls opCall, opCall is not static */ nextResults.Add(bt); requireStaticItems = false; } //TODO: Can other types work as function/are callable? } } } else if (b is DelegateType) { var dg = (DelegateType)b; /* * int a = delegate(x) { return x*2; } (12); // a is 24 after execution * auto dg=delegate(x) {return x*3;}; * int b = dg(4); */ if (dg.IsFunctionLiteral) { methodOverloads.Add(dg); } else { // If it's just wanted to pass back the delegate's return type, skip the remaining parts of this method. if (eval) { EvalError(call, "TODO", dg); return(null); } //TODO //if(returnBaseTypeOnly) //TODO: Check for multiple definitions. Also, make a parameter-argument check to inform the user about wrong arguments. return(dg); } } else if (b is ClassType || b is StructType) { var tit = (TemplateIntermediateType)b; /* * auto a = MyStruct(); -- opCall-Overloads can be used */ var classDef = tit.Definition; if (classDef == null) { continue; } foreach (var i in GetOpCalls(tit, requireStaticItems)) { methodOverloads.Add(TypeDeclarationResolver.HandleNodeMatch(i, ctxt, b, call) as MemberSymbol); } /* * Every struct can contain a default ctor: * * struct S { int a; bool b; } * * auto s = S(1,true); -- ok * auto s2= new S(2,false); -- error, no constructor found! */ if (b is StructType && methodOverloads.Count == 0) { //TODO: Deduce parameters return(b); } } /* * If the overload is a template, it quite exclusively means that we'll handle a method that is the only * child inside a template + that is named as the template. */ else if (b is TemplateType) { methodOverloads.Add(b); } } scanResults = nextResults.Count == 0 ? null : nextResults.ToArray(); nextResults.Clear(); } #endregion if (methodOverloads.Count == 0) { return(null); } // Get all arguments' types var callArguments = new List <ISemantic>(); bool hasNonFinalArgs = false; if (call.Arguments != null) { foreach (var arg in call.Arguments) { callArguments.Add(E(arg)); } } #region If explicit template type args were given, try to associate them with each overload if (tix != null) { var args = TemplateInstanceHandler.PreResolveTemplateArgs(tix, ctxt, out hasNonFinalArgs); var deducedOverloads = TemplateInstanceHandler.DeduceParamsAndFilterOverloads(methodOverloads, args, true, ctxt, hasNonFinalArgs); methodOverloads.Clear(); if (deducedOverloads != null) { methodOverloads.AddRange(deducedOverloads); } } #endregion #region Filter by parameter-argument comparison var argTypeFilteredOverloads = new List <AbstractType>(); bool hasHandledUfcsResultBefore = false; foreach (var ov in methodOverloads) { if (ov is MemberSymbol) { var ms = ov as MemberSymbol; var dm = ms.Definition as DMethod; if (dm != null) { // In the case of an ufcs, insert the first argument into the CallArguments list if (ms.IsUFCSResult && !hasHandledUfcsResultBefore) { callArguments.Insert(0, eval ? baseValue as ISemantic : ((MemberSymbol)baseExpression[0]).FirstArgument); hasHandledUfcsResultBefore = true; } else if (!ms.IsUFCSResult && hasHandledUfcsResultBefore) // In the rare case of having a ufcs result occuring _after_ a normal member result, remove the initial arg again { callArguments.RemoveAt(0); hasHandledUfcsResultBefore = false; } var deducedTypeDict = new DeducedTypeDictionary(ms); if (dm.TemplateParameters != null) { foreach (var tpar in dm.TemplateParameters) { if (!deducedTypeDict.ContainsKey(tpar.NameHash)) { deducedTypeDict[tpar.NameHash] = null; } } } var templateParamDeduction = new TemplateParameterDeduction(deducedTypeDict, ctxt); int currentArg = 0; bool add = true; if (callArguments.Count > 0 || dm.Parameters.Count > 0) { for (int i = 0; i < dm.Parameters.Count; i++) { var paramType = dm.Parameters[i].Type; // Handle the usage of tuples: Tuples may only be used as as-is, so not as an array, pointer or in a modified way.. if (paramType is IdentifierDeclaration && TryHandleMethodArgumentTuple(ref add, callArguments, dm, deducedTypeDict, i, ref currentArg)) { continue; } else if (currentArg < callArguments.Count) { if (!templateParamDeduction.HandleDecl(null, paramType, callArguments[currentArg++])) { add = false; break; } } else { // If there are more parameters than arguments given, check if the param has default values if (!(dm.Parameters[i] is DVariable) || (dm.Parameters[i] as DVariable).Initializer == null) { add = false; break; } // Assume that all further method parameters do have default values - and don't check further parameters break; } } } // If type params were unassigned, try to take the defaults if (add && dm.TemplateParameters != null) { foreach (var tpar in dm.TemplateParameters) { if (deducedTypeDict[tpar.NameHash] == null) { add = templateParamDeduction.Handle(tpar, null); if (!add) { if (hasNonFinalArgs) { deducedTypeDict[tpar.NameHash] = new TemplateParameterSymbol(tpar, null); add = true; } else { break; } } } } } if (add && (deducedTypeDict.AllParamatersSatisfied || hasNonFinalArgs)) { ms.DeducedTypes = deducedTypeDict.ToReadonly(); ctxt.CurrentContext.IntroduceTemplateParameterTypes(ms); var bt = ms.Base ?? TypeDeclarationResolver.GetMethodReturnType(dm, ctxt); ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals(ms); if (eval || !returnBaseTypeOnly) { argTypeFilteredOverloads.Add(ms.Base == null ? new MemberSymbol(dm, bt, ms.DeclarationOrExpressionBase, ms.DeducedTypes) : ms); } else { argTypeFilteredOverloads.Add(bt); } } } } else if (ov is DelegateType) { var dg = (DelegateType)ov; var bt = TypeDeclarationResolver.GetMethodReturnType(dg, ctxt); //TODO: Param-Arg check if (!eval || returnBaseTypeOnly) { argTypeFilteredOverloads.Add(bt); } else { argTypeFilteredOverloads.Add(new DelegateType(bt, dg.DeclarationOrExpressionBase as FunctionLiteral, dg.Parameters)); } } } #endregion if (eval) { // Convert ISemantic[] to ISymbolValue[] var args = new List <ISymbolValue>(callArguments.Count); foreach (var a in callArguments) { args.Add(a as ISymbolValue); } // Execute/Evaluate the variable contents etc. return(TryDoCTFEOrGetValueRefs(argTypeFilteredOverloads.ToArray(), call.PostfixForeExpression, true, args.ToArray())); } else { // Check if one overload remains and return that one. ctxt.CheckForSingleResult(argTypeFilteredOverloads.ToArray(), call); return(argTypeFilteredOverloads.Count != 0 ? argTypeFilteredOverloads[0] : null); } }
ISemantic E(PostfixExpression_MethodCall call, bool returnBaseTypeOnly = true) { // Deduce template parameters later on AbstractType[] baseExpression = null; ISymbolValue baseValue = null; TemplateInstanceExpression tix = null; bool isUFCSFunction = false; GetRawCallOverloads(call, out baseExpression, out baseValue, out tix, out isUFCSFunction); var methodOverloads = new List <AbstractType>(); #region Search possible methods, opCalls or delegates that could be called bool requireStaticItems = true; //TODO: What if there's an opCall and a foreign method at the same time? - and then this variable would be bullshit IEnumerable <AbstractType> scanResults = DResolver.StripAliasSymbols(baseExpression); var nextResults = new List <AbstractType>(); while (scanResults != null) { foreach (var b in scanResults) { if (b is MemberSymbol) { var mr = (MemberSymbol)b; if (mr.Definition is DMethod) { methodOverloads.Add(mr); continue; } else if (mr.Definition is DVariable) { // If we've got a variable here, get its base type/value reference if (eval) { var dgVal = ValueProvider[(DVariable)mr.Definition] as DelegateValue; if (dgVal != null) { nextResults.Add(dgVal.Definition); continue; } else { throw new EvaluationException(call, "Variable must be a delegate, not anything else", mr); } } else { var bt = DResolver.StripAliasSymbol(mr.Base ?? TypeDeclarationResolver.ResolveSingle(mr.Definition.Type, ctxt)); // Must be of type delegate if (bt is DelegateType) { //TODO: Ensure that there's no further overload - inform the user elsewise if (returnBaseTypeOnly) { return(bt); } else { return(new MemberSymbol(mr.Definition, bt, mr.DeclarationOrExpressionBase)); } } else { /* * If mr.Node is not a method, so e.g. if it's a variable * pointing to a delegate * * class Foo * { * string opCall() { return "asdf"; } * } * * Foo f=new Foo(); * f(); -- calls opCall, opCall is not static */ nextResults.Add(bt); requireStaticItems = false; } //TODO: Can other types work as function/are callable? } } } else if (b is DelegateType) { var dg = (DelegateType)b; /* * int a = delegate(x) { return x*2; } (12); // a is 24 after execution * auto dg=delegate(x) {return x*3;}; * int b = dg(4); */ if (dg.IsFunctionLiteral) { methodOverloads.Add(dg); } else { // If it's just wanted to pass back the delegate's return type, skip the remaining parts of this method. if (eval) { throw new EvaluationException(call, "TODO", dg); } //TODO //if(returnBaseTypeOnly) //TODO: Check for multiple definitions. Also, make a parameter-argument check to inform the user about wrong arguments. return(dg); } } else if (b is ClassType) { /* * auto a = MyStruct(); -- opCall-Overloads can be used */ var classDef = ((ClassType)b).Definition; if (classDef == null) { continue; } foreach (var i in classDef) { if (i.Name == "opCall" && i is DMethod && (!requireStaticItems || (i as DNode).IsStatic)) { methodOverloads.Add(TypeDeclarationResolver.HandleNodeMatch(i, ctxt, b, call) as MemberSymbol); } } } /* * Every struct can contain a default ctor: * * struct S { int a; bool b; } * * auto s = S(1,true); -- ok * auto s2= new S(2,false); -- error, no constructor found! */ else if (b is StructType && methodOverloads.Count == 0) { //TODO: Deduce parameters return(b); } /* * If the overload is a template, it quite exclusively means that we'll handle a method that is the only * child inside a template + that is named as the template. */ else if (b is TemplateType && ImplicitTemplateProperties.ContainsEquallyNamedChildrenOnly(((TemplateType)b).Definition)) { methodOverloads.Add(b); } } scanResults = nextResults.Count == 0 ? null : nextResults.ToArray(); nextResults.Clear(); } #endregion if (methodOverloads.Count == 0) { return(null); } // Get all arguments' types var callArguments = new List <ISemantic>(); // If it's sure that we got a ufcs call here, add the base expression's type as first argument type if (isUFCSFunction) { callArguments.Add(eval ? (ISemantic)baseValue : ((MemberSymbol)baseExpression[0]).Base); } if (call.Arguments != null) { foreach (var arg in call.Arguments) { callArguments.Add(E(arg)); } } #region Deduce template parameters and filter out unmatching overloads // First add optionally given template params // http://dlang.org/template.html#function-templates var tplParamDeductionArguments = tix == null ? new List <ISemantic>() : TemplateInstanceHandler.PreResolveTemplateArgs(tix, ctxt); // Then add the arguments[' member types] foreach (var arg in callArguments) { if (arg is VariableValue) { tplParamDeductionArguments.Add(ValueProvider[((VariableValue)arg).Variable]); } else if (arg is AbstractType) { tplParamDeductionArguments.Add(DResolver.StripMemberSymbols((AbstractType)arg)); } else { tplParamDeductionArguments.Add(arg); } } var templateParamFilteredOverloads = TemplateInstanceHandler.DeduceParamsAndFilterOverloads( methodOverloads, tplParamDeductionArguments.Count > 0 ? tplParamDeductionArguments.ToArray() : null, true, ctxt); #endregion #region Filter by parameter-argument comparison var argTypeFilteredOverloads = new List <AbstractType>(); if (templateParamFilteredOverloads != null) { foreach (var ov in templateParamFilteredOverloads) { if (ov is MemberSymbol) { var ms = (MemberSymbol)ov; var dm = ms.Definition as DMethod; bool add = false; if (dm != null) { ctxt.CurrentContext.IntroduceTemplateParameterTypes(ms); add = false; if (callArguments.Count == 0 && dm.Parameters.Count == 0) { add = true; } else { for (int i = 0; i < dm.Parameters.Count; i++) { var paramType = TypeDeclarationResolver.ResolveSingle(dm.Parameters[i].Type, ctxt); // TODO: Expression tuples & variable argument lengths if (i >= callArguments.Count || !ResultComparer.IsImplicitlyConvertible(callArguments[i], paramType, ctxt)) { continue; } add = true; } } if (add) { var bt = ms.Base ?? TypeDeclarationResolver.GetMethodReturnType(dm, ctxt); if (returnBaseTypeOnly) { argTypeFilteredOverloads.Add(bt); } else { argTypeFilteredOverloads.Add(ms.Base == null ? new MemberSymbol(dm, bt, ms.DeclarationOrExpressionBase, ms.DeducedTypes) : ms); } } ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals(ms); } } else if (ov is DelegateType) { var dg = (DelegateType)ov; var bt = TypeDeclarationResolver.GetMethodReturnType(dg, ctxt); //TODO: Param-Arg check if (returnBaseTypeOnly) { argTypeFilteredOverloads.Add(bt); } else { argTypeFilteredOverloads.Add(new DelegateType(bt, dg.DeclarationOrExpressionBase as FunctionLiteral, dg.Parameters)); } } } } #endregion if (eval) { // Convert ISemantic[] to ISymbolValue[] var args = new List <ISymbolValue>(callArguments.Count); foreach (var a in callArguments) { args.Add(a as ISymbolValue); } // Execute/Evaluate the variable contents etc. return(TryDoCTFEOrGetValueRefs(argTypeFilteredOverloads.ToArray(), call.PostfixForeExpression, true, args.ToArray())); } else { // Check if one overload remains and return that one. ctxt.CheckForSingleResult(argTypeFilteredOverloads.ToArray(), call); return(argTypeFilteredOverloads != null && argTypeFilteredOverloads.Count != 0 ? argTypeFilteredOverloads[0] : null); } }
public static List <AbstractType> EvalMethodCall(AbstractType[] baseExpression, ISymbolValue baseValue, TemplateInstanceExpression tix, ResolutionContext ctxt, PostfixExpression_MethodCall call, out List <ISemantic> callArguments, out ISymbolValue delegateValue, bool returnBaseTypeOnly, AbstractSymbolValueProvider ValueProvider = null) { //TODO: Refactor this crap! delegateValue = null; callArguments = null; var methodOverloads = new List <AbstractType>(); #region Search possible methods, opCalls or delegates that could be called bool requireStaticItems = true; //TODO: What if there's an opCall and a foreign method at the same time? - and then this variable would be bullshit IEnumerable <AbstractType> scanResults = DResolver.StripAliasSymbols(baseExpression); var nextResults = new List <AbstractType>(); while (scanResults != null) { foreach (var b in scanResults) { if (b is TemplateParameterSymbol) { nextResults.Add((b as TemplateParameterSymbol).Base); } else if (b is MemberSymbol) { var mr = (MemberSymbol)b; if (mr.Definition is DMethod) { methodOverloads.Add(mr); continue; } else if (mr.Definition is DVariable) { // If we've got a variable here, get its base type/value reference if (ValueProvider != null) { var dgVal = ValueProvider[(DVariable)mr.Definition] as DelegateValue; if (dgVal != null) { nextResults.Add(dgVal.Definition); continue; } else { ValueProvider.LogError(call, "Variable must be a delegate, not anything else"); return(null); } } else { var bt = DResolver.StripAliasSymbol(mr.Base ?? TypeDeclarationResolver.ResolveSingle(mr.Definition.Type, ctxt)); // Must be of type delegate if (bt is DelegateType) { var ret = HandleCallDelegateType(ValueProvider, bt as DelegateType, methodOverloads, returnBaseTypeOnly); if (ret is ISymbolValue) { delegateValue = ret as ISymbolValue; return(null); } else if (ret is AbstractType) { return new List <AbstractType> { ret as AbstractType } } ; } else { /* * If mr.Node is not a method, so e.g. if it's a variable * pointing to a delegate * * class Foo * { * string opCall() { return "asdf"; } * } * * Foo f=new Foo(); * f(); -- calls opCall, opCall is not static */ nextResults.Add(bt); requireStaticItems = false; } //TODO: Can other types work as function/are callable? } } } else if (b is DelegateType) { var ret = HandleCallDelegateType(ValueProvider, b as DelegateType, methodOverloads, returnBaseTypeOnly); if (ret is ISymbolValue) { delegateValue = ret as ISymbolValue; return(null); } else if (ret is AbstractType) { return new List <AbstractType> { ret as AbstractType } } ; } else if (b is ClassType || b is StructType) { var tit = (TemplateIntermediateType)b; /* * auto a = MyStruct(); -- opCall-Overloads can be used */ var classDef = tit.Definition; if (classDef == null) { continue; } foreach (var i in ExpressionTypeEvaluation.GetOpCalls(tit, requireStaticItems)) { methodOverloads.Add(TypeDeclarationResolver.HandleNodeMatch(i, ctxt, b, call) as MemberSymbol); } /* * Every struct can contain a default ctor: * * struct S { int a; bool b; } * * auto s = S(1,true); -- ok * auto s2= new S(2,false); -- error, no constructor found! */ if (b is StructType && methodOverloads.Count == 0) { //TODO: Deduce parameters return(new List <AbstractType> { b }); } } /* * If the overload is a template, it quite exclusively means that we'll handle a method that is the only * child inside a template + that is named as the template. */ else if (b is TemplateType) { methodOverloads.Add(b); } } scanResults = nextResults.Count == 0 ? null : nextResults.ToArray(); nextResults.Clear(); } #endregion if (methodOverloads.Count == 0) { return(null); } // Get all arguments' types callArguments = new List <ISemantic>(); bool hasNonFinalArgs = false; if (call.Arguments != null) { if (ValueProvider != null) { foreach (var arg in call.Arguments) { callArguments.Add(arg != null ? Evaluation.EvaluateValue(arg, ValueProvider) : null); } } else { foreach (var arg in call.Arguments) { callArguments.Add(arg != null ? ExpressionTypeEvaluation.EvaluateType(arg, ctxt) : null); } } } #region If explicit template type args were given, try to associate them with each overload if (tix != null) { var args = TemplateInstanceHandler.PreResolveTemplateArgs(tix, ctxt, out hasNonFinalArgs); var deducedOverloads = TemplateInstanceHandler.DeduceParamsAndFilterOverloads(methodOverloads, args, true, ctxt, hasNonFinalArgs); methodOverloads.Clear(); if (deducedOverloads != null) { methodOverloads.AddRange(deducedOverloads); } } #endregion #region Filter by parameter-argument comparison var argTypeFilteredOverloads = new List <AbstractType>(); bool hasHandledUfcsResultBefore = false; foreach (var ov in methodOverloads) { if (ov is MemberSymbol) { HandleDMethodOverload(ctxt, ValueProvider != null, baseValue, callArguments, returnBaseTypeOnly, hasNonFinalArgs, argTypeFilteredOverloads, ref hasHandledUfcsResultBefore, ov as MemberSymbol); } else if (ov is DelegateType) { var dg = ov as DelegateType; var bt = dg.Base ?? TypeDeclarationResolver.GetMethodReturnType(dg, ctxt); //TODO: Param-Arg check if (returnBaseTypeOnly) { argTypeFilteredOverloads.Add(bt); } else { if (dg.Base == null) { if (dg.IsFunctionLiteral) { dg = new DelegateType(bt, dg.DeclarationOrExpressionBase as FunctionLiteral, dg.Parameters); } else { dg = new DelegateType(bt, dg.DeclarationOrExpressionBase as DelegateDeclaration, dg.Parameters); } } argTypeFilteredOverloads.Add(new DelegateCallSymbol(dg, call)); } } } #endregion return(argTypeFilteredOverloads); }
/// <summary> /// Checks results for implicit type convertability /// </summary> public static bool IsImplicitlyConvertible(ISemantic resultToCheck, AbstractType targetType, ResolverContextStack ctxt = null) { var resToCheck = AbstractType.Get(resultToCheck); // Initially remove aliases from results var _r = DResolver.StripMemberSymbols(resToCheck); if (_r == null) { return(IsEqual(resToCheck, targetType)); } resToCheck = _r; targetType = DResolver.StripAliasSymbol(targetType); if (targetType is DSymbol) { var tpn = ((DSymbol)targetType).Definition as TemplateParameterNode; if (tpn != null) { var par = tpn.Parent as DNode; if (par != null && par.TemplateParameters != null) { var dedParam = new DeducedTypeDictionary { ParameterOwner = par }; foreach (var tp in par.TemplateParameters) { dedParam[tp.Name] = null; } return(new TemplateParameterDeduction(dedParam, ctxt).Handle(tpn.TemplateParameter, resToCheck)); } } } _r = DResolver.StripMemberSymbols(targetType); if (_r == null) { return(false); } targetType = _r; if (resToCheck is PrimitiveType && targetType is PrimitiveType) { var sr1 = (PrimitiveType)resToCheck; var sr2 = (PrimitiveType)targetType; if (sr1.TypeToken == sr2.TypeToken && sr1.Modifier == sr2.Modifier) { return(true); } switch (sr2.TypeToken) { case DTokens.Int: return(sr1.TypeToken == DTokens.Uint); case DTokens.Uint: return(sr1.TypeToken == DTokens.Int); //TODO: Further types that can be converted into each other implicitly } } else if (resToCheck is UserDefinedType && targetType is UserDefinedType) { return(IsImplicitlyConvertible((UserDefinedType)resToCheck, (UserDefinedType)targetType)); } else if (resToCheck is DelegateType && targetType is DelegateType) { //TODO } else if (resToCheck is ArrayType && targetType is ArrayType) { var ar1 = (ArrayType)resToCheck; var ar2 = (ArrayType)targetType; // Key as well as value types must be matching! var ar1_n = ar1.KeyType == null; var ar2_n = ar2.KeyType == null; if (ar1_n != ar2_n) { return(false); } if (ar1_n || IsImplicitlyConvertible(ar1.KeyType, ar2.KeyType, ctxt)) { return(IsImplicitlyConvertible(ar1.Base, ar2.Base, ctxt)); } } else if (resToCheck is TypeTuple && targetType is TypeTuple) { return(true); } else if (resToCheck is ExpressionTuple && targetType is ExpressionTuple) { return(true); } /*else if (resultToCheck is ExpressionValueResult && targetType is ExpressionValue) * { * return ((ExpressionValueResult)resultToCheck).Value.Equals(((ExpressionValueResult)targetType).Value); * }*/ // http://dlang.org/type.html //TODO: Pointer to non-pointer / vice-versa checkability? -- Can it really be done implicitly? return(false); }
/// <summary> /// Checks results for implicit type convertability /// </summary> public static bool IsImplicitlyConvertible(ISemantic resultToCheck, AbstractType targetType, ResolutionContext ctxt = null) { var resToCheck = AbstractType.Get(resultToCheck); bool isVariable = resToCheck is MemberSymbol; // Initially remove aliases from results var _r = DResolver.StripMemberSymbols(resToCheck); if (_r == null) { return(IsEqual(resToCheck, targetType)); } resToCheck = _r; targetType = DResolver.StripAliasSymbol(targetType); if (targetType is DSymbol) { var tpn = ((DSymbol)targetType).Definition as TemplateParameter.Node; if (tpn != null) { var par = tpn.Parent as DNode; if (par != null && par.TemplateParameters != null) { var dedParam = new DeducedTypeDictionary(par); return(new TemplateParameterDeduction(dedParam, ctxt).Handle(tpn.TemplateParameter, resToCheck)); } } } _r = DResolver.StripMemberSymbols(targetType); if (_r == null) { return(false); } targetType = _r; if (resToCheck is PrimitiveType && targetType is PrimitiveType) { var sr1 = (PrimitiveType)resToCheck; var sr2 = (PrimitiveType)targetType; if (sr1.TypeToken == sr2.TypeToken /*&& sr1.Modifier == sr2.Modifier*/) { return(true); } return(ImplicitConvertabilityTable.Contains((sr2.TypeToken << 8) + sr1.TypeToken)); } else if (resToCheck is UserDefinedType && targetType is UserDefinedType) { return(IsImplicitlyConvertible((UserDefinedType)resToCheck, (UserDefinedType)targetType)); } else if (resToCheck is DelegateType && targetType is DelegateType) { return(IsEqual(resToCheck, targetType)); //TODO: Can non-equal delegates be converted into each other? } else if (resToCheck is ArrayType && targetType is ArrayType) { var ar1 = (ArrayType)resToCheck; var ar2 = (ArrayType)targetType; // Key as well as value types must be matching! var ar1_n = ar1.KeyType == null; var ar2_n = ar2.KeyType == null; if (ar1_n != ar2_n) { return(false); } if (ar1_n || IsImplicitlyConvertible(ar1.KeyType, ar2.KeyType, ctxt)) { return(IsImplicitlyConvertible(ar1.Base, ar2.Base, ctxt)); } } else if (resToCheck is DSymbol && targetType is DSymbol) { var r1 = resToCheck as DSymbol; var r2 = targetType as DSymbol; if (r1.Definition == r2.Definition) { //TODO: Compare template param deductions return(true); } } else if (resToCheck is DTuple && targetType is DTuple) { var tup1 = resToCheck as DTuple; var tup2 = resToCheck as DTuple; //TODO return(true); } /*else if (resultToCheck is ExpressionValueResult && targetType is ExpressionValue) * { * return ((ExpressionValueResult)resultToCheck).Value.Equals(((ExpressionValueResult)targetType).Value); * }*/ // http://dlang.org/type.html //TODO: Pointer to non-pointer / vice-versa checkability? -- Can it really be done implicitly? else if (!isVariable && resToCheck is ArrayType && targetType is PointerType && ((targetType = (targetType as PointerType).Base) is PrimitiveType) && DTokens.IsBasicType_Character((targetType as PrimitiveType).TypeToken)) { return((resultToCheck as ArrayType).IsString); } return(false); }
/// <summary> /// Tries to resolve a static property's name. /// Returns a result describing the theoretical member (".init"-%gt;MemberResult; ".typeof"->TypeResult etc). /// Returns null if nothing was found. /// </summary> /// <param name="InitialResult"></param> /// <returns></returns> public static MemberSymbol TryResolveStaticProperties( ISemantic InitialResult, string propertyIdentifier, ResolverContextStack ctxt = null, bool Evaluate = false, IdentifierDeclaration idContainter = null) { // If a pointer'ed type is given, take its base type if (InitialResult is PointerType) { InitialResult = ((PointerType)InitialResult).Base; } if (InitialResult == null || InitialResult is ModuleSymbol) { return(null); } INode relatedNode = null; if (InitialResult is DSymbol) { relatedNode = ((DSymbol)InitialResult).Definition; } #region init if (propertyIdentifier == "init") { var prop_Init = new DVariable { Name = "init", Description = "Initializer" }; if (relatedNode != null) { if (!(relatedNode is DVariable)) { prop_Init.Parent = relatedNode.Parent; prop_Init.Type = new IdentifierDeclaration(relatedNode.Name); } else { prop_Init.Parent = relatedNode; prop_Init.Initializer = (relatedNode as DVariable).Initializer; prop_Init.Type = relatedNode.Type; } } return(new MemberSymbol(prop_Init, DResolver.StripAliasSymbol(AbstractType.Get(InitialResult)), idContainter)); } #endregion #region sizeof if (propertyIdentifier == "sizeof") { return(new MemberSymbol(new DVariable { Name = "sizeof", Type = new DTokenDeclaration(DTokens.Int), Initializer = new IdentifierExpression(4), Description = "Size in bytes (equivalent to C's sizeof(type))" }, new PrimitiveType(DTokens.Int), idContainter)); } #endregion #region alignof if (propertyIdentifier == "alignof") { return(new MemberSymbol(new DVariable { Name = "alignof", Type = new DTokenDeclaration(DTokens.Int), Description = "Alignment size" }, new PrimitiveType(DTokens.Int), idContainter)); } #endregion #region mangleof if (propertyIdentifier == "mangleof") { return(new MemberSymbol(new DVariable { Name = "mangleof", Type = new IdentifierDeclaration("string"), Description = "String representing the ‘mangled’ representation of the type" }, getStringType(ctxt), idContainter)); } #endregion #region stringof if (propertyIdentifier == "stringof") { return(new MemberSymbol(new DVariable { Name = "stringof", Type = new IdentifierDeclaration("string"), Description = "String representing the source representation of the type" }, getStringType(ctxt), idContainter)); } #endregion #region classinfo else if (propertyIdentifier == "classinfo") { var tr = DResolver.StripMemberSymbols(AbstractType.Get(InitialResult)) as TemplateIntermediateType; if (tr is ClassType || tr is InterfaceType) { var ci = new IdentifierDeclaration("TypeInfo_Class") { InnerDeclaration = new IdentifierDeclaration("object"), ExpressesVariableAccess = true, }; var ti = TypeDeclarationResolver.Resolve(ci, ctxt); ctxt.CheckForSingleResult(ti, ci); return(new MemberSymbol(new DVariable { Name = "classinfo", Type = ci }, ti != null && ti.Length != 0?ti[0]:null, idContainter)); } } #endregion //TODO: Resolve the types of type-specific properties (floats, ints, arrays, assocarrays etc.) return(null); }