IncludeCPP 3.7.27__tar.gz → 3.8.2__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.7.27 → includecpp-3.8.2}/IncludeCPP.egg-info/PKG-INFO +1 -1
  2. {includecpp-3.7.27 → includecpp-3.8.2}/PKG-INFO +1 -1
  3. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/__init__.py +1 -1
  4. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/cli/commands.py +26 -6
  5. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/cssl/cssl_builtins.py +2 -1
  6. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/cssl/cssl_parser.py +52 -6
  7. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/cssl/cssl_runtime.py +75 -10
  8. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/vscode/cssl/package.json +1 -1
  9. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/vscode/cssl/syntaxes/cssl.tmLanguage.json +54 -0
  10. {includecpp-3.7.27 → includecpp-3.8.2}/pyproject.toml +1 -1
  11. {includecpp-3.7.27 → includecpp-3.8.2}/IncludeCPP.egg-info/SOURCES.txt +0 -0
  12. {includecpp-3.7.27 → includecpp-3.8.2}/IncludeCPP.egg-info/dependency_links.txt +0 -0
  13. {includecpp-3.7.27 → includecpp-3.8.2}/IncludeCPP.egg-info/entry_points.txt +0 -0
  14. {includecpp-3.7.27 → includecpp-3.8.2}/IncludeCPP.egg-info/requires.txt +0 -0
  15. {includecpp-3.7.27 → includecpp-3.8.2}/IncludeCPP.egg-info/top_level.txt +0 -0
  16. {includecpp-3.7.27 → includecpp-3.8.2}/LICENSE +0 -0
  17. {includecpp-3.7.27 → includecpp-3.8.2}/MANIFEST.in +0 -0
  18. {includecpp-3.7.27 → includecpp-3.8.2}/README.md +0 -0
  19. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/__init__.pyi +0 -0
  20. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/__main__.py +0 -0
  21. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/cli/__init__.py +0 -0
  22. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/cli/config_parser.py +0 -0
  23. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/__init__.py +0 -0
  24. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/ai_integration.py +0 -0
  25. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/build_manager.py +0 -0
  26. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/cpp_api.py +0 -0
  27. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/cpp_api.pyi +0 -0
  28. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/cppy_converter.py +0 -0
  29. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/cssl/CSSL_DOCUMENTATION.md +0 -0
  30. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/cssl/__init__.py +0 -0
  31. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/cssl/cssl_builtins.pyi +0 -0
  32. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/cssl/cssl_events.py +0 -0
  33. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/cssl/cssl_modules.py +0 -0
  34. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/cssl/cssl_syntax.py +0 -0
  35. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/cssl/cssl_types.py +0 -0
  36. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/cssl_bridge.py +0 -0
  37. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/cssl_bridge.pyi +0 -0
  38. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/error_catalog.py +0 -0
  39. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/error_formatter.py +0 -0
  40. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/exceptions.py +0 -0
  41. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/path_discovery.py +0 -0
  42. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/project_ui.py +0 -0
  43. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/settings_ui.py +0 -0
  44. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/generator/__init__.py +0 -0
  45. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/generator/parser.cpp +0 -0
  46. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/generator/parser.h +0 -0
  47. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/generator/type_resolver.cpp +0 -0
  48. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/generator/type_resolver.h +0 -0
  49. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/py.typed +0 -0
  50. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/templates/cpp.proj.template +0 -0
  51. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/vscode/__init__.py +0 -0
  52. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/vscode/cssl/__init__.py +0 -0
  53. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/vscode/cssl/extension.js +0 -0
  54. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/vscode/cssl/images/cssl.png +0 -0
  55. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/vscode/cssl/images/cssl_pl.png +0 -0
  56. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/vscode/cssl/language-configuration.json +0 -0
  57. {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/vscode/cssl/snippets/cssl.snippets.json +0 -0
  58. {includecpp-3.7.27 → includecpp-3.8.2}/requirements.txt +0 -0
  59. {includecpp-3.7.27 → includecpp-3.8.2}/setup.cfg +0 -0
  60. {includecpp-3.7.27 → includecpp-3.8.2}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: IncludeCPP
3
- Version: 3.7.27
3
+ Version: 3.8.2
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.7.27
3
+ Version: 3.8.2
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.7.27"
5
+ __version__ = "3.8.2"
6
6
  __all__ = ["CppApi", "CSSL"]
7
7
 
8
8
  # Module-level cache for C++ modules
@@ -7457,11 +7457,24 @@ def cssl():
7457
7457
  pass
7458
7458
 
7459
7459
 
7460
+ @cssl.command(name='run')
7461
+ @click.argument('path', required=False, type=click.Path())
7462
+ @click.option('--code', '-c', type=str, help='Execute code directly')
7463
+ def cssl_run(path, code):
7464
+ """Run/execute CSSL code or file."""
7465
+ _cssl_execute(path, code)
7466
+
7467
+
7460
7468
  @cssl.command(name='exec')
7461
7469
  @click.argument('path', required=False, type=click.Path())
7462
7470
  @click.option('--code', '-c', type=str, help='Execute code directly')
7463
7471
  def cssl_exec(path, code):
7464
- """Execute CSSL code or file."""
7472
+ """Execute CSSL code or file (alias for 'run')."""
7473
+ _cssl_execute(path, code)
7474
+
7475
+
7476
+ def _cssl_execute(path, code):
7477
+ """Internal: Execute CSSL code or file."""
7465
7478
  from pathlib import Path as PathLib
7466
7479
 
7467
7480
  try:
@@ -7923,16 +7936,18 @@ cli.add_command(cssl)
7923
7936
 
7924
7937
  @cli.command()
7925
7938
  @click.option('--force', '-f', is_flag=True, help='Force overwrite existing files')
7939
+ @click.option('--reinstall', '-r', is_flag=True, help='Reinstall extension (removes all versions first)')
7926
7940
  @click.option('--stubs-only', is_flag=True, help='Only update stubs, skip extension files')
7927
- def vscode(force, stubs_only):
7941
+ def vscode(force, reinstall, stubs_only):
7928
7942
  """Initialize or update VSCode configuration for IncludeCPP/CSSL.
7929
7943
 
7930
7944
  Installs CSSL extension globally and sets up project stubs.
7931
7945
 
7932
7946
  \b
7933
7947
  Usage:
7934
- includecpp vscode # Install/update extension + stubs
7935
- includecpp vscode --force # Force reinstall extension
7948
+ includecpp vscode # Install/update extension + stubs
7949
+ includecpp vscode --force # Force reinstall extension
7950
+ includecpp vscode --reinstall # Remove ALL versions & reinstall fresh
7936
7951
  includecpp vscode --stubs-only # Only update stubs
7937
7952
 
7938
7953
  \b
@@ -7999,13 +8014,18 @@ def vscode(force, stubs_only):
7999
8014
  target_dir = global_ext_dir / f'includecpp.cssl-{current_version}'
8000
8015
 
8001
8016
  # Check if already installed with same or older version
8002
- needs_install = force
8017
+ needs_install = force or reinstall
8003
8018
  existing_version = None
8004
8019
 
8005
8020
  # Find existing installations
8006
8021
  for existing in global_ext_dir.glob('includecpp.cssl-*'):
8007
8022
  existing_version = existing.name.split('-')[-1]
8008
- if existing_version != current_version:
8023
+ if reinstall:
8024
+ # --reinstall: Remove ALL versions
8025
+ click.echo(f" Removing version: {existing_version}")
8026
+ shutil.rmtree(existing)
8027
+ needs_install = True
8028
+ elif existing_version != current_version:
8009
8029
  # Remove old version
8010
8030
  click.echo(f" Removing old version: {existing_version}")
8011
8031
  shutil.rmtree(existing)
@@ -2612,7 +2612,8 @@ class PythonizedMethod:
2612
2612
  raise RuntimeError(f"Cannot call method '{self._method_name}' - no runtime available")
2613
2613
 
2614
2614
  # Execute the method through the runtime
2615
- result = self._runtime._call_method(self._instance, self._method_name, list(args))
2615
+ # Pass the method AST node, not the method name
2616
+ result = self._runtime._call_method(self._instance, self._method_ast, list(args), kwargs)
2616
2617
 
2617
2618
  # Pythonize the result if it's a CSSL instance
2618
2619
  from .cssl_types import CSSLInstance
@@ -1025,7 +1025,11 @@ class CSSLParser:
1025
1025
  return result
1026
1026
 
1027
1027
  def _parse_typed_variable(self) -> Optional[ASTNode]:
1028
- """Parse a typed variable declaration: type varName; or type<T> varName = value;"""
1028
+ """Parse a typed variable declaration: type varName; or type<T> *varName = value;
1029
+
1030
+ The * prefix indicates a non-nullable variable (can never be None/null).
1031
+ Example: vector<dynamic> *MyVector - can never contain None values.
1032
+ """
1029
1033
  # Get type name
1030
1034
  type_name = self._advance().value # Consume type keyword
1031
1035
 
@@ -1039,6 +1043,11 @@ class CSSLParser:
1039
1043
  element_type = self._advance().value
1040
1044
  self._expect(TokenType.COMPARE_GT)
1041
1045
 
1046
+ # Check for * prefix (non-nullable indicator)
1047
+ non_null = False
1048
+ if self._match(TokenType.ASTERISK):
1049
+ non_null = True
1050
+
1042
1051
  # Get variable name
1043
1052
  if not self._check(TokenType.IDENTIFIER):
1044
1053
  return None
@@ -1056,14 +1065,16 @@ class CSSLParser:
1056
1065
  return ASTNode('instance_declaration', value={
1057
1066
  'instance_name': element_type,
1058
1067
  'name': var_name,
1059
- 'value': value
1068
+ 'value': value,
1069
+ 'non_null': non_null
1060
1070
  })
1061
1071
 
1062
1072
  return ASTNode('typed_declaration', value={
1063
1073
  'type': type_name,
1064
1074
  'element_type': element_type,
1065
1075
  'name': var_name,
1066
- 'value': value
1076
+ 'value': value,
1077
+ 'non_null': non_null
1067
1078
  })
1068
1079
 
1069
1080
  def parse_program(self) -> ASTNode:
@@ -1361,10 +1372,18 @@ class CSSLParser:
1361
1372
  printl("Hello " + this->name);
1362
1373
  }
1363
1374
  }
1375
+
1376
+ Non-null class (all methods return non-null):
1377
+ class *MyClass { ... }
1364
1378
  """
1379
+ # Check for * prefix (non-null class - all methods return non-null)
1380
+ non_null = False
1381
+ if self._match(TokenType.ASTERISK):
1382
+ non_null = True
1383
+
1365
1384
  class_name = self._advance().value
1366
1385
 
1367
- node = ASTNode('class', value={'name': class_name}, children=[])
1386
+ node = ASTNode('class', value={'name': class_name, 'non_null': non_null}, children=[])
1368
1387
  self._expect(TokenType.BLOCK_START)
1369
1388
 
1370
1389
  while not self._check(TokenType.BLOCK_END) and not self._is_at_end():
@@ -1400,6 +1419,17 @@ class CSSLParser:
1400
1419
  return node
1401
1420
 
1402
1421
  def _parse_define(self) -> ASTNode:
1422
+ """Parse define function declaration.
1423
+
1424
+ Syntax:
1425
+ define MyFunc(args) { }
1426
+ define *MyFunc(args) { } // Non-null: must never return None
1427
+ """
1428
+ # Check for * prefix (non-null function - must return non-null)
1429
+ non_null = False
1430
+ if self._match(TokenType.ASTERISK):
1431
+ non_null = True
1432
+
1403
1433
  name = self._advance().value
1404
1434
  params = []
1405
1435
 
@@ -1415,6 +1445,9 @@ class CSSLParser:
1415
1445
  # Handle reference operator &
1416
1446
  if self._match(TokenType.AMPERSAND):
1417
1447
  param_info['ref'] = True
1448
+ # Handle * prefix for non-null parameters
1449
+ if self._match(TokenType.ASTERISK):
1450
+ param_info['non_null'] = True
1418
1451
  # Get parameter name
1419
1452
  if self._check(TokenType.IDENTIFIER):
1420
1453
  param_name = self._advance().value
@@ -1435,7 +1468,7 @@ class CSSLParser:
1435
1468
  break
1436
1469
  self._expect(TokenType.PAREN_END)
1437
1470
 
1438
- node = ASTNode('function', value={'name': name, 'params': params}, children=[])
1471
+ node = ASTNode('function', value={'name': name, 'params': params, 'non_null': non_null}, children=[])
1439
1472
  self._expect(TokenType.BLOCK_START)
1440
1473
 
1441
1474
  while not self._check(TokenType.BLOCK_END) and not self._is_at_end():
@@ -2610,12 +2643,24 @@ class CSSLParser:
2610
2643
  'init_values': init_values
2611
2644
  })
