Skip to main content

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

SyntaxDescriptionExample
<<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")>>
&argPass by reference<<process(&data)>>

ParseTemplate Function

func ParseTemplate(template string, p *WorkerSessionContext) (string, error)

Process:

  1. Match <<...>> tokens using regex
  2. Check for function calls (pattern: name(args))
  3. Resolve function arguments recursively
  4. Call function via reflection or lookup in DI
  5. For non-function tokens, resolve from context
  6. Handle pipe modifiers (|)
  7. 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:

  1. Look up in session context properties
  2. Look up in DI container with helpers: prefix
  3. 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:

TypeExampleResult
Object{key: "value"}map[string]interface{}
Integer42int
Float3.14float64
Booleantrue, falsebool
String"text", 'text'string
Placeholder$Var"<<Var>>"

Edge Condition Mapping

WSL ConditionEngine Mapping
on successtrue field
on errorfalse field
elseelse field
Expressionelse (fallback)