WSL Compilation Pipeline
WSL (Workflow Specification Language) provides a declarative syntax for defining workflows.
Pipeline Stages
┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ WSL Source │───▶│ Lexer │───▶│ Parser │───▶│ AST Builder │───▶│ IR Generator │
│ (.wsl) │ │ (Tokenize) │ │ (CST) │ │ (Module) │ │ (Graph) │
└──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘
│
▼
┌──────────────┐
│ Workflow │
│ Engine │
└──────────────┘
1. Lexer (lexer.go)
Converts WSL source text into tokens.
Token Types:
- Keywords:
module,import,workflow,state,action,on,end - Symbols:
{,},(,),:,,,.,=,|,-> - Literals: strings, numbers, identifiers
2. Parser (parser.go)
Builds a Concrete Syntax Tree (CST) from tokens.
3. AST Builder (build_ast.go)
Transforms CST into an Abstract Syntax Tree with semantic meaning.
AST Structure:
type Module struct {
Name string
Imports []Import
Extends []string
Context []Field
Constants []Constant
Workflows []Workflow
}
type Workflow struct {
Name string
Start string
States map[string]*State
}
type State struct {
Name string
Params []string
Action *Action
Transitions []Transition
End *End
}
4. IR Generator (ir.go)
Creates an execution graph from the AST.
type Graph struct {
WorkflowName string
Nodes map[string]*Node
Start string
Constants map[string]string
}
type Node struct {
Name string
Action *Action
ParamNames []string
Edges []Edge
Terminal bool
TerminalKind string
Attr map[string]string
}
WSL Example
module example
import services/common
const {
event: "greet",
description: "A simple hello world workflow"
}
workflow hello_world {
start: Hello
state Hello {
action converse/speak.Say(message: "Hello World")
on success -> Response
}
state Response {
action services/common/response.ResponseValue(statusCode: 200)
end ok
}
}
Template Parser
The template parser (engine/workflow/parser.go) processes string templates with dynamic value resolution.
Template Syntax
| Syntax | Description | Example |
|---|---|---|
<<key>> | Simple property lookup | <<username>> |
<<key.field>> | Nested field access | <<user.profile.name>> |
<<key??default>> | Default value fallback | <<name??Guest>> |
<<func(args)>> | Function call | <<format(date, "YYYY-MM-DD")>> |
&arg | Pass by reference | <<process(&data)>> |
ParseTemplate Function
func ParseTemplate(template string, p *WorkerSessionContext) (string, error)
Process:
- Match
<<...>>tokens using regex - Check for function calls (pattern:
name(args)) - Resolve function arguments recursively
- Call function via reflection or lookup in DI
- For non-function tokens, resolve from context
- Handle pipe modifiers (
|) - Recursively process nested templates
Token Resolution
func resolveToken(token string, tokenRe *regexp.Regexp, p *WorkerSessionContext) (string, error)
Supports:
- Simple keys:
<<key>> - Nested paths:
<<obj.field.subfield>> - Default values:
<<key??fallback>> - Slice indexing:
<<array.0>> - Map access:
<<map.key>>
Function Invocation
func callFunction(functionName string, args []interface{}, p *WorkerSessionContext) (string, error)
Resolution Order:
- Look up in session context properties
- Look up in DI container with
helpers:prefix - Invoke via reflection
WSL Integration
The WSL integration (engine/workflow/wsl_integration.go) converts parsed WSL graphs to engine-compatible Flow schemas.
wslGraphToSchema
func wslGraphToSchema(g *wsl.Graph) map[string]interface{}
Converts a WSL Graph to the JSON structure expected by domain.Flow.FromMap.
Conversion Process:
┌─────────────────┐ ┌─────────────────┐ ┌───────────────────┐
│ WSL Graph │────▶│ Build States │────▶│ Build Transitions │
│ (wsl.Graph) │ │ from Nodes │ │ with edges │
└─────────────────┘ └─────────────────┘ └───────────────────┘
│
▼
┌─────────────────┐
│ Extract │
│ Resolvers │
└─────────────────┘
│
▼
┌─────────────────┐
│ Return Schema │
│ (map) │
└─────────────────┘
WSL Value Parsing (literals.go)
Parses WSL inline values:
func parseWSLValue(raw string) (interface{}, bool)
Supported Types:
| Type | Example | Result |
|---|---|---|
| Object | {key: "value"} | map[string]interface{} |
| Integer | 42 | int |
| Float | 3.14 | float64 |
| Boolean | true, false | bool |
| String | "text", 'text' | string |
| Placeholder | $Var | "<<Var>>" |
Edge Condition Mapping
| WSL Condition | Engine Mapping |
|---|---|
on success | true field |
on error | false field |
else | else field |
| Expression | else (fallback) |