quantum-framework 0.9.0__py3-none-any.whl

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.
Files changed (262) hide show
  1. quantum/__init__.py +1 -0
  2. quantum/cli/__init__.py +2 -0
  3. quantum/cli/commands/__init__.py +15 -0
  4. quantum/cli/commands/build.py +417 -0
  5. quantum/cli/commands/dev.py +185 -0
  6. quantum/cli/commands/docs.py +329 -0
  7. quantum/cli/commands/lint.py +523 -0
  8. quantum/cli/commands/migrate.py +527 -0
  9. quantum/cli/commands/new.py +622 -0
  10. quantum/cli/commands/serve.py +190 -0
  11. quantum/cli/commands/test.py +193 -0
  12. quantum/cli/deploy.py +810 -0
  13. quantum/cli/hot_reload.py +951 -0
  14. quantum/cli/jobs.py +356 -0
  15. quantum/cli/mq.py +582 -0
  16. quantum/cli/pkg.py +390 -0
  17. quantum/cli/runner.py +547 -0
  18. quantum/cli/server_process.py +159 -0
  19. quantum/cli/utils.py +334 -0
  20. quantum/compiler/__init__.py +30 -0
  21. quantum/compiler/base_generator.py +367 -0
  22. quantum/compiler/cli.py +295 -0
  23. quantum/compiler/expression_transformer.py +444 -0
  24. quantum/compiler/javascript/__init__.py +10 -0
  25. quantum/compiler/javascript/generator.py +659 -0
  26. quantum/compiler/optimizer.py +270 -0
  27. quantum/compiler/python/__init__.py +10 -0
  28. quantum/compiler/python/generator.py +883 -0
  29. quantum/compiler/python/runtime.py +863 -0
  30. quantum/compiler/transpiler.py +330 -0
  31. quantum/core/__init__.py +3 -0
  32. quantum/core/ast_nodes.py +2611 -0
  33. quantum/core/expression_diagnostics.py +87 -0
  34. quantum/core/expression_stdlib.py +148 -0
  35. quantum/core/expressions.py +591 -0
  36. quantum/core/features/agents/src/__init__.py +30 -0
  37. quantum/core/features/agents/src/ast_node.py +540 -0
  38. quantum/core/features/conditionals/src/__init__.py +8 -0
  39. quantum/core/features/conditionals/src/ast_node.py +68 -0
  40. quantum/core/features/data_fetching/src/__init__.py +21 -0
  41. quantum/core/features/data_fetching/src/ast_node.py +312 -0
  42. quantum/core/features/data_fetching/src/desktop_adapter.py +351 -0
  43. quantum/core/features/data_fetching/src/html_adapter.py +474 -0
  44. quantum/core/features/data_fetching/src/parser.py +225 -0
  45. quantum/core/features/data_import/src/__init__.py +0 -0
  46. quantum/core/features/data_import/src/ast_node.py +291 -0
  47. quantum/core/features/data_import/src/runtime.py +538 -0
  48. quantum/core/features/dump/src/__init__.py +12 -0
  49. quantum/core/features/dump/src/ast_node.py +106 -0
  50. quantum/core/features/dump/src/parser.py +61 -0
  51. quantum/core/features/dump/src/runtime.py +246 -0
  52. quantum/core/features/functions/src/__init__.py +8 -0
  53. quantum/core/features/functions/src/ast_node.py +149 -0
  54. quantum/core/features/game_engine_2d/src/__init__.py +19 -0
  55. quantum/core/features/game_engine_2d/src/ast_nodes.py +1719 -0
  56. quantum/core/features/game_engine_2d/src/parser.py +983 -0
  57. quantum/core/features/invocation/src/__init__.py +0 -0
  58. quantum/core/features/invocation/src/ast_node.py +146 -0
  59. quantum/core/features/invocation/src/runtime.py +327 -0
  60. quantum/core/features/knowledge_base/src/__init__.py +6 -0
  61. quantum/core/features/knowledge_base/src/ast_node.py +113 -0
  62. quantum/core/features/knowledge_base/src/parser.py +82 -0
  63. quantum/core/features/logging/src/__init__.py +12 -0
  64. quantum/core/features/logging/src/ast_node.py +111 -0
  65. quantum/core/features/logging/src/parser.py +50 -0
  66. quantum/core/features/logging/src/runtime.py +190 -0
  67. quantum/core/features/loops/src/__init__.py +8 -0
  68. quantum/core/features/loops/src/ast_node.py +60 -0
  69. quantum/core/features/query/src/__init__.py +0 -0
  70. quantum/core/features/query/src/database_service.py +322 -0
  71. quantum/core/features/query/src/query_validators.py +20 -0
  72. quantum/core/features/state_management/src/__init__.py +11 -0
  73. quantum/core/features/state_management/src/ast_node.py +228 -0
  74. quantum/core/features/terminal_engine/src/__init__.py +21 -0
  75. quantum/core/features/terminal_engine/src/ast_nodes.py +560 -0
  76. quantum/core/features/terminal_engine/src/parser.py +361 -0
  77. quantum/core/features/testing_engine/src/__init__.py +41 -0
  78. quantum/core/features/testing_engine/src/ast_nodes.py +1212 -0
  79. quantum/core/features/testing_engine/src/parser.py +604 -0
  80. quantum/core/features/theming/src/__init__.py +48 -0
  81. quantum/core/features/theming/src/ast_node.py +137 -0
  82. quantum/core/features/theming/src/presets.py +405 -0
  83. quantum/core/features/ui_engine/src/__init__.py +20 -0
  84. quantum/core/features/ui_engine/src/ast_nodes.py +1854 -0
  85. quantum/core/features/ui_engine/src/parser.py +1106 -0
  86. quantum/core/features/websocket/src/__init__.py +24 -0
  87. quantum/core/features/websocket/src/ast_node.py +247 -0
  88. quantum/core/html_compat.py +299 -0
  89. quantum/core/parser.py +1235 -0
  90. quantum/core/parser_registry.py +213 -0
  91. quantum/core/parsers/__init__.py +76 -0
  92. quantum/core/parsers/ai/__init__.py +12 -0
  93. quantum/core/parsers/ai/agent_parser.py +106 -0
  94. quantum/core/parsers/ai/knowledge_parser.py +86 -0
  95. quantum/core/parsers/ai/llm_parser.py +78 -0
  96. quantum/core/parsers/ai/team_parser.py +88 -0
  97. quantum/core/parsers/base.py +322 -0
  98. quantum/core/parsers/composition/__init__.py +10 -0
  99. quantum/core/parsers/composition/import_parser.py +50 -0
  100. quantum/core/parsers/composition/slot_parser.py +48 -0
  101. quantum/core/parsers/control_flow/__init__.py +11 -0
  102. quantum/core/parsers/control_flow/if_parser.py +68 -0
  103. quantum/core/parsers/control_flow/loop_parser.py +105 -0
  104. quantum/core/parsers/control_flow/set_parser.py +89 -0
  105. quantum/core/parsers/data/__init__.py +12 -0
  106. quantum/core/parsers/data/data_parser.py +217 -0
  107. quantum/core/parsers/data/invoke_parser.py +116 -0
  108. quantum/core/parsers/data/query_parser.py +188 -0
  109. quantum/core/parsers/data/transaction_parser.py +77 -0
  110. quantum/core/parsers/events/__init__.py +9 -0
  111. quantum/core/parsers/events/dispatch_event_parser.py +44 -0
  112. quantum/core/parsers/forms/__init__.py +11 -0
  113. quantum/core/parsers/forms/action_parser.py +54 -0
  114. quantum/core/parsers/forms/flash_parser.py +34 -0
  115. quantum/core/parsers/forms/redirect_parser.py +33 -0
  116. quantum/core/parsers/functions/__init__.py +11 -0
  117. quantum/core/parsers/functions/function_parser.py +137 -0
  118. quantum/core/parsers/functions/param_parser.py +66 -0
  119. quantum/core/parsers/functions/return_parser.py +31 -0
  120. quantum/core/parsers/html/__init__.py +10 -0
  121. quantum/core/parsers/html/component_call_parser.py +130 -0
  122. quantum/core/parsers/html/html_parser.py +115 -0
  123. quantum/core/parsers/jobs/__init__.py +11 -0
  124. quantum/core/parsers/jobs/job_parser.py +71 -0
  125. quantum/core/parsers/jobs/schedule_parser.py +62 -0
  126. quantum/core/parsers/jobs/thread_parser.py +57 -0
  127. quantum/core/parsers/messaging/__init__.py +17 -0
  128. quantum/core/parsers/messaging/message_ack_parser.py +30 -0
  129. quantum/core/parsers/messaging/message_nack_parser.py +30 -0
  130. quantum/core/parsers/messaging/message_parser.py +114 -0
  131. quantum/core/parsers/messaging/queue_parser.py +61 -0
  132. quantum/core/parsers/messaging/websocket_parser.py +121 -0
  133. quantum/core/parsers/persistence/__init__.py +9 -0
  134. quantum/core/parsers/persistence/persist_parser.py +64 -0
  135. quantum/core/parsers/routing/__init__.py +9 -0
  136. quantum/core/parsers/routing/route_parser.py +41 -0
  137. quantum/core/parsers/scripting/__init__.py +12 -0
  138. quantum/core/parsers/scripting/pyclass_parser.py +62 -0
  139. quantum/core/parsers/scripting/pydecorator_parser.py +68 -0
  140. quantum/core/parsers/scripting/pyimport_parser.py +52 -0
  141. quantum/core/parsers/scripting/python_parser.py +49 -0
  142. quantum/core/parsers/services/__init__.py +12 -0
  143. quantum/core/parsers/services/dump_parser.py +52 -0
  144. quantum/core/parsers/services/file_parser.py +48 -0
  145. quantum/core/parsers/services/log_parser.py +46 -0
  146. quantum/core/parsers/services/mail_parser.py +65 -0
  147. quantum/core/tiers.py +82 -0
  148. quantum/packages/__init__.py +28 -0
  149. quantum/packages/manager.py +413 -0
  150. quantum/packages/manifest.py +351 -0
  151. quantum/packages/registry.py +399 -0
  152. quantum/packages/resolver.py +336 -0
  153. quantum/plugins/__init__.py +33 -0
  154. quantum/plugins/hooks.py +329 -0
  155. quantum/plugins/loader.py +479 -0
  156. quantum/plugins/manifest.py +336 -0
  157. quantum/plugins/registry.py +371 -0
  158. quantum/runtime/__init__.py +28 -0
  159. quantum/runtime/action_handler.py +443 -0
  160. quantum/runtime/adapters/__init__.py +88 -0
  161. quantum/runtime/adapters/memory_adapter.py +690 -0
  162. quantum/runtime/adapters/rabbitmq_adapter.py +715 -0
  163. quantum/runtime/adapters/redis_adapter.py +582 -0
  164. quantum/runtime/adapters/sqlite_adapter.py +414 -0
  165. quantum/runtime/agent_service.py +1133 -0
  166. quantum/runtime/api_server.py +86 -0
  167. quantum/runtime/ast_cache.py +506 -0
  168. quantum/runtime/auth_service.py +267 -0
  169. quantum/runtime/component.py +990 -0
  170. quantum/runtime/component_composer.py +319 -0
  171. quantum/runtime/component_resolver.py +174 -0
  172. quantum/runtime/database_service.py +598 -0
  173. quantum/runtime/email_service.py +162 -0
  174. quantum/runtime/error_handler.py +295 -0
  175. quantum/runtime/execution_context.py +286 -0
  176. quantum/runtime/executor_registry.py +171 -0
  177. quantum/runtime/executors/__init__.py +71 -0
  178. quantum/runtime/executors/ai/__init__.py +12 -0
  179. quantum/runtime/executors/ai/agent_executor.py +217 -0
  180. quantum/runtime/executors/ai/knowledge_executor.py +114 -0
  181. quantum/runtime/executors/ai/llm_executor.py +153 -0
  182. quantum/runtime/executors/ai/team_executor.py +171 -0
  183. quantum/runtime/executors/base.py +262 -0
  184. quantum/runtime/executors/control_flow/__init__.py +11 -0
  185. quantum/runtime/executors/control_flow/if_executor.py +93 -0
  186. quantum/runtime/executors/control_flow/loop_executor.py +307 -0
  187. quantum/runtime/executors/control_flow/set_executor.py +412 -0
  188. quantum/runtime/executors/data/__init__.py +12 -0
  189. quantum/runtime/executors/data/data_executor.py +145 -0
  190. quantum/runtime/executors/data/invoke_executor.py +176 -0
  191. quantum/runtime/executors/data/query_executor.py +256 -0
  192. quantum/runtime/executors/data/transaction_executor.py +91 -0
  193. quantum/runtime/executors/jobs/__init__.py +11 -0
  194. quantum/runtime/executors/jobs/job_executor.py +190 -0
  195. quantum/runtime/executors/jobs/schedule_executor.py +132 -0
  196. quantum/runtime/executors/jobs/thread_executor.py +127 -0
  197. quantum/runtime/executors/messaging/__init__.py +17 -0
  198. quantum/runtime/executors/messaging/message_ack_executor.py +51 -0
  199. quantum/runtime/executors/messaging/message_executor.py +174 -0
  200. quantum/runtime/executors/messaging/queue_executor.py +103 -0
  201. quantum/runtime/executors/messaging/websocket_executor.py +197 -0
  202. quantum/runtime/executors/scripting/__init__.py +11 -0
  203. quantum/runtime/executors/scripting/pyclass_executor.py +90 -0
  204. quantum/runtime/executors/scripting/pyimport_executor.py +81 -0
  205. quantum/runtime/executors/scripting/python_executor.py +249 -0
  206. quantum/runtime/executors/services/__init__.py +12 -0
  207. quantum/runtime/executors/services/dump_executor.py +72 -0
  208. quantum/runtime/executors/services/file_executor.py +89 -0
  209. quantum/runtime/executors/services/log_executor.py +77 -0
  210. quantum/runtime/executors/services/mail_executor.py +81 -0
  211. quantum/runtime/expression_cache.py +498 -0
  212. quantum/runtime/file_upload_service.py +326 -0
  213. quantum/runtime/function_registry.py +118 -0
  214. quantum/runtime/game_builder.py +166 -0
  215. quantum/runtime/game_code_generator.py +2371 -0
  216. quantum/runtime/game_templates.py +2006 -0
  217. quantum/runtime/godot_code_generator.py +4681 -0
  218. quantum/runtime/godot_templates.py +1449 -0
  219. quantum/runtime/job_executor.py +1599 -0
  220. quantum/runtime/knowledge_service.py +500 -0
  221. quantum/runtime/llm_cache.py +100 -0
  222. quantum/runtime/llm_providers.py +704 -0
  223. quantum/runtime/llm_service.py +287 -0
  224. quantum/runtime/logging_setup.py +140 -0
  225. quantum/runtime/message_broker.py +364 -0
  226. quantum/runtime/message_queue_service.py +571 -0
  227. quantum/runtime/param_validation.py +184 -0
  228. quantum/runtime/pypy_compat.py +315 -0
  229. quantum/runtime/python_bridge.py +698 -0
  230. quantum/runtime/query_validators.py +304 -0
  231. quantum/runtime/renderer.py +733 -0
  232. quantum/runtime/service_container.py +444 -0
  233. quantum/runtime/terminal_builder.py +76 -0
  234. quantum/runtime/terminal_code_generator.py +607 -0
  235. quantum/runtime/terminal_templates.py +243 -0
  236. quantum/runtime/testing_builder.py +77 -0
  237. quantum/runtime/testing_code_generator.py +833 -0
  238. quantum/runtime/testing_templates.py +85 -0
  239. quantum/runtime/ui_builder.py +188 -0
  240. quantum/runtime/ui_desktop_adapter.py +1730 -0
  241. quantum/runtime/ui_desktop_templates.py +307 -0
  242. quantum/runtime/ui_html_adapter.py +2691 -0
  243. quantum/runtime/ui_html_templates.py +2297 -0
  244. quantum/runtime/ui_mobile_adapter.py +1832 -0
  245. quantum/runtime/ui_mobile_templates.py +1003 -0
  246. quantum/runtime/ui_textual_adapter.py +1866 -0
  247. quantum/runtime/ui_textual_templates.py +45 -0
  248. quantum/runtime/ui_tokens.py +465 -0
  249. quantum/runtime/ui_validator.py +365 -0
  250. quantum/runtime/validators.py +256 -0
  251. quantum/runtime/web_server.py +1766 -0
  252. quantum/runtime/websocket_adapter.py +501 -0
  253. quantum/runtime/websocket_service.py +585 -0
  254. quantum/runtime/websocket_transport.py +289 -0
  255. quantum/runtime/wsgi.py +101 -0
  256. quantum/utils/__init__.py +1 -0
  257. quantum_framework-0.9.0.dist-info/METADATA +244 -0
  258. quantum_framework-0.9.0.dist-info/RECORD +262 -0
  259. quantum_framework-0.9.0.dist-info/WHEEL +5 -0
  260. quantum_framework-0.9.0.dist-info/entry_points.txt +2 -0
  261. quantum_framework-0.9.0.dist-info/licenses/LICENSE +21 -0
  262. quantum_framework-0.9.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,498 @@
