IncludeCPP 3.7.9__py3-none-any.whl → 3.8.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- includecpp/__init__.py +1 -1
- includecpp/__init__.pyi +2 -2
- includecpp/cli/commands.py +129 -67
- includecpp/core/cssl/__init__.py +7 -2
- includecpp/core/cssl/cssl_builtins.py +411 -9
- includecpp/core/cssl/cssl_builtins.pyi +3682 -401
- includecpp/core/cssl/cssl_parser.py +130 -31
- includecpp/core/cssl/cssl_runtime.py +462 -26
- includecpp/core/cssl/cssl_syntax.py +7 -7
- includecpp/core/cssl/cssl_types.py +75 -2
- includecpp/core/cssl_bridge.py +64 -6
- includecpp/vscode/cssl/extension.js +133 -0
- includecpp/vscode/cssl/images/cssl.png +0 -0
- includecpp/vscode/cssl/images/cssl_pl.png +0 -0
- includecpp/vscode/cssl/package.json +117 -11
- includecpp/vscode/cssl/snippets/cssl.snippets.json +126 -0
- includecpp/vscode/cssl/syntaxes/cssl.tmLanguage.json +46 -15
- {includecpp-3.7.9.dist-info → includecpp-3.8.0.dist-info}/METADATA +56 -225
- {includecpp-3.7.9.dist-info → includecpp-3.8.0.dist-info}/RECORD +23 -20
- {includecpp-3.7.9.dist-info → includecpp-3.8.0.dist-info}/WHEEL +0 -0
- {includecpp-3.7.9.dist-info → includecpp-3.8.0.dist-info}/entry_points.txt +0 -0
- {includecpp-3.7.9.dist-info → includecpp-3.8.0.dist-info}/licenses/LICENSE +0 -0
- {includecpp-3.7.9.dist-info → includecpp-3.8.0.dist-info}/top_level.txt +0 -0
|
@@ -19,6 +19,45 @@ from .cssl_types import (
|
|
|
19
19
|
)
|
|
20
20
|
|
|
21
21
|
|
|
22
|
+
# Global custom filter registry
|
|
23
|
+
# Structure: { "type::helper": callback_function }
|
|
24
|
+
# Callback signature: (source, filter_value, runtime) -> Any
|
|
25
|
+
_custom_filters: Dict[str, Callable[[Any, Any, Any], Any]] = {}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def register_filter(filter_type: str, helper: str, callback: Callable[[Any, Any, Any], Any]) -> None:
|
|
29
|
+
"""Register a custom filter.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
filter_type: The filter type (e.g., "mytype")
|
|
33
|
+
helper: The helper name (e.g., "where", "index", or "*" for catch-all)
|
|
34
|
+
callback: Function(source, filter_value, runtime) -> filtered_result
|
|
35
|
+
|
|
36
|
+
Usage in CSSL:
|
|
37
|
+
result <==[mytype::where="value"] source;
|
|
38
|
+
|
|
39
|
+
Usage from Python:
|
|
40
|
+
from includecpp.core.cssl.cssl_runtime import register_filter
|
|
41
|
+
register_filter("mytype", "where", lambda src, val, rt: ...)
|
|
42
|
+
"""
|
|
43
|
+
key = f"{filter_type}::{helper}"
|
|
44
|
+
_custom_filters[key] = callback
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def unregister_filter(filter_type: str, helper: str) -> bool:
|
|
48
|
+
"""Unregister a custom filter."""
|
|
49
|
+
key = f"{filter_type}::{helper}"
|
|
50
|
+
if key in _custom_filters:
|
|
51
|
+
del _custom_filters[key]
|
|
52
|
+
return True
|
|
53
|
+
return False
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def get_custom_filters() -> Dict[str, Callable]:
|
|
57
|
+
"""Get all registered custom filters."""
|
|
58
|
+
return _custom_filters.copy()
|
|
59
|
+
|
|
60
|
+
|
|
22
61
|
class CSSLRuntimeError(Exception):
|
|
23
62
|
"""Runtime error during CSSL execution with detailed context"""
|
|
24
63
|
def __init__(self, message: str, line: int = 0, context: str = None, hint: str = None):
|
|
@@ -791,8 +830,18 @@ class CSSLRuntime:
|
|
|
791
830
|
if hasattr(instance, 'append'):
|
|
792
831
|
instance.append(init_value)
|
|
793
832
|
|
|
833
|
+
# Check for global modifier
|
|
834
|
+
modifiers = decl.get('modifiers', [])
|
|
835
|
+
is_global = 'global' in modifiers
|
|
836
|
+
|
|
794
837
|
# Store in scope
|
|
795
838
|
self.scope.set(var_name, instance)
|
|
839
|
+
|
|
840
|
+
# If global, also store in promoted_globals and global_scope
|
|
841
|
+
if is_global:
|
|
842
|
+
self._promoted_globals[var_name] = instance
|
|
843
|
+
self.global_scope.set(var_name, instance)
|
|
844
|
+
|
|
796
845
|
return instance
|
|
797
846
|
|
|
798
847
|
def _exec_instance_declaration(self, node: ASTNode) -> Any:
|
|
@@ -939,6 +988,14 @@ class CSSLRuntime:
|
|
|
939
988
|
result = self._evaluate(inner.value)
|
|
940
989
|
return result
|
|
941
990
|
|
|
991
|
+
# Handle typed declaration: global datastruct<int> data;
|
|
992
|
+
elif inner.type == 'typed_declaration':
|
|
993
|
+
# Add global modifier to the declaration
|
|
994
|
+
if isinstance(inner.value, dict):
|
|
995
|
+
inner.value['modifiers'] = inner.value.get('modifiers', []) + ['global']
|
|
996
|
+
result = self._exec_typed_declaration(inner)
|
|
997
|
+
return result
|
|
998
|
+
|
|
942
999
|
# Fallback: execute normally
|
|
943
1000
|
return self._execute_node(inner)
|
|
944
1001
|
|
|
@@ -1274,8 +1331,11 @@ class CSSLRuntime:
|
|
|
1274
1331
|
|
|
1275
1332
|
return command_name
|
|
1276
1333
|
|
|
1277
|
-
def _apply_injection_filter(self, source: Any, filter_info
|
|
1278
|
-
"""Apply injection filter to extract specific data from source.
|
|
1334
|
+
def _apply_injection_filter(self, source: Any, filter_info) -> Any:
|
|
1335
|
+
"""Apply injection filter(s) to extract specific data from source.
|
|
1336
|
+
|
|
1337
|
+
Supports both single filter dict and list of filter dicts for chained filters.
|
|
1338
|
+
Example: [dynamic::content=10][dynamic::content=100] applies both filters.
|
|
1279
1339
|
|
|
1280
1340
|
All BruteInjector Helpers:
|
|
1281
1341
|
- string::where=VALUE - Filter strings containing VALUE
|
|
@@ -1292,10 +1352,31 @@ class CSSLRuntime:
|
|
|
1292
1352
|
- combo::blocked - Get blocked items from combo
|
|
1293
1353
|
- dynamic::VarName=VALUE - Filter by dynamic variable value
|
|
1294
1354
|
- sql::data - Return only SQL-compatible data
|
|
1355
|
+
- instance::class - Get classes from object
|
|
1356
|
+
- instance::method - Get methods from object
|
|
1357
|
+
- instance::var - Get variables from object
|
|
1358
|
+
- instance::all - Get all categorized (methods, classes, vars)
|
|
1359
|
+
- instance::"ClassName" - Get specific class by name
|
|
1360
|
+
- name::"Name" - Filter by name (class, dict key, attribute)
|
|
1295
1361
|
"""
|
|
1296
1362
|
if not filter_info:
|
|
1297
1363
|
return source
|
|
1298
1364
|
|
|
1365
|
+
# Handle list of filters (chained filters)
|
|
1366
|
+
if isinstance(filter_info, list):
|
|
1367
|
+
result = source
|
|
1368
|
+
for single_filter in filter_info:
|
|
1369
|
+
result = self._apply_single_filter(result, single_filter)
|
|
1370
|
+
return result
|
|
1371
|
+
|
|
1372
|
+
# Single filter (dict)
|
|
1373
|
+
return self._apply_single_filter(source, filter_info)
|
|
1374
|
+
|
|
1375
|
+
def _apply_single_filter(self, source: Any, filter_info: dict) -> Any:
|
|
1376
|
+
"""Apply a single injection filter to extract specific data from source."""
|
|
1377
|
+
if not filter_info:
|
|
1378
|
+
return source
|
|
1379
|
+
|
|
1299
1380
|
result = source
|
|
1300
1381
|
|
|
1301
1382
|
for filter_key, filter_value in filter_info.items():
|
|
@@ -1303,6 +1384,18 @@ class CSSLRuntime:
|
|
|
1303
1384
|
filter_type, helper = filter_key.split('::', 1)
|
|
1304
1385
|
filter_val = self._evaluate(filter_value) if isinstance(filter_value, ASTNode) else filter_value
|
|
1305
1386
|
|
|
1387
|
+
# === CHECK CUSTOM FILTERS FIRST ===
|
|
1388
|
+
custom_key = f"{filter_type}::{helper}"
|
|
1389
|
+
if custom_key in _custom_filters:
|
|
1390
|
+
result = _custom_filters[custom_key](result, filter_val, self)
|
|
1391
|
+
continue
|
|
1392
|
+
|
|
1393
|
+
# Check for catch-all custom filter (type::*)
|
|
1394
|
+
catchall_key = f"{filter_type}::*"
|
|
1395
|
+
if catchall_key in _custom_filters:
|
|
1396
|
+
result = _custom_filters[catchall_key](result, filter_val, self)
|
|
1397
|
+
continue
|
|
1398
|
+
|
|
1306
1399
|
# === STRING HELPERS ===
|
|
1307
1400
|
if filter_type == 'string':
|
|
1308
1401
|
if helper == 'where':
|
|
@@ -1479,13 +1572,112 @@ class CSSLRuntime:
|
|
|
1479
1572
|
|
|
1480
1573
|
# === DYNAMIC HELPERS ===
|
|
1481
1574
|
elif filter_type == 'dynamic':
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1575
|
+
if helper == 'content':
|
|
1576
|
+
# dynamic::content=VALUE - General content filter for any type
|
|
1577
|
+
# Filters elements where content equals VALUE
|
|
1578
|
+
if isinstance(result, (list, tuple)):
|
|
1579
|
+
# Filter list/tuple elements by content value
|
|
1580
|
+
result = [item for item in result if item == filter_val]
|
|
1581
|
+
elif isinstance(result, dict):
|
|
1582
|
+
# Filter dict by values matching filter_val
|
|
1583
|
+
result = {k: v for k, v in result.items() if v == filter_val}
|
|
1584
|
+
elif result == filter_val:
|
|
1585
|
+
pass # Keep result if it matches
|
|
1586
|
+
else:
|
|
1587
|
+
result = None
|
|
1588
|
+
elif helper == 'not':
|
|
1589
|
+
# dynamic::not=VALUE - Exclude elements equal to VALUE
|
|
1590
|
+
if isinstance(result, (list, tuple)):
|
|
1591
|
+
result = [item for item in result if item != filter_val]
|
|
1592
|
+
elif isinstance(result, dict):
|
|
1593
|
+
result = {k: v for k, v in result.items() if v != filter_val}
|
|
1594
|
+
elif result != filter_val:
|
|
1595
|
+
pass # Keep result if it doesn't match
|
|
1596
|
+
else:
|
|
1597
|
+
result = None
|
|
1598
|
+
elif helper == 'gt':
|
|
1599
|
+
# dynamic::gt=VALUE - Greater than
|
|
1600
|
+
if isinstance(result, (list, tuple)):
|
|
1601
|
+
result = [item for item in result if item > filter_val]
|
|
1602
|
+
elif result > filter_val:
|
|
1603
|
+
pass
|
|
1604
|
+
else:
|
|
1605
|
+
result = None
|
|
1606
|
+
elif helper == 'lt':
|
|
1607
|
+
# dynamic::lt=VALUE - Less than
|
|
1608
|
+
if isinstance(result, (list, tuple)):
|
|
1609
|
+
result = [item for item in result if item < filter_val]
|
|
1610
|
+
elif result < filter_val:
|
|
1611
|
+
pass
|
|
1612
|
+
else:
|
|
1613
|
+
result = None
|
|
1614
|
+
elif helper == 'gte':
|
|
1615
|
+
# dynamic::gte=VALUE - Greater than or equal
|
|
1616
|
+
if isinstance(result, (list, tuple)):
|
|
1617
|
+
result = [item for item in result if item >= filter_val]
|
|
1618
|
+
elif result >= filter_val:
|
|
1619
|
+
pass
|
|
1620
|
+
else:
|
|
1621
|
+
result = None
|
|
1622
|
+
elif helper == 'lte':
|
|
1623
|
+
# dynamic::lte=VALUE - Less than or equal
|
|
1624
|
+
if isinstance(result, (list, tuple)):
|
|
1625
|
+
result = [item for item in result if item <= filter_val]
|
|
1626
|
+
elif result <= filter_val:
|
|
1627
|
+
pass
|
|
1628
|
+
else:
|
|
1629
|
+
result = None
|
|
1630
|
+
elif helper == 'mod':
|
|
1631
|
+
# dynamic::mod=VALUE - Modulo filter (item % VALUE == 0)
|
|
1632
|
+
if isinstance(result, (list, tuple)):
|
|
1633
|
+
result = [item for item in result if isinstance(item, (int, float)) and item % filter_val == 0]
|
|
1634
|
+
elif isinstance(result, (int, float)) and result % filter_val == 0:
|
|
1635
|
+
pass
|
|
1636
|
+
else:
|
|
1637
|
+
result = None
|
|
1638
|
+
elif helper == 'range':
|
|
1639
|
+
# dynamic::range="min:max" - Filter values in range
|
|
1640
|
+
if isinstance(filter_val, str) and ':' in filter_val:
|
|
1641
|
+
parts = filter_val.split(':')
|
|
1642
|
+
min_val = int(parts[0]) if parts[0] else None
|
|
1643
|
+
max_val = int(parts[1]) if parts[1] else None
|
|
1644
|
+
if isinstance(result, (list, tuple)):
|
|
1645
|
+
def in_range(x):
|
|
1646
|
+
if min_val is not None and x < min_val:
|
|
1647
|
+
return False
|
|
1648
|
+
if max_val is not None and x > max_val:
|
|
1649
|
+
return False
|
|
1650
|
+
return True
|
|
1651
|
+
result = [item for item in result if in_range(item)]
|
|
1652
|
+
elif isinstance(result, (int, float)):
|
|
1653
|
+
if min_val is not None and result < min_val:
|
|
1654
|
+
result = None
|
|
1655
|
+
elif max_val is not None and result > max_val:
|
|
1656
|
+
result = None
|
|
1657
|
+
elif helper == 'even':
|
|
1658
|
+
# dynamic::even - Filter even numbers
|
|
1659
|
+
if isinstance(result, (list, tuple)):
|
|
1660
|
+
result = [item for item in result if isinstance(item, int) and item % 2 == 0]
|
|
1661
|
+
elif isinstance(result, int) and result % 2 == 0:
|
|
1662
|
+
pass
|
|
1663
|
+
else:
|
|
1664
|
+
result = None
|
|
1665
|
+
elif helper == 'odd':
|
|
1666
|
+
# dynamic::odd - Filter odd numbers
|
|
1667
|
+
if isinstance(result, (list, tuple)):
|
|
1668
|
+
result = [item for item in result if isinstance(item, int) and item % 2 != 0]
|
|
1669
|
+
elif isinstance(result, int) and result % 2 != 0:
|
|
1670
|
+
pass
|
|
1671
|
+
else:
|
|
1672
|
+
result = None
|
|
1487
1673
|
else:
|
|
1488
|
-
|
|
1674
|
+
# dynamic::VarName=VALUE - Match if variable equals value
|
|
1675
|
+
var_name = helper
|
|
1676
|
+
var_value = self.scope.get(var_name)
|
|
1677
|
+
if var_value == filter_val:
|
|
1678
|
+
pass # Keep result
|
|
1679
|
+
else:
|
|
1680
|
+
result = None
|
|
1489
1681
|
|
|
1490
1682
|
# === SQL HELPERS ===
|
|
1491
1683
|
elif filter_type == 'sql':
|
|
@@ -1496,6 +1688,128 @@ class CSSLRuntime:
|
|
|
1496
1688
|
else:
|
|
1497
1689
|
result = str(result) # Convert to string
|
|
1498
1690
|
|
|
1691
|
+
# === INSTANCE HELPERS ===
|
|
1692
|
+
# Works on CSSLInstance, Python objects, dicts, modules
|
|
1693
|
+
elif filter_type == 'instance':
|
|
1694
|
+
from .cssl_types import CSSLInstance
|
|
1695
|
+
import inspect
|
|
1696
|
+
|
|
1697
|
+
if isinstance(result, CSSLInstance):
|
|
1698
|
+
# Filter CSSL instances
|
|
1699
|
+
if helper in ('class', 'classes'):
|
|
1700
|
+
classes = {}
|
|
1701
|
+
for name, member in result._members.items():
|
|
1702
|
+
if isinstance(member, CSSLInstance):
|
|
1703
|
+
classes[name] = member
|
|
1704
|
+
result = classes if classes else None
|
|
1705
|
+
elif helper in ('method', 'methods'):
|
|
1706
|
+
result = dict(result._class.methods)
|
|
1707
|
+
elif helper in ('var', 'vars', 'variable', 'variables'):
|
|
1708
|
+
vars_dict = {}
|
|
1709
|
+
for name, member in result._members.items():
|
|
1710
|
+
if not isinstance(member, CSSLInstance):
|
|
1711
|
+
vars_dict[name] = member
|
|
1712
|
+
result = vars_dict
|
|
1713
|
+
elif helper in ('all',):
|
|
1714
|
+
result = {
|
|
1715
|
+
'methods': list(result._class.methods.keys()),
|
|
1716
|
+
'classes': [result._class.name] + [m._class.name for m in result._members.values() if isinstance(m, CSSLInstance)],
|
|
1717
|
+
'vars': [n for n, m in result._members.items() if not isinstance(m, CSSLInstance)]
|
|
1718
|
+
}
|
|
1719
|
+
else:
|
|
1720
|
+
# Filter by class name
|
|
1721
|
+
class_name = filter_val if filter_val else helper
|
|
1722
|
+
found = None
|
|
1723
|
+
if result._class.name == class_name:
|
|
1724
|
+
found = result
|
|
1725
|
+
else:
|
|
1726
|
+
for name, member in result._members.items():
|
|
1727
|
+
if isinstance(member, CSSLInstance) and member._class.name == class_name:
|
|
1728
|
+
found = member
|
|
1729
|
+
break
|
|
1730
|
+
result = found
|
|
1731
|
+
elif isinstance(result, dict):
|
|
1732
|
+
# Filter dicts
|
|
1733
|
+
if helper in ('class', 'classes'):
|
|
1734
|
+
result = {k: v for k, v in result.items() if inspect.isclass(v)}
|
|
1735
|
+
elif helper in ('method', 'methods', 'func', 'function', 'functions'):
|
|
1736
|
+
result = {k: v for k, v in result.items() if callable(v)}
|
|
1737
|
+
elif helper in ('var', 'vars', 'variable', 'variables'):
|
|
1738
|
+
result = {k: v for k, v in result.items() if not callable(v) and not inspect.isclass(v)}
|
|
1739
|
+
else:
|
|
1740
|
+
# Get by key
|
|
1741
|
+
key_name = filter_val if filter_val else helper
|
|
1742
|
+
result = result.get(key_name)
|
|
1743
|
+
elif hasattr(result, '__dict__') or hasattr(result, '__class__'):
|
|
1744
|
+
# Filter Python objects/modules
|
|
1745
|
+
if helper in ('class', 'classes'):
|
|
1746
|
+
classes = {}
|
|
1747
|
+
for name in dir(result):
|
|
1748
|
+
if not name.startswith('_'):
|
|
1749
|
+
attr = getattr(result, name, None)
|
|
1750
|
+
if inspect.isclass(attr):
|
|
1751
|
+
classes[name] = attr
|
|
1752
|
+
result = classes if classes else None
|
|
1753
|
+
elif helper in ('method', 'methods', 'func', 'function', 'functions'):
|
|
1754
|
+
methods = {}
|
|
1755
|
+
for name in dir(result):
|
|
1756
|
+
if not name.startswith('_'):
|
|
1757
|
+
attr = getattr(result, name, None)
|
|
1758
|
+
if callable(attr):
|
|
1759
|
+
methods[name] = attr
|
|
1760
|
+
result = methods if methods else None
|
|
1761
|
+
elif helper in ('var', 'vars', 'variable', 'variables'):
|
|
1762
|
+
vars_dict = {}
|
|
1763
|
+
for name in dir(result):
|
|
1764
|
+
if not name.startswith('_'):
|
|
1765
|
+
attr = getattr(result, name, None)
|
|
1766
|
+
if not callable(attr) and not inspect.isclass(attr):
|
|
1767
|
+
vars_dict[name] = attr
|
|
1768
|
+
result = vars_dict if vars_dict else None
|
|
1769
|
+
elif helper in ('all',):
|
|
1770
|
+
all_info = {'methods': [], 'classes': [], 'vars': []}
|
|
1771
|
+
for name in dir(result):
|
|
1772
|
+
if not name.startswith('_'):
|
|
1773
|
+
attr = getattr(result, name, None)
|
|
1774
|
+
if inspect.isclass(attr):
|
|
1775
|
+
all_info['classes'].append(name)
|
|
1776
|
+
elif callable(attr):
|
|
1777
|
+
all_info['methods'].append(name)
|
|
1778
|
+
else:
|
|
1779
|
+
all_info['vars'].append(name)
|
|
1780
|
+
result = all_info
|
|
1781
|
+
else:
|
|
1782
|
+
# Get attribute by name
|
|
1783
|
+
attr_name = filter_val if filter_val else helper
|
|
1784
|
+
result = getattr(result, attr_name, None)
|
|
1785
|
+
|
|
1786
|
+
# === NAME HELPERS ===
|
|
1787
|
+
# General name filter for any object type
|
|
1788
|
+
elif filter_type == 'name':
|
|
1789
|
+
from .cssl_types import CSSLInstance
|
|
1790
|
+
target_name = filter_val if filter_val else helper
|
|
1791
|
+
|
|
1792
|
+
if isinstance(result, CSSLInstance):
|
|
1793
|
+
if result._class.name == target_name:
|
|
1794
|
+
pass # Keep result
|
|
1795
|
+
else:
|
|
1796
|
+
found = None
|
|
1797
|
+
for name, member in result._members.items():
|
|
1798
|
+
if isinstance(member, CSSLInstance) and member._class.name == target_name:
|
|
1799
|
+
found = member
|
|
1800
|
+
break
|
|
1801
|
+
result = found
|
|
1802
|
+
elif isinstance(result, dict):
|
|
1803
|
+
result = result.get(target_name)
|
|
1804
|
+
elif isinstance(result, list):
|
|
1805
|
+
result = [item for item in result if str(item) == target_name or (hasattr(item, 'name') and item.name == target_name)]
|
|
1806
|
+
elif hasattr(result, target_name):
|
|
1807
|
+
result = getattr(result, target_name)
|
|
1808
|
+
elif hasattr(result, '__class__') and result.__class__.__name__ == target_name:
|
|
1809
|
+
pass # Keep result if class name matches
|
|
1810
|
+
else:
|
|
1811
|
+
result = None
|
|
1812
|
+
|
|
1499
1813
|
return result
|
|
1500
1814
|
|
|
1501
1815
|
def _exec_inject(self, node: ASTNode) -> Any:
|
|
@@ -1553,7 +1867,15 @@ class CSSLRuntime:
|
|
|
1553
1867
|
final_value = source
|
|
1554
1868
|
elif mode == 'add':
|
|
1555
1869
|
# Copy & add - preserve target and add source
|
|
1556
|
-
|
|
1870
|
+
from .cssl_types import CSSLInstance
|
|
1871
|
+
|
|
1872
|
+
# Special handling for CSSLInstance - merge classes
|
|
1873
|
+
if isinstance(current_value, CSSLInstance) and isinstance(source, CSSLInstance):
|
|
1874
|
+
# Add the new class instance as a member with class name as key
|
|
1875
|
+
class_name = source._class.name
|
|
1876
|
+
current_value._members[class_name] = source
|
|
1877
|
+
final_value = current_value
|
|
1878
|
+
elif isinstance(current_value, list):
|
|
1557
1879
|
if isinstance(source, list):
|
|
1558
1880
|
final_value = current_value + source
|
|
1559
1881
|
else:
|
|
@@ -1569,9 +1891,14 @@ class CSSLRuntime:
|
|
|
1569
1891
|
elif mode == 'move':
|
|
1570
1892
|
# Move & remove from source
|
|
1571
1893
|
final_value = source
|
|
1572
|
-
# Clear the source
|
|
1573
|
-
if isinstance(source_node, ASTNode)
|
|
1574
|
-
|
|
1894
|
+
# Clear the source - handle all node types
|
|
1895
|
+
if isinstance(source_node, ASTNode):
|
|
1896
|
+
if source_node.type == 'identifier':
|
|
1897
|
+
self.scope.set(source_node.value, None)
|
|
1898
|
+
elif source_node.type == 'module_ref':
|
|
1899
|
+
self._set_module_value(source_node.value, None)
|
|
1900
|
+
elif source_node.type == 'member_access':
|
|
1901
|
+
self._set_member(source_node, None)
|
|
1575
1902
|
else:
|
|
1576
1903
|
final_value = source
|
|
1577
1904
|
|
|
@@ -1643,9 +1970,36 @@ class CSSLRuntime:
|
|
|
1643
1970
|
final_value = [current_value, source]
|
|
1644
1971
|
elif mode == 'move':
|
|
1645
1972
|
final_value = source
|
|
1646
|
-
#
|
|
1647
|
-
if isinstance(source_node, ASTNode)
|
|
1648
|
-
|
|
1973
|
+
# Remove filtered elements from source (not clear entirely)
|
|
1974
|
+
if isinstance(source_node, ASTNode):
|
|
1975
|
+
if filter_info:
|
|
1976
|
+
# Get original source value
|
|
1977
|
+
original_source = self._evaluate(source_node)
|
|
1978
|
+
if isinstance(original_source, list) and isinstance(final_value, list):
|
|
1979
|
+
# Remove filtered items from original list
|
|
1980
|
+
remaining = [item for item in original_source if item not in final_value]
|
|
1981
|
+
if source_node.type == 'identifier':
|
|
1982
|
+
self.scope.set(source_node.value, remaining)
|
|
1983
|
+
elif source_node.type == 'module_ref':
|
|
1984
|
+
self._set_module_value(source_node.value, remaining)
|
|
1985
|
+
elif source_node.type == 'member_access':
|
|
1986
|
+
self._set_member(source_node, remaining)
|
|
1987
|
+
else:
|
|
1988
|
+
# Single value filter - set source to None
|
|
1989
|
+
if source_node.type == 'identifier':
|
|
1990
|
+
self.scope.set(source_node.value, None)
|
|
1991
|
+
elif source_node.type == 'module_ref':
|
|
1992
|
+
self._set_module_value(source_node.value, None)
|
|
1993
|
+
elif source_node.type == 'member_access':
|
|
1994
|
+
self._set_member(source_node, None)
|
|
1995
|
+
else:
|
|
1996
|
+
# No filter - clear entire source
|
|
1997
|
+
if source_node.type == 'identifier':
|
|
1998
|
+
self.scope.set(source_node.value, None)
|
|
1999
|
+
elif source_node.type == 'module_ref':
|
|
2000
|
+
self._set_module_value(source_node.value, None)
|
|
2001
|
+
elif source_node.type == 'member_access':
|
|
2002
|
+
self._set_member(source_node, None)
|
|
1649
2003
|
else:
|
|
1650
2004
|
final_value = source
|
|
1651
2005
|
|
|
@@ -1668,6 +2022,42 @@ class CSSLRuntime:
|
|
|
1668
2022
|
self.global_scope.set(f'${name}', SharedObjectProxy(name, final_value))
|
|
1669
2023
|
elif target.type == 'member_access':
|
|
1670
2024
|
self._set_member(target, final_value)
|
|
2025
|
+
elif target.type == 'typed_declaration':
|
|
2026
|
+
# Handle typed target: source ==> datastruct<dynamic> Output
|
|
2027
|
+
var_name = target.value.get('name')
|
|
2028
|
+
type_name = target.value.get('type_name')
|
|
2029
|
+
element_type = target.value.get('element_type', 'dynamic')
|
|
2030
|
+
|
|
2031
|
+
# Create appropriate container with final_value
|
|
2032
|
+
from .cssl_types import (create_datastruct, create_vector, create_array,
|
|
2033
|
+
create_stack, create_list, create_dictionary, create_map)
|
|
2034
|
+
|
|
2035
|
+
container = None
|
|
2036
|
+
if type_name == 'datastruct':
|
|
2037
|
+
container = create_datastruct(element_type)
|
|
2038
|
+
elif type_name == 'vector':
|
|
2039
|
+
container = create_vector(element_type)
|
|
2040
|
+
elif type_name == 'array':
|
|
2041
|
+
container = create_array(element_type)
|
|
2042
|
+
elif type_name == 'stack':
|
|
2043
|
+
container = create_stack(element_type)
|
|
2044
|
+
elif type_name == 'list':
|
|
2045
|
+
container = create_list(element_type)
|
|
2046
|
+
elif type_name == 'dictionary':
|
|
2047
|
+
container = create_dictionary()
|
|
2048
|
+
elif type_name == 'map':
|
|
2049
|
+
container = create_map()
|
|
2050
|
+
|
|
2051
|
+
if container is not None:
|
|
2052
|
+
# Add final_value to container
|
|
2053
|
+
if isinstance(final_value, (list, tuple)):
|
|
2054
|
+
container.extend(final_value)
|
|
2055
|
+
elif final_value is not None:
|
|
2056
|
+
container.append(final_value)
|
|
2057
|
+
self.scope.set(var_name, container)
|
|
2058
|
+
else:
|
|
2059
|
+
# Unknown type, just set the value directly
|
|
2060
|
+
self.scope.set(var_name, final_value)
|
|
1671
2061
|
|
|
1672
2062
|
return final_value
|
|
1673
2063
|
|
|
@@ -1796,7 +2186,12 @@ class CSSLRuntime:
|
|
|
1796
2186
|
|
|
1797
2187
|
if isinstance(target, ASTNode):
|
|
1798
2188
|
if target.type == 'identifier':
|
|
1799
|
-
|
|
2189
|
+
# Check if we're in a class method and this is a class member
|
|
2190
|
+
# If so, set the member instead of creating a local variable
|
|
2191
|
+
if self._current_instance is not None and self._current_instance.has_member(target.value):
|
|
2192
|
+
self._current_instance.set_member(target.value, value)
|
|
2193
|
+
else:
|
|
2194
|
+
self.scope.set(target.value, value)
|
|
1800
2195
|
elif target.type == 'global_ref':
|
|
1801
2196
|
# r@Name = value - store in promoted globals
|
|
1802
2197
|
self._promoted_globals[target.value] = value
|
|
@@ -1860,6 +2255,10 @@ class CSSLRuntime:
|
|
|
1860
2255
|
"""Execute expression statement"""
|
|
1861
2256
|
return self._evaluate(node.value)
|
|
1862
2257
|
|
|
2258
|
+
def _exec_type_instantiation(self, node: ASTNode) -> Any:
|
|
2259
|
+
"""Execute type instantiation as statement (e.g., vector<int>)"""
|
|
2260
|
+
return self._evaluate(node)
|
|
2261
|
+
|
|
1863
2262
|
def _exec_await(self, node: ASTNode) -> Any:
|
|
1864
2263
|
"""Execute await statement - waits for expression to complete"""
|
|
1865
2264
|
# Evaluate the awaited expression
|
|
@@ -1929,6 +2328,16 @@ class CSSLRuntime:
|
|
|
1929
2328
|
if node.type == 'identifier':
|
|
1930
2329
|
name = node.value
|
|
1931
2330
|
value = self.scope.get(name)
|
|
2331
|
+
# Check if it's a class member in current instance context
|
|
2332
|
+
# This allows accessing members without 'this->' inside methods
|
|
2333
|
+
if value is None and self._current_instance is not None:
|
|
2334
|
+
if self._current_instance.has_member(name):
|
|
2335
|
+
value = self._current_instance.get_member(name)
|
|
2336
|
+
elif self._current_instance.has_method(name):
|
|
2337
|
+
# Return bound method
|
|
2338
|
+
method_node = self._current_instance.get_method(name)
|
|
2339
|
+
instance = self._current_instance
|
|
2340
|
+
value = lambda *args, **kwargs: self._call_method(instance, method_node, list(args), kwargs)
|
|
1932
2341
|
# Fallback to global scope
|
|
1933
2342
|
if value is None:
|
|
1934
2343
|
value = self.global_scope.get(name)
|
|
@@ -1941,12 +2350,13 @@ class CSSLRuntime:
|
|
|
1941
2350
|
return value
|
|
1942
2351
|
|
|
1943
2352
|
if node.type == 'module_ref':
|
|
1944
|
-
#
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
value = self._promoted_globals.get(node.value)
|
|
2353
|
+
# User-defined globals have priority over SDK modules
|
|
2354
|
+
# Check promoted globals first, then global scope, then SDK modules
|
|
2355
|
+
value = self._promoted_globals.get(node.value)
|
|
1948
2356
|
if value is None:
|
|
1949
2357
|
value = self.global_scope.get(node.value)
|
|
2358
|
+
if value is None:
|
|
2359
|
+
value = self.get_module(node.value) # SDK modules as fallback
|
|
1950
2360
|
return value
|
|
1951
2361
|
|
|
1952
2362
|
if node.type == 'self_ref':
|
|
@@ -2030,12 +2440,28 @@ class CSSLRuntime:
|
|
|
2030
2440
|
value_type = node.value.get('value_type') # For map<K, V>
|
|
2031
2441
|
init_values = node.value.get('init_values') # For inline init: map<K,V>{...}
|
|
2032
2442
|
|
|
2443
|
+
# Helper to populate container with init values
|
|
2444
|
+
def _populate_container(container, init_vals):
|
|
2445
|
+
if init_vals and isinstance(init_vals, list):
|
|
2446
|
+
for val_node in init_vals:
|
|
2447
|
+
val = self._evaluate(val_node) if isinstance(val_node, ASTNode) else val_node
|
|
2448
|
+
if hasattr(container, 'push'):
|
|
2449
|
+
container.push(val)
|
|
2450
|
+
elif hasattr(container, 'add'):
|
|
2451
|
+
container.add(val)
|
|
2452
|
+
elif hasattr(container, 'append'):
|
|
2453
|
+
container.append(val)
|
|
2454
|
+
return container
|
|
2455
|
+
|
|
2033
2456
|
if type_name == 'stack':
|
|
2034
|
-
|
|
2457
|
+
s = Stack(element_type)
|
|
2458
|
+
return _populate_container(s, init_values)
|
|
2035
2459
|
elif type_name == 'vector':
|
|
2036
|
-
|
|
2460
|
+
v = Vector(element_type)
|
|
2461
|
+
return _populate_container(v, init_values)
|
|
2037
2462
|
elif type_name == 'datastruct':
|
|
2038
|
-
|
|
2463
|
+
d = DataStruct(element_type)
|
|
2464
|
+
return _populate_container(d, init_values)
|
|
2039
2465
|
elif type_name == 'shuffled':
|
|
2040
2466
|
return Shuffled(element_type)
|
|
2041
2467
|
elif type_name == 'iterator':
|
|
@@ -2047,9 +2473,11 @@ class CSSLRuntime:
|
|
|
2047
2473
|
elif type_name == 'openquote':
|
|
2048
2474
|
return OpenQuote()
|
|
2049
2475
|
elif type_name == 'array':
|
|
2050
|
-
|
|
2476
|
+
a = Array(element_type)
|
|
2477
|
+
return _populate_container(a, init_values)
|
|
2051
2478
|
elif type_name == 'list':
|
|
2052
|
-
|
|
2479
|
+
l = List(element_type)
|
|
2480
|
+
return _populate_container(l, init_values)
|
|
2053
2481
|
elif type_name in ('dictionary', 'dict'):
|
|
2054
2482
|
return Dictionary(element_type)
|
|
2055
2483
|
elif type_name == 'map':
|
|
@@ -2836,12 +3264,20 @@ class CSSLRuntime:
|
|
|
2836
3264
|
pass
|
|
2837
3265
|
|
|
2838
3266
|
def _set_module_value(self, path: str, value: Any):
|
|
2839
|
-
"""Set a value on a module path"""
|
|
3267
|
+
"""Set a value on a module path or promoted global"""
|
|
2840
3268
|
parts = path.split('.')
|
|
2841
3269
|
if len(parts) < 2:
|
|
3270
|
+
# Single name (no dots) - set in promoted_globals and global_scope
|
|
3271
|
+
self._promoted_globals[path] = value
|
|
3272
|
+
self.global_scope.set(path, value)
|
|
2842
3273
|
return
|
|
2843
3274
|
|
|
2844
3275
|
obj = self._modules.get(parts[0])
|
|
3276
|
+
# Also check promoted_globals for the base object
|
|
3277
|
+
if obj is None:
|
|
3278
|
+
obj = self._promoted_globals.get(parts[0])
|
|
3279
|
+
if obj is None:
|
|
3280
|
+
obj = self.global_scope.get(parts[0])
|
|
2845
3281
|
if obj is None:
|
|
2846
3282
|
return
|
|
2847
3283
|
|