/// <summary> /// Returns all constructors from the given class or struct. /// If no explicit constructor given, an artificial implicit constructor method stub will be created. /// </summary> public static IEnumerable <DMethod> GetConstructors(TemplateIntermediateType ct) { bool foundExplicitCtor = false; // Simply get all constructors that have the ctor id assigned. Makin' it faster ;) var ch = ct.Definition[DMethod.ConstructorIdentifier]; if (ch != null) { foreach (var m in ch) { // Not to forget: 'this' aliases are also possible - so keep checking for m being a genuine ctor var dm = m as DMethod; if (m != null && dm.SpecialType == DMethod.MethodType.Constructor) { yield return(dm); foundExplicitCtor = true; } } } if (!foundExplicitCtor) { yield return new DMethod(DMethod.MethodType.Constructor) { Name = DMethod.ConstructorIdentifier, Parent = ct.Definition, Description = "Default constructor for " + ct.Name } } ; } ISemantic E(CastExpression ce) { AbstractType castedType = null; if (ce.Type != null) { var castedTypes = TypeDeclarationResolver.Resolve(ce.Type, ctxt); ctxt.CheckForSingleResult(castedTypes, ce.Type); if (castedTypes != null && castedTypes.Length != 0) { castedType = castedTypes[0]; } } else { castedType = AbstractType.Get(E(ce.UnaryExpression)); if (castedType != null && ce.CastParamTokens != null && ce.CastParamTokens.Length > 0) { //TODO: Wrap resolved type with member function attributes } } return(castedType); } ISemantic E(UnaryExpression_Cat x) // a = ~b; { return(E(x.UnaryExpression)); } ISemantic E(UnaryExpression_Increment x) { return(E(x.UnaryExpression)); } ISemantic E(UnaryExpression_Decrement x) { return(E(x.UnaryExpression)); } ISemantic E(UnaryExpression_Add x) { return(E(x.UnaryExpression)); } ISemantic E(UnaryExpression_Sub x) { var v = E(x.UnaryExpression); if (eval) { if (v is AbstractType) { v = DResolver.StripMemberSymbols((AbstractType)v); } if (v is PrimitiveValue) { var pv = (PrimitiveValue)v; return(new PrimitiveValue(pv.BaseTypeToken, -pv.Value, x, -pv.ImaginaryPart)); } } return(v); } ISemantic E(UnaryExpression_Not x) { return(E(x.UnaryExpression)); } ISemantic E(UnaryExpression_Mul x) { return(E(x.UnaryExpression)); } ISemantic E(UnaryExpression_And x) { var ptrBase = E(x.UnaryExpression); if (eval) { // Create a new pointer // } // &i -- makes an int* out of an int return(new PointerType(AbstractType.Get(ptrBase), x)); } ISemantic E(DeleteExpression x) { if (eval) { // Reset the content of the variable } return(null); } ISemantic E(UnaryExpression_Type x) { var uat = x as UnaryExpression_Type; if (uat.Type == null) { return(null); } var types = TypeDeclarationResolver.Resolve(uat.Type, ctxt); ctxt.CheckForSingleResult(types, uat.Type); if (types != null && types.Length != 0) { var id = new IdentifierDeclaration(uat.AccessIdentifier) { EndLocation = uat.EndLocation }; // First off, try to resolve static properties var statProp = StaticPropertyResolver.TryResolveStaticProperties(types[0], uat.AccessIdentifier, ctxt, eval, id); if (statProp != null) { return(statProp); } // If it's not the case, try the conservative way var res = TypeDeclarationResolver.Resolve(id, ctxt, types); ctxt.CheckForSingleResult(res, x); if (res != null && res.Length != 0) { return(res[0]); } } return(null); } }
/// <summary> /// Returns either all unfiltered and undeduced overloads of a member of a base type/value (like b from type a if the expression is a.b). /// if <param name="EvalAndFilterOverloads"></param> is false. /// If true, all overloads will be deduced, filtered and evaluated, so that (in most cases,) a one-item large array gets returned /// which stores the return value of the property function b that is executed without arguments. /// Also handles UFCS - so if filtering is wanted, the function becom /// </summary> ISemantic[] E(PostfixExpression_Access acc, out bool IsUFCS, ISemantic resultBase = null, bool EvalAndFilterOverloads = true) { IsUFCS = false; if (acc == null) { return(null); } var baseExpression = resultBase ?? E(acc.PostfixForeExpression); if (acc.AccessExpression is NewExpression) { /* * This can be both a normal new-Expression as well as an anonymous class declaration! */ //TODO! return(null); } /* * Try to get ufcs functions at first! * * void foo(int i) {} * * class A * { * void foo(int i, int a) {} * * void bar(){ * 123.foo(23); // Not allowed! * // Anyway, if we tried to search ufcs functions AFTER searching from child to parent scope levels, * // it would return the local foo() only, not the global one..which would be an error then! * } * * Probably also worth to notice is the property syntax..are property functions rather preferred than ufcs ones? * } */ var overloads = UFCSResolver.TryResolveUFCS(baseExpression, acc, ctxt) as AbstractType[]; if (overloads == null) { if (acc.AccessExpression is TemplateInstanceExpression) { var tix = (TemplateInstanceExpression)acc.AccessExpression; // Do not deduce and filter if superior expression is a method call since call arguments' types also count as template arguments! overloads = GetOverloads(tix, resultBase == null ? null : new[] { AbstractType.Get(resultBase) }, EvalAndFilterOverloads); } else if (acc.AccessExpression is IdentifierExpression) { var id = ((IdentifierExpression)acc.AccessExpression).Value as string; overloads = TypeDeclarationResolver.ResolveFurtherTypeIdentifier(id, new[] { AbstractType.Get(baseExpression) }, ctxt, acc.AccessExpression); // Might be a static property if (overloads == null) { var staticTypeProperty = StaticPropertyResolver.TryResolveStaticProperties(AbstractType.Get(baseExpression), id, ctxt); if (staticTypeProperty != null) { return new[] { staticTypeProperty } } ; } } else { if (eval) { throw new EvaluationException(acc, "Invalid access expression"); } ctxt.LogError(acc, "Invalid post-dot expression"); return(null); } } else { IsUFCS = true; } // If evaluation active and the access expression is stand-alone, return a single item only. if (EvalAndFilterOverloads && eval) { return new[] { TryDoCTFEOrGetValueRefs(overloads, acc.AccessExpression) } } ; return(overloads); } ISemantic E(PostfixExpression_Index x, ISemantic foreExpression) { if (eval) { //TODO: Access pointer arrays(?) if (foreExpression is ArrayValue) // ArrayValue must be checked first due to inheritance! { var av = foreExpression as ArrayValue; // Make $ operand available var arrLen_Backup = ValueProvider.CurrentArrayLength; ValueProvider.CurrentArrayLength = av.Elements.Length; var n = E(x.Arguments[0]) as PrimitiveValue; ValueProvider.CurrentArrayLength = arrLen_Backup; if (n == null) { throw new EvaluationException(x.Arguments[0], "Returned no value"); } int i = 0; try { i = Convert.ToInt32(n.Value); } catch { throw new EvaluationException(x.Arguments[0], "Index expression must be of type int"); } if (i < 0 || i > av.Elements.Length) { throw new EvaluationException(x.Arguments[0], "Index out of range - it must be between 0 and " + av.Elements.Length); } return(av.Elements[i]); } else if (foreExpression is AssociativeArrayValue) { var aa = (AssociativeArrayValue)foreExpression; var key = E(x.Arguments[0]); if (key == null) { throw new EvaluationException(x.Arguments[0], "Returned no value"); } ISymbolValue val = null; foreach (var kv in aa.Elements) { if (kv.Key.Equals(key)) { return(kv.Value); } } throw new EvaluationException(x, "Could not find key '" + val + "'"); } throw new EvaluationException(x.PostfixForeExpression, "Invalid index expression base value type", foreExpression); } else { if (foreExpression is AssocArrayType) { var ar = (AssocArrayType)foreExpression; /* * myType_Array[0] -- returns TypeResult myType * return the value type of a given array result */ //TODO: Handle opIndex overloads return(ar.ValueType); } /* * int* a = new int[10]; * * a[0] = 12; */ else if (foreExpression is PointerType) { return(((PointerType)foreExpression).Base); } ctxt.LogError(new ResolutionError(x, "Invalid base type for index expression")); } return(null); } ISemantic E(PostfixExpression_Slice x, ISemantic foreExpression) { if (!eval) { return(foreExpression); // Still of the array's type. } if (!(foreExpression is ArrayValue)) { throw new EvaluationException(x.PostfixForeExpression, "Must be an array"); } var ar = (ArrayValue)foreExpression; var sl = (PostfixExpression_Slice)x; // If the [ ] form is used, the slice is of the entire array. if (sl.FromExpression == null && sl.ToExpression == null) { return(foreExpression); } // Make $ operand available var arrLen_Backup = ValueProvider.CurrentArrayLength; ValueProvider.CurrentArrayLength = ar.Elements.Length; var bound_lower = E(sl.FromExpression) as PrimitiveValue; var bound_upper = E(sl.ToExpression) as PrimitiveValue; ValueProvider.CurrentArrayLength = arrLen_Backup; if (bound_lower == null || bound_upper == null) { throw new EvaluationException(bound_lower == null ? sl.FromExpression : sl.ToExpression, "Must be of an integral type"); } int lower = -1, upper = -1; try { lower = Convert.ToInt32(bound_lower.Value); upper = Convert.ToInt32(bound_upper.Value); } catch { throw new EvaluationException(lower != -1 ? sl.FromExpression : sl.ToExpression, "Boundary expression must base an integral type"); } if (lower < 0) { throw new EvaluationException(sl.FromExpression, "Lower boundary must be greater than 0"); } if (lower >= ar.Elements.Length) { throw new EvaluationException(sl.FromExpression, "Lower boundary must be smaller than " + ar.Elements.Length); } if (upper < lower) { throw new EvaluationException(sl.ToExpression, "Upper boundary must be greater than " + lower); } if (upper >= ar.Elements.Length) { throw new EvaluationException(sl.ToExpression, "Upper boundary must be smaller than " + ar.Elements.Length); } var rawArraySlice = new ISymbolValue[upper - lower]; int j = 0; for (int i = lower; i < upper; i++) { rawArraySlice[j++] = ar.Elements[i]; } return(new ArrayValue(ar.RepresentedType as ArrayType, rawArraySlice)); } ISemantic E(PostfixExpression_Increment x, ISemantic foreExpression) { // myInt++ is still of type 'int' if (!eval) { return(foreExpression); } if (resolveConstOnly) { throw new NoConstException(x); } // Must be implemented anyway regarding ctfe return(null); } ISemantic E(PostfixExpression_Decrement x, ISemantic foreExpression) { if (!eval) { return(foreExpression); } if (resolveConstOnly) { throw new NoConstException(x); } // Must be implemented anyway regarding ctfe return(null); } } }