2612
2645
 
2613
- # Check for type-parameterized function call: OpenFind<string>(0)
2646
+ # Check for type-parameterized function call: OpenFind<string>(0) or OpenFind<dynamic, "name">
2614
2647
  if name in TYPE_PARAM_FUNCTIONS and self._check(TokenType.COMPARE_LT):
2615
2648
  self._advance() # consume <
2616
2649
  type_param = 'dynamic'
2650
+ param_name = None # Optional: named parameter search
2651
+
2617
2652
  if self._check(TokenType.KEYWORD) or self._check(TokenType.IDENTIFIER):
2618
2653
  type_param = self._advance().value
2654
+
2655
+ # Check for second parameter: OpenFind<type, "name">
2656
+ if self._check(TokenType.COMMA):
2657
+ self._advance() # consume comma
2658
+ # Expect a string literal for the parameter name
2659
+ if self._check(TokenType.STRING):
2660
+ param_name = self._advance().value
2661
+ elif self._check(TokenType.IDENTIFIER):
2662
+ param_name = self._advance().value
2663
+
2619
2664
  self._expect(TokenType.COMPARE_GT) # consume >
2620
2665
 
2621
2666
  # Must be followed by ()
@@ -2632,6 +2677,7 @@ class CSSLParser:
2632
2677
  return ASTNode('typed_call', value={
2633
2678
  'name': name,
2634
2679
  'type_param': type_param,
2680
+ 'param_name': param_name, # Named parameter for OpenFind
2635
2681
  'args': args
2636
2682
  })
