De talen
De brontalen en wat ze kunnen uitdrukken
uchar heeft nu drie brontalen: RegelSpraak met GegevensSpraak, Catala en F-logic. Alle drie vertalen naar één IR. Dat aantal is geen grens: een nieuwe brontaal kost één vertaler naar de IR, en elke toevoeging toetst de IR opnieuw op neutraliteit. Deze pagina laat per taal zien wat zij kan uitdrukken, met echte fragmenten uit het corpus en de uitkomst die elke uitvoerder ervan moet geven.
The languages
The source languages and what they can express
uchar currently has three source languages: RegelSpraak with GegevensSpraak, Catala and F-logic. All three translate into one IR. That number is not a limit: a new source language costs one translator into the IR, and every addition tests the IR again for neutrality. This page shows, per language, what it can express, with real fragments from the corpus and the outcome every executor must produce for them.
Drie talen, één IR
Waarom juist deze drie, staat op de startpagina. De lijst is een momentopname, geen ontwerpkeuze: welke talen erbij komen, bepaalt wie ze nodig heeft. Per taal eist een gate dat de frontend elk bronbestand in het corpus opnieuw tot precies de ingecheckte IR vertaalt.
| RegelSpraak | Catala | F-logic | |
|---|---|---|---|
| Wat het is | Gecontroleerde natuurlijke taal in het Nederlands, versie 2.3.0 | Programmeertaal voor wetgeving met een default-calculus als kern | Logica van frames met klassehiërarchie en overerfbare klasse-defaults |
| Herkomst | Belastingdienst | Inria; Merigoux, Chataing & Protzenko, ICFP 2021 | Kifer, Lausen & Wu, JACM 1995 |
| Rol in uchar | Eerste brontaal; de productieroute is de Drools-backend van uchar, verpakt in de distributie regelspraak-toolchain | Tweede brontaal; bron voor geprioriteerde defaults | Derde brontaal; toetst de overervingskern |
| Goldens met bron (7-11-2026) | 209 · source.rgs | 12 · source.catala_en | 2 · source.flogic |
| Gate | 10: byte-identieke her-emissie; 16: scenariotoetsen regenereren hun casebestanden byte-identiek | 9: frontendsuite (ondergrens 201 checks) en her-emissie | 14: frontendsuite (ondergrens 81 checks) en her-emissie |
Three languages, one IR
Why these three were chosen is explained on the home page. The list is a snapshot, not a design decision: which languages are added is decided by who needs them. For each language a gate requires the frontend to translate every source file in the corpus into exactly the checked-in IR again.
| RegelSpraak | Catala | F-logic | |
|---|---|---|---|
| What it is | Controlled natural language in Dutch, version 2.3.0 | Programming language for legislation with a default calculus at its core | Logic of frames with a class hierarchy and inheritable class-level defaults |
| Origin | Dutch Tax Administration | Inria; Merigoux, Chataing & Protzenko, ICFP 2021 | Kifer, Lausen & Wu, JACM 1995 |
| Role in uchar | First source language; its production route is uchar's Drools backend, packaged in the distribution regelspraak-toolchain | Second source language; source for prioritized defaults | Third source language; tests the inheritance kernel |
| Goldens with source (2026-11-07) | 209 · source.rgs | 12 · source.catala_en | 2 · source.flogic |
| Gate | 10: byte-identical re-emission; 16: scenario tests regenerate their case files byte-identically | 9: frontend suite (floor of 201 checks) and re-emission | 14: frontend suite (floor of 81 checks) and re-emission |
RegelSpraak en GegevensSpraak
Een .rgs-bestand is een reeks definities en regels; meerdere bestanden, zoals objectmodel, regels en scenario's, worden in opgegeven volgorde samengevoegd. De grammatica noemt het declaratiedeel GegevensSpraak en het regeldeel RegelSpraak; de fragmenten staan zoals in het corpus.
Het declaratiedeel
Een objecttype heeft attributen en kenmerken. Een attribuut heeft een datatype (Numeriek, Percentage, Tekst, Boolean, Datum in dagen, Datum en tijd in millisecondes of een domein) en soms een eenheid uit een eenheidsysteem. Een parameter krijgt zijn waarde uit de invoer.
RegelSpraak and GegevensSpraak
An .rgs file is a sequence of definitions and rules; several files, such as an object model, rules and scenarios, are concatenated in the given order. The grammar calls the declaration part GegevensSpraak and the rule part RegelSpraak. RegelSpraak is Dutch by definition: keywords and names are Dutch, and the fragments are quoted as they stand in the corpus, untranslated.
The declaration part
An object type has attributes and characteristics. An attribute has a datatype (Numeriek, Percentage, Tekst, Boolean, Datum in dagen, Datum en tijd in millisecondes or a domain) and sometimes a unit from a unit system. A parameter receives its value from the input.
Eenheidsysteem Gewicht
het kilogram (mv: kilogrammen) kg
Eenheidsysteem Munt
de euro (mv: euros) EUR €
Objecttype de Jutter (mv: Jutters) (bezield)
is aanvoerplichtig kenmerk (bijvoeglijk);
het aangevoerd gewicht Numeriek (niet-negatief getal met 2 decimalen) met eenheid kg;
de aanvoerwaarde Numeriek (niet-negatief getal met 2 decimalen) met eenheid €;
het aanvoergeld Numeriek (getal met 2 decimalen) met eenheid €;
Parameter de aanvoerdrempel : Numeriek (niet-negatief getal met 2 decimalen) met eenheid kg
Parameter het aanvoertarief : Numeriek (getal met 2 decimalen) met eenheid €
Een domein is in het corpus een enumeratie, een feittype verbindt objecttypen via rollen met een kardinaliteit, en een dagsoort benoemt een soort dag. Een kenmerk is bijvoeglijk (is …) of bezittelijk (heeft …); beide komen in het corpus voor.
In the corpus a domain is an enumeration, a fact type connects object types through roles with a cardinality, and a day type names a kind of day. A characteristic is adjectival (is …) or possessive (heeft …); both occur in the corpus.
Objecttype de Vondst (mv: Vondsten)
het vondstnummer (mv: vondstnummers) Numeriek (positief geheel getal);
de vondstdag Datum in dagen;
de aanmelddatum Datum in dagen;
Domein Vondstklasse is van het type Enumeratie
'drijfgoed'
'strandgoed'
'wrakgoed'
Objecttype de Vondst (mv: Vondsten)
de klasse Vondstklasse;
de bestemming Vondstklasse;
Feittype ketenband
de voorligger (mv: voorliggers) Wachter
de opvolger (mv: opvolgers) Wachter
Eén voorligger heeft meerdere opvolgers
// Bron: art. 3b-3c Jutterswet
Dagsoort de schouwdag (mv: schouwdagen);
Dagsoort de stormvloeddag (mv: stormvloeddagen);
Het regeldeel
Een regel heeft een naam, een geldigheid en een regelzin (onder meer gelijkstelling, berekening, kenmerktoekenning, initialisatie of consistentie-eis), eventueel met een voorwaarde na indien.
Het uchar-dialect
uchar draagt een dialect met uitbreidingen die officieel RegelSpraak v2.3.0 niet kent. De frontend registreert zijn afwijkingen in frontends/regelspraak/grammar/DIVERGENCES.md; elke uitbreiding is additief en laat officiële v2.3.0-documenten ongemoeid. Daarnaast legt het register enkele versmallingen vast: plaatsen waar de frontend een v2.3.0-spelling bewust smaller leest of weigert. Twee uitbreidingen volgen ALEF (Agile Law Execution Factory), de ontwikkelomgeving van de Belastingdienst waarin RegelSpraak wordt geschreven, gebouwd op JetBrains MPS en open source onder EUPL-1.2; de andere hebben een andere herkomst.
- Uitzonderingen:
Uitzondering op <naam>: <naam>,Afwijking van <basisregel>: <naam>enUitzonderingen ongeordend:(ook alsUitzonderingen ongeordend op <naam>:). v2.3.0 kent geen uitzondering, voorrang of regelvolgorde, en ALEF evenmin: daar zijn twee verschillende toekenningen aan hetzelfde attribuut een fout. Een uitzondering kan zelf weer uitzonderingen dragen, zonder grens aan de diepte. EenUitzondering opgeldt alleen waar ook haar drager geldt; eenAfwijking vangeldt onder haar eigen voorwaarde en kan de basisregel dus verruimen. De blokken zijn een eigen uitbreiding van uchar; het model van geprioriteerde defaults eronder volgt de default-calculus van Catala. - Subtypen:
Objecttype het Wrakrecht is een Strandrecht (mv: Wrakrechten). v2.3.0 en ALEF kennen geen overerving tussen objecttypen; dit is een eigen uitbreiding van uchar voor gegevensmodellen die overerving gebruiken. - Het tellen van gevulde waarden:
het aantal gevulde waarden van …. v2.3.0 heeft er geen spelling voor; de woordgroep is van uchar. ALEF dient hetzelfde doel door objecten te tellen met een subselectie op "gevuld". - Recursieve regelgroepen:
Regelgroep <naam> is recursief. v2.3.0 beschrijft recursie alleen in proza. In ALEF is "recursief" een eigenschap van een regelgroep en mag een cyclus alleen lopen via een regel die objecten aanmaakt. uchar eist dat een recursieve groep een regel bevat die objecten of feiten aanmaakt, en dat elke objectcreatie daarin voorwaardelijk is. - Scenariotoetsen:
Situatie …:,Scenario …enParameterset …:, achter een eigen startregel. v2.3.0 kent geen testhoofdstuk. Het idee komt uit TestSpraak, de testtaal van ALEF, waarin de regelanalist naast de regels testgevallen vastlegt met een situatie, een verwacht resultaat en een rekendatum. De tekstvorm komt uit regelspraak-java; de RegelSpraak-frontend van uchar vertaalt elk scenario naar een casebestand (gate 16). In het corpus staat zo'n toetsdocument alsscenario.rgsnaast desource.rgs. - Opgave boven berekening:
(mag opgegeven worden)achter een attribuut. v2.3.0 kan niet uitdrukken dat een opgegeven waarde voorrang heeft op de berekening. De markering is syntactische suiker van uchar: de frontend maakt er een eigen invoerattribuut van en een defaults-groep die de opgave boven de berekening zet. - Afwezigheidsmarkers:
(of onbekend),(of niet van toepassing)of(of onbekend of niet van toepassing)achter een attribuut. Een afwezigheidsmarker is een gevulde waarde en niet leeg: een regel kan hem schrijven en een voorwaarde toetsen (indien zijn taxatie onbekend is). v2.3.0 kentn.v.t.alleen in een cel van een beslistabel. Goldenjutterswet-afwezigheidsmarkers. - Vocabulaires en benamingen:
Vocabulaire <naam>, desgewenst met(standaard)en(taal: <code>), declareert een vocabulaire, en(<vocabulaire>: <benaming>)aan het eind van de naamgroep geeft een declaratie een naam in dat vocabulaire, zoals een term uit een handboek of een veldnaam uit een gegevensmodel:Objecttype de Jutter (mv: Jutters) (bezield) (handboek: strandjutter) (cgm: JUTTER). Objecttypen, attributen, kenmerken, feittypen, rollen, enumeratiewaarden, parameters, regels en regelgroepen kunnen een benaming dragen. v2.3.0 kan zulke namen alleen in commentaar kwijt; de uitbreiding is van uchar zelf. In de IR zijn de benamingen een zijtafel zonder semantiek (IR-SPEC hoofdstuk 2.12, WF-116 tot en met WF-120): regels gebruiken altijd de gedeclareerde namen, en gate 13 controleert dat de uitvoerders hetzelfde antwoord geven als de tabel ontbreekt of als de benamingen van plaats wisselen. Het standaardvocabulaire moet elke benoembare declaratie een benaming geven (WF-119), ook de declaraties die de frontend zelf maakt. Voor de elementen van de opgave-markering, de groep van de blokken van een subtype en het lid en de regel van een vouw met stappen na de verzameling stelt de frontend die benaming samen uit de benamingen van hun delen. De regels van de rijen van een beslistabel en het anker van een startpuntbepaling hebben geen benaming; een document met een standaardvocabulaire kan die twee constructies niet gebruiken, en de frontend weigert het met die reden. De distributie regelspraak-toolchain gebruikt de benamingen aan de rand van de beslisservice: een verzoek mag ze schrijven, en antwoord en uitleg kunnen in een gekozen vocabulaire (Voor de DevOps-engineer).
Verdere constructies
Elk van de volgende vormen heeft een golden met cases die de referentie-interpreter, Clingo en Drools naspelen. Voorbeelden met uitleg staan op Voor de regelanalist.
- Een kwantor over een pad van relaties:
indien ten minste één van de vondsten van de melder van de Melding zwaar is. In de IR is het bereik van deQuantifierFoldhet geschreven pad (sourcePath, IR-SPEC 4.5). Goldenjutterswet-dringende-melding. - Een vouw in het filter van een andere vouw: de laatste einddag van de zware klachten van een Schuit, gelezen in het filter over haar ladingen. De binnenste vouw draagt het vormanker (§ 7). Golden
jutterswet-schone-maand-na-zware-klacht. - Geneste voorwaarden op drie en meer niveaus. Het niveau van een opsommingsteken volgt uit het aantal tekens:
-en•zijn niveau 1,..en••niveau 2,...en•••niveau 3; een dieper teken opent een niveau onder het vorige. Goldenjutterswet-vrijstelling-drie-niveaus. zelf, een uitbreiding van het dialect:de Vergunning zelfnoemt in een filter of in de toets van een kwantor het onderwerp van de regel, ook als de elementen hetzelfde type hebben (- hij is niet de Vergunning zelf). In de IR is dat het vormanker met de knoopIdentityCheck(§ 7). Goldenjutterswet-registervoorrang.- Een kenmerk dat een subtype declareert, getoetst op een object van het supertype:
Een Strandrecht is landvast indien hij geen vaartijd heeft, waar alleen het subtype Wrakrechtvaartijddeclareert. De toets is waar voor een instantie van het subtype met het kenmerk en onwaar voor elk ander object. In de IR noemt het veldhostvan deCharacteristicCheckhet subtype (IR-SPEC 4.6, RUNTIME-SEMANTICS 5.8b, WF-109). Goldenjutterswet-ploegblokkade. - Een kring over instanties: een waarde van een object hangt af van dezelfde waarde van zijn voorganger, een object van hetzelfde type. De einddag van een vergunning telt het restant van de vorige vergunning mee, en dat restant hangt af van de einddag van die vorige vergunning. De uitvoerders rekenen per object in de volgorde van de keten; vormen de schakels in de case zelf een kring, dan wordt de case geweigerd met EF-033 (IR-SPEC 5.3, RUNTIME-SEMANTICS 6.2). Goldens
jutterswet-vergunningketenenjutterswet-vergunningtermijnen. - De datumconstructie
de datum met jaar: …, maand: … en dag: …. Delen die geen kalenderdag noemen, zoals 31 april, geven een fout met code EF-032 (RUNTIME-SEMANTICS 3.8). Goldendate-with-parts. - Een voorwaarde die veel waarden leest: in
jutterswet-strandvoogdkeuringachttien, veertien van de Jutter zelf en vier van zijn strandpost. De DRL-tekst geeft ze alle aan één Java-functie, die ten hoogste 255 parameters neemt.
The rule part
A rule has a name, a validity and a rule sentence (among others assignment, calculation, characteristic assignment, initialisation or consistency requirement), optionally with a condition after indien (if).
The uchar dialect
uchar carries a dialect with extensions that official RegelSpraak v2.3.0 does not have. The frontend records its deviations in frontends/regelspraak/grammar/DIVERGENCES.md; every extension is additive and leaves official v2.3.0 documents unaffected. The register also records a few narrowings: places where the frontend deliberately reads a v2.3.0 spelling more narrowly or refuses it. Two extensions follow ALEF (Agile Law Execution Factory), the Dutch Tax Administration's development environment for writing RegelSpraak, built on JetBrains MPS and open source under EUPL-1.2; the others have a different origin.
- Exceptions:
Uitzondering op <naam>: <naam>(exception to),Afwijking van <basisregel>: <naam>(deviation from) andUitzonderingen ongeordend:(unordered exceptions, also asUitzonderingen ongeordend op <naam>:). v2.3.0 has no exception, priority or rule ordering, and neither has ALEF: there, two different assignments to the same attribute are an error. An exception can carry exceptions of its own, to any depth. AnUitzondering opapplies only where its carrier applies as well; anAfwijking vanapplies under its own condition and can therefore widen the base rule. The blocks are uchar's own extension; the prioritized-defaults model beneath them follows Catala's default calculus. - Subtypes:
Objecttype het Wrakrecht is een Strandrecht (mv: Wrakrechten). v2.3.0 and ALEF have no inheritance between object types; this is uchar's own extension for data models that use inheritance. - Counting filled values:
het aantal gevulde waarden van …. v2.3.0 has no spelling for that operation; the phrase is uchar's own. ALEF serves the same purpose by counting objects with a sub-selection on "filled". - Recursive rule groups:
Regelgroep <naam> is recursief. v2.3.0 describes recursion in prose only. In ALEF "recursive" is a property of a rule group and a cycle may only run through a rule that creates objects. uchar requires a recursive group to contain a rule that creates objects or facts, and every object creation in it to be conditional. - Scenario tests:
Situatie …:(situation),Scenario …andParameterset …:(parameter set), behind a start rule of their own. v2.3.0 has no test chapter. The idea comes from TestSpraak, ALEF's test language, in which the rule analyst records test cases next to the rules with a situation, an expected result and a calculation date. The textual form comes from regelspraak-java; uchar's RegelSpraak frontend translates every scenario into a case file (gate 16). In the corpus such a test document sits asscenario.rgsnext to thesource.rgs. - Given before computed:
(mag opgegeven worden)(may be given) after an attribute. v2.3.0 cannot express that a supplied value takes precedence over the computation. The marker is uchar's syntactic sugar: the frontend turns it into a separate input attribute and a defaults group that ranks the given value above the computation. - Absence markers:
(of onbekend)(or unknown),(of niet van toepassing)(or not applicable) or(of onbekend of niet van toepassing)after an attribute. An absence marker is a filled value, not an empty one: a rule can write it and a condition test it (indien zijn taxatie onbekend is, if its valuation is unknown). v2.3.0 hasn.v.t.only in a cell of a decision table. Goldenjutterswet-afwezigheidsmarkers. - Vocabularies and designations:
Vocabulaire <naam>, optionally with(standaard)(default) and(taal: <code>)(language), declares a vocabulary, and(<vocabulaire>: <benaming>)at the end of the name group gives a declaration a name in that vocabulary, such as a term from a handbook or a field name from a data model:Objecttype de Jutter (mv: Jutters) (bezield) (handboek: strandjutter) (cgm: JUTTER). Object types, attributes, characteristics, fact types, roles, enumeration values, parameters, rules and rule groups can carry a designation. v2.3.0 can hold such names only in comments; the extension is uchar's own. In the IR the designations are a side table without semantics (IR-SPEC chapter 2.12, WF-116 to WF-120): rules always use the declared names, and gate 13 checks that the executors give the same answer when the table is absent or when the designations change places. The default vocabulary must give every designatable declaration a designation (WF-119), the declarations the frontend makes itself included. For the elements of the given-before-computed marker, the group of a subtype's blocks and the member and the rule of a fold with steps after the set, the frontend composes that designation from the designations of their parts. The rules of a decision table's rows and the anchor of a start-point determination carry none; a document with a default vocabulary cannot use those two constructs, and the frontend refuses it with that reason. The distribution regelspraak-toolchain uses the designations at the edge of the decision service: a request may write them, and the response and the explanation can be in a chosen vocabulary (For the DevOps engineer).
Further constructs
Each of the following forms has a golden with cases that the reference interpreter, Clingo and Drools replay. Examples with an explanation are on For the rule analyst.
- A quantifier over a path of relations:
indien ten minste één van de vondsten van de melder van de Melding zwaar is(if at least one of the finds of the reporter of the report is heavy). In the IR the range of theQuantifierFoldis the written path (sourcePath, IR-SPEC 4.5). Goldenjutterswet-dringende-melding. - A fold in the filter of another fold: the last end day of a Schuit's heavy complaints, read in the filter over its loads. The inner fold carries the form anchor (§ 7). Golden
jutterswet-schone-maand-na-zware-klacht. - Nested conditions on three or more levels. The level of a bullet follows from the number of signs:
-and•are level 1,..and••level 2,...and•••level 3; a deeper sign opens a level below the previous one. Goldenjutterswet-vrijstelling-drie-niveaus. zelf(itself), a dialect extension:de Vergunning zelfnames, in a filter or in the test of a quantifier, the subject of the rule, also where the elements have the same type (- hij is niet de Vergunning zelf, he is not the licence itself). In the IR this is the form anchor with the nodeIdentityCheck(§ 7). Goldenjutterswet-registervoorrang.- A characteristic that a subtype declares, tested on an object of the supertype:
Een Strandrecht is landvast indien hij geen vaartijd heeft(a Strandrecht is landbound if it has no sailing time), where only the subtype Wrakrecht declaresvaartijd. The test is true for an instance of the subtype that has the characteristic and false for every other object. In the IR the fieldhostof theCharacteristicChecknames the subtype (IR-SPEC 4.6, RUNTIME-SEMANTICS 5.8b, WF-109). Goldenjutterswet-ploegblokkade. - A cycle across instances: a value of an object depends on the same value of its predecessor, an object of the same type. The end day of a licence adds the remainder of the previous licence, and that remainder depends on the end day of the previous licence. The executors compute per object in the order of the chain; where the links in the case itself form a cycle, the case is refused with EF-033 (IR-SPEC 5.3, RUNTIME-SEMANTICS 6.2). Goldens
jutterswet-vergunningketenandjutterswet-vergunningtermijnen. - The date construction
de datum met jaar: …, maand: … en dag: …(the date with year, month and day). Parts that name no calendar day, such as 31 April, give a fault with code EF-032 (RUNTIME-SEMANTICS 3.8). Goldendate-with-parts. - A condition that reads many values: in
jutterswet-strandvoogdkeuringeighteen, fourteen of the Jutter itself and four of his beach post. The DRL text passes them all to one Java function, which takes at most 255 parameters.
Constructencatalogus
Per construct een fragment uit een source.rgs en de case met handgerekende verwachtingen, die de referentie-interpreter en Clingo exact moeten naspelen en Drools naspeelt of met reden weigert. Notatie: invoer → verwachting; ¬ is een afwezig kenmerk, leeg een attribuut zonder waarde.
Catalogue of constructs
For each construct, a fragment from a source.rgs and the case with hand-computed expectations, which the reference interpreter and Clingo must replay exactly and Drools replays or refuses with a reason. Notation: input → expectation; ¬ is an absent characteristic, leeg (empty) an attribute without a value.
Gelijkstelling en berekening
Een attribuut krijgt een waarde door gelijkstelling (moet gesteld worden op) of berekening (moet berekend worden als); er wordt exact met breuken gerekend. Afronden is een operator in de expressie, geen eigenschap van het attribuut: 100/8 = 12,5 wordt 12. Kan de uitkomst meer decimalen hebben dan het doel toelaat, zoals bij een deling door een attribuut, dan weigeren frontend en verifier de regel vóór de uitvoering (WF-023); de auteur rondt zelf af, zoals bij het helpersdeel hieronder, of kiest een doel Numeriek (getal). Een waarde die bij de uitvoering toch niet past, geeft de fout EF-006. Een gevulde teller gedeeld door een lege deler geeft leeg en een feit EF-031 op het foutkanaal (case3 hieronder); gedeeld door een numerieke nul geeft hij leeg en een feit EF-005 (golden division-by-numeric-zero). De berekening breekt in beide gevallen niet af (§ 8).
Assignment and calculation
An attribute receives a value by assignment (moet gesteld worden op) or by calculation (moet berekend worden als); arithmetic is exact, on fractions. Rounding is an operator in the expression, not a property of the attribute: 100/8 = 12.5 becomes 12. If the result can have more decimals than the target allows, as with a division by an attribute, the frontend and the verifier refuse the rule before execution (WF-023); the author rounds explicitly, as for helpersdeel below, or chooses a target Numeriek (getal). A value that still does not fit at execution gives the fault EF-006. A filled dividend divided by an empty divisor gives an empty value and a fact EF-031 on the error channel (case3 below); divided by a numeric zero it gives an empty value and a fact EF-005 (golden division-by-numeric-zero). In neither case does the computation abort (§ 8).
Regel premie van een berging
geldig altijd
De premie van een Berging moet berekend worden als 20% van de opbrengst van de Berging.
Regel helpersdeel van een berging
geldig altijd
Het helpersdeel van een Berging moet berekend worden als de opbrengst van de Berging gedeeld door het helpersaantal van de Berging rekenkundig afgerond op 0 decimalen.
Regel dagdeel van een berging
geldig altijd
Het dagdeel van een Berging moet berekend worden als de opbrengst van de Berging gedeeld door de vermenigvuldiger van de Berging naar beneden afgerond op 0 decimalen.
case1 opbrengst 100 · helpersaantal 4 · vermenigvuldiger 8
→ premie 20 · helpersdeel 25 · dagdeel 12
case3 opbrengst 90 · helpersaantal leeg · vermenigvuldiger 8
→ premie 18 · helpersdeel leeg · dagdeel 11 · inconsistent EF-031 (helpersdeel van een berging)
Daarbij geldt benoemt een tussenwaarde; in de IR van deze golden is dat één Let met twee leesverwijzingen.
Daarbij geldt (where) names an intermediate value; in this golden's IR it is one Let with two reads.
Regel lichterloon van een lichterbeurt
geldig altijd
Het lichterloon van een Lichterbeurt moet berekend worden als het grondloon plus het grondloon maal het spoedtal van de Lichterbeurt.
Daarbij geldt:
het grondloon is het vrachttal van de Lichterbeurt maal het eenheidsloon van de Lichterbeurt.
vrachttal 3 · spoedtal 2 · eenheidsloon 40 → lichterloon 360
vrachttal 5 · spoedtal 0 · eenheidsloon 20 → lichterloon 100
Eenheden en omrekening
Een eenheidsysteem legt eenheden en verhoudingen vast; omrekenfactoren zijn exacte breuken. Een eenheid kan samengesteld zijn uit eenheden met een gehele macht, zoals €/dg/m en 1/dg (golden jutterswet-sleeptarief). M2 vangt een uitvoerder die 1 t als heel getal 1000 neemt en de decimalen van de operand laat vallen: die antwoordt 1000,00.
Units and conversion
A unit system fixes units and ratios; conversion factors are exact fractions. A unit can be compound, built from units with whole exponents, such as €/dg/m and 1/dg (golden jutterswet-sleeptarief). M2 catches an executor that takes 1 t as the whole number 1000 and drops the operand's decimals: it would answer 1000.00.
Eenheidsysteem Gewicht
het kilogram (mv: kilogrammen) kg
de ton (mv: tonnen) t = 1000 kg
…
Het aangegeven gewicht van een Vondst moet berekend worden als het brutogewicht van de Vondst plus 1 t.
V1 brutogewicht 3.00 → aangegeven gewicht 1003.00
M1 brutogewicht 2.00 → aangegeven gewicht 1002.00
M2 brutogewicht 0.50 → aangegeven gewicht 1000.50
Kenmerktoekenning met voorwaarde
Een object krijgt een kenmerk als de voorwaarde geldt; afwezigheid is een eigen, toetsbare uitkomst. eerder is dan is strikt.
Characteristic assignment with a condition
An object receives a characteristic when the condition holds; absence is an outcome in its own right and can be tested. eerder is dan (earlier than) is strict.
Een Vondst is verjaard
indien zijn vondstdag eerder is dan 31-01-2024.
vondstdag 2023-12-31 → verjaard
vondstdag 2024-01-31 → ¬verjaard
vondstdag 2024-02-01 → ¬verjaard
Samengestelde voorwaarden
Leden combineren met alle, geen van, ten minste, ten hoogste of precies … van de volgende voorwaarden; een tweelingregel zet minsteteken met ten minste één. Bij W1 beslist het eerste lid al, dus 100/0 wordt nooit berekend. Zou het wel berekend worden, dan bleef het aandeel leeg en ontstond een feit EF-005; de case pint consistent en legt zo vast dat de evaluatie na het eerste lid stopt.
Compound conditions
Members combine with alle (all), geen van (none of), ten minste (at least), ten hoogste (at most) or precies (exactly) … van de volgende voorwaarden (of the following conditions); a twin rule sets minsteteken with ten minste één (at least one). For W1 the first member already decides, so 100/0 is never computed. If it were computed, the share would stay empty and a fact EF-005 would arise; the case pins consistent and so pins down that evaluation stops after the first member.
Regel geenteken van een wacht
geldig altijd
Het geenteken van een Wacht moet gesteld worden op 1
indien hij aan geen van de volgende voorwaarden voldoet:
- zijn ploegomvang is gelijk aan 0
- het aandeel is groter dan 0.
Daarbij geldt:
het aandeel is de vangstwaarde van de Wacht gedeeld door de ploegomvang van de Wacht naar beneden afgerond op 0 decimalen.
W1 ploegomvang 0 · vangstwaarde 100 → geenteken leeg · minsteteken 1
W2 ploegomvang 4 · vangstwaarde 100 → geenteken leeg · minsteteken 1
W3 ploegomvang 7 · vangstwaarde 3 → geenteken 1 · minsteteken leeg
→ consistent
Kwantoren over gekoppelde instanties
Een telling over de leden van een via een feittype gekoppelde verzameling, eventueel met subselectie (die gekeurd zijn). Een lid zonder waarde telt niet mee, want vergelijken met leeg is onwaar; over een lege verzameling zijn alle en geen van allebei waar (jutterswet-schouwploeg).
Quantifiers over linked instances
A count over the members of a set linked through a fact type, optionally with a sub-selection (die gekeurd zijn, that are inspected). A member without a value does not count, because comparing with an empty value is false; over an empty set, alle (all) and geen van (none of) are both true (jutterswet-schouwploeg).
Regel helder bij sterkte
geldig altijd
Een Vuurtoren is helder indien de sterkte van ten minste 2 van de lampen van de Vuurtoren groter is dan 5.
Regel zuinig bij sterkte
geldig altijd
Een Vuurtoren is zuinig indien de sterkte van ten hoogste 1 van de lampen van de Vuurtoren groter is dan 5.
Regel enkelvoudig bij sterkte
geldig altijd
Een Vuurtoren is enkelvoudig indien de sterkte van precies 1 van de lampen van de Vuurtoren groter is dan 5.
Regel keurig bij sterkte
geldig altijd
Een Vuurtoren is keurig indien de sterkte van ten minste 2 van de lampen van de Vuurtoren die gekeurd zijn groter is dan 5.
L1 sterkte 8, gekeurd · L2 sterkte 6, gekeurd
→ helder · keurig · ¬zuinig · ¬enkelvoudig · lampental 2
L1 sterkte leeg · L2 sterkte 3
→ zuinig · ¬helder · ¬enkelvoudig · ¬keurig · lampental 2
Met alle over een hele periode: K1 is aangemeld met 50 per maand, K2 niet; diens 30 telt dus niet en de keurploeg is premiewaardig.
With alle over a whole period: K1 is registered at 50 a month, K2 is not; its 30 therefore does not count and the crew is premiewaardig (eligible for a bonus).
Een Keurploeg is premiewaardig indien de keurvergoeding van alle keurmeesters van de Keurploeg die aangemeld zijn gedurende het gehele jaar groter is dan 40.
Aggregaties
het aantal, de som van, het totaal van en de minimale waarde van vouwen over een verzameling, ook langs twee rollen (jutterswet-vondstketen). Zonder of 0 als die er niet zijn is een som over niets leeg, maar geeft het totaal van 0; het aantal gevulde waarden van (dialect) telt alleen gevulde waarden.
Aggregations
het aantal (the number of), de som van (the sum of), het totaal van (the total of) and de minimale waarde van (the minimum of) fold over a set, also along two roles (jutterswet-vondstketen). Without of 0 als die er niet zijn (or 0 if there are none), a sum over nothing is empty, but het totaal van gives 0; het aantal gevulde waarden van (dialect) counts only filled values.
Regel aantal aangemelde vondsten
geldig altijd
Het aantal aangemelde vondsten van een Jutter moet berekend worden als het aantal vondsten van de Jutter.
Regel aangemeld gewicht
geldig altijd
Het aangemeld gewicht van een Jutter moet berekend worden als de som van het gewicht van alle vondsten van de Jutter of 0 als die er niet zijn.
J1 vondsten.gewicht [2.50, 1.25, leeg] → aantal aangemelde vondsten 3 · aangemeld gewicht 3.75
J2 vondsten.gewicht [] → aantal aangemelde vondsten 0 · aangemeld gewicht 0
J3 vondsten.gewicht [leeg] → aantal aangemelde vondsten 1 · aangemeld gewicht 0
Verdeling
Een bedrag wordt naar rato verdeeld, met een maximum per lid en afronding; wat boven het maximum uitkomt, wordt niet herverdeeld maar valt in de rest. In gelijke delen (jutterswet-bergingsdeling) geeft 1001 over twee leden 500 en 500, rest 1.
Distribution
An amount is distributed in proportion, with a maximum per member and rounding; what exceeds the maximum is not redistributed but goes to the remainder. In equal shares (jutterswet-bergingsdeling), 1001 over two members gives 500 and 500, remainder 1.
Regel verdeel de opbrengst van een berging
geldig altijd
De opbrengst van een berging wordt verdeeld over de bergingsaandelen van alle bergers van de berging, waarbij wordt verdeeld:
- naar rato van het geborgen gewicht,
- met een maximum van het bergingsmaximum,
- afgerond op 0 decimalen naar beneden.
Als onverdeelde rest blijft de onverdeelde rest van de berging over.
opbrengst 1200
W geborgen gewicht 3.00 · bergingsmaximum 300
H geborgen gewicht 1.00 · bergingsmaximum 300
D geborgen gewicht 2.00 · bergingsmaximum 300
→ bergingsaandeel W 300 · H 200 · D 300 · onverdeelde rest 400
Tijdlijnen
Een attribuut, kenmerk of parameter voor elke maand (of dag, of jaar) heeft een tijdlijn: een waarde per periode, over alle tijd. het totaal van … gedurende de tijd dat hij wachtplichtig is telt alleen de perioden waarin het kenmerk geldt, en een deel van een maand naar zijn dagen. Het aantal decimalen van zo'n deel is niet begrensd; daarom rondt de regel af.
Timelines
An attribute, characteristic or parameter voor elke maand (for every month; also per day or per year) has a timeline: a value per period, over all time. het totaal van … gedurende de tijd dat hij wachtplichtig is (the total of … during the time he is on watch duty) counts only the periods in which the characteristic holds, and a part of a month by its days. The decimals of such a part are unbounded; that is why the rule rounds.
de wachtvergoeding per maand Numeriek (geheel getal) voor elke maand;
is wachtplichtig kenmerk (bijvoeglijk) voor elke maand;
…
Regel wachtsom van een jutter
geldig altijd
De wachtsom van een Jutter moet gesteld worden op (het totaal van zijn wachtvergoeding per maand gedurende de tijd dat hij wachtplichtig is) rekenkundig afgerond op 0 decimalen.
wachtvergoeding per maand: 10 in 2023 · 11 in 2024-01 – 2024-06
wachtplichtig: 2023-07-01 – 2024-02-01
→ wachtsom 71 = 6 × 10 + 1 × 11
Een bewerking zonder eigen tijdsbetekenis, zoals plus of een vergelijking, geldt op een tijdlijn per dag. Een regel met een tijdlijndoel leest zijn voorwaarde per periode en schrijft alleen waar die geldt; twee regels botsen alleen op een dag waarop ze verschillend beslissen, en waar geen regel beslist, blijft de invoer staan. Uitzonderingen, (mag opgegeven worden) en initialisaties werken daar ook per dag. Wat open blijft, zoals de macht of het minimum over een tijdlijn, weigert elke uitvoerder met naam (RUNTIME-SEMANTICS 3.12).
An operation without a time semantics of its own, such as plus or a comparison, holds per day on a timeline. A rule with a timeline target reads its condition per period and writes only where it holds; two rules clash only on a day on which they decide differently, and where no rule decides, the input stays. Exceptions, (mag opgegeven worden) and initialisations work per day there as well. Every executor refuses by name what remains open, such as the power or the minimum over a timeline (RUNTIME-SEMANTICS 3.12).
Objecttype de Jutter (mv: Jutters) (bezield)
is aangesteld kenmerk (bijvoeglijk) voor elke maand;
…
het strandloon Numeriek (geheel getal) voor elke maand;
de stormtoeslag Numeriek (geheel getal) voor elke maand;
het aangestelde loon Numeriek (geheel getal) voor elke maand;
…
Regel aangesteld loon van een jutter
geldig altijd
Het aangestelde loon van een Jutter moet berekend worden als zijn strandloon plus zijn stormtoeslag gedurende de tijd dat hij aangesteld is.
strandloon: 100 in 2024-01 – 2024-03 · 150 in 2024-04 – 2024-09
stormtoeslag: 30 in 2024-03 – 2024-05
aangesteld: 2024-02-01 – 2024-08-01
→ aangestelde loon: 100 in 2024-02 · 130 in 2024-03 · 180 in 2024-04 – 2024-05 · 150 in 2024-06 – 2024-07
Tijdrekening
Een datum schuift op met dagen van een dagsoort, hier springtijdagen: de 1e en de 15e van de maand. Een tijdsduur telt hele eenheden; de begindag telt niet mee.
Date arithmetic
A date moves by days of a day type, here springtijdagen (spring-tide days): the 1st and the 15th of the month. A duration counts whole units; the start day does not count.
Regel uiterste bergingsdatum van een bergingsploeg
geldig altijd
De uiterste bergingsdatum van een Bergingsploeg moet berekend worden als zijn meldingsdatum plus zijn bergingsbestek.
Regel vroegste meldingsdatum van een bergingsploeg
geldig altijd
De vroegste meldingsdatum van een Bergingsploeg moet berekend worden als zijn meldingsdatum min zijn bergingsbestek.
Regel bergingsspanne van een bergingsploeg
geldig altijd
De bergingsspanne van een Bergingsploeg moet berekend worden als de tijdsduur van zijn meldingsdatum tot zijn opleverdatum in hele springtijdagen.
Regel bergingsafstand van een bergingsploeg
geldig altijd
De bergingsafstand van een Bergingsploeg moet berekend worden als de absolute tijdsduur van zijn opleverdatum tot zijn meldingsdatum in hele springtijdagen.
P1 meldingsdatum 2026-03-10 · bergingsbestek 3 · opleverdatum 2026-04-20
→ uiterste bergingsdatum 2026-04-15 · vroegste meldingsdatum 2026-02-01 · bergingsspanne 3 · bergingsafstand 3
P2 meldingsdatum 2026-03-15 · bergingsbestek 1
→ uiterste bergingsdatum 2026-04-01
P3 bergingsbestek 0 · opleverdatum < meldingsdatum
→ uiterste bergingsdatum = meldingsdatum · bergingsspanne −1 · bergingsafstand 1
Dagsoorten
Een definitieregel legt vast welke dagen tot een dagsoort behoren; in deze golden gebruikt geen expressie de stormvloeddag.
Day types
A definition rule determines which days belong to a day type; in this golden no expression uses stormvloeddag (storm-surge day).
Regel Dagsoortdefinitie stormvloeddag
geldig altijd
Een dag is een stormvloeddag
indien er aan alle volgende voorwaarden wordt voldaan:
- de dag later is dan 30-09-2026
- de dag eerder is dan 01-03-2027.
Dimensies
Een attribuut kan gedimensioneerd zijn, hier naar seizoen: het heeft een waarde per cel. Een regel leest één cel met in voorjaar; een cel zonder invoer leest leeg. Alle uitvoerders lezen en schrijven cellen en vouwen erover, ook over meer dimensies.
Dimensions
An attribute can be dimensioned, here by season: it has a value per cell. A rule reads one cell with in voorjaar (in spring); a cell without input reads as empty. All executors read and write cells and fold over them, also over more than one dimension.
Dimensie het seizoen, bestaande uit de seizoenen (na het attribuut met voorzetsel in):
1. voorjaar
2. najaar
Objecttype de Jutter (mv: Jutters) (bezield)
het vondstgewicht Numeriek (niet-negatief getal met 2 decimalen) met eenheid kg gedimensioneerd met seizoen;
het voorjaarsgewicht Numeriek (niet-negatief getal met 2 decimalen) met eenheid kg;
…
… moet berekend worden als zijn vondstgewicht in voorjaar.
J1 vondstgewicht voorjaar 12.50 · najaar 4.00 → voorjaarsgewicht 12.50
J2 vondstgewicht najaar 4.00 → voorjaarsgewicht leeg
→ consistent
Uitzonderingen en geprioriteerde defaults
Een uitzondering gaat vóór haar basisregel. Het subtype Wrakrecht vervangt de geërfde basis door grondslag maal 2 en voegt een eigen uitzondering toe (55,00 bij bergingsdiepte boven 20), die vóór de geërfde gaat.
Exceptions and prioritized defaults
An exception takes precedence over its base rule. The subtype Wrakrecht replaces the inherited base with the base amount times 2 and adds its own exception (55.00 for a salvage depth above 20), which precedes the inherited one.
Regel uitkering van een strandrecht
geldig altijd
De uitkering van een Strandrecht moet gesteld worden op zijn grondslag.
Uitzondering op uitkering van een strandrecht: uitkering van een betwist strandrecht
geldig altijd
De uitkering van een Strandrecht moet gesteld worden op 99,00
indien het Strandrecht betwist is.
grondslag 10.00
Strandrecht → uitkering 10.00
Wrakrecht, bergingsdiepte 5 → uitkering 20.00
Strandrecht, betwist → uitkering 99.00
Wrakrecht, bergingsdiepte 5, betwist → uitkering 99.00
Wrakrecht, bergingsdiepte 25 → uitkering 55.00
Wrakrecht, bergingsdiepte 25, betwist → uitkering 55.00
Een ongeordende groep kent geen voorrang: beslissen twee leden verschillend, dan blijft het attribuut leeg en volgt een inconsistentie met code EF-027, geen afbreking.
An unordered group has no priority: if two members decide differently, the attribute stays empty and an inconsistency with code EF-027 follows, not an abort.
Uitzonderingen ongeordend:
Regel wachtgeld voor kustwachters
geldig altijd
Het wachtgeld van een Jutter moet gesteld worden op 30
indien hij kustwacht is.
M kustwacht · havenmeester → wachtgeld leeg · inconsistent EF-027 (Jutter.wachtgeld)
Consistentie en uniciteit
Een schending is geen fout maar een waarneembaar inconsistentie-feit per betrokken object, met de code van haar soort: EF-025 voor een consistentie-eis, EF-026 voor een uniciteit.
Consistency and uniqueness
A violation is not an error but an observable inconsistency fact per object involved, with the code of its kind: EF-025 for a consistency requirement, EF-026 for a uniqueness.
Regel eenmalig vondstnummer
geldig altijd
De vondstnummers van alle Vondsten moeten uniek zijn.
Regel aanmelding niet voor de vondstdag
geldig altijd
De aanmelddatum van een Vondst moet later of gelijk zijn aan de vondstdag van de Vondst.
V1 vondstnummer 7 · V2 vondstnummer 7 → inconsistent EF-026: V1, V2 (eenmalig vondstnummer)
vondstdag 2025-03-01 · aanmelddatum 2025-02-01 → inconsistent EF-025 (aanmelding niet voor de vondstdag)
V1 vondstnummer 7 · V2 vondstnummer 8 → consistent
Regelversies met geldigheid
Deze regel heeft een geldigheidsvenster en doet alleen mee als de evaluatiedatum erin valt. Op 2026-06-01 is het wintertal van H1 2 en van H2 1, op 2026-02-01 overal 0.
Rule versions with validity
This rule has a validity window and applies only if the evaluation date falls within it. On 2026-06-01 the winter count of H1 is 2 and of H2 1, on 2026-02-01 it is 0 everywhere.
Regel winterberging door de haven
geldig vanaf 01-03-2026
Een winterschuit van een Haven is een ligger van de Haven
indien de Haven veilig is.
De Jutterswet als casus
Het corpus is gebouwd op de Jutterswet, de Wet op de jutterspenning van het verzonnen eiland Scholde. De wet regelt wie erkend jutter is en wie recht heeft op de jutterspenning. Er zijn vijf versies met fictieve data, van v0 (2020, vijf artikelen) tot v4 (2025, dertien artikelen); negen dossiers leggen per versie de bedoelde uitkomst vast. "Bergloon" en "keurmeester" komen uit de goldens, niet uit de wet. De README van het corpus koppelt vijf goldens aan hun artikel; deze pagina toont er drie.
The Jutterswet as a case study
The corpus is built on the Jutterswet, the Beachcombers' Token Act of the fictional island of Scholde. The act governs who is a recognised beachcomber and who is entitled to the beachcombers' token. There are five versions with fictional dates, from v0 (2020, five articles) to v4 (2025, thirteen articles); nine dossiers fix the intended outcome per version. "Bergloon" (salvage fee) and "keurmeester" (inspector) come from the goldens, not from the act. The corpus README links five goldens to their articles; this page shows three of them.
Artikel 3 en jutterswet-penningdrempel
Recht op de jutterspenning heeft de erkende jutter van onbesproken juttersgedrag die in het penningjaar ten minste zoveel vondsten als de vondstdrempel bij de strandvoogd heeft aangemeld.
Article 3 and jutterswet-penningdrempel
Entitled to the beachcombers' token is the recognised beachcomber of irreproachable beachcombing conduct who, in the token year, has reported at least as many finds to the beach warden as the find threshold.
Parameter de vondstdrempel : Numeriek (geheel getal)
Regel Kenmerktoekenning jutter penninggerechtigd
geldig altijd
Een Jutter is penninggerechtigd
indien zijn aantal aangemelde vondsten groter of gelijk is aan de vondstdrempel.
De vondstdrempel uit artikel 7 is een parameter. "Erkende jutter" en "van onbesproken juttersgedrag" ontbreken, en het aantal aangemelde vondsten is invoer (zie § 8).
The find threshold from article 7 is a parameter. "Recognised beachcomber" and "of irreproachable beachcombing conduct" are absent, and the number of reported finds is input (see § 8).
Artikel 3b en jutterswet-penningjaar
Voor de toepassing van artikel 3 telt iedere in het penningjaar aangemelde vondst eenmaal; een vondst waarvan de dag een stormvloeddag is, telt tweemaal. Het penningjaar is het kalenderjaar.
Article 3b and jutterswet-penningjaar
For the purposes of article 3, every find reported in the token year counts once; a find whose day is a storm-surge day counts twice. The token year is the calendar year.
Tijdlijn het penningjaar heeft tijdvakken van een jaar startend op dag 1 van maand 1;
Eenheidsysteem Munt
de euro (mv: euros) EUR €
Objecttype de Jutter (mv: Jutters) (bezield)
is penninggerechtigd kenmerk (bijvoeglijk);
is aanmeldplichtig kenmerk (bijvoeglijk);
het aantal aangemelde vondsten Numeriek (niet-negatief geheel getal) voor elke penningjaar;
het totaal aangemelde vondsten Numeriek (geheel getal);
Parameter de vondstdrempel : Numeriek (geheel getal)
Parameter het penningbedrag : Numeriek (geheel getal) met eenheid € voor elk jaar
Regel totaal aangemelde vondsten
geldig altijd
Het totaal aangemelde vondsten van een Jutter moet berekend worden als het totaal van zijn aantal aangemelde vondsten.
Regel Kenmerktoekenning penninggerechtigd
geldig altijd
Een Jutter is penninggerechtigd
indien zijn totaal aangemelde vondsten groter of gelijk is aan de vondstdrempel.
Regel Kenmerktoekenning aanmeldplichtig
geldig altijd
Een Jutter is aanmeldplichtig
indien hij niet penninggerechtigd is.
asOfDate 2026-03-15 · vondstdrempel 12
J1 aantal aangemelde vondsten 14 → totaal aangemelde vondsten 14 · penninggerechtigd · ¬aanmeldplichtig
J2 aantal aangemelde vondsten 3 → ¬penninggerechtigd · aanmeldplichtig
J3 aantal aangemelde vondsten leeg → totaal aangemelde vondsten 0 · ¬penninggerechtigd · aanmeldplichtig
Het penningjaar was de eerste benoemde tijdlijn in het corpus, en indien hij niet penninggerechtigd is de eerste negatieve afhankelijkheid. Niet gemodelleerd: de dubbele telling op stormvloeddagen en de beperking van de telling tot het penningjaar.
The token year was the corpus's first named timeline, and indien hij niet penninggerechtigd is (if he is not entitled) the first negative dependency. Not modelled: the double count on storm-surge days and the restriction of the count to the token year.
Artikel 9 en jutterswet-berging
Bergen twee of meer jutters gezamenlijk één zaak, dan wordt de opbrengst van de berging in euro's over de bergers verdeeld naar rato van ieders aandeel in het geborgen gewicht, met voor iedere berger ten hoogste het bergingsmaximum dat de strandvoogd bij de aanvang van de berging voor hem heeft vastgesteld, en ieder aandeel afgerond op hele euro's naar beneden. Wat door het maximum of de afronding onverdeeld blijft, valt toe aan het eilandfonds. Is geen gewicht per berger vastgesteld, dan wordt in gelijke delen verdeeld.
Article 9 and jutterswet-berging
If two or more beachcombers jointly salvage one item, the proceeds of the salvage in euros are distributed over the salvors in proportion to each one's share of the salvaged weight, with for each salvor at most the salvage maximum the beach warden set for him at the start of the salvage, and each share rounded down to whole euros. Whatever remains undistributed because of the maximum or the rounding accrues to the island fund. If no weight has been established per salvor, the proceeds are distributed in equal shares.
Eenheidsysteem Munt
de euro (mv: euros) EUR €
Eenheidsysteem Gewicht
het kilogram (mv: kilogrammen) kg
de ton (mv: tonnen) t = 1000 kg
Objecttype de Berging (mv: Bergingen)
de opbrengst Numeriek (geheel getal) met eenheid €;
de onverdeelde rest Numeriek (geheel getal) met eenheid €;
Objecttype de Berger (mv: Bergers) (bezield)
het bergingsaandeel (mv: bergingsaandelen) Numeriek (geheel getal) met eenheid €;
het geborgen gewicht Numeriek (getal met 2 decimalen) met eenheid kg;
het bergingsmaximum Numeriek (geheel getal) met eenheid €;
Feittype bergingsdeelname
de berging Berging
de berger (mv: bergers) Berger
Eén berging heeft meerdere bergers
Regel verdeel de opbrengst van een berging
geldig altijd
De opbrengst van een berging wordt verdeeld over de bergingsaandelen van alle bergers van de berging, waarbij wordt verdeeld:
- naar rato van het geborgen gewicht,
- met een maximum van het bergingsmaximum,
- afgerond op 0 decimalen naar beneden.
Als onverdeelde rest blijft de onverdeelde rest van de berging over.
Vastgelegde afwijkingen: de rest blijft op de Berging in plaats van naar het eilandfonds te gaan, en de terugval op gelijke delen staat in een aparte golden.
Recorded deviations: the remainder stays on the Berging instead of going to the island fund, and the fallback to equal shares lives in a separate golden.
Catala
Catala is de programmeertaal voor wetgeving van Inria (Merigoux, Chataing & Protzenko, ICFP 2021). Haar kern is een default-calculus: een algemene regel met geprioriteerde uitzonderingen, in de taal zelf en niet in de engine. Een bron is literate: artikeltekst en code in één bestand.
De frontend is een zelfstandig OCaml-programma dat de Catala-compiler als bibliotheek linkt en aanhaakt op scopelang, vóórdat scopes tot functies worden gecompileerd; zo zijn scopestructuur en richting van overrides nog zichtbaar. Een scope wordt een objecttype, een basis met uitzonderingen één groep geprioriteerde defaults. Wat buiten het vastgestelde fragment valt, weigert de frontend met naam en exitcode 3.
Catala
Catala is Inria's programming language for legislation (Merigoux, Chataing & Protzenko, ICFP 2021). Its core is a default calculus: a general rule with prioritized exceptions, in the language itself rather than in the engine. A source is literate: article text and code in one file.
The frontend is a standalone OCaml program that links the Catala compiler as a library and attaches at scopelang, before scopes compile to functions, so scope structure and the direction of overrides are still visible. A scope becomes an object type, a base with exceptions one group of prioritized defaults. The frontend refuses anything outside the decided fragment by name, with exit code 3.
catala_frontend: refused: row 10: list sorting (Sort) is out of the 5b kernel — argmin/argmax and ordering stay refused (§4)
Kamerheffing: het kortste voorbeeld
Kamerheffing roept per grondslag Kamerbedrag aan en telt op; in de IR wordt dat een functiedefinitie met een aanroep per element. Het artikelnummer hoort bij de golden; de nummering van v4 van de wet loopt tot artikel 9.
Kamerheffing: the shortest example
Kamerheffing calls Kamerbedrag for every base amount and sums the results; in the IR that becomes a function definition with one call per element. The article number belongs to the golden; the numbering of v4 of the act runs up to article 9.
# Jutterswet, artikel 14 — de kamerheffing
Art. 14 (kamerheffing). Een jutter die over meer vondsten verschuldigd is,
betaalt per vondst een kamerbedrag. Het kamerbedrag is de grondslag van de
vondst, vermeerderd met het vaste kamerrecht van honderd gulden. De
kamerheffing is de som van de kamerbedragen over alle grondslagen.
…
```catala
declaration scope Kamerbedrag:
input grondslag content integer
output bedrag content integer
scope Kamerbedrag:
definition bedrag equals grondslag + 100
declaration scope Kamerheffing:
input grondslagen content list of integer
output heffing content integer
scope Kamerheffing:
definition heffing equals
combine all b
among (map each g among grondslagen to (output of Kamerbedrag with { -- grondslag: g }).bedrag)
in acc initially 0 with (acc + b)
```
grondslagen [200, 400] → heffing 800 · consistent
grondslagen [] → heffing 0 · consistent
Penningrecht: de default-calculus
Deze golden modelleert artikel 3 in de v0-lezing (drempel twaalf) met een hardheidsgrond: boven de basis false staat artikel 3, en daarboven artikel 5 als uitzondering óp artikel 3. In de IR is dat één PrioritizedDefaults-knoop met drie leden; de RegelSpraak-tweeling jutterswet-penningrecht schrijft hetzelfde als twee kenmerktoekenningen, met dezelfde cases.
Penningrecht: the default calculus
This golden models article 3 in its v0 reading (threshold twelve) with a hardship ground: above the base false stands article 3, and above it article 5 as an exception to article 3. In the IR this is one PrioritizedDefaults node with three members; the RegelSpraak twin jutterswet-penningrecht writes the same as two characteristic assignments, with the same cases.
declaration scope Penningrecht:
input aantal_aangemelde_vondsten content integer
input hardheid_toegepast content boolean
output penninggerechtigd content boolean
scope Penningrecht:
# De stilte-basis: zonder gegronde aanspraak geen recht.
definition penninggerechtigd equals false
# Artikel 3: de gewone drempel.
label artikel_3 exception
definition penninggerechtigd
under condition aantal_aangemelde_vondsten >= 12
consequence equals
true
# Artikel 5 leest artikel 3 met "zes": de hardheidsgrond gaat vóór
# en is daarom een uitzondering óp artikel 3 — de keten, niet een
# tweede ongeordende grond.
exception artikel_3
definition penninggerechtigd
under condition
hardheid_toegepast
and aantal_aangemelde_vondsten >= 6
consequence equals
true
aantal_aangemelde_vondsten 12 → penninggerechtigd · consistent
aantal_aangemelde_vondsten 6 · hardheid_toegepast → penninggerechtigd · consistent
aantal_aangemelde_vondsten 6 → ¬penninggerechtigd · consistent
aantal_aangemelde_vondsten 4 · hardheid_toegepast → ¬penninggerechtigd · consistent
aantal_aangemelde_vondsten 12 · hardheid_toegepast → penninggerechtigd · consistent
Conflict: bewust anders dan Catala
In jutterswet-tariefrecht-catala staan boven een basistarief en een eerste uitzondering twee ongeordende uitzonderingen: 10 % bij ten minste vier kinderen, 0 % bij een inkomen tot en met $10,000. Gelden beide, dan breekt catala interpret af met een ConflictError; referentie-interpreter en Clingo laten tarief bewust leeg en melden een inconsistentie met code EF-027.
Conflict: deliberately unlike Catala
In jutterswet-tariefrecht-catala, two unordered exceptions sit above a base rate and a first exception: 10 % with at least four children, 0 % with an income of at most $10,000. If both apply, catala interpret aborts with a ConflictError; the reference interpreter and Clingo deliberately leave tarief empty and report an inconsistency with code EF-027.
inkomen 20000.00 · kindertal 4 → tarief 0.1000 · aanslag 1000.00
inkomen 8000.00 · kindertal 4 → tarief leeg · aanslag 0.00 · inconsistent EF-027 (Penningplichtige.tarief/0)
Gate 9 vertaalt alle twaalf Catala-goldens opnieuw, na canonicalisatie byte-identiek aan hun ir.json; de suite blijft boven haar ondergrens van 201 checks. Drools speelt er zes na en weigert er zes, elk met een code en een reden: structs (DROOLS-009), functiedefinities (twee keer, DROOLS-002), lijsten (DROOLS-008) en Match (twee keer, DROOLS-021). Beide weergaven van de Drools-backend geven daarbij per golden dezelfde statusregel (§ 7).
Gate 9 translates all twelve Catala goldens again; after canonicalization each is byte-identical to its ir.json, and the suite stays above its floor of 201 checks. Drools replays six and refuses six, each with a code and a reason: structs (DROOLS-009), function definitions (twice, DROOLS-002), lists (DROOLS-008) and Match (twice, DROOLS-021). Both renderings of the Drools backend give the same status line per golden (§ 7).
F-logic
F-logic (Kifer, Lausen & Wu, JACM 1995) beschrijft objecten als frames, met een klassehiërarchie en waarden die een klasse aan haar subklassen doorgeeft. Komen het supertype, de ketengesloten ledenresolutie en de voorrang van de subklasse ook vanuit F-logic op de wire, dan is de overervingskern aantoonbaar geen weergave van RegelSpraak. F-logic bewaakt ook de kwantorvouw: een telling vergeleken met een getal geeft atLeast, atMost, exactly, none of all, zonder negatievorm; de golden jutterswet-vuurtoren-flogic toont de eerste drie, de suite van de frontend alle vijf.
De frontend accepteert een syntactische deelverzameling van Flora-2 2.2. Elke vorm tot 12 september 2026 is in die onafhankelijke redeneerder zelf gecontroleerd; drie latere vormen, de count{…}-body met een conjunctie, de kenmerkkop ?X : k :- … en <=, zijn alleen aan de hand van de gedocumenteerde grammatica van Flora-2 beredeneerd, nog niet in de redeneerder zelf gedraaid. De vorm van de regel bepaalt de IR:
| Vorm | Betekenis |
|---|---|
C::D. | D is het enige directe supertype van C |
C[|a => numeriek(sign, scale)|]. | attribuutdeclaratie op C |
@!{'name'} C[|a -> 5|]. | overerfbare klasse-default: de basis van een defaultsgroep op C.a |
@!{'name'} ?X[a -> Expr] :- ?X : C, Cond, …. | voorwaardelijke definitie: een uitzondering |
@!{'name'} ?X : k :- ?X : C, Cond, …. | kenmerktoekenning: C.k geldt waar het lichaam geldt |
F-logic
F-logic (Kifer, Lausen & Wu, JACM 1995) describes objects as frames, with a class hierarchy and values that a class passes on to its subclasses. If the supertype, chain-closed member resolution and the precedence of the subclass also reach the wire from F-logic, the inheritance kernel is demonstrably not a rendering of RegelSpraak. F-logic also guards the quantifier fold: a count compared with a number gives atLeast, atMost, exactly, none or all, without a negation form; the golden jutterswet-vuurtoren-flogic shows the first three, the frontend's suite all five.
The frontend accepts a syntactic subset of Flora-2 2.2. Every form up to 12 September 2026 was checked in that independently maintained reasoner itself; three later forms, the count{…} body with a conjunction, the characteristic head ?X : k :- … and <=, have only been argued from Flora-2's documented grammar, not yet run in the reasoner itself. The shape of the rule determines the IR:
| Form | Reading |
|---|---|
C::D. | C's single direct supertype is D |
C[|a => numeriek(sign, scale)|]. | an attribute declaration on C |
@!{'name'} C[|a -> 5|]. | the inheritable class-level default: a defaults base on C.a |
@!{'name'} ?X[a -> Expr] :- ?X : C, Cond, …. | a conditional definition: an exception |
@!{'name'} ?X : k :- ?X : C, Cond, …. | a characteristic assignment: C.k holds where the body does |
// The bare rule on the supertype: no exception anywhere, so it is a
// standing norm rather than a default, and it fires for Wrakrechten too.
@!{'registratiekosten van een strandrecht'}
?S[registratiekosten -> 5.00] :- ?S : Strandrecht.
// Strandrecht.uitkering: an unconditional rule is the base, a conditional
// one an exception above it.
@!{'uitkering van een strandrecht'}
?S[uitkering -> ?S.grondslag] :- ?S : Strandrecht.
@!{'uitkering van een betwist strandrecht'}
?S[uitkering -> 99.00] :- ?S : Strandrecht, ?S : betwist.
// Wrakrecht.uitkering: its own base replaces the inherited one, its own
// exception joins the inherited one above that.
@!{'uitkering van een wrakrecht'}
?W[uitkering -> ?W.grondslag * 2] :- ?W : Wrakrecht.
@!{'uitkering van een diep wrakrecht'}
?W[uitkering -> 55.00] :- ?W : Wrakrecht, ?W.bergingsdiepte > 20.
grondslag 10.00
Strandrecht → uitkering 10.00 · registratiekosten 5.00
Wrakrecht, bergingsdiepte 5 → uitkering 20.00 · registratiekosten 5.00
Strandrecht, betwist → uitkering 99.00
Wrakrecht, bergingsdiepte 5, betwist → uitkering 99.00
Wrakrecht, bergingsdiepte 25 → uitkering 55.00
Wrakrecht, bergingsdiepte 25, betwist → uitkering 55.00
De vier case-bestanden van jutterswet-wrakrecht-flogic zijn byte-gelijk aan die van de RegelSpraak-versie in § 3 en van het anker jutterswet-strandrechtketen. Twee goldens hebben een F-logic-bron; de suite blijft boven haar ondergrens van 81 checks. Een weigering eindigt met exitcode 2, zonder uitvoerbestand.
The four case files of jutterswet-wrakrecht-flogic are byte-identical to those of the RegelSpraak version in § 3 and of the anchor jutterswet-strandrechtketen. Two goldens have an F-logic source; the suite stays above its floor of 81 checks. A refusal exits with code 2 and leaves no output file.
flogic: REFUSED refuse_naf.flogic: the negation form \naf (line 4) — outside the F-logic slice fixed by spec/proposals/SUBTYPING.md
Eén regel, vier gedaanten
Artikel 3 geeft recht op de jutterspenning bij ten minste zoveel aangemelde vondsten als de vondstdrempel. jutterswet-penningdrempel modelleert alleen dat drempeldeel: één regel, één parameter, één vergelijking. De case: J1 met 14 en J2 met 3 aangemelde vondsten, drempel 12. In bron, ASP en DRL zijn de gemarkeerde regels de wetsregel zelf.
One rule, four forms
Article 3 grants the beachcombers' token for at least as many reported finds as the find threshold. jutterswet-penningdrempel models only that threshold part: one rule, one parameter, one comparison. The case: J1 with 14 and J2 with 3 reported finds, threshold 12. In the source, the ASP and the DRL the highlighted lines are the legal rule itself.
Objecttype de Jutter (mv: Jutters) (bezield)
is penninggerechtigd kenmerk (bijvoeglijk);
het aantal aangemelde vondsten Numeriek (niet-negatief geheel getal);
Parameter de vondstdrempel : Numeriek (geheel getal)
Regel Kenmerktoekenning jutter penninggerechtigd
geldig altijd
» Een Jutter is penninggerechtigd
» indien zijn aantal aangemelde vondsten groter of gelijk is aan de vondstdrempel.
De bron zoals ingecheckt; de RegelSpraak-frontend vertaalt haar zonder canonicalisatie byte-identiek naar ir.json (gate 10).
The source as checked in; the RegelSpraak frontend translates it, without canonicalization, byte-identically into ir.json (gate 10).
"format": "uchar-ir-v1",
"model": {
"objectTypes": [
{
"node": "ObjectType",
"name": "Jutter",
"animate": true,
"plural": "Jutters",
"attributes": [
{
"node": "Attribute",
"name": "aantal aangemelde vondsten",
"datatype": {
"node": "Number",
"whole": true,
"decimals": 0,
"sign": "nonNegative"
…
"characteristics": [
{
"node": "Characteristic",
"name": "penninggerechtigd",
"kind": "adjectival"
…
"parameters": [
{
"node": "Parameter",
"name": "vondstdrempel",
…
"rules": {
"rules": [
{
"node": "Rule",
"name": "Kenmerktoekenning jutter penninggerechtigd",
"versions": [
…
"target": {
"node": "AttributeReference",
"attribute": "penninggerechtigd",
"subjectType": "Jutter",
…
"value": {
"node": "Literal",
"value": {
"boolean": true
…
"condition": {
"node": "Comparison",
"op": "greaterOrEqual",
"left": {
"node": "AttributeReference",
"attribute": "aantal aangemelde vondsten",
…
"right": {
"node": "ParameterReference",
"parameter": "vondstdrempel",
…
"source": {
"snippet": "zijn aantal aangemelde vondsten groter of gelijk is aan de vondstdrempel"
Fragmenten uit ir.json; de verifier meldt verifier: PASS en gate 2 schrijft het byte-identiek terug.
Fragments of ir.json; the verifier reports verifier: PASS and gate 2 writes it back byte-identically.
% generated by backends/clingo from uchar-ir-v1 + uchar-case-v0.
#defined val/3. #defined has/2. #defined role/3. #defined param/2.
#defined inconsistent/2. #defined tl/5. #defined param_tl/4. #defined ktl/4.
#defined inconsistent_code/3.
#defined inputval/3. #defined inputtl/5. #defined viol/2. #defined inputrole/3.
#defined lpres/1. #defined lelem/3.
isa(X,T) :- is_a(X,T).
:- viol(_,_).
viol("arithmetic range exceeded (clingo grounds in machine integers)",S) :- isa(S,"jutter"), val(S,"aantal aangemelde vondsten",A1), param("vondstdrempel",P2), |(A1)| > 2147483647.
viol("arithmetic range exceeded (clingo grounds in machine integers)",S) :- isa(S,"jutter"), val(S,"aantal aangemelde vondsten",A1), param("vondstdrempel",P2), |(P2)| > 2147483647.
»has(S,"penninggerechtigd") :- isa(S,"jutter"), val(S,"aantal aangemelde vondsten",A1), param("vondstdrempel",P2), A1 >= P2.
is_a("J1","jutter").
val("J1","aantal aangemelde vondsten",14).
is_a("J2","jutter").
val("J2","aantal aangemelde vondsten",3).
param("vondstdrempel",12).
#show val/3. #show has/2. #show inconsistent/2. #show tl/5.
#show inconsistent_code/3.
Answer: 1 (Time: 0.000s)
has("J1","penninggerechtigd") val("J1","aantal aangemelde vondsten",14) val("J2","aantal aangemelde vondsten",3)
SATISFIABLE
Het programma dat de clingo-backend uit IR en case maakt, zoals clingo_runner, de runner van gate 6, het op 7-11-2026 aan clingo gaf (onderschept op weg naar clingo). Daaronder het ene stable model, met clingo -n 2 op hetzelfde programma: J2 krijgt geen has-atoom (negation-as-failure). De runner meldt clingo: PASS (3 expectations).
The program the clingo backend makes from IR and case, as clingo_runner, the runner of gate 6, handed it to clingo on 2026-11-07 (intercepted on its way to clingo). Below it the one stable model, from clingo -n 2 on the same program: J2 gets no has atom (negation as failure). The runner reports clingo: PASS (3 expectations).
package dev.uchar.regelspraak.tms;
import dev.uchar.regelspraak.graph.ProducerConsumer.ElementKey;
import dev.uchar.regelspraak.runtime.RegelSpraakRuntime;
import dev.uchar.regelspraak.transpiler.tms.ComputeHelpers;
import dev.uchar.regelspraak.transpiler.tms.HasCharacteristic;
import dev.uchar.regelspraak.transpiler.tms.ParameterState;
global java.math.BigDecimal vondstdrempel;
// zijn aantal aangemelde vondsten groter of gelijk is aan de vondstdrempel
function boolean toets_kenmerktoekenningJutterPenninggerechtigd(Object $aantalAangemeldeVondsten, Object $vondstdrempel) {
» return RegelSpraakRuntime.rsAggVergelijk($aantalAangemeldeVondsten, $vondstdrempel, ">=");
}
rule "Kenmerktoekenning jutter penninggerechtigd"
dialect "mvel"
when
$onderwerp : dev.uchar.regelspraak.facts.Jutter( $aantalAangemeldeVondsten : aantalAangemeldeVondsten )
$parameter_1 : ParameterState( parameter == "vondstdrempel", $vondstdrempel : value )
» eval( toets_kenmerktoekenningJutterPenninggerechtigd($aantalAangemeldeVondsten, $vondstdrempel) )
then
» insertLogical(new HasCharacteristic($onderwerp, ElementKey.of("jutter", "penninggerechtigd", true)));
end
rule "parameterstand vondstdrempel"
dialect "mvel"
when
then
insertLogical(new ParameterState("vondstdrempel", vondstdrempel));
end
De volledige uitvoer van bin/regelspraak drl uit de distributie regelspraak-toolchain op de source.rgs van deze golden, 7-11-2026. Het commando bouwt via de publieke ingang DroolsBackend.build van de Drools-backend, tak DRL_TEXT. De backend analyseert elke regel één keer (TmsTranspiler) en geeft die analyse op twee manieren weer: als executable model, waarop de beslisservice draait, en als deze DRL-tekst. Beide leiden af met truth maintenance: de regel stelt het kenmerk met insertLogical als logisch feit (HasCharacteristic), en Drools haalt dat feit weg zodra de voorwaarde niet meer geldt. De vergelijking staat in een Java-functie met de RegelSpraak-zin als commentaar erboven; de parameter komt uit een global en wordt gelezen via een ParameterState-feit. Beide weergaven spelen de case na: PLAYED 1.
The complete output of bin/regelspraak drl from the distribution regelspraak-toolchain on this golden's source.rgs, 2026-11-07. The command builds through the Drools backend's public entry DroolsBackend.build, branch DRL_TEXT. The backend analyses every rule once (TmsTranspiler) and renders that analysis in two ways: as the executable model, on which the decision service runs, and as this DRL text. Both derive with truth maintenance: the rule states the characteristic with insertLogical as a logical fact (HasCharacteristic), and Drools withdraws that fact as soon as the condition no longer holds. The comparison sits in a Java function with the RegelSpraak sentence as a comment above it; the parameter comes from a global and is read through a ParameterState fact. Both renderings replay the case: PLAYED 1.
$ _build/default/ref/bin/runner.exe corpus/golden/jutterswet-penningdrempel/ir.json corpus/golden/jutterswet-penningdrempel/case.json
oracle: PASS (3 expectations)
MISMATCH: J1 lacks characteristic "penninggerechtigd"
$ _build/default/ref/bin/runner.exe --trace corpus/golden/jutterswet-penningdrempel/ir.json corpus/golden/jutterswet-penningdrempel/case.json
reading /rules/rules/0/versions/0 "J1" 0 Comparison true
reading /rules/rules/0/versions/0 "J1" 1 AttributeReference 14
reading /rules/rules/0/versions/0 "J1" 2 ParameterReference 12
reading /rules/rules/0/versions/0 "J1" HOLDS
reading /rules/rules/0/versions/0 "J2" 0 Comparison false
reading /rules/rules/0/versions/0 "J2" 1 AttributeReference 3
reading /rules/rules/0/versions/0 "J2" 2 ParameterReference 12
reading /rules/rules/0/versions/0 "J2" FAILS
"instances": [
{
"label": "J1",
"objectType": "Jutter",
"attributes": { "aantal aangemelde vondsten": { "number": "14" } },
…
"label": "J2",
"objectType": "Jutter",
"attributes": { "aantal aangemelde vondsten": { "number": "3" } },
…
"parameters": { "vondstdrempel": { "number": "12" } }
…
"expected": [
{ "kind": "characteristicPresent", "label": "J1", "characteristic": "penninggerechtigd" },
{ "kind": "characteristicAbsent", "label": "J2", "characteristic": "penninggerechtigd" },
{ "kind": "consistent" }
]
De referentie-interpreter print alleen de vergelijking met de case (exit 0). Met --noop slaat hij de evaluatie over en faalt de case, zoals bedoeld (exit 1): een case die een niets-doende uitvoerder haalt, test niets (gate 7). Met --trace schrijft hij de lezing van de voorwaarde: per object en per knoop wat hij in het fixpunt vond, en per object de status (zie onder de tabel). Alle drie de runs op 7-11-2026.
The reference interpreter prints only the comparison with the case (exit 0). With --noop it skips evaluation and the case fails, as intended (exit 1): a case a do-nothing executor passes tests nothing (gate 7). With --trace it writes the reading of the condition: per object and per node what it found at the fixpoint, and per object the status (see below the table). All three runs on 2026-11-07.
Zo komen de onderdelen overeen:
How the parts correspond:
| RegelSpraak | IR | ASP | DRL |
|---|---|---|---|
| "Een Jutter" | target.subjectType "Jutter" | isa(S,"jutter") | $onderwerp : dev.uchar.regelspraak.facts.Jutter( … ) |
| "is penninggerechtigd" | target: AttributeReference "penninggerechtigd"; value: Literal {"boolean": true} | has(S,"penninggerechtigd") | insertLogical(new HasCharacteristic($onderwerp, ElementKey.of("jutter", "penninggerechtigd", true))) |
| "zijn aantal aangemelde vondsten" | AttributeReference "aantal aangemelde vondsten" | val(S,"aantal aangemelde vondsten",A1) | $aantalAangemeldeVondsten : aantalAangemeldeVondsten |
| "groter of gelijk is aan" | Comparison, op greaterOrEqual | A1 >= P2 | rsAggVergelijk(…, ">=") in de toetsfunctie, aangeroepen inin the test function, called in eval( … ) |
| "de vondstdrempel" | ParameterReference "vondstdrempel" | param("vondstdrempel",P2) | ParameterState( parameter == "vondstdrempel", $vondstdrempel : value ) |
| afwezig bij J2: geen tekst nodigabsent for J2: no text needed | geen knoopno node | geen atoom (negation-as-failure)no atom (negation as failure) | regel vuurt niet: geen HasCharacteristicrule does not fire: no HasCharacteristic |
De IR en het differentiaalvierkant
De IR gaat als JSON over de draad in het formaat uchar-ir-v1, cases in uchar-case-v0, elk met een strikt JSON Schema (additionalProperties: false). Knopen, velden en enumeratiewaarden hebben Engelse namen (AttributeReference, greaterOrEqual), en de brontekst staat in een record source. Gedeclareerde namen, zoals objecttypen, attributen en labels, staan zoals ze geschreven zijn, in het Nederlands. v1 is afgeleid van v0, de getrouwe dump van het opgeloste model van regelspraak-java; elke afwijking van v0 staat in het constructenregister (§ 8). Elke MUST in de specificatie draagt een id WF-### en heeft een check in de verifier, een slagende golden en een falende negatieve case, of staat als OPEN in de index. Gate 2 eist dat elk document na inlezen en canoniek terugschrijven byte-identiek is.
Naast wat de evaluatie leest, draagt de IR velden zonder semantiek, voor wie een document toont of een beslissing uitlegt. Gate 13 haalt ze weg en eist dat de referentie-interpreter, Clingo en beide Drools-weergaven daarna dezelfde uitkomst geven als met de velden.
origin(IR-SPEC 2.13, WF-121), op een declaratie die de frontend zelf maakte: de vorm die haar maakte (inputAboveComputation,exceptionForSubtype,decisionTableRow,stepsAfterSetofstartPoint) en de declaratie waar zij van komt. Aan de naam is zo'n declaratie niet te herkennen, want een auteur kan dezelfde woorden schrijven.Default.name(IR-SPEC 6.1): de naam die de bron aan het blok van een default geeft. Injutterswet-meldingsketendraagt de default vanUitzondering op erkende meldingsdatum: herstelde meldingde naamherstelde melding; een uitleg kan zo de default noemen die besliste.Default.statuteAnnotations(IR-SPEC 6.1, WF-082): de// Bron:-regels boven het blok van een default, één string per regel, in bronvolgorde.
Het vormanker heeft wel semantiek. Het filter van een vouw en de toets van een kwantor worden per element gelezen, met het element als onderwerp. Met anchor: "form" op een AttributeReference, CharacteristicCheck, Aggregation of QuantifierFold wordt die knoop gelezen op het onderwerp van de vorm, het object waarop de regel loopt; de voorwaardeknoop IdentityCheck toetst of het element dat onderwerp is (IR-SPEC 4.1a en 4.5, WF-122). Zo vertaalt de frontend het woord zelf en een vouw over een relatie van het onderwerp in een filter (§ 2). De specificatie legt het vormanker vast als voorlopig besluit.
De specificatie legt ook vast hoe de voorwaarde van een vorm wordt gelezen in het fixpunt, de toestand waarin geen regel nog iets verandert (RUNTIME-SEMANTICS 5.12): per vorm en object een status (HOLDS, FAILS, FAULTS, DISPLACED of OUTSIDE_VALIDITY) en per knoop het oordeel of de waarde die de evaluatie vond, of de fout met haar EF-code. Een lezing verandert niets aan wat de sessie berekent; een uitleg leest haar, in plaats van de voorwaarde in een eigen semantiek opnieuw uit te rekenen. De referentie-interpreter schrijft haar met --trace (tab Uitkomst hierboven), de Drools-backend met DroolsBackendMain --readings, en gate 17 houdt beide per casebestand gelijk; Clingo levert geen lezing. Meer op Onder de motorkap.
Referentie-interpreter, Clingo en Drools spelen elke case na tegen dezelfde vastgelegde verwachtingen; wat Clingo of Drools niet draagt, weigert die uitvoerder met naam, code en reden (gates 6 en 12, § 8). Overeenstemming alleen geldt niet als waarheid: de ankersubset legt absolute, met de hand berekende waarden vast. Specificatie en gates staan op Onder de motorkap.
The IR and the differential square
The IR travels over the wire as JSON in the format uchar-ir-v1, cases in uchar-case-v0, each with a strict JSON Schema (additionalProperties: false). Nodes, fields and enumeration values have English names (AttributeReference, greaterOrEqual), and the source text sits in a source record. Declared names, such as object types, attributes and labels, stand as they were written, in Dutch. v1 derives from v0, the faithful dump of regelspraak-java's resolved model; every deviation from v0 is in the construct register (§ 8). Every MUST in the specification carries an id WF-### and has a check in the verifier, a passing golden and a failing negative case, or is marked OPEN in the index. Gate 2 requires every document to round-trip canonically, byte for byte.
Beside what evaluation reads, the IR carries fields without semantics, for a consumer that shows a document or explains a decision. Gate 13 removes them and requires the reference interpreter, Clingo and both Drools renderings to give the same outcome without them as with them.
origin(IR-SPEC 2.13, WF-121), on a declaration the frontend made itself: the form that made it (inputAboveComputation,exceptionForSubtype,decisionTableRow,stepsAfterSetorstartPoint) and the declaration it comes from. Such a declaration cannot be recognised by its name, because an author can write the same words.Default.name(IR-SPEC 6.1): the name the source gives the block a default comes from. Injutterswet-meldingsketenthe default ofUitzondering op erkende meldingsdatum: herstelde meldingcarries the nameherstelde melding; an explanation can thus name the default that decided.Default.statuteAnnotations(IR-SPEC 6.1, WF-082): the// Bron:lines above the block of a default, one string per line, in source order.
The form anchor does carry semantics. The filter of a fold and the test of a quantifier are read per element, with the element as subject. With anchor: "form" on an AttributeReference, CharacteristicCheck, Aggregation or QuantifierFold, that node is read on the subject of the form, the object the rule runs on; the condition node IdentityCheck tests whether the element is that subject (IR-SPEC 4.1a and 4.5, WF-122). This is how the frontend translates the word zelf and a fold over a relation of the subject in a filter (§ 2). The specification records the form anchor as a provisional decision.
The specification also fixes how the condition of a form is read at the fixpoint, the state in which no rule changes anything any more (RUNTIME-SEMANTICS 5.12): per form and object a status (HOLDS, FAILS, FAULTS, DISPLACED or OUTSIDE_VALIDITY) and per node the verdict or value the evaluation found, or the fault with its EF code. A reading changes nothing the session computes; an explanation reads it instead of evaluating the condition again in a semantics of its own. The reference interpreter writes it with --trace (tab Result above), the Drools backend with DroolsBackendMain --readings, and gate 17 holds the two equal per case file; Clingo gives no reading. More in Under the hood.
The reference interpreter, Clingo and Drools replay every case against the same pinned expectations; what Clingo or Drools does not carry, that executor refuses by name, with a code and a reason (gates 6 and 12, § 8). Agreement alone does not count as truth: the anchor subset pins absolute, hand-computed values. The specification and the gates are described in Under the hood.
Beperkingen en reikwijdte
Een parser of backend mag zeggen dat hij iets niet kan; hij mag niet doen alsof. Wat een frontend-parser niet in de IR kan uitdrukken, staat er als Unresolved; wat een backend niet kan uitvoeren, weigert hij met naam en reden, en de gate telt die weigeringen, zodat een uitkomst óf volgens de specificatie is berekend óf uitdrukkelijk is geweigerd, en nooit stil ontbreekt.
Unresolved
Voor wat een bron niet kan uitdrukken heeft de IR de knoop Unresolved (in v0: Onopgelost); een document mag hem bevatten maar nooit verbergen (WF-044). Alleen een knoop die de evaluatie bereikt, geeft een fout; de met de hand gebouwde golden unresolved-behind-a-failing-condition heeft er drie achter een voorwaarde die niet geldt. De rode case corpus/red/wf044-unresolved-reached bereikt de knoop en moet in elke uitvoerder falen met foutsoort EF-019. De case pint die code, niet de tekst van een melding; de runners van referentie-interpreter en Clingo schrijven CODE EF-019 {}. De open begrippen van de Jutterswet, "onbesproken juttersgedrag" en "bijzondere gevallen", zijn bewust zo'n grens.
Zonder bronspelling
Eén IR-vorm heeft nog geen spelling in een brontaal: het lezen van een tijdlijn op een ander tijdstip dan de evaluatiedatum (TemporalRead). Geen frontend produceert hem; hij komt alleen voor in handgeschreven goldens. Beslistabellen (de frontend ontsuikert ze tot één regel per rij), objectcreatie, machtsverheffen, alle afrondingsrichtingen, verdeling op volgorde van, het maximum, recursieve regelgroepen en twee versies van één regelnaam hebben elk een golden met RegelSpraak-bron, zodat gate 10 ook hun byte-identieke her-emissie bewijst.
Weigeringen
Een tijdsafhankelijk attribuut of kenmerk in de voorwaarde van een regel met een scalair doel weigeren alle uitvoerders, behalve onder gedurende het gehele …; op een tijdlijndoel lezen ze zo'n voorwaarde per periode (§ 3). Clingo weigert vijf goldens met naam en code (gate 6). Drools speelt het merendeel van de goldens na en weigert de rest met naam en code (de actuele dekking staat in de gates-tabel op Onder de motorkap), zoals EXCLUDE DROOLS-023: loader: form not carried by the v0 Drools backend: Expr:TemporalRead (unknown expression node). De twee weergaven van de backend, executable model en DRL-tekst, geven per golden dezelfde statusregel (gate 12); een deel van de Catala-goldens gebruikt vormen die Drools niet ondersteunt (§ 5). De Catala-frontend weigert onder meer duration en het sorteren van lijsten, de F-logic-frontend onder meer \naf, F-logic's eigen verweerbare redeneren en een tweede supertype.
Foutsoorten
RUNTIME-SEMANTICS 5.7b geeft elke foutsoort een code, EF-001 tot en met EF-040, met een kanaal, parameters en een getuige in het corpus; een code wordt nooit hergebruikt of hernummerd. Het kanaal zegt wat er gebeurt: de case wordt bij het inlezen geweigerd (case input), de sessie breekt af (fault), elke uitvoerder weigert een vorm waaraan de specificatie geen betekenis geeft (declined), of er ontstaat een feit op het foutkanaal (§9.5, RUNTIME-SEMANTICS 5.6). Op dat laatste kanaal staan een schending van een consistentie-eis (EF-025), een dubbele uniciteitssleutel (EF-026), ongeordende defaults die verschillend beslissen (EF-027), een leeg gewicht of een leeg of negatief maximum bij een verdeling (EF-028 tot en met EF-030), een negatief gewicht bij een verdeling naar rato (EF-038), een deling door een lege deler (EF-031), en een gevulde teller gedeeld door een numerieke nul of een numerieke nul tot een negatieve macht (EF-005). Zo'n feit breekt de sessie niet af en draagt de code naast regel en object. Een uitvoerder zet de code vóór de tekst van zijn melding; die tekst is van de uitvoerder zelf. Een rode case pint een code met parameters, geen tekst, en een golden mag op een inconsistentie een code pinnen (§ 3).
Buiten de reikwijdte van v1
v0 is de getrouwe kopie van de IR van regelspraak-java; v1 is de eigen versie van uchar, met Engelse namen op de draad (§ 7). Elke afwijking staat als rij in het constructenregister (spec/CONSTRUCTS.md): een tabel met per construct de herkomst (RegelSpraak, Catala, LegalRuleML, OpenFisca of de review), het oordeel voor v1 (kern, dialect, suiker, later, of geen doel), of het een eigen kernelknoop nodig heeft, en wat er van v0 naar v1 veranderde. Datzelfde register legt dus ook vast wat v1 bewust niet doet, met reden en termijn.
- Een tweede tijdas, kennistijd, en daarmee terugwerkende kracht: v1 kent één tijdas en benoemt alleen het uitbreidingspunt; gepland voor v2. Een later raadsbesluit met terugwerking is daarom nog niet te modelleren.
- Jurisdictie: geen doel van v1; het blijft een vaste toets aan LegalRuleML.
- De deontische laag, verplichting, toestemming, verbod, schending en herstel: geen doel, omdat v1 een constitutieve reken-IR is. Regels bepalen wat als wat geldt, niet wie wat moet doen. Gemeten aan de meldplicht in de Jutterswet: een plichtpositie kan als gewone waarde in de huidige kern meerijden, en een aparte laag werd daardoor minder waarschijnlijk, niet meer.
- Parameterschijven, schijventarieven zoals in de inkomstenbelasting: centraal in belastingrecht, maar afwezig in RegelSpraak; vandaag uit te drukken als regels of beslistabel. Een eigen knoop komt pas als een brontaal erom vraagt.
- Normautoriteit, wie de norm stelt: metadata op bronverwijzingen, later.
- Een scenario- of conformancetestformaat is voor de IR geen doel; het leverde wel het case-schema van het corpus. Daarom staan scenariotoetsen niet in de IR: de RegelSpraak-frontend vertaalt ze naar casebestanden (§ 2).
Limitations and scope
A parser or backend may say that it cannot do something; it may not pretend. What a frontend parser cannot express in the IR is recorded there as Unresolved; what a backend cannot execute, it refuses by name and with a reason, and the gate counts those refusals, so that an outcome is either computed according to the specification or explicitly refused, and never silently missing.
Unresolved
For what a source cannot express, the IR has the node Unresolved (in v0: Onopgelost); a document may contain it but never hide it (WF-044). Only a node the evaluation reaches gives a fault; the hand-built golden unresolved-behind-a-failing-condition has three behind a condition that does not hold. The red case corpus/red/wf044-unresolved-reached reaches the node and must fail in every executor with fault kind EF-019. The case pins that code, not the text of a message; the runners of the reference interpreter and Clingo write CODE EF-019 {}. The Jutterswet's open concepts, "onbesproken juttersgedrag" (irreproachable conduct) and "bijzondere gevallen" (special cases), are deliberately such a boundary.
Without a source spelling
One IR form has no spelling in a source language yet: reading a timeline at a time other than the evaluation date (TemporalRead). No frontend produces it; it occurs only in hand-written goldens. Decision tables (the frontend desugars them into one rule per row), object creation, exponentiation, all rounding directions, distribution op volgorde van (in order of), the maximum, recursive rule groups and two versions of one rule name each have a golden with a RegelSpraak source, so gate 10 proves their byte-identical re-emission as well.
Refusals
All executors refuse a time-dependent attribute or characteristic in the condition of a rule with a scalar target, except under gedurende het gehele … (during the whole …); on a timeline target they read such a condition per period (§ 3). Clingo refuses five goldens by name and code (gate 6). Drools replays most of the goldens and refuses the rest by name and code (the current coverage is in the gates table on Under the hood), such as EXCLUDE DROOLS-023: loader: form not carried by the v0 Drools backend: Expr:TemporalRead (unknown expression node). The two renderings of the backend, the executable model and DRL text, give the same status line per golden (gate 12); some of the Catala goldens use forms Drools does not carry (§ 5). The Catala frontend refuses, for instance, the duration type and list sorting; the F-logic frontend refuses, for instance, \naf, F-logic's own defeasible reasoning and a second supertype.
Fault kinds
RUNTIME-SEMANTICS 5.7b gives every fault kind a code, EF-001 to EF-040, with a channel, parameters and a witness in the corpus; a code is never reused or renumbered. The channel says what happens: the case is refused while it is read (case input), the session aborts (fault), every executor refuses a form to which the specification gives no meaning (declined), or a fact arises on the error channel (§9.5, RUNTIME-SEMANTICS 5.6). On that last channel stand a violated consistency requirement (EF-025), a duplicate uniqueness key (EF-026), unordered defaults that decide differently (EF-027), an empty weight or an empty or negative cap in an allocation (EF-028 to EF-030), a negative weight in a proportional allocation (EF-038), a division by an empty divisor (EF-031), and a division of a filled dividend by a numeric zero or a numeric zero raised to a negative power (EF-005). Such a fact does not abort the session and carries the code beside rule and object. An executor puts the code before the text of its message; that text is the executor's own. A red case pins a code with parameters, not a text, and a golden may pin a code on an inconsistency (§ 3).
Outside the scope of v1
v0 is the faithful copy of the IR of regelspraak-java; v1 is uchar's own version, with English names on the wire (§ 7). Every deviation is a row in the construct register (spec/CONSTRUCTS.md): a table with, per construct, its origin (RegelSpraak, Catala, LegalRuleML, OpenFisca or the review), the verdict for v1 (core, dialect, sugar, later, or non-goal), whether it needs a kernel node of its own, and what changed from v0 to v1. That same register therefore also fixes what v1 deliberately does not do, with a reason and a horizon.
- A second time axis, knowledge time, and with it retroactivity: v1 has one time axis and only names the extension point; planned for v2. A later council decision with retroactive effect therefore cannot be modelled yet.
- Jurisdiction: not a goal of v1; it remains a standing test against LegalRuleML.
- The deontic layer, obligation, permission, prohibition, violation and reparation: not a goal, because v1 is a constitutive calculation IR. Rules define what counts as what, not who must do what. Measured against the reporting duty in the Jutterswet: a duty position can ride along as an ordinary value in the current kernel, which made a separate layer less likely, not more.
- Parameter brackets, bracket tariffs as in income tax: central to tax law but absent from RegelSpraak; expressible today as rules or a decision table. A node of its own comes only when a source language asks for it.
- Norm authority, who sets the norm: metadata on source references, later.
- A scenario or conformance-test format is not a goal for the IR; it did supply the case schema of the corpus. That is why scenario tests are not part of the IR: the RegelSpraak frontend translates them into case files (§ 2).