IncludeCPP 3.8.9__py3-none-any.whl → 4.0.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.
@@ -144,16 +144,25 @@ KEYWORDS = {
144
144
  'structure', # Advanced C++/Py Class
145
145
  'openquote', # SQL openquote container
146
146
  # CSSL Function Modifiers
147
+ 'const', # Immutable function (like C++)
147
148
  'meta', # Source function (must return)
148
149
  'super', # Force execution (no exceptions)
149
150
  'closed', # Protect from external injection
150
151
  'private', # Disable all injections
151
152
  'virtual', # Import cycle safe
152
153
  'sqlbased', # SQL-based function
154
+ 'public', # Explicitly public (default)
155
+ 'static', # Static method/function
153
156
  # CSSL Include Keywords
154
157
  'include', 'get',
155
158
  }
156
159
 
160
+ # Function modifiers that can appear in any order before function name
161
+ FUNCTION_MODIFIERS = {
162
+ 'undefined', 'open', 'meta', 'super', 'closed', 'private', 'virtual',
163
+ 'sqlbased', 'const', 'public', 'static', 'global', 'shuffled'
164
+ }
165
+
157
166
  # Type literals that create empty instances
158
167
  TYPE_LITERALS = {'list', 'dict'}
159
168
 
@@ -719,7 +728,7 @@ class CSSLParser:
719
728
 
720
729
  def _is_function_modifier(self, value: str) -> bool:
721
730
  """Check if a keyword is a function modifier"""
722
- return value in ('undefined', 'open', 'meta', 'super', 'closed', 'private', 'virtual', 'sqlbased')
731
+ return value in FUNCTION_MODIFIERS
723
732
 
724
733
  def _is_type_keyword(self, value: str) -> bool:
725
734
  """Check if a keyword is a type declaration"""
@@ -730,53 +739,98 @@ class CSSLParser:
730
739
  def _looks_like_function_declaration(self) -> bool:
731
740
  """Check if current position looks like a C-style function declaration.
732
741
 
742
+ Supports flexible ordering of modifiers, types, non-null (*), and global (@):
743
+
733
744
  Patterns:
734
745
  - int funcName(...)
735
746
  - undefined int funcName(...)
736
747
  - vector<string> funcName(...)
737
748
  - undefined void funcName(...)
738
- - private super virtual meta FuncName(...) <- modifiers without return type
749
+ - private super virtual meta FuncName(...)
750
+ - private string *@Myfunc(...)
751
+ - const define myFunc(...)
752
+ - global private const void @Func(...)
753
+ - shuffled *[string] getNumbers(...)
754
+ - datastruct<dynamic> HelloCode(...)
755
+ - datastruct<dynamic> HelloCode() : extends @MyFunc { }
756
+
757
+ Distinguishes functions from variables:
758
+ - datastruct<dynamic> MyVar; <- variable (no () { })
759
+ - datastruct<dynamic> HelloCode() { } <- function (has () { })
739
760
  """
740
761
  saved_pos = self.pos
741
762
  has_modifiers = False
763
+ has_type = False
742
764
 
743
- # Skip modifiers (undefined, open, meta, super, closed, private, virtual)
744
- while self._check(TokenType.KEYWORD) and self._is_function_modifier(self._current().value):
745
- self._advance()
746
- has_modifiers = True
765
+ try:
766
+ # Skip modifiers in any order (global, private, const, undefined, etc.)
767
+ while self._check(TokenType.KEYWORD) and self._is_function_modifier(self._current().value):
768
+ self._advance()
769
+ has_modifiers = True
747
770
 
748
- # Check for type keyword (optional if modifiers present)
749
- if self._check(TokenType.KEYWORD) and self._is_type_keyword(self._current().value):
750
- self._advance()
771
+ # Check for 'define' keyword (special case: const define myFunc())
772
+ if self._check(TokenType.KEYWORD) and self._current().value == 'define':
773
+ self.pos = saved_pos
774
+ return False # Let _parse_define handle this
751
775
 
