rslc reads as RSL 0.4.1, form by form. Each excerpt quotes a checked example rater.
Names lists every section, type and annotation key, and
Functions explains every function.
The language tour teaches the same forms in reading order.
Two synthetic raters from the carrier “Example Mutual” supply the excerpts: auto and auto-extras.
Examples shows both whole. Save and check them with these commands:
Find a form
Each row names something a rater or a guideline states, its shortest form and the section that defines it.Notation
Each grammar block uses this notation:inputs block or a step, the comma is optional.
rslc fmt writes one comma between items and leaves the last item bare.
Files and versions
An RSL program is one entry file plus the files it imports. Three kinds of entry file exist:- Sections stand in any order, and a name resolves wherever its declaration stands in the program.
rslc fmtkeeps the order you write. - A file may repeat a section. The compiler reads the repeats as one section.
- Spaces and line ends only separate tokens.
- A comment starts with
#and runs to the end of its line. use,RolesandActsbelong to a guideline. See Guidelines.
The spec block
A value is a literal or a bare word, so
state: AZ and state: "AZ" both pass.
Write product for the name a customer reads. The older field name gets
E-RATER-METADATA-INVALID.
Versions
rslc reads the RSL 0.4 line: rsl: "0.4" and its patch rsl: "0.4.1".
Any other version, or a spec that lacks rsl, gets one
E-RSL-VERSION message and stops the check.
Versions explains how a patch relates to its line.
import
- The string is a path relative to the importing file, or a standard-library path that starts with
std/. - An import reads every section of the named file into the program. Sections with the same name merge.
- A scenario imports the rater it tests. A large rater imports files of types, constants or tables. See Split a rater into files.
package
package line is a shared-facts package: questions that several raters ask in the same words.
It holds Types, Tables and records made of inputs only. See Shared facts.
Lexical elements
- Case is syntax. Fields, constants, enumeration members, functions and steps start in lower case. Types, records, tables and sections start in upper case.
- Keywords such as
if,match,stepandwhereare identifiers that the grammar reads by position. - A number is an exact decimal. Write the digits on both sides of the point:
0.5. Exponents and digit separators are outside the language. - A minus sign directly before digits belongs to the number. Write
x - 1with spaces: the compiler readsx -1as two values and reports a parse error. - A date is a calendar day from
0001-01-01to9999-12-31. - A string appears in annotations, in a
Codecomparison, inotherwisecells, inimportanduse, and afternl.
Sources and citations
artifact and kind; anything else gets
E-SOURCE-SCHEMA.
The string in artifact(…) is the identifier of the stored document. The compiler checks each region’s form and leaves the document closed.
A citation is the annotation [cite: source:region]. The region follows the kind of the source:
reason states why a number that the filing leaves unstated is in the rater:
E-CITATION.
Evidence belongs in citations: a comment that carries a page reference gets
E-PROVENANCE-COMMENT.
Citations explains what a citation establishes.
Types
Types gives a type a name. The dimension forms and enumerations exist only as named types in Types.
Scalars
Premium, Rate, Factor and Pct are numbers with a stated meaning.
Words are enumerations or Code types: RSL has left Text behind.
Numbers and precision
Every number is an exact rational:1 / 3 stays one third until a round narrows it.
Exact numbers gives the reasons.
A numeric input states its precision in metadata after the type, and its range in a refinement:
- Metadata follows the whole type:
Option(Num) {precision: int}. - A numeric input needs both a precision and a range
where self in [a, b], else the check reportsE-INPUT-DOMAIN. - Either end of a range may be
_for an open side:[0, _]. - A request value off the precision grid or outside the range is refused before rating. See Refusals.
Enumerations
@Coverage.collisionnames a member in an expression.- A member written
frame = "F"has the valueF: a request and a table cell hold the value. A plain member’s value is its name. - A member takes a
label, the words a person reads. Combustible = Construction - { fire_resistive }declares a narrowed enumeration: the members ofConstructionminus the listed ones. Its members read@Combustible.frame.- An enumeration of more than 256 members belongs in a CSV file:
E-DATA-AS-CODE.
Name = Enum reads the members from enums/Name.csv beside the file:
A CSV-backed enumeration may key a table. A map or a fold needs an enumeration declared in the file:
E-MAP-DATA-SIZED.
The annotation [listed] on the type lists its members in the input contract.
Bands and value lists
- A band runs from its cut to the next cut. With a plain last cut, as in
IntBands(0, 10, 20), the bands are 0 to 9 and 10 to 19, and 20 is outside. - An open bottom is the first item and repeats its number in the next item. An open top is the last item. Cuts ascend.
- A sentinel bound such as 999999 gets
E-BAND-SENTINEL: write an open band. - A dimension lists at most 65,536 items.
A computed key of a band lookup must sit on the band’s grid: round it first, or declare
key: unrounded.
The check reports E-KEY-HOLE otherwise.
Codes
ACode type holds text that matches a pattern, such as a postal code or a license number:
- The pattern is a regular expression over printable ASCII that the whole value must match.
- A pattern holds literals, classes such as
[A-Z0-9], groups,|,?and counts such as{5}or{1,3}.*and+follow one literal or one class. - A pattern outside this set gets
E-CODE-PATTERN. - Two codes compare with
=and!=only. A code compares with a string literal:self.zip = "85001". - A
Codetypes an input and a table dimension. A column that holds codes of another table has the typeKey(Table).
Option
Option(T) is a value that is present, Some(value), or absent, None.
- A request leaves an optional field out, or sends
null, forNone. - A calculation reads an
Optionthroughmatch, through a rule clause, or with= None. Arithmetic on anOptionisE-TYPE. Some(x)makes a present value in a calculation of typeOption(T).- A refinement on an optional field tests the present value.
- A field with a filed default is an
OptionwhoseNonearm holds the default.
List, Ref and Key
self.principal above is an Option of a driver: a match binds the driver and reads its fields.
A plain Ref(Driver) field reads through the reference: self.principal.age.
A lookup keyed by a Key(Table) value always finds its row, so the table works with its filed rows alone.
Unions
- Each arm is a record that holds inputs and rules only.
- A request sends the arm’s name as
tag, beside the arm’s fields:{"tag": "Installments", "count": 6}. - A calculation reads a union with a
matchthat names every arm._is unavailable here:E-UNION-USE.
Maps
A map holds one value for each member of an enumeration. A calculation declares one with an index, and a table column declares one withType[Enumeration]:
cis the binder: inside the body it holds one member ofCoverage.- A read names its key:
self.base_rate[c]orself.base_rate[@Coverage.collision]. - The key type is an enumeration declared in the file, or a refined one such as
PhysicalDamage. - A read whose key may fall outside the map’s key type gets
E-MAP-DOMAIN. - A fold visits every member:
sum(Coverage as c, self.coverage_premium[c]).
Refinements
Bool expression. self is the value.
- A field of a refined type inherits the rule.
annual_miles: Milesrefuses 30,000 with the codeMILEAGE. - A value states one range, on its type or on its field:
E-REFINEMENT. - A bound has one spelling,
self in [a, b].self >= agetsE-REFINE-CANONICAL. c in PhysicalDamagetests membership of a refined enumeration in an expression.- Rules covers refinements on fields, lists and records, and their codes.
Constants
- A constant is a fixed value with a citation, or with
[reason: "…"]. - A calculation reads a constant by its bare name.
Constants.policy_feeis the long form.
Tables and lookups
Declaration
- Every column and every dimension is read by a calculation, or the check reports
E-TABLE-UNUSEDand its relatives in the same topic. - An
otherwiserow that each lookup already covers getsE-OTHERWISE-DEAD. - An
otherwisecell holds the text of a CSV cell: a number,true,false, or a string such as"remainder"for an enumeration value.
CSV files
The filetables/DriverClass.csv of the auto rater starts:
Read a filed table works through the layouts a filing uses.
lookup!
- The arguments are the table and one key for each dimension, in the declared order. The suffix names one column, and
[member]names one value of a map column. - The subscript of a map column is a binder or one member written
@Coverage.collision. The binder belongs to the map calculation that holds the lookup, ascdoes above, or to a fold such assum(Coverage as c, …). - Any other subscript, such as an input in
.rate[self.coverage], getsE-MAP-DOMAIN. - To read the member that an input names, read the column into a map calculation as above, then index that map:
self.base_rate[self.coverage]. Use a filed rate table shows both steps. - A number key selects its band or its listed value. An enumeration,
BoolorCodekey selects its exact row. - The check proves that every call finds a row. A key that may leave the dimension gets
E-KEY-RANGE, and a reachable key that lacks a row getsE-LOOKUP-GAP. - Close a gap with a narrower key type, a filed row, an open band or an
otherwiserow. - The
!is part of the name.lookup(…)getsE-LOOKUP-SYNTAX.
interpolate!
- The last dimension is a value-list type that holds the filed points. The last key is the value to read at.
- At a filed point the result is that row’s value. Between two points
p1andp2with valuesv1andv2, the result isround(v1 + round(ratio * (v2 - v1))), whereratio = round((x - p1) / (p2 - p1)). ratio,stepandresultstate the three roundings in that order, each as(scale, mode).ratioandstepmay beexact.- With 12,000 miles the example reads 1.048: two fifths of the way from 1.000 to 1.120.
- The key must lie inside the filed points, else the check reports
E-INTERP-RANGE. A band dimension or anotherwiserow getsE-INTERP-KEY.
Geographies and locate
cells table is one cell, with its key and one point inside it.
- Every field of the chosen method is required.
locate(Geography, latitude, longitude)givesSome(key)for a point inside a filed cell andNoneelsewhere.- A
Somekey is a filed key, so the lookup that follows always finds its row.
Records
- The records of a program form one tree with one root. The request is the root record.
E-RECORD-ROOT,E-RECORD-POSITIONandE-RECORD-RECURSIVEreport a broken tree. - A record sits at one field of one parent. A record that holds itself is outside the language.
- The input contract describes the request that the records define.
Inputs
- The clauses follow the order of the grammar.
keyed bystands before the metadata and the annotations. - An input takes a type and rules, and a calculation takes
=and a value. - Every input is read by a rating outcome or by a rule, or the check reports
E-UNREAD-INPUT.
Follow-up inputs
whenmakes an input a follow-up: the request gives it where the condition holds. Left out under a true condition, it is refused withINPUT-FOLLOW-UP.- Where the condition fails, the rater ignores a given value.
- A read of a follow-up sits under its condition, as in the rule
not self.prior_insurance or self.prior_lapse_days <= 30. Any other read getsE-FOLLOW-UP-READ. - A
Boolfollow-up follows the same rule:condition and answercounts an unasked question as false, andnot condition or answercounts it as true. - The condition reads inputs of the same record. A list follow-up gets
E-FOLLOW-UP-TYPE.
Lists and keys
keyed by numbernames an input of the item record. The key is distinct across the list, and a repeat is refused withINPUT-KEY.- A keyed list is a map from key to record, so one request rates the same way however its list is ordered.
find,argmax,argmin,topnandrankbreak ties by the key, and they need a keyed list:E-SELECT-TIE. indexreads a position, so it takes a plain list. On a keyed list it getsE-KEYED-ORDER, and so does=between two lists of keyed records.- A
Ref(Record)field names one item of a keyed list by its key. An unknown key is refused withINPUT-REF. len(self)bounds the length andunique(self as d, d.license)states a second distinct field.- Rate a list works through folds over a list.
Steps and calculations
- A step groups calculations under a name. A step takes
in stage,cite,label,noteandskip. - A calculation has a name, a type and one expression.
name[c: Enumeration]declares a map: one value for each member.- Calculations stand in any order. A cycle gets
E-CYCLE. - Every calculation reaches a rating outcome, or the check reports
E-ORPHAN-COMPUTED. - A child’s calculation that reads only its parent belongs on the parent:
E-HOIST. - A refinement on a calculation’s type,
where self in [a, b], is a claim that the check proves:E-COMPUTED-RANGE. [skip: "id":"reason"]on a step marks a step of the manual that the rater leaves out.
rsl: "0.4.1".
A clause belongs at the end of a calculation. To use one inside a larger expression, name the value as its own calculation.
A calculation whose value is still prose holds
nl "text". The strict check fails while a hole remains, and rslc check --allow-incomplete reports the rest.
Rules
A rule is a refinement on an input, on a list or on a record.self is the value that the rule tests.
- A rule that lacks a code is an input rule: the refusal is
InvalidInputswith a code such asINPUT-RANGE. citeis optional on every rule. A coded business rule and a plain range such aswhere self in [0, 6]both pass the check uncited.- A refusal of an uncited rule holds
"cite": null. - A
citeon a rule names a declared source and a region of that source’s kind, or the check reportsE-CITATION. - A rule takes
code,messageandciteonly.reasonon a rule getsE-ANNOTATION. codeandmessagefollow the rule’s expression. On the input’s own brackets they getE-ANNOTATION.- On an input, write an equality inside parentheses:
where (count(self as d, d.named_insured) = 1). A bare=there ends the declaration. - A rule reads its own value and what lies below it. A rule that relates a child to its parent stands on the parent:
E-REFINE-UPWARD. N% of xis an exact share, for rules only:self.coverage_c <= 70% of self.coverage_a.- A rule may use dates, arithmetic,
if,match, folds over its own lists, constants andlookup!. - Rating starts after every rule passes. A calculation always gives a value. Refusals lists each refusal code and the order of the checks.
Expressions
Precedence
From the loosest binding to the tightest:=tests equality and!=tests the opposite.==is a parse error.notbinds tighter than a comparison:not a = breads as(not a) = b, a type error. Writenot (a = b)ora != b.not self.prior_insurance or self.prior_lapse_days <= 30reads as(not …) or (… <= 30).- Both sides of a comparison have the same type.
<and its relatives order numbers and dates. - Every division proves a divisor other than zero, or the check reports
E-DIV-ZERO.
if and match
- Both branches of an
if, and every arm of amatch, have the type of the calculation. - A
matchcovers every case, or the check reportsE-MATCHorE-OPTION-MATCH. - Inside an arm, the check knows the matched case:
lookup!(DeductibleFactor, self.deductible, c)above passes becausecis aPhysicalDamagemember in those two arms. - An
ifthat sorts a number into classes belongs in a band table:E-IF-AS-TABLE.
Field access, self and binders
list as dbinds each item of a list todfor the rest of a call.Enumeration as cbinds each member.list as d by d.keyadds the order of a stepwise fold.- A read of a record that stands outside the path to the root gets
E-ANCESTOR-READ.
Membership
Dates
Dates compare with=, !=, <, <=, >, >= and in [a, b]. Arithmetic on dates goes through functions:
Work with dates derives ages and terms.
Functions
A call isname(arguments). Only lookup! and interpolate! take !. Functions gives the rules of each one.
Numbers:
Folds and lists:
A fold that walks a list once for each item of the same list gets
E-QUADRATIC when the walk reads the same value each time.
Rounding
- Arithmetic is exact, and a value changes precision only where the file says
round,root,powwith four arguments,round_eachorinterpolate!. scaleis a whole-number literal: the count of decimal places. A negative scale rounds to tens, hundreds and beyond:round(x, -3, half_up).- The mode is required.
- Every numeric rating outcome passes through a
roundin a calculation that cites the rounding rule.
round(1.25, 1, half_up) is 1.3 and round(1.25, 1, half_even) is 1.2. Round a premium compares the modes.
Questions and choices
A wrong placeholder, format or shape gets
E-QUESTION.
from and filled_by
These two inputs come from the package of the next section:
x: T from expressionsuggests an answer. The expression reads inputs and tables of the same record, and the person accepts the suggestion or answers over it.[filled_by: "function(input).field"]names a host function that fills the input, so the question is skipped.- Rating reads the answer and ignores the
fromexpression. An input that only afromreads stays optional, and a calculation that reads it getsE-FROM. x: T refines baseplaces a question directly afterbase, an input of the same record.
Shared facts
A shared-facts package declares questions once for many raters. This package and the rater that binds it check together:household/facts.rsl and household/rater.rsl
household/facts.rsl and household/rater.rsl
household/facts.rsl
household/rater.rsl
household/tables/ZipFactor.csv
household/tables/DeductibleFactor.csv
- A rater binds a shared fact by its name alone. A second declaration gets
E-FACT-REDECLARED, and an unknown name getsE-FACT-BINDING. - A shared fact that the rater leaves unread is optional in its requests.
- A package holds
Types,Tablesand records ofinputs:E-FACT-PACKAGE.
A host that shows the questions reads these keys as well.
The input contract shows each one in a checked rater.
In a rater that imports a package, each choice states its
shape:
E-CHOICE-SHAPE.
Outcomes
RatingOutcomeslists the calculations a program returns, each under a public name. The block holds one outcome or more.- A target is a calculation of type
Premium,Num,Rate,Factor,Pct,Boolor an enumeration. One outcome or more is aPremium. - Each numeric outcome is rounded in a calculation that cites the rule.
- A rater evaluates what its outcomes read. Results describes what a host returns.
- A wrong target gets
E-RATING-OUTCOME.
Stages, labels, notes and concepts
A concept wraps the type of a calculation, an input or a table column. The
rating@2 vocabulary holds these concepts:
- A concept must fit the value’s type and formula, or the check reports a message of the rating manual topic.
- Once a rater uses labels or concepts, the check prints hints for values that lack them:
H-LABEL-MISSINGandH-CONCEPT-MISSING. A hint leaves the check passing. - In an RSL 0.4.1 file, arithmetic reads named values, constants and inputs. An inline
lookup!,if,matchorroundinside arithmetic getsE-CHAIN: name it as its own calculation.
Scenarios
The scenario’s request passes the same rules as a rating request. The file stands beside the rater that it imports.
Test a rater covers expected premiums and refusals.
Guidelines
staffing:
- A guideline reads a used rater through its inputs and its outcomes only:
E-USE. - Every role that
Acts,byorrefernames is declared inRoles:E-ROLE. - A referral’s name is distinct:
E-REFER. - In an input,
byorper quotefollows the type and its metadata, beforerefines,fromandwhen.
Terms of a quote
staffing. per quote marks an input as a term. Each quote
of one submission may hold its own answer to a term. Every other input is a fact, and all
quotes of the submission share one answer to it.
- Only the submission log reads the mark. A rater rates the same with the mark and with the mark removed.
- A rater and a guideline each mark their own inputs. A term of a used rater is a term in each guideline that uses it.
- The mark covers its own input. On a record or an
Option, it covers whether the record is present. A field of that record is a term only when the field carries the mark too. - An input takes
byorper quote, one of the two. An input with both getsE-ROLE, because a role’s answer is a judgment that every quote shares.
rslc submission open holds the marks to three more rules, and each breach stops it with E-ROLE:
Quote options describes how the log answers and quotes a term.
Raters and guidelines explains the split, and
The submission log records answers, sign-offs, quotes and binds.
What the check proves
rslc check accepts a file only when every rule on this page holds, every lookup finds a row, every division has a divisor other than zero
and every request that passes the input rules gets a value for each outcome.
Each message has a code, and Check messages explains each code with an example and its fix.
What rslc checks and guarantees states what a passing check establishes.
Removed forms
rslc still reads these older spellings so that it reports the current one. Each row gets an error;
Messages for older forms explains the codes.