IncludeCPP 3.7.9__py3-none-any.whl → 3.7.25__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 CHANGED
@@ -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.9"
5
+ __version__ = "3.7.25"
6
6
  __all__ = ["CppApi", "CSSL"]
7
7
 
8
8
  # Module-level cache for C++ modules
includecpp/__init__.pyi CHANGED
@@ -13,7 +13,7 @@ except ImportError:
13
13
  pass # Generated during rebuild
14
14
 
15
15
 
16
- # ========== CSSL Module - CSO Service Script Language ==========
16
+ # ========== CSSL Module ==========
17
17
  class _CSSLModule:
18
18
  """CSSL callable module created via CSSL.module()"""
19
19
  def __call__(self, *args: Any) -> Any:
@@ -139,7 +139,7 @@ class _CSSLBridge:
139
139
  ...
140
140
 
141
141
 
142
- # CSSL module instance - CSO Service Script Language
142
+ # CSSL module instance
143
143
  CSSL: _CSSLBridge
144
144
 
145
145
  __version__: str
@@ -7720,7 +7720,13 @@ def cssl_doc(search, list_sections):
7720
7720
  click.echo("Or use: includecpp cssl doc --list")
7721
7721
  else:
7722
7722
  # Full documentation mode
7723
- click.echo_via_pager(content)
7723
+ # Replace Unicode characters that may not be supported on all terminals
7724
+ safe_content = content.replace('✓', '[OK]').replace('✗', '[X]').replace('→', '->').replace('←', '<-').replace('•', '*').replace('─', '-').replace('│', '|').replace('└', '+').replace('├', '+').replace('▸', '>').replace('▾', 'v')
7725
+ try:
7726
+ click.echo_via_pager(safe_content)
7727
+ except UnicodeEncodeError:
7728
+ # Fallback: encode with errors='replace'
7729
+ click.echo(safe_content.encode('ascii', errors='replace').decode('ascii'))
7724
7730
  else:
7725
7731
  click.secho("Documentation file not found.", fg='yellow')
7726
7732
  click.echo("Looking for: CSSL_DOCUMENTATION.md")
@@ -7858,26 +7864,46 @@ def cssl_vscode():
7858
7864
  click.secho("CSSL extension files not found in package.", fg='red')
7859
7865
  return
7860
7866
 
7861
- # Install extension
7862
- target_dir = vscode_ext_dir / 'includecpp.cssl-1.0.0'
7867
+ # Get version from package.json
7868
+ pkg_json = source_ext_dir / 'package.json'
7869
+ current_version = "1.1.0"
7870
+ if pkg_json.exists():
7871
+ try:
7872
+ pkg_data = json.loads(pkg_json.read_text(encoding='utf-8'))
7873
+ current_version = pkg_data.get('version', '1.1.0')
7874
+ except:
7875
+ pass
7876
+
7877
+ target_dir = vscode_ext_dir / f'includecpp.cssl-{current_version}'
7863
7878
 
7864
7879
  try:
7880
+ # Check for existing installations
7881
+ existing_version = None
7882
+ for existing in vscode_ext_dir.glob('includecpp.cssl-*'):
7883
+ existing_version = existing.name.split('-')[-1]
7884
+ if existing_version != current_version:
7885
+ click.echo(f"Removing old version: {existing_version}")
7886
+ shutil.rmtree(existing)
7887
+
7865
7888
  if target_dir.exists():
7866
7889
  shutil.rmtree(target_dir)
7867
7890
 
7868
7891
  shutil.copytree(source_ext_dir, target_dir)
7869
7892
 
7870
- click.secho("CSSL VSCode extension installed!", fg='green', bold=True)
7893
+ if existing_version and existing_version != current_version:
7894
+ click.secho(f"CSSL extension updated: v{existing_version} -> v{current_version}", fg='green', bold=True)
7895
+ else:
7896
+ click.secho(f"CSSL VSCode extension installed! (v{current_version})", fg='green', bold=True)
7871
7897
  click.echo()
7872
7898
  click.echo(f"Installed to: {target_dir}")
7873
7899
  click.echo()