752
- # Skip generic type parameters <T>
753
- if self._check(TokenType.COMPARE_LT):
754
- depth = 1
776
+ # Check for type keyword (int, string, void, vector, datastruct, etc.)
777
+ if self._check(TokenType.KEYWORD) and self._is_type_keyword(self._current().value):
755
778
  self._advance()
756
- while depth > 0 and not self._is_at_end():
757
- if self._check(TokenType.COMPARE_LT):
758
- depth += 1
759
- elif self._check(TokenType.COMPARE_GT):
760
- depth -= 1
779
+ has_type = True
780
+
781
+ # Skip generic type parameters <T> or <T, U>
782
+ if self._check(TokenType.COMPARE_LT):
783
+ depth = 1
761
784
  self._advance()
785
+ while depth > 0 and not self._is_at_end():
786
+ if self._check(TokenType.COMPARE_LT):
787
+ depth += 1
788
+ elif self._check(TokenType.COMPARE_GT):
789
+ depth -= 1
790
+ self._advance()
791
+
792
+ # Check for * prefix (non-null) or *[type] (type exclusion)
793
+ if self._check(TokenType.MULTIPLY):
794
+ self._advance()
795
+ # Check for type exclusion: *[string], *[int], etc.
796
+ if self._check(TokenType.BRACKET_START):
797
+ self._advance() # [
798
+ while not self._check(TokenType.BRACKET_END) and not self._is_at_end():
799
+ self._advance()
800
+ if self._check(TokenType.BRACKET_END):
801
+ self._advance() # ]
802
+
803
+ # Check for @ prefix (global function)
804
+ if self._check(TokenType.AT):
805
+ self._advance()
762
806
 
763
- # Check for identifier followed by (
807
+ # Now we should be at the function name (identifier)
764
808
  if self._check(TokenType.IDENTIFIER):
765
809
  self._advance()
766
- is_func = self._check(TokenType.PAREN_START)
767
- self.pos = saved_pos
768
- return is_func
769
810
 
770
- # If we have modifiers and the next token is an identifier followed by (
771
- # This handles: private super virtual meta FuncName()
772
- elif has_modifiers and self._check(TokenType.IDENTIFIER):
773
- self._advance()
774
- is_func = self._check(TokenType.PAREN_START)
811
+ # Check if followed by (
812
+ # IMPORTANT: Only a function declaration if we have modifiers OR type
813
+ # Plain identifier() is a function CALL, not a declaration
814
+ if self._check(TokenType.PAREN_START):
815
+ if has_modifiers or has_type:
816
+ self.pos = saved_pos
817
+ return True
818
+ else:
819
+ # No modifiers/type = function call, not declaration
820
+ self.pos = saved_pos
821
+ return False
822
+
823
+ # If we have a type and identifier but no (, it's a variable
824
+ if has_type and not self._check(TokenType.PAREN_START):
825
+ self.pos = saved_pos
826
+ return False
827
+
775
828
  self.pos = saved_pos
776
- return is_func
829
+ return False
777
830
 
778
- self.pos = saved_pos
779
- return False
831
+ except Exception:
832
+ self.pos = saved_pos
833
+ return False
780
834
 
781
835
  def _looks_like_typed_variable(self) -> bool:
782
836
  """Check if current position looks like a typed variable declaration.
@@ -816,51 +870,110 @@ class CSSLParser:
816
870
  self.pos = saved_pos
817
871
  return False
818
872
 
819
- def _parse_typed_function(self) -> ASTNode:
820
- """Parse C-style typed function declaration.
873
+ def _parse_typed_function(self, is_global: bool = False) -> ASTNode:
874
+ """Parse C-style typed function declaration with flexible modifier ordering.
875
+
876
+ Supports any order of modifiers, types, non-null (*), and global (@):
821
877
 
822
878
  Patterns:
823
879
  - int Add(int a, int b) { }
880
+ - global int Add(int a, int b) { }
881
+ - int @Add(int a, int b) { }
824
882
  - undefined int Func() { }
825
883
  - open void Handler(open Params) { }
826
884
  - vector<string> GetNames() { }
885
+ - private string *@Myfunc() { }
886
+ - const define myFunc() { }
887
+ - global private const void @Func() { }
888
+ - shuffled *[string] getNumbers() { }
889
+ - datastruct<dynamic> HelloCode() { }
890
+ - meta datastruct<string> MyData() { } // meta allows any returns
891
+ - datastruct<dynamic> HelloCode() : extends @MyFunc { }
892
+
893
+ Typed functions (with return type like int, string, void) MUST return that type.
894
+ Functions with 'meta' modifier can return any type regardless of declaration.
895
+ Functions with 'define' are dynamic (any return type allowed).
827
896
  """
828
897
  modifiers = []
829
898
  return_type = None
830
899
  generic_type = None
900
+ non_null = False
901
+ exclude_type = None
902
+ is_const = False
903
+
904
+ # Phase 1: Collect all modifiers, type, non-null, and global indicators
905
+ # These can appear in any order before the function name
906
+
907
+ parsing_prefix = True
908
+ while parsing_prefix and not self._is_at_end():
909
+ # Check for modifiers (global, private, const, undefined, etc.)
910
+ if self._check(TokenType.KEYWORD) and self._is_function_modifier(self._current().value):
911
+ mod = self._advance().value
912
+ if mod == 'global':
913
+ is_global = True
914
+ elif mod == 'const':
915
+ is_const = True
916
+ modifiers.append(mod)
917
+ else:
918
+ modifiers.append(mod)
919
+ continue
831
920
 
832
- # Collect modifiers (undefined, open, meta, super, closed, private, virtual)
833
- while self._check(TokenType.KEYWORD) and self._is_function_modifier(self._current().value):
834
- modifiers.append(self._advance().value)
921
+ # Check for type keyword (int, string, void, vector, datastruct, etc.)
922
+ if self._check(TokenType.KEYWORD) and self._is_type_keyword(self._current().value) and return_type is None:
923
+ return_type = self._advance().value
835
924
 
836
- # Get return type
837
- if self._check(TokenType.KEYWORD) and self._is_type_keyword(self._current().value):
838
- return_type = self._advance().value
925
+ # Check for generic type <T> or <T, U>
926
+ if self._check(TokenType.COMPARE_LT):
927
+ self._advance() # skip <
928
+ generic_parts = []
929
+ depth = 1
930
+ while depth > 0 and not self._is_at_end():
931
+ if self._check(TokenType.COMPARE_LT):
932
+ depth += 1
933
+ generic_parts.append('<')
934
+ elif self._check(TokenType.COMPARE_GT):
935
+ depth -= 1
936
+ if depth > 0:
937
+ generic_parts.append('>')
938
+ elif self._check(TokenType.COMMA):
939
+ generic_parts.append(',')
940
+ else:
941
+ generic_parts.append(str(self._current().value))
942
+ self._advance()
943
+ generic_type = ''.join(generic_parts)
944
+ continue
839
945
 
