public static IEnumerable<ReplaceAction> GetSimplifications(ForEachStatementSyntax forLoop, ISemanticModel model, Assumptions assume, CancellationToken cancellationToken = default(CancellationToken)) { // loop uses iterator once? var declaredSymbol = model.GetDeclaredSymbol(forLoop); var singleRead = forLoop.Statement.DescendantNodes() .OfType<SimpleNameSyntax>() .Where(e => model.GetSymbolInfo(e).Symbol == declaredSymbol) .SingleOrDefaultAllowMany(); if (singleRead == null) yield break; // safe iterator projection? var guaranteedProjectionPerIteration = forLoop.Statement.CompleteExecutionGuaranteesChildExecutedExactlyOnce(singleRead); var projection = singleRead.AncestorsAndSelf() .TakeWhile(e => !(e is StatementSyntax)) .OfType<ExpressionSyntax>() .TakeWhile(e => model.GetTypeInfo(e).Type.SpecialType != SpecialType.System_Void) .TakeWhile(e => guaranteedProjectionPerIteration == true || e.HasSideEffects(model, assume) == false) .LastOrDefault(); if (projection == null) yield break; if (projection.TryEvalAlternativeComparison(singleRead, model, assume) == true) yield break; // build replacement loop var projectedCollection = forLoop.Expression .Accessing("Select") .Invoking(forLoop.Identifier.Lambdad(projection).Args1()); var newBody = forLoop.Statement.ReplaceNode(projection, singleRead); var replacedLoop = forLoop.WithExpression(projectedCollection).WithStatement(newBody); // expose as code action/issue yield return new ReplaceAction( "Project collection", forLoop, replacedLoop); }
private void AssertNoOptimization(Assumptions assumptions, string pars, string collection, string body) { var tree1 = ("void f(" + pars + ") { foreach (var e in " + collection + ") { " + body + " }").ParseFunctionTreeFromStringUsingStandard(); var statements1 = (ForEachStatementSyntax)tree1.TestGetParsedFunctionStatements().Single(); var model = tree1.GetTestSemanticModel(); Assert.IsTrue(ForEachToFirstLast.GetSimplifications(statements1, model, assumptions).Count() == 0); }
public static IEnumerable<ReplaceAction> GetSimplifications(ForEachStatementSyntax forLoop, ISemanticModel model, Assumptions assume, CancellationToken cancellationToken = default(CancellationToken)) { var body = forLoop.Statement.Statements(); if (body.None()) yield break; var unconditionalStatements = body.Skip(1); var conditionalStatement = body.First() as IfStatementSyntax; if (conditionalStatement == null) yield break; var trueBranch = conditionalStatement.Statement.Statements().AppendUnlessJumps(unconditionalStatements).Block(); var falseBranch = conditionalStatement.ElseStatementOrEmptyBlock().Statements().AppendUnlessJumps(unconditionalStatements).Block(); var falseIsEmpty = falseBranch.HasSideEffects(model, assume) == false; var trueIsEmpty = trueBranch.HasSideEffects(model, assume) == false; if (falseIsEmpty == trueIsEmpty) yield break; var condition = falseIsEmpty ? conditionalStatement.Condition : conditionalStatement.Condition.Inverted(); var conditionalActions = falseIsEmpty ? trueBranch : falseBranch; var query = forLoop.Expression.Accessing("Where").Invoking(forLoop.Identifier.Lambdad(condition).Args1()); var forWhereDo = forLoop.WithExpression(query).WithStatement(conditionalActions); yield return new ReplaceAction( "Filter collection", forLoop, forWhereDo); }
private void AssertOptimizes(Assumptions assumptions, string pars, string collection, string body, string newBody = null) { var tree1 = ("void f(" + pars + ") { foreach (var e in " + collection + ") { " + body + " }").ParseFunctionTreeFromStringUsingStandard(); var tree2 = ("void f(" + pars + ") { if (" + collection + ".Any()) { " + (newBody ?? body) + " }").ParseFunctionTreeFromStringUsingStandard(); var statements1 = (ForEachStatementSyntax)tree1.TestGetParsedFunctionStatements().Single(); var statements2 = (IfStatementSyntax)tree2.TestGetParsedFunctionStatements().Single(); var model = tree1.GetTestSemanticModel(); TestUtil.AssertSameSyntax(ForEachToAny.GetSimplifications(statements1, model, assumptions).Single().NewNode, statements2); }
public static IEnumerable<ReplaceAction> GetSimplifications(BinaryExpressionSyntax b, ISemanticModel model, Assumptions assume, CancellationToken cancellationToken = default(CancellationToken)) { if (!b.Left.DefinitelyHasBooleanType(model)) yield break; if (!b.Right.DefinitelyHasBooleanType(model)) yield break; // prep basic analysis var leftEffects = b.Left.HasSideEffects(model, assume) != false; var rightEffects = b.Right.HasSideEffects(model, assume) != false; var lv = b.Left.TryGetConstBoolValue(); var rv = b.Right.TryGetConstBoolValue(); var cmp = b.Left.TryEvalAlternativeComparison(b.Right, model, assume); // prep utility funcs for adding simplifications var actions = new List<ReplaceAction>(); Action<String, ExpressionSyntax> include = (desc, rep) => actions.Add(new ReplaceAction(desc, b, rep)); Action<bool> useRight = v => { if (!leftEffects) include(v ? "rhs" : "!rhs", b.Right.MaybeInverted(!v)); }; Action<bool> useLeft = v => { if (!rightEffects) include(v ? "lhs" : "!lhs", b.Left.MaybeInverted(!v)); }; Action<bool> useBool = v => { if (!leftEffects && !rightEffects) { actions.Clear(); // override left/right include(v + "", v.AsLiteral()); } }; // try to simplify equality operators ==, !=, ^ bool? equality = null; if (b.Kind == SyntaxKind.EqualsExpression) equality = true; if (b.Kind == SyntaxKind.ExclusiveOrExpression || b.Kind == SyntaxKind.NotEqualsExpression) equality = false; if (equality != null) { if (lv != null) useRight(lv == equality); if (rv != null) useLeft(rv == equality); if (cmp != null) useBool(cmp == equality); } // try to simplify and/or operators &&, &, ||, | var sticky = b.Kind.IsAndBL() ? false : b.Kind.IsOrBL() ? true : (bool?)null; if (sticky != null) { if (b.Kind.IsShortCircuitingLogic() && lv == sticky) rightEffects = false; // short-circuit prevents effects if (cmp == true || lv == !sticky) useRight(true); if (cmp == true || rv == !sticky) useLeft(true); if (cmp == false || lv == sticky || rv == sticky) useBool(sticky.Value); } // expose simplifications as code issues/actions foreach (var action in actions) yield return action; }
public static IEnumerable<ReplaceAction> GetSimplifications(VariableDeclarationSyntax declaration, ISemanticModel model, Assumptions assume, CancellationToken cancellationToken = default(CancellationToken)) { if (declaration.Variables.Count != 1) yield break; var v = declaration.Variables.Single(); if (v.Initializer == null) yield break; if (declaration.Type.IsVar) yield break; var declaredType = model.GetTypeInfo(declaration.Type); var valueType = model.GetTypeInfo(v.Initializer.Value); if (!declaredType.Equals(valueType)) yield break; yield return new ReplaceAction("Use 'var'", declaration.Type, Syntax.IdentifierName("var")); }
public static IEnumerable<ReplaceAction> GetSimplifications(ForEachStatementSyntax loop, ISemanticModel model, Assumptions assume, CancellationToken cancellationToken = default(CancellationToken)) { if (loop.Type.IsVar) yield break; var declaredType = model.GetTypeInfo(loop.Type).Type as ITypeSymbol; var collectionType = model.GetTypeInfo(loop.Expression).Type as ITypeSymbol; if (declaredType == null || collectionType == null) yield break; var allInterfaces = new List<INamedTypeSymbol>(); allInterfaces.AddRange(collectionType.AllInterfaces); if (collectionType is INamedTypeSymbol) allInterfaces.Add((INamedTypeSymbol)collectionType); var enumerableTypes = allInterfaces .Where(e => e.OriginalDefinition.SpecialType == SpecialType.System_Collections_Generic_IEnumerable_T) .ToArray(); if (enumerableTypes.Count() != 1) yield break; var itemType = enumerableTypes.Single().TypeArguments.Single(); if (!declaredType.Equals(itemType)) yield break; yield return new ReplaceAction("Use 'var'", loop.Type, Syntax.IdentifierName("var")); }
public static IEnumerable<ReplaceAction> GetSimplifications(ForEachStatementSyntax forLoop, ISemanticModel model, Assumptions assumptions, CancellationToken cancellationToken = default(CancellationToken)) { if (forLoop.IsAnyIterationSufficient(model, assumptions) == true) yield break; // a more appropriate code issue handles this case // can the loop be replaced by its first or last iteration? var isFirstSufficient = forLoop.IsFirstIterationSufficient(model, assumptions) == true; var isLastSufficient = forLoop.IsLastIterationSufficient(model, assumptions) == true; var firstVsLast = isFirstSufficient ? "First" : isLastSufficient ? "Last" : null; if (firstVsLast == null) yield break; // do we know how to translate? var loopStatements = forLoop.Statement.Statements(); var rawThenStatements = loopStatements.SkipLast(loopStatements.Last().IsIntraLoopJump() ? 1 : 0).ToArray(); if (rawThenStatements.Any(e => e.HasTopLevelIntraLoopJumps())) yield break; // don't know how to translate jumps that aren't at the end // wrap collection items in a type with a new null value (so that a null result definitively indicates an empty collection) var iteratorType = ((LocalSymbol)model.GetDeclaredSymbol(forLoop)).Type; var nuller = GetNullabledQueryAndValueGetter(iteratorType, forLoop.Identifier, forLoop.Expression); var nullableQuery = nuller.Item1; var valueGetter = nuller.Item2; var tempNullableLocalName = Syntax.Identifier("_" + forLoop.Identifier.ValueText); var tempNullableLocalGet = Syntax.IdentifierName(tempNullableLocalName); // build replacement var iteratorReads = forLoop.Statement.ReadsOfLocalVariable(forLoop.Identifier).ToArray(); var desiredIterationQuery = nullableQuery.Accessing(firstVsLast + "OrDefault").Invoking(); var condition = tempNullableLocalGet.BOpNotEquals(Syntax.LiteralExpression(SyntaxKind.NullLiteralExpression)); var useDenulledLocal = iteratorReads.Length > 2; var thenStatement = useDenulledLocal ? rawThenStatements.Prepend(forLoop.Identifier.VarInit(valueGetter(tempNullableLocalGet))).Block() : rawThenStatements.Select(e => e.ReplaceNodes(iteratorReads, (n, a) => valueGetter(tempNullableLocalGet))).Block(); var replacementStatements = new StatementSyntax[] { tempNullableLocalName.VarInit(desiredIterationQuery), condition.IfThen(thenStatement) }; // expose as code action/issue yield return forLoop.MakeReplaceStatementWithManyAction( replacementStatements, "Execute " + firstVsLast + " if any"); }
public static IEnumerable<ReplaceAction> GetSimplifications(LocalDeclarationStatementSyntax declaration, ISemanticModel model, Assumptions assume, CancellationToken cancellationToken = default(CancellationToken)) { var scope = declaration.Ancestors().OfType<BlockSyntax>().First(); var i = scope.Statements.IndexOf(declaration); foreach (var v in declaration.Declaration.Variables) { if (v.Initializer != null) { if (v.Initializer.Value.HasSideEffects(model, assume) != false) continue; var anyEffects = declaration.Declaration.Variables.Where(e => e.Initializer != null && e.Initializer.Value.HasSideEffects(model, assume) != false).Any(); if (v.Initializer.Value.IsConst(model) != true && anyEffects) continue; } var r = WithDeclarationMoved(scope, declaration, v, model, assume, cancellationToken); if (r == null) continue; var reducedDeclaration = declaration.Declaration.Variables.Count == 1 ? new LocalDeclarationStatementSyntax[0] : new[] { declaration.WithDeclaration(declaration.Declaration.WithVariables(declaration.Declaration.Variables.Without(v))) }; var newScopeWithReducedDeclaration = r.WithStatements(r.Statements.TakeSkipPutTake(i, 1, reducedDeclaration).List()); yield return new ReplaceAction("Reduce scope", scope, newScopeWithReducedDeclaration, v.Identifier.Span); } }
public static IEnumerable<ReplaceAction> GetSimplifications(ForEachStatementSyntax forLoop, ISemanticModel model, Assumptions assumptions, CancellationToken cancellationToken = default(CancellationToken)) { // loop body idempotent and independent of the iterator? if (forLoop.IsAnyIterationSufficient(model, assumptions) != true) yield break; // build replacement if statement, if possible var loopStatements = forLoop.Statement.Statements(); if (loopStatements.None()) yield break; var ifBody = loopStatements.SkipLast(loopStatements.Last().IsIntraLoopJump() ? 1 : 0).Block(); if (ifBody.HasTopLevelIntraLoopJumps()) yield break; var ifCondition = forLoop.Expression.Accessing("Any").Invoking(); var rawReplacement = Syntax.IfStatement( condition: ifCondition, statement: ifBody); var replacement = rawReplacement.IncludingTriviaSurrounding(forLoop, TrivialTransforms.Placement.Around); // expose as code action/issue yield return new ReplaceAction( "Execute once if any", forLoop, replacement); }
public static IEnumerable<ReplaceAction> GetSimplifications(ConditionalExpressionSyntax ternaryNode, ISemanticModel model, Assumptions assume, CancellationToken cancellationToken = default(CancellationToken)) { if (!ternaryNode.DefinitelyHasBooleanType(model)) yield break; var whenTrueFalseCmp = ternaryNode.WhenTrue.TryEvalAlternativeComparison(ternaryNode.WhenFalse, model, assume); if (whenTrueFalseCmp == true) { // (c ? b : b) --> b yield return new ReplaceAction( "Simplify", ternaryNode, ternaryNode.WhenTrue); // if condition has side effects we may need to keep it // (c ? b : b) --> ((c && false) || b) if (ternaryNode.Condition.HasSideEffects(model, assume) != false) { var replacement = ternaryNode.Condition .BracketedOrProtected() .BOpLogicalAnd(false.AsLiteral()) .Bracketed() .BOpLogicalOr(ternaryNode.WhenTrue); yield return new ReplaceAction( "Simplify (keeping condition evaluation)", ternaryNode, replacement); } } if (whenTrueFalseCmp == false) { // (c ? b : !b) --> (c == b) var replacement = ternaryNode.Condition .BracketedOrProtected() .BOpEquals(ternaryNode.WhenTrue); yield return new ReplaceAction( "Simplify", ternaryNode, replacement); } }
public void ConfigureServices(IServiceCollection services) { var cultureInfo = new CultureInfo("en-GB"); CultureInfo.DefaultThreadCurrentCulture = cultureInfo; CultureInfo.DefaultThreadCurrentUICulture = cultureInfo; services.AddApplicationInsightsTelemetry("5df2bfe9-d72c-4622-9fed-adbee51c0a02"); services.AddControllers(options => { options.InputFormatters.Insert(0, new TextPlainInputFormatter()); }); services.AddControllers().AddNewtonsoftJson(); services.AddSingleton <ITaxSystem, TwentyTwentyTaxSystem>(); services.AddSingleton <IIncomeTaxCalculator, IncomeTaxCalculator>(); services.AddSingleton <ITaxCalculatorDomainInterface, TaxCalculatorDomainInterface>(); services.AddSingleton <IDateProvider, DateProvider>(); services.AddSingleton <IPensionAgeCalc, PensionAgeCalc>(); services.AddSingleton <IStatePensionAmountCalculator, StatePensionAmountCalculator>(); services.AddTransient <IAssumptions>(x => Assumptions.SafeWithdrawalNoInflationTake25Assumptions()); services.AddSingleton <IRetirementCalculator, RetirementIncrementalApproachCalculator>(); services.AddSingleton <IRetirementDomainInterface, RetirementDomainInterface>(); services.AddControllers(); }
private static bool? IsLastIterationSufficient_Helper(this ExpressionSyntax syntax, ISemanticModel model, Assumptions assume, ISymbol iteratorVariable) { Contract.Requires(syntax != null); Contract.Requires(model != null); Contract.Requires(iteratorVariable != null); var isConst = syntax.IsConst(model); if (isConst == true) return true; if (syntax is IdentifierNameSyntax && model.GetSymbolInfo(syntax).Symbol == iteratorVariable) return true; if (syntax.Kind == SyntaxKind.AssignExpression) { var b = (BinaryExpressionSyntax)syntax; if (b.Left is IdentifierNameSyntax) { return b.Right.IsLastIterationSufficient_Helper2(model, assume, iteratorVariable); } } return null; }
private static bool? IsLastIterationSufficient_Helper(this StatementSyntax syntax, ISemanticModel model, Assumptions assume, ISymbol iteratorVariable) { Contract.Requires(syntax != null); Contract.Requires(model != null); Contract.Requires(iteratorVariable != null); if (syntax is ContinueStatementSyntax) return true; if (syntax is BlockSyntax) { var b = (BlockSyntax)syntax; if (b.Statements.Count == 0) return true; if (b.Statements.Count == 1) return b.Statements.Single().IsLastIterationSufficient_Helper(model, assume, iteratorVariable); var m = syntax.Statements().Min(e => e.IsLastIterationSufficient_Helper(model, assume, iteratorVariable)); if (m != true) return m; var assigned = syntax.DescendantNodes() .Where(e => e.Kind == SyntaxKind.AssignExpression) .Cast<BinaryExpressionSyntax>() .Select(e => e.Left) .ToArray(); var assignedSymbols = assigned.Select(e => model.GetSymbolInfo(e)); var reads = syntax.DescendantNodes() .Except(assigned) .Select(e => model.GetSymbolInfo(e)); if (!reads.Intersect(assignedSymbols).Any()) return true; } if (syntax is ExpressionStatementSyntax) return ((ExpressionStatementSyntax)syntax).Expression.IsLastIterationSufficient_Helper(model, assume, iteratorVariable); return null; }
public static ImplicitSingleStatementBranches TryGetImplicitBranchSingleStatements(this IfStatementSyntax syntax, ISemanticModel model, Assumptions assume) { return TryGetIfStatementBranches_BothSingle(syntax) ?? TryGetIfStatementBranches_ConditionalJump(syntax) ?? TryGetIfStatementBranches_OverwritePrev(syntax, model, assume); }
public static ImplicitSingleStatementBranches TryGetIfStatementBranches_OverwritePrev(IfStatementSyntax syntax, ISemanticModel model, Assumptions assume) { var trueAction = syntax.Statement.CollapsedStatements().SingleOrDefaultAllowMany(); if (trueAction == null) return null; if (syntax.Else != null) return null; var prev = syntax.TryGetPrevStatement(); if (prev == null) return null; if (trueAction.EffectsOverwriteEffectsOf(prev, model, assume) != true) return null; return new ImplicitSingleStatementBranches(trueAction, prev, prev); }
public static bool? TryEvalAlternativeComparison(this ExpressionSyntax expression, ExpressionSyntax other, ISemanticModel model, Assumptions assume) { var val1 = expression.TryGetConstBoolValue(); var val2 = other.TryGetConstBoolValue(); if (val1.HasValue != val2.HasValue) return null; if (val1.HasValue) return val1.Value == val2.Value; if (expression is ParenthesizedExpressionSyntax) return ((ParenthesizedExpressionSyntax)expression).Expression.TryEvalAlternativeComparison(other, model, assume); if (other is ParenthesizedExpressionSyntax) return expression.TryEvalAlternativeComparison(((ParenthesizedExpressionSyntax)other).Expression, model, assume); if (expression.Kind == SyntaxKind.LogicalNotExpression) return !((PrefixUnaryExpressionSyntax)expression).Operand.TryEvalAlternativeComparison(other, model, assume); if (other.Kind == SyntaxKind.LogicalNotExpression) return !expression.TryEvalAlternativeComparison(((PrefixUnaryExpressionSyntax)other).Operand, model, assume); if (expression.HasSideEffects(model, assume) == false && expression.WithoutAnyTriviaOrInternalTrivia().ToString() == other.WithoutAnyTriviaOrInternalTrivia().ToString()) return true; return null; }
///<summary>Determines if the effects of executing the statement with/without the given previous statement are equivalent.</summary> public static bool? EffectsOverwriteEffectsOf(this StatementSyntax syntax, StatementSyntax prev, ISemanticModel model, Assumptions assume) { if (prev.IsGuaranteedToJumpOut()) return false; if (prev.HasSideEffects(model, assume) == false) return null; if (prev.IsAssignmentOrSingleInitialization()) { var rhs = prev.TryGetRHSOfAssignmentOrInit(); if (rhs.HasSideEffects(model, assume) == false && syntax.HasMatchingLHSOrRet(prev, model, assume)) return true; return null; } return null; }
public ActionResult SetAssumptions(Assumptions model) { // do something meaningful with the assumptions values for tax rates return RedirectToRoute("ReportWizardStep", new {token = model.Token, stepNumber = 5}); }
private bool? Effects(string pars, string statement, Assumptions? assume = null) { var tree = ("void f(" + pars + ") {" + statement + "}").ParseFunctionTreeFromString(); var statementN = tree.TestGetParsedFunctionBody(); return statementN.HasSideEffects(tree.GetTestSemanticModel(), assume ?? Assumptions.All); }
private void AssertOptimizes(Assumptions assumptions, string pars, string collection, string body, string result) { var tree1 = ("void f(" + pars + ") { foreach (var e in " + collection + ") { " + body + " }").ParseFunctionTreeFromStringUsingStandard(); var tree2 = ("void f(" + pars + ") { " + result + "}").ParseFunctionTreeFromStringUsingStandard(); var statement1 = (ForEachStatementSyntax)tree1.TestGetParsedFunctionStatements().Single(); var body2 = tree2.TestGetParsedFunctionBody(); var model = tree1.GetTestSemanticModel(); var simplifications = ForEachToFirstLast.GetSimplifications(statement1, model, assumptions).ToArray(); TestUtil.AssertSameSyntax(simplifications.Single().NewNode, body2); }
public bool IsEmpty() { return(!FixedVariables.Any() && !Assumptions.Any()); }
public static bool? IsAnyIterationSufficient(this ForEachStatementSyntax syntax, ISemanticModel model, Assumptions assume) { Contract.Requires(syntax != null); Contract.Requires(model != null); if (!assume.IterationHasNoSideEffects) return null; // shouldn't depend on iterator value if (model.AnalyzeStatementDataFlow(syntax.Statement).ReadInside.Contains(model.GetDeclaredSymbol(syntax))) return null; // probably false, but uses might happen to cancel // always jumping out of the loop on the first iteration, and independence from iterator value, should mean equivalence // unless the collection iterator has side-effects... but that's bad form, so probably true if (syntax.IsGuaranteedToJumpOut(includeContinue: false)) return true; return syntax.Statement.IsIdempotent(model, assume); }
public static bool? HasSideEffects(this StatementSyntax statement, ISemanticModel model, Assumptions assume) { if (statement is EmptyStatementSyntax) return false; var block = statement as BlockSyntax; if (statement is BlockSyntax) { if (((BlockSyntax)statement).Statements.Count == 0) return false; return ((BlockSyntax)statement).Statements.Select(e => e.HasSideEffects(model, assume)).Max(); } if (statement is ExpressionStatementSyntax) { return ((ExpressionStatementSyntax)statement).Expression.HasSideEffects(model, assume); } if (statement is IfStatementSyntax) { var s = (IfStatementSyntax)statement; return new[] { s.Condition.HasSideEffects(model, assume), s.Statement.HasSideEffects(model, assume), s.Else == null ? false : s.Else.Statement.HasSideEffects(model, assume) }.Max(); } return null; }
public static bool? HasSideEffects(this ExpressionSyntax expression, ISemanticModel model, Assumptions assume) { if (expression is IdentifierNameSyntax) return false; if (expression is LiteralExpressionSyntax) return false; if (expression is DefaultExpressionSyntax) return false; if (expression is MemberAccessExpressionSyntax) { var m = (MemberAccessExpressionSyntax)expression; if (!assume.PropertyGettersHaveNoSideEffects) return null; return m.Expression.HasSideEffects(model, assume); } if (expression is InvocationExpressionSyntax) { var i = (InvocationExpressionSyntax)expression; if (i.ArgumentList.Arguments.Any(e => e.RefOrOutKeyword != null)) return true; return i.ArgumentList.Arguments.Select(e => e.Expression.HasSideEffects(model, assume)).Append(i.Expression.HasSideEffects(model, assume), null).Max(); } if (expression is PostfixUnaryExpressionSyntax) { var u = (PostfixUnaryExpressionSyntax)expression; var unsafeOperators = new[] { SyntaxKind.PostDecrementExpression, SyntaxKind.PostIncrementExpression }; if (unsafeOperators.Contains(u.Kind)) return true; return null; } if (expression is PrefixUnaryExpressionSyntax) { var u = (PrefixUnaryExpressionSyntax)expression; var shouldBeSafeOperators = new[] { SyntaxKind.LogicalNotExpression, SyntaxKind.BitwiseNotExpression, SyntaxKind.NegateExpression, }; var unsafeOperators = new[] { SyntaxKind.PreDecrementExpression, SyntaxKind.PreIncrementExpression }; if (unsafeOperators.Contains(u.Kind)) return true; var ns = assume.OperatorsHaveNoSideEffects || _SpecialTypesWithSafeOperators.Contains(model.GetTypeInfo(u.Operand).Type.SpecialType); var op = ns && shouldBeSafeOperators.Contains(u.Kind) ? (bool?)false : null; return op.Max(u.Operand.HasSideEffects(model, assume)); } if (expression is BinaryExpressionSyntax) { var b = (BinaryExpressionSyntax)expression; if (AssignmentOperatorKinds.Contains(b.Kind)) return null; //probably true, but some cases like x += 0 are fine. var ns = assume.OperatorsHaveNoSideEffects || new[] {b.Left, b.Right}.All(e => _SpecialTypesWithSafeOperators.Contains(model.GetTypeInfo(e).Type.SpecialType)); var op = ns && ProbablySafeBinaryOperators.Contains(b.Kind) ? (bool?)false : null; return new[] { op, b.Left.HasSideEffects(model, assume), b.Right.HasSideEffects(model, assume) }.Max(); } if (expression is ParenthesizedExpressionSyntax) { return ((ParenthesizedExpressionSyntax)expression).Expression.HasSideEffects(model, assume); } if (expression is ConditionalExpressionSyntax) { var e = (ConditionalExpressionSyntax)expression; return new[] { e.Condition, e.WhenTrue, e.WhenFalse }.Select(x => x.HasSideEffects(model, assume)).Max(); } if (expression is ObjectCreationExpressionSyntax) { if (!assume.ConstructorsHaveNoSideEffects) return null; var e = (ObjectCreationExpressionSyntax)expression; return e.ArgumentList.Arguments.Select(a => a.Expression.HasSideEffects(model, assume)).Max(); } return null; }
public static bool HasMatchingLHSOrRet(this StatementSyntax expression, StatementSyntax other, ISemanticModel model, Assumptions assume) { Contract.Requires(model != null); if (expression == null) return false; if (other == null) return false; if (expression.IsReturnValue() && other.IsReturnValue()) return true; var lhs1 = expression.TryGetLHSExpOfAssignmentOrInit(); var lhs2 = other.TryGetLHSExpOfAssignmentOrInit(); if (lhs1 == null || lhs2 == null) return false; return lhs1.IsMatchingLHS(lhs2, model, assume); }
private static bool? IsLastIterationSufficient_Helper2(this ExpressionSyntax syntax, ISemanticModel model, Assumptions assume, ISymbol iteratorVariable) { Contract.Requires(syntax != null); Contract.Requires(model != null); Contract.Requires(iteratorVariable != null); var isConst = syntax.IsConst(model); if (isConst == true) return true; if (syntax is IdentifierNameSyntax && model.GetSymbolInfo(syntax).Symbol == iteratorVariable) return true; return null; }
/// <summary> /// Query on Wolfram Alpha using the specified /// </summary> /// <param name="query">The query you would like to search for on Wolfram Alpha</param> /// <returns>The results of the query</returns> public QueryResult Query(string query) { //http://api.wolframalpha.com/v2/query?input=xx&appid=xxxxx RestRequest request = CreateRequest("query", query); //Output if (Formats.HasElements()) { request.AddParameter("format", string.Join(",", Formats)); } if (OutputUnit != Unit.NotSet) { request.AddParameter("units", OutputUnit.ToString().ToLower()); } if (Assumptions.HasElements()) { foreach (string assumption in Assumptions) { request.AddParameter("assumption", assumption); } } //Filtering if (IncludePodIDs.HasElements()) { foreach (string include in IncludePodIDs) { request.AddParameter("includepodid", include); } } if (ExcludePodIDs.HasElements()) { foreach (string exclude in ExcludePodIDs) { request.AddParameter("excludepodid", exclude); } } if (PodTitles.HasElements()) { foreach (string podTitle in PodTitles) { request.AddParameter("podtitle", podTitle); } } if (PodIndex.HasElements()) { request.AddParameter("podindex", string.Join(",", PodIndex)); } if (Scanners.HasElements()) { request.AddParameter("scanner", string.Join(",", Scanners)); } //Timeout if (ParseTimeout >= Epsilon) { request.AddParameter("parsetimeout", ParseTimeout.ToString(_culture)); } if (ScanTimeout >= Epsilon) { request.AddParameter("scantimeout", ScanTimeout.ToString(_culture)); } if (PodTimeout >= Epsilon) { request.AddParameter("podtimeout", PodTimeout.ToString(_culture)); } if (FormatTimeout >= Epsilon) { request.AddParameter("formattimeout", FormatTimeout.ToString(_culture)); } //Async if (UseAsync) { request.AddParameter("async", UseAsync.ToString().ToLower()); } //Location if (IpAddress != null) { request.AddParameter("ip", IpAddress.ToString()); } if (!string.IsNullOrEmpty(Location)) { request.AddParameter("location", Location); } if (GPSLocation != null) { request.AddParameter("latlong", GPSLocation.ToString()); } //Size if (Width >= 1f) { request.AddParameter("width", Width); } if (MaxWidth >= 1f) { request.AddParameter("maxwidth", MaxWidth); } if (PlotWidth >= 1f) { request.AddParameter("plotwidth", PlotWidth); } if (Magnification >= 0.1f) { request.AddParameter("mag", Magnification.ToString(_culture)); } //Misc if (!string.IsNullOrEmpty(Signature)) { request.AddParameter("sig", Signature); } if (ReInterpret.HasValue) { request.AddParameter("reinterpret", ReInterpret.ToString().ToLower()); } if (IgnoreCase.HasValue) { request.AddParameter("ignorecase", IgnoreCase.ToString().ToLower()); } if (EnableTranslate.HasValue) { request.AddParameter("translation", EnableTranslate.ToString().ToLower()); } QueryResult results = GetResponse <QueryResult>(request); return(results); }
public QueryExecutionTypeTest(Assumptions expected) { this._expected = expected; }
public static bool? IsIdempotent(this StatementSyntax syntax, ISemanticModel model, Assumptions assume) { if (syntax is EmptyStatementSyntax) return true; if (syntax.IsGuaranteedToJumpOut()) return true; if (syntax is BlockSyntax) { var b = (BlockSyntax)syntax; if (b.Statements.Count == 0) return true; if (b.Statements.Count == 1) return b.Statements.Single().IsIdempotent(model, assume); var m = syntax.Statements().Min(e => e.IsIdempotent(model, assume)); if (m != true) return m; var assigned = syntax.DescendantNodes() .Where(e => e.Kind == SyntaxKind.AssignExpression) .Cast<BinaryExpressionSyntax>() .Select(e => e.Left) .ToArray(); var assignedSymbols = assigned.Select(e => model.GetSymbolInfo(e)); var reads = syntax.DescendantNodes() .Except(assigned) .Select(e => model.GetSymbolInfo(e)); if (reads.Intersect(assignedSymbols).Any()) return null; return true; } if (syntax is ExpressionStatementSyntax) return ((ExpressionStatementSyntax)syntax).Expression.IsIdempotent(model, assume); return null; }
public static bool IsMatchingLHS(this ExpressionSyntax lhs1, ExpressionSyntax lhs2, ISemanticModel model, Assumptions assume) { Contract.Requires(lhs1 != null); Contract.Requires(lhs2 != null); Contract.Requires(model != null); if (lhs1.Kind != lhs2.Kind) return false; if (lhs1.HasSideEffects(model, assume) != false) return false; if (lhs1 is SimpleNameSyntax) return ((SimpleNameSyntax)lhs1).PlainName == ((SimpleNameSyntax)lhs2).PlainName; var s1 = model.GetSymbolInfo(lhs1); var s2 = model.GetSymbolInfo(lhs2); if (s1.Symbol != s2.Symbol) return false; var inv1 = lhs1 as InvocationExpressionSyntax; var inv2 = lhs2 as InvocationExpressionSyntax; if (inv1 != null) { return inv1.Expression.IsMatchingLHS(inv2.Expression, model, assume) && inv1.ArgumentList.Arguments.Count == inv2.ArgumentList.Arguments.Count && inv1.ArgumentList.Arguments.Zip( inv2.ArgumentList.Arguments, (e1, e2) => e1.NameColon == null && e2.NameColon == null && e1.Expression.IsMatchingLHS(e2.Expression, model, assume) ).All(e => e); } if (lhs1 is MemberAccessExpressionSyntax) return ((MemberAccessExpressionSyntax)lhs1).Expression.IsMatchingLHS(((MemberAccessExpressionSyntax)lhs2).Expression, model, assume); return false; }
public static bool? IsIdempotent(this ExpressionSyntax syntax, ISemanticModel model, Assumptions assume) { if (syntax is ParenthesizedExpressionSyntax) return ((ParenthesizedExpressionSyntax)syntax).Expression.IsIdempotent(model, assume); if (syntax is IdentifierNameSyntax) return true; if (syntax is InvocationExpressionSyntax) return null; if (syntax is MemberAccessExpressionSyntax) { var m = (MemberAccessExpressionSyntax)syntax; if (!assume.PropertyGettersHaveNoSideEffects) return null; return m.Expression.IsIdempotent(model, assume); }; if (syntax.Kind == SyntaxKind.AssignExpression) { var b = (BinaryExpressionSyntax)syntax; if (b.Left is IdentifierNameSyntax) { var effects = b.Right.HasSideEffects(model, assume); if (effects == false) return true; } return null; } else if (AssignmentOperatorKinds.Contains(syntax.Kind)) { return null; } var isConst = syntax.IsConst(model); if (isConst == true) return true; return null; }
public static bool? IsLastIterationSufficient(this ForEachStatementSyntax syntax, ISemanticModel model, Assumptions assume) { Contract.Requires(syntax != null); Contract.Requires(model != null); if (!assume.IterationHasNoSideEffects) return null; // any iteration works? then so does the last one var anyIsGood = syntax.IsAnyIterationSufficient(model, assume); if (anyIsGood == true) return true; if (syntax.DescendantNodes(e => e is StatementSyntax).Any(e => e is BreakStatementSyntax || e is ReturnStatementSyntax || e is ThrowStatementSyntax)) return null; //loop might end before last iteration return syntax.Statement.IsLastIterationSufficient_Helper(model, assume, model.GetDeclaredSymbol(syntax)); }
public static bool? IsFirstIterationSufficient(this ForEachStatementSyntax syntax, ISemanticModel model, Assumptions assume) { Contract.Requires(syntax != null); Contract.Requires(model != null); if (!assume.IterationHasNoSideEffects) return null; // always breaks outs? then only the first iteration CAN happen if (syntax.Statement.IsGuaranteedToJumpOut(includeContinue: false)) return true; // any iteration works? then so does the first one var anyIsGood = syntax.IsAnyIterationSufficient(model, assume); if (anyIsGood == true) return true; return null; }
private static object[] Verify(Assumptions assumptions) { return(new object[] { assumptions }); }