xvcl 2.5.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of xvcl might be problematic. Click here for more details.

xvcl-2.5.0/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *~
2
+ .ruff_cache
3
+ .venv
4
+ __pycache__
@@ -0,0 +1 @@
1
+ 3.9
xvcl-2.5.0/CLAUDE.md ADDED
@@ -0,0 +1,246 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Project Overview
6
+
7
+ xvcl is a VCL transpiler/preprocessor that extends Fastly VCL with metaprogramming features. It compiles `.xvcl` files (extended VCL source) into standard `.vcl` files (valid Fastly VCL) by processing directives like loops, conditionals, constants, macros, and functions. The output VCL works with Fastly and can be validated/tested with the Falco tool.
8
+
9
+ **Key concept**: xvcl is a build step for VCL. Write enhanced VCL source files, run xvcl, get clean VCL output.
10
+
11
+ ## Build and Development Commands
12
+
13
+ ### Setup and Installation
14
+
15
+ ```bash
16
+ # Install dependencies using uv (preferred) or pip
17
+ uv pip install -e ".[dev]"
18
+
19
+ # Or using pip
20
+ pip install -e ".[dev]"
21
+
22
+ # Run xvcl directly after installation
23
+ xvcl input.xvcl -o output.vcl
24
+ ```
25
+
26
+ ### Development and Testing
27
+
28
+ ```bash
29
+ # Run the compiler directly (during development)
30
+ python -m xvcl.compiler input.xvcl -o output.vcl
31
+
32
+ # Or use uv to run it
33
+ uv run xvcl input.xvcl -o output.vcl
34
+
35
+ # Run with debug mode to trace expansion
36
+ xvcl input.xvcl -o output.vcl --debug
37
+
38
+ # With include paths
39
+ xvcl input.xvcl -o output.vcl -I ./includes -I ./shared
40
+
41
+ # With source maps (adds comments showing where code came from)
42
+ xvcl input.xvcl -o output.vcl --source-maps
43
+ ```
44
+
45
+ ### Code Quality
46
+
47
+ ```bash
48
+ # Format code with ruff
49
+ ruff format .
50
+
51
+ # Lint code
52
+ ruff check .
53
+
54
+ # Type check with mypy
55
+ mypy src/xvcl
56
+
57
+ # Fix auto-fixable linting issues
58
+ ruff check --fix .
59
+ ```
60
+
61
+ ### Testing Workflow
62
+
63
+ Since xvcl generates VCL, test the generated output:
64
+
65
+ ```bash
66
+ # 1. Compile xvcl to vcl
67
+ xvcl example.xvcl -o example.vcl
68
+
69
+ # 2. Validate generated VCL with Falco (if available)
70
+ falco lint example.vcl
71
+
72
+ # 3. Test generated VCL with Falco
73
+ falco test example.vcl
74
+
75
+ # 4. Simulate generated VCL with Falco
76
+ falco simulate example.vcl
77
+ ```
78
+
79
+ ## Architecture
80
+
81
+ ### Single-File Compiler Design
82
+
83
+ The entire compiler is implemented in `src/xvcl/compiler.py` (~1380 lines). This is intentional - xvcl is a standalone tool with no external dependencies beyond Python stdlib.
84
+
85
+ ### Core Components
86
+
87
+ **XVCLCompiler Class** (`src/xvcl/compiler.py`):
88
+ - Main compiler orchestrator
89
+ - Manages state: constants, macros, functions, include tracking, output
90
+ - Multi-pass compilation strategy
91
+
92
+ **Data Structures**:
93
+ - `Macro`: Represents inline macros for zero-overhead text substitution
94
+ - `Function`: Represents user-defined functions that compile to VCL subroutines
95
+ - `SourceLocation`: Tracks file/line for error reporting
96
+ - `PreprocessorError`: Exception with rich context and formatting
97
+
98
+ ### Compilation Pipeline (Multi-Pass)
99
+
100
+ The compiler processes xvcl source files in **6 passes**:
101
+
102
+ 1. **Pass 1 - Extract Constants**: Parse `#const NAME TYPE = value` declarations and store them. Constants are removed from output and available for template substitution.
103
+
104
+ 2. **Pass 2 - Process Includes**: Process `#include "file.xvcl"` directives. Supports include-once semantics (files only included once even if referenced multiple times) and cycle detection. Include path resolution: relative to current file first, then search include paths specified with `-I`.
105
+
106
+ 3. **Pass 3 - Extract Inline Macros**: Parse `#inline...#endinline` blocks. Macros are zero-overhead text substitution that expand at compile time. Automatically handles operator precedence by wrapping arguments in parentheses when needed.
107
+
108
+ 4. **Pass 4 - Extract Functions**: Parse `#def...#enddef` blocks. Functions compile to VCL subroutines that use global HTTP headers for parameter passing and return values. Supports single return values and tuple returns.
109
+
110
+ 5. **Pass 4.5 - Join Multi-line Function Calls**: Normalize multi-line function calls into single lines to simplify pattern matching in the next pass.
111
+
112
+ 6. **Pass 5 - Process Directives**: Process `#for` loops, `#if` conditionals, `#let` variable declarations, function calls, macro expansions, and template expressions (`{{expr}}`). This is the main code generation pass.
113
+
114
+ 7. **Pass 6 - Generate Function Subroutines**: Append VCL subroutine implementations for all user-defined functions. Each function becomes a VCL subroutine with scope annotations.
115
+
116
+ ### Key Implementation Details
117
+
118
+ **Function Compilation Strategy**:
119
+ - Functions are compiled into VCL subroutines with scope annotations (`//@recv, hash, hit, miss, pass, fetch, error, deliver, log`)
120
+ - Parameters are passed via global HTTP headers: `req.http.X-Func-{funcname}-{paramname}`
121
+ - Return values use global headers: `req.http.X-Func-{funcname}-Return` (or `Return0`, `Return1` for tuples)
122
+ - Type conversions are automatic: INTEGER/FLOAT/BOOL converted to/from STRING using `std.itoa()`, `std.atoi()`, `std.atof()`, etc.
123
+
124
+ **Macro Expansion**:
125
+ - Macros expand inline (no function call overhead)
126
+ - Nested macros are supported (up to 10 iterations)
127
+ - Arguments containing operators are automatically wrapped in parentheses to preserve precedence
128
+ - Expansion happens during Pass 5 before other processing
129
+
130
+ **Error Reporting**:
131
+ - Tracks source location (file, line) throughout compilation
132
+ - Shows context lines around errors (3 lines before/after)
133
+ - Provides "did you mean" suggestions for undefined names
134
+ - Color-coded terminal output for readability
135
+
136
+ **Include System**:
137
+ - Include-once semantics prevent duplicate inclusion
138
+ - Circular include detection with stack tracking
139
+ - Path resolution order: relative to current file → include paths (`-I`)
140
+ - Optional source map comments (`--source-maps`) mark included file boundaries
141
+
142
+ ## Feature Directives
143
+
144
+ ### Constants (`#const`)
145
+ ```vcl
146
+ #const MAX_AGE INTEGER = 3600
147
+ #const ORIGIN STRING = "origin.example.com"
148
+ ```
149
+ Constants are compile-time values substituted into templates. Type-checked when type is specified.
150
+
151
+ ### Template Expressions (`{{expr}}`)
152
+ ```vcl
153
+ set req.http.X-Port = "{{PORT}}";
154
+ backend F_{{REGION}}_{{ENV}} { ... }
155
+ ```
156
+ Evaluated at compile time using Python's `eval()`. Has access to constants, loop variables, and safe built-ins (`range`, `len`, `str`, `int`, `hex`, `min`, `max`, `abs`).
157
+
158
+ ### For Loops (`#for...#endfor`)
159
+ ```vcl
160
+ #for i in range(5)
161
+ backend web{{i}} { .host = "web{{i}}.example.com"; }
162
+ #endfor
163
+ ```
164
+ Generate repetitive code. Can iterate over ranges or lists.
165
+
166
+ ### Conditionals (`#if...#else...#endif`)
167
+ ```vcl
168
+ #if PRODUCTION
169
+ set req.http.X-Env = "prod";
170
+ #else
171
+ set req.http.X-Env = "dev";
172
+ #endif
173
+ ```
174
+ Conditional compilation based on compile-time conditions.
175
+
176
+ ### Variables (`#let`)
177
+ ```vcl
178
+ #let timestamp STRING = std.time(now, now);
179
+ ```
180
+ Shorthand for `declare local` + `set`. Expands to two VCL statements.
181
+
182
+ ### Inline Macros (`#inline...#endinline`)
183
+ ```vcl
184
+ #inline normalize_host(host)
185
+ std.tolower(regsub(host, "^www\.", ""))
186
+ #endinline
187
+ ```
188
+ Zero-overhead text substitution. Use for simple expressions repeated throughout code.
189
+
190
+ ### Functions (`#def...#enddef`)
191
+ ```vcl
192
+ #def normalize_path(path STRING) -> STRING
193
+ declare local var.result STRING;
194
+ set var.result = std.tolower(path);
195
+ return var.result;
196
+ #enddef
197
+ ```
198
+ Reusable logic that compiles to VCL subroutines. Supports single and tuple returns.
199
+
200
+ ### File Includes (`#include`)
201
+ ```vcl
202
+ #include "includes/backends.xvcl"
203
+ ```
204
+ Include other xvcl files. Include-once semantics and cycle detection.
205
+
206
+ ## Code Organization
207
+
208
+ ```
209
+ .
210
+ ├── src/xvcl/
211
+ │ ├── __init__.py # Package exports (XVCLCompiler, __version__)
212
+ │ └── compiler.py # Single-file compiler implementation (~1380 lines)
213
+ ├── pyproject.toml # Project metadata, dependencies, build config
214
+ ├── README.md # Comprehensive user documentation with examples
215
+ ├── xvcl-quick-reference.md # Quick syntax reference for users
216
+ └── .python-version # Python version (3.9)
217
+ ```
218
+
219
+ **No tests directory**: xvcl is tested by compiling example files and validating the generated VCL with Falco. The project relies on Falco for VCL validation rather than unit tests.
220
+
221
+ ## Configuration
222
+
223
+ Configured via `pyproject.toml`:
224
+ - **Build system**: Hatchling (PEP 517)
225
+ - **Entry point**: `xvcl` command → `xvcl.compiler:main`
226
+ - **Linting**: Ruff (replaces flake8, isort, pyupgrade)
227
+ - **Type checking**: mypy (lenient config, not strict)
228
+ - **Python version**: 3.9+ required
229
+
230
+ ## Integration with Falco
231
+
232
+ xvcl is designed to work with Falco (VCL linter/tester/simulator). Typical workflow:
233
+
234
+ 1. Write xvcl source (`.xvcl` files)
235
+ 2. Compile with xvcl → generates `.vcl` files
236
+ 3. Validate with Falco: `falco lint output.vcl`
237
+ 4. Test with Falco: `falco test output.vcl`
238
+ 5. Deploy the generated `.vcl` to Fastly
239
+
240
+ ## Notes
241
+
242
+ - **No backwards compatibility concerns**: The user has explicitly stated they don't care about backwards compatibility for the VCL preprocessor
243
+ - **Standalone tool**: xvcl has zero external dependencies (only Python stdlib)
244
+ - **Single-file design**: The entire compiler is intentionally in one file for portability
245
+ - **Debug mode**: Always use `--debug` flag when troubleshooting compilation issues
246
+ - **Source maps**: Use `--source-maps` during development to track code origin
xvcl-2.5.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Frank Denis
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.