840
- # Check for generic type <T>
841
- if self._check(TokenType.COMPARE_LT):
842
- self._advance() # skip <
843
- generic_parts = []
844
- depth = 1
845
- while depth > 0 and not self._is_at_end():
846
- if self._check(TokenType.COMPARE_LT):
847
- depth += 1
848
- generic_parts.append('<')
849
- elif self._check(TokenType.COMPARE_GT):
850
- depth -= 1
851
- if depth > 0:
852
- generic_parts.append('>')
853
- elif self._check(TokenType.COMMA):
854
- generic_parts.append(',')
855
- else:
856
- generic_parts.append(self._current().value)
857
- self._advance()
858
- generic_type = ''.join(generic_parts)
946
+ # Check for * prefix (non-null) or *[type] (type exclusion)
947
+ if self._check(TokenType.MULTIPLY):
948
+ self._advance()
949
+ # Check for type exclusion filter: *[string], *[int], etc.
950
+ if self._check(TokenType.BRACKET_START):
951
+ self._advance() # consume [
952
+ exclude_type = self._advance().value # get type name
953
+ self._expect(TokenType.BRACKET_END)
954
+ else:
955
+ non_null = True
956
+ continue
957
+
958
+ # Check for @ prefix (global function)
959
+ if self._check(TokenType.AT):
960
+ self._advance()
961
+ is_global = True
962
+ continue
859
963
 
860
- # Get function name
964
+ # If we've reached an identifier, we're at the function name
965
+ if self._check(TokenType.IDENTIFIER):
966
+ parsing_prefix = False
967
+ else:
968
+ # Unknown token in prefix, break out
969
+ parsing_prefix = False
970
+
971
+ # Phase 2: Get function name
972
+ if not self._check(TokenType.IDENTIFIER):
973
+ self.error(f"Expected function name, got {self._current().type.name}")
861
974
  name = self._advance().value
862
975
 
863
- # Parse parameters
976
+ # Phase 3: Parse parameters
864
977
  params = []
865
978
  self._expect(TokenType.PAREN_START)
866
979
 
@@ -871,6 +984,10 @@ class CSSLParser:
871
984
  if self._match_keyword('open'):
872
985
  param_info['open'] = True
873
986
 
987
+ # Handle const parameters
988
+ if self._match_keyword('const'):
989
+ param_info['const'] = True
990
+
874
991
  # Handle type annotations (builtin types like int, string, etc.)
875
992
  if self._check(TokenType.KEYWORD) and self._is_type_keyword(self._current().value):
876
993
  param_info['type'] = self._advance().value
@@ -891,13 +1008,12 @@ class CSSLParser:
891
1008
  elif self._check(TokenType.COMMA):
892
1009
  generic_parts.append(',')
893
1010
  else:
894
- generic_parts.append(self._current().value)
1011
+ generic_parts.append(str(self._current().value))
895
1012
  self._advance()
896
1013
  param_info['generic'] = ''.join(generic_parts)
897
1014
 
898
1015
  # Handle custom class types (identifier followed by another identifier = type + name)
899
1016
  elif self._check(TokenType.IDENTIFIER):
900
- # Look ahead: if next token is also an identifier, current is the type
901
1017
  saved_pos = self.pos
902
1018
  potential_type = self._advance().value
903
1019
 
@@ -917,7 +1033,7 @@ class CSSLParser:
917
1033
  elif self._check(TokenType.COMMA):
918
1034
  generic_parts.append(',')
919
1035
  else:
920
- generic_parts.append(self._current().value)
1036
+ generic_parts.append(str(self._current().value))
921
1037
  self._advance()
922
1038
  param_info['generic'] = ''.join(generic_parts)
923
1039
 
@@ -928,6 +1044,10 @@ class CSSLParser:
928
1044
  # Not a type, restore position - this is just a param name
929
1045
  self.pos = saved_pos
930
1046
 
1047
+ # Handle * prefix for non-null parameters
1048
+ if self._match(TokenType.MULTIPLY):
1049
+ param_info['non_null'] = True
1050
+
931
1051
  # Handle reference operator &
932
1052
  if self._match(TokenType.AMPERSAND):
933
1053
  param_info['ref'] = True
@@ -940,7 +1060,7 @@ class CSSLParser:
940
1060
  else:
941
1061
  params.append(param_name)
942
1062
  elif self._check(TokenType.KEYWORD):
943
- # Parameter name could be a keyword
1063
+ # Parameter name could be a keyword like 'Params'
944
1064
  param_name = self._advance().value
