From 47f1620e5d67fdb836686a441b39797210b66423 Mon Sep 17 00:00:00 2001 From: Alexandre Hajjar Date: Fri, 24 Apr 2020 20:32:24 +0200 Subject: [PATCH] =?UTF-8?q?WIP=20=E2=9A=99=EF=B8=8F=20Detect=20cycles:=20f?= =?UTF-8?q?inish=20all=20node=20types=20and=20visitors?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- publicodes/source/cyclesLib.ts | 750 +++++++++++++++++++++--- publicodes/source/mecanisms/arrondi.tsx | 2 +- 2 files changed, 682 insertions(+), 70 deletions(-) diff --git a/publicodes/source/cyclesLib.ts b/publicodes/source/cyclesLib.ts index a9c4e0eac..418561f28 100644 --- a/publicodes/source/cyclesLib.ts +++ b/publicodes/source/cyclesLib.ts @@ -4,6 +4,7 @@ */ import R from 'ramda' +import { ArrondiExplanation } from './mecanisms/arrondi' import { ParsedRule, ParsedRules } from './types' type OnOff = 'oui' | 'non' @@ -24,15 +25,14 @@ type ASTNode = { [_: string]: {} | undefined } type RuleNode = /* ASTNode & */ ParsedRule type Value = ASTNode & { - nodeValue: number | string - constant?: boolean + nodeValue: number | string | boolean } export function isValue(node: ASTNode): node is Value { const value = node as Value return ( - (typeof value.nodeValue === 'string' || - typeof value.nodeValue === 'number') && - (value.constant === undefined || typeof value.constant === 'boolean') + typeof value.nodeValue === 'string' || + typeof value.nodeValue === 'number' || + typeof value.nodeValue === 'boolean' ) } @@ -62,13 +62,29 @@ export function isPossibilities(node: ASTNode): node is Possibilities { isOnOff(possibilities['une possibilité']) ) } +type Possibilities2 = ASTNode & { + [index: number]: string // short dotted name + 'choix obligatoire'?: OnOff + 'une possibilité': OnOff +} +export function isPossibilities2(node: ASTNode): node is Possibilities2 { + const possibilities2 = node as Possibilities2 + return ( + R.all( + ([k, v]) => isNaN(parseInt(k, 10)) || typeof v === 'string', + R.toPairs(possibilities2) + ) && + (possibilities2['choix obligatoire'] === undefined || + isOnOff(possibilities2['choix obligatoire'])) && + isOnOff(possibilities2['une possibilité']) + ) +} type Reference = ASTNode & { category: 'reference' name: Name partialReference: Name dottedName: Name - unit: {} | undefined } export function isReference( node: ASTNode @@ -92,10 +108,13 @@ export function isRecalcul( node: ASTNode ): node is Recalcul { const recalcul = node as Recalcul + const isReferenceSpec = isReference as ( + node: ASTNode + ) => node is Reference return ( typeof recalcul.explanation === 'object' && typeof recalcul.explanation.recalcul === 'object' && - isReference(recalcul.explanation.recalcul as ASTNode) && + isReferenceSpec(recalcul.explanation.recalcul as ASTNode) && typeof recalcul.explanation.amendedSituation === 'object' // [XXX] - We would like to do // && R.all(isDottedName, R.keys(recalcul.explanation.amendedSituation)) @@ -119,18 +138,21 @@ export function isAbstractMechanism(node: ASTNode): node is AbstractMechanism { type EncadrementMech = AbstractMechanism & { name: 'encadrement' - valeur: { - explanation: Array - [_: string]: {} | undefined + explanation: { + valeur: ASTNode + plafond: ASTNode + plancher: ASTNode } } export function isEncadrementMech(node: ASTNode): node is EncadrementMech { const encadrementMech = node as EncadrementMech return ( isAbstractMechanism(encadrementMech) && - typeof encadrementMech.valeur === 'object' && - encadrementMech.valeur.explanation instanceof Array && - encadrementMech.name === 'encadrement' + encadrementMech.name == 'encadrement' && + typeof encadrementMech.explanation === 'object' && + encadrementMech.explanation.valeur !== undefined && + encadrementMech.explanation.plafond !== undefined && + encadrementMech.explanation.plancher !== undefined ) } @@ -143,14 +165,12 @@ export function isSommeMech(node: ASTNode): node is SommeMech { return ( isAbstractMechanism(sommeMech) && sommeMech.name === 'somme' && - typeof sommeMech.explanation === 'object' + sommeMech.explanation instanceof Array ) } type ProduitMech = AbstractMechanism & { name: 'produit' - type: 'numeric' - unit: {} explanation: { assiette: ASTNode plafond: ASTNode @@ -161,9 +181,8 @@ type ProduitMech = AbstractMechanism & { export function isProduitMech(node: ASTNode): node is ProduitMech { const produitMech = node as ProduitMech return ( + isAbstractMechanism(produitMech) && produitMech.name === 'produit' && - produitMech.type === 'numeric' && - produitMech.unit !== undefined && typeof produitMech.explanation === 'object' && typeof produitMech.explanation.assiette === 'object' && typeof produitMech.explanation.plafond === 'object' && @@ -172,15 +191,308 @@ export function isProduitMech(node: ASTNode): node is ProduitMech { ) } +type VariationsMech = AbstractMechanism & { + name: 'variations' + explanation: { + condition: ASTNode + consequence: ASTNode + }[] +} +export function isVariationsMech(node: ASTNode): node is VariationsMech { + const variationsMech = node as VariationsMech + return ( + isAbstractMechanism(variationsMech) && + variationsMech.name === 'variations' && + variationsMech.explanation instanceof Array && + variationsMech.explanation.every( + variation => + typeof variation === 'object' && + variation.condition !== undefined && + variation.consequence !== undefined + ) + ) +} + +type AllegementMech = AbstractMechanism & { + name: 'allègement' + explanation: { + abattement: ASTNode + assiette: ASTNode + décote: + | undefined + | { + plafond: ASTNode + taux: ASTNode + } + franchise: ASTNode + plafond: ASTNode + } +} +export function isAllegementMech(node: ASTNode): node is AllegementMech { + const allegementMech = node as AllegementMech + return ( + isAbstractMechanism(allegementMech) && + allegementMech.name === 'allègement' && + typeof allegementMech.explanation === 'object' && + allegementMech.explanation.abattement !== undefined && + allegementMech.explanation.assiette !== undefined && + allegementMech.explanation.franchise !== undefined && + allegementMech.explanation.plafond !== undefined && + (allegementMech.explanation.décote === undefined || + (typeof allegementMech.explanation.décote === 'object' && + allegementMech.explanation.décote.plafond !== undefined && + allegementMech.explanation.décote.taux !== undefined)) + ) +} + +type BaremeMech = AbstractMechanism & { + name: 'barème' + explanation: { + assiette: ASTNode + multiplicateur: ASTNode + tranches: { + plafond: ASTNode + taux: ASTNode + }[] + } +} +export function isBaremeMech(node: ASTNode): node is BaremeMech { + const baremeMech = node as BaremeMech + return ( + isAbstractMechanism(baremeMech) && + baremeMech.name === 'barème' && + typeof baremeMech.explanation === 'object' && + baremeMech.explanation.assiette !== undefined && + baremeMech.explanation.multiplicateur !== undefined && + baremeMech.explanation.tranches instanceof Array && + baremeMech.explanation.tranches.every( + tranche => + typeof tranche === 'object' && + tranche.plafond !== undefined && + tranche.taux !== undefined + ) + ) +} + +type InversionNumMech = AbstractMechanism & { + name: 'inversion numérique' + avec: Array // Actually: short dotted name + explanation: { + avec: Array> + } +} +export function isInversionNumMech( + node: ASTNode +): node is InversionNumMech { + const inversionNumMech = node as InversionNumMech + const isReferenceSpec = isReference as ( + node: ASTNode + ) => node is Reference + return ( + isAbstractMechanism(inversionNumMech) && + inversionNumMech.name === 'inversion numérique' && + inversionNumMech.avec instanceof Array && + typeof inversionNumMech.explanation === 'object' && + inversionNumMech.explanation.avec instanceof Array && + R.all(isReferenceSpec, inversionNumMech.explanation.avec) + ) +} + +type ArrondiMech = AbstractMechanism & { + name: 'arrondi' + explanation: ArrondiExplanation +} +export function isArrondiMech(node: ASTNode): node is ArrondiMech { + const arrondiMech = node as ArrondiMech + return ( + isAbstractMechanism(arrondiMech) && + arrondiMech.name === 'arrondi' && + typeof arrondiMech.explanation === 'object' && + arrondiMech.explanation.decimals !== undefined && + arrondiMech.explanation.value !== undefined + ) +} + +type MaxMech = AbstractMechanism & { + name: 'le maximum de' + explanation: Array +} +export function isMaxMech(node: ASTNode): node is MaxMech { + const maxMech = node as MaxMech + return ( + isAbstractMechanism(maxMech) && + maxMech.name === 'le maximum de' && + maxMech.explanation instanceof Array + ) +} + +type MinMech = AbstractMechanism & { + name: 'le minimum de' + explanation: Array +} +export function isMinMech(node: ASTNode): node is MinMech { + const minMech = node as MinMech + return ( + isAbstractMechanism(minMech) && + minMech.name === 'le minimum de' && + minMech.explanation instanceof Array + ) +} + +type ComposantesMech = AbstractMechanism & { + name: 'composantes' + explanation: Array +} +export function isComposantesMech(node: ASTNode): node is ComposantesMech { + const composantesMech = node as ComposantesMech + return ( + isAbstractMechanism(composantesMech) && + composantesMech.name === 'composantes' && + composantesMech.explanation instanceof Array + ) +} + +type UneConditionsMech = AbstractMechanism & { + name: 'une de ces conditions' + explanation: Array +} +export function isUneConditionsMech(node: ASTNode): node is UneConditionsMech { + const uneConditionsMech = node as UneConditionsMech + return ( + isAbstractMechanism(uneConditionsMech) && + uneConditionsMech.name === 'une de ces conditions' && + uneConditionsMech.explanation instanceof Array + ) +} + +type ToutesConditionsMech = AbstractMechanism & { + name: 'toutes ces conditions' + explanation: Array +} +export function isToutesConditionsMech( + node: ASTNode +): node is ToutesConditionsMech { + const toutesConditionsMech = node as ToutesConditionsMech + return ( + isAbstractMechanism(toutesConditionsMech) && + toutesConditionsMech.name === 'toutes ces conditions' && + toutesConditionsMech.explanation instanceof Array + ) +} + +type SyncMech = AbstractMechanism & { + name: 'synchronisation' + API: {} +} +export function isSyncMech(node: ASTNode): node is SyncMech { + const syncMech = node as SyncMech + return isAbstractMechanism(syncMech) && syncMech.name === 'synchronisation' +} + +type GrilleMech = AbstractMechanism & { + name: 'grille' + explanation: { + assiette: ASTNode + multiplicateur: ASTNode + tranches: { + montant: ASTNode + plafond: ASTNode + }[] + } +} +export function isGrilleMech(node: ASTNode): node is GrilleMech { + const grilleMech = node as GrilleMech + return ( + isAbstractMechanism(grilleMech) && + grilleMech.name === 'grille' && + typeof grilleMech.explanation === 'object' && + grilleMech.explanation.assiette !== undefined && + grilleMech.explanation.multiplicateur !== undefined && + grilleMech.explanation.tranches instanceof Array && + grilleMech.explanation.tranches.every( + tranche => + typeof tranche === 'object' && + tranche.montant !== undefined && + tranche.plafond !== undefined + ) + ) +} + +type TauxProgMech = AbstractMechanism & { + name: 'taux progressif' + explanation: { + assiette: ASTNode + multiplicateur: ASTNode + tranches: { + plafond: ASTNode + taux: ASTNode + }[] + } +} +export function isTauxProgMech(node: ASTNode): node is TauxProgMech { + const tauxProgMech = node as TauxProgMech + return ( + isAbstractMechanism(tauxProgMech) && + tauxProgMech.name === 'taux progressif' && + typeof tauxProgMech.explanation === 'object' && + tauxProgMech.explanation.assiette !== undefined && + tauxProgMech.explanation.multiplicateur !== undefined && + tauxProgMech.explanation.tranches instanceof Array && + tauxProgMech.explanation.tranches.every( + tranche => + typeof tranche === 'object' && + tranche.plafond !== undefined && + tranche.taux !== undefined + ) + ) +} + +type DureeMech = AbstractMechanism & { + name: 'Durée' + explanation: { + depuis: ASTNode + "jusqu'à": ASTNode + } +} +export function isDureeMech(node: ASTNode): node is DureeMech { + const dureeMech = node as DureeMech + return ( + isAbstractMechanism(dureeMech) && + dureeMech.name === 'Durée' && + typeof dureeMech.explanation === 'object' && + dureeMech.explanation.depuis !== undefined && + dureeMech.explanation["jusqu'à"] !== undefined + ) +} + type AnyMechanism = EncadrementMech | SommeMech export function isAnyMechanism(node: ASTNode): node is AnyMechanism { - return isEncadrementMech(node) || isSommeMech(node) || isProduitMech(node) + return ( + isEncadrementMech(node) || + isSommeMech(node) || + isProduitMech(node) || + isVariationsMech(node) || + isAllegementMech(node) || + isBaremeMech(node) || + isInversionNumMech(node) || + isArrondiMech(node) || + isMaxMech(node) || + isMinMech(node) || + isComposantesMech(node) || + isUneConditionsMech(node) || + isToutesConditionsMech(node) || + isSyncMech(node) || + isGrilleMech(node) || + isTauxProgMech(node) || + isDureeMech(node) + ) } type FormuleNode = | Value | Operation | Possibilities + | Possibilities2 | Reference | Recalcul | AnyMechanism @@ -192,16 +504,14 @@ export function isFormuleNode( isOperation(node) || isReference(node) || isPossibilities(node) || + isPossibilities2(node) || isRecalcul(node) || isAnyMechanism(node) ) } -function logVisit( - depth: number, - typeName: string, - obj: string | number | object -): void { +function logVisit(depth: number, typeName: string, obj: {}): void { + return let cleanRepr = obj if (typeof obj === 'object') { cleanRepr = JSON.stringify(obj, null) @@ -235,7 +545,18 @@ export function ruleDependenciesOfNode( depth: number, possibilities: Possibilities ): Array { - logVisit(depth, 'possibilities', possibilities.possibilités.join(', ')) + logVisit(depth, 'possibilities', possibilities.possibilités) + return [] + } + function ruleDependenciesOfPossibilities2( + depth: number, + possibilities: Possibilities2 + ): Array { + logVisit( + depth, + 'possibilities2', + R.filter(([k, _]) => !isNaN(parseInt(k, 10)), R.toPairs(possibilities)) + ) return [] } @@ -263,68 +584,359 @@ export function ruleDependenciesOfNode( depth: number, encadrementMech: EncadrementMech ): Array { - debugger // [XXX] - correct the type, guard and visit logger - logVisit(depth, 'encadrement mechanism', '??') // [XXX] - return R.chain( + logVisit(depth, 'encadrement mechanism', '??') + const result = R.chain( R.partial>(ruleDependenciesOfNode, [ depth + 1 ]), - encadrementMech.valeur.explanation + [ + encadrementMech.explanation.plafond, + encadrementMech.explanation.plancher, + encadrementMech.explanation.valeur + ] ) + return result } function ruleDependenciesOfSommeMech( depth: number, sommeMech: SommeMech ): Array { - debugger // [XXX] - correct the type, guard and visit logger - logVisit(depth, 'somme mech', '??') // [XXX] - return R.chain( + logVisit(depth, 'somme mech', '??') + const result = R.chain( R.partial>(ruleDependenciesOfNode, [ depth + 1 ]), sommeMech.explanation ) + return result } function ruleDependenciesOfProduitMech( depth: number, produitMech: ProduitMech ): Array { - logVisit(depth, 'produit mech', '') - const result = R.chain, Name>(R.identity, [ - ruleDependenciesOfNode(depth + 1, produitMech.explanation.assiette), - ruleDependenciesOfNode(depth + 1, produitMech.explanation.plafond), - ruleDependenciesOfNode(depth + 1, produitMech.explanation.facteur), - ruleDependenciesOfNode(depth + 1, produitMech.explanation.taux) - ]) + logVisit(depth, 'produit mech', '??') + const result = R.chain( + R.partial>(ruleDependenciesOfNode, [ + depth + 1 + ]), + [ + produitMech.explanation.assiette, + produitMech.explanation.plafond, + produitMech.explanation.facteur, + produitMech.explanation.taux + ] + ) + return result + } + + function ruleDependenciesOfVariationsMech( + depth: number, + variationsMech: VariationsMech + ): Array { + logVisit(depth, 'variations mech', '??') + + function ruleOfVariation({ + condition, + consequence + }: { + condition: ASTNode + consequence: ASTNode + }): Array { + return R.concat( + ruleDependenciesOfNode(depth + 1, condition), + ruleDependenciesOfNode(depth + 1, consequence) + ) + } + const result = R.chain(ruleOfVariation, variationsMech.explanation) + return result + } + + function ruleDependenciesOfAllegementMech( + depth: number, + allegementMech: AllegementMech + ): Array { + logVisit(depth, 'allegement mech', '??') + const subNodes = R.concat( + [ + allegementMech.explanation.abattement, + allegementMech.explanation.assiette, + allegementMech.explanation.franchise, + allegementMech.explanation.plafond + ], + allegementMech.explanation.décote + ? [ + allegementMech.explanation.décote.plafond, + allegementMech.explanation.décote.taux + ] + : [] + ) + const result = R.chain( + R.partial>(ruleDependenciesOfNode, [ + depth + 1 + ]), + subNodes + ) + return result + } + + function ruleDependenciesOfBaremeMech( + depth: number, + baremeMech: BaremeMech + ): Array { + logVisit(depth, 'barème mech', '??') + const tranchesNodes = R.chain( + ({ plafond, taux }) => [plafond, taux], + baremeMech.explanation.tranches + ) + const result = R.chain( + R.partial>(ruleDependenciesOfNode, [ + depth + 1 + ]), + R.concat( + [ + baremeMech.explanation.assiette, + baremeMech.explanation.multiplicateur + ], + tranchesNodes + ) + ) + return result + } + + /** + * Returns 0 dependency for _inversion numérique_ as it's not creating a logical dependency. + */ + function ruleDependenciesOfInversionNumMech( + depth: number, + inversionNumMech: InversionNumMech + ): Array { + logVisit(depth, 'inversion numérique', inversionNumMech.avec) + return [] + } + + function ruleDependenciesOfArrondiMech( + depth: number, + arrondiMech: ArrondiMech + ): Array { + logVisit(depth, 'arrondi mech', '??') + + const result = R.chain( + R.partial>(ruleDependenciesOfNode, [ + depth + 1 + ]), + [arrondiMech.explanation.decimals, arrondiMech.explanation.value] + ) + return result + } + + function ruleDependenciesOfMaxMech( + depth: number, + maxMech: MaxMech + ): Array { + logVisit(depth, 'max mech', '??') + + const result = R.chain( + R.partial>(ruleDependenciesOfNode, [ + depth + 1 + ]), + maxMech.explanation + ) + return result + } + + function ruleDependenciesOfMinMech( + depth: number, + minMech: MinMech + ): Array { + logVisit(depth, 'min mech', '??') + + const result = R.chain( + R.partial>(ruleDependenciesOfNode, [ + depth + 1 + ]), + minMech.explanation + ) + return result + } + + function ruleDependenciesOfComposantesMech( + depth: number, + composantesMech: ComposantesMech + ): Array { + logVisit(depth, 'composantes mech', '??') + + const result = R.chain( + R.partial>(ruleDependenciesOfNode, [ + depth + 1 + ]), + composantesMech.explanation + ) + return result + } + + function ruleDependenciesOfUneConditionsMech( + depth: number, + uneConditionsMech: UneConditionsMech + ): Array { + logVisit(depth, 'une conditions mech', '??') + + const result = R.chain( + R.partial>(ruleDependenciesOfNode, [ + depth + 1 + ]), + uneConditionsMech.explanation + ) + return result + } + + function ruleDependenciesOfToutesConditionsMech( + depth: number, + toutesConditionsMech: ToutesConditionsMech + ): Array { + logVisit(depth, 'toutes conditions mech', '??') + + const result = R.chain( + R.partial>(ruleDependenciesOfNode, [ + depth + 1 + ]), + toutesConditionsMech.explanation + ) + return result + } + + function ruleDependenciesOfSyncMech(depth: number, _: SyncMech): Array { + logVisit(depth, 'sync mech', '??') + return [] + } + + function ruleDependenciesOfGrilleMech( + depth: number, + grilleMech: GrilleMech + ): Array { + logVisit(depth, 'grille mech', '??') + const tranchesNodes = R.chain( + ({ montant, plafond }) => [montant, plafond], + grilleMech.explanation.tranches + ) + const result = R.chain( + R.partial>(ruleDependenciesOfNode, [ + depth + 1 + ]), + R.concat( + [ + grilleMech.explanation.assiette, + grilleMech.explanation.multiplicateur + ], + tranchesNodes + ) + ) + return result + } + + function ruleDependenciesOfTauxProgMech( + depth: number, + tauxProgMech: TauxProgMech + ): Array { + logVisit(depth, 'taux progressif mech', '??') + const tranchesNodes = R.chain( + ({ plafond, taux }) => [plafond, taux], + tauxProgMech.explanation.tranches + ) + const result = R.chain( + R.partial>(ruleDependenciesOfNode, [ + depth + 1 + ]), + R.concat( + [ + tauxProgMech.explanation.assiette, + tauxProgMech.explanation.multiplicateur + ], + tranchesNodes + ) + ) + return result + } + + function ruleDependenciesOfDureeMech( + depth: number, + dureeMech: DureeMech + ): Array { + logVisit(depth, 'durée mech', '??') + const result = R.chain( + R.partial>(ruleDependenciesOfNode, [ + depth + 1 + ]), + [dureeMech.explanation.depuis, dureeMech.explanation["jusqu'à"]] + ) return result } if (isValue(node)) { - return ruleDependenciesOfValue(depth, node as Value) + return ruleDependenciesOfValue(depth, node) } else if (isOperation(node)) { - return ruleDependenciesOfOperation(depth, node as Operation) - } else if (isReference(node)) { - return ruleDependenciesOfReference(depth, node as Reference) + return ruleDependenciesOfOperation(depth, node) + } else if (isReference(node)) { + return ruleDependenciesOfReference(depth, node) } else if (isPossibilities(node)) { - return ruleDependenciesOfPossibilities(depth, node as Possibilities) - } else if (isRecalcul(node)) { - return ruleDependenciesOfRecalcul(depth, node as Recalcul) + return ruleDependenciesOfPossibilities(depth, node) + } else if (isPossibilities2(node)) { + return ruleDependenciesOfPossibilities2(depth, node) + } else if (isRecalcul(node)) { + return ruleDependenciesOfRecalcul(depth, node) } else if (isEncadrementMech(node)) { - return ruleDependenciesOfEncadrementMech(depth, node as EncadrementMech) + return ruleDependenciesOfEncadrementMech(depth, node) } else if (isSommeMech(node)) { - return ruleDependenciesOfSommeMech(depth, node as SommeMech) + return ruleDependenciesOfSommeMech(depth, node) } else if (isProduitMech(node)) { return ruleDependenciesOfProduitMech(depth, node) + } else if (isVariationsMech(node)) { + return ruleDependenciesOfVariationsMech(depth, node) + } else if (isAllegementMech(node)) { + return ruleDependenciesOfAllegementMech(depth, node) + } else if (isBaremeMech(node)) { + return ruleDependenciesOfBaremeMech(depth, node) + } else if (isInversionNumMech(node)) { + return ruleDependenciesOfInversionNumMech(depth, node) + } else if (isArrondiMech(node)) { + return ruleDependenciesOfArrondiMech(depth, node) + } else if (isMaxMech(node)) { + return ruleDependenciesOfMaxMech(depth, node) + } else if (isMinMech(node)) { + return ruleDependenciesOfMinMech(depth, node) + } else if (isComposantesMech(node)) { + return ruleDependenciesOfComposantesMech(depth, node) + } else if (isUneConditionsMech(node)) { + return ruleDependenciesOfUneConditionsMech(depth, node) + } else if (isToutesConditionsMech(node)) { + return ruleDependenciesOfToutesConditionsMech(depth, node) + } else if (isSyncMech(node)) { + return ruleDependenciesOfSyncMech(depth, node) + } else if (isGrilleMech(node)) { + return ruleDependenciesOfGrilleMech(depth, node) + } else if (isTauxProgMech(node)) { + return ruleDependenciesOfTauxProgMech(depth, node) + } else if (isDureeMech(node)) { + return ruleDependenciesOfDureeMech(depth, node) } - throw new Error( - `This node doesn't have a visitor method defined: ${JSON.stringify( - node, - null, - 4 - )}` - ) + + if (node.avec) { + // [XXX] - How come we meet this? Souldn't `mecanismRecalcul` (in `mecanisms.js`) build a `Recalcul` type node? + console.error( + `Visited a non-parsed recalcul node, to investigate: règle ${node.règle}` + ) + } else { + debugger + throw new Error( + `This node doesn't have a visitor method defined: ${JSON.stringify( + node, + null, + 4 + )}` + ) + } + return [] } function ruleDependenciesOfRule( @@ -334,15 +946,16 @@ function ruleDependenciesOfRule( logVisit(depth, 'rule', rule.dottedName as string) if (rule.formule) { const formuleNode: FormuleNode = rule.formule.explanation - // This is for comfort, as the responsibility over structure isn't owned by this piece of code: - if (!isFormuleNode(formuleNode)) { - debugger - // throw Error( - // `This rule's formule is not of a known type: ${rule.dottedName}` - // ) - } + // // This is for comfort, as the responsibility over structure isn't owned by this piece of code: + // if (!isFormuleNode(formuleNode)) { + // debugger + // // throw Error( + // // `This rule's formule is not of a known type: ${rule.dottedName}` + // // ) + // } return ruleDependenciesOfNode(depth + 1, formuleNode) - } else return [rule.dottedName] + } + return [] } export function buildRulesDependencies( @@ -355,12 +968,11 @@ export function buildRulesDependencies( const pairs: Array<[Name, RuleNode]> = stringPairs as Array< [Name, RuleNode] > - const pairsResults: Array> = R.map( - ([_, ruleNode]: [Name, RuleNode]): Array => - ruleDependenciesOfRule(0, ruleNode), - pairs - ) - console.log(pairsResults) + // const pairsResults: Array> = R.map( + // ([_, ruleNode]: [Name, RuleNode]): Array => + // ruleDependenciesOfRule(0, ruleNode), + // pairs + // ) return R.map( ([dottedName, ruleNode]: [Name, RuleNode]): [Name, Array] => [ diff --git a/publicodes/source/mecanisms/arrondi.tsx b/publicodes/source/mecanisms/arrondi.tsx index 0490ba20d..26cf7b72a 100644 --- a/publicodes/source/mecanisms/arrondi.tsx +++ b/publicodes/source/mecanisms/arrondi.tsx @@ -12,7 +12,7 @@ type MecanismRoundProps = { explanation: ArrondiExplanation } -type ArrondiExplanation = { +export type ArrondiExplanation = { value: EvaluatedNode decimals: EvaluatedNode }