IncludeCPP 3.7.3__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 (49) hide show
  1. includecpp/__init__.py +59 -0
  2. includecpp/__init__.pyi +255 -0
  3. includecpp/__main__.py +4 -0
  4. includecpp/cli/__init__.py +4 -0
  5. includecpp/cli/commands.py +8270 -0
  6. includecpp/cli/config_parser.py +127 -0
  7. includecpp/core/__init__.py +19 -0
  8. includecpp/core/ai_integration.py +2132 -0
  9. includecpp/core/build_manager.py +2416 -0
  10. includecpp/core/cpp_api.py +376 -0
  11. includecpp/core/cpp_api.pyi +95 -0
  12. includecpp/core/cppy_converter.py +3448 -0
  13. includecpp/core/cssl/CSSL_DOCUMENTATION.md +2075 -0
  14. includecpp/core/cssl/__init__.py +42 -0
  15. includecpp/core/cssl/cssl_builtins.py +2271 -0
  16. includecpp/core/cssl/cssl_builtins.pyi +1393 -0
  17. includecpp/core/cssl/cssl_events.py +621 -0
  18. includecpp/core/cssl/cssl_modules.py +2803 -0
  19. includecpp/core/cssl/cssl_parser.py +2575 -0
  20. includecpp/core/cssl/cssl_runtime.py +3051 -0
  21. includecpp/core/cssl/cssl_syntax.py +488 -0
  22. includecpp/core/cssl/cssl_types.py +1512 -0
  23. includecpp/core/cssl_bridge.py +882 -0
  24. includecpp/core/cssl_bridge.pyi +488 -0
  25. includecpp/core/error_catalog.py +802 -0
  26. includecpp/core/error_formatter.py +1016 -0
  27. includecpp/core/exceptions.py +97 -0
  28. includecpp/core/path_discovery.py +77 -0
  29. includecpp/core/project_ui.py +3370 -0
  30. includecpp/core/settings_ui.py +326 -0
  31. includecpp/generator/__init__.py +1 -0
  32. includecpp/generator/parser.cpp +1903 -0
  33. includecpp/generator/parser.h +281 -0
  34. includecpp/generator/type_resolver.cpp +363 -0
  35. includecpp/generator/type_resolver.h +68 -0
  36. includecpp/py.typed +0 -0
  37. includecpp/templates/cpp.proj.template +18 -0
  38. includecpp/vscode/__init__.py +1 -0
  39. includecpp/vscode/cssl/__init__.py +1 -0
  40. includecpp/vscode/cssl/language-configuration.json +38 -0
  41. includecpp/vscode/cssl/package.json +50 -0
  42. includecpp/vscode/cssl/snippets/cssl.snippets.json +1080 -0
  43. includecpp/vscode/cssl/syntaxes/cssl.tmLanguage.json +341 -0
  44. includecpp-3.7.3.dist-info/METADATA +1076 -0
  45. includecpp-3.7.3.dist-info/RECORD +49 -0
  46. includecpp-3.7.3.dist-info/WHEEL +5 -0
  47. includecpp-3.7.3.dist-info/entry_points.txt +2 -0
  48. includecpp-3.7.3.dist-info/licenses/LICENSE +21 -0
  49. includecpp-3.7.3.dist-info/top_level.txt +1 -0
