IncludeCPP 3.8.5__tar.gz → 3.9.0__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.
Files changed (60) hide show
  1. {includecpp-3.8.5 → includecpp-3.9.0}/IncludeCPP.egg-info/PKG-INFO +1 -1
  2. {includecpp-3.8.5 → includecpp-3.9.0}/PKG-INFO +1 -1
  3. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/__init__.py +1 -1
  4. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/core/cssl/CSSL_DOCUMENTATION.md +100 -1
  5. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/core/cssl/cssl_parser.py +177 -15
  6. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/core/cssl/cssl_runtime.py +195 -3
  7. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/vscode/cssl/syntaxes/cssl.tmLanguage.json +25 -0
  8. {includecpp-3.8.5 → includecpp-3.9.0}/pyproject.toml +1 -1
  9. {includecpp-3.8.5 → includecpp-3.9.0}/IncludeCPP.egg-info/SOURCES.txt +0 -0
  10. {includecpp-3.8.5 → includecpp-3.9.0}/IncludeCPP.egg-info/dependency_links.txt +0 -0
  11. {includecpp-3.8.5 → includecpp-3.9.0}/IncludeCPP.egg-info/entry_points.txt +0 -0
  12. {includecpp-3.8.5 → includecpp-3.9.0}/IncludeCPP.egg-info/requires.txt +0 -0
  13. {includecpp-3.8.5 → includecpp-3.9.0}/IncludeCPP.egg-info/top_level.txt +0 -0
  14. {includecpp-3.8.5 → includecpp-3.9.0}/LICENSE +0 -0
  15. {includecpp-3.8.5 → includecpp-3.9.0}/MANIFEST.in +0 -0
  16. {includecpp-3.8.5 → includecpp-3.9.0}/README.md +0 -0
  17. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/__init__.pyi +0 -0
  18. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/__main__.py +0 -0
  19. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/cli/__init__.py +0 -0
  20. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/cli/commands.py +0 -0
  21. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/cli/config_parser.py +0 -0
  22. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/core/__init__.py +0 -0
  23. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/core/ai_integration.py +0 -0
  24. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/core/build_manager.py +0 -0
  25. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/core/cpp_api.py +0 -0
  26. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/core/cpp_api.pyi +0 -0
  27. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/core/cppy_converter.py +0 -0
  28. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/core/cssl/__init__.py +0 -0
  29. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/core/cssl/cssl_builtins.py +0 -0
  30. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/core/cssl/cssl_builtins.pyi +0 -0
  31. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/core/cssl/cssl_events.py +0 -0
  32. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/core/cssl/cssl_modules.py +0 -0
  33. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/core/cssl/cssl_syntax.py +0 -0
  34. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/core/cssl/cssl_types.py +0 -0
  35. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/core/cssl_bridge.py +0 -0
  36. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/core/cssl_bridge.pyi +0 -0
  37. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/core/error_catalog.py +0 -0
  38. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/core/error_formatter.py +0 -0
  39. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/core/exceptions.py +0 -0
  40. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/core/path_discovery.py +0 -0
  41. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/core/project_ui.py +0 -0
  42. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/core/settings_ui.py +0 -0
  43. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/generator/__init__.py +0 -0
  44. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/generator/parser.cpp +0 -0
  45. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/generator/parser.h +0 -0
  46. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/generator/type_resolver.cpp +0 -0
  47. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/generator/type_resolver.h +0 -0
  48. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/py.typed +0 -0
  49. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/templates/cpp.proj.template +0 -0
  50. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/vscode/__init__.py +0 -0
  51. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/vscode/cssl/__init__.py +0 -0
  52. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/vscode/cssl/extension.js +0 -0
  53. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/vscode/cssl/images/cssl.png +0 -0
  54. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/vscode/cssl/images/cssl_pl.png +0 -0
  55. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/vscode/cssl/language-configuration.json +0 -0
  56. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/vscode/cssl/package.json +0 -0
  57. {includecpp-3.8.5 → includecpp-3.9.0}/includecpp/vscode/cssl/snippets/cssl.snippets.json +0 -0
  58. {includecpp-3.8.5 → includecpp-3.9.0}/requirements.txt +0 -0
  59. {includecpp-3.8.5 → includecpp-3.9.0}/setup.cfg +0 -0
  60. {includecpp-3.8.5 → includecpp-3.9.0}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: IncludeCPP
3
- Version: 3.8.5
3
+ Version: 3.9.0
4
4
  Summary: Professional C++ Python bindings with type-generic templates, pystubs and native threading
5
5
  Home-page: https://github.com/liliassg/IncludeCPP
6
6
  Author: Lilias Hatterscheidt
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: IncludeCPP
3
- Version: 3.8.5
3
+ Version: 3.9.0
4
4
  Summary: Professional C++ Python bindings with type-generic templates, pystubs and native threading
5
5
  Home-page: https://github.com/liliassg/IncludeCPP
6
6
  Author: Lilias Hatterscheidt
@@ -2,7 +2,7 @@ from .core.cpp_api import CppApi
2
2
  from .core import cssl_bridge as CSSL
3
3
  import warnings
4
4
 
