def checkFormulaRules(val, formula, nameVariables):
    if not (formula.hasRule(Aspect.CONCEPT) or formula.source(Aspect.CONCEPT)):
        if XmlUtil.hasDescendant(formula, XbrlConst.formula, "concept"):
            val.modelXbrl.error("xbrlfe:incompleteConceptRule",
                _("Formula %(xlinkLabel)s concept rule does not have a nearest source and does not have a child element"),
                modelObject=formula, xlinkLabel=formula.xlinkLabel)
        else:
            val.modelXbrl.error("xbrlfe:missingConceptRule",
                _("Formula %(xlinkLabel)s omits a rule for the concept aspect"),
                modelObject=formula, xlinkLabel=formula.xlinkLabel)
    if not isinstance(formula, ModelTuple):
        if (not (formula.hasRule(Aspect.SCHEME) or formula.source(Aspect.SCHEME)) or
            not (formula.hasRule(Aspect.VALUE) or formula.source(Aspect.VALUE))):
            if XmlUtil.hasDescendant(formula, XbrlConst.formula, "entityIdentifier"):
                val.modelXbrl.error("xbrlfe:incompleteEntityIdentifierRule",
                    _("Formula %(xlinkLabel)s entity identifier rule does not have a nearest source and does not have either a @scheme or a @value attribute"),
                    modelObject=formula, xlinkLabel=formula.xlinkLabel)
            else:
                val.modelXbrl.error("xbrlfe:missingEntityIdentifierRule",
                    _("Formula %(xlinkLabel)s omits a rule for the entity identifier aspect"),
                    modelObject=formula, xlinkLabel=formula.xlinkLabel)
        if not (formula.hasRule(Aspect.PERIOD_TYPE) or formula.source(Aspect.PERIOD_TYPE)):
            if XmlUtil.hasDescendant(formula, XbrlConst.formula, "period"):
                val.modelXbrl.error("xbrlfe:incompletePeriodRule",
                    _("Formula %(xlinkLabel)s period rule does not have a nearest source and does not have a child element"),
                    modelObject=formula, xlinkLabel=formula.xlinkLabel)
            else:
                val.modelXbrl.error("xbrlfe:missingPeriodRule",
                    _("Formula %(xlinkLabel)s omits a rule for the period aspect"),
                    modelObject=formula, xlinkLabel=formula.xlinkLabel)
        # for unit need to see if the qname is statically determinable to determine if numeric
        concept = val.modelXbrl.qnameConcepts.get(formula.evaluateRule(None, Aspect.CONCEPT))
        if concept is None: # is there a source with a static QName filter
            sourceFactVar = nameVariables.get(formula.source(Aspect.CONCEPT))
            if isinstance(sourceFactVar, ModelFactVariable):
                for varFilterRels in (formula.groupFilterRelationships, sourceFactVar.filterRelationships):
                    for varFilterRel in varFilterRels:
                        _filter = varFilterRel.toModelObject
                        if isinstance(_filter,ModelConceptName):  # relationship not constrained to real filters
                            for conceptQname in _filter.conceptQnames:
                                concept = val.modelXbrl.qnameConcepts.get(conceptQname)
                                if concept is not None and concept.isNumeric:
                                    break
        if concept is not None: # from concept aspect rule or from source factVariable concept Qname filter
            if concept.isNumeric:
                if not (formula.hasRule(Aspect.MULTIPLY_BY) or formula.hasRule(Aspect.DIVIDE_BY) or formula.source(Aspect.UNIT)):
                    if XmlUtil.hasDescendant(formula, XbrlConst.formula, "unit"):
                        val.modelXbrl.error("xbrlfe:missingSAVForUnitRule",
                            _("Formula %(xlinkLabel)s unit rule does not have a source and does not have a child element"),
                            modelObject=formula, xlinkLabel=formula.xlinkLabel)
                    else:
                        val.modelXbrl.error("xbrlfe:missingUnitRule",
                            _("Formula %(xlinkLabel)s omits a rule for the unit aspect"),
                            modelObject=formula, xlinkLabel=formula.xlinkLabel)
            elif (formula.hasRule(Aspect.MULTIPLY_BY) or formula.hasRule(Aspect.DIVIDE_BY) or 
                  formula.source(Aspect.UNIT, acceptFormulaSource=False)):
                val.modelXbrl.error("xbrlfe:conflictingAspectRules",
                    _("Formula %(xlinkLabel)s has a rule for the unit aspect of a non-numeric concept %(concept)s"),
                    modelObject=formula, xlinkLabel=formula.xlinkLabel, concept=concept.qname)
            aspectPeriodType = formula.evaluateRule(None, Aspect.PERIOD_TYPE)
            if ((concept.periodType == "duration" and aspectPeriodType == "instant") or
                (concept.periodType == "instant" and aspectPeriodType in ("duration","forever"))):
                val.modelXbrl.error("xbrlfe:conflictingAspectRules",
                    _("Formula %(xlinkLabel)s has a rule for the %(aspectPeriodType)s period aspect of a %(conceptPeriodType)s concept %(concept)s"),
                    modelObject=formula, xlinkLabel=formula.xlinkLabel, concept=concept.qname, aspectPeriodType=aspectPeriodType, conceptPeriodType=concept.periodType)
        
        # check dimension elements
        for eltName, dim, badUsageErr, missingSavErr in (("explicitDimension", "explicit", "xbrlfe:badUsageOfExplicitDimensionRule", "xbrlfe:missingSAVForExplicitDimensionRule"),
                                                         ("typedDimension", "typed", "xbrlfe:badUsageOfTypedDimensionRule", "xbrlfe:missingSAVForTypedDimensionRule")):
            for dimElt in XmlUtil.descendants(formula, XbrlConst.formula, eltName):
                dimQname = qname(dimElt, dimElt.get("dimension"))
                dimConcept = val.modelXbrl.qnameConcepts.get(dimQname)
                if dimQname and (dimConcept is None or (not dimConcept.isExplicitDimension if dim == "explicit" else not dimConcept.isTypedDimension)):
                    val.modelXbrl.error(badUsageErr,
                        _("Formula %(xlinkLabel)s dimension attribute %(dimension)s on the %(dimensionType)s dimension rule contains a QName that does not identify an (dimensionType)s dimension."),
                        modelObject=formula, xlinkLabel=formula.xlinkLabel, dimensionType=dim, dimension=dimQname,
                        messageCodes=("xbrlfe:badUsageOfExplicitDimensionRule", "xbrlfe:badUsageOfTypedDimensionRule"))
                elif not XmlUtil.hasChild(dimElt, XbrlConst.formula, "*") and not formula.source(Aspect.DIMENSIONS, dimElt):
                    val.modelXbrl.error(missingSavErr,
                        _("Formula %(xlinkLabel)s %(dimension)s dimension rule does not have any child elements and does not have a SAV for the %(dimensionType)s dimension that is identified by its dimension attribute."),
                        modelObject=formula, xlinkLabel=formula.xlinkLabel, dimensionType=dim, dimension=dimQname,
                        messageCodes=("xbrlfe:missingSAVForExplicitDimensionRule", "xbrlfe:missingSAVForTypedDimensionRule"))
        
        # check aspect model expectations
        if formula.aspectModel == "non-dimensional":
            unexpectedElts = XmlUtil.descendants(formula, XbrlConst.formula, ("explicitDimension", "typedDimension"))
            if unexpectedElts:
                val.modelXbrl.error("xbrlfe:unrecognisedAspectRule",
                    _("Formula %(xlinkLabel)s aspect model, %(aspectModel)s, includes an rule for aspect not defined in this aspect model: %(undefinedAspects)s"),
                    modelObject=formula, xlinkLabel=formula.xlinkLabel, aspectModel=formula.aspectModel, undefinedAspects=", ".join([elt.localName for elt in unexpectedElts]))

    # check source qnames
    for sourceElt in ([formula] + 
                     XmlUtil.descendants(formula, XbrlConst.formula, "*", "source","*")):
        if sourceElt.get("source") is not None:
            qnSource = qname(sourceElt, sourceElt.get("source"), noPrefixIsNoNamespace=True)
            if qnSource == XbrlConst.qnFormulaUncovered:
                if formula.implicitFiltering != "true":
                    val.modelXbrl.error("xbrlfe:illegalUseOfUncoveredQName",
                        _("Formula %(xlinkLabel)s, not implicit filtering element has formulaUncovered source: %(name)s"),
                        modelObject=formula, xlinkLabel=formula.xlinkLabel, name=sourceElt.localName) 
            elif qnSource not in nameVariables:
                val.modelXbrl.error("xbrlfe:nonexistentSourceVariable",
                    _("Variable set %(xlinkLabel)s, source %(name)s is not in the variable set"),
                    modelObject=formula, xlinkLabel=formula.xlinkLabel, name=qnSource)
            else:
                factVariable = nameVariables.get(qnSource)
                if isinstance(factVariable, ModelVariableSet):
                    pass
                elif not isinstance(factVariable, ModelFactVariable):
                    val.modelXbrl.error("xbrlfe:nonexistentSourceVariable",
                        _("Variable set %(xlinkLabel)s, source %(name)s not a factVariable but is a %(element)s"),
                        modelObject=formula, xlinkLabel=formula.xlinkLabel, name=qnSource, element=factVariable.localName)
                elif factVariable.fallbackValue is not None:
                    val.modelXbrl.error("xbrlfe:bindEmptySourceVariable",
                        _("Formula %(xlinkLabel)s: source %(name)s is a fact variable that has a fallback value"),
                        modelObject=formula, xlinkLabel=formula.xlinkLabel, name=qnSource)
                elif sourceElt.localName == "formula" and factVariable.bindAsSequence == "true":
                    val.modelXbrl.error("xbrlfe:defaultAspectValueConflicts",
                        _("Formula %(xlinkLabel)s: formula source %(name)s is a fact variable that binds as a sequence"),
                        modelObject=formula, xlinkLabel=formula.xlinkLabel, name=qnSource)
dataset/ETHPy150Open Arelle/Arelle/arelle/ValidateFormula.py/checkFormulaRules/original