@@ -0,0 +1,882 @@
1
+ """
2
+ CSSL Bridge - Python API for CSSL Language
3
+ Provides CsslLang class for executing CSSL code from Python.
4
+ """
5
+
6
+ import os
7
+ import pickle
8
+ import random
9
+ import threading
10
+ from pathlib import Path
11
+ from typing import Any, List, Optional, Callable, Dict
12
+
13
+
14
+ def _get_share_directory() -> Path:
15
+ """Get the directory for shared objects."""
16
+ # Use APPDATA on Windows, ~/.config on Unix
17
+ if os.name == 'nt':
18
+ base = Path(os.environ.get('APPDATA', Path.home() / 'AppData' / 'Roaming'))
19
+ else:
20
+ base = Path(os.environ.get('XDG_CONFIG_HOME', Path.home() / '.config'))
21
+
22
+ share_dir = base / 'IncludeCPP' / 'shared_objects'
23
+ share_dir.mkdir(parents=True, exist_ok=True)
24
+ return share_dir
25
+
26
+
27
+ # Global live object registry - holds actual object references for live sharing
28
+ _live_objects: Dict[str, Any] = {}
29
+
30
+
31
+ class SharedObjectProxy:
32
+ """
33
+ Live proxy for accessing a shared Python object from CSSL.
34
+ Changes made through this proxy are reflected in the original object.
35
+ """
36
+
37
+ def __init__(self, name: str, obj: Any = None):
38
+ object.__setattr__(self, '_name', name)
39
+ object.__setattr__(self, '_direct_object', obj)
40
+
41
+ def _get_object(self):
42
+ """Get the live object reference."""
43
+ # First check direct object (same-instance sharing)
44
+ direct = object.__getattribute__(self, '_direct_object')
45
+ if direct is not None:
46
+ return direct
47
+
48
+ # Fall back to global registry
49
+ name = object.__getattribute__(self, '_name')
50
+ if name in _live_objects:
51
+ return _live_objects[name]
52
+
53
+ return None
54
+
55
+ def __getattr__(self, name: str):
56
+ """Access attributes/methods on the shared object."""
57
+ obj = self._get_object()
58
+ if obj is None:
59
+ obj_name = object.__getattribute__(self, '_name')
60
+ raise AttributeError(f"Shared object '${obj_name}' not available")
61
+
62
+ return getattr(obj, name)
63
+
64
+ def __setattr__(self, name: str, value: Any):
65
+ """Set attributes on the shared object (live update)."""
66
+ if name.startswith('_'):
67
+ object.__setattr__(self, name, value)
68
+ return
69
+
70
+ obj = self._get_object()
71
+ if obj is None:
72
+ obj_name = object.__getattribute__(self, '_name')
73
+ raise AttributeError(f"Shared object '${obj_name}' not available")
74
+
75
+ setattr(obj, name, value)
76
+
77
+ def __repr__(self):
78
+ obj = self._get_object()
79
+ name = object.__getattribute__(self, '_name')
80
+ return f"<SharedObject ${name} type={type(obj).__name__ if obj else 'None'}>"
81
+
82
+ def __call__(self, *args, **kwargs):
83
+ """Allow calling the object if it's callable."""
84
+ obj = self._get_object()
85
+ if obj is None:
86
+ name = object.__getattribute__(self, '_name')
87
+ raise TypeError(f"Shared object '${name}' not available")
88
+ if callable(obj):
89
+ return obj(*args, **kwargs)
90
+ name = object.__getattribute__(self, '_name')
91
+ raise TypeError(f"Shared object '${name}' is not callable")
92
+
93
+ def __getitem__(self, key):
94
+ """Allow indexing on the shared object."""
95
+ obj = self._get_object()
96
+ if obj is None:
97
+ name = object.__getattribute__(self, '_name')
98
+ raise KeyError(f"Shared object '${name}' not available")
99
+ return obj[key]
100
+
101
+ def __setitem__(self, key, value):
102
+ """Allow setting items on the shared object (live update)."""
103
+ obj = self._get_object()
104
+ if obj is None:
105
+ name = object.__getattribute__(self, '_name')
106
+ raise KeyError(f"Shared object '${name}' not available")
107
+ obj[key] = value
108
+
109
+ def __iter__(self):
110
+ """Allow iterating over the shared object."""
111
+ obj = self._get_object()
112
+ if obj is None:
113
+ name = object.__getattribute__(self, '_name')
114
+ raise TypeError(f"Shared object '${name}' not available")
115
+ return iter(obj)
116
+
117
+ def __len__(self):
118
+ """Get length of the shared object."""
119
+ obj = self._get_object()
120
+ if obj is None:
121
+ return 0
122
+ return len(obj)
123
+
124
+
125
+ class CSSLModule:
126
+ """
127
+ A callable CSSL module that executes code with arguments.
128
+
129
+ Created via CSSL.module() - the code is executed each time the module is called,
130
+ with arguments accessible via parameter.get(index).
131
+ """
132
+
133
+ def __init__(self, cssl_instance: 'CsslLang', code: str):
134
+ self._cssl = cssl_instance
135
+ self._code = code
136
+
137
+ def __call__(self, *args) -> Any:
138
+ """Execute the module code with the given arguments."""
139
+ return self._cssl.exec(self._code, *args)
140
+
141
+ def __repr__(self) -> str:
142
+ return f"<CSSLModule code_len={len(self._code)}>"
143
+
144
+
145
+ class CSSLFunctionModule:
146
+ """
147
+ A CSSL module with accessible functions as methods.
148
+
149
+ Created via CSSL.makemodule() - functions defined in the CSSL code
150
+ become callable attributes on this module.
151
+ """
152
+
153
+ def __init__(self, cssl_instance: 'CsslLang', code: str):
154
+ self._cssl = cssl_instance
155
+ self._code = code
156
+ self._runtime = None
157
+ self._functions: Dict[str, Any] = {}
158
+ self._initialized = False
159
+
160
+ def _ensure_initialized(self):
161
+ """Initialize the module by parsing and registering functions."""
162
+ if self._initialized:
163
+ return
164
+
165
+ from .cssl import CSSLRuntime, parse_cssl_program, ASTNode
166
+
167
+ # Create a dedicated runtime for this module
168
+ self._runtime = CSSLRuntime()
169
+
170
+ # Parse the code
171
+ ast = parse_cssl_program(self._code)
172
+
173
+ # Execute to register all function definitions
174
+ for child in ast.children:
175
+ if child.type == 'function':
176
+ func_info = child.value
177
+ func_name = func_info.get('name')
178
+ self._functions[func_name] = child
179
+ self._runtime.scope.set(func_name, child)
180
+ else:
181
+ # Execute other statements (like struct definitions)
182
+ try:
183
+ self._runtime._execute_node(child)
184
+ except Exception:
185
+ pass
186
+
187
+ self._initialized = True
188
+
189
+ def __getattr__(self, name: str) -> Callable:
190
+ """Get a function from the module."""
191
+ # Avoid recursion for internal attributes
192
+ if name.startswith('_'):
193
+ raise AttributeError(f"'{type(self).__name__}' has no attribute '{name}'")
194
+
195
+ self._ensure_initialized()
196
+
197
+ if name in self._functions:
198
+ func_node = self._functions[name]
199
+
200
+ def wrapper(*args):
201
+ from .cssl import Parameter
202
+ # Set up parameter object for this call
203
+ self._runtime.global_scope.set('parameter', Parameter(list(args)))
204
+ self._runtime.global_scope.set('args', list(args))
205
+ self._runtime.global_scope.set('argc', len(args))
206
+ return self._runtime._call_function(func_node, list(args))
207
+
208
+ return wrapper
209
+
210
+ raise AttributeError(f"CSSL module has no function '{name}'")
211
+
212
+ def __dir__(self) -> List[str]:
213
+ """List available functions."""
214
+ self._ensure_initialized()
215
+ return list(self._functions.keys())
216
+
217
+ def __repr__(self) -> str:
218
+ self._ensure_initialized()
219
+ funcs = ', '.join(self._functions.keys())
220
+ return f"<CSSLFunctionModule functions=[{funcs}]>"
221
+
222
+
223
+ class CsslLang:
224
+ """
225
+ CSSL Language interface for Python.
226
+
227
+ Usage:
228
+ from includecpp import CSSL
229
+ cssl = CSSL.CsslLang()
230
+ result = cssl.exec("script.cssl", arg1, arg2)
231
+ cssl.T_exec("async_script.cssl", arg1) # Threaded
232
+ """
233
+
234
+ def __init__(self, output_callback: Optional[Callable[[str, str], None]] = None):
235
+ """
236
+ Initialize CSSL runtime.
237
+
238
+ Args:
239
+ output_callback: Optional callback for output (text, level)
240
+ """
241
+ self._output_callback = output_callback
242
+ self._runtime = None
243
+ self._threads: List[threading.Thread] = []
244
+
245
+ def _get_runtime(self):
246
+ """Lazy load CSSL runtime."""
247
+ if self._runtime is None:
248
+ from .cssl import CSSLRuntime
249
+ self._runtime = CSSLRuntime(output_callback=self._output_callback)
250
+ return self._runtime
251
+
252
+ def exec(self, path_or_code: str, *args) -> Any:
253
+ """
254
+ Execute CSSL code or file.
255
+
256
+ Args:
257
+ path_or_code: Path to .cssl file or CSSL code string
258
+ *args: Arguments to pass to the script
259
+
260
+ Returns:
261
+ Execution result. If parameter.return() was called, returns
262
+ the list of returned values (or single value if only one).
263
+ """
264
+ runtime = self._get_runtime()
265
+
266
+ # Check if it's a file path
267
+ path = Path(path_or_code)
268
+ if path.exists() and path.suffix in ('.cssl', '.cssl-mod'):
269
+ source = path.read_text(encoding='utf-8')
270
+ else:
271
+ source = path_or_code
272
+
273
+ # Set arguments in runtime scope
274
+ from .cssl import Parameter
275
+ param = Parameter(list(args))
276
+ runtime.global_scope.set('args', list(args))
277
+ runtime.global_scope.set('argc', len(args))
278
+ runtime.global_scope.set('parameter', param)
279
+
280
+ # Execute as standalone program
281
+ try:
282
+ result = runtime.execute_program(source)
283
+
284
+ # Check if parameter.return() was used (generator-like returns)
285
+ if param.has_returns():
286
+ returns = param.returns()
287
+ # Return single value if only one, else return list
288
+ return returns[0] if len(returns) == 1 else returns
289
+
290
+ return result
291
+ except Exception as e:
292
+ # Format error message nicely
293
+ error_msg = str(e)
294
+ # Don't double-wrap error messages
295
+ if error_msg.startswith("CSSL Error:"):
296
+ raise RuntimeError(error_msg) from e
297
+ raise RuntimeError(f"CSSL Error:\n{error_msg}") from e
298
+
299
+ def T_exec(self, path_or_code: str, *args, callback: Optional[Callable[[Any], None]] = None) -> threading.Thread:
300
+ """
301
+ Execute CSSL code asynchronously in a thread.
302
+
303
+ Args:
304
+ path_or_code: Path to .cssl file or CSSL code string
305
+ *args: Arguments to pass to the script
306
+ callback: Optional callback when execution completes
307
+
308
+ Returns:
309
+ Thread object
310
+ """
311
+ def _run():
312
+ try:
313
+ result = self.exec(path_or_code, *args)
314
+ if callback:
315
+ callback(result)
316
+ except Exception as e:
317
+ if callback:
318
+ callback(e)
319
+
320
+ thread = threading.Thread(target=_run, daemon=True)
321
+ thread.start()
322
+ self._threads.append(thread)
323
+ return thread
324
+
325
+ def wait_all(self, timeout: Optional[float] = None):
326
+ """Wait for all async executions to complete."""
327
+ for thread in self._threads:
328
+ thread.join(timeout=timeout)
329
+ self._threads.clear()
330
+
331
+ def get_output(self) -> List[str]:
332
+ """Get output buffer from last execution."""
333
+ runtime = self._get_runtime()
334
+ return list(runtime.output_buffer)
335
+
336
+ def clear_output(self):
337
+ """Clear output buffer."""
338
+ runtime = self._get_runtime()
339
+ runtime.output_buffer.clear()
340
+
341
+ def set_global(self, name: str, value: Any):
342
+ """Set a global variable in CSSL runtime."""
343
+ runtime = self._get_runtime()
344
+ runtime.global_scope.set(name, value)
345
+
346
+ def get_global(self, name: str) -> Any:
347
+ """Get a global variable from CSSL runtime."""
348
+ runtime = self._get_runtime()
349
+ return runtime.global_scope.get(name)
350
+
351
+ def module(self, code: str) -> 'CSSLModule':
352
+ """
353
+ Create a callable CSSL module from code.
354
+
355
+ The module can be called with arguments that are passed to the CSSL code.
356
+
357
+ Usage:
358
+ module = CSSL.module('''
359
+ printl(parameter.get(0));
360
+ ''')
361
+ module("Hello") # Prints "Hello"
362
+
363
+ Args:
364
+ code: CSSL code string
365
+
366
+ Returns:
367
+ CSSLModule - a callable module
368
+ """
369
+ return CSSLModule(self, code)
370
+
371
+ def makemodule(self, code: str) -> 'CSSLFunctionModule':
372
+ """
373
+ Create a CSSL module with accessible functions.
374
+
375
+ Functions defined in the code become methods on the returned module.
376
+
377
+ Usage:
378
+ module = CSSL.makemodule('''
379
+ string greet(string name) {
380
+ return "Hello, " + name + "!";
381
+ }
382
+
383
+ int add(int a, int b) {
384
+ return a + b;
385
+ }
386
+ ''')
387
+ module.greet("World") # Returns "Hello, World!"
388
+ module.add(2, 3) # Returns 5
389
+
390
+ Args:
391
+ code: CSSL code string with function definitions
392
+
393
+ Returns:
394
+ CSSLFunctionModule - module with callable function attributes
395
+ """
396
+ return CSSLFunctionModule(self, code)
397
+
398
+ def code(self, name: str, code: str) -> None:
399
+ """
400
+ Register inline CSSL code as a payload that can be loaded via payload().
401
+
402
+ This allows creating payloads from Python code without external files.
403
+
404
+ Usage:
405
+ from includecpp import CSSL
406
+ cssl = CSSL.CsslLang()
407
+
408
+ # Register a helper payload
409
+ cssl.code("helpers", '''
410
+ global version = "1.0.0";
411
+ void log(string msg) {
412
+ printl("[LOG] " + msg);
413
+ }
414
+ ''')
415
+
416
+ # Use it in CSSL code
417
+ cssl.exec('''
418
+ payload("helpers"); // Load the inline payload
419
+ @log("Hello!"); // Call the helper function
420
+ printl(@version); // Access the global
421
+ ''')
422
+
423
+ Args:
424
+ name: Name to register the payload under (used in payload("name"))
425
+ code: CSSL code string
426
+ """
427
+ runtime = self._get_runtime()
428
+ if not hasattr(runtime, '_inline_payloads'):
429
+ runtime._inline_payloads = {}
430
+ runtime._inline_payloads[name] = code
431
+
432
+ def share(self, instance: Any, name: str = None) -> str:
433
+ """
434
+ Share a Python object instance with CSSL scripts (LIVE sharing).
435
+
436
+ The object is stored as a LIVE reference - changes made in CSSL
437
+ will be reflected in the original Python object immediately.
438
+ Call share() again with the same name to update the shared object.
439
+
440
+ Args:
441
+ instance: The Python object to share (or name if using old API)
442
+ name: The name to reference the object in CSSL ($name)
443
+
444
+ Note: Arguments can be passed in either order:
445
+ cssl.share(my_object, "name") # Preferred
446
+ cssl.share("name", my_object) # Also works
447
+
448
+ Usage in Python:
449
+ from includecpp import CSSL
450
+ cssl = CSSL.CsslLang()
451
+
452
+ # Share a Python object
453
+ class MyAPI:
454
+ def __init__(self):
455
+ self.counter = 0
456
+ def greet(self, name):
457
+ return f"Hello, {name}!"
458
+ def increment(self):
459
+ self.counter += 1
460
+
461
+ api = MyAPI()
462
+ cssl.share(api, "myapi")
463
+
464
+ # Use in CSSL - changes are LIVE!
465
+ cssl.exec('''
466
+ ob <== $myapi;
467
+ printl(ob.greet("World"));
468
+ ob.increment();
469
+ printl(ob.counter); // 1
470
+ ''')
471
+
472
+ # Changes reflect back to Python!
473
+ print(api.counter) # 1
474
+
475
+ Args:
476
+ instance: Python object to share
477
+ name: Name for the shared object (accessed as $name in CSSL)
478
+
479
+ Returns:
480
+ Path to the shared object marker file
481
+ """
482
+ global _live_objects
483
+ runtime = self._get_runtime()
484
+
485
+ # Handle argument order flexibility: share(instance, name) or share(name, instance)
486
+ if name is None:
487
+ # Only one argument - use object type as name
488
+ name = type(instance).__name__
489
+ elif isinstance(instance, str) and not isinstance(name, str):
490
+ # Arguments are swapped: share("name", instance) -> swap them
491
+ instance, name = name, instance
492
+ elif not isinstance(name, str):
493
+ # name is not a string - use its type as name
494
+ name = type(name).__name__
495
+
496
+ # Sanitize filename: remove invalid characters for Windows
497
+ import re
498
+ safe_name = re.sub(r'[<>:"/\\|?*\x00-\x1f]', '_', str(name))
499
+
500
+ # Initialize shared objects registry
501
+ if not hasattr(runtime, '_shared_objects'):
502
+ runtime._shared_objects = {}
503
+
504
+ # Generate unique filename: <name>.shareobj<7digits>
505
+ random_suffix = ''.join([str(random.randint(0, 9)) for _ in range(7)])
506
+ share_dir = _get_share_directory()
507
+ filepath = share_dir / f"{safe_name}.shareobj{random_suffix}"
508
+
509
+ # Remove old file if updating
510
+ if name in runtime._shared_objects:
511
+ old_path = runtime._shared_objects[name]['path']
512
+ try:
513
+ Path(old_path).unlink(missing_ok=True)
514
+ except Exception:
515
+ pass
516
+
517
+ # Store LIVE object reference in global registry
518
+ _live_objects[name] = instance
519
+
520
+ # Write marker file with metadata (not the actual object)
521
+ import json
522
+ metadata = {
523
+ 'name': name,
524
+ 'type': type(instance).__name__,
525
+ 'live': True,
526
+ 'id': id(instance)
527
+ }
528
+ with open(filepath, 'w', encoding='utf-8') as f:
529
+ json.dump(metadata, f)
530
+
531
+ # Register in runtime
532
+ runtime._shared_objects[name] = {
533
+ 'path': str(filepath),
534
+ 'type': type(instance).__name__,
535
+ 'live': True
536
+ }
537
+
538
+ # Also register the live proxy in the runtime's scope for $name access
539
+ proxy = SharedObjectProxy(name, instance)
540
+ runtime.global_scope.set(f'${name}', proxy)
541
+
542
+ return str(filepath)
543
+
544
+ def unshare(self, name: str) -> bool:
545
+ """
546
+ Remove a shared object.
547
+
548
+ Args:
549
+ name: Name of the shared object to remove
550
+
551
+ Returns:
552
+ True if removed, False if not found
553
+ """
554
+ global _live_objects
555
+ runtime = self._get_runtime()
556
+
557
+ if not hasattr(runtime, '_shared_objects'):
558
+ return False
559
+
560
+ if name not in runtime._shared_objects:
561
+ return False
562
+
563
+ # Remove from live objects registry
564
+ if name in _live_objects:
565
+ del _live_objects[name]
566
+
567
+ # Remove from runtime scope
568
+ try:
569
+ runtime.global_scope.delete(f'${name}')
570
+ except Exception:
571
+ pass
572
+
573
+ # Remove marker file
574
+ filepath = runtime._shared_objects[name]['path']
575
+ try:
576
+ Path(filepath).unlink(missing_ok=True)
577
+ except Exception:
578
+ pass
579
+
580
+ del runtime._shared_objects[name]
581
+ return True
582
+
583
+ def get_shared(self, name: str) -> Optional[Any]:
584
+ """
585
+ Get a shared object by name (for Python-side access).
586
+
587
+ Returns the actual live object reference, not a copy.
588
+
589
+ Args:
590
+ name: Name of the shared object
591
+
592
+ Returns:
593
+ The live shared object or None if not found
594
+ """
595
+ global _live_objects
596
+
597
+ # Return live object if available
598
+ if name in _live_objects:
599
+ return _live_objects[name]
600
+
601
+ return None
602
+
603
+ def shared(self, name: str) -> Optional[Any]:
604
+ """
605
+ Get a shared object by name (alias for get_shared).
606
+
607
+ Returns the actual live object reference, not a copy.
608
+ Works with both Python cssl.share() and CSSL ==> $name shared objects.
609
+
610
+ Usage:
611
+ from includecpp import CSSL
612
+ cssl = CSSL.CsslLang()
613
+
614
+ # Share an object
615
+ my_obj = {"value": 42}
616
+ cssl.share(my_obj, "data")
617
+
618
+ # Retrieve it later
619
+ obj = cssl.shared("data")
620
+ print(obj["value"]) # 42
621
+
622
+ Args:
623
+ name: Name of the shared object (without $ prefix)
624
+
625
+ Returns:
626
+ The live shared object or None if not found
627
+ """
628
+ return self.get_shared(name)
629
+
630
+
631
+ # Global shared objects registry (for cross-instance sharing)
632
+ _global_shared_objects: Dict[str, str] = {}
633
+
634
+
635
+ def share(instance: Any, name: str = None) -> str:
636
+ """
637
+ Share a Python object globally for all CSSL instances (LIVE sharing).
638
+
639
+ Changes made through CSSL will reflect back to the original object.
640
+
641
+ Args can be passed in either order:
642
+ share(my_object, "name") # Preferred
643
+ share("name", my_object) # Also works
644
+ """
645
+ global _live_objects
646
+ import re
647
+
648
+ # Handle argument order flexibility
649
+ if name is None:
650
+ name = type(instance).__name__
651
+ elif isinstance(instance, str) and not isinstance(name, str):
652
+ instance, name = name, instance
653
+ elif not isinstance(name, str):
654
+ name = type(name).__name__
655
+
656
+ # Sanitize filename
657
+ safe_name = re.sub(r'[<>:"/\\|?*\x00-\x1f]', '_', str(name))
658
+
659
+ random_suffix = ''.join([str(random.randint(0, 9)) for _ in range(7)])
660
+ share_dir = _get_share_directory()
661
+ filepath = share_dir / f"{safe_name}.shareobj{random_suffix}"
662
+
663
+ # Remove old file if updating
664
+ if name in _global_shared_objects:
665
+ try:
666
+ Path(_global_shared_objects[name]).unlink(missing_ok=True)
667
+ except Exception:
668
+ pass
669
+
670
+ # Store LIVE object reference
671
+ _live_objects[name] = instance
672
+
673
+ # Write marker file with metadata
674
+ import json
675
+ metadata = {
676
+ 'name': name,
677
+ 'type': type(instance).__name__,
678
+ 'live': True,
679
+ 'id': id(instance)
680
+ }
681
+ with open(filepath, 'w', encoding='utf-8') as f:
682
+ json.dump(metadata, f)
683
+
684
+ _global_shared_objects[name] = str(filepath)
685
+ return str(filepath)
686
+
687
+
688
+ def unshare(name: str) -> bool:
689
+ """Remove a globally shared object."""
690
+ global _live_objects
691
+
692
+ if name not in _global_shared_objects:
693
+ return False
694
+
695
+ # Remove from live objects
696
+ if name in _live_objects:
697
+ del _live_objects[name]
698
+
699
+ try:
700
+ Path(_global_shared_objects[name]).unlink(missing_ok=True)
701
+ except Exception:
702
+ pass
703
+
704
+ del _global_shared_objects[name]
705
+ return True
706
+
707
+
708
+ def get_shared(name: str) -> Optional[Any]:
709
+ """Get a globally shared object by name."""
710
+ global _live_objects
711
+ return _live_objects.get(name)
712
+
713
+
714
+ def shared(name: str) -> Optional[Any]:
715
+ """
716
+ Get a shared object by name (alias for get_shared).
717
+
718
+ Works with both Python share() and CSSL ==> $name shared objects.
719
+
720
+ Usage:
721
+ from includecpp import CSSL
722
+
723
+ # Share an object
724
+ my_obj = {"value": 42}
725
+ CSSL.share(my_obj, "data")
726
+
727
+ # Retrieve it later
728
+ obj = CSSL.shared("data")
729
+ print(obj["value"]) # 42
730
+
731
+ Args:
732
+ name: Name of the shared object (without $ prefix)
733
+
734
+ Returns:
735
+ The live shared object or None if not found
736
+ """
737
+ return get_shared(name)
738
+
739
+
740
+ # Singleton for convenience
741
+ _default_instance: Optional[CsslLang] = None
742
+
743
+ def get_cssl() -> CsslLang:
744
+ """Get default CSSL instance."""
745
+ global _default_instance
746
+ if _default_instance is None:
747
+ _default_instance = CsslLang()
748
+ return _default_instance
749
+
750
+
751
+ # Module-level convenience functions
752
+ def exec(path_or_code: str, *args) -> Any:
753
+ """
754
+ Execute CSSL code or file.
755
+
756
+ Usage:
757
+ from includecpp import CSSL
758
+ CSSL.exec("script.cssl", arg1, arg2)
759
+ CSSL.exec("printl('Hello World');")
760
+
761
+ Args:
762
+ path_or_code: Path to .cssl file or CSSL code string
763
+ *args: Arguments to pass to the script
764
+
765
+ Returns:
766
+ Execution result
767
+ """
768
+ return get_cssl().exec(path_or_code, *args)
769
+
770
+
771
+ def T_exec(path_or_code: str, *args, callback: Optional[Callable[[Any], None]] = None) -> threading.Thread:
772
+ """
773
+ Execute CSSL code asynchronously in a thread.
774
+
775
+ Usage:
776
+ from includecpp import CSSL
777
+ CSSL.T_exec("async_script.cssl", arg1, callback=on_done)
778
+
779
+ Args:
780
+ path_or_code: Path to .cssl file or CSSL code string
781
+ *args: Arguments to pass to the script
782
+ callback: Optional callback when execution completes
783
+
784
+ Returns:
785
+ Thread object
786
+ """
787
+ return get_cssl().T_exec(path_or_code, *args, callback=callback)
788
+
789
+
790
+ def set_global(name: str, value: Any) -> None:
791
+ """Set a global variable in CSSL runtime."""
792
+ get_cssl().set_global(name, value)
793
+
794
+
795
+ def get_global(name: str) -> Any:
796
+ """Get a global variable from CSSL runtime."""
797
+ return get_cssl().get_global(name)
798
+
799
+
800
+ def get_output() -> List[str]:
801
+ """Get output buffer from last execution."""
802
+ return get_cssl().get_output()
803
+
804
+
805
+ def clear_output() -> None:
806
+ """Clear output buffer."""
807
+ get_cssl().clear_output()
808
+
809
+
810
+ # Aliases to avoid conflict with Python builtin exec
811
+ _exec = exec
812
+ _T_exec = T_exec
813
+
814
+
815
+ def module(code: str) -> CSSLModule:
816
+ """
817
+ Create a callable CSSL module from code.
818
+
819
+ Usage:
820
+ from includecpp import CSSL
821
+ greet = CSSL.module('''
822
+ printl("Hello, " + parameter.get(0) + "!");
823
+ ''')
824
+ greet("World") # Prints "Hello, World!"
825
+
826
+ Args:
827
+ code: CSSL code string
828
+
829
+ Returns:
830
+ CSSLModule - a callable module
831
+ """
832
+ return get_cssl().module(code)
833
+
834
+
835
+ def makemodule(code: str) -> CSSLFunctionModule:
836
+ """
837
+ Create a CSSL module with accessible functions.
838
+
839
+ Usage:
840
+ from includecpp import CSSL
841
+ math_mod = CSSL.makemodule('''
842
+ int add(int a, int b) {
843
+ return a + b;
844
+ }
845
+
846
+ int multiply(int a, int b) {
847
+ return a * b;
848
+ }
849
+ ''')
850
+ math_mod.add(2, 3) # Returns 5
851
+ math_mod.multiply(4, 5) # Returns 20
852
+
853
+ Args:
854
+ code: CSSL code string with function definitions
855
+
856
+ Returns:
857
+ CSSLFunctionModule - module with callable function attributes
858
+ """
859
+ return get_cssl().makemodule(code)
860
+
861
+
862
+ # Export all
863
+ __all__ = [
864
+ 'CsslLang',
865
+ 'CSSLModule',
866
+ 'CSSLFunctionModule',
867
+ 'get_cssl',
868
+ 'exec',
869
+ '_exec', # Alias for exec (avoids Python builtin conflict)
870
+ 'T_exec',
871
+ '_T_exec', # Alias for T_exec
872
+ 'set_global',
873
+ 'get_global',
874
+ 'get_output',
875
+ 'clear_output',
876
+ 'module',
877
+ 'makemodule',
878
+ 'share',
879
+ 'unshare',
880
+ 'shared',
881
+ 'get_shared',
882
+ ]