IncludeCPP 3.7.9__py3-none-any.whl → 3.8.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- includecpp/__init__.py +1 -1
- includecpp/__init__.pyi +2 -2
- includecpp/cli/commands.py +129 -67
- includecpp/core/cssl/__init__.py +7 -2
- includecpp/core/cssl/cssl_builtins.py +411 -9
- includecpp/core/cssl/cssl_builtins.pyi +3682 -401
- includecpp/core/cssl/cssl_parser.py +130 -31
- includecpp/core/cssl/cssl_runtime.py +462 -26
- includecpp/core/cssl/cssl_syntax.py +7 -7
- includecpp/core/cssl/cssl_types.py +75 -2
- includecpp/core/cssl_bridge.py +64 -6
- includecpp/vscode/cssl/extension.js +133 -0
- includecpp/vscode/cssl/images/cssl.png +0 -0
- includecpp/vscode/cssl/images/cssl_pl.png +0 -0
- includecpp/vscode/cssl/package.json +117 -11
- includecpp/vscode/cssl/snippets/cssl.snippets.json +126 -0
- includecpp/vscode/cssl/syntaxes/cssl.tmLanguage.json +46 -15
- {includecpp-3.7.9.dist-info → includecpp-3.8.0.dist-info}/METADATA +56 -225
- {includecpp-3.7.9.dist-info → includecpp-3.8.0.dist-info}/RECORD +23 -20
- {includecpp-3.7.9.dist-info → includecpp-3.8.0.dist-info}/WHEEL +0 -0
- {includecpp-3.7.9.dist-info → includecpp-3.8.0.dist-info}/entry_points.txt +0 -0
- {includecpp-3.7.9.dist-info → includecpp-3.8.0.dist-info}/licenses/LICENSE +0 -0
- {includecpp-3.7.9.dist-info → includecpp-3.8.0.dist-info}/top_level.txt +0 -0
|
@@ -205,6 +205,11 @@ class CSSLBuiltins:
|
|
|
205
205
|
self._functions['isavailable'] = self.builtin_isavailable
|
|
206
206
|
self._functions['instance::exists'] = self.builtin_isavailable # Alias
|
|
207
207
|
|
|
208
|
+
# Python interop functions
|
|
209
|
+
self._functions['python::pythonize'] = self.builtin_python_pythonize
|
|
210
|
+
self._functions['python::wrap'] = self.builtin_python_pythonize # Alias
|
|
211
|
+
self._functions['python::export'] = self.builtin_python_pythonize # Alias
|
|
212
|
+
|
|
208
213
|
# Regex functions
|
|
209
214
|
self._functions['match'] = self.builtin_match
|
|
210
215
|
self._functions['search'] = self.builtin_search
|
|
@@ -307,6 +312,10 @@ class CSSLBuiltins:
|
|
|
307
312
|
self._functions['dataspace'] = self.builtin_dataspace
|
|
308
313
|
self._functions['openquote'] = self.builtin_openquote
|
|
309
314
|
self._functions['OpenFind'] = self.builtin_openfind
|
|
315
|
+
self._functions['vector'] = self.builtin_vector
|
|
316
|
+
self._functions['array'] = self.builtin_array
|
|
317
|
+
self._functions['stack'] = self.builtin_stack
|
|
318
|
+
self._functions['map'] = self.builtin_map
|
|
310
319
|
|
|
311
320
|
# Print aliases for CSSL
|
|
312
321
|
self._functions['printl'] = self.builtin_println # CSSL uses printl for println
|
|
@@ -433,13 +442,50 @@ class CSSLBuiltins:
|
|
|
433
442
|
# ============= Type Checking =============
|
|
434
443
|
|
|
435
444
|
def builtin_typeof(self, value: Any) -> str:
|
|
436
|
-
"""Get type name"""
|
|
445
|
+
"""Get type name - returns CSSL-specific type names for CSSL types"""
|
|
437
446
|
if value is None:
|
|
438
447
|
return 'null'
|
|
448
|
+
|
|
449
|
+
# Check CSSL-specific types first
|
|
450
|
+
from .cssl_types import (Vector, Array, Stack, DataStruct,
|
|
451
|
+
List as CSSLList, Dictionary, Map,
|
|
452
|
+
Shuffled, Iterator, Combo, DataSpace,
|
|
453
|
+
OpenQuote, Parameter, CSSLInstance)
|
|
454
|
+
|
|
455
|
+
if isinstance(value, Vector):
|
|
456
|
+
return 'vector'
|
|
457
|
+
elif isinstance(value, Array):
|
|
458
|
+
return 'array'
|
|
459
|
+
elif isinstance(value, Stack):
|
|
460
|
+
return 'stack'
|
|
461
|
+
elif isinstance(value, DataStruct):
|
|
462
|
+
return 'datastruct'
|
|
463
|
+
elif isinstance(value, CSSLList):
|
|
464
|
+
return 'list'
|
|
465
|
+
elif isinstance(value, Dictionary):
|
|
466
|
+
return 'dictionary'
|
|
467
|
+
elif isinstance(value, Map):
|
|
468
|
+
return 'map'
|
|
469
|
+
elif isinstance(value, Shuffled):
|
|
470
|
+
return 'shuffled'
|
|
471
|
+
elif isinstance(value, Iterator):
|
|
472
|
+
return 'iterator'
|
|
473
|
+
elif isinstance(value, Combo):
|
|
474
|
+
return 'combo'
|
|
475
|
+
elif isinstance(value, DataSpace):
|
|
476
|
+
return 'dataspace'
|
|
477
|
+
elif isinstance(value, OpenQuote):
|
|
478
|
+
return 'openquote'
|
|
479
|
+
elif isinstance(value, Parameter):
|
|
480
|
+
return 'parameter'
|
|
481
|
+
elif isinstance(value, CSSLInstance):
|
|
482
|
+
return value._class.name
|
|
483
|
+
|
|
484
|
+
# Python types as fallback
|
|
439
485
|
type_map = {
|
|
440
486
|
int: 'int',
|
|
441
487
|
float: 'float',
|
|
442
|
-
str: '
|
|
488
|
+
str: 'string',
|
|
443
489
|
bool: 'bool',
|
|
444
490
|
list: 'list',
|
|
445
491
|
dict: 'dict',
|
|
@@ -1044,6 +1090,13 @@ class CSSLBuiltins:
|
|
|
1044
1090
|
Usage: instance::getMethods(@module) or instance::getMethods($obj)
|
|
1045
1091
|
Returns list of method names.
|
|
1046
1092
|
"""
|
|
1093
|
+
from .cssl_types import CSSLInstance
|
|
1094
|
+
|
|
1095
|
+
# Handle CSSL class instances
|
|
1096
|
+
if isinstance(obj, CSSLInstance):
|
|
1097
|
+
return list(obj._class.methods.keys())
|
|
1098
|
+
|
|
1099
|
+
# Handle Python objects
|
|
1047
1100
|
import inspect
|
|
1048
1101
|
methods = []
|
|
1049
1102
|
for name in dir(obj):
|
|
@@ -1056,8 +1109,20 @@ class CSSLBuiltins:
|
|
|
1056
1109
|
def builtin_instance_getClasses(self, obj: Any) -> list:
|
|
1057
1110
|
"""Get all classes from an object/module.
|
|
1058
1111
|
Usage: instance::getClasses(@module)
|
|
1059
|
-
Returns list of class names.
|
|
1112
|
+
Returns list of class names (including merged classes).
|
|
1060
1113
|
"""
|
|
1114
|
+
from .cssl_types import CSSLInstance
|
|
1115
|
+
|
|
1116
|
+
# Handle CSSL class instances
|
|
1117
|
+
if isinstance(obj, CSSLInstance):
|
|
1118
|
+
classes = [obj._class.name] # Primary class
|
|
1119
|
+
# Check for merged class instances in members
|
|
1120
|
+
for name, member in obj._members.items():
|
|
1121
|
+
if isinstance(member, CSSLInstance):
|
|
1122
|
+
classes.append(member._class.name)
|
|
1123
|
+
return classes
|
|
1124
|
+
|
|
1125
|
+
# Handle Python objects
|
|
1061
1126
|
import inspect
|
|
1062
1127
|
classes = []
|
|
1063
1128
|
for name in dir(obj):
|
|
@@ -1070,8 +1135,20 @@ class CSSLBuiltins:
|
|
|
1070
1135
|
def builtin_instance_getVars(self, obj: Any) -> list:
|
|
1071
1136
|
"""Get all variables/attributes (non-callable) from an object.
|
|
1072
1137
|
Usage: instance::getVars(@module)
|
|
1073
|
-
Returns list of variable names.
|
|
1138
|
+
Returns list of variable names (excludes merged class instances).
|
|
1074
1139
|
"""
|
|
1140
|
+
from .cssl_types import CSSLInstance
|
|
1141
|
+
|
|
1142
|
+
# Handle CSSL class instances
|
|
1143
|
+
if isinstance(obj, CSSLInstance):
|
|
1144
|
+
vars_list = []
|
|
1145
|
+
for name, member in obj._members.items():
|
|
1146
|
+
# Exclude merged class instances
|
|
1147
|
+
if not isinstance(member, CSSLInstance):
|
|
1148
|
+
vars_list.append(name)
|
|
1149
|
+
return vars_list
|
|
1150
|
+
|
|
1151
|
+
# Handle Python objects
|
|
1075
1152
|
vars_list = []
|
|
1076
1153
|
for name in dir(obj):
|
|
1077
1154
|
if not name.startswith('_'):
|
|
@@ -1085,12 +1162,31 @@ class CSSLBuiltins:
|
|
|
1085
1162
|
Usage: instance::getAll(@module)
|
|
1086
1163
|
Returns dict with 'methods', 'classes', 'vars' keys.
|
|
1087
1164
|
"""
|
|
1088
|
-
import
|
|
1165
|
+
from .cssl_types import CSSLInstance
|
|
1166
|
+
|
|
1089
1167
|
result = {
|
|
1090
1168
|
'methods': [],
|
|
1091
1169
|
'classes': [],
|
|
1092
1170
|
'vars': []
|
|
1093
1171
|
}
|
|
1172
|
+
|
|
1173
|
+
# Handle CSSL class instances
|
|
1174
|
+
if isinstance(obj, CSSLInstance):
|
|
1175
|
+
result['methods'] = list(obj._class.methods.keys())
|
|
1176
|
+
result['classes'] = [obj._class.name]
|
|
1177
|
+
|
|
1178
|
+
# Separate regular vars from merged class instances
|
|
1179
|
+
for name, member in obj._members.items():
|
|
1180
|
+
if isinstance(member, CSSLInstance):
|
|
1181
|
+
# Merged class - add to classes list
|
|
1182
|
+
result['classes'].append(member._class.name)
|
|
1183
|
+
else:
|
|
1184
|
+
# Regular variable
|
|
1185
|
+
result['vars'].append(name)
|
|
1186
|
+
return result
|
|
1187
|
+
|
|
1188
|
+
# Handle Python objects
|
|
1189
|
+
import inspect
|
|
1094
1190
|
for name in dir(obj):
|
|
1095
1191
|
if not name.startswith('_'):
|
|
1096
1192
|
attr = getattr(obj, name, None)
|
|
@@ -1106,21 +1202,46 @@ class CSSLBuiltins:
|
|
|
1106
1202
|
"""Dynamically call a method on an object.
|
|
1107
1203
|
Usage: instance::call(@module, 'methodName', arg1, arg2)
|
|
1108
1204
|
"""
|
|
1205
|
+
from .cssl_types import CSSLInstance
|
|
1206
|
+
|
|
1207
|
+
# Handle CSSL class instances
|
|
1208
|
+
if isinstance(obj, CSSLInstance):
|
|
1209
|
+
if obj.has_method(method_name):
|
|
1210
|
+
# Need runtime to call the method
|
|
1211
|
+
if self.runtime:
|
|
1212
|
+
return self.runtime._call_method(obj, obj.get_method(method_name), list(args), kwargs or {})
|
|
1213
|
+
raise RuntimeError(f"Method '{method_name}' not found on CSSL instance")
|
|
1214
|
+
|
|
1215
|
+
# Handle Python objects
|
|
1109
1216
|
method = getattr(obj, method_name, None)
|
|
1110
1217
|
if method and callable(method):
|
|
1111
1218
|
return method(*args, **kwargs)
|
|
1112
1219
|
raise RuntimeError(f"Method '{method_name}' not found on object")
|
|
1113
1220
|
|
|
1114
1221
|
def builtin_instance_has(self, obj: Any, name: str) -> bool:
|
|
1115
|
-
"""Check if object has an attribute.
|
|
1222
|
+
"""Check if object has an attribute or method.
|
|
1116
1223
|
Usage: instance::has(@module, 'methodName')
|
|
1117
1224
|
"""
|
|
1225
|
+
from .cssl_types import CSSLInstance
|
|
1226
|
+
|
|
1227
|
+
# Handle CSSL class instances
|
|
1228
|
+
if isinstance(obj, CSSLInstance):
|
|
1229
|
+
return obj.has_member(name) or obj.has_method(name)
|
|
1230
|
+
|
|
1231
|
+
# Handle Python objects
|
|
1118
1232
|
return hasattr(obj, name)
|
|
1119
1233
|
|
|
1120
1234
|
def builtin_instance_type(self, obj: Any) -> str:
|
|
1121
1235
|
"""Get the type name of an object.
|
|
1122
1236
|
Usage: instance::type(@module)
|
|
1123
1237
|
"""
|
|
1238
|
+
from .cssl_types import CSSLInstance
|
|
1239
|
+
|
|
1240
|
+
# Handle CSSL class instances
|
|
1241
|
+
if isinstance(obj, CSSLInstance):
|
|
1242
|
+
return obj._class.name
|
|
1243
|
+
|
|
1244
|
+
# Handle Python objects
|
|
1124
1245
|
return type(obj).__name__
|
|
1125
1246
|
|
|
1126
1247
|
def builtin_isavailable(self, name_or_obj: Any) -> bool:
|
|
@@ -1140,6 +1261,50 @@ class CSSLBuiltins:
|
|
|
1140
1261
|
# Otherwise, check if the object is not None (for $name or instance<"name">)
|
|
1141
1262
|
return name_or_obj is not None
|
|
1142
1263
|
|
|
1264
|
+
# ============= Filter Registration Functions =============
|
|
1265
|
+
|
|
1266
|
+
def builtin_filter_register(self, filter_type: str, helper: str, callback: Any) -> bool:
|
|
1267
|
+
"""Register a custom filter.
|
|
1268
|
+
Usage: filter::register("mytype", "where", myCallback)
|
|
1269
|
+
|
|
1270
|
+
The callback receives (source, filter_value, runtime) and returns filtered result.
|
|
1271
|
+
Use "*" as helper for catch-all.
|
|
1272
|
+
|
|
1273
|
+
Example:
|
|
1274
|
+
define myFilter(source, value, runtime) {
|
|
1275
|
+
return source + value;
|
|
1276
|
+
}
|
|
1277
|
+
filter::register("custom", "add", myFilter);
|
|
1278
|
+
|
|
1279
|
+
result <==[custom::add=10] 5; // result = 15
|
|
1280
|
+
"""
|
|
1281
|
+
from .cssl_runtime import register_filter
|
|
1282
|
+
register_filter(filter_type, helper, callback)
|
|
1283
|
+
return True
|
|
1284
|
+
|
|
1285
|
+
def builtin_filter_unregister(self, filter_type: str, helper: str) -> bool:
|
|
1286
|
+
"""Unregister a custom filter.
|
|
1287
|
+
Usage: filter::unregister("mytype", "where")
|
|
1288
|
+
"""
|
|
1289
|
+
from .cssl_runtime import unregister_filter
|
|
1290
|
+
return unregister_filter(filter_type, helper)
|
|
1291
|
+
|
|
1292
|
+
def builtin_filter_list(self) -> list:
|
|
1293
|
+
"""List all registered custom filters.
|
|
1294
|
+
Usage: filter::list()
|
|
1295
|
+
Returns list of filter keys like ["mytype::where", "custom::*"]
|
|
1296
|
+
"""
|
|
1297
|
+
from .cssl_runtime import get_custom_filters
|
|
1298
|
+
return list(get_custom_filters().keys())
|
|
1299
|
+
|
|
1300
|
+
def builtin_filter_exists(self, filter_type: str, helper: str) -> bool:
|
|
1301
|
+
"""Check if a custom filter exists.
|
|
1302
|
+
Usage: filter::exists("mytype", "where")
|
|
1303
|
+
"""
|
|
1304
|
+
from .cssl_runtime import get_custom_filters
|
|
1305
|
+
key = f"{filter_type}::{helper}"
|
|
1306
|
+
return key in get_custom_filters()
|
|
1307
|
+
|
|
1143
1308
|
# ============= Regex Functions =============
|
|
1144
1309
|
|
|
1145
1310
|
def builtin_match(self, pattern: str, string: str) -> Optional[dict]:
|
|
@@ -1680,7 +1845,7 @@ class CSSLBuiltins:
|
|
|
1680
1845
|
|
|
1681
1846
|
def builtin_cso_root(self, path: str = "") -> str:
|
|
1682
1847
|
"""
|
|
1683
|
-
Get absolute path relative to
|
|
1848
|
+
Get absolute path relative to project root directory
|
|
1684
1849
|
Usage: cso_root('/services/myservice.cssl')
|
|
1685
1850
|
Returns: Full absolute path to the file
|
|
1686
1851
|
"""
|
|
@@ -1729,7 +1894,7 @@ class CSSLBuiltins:
|
|
|
1729
1894
|
if os.path.exists(cwd_path):
|
|
1730
1895
|
filepath = cwd_path
|
|
1731
1896
|
else:
|
|
1732
|
-
# Fall back to cso_root for
|
|
1897
|
+
# Fall back to cso_root for service context
|
|
1733
1898
|
filepath = self.builtin_cso_root(filepath)
|
|
1734
1899
|
|
|
1735
1900
|
# Check file exists
|
|
@@ -1923,7 +2088,7 @@ class CSSLBuiltins:
|
|
|
1923
2088
|
if os.path.exists(cwd_path):
|
|
1924
2089
|
filepath = cwd_path
|
|
1925
2090
|
else:
|
|
1926
|
-
# Fall back to cso_root for
|
|
2091
|
+
# Fall back to cso_root for service context
|
|
1927
2092
|
filepath = self.builtin_cso_root(filepath)
|
|
1928
2093
|
|
|
1929
2094
|
# Check file exists
|
|
@@ -2203,6 +2368,38 @@ class CSSLBuiltins:
|
|
|
2203
2368
|
from .cssl_types import OpenQuote
|
|
2204
2369
|
return OpenQuote(db_ref)
|
|
2205
2370
|
|
|
2371
|
+
def builtin_vector(self, element_type: str = 'dynamic') -> Any:
|
|
2372
|
+
"""Create a vector container.
|
|
2373
|
+
|
|
2374
|
+
Usage: vector<int> myVector; or vector('int')
|
|
2375
|
+
"""
|
|
2376
|
+
from .cssl_types import Vector
|
|
2377
|
+
return Vector(element_type)
|
|
2378
|
+
|
|
2379
|
+
def builtin_array(self, element_type: str = 'dynamic') -> Any:
|
|
2380
|
+
"""Create an array container.
|
|
2381
|
+
|
|
2382
|
+
Usage: array<string> myArray; or array('string')
|
|
2383
|
+
"""
|
|
2384
|
+
from .cssl_types import Array
|
|
2385
|
+
return Array(element_type)
|
|
2386
|
+
|
|
2387
|
+
def builtin_stack(self, element_type: str = 'dynamic') -> Any:
|
|
2388
|
+
"""Create a stack container.
|
|
2389
|
+
|
|
2390
|
+
Usage: stack<int> myStack; or stack('int')
|
|
2391
|
+
"""
|
|
2392
|
+
from .cssl_types import Stack
|
|
2393
|
+
return Stack(element_type)
|
|
2394
|
+
|
|
2395
|
+
def builtin_map(self, key_type: str = 'dynamic', value_type: str = 'dynamic') -> Any:
|
|
2396
|
+
"""Create a map container.
|
|
2397
|
+
|
|
2398
|
+
Usage: map<string, int> myMap; or map('string', 'int')
|
|
2399
|
+
"""
|
|
2400
|
+
from .cssl_types import Map
|
|
2401
|
+
return Map(key_type, value_type)
|
|
2402
|
+
|
|
2206
2403
|
def builtin_openfind(self, combo_or_type: Any, index: int = 0, params: list = None) -> Any:
|
|
2207
2404
|
"""Find open parameter by type or combo space.
|
|
2208
2405
|
|
|
@@ -2253,6 +2450,211 @@ class CSSLBuiltins:
|
|
|
2253
2450
|
|
|
2254
2451
|
return None
|
|
2255
2452
|
|
|
2453
|
+
# ============= Python Interop Functions =============
|
|
2454
|
+
|
|
2455
|
+
def builtin_python_pythonize(self, cssl_instance: Any) -> Any:
|
|
2456
|
+
"""Convert a CSSL class instance to a Python-usable object.
|
|
2457
|
+
|
|
2458
|
+
This allows CSSL classes to be returned and used in Python code
|
|
2459
|
+
with proper attribute access and method calls.
|
|
2460
|
+
|
|
2461
|
+
Usage in CSSL:
|
|
2462
|
+
class Greeter {
|
|
2463
|
+
string name;
|
|
2464
|
+
|
|
2465
|
+
Greeter(string n) {
|
|
2466
|
+
this->name = n;
|
|
2467
|
+
}
|
|
2468
|
+
|
|
2469
|
+
string sayHello() {
|
|
2470
|
+
return "Hello, " + this->name + "!";
|
|
2471
|
+
}
|
|
2472
|
+
|
|
2473
|
+
void setName(string newName) {
|
|
2474
|
+
this->name = newName;
|
|
2475
|
+
}
|
|
2476
|
+
|
|
2477
|
+
string getName() {
|
|
2478
|
+
return this->name;
|
|
2479
|
+
}
|
|
2480
|
+
}
|
|
2481
|
+
|
|
2482
|
+
greeter = new Greeter("World");
|
|
2483
|
+
pyclass = python::pythonize(greeter);
|
|
2484
|
+
parameter.return(pyclass);
|
|
2485
|
+
|
|
2486
|
+
Usage in Python:
|
|
2487
|
+
from includecpp import CSSL
|
|
2488
|
+
|
|
2489
|
+
cssl = CSSL.CsslLang()
|
|
2490
|
+
greeter = cssl.run('''
|
|
2491
|
+
class Greeter { ... }
|
|
2492
|
+
g = new Greeter("World");
|
|
2493
|
+
parameter.return(python::pythonize(g));
|
|
2494
|
+
''')
|
|
2495
|
+
|
|
2496
|
+
# Now use it like a normal Python object:
|
|
2497
|
+
print(greeter.name) # "World"
|
|
2498
|
+
print(greeter.sayHello()) # "Hello, World!"
|
|
2499
|
+
greeter.setName("Python")
|
|
2500
|
+
print(greeter.getName()) # "Python"
|
|
2501
|
+
|
|
2502
|
+
Args:
|
|
2503
|
+
cssl_instance: A CSSLInstance object (created via 'new ClassName()')
|
|
2504
|
+
|
|
2505
|
+
Returns:
|
|
2506
|
+
PythonizedCSSLInstance - A Python-friendly wrapper
|
|
2507
|
+
"""
|
|
2508
|
+
from .cssl_types import CSSLInstance, CSSLClass
|
|
2509
|
+
|
|
2510
|
+
if cssl_instance is None:
|
|
2511
|
+
return None
|
|
2512
|
+
|
|
2513
|
+
# Already pythonized
|
|
2514
|
+
if isinstance(cssl_instance, PythonizedCSSLInstance):
|
|
2515
|
+
return cssl_instance
|
|
2516
|
+
|
|
2517
|
+
# Must be a CSSLInstance
|
|
2518
|
+
if not isinstance(cssl_instance, CSSLInstance):
|
|
2519
|
+
# If it's a dict, wrap it as a simple object
|
|
2520
|
+
if isinstance(cssl_instance, dict):
|
|
2521
|
+
return PythonizedDict(cssl_instance)
|
|
2522
|
+
# Return as-is for primitives
|
|
2523
|
+
return cssl_instance
|
|
2524
|
+
|
|
2525
|
+
return PythonizedCSSLInstance(cssl_instance, self.runtime)
|
|
2526
|
+
|
|
2527
|
+
|
|
2528
|
+
class PythonizedCSSLInstance:
|
|
2529
|
+
"""Python wrapper for CSSL class instances.
|
|
2530
|
+
|
|
2531
|
+
Provides Pythonic attribute access and method calling for CSSL objects.
|
|
2532
|
+
"""
|
|
2533
|
+
|
|
2534
|
+
def __init__(self, instance: Any, runtime: Any = None):
|
|
2535
|
+
# Use object.__setattr__ to avoid triggering our custom __setattr__
|
|
2536
|
+
object.__setattr__(self, '_cssl_instance', instance)
|
|
2537
|
+
object.__setattr__(self, '_cssl_runtime', runtime)
|
|
2538
|
+
object.__setattr__(self, '_cssl_class_name', instance._class.name if hasattr(instance, '_class') else 'Unknown')
|
|
2539
|
+
|
|
2540
|
+
def __getattr__(self, name: str) -> Any:
|
|
2541
|
+
"""Get member or method from CSSL instance."""
|
|
2542
|
+
if name.startswith('_'):
|
|
2543
|
+
raise AttributeError(f"'{self._cssl_class_name}' has no attribute '{name}'")
|
|
2544
|
+
|
|
2545
|
+
instance = object.__getattribute__(self, '_cssl_instance')
|
|
2546
|
+
runtime = object.__getattribute__(self, '_cssl_runtime')
|
|
2547
|
+
|
|
2548
|
+
# Check for member variable first
|
|
2549
|
+
if instance.has_member(name):
|
|
2550
|
+
value = instance.get_member(name)
|
|
2551
|
+
# Recursively pythonize nested CSSL instances
|
|
2552
|
+
from .cssl_types import CSSLInstance
|
|
2553
|
+
if isinstance(value, CSSLInstance):
|
|
2554
|
+
return PythonizedCSSLInstance(value, runtime)
|
|
2555
|
+
return value
|
|
2556
|
+
|
|
2557
|
+
# Check for method
|
|
2558
|
+
method = instance.get_method(name)
|
|
2559
|
+
if method is not None:
|
|
2560
|
+
# Return a callable wrapper for the method
|
|
2561
|
+
return PythonizedMethod(instance, name, method, runtime)
|
|
2562
|
+
|
|
2563
|
+
raise AttributeError(f"'{self._cssl_class_name}' has no attribute '{name}'")
|
|
2564
|
+
|
|
2565
|
+
def __setattr__(self, name: str, value: Any) -> None:
|
|
2566
|
+
"""Set member value on CSSL instance."""
|
|
2567
|
+
if name.startswith('_'):
|
|
2568
|
+
object.__setattr__(self, name, value)
|
|
2569
|
+
return
|
|
2570
|
+
|
|
2571
|
+
instance = object.__getattribute__(self, '_cssl_instance')
|
|
2572
|
+
instance.set_member(name, value)
|
|
2573
|
+
|
|
2574
|
+
def __repr__(self) -> str:
|
|
2575
|
+
class_name = object.__getattribute__(self, '_cssl_class_name')
|
|
2576
|
+
instance = object.__getattribute__(self, '_cssl_instance')
|
|
2577
|
+
members = list(instance._members.keys()) if hasattr(instance, '_members') else []
|
|
2578
|
+
return f"<PythonizedCSSL '{class_name}' members={members}>"
|
|
2579
|
+
|
|
2580
|
+
def __dir__(self) -> list:
|
|
2581
|
+
"""List available attributes."""
|
|
2582
|
+
instance = object.__getattribute__(self, '_cssl_instance')
|
|
2583
|
+
members = list(instance._members.keys()) if hasattr(instance, '_members') else []
|
|
2584
|
+
methods = list(instance._class.methods.keys()) if hasattr(instance._class, 'methods') else []
|
|
2585
|
+
return members + methods
|
|
2586
|
+
|
|
2587
|
+
def _to_dict(self) -> dict:
|
|
2588
|
+
"""Convert to Python dictionary."""
|
|
2589
|
+
instance = object.__getattribute__(self, '_cssl_instance')
|
|
2590
|
+
result = {}
|
|
2591
|
+
for name, value in instance._members.items():
|
|
2592
|
+
from .cssl_types import CSSLInstance
|
|
2593
|
+
if isinstance(value, CSSLInstance):
|
|
2594
|
+
result[name] = PythonizedCSSLInstance(value, None)._to_dict()
|
|
2595
|
+
else:
|
|
2596
|
+
result[name] = value
|
|
2597
|
+
return result
|
|
2598
|
+
|
|
2599
|
+
|
|
2600
|
+
class PythonizedMethod:
|
|
2601
|
+
"""Wrapper that makes CSSL methods callable from Python."""
|
|
2602
|
+
|
|
2603
|
+
def __init__(self, instance: Any, method_name: str, method_ast: Any, runtime: Any):
|
|
2604
|
+
self._instance = instance
|
|
2605
|
+
self._method_name = method_name
|
|
2606
|
+
self._method_ast = method_ast
|
|
2607
|
+
self._runtime = runtime
|
|
2608
|
+
|
|
2609
|
+
def __call__(self, *args, **kwargs) -> Any:
|
|
2610
|
+
"""Call the CSSL method with arguments."""
|
|
2611
|
+
if self._runtime is None:
|
|
2612
|
+
raise RuntimeError(f"Cannot call method '{self._method_name}' - no runtime available")
|
|
2613
|
+
|
|
2614
|
+
# Execute the method through the runtime
|
|
2615
|
+
# Pass the method AST node, not the method name
|
|
2616
|
+
result = self._runtime._call_method(self._instance, self._method_ast, list(args), kwargs)
|
|
2617
|
+
|
|
2618
|
+
# Pythonize the result if it's a CSSL instance
|
|
2619
|
+
from .cssl_types import CSSLInstance
|
|
2620
|
+
if isinstance(result, CSSLInstance):
|
|
2621
|
+
return PythonizedCSSLInstance(result, self._runtime)
|
|
2622
|
+
|
|
2623
|
+
return result
|
|
2624
|
+
|
|
2625
|
+
def __repr__(self) -> str:
|
|
2626
|
+
return f"<method '{self._method_name}' of '{self._instance._class.name}'>"
|
|
2627
|
+
|
|
2628
|
+
|
|
2629
|
+
class PythonizedDict:
|
|
2630
|
+
"""Simple wrapper for dict objects with attribute access."""
|
|
2631
|
+
|
|
2632
|
+
def __init__(self, data: dict):
|
|
2633
|
+
object.__setattr__(self, '_data', data)
|
|
2634
|
+
|
|
2635
|
+
def __getattr__(self, name: str) -> Any:
|
|
2636
|
+
data = object.__getattribute__(self, '_data')
|
|
2637
|
+
if name in data:
|
|
2638
|
+
value = data[name]
|
|
2639
|
+
if isinstance(value, dict):
|
|
2640
|
+
return PythonizedDict(value)
|
|
2641
|
+
return value
|
|
2642
|
+
raise AttributeError(f"No attribute '{name}'")
|
|
2643
|
+
|
|
2644
|
+
def __setattr__(self, name: str, value: Any) -> None:
|
|
2645
|
+
if name.startswith('_'):
|
|
2646
|
+
object.__setattr__(self, name, value)
|
|
2647
|
+
return
|
|
2648
|
+
data = object.__getattribute__(self, '_data')
|
|
2649
|
+
data[name] = value
|
|
2650
|
+
|
|
2651
|
+
def __repr__(self) -> str:
|
|
2652
|
+
data = object.__getattribute__(self, '_data')
|
|
2653
|
+
return f"<PythonizedDict {data}>"
|
|
2654
|
+
|
|
2655
|
+
def _to_dict(self) -> dict:
|
|
2656
|
+
return object.__getattribute__(self, '_data')
|
|
2657
|
+
|
|
2256
2658
|
|
|
2257
2659
|
# Module-level convenience functions
|
|
2258
2660
|
_default_builtins: Optional[CSSLBuiltins] = None
|