7874
7900
  click.echo("Features:")
7875
7901
  click.echo(" - Syntax highlighting for .cssl, .cssl-pl, .cssl-mod files")
7876
- click.echo(" - BruteInjection operators: <==, ==>, <<==, +<==, etc.")
7877
- click.echo(" - Type highlighting: int, string, stack<T>, datastruct<T>")
7902
+ click.echo(" - OOP support: class, constructor, this->member")
7903
+ click.echo(" - Injection operators: <== (brute), <<== (infuse)")
7904
+ click.echo(" - Type highlighting: int, string, stack<T>, instance<>")
7878
7905
  click.echo(" - Global references: @Name, r@Name, s@Name")
7879
7906
  click.echo(" - Shared objects: $Name")
7880
- click.echo(" - Filter helpers: string::contains, json::key, etc.")
7881
7907
  click.echo()
7882
7908
  click.secho("Restart VSCode to activate the extension.", fg='yellow')
7883
7909
 
@@ -7901,35 +7927,28 @@ cli.add_command(cssl)
7901
7927
  def vscode(force, stubs_only):
7902
7928
  """Initialize or update VSCode configuration for IncludeCPP/CSSL.
7903
7929
 
7904
- Sets up .vscode folder with:
7905
- - CSSL language support (syntax highlighting, snippets)
7906
- - Type stubs for builtins (.pyi files)
7907
- - Auto-generated stubs for your plugins and modules
7930
+ Installs CSSL extension globally and sets up project stubs.
7908
7931
 
7909
7932
  \b
7910
7933
  Usage:
7911
- includecpp vscode # Initialize .vscode
7912
- includecpp vscode --force # Force overwrite existing
7934
+ includecpp vscode # Install/update extension + stubs
7935
+ includecpp vscode --force # Force reinstall extension
7913
7936
  includecpp vscode --stubs-only # Only update stubs
7914
7937
 
7915
7938
  \b
7916
- What it creates:
7917
- .vscode/
7918
- settings.json - VSCode settings for CSSL
7919
- cssl/ - CSSL language extension
7920
- stubs/ - Type stubs for IDE support
7921
- cssl_builtins.pyi - CSSL builtin functions
7922
- plugins/ - Stubs for your .cp plugins
7923
- modules/ - Stubs for your modules
7939
+ What it does:
7940
+ 1. Installs CSSL extension globally (~/.vscode/extensions/)
7941
+ 2. Creates .vscode/settings.json with file associations
7942
+ 3. Creates .vscode/stubs/ with type hints for IDE support
7924
7943
  """
7925
7944
  from pathlib import Path as PathLib
7945
+ import os
7926
7946
 
7927
7947
  cwd = PathLib.cwd()
7928
7948
  vscode_dir = cwd / '.vscode'
7929
7949
  stubs_dir = vscode_dir / 'stubs'
7930
7950
  plugins_stubs_dir = stubs_dir / 'plugins'
7931
7951
  modules_stubs_dir = stubs_dir / 'modules'
7932
- cssl_ext_dir = vscode_dir / 'cssl'
7933
7952
 
7934
7953
  # Create directories
7935
7954
  vscode_dir.mkdir(exist_ok=True)
@@ -7945,56 +7964,79 @@ def vscode(force, stubs_only):
7945
7964
  updated_count = 0
7946
7965
  created_count = 0
7947
7966
 
7948
- # 1. Copy CSSL extension files (unless stubs-only)
7967
+ # 1. Install CSSL extension GLOBALLY (unless stubs-only)
7949
7968
  if not stubs_only:
7950
- click.secho("Setting up CSSL language support...", fg='yellow')
7969
+ click.secho("Installing CSSL extension globally...", fg='yellow')
7951
7970
 
7952
7971
  # Find source extension directory
7953
7972
  source_ext_dir = PathLib(__file__).parent.parent / 'vscode' / 'cssl'
7954
7973
 
7955
7974
  if source_ext_dir.exists():
