IncludeCPP 4.0.0__py3-none-any.whl → 4.0.2__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 +1 -1
- includecpp/cli/commands.py +7 -14
- includecpp/core/cssl/cssl_parser.py +8 -6
- includecpp/core/cssl/cssl_runtime.py +204 -16
- includecpp/core/cssl_bridge.py +4 -4
- includecpp/core/cssl_bridge.pyi +586 -193
- {includecpp-4.0.0.dist-info → includecpp-4.0.2.dist-info}/METADATA +2 -1
- {includecpp-4.0.0.dist-info → includecpp-4.0.2.dist-info}/RECORD +12 -12
- {includecpp-4.0.0.dist-info → includecpp-4.0.2.dist-info}/WHEEL +0 -0
- {includecpp-4.0.0.dist-info → includecpp-4.0.2.dist-info}/entry_points.txt +0 -0
- {includecpp-4.0.0.dist-info → includecpp-4.0.2.dist-info}/licenses/LICENSE +0 -0
- {includecpp-4.0.0.dist-info → includecpp-4.0.2.dist-info}/top_level.txt +0 -0
includecpp/__init__.py
CHANGED
includecpp/cli/commands.py
CHANGED
|
@@ -9,8 +9,12 @@ import re
|
|
|
9
9
|
import urllib.request
|
|
10
10
|
import urllib.error
|
|
11
11
|
from pathlib import Path
|
|
12
|
+
from colorama import init as colorama_init, Fore, Style
|
|
12
13
|
from .config_parser import CppProjectConfig
|
|
13
14
|
|
|
15
|
+
# Initialize colorama for Windows ANSI color support
|
|
16
|
+
colorama_init()
|
|
17
|
+
|
|
14
18
|
|
|
15
19
|
def _is_experimental_enabled() -> bool:
|
|
16
20
|
"""Check if experimental features (cppy, ai) are enabled."""
|
|
@@ -7320,7 +7324,6 @@ def exec_repl(lang, path, import_all):
|
|
|
7320
7324
|
code_lines = imports + [''] + lines if imports else lines
|
|
7321
7325
|
|
|
7322
7326
|
click.echo()
|
|
7323
|
-
click.secho("--- Output ---", fg='green')
|
|
7324
7327
|
|
|
7325
7328
|
if is_python:
|
|
7326
7329
|
# Execute Python code
|
|
@@ -7443,9 +7446,6 @@ def exec_repl(lang, path, import_all):
|
|
|
7443
7446
|
except Exception:
|
|
7444
7447
|
pass
|
|
7445
7448
|
|
|
7446
|
-
click.echo()
|
|
7447
|
-
click.secho("--------------", fg='green')
|
|
7448
|
-
|
|
7449
7449
|
|
|
7450
7450
|
# ============================================================================
|
|
7451
7451
|
# CSSL - Hidden Command Group
|
|
@@ -7526,19 +7526,12 @@ def _cssl_execute(path, code):
|
|
|
7526
7526
|
source = '\n'.join(lines)
|
|
7527
7527
|
|
|
7528
7528
|
# Execute
|
|
7529
|
-
click.secho("--- Output ---", fg='green')
|
|
7530
7529
|
try:
|
|
7531
7530
|
result = cssl_lang.run(source)
|
|
7532
|
-
|
|
7533
|
-
# Output is already printed to stdout during execution via runtime.output()
|
|
7534
|
-
# Don't print "Result:" automatically - users should use printl() for output
|
|
7535
|
-
# This prevents unwanted output for function calls like: Function();
|
|
7536
|
-
pass
|
|
7537
|
-
|
|
7538
7531
|
except Exception as e:
|
|
7539
|
-
|
|
7540
|
-
|
|
7541
|
-
|
|
7532
|
+
error_msg = str(e)
|
|
7533
|
+
# Clean display - single CSSL Error: prefix with colorama
|
|
7534
|
+
click.echo(f"{Fore.RED}CSSL Error: {error_msg}{Style.RESET_ALL}")
|
|
7542
7535
|
|
|
7543
7536
|
|
|
7544
7537
|
@cssl.command(name='makemodule')
|
|
@@ -1084,7 +1084,7 @@ class CSSLParser:
|
|
|
1084
1084
|
append_ref_class = None
|
|
1085
1085
|
append_ref_member = None
|
|
1086
1086
|
|
|
1087
|
-
# Check for &ClassName::member reference
|
|
1087
|
+
# Check for &ClassName::member or &ClassName.member or &function reference
|
|
1088
1088
|
if self._match(TokenType.AMPERSAND):
|
|
1089
1089
|
if self._check(TokenType.IDENTIFIER):
|
|
1090
1090
|
append_ref_class = self._advance().value
|
|
@@ -1095,8 +1095,8 @@ class CSSLParser:
|
|
|
1095
1095
|
elif self._check(TokenType.SHARED_REF):
|
|
1096
1096
|
append_ref_class = f'${self._advance().value}'
|
|
1097
1097
|
|
|
1098
|
-
# Check for ::member
|
|
1099
|
-
if self._match(TokenType.DOUBLE_COLON):
|
|
1098
|
+
# Check for ::member or .member (support both syntaxes)
|
|
1099
|
+
if self._match(TokenType.DOUBLE_COLON) or self._match(TokenType.DOT):
|
|
1100
1100
|
if self._check(TokenType.IDENTIFIER) or self._check(TokenType.KEYWORD):
|
|
1101
1101
|
append_ref_member = self._advance().value
|
|
1102
1102
|
|
|
@@ -1108,7 +1108,7 @@ class CSSLParser:
|
|
|
1108
1108
|
if self._match(TokenType.DOUBLE_COLON) or self._match(TokenType.COLON):
|
|
1109
1109
|
while True:
|
|
1110
1110
|
if self._match_keyword('extends'):
|
|
1111
|
-
# Parse target: @ModuleName, $PythonObject, Parent::method
|
|
1111
|
+
# Parse target: @ModuleName, $PythonObject, Parent::method, Parent.method
|
|
1112
1112
|
if self._check(TokenType.AT):
|
|
1113
1113
|
self._advance()
|
|
1114
1114
|
extends_func = '@' + self._advance().value
|
|
@@ -1117,7 +1117,8 @@ class CSSLParser:
|
|
|
1117
1117
|
extends_func = self._advance().value
|
|
1118
1118
|
elif self._check(TokenType.IDENTIFIER):
|
|
1119
1119
|
first_part = self._advance().value
|
|
1120
|
-
|
|
1120
|
+
# Support both :: and . for class method access
|
|
1121
|
+
if self._match(TokenType.DOUBLE_COLON) or self._match(TokenType.DOT):
|
|
1121
1122
|
extends_class_ref = first_part
|
|
1122
1123
|
extends_method_ref = self._advance().value
|
|
1123
1124
|
else:
|
|
@@ -1134,7 +1135,8 @@ class CSSLParser:
|
|
|
1134
1135
|
overwrites_func = self._advance().value
|
|
1135
1136
|
elif self._check(TokenType.IDENTIFIER):
|
|
1136
1137
|
first_part = self._advance().value
|
|
1137
|
-
|
|
1138
|
+
# Support both :: and . for class method access
|
|
1139
|
+
if self._match(TokenType.DOUBLE_COLON) or self._match(TokenType.DOT):
|
|
1138
1140
|
overwrites_class_ref = first_part
|
|
1139
1141
|
overwrites_method_ref = self._advance().value
|
|
1140
1142
|
else:
|
|
@@ -68,11 +68,11 @@ class CSSLRuntimeError(Exception):
|
|
|
68
68
|
# Build detailed error message
|
|
69
69
|
error_parts = []
|
|
70
70
|
|
|
71
|
-
# Main error message
|
|
71
|
+
# Main error message (no "Error:" prefix - CLI handles that)
|
|
72
72
|
if line:
|
|
73
|
-
error_parts.append(f"
|
|
73
|
+
error_parts.append(f"Line {line}: {message}")
|
|
74
74
|
else:
|
|
75
|
-
error_parts.append(
|
|
75
|
+
error_parts.append(message)
|
|
76
76
|
|
|
77
77
|
# Add context if available
|
|
78
78
|
if context:
|
|
@@ -363,11 +363,11 @@ class CSSLRuntime:
|
|
|
363
363
|
"""Format a detailed error with source context"""
|
|
364
364
|
error_parts = []
|
|
365
365
|
|
|
366
|
-
# Main error header
|
|
366
|
+
# Main error header (no "Error:" prefix - CLI handles that)
|
|
367
367
|
if line and line > 0:
|
|
368
|
-
error_parts.append(f"
|
|
368
|
+
error_parts.append(f"Line {line} in {self._current_file}:")
|
|
369
369
|
else:
|
|
370
|
-
error_parts.append(f"
|
|
370
|
+
error_parts.append(f"In {self._current_file}:")
|
|
371
371
|
|
|
372
372
|
# Extract message without existing line info
|
|
373
373
|
clean_msg = message
|
|
@@ -1005,13 +1005,29 @@ class CSSLRuntime:
|
|
|
1005
1005
|
overwrites_func = func_info.get('overwrites')
|
|
1006
1006
|
overwrites_is_python = func_info.get('overwrites_is_python', False)
|
|
1007
1007
|
|
|
1008
|
+
# Get append/overwrite reference info (&Class::method syntax)
|
|
1009
|
+
append_mode = func_info.get('append_mode', False)
|
|
1010
|
+
append_ref_class = func_info.get('append_ref_class')
|
|
1011
|
+
append_ref_member = func_info.get('append_ref_member')
|
|
1012
|
+
|
|
1008
1013
|
# Store function extends info for runtime use
|
|
1009
1014
|
if extends_func:
|
|
1010
1015
|
node.value['_extends_resolved'] = self._resolve_function_target(
|
|
1011
1016
|
extends_func, extends_is_python
|
|
1012
1017
|
)
|
|
1013
1018
|
|
|
1014
|
-
# Handle
|
|
1019
|
+
# Handle &Class::method syntax
|
|
1020
|
+
# Without ++ = full replacement
|
|
1021
|
+
# With ++ = append (run original first, then new code)
|
|
1022
|
+
if append_ref_class:
|
|
1023
|
+
if append_mode:
|
|
1024
|
+
# Append mode: wrap original to run original + new
|
|
1025
|
+
self._append_to_target(append_ref_class, append_ref_member, node)
|
|
1026
|
+
else:
|
|
1027
|
+
# Full replacement
|
|
1028
|
+
self._overwrite_target(append_ref_class, append_ref_member, node)
|
|
1029
|
+
|
|
1030
|
+
# Handle overwrites keyword - replace the target function
|
|
1015
1031
|
if overwrites_func:
|
|
1016
1032
|
target = self._resolve_function_target(overwrites_func, overwrites_is_python)
|
|
1017
1033
|
if target is not None:
|
|
@@ -1054,6 +1070,142 @@ class CSSLRuntime:
|
|
|
1054
1070
|
return self._call_function(func_node, list(args), kwargs)
|
|
1055
1071
|
return wrapper
|
|
1056
1072
|
|
|
1073
|
+
def _overwrite_target(self, ref_class: str, ref_member: str, replacement_node: ASTNode):
|
|
1074
|
+
"""Overwrite a class method or function with the replacement.
|
|
1075
|
+
|
|
1076
|
+
Handles:
|
|
1077
|
+
- &ClassName::method - Overwrite method in CSSL class
|
|
1078
|
+
- &$PyObject.method - Overwrite method in Python shared object
|
|
1079
|
+
- &functionName - Overwrite standalone function
|
|
1080
|
+
"""
|
|
1081
|
+
from ..cssl_bridge import _live_objects, SharedObjectProxy
|
|
1082
|
+
|
|
1083
|
+
# Handle Python shared objects
|
|
1084
|
+
if ref_class.startswith('$'):
|
|
1085
|
+
var_name = ref_class[1:]
|
|
1086
|
+
ref_obj = _live_objects.get(var_name)
|
|
1087
|
+
if ref_obj is None:
|
|
1088
|
+
ref_obj = self.scope.get(var_name) or self.global_scope.get(var_name)
|
|
1089
|
+
|
|
1090
|
+
if ref_obj is None:
|
|
1091
|
+
return
|
|
1092
|
+
|
|
1093
|
+
# Unwrap SharedObjectProxy
|
|
1094
|
+
if isinstance(ref_obj, SharedObjectProxy):
|
|
1095
|
+
ref_obj = ref_obj._obj
|
|
1096
|
+
|
|
1097
|
+
# Overwrite Python object method
|
|
1098
|
+
if ref_member and hasattr(ref_obj, ref_member):
|
|
1099
|
+
wrapper = self._create_python_wrapper(replacement_node)
|
|
1100
|
+
try:
|
|
1101
|
+
setattr(ref_obj, ref_member, wrapper)
|
|
1102
|
+
except (AttributeError, TypeError):
|
|
1103
|
+
pass # Can't overwrite (immutable or builtin)
|
|
1104
|
+
return
|
|
1105
|
+
|
|
1106
|
+
# Handle CSSL class method overwrite
|
|
1107
|
+
target_class = self.scope.get(ref_class) or self.global_scope.get(ref_class)
|
|
1108
|
+
if target_class is None:
|
|
1109
|
+
# Maybe it's a standalone function reference (no ::member)
|
|
1110
|
+
if ref_member is None:
|
|
1111
|
+
# &functionName - overwrite the function
|
|
1112
|
+
self.scope.set(ref_class, replacement_node)
|
|
1113
|
+
self.global_scope.set(ref_class, replacement_node)
|
|
1114
|
+
return
|
|
1115
|
+
|
|
1116
|
+
if isinstance(target_class, CSSLClass) and ref_member:
|
|
1117
|
+
# Overwrite method in the class
|
|
1118
|
+
if hasattr(target_class, 'methods') and isinstance(target_class.methods, dict):
|
|
1119
|
+
target_class.methods[ref_member] = replacement_node
|
|
1120
|
+
# Also check members list
|
|
1121
|
+
if hasattr(target_class, 'members'):
|
|
1122
|
+
for i, member in enumerate(target_class.members):
|
|
1123
|
+
if member.type in ('function', 'FUNCTION') and member.value.get('name') == ref_member:
|
|
1124
|
+
target_class.members[i] = replacement_node
|
|
1125
|
+
break
|
|
1126
|
+
|
|
1127
|
+
def _append_to_target(self, ref_class: str, ref_member: str, append_node: ASTNode):
|
|
1128
|
+
"""Append new code to an existing class method or function.
|
|
1129
|
+
|
|
1130
|
+
Creates a wrapper that runs original first, then the appended code.
|
|
1131
|
+
Handles:
|
|
1132
|
+
- &ClassName::method ++ - Append to method in CSSL class
|
|
1133
|
+
- &$PyObject.method ++ - Append to method in Python shared object
|
|
1134
|
+
- &functionName ++ - Append to standalone function
|
|
1135
|
+
"""
|
|
1136
|
+
from ..cssl_bridge import _live_objects, SharedObjectProxy
|
|
1137
|
+
|
|
1138
|
+
# Handle Python shared objects
|
|
1139
|
+
if ref_class.startswith('$'):
|
|
1140
|
+
var_name = ref_class[1:]
|
|
1141
|
+
ref_obj = _live_objects.get(var_name)
|
|
1142
|
+
if ref_obj is None:
|
|
1143
|
+
ref_obj = self.scope.get(var_name) or self.global_scope.get(var_name)
|
|
1144
|
+
|
|
1145
|
+
if ref_obj is None:
|
|
1146
|
+
return
|
|
1147
|
+
|
|
1148
|
+
if isinstance(ref_obj, SharedObjectProxy):
|
|
1149
|
+
ref_obj = ref_obj._obj
|
|
1150
|
+
|
|
1151
|
+
# Create wrapper that calls original + new
|
|
1152
|
+
if ref_member and hasattr(ref_obj, ref_member):
|
|
1153
|
+
original_method = getattr(ref_obj, ref_member)
|
|
1154
|
+
runtime = self
|
|
1155
|
+
def appended_wrapper(*args, **kwargs):
|
|
1156
|
+
# Run original first
|
|
1157
|
+
result = None
|
|
1158
|
+
if callable(original_method):
|
|
1159
|
+
try:
|
|
1160
|
+
result = original_method(*args, **kwargs)
|
|
1161
|
+
except:
|
|
1162
|
+
pass
|
|
1163
|
+
# Then run appended code
|
|
1164
|
+
return runtime._call_function(append_node, list(args), kwargs)
|
|
1165
|
+
try:
|
|
1166
|
+
setattr(ref_obj, ref_member, appended_wrapper)
|
|
1167
|
+
except (AttributeError, TypeError):
|
|
1168
|
+
pass
|
|
1169
|
+
return
|
|
1170
|
+
|
|
1171
|
+
# Handle CSSL class method append
|
|
1172
|
+
target_class = self.scope.get(ref_class) or self.global_scope.get(ref_class)
|
|
1173
|
+
if target_class is None:
|
|
1174
|
+
# Standalone function append
|
|
1175
|
+
if ref_member is None:
|
|
1176
|
+
original_func = self.scope.get(ref_class) or self.global_scope.get(ref_class)
|
|
1177
|
+
if original_func:
|
|
1178
|
+
# Store original in append_node so it can run first
|
|
1179
|
+
append_node.value['_original_func'] = original_func
|
|
1180
|
+
self.scope.set(ref_class, append_node)
|
|
1181
|
+
self.global_scope.set(ref_class, append_node)
|
|
1182
|
+
return
|
|
1183
|
+
|
|
1184
|
+
if isinstance(target_class, CSSLClass) and ref_member:
|
|
1185
|
+
# Find original method
|
|
1186
|
+
original_method = None
|
|
1187
|
+
if hasattr(target_class, 'methods') and isinstance(target_class.methods, dict):
|
|
1188
|
+
original_method = target_class.methods.get(ref_member)
|
|
1189
|
+
|
|
1190
|
+
if original_method is None and hasattr(target_class, 'members'):
|
|
1191
|
+
for member in target_class.members:
|
|
1192
|
+
if member.type in ('function', 'FUNCTION') and member.value.get('name') == ref_member:
|
|
1193
|
+
original_method = member
|
|
1194
|
+
break
|
|
1195
|
+
|
|
1196
|
+
# Store original in append_node for runtime execution
|
|
1197
|
+
if original_method:
|
|
1198
|
+
append_node.value['_original_method'] = original_method
|
|
1199
|
+
|
|
1200
|
+
# Replace with append_node (which will call original first via _call_function)
|
|
1201
|
+
if hasattr(target_class, 'methods') and isinstance(target_class.methods, dict):
|
|
1202
|
+
target_class.methods[ref_member] = append_node
|
|
1203
|
+
if hasattr(target_class, 'members'):
|
|
1204
|
+
for i, member in enumerate(target_class.members):
|
|
1205
|
+
if member.type in ('function', 'FUNCTION') and member.value.get('name') == ref_member:
|
|
1206
|
+
target_class.members[i] = append_node
|
|
1207
|
+
break
|
|
1208
|
+
|
|
1057
1209
|
def _exec_typed_declaration(self, node: ASTNode) -> Any:
|
|
1058
1210
|
"""Execute typed variable declaration: type<T> varName = value;
|
|
1059
1211
|
|
|
@@ -1352,12 +1504,15 @@ class CSSLRuntime:
|
|
|
1352
1504
|
if not self._running:
|
|
1353
1505
|
break
|
|
1354
1506
|
self._execute_node(child)
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1507
|
+
except CSSLReturn:
|
|
1508
|
+
# Parent returned - that's fine, we just want the local vars
|
|
1509
|
+
pass
|
|
1358
1510
|
except:
|
|
1359
1511
|
pass
|
|
1360
1512
|
finally:
|
|
1513
|
+
# ALWAYS copy local vars (even if parent returned)
|
|
1514
|
+
for name, value in temp_scope.variables.items():
|
|
1515
|
+
new_scope.set(name, value)
|
|
1361
1516
|
self.scope = old_scope
|
|
1362
1517
|
|
|
1363
1518
|
# Bind parameters - handle both positional and named arguments
|
|
@@ -1420,7 +1575,7 @@ class CSSLRuntime:
|
|
|
1420
1575
|
|
|
1421
1576
|
# Check exclude_type: *[type] - must NOT return excluded type
|
|
1422
1577
|
exclude_type = func_info.get('exclude_type')
|
|
1423
|
-
if exclude_type:
|
|
1578
|
+
if exclude_type and isinstance(exclude_type, str):
|
|
1424
1579
|
type_map = {
|
|
1425
1580
|
'string': str, 'int': int, 'float': float, 'bool': bool,
|
|
1426
1581
|
'null': type(None), 'none': type(None),
|
|
@@ -3076,7 +3231,7 @@ class CSSLRuntime:
|
|
|
3076
3231
|
'json': dict,
|
|
3077
3232
|
}
|
|
3078
3233
|
|
|
3079
|
-
excluded_py_type = type_map.get(exclude_type.lower())
|
|
3234
|
+
excluded_py_type = type_map.get(exclude_type.lower() if isinstance(exclude_type, str) else exclude_type)
|
|
3080
3235
|
if excluded_py_type and isinstance(value, excluded_py_type):
|
|
3081
3236
|
raise self._format_error(
|
|
3082
3237
|
node.line if hasattr(node, 'line') else 0,
|
|
@@ -3628,12 +3783,34 @@ class CSSLRuntime:
|
|
|
3628
3783
|
|
|
3629
3784
|
# Resolve the class/instance reference
|
|
3630
3785
|
if ref_class.startswith('$'):
|
|
3631
|
-
# Dynamic instance reference: &$instanceVar::member
|
|
3786
|
+
# Dynamic instance reference: &$instanceVar::member or &$PyObject.method
|
|
3632
3787
|
var_name = ref_class[1:]
|
|
3633
|
-
|
|
3788
|
+
|
|
3789
|
+
# First check in _live_objects for Python shared objects
|
|
3790
|
+
from ..cssl_bridge import _live_objects, SharedObjectProxy
|
|
3791
|
+
ref_obj = _live_objects.get(var_name)
|
|
3792
|
+
if ref_obj is None:
|
|
3793
|
+
ref_obj = self.scope.get(var_name) or self.global_scope.get(var_name)
|
|
3794
|
+
|
|
3634
3795
|
if ref_obj is None:
|
|
3635
3796
|
return # Instance not found, skip silently
|
|
3636
3797
|
|
|
3798
|
+
# Handle Python shared objects
|
|
3799
|
+
if isinstance(ref_obj, SharedObjectProxy):
|
|
3800
|
+
ref_obj = ref_obj._obj
|
|
3801
|
+
|
|
3802
|
+
# If it's a Python object (not CSSL), call the method directly
|
|
3803
|
+
if not isinstance(ref_obj, (CSSLInstance, CSSLClass)):
|
|
3804
|
+
if ref_member and hasattr(ref_obj, ref_member):
|
|
3805
|
+
method = getattr(ref_obj, ref_member)
|
|
3806
|
+
if callable(method):
|
|
3807
|
+
try:
|
|
3808
|
+
method(*args, **kwargs)
|
|
3809
|
+
except TypeError:
|
|
3810
|
+
# Try without args
|
|
3811
|
+
method()
|
|
3812
|
+
return
|
|
3813
|
+
|
|
3637
3814
|
if isinstance(ref_obj, CSSLInstance):
|
|
3638
3815
|
# Get the class definition from the instance
|
|
3639
3816
|
target_class = ref_obj.class_def
|
|
@@ -3853,9 +4030,19 @@ class CSSLRuntime:
|
|
|
3853
4030
|
self.scope = new_scope
|
|
3854
4031
|
self._current_instance = instance
|
|
3855
4032
|
|
|
4033
|
+
original_return = None
|
|
3856
4034
|
try:
|
|
4035
|
+
# Handle append mode via _append_to_target (stored original)
|
|
4036
|
+
original_method = func_info.get('_original_method')
|
|
4037
|
+
if original_method:
|
|
4038
|
+
# Execute original method first - capture return for fallback
|
|
4039
|
+
try:
|
|
4040
|
+
original_return = self._call_method(instance, original_method, args, kwargs)
|
|
4041
|
+
except CSSLReturn as ret:
|
|
4042
|
+
original_return = ret.value
|
|
4043
|
+
|
|
3857
4044
|
# Handle append mode (++) - execute referenced parent method first
|
|
3858
|
-
|
|
4045
|
+
elif append_mode and append_ref_class:
|
|
3859
4046
|
self._execute_append_reference(
|
|
3860
4047
|
instance, append_ref_class, append_ref_member,
|
|
3861
4048
|
args, kwargs, {}, is_constructor=False
|
|
@@ -3876,7 +4063,8 @@ class CSSLRuntime:
|
|
|
3876
4063
|
self.scope = old_scope
|
|
3877
4064
|
self._current_instance = old_instance
|
|
3878
4065
|
|
|
3879
|
-
return
|
|
4066
|
+
# If no return in appended code, use original's return
|
|
4067
|
+
return original_return
|
|
3880
4068
|
|
|
3881
4069
|
def _eval_member_access(self, node: ASTNode) -> Any:
|
|
3882
4070
|
"""Evaluate member access"""
|
includecpp/core/cssl_bridge.py
CHANGED
|
@@ -455,12 +455,12 @@ class CsslLang:
|
|
|
455
455
|
|
|
456
456
|
return result
|
|
457
457
|
except Exception as e:
|
|
458
|
-
# Format error message nicely
|
|
458
|
+
# Format error message nicely - don't add prefixes, let CLI handle that
|
|
459
459
|
error_msg = str(e)
|
|
460
|
-
#
|
|
460
|
+
# Strip any existing CSSL Error: prefix to avoid duplication
|
|
461
461
|
if error_msg.startswith("CSSL Error:"):
|
|
462
|
-
|
|
463
|
-
raise RuntimeError(
|
|
462
|
+
error_msg = error_msg[11:].strip()
|
|
463
|
+
raise RuntimeError(error_msg) from e
|
|
464
464
|
|
|
465
465
|
def exec(self, path_or_code: str, *args) -> Any:
|
|
466
466
|
"""
|