Value DSL
The Value DSL is Fascia's restricted expression language for defining computed values, transition guards, invariants, and data transformations. It is intentionally limited -- no function definitions, no loops, no side effects. Every expression is a pure computation that produces a result from existing data.
Value DSL expressions appear throughout Fascia specs:
- Entity invariants -- Business rules that must always hold true
- Status machine guards -- Conditions that must be met for a transition to occur
- Flow Transform nodes -- Data transformations between flow steps
- If/Switch conditions -- Branching logic in flow graphs
- Policy conditions -- Rules evaluated by the Risk Engine
Operators
Arithmetic
| Operator | Description | Example |
|---|---|---|
+ | Addition | order.subtotal + order.tax |
- | Subtraction | order.total - order.discount |
* | Multiplication | item.price * item.quantity |
/ | Division | total / count |
% | Modulo | index % 2 |
Comparison
| Operator | Description | Example |
|---|---|---|
== | Equal | order.status == "confirmed" |
!= | Not equal | user.role != "guest" |
> | Greater than | reservation.totalPrice > 0 |
< | Less than | now() < reservation.startDate |
>= | Greater than or equal | account.balance >= withdrawal.amount |
<= | Less than or equal | deposit <= totalPrice |
Logical
| Operator | Description | Example |
|---|---|---|
&& | Logical AND | isActive && isVerified |
|| | Logical OR | isAdmin || isStaff |
! | Logical NOT | !isDeleted |
Member Access
Use dot notation to access fields on entities and nested objects:
reservation.totalPrice
reservation.customer.name
input.paymentMethod
Built-in Functions
String
| Function | Signature | Description |
|---|---|---|
concat | concat(a, b, ...) | Concatenate strings |
length | length(str) | String length |
substring | substring(str, start, end) | Extract substring |
toLowerCase | toLowerCase(str) | Convert to lowercase |
toUpperCase | toUpperCase(str) | Convert to uppercase |
trim | trim(str) | Remove leading/trailing whitespace |
startsWith | startsWith(str, prefix) | Check if string starts with prefix |
endsWith | endsWith(str, suffix) | Check if string ends with suffix |
contains | contains(str, search) | Check if string contains substring |
replace | replace(str, search, replacement) | Replace first occurrence |
split | split(str, delimiter) | Split string into list |
Date
| Function | Signature | Description |
|---|---|---|
now | now() | Current date and time |
addDays | addDays(date, days) | Add days to a date |
addHours | addHours(date, hours) | Add hours to a date |
diffDays | diffDays(date1, date2) | Difference in days between two dates |
format | format(date, pattern) | Format date as string |
Math
| Function | Signature | Description |
|---|---|---|
abs | abs(n) | Absolute value |
ceil | ceil(n) | Round up |
floor | floor(n) | Round down |
round | round(n) | Round to nearest integer |
min | min(a, b) | Smaller of two values |
max | max(a, b) | Larger of two values |
Aggregation
| Function | Signature | Description |
|---|---|---|
sum | sum(list, field) | Sum a field across a list |
count | count(list) | Count items in a list |
avg | avg(list, field) | Average a field across a list |
Type
| Function | Signature | Description |
|---|---|---|
toString | toString(value) | Convert to string |
toNumber | toNumber(value) | Convert to number |
isNull | isNull(value) | Check if value is null |
coalesce | coalesce(a, b) | Return first non-null value |
Conditional
| Function | Signature | Description |
|---|---|---|
if | if(condition, thenValue, elseValue) | Conditional expression |
Example Expressions
Calculate 10% of a total:
reservation.totalPrice * 0.1
Conditional display text:
if(order.status == "pending", "Waiting for confirmation", "Processed")
Duration in days:
diffDays(reservation.endDate, reservation.startDate)
Check a business rule:
reservation.depositAmount <= reservation.totalPrice && reservation.totalPrice > 0
Format a summary string:
concat("Order #", toString(order.id), " - ", toUpperCase(order.status))
Constraints
The Value DSL is deliberately restricted for safety and predictability:
| Constraint | Limit |
|---|---|
| No function definitions | You cannot define custom functions |
| No loops or recursion | Iteration is not supported |
| No variable mutation | All expressions are pure; no assignment |
| No external calls | Cannot call APIs or services |
| No system calls | Cannot access the filesystem, network, or OS |
| Maximum expression depth | 256 levels of nesting |
| Maximum AST nodes | 1000 nodes per expression |
These constraints ensure that every Value DSL expression terminates in bounded time with no side effects, making the runtime fully deterministic.