945
1065
  if param_info:
946
1066
  params.append({'name': param_name, **param_info})
@@ -951,13 +1071,104 @@ class CSSLParser:
951
1071
 
952
1072
  self._expect(TokenType.PAREN_END)
953
1073
 
954
- # Parse function body
1074
+ # Phase 4: Check for extends/overwrites and append mode
1075
+ extends_func = None
1076
+ extends_is_python = False
1077
+ extends_class_ref = None
1078
+ extends_method_ref = None
1079
+ overwrites_func = None
1080
+ overwrites_is_python = False
1081
+ overwrites_class_ref = None
1082
+ overwrites_method_ref = None
1083
+ append_mode = False
1084
+ append_ref_class = None
1085
+ append_ref_member = None
1086
+
1087
+ # Check for &ClassName::member reference
1088
+ if self._match(TokenType.AMPERSAND):
1089
+ if self._check(TokenType.IDENTIFIER):
1090
+ append_ref_class = self._advance().value
1091
+ elif self._check(TokenType.AT):
1092
+ self._advance()
1093
+ if self._check(TokenType.IDENTIFIER):
1094
+ append_ref_class = '@' + self._advance().value
1095
+ elif self._check(TokenType.SHARED_REF):
1096
+ append_ref_class = f'${self._advance().value}'
1097
+
1098
+ # Check for ::member
1099
+ if self._match(TokenType.DOUBLE_COLON):
1100
+ if self._check(TokenType.IDENTIFIER) or self._check(TokenType.KEYWORD):
1101
+ append_ref_member = self._advance().value
1102
+
1103
+ # Check for ++ append operator
1104
+ if self._match(TokenType.PLUS_PLUS):
1105
+ append_mode = True
1106
+
1107
+ # Check for : or :: extends/overwrites
1108
+ if self._match(TokenType.DOUBLE_COLON) or self._match(TokenType.COLON):
1109
+ while True:
1110
+ if self._match_keyword('extends'):
1111
+ # Parse target: @ModuleName, $PythonObject, Parent::method
1112
+ if self._check(TokenType.AT):
1113
+ self._advance()
1114
+ extends_func = '@' + self._advance().value
1115
+ elif self._check(TokenType.SHARED_REF):
1116
+ extends_is_python = True
1117
+ extends_func = self._advance().value
1118
+ elif self._check(TokenType.IDENTIFIER):
1119
+ first_part = self._advance().value
1120
+ if self._match(TokenType.DOUBLE_COLON):
1121
+ extends_class_ref = first_part
1122
+ extends_method_ref = self._advance().value
1123
+ else:
1124
+ extends_func = first_part
1125
+ # Skip optional ()
1126
+ if self._match(TokenType.PAREN_START):
1127
+ self._expect(TokenType.PAREN_END)
1128
+ elif self._match_keyword('overwrites'):
1129
+ if self._check(TokenType.AT):
1130
+ self._advance()
1131
+ overwrites_func = '@' + self._advance().value
1132
+ elif self._check(TokenType.SHARED_REF):
1133
+ overwrites_is_python = True
1134
+ overwrites_func = self._advance().value
1135
+ elif self._check(TokenType.IDENTIFIER):
1136
+ first_part = self._advance().value
1137
+ if self._match(TokenType.DOUBLE_COLON):
1138
+ overwrites_class_ref = first_part
1139
+ overwrites_method_ref = self._advance().value
1140
+ else:
1141
+ overwrites_func = first_part
1142
+ if self._match(TokenType.PAREN_START):
1143
+ self._expect(TokenType.PAREN_END)
1144
+ else:
1145
+ break
1146
+ if not (self._match(TokenType.DOUBLE_COLON) or self._match(TokenType.COLON)):
1147
+ break
1148
+
1149
+ # Phase 5: Parse function body
955
1150
  node = ASTNode('function', value={
956
1151
  'name': name,
1152
+ 'is_global': is_global,
1153
+ 'is_const': is_const,
957
1154
  'params': params,
958
1155
  'return_type': return_type,
959
1156
  'generic_type': generic_type,
960
- 'modifiers': modifiers
1157
+ 'modifiers': modifiers,
1158
+ 'non_null': non_null,
1159
+ 'exclude_type': exclude_type,
1160
+ 'extends': extends_func,
1161
+ 'extends_is_python': extends_is_python,
1162
+ 'extends_class': extends_class_ref,
1163
+ 'extends_method': extends_method_ref,
1164
+ 'overwrites': overwrites_func,
1165
+ 'overwrites_is_python': overwrites_is_python,
1166
+ 'overwrites_class': overwrites_class_ref,
1167
+ 'overwrites_method': overwrites_method_ref,
1168
+ 'append_mode': append_mode,
1169
+ 'append_ref_class': append_ref_class,
1170
+ 'append_ref_member': append_ref_member,
1171
+ 'enforce_return_type': return_type is not None and 'meta' not in modifiers
961
1172
  }, children=[])