7956
- cssl_ext_dir.mkdir(exist_ok=True)
7957
-
7958
- # Copy extension files
7959
- ext_files = [
7960
- 'language-configuration.json',
7961
- 'package.json',
7962
- ]
7963
-
7964
- for fname in ext_files:
7965
- src = source_ext_dir / fname
7966
- dst = cssl_ext_dir / fname
7967
- if src.exists():
7968
- if not dst.exists() or force:
7969
- shutil.copy2(src, dst)
7970
- created_count += 1
7971
- click.echo(f" Created: .vscode/cssl/{fname}")
7972
-
7973
- # Copy syntaxes folder
7974
- syntaxes_src = source_ext_dir / 'syntaxes'
7975
- syntaxes_dst = cssl_ext_dir / 'syntaxes'
7976
- if syntaxes_src.exists():
7977
- syntaxes_dst.mkdir(exist_ok=True)
7978
- for f in syntaxes_src.glob('*.json'):
7979
- dst = syntaxes_dst / f.name
7980
- if not dst.exists() or force:
7981
- shutil.copy2(f, dst)
7982
- created_count += 1
7983
- click.echo(f" Created: .vscode/cssl/syntaxes/{f.name}")
7984
-
7985
- # Copy snippets folder
7986
- snippets_src = source_ext_dir / 'snippets'
7987
- snippets_dst = cssl_ext_dir / 'snippets'
7988
- if snippets_src.exists():
7989
- snippets_dst.mkdir(exist_ok=True)
7990
- for f in snippets_src.glob('*.json'):
7991
- dst = snippets_dst / f.name
7992
- if not dst.exists() or force:
7993
- shutil.copy2(f, dst)
7994
- created_count += 1
7995
- click.echo(f" Created: .vscode/cssl/snippets/{f.name}")
7975
+ # Get version from package.json
7976
+ pkg_json = source_ext_dir / 'package.json'
7977
+ current_version = "1.1.0"
7978
+ if pkg_json.exists():
7979
+ try:
7980
+ pkg_data = json.loads(pkg_json.read_text(encoding='utf-8'))
7981
+ current_version = pkg_data.get('version', '1.1.0')
7982
+ except:
7983
+ pass
7984
+
7985
+ # Find global VSCode extensions directory
7986
+ if os.name == 'nt': # Windows
7987
+ global_ext_dir = PathLib(os.environ.get('USERPROFILE', '')) / '.vscode' / 'extensions'
7988
+ else: # Linux/Mac
7989
+ global_ext_dir = PathLib.home() / '.vscode' / 'extensions'
7990
+
7991
+ if not global_ext_dir.exists():
7992
+ # Try VSCode Insiders
7993
+ if os.name == 'nt':
7994
+ global_ext_dir = PathLib(os.environ.get('USERPROFILE', '')) / '.vscode-insiders' / 'extensions'
7995
+ else:
7996
+ global_ext_dir = PathLib.home() / '.vscode-insiders' / 'extensions'
7997
+
7998
+ if global_ext_dir.exists():
7999
+ target_dir = global_ext_dir / f'includecpp.cssl-{current_version}'
8000
+
8001
+ # Check if already installed with same or older version
8002
+ needs_install = force
8003
+ existing_version = None
8004
+
8005
+ # Find existing installations
8006
+ for existing in global_ext_dir.glob('includecpp.cssl-*'):
8007
+ existing_version = existing.name.split('-')[-1]
8008
+ if existing_version != current_version:
8009
+ # Remove old version
8010
+ click.echo(f" Removing old version: {existing_version}")
8011
+ shutil.rmtree(existing)
8012
+ needs_install = True
8013
+ elif not force:
8014
+ click.echo(f" Already installed: v{current_version}")
8015
+ needs_install = False
8016
+
8017
+ if not target_dir.exists():
8018
+ needs_install = True
8019
+
8020
+ if needs_install:
8021
+ # Remove target if exists (force reinstall)
8022
+ if target_dir.exists():
8023
+ shutil.rmtree(target_dir)
8024
+
8025
+ # Copy extension to global directory
8026
+ shutil.copytree(source_ext_dir, target_dir)
8027
+ created_count += 1
8028
+
8029
+ if existing_version and existing_version != current_version:
8030
+ click.secho(f" Updated: v{existing_version} -> v{current_version}", fg='green')
8031
+ else:
8032
+ click.secho(f" Installed: v{current_version}", fg='green')
7996
8033
 
