// this needs to do what usually DefIL does and, in addition, create all the contained variables
        private void RegisterILAndContent(ParIL parIL, int iteration)
        {
            // first create the content: e.g. for ils_earns_loop3: yem_loop3, yse_loop3 ...
            Dictionary <string, double> content = new Dictionary <string, double>();

            foreach (var entry in parIL.GetFlatContent())
            {
                string origVarName = entry.varSpec.name;
                if (!RegisterVar(origVarName, parIL.description, iteration))
                {
                    return;
                }
                string storeName = ComposeStoreName(origVarName, iteration);
                // entry of new il: e.g. name: yem_loop3, factor: 1
                if (!content.ContainsKey(storeName))
                {
                    content.Add(storeName, entry.addFactor);                                  // the usual case
                }
                else
                {
                    content[storeName] += entry.addFactor;  // exception: e.g. il contains two ils, which share variables
                }
            }

            // ... then do do what usually DefIL does, i.e. register the incomelist (e.g. ils_earns_loop3)
            // note: this IL differs from its original by being "flat", i.e. ils are resolved into their variables
            infoStore.operandAdmin.RegisterIL(
                name: ComposeStoreName(parIL.name, iteration),
                creatorFun: DefFun.Store,
                description: parIL.description,
                content: content,
                warnIfNonMon: false);
        }
Example #2
0
        internal bool isMonetary = false;       // should this varil be formatted like monetary

        internal override void CheckAndPrepare(FunBase fun)
        {
            GetFootnoteNumbers(xmlValue, out string potentialIL);

            if (infoStore.operandAdmin.Exists(potentialIL) &&
                infoStore.operandAdmin.GetParType(potentialIL) == DefPar.PAR_TYPE.IL)
            {
                parIL = new ParIL(infoStore)
                {
                    xmlValue = xmlValue, description = this.description
                };
                parIL.CheckAndPrepare(fun);
            }
            else
            {
                parVal = new ParVar(infoStore)
                {
                    xmlValue = xmlValue, description = this.description
                };
                parVal.CheckAndPrepare(fun);
            }

            if (infoStore.operandAdmin.GetIsMonetary(GetName()))
            {
                isMonetary = true;
            }
        }
Example #3
0
        private bool CheckPrePost(ILSpecification ilSpecification, ParBase parPrefix, ParBase parPostfix, bool checkContent = true)
        {
            ilSpecification.prefix  = parPrefix?.xmlValue ?? string.Empty;
            ilSpecification.postfix = parPostfix?.xmlValue ?? string.Empty;
            if (string.IsNullOrEmpty(ilSpecification.prefix) && string.IsNullOrEmpty(ilSpecification.postfix))
            {
                return(true);    // if no prefix or postfix is defined, then all vars match naming by definition.
            }
            if (!checkContent)
            {
                return(true);
            }

            foreach (string v in ParIL.GetILComponents(ilSpecification.ilName, infoStore.operandAdmin))
            {
                if (v.StartsWith(ilSpecification.prefix, StringComparison.OrdinalIgnoreCase) &&
                    v.EndsWith(ilSpecification.postfix, StringComparison.OrdinalIgnoreCase))
                {
                    continue;
                }
                infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                {
                    isWarning = false,
                    message   = $"{description.Get()}: {ilSpecification.ilName}: contained variables must be named {GetFullVarName("*", ilSpecification)}; " +
                                $"variable {v} does not follow this rule"
                });
                return(false);
            }
            return(true);
        }
Example #4
0
        private List <string> GetCoreVars(ILSpecification ilSpecification)
        {
            List <string> cv = new List <string>();

            foreach (string v in ParIL.GetILComponents(ilSpecification.ilName, infoStore.operandAdmin))
            {
                cv.Add(GetCoreVarName(v, ilSpecification));
            }
            return(cv);
        }
