public CalcValue(VarRun v) { Type = CalcValueType.Var; VarRun = v; }
//Вычисляет значение выражения public void Calculate() { var stack = new Stack <CalcValue>(); //Стек для расчетов var stackif = new Stack <FilterIf>(); //Стек для фильтров по if stackif.Push(new FilterIf()); int i = 0, n = CalcParam.Exprs.Length; while (i < n) { var expr = CalcParam.Exprs[i]; if (!(expr is ExprOp) || !((ExprOp)expr).IsFilterIf) { expr.ProcessCalcValue(stack, this); } else //Обработка операторов If, While и присваиваний { var par = new CalcValue[expr.ParamsCount]; for (int j = expr.ParamsCount - 1; j >= 0; j--) { par[j] = stack.Pop(); } var f = ((ExprOp)expr).Code; int adr = ((ExprOp)expr).LinkAddress; switch (f) { case "assign": case "assignr": case "assignv": case "assigni": case "assigns": CalcValue z = null; VarRun vr = null; switch (f) { case "assign": vr = par[0].VarRun; z = par[1]; break; case "assignr": vr = par[1].VarRun; z = par[0]; break; case "assignv": vr = par[0].VarRun; z = new CalcValue(); break; case "assigni": z = par[2]; int ii = par[1].SingleValue.LastMoment.Integer; vr = par[0].VarRun; if (vr.CalcValue == null) { vr.CalcValue = new CalcValue(new SortedDictionary <int, VarRun>()); } var ia = vr.CalcValue.IntArray; if (ia.ContainsKey(ii)) { vr = ia[ii]; } else { vr = new VarRun(); ia.Add(ii, vr); } break; case "assigns": z = par[2]; string ss = par[1].SingleValue.LastMoment.String; vr = par[0].VarRun; if (vr.CalcValue == null) { vr.CalcValue = new CalcValue(new SortedDictionary <string, VarRun>()); } var sa = vr.CalcValue.StringArray; if (sa.ContainsKey(ss)) { vr = sa[ss]; } else { vr = new VarRun(); sa.Add(ss, vr); } break; } if (z.Type == CalcValueType.Void || vr.CalcValue == null) { vr.CalcValue = z; } else { var ppar = new CalcValue[3]; ppar[0] = vr.CalcValue; ppar[1] = z; ppar[2] = stackif.Peek().True; vr.CalcValue = stackif.Peek().IsPoints ? ThreadCalc.Funs.GeneralFunction(ppar, vr.DataType, this, null, ThreadCalc.Funs.assignp) : ThreadCalc.Funs.GeneralFunction(ppar, vr.DataType, this, ThreadCalc.Funs.assign, null); } vr.CalcValue.ParentParam = z.ParentParam; break; case "begin": stackif.Push(stackif.Peek()); break; case "if": case "ifp": case "ifv": case "ifpv": stackif.Push(new FilterIf(stackif.Peek(), par[0], this, f == "ifp" || f == "ifpv")); if (f == "ifv" || f == "ifpv") { stack.Push(stackif.Peek().True); } if (IsFalse(stackif.Peek().True)) { if (f == "ifv" || f == "ifpv") { stack.Push(new CalcValue(new SingleValue(new Moment(false)))); } i = adr - 1; } break; case "while": case "whilep": stackif.Push(new FilterIf(stackif.Pop(), par[0], this, f == "whilep")); if (IsFalse(stackif.Peek().True)) { i = adr - 1; } break; case "else": case "elsev": stackif.Peek().ChangeToElse(); if (f == "elsev") { stack.Push(stackif.Peek().True); } if (IsFalse(stackif.Peek().True)) { if (f == "elsev") { stack.Push(new CalcValue(new SingleValue(new Moment(false)))); } i = adr - 1; } break; case "ret": i = adr - 1; break; case "end": bool ep = stackif.Pop().IsPoints; if (par.Length == 2) { stack.Push(par[1]); } if (par.Length == 4) { var dt = ((ExprOp)expr).DataType; if (IsFalse(par[0])) { stack.Push(par[3].ChangeDataType(dt)); } else if (IsFalse(par[2])) { stack.Push(par[1].ChangeDataType(dt)); } else { stack.Push(ep ? ThreadCalc.Funs.GeneralFunction(par, dt, this, null, ThreadCalc.Funs.endifp) : ThreadCalc.Funs.GeneralFunction(par, dt, this, ThreadCalc.Funs.endif, null)); } } break; case "for": var ef = ((ExprOp)expr); if (par[1].Type == CalcValueType.IntArray) { if (ef.Num == 0) { ef.IntInd = new List <int>(); foreach (var k in par[1].IntArray.Keys) { ef.IntInd.Add(k); } } if (ef.Num == ef.IntInd.Count) { ef.Num = 0; i = adr - 1; } else { par[0].VarRun.CalcValue = new CalcValue(new SingleValue(new Moment(ef.IntInd[ef.Num]))) { Error = par[1].Error } }; } else { if (ef.Num == 0) { ef.StringInd = new List <string>(); foreach (var k in par[1].StringArray.Keys) { ef.StringInd.Add(k); } } if (ef.Num == ef.StringInd.Count) { ef.Num = 0; i = adr - 1; } else { par[0].VarRun.CalcValue = new CalcValue(new SingleValue(new Moment(ef.StringInd[ef.Num]))) { Error = par[1].Error } }; } break; } } i++; } CalcValue = stack.Count > 0 ? stack.Pop() : new CalcValue(); }
//Сохранение одного параметра или одной переменной, возвращает словарь ключи - коды переменных, значения - величичны //code - полный код для для записи в DebugParams //debugType - Параметр, Подпараметр, Объект, Переменная, Сигнал, paramId - id параметра или подпараметра, для остальных 0 //c - расчетный параметр, v - переменная, всегда одно из двух, level - уровень вложенности, //saveToRec - сохранять в рекордсет и переменные, если false, то сам параметр не сохраняется но могут сохраняться его подпараметры и переменные public Dictionary <string, string> SaveValues(string code, string debugType, int paramId, CalcParamRun c, VarRun v, int level, bool saveToRec = true) { if (level > 3) { return(null); } var dic = new Dictionary <string, string>(); CalcValue cv; string adderr = ""; if (v != null) { cv = v.CalcValue; } else { if (c == null || c.CalcValue == null) { return(null); } if (_thread.IsSaveProperties) { foreach (var met in c.Methods.Values) { bool e = met.CalcParam.IsNotObject; AddDic(dic, SaveValues(code + "." + met.CalcParam.Code, e ? "Подпараметр" : "Порождаемый", e ? met.CalcParam.Id : 0, met, null, level + 1), met.CalcParam.Code); if (met.CalcValue.Error != null && adderr.IsEmpty()) { adderr = "Ошибки в " + (e ? "" : "порожденных ") + "подпараметрах"; } } } if (_thread.IsSaveVariables) { foreach (var vr in c.Vars.Dic) { if (vr.Key != "calc" || (c.CalcValue.Type == CalcValueType.Single && c.CalcValue.SingleValue != vr.Value.CalcValue.SingleValue)) { AddDic(dic, SaveValues(code + "." + vr.Key, "Переменная", 0, null, vr.Value, level + 1), vr.Key); } } } cv = c.CalcValue; } if (cv != null) { switch (cv.Type) { case CalcValueType.Void: case CalcValueType.Single: if ((saveToRec && cv.SingleValue != null) || !adderr.IsEmpty()) { ValuesToRec(code, debugType, paramId, dic, cv.SingleValue ?? new SingleValue(), adderr); dic.Add("", SvToStr(cv.SingleValue)); } break; case CalcValueType.IntArray: foreach (var a in cv.IntArray) { AddDic(dic, SaveValues(code + "[" + a.Key + "]", "Переменная", 0, null, a.Value, level + 1), null); } break; case CalcValueType.StringArray: foreach (var a in cv.StringArray) { AddDic(dic, SaveValues(code + "[" + a.Key + "]", "Переменная", 0, null, a.Value, level + 1), null); } break; } if (cv.ParentParam != null && cv.ParentParam.Inputs.Count != 0) { if (c == cv.ParentParam) { ValuesToRec(code, debugType, paramId, dic, new SingleValue()); } else { AddDic(dic, SaveValues(code + ":" + cv.ParentParam.CalcParam.Code, debugType, paramId, cv.ParentParam, null, level, false), null); } } } return(dic); }
//calc - CalcParam с формулой для расчета, inputs - список входных значений //owner - владелец, caller - параметр, из которого вызывается public CalcParamRun(CalcParam calc, CalcValue[] inputs, CalcParamRun owner, CalcParamRun caller) { CalcParam = calc; Owner = owner; Caller = caller; if (inputs == null || inputs.Length == 0) { Owner.Methods.Add(calc.Code, this); if (calc.IsNotObject) { calc.RunParam = this; } } StackDepth = caller == null ? 1 : caller.StackDepth + 1; if (StackDepth > 500) { CalcValue = new CalcValue(new SingleValue(new Moment(DataType.Value, new ErrorCalc("Переполнение стека", CalcParam.FullCode)))); return; } foreach (var k in calc.Vars.Keys) { Vars.Add(k, new VarRun(calc.Vars[k])); } if (inputs != null) { for (int i = 0; i < inputs.Length; i++) { VarRun v = Vars[calc.Inputs[i]]; v.CalcValue = inputs[i]; Inputs.Add(v); } } ThreadCalc = CalcParam.Project.ThreadCalc; //Сразу производится расчет Calculate(); //Добавление ошибок расчета в проект if (CalcParam.Inputs.Count == 0) { var errors = CalcParam.Project.CalcErrors; if (CalcValue.Type != CalcValueType.Single) { if (CalcValue.Error != null) { errors.Add(CalcValue.Error); } } else { var sv = CalcValue.SingleValue; if (sv.Moment != null && sv.Moment.Error != null) { errors.Add(sv.Moment.Error); } if (sv.Moments != null) { foreach (var m in sv.Moments) { if (m.Error != null) { errors.Add(m.Error); break; } } } if (sv.Segments != null) { foreach (var seg in sv.Segments) { if (seg.Error != null) { errors.Add(seg.Error); break; } } } } } }