2637
2683
 
@@ -772,12 +772,16 @@ class CSSLRuntime:
772
772
  """Execute typed variable declaration: type<T> varName = value;
773
773
 
774
774
  Creates appropriate type instances for stack, vector, datastruct, etc.
775
+
776
+ The * prefix indicates a non-nullable variable (can never be None/null).
777
+ Example: vector<dynamic> *MyVector - can never contain None values.
775
778
  """
776
779
  decl = node.value
777
780
  type_name = decl.get('type')
778
781
  element_type = decl.get('element_type', 'dynamic')
779
782
  var_name = decl.get('name')
780
783
  value_node = decl.get('value')
784
+ non_null = decl.get('non_null', False)
781
785
 
782
786
  # Create the appropriate type instance
783
787
  if type_name == 'stack':
@@ -825,11 +829,32 @@ class CSSLRuntime:
825
829
  # For container types, the value might be initialization data
826
830
  init_value = self._evaluate(value_node)
827
831
  if isinstance(init_value, (list, tuple)):
832
+ # For non-null containers, filter out None values
833
+ if non_null:
834
+ init_value = [v for v in init_value if v is not None]
828
835
  instance.extend(init_value)
829
836
  elif init_value is not None:
830
837
  if hasattr(instance, 'append'):
831
838
  instance.append(init_value)
