/// <summary> /// Constructs an incomplete phi. /// </summary> /// <param name="variableRef">The referenced variable.</param> /// <param name="phiBuilder">The phi builder.</param> public IncompletePhi( TVariable variableRef, PhiValue.Builder phiBuilder) { VariableRef = variableRef; PhiBuilder = phiBuilder; }
// // Implements an adapted version of the SSA-construction algorithm from the paper: // Simple and Efficient Construction of Static Single Assignment Form // /// <summary> /// Returns the value of the given variable by asking the predecessors. /// This method recursively constructs required phi nodes to break cycles. /// </summary> /// <param name="var">The variable reference.</param> /// <param name="markerProvider">A provider of new marker values.</param> /// <returns>The value of the given variable.</returns> private Value GetValueRecursive(TVariable var, ref MarkerProvider markerProvider) { Debug.Assert(Node.NumPredecessors > 0); Value value; if (Node.NumPredecessors == 1 && IsSealed) { var valueContainer = Parent[Node.Predecessors[0]]; value = valueContainer.GetValue(var, ref markerProvider); } else { // Insert the actual phi param var peekedValue = PeekValue(var, markerProvider.CreateMarker()); var phiBuilder = Builder.CreatePhi(peekedValue.Type); value = phiBuilder.PhiValue; var incompletePhi = new IncompletePhi(var, phiBuilder); if (IsSealed) { SetValue(var, value); value = SetupPhiArguments(incompletePhi, ref markerProvider); } else { incompletePhis[var] = incompletePhi; } } SetValue(var, value); return(value); }
/// <summary> /// Attempts to find a TNumber value for the TType given. If there is no error, but the TNumber reference /// given is still null after calling, then the TType is a TString (i.e. some arithmetic will work (+)). /// </summary> /// <param name="interpreter">The interpreter that the method is being called from.</param> /// <param name="number">The TNumber reference to assign the result to.</param> /// <param name="value">The TType to get a TNumber out of.</param> /// <returns>An exception if there was an error, otherwise null.</returns> private static TException AssignNumberValue(Interpreter interpreter, out TNumber number, TType value) { // Attempt to cast the TType 'value' argument to a TNumber. Failing that, check if it's a TString. // If the value is a TNumber or a TString, return null (i.e. no exception). If it's a TVariable then // work on the value of the TVariable, otherwise return an exception. number = value as TNumber; if ((number != null) || (value is TString)) { return(null); } TVariable variable = value as TVariable; if (variable != null) { value = variable.Value; number = value as TNumber; if ((number != null) || (value is TString)) { return(null); } return(new TException(interpreter, "Value of '" + variable.Identifier + "' is not a number", "it is of type '" + value.TypeName + "'")); } return(new TException(interpreter, "'" + value.ToCSString() + "' is not a number", "it is of type '" + value.TypeName + "'")); }
public void TestRegExReplace() { var tstr = new TVariable("") { regex_pattern = new Regex(@"(\S+)а,\s*(\S+)"), regex_replace = "район $2 города $1ы" }; tstr.Set("Москва, ЦАО"); Assert.AreEqual("район ЦАО города Москвы", tstr.value); var tnumeric = new TNumeric("") { regex_pattern = new Regex(@"(\d)(\d)(\d)"), regex_replace = "$2$3$1" }; ((TVariable)tnumeric).Set("123"); Assert.AreEqual(231f, tnumeric.value); var tdate = new TDate("") { regex_pattern = new Regex(@".* (\d{4}) года за (\d) месяц"), regex_replace = "1.$2.$1", format = "d.M.yyyy", lastday = true }; tdate.Set("отчёт 2020 года за 2 месяц"); Assert.AreEqual(new DateTime(2020, 2, 29), tdate.value); }
public AssertionObligation(APC pc, EdgeTag tag, TVariable cond, bool isAssume) { this.Apc = pc; this.Tag = tag; this.Condition = cond; this.IsAssume = isAssume; }
/// <summary> /// Returns the value of the given variable. /// </summary> /// <param name="var">The variable reference.</param> /// <param name="markerProvider">A provider of new marker values.</param> /// <returns>The value of the given variable.</returns> public Value GetValue(TVariable var, ref MarkerProvider markerProvider) { if (values.TryGetValue(var, out Value value)) { return(value); } return(GetValueRecursive(var, ref markerProvider)); }
public TVariable(TVariable origin) { evaluated = origin.evaluated; unevaluated = origin.unevaluated; ident = origin.ident; name = origin.name; scope = origin.scope; status = origin.status; persistence = origin.persistence; prev = origin.prev; }
public void TestOverrided() { var var = new TVariable("TEST"); var var_same = new TVariable("TEST"); var var_another = new TVariable("TEST_NEW"); Assert.IsTrue(var.Equals(var_same)); Assert.IsFalse(var.Equals(var_another)); Assert.IsFalse(var.Equals(null)); Assert.AreEqual(var.GetHashCode(), var.name.GetHashCode()); }
private protected void DefProperty(TVariable uvar, Project project) { if (uvar.status != ValStatus.Started) { SetGlobalProperty(project, uvar.ident, GetUVarValue(uvar.ident)); return; } if (uvar.prev != null && ((TVariable)uvar.prev).unevaluated != null) { TVariable prev = (TVariable)uvar.prev; SetGlobalProperty(project, uvar.ident, prev.evaluated ?? prev.unevaluated); } }
public void TestAction() { TVariable test = new TVariable("test"); TInterrupt stop = new TInterrupt(TInterrupt.Action.STOP_LOOP); TCondition cond = new TCondition { x = 15, mustBe = "25" }; cond.onFalse.Add(test); cond.onTrue.Add(stop); }
/// <summary> /// Peeks a value recursively. This method only retrieves a value /// from a predecessor but does not build any phi nodes. /// </summary> /// <param name="var">The variable reference.</param> /// <param name="marker">The current marker to break cycles.</param> /// <returns></returns> private Value PeekValue(TVariable var, int marker) { if (!IsProcessed || !Mark(marker)) { return(null); } if (values.TryGetValue(var, out Value value)) { return(value); } foreach (var predecessor in Block.Predecessors) { var valueContainer = Parent[predecessor]; Value result; if ((result = valueContainer.PeekValue(var, marker)) != null) { return(result); } } return(null); }
public static Dictionary <string, TVariable> getVariables() { Dictionary <string, TVariable> data = new Dictionary <string, TVariable>(); var tvariable = new TVariable("FIO"); tvariable.Set("Ivanov Ivan Ivanovich"); data.Add(tvariable.name, tvariable); var tnumeric = new TNumeric("SUMMA"); tnumeric.Set(12.3456f); data.Add(tnumeric.name, tnumeric); var tdate = new TDate("DATE"); tdate.Set("22.11.2001"); data.Add(tdate.name, tdate); return(data); }
public void TestRegEx() { var tstr = new TVariable("") { regex_pattern = new Regex("(\\S+) округа города (\\S+)"), regex_group = 2 }; tstr.Set("Центрального округа города Москвы"); Assert.AreEqual("Москвы", tstr.value); tstr.Set("Не подходящий условию текст"); Assert.AreEqual("", tstr.value); tstr.regex_group = 4; tstr.Set("Центрального округа города Москвы"); Assert.AreEqual("", tstr.value); var tnumeric = new TNumeric("") { regex_pattern = new Regex("Итого (\\S+)р.") }; ((TVariable)tnumeric).Set("Итого 800,45р. начислено"); Assert.AreEqual(800.45f, tnumeric.value); var tdate = new TDate("") { regex_pattern = new Regex("основан (.*) год"), format = "dd MMMM yyyy" }; ((TVariable)tdate).Set("Санкт-Петербург был основан 27 мая 1703 года"); Assert.AreEqual(new DateTime(1703, 05, 27), tdate.value); }
// // Implements an adapted version of the SSA-construction algorithm from the // paper: Simple and Efficient Construction of Static Single Assignment Form // /// <summary> /// Returns the value of the given variable by asking the predecessors. /// This method recursively constructs required phi nodes to break cycles. /// </summary> /// <param name="var">The variable reference.</param> /// <param name="markerProvider">A provider of new marker values.</param> /// <returns>The value of the given variable.</returns> private Value GetValueRecursive( TVariable var, ref MarkerProvider markerProvider) { Block.Assert(Block.Predecessors.Length > 0); Value value; if (Block.Predecessors.Length == 1 && IsSealed) { var valueContainer = Parent[Block.Predecessors[0]]; value = valueContainer.GetValue(var, ref markerProvider); } else { // Insert the actual phi value var peekedValue = PeekValue(var, markerProvider.CreateMarker()); // Let the phi point to the beginning of the current block var phiBuilder = Builder.CreatePhi( blockBuilder.BasicBlock.Location, peekedValue.Type); value = phiBuilder.PhiValue; var incompletePhi = new IncompletePhi(var, phiBuilder); if (IsSealed) { SetValue(var, value); value = SetupPhiArguments(incompletePhi, ref markerProvider); } else { incompletePhis[var] = incompletePhi; } } SetValue(var, value); return(value); }
/// <summary> /// Indexer used to retrieve the address where a variable has been injected, through a call /// to <see cref="Injector{TMemoryAlterationSetID, TCodeCave, TVariable}"/>.GetInjectedVariableAddress(). /// </summary> /// <param name="variableID">The identifier of the variable whose injected address is to be retrieved.</param> /// <returns>Returns the address where the given variable has been injected.</returns> public IntPtr this[TVariable variableID] { get { return(m_injector.GetInjectedVariableAddress(variableID).Address); } internal set { this.SendPropertyChangedNotification(DEFAULT_INDEXER_PROPERTY_NAME); } }
/// <summary> /// Does an equality comparison of one TType with another. /// </summary> /// <param name="interpreter">The interpreter that the method is being called from.</param> /// <param name="a">The left hand operand of the comparison.</param> /// <param name="b">The right hand operand of the comparison.</param> /// <param name="strict"> /// Whether the equality should be approximate or not. Give true for exact equality comparisons, and false for /// approximate equality comparisons of TNumbers. /// </param> /// <returns> /// An TBoolean containing the result of the comparison. Returns a TException or null when there is an error. /// </returns> public static TType Equal(Interpreter interpreter, TType a, TType b, bool strict) { // If arguments are TVariable, get their value. The values of the TVariable need to be compared, // not the TVariable objects themselves TVariable variable = a as TVariable; if (variable != null) { a = variable.Value; } variable = b as TVariable; if (variable != null) { b = variable.Value; } // Make sure that each operand is of the same type. TNumbers are an exception; any TNumber derivative can // be compared with any other TNumber derivative if ((a.TypeName != b.TypeName) && !((a is TNumber) && (b is TNumber))) { return(new TException(interpreter, "Type '" + a.TypeName + "' cannot be compared with type '" + b.TypeName + "'")); } // Using 'as' syntax instead of '()' for casting, because it looks cleaner. The result of the 'as' will not // return null because we've done the necessary check beforehand (i.e. if 'a' is a TNumber, then 'b' must // also be a TNumber) if (a is TNumber) { bool result; if (strict) { result = (System.Math.Abs((a as TNumber).TRealValue - (b as TNumber).TRealValue) < 0.000001); } else { double aVal = (a as TNumber).TRealValue, bVal = (b as TNumber).TRealValue; if ((System.Math.Round(aVal) == bVal) || (System.Math.Round(bVal) == aVal)) { result = true; } else { result = (System.Math.Abs(aVal - bVal) < 0.5); } } return(new TBoolean(result)); } else if (a is TBoolean) { return(new TBoolean((a as TBoolean).Value == (b as TBoolean).Value)); } else if (a is TString) { return(new TBoolean((a as TString).Value == (b as TString).Value)); } else if (a is TVariable) // i.e. if argument 'a' is a reference { return(new TBoolean(a == b)); } else if (a is TFunction) { TFunction funcA = a as TFunction, funcB = b as TFunction; return(new TBoolean( (funcA.HardCodedFunction == funcB.HardCodedFunction) && (funcA.CustomFunction == funcB.CustomFunction) && (funcA.Block == funcB.Block))); } else if (a is TNil) { return(new TBoolean(b is TNil)); } return(null); }
/// <summary> /// Takes two TNumbers or two TStrings (or up to two TVariables containing TNumbers or TStrings) and /// adds them together. /// </summary> /// <param name="interpreter">The interpreter that the method is being called from.</param> /// <param name="a">The left hand operand of the operation.</param> /// <param name="b">The right hand operand of the operation.</param> /// <returns> /// The TType resulting from the operation. An MExcpetion or null is returned when there is an error. /// </returns> public static TType Add(Interpreter interpreter, TType a, TType b) { // Convert arguments 'a' and 'b' into either a TNumber or a TString TNumber numberA, numberB; TString strA = null, strB = null; TException exception = AssignNumberValue(interpreter, out numberA, a); if (exception != null) { return(exception); } if (numberA == null) { // No errors yet, and numberA is null, so argument 'a' could be a TString or a TVariable // containing a TString strA = a as TString; if (strA == null) { TVariable variable = a as TVariable; if (variable != null) { strA = variable.Value as TString; } } } if ((numberA == null) && (strA == null)) // Nothing useful, return a TException { return(new TException(interpreter, "Value is not a number or string")); } // Same procedure for argument 'b' exception = AssignNumberValue(interpreter, out numberB, b); if (exception != null) { return(exception); } if (numberB == null) { strB = b as TString; if (strB == null) { TVariable variable = b as TVariable; if (variable != null) { strB = variable.Value as TString; } } } if ((numberB == null) && (strB == null)) { return(new TException(interpreter, "Value is not a number or string")); } // Attempt addition if both operands are the same type, otherwise return a TException if ((numberB == null) && (strA == null)) { return(new TException(interpreter, "Attempted addition of a string to a number")); } else if ((numberA == null) && (strB == null)) { return(new TException(interpreter, "Attempted addition of a number to a string")); } else if ((numberA == null) && (numberB == null)) { return(new TString(strA.Value + strB.Value)); } else { //The left hand operand decides the type of the returned value switch (numberA.TypeName) { case TType.T_INTEGER_TYPENAME: { // If the other operand is a fraction, treat this integer as a fraction (i.e. value/1) TFraction fraction = numberB as TFraction; if (fraction != null) { // Copy the right hand fraction and add the left hand integer to it fraction = new TFraction(fraction.Numerator, fraction.Denominator); fraction.Add(numberA.TIntegerValue, 1); return(fraction); } return(new TInteger(numberA.TIntegerValue + numberB.TIntegerValue)); } case TType.T_REAL_TYPENAME: return(new TReal(numberA.TRealValue + numberB.TRealValue)); case TType.T_FRACTION_TYPENAME: { // Create a copy of the left hand fraction TFraction fraction = numberA as TFraction; fraction = new TFraction(fraction.Numerator, fraction.Denominator); // Convert the right hand operand to a fraction long numerator, denominator; TFraction otherFraction = numberB as TFraction; if (otherFraction != null) // If it's a fraction, simply copy the values { numerator = otherFraction.Numerator; denominator = otherFraction.Denominator; } else { // Check if it's a TInteger first. It might not need to use DoubleToFraction if (numberB is TInteger) { numerator = numberB.TIntegerValue; denominator = 1; } else { Operations.Misc.DoubleToFraction(numberB.TRealValue, out numerator, out denominator); } } fraction.Add(numerator, denominator); return(fraction); } } } return(null); }
/// <summary> /// Removes the value of the given variable. /// </summary> /// <param name="var">The variable reference.</param> public void RemoveValue(TVariable var) => values.Remove(var);
protected void SetVar(TVariable var, object value) { exception_var = var; var.Set(value); stepScope[var.name] = var; }
/// <summary> /// Sets the given variable to the given value. /// </summary> /// <param name="var">The variable reference.</param> /// <param name="value">The value to set.</param> public void SetValue(TVariable var, Value value) => values[var] = value;
/// <summary> /// Returns the value of the given variable. /// </summary> /// <param name="var">The variable reference.</param> /// <param name="markerProvider">A provider of new marker values.</param> /// <returns>The value of the given variable.</returns> public Value GetValue(TVariable var, ref MarkerProvider markerProvider) => values.TryGetValue(var, out Value value) ? value : GetValueRecursive(var, ref markerProvider);
protected void AddVar(IDictionary <string, TVariable> dictionary, TVariable variable) { dictionary.Add(variable.name, variable); }
protected TVariable getVar(XElement xml, bool dynamic) { var name = xml.Attribute("name")?.Value ?? throw new NullReferenceException("Variable attribute 'name' can't be null!"); var ctype = xml.Attribute("type")?.Value ?? "string"; TVariable variable; switch (ctype) { case "numeric": variable = new TNumeric(name); break; case "date": variable = new TDate(name); break; default: variable = new TVariable(name); break; } variable.x = Int32.Parse(xml.Attribute("X")?.Value ?? throw new NullReferenceException("Variable attribute 'X' can't be null!")); if (!dynamic) { variable.y = Int32.Parse(xml.Attribute("Y")?.Value ?? throw new NullReferenceException("Variable attribute 'Y' can't be null!")); } variable.dynamic = dynamic; if (variable is TNumeric tnumeric) { var function = xml.Attribute("function"); if (function != null) { tnumeric.function = TNumeric.getFuncByString(function.Value); } } if (variable is TDate tdate) { var lastday = xml.Attribute("lastday"); var language = xml.Attribute("language"); var format = xml.Attribute("format"); if (lastday != null) { tdate.lastday = Boolean.Parse(lastday.Value); } if (language != null) { tdate.language = language.Value; } if (format != null) { tdate.format = format.Value; } } var regex_pattern = xml.Attribute("regex_pattern"); if (regex_pattern != null) { variable.regex_pattern = new Regex(regex_pattern.Value, RegexOptions.Compiled); var regex_group = xml.Attribute("regex_group"); variable.regex_group = int.Parse(regex_group?.Value ?? "1"); } return(variable); }
public AssertionObligation(APC pc, EdgeTag tag, TVariable cond) : this(pc, tag, cond, false) { }
/// <summary>Indexer used to retrieve the size of a variable, through a call to <see cref="Injector{TMemoryAlterationSetID, TCodeCave, TVariable}"/>.GetVariableSize().</summary> /// <param name="variableID">The identifier of the variable whose size is to be retrieved.</param> /// <returns>Returns the size of the given variable.</returns> public int this[TVariable variableID] { get { return(m_injector.GetVariableSize(variableID)); } internal set { this.SendPropertyChangedNotification(DEFAULT_INDEXER_PROPERTY_NAME); } }
protected void __IterateRecords(Worksheet worksheet, Action <Dictionary <string, TVariable> > callback, Action <int> guiCallback = null) { int begin = startY; int end = startY + buffer; var maxY = worksheet.UsedRange.Rows.Count + 1; bool EOF = false; Stopwatch watch = Stopwatch.StartNew(); stepScope.Clear(); foreach (var var in staticVars.Values) { SetVar(var, worksheet.Cells[var.y, var.x].Value); } watch.Stop(); Logger.debug("Заполнение массива локальных переменных: " + watch.ElapsedMilliseconds); int i = 0; bool skipRecord = false; bool stopLoop = false; object[,] tmp = null; var engine = new Jint.Engine(); engine.SetValue("skipRecord", (System.Action)(() => skipRecord = true)); engine.SetValue("stopLoop", (System.Action)(() => stopLoop = true)); engine.SetValue("throwError", (Action <string>)((message) => throw new ApplicationException($"JS ошибка: {message}"))); engine.SetValue("log", (Action <object>)Logger.info); engine.SetValue("info", (Action <string>)((msg) => guiLogger?.Invoke(DataLog.LogImage.INFO, msg))); engine.SetValue("warn", (Action <string>)((msg) => guiLogger?.Invoke(DataLog.LogImage.WARNING, msg))); engine.SetValue("getRow", (Func <object>)(() => tmp?.GetRow(i, 1))); var getCache = new Dictionary <string, object>(); engine.SetValue("cell", (Func <int, int, object>)((y, x) => { bool hasValue = getCache.TryGetValue($"{y}/{x}", out var obj); if (hasValue) { return(obj); } obj = worksheet.Cells[y, x]?.Value; getCache[$"{y}/{x}"] = obj; return(obj); })); engine.SetValue("set", (Func <string, object, bool>)((name, value) => { TVariable tVar = null; bool hasValue = false; if (!hasValue) { hasValue = dynamicVars.TryGetValue(name, out tVar); } if (!hasValue) { hasValue = staticVars.TryGetValue(name, out tVar); } if (hasValue) { SetVar(tVar, value); } return(hasValue); })); engine.SetValue("get", (Func <string, object>)((name) => { TVariable tVar = null; bool hasValue = false; if (!hasValue) { hasValue = dynamicVars.TryGetValue(name, out tVar); } if (!hasValue) { hasValue = staticVars.TryGetValue(name, out tVar); } if (hasValue) { return(tVar.value); } return(null); })); JsValue scriptEveryRow = null; JsValue scriptBefore = null; JsValue scriptAfter = null; if (jScript != null) { var jVal = engine.Execute(JSHelper.decodeXMLEntities(jScript)).GetCompletionValue(); if (jVal.IsObject()) { var jObj = jVal.AsObject(); scriptEveryRow = jObj.getOrDefault("row", null); scriptAfter = jObj.getOrDefault("after", null); scriptBefore = jObj.getOrDefault("before", null); } } Stopwatch watchTotal = Stopwatch.StartNew(); scriptBefore?.Invoke(); while (!EOF) { var range_start = worksheet.Cells[begin, 1]; var range_end = worksheet.Cells[end, endX]; var range = worksheet.Range[range_start, range_end]; tmp = range.Value; watch = Stopwatch.StartNew(); for (i = 1; i <= buffer; i++) { skipRecord = false; stopLoop = false; total++; foreach (TCondition cond in conditions) { var cellValue = tmp[i, cond.x]?.ToString() ?? ""; bool equal = false; if (cond.isRegex) { equal = Regex.Match(cellValue, cond.mustBe).Success; } else { equal = cellValue == cond.mustBe; } if (equal) { foreach (TAction item in cond.onTrue) { switch (item) { case TInterrupt tinter: switch (tinter.action) { case TInterrupt.Action.SKIP_RECORD: Logger.tracer($"Пропуск записи по условию: значение в ячейке x={cond.x} равно {cond.mustBe}"); skipRecord = true; break; case TInterrupt.Action.STOP_LOOP: Logger.tracer($"Выход из цикла по условию: значение в ячейке x={cond.x} равно {cond.mustBe}"); stopLoop = true; break; } continue; case TVariable var: SetVar(var, tmp[i, var.x]); break; } } } else { foreach (TAction item in cond.onFalse) { switch (item) { case TInterrupt tinter: switch (tinter.action) { case TInterrupt.Action.SKIP_RECORD: Logger.tracer($"Пропуск записи по условию: значение в ячейке x={cond.x} равно {cond.mustBe}"); skipRecord = true; break; case TInterrupt.Action.STOP_LOOP: Logger.tracer($"Выход из цикла по условию: значение в ячейке x={cond.x} равно {cond.mustBe}"); stopLoop = true; break; } continue; case TVariable var: SetVar(var, tmp[i, var.x]); break; } } } } if (total > maxY - startY + 1) { Logger.warn("Попытка выйти за пределы документа, выход из цикла"); EOF = true; break; } if (stopLoop) { Logger.debug("Выход из цикла по условию"); EOF = true; break; } if (skipRecord) { continue; } foreach (var var in dynamicVars.Values) { SetVar(var, tmp[i, var.x]); } scriptEveryRow?.Invoke(); if (skipRecord) { continue; } if (stopLoop) { Logger.debug("Выход из цикла вызван JS хуком row"); EOF = true; break; } callback(stepScope); } watch.Stop(); Logger.debug($"Сегмент в {buffer} элементов (с {begin} по {end}) обработан за {watch.ElapsedMilliseconds} мс"); guiCallback?.Invoke(total); begin += buffer; end += buffer; } watchTotal.Stop(); Logger.debug("Времени всего: " + watchTotal.ElapsedMilliseconds); Logger.debug("Строк обработано: " + total); Logger.debug("Размер буффера:" + buffer); scriptAfter?.Invoke(); }