/// <summary> /// Returns false if the item has already been set before and if the already set item is not equal to 'r'. /// Inserts 'r' into the target dictionary and returns true otherwise. /// </summary> bool Set(ITemplateParameter p, ISemantic r, string name = null) { if (string.IsNullOrEmpty(name)) { name = p.Name; } TemplateParameterSymbol rl = null; if (!TargetDictionary.TryGetValue(name, out rl) || rl == null) { TargetDictionary[name] = new TemplateParameterSymbol(p, r, null, TargetDictionary.ParameterOwner); return(true); } else { if (rl != null) { if (ResultComparer.IsEqual(rl.Base, r)) { return(true); } else { // Error: Ambiguous assignment } } TargetDictionary[name] = new TemplateParameterSymbol(p, r, null, TargetDictionary.ParameterOwner); return(false); } }
public long GetCustomerAndOrdersByEmp(int empID) { Stopwatch clock = new Stopwatch(); clock.Start(); List <Order> result; using (IDbConnection db = new SqlConnection(connString)) { result = db.Query <Order, Employee, Customer, Order>(Constants.GET_ENTIRE_ORDER, (order, employee, customer) => { order.Employee = employee; order.Customer = customer; return(order); }, new { EmployeeID = empID }, splitOn: "EmployeeID, CustomerID").ToList(); } clock.Stop(); var elapsedTime = clock.ElapsedMilliseconds; ResultComparer.GetCustomerAndOrdersByEmp(result, method); return(elapsedTime); }
protected void MaybeOnResultChanged(BindingResult<TResult> newResult) { if (!ResultComparer.Equals(newResult, Result)) { OnResultChanged(newResult); } }
public IEnumerable <DMethod> FindFitting(ResolverContextStack ctxt, CodeLocation currentLocation, ISemantic firstArgument, string nameFilter = null) { if (IsProcessing) { return(null); } var preMatchList = new List <DMethod>(); bool dontUseNameFilter = nameFilter == null; lock (CachedMethods) foreach (var kv in CachedMethods) { // First test if arg is matching the parameter if ((dontUseNameFilter || kv.Key.Name == nameFilter) && ResultComparer.IsImplicitlyConvertible(firstArgument, kv.Value, ctxt)) { preMatchList.Add(kv.Key); } } // Then filter out methods which cannot be accessed in the current context // (like when the method is defined in a module that has not been imported) var mv = new MatchFilterVisitor <DMethod>(ctxt, preMatchList); mv.IterateThroughScopeLayers(currentLocation); return(mv.filteredList); }
public long GetOrdersByCustomer(string id) { Stopwatch clock = new Stopwatch(); clock.Start(); List <Order> customerOrders; using (IDbConnection db = new SqlConnection(connString)) { customerOrders = db.Query <Order, Customer, Order>(Constants.GET_CUSTOMERS_ORDER, (order, customer) => { order.Customer = customer; return(order); }, new { CustomerID = id }, splitOn: "CustomerID").ToList(); } clock.Stop(); var elapsedTime = clock.ElapsedMilliseconds; ResultComparer.GetOrdersByCustomer(customerOrders, method); return(elapsedTime); }
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))); }
void HandleMethod(DMethod dm, MemberSymbol alreadyResolvedMethod = null) { if (dm != null && dm.Parameters.Count > 0 && dm.Parameters[0].Type != null) { var pop = ctxt.ScopedBlock != dm; if (pop) { ctxt.PushNewScope(dm); } var t = TypeDeclarationResolver.ResolveSingle(dm.Parameters [0].Type, ctxt); if (ResultComparer.IsImplicitlyConvertible(firstArgument, t, ctxt)) { var res = alreadyResolvedMethod ?? new MemberSymbol(dm, null, sr); res.Tag = new UfcsTag { firstArgument = firstArgument }; matches.Add(res); } if (pop) { ctxt.Pop(); } } }
/// <summary> /// Returns false if the item has already been set before and if the already set item is not equal to 'r'. /// Inserts 'r' into the target dictionary and returns true otherwise. /// </summary> bool Set(TemplateParameter p, ISemantic r, int nameHash) { if (p == null) { if (nameHash != 0 && TargetDictionary.ExpectedParameters != null) { foreach (var tpar in TargetDictionary.ExpectedParameters) { if (tpar.NameHash == nameHash) { p = tpar; break; } } } } if (p == null) { ctxt.LogError(null, "no fitting template parameter found!"); return(false); } // void call(T)(T t) {} // call(myA) -- T is *not* myA but A, so only assign myA's type to T. if (p is TemplateTypeParameter) { var newR = Resolver.TypeResolution.DResolver.StripMemberSymbols(AbstractType.Get(r)); if (newR != null) { r = newR; } } TemplateParameterSymbol rl; if (!TargetDictionary.TryGetValue(p, out rl) || rl == null) { TargetDictionary[p] = new TemplateParameterSymbol(p, r); return(true); } else { if (ResultComparer.IsEqual(rl.Base, r)) { TargetDictionary[p] = new TemplateParameterSymbol(p, r); return(true); } else if (rl == null) { TargetDictionary[p] = new TemplateParameterSymbol(p, r); } // Error: Ambiguous assignment return(false); } }
bool Handle(TemplateValueParameter p, ISemantic arg) { // Handle default arg case if (arg == null) { if (p.DefaultExpression != null) { var eval = Evaluation.EvaluateValue(p.DefaultExpression, ctxt); if (eval == null) { return(false); } return(Set(p, eval)); } else { return(false); } } var valueArgument = arg as ISymbolValue; // There must be a constant expression given! if (valueArgument == null) { return(false); } // Check for param type <-> arg expression type match var paramType = TypeDeclarationResolver.Resolve(p.Type, ctxt); if (paramType == null || paramType.Length == 0) { return(false); } if (valueArgument.RepresentedType == null || !ResultComparer.IsImplicitlyConvertible(paramType[0], valueArgument.RepresentedType)) { return(false); } // If spec given, test for equality (only ?) if (p.SpecializationExpression != null) { var specVal = Evaluation.EvaluateValue(p.SpecializationExpression, ctxt); if (specVal == null || !SymbolValueComparer.IsEqual(specVal, valueArgument)) { return(false); } } return(Set(p, arg)); }
static bool HandleDecl(DTokenDeclaration tk, AbstractType r) { if (r is PrimitiveType) { return(ResultComparer.IsPrimitiveTypeImplicitlyConvertible(((PrimitiveType)r).TypeToken, tk.Token)); } return(false); }
bool HandleDecl(TypeOfDeclaration t, AbstractType r) { // Can I enter some template parameter referencing id into a typeof specialization!? // class Foo(T:typeof(1)) {} ? var t_res = TypeDeclarationResolver.Resolve(t, ctxt); if (t_res == null) { return(false); } return(ResultComparer.IsImplicitlyConvertible(r, t_res)); }
private bool evalIsExpression_NoAlias(IsExpression isExpression, AbstractType typeToCheck) { if (isExpression.TypeSpecialization != null) { var spec = DResolver.StripAliasSymbols(TypeDeclarationResolver.Resolve(isExpression.TypeSpecialization, ctxt)); return(spec != null && spec.Length != 0 && (isExpression.EqualityTest ? ResultComparer.IsEqual(typeToCheck, spec[0]) : ResultComparer.IsImplicitlyConvertible(typeToCheck, spec[0], ctxt))); } return(isExpression.EqualityTest && evalIsExpression_EvalSpecToken(isExpression, typeToCheck, false).Item1); }
public static void RouteMatched <TValues>( this Assert assert, RouteBuilder.IBuildRoutesWithVariablesToMatch <TValues> routeInfo, UrlPathDetails url, TValues expectedValue, ResultComparer <TValues> comparer) { var routeMatched = false; var route = routeInfo.ToRoute(extractedValue => routeMatched = comparer(extractedValue, expectedValue)); route.ExecuteCallbackIfUrlMatches(url); assert.Ok(routeMatched); }
protected override bool HandleItem(INode n) { AbstractType t; if (n is DMethod && (nameFilterHash == 0 || n.NameHash == nameFilterHash) && cache.TryGetValue(n as DMethod, out t) && ResultComparer.IsImplicitlyConvertible(firstArgument, t, ctxt)) { filteredMethods.Add(n as DMethod); } return(false); }
public override void Set(AbstractSymbolValueProvider vp, ISymbolValue value) { var oldV = vp[Variable]; if (oldV is ArrayValue) { var av = (ArrayValue)oldV; //TODO: Immutability checks if (av.IsString) { } else { var at = av.RepresentedType as ArrayType; var newElements = new ISymbolValue[av.Elements.Length + (ItemNumber < 0 ? 1:0)]; av.Elements.CopyTo(newElements, 0); if (!ResultComparer.IsImplicitlyConvertible(value.RepresentedType, at.ValueType)) { if (vp.ev != null) { vp.ev.EvalError(null, value.ToCode() + " must be implicitly convertible to the array's value type!", value); } return; } // Add.. if (ItemNumber < 0) { av.Elements[av.Elements.Length - 1] = value; } else // or set the new value { av.Elements[ItemNumber] = value; } vp[Variable] = new ArrayValue(at, newElements); } } else { if (vp.ev != null) { vp.ev.EvalError(null, "Type of accessed item must be an array", oldV); } } }
public long GetOrdersByCustomer(string customerId) { Stopwatch clock = new Stopwatch(); clock.Start(); var query = from order in db.Orders join customer in db.Customers on order.CustomerID equals customer.CustomerID where customer.CustomerID == customerId select order; query.ToList(); clock.Stop(); var elapsedTime = clock.ElapsedMilliseconds; ResultComparer.GetOrdersByCustomer(query.ToList(), method); return(elapsedTime); }
public long GetCustomersByCountry(string countryName) { Stopwatch clock = new Stopwatch(); clock.Start(); List <Customer> result; using (IDbConnection db = new SqlConnection(connString)) { result = db.Query <Customer>(Constants.GET_CUSTOMERS_BY_COUNTRY, new { Country = countryName }).ToList(); } clock.Stop(); ResultComparer.getCustomerData(result, method); var elapsedTime = clock.ElapsedMilliseconds; return(elapsedTime); }
public long GetCustomersByCountry(string countryName) { Stopwatch clock = new Stopwatch(); clock.Start(); var query = from c in db.Customers where c.Country == countryName select c; clock.Stop(); query.ToList(); var elapsedTime = clock.ElapsedMilliseconds; ResultComparer.getCustomerData(query.ToList(), method); return(elapsedTime); }
public long GetCustomerAndOrdersByEmp(int empId) { Stopwatch clock = new Stopwatch(); clock.Start(); List <Order> result; using (NwEntityContext context = new NwEntityContext()) { result = context.Orders.Include(x => x.Customer).Include(x => x.Customer).Include(x => x.Employee).Where(x => x.Employee.EmployeeID == empId).ToList(); } clock.Stop(); var elapsedTime = clock.ElapsedMilliseconds; ResultComparer.GetCustomerAndOrdersByEmp(result, method); return(elapsedTime); }
public long GetCustomersByCountry(string countryName) { Stopwatch clock = new Stopwatch(); clock.Start(); List <Customer> result; using (NwEntityContext context = new NwEntityContext()) { result = context.Customers.Where(x => x.Country == countryName).ToList(); } clock.Stop(); var elapsedTime = clock.ElapsedMilliseconds; ResultComparer.getCustomerData(result, method); return(elapsedTime); }
public long GetOrdersByCustomer(string customerId) { Stopwatch clock = new Stopwatch(); clock.Start(); List <Order> result; using (NwEntityContext context = new NwEntityContext()) { result = context.Orders.Include(x => x.Customer).Include(x => x.Customer).Where(x => x.Customer.CustomerID == customerId).ToList(); } clock.Stop(); var elapsedTime = clock.ElapsedMilliseconds; ResultComparer.GetOrdersByCustomer(result, method); return(elapsedTime); }
bool HandleDecl(VectorDeclaration v, AbstractType r) { if (r.DeclarationOrExpressionBase is VectorDeclaration) { var v_res = ExpressionTypeEvaluation.EvaluateType(v.Id, ctxt); var r_res = ExpressionTypeEvaluation.EvaluateType(((VectorDeclaration)r.DeclarationOrExpressionBase).Id, ctxt); if (v_res == null || r_res == null) { return(false); } else { return(ResultComparer.IsImplicitlyConvertible(r_res, v_res)); } } return(false); }
void HandleMethod(DMethod dm, MemberSymbol alreadyResolvedMethod = null) { if (dm != null && dm.Parameters.Count > 0 && dm.Parameters[0].Type != null) { var loc = dm.Body != null ? dm.Body.Location : dm.Location; using (alreadyResolvedMethod != null ? ctxt.Push(alreadyResolvedMethod, loc) : ctxt.Push(dm, loc)) { var t = TypeDeclarationResolver.ResolveSingle(dm.Parameters[0].Type, ctxt); if (ResultComparer.IsImplicitlyConvertible(firstArgument, t, ctxt)) { var res = alreadyResolvedMethod ?? TypeDeclarationResolver.HandleNodeMatch(dm, ctxt, typeBase: sr); res.Tag = new UfcsTag { firstArgument = firstArgument }; matches.Add(res); } } } }
public long GetCustomerAndOrdersByEmp(int empId) { Stopwatch clock = new Stopwatch(); clock.Start(); var query = from order in db.Orders join customer in db.Customers on order.CustomerID equals customer.CustomerID join employee in db.Employees on order.EmployeeID equals employee.EmployeeID where employee.EmployeeID == empId select order; query.ToList(); clock.Stop(); var elapsedTime = clock.ElapsedMilliseconds; ResultComparer.GetCustomerAndOrdersByEmp(query.ToList(), method); return(elapsedTime); }
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]))); }
internal static bool TryHandleMethodArgumentTuple(ResolutionContext ctxt, ref bool add, List <ISemantic> callArguments, DMethod dm, DeducedTypeDictionary deducedTypeDict, int currentParameter, ref int currentArg) { // .. so only check if it's an identifer & if the id represents a tuple parameter var id = dm.Parameters[currentParameter].Type as IdentifierDeclaration; var curNode = dm as DNode; TemplateParameter tpar = null; while (curNode != null && !curNode.TryGetTemplateParameter(id.IdHash, out tpar)) { curNode = curNode.Parent as DNode; } if (!(tpar is TemplateTupleParameter)) { return(false); } int lastArgumentToTake = -1; /* * Note: an expression tuple parameter can occur also somewhere in between the parameter list! * void write(A...)(bool b, A a, double d) {} * * can be matched by * write(true, 1.2) as well as * write(true, "asdf", 1.2) as well as * write(true, 123, true, 'c', [3,4,5], 3.4) ! */ TemplateParameterSymbol tps; DTuple tuple = null; if (deducedTypeDict.TryGetValue(tpar, out tps) && tps != null) { if (tps.Base is DTuple) { tuple = tps.Base as DTuple; lastArgumentToTake = currentParameter + (tuple.Items == null ? 0 : (tuple.Items.Length - 1)); } else { // Error: Type param must be tuple! } } // - Get the (amount of) arguments that shall be put into the tuple else if (currentParameter == dm.Parameters.Count - 1) { // The usual case: A tuple of a variable length is put at the end of a parameter list.. // take all arguments from i until the end of the argument list.. // ; Also accept empty tuples lastArgumentToTake = callArguments.Count - 1; } else { // Get the type of the next expected parameter var nextExpectedParameter = DResolver.StripMemberSymbols(TypeDeclarationResolver.ResolveSingle(dm.Parameters[currentParameter + 1].Type, ctxt)); // Look for the first argument whose type is equal to the next parameter's type.. for (int k = currentArg; k < callArguments.Count; k++) { if (ResultComparer.IsEqual(AbstractType.Get(callArguments[k]), nextExpectedParameter)) { // .. and assume the tuple to go from i to the previous argument.. lastArgumentToTake = k - 1; break; } } } int argCountToHandle = lastArgumentToTake - currentArg + 1; if (tuple != null) { // - If there's been set an explicit type tuple, compare all arguments' types with those in the tuple if (tuple.Items != null) { foreach (ISemantic item in tuple.Items) { if (currentArg >= callArguments.Count || !ResultComparer.IsImplicitlyConvertible(callArguments[currentArg++], AbstractType.Get(item), ctxt)) { add = false; return(true); } } } } else { // - If there was no explicit initialization, put all arguments' types into a type tuple var argsToTake = new ISemantic[argCountToHandle]; callArguments.CopyTo(currentArg, argsToTake, 0, argsToTake.Length); currentArg += argsToTake.Length; var tt = new DTuple(null, argsToTake); tps = new TemplateParameterSymbol(tpar, tt); // and set the actual template tuple parameter deduction deducedTypeDict[tpar] = tps; } add = true; return(true); }
/// <summary> /// a + b; a - b; etc. /// </summary> ISemantic E_MathOp(OperatorBasedExpression x, ISemantic lValue = null, ISemantic rValue = null) { if (!eval) { return(lValue ?? E(x.LeftOperand)); } var l = TryGetValue(lValue ?? E(x.LeftOperand)); if (l == null) { /* * In terms of adding opOverloading later on, * lvalue not being a PrimitiveValue shouldn't be a problem anymore - we simply had to * search the type of l for methods called opAdd etc. and call that method via ctfe. * Finally, return the value the opAdd method passed back - and everything is fine. */ /* * Also, pointers should be implemented later on. * http://dlang.org/expression.html#AddExpression */ throw new EvaluationException(x, "Left value must evaluate to a constant scalar value. Operator overloads aren't supported yet", lValue); } //TODO: Operator overloading // Note: a * b + c is theoretically treated as a * (b + c), but it's needed to evaluate it as (a * b) + c ! if (x is MulExpression || x is PowExpression) { if (x.RightOperand is OperatorBasedExpression && !(x.RightOperand is AssignExpression)) //TODO: This must be true only if it's a math expression, so not an assign expression etc. { var sx = (OperatorBasedExpression)x.RightOperand; // Now multiply/divide/mod expression 'l' with sx.LeftOperand var intermediateResult = HandleSingleMathOp(x, l, E(sx.LeftOperand), mult); // afterwards, evaluate the operation between the result just returned and the sx.RightOperand. return(E(sx, intermediateResult)); } return(HandleSingleMathOp(x, l, rValue ?? E(x.RightOperand), mult)); } var r = TryGetValue(rValue ?? E(x.RightOperand)); if (r == null) { throw new EvaluationException(x, "Right operand must evaluate to a value", lValue); } /* * TODO: Handle invalid values/value ranges. */ if (x is XorExpression) { return(HandleSingleMathOp(x, l, r, (a, b) => { EnsureIntegralType(a); EnsureIntegralType(b); return (long)a.Value ^ (long)b.Value; })); } else if (x is OrExpression) { return(HandleSingleMathOp(x, l, r, (a, b) => { EnsureIntegralType(a); EnsureIntegralType(b); return (long)a.Value | (long)b.Value; })); } else if (x is AndExpression) { return(HandleSingleMathOp(x, l, r, (a, b) => { EnsureIntegralType(a); EnsureIntegralType(b); return (long)a.Value & (long)b.Value; })); } else if (x is ShiftExpression) { return(HandleSingleMathOp(x, l, r, (a, b) => { EnsureIntegralType(a); EnsureIntegralType(b); if (b.Value < 0 || b.Value > 31) { throw new EvaluationException(b.BaseExpression, "Shift operand must be between 0 and 31", b); } switch (x.OperatorToken) { case DTokens.ShiftLeft: return (long)a.Value << (int)b.Value; // TODO: Handle the imaginary part case DTokens.ShiftRight: return (long)a.Value >> (int)b.Value; case DTokens.ShiftRightUnsigned: //TODO: Find out where's the difference between >> and >>> return (ulong)a.Value >> (int)(uint)b.Value; } throw new EvaluationException(x, "Invalid token for shift expression", l, r); })); } else if (x is AddExpression) { return(HandleSingleMathOp(x, l, r, (a, b, op) => { switch (op.OperatorToken) { case DTokens.Plus: return new PrimitiveValue(a.BaseTypeToken, a.Value + b.Value, x, a.ImaginaryPart + b.ImaginaryPart); case DTokens.Minus: return new PrimitiveValue(a.BaseTypeToken, a.Value - b.Value, x, a.ImaginaryPart - b.ImaginaryPart); } throw new EvaluationException(x, "Invalid token for add/sub expression", l, r); })); } else if (x is CatExpression) { // Notable: If one element is of the value type of the array, the element is added (either at the front or at the back) to the array var av_l = l as ArrayValue; var av_r = r as ArrayValue; if (av_l != null && av_r != null) { // Ensure that both arrays are of the same type if (!ResultComparer.IsEqual(av_l.RepresentedType, av_r.RepresentedType)) { throw new EvaluationException(x, "Both arrays must be of same type", l, r); } // Might be a string if (av_l.IsString && av_r.IsString) { return(new ArrayValue(av_l.RepresentedType as ArrayType, x, av_l.StringValue + av_r.StringValue)); } else { var elements = new ISymbolValue[av_l.Elements.Length + av_r.Elements.Length]; Array.Copy(av_l.Elements, 0, elements, 0, av_l.Elements.Length); Array.Copy(av_r.Elements, 0, elements, av_l.Elements.Length, av_r.Elements.Length); return(new ArrayValue(av_l.RepresentedType as ArrayType, elements)); } } ArrayType at = null; // Append the right value to the array if (av_l != null && (at = av_l.RepresentedType as ArrayType) != null && ResultComparer.IsImplicitlyConvertible(r.RepresentedType, at.ValueType, ctxt)) { var elements = new ISymbolValue[av_l.Elements.Length + 1]; Array.Copy(av_l.Elements, elements, av_l.Elements.Length); elements[elements.Length - 1] = r; return(new ArrayValue(at, elements)); } // Put the left value into the first position else if (av_r != null && (at = av_r.RepresentedType as ArrayType) != null && ResultComparer.IsImplicitlyConvertible(l.RepresentedType, at.ValueType, ctxt)) { var elements = new ISymbolValue[1 + av_r.Elements.Length]; elements[0] = l; Array.Copy(av_r.Elements, 0, elements, 1, av_r.Elements.Length); return(new ArrayValue(at, elements)); } throw new EvaluationException(x, "At least one operand must be an (non-associative) array. If so, the other operand must be of the array's element type.", l, r); } throw new WrongEvaluationArgException(); }
/// <summary> /// Item1 - True, if isExpression returns true /// Item2 - If Item1 is true, it contains the type of the alias that is defined in the isExpression /// </summary> private Tuple <bool, AbstractType> evalIsExpression_EvalSpecToken(IsExpression isExpression, AbstractType typeToCheck, bool DoAliasHandling = false) { bool r = false; AbstractType res = null; switch (isExpression.TypeSpecializationToken) { /* * To handle semantic tokens like "return" or "super" it's just needed to * look into the current resolver context - * then, we'll be able to gather either the parent method or the currently scoped class definition. */ case DTokens.Struct: case DTokens.Union: case DTokens.Class: case DTokens.Interface: if (r = typeToCheck is UserDefinedType && ((TemplateIntermediateType)typeToCheck).Definition.ClassType == isExpression.TypeSpecializationToken) { res = typeToCheck; } break; case DTokens.Enum: if (!(typeToCheck is EnumType)) { break; } { var tr = (UserDefinedType)typeToCheck; r = true; res = tr.Base; } break; case DTokens.Function: case DTokens.Delegate: if (typeToCheck is DelegateType) { var isFun = false; var dgr = (DelegateType)typeToCheck; if (!dgr.IsFunctionLiteral) { r = isExpression.TypeSpecializationToken == ( (isFun = ((DelegateDeclaration)dgr.DeclarationOrExpressionBase).IsFunction) ? DTokens.Function : DTokens.Delegate); } // Must be a delegate otherwise else { isFun = !(r = isExpression.TypeSpecializationToken == DTokens.Delegate); } if (r) { //TODO if (isFun) { // TypeTuple of the function parameter types. For C- and D-style variadic functions, only the non-variadic parameters are included. // For typesafe variadic functions, the ... is ignored. } else { // the function type of the delegate } } } else // Normal functions are also accepted as delegates { r = isExpression.TypeSpecializationToken == DTokens.Delegate && typeToCheck is MemberSymbol && ((DSymbol)typeToCheck).Definition is DMethod; //TODO: Alias handling, same as couple of lines above } break; case DTokens.Super: //TODO: Test this var dc = DResolver.SearchClassLikeAt(ctxt.ScopedBlock, isExpression.Location) as DClassLike; if (dc != null) { var udt = DResolver.ResolveBaseClasses(new ClassType(dc, dc, null), ctxt, true) as ClassType; if (r = udt.Base != null && ResultComparer.IsEqual(typeToCheck, udt.Base)) { var l = new List <AbstractType>(); if (udt.Base != null) { l.Add(udt.Base); } if (udt.BaseInterfaces != null && udt.BaseInterfaces.Length != 0) { l.AddRange(udt.BaseInterfaces); } res = new DTuple(isExpression, l); } } break; case DTokens.Const: case DTokens.Immutable: case DTokens.InOut: // TODO? case DTokens.Shared: if (r = typeToCheck.Modifier == isExpression.TypeSpecializationToken) { res = typeToCheck; } break; case DTokens.Return: // TODO: Test IStatement _u = null; var dm = DResolver.SearchBlockAt(ctxt.ScopedBlock, isExpression.Location, out _u) as DMethod; if (dm != null) { var retType_ = TypeDeclarationResolver.GetMethodReturnType(dm, ctxt); if (r = retType_ != null && ResultComparer.IsEqual(typeToCheck, retType_)) { res = retType_; } } break; } return(new Tuple <bool, AbstractType>(r, res)); }
ISymbolValue EvalConcatenation(CatExpression x, ISymbolValue lValue) { // In the (not unusual) case that more than 2 arrays/strings shall be concat'ed - process them more efficiently var catQueue = new Queue <ISymbolValue>(); var catEx = (x as CatExpression); catQueue.Enqueue(lValue); catEx = catEx.RightOperand as CatExpression; ISymbolValue r; while (catEx != null) { r = TryGetValue(E(catEx.LeftOperand)); if (r == null) { EvalError(catEx.LeftOperand, "Couldn't be evaluated."); return(null); } catQueue.Enqueue(r); if (catEx.RightOperand is CatExpression) { catEx = catEx.RightOperand as CatExpression; } else { break; } } r = TryGetValue(E((catEx ?? x).RightOperand)); if (r == null) { EvalError(catEx.LeftOperand, "Couldn't be evaluated."); return(null); } catQueue.Enqueue(r); // Notable: If one element is of the value type of the array, the element is added (either at the front or at the back) to the array // myString ~ 'a' will append an 'a' to the string // 'a' ~ myString inserts 'a' at index 0 // Determine whether we have to build up a string OR a normal list of atomic elements bool isString = true; ArrayType lastArrayType = null; foreach (var e in catQueue) { if (e is AssociativeArrayValue) { EvalError(x, "Can't concatenate associative arrays", e); return(null); } else if (e is ArrayValue) { if (lastArrayType != null && !ResultComparer.IsEqual(lastArrayType, e.RepresentedType)) { EvalError(x, "Both arrays must be of same type", new[] { lastArrayType, e.RepresentedType }); return(null); } lastArrayType = e.RepresentedType as ArrayType; if ((e as ArrayValue).IsString) { continue; } } else if (e is PrimitiveValue) { var btt = (e as PrimitiveValue).BaseTypeToken; if (btt == DTokens.Char || btt == DTokens.Dchar || btt == DTokens.Wchar) { continue; } } isString = false; } if (lastArrayType == null) { EvalError(x, "At least one operand must be an (non-associative) array. If so, the other operand must be of the array's element type.", catQueue.ToArray()); return(null); } if (isString) { var sb = new StringBuilder(); while (catQueue.Count != 0) { var e = catQueue.Dequeue(); if (e is ArrayValue) { sb.Append((e as ArrayValue).StringValue); } else if (e is PrimitiveValue) { sb.Append((char)((e as PrimitiveValue).Value)); } } return(new ArrayValue(GetStringType(LiteralSubformat.Utf8), sb.ToString())); } var elements = new List <ISymbolValue>(); while (catQueue.Count != 0) { var e = catQueue.Dequeue(); var av = e as ArrayValue; if (av != null) { if (av.IsString) { elements.Add(av); } else if (av.Elements != null) { elements.AddRange(av.Elements); } continue; } if (!ResultComparer.IsImplicitlyConvertible(e.RepresentedType, lastArrayType.ValueType, ctxt)) { EvalError(x, "Element with type " + e.RepresentedType.ToCode() + " doesn't fit into array with type " + lastArrayType.ToCode(), catQueue.ToArray()); return(null); } elements.Add(e); } return(new ArrayValue(lastArrayType, elements.ToArray())); }
public static DNode ExamTraceSymbol(string symName, ResolutionContext ctxt, out bool mightBeLegalUnresolvableSymbol) { DSymbol ds = null; mightBeLegalUnresolvableSymbol = false; if (string.IsNullOrWhiteSpace(symName)) { return(null); } // Try to handle a probably mangled string or C function. if (symName.StartsWith("_")) { try{ ds = Demangler.DemangleAndResolve(symName, ctxt) as DSymbol; }catch {} } // Stuff like void std.stdio.File.LockingTextWriter.put!(immutable(char)[]).put(immutable(char)[]) if (ds == null && Lexer.IsIdentifierPart((int)symName[0])) { mightBeLegalUnresolvableSymbol = true; ITypeDeclaration q; var method = DParser.ParseMethodDeclarationHeader(symName, out q); q = Demangler.RemoveNestedTemplateRefsFromQualifier(q); method.Type = Demangler.RemoveNestedTemplateRefsFromQualifier(method.Type); var methodType = TypeDeclarationResolver.GetMethodReturnType(method, ctxt); var methodParameters = new List <AbstractType>(); if (method.Parameters != null && method.Parameters.Count != 0) { foreach (var parm in method.Parameters) { methodParameters.Add(TypeDeclarationResolver.ResolveSingle(Demangler.RemoveNestedTemplateRefsFromQualifier(parm.Type), ctxt)); } } ctxt.ContextIndependentOptions |= ResolutionOptions.IgnoreAllProtectionAttributes; var overloads = TypeDeclarationResolver.Resolve(q, ctxt); if (overloads == null || overloads.Length == 0) { return(null); } else if (overloads.Length == 1) { ds = overloads[0] as DSymbol; } else { foreach (var o in overloads) { ds = o as DSymbol; if (ds == null || !(ds.Definition is DMethod)) { continue; } var dm = ds.Definition as DMethod; // Compare return types if (dm.Type != null) { if (methodType == null || ds.Base == null || !ResultComparer.IsEqual(methodType, ds.Base)) { continue; } } else if (dm.Type == null && methodType != null) { return(null); } // Compare parameters if (methodParameters.Count != dm.Parameters.Count) { continue; } for (int i = 0; i < methodParameters.Count; i++) { if (!ResultComparer.IsImplicitlyConvertible(methodParameters[i], TypeDeclarationResolver.ResolveSingle(Demangler.RemoveNestedTemplateRefsFromQualifier(dm.Parameters[i].Type), ctxt))) { continue; } } } } } if (ds != null) { return(ds.Definition); } return(null); }