예제 #1
0
        //Неглубокое копирование, все свойства копируются как ссылки, 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);
        }
예제 #2
0
        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));
        }
예제 #3
0
        //Вычисление значения, свое для каждого типа выражения
        //На входе стек расчета и расчетный параметр, содержащий этот 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;
        }
예제 #4
0
        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);
        }
예제 #5
0
        //Вычисление значения функций типа 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);
        }
예제 #6
0
 public FilterIf()
 {
     True  = new CalcValue(new SingleValue(new Moment(true)));
     False = new CalcValue(new SingleValue(new Moment(false)));
 }
예제 #7
0
 public void ChangeToElse()
 {
     True  = False;
     False = new CalcValue(new SingleValue(new Moment(false)));
 }
예제 #8
0
 //True, если cv - всегда false
 public bool IsFalse(CalcValue cv)
 {
     return(cv.Type == CalcValueType.Single && cv.SingleValue.Type == SingleType.Moment && !cv.SingleValue.Moment.Boolean);
 }
예제 #9
0
        //Вычисляет значение выражения
        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();
        }
예제 #10
0
        //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;
                            }
                        }
                    }
                }
            }
        }
예제 #11
0
 public VarRun(CalcValue calcValue)
 {
     CalcValue = calcValue;
 }