Example #5
0
 private void PrepareDefILPar()
 {
     foreach (ParIL parIL in GetNonUniquePar <ParIL>(DefPar.DefOutput.DefIL))
     {   // see comment in PrepareOutVar upon creating a ParIL
         // note, that existence of IL and IL-content is checked in the "standard" parameter checking
         foreach (string v in ParIL.GetILComponents(parIL.name, infoStore.operandAdmin))
         {
             AddToOutList(v, parIL.description);
         }
     }
 }
        /// <summary>
        /// called by OperandAdmin.CheckRegistration, i.e. on checking if a variable/IL, e.g. used in a formula, is valid
        /// checks if this Store-function could be possibly "responsible" for this variable/IL
        /// (e.g. ask for yem_loop3 - Store is responsible if POSTLOOP-parameter=loop and there is a VAR-parameter=yem)
        /// if responsible, registration takes place as described above
        /// </summary>
        internal bool IsStoreOperand(string testOperandName)
        {
            if (storeType == STORETYPE.FIX)
            {
                return(false);                            // variables of POSTFIX-Stores are not produced "on demand" (see explanation above)
            }
            int iteration = NOTAP;

            foreach (ParVar par in GetNonUniquePar <ParVar>(DefPar.Store.Var))
            {
                if (CheckIfResponsibleAndGetIteration(par.name))
                {
                    RegisterVar(par.name, par.description, iteration); return(true);
                }
            }
            foreach (ParIL par in GetNonUniquePar <ParIL>(DefPar.Store.IL))
            {
                // first check for IL itself, e.g. ils_earns_loop7
                if (CheckIfResponsibleAndGetIteration(par.name))
                {
                    RegisterILAndContent(par, iteration); return(true);
                }
                // then check for the content, e.g. yem_loop7, yse_loop7
                foreach (string ilVar in ParIL.GetILComponents(par.name, infoStore.operandAdmin))
                {
                    if (CheckIfResponsibleAndGetIteration(ilVar))
                    {
                        RegisterVar(ilVar, par.description, iteration); return(true);
                    }
                }
            }
            return(false);

            bool CheckIfResponsibleAndGetIteration(string origName)
            {
                string storeName = ComposeStoreName(origName, NOTAP);

                return(testOperandName.StartsWith(storeName) &&
                       int.TryParse(testOperandName.Substring(storeName.Length), out iteration));
            }
        }
        internal bool IsProspectiveLoopOperand(string operand) // see InfoStore.IsProspectiveStoreOperand for description
        {                                                      // note that this can be called before (or after) PrepareNonCommonPar, therefore one cannot rely on variables (e.g. post, storeType, ...)
          // also note that we are only looking for the "running" operands, e.g. yem_loop, ils_earns_loop (i.e. without an iteration)
            ParBase parPostLoop = GetUniquePar <ParBase>(DefPar.Store.PostLoop);

            if (parPostLoop == null)
            {
                return(false);                     // most likely a PostFix-Store, thus not relevant
            }
            foreach (ParVar par in GetNonUniquePar <ParVar>(DefPar.Store.Var))
            {
                if (ComposeStoreName(par.xmlValue, NOTAP, parPostLoop.xmlValue).ToLower() == operand.ToLower())
                {
                    return(true);
                }
            }

            foreach (ParIL par in GetNonUniquePar <ParIL>(DefPar.Store.IL))
            {
                // first check for IL itself, e.g. ils_earns_loop
                string ili = ComposeStoreName(par.xmlValue, NOTAP, parPostLoop.xmlValue);
                if (ComposeStoreName(par.xmlValue, NOTAP, parPostLoop.xmlValue).ToLower() == operand.ToLower())
                {
                    return(true);
                }
                // then check for the content, e.g. yem_loop, yse_loop
                if (!infoStore.operandAdmin.Exists(par.xmlValue))
                {
                    continue;                                               // only check if il is already registered
                }
                foreach (string ilVar in ParIL.GetILComponents(par.xmlValue, infoStore.operandAdmin))
                {
                    if (ComposeStoreName(ilVar, NOTAP, parPostLoop.xmlValue).ToLower() == operand.ToLower())
                    {
                        return(true);
                    }
                }
            }
            return(false);
        }