832
839
 
840
+ # Non-null enforcement: container types get wrapped to filter None on operations
841
+ if non_null:
842
+ # Mark the instance as non-null for runtime checks
843
+ if hasattr(instance, '_non_null'):
844
+ instance._non_null = True
845
+ # Track non-null variables for assignment enforcement
846
+ if not hasattr(self, '_non_null_vars'):
847
+ self._non_null_vars = set()
848
+ self._non_null_vars.add(var_name)
849
+
850
+ # Ensure initial value is not None for non-null variables
851
+ if instance is None:
852
+ raise CSSLRuntimeError(
853
+ f"Non-null variable '*{var_name}' cannot be initialized to None",
854
+ node.line,
855
+ hint="Use a default value or remove the * prefix"
856
+ )
857
+
833
858
  # Check for global modifier
834
859
  modifiers = decl.get('modifiers', [])
835
860
  is_global = 'global' in modifiers
@@ -1031,8 +1056,16 @@ class CSSLRuntime:
1031
1056
  # Check if this is an 'open' parameter - receives all args as a list
1032
1057
  if param_type == 'open' or param_name == 'Params':
1033
1058
  # 'open Params' receives all arguments as a list
1034
- new_scope.set(param_name, list(args))
1035
- new_scope.set('Params', list(args)) # Also set 'Params' for OpenFind
1059
+ # Check for non_null flag: open *Params filters out None values
1060
+ is_non_null = isinstance(param, dict) and param.get('non_null', False)
1061
+ args_list = list(args)
1062
+ if is_non_null:
1063
+ args_list = [a for a in args_list if a is not None]
1064
+ # Also filter kwargs
1065
+ kwargs = {k: v for k, v in kwargs.items() if v is not None}
1066
+ new_scope.set(param_name, args_list)
1067
+ new_scope.set('Params', args_list) # Also set 'Params' for OpenFind
1068
+ new_scope.set('_OpenKwargs', kwargs) # Store kwargs for OpenFind<type, "name">
1036
1069
  elif param_name in kwargs:
1037
1070
  # Named argument takes priority
1038
1071
  new_scope.set(param_name, kwargs[param_name])
@@ -2186,7 +2219,12 @@ class CSSLRuntime:
2186
2219
 
2187
2220
  if isinstance(target, ASTNode):
2188
2221
  if target.type == 'identifier':
2189
- self.scope.set(target.value, value)
2222
+ # Check if we're in a class method and this is a class member
2223
+ # If so, set the member instead of creating a local variable
2224
+ if self._current_instance is not None and self._current_instance.has_member(target.value):
2225
+ self._current_instance.set_member(target.value, value)
2226
+ else:
2227
+ self.scope.set(target.value, value)
2190
2228
  elif target.type == 'global_ref':
2191
2229
  # r@Name = value - store in promoted globals
2192
2230
  self._promoted_globals[target.value] = value
@@ -2303,6 +2341,9 @@ class CSSLRuntime:
2303
2341
 
2304
2342
  if node.type == 'literal':
2305
2343
  value = node.value
2344
+ # Handle dict-format literals from parser: {'type': 'int', 'value': 0}
2345
+ if isinstance(value, dict) and 'value' in value:
2346
+ value = value['value']
2306
2347
  # String interpolation - replace {var} or <var> with scope values
2307
2348
  if isinstance(value, str):
2308
2349
  has_fstring = '{' in value and '}' in value