7997
- click.secho(" CSSL extension configured", fg='green')
8034
+ click.echo(f" Location: {target_dir}")
8035
+ click.echo()
8036
+ click.secho(" Restart VSCode to activate the extension!", fg='yellow', bold=True)
8037
+ else:
8038
+ click.secho(" VSCode extensions directory not found.", fg='red')
8039
+ click.echo(" Make sure VSCode is installed.")
7998
8040
  else:
7999
8041
  click.secho(" Warning: CSSL extension source not found", fg='yellow')
8000
8042
 
@@ -1,5 +1,5 @@
1
1
  """
2
- CSSL - CSO Service Script Language
2
+ CSSL - C-Style Scripting Language
3
3
  Bundled with IncludeCPP for integrated scripting support.
4
4
 
5
5
  Features:
@@ -16,7 +16,10 @@ from .cssl_parser import (
16
16
  CSSLSyntaxError, CSSLLexer, CSSLParser, ASTNode,
17
17
  KEYWORDS, TYPE_GENERICS, TYPE_PARAM_FUNCTIONS, INJECTION_HELPERS
18
18
  )
19
- from .cssl_runtime import CSSLRuntime, CSSLRuntimeError, CSSLServiceRunner, run_cssl, run_cssl_file
19
+ from .cssl_runtime import (
20
+ CSSLRuntime, CSSLRuntimeError, CSSLServiceRunner, run_cssl, run_cssl_file,
21
+ register_filter, unregister_filter, get_custom_filters
22
+ )
20
23
  from .cssl_types import (
21
24
  DataStruct, Shuffled, Iterator, Combo, DataSpace, OpenQuote,
22
25
  OpenFind, Parameter, Stack, Vector, Array,
@@ -33,6 +36,8 @@ __all__ = [
33
36
  # Runtime
34
37
  'CSSLRuntime', 'CSSLRuntimeError', 'CSSLServiceRunner',
35
38
  'run_cssl', 'run_cssl_file',
39
+ # Filter Registration
40
+ 'register_filter', 'unregister_filter', 'get_custom_filters',
36
41
  # Data Types
37
42
  'DataStruct', 'Shuffled', 'Iterator', 'Combo', 'DataSpace', 'OpenQuote',
38
43
  'OpenFind', 'Parameter', 'Stack', 'Vector', 'Array',
@@ -307,6 +307,10 @@ class CSSLBuiltins:
307
307
  self._functions['dataspace'] = self.builtin_dataspace
308
308
  self._functions['openquote'] = self.builtin_openquote
309
309
  self._functions['OpenFind'] = self.builtin_openfind
310
+ self._functions['vector'] = self.builtin_vector
311
+ self._functions['array'] = self.builtin_array
312
+ self._functions['stack'] = self.builtin_stack
313
+ self._functions['map'] = self.builtin_map
310
314
 
311
315
  # Print aliases for CSSL
312
316
  self._functions['printl'] = self.builtin_println # CSSL uses printl for println
@@ -433,13 +437,50 @@ class CSSLBuiltins:
433
437
  # ============= Type Checking =============
434
438
 
435
439
  def builtin_typeof(self, value: Any) -> str:
436
- """Get type name"""
440
+ """Get type name - returns CSSL-specific type names for CSSL types"""
437
441
  if value is None:
438
442
  return 'null'
443
+
444
+ # Check CSSL-specific types first
445
+ from .cssl_types import (Vector, Array, Stack, DataStruct,
446
+ List as CSSLList, Dictionary, Map,
447
+ Shuffled, Iterator, Combo, DataSpace,
448
+ OpenQuote, Parameter, CSSLInstance)
449
+
450
+ if isinstance(value, Vector):
451
+ return 'vector'
452
+ elif isinstance(value, Array):
453
+ return 'array'
454
+ elif isinstance(value, Stack):
455
+ return 'stack'
456
+ elif isinstance(value, DataStruct):
457
+ return 'datastruct'
458
+ elif isinstance(value, CSSLList):
459
+ return 'list'
460
+ elif isinstance(value, Dictionary):
461
+ return 'dictionary'
462
+ elif isinstance(value, Map):
463
+ return 'map'
464
+ elif isinstance(value, Shuffled):
465
+ return 'shuffled'
466
+ elif isinstance(value, Iterator):
467
+ return 'iterator'
468
+ elif isinstance(value, Combo):
469
+ return 'combo'
470
+ elif isinstance(value, DataSpace):
471
+ return 'dataspace'
472
+ elif isinstance(value, OpenQuote):
473
+ return 'openquote'
474
+ elif isinstance(value, Parameter):
475
+ return 'parameter'
476
+ elif isinstance(value, CSSLInstance):
477
+ return value._class.name
478
+
479
+ # Python types as fallback
439
480
  type_map = {
440
481
  int: 'int',
441
482
  float: 'float',
442
- str: 'str',
483
+ str: 'string',
443
484
  bool: 'bool',
444
485
  list: 'list',
445
486
  dict: 'dict',
@@ -1044,6 +1085,13 @@ class CSSLBuiltins:
1044
1085
  Usage: instance::getMethods(@module) or instance::getMethods($obj)
1045
1086
  Returns list of method names.
1046
1087
  """
