Skip to content

Expressions (PEL)

PEL (Phony Expression Language) is the small language used wherever PDL composes or transforms values:

Used inAs
template.pattern / variants[].patterna template string with {{ … }} placeholders
field computeda bare expression over sibling fields
modifiers.transforman expression over the produced value
template.operationsa list of function names applied in sequence
Linked rulesan expression over prior columns

Template syntax

Anything outside {{ … }} is literal text; inside is an expression. Escape braces with a backslash.

text
Hi {{first_name}}!  Ref #{{number:1000-9999}}
\{\{ literal braces \}\}

References

text
{{name}}             run the generator "name" (or reuse a same-named row field)
{{country.code}}     a nested property of an object value
{{self.first_name}}  another field in the same entity row

References are memoized per row (same reference → one value).

Inline generators

Generate a value inline, without a separate generator definition. Each occurrence draws a fresh sub-seed.

text
{{number:1-100}}        {{number:0.0-1.0:2}}        {{number:1-100:step:5}}
{{pattern:###-##}}      # digit · ? A–Z · ^ hex · * alphanumeric
{{date:2020-01-01..2024-12-31}}   {{datetime:-1year..now}}   {{time:09:00..18:00}}
{{uuid}}  {{uuid:v7}}  {{ulid}}  {{nanoid}}  {{nanoid:10}}

Operators

ClassOperators
arithmetic+ - * / %
comparison== != < > <= >=
logical&& || !
grouping( )
literalsnumbers, 'strings'/"strings", inline lists ["a","b"]
json
"grade": { "computed": "if(score >= 90, 'A', if(score >= 80, 'B', 'C'))" },
"total": { "computed": "round((subtotal + tax) * (1 - discount), 2)" }

Function reference

Case & string

FunctionResult
lowercase uppercase capitalize titlecasecase transforms
camelcase snakecase kebabcase pascalcaseidentifier casings
trim reverse length repeat(s, n)basic ops
truncate(s, n[, suffix])cut to n chars
substring(s, start[, len])slice
pad(s, n[, ch]) padRight(s, n[, ch])pad to width
replace(s, from, to) concat(…) slugify(s)rewrite

Numeric

FunctionResult
add subtract multiply divide moduloarithmetic (also + - * / %)
round(n[, places]) floor ceil absrounding
min(a, b) max(a, b) clamp(v, lo, hi)bounds
uniform(lo, hi)random float in range

Conditional

FunctionResult
if(cond, then, else)branch
switch(x, k: v, …, default: v)multi-way
coalesce(…)first non-null
default(v, fallback)fallback if v is empty/null
optional(v)"" if null

Lists

FunctionResult
pick(list)random element
cycle(list)element at row % len (sequential by row)
sample(list, n|"a-b")n unique elements (array)
pick_weighted(list)weighted pick from [{value, weight}]

Masking & crypto

FunctionResult
mask(v, n[, "start"])show last (or first) n, mask the rest
redact(v)[REDACTED]
hash(v[, "sha256"|"sha1"|"md5"])hex digest
hmac(data, key)HMAC-SHA256 hex
base64(v) urlEncode(v)encodings
anonymize(v[, "domain"])consistent pseudonym (referential integrity)

Format

CallOutput
format(x, "decimal:2")1234.56
format(x, "percent")12.34%
format(x, "number")1,234
format(x, "currency[:CODE]")$1,234.56 / ₺…
format(x, "filesize")1.5 MB

Date & time

FunctionResult
now() today()the reference instant
age(date)whole years to the reference instant
addDays subtractDays addMonths addYearsshift a date
startOfMonth endOfMonth startOfYearsnap a date
dateDiff(a, b, "days"|"hours"|"months"|"years")difference

TIP

now/today/age and relative ranges never read the system clock — they resolve against an injected reference instant, so output stays reproducible.

For the complete language design (including parts still on the roadmap), see Spec → Expression Language.

Phony Cloud — Documentation & Specification