IncludeCPP 4.0.2__py3-none-any.whl → 4.2.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.
@@ -278,6 +278,26 @@ class CSSLRuntime:
278
278
  self._setup_modules()
279
279
  self._setup_builtins()
280
280
 
281
+ def output(self, text: str, level: str = 'normal') -> None:
282
+ """Output text, using callback if available, otherwise print."""
283
+ if self._output_callback:
284
+ self._output_callback(text, level)
285
+ else:
286
+ print(text, end='')
287
+ self.output_buffer.append(text)
288
+
289
+ def debug(self, text: str) -> None:
290
+ """Debug output."""
291
+ self.output(f"[DEBUG] {text}\n", 'debug')
292
+
293
+ def error(self, text: str) -> None:
294
+ """Error output."""
295
+ self.output(f"[ERROR] {text}\n", 'error')
296
+
297
+ def warn(self, text: str) -> None:
298
+ """Warning output."""
299
+ self.output(f"[WARN] {text}\n", 'warning')
300
+
281
301
  def _setup_modules(self):
282
302
  """Setup module references for @KernelClient, @VSRAM, etc."""
283
303
  if self.service_engine:
@@ -863,6 +883,18 @@ class CSSLRuntime:
863
883
  class_params = class_info.get('class_params', [])
864
884
  extends_args = class_info.get('extends_args', [])
865
885
 
886
+ # v4.2.0: Handle 'supports' language transformation for raw_body
887
+ supports_language = class_info.get('supports_language')
888
+ raw_body = class_info.get('raw_body')
889
+
890
+ if raw_body and supports_language:
891
+ # Transform raw body from target language to CSSL and parse
892
+ transformed_children = self._transform_and_parse_class_body(
893
+ raw_body, supports_language, class_name
894
+ )
895
+ # Add transformed children to node's children
896
+ node.children = transformed_children
897
+
866
898
  for child in node.children:
867
899
  if child.type == 'constructor':
868
900
  # New-style constructor from 'constr' keyword
@@ -987,6 +1019,119 @@ class CSSLRuntime:
987
1019
  self._current_instance = old_instance
988
1020
  return wrapper
989
1021
 
1022
+ def _transform_and_parse_class_body(self, raw_body: str, language: str, class_name: str) -> list:
1023
+ """Transform source code from another language to CSSL and parse as class body.
1024
+
1025
+ v4.2.0: Used for 'supports <lang>' in class definitions.
1026
+
1027
+ Args:
1028
+ raw_body: Raw source code in the target language
1029
+ language: Language identifier (py, python, cpp, c++, js, javascript, etc.)
1030
+ class_name: Name of the class (for constructor recognition)
1031
+
1032
+ Returns:
1033
+ List of parsed AST nodes representing methods, constructors, and members
1034
+ """
1035
+ import textwrap
1036
+ from .cssl_languages import get_language
1037
+ from .cssl_parser import parse_cssl_program, ASTNode
1038
+
1039
+ # Normalize language ID
1040
+ lang_id = language.lstrip('@').lower()
1041
+
1042
+ # Get language support and transformer
1043
+ lang_support = get_language(lang_id)
1044
+ if lang_support is None:
1045
+ raise CSSLRuntimeError(f"Unknown language '{lang_id}' in 'supports' clause")
1046
+
1047
+ # Dedent the raw body to normalize indentation
1048
+ # This fixes the issue where code inside CSSL {} has relative indentation
1049
+ dedented_body = textwrap.dedent(raw_body)
1050
+
1051
+ # Transform the raw body to CSSL syntax
1052
+ transformer = lang_support.get_transformer()
1053
+ transformed_source = transformer.transform_source(dedented_body)
1054
+
1055
+ # Wrap in a dummy class for parsing
1056
+ wrapper_source = f"class _TempClass {{\n{transformed_source}\n}}"
1057
+
1058
+ try:
1059
+ ast = parse_cssl_program(wrapper_source)
1060
+ except Exception as e:
1061
+ raise CSSLRuntimeError(
1062
+ f"Failed to parse transformed '{lang_id}' code: {e}\n"
1063
+ f"Dedented:\n{dedented_body}\n"
1064
+ f"Transformed:\n{transformed_source}"
1065
+ )
1066
+
1067
+ # Extract children from the parsed temp class
1068
+ children = []
1069
+ for top_level in ast.children:
1070
+ if top_level.type == 'class':
1071
+ for child in top_level.children:
1072
+ # Mark constructor if method name matches class_name or is __init__
1073
+ if child.type == 'function':
1074
+ func_info = child.value
1075
+ method_name = func_info.get('name')
1076
+ if method_name == class_name or method_name == '__init__':
1077
+ child.value['is_constructor'] = True
1078
+ children.append(child)
1079
+ break
1080
+
1081
+ return children
1082
+
1083
+ def _transform_and_parse_function_body(self, raw_body: str, language: str) -> list:
1084
+ """Transform source code from another language to CSSL and parse as function body.
1085
+
1086
+ v4.2.0: Used for 'supports <lang>' in function definitions.
1087
+
1088
+ Args:
1089
+ raw_body: Raw source code in the target language
1090
+ language: Language identifier (py, python, cpp, c++, js, javascript, etc.)
1091
+
1092
+ Returns:
1093
+ List of parsed AST nodes representing statements in the function body
1094
+ """
1095
+ import textwrap
1096
+ from .cssl_languages import get_language
1097
+ from .cssl_parser import parse_cssl_program
1098
+
1099
+ # Normalize language ID
1100
+ lang_id = language.lstrip('@').lower()
1101
+
1102
+ # Get language support and transformer
1103
+ lang_support = get_language(lang_id)
1104
+ if lang_support is None:
1105
+ raise CSSLRuntimeError(f"Unknown language '{lang_id}' in 'supports' clause")
1106
+
1107
+ # Dedent the raw body to normalize indentation
1108
+ dedented_body = textwrap.dedent(raw_body)
1109
+
1110
+ # Transform the raw body to CSSL syntax
1111
+ transformer = lang_support.get_transformer()
1112
+ transformed_source = transformer.transform_source(dedented_body)
1113
+
1114
+ # Wrap in a dummy function for parsing
1115
+ wrapper_source = f"define _TempFunc() {{\n{transformed_source}\n}}"
1116
+
1117
+ try:
1118
+ ast = parse_cssl_program(wrapper_source)
1119
+ except Exception as e:
1120
+ raise CSSLRuntimeError(
1121
+ f"Failed to parse transformed '{lang_id}' code: {e}\n"
1122
+ f"Dedented:\n{dedented_body}\n"
1123
+ f"Transformed:\n{transformed_source}"
1124
+ )
1125
+
1126
+ # Extract children from the parsed temp function
1127
+ children = []
1128
+ for top_level in ast.children:
1129
+ if top_level.type == 'function':
1130
+ children = top_level.children
1131
+ break
1132
+
1133
+ return children
1134
+
990
1135
  def _exec_function(self, node: ASTNode) -> Any:
991
1136
  """Execute function definition - registers it and handles extends/overwrites.
992
1137
 
@@ -1152,16 +1297,22 @@ class CSSLRuntime:
1152
1297
  if ref_member and hasattr(ref_obj, ref_member):
1153
1298
  original_method = getattr(ref_obj, ref_member)
1154
1299
  runtime = self
1300
+ # Store the original method before wrapping
1301
+ _saved_original = original_method
1155
1302
  def appended_wrapper(*args, **kwargs):
1156
- # Run original first
1303
+ # Run original first (use saved reference to avoid recursion)
1157
1304
  result = None
1158
- if callable(original_method):
1305
+ if callable(_saved_original):
1159
1306
  try:
1160
- result = original_method(*args, **kwargs)
1307
+ result = _saved_original(*args, **kwargs)
1161
1308
  except:
1162
1309
  pass
1163
- # Then run appended code
1164
- return runtime._call_function(append_node, list(args), kwargs)
1310
+ # Then run appended code - disable append_mode to prevent recursion
1311
+ append_node.value['append_mode'] = False
1312
+ try:
1313
+ return runtime._call_function(append_node, list(args), kwargs)
1314
+ finally:
1315
+ append_node.value['append_mode'] = True
1165
1316
  try:
1166
1317
  setattr(ref_obj, ref_member, appended_wrapper)
1167
1318
  except (AttributeError, TypeError):
@@ -1310,29 +1461,38 @@ class CSSLRuntime:
1310
1461
  def _exec_instance_declaration(self, node: ASTNode) -> Any:
1311
1462
  """Execute instance declaration: instance<"name"> varName;
1312
1463
 