5
- __version__ = "3.8.5"
5
+ __version__ = "3.9.0"
6
6
  __all__ = ["CppApi", "CSSL"]
7
7
 
8
8
  # Module-level cache for C++ modules
@@ -1,6 +1,6 @@
1
1
  # CSSL - C-Style Scripting Language
2
2
 
3
- > Version 3.8.5 | A modern scripting language with C++-style syntax and unique features like CodeInfusion, BruteInjection, and Python Interop.
3
+ > Version 3.8.9 | A modern scripting language with C++-style syntax and unique features like CodeInfusion, BruteInjection, and Python Interop.
4
4
 
5
5
  ---
6
6
 
@@ -2007,6 +2007,101 @@ class Derived : extends Base {
2007
2007
  }
2008
2008
  ```
2009
2009
 
2010
+ ### Append Mode with `++` Operator
2011
+
2012
+ The `++` append operator allows you to extend constructors and functions by keeping the original code and adding new code. This is useful for extending behavior without completely replacing it.
2013
+
2014
+ #### Basic Function Append
2015
+
2016
+ ```cssl
2017
+ // Original function
2018
+ define BaseFunc() {
2019
+ printl("Base functionality");
2020
+ }
2021
+
2022
+ // Append to BaseFunc - keeps original + adds new
2023
+ define ExtendedFunc() &BaseFunc ++ {
2024
+ printl("Extended functionality");
2025
+ }
2026
+
2027
+ ExtendedFunc();
2028
+ // Output:
2029
+ // Base functionality
2030
+ // Extended functionality
2031
+ ```
2032
+
2033
+ #### Constructor Append with Class Reference
2034
+
2035
+ ```cssl
2036
+ class MyClass {
2037
+ constr MyClassConstructor() {
2038
+ printl("MyClass constructor");
2039
+ this->value = 10;
2040
+ }
2041
+ }
2042
+
2043
+ class BetterClass :: extends MyClass {
2044
+ // Append to specific parent constructor
2045
+ constr BetterConstructor() &MyClass::MyClassConstructor ++ {
2046
+ printl("BetterClass - added code");
2047
+ this->extra = 20;
2048
+ }
2049
+ }
2050
+
2051
+ $instance = new BetterClass();
2052
+ // Output:
2053
+ // MyClass constructor
2054
+ // BetterClass - added code
2055
+ printl($instance.value); // 10
2056
+ printl($instance.extra); // 20
2057
+ ```
2058
+
2059
+ #### Method Append
2060
+
2061
+ ```cssl
2062
+ class Parent {
2063
+ define greet() {
2064
+ printl("Hello from Parent");
2065
+ }
2066
+ }
2067
+
2068
+ class Child :: extends Parent {
2069
+ // Append to parent method
2070
+ define betterGreet() &Parent::greet ++ {
2071
+ printl("And also from Child!");
2072
+ }
2073
+ }
2074
+
2075
+ $child = new Child();
2076
+ $child.betterGreet();
2077
+ // Output:
2078
+ // Hello from Parent
2079
+ // And also from Child!
2080
+ ```
2081
+
2082
+ #### Dynamic Instance Reference
2083
+
2084
+ You can also reference methods from instances using `&$instanceVar::member`:
2085
+
2086
+ ```cssl
2087
+ global $myInstance = new SomeClass();
2088
+
2089
+ class Extended {
2090
+ define extendedMethod() &$myInstance::originalMethod ++ {
2091
+ printl("Added to instance method");
2092
+ }
2093
+ }
2094
+ ```
2095
+
2096
+ #### Append Mode Syntax Summary
2097
+
2098
+ | Syntax | Description |
2099
+ |--------|-------------|
2100
+ | `&FunctionName ++` | Append to a function |
2101
+ | `&ClassName::member ++` | Append to a class member (constructor/method) |
2102
+ | `&$instanceVar::member ++` | Append to an instance member |
2103
+ | `&ClassName::constructors ++` | Append to all constructors of a class |
2104
+
2010
2105
  ---
2011
2106
 
2012
2107
  ## Map Container
@@ -2375,6 +2470,7 @@ print(result) # ["Missing colon after def"]
2375
2470
  | `-<==` | BruteInjection | Move data |
2376
2471
  | `==>` | BruteInjection | Replace data |
2377
2472
  | `==>-` | BruteInjection | Remove matching items |
2473
+ | `++` | AppendMode | Append to parent (with `&ref`) |
2378
2474
 
2379
2475
  ### Special Syntax
2380
2476
 
@@ -2386,6 +2482,9 @@ print(result) # ["Missing colon after def"]
2386
2482
  | `$name` | Access shared Python object |
2387
2483
  | `s@name` | Self-reference to struct |
2388
2484
  | `r@name` | Global variable declaration |
2485
+ | `&ClassName::member` | Reference class member for append mode |
2486
+ | `&$instance::member` | Reference instance member for append mode |
2487
+ | `&FunctionName ++` | Append to function (keeps old + adds new) |
2389
2488
 
2390
2489
  ---
2391
2490
 
@@ -110,6 +110,9 @@ class TokenType(Enum):
110
110
  EOF = auto()
111
111
  # Super-functions for .cssl-pl payload files (v3.8.0)
112
112
  SUPER_FUNC = auto() # #$run(), #$exec(), #$printl() - pre-execution hooks
113
+ # Append operator for constructor/function extension
114
+ PLUS_PLUS = auto() # ++ for constructor/function append (keeps old + adds new)
115
+ MINUS_MINUS = auto() # -- for potential future use
113
116
 
114
117
 
115
118
  KEYWORDS = {
@@ -307,8 +310,13 @@ class CSSLLexer:
307
310
  self._add_token(TokenType.DOT, '.')
308
311
  self._advance()
309
312
  elif char == '+':
313
+ # Check for ++ (append operator for constructor/function extension)
314
+ if self._peek(1) == '+':
315
+ self._add_token(TokenType.PLUS_PLUS, '++')
316
+ self._advance()
317
+ self._advance()
310
318
  # Check for BruteForce Injection: +<== or +<<==
311
- if self._peek(1) == '<' and self._peek(2) == '<' and self._peek(3) == '=' and self._peek(4) == '=':
319
+ elif self._peek(1) == '<' and self._peek(2) == '<' and self._peek(3) == '=' and self._peek(4) == '=':
312
320
  self._add_token(TokenType.INFUSE_PLUS_LEFT, '+<<==')
313
321
  for _ in range(5): self._advance()
314
322
  elif self._peek(1) == '<' and self._peek(2) == '=' and self._peek(3) == '=':
@@ -849,6 +857,18 @@ class CSSLParser:
849
857
  self._advance()
850
858
  generic_type = ''.join(generic_parts)
851
859
 
860
+ # Check for * prefix (non-null function) or *[type] (type exclusion)
861
+ non_null = False
862
+ exclude_type = None
863
+ if self._match(TokenType.MULTIPLY):
864
+ # Check for type exclusion filter: *[string], *[int], etc.
865
+ if self._check(TokenType.BRACKET_START):
866
+ self._advance() # consume [
867
+ exclude_type = self._advance().value # get type name
868
+ self._expect(TokenType.BRACKET_END)
869
+ else:
870
+ non_null = True
871
+
852
872
  # Get function name
853
873
  name = self._advance().value
854
874
 
@@ -949,7 +969,9 @@ class CSSLParser:
949
969
  'params': params,
950
970
  'return_type': return_type,
951
971
  'generic_type': generic_type,
952
- 'modifiers': modifiers
972
+ 'modifiers': modifiers,
973
+ 'non_null': non_null,
974
+ 'exclude_type': exclude_type # *[type] - must NOT return this type
953
975
  }, children=[])
954
976
 
955
977
  self._expect(TokenType.BLOCK_START)
@@ -1400,8 +1422,8 @@ class CSSLParser:
1400
1422
  overwrites_class = None
1401
1423
  overwrites_is_python = False
1402
1424
 
1403
- if self._match(TokenType.COLON):
1404
- # Parse extends and/or overwrites (can be chained)
1425
+ if self._match(TokenType.DOUBLE_COLON) or self._match(TokenType.COLON):
1426
+ # Parse extends and/or overwrites (can be chained with : or ::)
1405
1427
  while True:
1406
1428
  if self._match_keyword('extends'):
1407
1429
  if self._check(TokenType.IDENTIFIER):
@@ -1430,9 +1452,9 @@ class CSSLParser:
1430
1452
  if self._match(TokenType.PAREN_START):
1431
1453
  self._expect(TokenType.PAREN_END)
1432
1454
  else:
1433
- raise CSSLSyntaxError("Expected 'extends' or 'overwrites' after ':' in class declaration")
1434
- # Check for another : for chaining
1435
- if not self._match(TokenType.COLON):
1455
+ raise CSSLSyntaxError("Expected 'extends' or 'overwrites' after ':' or '::' in class declaration")
1456
+ # Check for another : or :: for chaining
1457
+ if not (self._match(TokenType.DOUBLE_COLON) or self._match(TokenType.COLON)):
1436
1458
  break
1437
1459
 
1438
1460
  node = ASTNode('class', value={
@@ -1491,11 +1513,13 @@ class CSSLParser:
1491
1513
 
1492
1514
  Syntax:
1493
1515
  constr ConstructorName() { ... }
1516
+ constr ConstructorName() ++ { ... } // Append: keeps parent constructor + adds new code
1517
+ constr ConstructorName() &ParentClass::constructors ++ { ... } // Append specific parent constructor
1494
1518
  constr ConstructorName() : extends ParentClass::ConstructorName { ... }
1495
1519
  constr ConstructorName() : extends ParentClass::ConstructorName : overwrites ParentClass::ConstructorName { ... }
1496
1520
 
1497
- Multiple constructors are allowed and executed in order.
1498
- Constructors can access parent constructor via super().
1521
+ The ++ operator means: execute parent's version first, then execute this code (append mode).
1522
+ The &ClassName::member syntax references a specific member from the overwritten class.
1499
1523
  """
1500
1524
  # Get constructor name
1501
1525
  if not self._check(TokenType.IDENTIFIER):
@@ -1503,7 +1527,6 @@ class CSSLParser:
1503
1527
  constr_name = self._advance().value
1504
1528
 
1505
1529
  # Parse method-level extends/overwrites with :: syntax
1506
- # constr Name() :: extends Parent::Name :: overwrites Parent::Name { ... }
1507
1530
  extends_target = None
1508
1531
  extends_class_ref = None
1509
1532
  extends_method_ref = None
@@ -1511,12 +1534,39 @@ class CSSLParser:
1511
1534
  overwrites_class_ref = None
1512
1535
  overwrites_method_ref = None
1513
1536
 
1537
+ # New: Append mode and reference tracking
1538
+ append_mode = False # ++ operator: keep parent code + add new
1539
+ append_ref_class = None # &ClassName part
1540
+ append_ref_member = None # ::member part (constructors, functionName, etc.)
1541
+
1514
1542
  # Parse parameters
1515
1543
  params = []
1516
1544
  if self._match(TokenType.PAREN_START):
1517
1545
  params = self._parse_parameter_list()
1518
1546
  self._expect(TokenType.PAREN_END)
1519
1547
 
1548
+ # Check for &ClassName::member reference (for targeting specific parent member)
1549
+ # Syntax: constr Name() &ParentClass::constructors ++ { ... }
1550
+ if self._match(TokenType.AMPERSAND):
1551
+ # Parse the class reference
1552
+ if self._check(TokenType.IDENTIFIER):
1553
+ append_ref_class = self._advance().value
1554
+ elif self._check(TokenType.SHARED_REF):
1555
+ append_ref_class = f'${self._advance().value}'
1556
+ else:
1557
+ raise CSSLSyntaxError("Expected class name after '&' in constructor reference")
1558
+
1559
+ # Check for ::member
1560
+ if self._match(TokenType.DOUBLE_COLON):
1561
+ if self._check(TokenType.IDENTIFIER) or self._check(TokenType.KEYWORD):
1562
+ append_ref_member = self._advance().value
1563
+ else:
1564
+ raise CSSLSyntaxError("Expected member name after '::' in constructor reference")
1565
+
1566
+ # Check for ++ append operator
1567
+ if self._match(TokenType.PLUS_PLUS):
1568
+ append_mode = True
1569
+
1520
1570
  # Check for method-level extends/overwrites with :: or :
1521
1571
  if self._match(TokenType.DOUBLE_COLON) or self._match(TokenType.COLON):
1522
1572
  while True:
@@ -1563,7 +1613,11 @@ class CSSLParser:
1563
1613
  'extends_method': extends_method_ref,
1564
1614
  'overwrites_target': overwrites_target,
1565
1615
  'overwrites_class': overwrites_class_ref,
1566
- 'overwrites_method': overwrites_method_ref
1616
+ 'overwrites_method': overwrites_method_ref,
1617
+ # New append mode fields
1618
+ 'append_mode': append_mode,
1619
+ 'append_ref_class': append_ref_class,
1620
+ 'append_ref_member': append_ref_member
1567
1621
  }, children=body)
1568
1622
 
1569
1623
  def _parse_qualified_method_ref(self) -> str:
@@ -1591,6 +1645,54 @@ class CSSLParser:
1591
1645
  # Just method name, no class qualifier
1592
1646
  return class_ref
1593
1647
 
1648
+ def _parse_parameter_list(self) -> list:
1649
+ """Parse a list of parameters (without the surrounding parentheses).
1650
+
1651
+ Returns a list of parameter definitions, each can be:
1652
+ - Simple string name: "paramName"
1653
+ - Dict with type info: {'name': 'paramName', 'type': 'string', 'ref': True, ...}
1654
+ """
1655
+ params = []
1656
+ while not self._check(TokenType.PAREN_END) and not self._is_at_end():
1657
+ param_info = {}
1658
+
1659
+ # Handle 'open' keyword for open parameters
1660
+ if self._match_keyword('open'):
1661
+ param_info['open'] = True
1662
+
1663
+ # Handle type annotations (e.g., string, int, dynamic, etc.)
1664
+ if self._check(TokenType.KEYWORD):
1665
+ param_info['type'] = self._advance().value
1666
+
1667
+ # Handle reference operator &
1668
+ if self._match(TokenType.AMPERSAND):
1669
+ param_info['ref'] = True
1670
+
1671
+ # Handle * prefix for non-null parameters
1672
+ if self._match(TokenType.MULTIPLY):
1673
+ param_info['non_null'] = True
1674
+
1675
+ # Get parameter name
1676
+ if self._check(TokenType.IDENTIFIER):
1677
+ param_name = self._advance().value
1678
+ if param_info:
1679
+ params.append({'name': param_name, **param_info})
1680
+ else:
1681
+ params.append(param_name)
1682
+ self._match(TokenType.COMMA)
1683
+ elif self._check(TokenType.KEYWORD):
1684
+ # Parameter name could be a keyword like 'Params'
1685
+ param_name = self._advance().value
1686
+ if param_info:
1687
+ params.append({'name': param_name, **param_info})
1688
+ else:
1689
+ params.append(param_name)
1690
+ self._match(TokenType.COMMA)
1691
+ else:
1692
+ break
1693
+
1694
+ return params
1695
+
1594
1696
  def _parse_define(self) -> ASTNode:
1595
1697
  """Parse define function declaration.
1596
1698
 
@@ -1602,9 +1704,17 @@ class CSSLParser:
1602
1704
  define MyFunc :: extends Parent::Method :: overwrites Parent::Method() { } // Method-level inheritance
1603
1705
  """
1604
1706
  # Check for * prefix (non-null function - must return non-null)
1707
+ # Also *[type] for type exclusion (must NOT return that type)
1605
1708
  non_null = False
1709
+ exclude_type = None
1606
1710
  if self._match(TokenType.MULTIPLY):
1607
- non_null = True
1711
+ # Check for type exclusion filter: *[string], *[int], etc.
1712
+ if self._check(TokenType.BRACKET_START):
1713
+ self._advance() # consume [
1714
+ exclude_type = self._advance().value # get type name
1715
+ self._expect(TokenType.BRACKET_END)
1716
+ else:
1717
+ non_null = True
1608
1718
 
1609
1719
  name = self._advance().value
1610
1720
 
@@ -1721,10 +1831,37 @@ class CSSLParser:
1721
1831
  break
1722
1832
  self._expect(TokenType.PAREN_END)
1723
1833
 
1834
+ # New: Append mode and reference tracking for functions
1835
+ # Syntax: define XYZ(int zahl) &overwrittenclass::functionyouwanttokeep ++ { ... }
1836
+ append_mode = False
1837
+ append_ref_class = None
1838
+ append_ref_member = None
1839
+
1840
+ # Check for &ClassName::member reference
1841
+ if self._match(TokenType.AMPERSAND):
1842
+ if self._check(TokenType.IDENTIFIER):
1843
+ append_ref_class = self._advance().value
1844
+ elif self._check(TokenType.SHARED_REF):
1845
+ append_ref_class = f'${self._advance().value}'
1846
+ else:
1847
+ raise CSSLSyntaxError("Expected class name after '&' in function reference")
1848
+
1849
+ # Check for ::member
1850
+ if self._match(TokenType.DOUBLE_COLON):
1851
+ if self._check(TokenType.IDENTIFIER) or self._check(TokenType.KEYWORD):
1852
+ append_ref_member = self._advance().value
1853
+ else:
1854
+ raise CSSLSyntaxError("Expected member name after '::' in function reference")
1855
+
1856
+ # Check for ++ append operator
1857
+ if self._match(TokenType.PLUS_PLUS):
1858
+ append_mode = True
1859
+
1724
1860
  node = ASTNode('function', value={
1725
1861
  'name': name,
1726
1862
  'params': params,
1727
1863
  'non_null': non_null,
1864
+ 'exclude_type': exclude_type, # *[type] - must NOT return this type
1728
1865
  'extends': extends_func,
1729
1866
  'extends_is_python': extends_is_python,
1730
1867
  'overwrites': overwrites_func,
@@ -1733,7 +1870,11 @@ class CSSLParser:
1733
1870
  'extends_class': extends_class_ref,
1734
1871
  'extends_method': extends_method_ref,
1735
1872
  'overwrites_class': overwrites_class_ref,
1736
- 'overwrites_method': overwrites_method_ref
1873
+ 'overwrites_method': overwrites_method_ref,
1874
+ # New append mode fields
1875
+ 'append_mode': append_mode,
1876
+ 'append_ref_class': append_ref_class,
1877
+ 'append_ref_member': append_ref_member
1737
1878
  }, children=[])
1738
1879
  self._expect(TokenType.BLOCK_START)
1739
1880
 
@@ -1781,8 +1922,9 @@ class CSSLParser:
1781
1922
  # Super-function for .cssl-pl payload files
1782
1923
  return self._parse_super_function()
1783
1924
  elif (self._check(TokenType.KEYWORD) and self._current().value == 'super' and
1784
- self._peek(1).type == TokenType.PAREN_START):
1785
- # super() call - calls parent constructor/method
1925
+ (self._peek(1).type == TokenType.PAREN_START or
1926
+ self._peek(1).type == TokenType.DOUBLE_COLON)):
1927
+ # super() or super::method() call - calls parent constructor/method
1786
1928
  return self._parse_super_call()
1787
1929
  elif (self._check(TokenType.IDENTIFIER) or self._check(TokenType.AT) or
1788
1930
  self._check(TokenType.CAPTURED_REF) or self._check(TokenType.SHARED_REF) or
@@ -2593,6 +2735,26 @@ class CSSLParser:
2593
2735
  operand = self._parse_unary()
2594
2736
  return ASTNode('reference', value=operand)
2595
2737
 
2738
+ # Non-null assertion: *$var, *@module, *identifier
2739
+ # Also type exclusion filter: *[type]expr - exclude type from return
2740
+ if self._check(TokenType.MULTIPLY):
2741
+ next_token = self._peek(1)
2742
+
2743
+ # Check for type exclusion filter: *[string], *[int], etc.
2744
+ if next_token and next_token.type == TokenType.BRACKET_START:
2745
+ self._advance() # consume *
2746
+ self._advance() # consume [
2747
+ exclude_type = self._advance().value # get type name
2748
+ self._expect(TokenType.BRACKET_END)
2749
+ operand = self._parse_unary()
2750
+ return ASTNode('type_exclude_assert', value={'exclude_type': exclude_type, 'operand': operand})
2751
+
2752
+ # Non-null assertion when followed by $ (shared ref), @ (global), or identifier
2753
+ if next_token and next_token.type in (TokenType.SHARED_REF, TokenType.AT, TokenType.IDENTIFIER):
2754
+ self._advance() # consume *
2755
+ operand = self._parse_unary()
2756
+ return ASTNode('non_null_assert', value={'operand': operand})
2757
+
2596
2758
  return self._parse_primary()
2597
2759
 
2598
2760
  def _parse_primary(self) -> ASTNode:
@@ -1242,7 +1242,7 @@ class CSSLRuntime:
1242
1242
  for child in extends_resolved.children:
1243
1243
  if not self._running:
1244
1244
  break
1245
- self._execute(child)
1245
+ self._execute_node(child)
1246
1246
  # Copy all local vars to new scope
1247
1247
  for name, value in temp_scope._vars.items():
1248
1248
  new_scope.set(name, value)
@@ -1290,13 +1290,43 @@ class CSSLRuntime:
1290
1290
  self.scope = new_scope
1291
1291
 
1292
1292
  try:
1293
+ # Handle append mode (++) - execute referenced function first
1294
+ append_mode = func_info.get('append_mode', False)
1295
+ append_ref_class = func_info.get('append_ref_class')
1296
+ append_ref_member = func_info.get('append_ref_member')
1297
+
1298
+ if append_mode and append_ref_class:
1299
+ self._execute_append_reference(
1300
+ None, append_ref_class, append_ref_member,
1301
+ args, kwargs, {}, is_constructor=False
1302
+ )
1303
+
1293
1304
  for child in func_node.children:
1294
1305
  # Check if exit() was called
1295
1306
  if not self._running:
1296
1307
  break
1297
1308
  self._execute_node(child)
1298
1309
  except CSSLReturn as ret:
1299
- return ret.value
1310
+ return_value = ret.value
1311
+
1312
+ # Check exclude_type: *[type] - must NOT return excluded type
1313
+ exclude_type = func_info.get('exclude_type')
1314
+ if exclude_type:
1315
+ type_map = {
1316
+ 'string': str, 'int': int, 'float': float, 'bool': bool,
1317
+ 'null': type(None), 'none': type(None),
1318
+ 'list': list, 'array': list, 'dict': dict, 'json': dict,
1319
+ }
1320
+ excluded_py_type = type_map.get(exclude_type.lower())
1321
+ # For shuffled returns (tuples), check each element
1322
+ if isinstance(return_value, tuple):
1323
+ for val in return_value:
1324
+ if excluded_py_type and isinstance(val, excluded_py_type):
1325
+ raise CSSLError(f"Type exclusion: function must NOT return '{exclude_type}' values")
1326
+ elif excluded_py_type and isinstance(return_value, excluded_py_type):
1327
+ raise CSSLError(f"Type exclusion: function must NOT return '{exclude_type}'")
1328
+
1329
+ return return_value
1300
1330
  except Exception as e:
1301
1331
  # If undefined modifier, suppress all errors
1302
1332
  if is_undefined:
@@ -1537,7 +1567,11 @@ class CSSLRuntime:
1537
1567
  )
1538
1568
 
1539
1569
  instance = self._current_instance
1570
+
1571
+ # Try to get parent from instance first, then from class definition
1540
1572
  parent = getattr(instance, '_parent_class', None)
1573
+ if parent is None and hasattr(instance, '_class') and instance._class:
1574
+ parent = getattr(instance._class, 'parent', None)
1541
1575
 
1542
1576
  if parent is None:
1543
1577
  raise CSSLRuntimeError(
@@ -2816,6 +2850,39 @@ class CSSLRuntime:
2816
2850
  if node.type == 'unary':
2817
2851
  return self._eval_unary(node)
2818
2852
 
2853
+ if node.type == 'non_null_assert':
2854
+ # *$var, *@module, *identifier - assert value is not null/None
2855
+ operand = node.value.get('operand')
2856
+ value = self._evaluate(operand)
2857
+ if value is None:
2858
+ raise CSSLError(f"Non-null assertion failed: value is null/None")
2859
+ return value
2860
+
2861
+ if node.type == 'type_exclude_assert':
2862
+ # *[type]expr - assert value is NOT of excluded type
2863
+ exclude_type = node.value.get('exclude_type')
2864
+ operand = node.value.get('operand')
2865
+ value = self._evaluate(operand)
2866
+
2867
+ # Map CSSL types to Python types
2868
+ type_map = {
2869
+ 'string': str,
2870
+ 'int': int,
2871
+ 'float': float,
2872
+ 'bool': bool,
2873
+ 'null': type(None),
2874
+ 'none': type(None),
2875
+ 'list': list,
2876
+ 'array': list,
2877
+ 'dict': dict,
2878
+ 'json': dict,
2879
+ }
2880
+
2881
+ excluded_py_type = type_map.get(exclude_type.lower())
2882
+ if excluded_py_type and isinstance(value, excluded_py_type):
2883
+ raise CSSLError(f"Type exclusion assertion failed: value is of excluded type '{exclude_type}'")
2884
+ return value
2885
+
2819
2886
  if node.type == 'call':
2820
2887
  return self._eval_call(node)
2821
2888
 
@@ -3267,17 +3334,122 @@ class CSSLRuntime:
3267
3334
  except TypeError:
3268
3335
  pass
3269
3336
 
3337
+ def _execute_append_reference(self, instance: CSSLInstance, ref_class: str, ref_member: str,
3338
+ args: list, kwargs: dict, param_values: dict, is_constructor: bool = True):
3339
+ """Execute referenced parent constructor/method for append mode (++).
3340
+
3341
+ Resolves the class/instance reference and executes the specified member.
3342
+ Supports:
3343
+ - Static class references: &ClassName::member
3344
+ - Dynamic instance references: &$instanceVar::member
3345
+ - Direct function references: &FunctionName (for define functions)
3346
+
3347
+ Args:
3348
+ instance: Current class instance (can be None for standalone functions)
3349
+ ref_class: Referenced class name, $instanceVar, or function name
3350
+ ref_member: Member name (constructor name, 'constructors', or method name) - can be None
3351
+ args: Arguments to pass
3352
+ kwargs: Keyword arguments to pass
3353
+ param_values: Parameter values from class params
3354
+ is_constructor: True if looking for constructor, False for method
3355
+ """
3356
+ from .cssl_builtins import CSSLizedPythonObject
3357
+
3358
+ # Handle direct function reference: &FunctionName ++ (no ::member part)
3359
+ if ref_member is None and not is_constructor:
3360
+ # ref_class is actually a function name
3361
+ func_name = ref_class
3362
+ if func_name.startswith('$'):
3363
+ func_name = func_name[1:]
3364
+
3365
+ # Look for the function in scope
3366
+ func = self.scope.get(func_name) or self.global_scope.get(func_name)
3367
+ if func is not None:
3368
+ if isinstance(func, ASTNode) and func.type in ('function', 'FUNCTION'):
3369
+ # Execute the referenced function
3370
+ if instance:
3371
+ self._call_method(instance, func, args, kwargs)
3372
+ else:
3373
+ self._call_function(func, args, kwargs)
3374
+ elif callable(func):
3375
+ # It's a callable (Python function or lambda)
3376
+ func(*args, **kwargs)
3377
+ return
3378
+
3379
+ # Resolve the class/instance reference
3380
+ if ref_class.startswith('$'):
3381
+ # Dynamic instance reference: &$instanceVar::member
3382
+ var_name = ref_class[1:]
3383
+ ref_obj = self.scope.get(var_name) or self.global_scope.get(var_name)
3384
+ if ref_obj is None:
3385
+ return # Instance not found, skip silently
3386
+
3387
+ if isinstance(ref_obj, CSSLInstance):
3388
+ # Get the class definition from the instance
3389
+ target_class = ref_obj.class_def
3390
+ elif isinstance(ref_obj, CSSLClass):
3391
+ target_class = ref_obj
3392
+ else:
3393
+ return # Not a valid reference
3394
+ else:
3395
+ # Static class reference: &ClassName::member
3396
+ target_class = self.scope.get(ref_class) or self.global_scope.get(ref_class)
3397
+
3398
+ if target_class is None:
3399
+ return # Class not found, skip silently
3400
+
3401
+ # Handle different target types
3402
+ if isinstance(target_class, CSSLInstance):
3403
+ # Referenced an instance variable directly
3404
+ target_class = target_class.class_def
3405
+
3406
+ if not isinstance(target_class, CSSLClass):
3407
+ return # Not a CSSL class
3408
+
3409
+ # Find and execute the referenced member
3410
+ if is_constructor:
3411
+ # Looking for a constructor
3412
+ if ref_member == 'constructors' or ref_member is None:
3413
+ # Execute all constructors from the referenced class
3414
+ for constr in getattr(target_class, 'constructors', []):
3415
+ self._call_constructor(instance, constr, args, kwargs, param_values)
3416
+ else:
3417
+ # Execute specific constructor by name
3418
+ for constr in getattr(target_class, 'constructors', []):
3419
+ if constr.value.get('name') == ref_member:
3420
+ self._call_constructor(instance, constr, args, kwargs, param_values)
3421
+ break
3422
+ else:
3423
+ # Looking for a method (define function)
3424
+ if ref_member:
3425
+ # Find method in class
3426
+ for member in getattr(target_class, 'members', []):
3427
+ if member.type in ('function', 'FUNCTION') and member.value.get('name') == ref_member:
3428
+ self._call_method(instance, member, args, kwargs)
3429
+ break
3430
+ # Also check in methods dict if available
3431
+ methods = getattr(target_class, 'methods', {})
3432
+ if ref_member in methods:
3433
+ method_node = methods[ref_member]
3434
+ self._call_method(instance, method_node, args, kwargs)
3435
+
3270
3436
  def _call_constructor(self, instance: CSSLInstance, constr_node: ASTNode,
3271
3437
  args: list, kwargs: dict, param_values: dict):
3272
3438
  """Call a constructor defined with 'constr' keyword.
3273
3439
 
3274
3440
  Handles constructor extends/overwrites and sets up the instance scope.
3441
+ Supports append mode (++) for keeping parent code and adding new code.
3275
3442
  """
3276
3443
  constr_info = constr_node.value
3277
3444
  constr_params = constr_info.get('params', [])
3278
3445
  extends_class = constr_info.get('extends_class')
3279
3446
  extends_method = constr_info.get('extends_method')
3280
3447
 
3448
+ # Append mode: ++ operator for keeping parent code + adding new
3449
+ append_mode = constr_info.get('append_mode', False)
3450
+ append_ref_class = constr_info.get('append_ref_class') # &ClassName or &$instanceVar
3451
+ append_ref_member = constr_info.get('append_ref_member') # ::constructorName or ::methodName
3452
+
3281
3453
  # Save previous instance context
3282
3454
  prev_instance = self._current_instance
3283
3455
  self._current_instance = instance
@@ -3309,13 +3481,20 @@ class CSSLRuntime:
3309
3481
  self._call_constructor(instance, constr, args, kwargs, param_values)
3310
3482
  break
3311
3483
 
3484
+ # Handle append mode (++) - execute referenced parent member first
3485
+ if append_mode and append_ref_class:
3486
+ self._execute_append_reference(
3487
+ instance, append_ref_class, append_ref_member,
3488
+ args, kwargs, param_values, is_constructor=True
3489
+ )
3490
+
3312
3491
  # Execute constructor body
3313
3492
  prev_scope = self.scope
3314
3493
  self.scope = new_scope
3315
3494
 
3316
3495
  try:
3317
3496
  for stmt in constr_node.children:
3318
- self._execute(stmt)
3497
+ self._execute_node(stmt)
3319
3498
  finally:
3320
3499
  self.scope = prev_scope
3321
3500
  self._current_instance = prev_instance
@@ -3372,12 +3551,18 @@ class CSSLRuntime:
3372
3551
  """Call a method on an instance with 'this' context.
3373
3552
 
3374
3553
  Sets up the instance as the current 'this' context and executes the method.
3554
+ Supports append mode (++) for keeping parent code and adding new code.
3375
3555
  """
3376
3556
  kwargs = kwargs or {}
3377
3557
  func_info = method_node.value
3378
3558
  params = func_info.get('params', [])
3379
3559
  modifiers = func_info.get('modifiers', [])
3380
3560
 
3561
+ # Append mode: ++ operator for keeping parent code + adding new
3562
+ append_mode = func_info.get('append_mode', False)
3563
+ append_ref_class = func_info.get('append_ref_class') # &ClassName or &$instanceVar
3564
+ append_ref_member = func_info.get('append_ref_member') # ::methodName
3565
+
3381
3566
  # Check for undefined modifier
3382
3567
  is_undefined = 'undefined' in modifiers
3383
3568
 
@@ -3404,6 +3589,13 @@ class CSSLRuntime:
3404
3589
  self._current_instance = instance
3405
3590
 
3406
3591
  try:
3592
+ # Handle append mode (++) - execute referenced parent method first
3593
+ if append_mode and append_ref_class:
3594
+ self._execute_append_reference(
3595
+ instance, append_ref_class, append_ref_member,
3596
+ args, kwargs, {}, is_constructor=False
3597
+ )
3598
+
3407
3599
  for child in method_node.children:
3408
3600
  if not self._running:
3409
3601
  break
@@ -7,6 +7,8 @@
7
7
  { "include": "#comments" },
8
8
  { "include": "#strings" },
9
9
  { "include": "#numbers" },
10
+ { "include": "#append-operator" },
11
+ { "include": "#append-reference" },
10
12
  { "include": "#class-definition" },
11
13
  { "include": "#function-definitions" },
12
14
  { "include": "#constructor-definition" },
@@ -35,6 +37,29 @@
35
37
  { "include": "#variables" }
36
38
  ],
37
39
  "repository": {
40
+ "append-operator": {
41
+ "patterns": [
42
+ {
43
+ "comment": "++ append operator for constructor/function extension - orange",
44
+ "name": "constant.character.escape.infuse.cssl",
45
+ "match": "\\+\\+(?=\\s*\\{)"
46
+ }
47
+ ]
48
+ },
49
+ "append-reference": {
50
+ "patterns": [
51
+ {
52
+ "comment": "&ClassName::member or &$var::member - all yellow for append reference",
53
+ "name": "entity.name.tag.super.cssl",
54
+ "match": "&(\\$?[a-zA-Z_][a-zA-Z0-9_]*)(::)([a-zA-Z_][a-zA-Z0-9_]*)"
55
+ },
56
+ {
57
+ "comment": "&FunctionName - yellow for direct function reference",
58
+ "name": "entity.name.tag.super.cssl",
59
+ "match": "&([a-zA-Z_][a-zA-Z0-9_]*)(?=\\s*\\+\\+)"
60
+ }
61
+ ]
62
+ },
38
63
  "non-null-declarations": {
39
64
  "patterns": [
40
65
  {
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "IncludeCPP"
7
- version = "3.8.5"
7
+ version = "3.9.0"
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