962
1173
 
963
1174
  self._expect(TokenType.BLOCK_START)
@@ -1117,19 +1328,30 @@ class CSSLParser:
1117
1328
  root.children.append(self._parse_package_includes())
1118
1329
  # Handle global declarations
1119
1330
  elif self._match_keyword('global'):
1120
- stmt = self._parse_expression_statement()
1121
- if stmt:
1122
- # Wrap in global_assignment to mark as global variable
1123
- global_stmt = ASTNode('global_assignment', value=stmt)
1124
- root.children.append(global_stmt)
1331
+ # Check if followed by class or define (global class/function)
1332
+ if self._match_keyword('class'):
1333
+ root.children.append(self._parse_class(is_global=True))
1334
+ elif self._match_keyword('define'):
1335
+ root.children.append(self._parse_define(is_global=True))
1336
+ elif self._looks_like_function_declaration():
1337
+ # global void MyFunc() { } or global int MyFunc() { }
1338
+ root.children.append(self._parse_typed_function(is_global=True))
1339
+ else:
1340
+ stmt = self._parse_expression_statement()
1341
+ if stmt:
1342
+ # Wrap in global_assignment to mark as global variable
1343
+ global_stmt = ASTNode('global_assignment', value=stmt)
1344
+ root.children.append(global_stmt)
1125
1345
  elif self._check(TokenType.GLOBAL_REF):
1126
1346
  stmt = self._parse_expression_statement()
1127
1347
  if stmt:
1128
1348
  # Wrap in global_assignment to mark as global variable (same as 'global' keyword)
1129
1349
  global_stmt = ASTNode('global_assignment', value=stmt)
1130
1350
  root.children.append(global_stmt)
1131
- # Handle statements
1132
- elif self._check(TokenType.IDENTIFIER) or self._check(TokenType.AT) or self._check(TokenType.SELF_REF) or self._check(TokenType.SHARED_REF):
1351
+ # Handle statements - keywords like 'instance', 'list', 'map' can be variable names
1352
+ elif (self._check(TokenType.IDENTIFIER) or self._check(TokenType.AT) or
1353
+ self._check(TokenType.SELF_REF) or self._check(TokenType.SHARED_REF) or
1354
+ self._check(TokenType.KEYWORD)):
1133
1355
  stmt = self._parse_expression_statement()
1134
1356
  if stmt:
1135
1357
  root.children.append(stmt)
@@ -1366,20 +1588,14 @@ class CSSLParser:
1366
1588
  self._expect(TokenType.BLOCK_END)
1367
1589
  return node
1368
1590
 
