Result GetResult(AstNode node) { if (node is BlockStatement) { return(GetResultFromBlock((BlockStatement)node)); } Result result = new Result(); for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) { Result childResult = GetResult(child); result.CostInCheckedContext += childResult.CostInCheckedContext; result.NodesToInsertInCheckedContext += childResult.NodesToInsertInCheckedContext; result.CostInUncheckedContext += childResult.CostInUncheckedContext; result.NodesToInsertInUncheckedContext += childResult.NodesToInsertInUncheckedContext; } Expression expr = node as Expression; if (expr != null) { CheckedUncheckedAnnotation annotation = expr.Annotation <CheckedUncheckedAnnotation>(); if (annotation != null) { // If the annotation requires this node to be in a specific context, add a huge cost to the other context // That huge cost gives us the option to ignore a required checked/unchecked expression when there wouldn't be any // solution otherwise. (e.g. "for (checked(M().x += 1); true; unchecked(M().x += 2)) {}") if (annotation.IsChecked) { result.CostInUncheckedContext += new Cost(10000, 0); } else { result.CostInCheckedContext += new Cost(10000, 0); } } // Embed this node in an checked/unchecked expression: if (expr.Parent is ExpressionStatement) { // We cannot use checked/unchecked for top-level-expressions. } else if (expr.Role.IsValid(Expression.Null)) { // We use '<' so that expressions are introduced on the deepest level possible (goal 3) var costIfWrapWithChecked = result.CostInCheckedContext.WrapInCheckedExpr(); var costIfWrapWithUnchecked = result.CostInUncheckedContext.WrapInCheckedExpr(); if (costIfWrapWithChecked < result.CostInUncheckedContext) { result.CostInUncheckedContext = costIfWrapWithChecked; result.NodesToInsertInUncheckedContext = result.NodesToInsertInCheckedContext + new InsertedExpression(expr, true); } else if (costIfWrapWithUnchecked < result.CostInCheckedContext) { result.CostInCheckedContext = costIfWrapWithUnchecked; result.NodesToInsertInCheckedContext = result.NodesToInsertInUncheckedContext + new InsertedExpression(expr, false); } } } return(result); }
Result GetResult(AstNode node) { if (node is BlockStatement) { return(GetResultFromBlock((BlockStatement)node)); } Result result = new Result(); for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) { Result childResult = GetResult(child); result.CostInCheckedContext += childResult.CostInCheckedContext; result.NodesToInsertInCheckedContext += childResult.NodesToInsertInCheckedContext; result.CostInUncheckedContext += childResult.CostInUncheckedContext; result.NodesToInsertInUncheckedContext += childResult.NodesToInsertInUncheckedContext; } Expression expr = node as Expression; if (expr != null) { CheckedUncheckedAnnotation annotation = expr.Annotation <CheckedUncheckedAnnotation>(); if (annotation != null) { // If the annotation requires this node to be in a specific context, set the cost of the other context to infinite. if (annotation.IsChecked) { result.CostInUncheckedContext = Cost.Infinite; } else { result.CostInCheckedContext = Cost.Infinite; } } // Embed this node in an checked/unchecked expression: // We use '<' so that expressions are introduced on the deepest level possible (goal 3) if (result.CostInCheckedContext + new Cost(0, 1) < result.CostInUncheckedContext) { result.CostInUncheckedContext = result.CostInCheckedContext + new Cost(0, 1); result.NodesToInsertInUncheckedContext = result.NodesToInsertInCheckedContext + new InsertedExpression(expr, true); } else if (result.CostInUncheckedContext + new Cost(0, 1) < result.CostInCheckedContext) { result.CostInCheckedContext = result.CostInUncheckedContext + new Cost(0, 1); result.NodesToInsertInCheckedContext = result.NodesToInsertInUncheckedContext + new InsertedExpression(expr, false); } } return(result); }
Result GetResult(AstNode node) { if (node is BlockStatement) { return(GetResultFromBlock((BlockStatement)node)); } Result result = new Result(); for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) { Result childResult = GetResult(child); result.CostInCheckedContext += childResult.CostInCheckedContext; result.NodesToInsertInCheckedContext += childResult.NodesToInsertInCheckedContext; result.CostInUncheckedContext += childResult.CostInUncheckedContext; result.NodesToInsertInUncheckedContext += childResult.NodesToInsertInUncheckedContext; } Expression expr = node as Expression; if (expr != null) { CheckedUncheckedAnnotation annotation = expr.Annotation <CheckedUncheckedAnnotation>(); if (annotation != null) { // If the annotation requires this node to be in a specific context, add a huge cost to the other context // That huge cost gives us the option to ignore a required checked/unchecked expression when there wouldn't be any // solution otherwise. (e.g. "for (checked(M().x += 1); true; unchecked(M().x += 2)) {}") if (annotation.IsChecked) { result.CostInUncheckedContext += new Cost(10000, 0); } else { result.CostInCheckedContext += new Cost(10000, 0); } } // Embed this node in an checked/unchecked expression: if (expr.Parent is ExpressionStatement) { // We cannot use checked/unchecked for top-level-expressions. // However, we could try converting a compound assignment (checked(a+=b);) or unary operator (checked(a++);) // back to its old form. if (expr.Annotation <ReplaceMethodCallsWithOperators.RestoreOriginalAssignOperatorAnnotation>() != null) { // We use '<' so that expressions are introduced on the deepest level possible (goal 3) if (result.CostInCheckedContext + new Cost(1, 1) < result.CostInUncheckedContext) { result.CostInUncheckedContext = result.CostInCheckedContext + new Cost(1, 1); result.NodesToInsertInUncheckedContext = result.NodesToInsertInCheckedContext + new ConvertCompoundAssignment(expr, true); } else if (result.CostInUncheckedContext + new Cost(1, 1) < result.CostInCheckedContext) { result.CostInCheckedContext = result.CostInUncheckedContext + new Cost(1, 1); result.NodesToInsertInCheckedContext = result.NodesToInsertInUncheckedContext + new ConvertCompoundAssignment(expr, false); } } } else if (expr.Role.IsValid(Expression.Null)) { // We use '<' so that expressions are introduced on the deepest level possible (goal 3) if (result.CostInCheckedContext + new Cost(0, 1) < result.CostInUncheckedContext) { result.CostInUncheckedContext = result.CostInCheckedContext + new Cost(0, 1); result.NodesToInsertInUncheckedContext = result.NodesToInsertInCheckedContext + new InsertedExpression(expr, true); } else if (result.CostInUncheckedContext + new Cost(0, 1) < result.CostInCheckedContext) { result.CostInCheckedContext = result.CostInUncheckedContext + new Cost(0, 1); result.NodesToInsertInCheckedContext = result.NodesToInsertInUncheckedContext + new InsertedExpression(expr, false); } } } return(result); }