1088
+ from .cssl_types import CSSLInstance
1089
+
1090
+ # Handle CSSL class instances
1091
+ if isinstance(obj, CSSLInstance):
1092
+ return list(obj._class.methods.keys())
1093
+
1094
+ # Handle Python objects
1047
1095
  import inspect
1048
1096
  methods = []
1049
1097
  for name in dir(obj):
@@ -1056,8 +1104,20 @@ class CSSLBuiltins:
1056
1104
  def builtin_instance_getClasses(self, obj: Any) -> list:
1057
1105
  """Get all classes from an object/module.
1058
1106
  Usage: instance::getClasses(@module)
1059
- Returns list of class names.
1107
+ Returns list of class names (including merged classes).
1060
1108
  """
1109
+ from .cssl_types import CSSLInstance
1110
+
1111
+ # Handle CSSL class instances
1112
+ if isinstance(obj, CSSLInstance):
1113
+ classes = [obj._class.name] # Primary class
1114
+ # Check for merged class instances in members
1115
+ for name, member in obj._members.items():
1116
+ if isinstance(member, CSSLInstance):
1117
+ classes.append(member._class.name)
1118
+ return classes
1119
+
1120
+ # Handle Python objects
1061
1121
  import inspect
1062
1122
  classes = []
1063
1123
  for name in dir(obj):
@@ -1070,8 +1130,20 @@ class CSSLBuiltins:
1070
1130
  def builtin_instance_getVars(self, obj: Any) -> list:
1071
1131
  """Get all variables/attributes (non-callable) from an object.
1072
1132
  Usage: instance::getVars(@module)
1073
- Returns list of variable names.
1133
+ Returns list of variable names (excludes merged class instances).
1074
1134
  """
1135
+ from .cssl_types import CSSLInstance
1136
+
1137
+ # Handle CSSL class instances
1138
+ if isinstance(obj, CSSLInstance):
1139
+ vars_list = []
1140
+ for name, member in obj._members.items():
1141
+ # Exclude merged class instances
1142
+ if not isinstance(member, CSSLInstance):
1143
+ vars_list.append(name)
1144
+ return vars_list
1145
+
1146
+ # Handle Python objects
1075
1147
  vars_list = []
1076
1148
  for name in dir(obj):
1077
1149
  if not name.startswith('_'):
@@ -1085,12 +1157,31 @@ class CSSLBuiltins:
1085
1157
  Usage: instance::getAll(@module)
1086
1158
  Returns dict with 'methods', 'classes', 'vars' keys.