1369
- def _parse_class(self) -> ASTNode:
1591
+ def _parse_class(self, is_global: bool = False) -> ASTNode:
1370
1592
  """Parse class declaration with members and methods.
1371
1593
 
1372
1594
  Syntax:
1373
- class ClassName {
1374
- string name;
1375
- int age;
1376
-
1377
- void ClassName(string n) { this->name = n; }
1378
-
1379
- void sayHello() {
1380
- printl("Hello " + this->name);
1381
- }
1382
- }
1595
+ class ClassName { ... } // Local class
1596
+ global class ClassName { ... } // Global class
1597
+ class @ClassName { ... } // Global class (alternative)
1598
+ class *ClassName { ... } // Non-null class
1383
1599
 
1384
1600
  Non-null class (all methods return non-null):
1385
1601
  class *MyClass { ... }
@@ -1389,6 +1605,11 @@ class CSSLParser:
1389
1605
  if self._match(TokenType.MULTIPLY):
1390
1606
  non_null = True
1391
1607
 
1608
+ # Check for @ prefix (global class): class @ClassName
1609
+ if self._check(TokenType.AT):
1610
+ self._advance() # consume @
1611
+ is_global = True
1612
+
1392
1613
  class_name = self._advance().value
1393
1614
 
1394
1615
  # Check for class-level constructor parameters: class MyClass (int x, string y) { ... }
@@ -1445,6 +1666,7 @@ class CSSLParser:
1445
1666
 
1446
1667
  node = ASTNode('class', value={
1447
1668
  'name': class_name,
1669
+ 'is_global': is_global,
1448
1670
  'non_null': non_null,
1449
1671
  'class_params': class_params,
1450
1672
  'extends': extends_class,
@@ -1679,20 +1901,35 @@ class CSSLParser:
1679
1901
 
1680
1902
  return params
1681
1903
 
1682
- def _parse_define(self) -> ASTNode:
1904
+ def _parse_define(self, is_global: bool = False) -> ASTNode:
1683
1905
  """Parse define function declaration.
1684
1906
 
1685
1907
  Syntax:
1686
- define MyFunc(args) { }
1687
- define *MyFunc(args) { } // Non-null: must never return None
1908
+ define MyFunc(args) { } // Local function
1909
+ global define MyFunc(args) { } // Global function
1910
+ define @MyFunc(args) { } // Global function (alternative)
1911
+ define *MyFunc(args) { } // Non-null: must never return None
1688
1912
  define MyFunc : extends OtherFunc() { } // Inherit local vars
1689
1913
  define MyFunc : overwrites OtherFunc() { } // Replace OtherFunc
1690
1914
  define MyFunc :: extends Parent::Method :: overwrites Parent::Method() { } // Method-level inheritance
