Skip to content

Simpra DSL Language Tutorial

Gregory Nikolaishvili edited this page Aug 27, 2025 · 1 revision

Simpra DSL is a powerful, type-safe, and extensible expression language for .NET, designed for business rules, data validation, and dynamic logic. It is especially useful for financial and ISO 20022-based data models.


Table of Contents

  1. Introduction
  2. Basic Syntax
  3. Variables and Assignment
  4. Data Types
  5. Operators
  6. Conditionals
  7. Lists and Indexing
  8. Functions
  9. Pattern Matching
  10. Null and Existence Checks
  11. Mutability
  12. ISO 20022-Specific Examples
  13. Advanced Examples
  14. Grammar and Syntax Reference

Introduction

Simpra DSL allows you to write business logic and validation rules in a concise, readable way. It supports arithmetic, logical, and comparison operations, as well as advanced features like pattern matching, list operations, and custom functions. It is designed to be safe, predictable, and easy to integrate with .NET models, especially for financial and ISO 20022 data.


Basic Syntax

  • Each statement ends with a newline
  • Use let to declare variables.
  • Use return to output a value.
let x = 10
let y = 20
return x + y

Variables and Assignment

  • Variables are declared with let and can be reassigned if mutability is enabled.
  • Variable names are case-sensitive by default (can be changed with $case_sensitive directive).
let amount = Transfer.Amount
let currency = Transfer.Currency
return amount * 2

Data Types

  • Numbers: 10, 3.14, -5
  • Strings: 'USD', "Test"
  • Booleans: true, false
  • Lists: [1, 2, 3], ['USD', 'EUR']
  • Enums: Color.Red, Color.Green, or just 'Green' for comparison
  • Nullable: NullableEnum, Nint1
  • Domain Primitives: e.g., Max35Text, NonNegativeAmount
  • Dictionaries: Countries['US'], DictionaryOfObjects['Georgia']

Operators

Arithmetic

  • +, -, *, /, %, // (integer division)
let total = Transfer.Amount + 100
let percent = Transfer.Amount * 0.05

Comparison

  • is, is not, <, <=, >, >=
return Transfer.Amount > 100
return Transfer.Currency is 'USD'
return NullableEnum has value

Logical

  • and, or, not
return Transfer.Amount > 100 and Transfer.Currency is 'USD'
return not (Transfer.Amount < 0)

Membership

  • in, not in
return Transfer.Currency in ['USD', 'EUR']
return Transfer.Currency not in ['USD', 'EUR']

Pattern Matching

  • matches (regex), like (SQL-like patterns)
return Remittance matches '[A-Z]{4,}'
return Transfer.Currency like 'U%'

Conditionals

When Expression

let amount = Transfer.Amount
let result = when amount < 50 then 'Low'
             when amount >= 50 and amount < 200 then 'Medium'
             else 'High'
return result

If Statement

let x = Transfer.Amount
if x > 100 then
    return 'Large'
else
    return 'Small'
end
  • You can chain else if blocks as needed.

Lists and Indexing

List Declaration

let currencies = ['USD', 'EUR', 'GBP']
let numbers = [1, 2, 3, 4]

Indexing

  • Lists and arrays are 1-based.
return currencies[1]  // 'USD'
return Transfer.RegulatoryReporting[1].Authority.Country

List Operations

let all = ['USD', 'EUR'] + 'GEL'         // ['USD', 'EUR', 'GEL']
let diff = ['USD', 'EUR', 'GEL'] - ['GEL'] // ['USD', 'EUR']
let sumVal = sum([1, 2, 3])              // 6
let len = length(['USD', 'EUR'])         // 2

Functions

Built-in Functions

  • sum(list) - Sum of numeric list
  • length(list) - Number of elements
  • Upper(str) - Uppercase string
  • Lower(str) - Lowercase string
let values = [10, 20, 30]
return sum(values) / length(values)
return Upper('usd')  // 'USD'

Custom Functions

You can call user-defined functions registered in your host application.

return ListSomeCountries('GE')  // ["RU", "BE", "GE"]

Pattern Matching

Regex

let value = 'abc123'
return value matches '[a-zA-Z_][a-zA-Z_0-9]*'

SQL-Like

let str = 'foobar'
return str like 'foo%'

Null and Existence Checks

  • Use has value to check for non-null/non-empty values.
return Transfer.Customer has value
return NullableEnum has value
return not (NullableEnum has value) // check if null

Mutability

By default, Simpra is immutable. Enable mutability to allow assignments:

$mutable on
let x = 10
x = x + 5
return x

You can also assign to model properties:

$mutable on
Transfer.Amount = Transfer.Amount + 50
return Transfer.Amount

ISO 20022-Specific Examples

Accessing ISO 20022 Transfer Fields

// Accessing nested fields
return Transfer.RegulatoryReporting[1].Authority.Country

// Checking for a specific country
return Transfer.RegulatoryReporting[1].Authority.Country is 'US'

// Handling nullable fields
return Transfer.RegulatoryReporting[1].Details[1].Information[0] has value

// Comparing domain primitives
return Transfer.RegulatoryReporting[1].Details[1].Information[0] is 'Information1'

Aggregating and Validating Amounts

let amounts = [10, 20, 30, 40]
let maxAmount = amounts[3]
return Transfer.Amount > maxAmount

Pattern Matching on Remittance

return Remittance matches '[A-Z]{4,}'

List Membership for Currencies

return Transfer.Currency in ['USD', 'EUR', 'GBP']

Complex ISO 20022 Example

let transfer = Transfer
let amount = transfer.Amount
let ccy = transfer.Currency
let validCurrencies = ['USD', 'EUR', 'GBP']
let increasedAmount = when ccy in validCurrencies then amount + (amount * 0.05) else amount end
return increasedAmount > 180 and increasedAmount < 500

Dictionary Access

return Countries['US'] is 'United States'
return DictionaryOfObjects['Georgia'].Id

Advanced Examples

Safe Division

let divisor = 0
let safeDivision = when divisor is not 0 then Transfer.Amount / divisor else 0 end
return safeDivision

Nested List Access

return Transfer.RegulatoryReporting[1].Details[1].Information[0]

Null Handling in Nested Properties

return Transfer.Customer.Id is 1  // returns false if Transfer or Customer is null

Chained Conditionals

let x = Transfer.Amount
if x > 7 then 
    return 10
else if x > 5 then 
    return 6
else if x > 1 then 
    return 2
else 
    return round(1000)
end

Grammar and Syntax Reference

Directives

  • $mutable on|off - Enable/disable mutability
  • $case_sensitive on|off - Enable/disable case sensitivity for identifiers

Statement Types

  • Variable declaration: let name = expr
  • Assignment (if mutable): name = expr or Model.Property = expr
  • Return: return expr
  • Conditional: when ... then ... else ... end, if ... then ... else ... end
  • Function call: FunctionName(args)
  • List: [expr1, expr2, ...]
  • Indexing: list[index], dict[key]
  • Member access: object.Property

Supported Types

  • Numbers, strings, booleans, lists, enums, domain primitives, dictionaries

Supported Operators

  • Arithmetic: +, -, *, /, %, //
  • Comparison: is, is not, <, <=, >, >=
  • Logical: and, or, not
  • Membership: in, not in
  • Pattern: matches, like
  • Null: has value

Summary

Simpra DSL is a robust, extensible language for business rules and ISO 20022 data validation. It supports advanced data access, pattern matching, list operations, and custom functions, making it ideal for financial and regulatory applications.


For more details, see the README or your project's documentation.