1087
1159
  """
1088
- import inspect
1160
+ from .cssl_types import CSSLInstance
1161
+
1089
1162
  result = {
1090
1163
  'methods': [],
1091
1164
  'classes': [],
1092
1165
  'vars': []
1093
1166
  }
1167
+
1168
+ # Handle CSSL class instances
1169
+ if isinstance(obj, CSSLInstance):
1170
+ result['methods'] = list(obj._class.methods.keys())
1171
+ result['classes'] = [obj._class.name]
1172
+
1173
+ # Separate regular vars from merged class instances
1174
+ for name, member in obj._members.items():
1175
+ if isinstance(member, CSSLInstance):
1176
+ # Merged class - add to classes list
1177
+ result['classes'].append(member._class.name)
1178
+ else:
1179
+ # Regular variable
1180
+ result['vars'].append(name)
1181
+ return result
1182
+
1183
+ # Handle Python objects
1184
+ import inspect
1094
1185
  for name in dir(obj):
1095
1186
  if not name.startswith('_'):
1096
1187
  attr = getattr(obj, name, None)
@@ -1106,21 +1197,46 @@ class CSSLBuiltins:
1106
1197
  """Dynamically call a method on an object.
1107
1198
  Usage: instance::call(@module, 'methodName', arg1, arg2)
1108
1199
  """
1200
+ from .cssl_types import CSSLInstance
1201
+
1202
+ # Handle CSSL class instances
1203
+ if isinstance(obj, CSSLInstance):
1204
+ if obj.has_method(method_name):
1205
+ # Need runtime to call the method
1206
+ if self.runtime:
1207
+ return self.runtime._call_method(obj, obj.get_method(method_name), list(args), kwargs or {})
1208
+ raise RuntimeError(f"Method '{method_name}' not found on CSSL instance")
1209
+
1210
+ # Handle Python objects
1109
1211
  method = getattr(obj, method_name, None)
1110
1212
  if method and callable(method):
1111
1213
  return method(*args, **kwargs)
1112
1214
  raise RuntimeError(f"Method '{method_name}' not found on object")
1113
1215
 
1114
1216
  def builtin_instance_has(self, obj: Any, name: str) -> bool:
1115
- """Check if object has an attribute.
1217
+ """Check if object has an attribute or method.
1116
1218
  Usage: instance::has(@module, 'methodName')
1117
1219
  """
1220
+ from .cssl_types import CSSLInstance
1221
+
1222
+ # Handle CSSL class instances
1223
+ if isinstance(obj, CSSLInstance):
1224
+ return obj.has_member(name) or obj.has_method(name)
1225
+
1226
+ # Handle Python objects
1118
1227
  return hasattr(obj, name)
1119
1228
 
1120
1229
  def builtin_instance_type(self, obj: Any) -> str:
1121
1230
  """Get the type name of an object.
1122
1231
  Usage: instance::type(@module)
1123
1232
  """
1233
+ from .cssl_types import CSSLInstance
1234
+
1235
+ # Handle CSSL class instances
1236
+ if isinstance(obj, CSSLInstance):
1237
+ return obj._class.name
1238
+
1239
+ # Handle Python objects
1124
1240
  return type(obj).__name__
1125
1241
 
1126
1242
  def builtin_isavailable(self, name_or_obj: Any) -> bool:
@@ -1140,6 +1256,50 @@ class CSSLBuiltins:
1140
1256
  # Otherwise, check if the object is not None (for $name or instance<"name">)
1141
1257
  return name_or_obj is not None
1142
1258
 
