private void ProcessAssignments(CLanguageParser.FunctionDefinitionContext context, int index) { List <RelationalExpression> conditionRelations = _relationService.GetConditionRelations(context); List <RelationalExpression> assignmentRelations = _relationService.GetAssignmentRelations(context); List <RelationalExpression> initDeclarationRelations = _relationService.GetInitializationRelations(context); List <string> nullCheckOperands = conditionRelations .Select(x => x.RightOperand == NULL_TOKEN ? x.LeftOperand : (x.LeftOperand == NULL_TOKEN ? x.RightOperand : null)) .Where(x => x != null) .ToList(); //todo: this is not right: tail = head->next; if a check is made for head //todo: further reconsider this: in the case of a "check null and return", further assignments can be replaced with old* correspondents //assignmentRelations // .RemoveAll(x => nullCheckOperands.Any(op => x.LeftOperand.ContainsInvariant($"{op}{POINTER_ACCESS_MARKER}") || // x.RightOperand.ContainsInvariant($"{op}{POINTER_ACCESS_MARKER}"))); var relations = new List <RelationalExpression>(); relations.AddRange(conditionRelations); relations.AddRange(assignmentRelations); string variablesSnapshot = GetVariablesSnapshot(relations); string snapshotFlagCheck = GetSnapshotsFlagCheckExpression(relations); //todo: fix indenting //var indent = index - CodeInput.Substring(0, index).InvariantLastIndexOf(Environment.NewLine); InsertionDeclaration snapshotAndCheckInsertion = new InsertionDeclaration(index + 1, $"{variablesSnapshot}{Environment.NewLine}{snapshotFlagCheck}".Indent(51)); List <IDeclaration> conditionReplacements = GetConditionReplacements(conditionRelations); List <IDeclaration> assignmentReplacements = GetCasAssignmentsReplacements(assignmentRelations); List <IDeclaration> initReplacements = GetInitDeclarationsReplacements(initDeclarationRelations); _updateTable.Add(snapshotAndCheckInsertion); conditionReplacements.ForEach(_updateTable.Add); assignmentReplacements.ForEach(_updateTable.Add); initReplacements.ForEach(_updateTable.Add); }
public override object VisitFunctionDefinition(CLanguageParser.FunctionDefinitionContext context) { var index = AddWhileLoop(context); ProcessAssignments(context, index); return(base.VisitFunctionDefinition(context)); }
public List <RelationalExpression> GetInitializationRelations(CLanguageParser.FunctionDefinitionContext context) { var relations = context .GetDescendants <CLanguageParser.InitDeclaratorContext>() .Where(x => x.ChildCount > 1) .Select(GetRelationalExpression) .ToList(); return(relations); }
/// <summary> /// Adds the "while loop for this method and returns the "while" loop insertion index. /// </summary> private int AddWhileLoop(CLanguageParser.FunctionDefinitionContext context) { int insertionIndex = int.MaxValue; string operationName = context.GetFirstDescendant <CLanguageParser.DirectDeclaratorContext>().GetName(); var localVariables = _dataStructure[operationName] .LocalVariables .OrderBy(x => x.Index) .ToList(); var variable = localVariables .Skip(1) //todo:why?? .Select((var, ix) => new { Variable = var, Index = ix }) .FirstOrDefault(x => x.Variable.LinksToGlobalState); if (variable != null) { insertionIndex = localVariables[variable.Index].Index; } var bodyContext = context.compoundStatement(); string body = bodyContext.GetContextText(); var globalVariableIndexes = _dataStructure .GlobalVariables .Select(x => new Regex($"[^a-zA-Z\\d:]{x.Name}[^a-zA-Z\\d:]")) .Select(x => x.IsMatch(body) ? x.Match(body).Index : -1) .Where(x => x > 0) .Select(x => x + bodyContext.GetStartIndex()); // If there is a global variable, we take the minimum between that index and the local variable that links to global state insertionIndex = Math.Min(insertionIndex, globalVariableIndexes.Any() ? globalVariableIndexes.Min() : insertionIndex); Method method = _dataStructure[operationName]; // If the local or global variable is embedded in an "if" statement, we will embed the "if" statement in the "while" loop as well if (method.IfStatements.Any()) { var index = insertionIndex; var surroundingIfStatements = method.IfStatements.Where(x => x.Context.ContainsIndex(index)); if (surroundingIfStatements.Any()) { insertionIndex = Math.Min(insertionIndex, surroundingIfStatements.Min(x => x.StartIndex)); } } string trimmedBody = body.Substring(0, insertionIndex - bodyContext.GetStartIndex()); insertionIndex = trimmedBody.InvariantLastIndexOf(Environment.NewLine) + bodyContext.GetStartIndex() + 2; int offset = trimmedBody.Length - trimmedBody.InvariantLastIndexOf(Environment.NewLine) - 2; _updateTable.Add(new InsertionDeclaration(insertionIndex, new string(' ', offset) + "while (true) {")); _updateTable.Add(new InsertionDeclaration(context.GetStopIndex() - 1, "}")); return(insertionIndex); }
public List <RelationalExpression> GetConditionRelations(CLanguageParser.FunctionDefinitionContext context) { var relations = context .GetDescendants <CLanguageParser.SelectionStatementContext>() .SelectMany(x => x.expression().GetLeafDescendants <CLanguageParser.EqualityExpressionContext>()) .Select(x => (object)x.Parent) .Select(GetRelationalExpression) .ToList(); return(relations); }
public override object VisitFunctionDefinition(CLanguageParser.FunctionDefinitionContext context) { string functionName = context.GetFirstDescendant <CLanguageParser.DirectDeclaratorContext>().GetName(); var bodyContext = context.compoundStatement(); var operation = new Method(functionName) { StartIndex = bodyContext.Start.StartIndex, EndIndex = bodyContext.Stop.StopIndex, Context = bodyContext }; DataStructure.AddOperation(operation); return(base.VisitFunctionDefinition(context)); }
public List <RelationalExpression> GetAssignmentRelations(CLanguageParser.FunctionDefinitionContext context) { var relations = context .GetDescendants <CLanguageParser.AssignmentExpressionContext>() .Where(x => x.ChildCount > 1) .Select(GetRelationalExpression) .ToList(); foreach (var relation in relations) { //todo: this is incorrect since we need to track only those relations from the root to this relation; //todo "if (condition) {1} else {2;3}" => for relation "3" we don't track relation "1" relation.PreviousRelations = relations .Where(x => x.LeftOperandSnapshot != null || x.RightOperandSnapshot != null) .Where(x => x.RightOperandInterval.End <= relation.LeftOperandInterval.Start) .ToList(); } return(relations); }