1313
- Gets or creates a shared instance by name.
1464
+ Gets or creates a universal shared instance by name.
1465
+ Universal instances are accessible from CSSL, Python, and C++.
1466
+
1467
+ Usage:
1468
+ instance<"myContainer"> container; // Creates or gets instance
1469
+ container.member = "value"; // Set member
1470
+ container +<<== { void func() {} } // Inject methods
1314
1471
  """
1315
- from ..cssl_bridge import _live_objects, SharedObjectProxy
1472
+ from .cssl_types import UniversalInstance
1473
+
1316
1474
  decl = node.value
1317
1475
  instance_name = decl.get('instance_name')
1318
1476
  var_name = decl.get('name')
1319
1477
  value_node = decl.get('value')
1320
1478
 
1321
- # Get existing shared instance
1322
- instance = None
1323
- if instance_name in _live_objects:
1324
- instance = SharedObjectProxy(instance_name, _live_objects[instance_name])
1325
- elif self.global_scope.has(f'${instance_name}'):
1326
- instance = self.global_scope.get(f'${instance_name}')
1479
+ # Get existing or create new universal instance
1480
+ instance = UniversalInstance.get_or_create(instance_name)
1327
1481
 
1328
- # If value is provided, use that and register as shared
1482
+ # If value is provided, set it as initial content
1329
1483
  if value_node:
1330
- instance = self._evaluate(value_node)
1331
- # Register in global scope for future access
1332
- self.global_scope.set(f'${instance_name}', instance)
1484
+ initial_value = self._evaluate(value_node)
1485
+ # If it's a dict, set all keys as members
1486
+ if isinstance(initial_value, dict):
1487
+ for key, val in initial_value.items():
1488
+ instance.set_member(key, val)
1489
+ else:
1490
+ instance.set_member('value', initial_value)
1333
1491
 
1334
- # Store in scope
1492
+ # Store in scope and global scope for access
1335
1493
  self.scope.set(var_name, instance)
1494
+ self.global_scope.set(f'${instance_name}', instance)
1495
+
1336
1496
  return instance
1337
1497
 
1338
1498
  def _exec_super_func(self, node: ASTNode) -> Any:
@@ -1517,13 +1677,15 @@ class CSSLRuntime:
1517
1677
 
1518
1678
  # Bind parameters - handle both positional and named arguments
1519
1679
  for i, param in enumerate(params):
1520
- # Extract param name and type from dict format: {'name': 'a', 'type': 'int'}
1680
+ # Extract param name, type, and default from dict format: {'name': 'a', 'type': 'int', 'default': ...}
1521
1681
  if isinstance(param, dict):
1522
1682
  param_name = param['name']
1523
1683
  param_type = param.get('type', '')
1684
+ param_default = param.get('default') # v4.2.0: Default value AST node
1524
1685
  else:
1525
1686
  param_name = param
1526
1687
  param_type = ''
1688
+ param_default = None
1527
1689
 
1528
1690
  # Check if this is an 'open' parameter - receives all args as a list
1529
1691
  # The parser sets param['open'] = True for 'open' keyword
@@ -1546,6 +1708,10 @@ class CSSLRuntime:
1546
1708
  elif i < len(args):
1547
1709
  # Positional argument
1548
1710
  new_scope.set(param_name, args[i])
1711
+ elif param_default is not None:
1712
+ # v4.2.0: Use default value if no argument provided
1713
+ default_value = self._evaluate(param_default)
1714
+ new_scope.set(param_name, default_value)
1549
1715
  else:
1550
1716
  new_scope.set(param_name, None)
1551
1717
 
@@ -1565,11 +1731,24 @@ class CSSLRuntime:
1565
1731
  args, kwargs, {}, is_constructor=False
1566
1732
  )
1567
1733
 
1568
- for child in func_node.children:
1569
- # Check if exit() was called
1570
- if not self._running:
1571
- break
1572
- self._execute_node(child)
1734
+ # v4.2.0: Handle raw_body with supports_language (multi-language support)
1735
+ raw_body = func_info.get('raw_body')
1736
+ supports_language = func_info.get('supports_language')
1737
+
1738
+ if raw_body and supports_language:
1739
+ # Transform and parse the raw body from the target language
1740
+ body_children = self._transform_and_parse_function_body(raw_body, supports_language)
1741
+ for child in body_children:
1742
+ if not self._running:
1743
+ break
1744
+ self._execute_node(child)
1745
+ else:
1746
+ # Normal CSSL function body
1747
+ for child in func_node.children:
1748
+ # Check if exit() was called
1749
+ if not self._running:
1750
+ break
1751
+ self._execute_node(child)
1573
1752
  except CSSLReturn as ret:
1574
1753
  return_value = ret.value
1575
1754
 
@@ -1952,6 +2131,71 @@ class CSSLRuntime:
1952
2131
 
1953
2132
  return None
1954
2133
 
2134
+ def _exec_supports_block(self, node: ASTNode) -> Any:
2135
+ """Execute standalone supports block for multi-language syntax.
2136
+
2137
+ v4.2.0: Allows 'supports' to be used anywhere, not just in class/function.
2138
+
2139
+ Syntax:
2140
+ supports py {
2141
+ for i in range(10):
2142
+ print(i)
2143
+ }
2144
+
2145
+ supports cpp {
2146
+ int x = 42;
2147
+ std::cout << x << std::endl;
2148
+ }
2149
+ """
2150
+ block_info = node.value
2151
+ language = block_info.get('language')
2152
+ raw_source = block_info.get('raw_source')
2153
+
2154
+ # If we have raw_source, transform and execute
2155
+ if raw_source and language:
2156
+ import textwrap
2157
+ from .cssl_languages import get_language
2158
+ from .cssl_parser import parse_cssl_program
2159
+
2160
+ # Normalize language ID
2161
+ lang_id = language.lstrip('@').lower()
2162
+
2163
+ # Get language support and transformer
2164
+ lang_support = get_language(lang_id)
2165
+ if lang_support is None:
2166
+ raise CSSLRuntimeError(f"Unknown language '{lang_id}' in 'supports' block")
2167
+
2168
+ # Dedent the raw source to normalize indentation
2169
+ dedented_source = textwrap.dedent(raw_source)
2170
+
2171
+ # Transform the raw source to CSSL
2172
+ transformer = lang_support.get_transformer()
2173
+ transformed_source = transformer.transform_source(dedented_source)
2174
+
2175
+ # Parse the transformed CSSL
2176
+ try:
2177
+ ast = parse_cssl_program(transformed_source)
2178
+ except Exception as e:
2179
+ raise CSSLRuntimeError(
2180
+ f"Failed to parse transformed '{lang_id}' code in supports block: {e}\n"
2181
+ f"Dedented:\n{dedented_source}\n"
2182
+ f"Transformed:\n{transformed_source}"
2183
+ )
2184
+
2185
+ # Execute the transformed AST
2186
+ result = None
2187
+ for child in ast.children:
2188
+ result = self._execute_node(child)
2189
+
2190
+ return result
2191
+
2192
+ # Fallback: execute already-parsed children (CSSL syntax)
2193
+ result = None
2194
+ for child in node.children:
2195
+ result = self._execute_node(child)
2196
+
2197
+ return result
2198
+
1955
2199
  def _exec_createcmd_inject(self, node: ASTNode) -> Any:
1956
2200
  """Execute createcmd injection: createcmd('cmd') <== { action }"""
1957
2201
  command_call = node.value.get('command_call')
@@ -2520,24 +2764,60 @@ class CSSLRuntime:
2520
2764
  if filter_info:
2521
2765
  source = self._apply_injection_filter(source, filter_info)
2522
2766
 
2523
- # Get current target value for add/move modes
2767
+ # Get current target value for add/move/replace modes (needed for UniversalInstance handling)
2524
2768
  current_value = None
2525
- if mode in ('add', 'move'):
2526
- try:
2527
- current_value = self._evaluate(target)
2528
- except Exception:
2529
- # Target might not exist yet, that's okay for add mode
2530
- current_value = None
2769
+ try:
2770
+ current_value = self._evaluate(target)
2771
+ except Exception:
2772
+ # Target might not exist yet, that's okay for add mode
2773
+ current_value = None
2531
2774
 
2532
2775
  # Determine final value based on mode
2533
2776
  if mode == 'replace':
2534
- final_value = source
2777
+ from .cssl_types import CSSLInstance, UniversalInstance, CSSLClass
2778
+ # Special handling for UniversalInstance targets - inject instead of replace
2779
+ if isinstance(current_value, UniversalInstance):
2780
+ if isinstance(source, CSSLClass):
2781
+ current_value.set_member(source.name, source)
2782
+ final_value = current_value
2783
+ elif isinstance(source, ASTNode) and source.type == 'function':
2784
+ func_info = source.value
2785
+ func_name = func_info.get('name') if isinstance(func_info, dict) else None
2786
+ if func_name:
2787
+ current_value.set_method(func_name, source, self)
2788
+ final_value = current_value
2789
+ elif isinstance(source, CSSLInstance):
2790
+ current_value.set_member(source._class.name, source)
2791
+ final_value = current_value
2792
+ else:
2793
+ # For other types, store as member with source type name
2794
+ final_value = source
2795
+ else:
2796
+ final_value = source
2535
2797
  elif mode == 'add':
2536
2798
  # Copy & add - preserve target and add source
2537
- from .cssl_types import CSSLInstance
2799
+ from .cssl_types import CSSLInstance, UniversalInstance, CSSLClass
2538
2800
 
2801
+ # Special handling for UniversalInstance + CSSLClass
2802
+ if isinstance(current_value, UniversalInstance) and isinstance(source, CSSLClass):
2803
+ # Inject class definition into universal instance
2804
+ current_value.set_member(source.name, source)
2805
+ final_value = current_value
2806
+ # Special handling for UniversalInstance + Function (AST node)
2807
+ elif isinstance(current_value, UniversalInstance) and isinstance(source, ASTNode) and source.type == 'function':
2808
+ # Inject function as a method into universal instance
2809
+ func_info = source.value
2810
+ func_name = func_info.get('name') if isinstance(func_info, dict) else None
2811
+ if func_name:
2812
+ current_value.set_method(func_name, source, self)
2813
+ final_value = current_value
2814
+ # Special handling for UniversalInstance + CSSLInstance
2815
+ elif isinstance(current_value, UniversalInstance) and isinstance(source, CSSLInstance):
2816
+ class_name = source._class.name
2817
+ current_value.set_member(class_name, source)
2818
+ final_value = current_value
2539
2819
  # Special handling for CSSLInstance - merge classes
2540
- if isinstance(current_value, CSSLInstance) and isinstance(source, CSSLInstance):
2820
+ elif isinstance(current_value, CSSLInstance) and isinstance(source, CSSLInstance):
2541
2821
  # Add the new class instance as a member with class name as key
2542
2822
  class_name = source._class.name
2543
2823
  current_value._members[class_name] = source
@@ -2736,8 +3016,13 @@ class CSSLRuntime:
2736
3016
  - add: func +<<== { code } - ADDS code to function (both execute)
2737
3017
  - remove: func -<<== { code } - REMOVES matching code from function
2738
3018
 
3019
+ Also supports instance injection:
3020
+ - instance +<<== { void method() { ... } } - ADDS methods to UniversalInstance
3021
+
2739
3022
  Also supports expression form: func <<== %exit() (wraps in action_block)
2740
3023
  """
