Language Reference Overview¶
USL is a layered, policy-driven specification language for building secure, correct applications.
Language Structure¶
USL specifications consist of five layers:
graph TD
A[Domain Layer] --> B[Policy Layer]
B --> C[Behavior Layer]
C --> D[Service Layer]
D --> E[Escape Layer]
style A fill:#e3f2fd
style B fill:#fff3e0
style C fill:#f3e5f5
style D fill:#e8f5e9
style E fill:#fce4ec Domain Layer¶
Define entities, value objects, and business rules:
domain MyApp {
entity User {
id: UserId @primary
email: Email @unique
name: String
invariant valid_name {
len(this.name) >= 2
}
}
value Email {
address: String
invariant valid_format {
matches(this.address, EMAIL_REGEX)
}
}
}
Key Concepts: - Entities (mutable, with identity) - Value objects (immutable, validated) - Invariants (business rules) - Relationships (foreign keys)
Policy Layer¶
Define authorization rules:
policy UserPolicy {
actor user: User
rule can_edit(target: User) {
user.id == target.id || user.role == Role.Admin
}
deny rule no_self_delete {
user.id == target.id
}
}
Key Concepts: - Actor (who is acting) - Rules (authorization logic) - Allow/deny precedence - Policy composition
Behavior Layer¶
Model state machines and workflows:
behavior UserLifecycle for User {
initial state Pending
state Pending {
on verify -> Active
requires hasValidEmail(this)
effects {
this.verified = true
this.verifiedAt = now()
}
}
state Active {
on suspend -> Suspended
}
state Suspended {
on reactivate -> Active
}
}
Key Concepts: - States and transitions - Guards (preconditions) - Effects (state changes) - Events
Service Layer¶
Define external APIs:
service UserService {
action createUser(email: Email, name: String) -> User
enforces UserPolicy.can_create
effects { Write(User) }
implementation {
let user = User {
id: generateId(),
email: email,
name: name,
verified: false
}
store(user)
emit UserCreated(user.id)
return user
}
}
Key Concepts: - Actions (API operations) - Policy enforcement - Effect tracking - Implementation logic
Escape Layer¶
Integrate with external systems:
escape SendEmail {
capability Email.Send
function send(to: Email, subject: String, body: String) -> Result[Void, Error]
nondeterministic: true
timeout: 5s
adapter typescript {
implementation "sendgrid"
}
}
Key Concepts: - Capabilities (security permissions) - Adapters (platform-specific code) - Nondeterminism marking - Timeout constraints
Type System¶
USL has a rich type system:
// Primitive types
String, Int, Float, Boolean, Timestamp, Date, Time
// Custom types
UserId, Email, Money
// Collections
List[T], Set[T], Map[K, V]
// Optional
Option[T] // Some(value) or None
// Result
Result[T, E] // Ok(value) or Err(error)
// Variants (sum types)
variant Status {
Active
Suspended { reason: String }
Banned { until: Date }
}
Expressions¶
Literals¶
Operators¶
// Arithmetic
+ - * / %
// Comparison
== != < > <= >=
// Logical
&& || !
// String
+ (concatenation)
Control Flow¶
// If expression
if condition {
value1
} else {
value2
}
// Match expression
match value {
Some(x) => x
None => default
}
Functions¶
Modules¶
Organize code into modules:
module users {
entity User { ... }
service UserService { ... }
}
module posts {
use users::User
entity Post {
authorId: UserId
}
}
Annotations¶
entity User {
id: UserId @primary // Primary key
email: Email @unique // Unique constraint
password: String @secret // Sensitive data
data: Json @indexed // Database index
}
Comments¶
Compilation Model¶
graph LR
A[USL Source] --> B[Lexer]
B --> C[Parser]
C --> D[AST]
D --> E[Semantic Analysis]
E --> F[Type Checking]
F --> G[Verification]
G --> H[IR]
H --> I[Code Generation]
I --> J[Target Code] - Lexical Analysis: Tokenize source
- Parsing: Build AST
- Semantic Analysis: Resolve symbols
- Type Checking: Verify types
- Verification: Prove properties
- IR Generation: Intermediate representation
- Code Generation: Target platform code
Best Practices¶
DO ✅¶
- Keep domains focused and cohesive
- Write comprehensive invariants
- Use value objects for validated concepts
- Leverage type system for correctness
- Document complex policies
DON'T ❌¶
- Mix layers (domain logic in service layer)
- Skip verification
- Use primitive types for domain concepts
- Hard-code configuration
- Ignore compiler warnings
Language Design Principles¶
- Safety: Prevent bugs through types and verification
- Security: Authorization is built-in, not bolted-on
- Clarity: Express intent clearly
- Correctness: Mathematical guarantees
- Productivity: Generate boilerplate automatically
Further Reading¶
- Syntax Guide
- Type System
- Domain Layer
- Policy Layer
- Behavior Layer
- Service Layer
- Escape Layer
- Error Codes
Examples¶
Complete examples available at: - GitHub Examples - Tutorial Series