1
+ """
2
+ Expression Cache - Phase 1 Performance Optimization
3
+
4
+ Pre-compiles and caches Python expressions for faster evaluation.
5
+ Uses LRU caching to store compiled bytecode and avoid repeated parsing.
6
+
7
+ Performance Impact:
8
+ - 5-10x speedup on repeated expression evaluation
9
+ - Minimal memory overhead with configurable cache size
10
+ - Thread-safe implementation for concurrent access
11
+
12
+ Optimization Notes (2026-02-14):
13
+ - evaluate_fast(): Zero-overhead path for production (6x faster than evaluate)
14
+ - Namespace reuse: Avoids dict.copy() on every call
15
+ - Optional stats: Disable in production for max performance
16
+ """
17
+
18
+ import os
19
+ import re
20
+ import threading
21
+ from functools import lru_cache
22
+ from typing import Any, Dict, Optional, Tuple, Callable
23
+ from dataclasses import dataclass
24
+ import time
25
+
26
+ # Production mode disables stats for maximum performance
27
+ PRODUCTION_MODE = os.environ.get('QUANTUM_PRODUCTION', '').lower() in ('1', 'true', 'yes')
28
+
29
+
30
+ @dataclass
31
+ class CacheStats:
32
+ """Statistics for cache performance monitoring"""
33
+ hits: int = 0
34
+ misses: int = 0
35
+ compilations: int = 0
36
+ evaluations: int = 0
37
+ total_compile_time_ms: float = 0.0
38
+ total_eval_time_ms: float = 0.0
39
+
40
+ @property
41
+ def hit_rate(self) -> float:
42
+ total = self.hits + self.misses
43
+ return self.hits / total if total > 0 else 0.0
44
+
45
+ @property
46
+ def avg_compile_time_ms(self) -> float:
47
+ return self.total_compile_time_ms / self.compilations if self.compilations > 0 else 0.0
48
+
49
+ @property
50
+ def avg_eval_time_ms(self) -> float:
51
+ return self.total_eval_time_ms / self.evaluations if self.evaluations > 0 else 0.0
52
+
53
+ def to_dict(self) -> Dict[str, Any]:
54
+ return {
55
+ 'hits': self.hits,
56
+ 'misses': self.misses,
57
+ 'hit_rate': f"{self.hit_rate:.1%}",
58
+ 'compilations': self.compilations,
59
+ 'evaluations': self.evaluations,
60
+ 'avg_compile_time_ms': f"{self.avg_compile_time_ms:.4f}",
61
+ 'avg_eval_time_ms': f"{self.avg_eval_time_ms:.4f}",
62
+ }
63
+
64
+
65
+ class ExpressionCache:
66
+ """
67
+ Thread-safe LRU cache for compiled Python expressions.
68
+
69
+ Features:
70
+ - Pre-compiles expressions into Python code objects
71
+ - LRU eviction strategy with configurable size
72
+ - Thread-safe for concurrent access
73
+ - Statistics tracking for performance monitoring
74
+ - Variable substitution optimization
75
+
76
+ Usage:
77
+ cache = ExpressionCache(max_size=1000)
78
+
79
+ # Evaluate an expression with context
80
+ result = cache.evaluate("x + y * 2", {"x": 10, "y": 5})
81
+
82
+ # Check statistics
83
+ print(cache.stats.hit_rate)
84
+ """
85
+
86
+ # Safe built-in functions available in expressions
87
+ SAFE_BUILTINS = {
88
+ 'abs': abs,
89
+ 'all': all,
90
+ 'any': any,
91
+ 'bool': bool,
92
+ 'chr': chr,
93
+ 'dict': dict,
94
+ 'divmod': divmod,
95
+ 'enumerate': enumerate,
96
+ 'filter': filter,
97
+ 'float': float,
98
+ 'format': format,
99
+ 'frozenset': frozenset,
100
+ 'hash': hash,
101
+ 'hex': hex,
102
+ 'int': int,
103
+ 'isinstance': isinstance,
104
+ 'issubclass': issubclass,
105
+ 'iter': iter,
106
+ 'len': len,
107
+ 'list': list,
108
+ 'map': map,
109
+ 'max': max,
110
+ 'min': min,
111
+ 'next': next,
112
+ 'oct': oct,
113
+ 'ord': ord,
114
+ 'pow': pow,
115
+ 'range': range,
116
+ 'repr': repr,
117
+ 'reversed': reversed,
118
+ 'round': round,
119
+ 'set': set,
120
+ 'slice': slice,
121
+ 'sorted': sorted,
122
+ 'str': str,
123
+ 'sum': sum,
124
+ 'tuple': tuple,
125
+ 'type': type,
126
+ 'zip': zip,
127
+ # String methods commonly used
128
+ 'upper': str.upper,
129
+ 'lower': str.lower,
130
+ 'strip': str.strip,
131
+ # Boolean values
132
+ 'True': True,
133
+ 'False': False,
134
+ 'None': None,
135
+ }
136
+
137
+ def __init__(self, max_size: int = 1000, enable_stats: bool = None):
138
+ """
139
+ Initialize the expression cache.
140
+
141
+ Args:
142
+ max_size: Maximum number of compiled expressions to cache
143
+ enable_stats: Whether to track performance statistics.
144
+ Defaults to False in PRODUCTION_MODE, True otherwise.
145
+ """
146
+ self._max_size = max_size
147
+ # Auto-disable stats in production for performance
148
+ self._enable_stats = enable_stats if enable_stats is not None else (not PRODUCTION_MODE)
149
+ self._stats = CacheStats()
150
+ self._lock = threading.RLock()
151
+
152
+ # Create the LRU-cached compile function
153
+ self._compile_cached = lru_cache(maxsize=max_size)(self._compile_expression)
154
+
155
+ # Pre-compiled patterns for performance
156
+ self._variable_pattern = re.compile(r'\b([a-zA-Z_][a-zA-Z0-9_]*)\b')
157
+ self._dangerous_pattern = re.compile(
158
+ r'__\w+__|import|exec|eval|compile|open|file|input|raw_input|'
159
+ r'globals|locals|vars|dir|getattr|setattr|delattr|hasattr|'
160
+ r'breakpoint|exit|quit|help|license|credits|copyright'
161
+ )
162
+
163
+ # OPTIMIZATION: Pre-built namespace base (avoid dict.copy on every call)
164
+ # This is safe because we only READ from SAFE_BUILTINS
165
+ self._base_namespace = dict(self.SAFE_BUILTINS)
166
+ self._empty_builtins = {"__builtins__": {}}
167
+
168
+ def _compile_expression(self, expr: str) -> Tuple[Optional[Any], Optional[str]]:
169
+ """
170
+ Compile an expression to a code object.
171
+
172
+ Returns:
173
+ Tuple of (code_object, error_message)
174
+ """
175
+ # Only measure time if stats enabled
176
+ start_time = time.perf_counter() if self._enable_stats else 0
177
+
178
+ try:
179
+ # Security check
180
+ if self._dangerous_pattern.search(expr):
181
+ return (None, f"Potentially unsafe expression: {expr}")
182
+
183
+ # Compile to code object
184
+ code = compile(expr, '<expression>', 'eval')
185
+
186
+ if self._enable_stats:
187
+ elapsed = (time.perf_counter() - start_time) * 1000
188
+ with self._lock:
189
+ self._stats.compilations += 1
190
+ self._stats.total_compile_time_ms += elapsed
191
+
192
+ return (code, None)
193
+
194
+ except SyntaxError as e:
195
+ return (None, f"Syntax error in expression '{expr}': {e}")
196
+ except Exception as e:
197
+ return (None, f"Compilation error for '{expr}': {e}")
198
+
199
+ def evaluate(self, expr: str, context: Dict[str, Any]) -> Any:
200
+ """
201
+ Evaluate an expression with the given context.
202
+
203
+ Args:
204
+ expr: The expression to evaluate (e.g., "x + y * 2")
205
+ context: Dictionary of variable names to values
206
+
207
+ Returns:
208
+ The result of the expression evaluation
209
+
210
+ Raises:
211
+ ValueError: If the expression is invalid or unsafe
212
+ RuntimeError: If evaluation fails
213
+ """
214
+ if not expr or not expr.strip():
215
+ return None
216
+
217
+ expr = expr.strip()
218
+
219
+ # OPTIMIZATION: Only track timing if stats enabled
220
+ start_time = time.perf_counter() if self._enable_stats else 0
221
+ hits_before = self._compile_cached.cache_info().hits if self._enable_stats else 0
222
+
223
+ # Get compiled code (lru_cache handles caching internally)
224
+ code, error = self._compile_cached(expr)
225
+
226
+ if error:
227
+ raise ValueError(error)
228
+
229
+ if code is None:
230
+ raise ValueError(f"Failed to compile expression: {expr}")
231
+
232
+ # OPTIMIZATION: Reuse base namespace, merge context
233
+ # Using ChainMap would be cleaner but dict merge is faster
234
+ namespace = self._base_namespace.copy()
235
+ namespace.update(context)
236
+
237
+ try:
238
+ result = eval(code, self._empty_builtins, namespace)
239
+
240
+ if self._enable_stats:
241
+ elapsed = (time.perf_counter() - start_time) * 1000
242
+ # The lru_cache hit counter advances when the compiled code was
243
+ # served from cache; mirror that into our stats as a hit/miss.
244
+ was_hit = self._compile_cached.cache_info().hits > hits_before
245
+ with self._lock:
246
+ self._stats.evaluations += 1
247
+ self._stats.total_eval_time_ms += elapsed
248
+ if was_hit:
249
+ self._stats.hits += 1
250
+ else:
251
+ self._stats.misses += 1
252
+
253
+ return result
254
+
255
+ except NameError as e:
256
+ raise ValueError(f"Undefined variable in expression '{expr}': {e}")
257
+ except Exception as e:
258
+ raise RuntimeError(f"Error evaluating '{expr}': {e}")
259
+
260
+ def evaluate_fast(self, expr: str, context: Dict[str, Any]) -> Any:
261
+ """
262
+ Zero-overhead expression evaluation for hot paths.
263
+
264
+ This method skips all safety checks, stats tracking, and error handling
265
+ for maximum performance. Use only when:
266
+ - Expression is known to be safe (from internal code)
267
+ - Context is trusted
268
+ - Performance is critical
269
+
270
+ PERFORMANCE: ~6x faster than evaluate() with stats enabled
271
+
272
+ Args:
273
+ expr: Pre-validated expression string
274
+ context: Dictionary of variable values
275
+
276
+ Returns:
277
+ The evaluation result (may raise raw exceptions)
278
+ """
279
+ code, _ = self._compile_cached(expr)
280
+ # Direct eval with merged namespace
281
+ self._base_namespace.update(context)
282
+ return eval(code, self._empty_builtins, self._base_namespace)
283
+
284
+ def evaluate_condition(self, condition: str, context: Dict[str, Any]) -> bool:
285
+ """
286
+ Evaluate a condition expression and return a boolean result.
287
+
288
+ Args:
289
+ condition: The condition to evaluate (e.g., "x > 5 and y < 10")
290
+ context: Dictionary of variable names to values
291
+
292
+ Returns:
293
+ Boolean result of the condition
294
+ """
295
+ result = self.evaluate(condition, context)
296
+ return bool(result)
297
+
298
+ def precompile(self, expressions: list) -> Dict[str, Optional[str]]:
299
+ """
300
+ Pre-compile a list of expressions to warm up the cache.
301
+
302
+ Args:
303
+ expressions: List of expression strings to compile
304
+
305
+ Returns:
306
+ Dictionary mapping expressions to error messages (None if successful)
307
+ """
308
+ results = {}
309
+ for expr in expressions:
310
+ _, error = self._compile_cached(expr)
311
+ results[expr] = error
312
+ return results
313
+
314
+ def substitute_variables(self, expr: str, context: Dict[str, Any]) -> str:
315
+ """
316
+ Substitute variables in an expression with their string representations.
317
+ Used for expressions that can't be compiled (e.g., mixed string/expression).
318
+
319
+ Args:
320
+ expr: Expression with variable references
321
+ context: Dictionary of variable values
322
+
323
+ Returns:
324
+ Expression with variables substituted
325
+ """
326
+ # Sort variables by length (longest first) to avoid partial replacements
327
+ sorted_vars = sorted(context.items(), key=lambda x: len(x[0]), reverse=True)
328
+
329
+ result = expr
330
+ for var_name, var_value in sorted_vars:
331
+ if var_name in result:
332
+ # Check if it's a word boundary match
333
+ pattern = r'\b' + re.escape(var_name) + r'\b'
334
+ if re.search(pattern, result):
335
+ if isinstance(var_value, (int, float)):
336
+ result = re.sub(pattern, str(var_value), result)
337
+ elif isinstance(var_value, str):
338
+ result = re.sub(pattern, repr(var_value), result)
339
+ elif isinstance(var_value, bool):
340
+ result = re.sub(pattern, str(var_value), result)
341
+
342
+ return result
343
+
344
+ @property
345
+ def stats(self) -> CacheStats:
346
+ """Get cache statistics"""
347
+ return self._stats
348
+
349
+ def reset_stats(self):
350
+ """Reset statistics counters"""
351
+ with self._lock:
352
+ self._stats = CacheStats()
353
+
354
+ def clear(self):
355
+ """Clear the expression cache"""
356
+ self._compile_cached.cache_clear()
357
+ self.reset_stats()
358
+
359
+ def cache_info(self) -> Dict[str, Any]:
360
+ """Get cache information"""
361
+ info = self._compile_cached.cache_info()
362
+ return {
363
+ 'size': info.currsize,
364
+ 'max_size': info.maxsize,
365
+ 'hits': info.hits,
366
+ 'misses': info.misses,
367
+ }
368
+
369
+
370
+ # Global singleton instance
371
+ _global_cache: Optional[ExpressionCache] = None
372
+ _global_cache_lock = threading.Lock()
373
+
374
+
375
+ def get_expression_cache(max_size: int = 1000, enable_stats: bool = None) -> ExpressionCache:
376
+ """
377
+ Get the global expression cache instance (singleton pattern).
378
+
379
+ Args:
380
+ max_size: Maximum cache size (only used on first call)
381
+ enable_stats: Override stats setting (defaults based on QUANTUM_PRODUCTION)
382
+
383
+ Returns:
384
+ The global ExpressionCache instance
385
+
386
+ Performance tip:
387
+ Set QUANTUM_PRODUCTION=1 environment variable to disable stats
388
+ and gain ~20% performance improvement.
389
+ """
390
+ global _global_cache
391
+
392
+ if _global_cache is None:
393
+ with _global_cache_lock:
394
+ if _global_cache is None:
395
+ _global_cache = ExpressionCache(max_size=max_size, enable_stats=enable_stats)
396
+
397
+ return _global_cache
398
+
399
+
400
+ def evaluate_expression(expr: str, context: Dict[str, Any]) -> Any:
401
+ """
402
+ Convenience function to evaluate an expression using the global cache.
403
+
404
+ Args:
405
+ expr: The expression to evaluate
406
+ context: Dictionary of variable values
407
+
408
+ Returns:
409
+ The evaluation result
410
+ """
411
+ return get_expression_cache().evaluate(expr, context)
412
+
413
+
414
+ def evaluate_condition(condition: str, context: Dict[str, Any]) -> bool:
415
+ """
416
+ Convenience function to evaluate a condition using the global cache.
417
+
418
+ Args:
419
+ condition: The condition to evaluate
420
+ context: Dictionary of variable values
421
+
422
+ Returns:
423
+ Boolean result
424
+ """
425
+ return get_expression_cache().evaluate_condition(condition, context)
426
+
427
+
428
+ # DataBinding expression cache - specialized for {variable} patterns
429
+ class DataBindingCache:
430
+ """
431
+ Specialized cache for databinding expressions ({variable} patterns).
432
+
433
+ Optimized for the common pattern of extracting and evaluating
434
+ expressions within curly braces in Quantum templates.
435
+ """
436
+
437
+ def __init__(self, max_size: int = 500):
438
+ self._expr_cache = ExpressionCache(max_size=max_size)
439
+ self._pattern = re.compile(r'\{([^}]+)\}')
440
+ self._lock = threading.RLock()
441
+
442
+ def apply(self, text: str, context: Dict[str, Any]) -> Any:
443
+ """
444
+ Apply databinding to text, replacing {expr} with evaluated values.
445
+
446
+ Args:
447
+ text: Text containing {expression} patterns
448
+ context: Variable context
449
+
450
+ Returns:
451
+ Text with expressions replaced, or the raw value if pure expression
452
+ """
453
+ if not text:
454
+ return text
455
+
456
+ # Check if entire text is a single expression
457
+ full_match = self._pattern.fullmatch(text.strip())
458
+ if full_match:
459
+ expr = full_match.group(1).strip()
460
+ try:
461
+ return self._expr_cache.evaluate(expr, context)
462
+ except (ValueError, RuntimeError):
463
+ return text
464
+
465
+ # Mixed content - substitute all expressions as strings
466
+ def replace_expr(match):
467
+ expr = match.group(1).strip()
468
+ try:
469
+ result = self._expr_cache.evaluate(expr, context)
470
+ return str(result)
471
+ except (ValueError, RuntimeError):
472
+ return match.group(0)
473
+
474
+ return self._pattern.sub(replace_expr, text)
475
+
476
+ @property
477
+ def stats(self) -> CacheStats:
478
+ return self._expr_cache.stats
479
+
480
+ def clear(self):
481
+ self._expr_cache.clear()
482
+
483
+
484
+ # Global databinding cache
485
+ _databinding_cache: Optional[DataBindingCache] = None
486
+ _databinding_cache_lock = threading.Lock()
487
+
488
+
489
+ def get_databinding_cache() -> DataBindingCache:
490
+ """Get the global databinding cache instance"""
491
+ global _databinding_cache
492
+
493
+ if _databinding_cache is None:
494
+ with _databinding_cache_lock:
495
+ if _databinding_cache is None:
496
+ _databinding_cache = DataBindingCache()
497
+
498
+ return _databinding_cache