3024
+ from .cssl_types import UniversalInstance
3025
+
2741
3026
  target = node.value.get('target')
2742
3027
  code_block = node.value.get('code')
2743
3028
  source_expr = node.value.get('source') # For expression form: func <<== expr
@@ -2749,6 +3034,17 @@ class CSSLRuntime:
2749
3034
  expr_node = ASTNode('expression', value=source_expr)
2750
3035
  code_block = ASTNode('action_block', children=[expr_node])
2751
3036
 
3037
+ # Check if target is a UniversalInstance
3038
+ target_value = None
3039
+ if isinstance(target, ASTNode) and target.type == 'identifier':
3040
+ target_value = self.scope.get(target.value)
3041
+ if target_value is None:
3042
+ target_value = self.global_scope.get(target.value)
3043
+
3044
+ # Handle UniversalInstance injection
3045
+ if isinstance(target_value, UniversalInstance):
3046
+ return self._inject_into_instance(target_value, code_block, mode)
3047
+
2752
3048
  # Get function name from target
2753
3049
  func_name = None
2754
3050
  if isinstance(target, ASTNode):
@@ -2796,6 +3092,60 @@ class CSSLRuntime:
2796
3092
 
2797
3093
  return None
2798
3094
 
3095
+ def _inject_into_instance(self, instance: Any, code_block: Any, mode: str) -> Any:
3096
+ """Inject code/methods into a UniversalInstance.
3097
+
3098
+ Usage:
3099
+ instance<"myContainer"> container;
3100
+ container +<<== {
3101
+ void sayHello() { printl("Hello!"); }
3102
+ int value = 42;
3103
+ }
3104
+ """
3105
+ from .cssl_types import UniversalInstance
3106
+
3107
+ if not isinstance(instance, UniversalInstance):
3108
+ return None
3109
+
3110
+ if code_block is None:
3111
+ return None
3112
+
3113
+ # Store the raw injection
3114
+ instance.add_injection(code_block)
3115
+
3116
+ # Parse the code block for function definitions and variable declarations
3117
+ if isinstance(code_block, ASTNode):
3118
+ children = code_block.children if hasattr(code_block, 'children') else []
3119
+
3120
+ for child in children:
3121
+ if isinstance(child, ASTNode):
3122
+ if child.type == 'function':
3123
+ # Extract function name and store the AST node
3124
+ func_info = child.value
3125
+ func_name = func_info.get('name') if isinstance(func_info, dict) else None
3126
+ if func_name:
3127
+ instance.set_method(func_name, child, self)
3128
+ elif child.type == 'var_declaration':
3129
+ # Extract variable and value
3130
+ var_info = child.value
3131
+ if isinstance(var_info, dict):
3132
+ var_name = var_info.get('name')
3133
+ value_node = var_info.get('value')
3134
+ if var_name:
3135
+ value = self._evaluate(value_node) if value_node else None
3136
+ instance.set_member(var_name, value)
3137
+ elif child.type == 'typed_var_declaration':
3138
+ # Typed variable declaration
3139
+ var_info = child.value
3140
+ if isinstance(var_info, dict):
3141
+ var_name = var_info.get('name')
3142
+ value_node = var_info.get('value')
3143
+ if var_name:
3144
+ value = self._evaluate(value_node) if value_node else None
3145
+ instance.set_member(var_name, value)
3146
+
3147
+ return instance
3148
+
2799
3149
  def _exec_infuse_right(self, node: ASTNode) -> Any:
2800
3150
  """Execute right-side code infusion (==>>)"""
2801
3151
  source = node.value.get('source')
@@ -2882,7 +3232,13 @@ class CSSLRuntime:
2882
3232
  if self._current_instance is None:
2883
3233
  raise CSSLRuntimeError("'this' used outside of class method context")
2884
3234
  member = target.value.get('member')
2885
- self._current_instance.set_member(member, value)
3235
+ instance = self._current_instance
3236
+ # Check if instance is a CSSL instance or a plain Python object
3237
+ if hasattr(instance, 'set_member'):
3238
+ instance.set_member(member, value)
3239
+ else:
3240
+ # Plain Python object - use setattr
3241
+ setattr(instance, member, value)
2886
3242
  elif isinstance(target, str):
2887
3243
  self.scope.set(target, value)
2888
3244
 
@@ -3115,6 +3471,83 @@ class CSSLRuntime:
3115
3471
  # Return None if instance doesn't exist (can be created via ==>)
3116
3472
  return None
3117
3473
 
3474
+ # v4.1.0/v4.1.1: Cross-language instance reference: cpp$ClassName, py$Object
3475
+ # Enhanced bidirectional access with real runtime bridges
3476
+ if node.type == 'lang_instance_ref':
3477
+ ref = node.value # {'lang': 'cpp', 'instance': 'ClassName'}
3478
+ lang_id = ref['lang']
3479
+ instance_name = ref['instance']
3480
+
3481
+ # First, try to get the language support object from scope
3482
+ lang_support = self.scope.get(lang_id)
3483
+ if lang_support is None:
3484
+ lang_support = self.global_scope.get(lang_id)
3485
+
3486
+ # If not found in scope, try to get from modules
3487
+ if lang_support is None:
3488
+ lang_support = self._modules.get(lang_id)
3489
+
3490
+ # If still not found, try getting default language support
3491
+ if lang_support is None:
3492
+ from .cssl_languages import get_language
3493
+ lang_support = get_language(lang_id)
3494
+
3495
+ if lang_support is not None:
3496
+ # v4.1.1: Check if it's a LanguageSupport object with get_instance method
3497
+ if hasattr(lang_support, 'get_instance'):
3498
+ instance = lang_support.get_instance(instance_name)
3499
+ if instance is not None:
3500
+ return instance
3501
+
3502
+ # v4.1.1: For C++, also try to get class from loaded modules directly
3503
+ if hasattr(lang_support, '_get_bridge'):
3504
+ bridge = lang_support._get_bridge()
3505
+ if bridge is not None:
3506
+ # Try to get from bridge's instances
3507
+ bridge_instance = bridge.get_instance(instance_name)
3508
+ if bridge_instance is not None:
3509
+ return bridge_instance
3510
+
3511
+ # For C++: Try to access class from IncludeCPP modules
3512
+ if hasattr(bridge, '_modules'):
3513
+ for mod in bridge._modules.values():
3514
+ if hasattr(mod, instance_name):
3515
+ cls_or_instance = getattr(mod, instance_name)
3516
+ # Cache it for future access
3517
+ lang_support._instances[instance_name] = cls_or_instance
3518
+ return cls_or_instance
3519
+
3520
+ # Check _instances dict directly as fallback
3521
+ if hasattr(lang_support, '_instances'):
3522
+ if instance_name in lang_support._instances:
3523
+ return lang_support._instances[instance_name]
3524
+
3525
+ # Build helpful error message based on language
3526
+ if lang_id in ('cpp', 'c++'):
3527
+ hint = (f"For C++ access:\n"
3528
+ f" 1. Build your module with 'includecpp build'\n"
3529
+ f" 2. Use cpp.share(\"{instance_name}\", instance) to register\n"
3530
+ f" 3. Or access a class directly: obj = new cpp${instance_name}()")
3531
+ elif lang_id in ('java',):
3532
+ hint = (f"For Java access:\n"
3533
+ f" 1. Install JPype: pip install jpype1\n"
3534
+ f" 2. Add classpath: java.add_classpath(\"path/to/jar\")\n"
3535
+ f" 3. Load class: MyClass = java.load_class(\"com.example.{instance_name}\")\n"
3536
+ f" 4. Share instance: java.share(\"{instance_name}\", instance)")
3537
+ elif lang_id in ('js', 'javascript'):
3538
+ hint = (f"For JavaScript access:\n"
3539
+ f" 1. Make sure Node.js is installed\n"
3540
+ f" 2. Define in JS: js.eval(\"function {instance_name}() {{...}}\")\n"
3541
+ f" 3. Share result: js.share(\"{instance_name}\", result)")
3542
+ else:
3543
+ hint = f"Use '{lang_id}.share(\"{instance_name}\", instance)' to register the instance first."
3544
+
3545
+ raise self._format_error(
3546
+ node.line if hasattr(node, 'line') else 0,
3547
+ f"Cross-language instance '{lang_id}${instance_name}' not found",
3548
+ hint
3549
+ )
3550
+
3118
3551
  if node.type == 'new':