@@ -2323,6 +2364,16 @@ class CSSLRuntime:
2323
2364
  if node.type == 'identifier':
2324
2365
  name = node.value
2325
2366
  value = self.scope.get(name)
2367
+ # Check if it's a class member in current instance context
2368
+ # This allows accessing members without 'this->' inside methods
2369
+ if value is None and self._current_instance is not None:
2370
+ if self._current_instance.has_member(name):
2371
+ value = self._current_instance.get_member(name)
2372
+ elif self._current_instance.has_method(name):
2373
+ # Return bound method
2374
+ method_node = self._current_instance.get_method(name)
2375
+ instance = self._current_instance
2376
+ value = lambda *args, **kwargs: self._call_method(instance, method_node, list(args), kwargs)
2326
2377
  # Fallback to global scope
2327
2378
  if value is None:
2328
2379
  value = self.global_scope.get(name)
@@ -2768,19 +2819,20 @@ class CSSLRuntime:
2768
2819
  )
2769
2820
 
2770
2821
  def _eval_typed_call(self, node: ASTNode) -> Any:
2771
- """Evaluate typed function call like OpenFind<string>(0)"""
2822
+ """Evaluate typed function call like OpenFind<string>(0) or OpenFind<dynamic, "name">"""
2772
2823
  name = node.value.get('name')
2773
2824
  type_param = node.value.get('type_param', 'dynamic')
2825
+ param_name = node.value.get('param_name') # For OpenFind<type, "name">
2774
2826
  args = [self._evaluate(a) for a in node.value.get('args', [])]
2775
2827
 
2776
- # Handle OpenFind<type>(index)
2828
+ # Handle OpenFind<type>(index) or OpenFind<type, "name">
2777
2829
  if name == 'OpenFind':
2778
2830
  # OpenFind searches for a value of the specified type
2779
2831
  # from the open parameters in scope
2780
2832
  open_params = self.scope.get('Params') or []
2781
- index = args[0] if args else 0
2833
+ open_kwargs = self.scope.get('_OpenKwargs') or {}
2782
2834
 
2783
- # Search for value of matching type at or near the index
2835
+ # Type mapping for type checking
2784
2836
  type_map = {
2785
2837
  'string': str, 'str': str,
2786
2838
  'int': int, 'integer': int,
@@ -2788,10 +2840,23 @@ class CSSLRuntime:
2788
2840
  'bool': bool, 'boolean': bool,
2789
2841
  'list': list, 'array': list,
2790
2842
  'dict': dict, 'json': dict,
2843
+ 'dynamic': None, # Accept any type
2791
2844
  }
2792
-
2793
2845
  target_type = type_map.get(type_param.lower())
2794
2846
 
2847
+ # If param_name is specified, search by name in kwargs
2848
+ # OpenFind<dynamic, "tasks"> -> searches for MyFunc(tasks="value")
2849
+ if param_name:
2850
+ if param_name in open_kwargs:
2851
+ value = open_kwargs[param_name]
2852
+ # Type check if not dynamic
2853
+ if target_type is None or isinstance(value, target_type):
2854
+ return value
2855
+ return None
2856
+
2857
+ # Otherwise, search by index in positional args
2858
+ index = args[0] if args else 0
2859
+
2795
2860
  if isinstance(open_params, (list, tuple)):
2796
2861
  # Find first matching type starting from index
2797
2862
  for i in range(index, len(open_params)):
@@ -2812,8 +2877,8 @@ class CSSLRuntime:
2812
2877
  raise CSSLRuntimeError(
2813
2878
  f"Unknown typed function: {name}<{type_param}>",
2814
2879
  node.line,
2815
- context=f"Available typed functions: OpenFind<type>",
2816
- hint="Typed functions use format: FunctionName<Type>(args)"
2880
+ context=f"Available typed functions: OpenFind<type>, OpenFind<type, \"name\">",
2881
+ hint="Use OpenFind<type>(index) for positional or OpenFind<type, \"name\"> for named params"
2817
2882
  )
