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.
- {includecpp-3.7.27 → includecpp-3.8.2}/IncludeCPP.egg-info/PKG-INFO +1 -1
- {includecpp-3.7.27 → includecpp-3.8.2}/PKG-INFO +1 -1
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/__init__.py +1 -1
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/cli/commands.py +26 -6
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/cssl/cssl_builtins.py +2 -1
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/cssl/cssl_parser.py +52 -6
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/cssl/cssl_runtime.py +75 -10
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/vscode/cssl/package.json +1 -1
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/vscode/cssl/syntaxes/cssl.tmLanguage.json +54 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/pyproject.toml +1 -1
- {includecpp-3.7.27 → includecpp-3.8.2}/IncludeCPP.egg-info/SOURCES.txt +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/IncludeCPP.egg-info/dependency_links.txt +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/IncludeCPP.egg-info/entry_points.txt +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/IncludeCPP.egg-info/requires.txt +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/IncludeCPP.egg-info/top_level.txt +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/LICENSE +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/MANIFEST.in +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/README.md +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/__init__.pyi +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/__main__.py +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/cli/__init__.py +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/cli/config_parser.py +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/__init__.py +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/ai_integration.py +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/build_manager.py +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/cpp_api.py +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/cpp_api.pyi +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/cppy_converter.py +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/cssl/CSSL_DOCUMENTATION.md +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/cssl/__init__.py +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/cssl/cssl_builtins.pyi +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/cssl/cssl_events.py +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/cssl/cssl_modules.py +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/cssl/cssl_syntax.py +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/cssl/cssl_types.py +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/cssl_bridge.py +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/cssl_bridge.pyi +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/error_catalog.py +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/error_formatter.py +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/exceptions.py +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/path_discovery.py +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/project_ui.py +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/core/settings_ui.py +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/generator/__init__.py +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/generator/parser.cpp +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/generator/parser.h +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/generator/type_resolver.cpp +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/generator/type_resolver.h +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/py.typed +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/templates/cpp.proj.template +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/vscode/__init__.py +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/vscode/cssl/__init__.py +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/vscode/cssl/extension.js +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/vscode/cssl/images/cssl.png +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/vscode/cssl/images/cssl_pl.png +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/vscode/cssl/language-configuration.json +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/includecpp/vscode/cssl/snippets/cssl.snippets.json +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/requirements.txt +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/setup.cfg +0 -0
- {includecpp-3.7.27 → includecpp-3.8.2}/setup.py +0 -0
|
@@ -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
|
|
7935
|
-
includecpp vscode --force
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
1035
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2833
|
+
open_kwargs = self.scope.get('_OpenKwargs') or {}
|
|
2782
2834
|
|
|
2783
|
-
#
|
|
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="
|
|
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.
|
|
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
|
+
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|