3119
3552
  # Create new instance of a class: new ClassName(args)
3120
3553
  return self._eval_new(node)
@@ -3188,6 +3621,14 @@ class CSSLRuntime:
3188
3621
  if node.type == 'unary':
3189
3622
  return self._eval_unary(node)
3190
3623
 
3624
+ # Increment: ++i or i++
3625
+ if node.type == 'increment':
3626
+ return self._eval_increment(node)
3627
+
3628
+ # Decrement: --i or i--
3629
+ if node.type == 'decrement':
3630
+ return self._eval_decrement(node)
3631
+
3191
3632
  if node.type == 'non_null_assert':
3192
3633
  # *$var, *@module, *identifier - assert value is not null/None
3193
3634
  operand = node.value.get('operand')
@@ -3473,6 +3914,74 @@ class CSSLRuntime:
3473
3914
 
3474
3915
  return None
3475
3916
 
3917
+ def _eval_increment(self, node: ASTNode) -> Any:
3918
+ """Evaluate increment operation (++i or i++)"""
3919
+ op_type = node.value.get('op') # 'prefix' or 'postfix'
3920
+ operand = node.value.get('operand')
3921
+
3922
+ # Get variable name
3923
+ var_name = None
3924
+ if isinstance(operand, ASTNode):
3925
+ if operand.type == 'identifier':
3926
+ var_name = operand.value
3927
+ elif operand.type == 'shared_ref':
3928
+ # Handle $var++
3929
+ var_name = operand.value
3930
+ current = self.shared_vars.get(var_name, 0)
3931
+ if op_type == 'prefix':
3932
+ self.shared_vars[var_name] = current + 1
3933
+ return current + 1
3934
+ else: # postfix
3935
+ self.shared_vars[var_name] = current + 1
3936
+ return current
3937
+
3938
+ if var_name:
3939
+ current = self.scope.get(var_name, 0)
3940
+ if op_type == 'prefix':
3941
+ # ++i: increment then return
3942
+ self.scope.set(var_name, current + 1)
3943
+ return current + 1
3944
+ else:
3945
+ # i++: return then increment
3946
+ self.scope.set(var_name, current + 1)
3947
+ return current
3948
+
3949
+ return None
3950
+
3951
+ def _eval_decrement(self, node: ASTNode) -> Any:
3952
+ """Evaluate decrement operation (--i or i--)"""
3953
+ op_type = node.value.get('op') # 'prefix' or 'postfix'
3954
+ operand = node.value.get('operand')
3955
+
3956
+ # Get variable name
3957
+ var_name = None
3958
+ if isinstance(operand, ASTNode):
3959
+ if operand.type == 'identifier':
3960
+ var_name = operand.value
3961
+ elif operand.type == 'shared_ref':
3962
+ # Handle $var--
3963
+ var_name = operand.value
3964
+ current = self.shared_vars.get(var_name, 0)
3965
+ if op_type == 'prefix':
3966
+ self.shared_vars[var_name] = current - 1
3967
+ return current - 1
3968
+ else: # postfix
3969
+ self.shared_vars[var_name] = current - 1
3970
+ return current
3971
+
3972
+ if var_name:
3973
+ current = self.scope.get(var_name, 0)
3974
+ if op_type == 'prefix':
3975
+ # --i: decrement then return
3976
+ self.scope.set(var_name, current - 1)
3977
+ return current - 1
3978
+ else:
3979
+ # i--: return then decrement
3980
+ self.scope.set(var_name, current - 1)
3981
+ return current
3982
+
3983
+ return None
3984
+
3476
3985
  def _eval_call(self, node: ASTNode) -> Any:
3477
3986
  """Evaluate function call with optional named arguments"""
3478
3987
  callee_node = node.value.get('callee')
@@ -3516,7 +4025,33 @@ class CSSLRuntime:
3516
4025
  if isinstance(callee, ASTNode) and callee.type == 'function':
3517
4026
  return self._call_function(callee, args, kwargs)
3518
4027
 
3519
- callee_name = callee_node.value if isinstance(callee_node, ASTNode) and hasattr(callee_node, 'value') else str(callee_node)
4028
+ # Extract callee name for error messages
4029
+ if isinstance(callee_node, ASTNode) and hasattr(callee_node, 'value'):
4030
+ val = callee_node.value
4031
+ if isinstance(val, str):
4032
+ callee_name = val
4033
+ elif isinstance(val, dict):
4034
+ # For member access nodes like obj.method, get the member name
4035
+ if 'member' in val:
4036
+ obj_node = val.get('object')
4037
+ member = val.get('member')
4038
+ obj_name = obj_node.value if isinstance(obj_node, ASTNode) else str(obj_node)
4039
+ callee_name = f"{obj_name}.{member}"
4040
+ # For call nodes, try to get the callee name
4041
+ elif 'callee' in val:
4042
+ callee_val = val.get('callee')
4043
+ if isinstance(callee_val, ASTNode):
4044
+ callee_name = callee_val.value if isinstance(callee_val.value, str) else str(callee_val.value)
4045
+ else:
4046
+ callee_name = str(callee_val)
4047
+ elif 'name' in val:
4048
+ callee_name = str(val.get('name'))
4049
+ else:
4050
+ callee_name = str(val)
4051
+ else:
4052
+ callee_name = str(val)
4053
+ else:
4054
+ callee_name = str(callee_node)
3520
4055
 
3521
4056
  # Build detailed error with suggestions
3522
4057
  available_funcs = _get_available_functions(self.scope, self.global_scope, self.builtins)
@@ -3658,6 +4193,22 @@ class CSSLRuntime:
3658
4193
  hint
3659
4194
  )
3660
4195
 
4196
+ # If we got a variable that holds a class reference, use that class
4197
+ if not isinstance(class_def, CSSLClass):
4198
+ # Check if it's a variable holding a class (dynamic class instantiation)
4199
+ if hasattr(class_def, '__class__') and isinstance(class_def, CSSLClass):
4200
+ pass # Already a CSSLClass, continue
4201
+ elif isinstance(class_def, dict) and 'class_def' in class_def:
4202
+ # Injected class reference from +<== operator
4203
+ class_def = class_def['class_def']
4204
+ else:
4205
+ # Not a class - show error
4206
+ raise CSSLRuntimeError(
4207
+ f"'{class_name}' is not a class",
4208
+ node.line,
4209
+ hint=f"'{class_name}' is of type {type(class_def).__name__}"
4210
+ )
4211
+
3661
4212
  if not isinstance(class_def, CSSLClass):