2818
2883
 
2819
2884
  def _eval_new(self, node: ASTNode) -> CSSLInstance:
@@ -2,7 +2,7 @@
2
2
  "name": "cssl",
3
3
  "displayName": "CSSL Language",
4
4
  "description": "Professional syntax highlighting, snippets, and language support for CSSL scripts (.cssl, .cssl-pl, .cssl-mod)",
5
- "version": "1.3.0",
5
+ "version": "1.4.0",
6
6
  "publisher": "IncludeCPP",
7
7
  "icon": "images/cssl.png",
8
8
  "engines": {
@@ -28,9 +28,63 @@
28
28
  { "include": "#builtins" },
29
29
  { "include": "#operators" },
30
30
  { "include": "#constants" },
31
+ { "include": "#non-null-declarations" },
31
32
  { "include": "#variables" }
32
33
  ],
33
34
  "repository": {
35
+ "non-null-declarations": {
36
+ "patterns": [
37
+ {
38
+ "comment": "Non-null class: class *ClassName - light pink",
39
+ "name": "meta.class.non-null.cssl",
40
+ "match": "\\b(class)\\s+(\\*)([a-zA-Z_][a-zA-Z0-9_]*)",
41
+ "captures": {
42
+ "1": { "name": "storage.type.class.cssl" },
43
+ "2": { "name": "keyword.operator.non-null.cssl" },
44
+ "3": { "name": "entity.name.class.non-null.cssl" }
45
+ }
46
+ },
47
+ {
48
+ "comment": "Non-null function: define *FuncName - light pink",
49
+ "name": "meta.function.non-null.cssl",
50
+ "match": "\\b(define)\\s+(\\*)([a-zA-Z_][a-zA-Z0-9_]*)",
51
+ "captures": {
52
+ "1": { "name": "storage.type.function.cssl" },
53
+ "2": { "name": "keyword.operator.non-null.cssl" },
54
+ "3": { "name": "entity.name.function.non-null.cssl" }
55
+ }
56
+ },
57
+ {
58
+ "comment": "Non-null typed variable: type<T> *varName - light pink",
59
+ "name": "meta.declaration.non-null.cssl",
60
+ "match": "\\b(int|string|float|bool|dynamic|vector|stack|array|list|dict|json|datastruct|iterator)\\s*(<[^>]+>)?\\s+(\\*)([a-zA-Z_][a-zA-Z0-9_]*)",
61
+ "captures": {
62
+ "1": { "name": "storage.type.cssl" },
63
+ "2": { "name": "storage.type.generic.cssl" },
64
+ "3": { "name": "keyword.operator.non-null.cssl" },
65
+ "4": { "name": "variable.other.non-null.cssl" }
66
+ }
67
+ },
68
+ {
69
+ "comment": "Non-null open parameter: open *Params - light pink",
70
+ "name": "meta.parameter.non-null.cssl",
71
+ "match": "\\b(open)\\s+(\\*)([a-zA-Z_][a-zA-Z0-9_]*)",
72
+ "captures": {
73
+ "1": { "name": "storage.modifier.open.cssl" },
74
+ "2": { "name": "keyword.operator.non-null.cssl" },
75
+ "3": { "name": "variable.parameter.non-null.cssl" }
76
+ }
77
+ },
78
+ {
79
+ "comment": "Return type -> * (non-null return)",
80
+ "name": "meta.return-type.non-null.cssl",
81
+ "match": "->\\s*\\*",
82
+ "captures": {
83
+ "0": { "name": "keyword.operator.non-null.return.cssl" }
84
+ }
85
+ }
86
+ ]
87
+ },
34
88
  "super-functions": {
35
89
  "patterns": [
36
90
  {
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "IncludeCPP"
7
- version = "3.7.27"
7
+ version = "3.8.2"
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