Example #8
0
        private bool CloneILStructure(string ilName, string outIlName)
        {
            Dictionary <string, double> content = new Dictionary <string, double>();

            foreach (ParIL.Entry varIL in ParIL.ResolveILContent(ilName, infoStore.operandAdmin))
            {
                if (!varIL.isIL)
                {
                    string corename   = GetCoreVarName(varIL.varSpec.name, baseILSpecification);
                    string outVarName = GetFullVarName(corename, outILSpecification);
                    infoStore.operandAdmin.RegisterVar(
                        name: outVarName,
                        creatorFun: DefFun.Store,
                        description: description,
                        isMonetary: infoStore.operandAdmin.GetIsMonetary(varIL.varSpec.name),
                        isGlobal: infoStore.operandAdmin.GetIsGlobal(varIL.varSpec.name),
                        isWriteable: false, // cannot be used as output variable
                        setInitialised: true);
                    if (!infoStore.operandAdmin.Exists(outVarName))
                    {
                        return(false);                                            // registration failed
                    }
                    content.Add(outVarName, varIL.addFactor);
                }
                else
                {
                    string newILName = GetFullVarName(GetCoreVarName(varIL.ilName, baseILSpecification), outILSpecification);
                    CloneILStructure(varIL.ilName, newILName);
                    content.Add(newILName, varIL.addFactor);
                }
            }
            infoStore.operandAdmin.RegisterIL( // do what usually DefIL does, i.e. register the incomelist
                name: outIlName,
                creatorFun: DefFun.IlArithOp,
                description: description,
                content: content,
                warnIfNonMon: false);
            return(infoStore.operandAdmin.Exists(outIlName));
        }
        private bool RegisterVar(string origVarName, Description description, int iteration, string level = null, ParIL unitLoopILPar = null)
        {
            string storeVarName = ComposeStoreName(origVarName, iteration);

            if ((from v in vars select v.storeVar.name).Contains(storeVarName))
            {
                return(true); // this can easily happen by storing ILs with overlapping content
            }
            infoStore.operandAdmin.RegisterVar(
                name: storeVarName,
                creatorFun: DefFun.Store,
                description: description,
                isMonetary: infoStore.operandAdmin.GetIsMonetary(origVarName),
                isGlobal: false,
                isWriteable: false, // cannot be used as output variable
                setInitialised: true);

            if (!infoStore.operandAdmin.Exists(storeVarName))
            {
                return(false);                                              // registration failed
            }
            vars.Add(new StoreVar()
            {
                origVar = new VarSpec()
                {
                    name = origVarName
                },
                storeVar = new VarSpec()
                {
                    name = storeVarName
                },
                iteration     = iteration,
                level         = level,
                unitLoopILPar = unitLoopILPar
            });
            return(true);
        }
        internal override void CheckAndPrepare(FunBase fun)
        {
            if (FunIlArithOp.HandlesCheckAndPrepare(this))
            {
                return;                                            // IlArithOp has a special handling for the Formula parameter (see FunIlArithOp.cs)
            }
            if (xmlValue.Contains("}#"))
            {
                infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                {
                    isWarning = true, runTimeErrorId = description.funID, message = $"{description.Get()}: Footnotes should not be placed outside curly brackets! Please make sure that all footnotes are directly applied to a single operand."
                });
            }
            // for optimisation reasons handle #Amount and periods (#y, #w, ...) before parsing the formula:
            // alternatively one could allow for PAR_TYPE.NUMBER in the switch below, which would create a ParNumber that takes care
            // but then e.g. 1200#y*3 would, for each HH, ask for parNumber.GetValue()*3, while with this "preparsing" we just have 300
            string preParsedFormula = PreParse(xmlValue, fun);

            // parse the main formula
            try { parsedExpression = calc.CompileExpression(preParsedFormula); }
            catch (Exception e)
            {
                infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                {
                    isWarning = false, message = $"{description.Get()}: {e.Message}"
                }); return;
            }

            foreach (string op in calc.Variables.Keys)     // parse the formula ...
            {
                ParBase_FormulaComponent opPar = null;     // ... and prepare the operands

                GetFootnoteNumbers(op, out string opName); // temporarily remove potential footnotes to get the pure operand (e.g. yem#1->yem)

                // handle "partner:yem" or "head:yem"
                if (opName.Contains(":"))
                {
                    // this is not allowed outside DefTU!
                    if (description.fun.Name != DefFun.DefTu)
                    {
                        infoStore.communicator.ReportError(new Communicator.ErrorInfo()
                        {
                            isWarning = false, message = $"{description.Get()}: invalid use of target outside of a DefTU '{opName}'."
                        });
                    }
                    opName = opName.Substring(opName.IndexOf(":") + 1);
                }

                if (infoStore.operandAdmin.Exists(opName))
                {
                    switch (infoStore.operandAdmin.GetParType(opName))
                    {
                    //case DefPar.PAR_TYPE.NUMBER: opPar = new ParNumber(infoStore); break; // see PreParse above
                    case DefPar.PAR_TYPE.VAR: opPar = new ParVar(infoStore); break;

                    case DefPar.PAR_TYPE.IL: opPar = new ParIL(infoStore); break;

                    case DefPar.PAR_TYPE.QUERY: opPar = new ParQuery(infoStore); break;
                    }
                }
                else
                {
                    opPar = new ParVar(infoStore);  // if not yet in the operand-list, the only (not faulty) option is a data-variable
                }
                opPar.description = description;
                opPar.xmlValue    = op;
                opPar.CheckAndPrepare(fun);
                operands.Add(op, opPar);
            }
        }