3662
4213
  raise CSSLRuntimeError(
3663
4214
  f"'{class_name}' is not a class",
@@ -3955,24 +4506,40 @@ class CSSLRuntime:
3955
4506
  # Direct this->member access
3956
4507
  instance = self._current_instance
3957
4508
 
3958
- # Check if it's a member variable
3959
- if instance.has_member(member):
3960
- return instance.get_member(member)
4509
+ # Check if instance is a CSSL instance or a plain Python object
4510
+ is_cssl_instance = hasattr(instance, 'has_member') and hasattr(instance, 'has_method')
3961
4511
 
3962
- # Check if it's a method
3963
- if instance.has_method(member):
3964
- # Return a callable that will invoke the method with instance context
3965
- method_node = instance.get_method(member)
3966
- # Check if this is an inherited Python method
3967
- if isinstance(method_node, tuple) and method_node[0] == 'python_method':
3968
- python_method = method_node[1]
3969
- return lambda *args, **kwargs: python_method(*args, **kwargs)
3970
- return lambda *args, **kwargs: self._call_method(instance, method_node, list(args), kwargs)
4512
+ if is_cssl_instance:
4513
+ # CSSL instance - use CSSL methods
4514
+ if instance.has_member(member):
4515
+ return instance.get_member(member)
4516
+
4517
+ # Check if it's a method
4518
+ if instance.has_method(member):
4519
+ # Return a callable that will invoke the method with instance context
4520
+ method_node = instance.get_method(member)
4521
+ # Check if this is an inherited Python method
4522
+ if isinstance(method_node, tuple) and method_node[0] == 'python_method':
4523
+ python_method = method_node[1]
4524
+ return lambda *args, **kwargs: python_method(*args, **kwargs)
4525
+ return lambda *args, **kwargs: self._call_method(instance, method_node, list(args), kwargs)
4526
+ else:
4527
+ # Plain Python object - use standard attribute access
4528
+ if hasattr(instance, member):
4529
+ return getattr(instance, member)
4530
+ # Also check __dict__ for dynamic attributes
4531
+ if hasattr(instance, '__dict__') and member in instance.__dict__:
4532
+ return instance.__dict__[member]
3971
4533
 
3972
4534
  # Build helpful error with available members
3973
- class_name = instance._class.name
3974
- available_members = list(instance._members.keys()) if hasattr(instance, '_members') else []
3975
- available_methods = list(instance._methods.keys()) if hasattr(instance, '_methods') else []
4535
+ if is_cssl_instance:
4536
+ class_name = instance._class.name
4537
+ available_members = list(instance._members.keys()) if hasattr(instance, '_members') else []
4538
+ available_methods = list(instance._methods.keys()) if hasattr(instance, '_methods') else []
4539
+ else:
4540
+ class_name = type(instance).__name__
4541
+ available_members = [k for k in dir(instance) if not k.startswith('_')]
4542
+ available_methods = []
3976
4543
  all_available = available_members + available_methods
3977
4544
  similar = _find_similar_names(member, all_available)
3978
4545
 
@@ -4112,6 +4679,48 @@ class CSSLRuntime:
4112
4679
  hint
4113
4680
  )
4114
4681
 
4682
+ # === UNIVERSAL INSTANCE METHODS ===
4683
+ from .cssl_types import UniversalInstance
4684
+ if isinstance(obj, UniversalInstance):
4685
+ # Check for member variable
4686
+ if obj.has_member(member):
4687
+ return obj.get_member(member)
4688
+ # Check for method
4689
+ if obj.has_method(member):
4690
+ method_node = obj.get_method(member)
4691
+ # Create a callable that executes the method in context
4692
+ def instance_method_caller(*args, **kwargs):
4693
+ # Set 'this' to refer to the instance
4694
+ old_this = self.scope.get('this')
4695
+ self.scope.set('this', obj)
4696
+ try:
4697
+ return self._call_function(method_node, list(args))
4698
+ finally:
4699
+ if old_this is not None:
4700
+ self.scope.set('this', old_this)
4701
+ else:
4702
+ self.scope.remove('this') if hasattr(self.scope, 'remove') else None
4703
+ return instance_method_caller
4704
+ # Build helpful error with available members
4705
+ instance_name = obj.name
4706
+ available_members = list(obj.get_all_members().keys())
4707
+ available_methods = list(obj.get_all_methods().keys())
4708
+ all_available = available_members + available_methods
4709
+ similar = _find_similar_names(member, all_available)
4710
+
4711
+ if similar:
4712
+ hint = f"Did you mean: {', '.join(similar)}?"
4713
+ elif all_available:
4714
+ hint = f"Available: {', '.join(all_available[:5])}"
4715
+ else:
4716
+ hint = f"Instance '{instance_name}' has no accessible members."
4717
+
4718
+ raise self._format_error(
4719
+ node.line,
4720
+ f"Instance '{instance_name}' has no member or method '{member}'",
4721
+ hint
4722
+ )
4723
+
4115
4724
  # === STRING METHODS ===
4116
4725
  if isinstance(obj, str):
4117
4726
  string_methods = self._get_string_method(obj, member)
@@ -4350,6 +4959,12 @@ class CSSLRuntime:
4350
4959
  obj.set_member(member, value)
4351
4960
  return
4352
4961
 
4962
+ # Check for UniversalInstance - use set_member method
4963
+ from .cssl_types import UniversalInstance
4964
+ if isinstance(obj, UniversalInstance):
4965
+ obj.set_member(member, value)
4966
+ return
4967
+
4353
4968
  # Check for SharedObjectProxy - directly access underlying object
4354
4969
  # This is more robust than relying on the proxy's __setattr__
4355
4970
  if hasattr(obj, '_direct_object') and hasattr(obj, '_name'):