1259
+ # ============= Filter Registration Functions =============
1260
+
1261
+ def builtin_filter_register(self, filter_type: str, helper: str, callback: Any) -> bool:
1262
+ """Register a custom filter.
1263
+ Usage: filter::register("mytype", "where", myCallback)
1264
+
1265
+ The callback receives (source, filter_value, runtime) and returns filtered result.
1266
+ Use "*" as helper for catch-all.
1267
+
1268
+ Example:
1269
+ define myFilter(source, value, runtime) {
1270
+ return source + value;
1271
+ }
1272
+ filter::register("custom", "add", myFilter);
1273
+
1274
+ result <==[custom::add=10] 5; // result = 15
1275
+ """
1276
+ from .cssl_runtime import register_filter
1277
+ register_filter(filter_type, helper, callback)
1278
+ return True
1279
+
1280
+ def builtin_filter_unregister(self, filter_type: str, helper: str) -> bool:
1281
+ """Unregister a custom filter.
1282
+ Usage: filter::unregister("mytype", "where")
1283
+ """
1284
+ from .cssl_runtime import unregister_filter
1285
+ return unregister_filter(filter_type, helper)
1286
+
1287
+ def builtin_filter_list(self) -> list:
1288
+ """List all registered custom filters.
1289
+ Usage: filter::list()
1290
+ Returns list of filter keys like ["mytype::where", "custom::*"]
1291
+ """
1292
+ from .cssl_runtime import get_custom_filters
1293
+ return list(get_custom_filters().keys())
1294
+
1295
+ def builtin_filter_exists(self, filter_type: str, helper: str) -> bool:
1296
+ """Check if a custom filter exists.
1297
+ Usage: filter::exists("mytype", "where")
1298
+ """
1299
+ from .cssl_runtime import get_custom_filters
1300
+ key = f"{filter_type}::{helper}"
1301
+ return key in get_custom_filters()
1302
+
1143
1303
  # ============= Regex Functions =============
1144
1304
 
1145
1305
  def builtin_match(self, pattern: str, string: str) -> Optional[dict]:
@@ -1680,7 +1840,7 @@ class CSSLBuiltins:
1680
1840
 
1681
1841
  def builtin_cso_root(self, path: str = "") -> str:
1682
1842
  """
1683
- Get absolute path relative to CSO root directory
1843
+ Get absolute path relative to project root directory
1684
1844
  Usage: cso_root('/services/myservice.cssl')
1685
1845
  Returns: Full absolute path to the file
1686
1846
  """
@@ -1729,7 +1889,7 @@ class CSSLBuiltins:
1729
1889
  if os.path.exists(cwd_path):
1730
1890
  filepath = cwd_path
1731
1891
  else:
1732
- # Fall back to cso_root for CSO service context
1892
+ # Fall back to cso_root for service context
1733
1893
  filepath = self.builtin_cso_root(filepath)
1734
1894
 
1735
1895
  # Check file exists
@@ -1923,7 +2083,7 @@ class CSSLBuiltins:
1923
2083
  if os.path.exists(cwd_path):
1924
2084
  filepath = cwd_path
1925
2085
  else:
1926
- # Fall back to cso_root for CSO service context
2086
+ # Fall back to cso_root for service context
1927
2087
  filepath = self.builtin_cso_root(filepath)
1928
2088
 
1929
2089
  # Check file exists
@@ -2203,6 +2363,38 @@ class CSSLBuiltins:
2203
2363
  from .cssl_types import OpenQuote
2204
2364
  return OpenQuote(db_ref)
2205
2365
 
2366
+ def builtin_vector(self, element_type: str = 'dynamic') -> Any:
2367
+ """Create a vector container.
2368
+
2369
+ Usage: vector<int> myVector; or vector('int')
2370
+ """
2371
+ from .cssl_types import Vector
2372
+ return Vector(element_type)
2373
+
2374
+ def builtin_array(self, element_type: str = 'dynamic') -> Any:
2375
+ """Create an array container.
2376
+
2377
+ Usage: array<string> myArray; or array('string')
2378
+ """
2379
+ from .cssl_types import Array
2380
+ return Array(element_type)
2381
+
2382
+ def builtin_stack(self, element_type: str = 'dynamic') -> Any:
2383
+ """Create a stack container.
2384
+
2385
+ Usage: stack<int> myStack; or stack('int')
2386
+ """
2387
+ from .cssl_types import Stack
2388
+ return Stack(element_type)
2389
+
2390
+ def builtin_map(self, key_type: str = 'dynamic', value_type: str = 'dynamic') -> Any:
2391
+ """Create a map container.
2392
+
2393
+ Usage: map<string, int> myMap; or map('string', 'int')
2394
+ """
2395
+ from .cssl_types import Map
2396
+ return Map(key_type, value_type)
2397
+
2206
2398
  def builtin_openfind(self, combo_or_type: Any, index: int = 0, params: list = None) -> Any:
2207
2399
  """Find open parameter by type or combo space.
2208
2400