/// <summary> /// Translates an assignment statement, e.g. "x = a + b". /// </summary> public override StringBuilder VisitAssignmentExpression(AssignmentExpression assignmentExpr) { var result = assignmentExpr.Left.AcceptVisitor(this); // assignment operator type mapping var opAssignment = new Dictionary <AssignmentOperatorType, string> { { AssignmentOperatorType.Assign, String.Empty }, { AssignmentOperatorType.Add, "+" }, { AssignmentOperatorType.BitwiseAnd, "&" }, { AssignmentOperatorType.BitwiseOr, "|" }, { AssignmentOperatorType.Divide, "/" }, { AssignmentOperatorType.ExclusiveOr, "^" }, { AssignmentOperatorType.Modulus, "%" }, { AssignmentOperatorType.Multiply, "*" }, { AssignmentOperatorType.ShiftLeft, "<<" }, { AssignmentOperatorType.ShiftRight, ">>" }, { AssignmentOperatorType.Subtract, "-" }, }; result.Assign(opAssignment[assignmentExpr.Operator]); var rightRes = assignmentExpr.Right.AcceptVisitor(this); // add value to RefVariables if this is an "constant initialization" if (assignmentExpr.Operator == AssignmentOperatorType.Assign) { if (assignmentExpr.Left.IsType <MemberReferenceExpression>()) { var left = (MemberReferenceExpression)assignmentExpr.Left; var memberRef = left.Annotation <IMemberDefinition>(); if (RefVariables.Any(var => var.Definition == memberRef)) { var refVar = RefVariables.Last(var => var.Definition == memberRef); if (assignmentExpr.Right.IsType <ObjectCreateExpression>() || assignmentExpr.Right.IsType <PrimitiveExpression>() || assignmentExpr.Right.IsType <ArrayCreateExpression>()) { RefVariables[RefVariables.IndexOf(refVar)].Value = rightRes; } else { RefVariables[RefVariables.IndexOf(refVar)].Value = "Exception"; } } } } return(result.Append(rightRes)); }
public void Validate() { //Test 1: Depending on Statement type the number of RefVars is fixed switch (statementType) { case Common.StatementType.FullAssignment: if (RefVariables.Count < 1 || RefVariables.Count > 3) { throw new ValidatorException("Number of referenced variables does not match statement type in instruction " + ID); } break; case Common.StatementType.UnaryAssignment: case Common.StatementType.PointerAssignment: case Common.StatementType.ConditionalJump: if (RefVariables.Count < 1 || RefVariables.Count > 2) { throw new ValidatorException("Number of referenced variables does not match statement type in instruction " + ID); } break; case Common.StatementType.Copy: if (RefVariables.Count < 1 || RefVariables.Count > 2) { throw new ValidatorException("Number of referenced variables does not match statement type in instruction " + ID); } if (RefVariables.First().pointer != RefVariables.Last().pointer) { throw new ValidatorException("You are trying to copy a pointer value to a non-pointer variable (or vice-versa) in COPY instruction " + ID); } break; case Common.StatementType.UnconditionalJump: case Common.StatementType.NoOperation: if (RefVariables.Count != 0) { throw new ValidatorException("Number of referenced variables does not match statement type in instruction " + ID); } break; case Common.StatementType.Procedural: if (RefVariables.Count > 1) { throw new ValidatorException("Number of referenced variables does not match statement type in instruction " + ID); } break; case Common.StatementType.IndexedAssignment: if (RefVariables.Count < 2 || RefVariables.Count > 3) { throw new ValidatorException("Number of referenced variables does not match statement type in instruction " + ID); } break; default: throw new ValidatorException("Invalid statement type in instruction " + ID); } // Test 2: TAC text by Regexp switch (statementType) { case Common.StatementType.FullAssignment: // var := var op var OR var:= var op number if (Regex.IsMatch(TACtext, @"^[vtcfp]_ID_[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12} := [vtcfp]_ID_[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12} [-+*/%] ([vtcfp]_ID_[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12})$", RegexOptions.None) | Regex.IsMatch(TACtext, @"^[vtcfp]_ID_[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12} := [vtcfp]_ID_[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12} [-+*/%] ([-+]?\d+)$", RegexOptions.None)) { break; } else { throw new ValidatorException("The instruction Text value does not match its StatementType property. Instruction: " + ID); } case Common.StatementType.UnaryAssignment: // var := op var if (Regex.IsMatch(TACtext, @"^[vtcfp]_ID_[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12} := [-!] [vtcfp]_ID_[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12}$", RegexOptions.None)) { break; } else { throw new ValidatorException("The instruction Text value does not match its StatementType property. Instruction: " + ID); } case Common.StatementType.Copy: // var := var OR var := number if (Regex.IsMatch(TACtext, @"^[vtcfp]_ID_[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12} := [vtcfp]_ID_[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12}$", RegexOptions.None) | Regex.IsMatch(TACtext, @"^[vtcfp]_ID_[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12} := ([-+]?\d+)$", RegexOptions.None)) { break; } else { throw new ValidatorException("The instruction Text value does not match its StatementType property. Instruction: " + ID); } case Common.StatementType.UnconditionalJump: // goto ID_GUID if (Regex.IsMatch(TACtext, @"^goto ID_[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12}$", RegexOptions.None)) { break; } else { throw new ValidatorException("The instruction Text value does not match its StatementType property. Instruction: " + ID); } case Common.StatementType.ConditionalJump: // if var relop var goto ID_GUID OR if var relop number goto ID_GUID if (Regex.IsMatch(TACtext, @"^if [vtcfp]_ID_[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12} (?:==|!=|>|<|>=|<=) [vtcfp]_ID_[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12} goto ID_[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12}$", RegexOptions.None) | Regex.IsMatch(TACtext, @"^if [vtcfp]_ID_[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12} (?:==|!=|>|<|>=|<=) ([-+]?\d+) goto ID_[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12}$", RegexOptions.None)) { break; } else { throw new ValidatorException("The instruction Text value does not match its StatementType property. Instruction: " + ID); } case Common.StatementType.Procedural: // param var OR param number if (Regex.IsMatch(TACtext, @"^param [vtcfp]_ID_[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12}$", RegexOptions.None) | Regex.IsMatch(TACtext, @"^param ([-+]?\d+)$", RegexOptions.None) | // call some_string decimal Regex.IsMatch(TACtext, @"^call \w+ \d+$", RegexOptions.None) | // call ID_GUID decimal Regex.IsMatch(TACtext, @"^call ID_[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12} \d+$", RegexOptions.None) | // return Regex.IsMatch(TACtext, @"^return$", RegexOptions.None) | // return number Regex.IsMatch(TACtext, @"^return ([-+]?\d+)$", RegexOptions.None) | // return var Regex.IsMatch(TACtext, @"^return [vtcfp]_ID_[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12}$", RegexOptions.None) | // retrieve var Regex.IsMatch(TACtext, @"^retrieve [vtcfp]_ID_[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12}$", RegexOptions.None) | // enter ID_GUID Regex.IsMatch(TACtext, @"^enter ID_[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12}$", RegexOptions.None) | // leave ID_GUID Regex.IsMatch(TACtext, @"^leave ID_[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12}$", RegexOptions.None) ) { break; } else { throw new ValidatorException("The instruction Text value does not match its StatementType property. Instruction: " + ID); } case Common.StatementType.IndexedAssignment: // var := var[number] OR var[number] := var OR var[number] = number; //if (Regex.IsMatch(TACtext, @"^[vtcfp]_ID_[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12} := [vtcfp]_ID_[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12} \[\d+\]$", RegexOptions.None) | // Regex.IsMatch(TACtext, @"^[vtcfp]_ID_[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12} \[\d+\] := [vtcfp]_ID_[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12}$", RegexOptions.None) | // Regex.IsMatch(TACtext, @"^[vtcfp]_ID_[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12} \[\d+\] := ([-+]?\d+)$", RegexOptions.None)) // break; //else // throw new ValidatorException("The instruction Text value does not match its StatementType property. Instruction: " + ID); throw new ValidatorException("The 'IndexedAssignment' statement type is not supported. Please use 'PointerAssignment' instead. Instruction: " + ID); case Common.StatementType.PointerAssignment: // var := & var if (Regex.IsMatch(TACtext, @"^[vtcfp]_ID_[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12} := & [vtcfp]_ID_[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12}$", RegexOptions.None) | // var := * var Regex.IsMatch(TACtext, @"^[vtcfp]_ID_[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12} := \* [vtcfp]_ID_[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12}$", RegexOptions.None) | // * var := var Regex.IsMatch(TACtext, @"^\* [vtcfp]_ID_[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12} := [vtcfp]_ID_[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12}$", RegexOptions.None) | // * var = number Regex.IsMatch(TACtext, @"^\* [vtcfp]_ID_[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12} := ([-+]?\d+)$", RegexOptions.None)) { break; } else { throw new ValidatorException("The instruction Text value does not match its StatementType property. Instruction: " + ID); } case Common.StatementType.NoOperation: if (Regex.IsMatch(TACtext, @"^nop$", RegexOptions.None)) { break; } else { throw new ValidatorException("The instruction Text value does not match its StatementType property. Instruction: " + ID); } default: break; } // Test 3: RETRIEVE instruction must be preceeded by CALL int num = parent.Instructions.BinarySearch(this); if (Regex.IsMatch(TACtext, @"^retrieve [vtcfp]_ID_[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12}$", RegexOptions.None)) { if (num == 0) { throw new ValidatorException("The first instruction in a basic block cannot be 'retrieve'. Instruction: " + ID); } else if (!( Regex.IsMatch(parent.Instructions[num - 1].TACtext, @"^call \w+ \d+$", RegexOptions.None) || Regex.IsMatch(parent.Instructions[num - 1].TACtext, @"^call ID_[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12} \d+$", RegexOptions.None) )) { throw new ValidatorException("Instruction 'retrieve' must be directly preceeded by instruction 'call'. Instruction: " + ID); } } }