IncludeCPP 4.0.2__py3-none-any.whl → 4.2.2__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.
- includecpp/CHANGELOG.md +175 -0
- includecpp/DOCUMENTATION.md +593 -0
- includecpp/__init__.py +1 -1
- includecpp/__init__.pyi +4 -1
- includecpp/cli/commands.py +698 -84
- includecpp/core/ai_integration.py +46 -13
- includecpp/core/cpp_api_extensions.pyi +350 -0
- includecpp/core/cssl/CSSL_DOCUMENTATION.md +186 -5
- includecpp/core/cssl/cssl_builtins.py +101 -4
- includecpp/core/cssl/cssl_languages.py +1757 -0
- includecpp/core/cssl/cssl_parser.py +429 -98
- includecpp/core/cssl/cssl_runtime.py +666 -51
- includecpp/core/cssl/cssl_syntax.py +88 -4
- includecpp/core/cssl/cssl_types.py +172 -1
- includecpp/core/cssl_bridge.py +194 -8
- includecpp/core/cssl_bridge.pyi +148 -10
- includecpp/generator/parser.cpp +121 -4
- includecpp/generator/parser.h +6 -0
- includecpp/vscode/cssl/package.json +43 -1
- includecpp/vscode/cssl/syntaxes/cssl.tmLanguage.json +140 -17
- {includecpp-4.0.2.dist-info → includecpp-4.2.2.dist-info}/METADATA +101 -1
- {includecpp-4.0.2.dist-info → includecpp-4.2.2.dist-info}/RECORD +26 -22
- {includecpp-4.0.2.dist-info → includecpp-4.2.2.dist-info}/WHEEL +0 -0
- {includecpp-4.0.2.dist-info → includecpp-4.2.2.dist-info}/entry_points.txt +0 -0
- {includecpp-4.0.2.dist-info → includecpp-4.2.2.dist-info}/licenses/LICENSE +0 -0
- {includecpp-4.0.2.dist-info → includecpp-4.2.2.dist-info}/top_level.txt +0 -0
|
@@ -31,6 +31,11 @@ class TokenCategory(Enum):
|
|
|
31
31
|
NULL = auto() # null, None
|
|
32
32
|
PACKAGE_KW = auto() # package, package-includes - NEW
|
|
33
33
|
TYPE_LITERAL = auto() # list, dict - NEW
|
|
34
|
+
# v4.1.0: Multi-language support
|
|
35
|
+
SUPPORTS_KW = auto() # supports keyword (magenta)
|
|
36
|
+
LIBINCLUDE_KW = auto() # libinclude (yellow/gold)
|
|
37
|
+
LANG_PREFIX = auto() # Language prefix before $ (cyan): cpp$, py$, java$
|
|
38
|
+
LANG_INSTANCE = auto() # Instance name after $ (orange): cpp$ClassName
|
|
34
39
|
|
|
35
40
|
|
|
36
41
|
@dataclass
|
|
@@ -52,9 +57,17 @@ KEYWORDS = {
|
|
|
52
57
|
'start', 'stop', 'wait_for', 'on_event', 'emit_event',
|
|
53
58
|
'await',
|
|
54
59
|
# NEW: Extended keywords
|
|
55
|
-
'package', 'package-includes', 'exec', 'as', 'global'
|
|
60
|
+
'package', 'package-includes', 'exec', 'as', 'global',
|
|
61
|
+
# v4.1.0: Multi-language support (handled separately for special colors)
|
|
62
|
+
# 'supports', 'libinclude' - see MULTI_LANG_KEYWORDS
|
|
56
63
|
}
|
|
57
64
|
|
|
65
|
+
# v4.1.0: Multi-language keywords with special highlighting
|
|
66
|
+
MULTI_LANG_KEYWORDS = {'supports', 'libinclude'}
|
|
67
|
+
|
|
68
|
+
# v4.1.0: Language identifiers for cross-language instance access
|
|
69
|
+
LANGUAGE_IDS = {'cpp', 'py', 'python', 'java', 'csharp', 'js', 'javascript'}
|
|
70
|
+
|
|
58
71
|
# NEW: Package-related keywords for special highlighting
|
|
59
72
|
PACKAGE_KEYWORDS = {'package', 'package-includes'}
|
|
60
73
|
|
|
@@ -145,6 +158,33 @@ class CSSLSyntaxRules:
|
|
|
145
158
|
category=TokenCategory.TYPE_LITERAL
|
|
146
159
|
))
|
|
147
160
|
|
|
161
|
+
# v4.1.0: Multi-language support keywords
|
|
162
|
+
# 'supports' keyword (magenta) - must be before regular keywords
|
|
163
|
+
rules.append(HighlightRule(
|
|
164
|
+
pattern=r'\bsupports\b',
|
|
165
|
+
category=TokenCategory.SUPPORTS_KW
|
|
166
|
+
))
|
|
167
|
+
|
|
168
|
+
# 'libinclude' keyword (yellow/gold)
|
|
169
|
+
rules.append(HighlightRule(
|
|
170
|
+
pattern=r'\blibinclude\b',
|
|
171
|
+
category=TokenCategory.LIBINCLUDE_KW
|
|
172
|
+
))
|
|
173
|
+
|
|
174
|
+
# v4.1.0: Language$Instance patterns (cpp$ClassName, py$Object)
|
|
175
|
+
# Match language prefix before $ (cyan)
|
|
176
|
+
rules.append(HighlightRule(
|
|
177
|
+
pattern=r'\b(cpp|py|python|java|csharp|js|javascript)\$',
|
|
178
|
+
category=TokenCategory.LANG_PREFIX,
|
|
179
|
+
group=1
|
|
180
|
+
))
|
|
181
|
+
# Match instance name after $ (orange)
|
|
182
|
+
rules.append(HighlightRule(
|
|
183
|
+
pattern=r'\b(?:cpp|py|python|java|csharp|js|javascript)\$([A-Za-z_][A-Za-z0-9_]*)',
|
|
184
|
+
category=TokenCategory.LANG_INSTANCE,
|
|
185
|
+
group=1
|
|
186
|
+
))
|
|
187
|
+
|
|
148
188
|
# Self-references (s@Name, s@Backend.Loop)
|
|
149
189
|
rules.append(HighlightRule(
|
|
150
190
|
pattern=r's@[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)*',
|
|
@@ -233,6 +273,11 @@ class ColorScheme:
|
|
|
233
273
|
TokenCategory.NULL: '#ff6464', # Red
|
|
234
274
|
TokenCategory.PACKAGE_KW: '#bd93f9', # Purple for package - NEW
|
|
235
275
|
TokenCategory.TYPE_LITERAL: '#8be9fd', # Cyan for type literals - NEW
|
|
276
|
+
# v4.1.0: Multi-language support colors
|
|
277
|
+
TokenCategory.SUPPORTS_KW: '#ff79c6', # Magenta/Pink for 'supports'
|
|
278
|
+
TokenCategory.LIBINCLUDE_KW: '#f1fa8c',# Yellow/Gold for 'libinclude'
|
|
279
|
+
TokenCategory.LANG_PREFIX: '#8be9fd', # Cyan for language prefix (cpp$)
|
|
280
|
+
TokenCategory.LANG_INSTANCE: '#ffb86c',# Orange for instance name ($ClassName)
|
|
236
281
|
}
|
|
237
282
|
|
|
238
283
|
# Light theme variant
|
|
@@ -252,6 +297,11 @@ class ColorScheme:
|
|
|
252
297
|
TokenCategory.NULL: '#ff0000', # Red
|
|
253
298
|
TokenCategory.PACKAGE_KW: '#8b008b', # DarkMagenta for package - NEW
|
|
254
299
|
TokenCategory.TYPE_LITERAL: '#008b8b', # Dark cyan for type literals - NEW
|
|
300
|
+
# v4.1.0: Multi-language support colors
|
|
301
|
+
TokenCategory.SUPPORTS_KW: '#d63384', # Dark Magenta for 'supports'
|
|
302
|
+
TokenCategory.LIBINCLUDE_KW: '#b8860b',# DarkGoldenrod for 'libinclude'
|
|
303
|
+
TokenCategory.LANG_PREFIX: '#0d6efd', # Blue for language prefix (cpp$)
|
|
304
|
+
TokenCategory.LANG_INSTANCE: '#fd7e14',# Orange for instance name ($ClassName)
|
|
255
305
|
}
|
|
256
306
|
|
|
257
307
|
|
|
@@ -334,6 +384,11 @@ def highlight_cssl_ansi(source: str) -> str:
|
|
|
334
384
|
TokenCategory.NULL: '\033[91m', # Red
|
|
335
385
|
TokenCategory.PACKAGE_KW: '\033[95m', # Magenta for package - NEW
|
|
336
386
|
TokenCategory.TYPE_LITERAL: '\033[96m', # Cyan for type literals - NEW
|
|
387
|
+
# v4.1.0: Multi-language support colors
|
|
388
|
+
TokenCategory.SUPPORTS_KW: '\033[95m', # Magenta for 'supports'
|
|
389
|
+
TokenCategory.LIBINCLUDE_KW: '\033[93m',# Yellow for 'libinclude'
|
|
390
|
+
TokenCategory.LANG_PREFIX: '\033[96m', # Cyan for language prefix (cpp$)
|
|
391
|
+
TokenCategory.LANG_INSTANCE: '\033[33m',# Orange/Yellow for instance name
|
|
337
392
|
}
|
|
338
393
|
RESET = '\033[0m'
|
|
339
394
|
|
|
@@ -439,6 +494,10 @@ def export_textmate_grammar() -> dict:
|
|
|
439
494
|
"name": "comment.line.cssl",
|
|
440
495
|
"match": "#.*$"
|
|
441
496
|
},
|
|
497
|
+
{
|
|
498
|
+
"name": "comment.line.double-slash.cssl",
|
|
499
|
+
"match": "//.*$"
|
|
500
|
+
},
|
|
442
501
|
{
|
|
443
502
|
"name": "string.quoted.double.cssl",
|
|
444
503
|
"match": '"(?:[^"\\\\]|\\\\.)*"'
|
|
@@ -447,6 +506,23 @@ def export_textmate_grammar() -> dict:
|
|
|
447
506
|
"name": "string.quoted.single.cssl",
|
|
448
507
|
"match": "'(?:[^'\\\\]|\\\\.)*'"
|
|
449
508
|
},
|
|
509
|
+
# v4.1.0: Multi-language support
|
|
510
|
+
{
|
|
511
|
+
"name": "keyword.control.supports.cssl",
|
|
512
|
+
"match": "\\bsupports\\b"
|
|
513
|
+
},
|
|
514
|
+
{
|
|
515
|
+
"name": "support.function.libinclude.cssl",
|
|
516
|
+
"match": "\\blibinclude\\b"
|
|
517
|
+
},
|
|
518
|
+
{
|
|
519
|
+
"name": "variable.language.lang-instance.cssl",
|
|
520
|
+
"match": "\\b(cpp|py|python|java|csharp|js|javascript)\\$([A-Za-z_][A-Za-z0-9_]*)",
|
|
521
|
+
"captures": {
|
|
522
|
+
"1": {"name": "entity.name.type.language.cssl"},
|
|
523
|
+
"2": {"name": "variable.other.instance.cssl"}
|
|
524
|
+
}
|
|
525
|
+
},
|
|
450
526
|
{
|
|
451
527
|
"name": "variable.other.self-reference.cssl",
|
|
452
528
|
"match": "s@[A-Za-z_][A-Za-z0-9_]*(?:\\.[A-Za-z_][A-Za-z0-9_]*)*"
|
|
@@ -455,9 +531,13 @@ def export_textmate_grammar() -> dict:
|
|
|
455
531
|
"name": "variable.other.module-reference.cssl",
|
|
456
532
|
"match": "@[A-Za-z_][A-Za-z0-9_]*(?:\\.[A-Za-z_][A-Za-z0-9_]*)*"
|
|
457
533
|
},
|
|
534
|
+
{
|
|
535
|
+
"name": "keyword.other.package.cssl",
|
|
536
|
+
"match": "\\b(package|package-includes)\\b"
|
|
537
|
+
},
|
|
458
538
|
{
|
|
459
539
|
"name": "keyword.control.cssl",
|
|
460
|
-
"match": "\\b(service-init|service-run|service-include|struct|define|if|else|elif|while|for|foreach|in|switch|case|default|break|continue|return|try|catch|await)\\b"
|
|
540
|
+
"match": "\\b(service-init|service-run|service-include|struct|define|class|constr|if|else|elif|while|for|foreach|in|switch|case|default|break|continue|return|try|catch|finally|throw|await|extends|overwrites|global|as|exec)\\b"
|
|
461
541
|
},
|
|
462
542
|
{
|
|
463
543
|
"name": "keyword.operator.cssl",
|
|
@@ -465,7 +545,7 @@ def export_textmate_grammar() -> dict:
|
|
|
465
545
|
},
|
|
466
546
|
{
|
|
467
547
|
"name": "constant.language.cssl",
|
|
468
|
-
"match": "\\b(True|False|true|false|null|None)\\b"
|
|
548
|
+
"match": "\\b(True|False|true|false|null|None|none)\\b"
|
|
469
549
|
},
|
|
470
550
|
{
|
|
471
551
|
"name": "constant.numeric.cssl",
|
|
@@ -473,7 +553,11 @@ def export_textmate_grammar() -> dict:
|
|
|
473
553
|
},
|
|
474
554
|
{
|
|
475
555
|
"name": "keyword.operator.assignment.cssl",
|
|
476
|
-
"match": "
|
|
556
|
+
"match": "<==|==>|->|<-|::"
|
|
557
|
+
},
|
|
558
|
+
{
|
|
559
|
+
"name": "support.type.cssl",
|
|
560
|
+
"match": "\\b(list|dict)\\b(?!\\s*\\()"
|
|
477
561
|
}
|
|
478
562
|
]
|
|
479
563
|
}
|
|
@@ -1624,10 +1624,181 @@ class CSSLInstance:
|
|
|
1624
1624
|
return f"<{self._class.name} instance at 0x{id(self):x}>"
|
|
1625
1625
|
|
|
1626
1626
|
|
|
1627
|
+
class UniversalInstance:
|
|
1628
|
+
"""Universal shared container accessible from CSSL, Python, and C++.
|
|
1629
|
+
|
|
1630
|
+
Created via instance<"name"> syntax in CSSL or getInstance("name") in Python.
|
|
1631
|
+
Supports dynamic member/method injection via +<<== operator.
|
|
1632
|
+
|
|
1633
|
+
Example CSSL:
|
|
1634
|
+
instance<"myContainer"> container;
|
|
1635
|
+
container +<<== { void sayHello() { printl("Hello!"); } }
|
|
1636
|
+
container.sayHello();
|
|
1637
|
+
|
|
1638
|
+
Example Python:
|
|
1639
|
+
container = cssl.getInstance("myContainer")
|
|
1640
|
+
container.sayHello()
|
|
1641
|
+
"""
|
|
1642
|
+
|
|
1643
|
+
# Global registry for all universal instances
|
|
1644
|
+
_registry: Dict[str, 'UniversalInstance'] = {}
|
|
1645
|
+
|
|
1646
|
+
def __init__(self, name: str):
|
|
1647
|
+
self._name = name
|
|
1648
|
+
self._members: Dict[str, Any] = {}
|
|
1649
|
+
self._methods: Dict[str, Any] = {} # Method name -> AST node or callable
|
|
1650
|
+
self._injections: List[Any] = [] # Code blocks injected via +<<==
|
|
1651
|
+
self._runtime = None # Weak reference to CSSL runtime for method calls
|
|
1652
|
+
# Register globally
|
|
1653
|
+
UniversalInstance._registry[name] = self
|
|
1654
|
+
|
|
1655
|
+
@classmethod
|
|
1656
|
+
def get_or_create(cls, name: str) -> 'UniversalInstance':
|
|
1657
|
+
"""Get existing instance or create new one."""
|
|
1658
|
+
if name in cls._registry:
|
|
1659
|
+
return cls._registry[name]
|
|
1660
|
+
return cls(name)
|
|
1661
|
+
|
|
1662
|
+
@classmethod
|
|
1663
|
+
def get(cls, name: str) -> Optional['UniversalInstance']:
|
|
1664
|
+
"""Get existing instance by name, returns None if not found."""
|
|
1665
|
+
return cls._registry.get(name)
|
|
1666
|
+
|
|
1667
|
+
@classmethod
|
|
1668
|
+
def exists(cls, name: str) -> bool:
|
|
1669
|
+
"""Check if instance exists."""
|
|
1670
|
+
return name in cls._registry
|
|
1671
|
+
|
|
1672
|
+
@classmethod
|
|
1673
|
+
def delete(cls, name: str) -> bool:
|
|
1674
|
+
"""Delete instance from registry."""
|
|
1675
|
+
if name in cls._registry:
|
|
1676
|
+
del cls._registry[name]
|
|
1677
|
+
return True
|
|
1678
|
+
return False
|
|
1679
|
+
|
|
1680
|
+
@classmethod
|
|
1681
|
+
def clear_all(cls) -> int:
|
|
1682
|
+
"""Clear all instances. Returns count of cleared instances."""
|
|
1683
|
+
count = len(cls._registry)
|
|
1684
|
+
cls._registry.clear()
|
|
1685
|
+
return count
|
|
1686
|
+
|
|
1687
|
+
@classmethod
|
|
1688
|
+
def list_all(cls) -> List[str]:
|
|
1689
|
+
"""List all instance names."""
|
|
1690
|
+
return list(cls._registry.keys())
|
|
1691
|
+
|
|
1692
|
+
@property
|
|
1693
|
+
def name(self) -> str:
|
|
1694
|
+
"""Get instance name."""
|
|
1695
|
+
return self._name
|
|
1696
|
+
|
|
1697
|
+
def set_member(self, name: str, value: Any) -> None:
|
|
1698
|
+
"""Set a member value."""
|
|
1699
|
+
self._members[name] = value
|
|
1700
|
+
|
|
1701
|
+
def get_member(self, name: str) -> Any:
|
|
1702
|
+
"""Get a member value."""
|
|
1703
|
+
if name in self._members:
|
|
1704
|
+
return self._members[name]
|
|
1705
|
+
raise AttributeError(f"Instance '{self._name}' has no member '{name}'")
|
|
1706
|
+
|
|
1707
|
+
def has_member(self, name: str) -> bool:
|
|
1708
|
+
"""Check if member exists."""
|
|
1709
|
+
return name in self._members
|
|
1710
|
+
|
|
1711
|
+
def set_runtime(self, runtime: Any) -> None:
|
|
1712
|
+
"""Set the runtime reference for method calls from Python."""
|
|
1713
|
+
import weakref
|
|
1714
|
+
self._runtime = weakref.ref(runtime)
|
|
1715
|
+
|
|
1716
|
+
def set_method(self, name: str, method: Any, runtime: Any = None) -> None:
|
|
1717
|
+
"""Set a method (AST node or callable)."""
|
|
1718
|
+
self._methods[name] = method
|
|
1719
|
+
if runtime is not None and self._runtime is None:
|
|
1720
|
+
self.set_runtime(runtime)
|
|
1721
|
+
|
|
1722
|
+
def get_method(self, name: str) -> Any:
|
|
1723
|
+
"""Get a method by name."""
|
|
1724
|
+
if name in self._methods:
|
|
1725
|
+
return self._methods[name]
|
|
1726
|
+
raise AttributeError(f"Instance '{self._name}' has no method '{name}'")
|
|
1727
|
+
|
|
1728
|
+
def has_method(self, name: str) -> bool:
|
|
1729
|
+
"""Check if method exists."""
|
|
1730
|
+
return name in self._methods
|
|
1731
|
+
|
|
1732
|
+
def add_injection(self, code_block: Any) -> None:
|
|
1733
|
+
"""Add a code injection (from +<<== operator)."""
|
|
1734
|
+
self._injections.append(code_block)
|
|
1735
|
+
|
|
1736
|
+
def get_injections(self) -> List[Any]:
|
|
1737
|
+
"""Get all injected code blocks."""
|
|
1738
|
+
return self._injections
|
|
1739
|
+
|
|
1740
|
+
def get_all_members(self) -> Dict[str, Any]:
|
|
1741
|
+
"""Get all members."""
|
|
1742
|
+
return dict(self._members)
|
|
1743
|
+
|
|
1744
|
+
def get_all_methods(self) -> Dict[str, Any]:
|
|
1745
|
+
"""Get all methods."""
|
|
1746
|
+
return dict(self._methods)
|
|
1747
|
+
|
|
1748
|
+
def __getattr__(self, name: str) -> Any:
|
|
1749
|
+
"""Allow direct attribute access for members and methods."""
|
|
1750
|
+
if name.startswith('_'):
|
|
1751
|
+
raise AttributeError(name)
|
|
1752
|
+
if name in object.__getattribute__(self, '_members'):
|
|
1753
|
+
return object.__getattribute__(self, '_members')[name]
|
|
1754
|
+
if name in object.__getattribute__(self, '_methods'):
|
|
1755
|
+
method = object.__getattribute__(self, '_methods')[name]
|
|
1756
|
+
runtime_ref = object.__getattribute__(self, '_runtime')
|
|
1757
|
+
|
|
1758
|
+
# If method is an AST node and we have a runtime, create a callable wrapper
|
|
1759
|
+
if hasattr(method, 'type') and method.type == 'function' and runtime_ref is not None:
|
|
1760
|
+
runtime = runtime_ref() # Dereference weakref
|
|
1761
|
+
if runtime is not None:
|
|
1762
|
+
instance = self
|
|
1763
|
+
def method_caller(*args, **kwargs):
|
|
1764
|
+
# Set 'this' context and call the method
|
|
1765
|
+
old_this = runtime.scope.get('this')
|
|
1766
|
+
runtime.scope.set('this', instance)
|
|
1767
|
+
try:
|
|
1768
|
+
return runtime._call_function(method, list(args))
|
|
1769
|
+
finally:
|
|
1770
|
+
if old_this is not None:
|
|
1771
|
+
runtime.scope.set('this', old_this)
|
|
1772
|
+
elif hasattr(runtime.scope, 'remove'):
|
|
1773
|
+
runtime.scope.remove('this')
|
|
1774
|
+
return method_caller
|
|
1775
|
+
# Return method directly if already callable or no runtime
|
|
1776
|
+
return method
|
|
1777
|
+
raise AttributeError(f"Instance '{object.__getattribute__(self, '_name')}' has no attribute '{name}'")
|
|
1778
|
+
|
|
1779
|
+
def __setattr__(self, name: str, value: Any) -> None:
|
|
1780
|
+
"""Allow direct attribute setting for members."""
|
|
1781
|
+
if name.startswith('_'):
|
|
1782
|
+
object.__setattr__(self, name, value)
|
|
1783
|
+
else:
|
|
1784
|
+
if hasattr(self, '_members'):
|
|
1785
|
+
self._members[name] = value
|
|
1786
|
+
else:
|
|
1787
|
+
object.__setattr__(self, name, value)
|
|
1788
|
+
|
|
1789
|
+
def __repr__(self):
|
|
1790
|
+
members = len(self._members)
|
|
1791
|
+
methods = len(self._methods)
|
|
1792
|
+
return f"<UniversalInstance '{self._name}' ({members} members, {methods} methods)>"
|
|
1793
|
+
|
|
1794
|
+
def __str__(self):
|
|
1795
|
+
return f"<UniversalInstance '{self._name}'>"
|
|
1796
|
+
|
|
1797
|
+
|
|
1627
1798
|
__all__ = [
|
|
1628
1799
|
'DataStruct', 'Shuffled', 'Iterator', 'Combo', 'DataSpace', 'OpenQuote',
|
|
1629
1800
|
'OpenFind', 'Parameter', 'Stack', 'Vector', 'Array', 'List', 'Dictionary', 'Map',
|
|
1630
|
-
'CSSLClass', 'CSSLInstance',
|
|
1801
|
+
'CSSLClass', 'CSSLInstance', 'UniversalInstance',
|
|
1631
1802
|
'create_datastruct', 'create_shuffled', 'create_iterator',
|
|
1632
1803
|
'create_combo', 'create_dataspace', 'create_openquote', 'create_parameter',
|
|
1633
1804
|
'create_stack', 'create_vector', 'create_array', 'create_list', 'create_dictionary', 'create_map'
|
includecpp/core/cssl_bridge.py
CHANGED
|
@@ -266,8 +266,8 @@ class CSSLFunctionModule:
|
|
|
266
266
|
|
|
267
267
|
from .cssl import CSSLRuntime, parse_cssl_program, ASTNode
|
|
268
268
|
|
|
269
|
-
# Create a dedicated runtime for this module
|
|
270
|
-
self._runtime = CSSLRuntime()
|
|
269
|
+
# Create a dedicated runtime for this module, preserving output_callback
|
|
270
|
+
self._runtime = CSSLRuntime(output_callback=self._cssl._output_callback)
|
|
271
271
|
|
|
272
272
|
# If we have a payload, load it first (defines functions/globals for main)
|
|
273
273
|
if self._payload_code:
|
|
@@ -330,7 +330,12 @@ class CSSLFunctionModule:
|
|
|
330
330
|
self._runtime.global_scope.set('parameter', Parameter(list(args)))
|
|
331
331
|
self._runtime.global_scope.set('args', list(args))
|
|
332
332
|
self._runtime.global_scope.set('argc', len(args))
|
|
333
|
-
|
|
333
|
+
# Enable running flag for function execution
|
|
334
|
+
self._runtime._running = True
|
|
335
|
+
try:
|
|
336
|
+
return self._runtime._call_function(func_node, list(args))
|
|
337
|
+
finally:
|
|
338
|
+
self._runtime._running = False
|
|
334
339
|
|
|
335
340
|
return wrapper
|
|
336
341
|
|
|
@@ -603,7 +608,8 @@ class CsslLang:
|
|
|
603
608
|
self,
|
|
604
609
|
main_script: Union[str, 'CSSLScript'],
|
|
605
610
|
payload_script: Union[str, 'CSSLScript', None] = None,
|
|
606
|
-
name: str = None
|
|
611
|
+
name: str = None,
|
|
612
|
+
bind: str = None
|
|
607
613
|
) -> 'CSSLFunctionModule':
|
|
608
614
|
"""
|
|
609
615
|
Create a CSSL module with accessible functions.
|
|
@@ -612,13 +618,22 @@ class CsslLang:
|
|
|
612
618
|
Optionally registers the module for payload() access in other scripts.
|
|
613
619
|
|
|
614
620
|
Args:
|
|
615
|
-
main_script: Main CSSL code
|
|
621
|
+
main_script: Main CSSL code, file path, or CSSLScript
|
|
616
622
|
payload_script: Optional payload code (string or CSSLScript)
|
|
617
623
|
name: Optional name to register for payload(name) access
|
|
624
|
+
bind: Optional payload name to auto-prepend (from makepayload)
|
|
618
625
|
|
|
619
626
|
Returns:
|
|
620
627
|
CSSLFunctionModule - module with callable function attributes
|
|
621
628
|
|
|
629
|
+
Usage (simplified - with file path and bind):
|
|
630
|
+
# First register the payload
|
|
631
|
+
cssl.makepayload("api", "lib/api/einkaufsmanager.cssl-pl")
|
|
632
|
+
|
|
633
|
+
# Then create module from file, binding to payload
|
|
634
|
+
mod = cssl.makemodule("writer", "lib/writer.cssl", bind="api")
|
|
635
|
+
mod.SaySomething("Hello!") # Functions are now accessible
|
|
636
|
+
|
|
622
637
|
Usage (v3.8.0 - with CSSLScript objects):
|
|
623
638
|
main = cssl.script("cssl", '''
|
|
624
639
|
printl("Main");
|
|
@@ -644,6 +659,28 @@ class CsslLang:
|
|
|
644
659
|
''')
|
|
645
660
|
module.greet("World") # Returns "Hello, World!"
|
|
646
661
|
"""
|
|
662
|
+
# Handle simplified API: makemodule(name, path, bind=...)
|
|
663
|
+
# Check if main_script looks like a short identifier and payload_script looks like a path
|
|
664
|
+
if (isinstance(main_script, str) and isinstance(payload_script, str) and
|
|
665
|
+
not '\n' in main_script and not ';' in main_script and not '{' in main_script):
|
|
666
|
+
# main_script is likely a name, payload_script is likely a path
|
|
667
|
+
module_name = main_script
|
|
668
|
+
path = payload_script
|
|
669
|
+
|
|
670
|
+
# Check if it's actually a file path
|
|
671
|
+
path_obj = Path(path)
|
|
672
|
+
if path_obj.exists():
|
|
673
|
+
main_code = path_obj.read_text(encoding='utf-8')
|
|
674
|
+
|
|
675
|
+
# If bind is specified, prepend that payload's code
|
|
676
|
+
payload_code = None
|
|
677
|
+
if bind:
|
|
678
|
+
runtime = self._get_runtime()
|
|
679
|
+
if hasattr(runtime, '_inline_payloads') and bind in runtime._inline_payloads:
|
|
680
|
+
payload_code = runtime._inline_payloads[bind]
|
|
681
|
+
|
|
682
|
+
return CSSLFunctionModule(self, main_code, payload_code, module_name)
|
|
683
|
+
|
|
647
684
|
# Extract code from CSSLScript objects if provided
|
|
648
685
|
if isinstance(main_script, CSSLScript):
|
|
649
686
|
main_code = main_script.code
|
|
@@ -657,6 +694,12 @@ class CsslLang:
|
|
|
657
694
|
else:
|
|
658
695
|
payload_code = payload_script
|
|
659
696
|
|
|
697
|
+
# If bind is specified and no payload_script, use the bound payload
|
|
698
|
+
if bind and payload_code is None:
|
|
699
|
+
runtime = self._get_runtime()
|
|
700
|
+
if hasattr(runtime, '_inline_payloads') and bind in runtime._inline_payloads:
|
|
701
|
+
payload_code = runtime._inline_payloads[bind]
|
|
702
|
+
|
|
660
703
|
return CSSLFunctionModule(self, main_code, payload_code, name)
|
|
661
704
|
|
|
662
705
|
def load(self, path: str, name: str) -> None:
|
|
@@ -781,6 +824,45 @@ class CsslLang:
|
|
|
781
824
|
runtime._inline_payloads = {}
|
|
782
825
|
runtime._inline_payloads[name] = code
|
|
783
826
|
|
|
827
|
+
def makepayload(self, name: str, path: str) -> str:
|
|
828
|
+
"""
|
|
829
|
+
Register a payload from a file path.
|
|
830
|
+
|
|
831
|
+
Reads the file and registers it as a payload accessible via payload(name) in CSSL.
|
|
832
|
+
This is a convenience method that combines reading a file and calling code().
|
|
833
|
+
|
|
834
|
+
Usage:
|
|
835
|
+
from includecpp import CSSL
|
|
836
|
+
cssl = CSSL.CsslLang()
|
|
837
|
+
|
|
838
|
+
# Register a payload from file
|
|
839
|
+
cssl.makepayload("api", "lib/api/myapi.cssl-pl")
|
|
840
|
+
|
|
841
|
+
# Now use in CSSL code
|
|
842
|
+
cssl.run('''
|
|
843
|
+
payload("api"); // Load the payload
|
|
844
|
+
myApiFunction(); // Call functions from it
|
|
845
|
+
''')
|
|
846
|
+
|
|
847
|
+
# Or use with makemodule for automatic binding
|
|
848
|
+
mod = cssl.makemodule("writer", "lib/writer.cssl", bind="api")
|
|
849
|
+
mod.SaySomething("Hello!")
|
|
850
|
+
|
|
851
|
+
Args:
|
|
852
|
+
name: Name to register the payload under (used in payload(name) and bind=name)
|
|
853
|
+
path: Path to the .cssl-pl or .cssl file
|
|
854
|
+
|
|
855
|
+
Returns:
|
|
856
|
+
The payload code that was registered
|
|
857
|
+
"""
|
|
858
|
+
path_obj = Path(path)
|
|
859
|
+
if not path_obj.exists():
|
|
860
|
+
raise FileNotFoundError(f"Payload file not found: {path}")
|
|
861
|
+
|
|
862
|
+
code = path_obj.read_text(encoding='utf-8')
|
|
863
|
+
self.code(name, code)
|
|
864
|
+
return code
|
|
865
|
+
|
|
784
866
|
def share(self, instance: Any, name: str = None) -> str:
|
|
785
867
|
"""
|
|
786
868
|
Share a Python object instance with CSSL scripts (LIVE sharing).
|
|
@@ -979,6 +1061,73 @@ class CsslLang:
|
|
|
979
1061
|
"""
|
|
980
1062
|
return self.get_shared(name)
|
|
981
1063
|
|
|
1064
|
+
def getInstance(self, name: str) -> Optional[Any]:
|
|
1065
|
+
"""
|
|
1066
|
+
Get a universal instance by name (for Python-side access).
|
|
1067
|
+
|
|
1068
|
+
Universal instances are shared containers accessible from CSSL, Python, and C++.
|
|
1069
|
+
They support dynamic member/method access and are mutable across all contexts.
|
|
1070
|
+
|
|
1071
|
+
Usage:
|
|
1072
|
+
from includecpp import CSSL
|
|
1073
|
+
cssl = CSSL.CsslLang()
|
|
1074
|
+
|
|
1075
|
+
# In CSSL: instance<"myContainer"> container;
|
|
1076
|
+
# Then in Python:
|
|
1077
|
+
container = cssl.getInstance("myContainer")
|
|
1078
|
+
container.member = "value"
|
|
1079
|
+
print(container.member) # value
|
|
1080
|
+
|
|
1081
|
+
Args:
|
|
1082
|
+
name: Name of the instance (without quotes)
|
|
1083
|
+
|
|
1084
|
+
Returns:
|
|
1085
|
+
The UniversalInstance or None if not found
|
|
1086
|
+
"""
|
|
1087
|
+
from .cssl.cssl_types import UniversalInstance
|
|
1088
|
+
return UniversalInstance.get(name)
|
|
1089
|
+
|
|
1090
|
+
def createInstance(self, name: str) -> Any:
|
|
1091
|
+
"""
|
|
1092
|
+
Create or get a universal instance by name (for Python-side creation).
|
|
1093
|
+
|
|
1094
|
+
Usage:
|
|
1095
|
+
container = cssl.createInstance("myContainer")
|
|
1096
|
+
container.data = {"key": "value"}
|
|
1097
|
+
# Now accessible in CSSL via instance<"myContainer">
|
|
1098
|
+
|
|
1099
|
+
Args:
|
|
1100
|
+
name: Name for the instance
|
|
1101
|
+
|
|
1102
|
+
Returns:
|
|
1103
|
+
The UniversalInstance (new or existing)
|
|
1104
|
+
"""
|
|
1105
|
+
from .cssl.cssl_types import UniversalInstance
|
|
1106
|
+
return UniversalInstance.get_or_create(name)
|
|
1107
|
+
|
|
1108
|
+
def deleteInstance(self, name: str) -> bool:
|
|
1109
|
+
"""
|
|
1110
|
+
Delete a universal instance by name.
|
|
1111
|
+
|
|
1112
|
+
Args:
|
|
1113
|
+
name: Name of the instance to delete
|
|
1114
|
+
|
|
1115
|
+
Returns:
|
|
1116
|
+
True if deleted, False if not found
|
|
1117
|
+
"""
|
|
1118
|
+
from .cssl.cssl_types import UniversalInstance
|
|
1119
|
+
return UniversalInstance.delete(name)
|
|
1120
|
+
|
|
1121
|
+
def listInstances(self) -> list:
|
|
1122
|
+
"""
|
|
1123
|
+
List all universal instance names.
|
|
1124
|
+
|
|
1125
|
+
Returns:
|
|
1126
|
+
List of instance names
|
|
1127
|
+
"""
|
|
1128
|
+
from .cssl.cssl_types import UniversalInstance
|
|
1129
|
+
return UniversalInstance.list_all()
|
|
1130
|
+
|
|
982
1131
|
|
|
983
1132
|
# Global shared objects registry (for cross-instance sharing)
|
|
984
1133
|
_global_shared_objects: Dict[str, str] = {}
|
|
@@ -1303,14 +1452,49 @@ def module(code: str) -> CSSLModule:
|
|
|
1303
1452
|
return get_cssl().module(code)
|
|
1304
1453
|
|
|
1305
1454
|
|
|
1455
|
+
def makepayload(name: str, path: str) -> str:
|
|
1456
|
+
"""
|
|
1457
|
+
Register a payload from a file path.
|
|
1458
|
+
|
|
1459
|
+
Reads the file and registers it as a payload accessible via payload(name) in CSSL.
|
|
1460
|
+
|
|
1461
|
+
Usage:
|
|
1462
|
+
from includecpp import CSSL
|
|
1463
|
+
|
|
1464
|
+
# Register a payload from file
|
|
1465
|
+
CSSL.makepayload("api", "lib/api/myapi.cssl-pl")
|
|
1466
|
+
|
|
1467
|
+
# Use with makemodule for automatic binding
|
|
1468
|
+
mod = CSSL.makemodule("writer", "lib/writer.cssl", bind="api")
|
|
1469
|
+
mod.SaySomething("Hello!")
|
|
1470
|
+
|
|
1471
|
+
Args:
|
|
1472
|
+
name: Name to register the payload under (used in payload(name) and bind=name)
|
|
1473
|
+
path: Path to the .cssl-pl or .cssl file
|
|
1474
|
+
|
|
1475
|
+
Returns:
|
|
1476
|
+
The payload code that was registered
|
|
1477
|
+
"""
|
|
1478
|
+
return get_cssl().makepayload(name, path)
|
|
1479
|
+
|
|
1480
|
+
|
|
1306
1481
|
def makemodule(
|
|
1307
1482
|
main_script: Union[str, CSSLScript],
|
|
1308
1483
|
payload_script: Union[str, CSSLScript, None] = None,
|
|
1309
|
-
name: str = None
|
|
1484
|
+
name: str = None,
|
|
1485
|
+
bind: str = None
|
|
1310
1486
|
) -> CSSLFunctionModule:
|
|
1311
1487
|
"""
|
|
1312
1488
|
Create a CSSL module with accessible functions.
|
|
1313
1489
|
|
|
1490
|
+
Usage (simplified - with file path and bind):
|
|
1491
|
+
# First register the payload
|
|
1492
|
+
CSSL.makepayload("api", "lib/api/einkaufsmanager.cssl-pl")
|
|
1493
|
+
|
|
1494
|
+
# Then create module from file, binding to payload
|
|
1495
|
+
mod = CSSL.makemodule("writer", "lib/writer.cssl", bind="api")
|
|
1496
|
+
mod.SaySomething("Hello!")
|
|
1497
|
+
|
|
1314
1498
|
Usage (v3.8.0 - with CSSLScript):
|
|
1315
1499
|
main = CSSL.script("cssl", '''printl("Main");''')
|
|
1316
1500
|
payload = CSSL.script("cssl-pl", '''void helper() {}''')
|
|
@@ -1323,14 +1507,15 @@ def makemodule(
|
|
|
1323
1507
|
math_mod.add(2, 3) # Returns 5
|
|
1324
1508
|
|
|
1325
1509
|
Args:
|
|
1326
|
-
main_script: Main CSSL code
|
|
1510
|
+
main_script: Main CSSL code, file path, or CSSLScript
|
|
1327
1511
|
payload_script: Optional payload code (string or CSSLScript)
|
|
1328
1512
|
name: Optional name to register for payload(name) access
|
|
1513
|
+
bind: Optional payload name to auto-prepend (from makepayload)
|
|
1329
1514
|
|
|
1330
1515
|
Returns:
|
|
1331
1516
|
CSSLFunctionModule - module with callable function attributes
|
|
1332
1517
|
"""
|
|
1333
|
-
return get_cssl().makemodule(main_script, payload_script, name)
|
|
1518
|
+
return get_cssl().makemodule(main_script, payload_script, name, bind)
|
|
1334
1519
|
|
|
1335
1520
|
|
|
1336
1521
|
# Export all
|
|
@@ -1360,6 +1545,7 @@ __all__ = [
|
|
|
1360
1545
|
'get_output',
|
|
1361
1546
|
'clear_output',
|
|
1362
1547
|
'module',
|
|
1548
|
+
'makepayload',
|
|
1363
1549
|
'makemodule',
|
|
1364
1550
|
'share',
|
|
1365
1551
|
'unshare',
|