1691
1915
  """
1692
1916
  # Check for * prefix (non-null function - must return non-null)
1917
+ # Also *[type] for type exclusion (must NOT return that type)
1693
1918
  non_null = False
1919
+ exclude_type = None
1694
1920
  if self._match(TokenType.MULTIPLY):
1695
- non_null = True
1921
+ # Check for type exclusion filter: *[string], *[int], etc.
1922
+ if self._check(TokenType.BRACKET_START):
1923
+ self._advance() # consume [
1924
+ exclude_type = self._advance().value # get type name
1925
+ self._expect(TokenType.BRACKET_END)
1926
+ else:
1927
+ non_null = True
1928
+
1929
+ # Check for @ prefix (global function): define @FuncName
1930
+ if self._check(TokenType.AT):
1931
+ self._advance() # consume @
1932
+ is_global = True
1696
1933
 
1697
1934
  name = self._advance().value
1698
1935
 
@@ -1837,8 +2074,10 @@ class CSSLParser:
1837
2074
 
1838
2075
  node = ASTNode('function', value={
1839
2076
  'name': name,
2077
+ 'is_global': is_global,
1840
2078
  'params': params,
1841
2079
  'non_null': non_null,
2080
+ 'exclude_type': exclude_type, # *[type] - must NOT return this type
1842
2081
  'extends': extends_func,
1843
2082
  'extends_is_python': extends_is_python,
1844
2083
  'overwrites': overwrites_func,
@@ -2712,6 +2951,26 @@ class CSSLParser:
2712
2951
  operand = self._parse_unary()
2713
2952
  return ASTNode('reference', value=operand)
2714
2953
 
2954
+ # Non-null assertion: *$var, *@module, *identifier
2955
+ # Also type exclusion filter: *[type]expr - exclude type from return
2956
+ if self._check(TokenType.MULTIPLY):
2957
+ next_token = self._peek(1)
2958
+
2959
+ # Check for type exclusion filter: *[string], *[int], etc.
2960
+ if next_token and next_token.type == TokenType.BRACKET_START:
2961
+ self._advance() # consume *
2962
+ self._advance() # consume [
2963
+ exclude_type = self._advance().value # get type name
2964
+ self._expect(TokenType.BRACKET_END)
2965
+ operand = self._parse_unary()
2966
+ return ASTNode('type_exclude_assert', value={'exclude_type': exclude_type, 'operand': operand})
2967
+
2968
+ # Non-null assertion when followed by $ (shared ref), @ (global), or identifier
2969
+ if next_token and next_token.type in (TokenType.SHARED_REF, TokenType.AT, TokenType.IDENTIFIER):
2970
+ self._advance() # consume *
2971
+ operand = self._parse_unary()
2972
+ return ASTNode('non_null_assert', value={'operand': operand})
2973
+
2715
2974
  return self._parse_primary()
2716
2975
 
2717
2976
  def _parse_primary(self) -> ASTNode:
@@ -2748,16 +3007,21 @@ class CSSLParser:
2748
3007
  # Just 'this' keyword alone - return as identifier for now
2749
3008
  return ASTNode('identifier', value='this')
2750
3009
 
2751
- # Handle 'new ClassName(args)' instantiation
3010
+ # Handle 'new ClassName(args)' or 'new @ClassName(args)' instantiation
2752
3011
  if self._check(TokenType.KEYWORD) and self._current().value == 'new':
2753
3012
  self._advance() # consume 'new'
3013
+ # Check for @ prefix (global class reference)
3014
+ is_global_ref = False
3015
+ if self._check(TokenType.AT):
3016
+ self._advance() # consume @
3017
+ is_global_ref = True
2754
3018
  class_name = self._advance().value # get class name
2755
3019
  args = []
2756
3020
  kwargs = {}
2757
3021
  if self._match(TokenType.PAREN_START):
2758
3022
  args, kwargs = self._parse_call_arguments()
2759
3023
  self._expect(TokenType.PAREN_END)
2760
- node = ASTNode('new', value={'class': class_name, 'args': args, 'kwargs': kwargs})
3024
+ node = ASTNode('new', value={'class': class_name, 'args': args, 'kwargs': kwargs, 'is_global_ref': is_global_ref})
2761
3025
  # Continue to check for member access, calls on the new object
2762
3026
  while True:
2763
3027
  if self._match(TokenType.DOT):
@@ -2776,7 +3040,18 @@ class CSSLParser:
2776
3040
  return node
2777
3041
 
2778
3042
  if self._match(TokenType.AT):
3043
+ # Check for @* (global non-null reference): @*name
3044
+ is_non_null = False
3045
+ if self._check(TokenType.MULTIPLY):
3046
+ self._advance() # consume *
3047
+ is_non_null = True
3048
+
2779
3049
  node = self._parse_module_reference()
3050
+
3051
+ # Wrap in non_null_assert if @* was used
3052
+ if is_non_null:
3053
+ node = ASTNode('non_null_assert', value={'operand': node, 'is_global': True})
3054
+
2780
3055
  # Continue to check for calls, indexing, member access on module refs
2781
3056
  while True:
2782
3057
  if self._match(TokenType.PAREN_START):