//Неглубокое копирование, все свойства копируются как ссылки, parent - приписываемый владелец значения public CalcValue LinkClone(CalcParamRun parent = null) { CalcValue cv = null; switch (Type) { case CalcValueType.Var: cv = new CalcValue(VarRun); break; case CalcValueType.Single: cv = new CalcValue(SingleValue); break; case CalcValueType.IntArray: cv = new CalcValue(IntArray); break; case CalcValueType.StringArray: cv = new CalcValue(StringArray); break; case CalcValueType.Void: cv = new CalcValue(); break; } if (cv != null) { cv.Error = Error; cv.ParentParam = parent; } return(cv); }
protected override CalcValue GetValue(CalcParamRun calcRun) { CalcParamRun c = calcRun; var pr = calcRun.CalcParam.Project; if (IsMet) { c = MetOwner.ParentParam; while (c != null && !c.CalcParam.Methods.ContainsKey(Code)) { c = c.CalcValue.ParentParam; } } else { while (c.CalcParam != null && !c.CalcParam.Methods.ContainsKey(Code)) { c = c.Owner; } if (c.CalcParam == null) { c = pr.RootParam; } } CalcParamRun pp; if (c.Methods.ContainsKey(Code)) { pp = c.Methods[Code]; } else { var cp = c.CalcParam == null ? pr.CalcParamsCode[Code] : c.CalcParam.Methods[Code]; var cpr = new CalcParamRun(cp, Inputs, c, calcRun); pp = cpr; } //if (pp.CalcValue == null) return new CalcValue(); var cv = pp.CalcValue; if (cv.Error != null) { cv = cv.Clone(calcRun.CalcParam.FullCode); } MetOwner = null; return(cv.LinkClone(pp)); }
//Вычисление значения, свое для каждого типа выражения //На входе стек расчета и расчетный параметр, содержащий этот Expr public void ProcessCalcValue(Stack <CalcValue> stack, CalcParamRun calc) { CalcRun = calc; Inputs = new CalcValue[ParamsCount]; for (int i = ParamsCount - 1; i >= 0; i--) { Inputs[i] = stack.Pop(); } var em = this as ExprCalc; if (em != null && em.IsMet) { em.MetOwner = stack.Pop(); } var cv = GetValue(); //if (cv.Type != CalcValueType.Void) stack.Push(cv); Inputs = null; }
public FilterIf(FilterIf parent, CalcValue condition, CalcParamRun calc, bool isPoints) { var funs = calc.ThreadCalc.Funs; IsPoints = isPoints; var par = new CalcValue[2]; par[0] = parent.True; par[1] = condition; True = funs.GeneralFunction(par, DataType.Boolean, calc, funs.andbb, null); var parn = new[] { condition }; par[1] = funs.GeneralFunction(parn, DataType.Boolean, calc, funs.notb, null); False = funs.GeneralFunction(par, DataType.Boolean, calc, funs.andbb, null); var b = new CalcValue(new SingleValue(new Moment(true))); parn = new[] { True, b }; True = funs.GeneralFunction(parn, DataType.Boolean, calc, null, funs.deleterepetitionsub); parn = new[] { False, b }; False = funs.GeneralFunction(parn, DataType.Boolean, calc, null, funs.deleterepetitionsub); }
//Вычисление значения функций типа scalar и list public CalcValue GeneralFunction(CalcValue[] par, DataType dt, CalcParamRun calc, ScalarDelegate scalar, ListDelegate fun) { bool isScalar = scalar != null; int n = par.Count(); _calc = calc.CalcParam; Begin = calc.ThreadCalc.PeriodBegin; End = calc.ThreadCalc.PeriodEnd; _interpol = _calc.Interpolation; var sv = new SingleValue[n]; int ki = 0, ks = 0; for (int i = 0; i < n; i++) { var cvt = par[i].Type; if (ki == 0 && cvt == CalcValueType.IntArray) { ki = i; } if (ks == 0 && cvt == CalcValueType.StringArray) { ks = i; } if (cvt != CalcValueType.IntArray && cvt != CalcValueType.StringArray) { sv[i] = par[i].SingleValue; } } if (ki == 0 && ks == 0)//Нет массивов { if (isScalar) { return(new CalcValue(ScalarFunction(sv, dt, scalar))); } var ss = new SingleValue(); foreach (var s in sv) { ss.Error |= s.Error; } fun(sv, ss); if (ss.Type != SingleType.Segments && ss.Moment == null && ss.Moments == null) { ss.Moments = new List <Moment>(); } if (ss.Type == SingleType.Segments && ss.Segments == null) { ss.Segments = new List <Segment>(); } return(new CalcValue(ss)); } var cv = new CalcValue[n]; if (ki > 0)//Массивы с целыми индексами { var resi = new CalcValue(new SortedDictionary <int, VarRun>()); foreach (var key in par[ki].IntArray.Keys) { bool e = true; for (int i = 0; i < n; i++) { var p = par[i]; if (p.Type == CalcValueType.StringArray || (p.Type == CalcValueType.IntArray && !p.IntArray.ContainsKey(key))) { e = false; } else if (p.Type == CalcValueType.IntArray) { cv[i] = p.IntArray[key].CalcValue; } else { cv[i] = p; } } if (e) { var c = GeneralFunction(cv, dt, calc, scalar, fun); resi.Error |= c.Error; resi.IntArray.Add(key, new VarRun(c)); } } return(resi); } //Массивы со строковыми индексами var ress = new CalcValue(new SortedDictionary <int, VarRun>()); foreach (var key in par[ki].StringArray.Keys) { bool e = true; for (int i = 0; i < n; i++) { var p = par[i]; if (p.Type == CalcValueType.IntArray || (p.Type == CalcValueType.StringArray && !p.StringArray.ContainsKey(key))) { e = false; } else if (p.Type == CalcValueType.StringArray) { cv[i] = p.StringArray[key].CalcValue; } else { cv[i] = p; } } if (e) { var c = GeneralFunction(cv, dt, calc, scalar, fun); ress.Error |= c.Error; ress.StringArray.Add(key, new VarRun(c)); } } return(ress); }
public FilterIf() { True = new CalcValue(new SingleValue(new Moment(true))); False = new CalcValue(new SingleValue(new Moment(false))); }
public void ChangeToElse() { True = False; False = new CalcValue(new SingleValue(new Moment(false))); }
//True, если cv - всегда false public bool IsFalse(CalcValue cv) { return(cv.Type == CalcValueType.Single && cv.SingleValue.Type == SingleType.Moment && !cv.SingleValue.Moment.Boolean); }
//Вычисляет значение выражения 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(); }
//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; } } } } } }
public VarRun(CalcValue calcValue) { CalcValue = calcValue; }