Parameters and expressions
parameters are the numbers a person would want to change: the mattress size, the timber, the
deck height. Everything else in the document should be derived from them, so that changing
one moves the whole piece rather than leaving half of it behind.
parameters: - id: deck_height label: Height of the slat top above the floor type: length value: 300 min: 180 max: 500
- id: deck_width label: Clear width between the rails type: length derived: mattress.width + 2 * mattress_clearanceEvery parameter has an id and a type, and optionally a label and a description. The
label is what a person sees; write it as a sentence, not a variable name.
value or derived, never both
Section titled “value or derived, never both”value is entered. derived is computed, and is always an expression string. A parameter
with neither is SCH-002.
The distinction is the difference between a piece that can be resized and one that cannot. If
you find yourself typing the same arithmetic into two blank: entries, that number wanted to
be a derived parameter.
The five types
Section titled “The five types”length
Section titled “length”Millimetres. min and max bound it, and are themselves expressions.
- id: headboard_height type: length value: 900 min: 600 max: 1400number, count, angle
Section titled “number, count, angle”The same shape as length — value or derived, with optional min and max. count is
a whole number of things; angle is degrees.
A closed list, and a chosen value. Referencing it yields the string, so it is normally fed
into a material’s species rather than into arithmetic.
- id: species type: enum values: [walnut, white_oak, ash, maple, cherry] value: walnutboolean
Section titled “boolean”- id: add_centre_rail type: boolean value: truecatalog_ref
Section titled “catalog_ref”Names a catalogue family and one entry in it. This is the useful one: the parameter then behaves like the entry, so its fields read as sub-references.
- id: mattress type: catalog_ref catalog: standards.mattress value: us-queenmattress.width is then 1524 and mattress.length is 2032, and changing value to
uk-double moves every part derived from them. A value that is not in the family is
RES-005, and the report lists the ones that are.
The expression language
Section titled “The expression language”Expressions are the only computation in the format, and the evaluator is a hand-written
recursive-descent parser. It never calls eval, never builds a function and never reaches a
global. The only names it can see are the ones listed below.
Operators, in the usual precedence: ^ · * / % · + - · < <= > >= · == != · && ·
|| · ? :, with unary - and !, and parentheses.
Functions: min, max (both variadic), round, ceil, floor, abs, sqrt,
clamp(value, low, high).
count: ceil((slat_cleat.blank.length - slat.blank.width) / (slat.blank.width + max_slat_gap)) + 1There are no user-defined functions, no loops and no conditionals beyond the ternary. If a computation does not fit, the answer is another derived parameter, not a longer expression.
What an expression can see
Section titled “What an expression can see”| Reference | Yields |
|---|---|
deck_height |
A parameter’s value |
mattress.width |
A field of a catalog_ref parameter’s entry |
rail_stock.thickness, .width |
A resolved material’s actual milled dimension |
rail_stock.density, .modulus_of_elasticity |
That material’s species properties |
side_rail.blank.length, .width, .thickness |
Another part’s resolved blank |
standards.bed.slat_gap_max |
A catalogue standard |
That table is the whole reach of the language. A bare part or material name is not a value —
side_rail on its own resolves to nothing. Local names win over catalogue names, and nothing
local may be called standards.
Resolution is lazy and memoised, so these may depend on each other in any order. A real loop
is RES-003, and the finding names the cycle.
Where expressions are allowed
Section titled “Where expressions are allowed”Anywhere the reference says Expr: blank dimensions, feature sizes and positions, offsets,
pattern counts and spacings, min/max bounds, and array counts.
In a number-typed field, a string is always an expression — no marker needed:
blank: length: deck_length # expression width: rail_stock.width # expression thickness: 38 # numberIn a text-typed field, an expression needs a leading =, because the literal text is
usually what you meant:
species: walnut # the literal string "walnut"species: "=species" # the value of the `species` parameterThe hyphen rule
Section titled “The hyphen rule”Catalogue keys contain hyphens — standards.mattress.us-queen.width — and so does
subtraction. The rule the tokeniser applies:
A hyphen continues an identifier only when it sits directly between an identifier character and a letter or underscore, with no whitespace.
| Written | Read as |
|---|---|
us-queen |
one name |
deck_height - rail_stock.width |
subtraction |
width-10 |
subtraction — a digit follows the hyphen |
a-b |
one name |
So if you mean subtraction between two single-word names, put spaces around the minus. Getting
it wrong is a clear RES-002 — an unknown name — not
a wrong number quietly compiled.
Worked: sizing a bed from its mattress
Section titled “Worked: sizing a bed from its mattress”parameters: - { id: mattress, type: catalog_ref, catalog: standards.mattress, value: us-queen } - { id: mattress_clearance, type: length, value: 6, min: 3, max: 15 } - { id: deck_height, type: length, value: 300 }
- id: deck_width type: length derived: mattress.width + 2 * mattress_clearance
- id: max_slat_gap type: length derived: standards.bed.slat_gap_max
- id: post_centre_offset type: length derived: deck_width / 2 + rail_stock.thickness / 2Nothing in that block is a measurement of this particular bed. Change us-queen to
uk-double and the rails, the cleats, the slat count and the gap between slats all follow.