IncludeCPP 3.8.2__tar.gz → 3.8.4__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.
- {includecpp-3.8.2 → includecpp-3.8.4}/IncludeCPP.egg-info/PKG-INFO +1 -1
- {includecpp-3.8.2 → includecpp-3.8.4}/PKG-INFO +1 -1
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/__init__.py +1 -1
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/core/cssl/CSSL_DOCUMENTATION.md +196 -1
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/core/cssl/cssl_builtins.py +133 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/core/cssl/cssl_parser.py +99 -7
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/core/cssl/cssl_runtime.py +208 -3
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/core/cssl/cssl_types.py +58 -9
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/vscode/cssl/syntaxes/cssl.tmLanguage.json +33 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/pyproject.toml +1 -1
- {includecpp-3.8.2 → includecpp-3.8.4}/IncludeCPP.egg-info/SOURCES.txt +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/IncludeCPP.egg-info/dependency_links.txt +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/IncludeCPP.egg-info/entry_points.txt +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/IncludeCPP.egg-info/requires.txt +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/IncludeCPP.egg-info/top_level.txt +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/LICENSE +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/MANIFEST.in +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/README.md +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/__init__.pyi +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/__main__.py +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/cli/__init__.py +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/cli/commands.py +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/cli/config_parser.py +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/core/__init__.py +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/core/ai_integration.py +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/core/build_manager.py +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/core/cpp_api.py +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/core/cpp_api.pyi +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/core/cppy_converter.py +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/core/cssl/__init__.py +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/core/cssl/cssl_builtins.pyi +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/core/cssl/cssl_events.py +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/core/cssl/cssl_modules.py +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/core/cssl/cssl_syntax.py +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/core/cssl_bridge.py +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/core/cssl_bridge.pyi +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/core/error_catalog.py +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/core/error_formatter.py +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/core/exceptions.py +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/core/path_discovery.py +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/core/project_ui.py +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/core/settings_ui.py +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/generator/__init__.py +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/generator/parser.cpp +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/generator/parser.h +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/generator/type_resolver.cpp +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/generator/type_resolver.h +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/py.typed +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/templates/cpp.proj.template +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/vscode/__init__.py +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/vscode/cssl/__init__.py +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/vscode/cssl/extension.js +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/vscode/cssl/images/cssl.png +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/vscode/cssl/images/cssl_pl.png +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/vscode/cssl/language-configuration.json +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/vscode/cssl/package.json +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/includecpp/vscode/cssl/snippets/cssl.snippets.json +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/requirements.txt +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/setup.cfg +0 -0
- {includecpp-3.8.2 → includecpp-3.8.4}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# CSSL - C-Style Scripting Language
|
|
2
2
|
|
|
3
|
-
> Version 3.
|
|
3
|
+
> Version 3.8.4 | A modern scripting language with C++-style syntax and unique features like CodeInfusion, BruteInjection, and Python Interop.
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -1696,6 +1696,201 @@ string result = b.add("Hello ").add("World!").build();
|
|
|
1696
1696
|
printl(result); // prints: "Hello World!"
|
|
1697
1697
|
```
|
|
1698
1698
|
|
|
1699
|
+
### Class Inheritance (extends)
|
|
1700
|
+
|
|
1701
|
+
CSSL supports class inheritance using the `: extends` syntax:
|
|
1702
|
+
|
|
1703
|
+
```cssl
|
|
1704
|
+
// Base class
|
|
1705
|
+
class Animal {
|
|
1706
|
+
string name;
|
|
1707
|
+
|
|
1708
|
+
void Animal(string n) {
|
|
1709
|
+
this->name = n;
|
|
1710
|
+
}
|
|
1711
|
+
|
|
1712
|
+
void speak() {
|
|
1713
|
+
printl("Some sound");
|
|
1714
|
+
}
|
|
1715
|
+
}
|
|
1716
|
+
|
|
1717
|
+
// Derived class - inherits all members and methods from Animal
|
|
1718
|
+
class Dog : extends Animal {
|
|
1719
|
+
void Dog(string n) {
|
|
1720
|
+
this->name = n;
|
|
1721
|
+
}
|
|
1722
|
+
|
|
1723
|
+
// Override parent method
|
|
1724
|
+
void speak() {
|
|
1725
|
+
printl("Woof! I'm " + this->name);
|
|
1726
|
+
}
|
|
1727
|
+
|
|
1728
|
+
// New method only in Dog
|
|
1729
|
+
void fetch() {
|
|
1730
|
+
printl(this->name + " fetches the ball!");
|
|
1731
|
+
}
|
|
1732
|
+
}
|
|
1733
|
+
|
|
1734
|
+
Dog d = new Dog("Buddy");
|
|
1735
|
+
d.speak(); // "Woof! I'm Buddy"
|
|
1736
|
+
d.fetch(); // "Buddy fetches the ball!"
|
|
1737
|
+
```
|
|
1738
|
+
|
|
1739
|
+
### Extending Python Objects
|
|
1740
|
+
|
|
1741
|
+
You can extend Python classes/objects directly:
|
|
1742
|
+
|
|
1743
|
+
```cssl
|
|
1744
|
+
// Extend a Python object using $
|
|
1745
|
+
class ExtendedGame : extends $GameEngine {
|
|
1746
|
+
void newFeature() {
|
|
1747
|
+
printl("New CSSL feature!");
|
|
1748
|
+
}
|
|
1749
|
+
|
|
1750
|
+
// Override a Python method
|
|
1751
|
+
void showUsername() {
|
|
1752
|
+
printl("Custom username display: " + this->username);
|
|
1753
|
+
}
|
|
1754
|
+
}
|
|
1755
|
+
```
|
|
1756
|
+
|
|
1757
|
+
In Python:
|
|
1758
|
+
```python
|
|
1759
|
+
class GameEngine:
|
|
1760
|
+
def __init__(self):
|
|
1761
|
+
self.username = "Player1"
|
|
1762
|
+
def showUsername(self):
|
|
1763
|
+
print(f"Username: {self.username}")
|
|
1764
|
+
|
|
1765
|
+
cssl = CSSL.CsslLang()
|
|
1766
|
+
cssl.share('GameEngine', GameEngine())
|
|
1767
|
+
cssl.run('''
|
|
1768
|
+
class MyGame : extends $GameEngine {
|
|
1769
|
+
void customMethod() {
|
|
1770
|
+
printl("Extended from Python!");
|
|
1771
|
+
}
|
|
1772
|
+
}
|
|
1773
|
+
''')
|
|
1774
|
+
```
|
|
1775
|
+
|
|
1776
|
+
### Class Overwrites
|
|
1777
|
+
|
|
1778
|
+
Use `: overwrites` to replace methods in an existing class/object:
|
|
1779
|
+
|
|
1780
|
+
```cssl
|
|
1781
|
+
// Overwrite methods in a Python object
|
|
1782
|
+
class MyOverrides : extends $GameEngine : overwrites $GameEngine {
|
|
1783
|
+
// This method will REPLACE the original showUsername() in $GameEngine
|
|
1784
|
+
void showUsername() {
|
|
1785
|
+
printl("OVERWRITTEN: " + this->username);
|
|
1786
|
+
}
|
|
1787
|
+
}
|
|
1788
|
+
```
|
|
1789
|
+
|
|
1790
|
+
When you use `: overwrites TargetClass`, all methods defined in your class will replace the corresponding methods in the target. This works with:
|
|
1791
|
+
- Other CSSL classes
|
|
1792
|
+
- Python objects via `$ObjectName`
|
|
1793
|
+
- Shared objects
|
|
1794
|
+
|
|
1795
|
+
### python::csslize() - Import Python Objects
|
|
1796
|
+
|
|
1797
|
+
Convert Python objects to CSSL-compatible wrappers:
|
|
1798
|
+
|
|
1799
|
+
```cssl
|
|
1800
|
+
// Import a Python object
|
|
1801
|
+
py_obj <== python::csslize($MyPythonInstance);
|
|
1802
|
+
|
|
1803
|
+
// Now use it like a CSSL object
|
|
1804
|
+
py_obj.someMethod();
|
|
1805
|
+
printl(py_obj.someProperty);
|
|
1806
|
+
|
|
1807
|
+
// Or use it as a base class
|
|
1808
|
+
class Extended : extends py_obj {
|
|
1809
|
+
void newMethod() { ... }
|
|
1810
|
+
}
|
|
1811
|
+
```
|
|
1812
|
+
|
|
1813
|
+
In Python:
|
|
1814
|
+
```python
|
|
1815
|
+
class MyPythonClass:
|
|
1816
|
+
def __init__(self, name):
|
|
1817
|
+
self.name = name
|
|
1818
|
+
def greet(self):
|
|
1819
|
+
return f"Hello, {self.name}!"
|
|
1820
|
+
|
|
1821
|
+
cssl = CSSL.CsslLang()
|
|
1822
|
+
cssl.share('MyPython', MyPythonClass("World"))
|
|
1823
|
+
result = cssl.run('''
|
|
1824
|
+
py_obj <== python::csslize($MyPython);
|
|
1825
|
+
printl(py_obj.greet()); // "Hello, World!"
|
|
1826
|
+
''')
|
|
1827
|
+
```
|
|
1828
|
+
|
|
1829
|
+
### Function Extends & Overwrites
|
|
1830
|
+
|
|
1831
|
+
Functions can also extend or overwrite other functions:
|
|
1832
|
+
|
|
1833
|
+
```cssl
|
|
1834
|
+
// Base function
|
|
1835
|
+
define baseFunction() {
|
|
1836
|
+
string greeting = "Hello";
|
|
1837
|
+
int count = 42;
|
|
1838
|
+
printl(greeting);
|
|
1839
|
+
}
|
|
1840
|
+
|
|
1841
|
+
// Extend: inherit local variables from baseFunction
|
|
1842
|
+
define extendedFunc : extends baseFunction() {
|
|
1843
|
+
// 'greeting' and 'count' are available here!
|
|
1844
|
+
printl(greeting + " World! Count: " + count);
|
|
1845
|
+
}
|
|
1846
|
+
|
|
1847
|
+
// Overwrite: replace the original function
|
|
1848
|
+
define myReplacement : overwrites baseFunction() {
|
|
1849
|
+
printl("This replaces baseFunction entirely!");
|
|
1850
|
+
}
|
|
1851
|
+
|
|
1852
|
+
// After defining myReplacement, calling baseFunction()
|
|
1853
|
+
// will now execute myReplacement instead
|
|
1854
|
+
baseFunction(); // prints: "This replaces baseFunction entirely!"
|
|
1855
|
+
```
|
|
1856
|
+
|
|
1857
|
+
Overwriting Python functions:
|
|
1858
|
+
```cssl
|
|
1859
|
+
// Replace a shared Python function
|
|
1860
|
+
define myVersion : overwrites $pythonFunc() {
|
|
1861
|
+
printl("CSSL implementation replaces Python!");
|
|
1862
|
+
}
|
|
1863
|
+
```
|
|
1864
|
+
|
|
1865
|
+
### Non-Null Declarations
|
|
1866
|
+
|
|
1867
|
+
Use `*` prefix to declare non-nullable items:
|
|
1868
|
+
|
|
1869
|
+
```cssl
|
|
1870
|
+
// Non-null variable - can never be None
|
|
1871
|
+
vector<dynamic> *myList; // Always initialized, never null
|
|
1872
|
+
|
|
1873
|
+
// Non-null function - must never return None
|
|
1874
|
+
define *alwaysReturns() {
|
|
1875
|
+
return "Always a value"; // Error if returns null
|
|
1876
|
+
}
|
|
1877
|
+
|
|
1878
|
+
// Non-null class - all methods return non-null
|
|
1879
|
+
class *MyClass {
|
|
1880
|
+
string getValue() {
|
|
1881
|
+
return "Value"; // All methods must return non-null
|
|
1882
|
+
}
|
|
1883
|
+
}
|
|
1884
|
+
|
|
1885
|
+
// Non-null open parameter - filters out None values
|
|
1886
|
+
define process(open *Params) {
|
|
1887
|
+
// Params will never contain None values
|
|
1888
|
+
foreach item in Params {
|
|
1889
|
+
printl(item); // Guaranteed non-null
|
|
1890
|
+
}
|
|
1891
|
+
}
|
|
1892
|
+
```
|
|
1893
|
+
|
|
1699
1894
|
---
|
|
1700
1895
|
|
|
1701
1896
|
## Map Container
|
|
@@ -209,6 +209,8 @@ class CSSLBuiltins:
|
|
|
209
209
|
self._functions['python::pythonize'] = self.builtin_python_pythonize
|
|
210
210
|
self._functions['python::wrap'] = self.builtin_python_pythonize # Alias
|
|
211
211
|
self._functions['python::export'] = self.builtin_python_pythonize # Alias
|
|
212
|
+
self._functions['python::csslize'] = self.builtin_python_csslize
|
|
213
|
+
self._functions['python::import'] = self.builtin_python_csslize # Alias
|
|
212
214
|
|
|
213
215
|
# Regex functions
|
|
214
216
|
self._functions['match'] = self.builtin_match
|
|
@@ -2524,6 +2526,137 @@ class CSSLBuiltins:
|
|
|
2524
2526
|
|
|
2525
2527
|
return PythonizedCSSLInstance(cssl_instance, self.runtime)
|
|
2526
2528
|
|
|
2529
|
+
def builtin_python_csslize(self, python_obj: Any) -> Any:
|
|
2530
|
+
"""Convert a Python object (class instance or function) to a CSSL-compatible wrapper.
|
|
2531
|
+
|
|
2532
|
+
Syntax:
|
|
2533
|
+
cssl_obj <== python::csslize($python_instance);
|
|
2534
|
+
cssl_func <== python::csslize($python_function);
|
|
2535
|
+
|
|
2536
|
+
Example:
|
|
2537
|
+
# In Python:
|
|
2538
|
+
class MyPythonClass:
|
|
2539
|
+
def __init__(self, name):
|
|
2540
|
+
self.name = name
|
|
2541
|
+
def greet(self):
|
|
2542
|
+
return f"Hello, {self.name}!"
|
|
2543
|
+
|
|
2544
|
+
cssl = CSSL.CsslLang()
|
|
2545
|
+
cssl.set_variable('MyPython', MyPythonClass("World"))
|
|
2546
|
+
result = cssl.run('''
|
|
2547
|
+
py_obj <== python::csslize($MyPython);
|
|
2548
|
+
printl(py_obj.greet()); // "Hello, World!"
|
|
2549
|
+
''')
|
|
2550
|
+
|
|
2551
|
+
For class inheritance:
|
|
2552
|
+
py_class <== python::csslize($MyPythonClass);
|
|
2553
|
+
class MyExtended : extends py_class {
|
|
2554
|
+
void newMethod() { ... }
|
|
2555
|
+
}
|
|
2556
|
+
|
|
2557
|
+
Args:
|
|
2558
|
+
python_obj: A Python object (class instance, function, or class)
|
|
2559
|
+
|
|
2560
|
+
Returns:
|
|
2561
|
+
CSSLizedPythonObject - A CSSL-compatible wrapper
|
|
2562
|
+
"""
|
|
2563
|
+
if python_obj is None:
|
|
2564
|
+
return None
|
|
2565
|
+
|
|
2566
|
+
# Already csslized
|
|
2567
|
+
if isinstance(python_obj, CSSLizedPythonObject):
|
|
2568
|
+
return python_obj
|
|
2569
|
+
|
|
2570
|
+
# Wrap the Python object
|
|
2571
|
+
return CSSLizedPythonObject(python_obj, self.runtime)
|
|
2572
|
+
|
|
2573
|
+
|
|
2574
|
+
class CSSLizedPythonObject:
|
|
2575
|
+
"""CSSL wrapper for Python objects (classes, instances, functions).
|
|
2576
|
+
|
|
2577
|
+
Allows Python objects to be used within CSSL code, including as base classes.
|
|
2578
|
+
"""
|
|
2579
|
+
|
|
2580
|
+
def __init__(self, python_obj: Any, runtime: Any = None):
|
|
2581
|
+
self._python_obj = python_obj
|
|
2582
|
+
self._runtime = runtime
|
|
2583
|
+
self._is_class = isinstance(python_obj, type)
|
|
2584
|
+
self._is_callable = callable(python_obj) and not self._is_class
|
|
2585
|
+
|
|
2586
|
+
def __repr__(self):
|
|
2587
|
+
if self._is_class:
|
|
2588
|
+
return f"<CSSLizedPythonClass: {self._python_obj.__name__}>"
|
|
2589
|
+
elif self._is_callable:
|
|
2590
|
+
return f"<CSSLizedPythonFunction: {getattr(self._python_obj, '__name__', 'anonymous')}>"
|
|
2591
|
+
else:
|
|
2592
|
+
return f"<CSSLizedPythonInstance: {type(self._python_obj).__name__}>"
|
|
2593
|
+
|
|
2594
|
+
def __call__(self, *args, **kwargs):
|
|
2595
|
+
"""Call the wrapped object (for functions or class instantiation)."""
|
|
2596
|
+
return self._python_obj(*args, **kwargs)
|
|
2597
|
+
|
|
2598
|
+
def __getattr__(self, name: str) -> Any:
|
|
2599
|
+
"""Get attribute from wrapped Python object."""
|
|
2600
|
+
if name.startswith('_'):
|
|
2601
|
+
raise AttributeError(f"Cannot access private attribute '{name}'")
|
|
2602
|
+
|
|
2603
|
+
obj = object.__getattribute__(self, '_python_obj')
|
|
2604
|
+
|
|
2605
|
+
if hasattr(obj, name):
|
|
2606
|
+
attr = getattr(obj, name)
|
|
2607
|
+
# If it's a method, wrap it for CSSL calling
|
|
2608
|
+
if callable(attr):
|
|
2609
|
+
return CSSLizedPythonMethod(attr, self._runtime)
|
|
2610
|
+
return attr
|
|
2611
|
+
|
|
2612
|
+
raise AttributeError(f"Python object has no attribute '{name}'")
|
|
2613
|
+
|
|
2614
|
+
def __setattr__(self, name: str, value: Any):
|
|
2615
|
+
"""Set attribute on wrapped Python object."""
|
|
2616
|
+
if name.startswith('_'):
|
|
2617
|
+
object.__setattr__(self, name, value)
|
|
2618
|
+
else:
|
|
2619
|
+
setattr(self._python_obj, name, value)
|
|
2620
|
+
|
|
2621
|
+
def has_member(self, name: str) -> bool:
|
|
2622
|
+
"""Check if the Python object has a member."""
|
|
2623
|
+
return hasattr(self._python_obj, name)
|
|
2624
|
+
|
|
2625
|
+
def get_member(self, name: str) -> Any:
|
|
2626
|
+
"""Get a member from the Python object."""
|
|
2627
|
+
return getattr(self._python_obj, name, None)
|
|
2628
|
+
|
|
2629
|
+
def set_member(self, name: str, value: Any):
|
|
2630
|
+
"""Set a member on the Python object."""
|
|
2631
|
+
setattr(self._python_obj, name, value)
|
|
2632
|
+
|
|
2633
|
+
def get_method(self, name: str):
|
|
2634
|
+
"""Get a method from the Python object."""
|
|
2635
|
+
if hasattr(self._python_obj, name):
|
|
2636
|
+
method = getattr(self._python_obj, name)
|
|
2637
|
+
if callable(method):
|
|
2638
|
+
return CSSLizedPythonMethod(method, self._runtime)
|
|
2639
|
+
return None
|
|
2640
|
+
|
|
2641
|
+
def get_python_obj(self):
|
|
2642
|
+
"""Get the underlying Python object (for inheritance)."""
|
|
2643
|
+
return self._python_obj
|
|
2644
|
+
|
|
2645
|
+
|
|
2646
|
+
class CSSLizedPythonMethod:
|
|
2647
|
+
"""Wrapper for Python methods to be called from CSSL."""
|
|
2648
|
+
|
|
2649
|
+
def __init__(self, method: Any, runtime: Any = None):
|
|
2650
|
+
self._method = method
|
|
2651
|
+
self._runtime = runtime
|
|
2652
|
+
|
|
2653
|
+
def __call__(self, *args, **kwargs):
|
|
2654
|
+
"""Call the Python method."""
|
|
2655
|
+
return self._method(*args, **kwargs)
|
|
2656
|
+
|
|
2657
|
+
def __repr__(self):
|
|
2658
|
+
return f"<CSSLizedPythonMethod: {getattr(self._method, '__name__', 'anonymous')}>"
|
|
2659
|
+
|
|
2527
2660
|
|
|
2528
2661
|
class PythonizedCSSLInstance:
|
|
2529
2662
|
"""Python wrapper for CSSL class instances.
|
|
@@ -114,7 +114,7 @@ class TokenType(Enum):
|
|
|
114
114
|
|
|
115
115
|
KEYWORDS = {
|
|
116
116
|
# Service structure
|
|
117
|
-
'service-init', 'service-run', 'service-include', 'struct', 'define', 'main', 'class', 'new', 'this',
|
|
117
|
+
'service-init', 'service-run', 'service-include', 'struct', 'define', 'main', 'class', 'extends', 'overwrites', 'new', 'this',
|
|
118
118
|
# Control flow
|
|
119
119
|
'if', 'else', 'elif', 'while', 'for', 'foreach', 'in', 'range',
|
|
120
120
|
'switch', 'case', 'default', 'break', 'continue', 'return',
|
|
@@ -1045,7 +1045,7 @@ class CSSLParser:
|
|
|
1045
1045
|
|
|
1046
1046
|
# Check for * prefix (non-nullable indicator)
|
|
1047
1047
|
non_null = False
|
|
1048
|
-
if self._match(TokenType.
|
|
1048
|
+
if self._match(TokenType.MULTIPLY):
|
|
1049
1049
|
non_null = True
|
|
1050
1050
|
|
|
1051
1051
|
# Get variable name
|
|
@@ -1378,12 +1378,56 @@ class CSSLParser:
|
|
|
1378
1378
|
"""
|
|
1379
1379
|
# Check for * prefix (non-null class - all methods return non-null)
|
|
1380
1380
|
non_null = False
|
|
1381
|
-
if self._match(TokenType.
|
|
1381
|
+
if self._match(TokenType.MULTIPLY):
|
|
1382
1382
|
non_null = True
|
|
1383
1383
|
|
|
1384
1384
|
class_name = self._advance().value
|
|
1385
1385
|
|
|
1386
|
-
|
|
1386
|
+
# Check for inheritance and overwrites:
|
|
1387
|
+
# class Child : extends Parent { ... }
|
|
1388
|
+
# class Child : extends $PythonObject { ... }
|
|
1389
|
+
# class Child : extends Parent : overwrites Parent { ... }
|
|
1390
|
+
extends_class = None
|
|
1391
|
+
extends_is_python = False
|
|
1392
|
+
overwrites_class = None
|
|
1393
|
+
overwrites_is_python = False
|
|
1394
|
+
|
|
1395
|
+
if self._match(TokenType.COLON):
|
|
1396
|
+
# Parse extends and/or overwrites (can be chained)
|
|
1397
|
+
while True:
|
|
1398
|
+
if self._match_keyword('extends'):
|
|
1399
|
+
if self._check(TokenType.IDENTIFIER):
|
|
1400
|
+
extends_class = self._advance().value
|
|
1401
|
+
elif self._check(TokenType.SHARED_REF):
|
|
1402
|
+
extends_class = self._advance().value
|
|
1403
|
+
extends_is_python = True
|
|
1404
|
+
else:
|
|
1405
|
+
raise CSSLSyntaxError("Expected parent class name after 'extends'")
|
|
1406
|
+
elif self._match_keyword('overwrites'):
|
|
1407
|
+
if self._check(TokenType.IDENTIFIER):
|
|
1408
|
+
overwrites_class = self._advance().value
|
|
1409
|
+
elif self._check(TokenType.SHARED_REF):
|
|
1410
|
+
overwrites_class = self._advance().value
|
|
1411
|
+
overwrites_is_python = True
|
|
1412
|
+
else:
|
|
1413
|
+
raise CSSLSyntaxError("Expected class name after 'overwrites'")
|
|
1414
|
+
# Skip optional () after class name
|
|
1415
|
+
if self._match(TokenType.PAREN_START):
|
|
1416
|
+
self._expect(TokenType.PAREN_END)
|
|
1417
|
+
else:
|
|
1418
|
+
raise CSSLSyntaxError("Expected 'extends' or 'overwrites' after ':' in class declaration")
|
|
1419
|
+
# Check for another : for chaining
|
|
1420
|
+
if not self._match(TokenType.COLON):
|
|
1421
|
+
break
|
|
1422
|
+
|
|
1423
|
+
node = ASTNode('class', value={
|
|
1424
|
+
'name': class_name,
|
|
1425
|
+
'non_null': non_null,
|
|
1426
|
+
'extends': extends_class,
|
|
1427
|
+
'extends_is_python': extends_is_python,
|
|
1428
|
+
'overwrites': overwrites_class,
|
|
1429
|
+
'overwrites_is_python': overwrites_is_python
|
|
1430
|
+
}, children=[])
|
|
1387
1431
|
self._expect(TokenType.BLOCK_START)
|
|
1388
1432
|
|
|
1389
1433
|
while not self._check(TokenType.BLOCK_END) and not self._is_at_end():
|
|
@@ -1424,13 +1468,53 @@ class CSSLParser:
|
|
|
1424
1468
|
Syntax:
|
|
1425
1469
|
define MyFunc(args) { }
|
|
1426
1470
|
define *MyFunc(args) { } // Non-null: must never return None
|
|
1471
|
+
define MyFunc : extends OtherFunc() { } // Inherit local vars
|
|
1472
|
+
define MyFunc : overwrites OtherFunc() { } // Replace OtherFunc
|
|
1427
1473
|
"""
|
|
1428
1474
|
# Check for * prefix (non-null function - must return non-null)
|
|
1429
1475
|
non_null = False
|
|
1430
|
-
if self._match(TokenType.
|
|
1476
|
+
if self._match(TokenType.MULTIPLY):
|
|
1431
1477
|
non_null = True
|
|
1432
1478
|
|
|
1433
1479
|
name = self._advance().value
|
|
1480
|
+
|
|
1481
|
+
# Check for extends/overwrites: define func : extends/overwrites target() { }
|
|
1482
|
+
extends_func = None
|
|
1483
|
+
overwrites_func = None
|
|
1484
|
+
extends_is_python = False
|
|
1485
|
+
overwrites_is_python = False
|
|
1486
|
+
|
|
1487
|
+
if self._match(TokenType.COLON):
|
|
1488
|
+
# Parse extends and/or overwrites
|
|
1489
|
+
while True:
|
|
1490
|
+
if self._match_keyword('extends'):
|
|
1491
|
+
if self._check(TokenType.IDENTIFIER):
|
|
1492
|
+
extends_func = self._advance().value
|
|
1493
|
+
elif self._check(TokenType.SHARED_REF):
|
|
1494
|
+
extends_func = self._advance().value
|
|
1495
|
+
extends_is_python = True
|
|
1496
|
+
else:
|
|
1497
|
+
raise CSSLSyntaxError("Expected function name after 'extends'")
|
|
1498
|
+
# Skip optional () after function name
|
|
1499
|
+
if self._match(TokenType.PAREN_START):
|
|
1500
|
+
self._expect(TokenType.PAREN_END)
|
|
1501
|
+
elif self._match_keyword('overwrites'):
|
|
1502
|
+
if self._check(TokenType.IDENTIFIER):
|
|
1503
|
+
overwrites_func = self._advance().value
|
|
1504
|
+
elif self._check(TokenType.SHARED_REF):
|
|
1505
|
+
overwrites_func = self._advance().value
|
|
1506
|
+
overwrites_is_python = True
|
|
1507
|
+
else:
|
|
1508
|
+
raise CSSLSyntaxError("Expected function name after 'overwrites'")
|
|
1509
|
+
# Skip optional () after function name
|
|
1510
|
+
if self._match(TokenType.PAREN_START):
|
|
1511
|
+
self._expect(TokenType.PAREN_END)
|
|
1512
|
+
else:
|
|
1513
|
+
break
|
|
1514
|
+
# Check for another : for chaining extends/overwrites
|
|
1515
|
+
if not self._match(TokenType.COLON):
|
|
1516
|
+
break
|
|
1517
|
+
|
|
1434
1518
|
params = []
|
|
1435
1519
|
|
|
1436
1520
|
if self._match(TokenType.PAREN_START):
|
|
@@ -1446,7 +1530,7 @@ class CSSLParser:
|
|
|
1446
1530
|
if self._match(TokenType.AMPERSAND):
|
|
1447
1531
|
param_info['ref'] = True
|
|
1448
1532
|
# Handle * prefix for non-null parameters
|
|
1449
|
-
if self._match(TokenType.
|
|
1533
|
+
if self._match(TokenType.MULTIPLY):
|
|
1450
1534
|
param_info['non_null'] = True
|
|
1451
1535
|
# Get parameter name
|
|
1452
1536
|
if self._check(TokenType.IDENTIFIER):
|
|
@@ -1468,7 +1552,15 @@ class CSSLParser:
|
|
|
1468
1552
|
break
|
|
1469
1553
|
self._expect(TokenType.PAREN_END)
|
|
1470
1554
|
|
|
1471
|
-
node = ASTNode('function', value={
|
|
1555
|
+
node = ASTNode('function', value={
|
|
1556
|
+
'name': name,
|
|
1557
|
+
'params': params,
|
|
1558
|
+
'non_null': non_null,
|
|
1559
|
+
'extends': extends_func,
|
|
1560
|
+
'extends_is_python': extends_is_python,
|
|
1561
|
+
'overwrites': overwrites_func,
|
|
1562
|
+
'overwrites_is_python': overwrites_is_python
|
|
1563
|
+
}, children=[])
|
|
1472
1564
|
self._expect(TokenType.BLOCK_START)
|
|
1473
1565
|
|
|
1474
1566
|
while not self._check(TokenType.BLOCK_END) and not self._is_at_end():
|
|
@@ -715,9 +715,43 @@ class CSSLRuntime:
|
|
|
715
715
|
|
|
716
716
|
Parses class members and methods, creating a CSSLClass object
|
|
717
717
|
that can be instantiated with 'new'.
|
|
718
|
+
Supports inheritance via 'extends' keyword and method overwriting via 'overwrites'.
|
|
718
719
|
"""
|
|
719
720
|
class_info = node.value
|
|
720
721
|
class_name = class_info.get('name')
|
|
722
|
+
extends_class_name = class_info.get('extends')
|
|
723
|
+
extends_is_python = class_info.get('extends_is_python', False)
|
|
724
|
+
overwrites_class_name = class_info.get('overwrites')
|
|
725
|
+
overwrites_is_python = class_info.get('overwrites_is_python', False)
|
|
726
|
+
|
|
727
|
+
# Resolve parent class if extends is specified
|
|
728
|
+
parent_class = None
|
|
729
|
+
if extends_class_name:
|
|
730
|
+
if extends_is_python:
|
|
731
|
+
# extends $PythonObject - look up in shared objects
|
|
732
|
+
from ..cssl_bridge import _live_objects, SharedObjectProxy
|
|
733
|
+
if extends_class_name in _live_objects:
|
|
734
|
+
parent_class = _live_objects[extends_class_name]
|
|
735
|
+
# Unwrap SharedObjectProxy if needed
|
|
736
|
+
if isinstance(parent_class, SharedObjectProxy):
|
|
737
|
+
parent_class = parent_class._obj
|
|
738
|
+
else:
|
|
739
|
+
# Also check scope with $ prefix
|
|
740
|
+
parent_class = self.global_scope.get(f'${extends_class_name}')
|
|
741
|
+
else:
|
|
742
|
+
# Try to resolve from scope (could be CSSL class or variable holding Python object)
|
|
743
|
+
parent_class = self.scope.get(extends_class_name)
|
|
744
|
+
if parent_class is None:
|
|
745
|
+
parent_class = self.global_scope.get(extends_class_name)
|
|
746
|
+
|
|
747
|
+
if parent_class is None:
|
|
748
|
+
raise ValueError(f"Cannot extend unknown class '{extends_class_name}'")
|
|
749
|
+
|
|
750
|
+
# Auto-wrap Python objects for inheritance
|
|
751
|
+
from .cssl_builtins import CSSLizedPythonObject
|
|
752
|
+
if not isinstance(parent_class, (CSSLClass, CSSLizedPythonObject)):
|
|
753
|
+
# Wrap raw Python object
|
|
754
|
+
parent_class = CSSLizedPythonObject(parent_class, self)
|
|
721
755
|
|
|
722
756
|
members = {} # Member variable defaults/types
|
|
723
757
|
methods = {} # Method AST nodes
|
|
@@ -752,22 +786,152 @@ class CSSLRuntime:
|
|
|
752
786
|
name=class_name,
|
|
753
787
|
members=members,
|
|
754
788
|
methods=methods,
|
|
755
|
-
constructor=constructor
|
|
789
|
+
constructor=constructor,
|
|
790
|
+
parent=parent_class
|
|
756
791
|
)
|
|
757
792
|
|
|
758
793
|
# Register class in scope
|
|
759
794
|
self.scope.set(class_name, class_def)
|
|
760
795
|
self.global_scope.set(class_name, class_def)
|
|
761
796
|
|
|
797
|
+
# Handle class overwrites - replace methods in target class
|
|
798
|
+
if overwrites_class_name:
|
|
799
|
+
self._apply_class_overwrites(
|
|
800
|
+
class_def, overwrites_class_name, overwrites_is_python
|
|
801
|
+
)
|
|
802
|
+
|
|
762
803
|
return class_def
|
|
763
804
|
|
|
805
|
+
def _apply_class_overwrites(self, new_class: CSSLClass, target_name: str, is_python: bool):
|
|
806
|
+
"""Apply method overwrites from new_class to target class/object.
|
|
807
|
+
|
|
808
|
+
When a class has 'overwrites' specified, all methods defined in new_class
|
|
809
|
+
will replace the corresponding methods in the target.
|
|
810
|
+
"""
|
|
811
|
+
from .cssl_builtins import CSSLizedPythonObject
|
|
812
|
+
|
|
813
|
+
# Resolve target
|
|
814
|
+
target = None
|
|
815
|
+
if is_python:
|
|
816
|
+
from ..cssl_bridge import _live_objects
|
|
817
|
+
if target_name in _live_objects:
|
|
818
|
+
target = _live_objects[target_name]
|
|
819
|
+
else:
|
|
820
|
+
target = self.scope.get(target_name)
|
|
821
|
+
if target is None:
|
|
822
|
+
target = self.global_scope.get(target_name)
|
|
823
|
+
|
|
824
|
+
if target is None:
|
|
825
|
+
return # Target not found, silently skip
|
|
826
|
+
|
|
827
|
+
# Get methods to overwrite
|
|
828
|
+
methods_to_overwrite = new_class.methods
|
|
829
|
+
|
|
830
|
+
if is_python and hasattr(target, '__class__'):
|
|
831
|
+
# Python object - overwrite methods on the object/class
|
|
832
|
+
for method_name, method_node in methods_to_overwrite.items():
|
|
833
|
+
# Create a Python-callable wrapper for the CSSL method
|
|
834
|
+
wrapper = self._create_method_wrapper(method_node, target)
|
|
835
|
+
# Set on the object
|
|
836
|
+
try:
|
|
837
|
+
setattr(target, method_name, wrapper)
|
|
838
|
+
except AttributeError:
|
|
839
|
+
# Try setting on class instead
|
|
840
|
+
try:
|
|
841
|
+
setattr(target.__class__, method_name, wrapper)
|
|
842
|
+
except:
|
|
843
|
+
pass
|
|
844
|
+
elif isinstance(target, CSSLClass):
|
|
845
|
+
# CSSL class - directly replace methods
|
|
846
|
+
for method_name, method_node in methods_to_overwrite.items():
|
|
847
|
+
target.methods[method_name] = method_node
|
|
848
|
+
elif isinstance(target, CSSLizedPythonObject):
|
|
849
|
+
# CSSLized Python object - get underlying object and overwrite
|
|
850
|
+
py_obj = target.get_python_obj()
|
|
851
|
+
for method_name, method_node in methods_to_overwrite.items():
|
|
852
|
+
wrapper = self._create_method_wrapper(method_node, py_obj)
|
|
853
|
+
try:
|
|
854
|
+
setattr(py_obj, method_name, wrapper)
|
|
855
|
+
except AttributeError:
|
|
856
|
+
try:
|
|
857
|
+
setattr(py_obj.__class__, method_name, wrapper)
|
|
858
|
+
except:
|
|
859
|
+
pass
|
|
860
|
+
|
|
861
|
+
def _create_method_wrapper(self, method_node: ASTNode, instance: Any):
|
|
862
|
+
"""Create a Python-callable wrapper for a CSSL method that works with an instance."""
|
|
863
|
+
def wrapper(*args, **kwargs):
|
|
864
|
+
# Set up instance context for this->
|
|
865
|
+
old_instance = self._current_instance
|
|
866
|
+
# Create a fake CSSLInstance-like wrapper if needed
|
|
867
|
+
self._current_instance = instance
|
|
868
|
+
try:
|
|
869
|
+
return self._call_function(method_node, list(args), kwargs)
|
|
870
|
+
finally:
|
|
871
|
+
self._current_instance = old_instance
|
|
872
|
+
return wrapper
|
|
873
|
+
|
|
764
874
|
def _exec_function(self, node: ASTNode) -> Any:
|
|
765
|
-
"""Execute function definition -
|
|
875
|
+
"""Execute function definition - registers it and handles extends/overwrites.
|
|
876
|
+
|
|
877
|
+
Syntax:
|
|
878
|
+
define func() { ... }
|
|
879
|
+
define func : extends otherFunc() { ... } - Inherit local vars
|
|
880
|
+
define func : overwrites otherFunc() { ... } - Replace otherFunc
|
|
881
|
+
"""
|
|
766
882
|
func_info = node.value
|
|
767
883
|
func_name = func_info.get('name')
|
|
884
|
+
extends_func = func_info.get('extends')
|
|
885
|
+
extends_is_python = func_info.get('extends_is_python', False)
|
|
886
|
+
overwrites_func = func_info.get('overwrites')
|
|
887
|
+
overwrites_is_python = func_info.get('overwrites_is_python', False)
|
|
888
|
+
|
|
889
|
+
# Store function extends info for runtime use
|
|
890
|
+
if extends_func:
|
|
891
|
+
node.value['_extends_resolved'] = self._resolve_function_target(
|
|
892
|
+
extends_func, extends_is_python
|
|
893
|
+
)
|
|
894
|
+
|
|
895
|
+
# Handle overwrites - replace the target function
|
|
896
|
+
if overwrites_func:
|
|
897
|
+
target = self._resolve_function_target(overwrites_func, overwrites_is_python)
|
|
898
|
+
if target is not None:
|
|
899
|
+
# Store original for reference
|
|
900
|
+
node.value['_overwrites_original'] = target
|
|
901
|
+
# Replace the target function with this one
|
|
902
|
+
if overwrites_is_python:
|
|
903
|
+
from ..cssl_bridge import _live_objects
|
|
904
|
+
if overwrites_func in _live_objects:
|
|
905
|
+
# Create a wrapper that calls the CSSL function
|
|
906
|
+
_live_objects[overwrites_func] = self._create_python_wrapper(node)
|
|
907
|
+
else:
|
|
908
|
+
# Replace in CSSL scope
|
|
909
|
+
self.scope.set(overwrites_func, node)
|
|
910
|
+
self.global_scope.set(overwrites_func, node)
|
|
911
|
+
|
|
912
|
+
# Register the function
|
|
768
913
|
self.scope.set(func_name, node)
|
|
769
914
|
return None
|
|
770
915
|
|
|
916
|
+
def _resolve_function_target(self, name: str, is_python: bool) -> Any:
|
|
917
|
+
"""Resolve a function target for extends/overwrites."""
|
|
918
|
+
if is_python:
|
|
919
|
+
from ..cssl_bridge import _live_objects
|
|
920
|
+
if name in _live_objects:
|
|
921
|
+
return _live_objects[name]
|
|
922
|
+
return self.global_scope.get(f'${name}')
|
|
923
|
+
else:
|
|
924
|
+
target = self.scope.get(name)
|
|
925
|
+
if target is None:
|
|
926
|
+
target = self.global_scope.get(name)
|
|
927
|
+
return target
|
|
928
|
+
|
|
929
|
+
def _create_python_wrapper(self, func_node: ASTNode):
|
|
930
|
+
"""Create a Python-callable wrapper for a CSSL function."""
|
|
931
|
+
def wrapper(*args, **kwargs):
|
|
932
|
+
return self._call_function(func_node, list(args), kwargs)
|
|
933
|
+
return wrapper
|
|
934
|
+
|
|
771
935
|
def _exec_typed_declaration(self, node: ASTNode) -> Any:
|
|
772
936
|
"""Execute typed variable declaration: type<T> varName = value;
|
|
773
937
|
|
|
@@ -1031,6 +1195,9 @@ class CSSLRuntime:
|
|
|
1031
1195
|
func_node: The function AST node
|
|
1032
1196
|
args: List of positional arguments
|
|
1033
1197
|
kwargs: Dict of named arguments (param_name -> value)
|
|
1198
|
+
|
|
1199
|
+
Supports:
|
|
1200
|
+
define func : extends otherFunc() { ... } - Inherit local vars from otherFunc
|
|
1034
1201
|
"""
|
|
1035
1202
|
func_info = func_node.value
|
|
1036
1203
|
params = func_info.get('params', [])
|
|
@@ -1043,6 +1210,34 @@ class CSSLRuntime:
|
|
|
1043
1210
|
# Create new scope
|
|
1044
1211
|
new_scope = Scope(parent=self.scope)
|
|
1045
1212
|
|
|
1213
|
+
# Handle function extends - inherit local vars from extended function
|
|
1214
|
+
extends_resolved = func_info.get('_extends_resolved')
|
|
1215
|
+
if extends_resolved:
|
|
1216
|
+
if callable(extends_resolved):
|
|
1217
|
+
# Python function - call it first to populate any state
|
|
1218
|
+
try:
|
|
1219
|
+
extends_resolved(*args, **kwargs)
|
|
1220
|
+
except:
|
|
1221
|
+
pass
|
|
1222
|
+
elif hasattr(extends_resolved, 'value'):
|
|
1223
|
+
# CSSL function - execute it in a temporary scope to get local vars
|
|
1224
|
+
old_scope = self.scope
|
|
1225
|
+
temp_scope = Scope(parent=self.scope)
|
|
1226
|
+
self.scope = temp_scope
|
|
1227
|
+
try:
|
|
1228
|
+
# Execute extended function body to populate local vars
|
|
1229
|
+
for child in extends_resolved.children:
|
|
1230
|
+
if not self._running:
|
|
1231
|
+
break
|
|
1232
|
+
self._execute(child)
|
|
1233
|
+
# Copy all local vars to new scope
|
|
1234
|
+
for name, value in temp_scope._vars.items():
|
|
1235
|
+
new_scope.set(name, value)
|
|
1236
|
+
except:
|
|
1237
|
+
pass
|
|
1238
|
+
finally:
|
|
1239
|
+
self.scope = old_scope
|
|
1240
|
+
|
|
1046
1241
|
# Bind parameters - handle both positional and named arguments
|
|
1047
1242
|
for i, param in enumerate(params):
|
|
1048
1243
|
# Extract param name and type from dict format: {'name': 'a', 'type': 'int'}
|
|
@@ -1054,7 +1249,9 @@ class CSSLRuntime:
|
|
|
1054
1249
|
param_type = ''
|
|
1055
1250
|
|
|
1056
1251
|
# Check if this is an 'open' parameter - receives all args as a list
|
|
1057
|
-
|
|
1252
|
+
# The parser sets param['open'] = True for 'open' keyword
|
|
1253
|
+
is_open_param = (isinstance(param, dict) and param.get('open', False)) or param_name == 'Params'
|
|
1254
|
+
if is_open_param:
|
|
1058
1255
|
# 'open Params' receives all arguments as a list
|
|
1059
1256
|
# Check for non_null flag: open *Params filters out None values
|
|
1060
1257
|
is_non_null = isinstance(param, dict) and param.get('non_null', False)
|
|
@@ -2955,6 +3152,10 @@ class CSSLRuntime:
|
|
|
2955
3152
|
if instance.has_method(member):
|
|
2956
3153
|
# Return a callable that will invoke the method with instance context
|
|
2957
3154
|
method_node = instance.get_method(member)
|
|
3155
|
+
# Check if this is an inherited Python method
|
|
3156
|
+
if isinstance(method_node, tuple) and method_node[0] == 'python_method':
|
|
3157
|
+
python_method = method_node[1]
|
|
3158
|
+
return lambda *args, **kwargs: python_method(*args, **kwargs)
|
|
2958
3159
|
return lambda *args, **kwargs: self._call_method(instance, method_node, list(args), kwargs)
|
|
2959
3160
|
|
|
2960
3161
|
raise CSSLRuntimeError(
|
|
@@ -3036,6 +3237,10 @@ class CSSLRuntime:
|
|
|
3036
3237
|
# Check for method
|
|
3037
3238
|
if obj.has_method(member):
|
|
3038
3239
|
method_node = obj.get_method(member)
|
|
3240
|
+
# Check if this is an inherited Python method
|
|
3241
|
+
if isinstance(method_node, tuple) and method_node[0] == 'python_method':
|
|
3242
|
+
python_method = method_node[1]
|
|
3243
|
+
return lambda *args, **kwargs: python_method(*args, **kwargs)
|
|
3039
3244
|
return lambda *args, **kwargs: self._call_method(obj, method_node, list(args), kwargs)
|
|
3040
3245
|
raise CSSLRuntimeError(f"'{obj._class.name}' has no member or method '{member}'")
|
|
3041
3246
|
|
|
@@ -1448,17 +1448,62 @@ class CSSLClass:
|
|
|
1448
1448
|
|
|
1449
1449
|
Stores class name, member variables, methods, and constructor.
|
|
1450
1450
|
Used by the runtime to instantiate CSSLInstance objects.
|
|
1451
|
+
Supports inheritance via the 'parent' attribute.
|
|
1451
1452
|
"""
|
|
1452
1453
|
|
|
1453
1454
|
def __init__(self, name: str, members: Dict[str, Any] = None,
|
|
1454
|
-
methods: Dict[str, Any] = None, constructor: Any = None
|
|
1455
|
+
methods: Dict[str, Any] = None, constructor: Any = None,
|
|
1456
|
+
parent: Any = None):
|
|
1455
1457
|
self.name = name
|
|
1456
1458
|
self.members = members or {} # Default member values/types
|
|
1457
1459
|
self.methods = methods or {} # Method AST nodes
|
|
1458
1460
|
self.constructor = constructor # Constructor AST node
|
|
1461
|
+
self.parent = parent # Parent class (CSSLClass or CSSLizedPythonObject)
|
|
1462
|
+
|
|
1463
|
+
def get_all_members(self) -> Dict[str, Any]:
|
|
1464
|
+
"""Get all members including inherited ones."""
|
|
1465
|
+
all_members = {}
|
|
1466
|
+
# First add parent members (can be overridden)
|
|
1467
|
+
if self.parent:
|
|
1468
|
+
if hasattr(self.parent, 'get_all_members'):
|
|
1469
|
+
all_members.update(self.parent.get_all_members())
|
|
1470
|
+
elif hasattr(self.parent, 'members'):
|
|
1471
|
+
all_members.update(self.parent.members)
|
|
1472
|
+
elif hasattr(self.parent, '_python_obj'):
|
|
1473
|
+
# CSSLizedPythonObject - get attributes from Python object
|
|
1474
|
+
py_obj = self.parent._python_obj
|
|
1475
|
+
if hasattr(py_obj, '__dict__'):
|
|
1476
|
+
for key, val in py_obj.__dict__.items():
|
|
1477
|
+
if not key.startswith('_'):
|
|
1478
|
+
all_members[key] = {'type': 'dynamic', 'default': val}
|
|
1479
|
+
# Then add own members (override parent)
|
|
1480
|
+
all_members.update(self.members)
|
|
1481
|
+
return all_members
|
|
1482
|
+
|
|
1483
|
+
def get_all_methods(self) -> Dict[str, Any]:
|
|
1484
|
+
"""Get all methods including inherited ones."""
|
|
1485
|
+
all_methods = {}
|
|
1486
|
+
# First add parent methods (can be overridden)
|
|
1487
|
+
if self.parent:
|
|
1488
|
+
if hasattr(self.parent, 'get_all_methods'):
|
|
1489
|
+
all_methods.update(self.parent.get_all_methods())
|
|
1490
|
+
elif hasattr(self.parent, 'methods'):
|
|
1491
|
+
all_methods.update(self.parent.methods)
|
|
1492
|
+
elif hasattr(self.parent, '_python_obj'):
|
|
1493
|
+
# CSSLizedPythonObject - get methods from Python object
|
|
1494
|
+
py_obj = self.parent._python_obj
|
|
1495
|
+
for name in dir(py_obj):
|
|
1496
|
+
if not name.startswith('_'):
|
|
1497
|
+
attr = getattr(py_obj, name, None)
|
|
1498
|
+
if callable(attr):
|
|
1499
|
+
all_methods[name] = ('python_method', attr)
|
|
1500
|
+
# Then add own methods (override parent)
|
|
1501
|
+
all_methods.update(self.methods)
|
|
1502
|
+
return all_methods
|
|
1459
1503
|
|
|
1460
1504
|
def __repr__(self):
|
|
1461
|
-
|
|
1505
|
+
parent_info = f" extends {self.parent.name}" if self.parent and hasattr(self.parent, 'name') else ""
|
|
1506
|
+
return f"<CSSLClass '{self.name}'{parent_info} with {len(self.methods)} methods>"
|
|
1462
1507
|
|
|
1463
1508
|
|
|
1464
1509
|
class CSSLInstance:
|
|
@@ -1471,8 +1516,9 @@ class CSSLInstance:
|
|
|
1471
1516
|
def __init__(self, class_def: CSSLClass):
|
|
1472
1517
|
self._class = class_def
|
|
1473
1518
|
self._members: Dict[str, Any] = {}
|
|
1474
|
-
# Initialize members with defaults from class definition
|
|
1475
|
-
|
|
1519
|
+
# Initialize members with defaults from class definition (including inherited)
|
|
1520
|
+
all_members = class_def.get_all_members() if hasattr(class_def, 'get_all_members') else class_def.members
|
|
1521
|
+
for name, default in all_members.items():
|
|
1476
1522
|
if isinstance(default, dict):
|
|
1477
1523
|
# Type declaration with optional default
|
|
1478
1524
|
member_type = default.get('type')
|
|
@@ -1541,14 +1587,17 @@ class CSSLInstance:
|
|
|
1541
1587
|
return name in self._members
|
|
1542
1588
|
|
|
1543
1589
|
def get_method(self, name: str) -> Any:
|
|
1544
|
-
"""Get method AST node by name"""
|
|
1545
|
-
|
|
1546
|
-
|
|
1590
|
+
"""Get method AST node by name (including inherited methods)"""
|
|
1591
|
+
# Use get_all_methods to include inherited methods
|
|
1592
|
+
all_methods = self._class.get_all_methods() if hasattr(self._class, 'get_all_methods') else self._class.methods
|
|
1593
|
+
if name in all_methods:
|
|
1594
|
+
return all_methods[name]
|
|
1547
1595
|
raise AttributeError(f"'{self._class.name}' has no method '{name}'")
|
|
1548
1596
|
|
|
1549
1597
|
def has_method(self, name: str) -> bool:
|
|
1550
|
-
"""Check if method exists"""
|
|
1551
|
-
|
|
1598
|
+
"""Check if method exists (including inherited methods)"""
|
|
1599
|
+
all_methods = self._class.get_all_methods() if hasattr(self._class, 'get_all_methods') else self._class.methods
|
|
1600
|
+
return name in all_methods
|
|
1552
1601
|
|
|
1553
1602
|
def __getattr__(self, name: str) -> Any:
|
|
1554
1603
|
"""Allow direct attribute access for members"""
|
|
@@ -164,6 +164,35 @@
|
|
|
164
164
|
},
|
|
165
165
|
"class-definition": {
|
|
166
166
|
"patterns": [
|
|
167
|
+
{
|
|
168
|
+
"comment": "Class with inheritance: class Child : extends Parent { }",
|
|
169
|
+
"name": "meta.class.extends.cssl",
|
|
170
|
+
"begin": "\\b(class)\\s+([a-zA-Z_][a-zA-Z0-9_]*)\\s*:\\s*(extends)\\s+(\\$?[a-zA-Z_][a-zA-Z0-9_]*)\\s*\\{",
|
|
171
|
+
"beginCaptures": {
|
|
172
|
+
"1": { "name": "storage.type.class.cssl" },
|
|
173
|
+
"2": { "name": "entity.name.class.cssl" },
|
|
174
|
+
"3": { "name": "storage.modifier.extends.cssl" },
|
|
175
|
+
"4": { "name": "entity.other.inherited-class.cssl" }
|
|
176
|
+
},
|
|
177
|
+
"end": "\\}",
|
|
178
|
+
"patterns": [
|
|
179
|
+
{ "include": "#comments" },
|
|
180
|
+
{ "include": "#constructor-definition" },
|
|
181
|
+
{ "include": "#class-method-definition" },
|
|
182
|
+
{ "include": "#class-member-declaration" },
|
|
183
|
+
{ "include": "#types" },
|
|
184
|
+
{ "include": "#this-access" },
|
|
185
|
+
{ "include": "#captured-references" },
|
|
186
|
+
{ "include": "#global-references" },
|
|
187
|
+
{ "include": "#shared-references" },
|
|
188
|
+
{ "include": "#strings" },
|
|
189
|
+
{ "include": "#numbers" },
|
|
190
|
+
{ "include": "#keywords" },
|
|
191
|
+
{ "include": "#function-calls" },
|
|
192
|
+
{ "include": "#builtins" },
|
|
193
|
+
{ "include": "#operators" }
|
|
194
|
+
]
|
|
195
|
+
},
|
|
167
196
|
{
|
|
168
197
|
"name": "meta.class.cssl",
|
|
169
198
|
"begin": "\\b(class)\\s+([a-zA-Z_][a-zA-Z0-9_]*)\\s*\\{",
|
|
@@ -263,6 +292,10 @@
|
|
|
263
292
|
"name": "storage.type.class.cssl",
|
|
264
293
|
"match": "\\b(class|struct|structure|enum|interface)\\b"
|
|
265
294
|
},
|
|
295
|
+
{
|
|
296
|
+
"name": "storage.modifier.extends.cssl",
|
|
297
|
+
"match": "\\b(extends|overwrites)\\b"
|
|
298
|
+
},
|
|
266
299
|
{
|
|
267
300
|
"name": "keyword.operator.new.cssl",
|
|
268
301
|
"match": "\\bnew\\b"
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "IncludeCPP"
|
|
7
|
-
version = "3.8.
|
|
7
|
+
version = "3.8.4"
|
|
8
8
|
description = "Professional C++ Python bindings with type-generic templates, pystubs and native threading"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|